00001 /* 00002 * PROPRIETARY INFORMATION. This software is proprietary to 00003 * Side Effects Software Inc., and is not to be reproduced, 00004 * transmitted, or disclosed in any way without written permission. 00005 * 00006 * Produced by: 00007 * Mark Elendt 00008 * Side Effects Software Inc 00009 * 477 Richmond Street West 00010 * Toronto, Ontario 00011 * Canada M5V 3E7 00012 * 416-504-9876 00013 * 00014 * NAME: VRAY_Procedural.h ( VRAY Library, C++) 00015 * 00016 * COMMENTS: VRAY Procedural Primitive 00017 * 00018 * This primitive is used to generate procedural geometry during the 00019 * rendering process. 00020 * 00021 * The procedural primitive can generate further procedural primitives, or 00022 * as a leaf node, generate a GU_Detail. 00023 * 00024 * Shaders for the geometry are inherited from the instance of the detail 00025 * unless additional shaders are specified using the vm_surface or 00026 * vm_displace attributes. 00027 */ 00028 00029 #ifndef __VRAY_Procedural__ 00030 #define __VRAY_Procedural__ 00031 00032 #include "VRAY_API.h" 00033 #include <SYS/SYS_Types.h> 00034 #include <UT/UT_Matrix4.h> 00035 #include <UT/UT_String.h> 00036 00037 class UT_BoundingBox; 00038 class GU_Detail; 00039 class VRAY_Procedural; 00040 class VRAY_ProceduralArg; 00041 class VRAY_Volume; 00042 00043 // 00044 // When the procedural is defined as a dynamic object, the allocProcedural() 00045 // function is called to build a new instance of the procedural. The name 00046 // passed in will be the name defined by the table entry. This can be used 00047 // for: 00048 // a) Error checking -- you can verify that you're name is what you 00049 // expect. However, this isn't manditory. 00050 // b) To have more than one procedural defined per dynamic object. Using 00051 // the name, you can create procedurals of different types. 00052 // 00053 // The argument list for the procedural is specified by a list of arguments. 00054 // The getProceduralArgs() method should return a pointer to an array of 00055 // VRAY_ProceduralArg's. The list should be terminated by an entry with 00056 // default arguments (i.e. null pointers). For example: 00057 // static VRAY_ProceduralArg theArgs[] = { 00058 // VRAY_ProceduralArg("intarg", "int", "0" }, 00059 // VRAY_ProceduralArg("realarg", "real", "3.1415" }, 00060 // VRAY_ProceduralArg("stringarg", "string", "foo bar" }, 00061 // VRAY_ProceduralArg("vectorarg", "real", "1 2 3" }, 00062 // VRAY_ProceduralArg() 00063 // } 00064 // const VRAY_ProceduralArg *getProceduralArgs() { return theArgs; } 00065 // Arguments can then be queried using the argValue() methods in the procedural 00066 // 00067 extern "C" { 00068 DLLEXPORT extern VRAY_Procedural *allocProcedural(const char *name); 00069 DLLEXPORT extern const VRAY_ProceduralArg *getProceduralArgs(const char *n); 00070 } 00071 00072 // 00073 // 00074 class VRAY_API VRAY_ProceduralArg { 00075 public: 00076 // 00077 // name := The name of the parameter 00078 // type := The storage type of the parameter. This may be one of 00079 // "int" = Integer 00080 // "real" = Floating point (fpreal) value 00081 // "string" = String value 00082 // value := A string representing the default values for the argument 00083 // For int and real types, the string is tokenized, and the number 00084 // of tokens in the string determines the vector size of the 00085 // argument. For example: 00086 // VRAY_ProceduralArg("a", "int", "1 2 3 4") 00087 // Would specify a parameter named "a" which consists of 4 00088 // integers with a default value of {1, 2, 3, 4}. 00089 // For string types, the vector size is always defined as 1 and 00090 // the string is used verbatim as the default. 00091 // 00092 VRAY_ProceduralArg(const char *name=0, const char *type=0, 00093 const char *value=0) 00094 { 00095 myName = name; 00096 myType = type; 00097 myValue = value; 00098 } 00099 ~VRAY_ProceduralArg() 00100 { 00101 } 00102 00103 const char *getName() const { return myName; } 00104 const char *getType() const { return myType; } 00105 const char *getValue() const { return myValue; } 00106 00107 private: 00108 const char *myName; 00109 const char *myType; 00110 const char *myValue; 00111 }; 00112 00113 // 00114 // The ProcInstance class is used by the Procedural class to allow the 00115 // Procedural to contain multiple geometry details. 00116 // 00117 class VRAY_API VRAY_Procedural { 00118 public: 00119 VRAY_Procedural(); 00120 virtual ~VRAY_Procedural(); 00121 00122 // 00123 // The class name is used in diagnostic messages. It can simply be the 00124 // name of the class, or alternatively, you can choose a unique name for 00125 // each procedural instance. 00126 virtual const char *getClassName() = 0; 00127 00128 // 00129 // The initialize method is called when the procedural is created. 00130 // Returning zero (failure) will abort the rendering of this procedural. 00131 // The bounding box passed in is the user defined bounding box. If the 00132 // user didn't specify a bounding box, then the box will be a null pointer. 00133 virtual int initialize(const UT_BoundingBox *box) = 0; 00134 00135 // 00136 // The bounding box is the "object space" bounds of the procedural. 00137 virtual void getBoundingBox(UT_BoundingBox &box) = 0; 00138 00139 // 00140 // The render method is called when the procedural is required to either 00141 // generate geometry or split into more procedurals. The level of detail 00142 // passed in represents the rough screen space projection of the 00143 // procedural's bounding box. The value is roughly the number of pixels 00144 // that the bounding box occupies (modified by the LEVEL OF DETAIL rate). 00145 // For example, if a box occupies 10 horizontal pixels and 20 vertical 00146 // pixels, the lod passed in will be roughly 20 (the maximum bounds 00147 // occupied in screen space). If the object surrounds the camera, the lod 00148 // will be clamped at 2.0E6. The render method may be called more than 00149 // once during a render to regenerate the geometry. 00150 virtual void render() = 0; 00151 00152 // 00153 // The getParm() methods evaluate parameters attached to the procedural. 00154 // The lookup may be performed by name or by token. Each parameter has a 00155 // unique token associated with it. The token lookup methods are more 00156 // efficient than the name lookups and should be almost as efficient as 00157 // accessing member data. 00158 int lookupParmToken(const char *name); 00159 const int *getIParm(const char *name) const; 00160 const fpreal *getFParm(const char *name) const; 00161 const char **getSParm(const char *name) const; 00162 const int *getIParm(int token) const; 00163 const fpreal *getFParm(int token) const; 00164 const char **getSParm(int token) const; 00165 00166 // The import functions can be used as a general purpose query mechanism. 00167 // This will import values from: 00168 // - The argument list for the procedural 00169 // - The argument list for the object defining the procedural 00170 // - A global rendering setting. 00171 // For example, name could be "object:name", "object:shadingquality", 00172 // "camera:pixelaspect", or any of the other setting defined in mantra. 00173 bool import(const char *name, int *value, int vectorsize); 00174 bool import(const char *name, fpreal *value, int vectorsize); 00175 bool import(const char *name, UT_String &result, int idx=0); 00176 00177 // Or, if you've opened an object handle using queryObject(), it's possible 00178 // to query the settings of that object. 00179 bool import(void *handle, const char *name, int *value, 00180 int vectorsize); 00181 bool import(void *handle, const char *name, fpreal *value, 00182 int vectorsize); 00183 bool import(void *handle, const char *name, UT_String &result, 00184 int idx = 0); 00185 00186 protected: 00187 // 00188 // WARNING: 00189 // 00190 // Mantra uses a sub-class of GU_Detail. It is imperative that all 00191 // geometry to be rendered be allocated and free'd using the following 00192 // methods. Otherwise, crashes will ensue. 00193 GU_Detail *allocateGeometry(); 00194 00195 // The freeGeometry() method should probably never be called since the 00196 // geometry created by the procedural is usually passed off. However, it 00197 // is provided for completeness. 00198 void freeGeometry(GU_Detail *gdp); 00199 00200 // The following methods are now obsolete. The settings/flags should be 00201 // set by calling changeSetting() 00202 // - setGeometryFlag() 00203 // - copyGeometryFlags() 00204 00205 // 00206 // This method allows you to compute the level of detail of an arbitrary 00207 // bounding box. The shading_quality parameter is basically a multiplier 00208 // on the computed level of detail. Higher shading_qalities will result 00209 // in higher level of details. 00210 fpreal getLevelOfDetail(const UT_BoundingBox &box); 00211 00212 // 00213 // When the render method is called, the procedural can add objects to 00214 // the scene. It is possible for the render() method to add multiple 00215 // objects. 00216 // 00217 // The process for adding objects is: 00218 // a) open a geometry object 00219 // add geometry to the object 00220 // modify flags on the geometry 00221 // modify any settings (changeSetting()) 00222 // close the object 00223 // 00224 // b) open a procedural object 00225 // add procedurals to the object 00226 // modify any settings (changeSetting()) 00227 // close the object 00228 // 00229 // By writing multiple geometries to the object, deformation blur can be 00230 // accomplished. There are two ways that deformation blur can be 00231 // implemented in a procedural. There can be a single procedural entity 00232 // which generates multiple geometry entities, or there can be multiple 00233 // procedural entities which generate a single geometry each. 00234 // 00235 // If settings are not overridden by the procedural, they will be 00236 // inherited from the object defining the procedural. 00237 // The shutter time should be between 0 and 1. 00238 // 00239 // The renderer assumes ownership of any geometry or procedurals written 00240 // to objects. Thus, the geometry and procedurals should not be free'd 00241 // by the user. 00242 00243 void openGeometryObject(); 00244 00245 // Before adding the geometry, you can change geometry settings by calling 00246 // changeSettings(). For example, if you want to force computation of N, 00247 // you can call: 00248 // changeSetting("computeN", "true", "geometry"); 00249 // This needs to be done BEFORE the addGeometry() call is made. 00250 void addGeometry(GU_Detail *gdp, fpreal shutter); 00251 00252 // If you want to perform velocity motion blur on the geometry, you can add 00253 // all the detail at once, calling this convenience function. 00254 // Note: The "shutter" is really a scale on the velocity. However, since 00255 // velocity is typically specified in units/second, you usually need to 00256 // scale by the shutter time of the frame. To do this, you should multiply 00257 // by the "object:velocityscale" property of the object. 00258 // 00259 // Assume that we have a procedural where the user can specify an 00260 // individual shutter time in a parameter called "shutter". Then, the 00261 // initialization code might look something like: 00262 // float shutter, vscale; 00263 // if (!import("shutter", &shutter, 1)) 00264 // shutter = 1; // Default to full shutter 00265 // if (!import("object:velocityscale", &vscale, 1)) 00266 // { 00267 // // This should never happen since it's a property 00268 // vscale = 0; 00269 // } 00270 // this->myShutter = shutter * vscale; 00271 // Then, during the rendering process: 00272 // gdp = allocateGeometry(); 00273 // createGeometry(gdp); // Create the render geometry 00274 // addGeometry(gdp, 0); // Add geometry for beginning of frame 00275 // // Add the motion blur geometry 00276 // addVelocityBlurGeometry(gdp, this->myShutter); 00277 // 00278 // The maximum velocity displacement is returned (so that bounding boxes 00279 // may be computed). 00280 // 00281 float addVelocityBlurGeometry(GU_Detail *gdp, fpreal shutter, 00282 const char *velocity_attribute="v"); 00283 00284 // If the procedural has been split too many times, it will not be 00285 // possible to generate further procedurals. This can happen if the 00286 // procedural is centered around the origin (i.e. cuts the camera 00287 // clipping plane) and hasn't shrunk itself enough to isolate itself. 00288 int openProceduralObject(); 00289 void addProcedural(VRAY_Procedural *proc); 00290 // When passing argc/argv, the initialize method will be called on the 00291 // procedural. The method returns 0 if there was an error on the 00292 // procedural, 1 on success. 00293 int addProcedural(int argc, char *argv[], 00294 const UT_BoundingBox *box=0); 00295 00296 // Add primitive volumes. 00297 void openVolumeObject(); 00298 void addVolume(VRAY_Volume *volume, fpreal shutter); 00299 00300 // 00301 // The following functions will set attributes of the object currently 00302 // open. 00303 // 00304 // Transform the geometry/procedural at the shutter time specified. 00305 void setTransform(const UT_Matrix4 &transform, fpreal shutter); 00306 00307 // 00308 // Change any setting on the object (geometry or procedural) 00309 // * changeSetting(const char *name, const char *value) 00310 // Parses the string into arguments and changes the setting 00311 // If you want to change a setting to a single string value, it 00312 // is better to call: changeSettings(name, 1, &value); 00313 // * changeSetting(const char *name, int argc, char **argv) 00314 // * changeSetting(const char *name, int argc, int *argv) 00315 // * changeSetting(const char *name, int argc, fpreal *argv) 00316 // If the setting specified by "name" isn't found, the function will fail 00317 // (return false). 00318 // 00319 bool changeSetting(const char *name, const char *value, 00320 const char *style = "object"); 00321 bool changeSetting(const char *name, int argc, char **argv, 00322 const char *style = "object"); 00323 bool changeSetting(const char *name, int argc, const int *argv, 00324 const char *style = "object"); 00325 bool changeSetting(const char *name, int argc, const fpreal *argv, 00326 const char *style = "object"); 00327 00328 // 00329 // The following three methods are for backwards compatibility and are 00330 // simply wrappers around changeSettings(). 00331 void setSurface(const char *shader, fpreal =0) 00332 { changeSetting("surface", shader, "object"); } 00333 void setDisplacement(const char *shader, fpreal =0) 00334 { changeSetting("displace", shader, "object"); } 00335 void setDisplacementBounds(fpreal bounds) 00336 { changeSetting("displacebound", 1, &bounds, "object"); } 00337 00338 void setComputeN(int value) 00339 { changeSetting("computeN", 1, &value, "geometry"); } 00340 00341 // After all geometry/procedurals have been added and all the attributes 00342 // have been set, the object can be closed. 00343 void closeObject(); 00344 00345 protected: 00346 // 00347 // It is possible to query information about other objects in the scene to 00348 // some extent. This is done using the following query methods. 00349 00350 // 00351 // Find a handle to a given object in the scene. Note that for objects 00352 // which are rendered using point instances, the object handle will be a 00353 // single instance rather than all of the instances. 00354 // If a null pointer is passed in for the name, then the object refers to 00355 // the object containing this procedural. The object handle does not need 00356 // to be closed. 00357 void *queryObject(const char *name); 00358 00359 // 00360 // Given an object handle, it is now possible to query information about 00361 // the object. 00362 // 00363 00364 // Find out how many transforms are associated with the object. For 00365 // transformation blurred geometry, there will be more than one sample. 00366 int queryTransformSamples(void *object_handle); 00367 const UT_Matrix4 &queryTransform(void *object_handle, int sample); 00368 const UT_Matrix4 &queryShaderTransform(void *object_handle, int sample); 00369 00370 // Find out the name of the object queried. This is useful when trying to 00371 // find out which object the procedural belongs to (i.e. queryObject(0)) 00372 const char *queryObjectName(void *handle); 00373 00374 // Get the name of our root object. 00375 const char *queryRootName(); 00376 00377 // Find out how many geometry samples associated with the object. For 00378 // deformation blurred geometry, there will be more than one sample. 00379 int queryGeometrySamples(void *object_handle); 00380 const GU_Detail *queryGeometry(void *object_handle, int sample); 00381 00382 // Find out shader information about the object. This information is only 00383 // roughly accurate since the object shaders may be overridden by geometry 00384 // attributes. The shader information returned is the object level 00385 // shaders. The shaders returned are simply the setting bound at the 00386 // instance level (including arguments). 00387 void querySurfaceShader(void *handle, UT_String &shader) 00388 { 00389 if (!import(handle, "object:surface", shader, 0)) 00390 shader = 0; 00391 } 00392 void queryDisplacementShader(void *handle, UT_String &shader) 00393 { 00394 import(handle, "object:displace", shader, 0); 00395 shader = 0; 00396 } 00397 fpreal queryDisplacementBounds(void *handle) 00398 { 00399 fpreal dbound; 00400 if (!import(handle, "object:displacebound", 00401 &dbound, 1)) 00402 dbound = 0; 00403 return dbound; 00404 } 00405 int queryPhantom(void *handle) 00406 { 00407 int phantom; 00408 if (!import(handle, "object:phantom", &phantom, 1)) 00409 phantom = 0; 00410 return phantom; 00411 } 00412 int queryReflectBounce(void *handle) 00413 { 00414 int bounce; 00415 if (!import(handle, "object:reflectbounce", &bounce, 1)) 00416 bounce = 0; 00417 return bounce; 00418 } 00419 int queryRefractBounce(void *handle) 00420 { 00421 int bounce; 00422 if (!import(handle, "object:refractbounce", &bounce, 1)) 00423 bounce = 0; 00424 return bounce; 00425 } 00426 void queryReflectScope(void *handle, UT_String &mask) 00427 { 00428 if (!import(handle, "object:reflectmask", mask, 0)) 00429 mask = 0; 00430 } 00431 void queryRefractScope(void *handle, UT_String &mask) 00432 { 00433 if (!import(handle, "object:refractmask", mask, 0)) 00434 mask = 0; 00435 } 00436 00437 private: 00438 void *myObject, *myRoot; 00439 void *myArguments; 00440 void *myGeoSettings; 00441 friend class VRAY_Instance; 00442 friend class VRAY_Scene; 00443 friend class VRAY_ProcDef; 00444 }; 00445 00446 #endif
1.5.9