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_ProcInstance; 00040 class VRAY_Procedural; 00041 class VRAY_ProceduralArg; 00042 class VGEO_Volume; 00043 00044 /// @brief Mantra procedural primitives 00045 /// 00046 /// When a procedural is defined as a dynamic object, the allocProcedural() 00047 /// function is called to build a new instance of the procedural. The name 00048 /// passed in will be the name defined by the table entry. This can be used 00049 /// for: 00050 /// a) Error checking -- you can verify that you're name is what you 00051 /// expect. However, this isn't manditory. 00052 /// b) To have more than one procedural defined per C++ class. Using 00053 /// the name, you can create procedurals of different types. 00054 /// 00055 /// The argument list for the procedural is specified by a list of arguments. 00056 /// The getProceduralArgs() method should return a pointer to an array of 00057 /// VRAY_ProceduralArg's. The list should be terminated by an entry with 00058 /// default arguments (i.e. null pointers). For example: 00059 /// Arguments can then be queried using the argValue() methods in the procedural 00060 /// 00061 extern "C" { 00062 /// Dynamic load entry point to create an instance 00063 SYS_VISIBILITY_EXPORT extern VRAY_Procedural *allocProcedural(const char *name); 00064 /// Dynamic load entry point to query arguments for a procedural 00065 SYS_VISIBILITY_EXPORT extern const VRAY_ProceduralArg *getProceduralArgs(const char *n); 00066 } 00067 00068 /// @brief Parameter definition for arguments to VRAY_Procedural 00069 /// 00070 /// Each VRAY_Procedural has its arguments defined by a table of 00071 /// VRAY_ProceduralArg objects. The procedural can query the value of these 00072 /// parameters using VRAY_Procedural::import() at run time (without having to 00073 /// parse argument lists). The list of arguments should be terminated by an 00074 /// entry constructed with default arguments. For example: 00075 /// @code 00076 /// static VRAY_ProceduralArg theArgs[] = { 00077 /// VRAY_ProceduralArg("intarg", "int", "0" }, 00078 /// VRAY_ProceduralArg("realarg", "real", "3.1415" }, 00079 /// VRAY_ProceduralArg("stringarg", "string", "foo bar" }, 00080 /// VRAY_ProceduralArg("vectorarg", "real", "1 2 3" }, 00081 /// VRAY_ProceduralArg() 00082 /// } 00083 /// const VRAY_ProceduralArg *getProceduralArgs() { return theArgs; } 00084 /// @endcode 00085 class VRAY_API VRAY_ProceduralArg { 00086 public: 00087 /// @param name @n The name of the parameter (must be unique) 00088 /// @param type @n 00089 /// The storage type of the parameter. This should be one of 00090 /// - @c int = Integer 00091 /// - @c real = Floating point (fpreal) value 00092 /// - @c string = String value 00093 /// @param value @n A @b string representing the default values for the 00094 /// argument. For @c int and @c real types, the string is tokenized and 00095 /// the number of tokens in the trin determines the vector/tuple size of 00096 /// the argument. For example @code 00097 /// VRAY_ProceduralArg("a", "int", "1 2 3 4") 00098 /// @endcode 00099 /// would specify a parameter named "a" which consists of 4 integers, 00100 /// and has a default value of {1,2,3,4}. @n 00101 /// For string types, the vector size is always 1, and the string is 00102 /// used as the default value. 00103 /// 00104 /// @warning The procedural keeps shallow references to the 00105 /// <tt>const char *</tt> passed in. 00106 VRAY_ProceduralArg(const char *name=0, const char *type=0, 00107 const char *value=0) 00108 { 00109 myName = name; 00110 myType = type; 00111 myValue = value; 00112 } 00113 ~VRAY_ProceduralArg() 00114 { 00115 } 00116 00117 /// Return the name of the argument 00118 const char *getName() const { return myName; } 00119 /// Return the storage type of the argument 00120 const char *getType() const { return myType; } 00121 /// Return the default value 00122 const char *getValue() const { return myValue; } 00123 00124 private: 00125 const char *myName; 00126 const char *myType; 00127 const char *myValue; 00128 }; 00129 00130 /// @brief Procedural primitive for mantra (VRAY) 00131 /// 00132 /// The VRAY_Procedural class provides a means to create procedural geometry 00133 /// during the rendering process. 00134 class VRAY_API VRAY_Procedural { 00135 public: 00136 VRAY_Procedural(); 00137 virtual ~VRAY_Procedural(); 00138 00139 /// The class name is used in diagnostic messages. It can simply be the 00140 /// name of the class, or alternatively, you can choose a unique name for 00141 /// each procedural instance. 00142 virtual const char *getClassName() = 0; 00143 00144 /// The initialize method is called when the procedural is created. 00145 /// Returning zero (failure) will abort the rendering of this procedural. 00146 /// 00147 /// The bounding box passed in is the user defined bounding box. If the 00148 /// user didn't specify a bounding box, then the box will be NULL. 00149 virtual int initialize(const UT_BoundingBox *box) = 0; 00150 00151 /// The bounding box is the "object space" bounds of the procedural. 00152 virtual void getBoundingBox(UT_BoundingBox &box) = 0; 00153 00154 /// Returns true when the render() method of this procedural is 00155 /// thread-safe - that is, the render() method on different 00156 /// VRAY_Procedural objects can be called simultaneously by different 00157 /// threads. By default, procedurals are assumed to thread unsafe. 00158 virtual bool isThreadSafe() const { return false; } 00159 00160 /// The render method is called when the procedural is required to either 00161 /// generate geometry or split into more procedurals. The level of detail 00162 /// passed in represents the rough screen space projection of the 00163 /// procedural's bounding box. The value is roughly the number of pixels 00164 /// that the bounding box occupies (modified by the LEVEL OF DETAIL rate). 00165 /// 00166 /// For example, if a box occupies 10 horizontal pixels and 20 vertical 00167 /// pixels, the lod passed in will be roughly 20 (the maximum bounds 00168 /// occupied in screen space). If the object surrounds the camera, the lod 00169 /// will be clamped at a large number. 00170 /// @note The render method may be called more than once during a render to 00171 /// regenerate the geometry. 00172 virtual void render() = 0; 00173 00174 /// The getParm() methods evaluate parameters attached to the procedural. 00175 /// The lookup may be performed by name or by token. Each parameter has a 00176 /// unique token associated with it. The token lookup methods are more 00177 /// efficient than the name lookups and should be almost as efficient as 00178 /// accessing member data. 00179 00180 /// Parameters to the procedural are stored as a list of VRAY_ProceduralArg 00181 /// objects. Each parameter is given a unique integer. This allows for 00182 /// more efficient evaluation (avoiding comparing strings). 00183 int lookupParmToken(const char *name); 00184 00185 /// @{ 00186 /// Get the raw data pointers for a parameter by either name or value. 00187 /// @see import() 00188 /// 00189 const int *getIParm(const char *name) const; 00190 const fpreal *getFParm(const char *name) const; 00191 const char **getSParm(const char *name) const; 00192 const int *getIParm(int token) const; 00193 const fpreal *getFParm(int token) const; 00194 const char **getSParm(int token) const; 00195 /// @} 00196 00197 /// @{ 00198 /// The import functions can be used as a general purpose query mechanism. 00199 /// This will import values from: 00200 /// - The argument list for the procedural 00201 /// - The argument list for the object defining the procedural 00202 /// - A global rendering setting. 00203 /// Aside from a parameter name, the name could be "object:name", 00204 /// "object:shadingquality", "camera:pixelaspect", or any of the other 00205 /// setting defined in mantra. 00206 bool import(const char *name, int *value, int vectorsize); 00207 bool import(const char *name, fpreal32 *value, int vectorsize); 00208 bool import(const char *name, fpreal64 *value, int vectorsize); 00209 bool import(const char *name, UT_String &result, int idx=0); 00210 /// @} 00211 00212 /// @{ 00213 /// If you've opened an object handle using queryObject(), it's possible 00214 /// to query the settings of that object. This makes it possible to query 00215 /// the parameters/values/settings of other objects in the scene. 00216 bool import(void *handle, const char *name, int *value, 00217 int vectorsize); 00218 bool import(void *handle, const char *name, fpreal32 *value, 00219 int vectorsize); 00220 bool import(void *handle, const char *name, fpreal64 *value, 00221 int vectorsize); 00222 bool import(void *handle, const char *name, UT_String &result, 00223 int idx = 0); 00224 /// @} 00225 00226 protected: 00227 /// @warning 00228 /// 00229 /// Mantra uses a sub-class of GU_Detail. It is imperative that all 00230 /// geometry to be rendered be allocated and free'd using the following 00231 /// methods. Otherwise, crashes will ensue. 00232 GU_Detail *allocateGeometry(); 00233 00234 /// Normally freeGeometry() should never be called since you'll usually 00235 /// use allocateGeometry() to create a new geometry that is later 00236 /// passed off to the procedural using addGeometry(). However, if you 00237 /// need to keep a reference to the geometry using referenceGeometry() 00238 /// it is possible to free or clear the reference using freeGeometry(). 00239 /// freeGeometry() may also be used to deallocate geometry that was 00240 /// never passed off with addGeometry(). 00241 void freeGeometry(GU_Detail *gdp); 00242 00243 /// This method allows a single geometry object to be added multiple 00244 /// times with addGeometry(). For each addGeometry() operation, first 00245 /// call referenceGeometry() to allow the caller to keep a reference to 00246 /// the geometry, then use freeGeometry() to release the referenced 00247 /// geometry when you're done with it. For example: 00248 /// @code 00249 /// GU_Detail *gdp; 00250 /// // Allocate the geometry 00251 /// gdp = allocateGeometry(); 00252 /// // Create 2 instances of the geometry. Normally these 00253 /// // should be created with differing transforms. 00254 /// referenceGeometry(gdp); 00255 /// addGeometry(gdp); 00256 /// referenceGeometry(gdp); 00257 /// addGeometry(gdp); 00258 /// // Unreference the local copy 00259 /// freeGeometry(gdp); 00260 /// @endcode 00261 void referenceGeometry(GU_Detail *gdp); 00262 00263 // The following methods are now obsolete. The settings/flags should be 00264 // set by calling changeSetting() 00265 // - setGeometryFlag() 00266 // - copyGeometryFlags() 00267 00268 /// This method allows you to compute the level of detail of an arbitrary 00269 /// bounding box. The shading_quality parameter is a multiplier on the 00270 /// computed level of detail. Higher shading_qalities will result in 00271 /// higher level of details. 00272 fpreal getLevelOfDetail(const UT_BoundingBox &box); 00273 00274 /// When the render method is called, the procedural can add objects to 00275 /// the scene. It is possible for the render() method to add multiple 00276 /// objects. 00277 /// 00278 /// The process for adding a geometry object: 00279 /// - open a geometry object (openGeometryObject()) 00280 /// - add geometry to the object (addGeometry()) 00281 /// - modify any settings (changeSetting()) 00282 /// - close the object (closeObject()) 00283 /// 00284 /// The process for adding a new procedural is fairly similar: 00285 /// - open a procedural object (openProcecuralObject()) 00286 /// - add procedural(s) to the object (addProcedural()) 00287 /// - modify any settings (changeSetting()) 00288 /// - close the object (closeObject()) 00289 /// 00290 /// For a geometry object, deformation motion blur is done by adding 00291 /// multiple geometry objects. 00292 /// 00293 /// If settings are not overridden by the procedural, they will be 00294 /// inherited from the object defining the procedural. 00295 /// 00296 /// The shutter time should be between 0 and 1. 00297 /// 00298 /// The renderer assumes ownership of any geometry or procedurals written 00299 /// to objects. Thus, the geometry and procedurals should not be free'd 00300 /// by the user. 00301 void openGeometryObject(); 00302 00303 /// Before adding the geometry, you can change @b geometry settings by 00304 /// calling changeSettings(). For example, if you want to force 00305 /// computation of N, you can call: 00306 /// changeSetting("computeN", "true", "geometry"); 00307 /// This needs to be done @b BEFORE the addGeometry() call is made. 00308 /// Object settings can be changed after the geometry has been added. 00309 void addGeometry(GU_Detail *gdp, fpreal shutter); 00310 00311 /// If you want to perform velocity motion blur on the geometry, you can add 00312 /// all the detail at once, calling this convenience function. 00313 /// Note: The "shutter" is really a scale on the velocity. However, since 00314 /// velocity is typically specified in units/second, you usually need to 00315 /// scale by the shutter time of the frame. To do this, you should multiply 00316 /// by the "object:velocityscale" property of the object. 00317 /// 00318 /// Assume that we have a procedural where the user can specify an 00319 /// individual shutter time in a parameter called "shutter". Then, the 00320 /// initialization code might look something like: 00321 /// @code 00322 /// float shutter, vscale; 00323 /// if (!import("shutter", &shutter, 1)) 00324 /// shutter = 1; // Default to full shutter 00325 /// if (!import("object:velocityscale", &vscale, 1)) 00326 /// { 00327 /// // This should never happen since it's a property 00328 /// vscale = 0; 00329 /// } 00330 /// this->myShutter = shutter * vscale; 00331 /// @endcode 00332 /// Then, during the rendering process: 00333 /// @code 00334 /// gdp = allocateGeometry(); 00335 /// createGeometry(gdp); // Create the render geometry 00336 /// addGeometry(gdp, 0); // Add geometry for beginning of frame 00337 /// // Add the motion blur geometry 00338 /// addVelocityBlurGeometry(gdp, this->myShutter); 00339 /// @endcode 00340 /// 00341 /// The maximum velocity displacement is returned (so that bounding boxes 00342 /// may be computed). 00343 float addVelocityBlurGeometry(GU_Detail *gdp, fpreal shutter, 00344 const char *velocity_attribute="v"); 00345 00346 /// If the procedural has been split too many times, it will not be 00347 /// possible to generate further procedurals. This can happen if the 00348 /// procedural is centered around the origin (i.e. cuts the camera 00349 /// clipping plane) and hasn't shrunk itself enough to isolate itself. 00350 int openProceduralObject(); 00351 /// Add a procedural to the opened procedural object. Use this method when 00352 /// allocating a "private" procedural (i.e. a procedural object which isn't 00353 /// registered with mantra). 00354 /// @see openProceduralObject() 00355 void addProcedural(VRAY_Procedural *proc); 00356 /// Add a procedural the the opened procedural object. This method allows 00357 /// you to create any registered procedural by passing @c argc and @c argv 00358 /// arguments to initialize the procedural. 00359 /// @return 0 or 1 for failure/success 00360 /// @see openProceduralObject() 00361 int addProcedural(int argc, char *argv[], 00362 const UT_BoundingBox *box=0); 00363 00364 /// Open a volume object 00365 void openVolumeObject(); 00366 /// Add a volume primitive to the currently open volume object 00367 void addVolume(VGEO_Volume *volume, fpreal shutter); 00368 00369 /// Transform the currently open object (geometry, procedural, volume) at 00370 /// the shutter time specified. 00371 void setTransform(const UT_Matrix4 &transform, fpreal shutter); 00372 00373 /// @{ 00374 /// Change any setting on the object (geometry, procedural, volume) 00375 /// - <tt>changeSetting(const char *name, const char *value)</tt> @n 00376 /// Parses the string into arguments and changes the setting If you want 00377 /// to change a setting to a single string value, it is better to call: 00378 /// changeSettings(name, 1, &value); 00379 /// - <tt>changeSetting(const char *name, int argc, char **argv)</tt> 00380 /// - <tt>changeSetting(const char *name, int argc, int *argv)</tt> 00381 /// - <tt>changeSetting(const char *name, int argc, fpreal *argv)</tt> 00382 /// If the setting specified by "name" isn't found, the function will fail 00383 /// (return false). 00384 bool changeSetting(const char *name, const char *value, 00385 const char *style = "object"); 00386 bool changeSetting(const char *name, int argc, char **argv, 00387 const char *style = "object"); 00388 bool changeSetting(const char *name, int argc, const int *argv, 00389 const char *style = "object"); 00390 bool changeSetting(const char *name, int argc, const fpreal *argv, 00391 const char *style = "object"); 00392 /// @} 00393 00394 /// The following methods are for backwards compatibility and are 00395 /// simply wrappers around changeSettings(). 00396 /// @private 00397 void setSurface(const char *shader, fpreal =0) 00398 { changeSetting("surface", shader, "object"); } 00399 /// @private 00400 void setDisplacement(const char *shader, fpreal =0) 00401 { changeSetting("displace", shader, "object"); } 00402 /// @private 00403 void setDisplacementBounds(fpreal bounds) 00404 { changeSetting("displacebound", 1, &bounds, "object"); } 00405 00406 /// @private 00407 void setComputeN(int value) 00408 { changeSetting("computeN", 1, &value, "geometry"); } 00409 00410 /// After all geometry, procedurals, volumes have been added and all the 00411 /// attributes have been set, the object can be closed. 00412 void closeObject(); 00413 00414 protected: 00415 /// It is possible to query information about other objects in the scene to 00416 /// some extent. This is done using the following query methods. 00417 00418 /// Find a handle to a given object in the scene. Note that for objects 00419 /// which are rendered using point instances, the object handle will be a 00420 /// single instance rather than all of the instances. 00421 /// If a null pointer is passed in for the name, then the object refers to 00422 /// the object containing this procedural. The object handle does not need 00423 /// to be closed. 00424 void *queryObject(const char *name); 00425 00426 // 00427 // Given an object handle, it is now possible to query information about 00428 // the object. 00429 // 00430 00431 /// Query the number of transform samples for a given query object 00432 /// @see queryObject() 00433 int queryTransformSamples(void *object_handle); 00434 /// Get the transform associated with an object in the scene 00435 /// @see queryObject() 00436 const UT_Matrix4 &queryTransform(void *object_handle, int sample); 00437 /// Get the shading transform associated with an object in the scene 00438 /// @see queryObject() 00439 const UT_Matrix4 &queryShaderTransform(void *object_handle, int sample); 00440 00441 /// Find out the name of the object queried. This is useful when trying to 00442 /// find out which object the procedural belongs to (i.e. queryObject(0)) 00443 /// @see queryObject() 00444 const char *queryObjectName(void *handle); 00445 00446 /// Get the name of the object which owns this procedural. 00447 const char *queryRootName(); 00448 00449 /// Find out how many geometry samples associated with the object. 00450 /// @see queryObject() 00451 int queryGeometrySamples(void *object_handle); 00452 /// Get the geometry from another object 00453 /// @see queryObject() 00454 const GU_Detail *queryGeometry(void *object_handle, int sample); 00455 00456 /// Find out shader information about the object. This information is only 00457 /// roughly accurate since the object shaders may be overridden by geometry 00458 /// attributes. The shader information returned is the object level 00459 /// shaders. The shaders returned are simply the setting bound at the 00460 /// instance level (including arguments). 00461 /// @private: Use import() 00462 void querySurfaceShader(void *handle, UT_String &shader) 00463 { 00464 if (!import(handle, "object:surface", shader, 0)) 00465 shader = 0; 00466 } 00467 /// @private: Use import() 00468 void queryDisplacementShader(void *handle, UT_String &shader) 00469 { 00470 import(handle, "object:displace", shader, 0); 00471 shader = 0; 00472 } 00473 /// @private: Use import() 00474 fpreal queryDisplacementBounds(void *handle) 00475 { 00476 fpreal dbound; 00477 if (!import(handle, "object:displacebound", 00478 &dbound, 1)) 00479 dbound = 0; 00480 return dbound; 00481 } 00482 /// @private: Use import() 00483 int queryPhantom(void *handle) 00484 { 00485 int phantom; 00486 if (!import(handle, "object:phantom", &phantom, 1)) 00487 phantom = 0; 00488 return phantom; 00489 } 00490 /// @private: Use import() 00491 int queryReflectBounce(void *handle) 00492 { 00493 int bounce; 00494 if (!import(handle, "object:reflectbounce", &bounce, 1)) 00495 bounce = 0; 00496 return bounce; 00497 } 00498 /// @private: Use import() 00499 int queryRefractBounce(void *handle) 00500 { 00501 int bounce; 00502 if (!import(handle, "object:refractbounce", &bounce, 1)) 00503 bounce = 0; 00504 return bounce; 00505 } 00506 /// @private: Use import() 00507 void queryReflectScope(void *handle, UT_String &mask) 00508 { 00509 if (!import(handle, "object:reflectmask", mask, 0)) 00510 mask = 0; 00511 } 00512 /// @private: Use import() 00513 void queryRefractScope(void *handle, UT_String &mask) 00514 { 00515 if (!import(handle, "object:refractmask", mask, 0)) 00516 mask = 0; 00517 } 00518 00519 private: 00520 void *myObject, *myRoot; 00521 void *myArguments; 00522 void *myGeoSettings; 00523 vray_ProcInstance *myHandle; 00524 friend class VRAY_Instance; 00525 friend class VRAY_Scene; 00526 friend class VRAY_ProcDef; 00527 }; 00528 00529 #endif
1.5.9