├── GEO ├── GEO_ArnoldTranslator.C ├── GEO_ArnoldTranslator.h └── GEO_VoxelTranslator.C ├── HOM ├── ObjNode_setSelectable.C ├── SOP_HOMWave.C ├── SOP_HOMWave.h ├── SOP_HOMWave.py ├── SOP_HOMWaveInlinecpp.py └── SOP_HOMWaveNumpy.py ├── OBJ ├── OBJ_Lamp.C ├── OBJ_Shake.C ├── OBJ_Shake.h ├── OBJ_hdk_lamp.icon ├── OBJ_hdk_shake.icon ├── deflamp.bgeo └── hdk_lamp.cmd ├── README ├── ROP ├── README ├── ROP_DopField.C ├── ROP_DopField.h ├── ROP_Dumper.C ├── ROP_Dumper.h ├── ROP_Radiance.C └── ROP_Radiance.h ├── SOP ├── SOP_Star.C ├── SOP_Star.h ├── SOP_hdk_star.png ├── SOP_hdk_star.svg ├── SOP_lotus.py └── hdk_star.txt ├── packedsphere ├── GU_PackedSphere.C ├── GU_PackedSphere.h ├── README.TXT └── packedsphere.C └── standalone ├── gengeovolume.C ├── geoisosurface.C └── i3dsphere.C /GEO/GEO_ArnoldTranslator.C: -------------------------------------------------------------------------------- 1 | #include 2 | #include // UTgetGeoExtensions 3 | // header file 4 | #include "GEO_ArnoldTranslator.h" 5 | 6 | // class GEO_ArnoldIOTranslator 7 | 8 | GEO_IOTranslator* 9 | GEO_ArnoldIOTranslator::duplicate() const { 10 | return new GEO_ArnoldIOTranslator(*this); 11 | } 12 | 13 | const char* 14 | GEO_ArnoldIOTranslator::formatName() const { 15 | return "Arnold's .ass scene description files"; 16 | } 17 | 18 | int 19 | GEO_ArnoldIOTranslator::checkExtension(const char* name) { 20 | UT_String sname(name); 21 | 22 | if (sname.fileExtension() && !strcmp(sname.fileExtension(), ".ass")) { 23 | return true; 24 | } 25 | 26 | return false; 27 | } 28 | 29 | int 30 | GEO_ArnoldIOTranslator::checkMagicNumber(unsigned magic) { 31 | return 0; 32 | } 33 | 34 | GA_Detail::IOStatus 35 | GEO_ArnoldIOTranslator::fileLoad(GEO_Detail* gdp, 36 | UT_IStream& is, 37 | int ate_magic) { 38 | return GA_Detail::IOStatus(true); 39 | } 40 | 41 | GA_Detail::IOStatus 42 | GEO_ArnoldIOTranslator::fileSave(const GEO_Detail* gdp, 43 | ostream& os) { 44 | return GA_Detail::IOStatus(true); 45 | } 46 | 47 | 48 | // entry point 49 | 50 | SYS_VISIBILITY_EXPORT void 51 | newGeometryIO(void *) { 52 | GU_Detail::registerIOTranslator(new GEO_ArnoldIOTranslator()); 53 | UT_ExtensionList* geoextension; 54 | geoextension = UTgetGeoExtensions(); 55 | if (!geoextension->findExtension("ass")) { 56 | geoextension->addExtension("ass"); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /GEO/GEO_ArnoldTranslator.h: -------------------------------------------------------------------------------- 1 | #ifndef __GEO_ArnoldTranslator_h__ 2 | #define __GEO_ArnoldTranslator_h__ 3 | 4 | #include 5 | 6 | class GEO_ArnoldIOTranslator : public GEO_IOTranslator { 7 | public: 8 | GEO_ArnoldIOTranslator() {} 9 | GEO_ArnoldIOTranslator(const GEO_ArnoldIOTranslator& src) 10 | : GEO_IOTranslator() {} 11 | virtual ~GEO_ArnoldIOTranslator() {} 12 | // pure virtual functions (need implementation) 13 | virtual GEO_IOTranslator* duplicate() const; 14 | virtual const char* formatName(void) const; 15 | virtual int checkExtension(const char* name); 16 | virtual int checkMagicNumber(unsigned magic); 17 | // the load and save signatures changed between H11 and H12 18 | virtual GA_Detail::IOStatus fileLoad(GEO_Detail*, UT_IStream&, 19 | int ate_magic); 20 | virtual GA_Detail::IOStatus fileSave(const GEO_Detail*, ostream&); 21 | 22 | protected: 23 | private: 24 | }; 25 | 26 | #endif // __GEO_ArnoldTranslator_h__ 27 | -------------------------------------------------------------------------------- /GEO/GEO_VoxelTranslator.C: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | *---------------------------------------------------------------------------- 26 | */ 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include 39 | #include 40 | 41 | 42 | namespace HDK_Sample { 43 | 44 | class GEO_VoxelIOTranslator : public GEO_IOTranslator 45 | { 46 | public: 47 | GEO_VoxelIOTranslator() {} 48 | GEO_VoxelIOTranslator(const GEO_VoxelIOTranslator &src) {} 49 | virtual ~GEO_VoxelIOTranslator() {} 50 | 51 | virtual GEO_IOTranslator *duplicate() const; 52 | 53 | virtual const char *formatName() const; 54 | 55 | virtual int checkExtension(const char *name); 56 | 57 | virtual int checkMagicNumber(unsigned magic); 58 | 59 | virtual GA_Detail::IOStatus fileLoad(GEO_Detail *, UT_IStream &, 60 | bool ate_magic); 61 | virtual GA_Detail::IOStatus fileSave(const GEO_Detail *, std::ostream &); 62 | }; 63 | 64 | } 65 | 66 | using namespace HDK_Sample; 67 | 68 | GEO_IOTranslator * 69 | GEO_VoxelIOTranslator::duplicate() const 70 | { 71 | return new GEO_VoxelIOTranslator(*this); 72 | } 73 | 74 | const char * 75 | GEO_VoxelIOTranslator::formatName() const 76 | { 77 | return "Silly Sample Voxel Format"; 78 | } 79 | 80 | int 81 | GEO_VoxelIOTranslator::checkExtension(const char *name) 82 | { 83 | UT_String sname(name); 84 | 85 | if (sname.fileExtension() && !strcmp(sname.fileExtension(), ".voxel")) 86 | return true; 87 | return false; 88 | } 89 | 90 | int 91 | GEO_VoxelIOTranslator::checkMagicNumber(unsigned magic) 92 | { 93 | return 0; 94 | } 95 | 96 | GA_Detail::IOStatus 97 | GEO_VoxelIOTranslator::fileLoad(GEO_Detail *gdp, UT_IStream &is, bool ate_magic) 98 | { 99 | // Convert our stream to ascii. 100 | UT_IStreamAutoBinary forceascii(is, false); 101 | 102 | // Check our magic token 103 | if (!is.checkToken("VOXELS")) 104 | return GA_Detail::IOStatus(false); 105 | 106 | #if defined(HOUDINI_11) 107 | int def = -1; 108 | gdp->addPrimAttrib("name", sizeof(int), GB_ATTRIB_INDEX, &def); 109 | #endif 110 | gdp->addStringTuple(GA_ATTRIB_PRIMITIVE, "name", 1); 111 | GA_RWHandleS name_attrib(gdp->findPrimitiveAttribute("name")); 112 | 113 | while (is.checkToken("VOLUME")) 114 | { 115 | UT_String name; 116 | UT_WorkBuffer buf; 117 | 118 | is.getWord(buf); 119 | name.harden(buf.buffer()); 120 | 121 | int rx, ry, rz; 122 | 123 | is.read(&rx); is.read(&ry); is.read(&rz); 124 | 125 | // Center and size 126 | float tx, ty, tz, sx, sy, sz; 127 | 128 | is.read(&tx); is.read(&ty); is.read(&tz); 129 | is.read(&sx); is.read(&sy); is.read(&sz); 130 | 131 | GU_PrimVolume *vol; 132 | 133 | vol = (GU_PrimVolume *)GU_PrimVolume::build((GU_Detail *)gdp); 134 | 135 | // Set the name of the primitive 136 | name_attrib.set(vol->getMapOffset(), name); 137 | 138 | // Set the center of the volume 139 | #if defined(HOUDINI_11) 140 | vol->getVertex().getPos() = UT_Vector3(tx, ty, tz); 141 | #else 142 | gdp->setPos3(vol->getPointOffset(0), UT_Vector3(tx, ty, tz)); 143 | #endif 144 | 145 | UT_Matrix3 xform; 146 | 147 | // The GEO_PrimVolume treats the voxel array as a -1 to 1 cube 148 | // so its size is 2, so we scale by 0.5 here. 149 | xform.identity(); 150 | xform.scale(sx/2, sy/2, sz/2); 151 | 152 | vol->setTransform(xform); 153 | 154 | UT_VoxelArrayWriteHandleF handle = vol->getVoxelWriteHandle(); 155 | 156 | // Resize the array. 157 | handle->size(rx, ry, rz); 158 | 159 | if (!is.checkToken("{")) 160 | return GA_Detail::IOStatus(false); 161 | 162 | for (int z = 0; z < rz; z++) 163 | { 164 | for (int y = 0; y < ry; y++) 165 | { 166 | for (int x = 0; x < rx; x++) 167 | { 168 | float v; 169 | 170 | is.read(&v); 171 | 172 | handle->setValue(x, y, z, v); 173 | } 174 | } 175 | } 176 | 177 | if (!is.checkToken("}")) 178 | return GA_Detail::IOStatus(false); 179 | 180 | // Proceed to the next volume. 181 | } 182 | 183 | // All done successfully 184 | return GA_Detail::IOStatus(true); 185 | } 186 | 187 | GA_Detail::IOStatus 188 | GEO_VoxelIOTranslator::fileSave(const GEO_Detail *gdp, std::ostream &os) 189 | { 190 | // Write our magic token. 191 | os << "VOXELS" << std::endl; 192 | 193 | // Now, for each volume in our gdp... 194 | UT_WorkBuffer buf; 195 | 196 | GA_ROHandleS name_attrib(gdp->findPrimitiveAttribute("name")); 197 | const GEO_Primitive *prim; 198 | #if defined(HOUDINI_11) 199 | FOR_ALL_PRIMITIVES(gdp, prim) 200 | #else 201 | GA_FOR_ALL_PRIMITIVES(gdp, prim) 202 | #endif 203 | { 204 | #if defined(HOUDINI_11) 205 | if (prim->getPrimitiveId() == GEOPRIMVOLUME) 206 | // alternatively, this could be ported as 207 | // if (prim->getPrimitiveId() == GEO_PrimTypeCompat::GEOPRIMVOLUME) 208 | #else 209 | if (prim->getTypeId() == GEO_PRIMVOLUME) 210 | #endif 211 | { 212 | // Default name 213 | #if defined(HOUDINI_11) 214 | // Primitive numbers can now be 64 bit 215 | buf.sprintf("volume_%d", prim->getNum()); 216 | #else 217 | buf.sprintf("volume_%" SYS_PRId64, (exint)prim->getMapIndex()); 218 | #endif 219 | UT_String name; 220 | name.harden(buf.buffer()); 221 | 222 | // Which is overridden by any name attribute. 223 | if (name_attrib.isValid()) 224 | name = name_attrib.get(prim->getMapOffset()); 225 | 226 | os << "VOLUME " << name << std::endl; 227 | const GEO_PrimVolume *vol = (const GEO_PrimVolume *)prim; 228 | 229 | // Save resolution 230 | int resx, resy, resz; 231 | vol->getRes(resx, resy, resz); 232 | os << resx << " " << resy << " " << resz << std::endl; 233 | 234 | // Save the center and approximate size. 235 | // Calculating the size is complicated as we could be rotated 236 | // or sheared. We lose all these because the .voxel format 237 | // only supports aligned arrays. 238 | UT_Vector3 p1, p2; 239 | 240 | UT_Vector3 tmp = vol->getPos3(0); 241 | os << tmp.x() << " " << tmp.y() << " " << tmp.z() << std::endl; 242 | 243 | vol->indexToPos(0, 0, 0, p1); 244 | vol->indexToPos(1, 0, 0, p2); 245 | float length = (p1 - p2).length(); 246 | os << resx * length << " "; 247 | vol->indexToPos(0, 1, 0, p2); 248 | os << resy * length << " "; 249 | vol->indexToPos(0, 0, 1, p2); 250 | os << resz * length << std::endl; 251 | 252 | UT_VoxelArrayReadHandleF handle = vol->getVoxelHandle(); 253 | 254 | // Enough of a header, dump the data. 255 | os << "{" << std::endl; 256 | for (int z = 0; z < resz; z++) 257 | { 258 | for (int y = 0; y < resy; y++) 259 | { 260 | os << " "; 261 | for (int x = 0; x < resx; x++) 262 | { 263 | os << (*handle)(x, y, z) << " "; 264 | } 265 | os << std::endl; 266 | } 267 | } 268 | os << "}" << std::endl; 269 | os << std::endl; 270 | } 271 | } 272 | 273 | return GA_Detail::IOStatus(true); 274 | } 275 | 276 | void 277 | newGeometryIO(void *) 278 | { 279 | GU_Detail::registerIOTranslator(new GEO_VoxelIOTranslator()); 280 | 281 | // Note due to the just-in-time loading of GeometryIO, the f3d 282 | // won't be added until after your first f3d save/load. 283 | // Thus this is replicated in the newDriverOperator. 284 | UT_ExtensionList *geoextension; 285 | geoextension = UTgetGeoExtensions(); 286 | if (!geoextension->findExtension("voxel")) 287 | geoextension->addExtension("voxel"); 288 | } 289 | -------------------------------------------------------------------------------- /HOM/ObjNode_setSelectable.C: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | *---------------------------------------------------------------------------- 26 | */ 27 | 28 | //**************************************************************************** 29 | //**************************************************************************** 30 | //**************************************************************************** 31 | // 32 | // WARNING 33 | // 34 | // This example is deprecated, and is largely replaced by the inlinecpp 35 | // Python module. Except for the ability to raise exceptions, you can 36 | // implement this example with the following Python code: 37 | // 38 | // inlinecpp.extendClass( 39 | // hou.ObjNode, 40 | // "node_methods", 41 | // includes="#include ", 42 | // function_sources=[""" 43 | // void setSelectable(OBJ_Node *obj_node, int selectable) 44 | // { 45 | // if (!obj_node->canAccess(PRM_WRITE_OK)) 46 | // return; 47 | // 48 | // UT_AutoUndoBlock undo_block("Setting selectable flag", ANYLEVEL); 49 | // obj_node->setPickable(selectable != 0); 50 | // } 51 | // """]) 52 | // 53 | //**************************************************************************** 54 | //**************************************************************************** 55 | //**************************************************************************** 56 | 57 | // This sample shows how to extend HOM using C++. It adds a 58 | // hou.ObjNode.setSelectable method that makes an object node selectable/ 59 | // unselectable in the viewport. 60 | 61 | // Include Houdini's equivalent of python/Python.h. It creates wrappers of 62 | // Python's C API functions, so that Houdini can determine at runtime which 63 | // version of Python to use. This file needs to be included first to avoid 64 | // gcc warnings. See PY_CPythonAPI.h for more information about the API 65 | // wrapper. Note that you are limited to the Python API functions wrapped by 66 | // PY_CPythonAPI.h. 67 | #include 68 | 69 | // This file is needed for all HDK plugins: 70 | #include 71 | 72 | // We include this file only to get the forward declaration for 73 | // HOMextendLibrary(). See below for details. 74 | #include 75 | 76 | // This file contains functions that will run arbitrary Python code: 77 | #include 78 | 79 | // The class defined in this file acquires the GIL within Houdini's Python 80 | // runtime environment: 81 | #include 82 | 83 | // This file defines a convenience class to automatically decrement Python 84 | // reference counts: 85 | #include 86 | 87 | // This class in this file is Houdini's internal representation of an object 88 | // node: 89 | #include 90 | 91 | // This file defines OPgetDirector(), which returns the root ("/") node. 92 | #include 93 | 94 | // This file defines a function to demangle a C++ class name from the result 95 | // returned by type_info::name(): 96 | #include 97 | 98 | // This file lets us start a undo block. 99 | #include 100 | 101 | static void 102 | ObjNode_setSelectable(const char *node_path, bool selectable) 103 | throw(HOM_OperationFailed, HOM_PermissionError) 104 | { 105 | // This is the function that does the actual work. It takes a path 106 | // to the object node and a flag to say if it should be selectable. 107 | // 108 | // Look up the OBJ_Node for the path. 109 | OP_Node *op_node = OPgetDirector()->findNode(node_path); 110 | if (!op_node) 111 | throw HOM_OperationFailed("Internal error (could not find node)"); 112 | 113 | OBJ_Node *obj_node = op_node->castToOBJNode(); 114 | if (!obj_node) 115 | throw HOM_OperationFailed("Internal error (node is not an object)"); 116 | 117 | // Now that we have the OBJ_Node object, we can access anything exposed 118 | // by the HDK. For this example, we simply need to call setPickable(). 119 | // First, though, we create an undo block, so that any operations called 120 | // by setPickable will be put into this block. 121 | UT_AutoUndoBlock undo_block("Setting selectable flag", ANYLEVEL); 122 | 123 | // If this node is inside a locked asset, we want to raise a Python 124 | // hou.PermissionError exception. To do that, we simply throw an instance 125 | // of the C++ HOM_PermissionError class. 126 | if (!obj_node->canAccess(PRM_WRITE_OK)) 127 | throw HOM_PermissionError(); 128 | 129 | obj_node->setPickable(selectable); 130 | } 131 | 132 | static PY_PyObject * 133 | createHouException( 134 | const char *exception_class_name, const char *instance_message, 135 | PY_PyObject *&exception_class) 136 | { 137 | // Create an instance of the given exception class from the hou 138 | // module, passing the instance message into the exeption class's 139 | // __init__ method. This function returns a new exception instance, or 140 | // NULL if an error occurred. The class is returned in exception_class 141 | // and is a borrowed reference. 142 | exception_class = NULL; 143 | 144 | // Note that a PY_AutoObject class is just a wrapper around a 145 | // PY_PyObject pointer that will call PY_Py_XDECREF when the it's destroyed. 146 | // We use it for Python API functions that return new object instances. 147 | // Because this HDK extension is installed after the hou module is 148 | // imported, we can be sure that we can be sure hou_module won't be null. 149 | PY_AutoObject hou_module(PY_PyImport_ImportModule("hou")); 150 | 151 | // Look up the exception by name in the module's dictionary. Note that 152 | // PY_PyModule_GetDict returns a borrowed reference and that it never 153 | // returns NULL. PY_PyDict_GetItemString also returns a borrowed 154 | // reference. 155 | PY_PyObject *hou_module_dict = PY_PyModule_GetDict(hou_module); 156 | exception_class = PY_PyDict_GetItemString( 157 | hou_module_dict, exception_class_name); 158 | 159 | // PY_PyDict_GetItemString doesn't set a Python exception, so we are careful 160 | // to set it ourselves if the class name isn't valid. 161 | if (!exception_class) 162 | { 163 | PY_PyErr_SetString( 164 | PY_PyExc_RuntimeError(), 165 | "Could not find exception class in hou module"); 166 | return NULL; 167 | } 168 | 169 | // Create an instance of the exception. First create a tuple containing 170 | // the arguments to __init__. 171 | PY_AutoObject args(PY_Py_BuildValue("(s)", instance_message)); 172 | if (!args) 173 | return NULL; 174 | 175 | return PY_PyObject_Call(exception_class, args, /*kwargs=*/NULL); 176 | } 177 | 178 | static PY_PyObject * 179 | ObjNode_setSelectable_Wrapper(PY_PyObject *self, PY_PyObject *args) 180 | { 181 | // This is a wrapper that is called from the Python runtime engine. It 182 | // translates the Python arguments to C/C++ ones, calls a function to do 183 | // the actual work, and converts exceptions raised by that function into 184 | // Python exceptions. 185 | // 186 | // Note that you could also use swig to automatically generate wrapper 187 | // functions like this. 188 | // 189 | // Since this function is called from the Python runtime engine, we 190 | // don't need to manually acquire the Python global interpreter lock (GIL). 191 | 192 | // First extract the arguments: a string and an integer (bool). 193 | const char *node_path; 194 | int selectable; 195 | if (!PY_PyArg_ParseTuple(args, "si", &node_path, &selectable)) 196 | return NULL; 197 | 198 | // Now call ObjNode_setSelectable to do the actual work, taking care 199 | // of the locking and exception handling here. 200 | try 201 | { 202 | // If this code is called from a thread other than the main thread, 203 | // creating a HOM_AutoLock instance will lock, waiting until Houdini 204 | // is sitting idle in its event loop. This way, we can be sure that 205 | // any code that accesses Houdini's internal state is threadsafe. 206 | HOM_AutoLock hom_lock; 207 | 208 | // Call the wrapped function to do the actual work. 209 | ObjNode_setSelectable(node_path, (bool)selectable); 210 | 211 | // Return PY_Py_None to indicate that no error occurred. If your 212 | // wrapped function returns a value, you'll need to convert it into 213 | // a Python object here. 214 | return PY_Py_None(); 215 | } 216 | catch (HOM_Error &error) 217 | { 218 | // The exceptions used by the hou module are subclasses of HOM_Error 219 | // (and can be found in HOM_Errors.h). We use RTTI to get the class 220 | // name, remove the "HOM_" prefix, and look up the corresponding 221 | // exception class in the hou Python module. 222 | std::string exception_class_name = UTunmangleClassNameFromTypeIdName( 223 | typeid(error).name()); 224 | if (exception_class_name.find("HOM_") == 0) 225 | exception_class_name = exception_class_name.substr(4); 226 | 227 | // Note that a PY_AutoObject class is just a wrapper around a 228 | // PY_PyObject pointer that will call PY_Py_XDECREF when the it's 229 | // destroyed. 230 | PY_PyObject *exception_class; 231 | PY_AutoObject exception_instance(createHouException( 232 | exception_class_name.c_str(), error.instanceMessage().c_str(), 233 | exception_class)); 234 | if (!exception_instance) 235 | return NULL; 236 | 237 | // Set the exception and return NULL so Python knows an exception was 238 | // raised. 239 | PY_PyErr_SetObject(exception_class, exception_instance); 240 | return NULL; 241 | } 242 | } 243 | 244 | void 245 | HOMextendLibrary() 246 | { 247 | // This function installs the C++ HOM extension. When the hou module is 248 | // first imported, Houdini will call functions named HOMextendLibrary in 249 | // HDK dso's. This function is declared in an extern "C" in HOM_Module.h. 250 | 251 | { 252 | // A PY_InterpreterAutoLock will grab the Python global interpreter 253 | // lock (GIL). It's important that we have the GIL before making 254 | // any calls into the Python API. 255 | PY_InterpreterAutoLock interpreter_auto_lock; 256 | 257 | // We'll create a new module named "_hom_extensions", and add functions 258 | // to it. We don't give a docstring here because it's given in the 259 | // Python implementation below. 260 | static PY_PyMethodDef hom_extension_methods[] = { 261 | {"ObjNode_setSelectable", ObjNode_setSelectable_Wrapper, 262 | PY_METH_VARARGS(), ""}, 263 | { NULL, NULL, 0, NULL } 264 | }; 265 | 266 | PY_Py_InitModule("_hom_extensions", hom_extension_methods); 267 | } 268 | 269 | // Run some Python code to add a method to the hou.ObjectNode class that 270 | // will call our custom function. We create a Python function 271 | // that takes in a hou.ObjNode instance. That function calls path() 272 | // on the instance to get the full path to the object node, and passes 273 | // that path and other arguments to the function in the _hom_extensions 274 | // module. Then that function is assigned to a method in hou.ObjNode 275 | // and the function's name is removed from the global dictionary. 276 | PYrunPythonStatementsAndExpectNoErrors( 277 | "def _setSelectable(self, selectable):\n" 278 | " '''Make this node selectable/unselectable in the viewport\n" 279 | " and network editor.'''\n" 280 | " import _hom_extensions\n" 281 | " _hom_extensions.ObjNode_setSelectable(self.path(), selectable)\n" 282 | "__import__('hou').ObjNode.setSelectable = _setSelectable\n" 283 | "del _setSelectable\n"); 284 | } 285 | 286 | -------------------------------------------------------------------------------- /HOM/SOP_HOMWave.C: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | *---------------------------------------------------------------------------- 26 | * This SOP provides an example of how to access HOM from C++. 27 | * 28 | * NOTE: 29 | * See SOP_HOMWave.py for a pure Python implementation of this SOP. 30 | */ 31 | 32 | /// This SOP provides an example of how to access HOM from C++. See 33 | /// SOP_HOMWave.py and related files for a pure Python implementation of this 34 | /// SOP. 35 | /// @see @ref HOM/SOP_HOMWave.py, @ref HOM/SOP_HOMWaveNumpy.py, @ref HOM/SOP_HOMWaveInlinecpp.py, @ref SOP/SOP_CPPWave.C, @ref SOP/SOP_VEXWave.vfl 36 | 37 | #include 38 | #include "SOP_HOMWave.h" 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | 48 | using namespace HDK_Sample; 49 | 50 | void 51 | newSopOperator(OP_OperatorTable *table) 52 | { 53 | table->addOperator(new OP_Operator( 54 | "hom_wave", "HOM Wave", 55 | &SOP_HOMWave::myConstructor, SOP_HOMWave::myTemplateList, 56 | /*min_num_inputs=*/1, /*max_num_inputs=*/1)); 57 | } 58 | 59 | OP_Node * 60 | SOP_HOMWave::myConstructor(OP_Network *net, const char *name, OP_Operator *op) 61 | { 62 | return new SOP_HOMWave(net, name, op); 63 | } 64 | 65 | // List any of the sop's parameters here: 66 | PRM_Template 67 | SOP_HOMWave::myTemplateList[] = { 68 | PRM_Template(), 69 | }; 70 | 71 | SOP_HOMWave::SOP_HOMWave( 72 | OP_Network *network, const char *name, OP_Operator *op_type) 73 | : SOP_HOM(network, name, op_type) 74 | { 75 | } 76 | 77 | void 78 | SOP_HOMWave::cookWithHOM() 79 | { 80 | HOM_Module &hou = HOM(); 81 | 82 | // This C++ code does the equivalent of this Python code: 83 | // 84 | // import math 85 | // geo = hou.pwd().geometry() 86 | // f = hou.frame() * 0.03 87 | // for p in geo.points(): 88 | // pos = p.position() 89 | // pos[1] = math.sin(pos[0] * 0.2 + pos[2] * 0.3 + f) 90 | // p.setPosition(pos) 91 | // 92 | // It modifies the input geometry's y coordinate to create an animated 93 | // sin wave. Connect this sop to the output of a grid and press play. 94 | 95 | boost::shared_ptr geo(HOMdel( 96 | dynamic_cast(hou.pwd()))->geometry()); 97 | 98 | double f = hou.frame() * 0.03; 99 | std::vector > points = geo->points(); 100 | std::vector pos_vector(3); 101 | for (int i=0; i p(points[i].myPointer); 104 | 105 | boost::shared_ptr pos_ptr(p->position()); 106 | HOM_Vector3 &pos = *pos_ptr; 107 | pos[1] = sin(pos[0] * 0.2 + pos[2] * 0.3 + f); 108 | 109 | for (int i=0; i<3; ++i) 110 | pos_vector[i] = pos[i]; 111 | p->setPosition(pos_vector); 112 | } 113 | } 114 | 115 | -------------------------------------------------------------------------------- /HOM/SOP_HOMWave.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | *---------------------------------------------------------------------------- 26 | * This SOP provides an example of how to access HOM from C++. 27 | */ 28 | 29 | #ifndef __SOP_HOMWave_h__ 30 | #define __SOP_HOMWave_h__ 31 | 32 | #include 33 | 34 | namespace HDK_Sample { 35 | 36 | /// Example of using the C++ interface to HOM 37 | /// @see @ref HOM/SOP_HOMWave.py SOP_CPPWave, vex_wave() 38 | class SOP_HOMWave : public SOP_HOM 39 | { 40 | public: 41 | static OP_Node *myConstructor( 42 | OP_Network *network, const char *name, OP_Operator *op_type); 43 | 44 | static PRM_Template myTemplateList[]; 45 | 46 | private: 47 | SOP_HOMWave( 48 | OP_Network *network, const char *name, OP_Operator *script_op_type); 49 | 50 | // Override this method to provide the algorithm for the cook. 51 | virtual void cookWithHOM(); 52 | }; 53 | 54 | } // End HDK_Sample namespace 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /HOM/SOP_HOMWave.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2014 3 | # Side Effects Software Inc. All rights reserved. 4 | # 5 | # Redistribution and use of Houdini Development Kit samples in source and 6 | # binary forms, with or without modification, are permitted provided that the 7 | # following conditions are met: 8 | # 1. Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # 2. The name of Side Effects Software may not be used to endorse or 11 | # promote products derived from this software without specific prior 12 | # written permission. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | # NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | # 25 | #---------------------------------------------------------------------------- 26 | # This SOP provides an example of a SOP implemented in Python. 27 | # 28 | 29 | """This is the Python equivalent of SOP_HOMWave.C which uses the C++ API. 30 | 31 | To use this code, 32 | 1) In Houdini, choose File -> New Operator Type 33 | 2) Choose "Python Type" 34 | 3) Choose the network type as "Geometry Operator" 35 | 4) Paste this code in the "Code" tab of the type properties. 36 | 37 | @see @ref HOM/SOP_HOMWaveNumpy.py, @ref HOM/SOP_HOMWaveInlinecpp.py, @ref HOM/SOP_HOMWave.C, @ref SOP/SOP_CPPWave.C, @ref SOP/SOP_VEXWave.vfl 38 | """ 39 | 40 | import math 41 | 42 | geo = hou.pwd().geometry() 43 | f = hou.frame() * 0.03 44 | for p in geo.points(): 45 | pos = p.position() 46 | pos[1] = math.sin(pos[0] * 0.2 + pos[2] * 0.3 + f) 47 | p.setPosition(pos) 48 | 49 | -------------------------------------------------------------------------------- /HOM/SOP_HOMWaveInlinecpp.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2014 3 | # Side Effects Software Inc. All rights reserved. 4 | # 5 | # Redistribution and use of Houdini Development Kit samples in source and 6 | # binary forms, with or without modification, are permitted provided that the 7 | # following conditions are met: 8 | # 1. Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # 2. The name of Side Effects Software may not be used to endorse or 11 | # promote products derived from this software without specific prior 12 | # written permission. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | # NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | # 25 | #---------------------------------------------------------------------------- 26 | # This SOP provides an example of a SOP implemented in Python that uses the 27 | # inlinecpp module to speed it up with C++ embedded code. See also 28 | # SOP_HOMWave.py for a pure-Python implementation, SOP_HOMWave.C for an all-C++ 29 | # implementation using the HOM C++ API and SOP_CPPWave.C for an all-C++ 30 | # implementation using the HDK C++ API. 31 | # 32 | 33 | """This is the accelerated equivalent of SOP_HOMWave.py. It implements the 34 | same SOP but runs approximately 40x faster. 35 | 36 | To use this code, 37 | 1) In Houdini, choose File -> New Operator Type 38 | 2) Choose "Python Type" 39 | 3) Choose the network type as "Geometry Operator" 40 | 4) Paste this code in the "Code" tab of the type properties. 41 | 42 | @see @ref HOM/SOP_HOMWave.py, @ref HOM/SOP_HOMWaveNumpy.py, @ref HOM/SOP_HOMWave.C, @ref SOP/SOP_CPPWave.C, @ref SOP/SOP_VEXWave.vfl 43 | """ 44 | 45 | import inlinecpp 46 | 47 | inlinecpp.extendClass( 48 | hou.Geometry, "sop_homwave_code", function_sources=[""" 49 | void wave(GU_Detail *gdp, double f) 50 | { 51 | GA_Offset ptoff; 52 | GA_FOR_ALL_PTOFF(gdp, ptoff) 53 | { 54 | UT_Vector3 pos = gdp->getPos3(ptoff); 55 | pos.y() = sin(pos.x() * 0.2 + pos.z() * 0.3 + f); 56 | gdp->setPos3(ptoff, pos); 57 | } 58 | } 59 | """]) 60 | hou.pwd().geometry().wave(hou.frame() * 0.03) 61 | 62 | -------------------------------------------------------------------------------- /HOM/SOP_HOMWaveNumpy.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2014 3 | # Side Effects Software Inc. All rights reserved. 4 | # 5 | # Redistribution and use of Houdini Development Kit samples in source and 6 | # binary forms, with or without modification, are permitted provided that the 7 | # following conditions are met: 8 | # 1. Redistributions of source code must retain the above copyright notice, 9 | # this list of conditions and the following disclaimer. 10 | # 2. The name of Side Effects Software may not be used to endorse or 11 | # promote products derived from this software without specific prior 12 | # written permission. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | # NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | # 25 | #---------------------------------------------------------------------------- 26 | # This SOP provides an example of a SOP implemented in Python and accelerated 27 | # with Python's numpy module. 28 | # 29 | 30 | """This is the equivalent of SOP_HOMWave.py but uses numpy to speed it up. 31 | 32 | To use this code, 33 | 1) In Houdini, choose File -> New Operator Type 34 | 2) Choose "Python Type" 35 | 3) Choose the network type as "Geometry Operator" 36 | 4) Paste this code in the "Code" tab of the type properties. 37 | 38 | @see @ref HOM/SOP_HOMWave.py, @ref HOM/SOP_HOMWaveInlinecpp.py, @ref HOM/SOP_HOMWave.C, @ref SOP/SOP_CPPWave.C, @ref SOP/SOP_VEXWave.vfl 39 | """ 40 | 41 | import numpy 42 | 43 | geo = hou.pwd().geometry() 44 | positions = numpy.frombuffer( 45 | geo.pointFloatAttribValuesAsString("P"), dtype="f4,f4,f4").copy() 46 | positions.dtype.names = ("x", "y", "z") 47 | 48 | positions["y"] = numpy.sin( 49 | positions["x"] * 0.2 + positions["z"] * 0.3 + hou.frame() * 0.03) 50 | geo.setPointFloatAttribValuesFromString("P", positions) 51 | 52 | -------------------------------------------------------------------------------- /OBJ/OBJ_Lamp.C: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | *---------------------------------------------------------------------------- 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | // 34 | // This file just makes another entry in the object operator table 35 | // for an object that behaves exactly like the standard light, but 36 | // has a different name, icon, default setup, and parameter dialog. 37 | // 38 | 39 | void 40 | newObjectOperator(OP_OperatorTable *table) 41 | { 42 | table->addOperator(new OP_Operator("hdk_lamp", "Lamp", 43 | OBJ_Light::myConstructor, 44 | OBJ_Light::getTemplateList(OBJ_PARMS_PLAIN), 0, 1, 45 | 0)); 46 | } 47 | -------------------------------------------------------------------------------- /OBJ/OBJ_Shake.C: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | *---------------------------------------------------------------------------- 26 | * This custom object defines a geometry object that has parameters which 27 | * define a frame-dependent jitter in its translation. This can be used to make 28 | * earth-quake type effects. No doubt next year will be the year of the 29 | * Earthquake movie. 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "OBJ_Shake.h" 38 | 39 | 40 | using namespace HDK_Sample; 41 | 42 | // shakeIndirect is an array of indices that are used to access parameters 43 | // quickly. The indices are initialized by the EVAL_FLOAT methods in the 44 | // header file. 45 | int *OBJ_Shake::shakeIndirect = 0; 46 | 47 | 48 | 49 | // Constructor for new object class 50 | OBJ_Shake::OBJ_Shake(OP_Network *net, const char *name, OP_Operator *op) 51 | :OBJ_Geometry(net, name, op) 52 | { 53 | // initialize local member data here. 54 | 55 | // shakeIndirect is initialized to an array of 1 index (each initialized 56 | // to -1 -- ie not accessed yet). 57 | // 58 | // The base class, OBJ_Geometry, uses its own class static indirect array. 59 | // We don't have to worry about this as long as we don't change the order 60 | // of these base parameters in our template list. If we were to change 61 | // the order of these base parameters, then we would need to override the 62 | // getIndirect() method to ensure our class static indirect array is used. 63 | // In that case, we'd need to ensure it was large enough to handle all of 64 | // the base parameters as well (i.e. allocIndirect(I_N_GEO_INDICES + 1). 65 | if (!shakeIndirect) shakeIndirect = allocIndirect(1); 66 | } 67 | 68 | 69 | 70 | // virtual destructor for new object class 71 | OBJ_Shake::~OBJ_Shake() 72 | { 73 | } 74 | 75 | 76 | // Un-comment the next line to see an example of creating custom tabs 77 | //#define SWITCHER_EXAMPLE 78 | #ifdef SWITCHER_EXAMPLE 79 | static PRM_Name switcherName("shakeswitcher"); 80 | static PRM_Default switcher[] = { 81 | PRM_Default( 1, "Shake"), // 1 is number of parameters in tab 82 | PRM_Default( 0, "Other"), // actually have no parameters here 83 | }; 84 | #endif 85 | 86 | // here is the name of the parameter that is used by the shake object 87 | static PRM_Name OBJjitter("jitter", "Jitter Scale"); 88 | 89 | 90 | 91 | // this is the template list that defines the new parameters that are 92 | // used by the shake object. 93 | static PRM_Template templatelist[] = 94 | { 95 | // Here we define the new parameter 96 | #ifdef SWITCHER_EXAMPLE 97 | PRM_Template(PRM_SWITCHER, sizeof(switcher)/sizeof(PRM_Default), 98 | &switcherName, switcher), 99 | #endif 100 | PRM_Template(PRM_XYZ_J, 3, &OBJjitter, PRMoneDefaults), 101 | 102 | // followed by this blank terminating Template. 103 | PRM_Template() 104 | }; 105 | 106 | 107 | 108 | // this function returns the OP_TemplatePair that combines the parameters 109 | // of this object with those of its ancestors in the (object type hierarchy) 110 | OP_TemplatePair * 111 | OBJ_Shake::buildTemplatePair(OP_TemplatePair *prevstuff) 112 | { 113 | OP_TemplatePair *shake, *geo; 114 | 115 | // Here, we have to "inherit" template pairs from geometry and beyond. To 116 | // do this, we first need to instantiate our template list, then add the 117 | // base class templates. 118 | shake = new OP_TemplatePair(templatelist, prevstuff); 119 | geo = new OP_TemplatePair(OBJ_Geometry::getTemplateList(OBJ_PARMS_PLAIN), 120 | shake); 121 | return geo; 122 | } 123 | 124 | 125 | 126 | // the myConstructor method is used to create new objects of the correct 127 | // type from the OperatorTable. 128 | OP_Node * 129 | OBJ_Shake::myConstructor(OP_Network *net, const char *name, OP_Operator *op) 130 | { 131 | return new OBJ_Shake(net, name, op); 132 | } 133 | 134 | 135 | 136 | // this method pre-multiplies the given matrix with an appropriate transform 137 | // to shake the object. our shake transform gets inserted into the object 138 | // transform pipeline essentially before the transform parameters. 139 | int 140 | OBJ_Shake::applyInputIndependentTransform(OP_Context &context, UT_DMatrix4 &mat) 141 | { 142 | const fpreal t = context.getTime(); // extract time from OP_Context 143 | fpreal jx, jy, jz; 144 | unsigned seed; 145 | int modified; 146 | 147 | // call OBJ_Geometry::applyInputIndependentTransform() so that we don't 148 | // lose any information 149 | modified = OBJ_Geometry::applyInputIndependentTransform(context, mat); 150 | if (error() >= UT_ERROR_ABORT) 151 | { 152 | // don't do anything since an error has occurred. 153 | return modified; 154 | } 155 | 156 | // first we compute our jitter values as a random value within 157 | // the given jitter scale using a frame dependent seed value 158 | // (different for x, y, and z) 159 | jx = JX(t); jy = JY(t); jz = JZ(t); 160 | 161 | seed = (int)OPgetDirector()->getChannelManager()->getSample(t); 162 | jx *= 2*SYSfastRandom(seed) - 1.0; 163 | 164 | seed ^= 0xdeadbeef; 165 | jy *= 2*SYSfastRandom(seed) - 1.0; 166 | 167 | seed ^= 0xfadedcab; 168 | jz *= 2*SYSfastRandom(seed) - 1.0; 169 | 170 | // we add our jitter to the object transform 171 | mat.pretranslate(jx, jy, jz); 172 | 173 | // since the jitter value is frame dependent and this object won't 174 | // be flagged as time dependent through any other method, we need to 175 | // explicitly flag it here. 176 | // NB: this flag gets reset at the beginning of every cook, unless 177 | // tranform caching is enabled by the object parameter. 178 | // When transforms are cached, this flag is cleared before the cook on 179 | // which there was a miss that invalidated all cached transforms for 180 | // that object. 181 | flags().setTimeDep(true); 182 | 183 | // return 1 to indicate that we have modified the input matrix. 184 | // if we didn't modify mat, then we should return 0 instead. 185 | return 1; 186 | } 187 | 188 | 189 | 190 | // this function installs the new object in houdini's object table. 191 | void 192 | newObjectOperator(OP_OperatorTable *table) 193 | { 194 | table->addOperator(new OP_Operator("hdk_shake", "Shake", 195 | OBJ_Shake::myConstructor, 196 | OBJ_Shake::buildTemplatePair(0), 0, 1, 197 | 0)); 198 | } 199 | -------------------------------------------------------------------------------- /OBJ/OBJ_Shake.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | *---------------------------------------------------------------------------- 26 | * This custom object defines a geometry object that has parameters which 27 | * define a frame-dependent jitter in its translation. This can be used to make 28 | * earth-quake type effects. No doubt next year will be the year of the 29 | * Earthquake movie. 30 | */ 31 | 32 | #ifndef __OBJ_Shake__ 33 | #define __OBJ_Shake__ 34 | 35 | #include 36 | 37 | namespace HDK_Sample { 38 | 39 | class OBJ_Shake : public OBJ_Geometry 40 | { 41 | public: 42 | OBJ_Shake(OP_Network *net, 43 | const char *name, 44 | OP_Operator *op); 45 | virtual ~OBJ_Shake(); 46 | 47 | static OP_Node *myConstructor(OP_Network *net, 48 | const char *name, 49 | OP_Operator *entry); 50 | 51 | static OP_TemplatePair *buildTemplatePair(OP_TemplatePair *prevstuff); 52 | 53 | fpreal JX(fpreal t) { return evalFloat("jitter", &shakeIndirect[0], 0, t); } 54 | fpreal JY(fpreal t) { return evalFloat("jitter", &shakeIndirect[0], 1, t); } 55 | fpreal JZ(fpreal t) { return evalFloat("jitter", &shakeIndirect[0], 2, t); } 56 | 57 | protected: 58 | virtual int applyInputIndependentTransform( 59 | OP_Context &context, UT_DMatrix4 &mat); 60 | 61 | private: 62 | static int *shakeIndirect; 63 | }; 64 | 65 | } // End HDK_Sample namespace 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /OBJ/OBJ_hdk_lamp.icon: -------------------------------------------------------------------------------- 1 | 2 | # Path_0 3 | color(-153); 4 | bgnpolygon(); 5 | vertex(0.00, 100.00); 6 | vertex(100.00, 100.00); 7 | vertex(100.00, 0.00); 8 | vertex(0.00, 0.00); 9 | endpolygon(); 10 | 11 | # Path_0 12 | color(iconcolor); 13 | bgnpolygon(); 14 | vertex(65.00, 72.50); 15 | vertex(60.00, 90.00); 16 | vertex(70.00, 85.00); 17 | endpolygon(); 18 | 19 | # Path_1 20 | color(-119); 21 | bgnpolygon(); 22 | vertex(65.00, 72.50); 23 | vertex(47.50, 76.25); 24 | vertex(50.00, 90.00); 25 | vertex(60.00, 90.00); 26 | endpolygon(); 27 | 28 | # Path_2 29 | color(iconcolor); 30 | bgnpolygon(); 31 | vertex(32.50, 76.25); 32 | vertex(47.50, 76.25); 33 | vertex(50.00, 90.00); 34 | vertex(40.00, 90.00); 35 | endpolygon(); 36 | 37 | # Path_3 38 | color(-136); 39 | bgnpolygon(); 40 | vertex(40.00, 90.00); 41 | vertex(30.00, 85.00); 42 | vertex(32.50, 76.25); 43 | endpolygon(); 44 | 45 | # Path_4 46 | color(-128); 47 | bgnoutlinepolygon(); 48 | vertex(40.00, 35.00); 49 | vertex(42.50, 48.75); 50 | vertex(57.50, 48.75); 51 | vertex(60.00, 35.00); 52 | vertex(65.00, 27.50); 53 | vertex(65.00, 15.00); 54 | vertex(55.00, 7.50); 55 | vertex(45.00, 7.50); 56 | vertex(35.00, 15.00); 57 | vertex(35.00, 27.50); 58 | endoutlinepolygon(outlinecolor); 59 | 60 | # Path_5 61 | color(outlinecolor); 62 | bgnclosedline(); 63 | vertex(50.00, 90.00); 64 | vertex(40.00, 90.00); 65 | vertex(30.00, 85.00); 66 | vertex(40.00, 80.00); 67 | vertex(50.00, 80.00); 68 | vertex(60.00, 80.00); 69 | vertex(70.00, 85.00); 70 | vertex(60.00, 90.00); 71 | endclosedline(); 72 | 73 | # Path_6 74 | color(iconcolor); 75 | bgnpolygon(); 76 | vertex(30.00, 40.00); 77 | vertex(15.00, 47.50); 78 | vertex(30.00, 85.00); 79 | vertex(40.00, 80.00); 80 | endpolygon(); 81 | 82 | # Path_7 83 | color(-119); 84 | bgnpolygon(); 85 | vertex(50.00, 37.50); 86 | vertex(30.00, 40.00); 87 | vertex(40.00, 80.00); 88 | vertex(50.00, 80.00); 89 | endpolygon(); 90 | 91 | # Path_8 92 | color(-255); 93 | bgnpolygon(); 94 | vertex(70.00, 85.00); 95 | vertex(60.00, 80.00); 96 | vertex(70.00, 40.00); 97 | vertex(85.00, 47.50); 98 | endpolygon(); 99 | 100 | # Path_9 101 | color(iconcolor); 102 | bgnpolygon(); 103 | vertex(70.00, 40.00); 104 | vertex(50.00, 37.50); 105 | vertex(50.00, 80.00); 106 | vertex(60.00, 80.00); 107 | endpolygon(); 108 | 109 | # Path_10 110 | color(outlinecolor); 111 | bgnclosedline(); 112 | vertex(30.00, 85.00); 113 | vertex(40.00, 80.00); 114 | vertex(50.00, 80.00); 115 | vertex(60.00, 80.00); 116 | vertex(70.00, 85.00); 117 | vertex(85.00, 47.50); 118 | vertex(70.00, 40.00); 119 | vertex(50.00, 37.50); 120 | vertex(30.00, 40.00); 121 | vertex(15.00, 47.50); 122 | endclosedline(); 123 | -------------------------------------------------------------------------------- /OBJ/OBJ_hdk_shake.icon: -------------------------------------------------------------------------------- 1 | 2 | # Path_0 3 | color(0); 4 | bgnline(); 5 | vertex(20.50, 57.40); 6 | vertex(18.70, 67.20); 7 | vertex(18.90, 75.80); 8 | vertex(27.10, 87.00); 9 | endline(); 10 | 11 | # Path_1 12 | color(outlinecolor); 13 | bgnline(); 14 | vertex(18.90, 18.20); 15 | vertex(16.10, 29.20); 16 | vertex(19.10, 38.20); 17 | endline(); 18 | 19 | # Path_2 20 | bgnline(); 21 | vertex(84.30, 18.80); 22 | vertex(88.10, 37.80); 23 | vertex(86.10, 46.80); 24 | endline(); 25 | 26 | # Path_3 27 | color(0); 28 | bgnline(); 29 | vertex(84.10, 66.00); 30 | vertex(81.30, 83.00); 31 | vertex(74.50, 88.20); 32 | endline(); 33 | 34 | # Path_4 35 | color(outlinecolor); 36 | bgnline(); 37 | vertex(88.90, 78.00); 38 | vertex(87.30, 83.20); 39 | vertex(85.30, 88.20); 40 | endline(); 41 | 42 | # Path_5 43 | bgnline(); 44 | vertex(94.80, 29.60); 45 | vertex(94.60, 37.40); 46 | endline(); 47 | 48 | # Path_6 49 | bgnline(); 50 | vertex(8.70, 25.00); 51 | vertex(9.30, 35.80); 52 | endline(); 53 | 54 | # Path_7 55 | bgnline(); 56 | vertex(12.30, 68.00); 57 | vertex(11.10, 75.40); 58 | vertex(14.10, 83.80); 59 | endline(); 60 | 61 | # Path_8 62 | color(0); 63 | bgnpolygon(); 64 | vertex(38.30, 10.60); 65 | vertex(25.50, 19.80); 66 | vertex(27.50, 34.20); 67 | vertex(43.50, 24.80); 68 | endpolygon(); 69 | 70 | # Path_9 71 | bgnpolygon(); 72 | vertex(60.90, 25.40); 73 | vertex(43.50, 24.80); 74 | vertex(38.30, 10.60); 75 | vertex(66.50, 10.20); 76 | endpolygon(); 77 | 78 | # Path_10 79 | bgnpolygon(); 80 | vertex(66.50, 10.20); 81 | vertex(78.70, 26.20); 82 | vertex(69.10, 33.60); 83 | vertex(60.90, 25.40); 84 | endpolygon(); 85 | 86 | # Path_11 87 | bgnpolygon(); 88 | vertex(67.90, 44.20); 89 | vertex(76.50, 52.80); 90 | vertex(78.70, 26.20); 91 | vertex(69.10, 33.60); 92 | endpolygon(); 93 | 94 | # Path_12 95 | bgnpolygon(); 96 | vertex(67.90, 44.20); 97 | vertex(58.90, 49.00); 98 | vertex(60.90, 60.00); 99 | vertex(76.50, 52.80); 100 | endpolygon(); 101 | 102 | # Path_13 103 | bgnpolygon(); 104 | vertex(58.90, 49.00); 105 | vertex(39.80, 49.20); 106 | vertex(45.30, 61.00); 107 | vertex(60.90, 60.00); 108 | endpolygon(); 109 | 110 | # Path_14 111 | bgnpolygon(); 112 | vertex(39.80, 49.20); 113 | vertex(27.70, 63.00); 114 | vertex(39.90, 68.40); 115 | vertex(45.30, 61.00); 116 | endpolygon(); 117 | 118 | # Path_15 119 | bgnpolygon(); 120 | vertex(30.30, 80.20); 121 | vertex(45.70, 89.60); 122 | vertex(44.70, 76.60); 123 | vertex(39.90, 68.40); 124 | vertex(27.70, 63.00); 125 | endpolygon(); 126 | 127 | # Path_16 128 | bgnpolygon(); 129 | vertex(45.70, 89.60); 130 | vertex(63.40, 87.60); 131 | vertex(56.70, 78.40); 132 | vertex(44.70, 76.60); 133 | endpolygon(); 134 | 135 | # Path_17 136 | bgnpolygon(); 137 | vertex(56.70, 78.40); 138 | vertex(64.90, 75.00); 139 | vertex(75.00, 78.20); 140 | vertex(63.40, 87.60); 141 | endpolygon(); 142 | 143 | # Path_18 144 | bgnpolygon(); 145 | vertex(64.90, 75.00); 146 | vertex(69.90, 66.40); 147 | vertex(77.10, 66.60); 148 | vertex(75.00, 78.20); 149 | endpolygon(); 150 | -------------------------------------------------------------------------------- /OBJ/deflamp.bgeo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wahn/Houdini_HDK_Examples/750cd7599e9eb9a979a78fee14537d7ad723e9af/OBJ/deflamp.bgeo -------------------------------------------------------------------------------- /OBJ/hdk_lamp.cmd: -------------------------------------------------------------------------------- 1 | # Default script run when a lamp object is created. 2 | 3 | if ( "$arg1" != "" ) then 4 | set saved_path = `execute("oppwf")` 5 | opcf /obj/$arg1 6 | 7 | opadd file file1 8 | opparm file1 file 'deflamp.bgeo' 9 | oplocate -x 0.18 -y 3.0 file1 10 | 11 | opcf $saved_path 12 | endif 13 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | To get started: http://www.sidefx.com/docs/hdk15.0 2 | 3 | Several examples from the documentation or other sources (e.g. od[force] - 4 | http://odforce.net) will be collected here. 5 | 6 | -------------------------------------------------------------------------------- /ROP/README: -------------------------------------------------------------------------------- 1 | # before compiling ROP_Radiance: 2 | setenv SESI_TAGINFO "Produced by: Jan Walter (http://www.janwalter.com)" 3 | # compile 4 | hcustom -e ROP_Radiance.C 5 | # check with sesitag 6 | sesitag /Users/wahn/Library/Preferences/houdini/12.1/dso/ROP_Radiance.dylib 7 | 8 | -------------------------------------------------------------------------------- /ROP/ROP_DopField.C: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include "ROP_DopField.h" 45 | 46 | using namespace HDK_Sample; 47 | 48 | static PRM_Name dopPathName("doppath", "DOP Path"); 49 | static PRM_Name theObjectName("dopobject", "DOP Object"); 50 | static PRM_Name theDataName("dopdata", "DOP Data"); 51 | static PRM_Name theFileName("file", "Output File"); 52 | static PRM_Default theFileDefault(0, "$HIP/$F.bgeo"); 53 | static PRM_Name alfprogressName("alfprogress", "Alfred Style Progress"); 54 | 55 | 56 | static PRM_Name collateName("collatevector", "Collate Vector Fields"); 57 | 58 | static PRM_Template f3dTemplates[] = { 59 | PRM_Template(PRM_STRING, PRM_TYPE_DYNAMIC_PATH, 1, &dopPathName, 60 | 0, 0, 0, 0, &PRM_SpareData::dopPath), 61 | PRM_Template(PRM_FILE, 1, &theFileName, &theFileDefault,0, 62 | 0, 0, &PRM_SpareData::fileChooserModeWrite), 63 | PRM_Template(PRM_TOGGLE, 1, &alfprogressName, PRMzeroDefaults), 64 | 65 | PRM_Template(PRM_STRING, 1, &theObjectName), 66 | PRM_Template(PRM_STRING, 1, &theDataName), 67 | PRM_Template() 68 | 69 | }; 70 | 71 | static PRM_Template * 72 | getTemplates() 73 | { 74 | static PRM_Template *theTemplate = 0; 75 | 76 | if (theTemplate) 77 | return theTemplate; 78 | 79 | theTemplate = new PRM_Template[ROP_DOPFIELD_MAXPARMS+1]; 80 | theTemplate[ROP_DOPFIELD_RENDER] = theRopTemplates[ROP_RENDER_TPLATE]; 81 | theTemplate[ROP_DOPFIELD_RENDER_CTRL] = theRopTemplates[ROP_RENDERDIALOG_TPLATE]; 82 | theTemplate[ROP_DOPFIELD_TRANGE] = theRopTemplates[ROP_TRANGE_TPLATE]; 83 | theTemplate[ROP_DOPFIELD_FRANGE] = theRopTemplates[ROP_FRAMERANGE_TPLATE]; 84 | theTemplate[ROP_DOPFIELD_TAKE] = theRopTemplates[ROP_TAKENAME_TPLATE]; 85 | theTemplate[ROP_DOPFIELD_DOPPATH] = f3dTemplates[0]; 86 | theTemplate[ROP_DOPFIELD_DOPOUTPUT] = f3dTemplates[1]; 87 | theTemplate[ROP_DOPFIELD_DOPOBJECT] = f3dTemplates[3]; 88 | theTemplate[ROP_DOPFIELD_DOPDATA] = f3dTemplates[4]; 89 | theTemplate[ROP_DOPFIELD_INITSIM] = theRopTemplates[ROP_IFD_INITSIM_TPLATE]; 90 | theTemplate[ROP_DOPFIELD_ALFPROGRESS] = f3dTemplates[2]; 91 | theTemplate[ROP_DOPFIELD_TPRERENDER] = theRopTemplates[ROP_TPRERENDER_TPLATE]; 92 | theTemplate[ROP_DOPFIELD_PRERENDER] = theRopTemplates[ROP_PRERENDER_TPLATE]; 93 | theTemplate[ROP_DOPFIELD_LPRERENDER] = theRopTemplates[ROP_LPRERENDER_TPLATE]; 94 | theTemplate[ROP_DOPFIELD_TPREFRAME] = theRopTemplates[ROP_TPREFRAME_TPLATE]; 95 | theTemplate[ROP_DOPFIELD_PREFRAME] = theRopTemplates[ROP_PREFRAME_TPLATE]; 96 | theTemplate[ROP_DOPFIELD_LPREFRAME] = theRopTemplates[ROP_LPREFRAME_TPLATE]; 97 | theTemplate[ROP_DOPFIELD_TPOSTFRAME] = theRopTemplates[ROP_TPOSTFRAME_TPLATE]; 98 | theTemplate[ROP_DOPFIELD_POSTFRAME] = theRopTemplates[ROP_POSTFRAME_TPLATE]; 99 | theTemplate[ROP_DOPFIELD_LPOSTFRAME] = theRopTemplates[ROP_LPOSTFRAME_TPLATE]; 100 | theTemplate[ROP_DOPFIELD_TPOSTRENDER] = theRopTemplates[ROP_TPOSTRENDER_TPLATE]; 101 | theTemplate[ROP_DOPFIELD_POSTRENDER] = theRopTemplates[ROP_POSTRENDER_TPLATE]; 102 | theTemplate[ROP_DOPFIELD_LPOSTRENDER] = theRopTemplates[ROP_LPOSTRENDER_TPLATE]; 103 | theTemplate[ROP_DOPFIELD_MAXPARMS] = PRM_Template(); 104 | 105 | UT_ASSERT(PRM_Template::countTemplates(theTemplate) == ROP_DOPFIELD_MAXPARMS); 106 | 107 | return theTemplate; 108 | } 109 | 110 | OP_TemplatePair * 111 | ROP_DopField::getTemplatePair() 112 | { 113 | static OP_TemplatePair *ropPair = 0; 114 | if (!ropPair) 115 | { 116 | ropPair = new OP_TemplatePair(getTemplates()); 117 | } 118 | return ropPair; 119 | } 120 | 121 | OP_VariablePair * 122 | ROP_DopField::getVariablePair() 123 | { 124 | static OP_VariablePair *pair = 0; 125 | if (!pair) 126 | pair = new OP_VariablePair(ROP_Node::myVariableList); 127 | return pair; 128 | } 129 | 130 | OP_Node * 131 | ROP_DopField::myConstructor(OP_Network *net, const char *name, OP_Operator *op) 132 | { 133 | return new ROP_DopField(net, name, op); 134 | } 135 | 136 | ROP_DopField::ROP_DopField(OP_Network *net, const char *name, OP_Operator *entry) 137 | : ROP_Node(net, name, entry) 138 | { 139 | } 140 | 141 | 142 | ROP_DopField::~ROP_DopField() 143 | { 144 | } 145 | 146 | //------------------------------------------------------------------------------ 147 | // The startRender(), renderFrame(), and endRender() render methods are 148 | // invoked by Houdini when the ROP runs. 149 | 150 | int 151 | ROP_DopField::startRender(int /*nframes*/, fpreal tstart, fpreal tend) 152 | { 153 | int rcode = 1; 154 | 155 | myEndTime = tend; 156 | myStartTime = tstart; 157 | 158 | if (INITSIM()) 159 | { 160 | initSimulationOPs(); 161 | OPgetDirector()->bumpSkipPlaybarBasedSimulationReset(1); 162 | } 163 | 164 | if (error() < UT_ERROR_ABORT) 165 | { 166 | if( !executePreRenderScript(tstart) ) 167 | return 0; 168 | } 169 | 170 | return rcode; 171 | } 172 | 173 | static void 174 | addField(GU_Detail *gdp, const SIM_RawField *rawfield) 175 | { 176 | GU_PrimVolume *vol; 177 | 178 | vol = (GU_PrimVolume *) GU_PrimVolume::build(gdp); 179 | 180 | vol->getVertex().getPt()->setPos( 181 | rawfield->getOrig() + rawfield->getSize()*0.5 ); 182 | 183 | UT_Matrix3 scale; 184 | scale.identity(); 185 | scale.scale(rawfield->getSize().x(), rawfield->getSize().y(), rawfield->getSize().z()); 186 | scale.scale(0.5, 0.5, 0.5); 187 | vol->setTransform(scale); 188 | 189 | // If we use setVoxels, we'll have to make a copy of the field. 190 | // If we use steal, we can avoid this, but then we *must* leak 191 | // the gdp or we'll delete the field out from under DOPs. 192 | // vol->setVoxels(rawfield->fieldNC()); 193 | vol->stealVoxels(rawfield->fieldNC()); 194 | } 195 | 196 | ROP_RENDER_CODE 197 | ROP_DopField::renderFrame(fpreal time, UT_Interrupt *) 198 | { 199 | OP_Node *op; 200 | DOP_Parent *dopparent; 201 | UT_String doppath, savepath; 202 | UT_String dopobject, dopdata; 203 | 204 | if( !executePreFrameScript(time) ) 205 | return ROP_ABORT_RENDER; 206 | 207 | DOPPATH(doppath, time); 208 | 209 | if( !doppath.isstring() ) 210 | { 211 | addError(ROP_MESSAGE, "Invalid DOP path"); 212 | return ROP_ABORT_RENDER; 213 | } 214 | 215 | op = findNode(doppath); 216 | if (!op) 217 | { 218 | addError(ROP_COOK_ERROR, (const char *)doppath); 219 | return ROP_ABORT_RENDER; 220 | } 221 | 222 | dopparent = op ? op->castToDOPParent() : 0; 223 | if( !dopparent ) 224 | { 225 | addError(ROP_COOK_ERROR, (const char *)doppath); 226 | return ROP_ABORT_RENDER; 227 | } 228 | 229 | DOPOBJECT(dopobject, time); 230 | DOPDATA(dopdata, time); 231 | OUTPUT(savepath, time); 232 | 233 | 234 | time = DOPsetBestTime(dopparent, time); 235 | 236 | OP_Context context(time); 237 | 238 | const SIM_Object *object; 239 | object = dopparent->findObjectFromString(dopobject, 0, 0, time); 240 | 241 | if (!object) 242 | { 243 | addError(ROP_COOK_ERROR, (const char *)dopobject); 244 | return ROP_ABORT_RENDER; 245 | } 246 | 247 | const SIM_Data *data; 248 | 249 | data = object->getConstNamedSubData(dopdata); 250 | 251 | if (!data) 252 | { 253 | addError(ROP_COOK_ERROR, (const char *) dopdata); 254 | return ROP_ABORT_RENDER; 255 | } 256 | 257 | // Create our GDP. 258 | GU_Detail *gdp = new GU_Detail(); 259 | 260 | const SIM_ScalarField *scalarfield = SIM_DATA_CASTCONST(data, SIM_ScalarField); 261 | if (scalarfield) 262 | { 263 | addField(gdp, scalarfield->getField()); 264 | } 265 | const SIM_VectorField *vectorfield = SIM_DATA_CASTCONST(data, SIM_VectorField); 266 | if (vectorfield) 267 | { 268 | for (int i = 0; i < 3; i++) 269 | { 270 | addField(gdp, vectorfield->getField(i)); 271 | } 272 | } 273 | const SIM_MatrixField *matrixfield = SIM_DATA_CASTCONST(data, SIM_MatrixField); 274 | if (matrixfield) 275 | { 276 | for (int i = 0; i < 3; i++) 277 | for (int j = 0; j < 3; j++) 278 | { 279 | addField(gdp, matrixfield->getField(i, j)); 280 | } 281 | } 282 | 283 | if (!gdp->save((const char *)savepath, 0, 0).success()) 284 | { 285 | addError(ROP_SAVE_ERROR, (const char *)savepath); 286 | return ROP_ABORT_RENDER; 287 | } 288 | 289 | // DO NOT delete gdp if we are stealing the voxels! 290 | // delete gdp; 291 | 292 | if (ALFPROGRESS() && (myEndTime != myStartTime)) 293 | { 294 | fpreal fpercent = (time - myStartTime) / (myEndTime - myStartTime); 295 | int percent = (int)SYSrint(fpercent * 100); 296 | percent = SYSclamp(percent, 0, 100); 297 | fprintf(stdout, "ALF_PROGRESS %d%%\n", percent); 298 | fflush(stdout); 299 | } 300 | 301 | if (error() < UT_ERROR_ABORT) 302 | { 303 | if( !executePostFrameScript(time) ) 304 | return ROP_ABORT_RENDER; 305 | } 306 | 307 | return ROP_CONTINUE_RENDER; 308 | } 309 | 310 | ROP_RENDER_CODE 311 | ROP_DopField::endRender() 312 | { 313 | if (INITSIM()) 314 | OPgetDirector()->bumpSkipPlaybarBasedSimulationReset(-1); 315 | 316 | if (error() < UT_ERROR_ABORT) 317 | { 318 | if( !executePostRenderScript(myEndTime) ) 319 | return ROP_ABORT_RENDER; 320 | } 321 | return ROP_CONTINUE_RENDER; 322 | } 323 | 324 | void 325 | newDriverOperator(OP_OperatorTable *table) 326 | { 327 | table->addOperator(new OP_Operator("hdk_dopfield", 328 | "Dop Field", 329 | ROP_DopField::myConstructor, 330 | ROP_DopField::getTemplatePair(), 331 | 0, 332 | 0, 333 | ROP_DopField::getVariablePair(), 334 | OP_FLAG_GENERATOR)); 335 | } 336 | 337 | -------------------------------------------------------------------------------- /ROP/ROP_DopField.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef __ROP_DopField_h__ 27 | #define __ROP_DopField_h__ 28 | 29 | #include 30 | 31 | #define STR_PARM(name, vi, t) \ 32 | { evalString(str, name, vi, t); } 33 | #define INT_PARM(name, vi, t) \ 34 | { return evalInt(name, vi, t); } 35 | 36 | class OP_TemplatePair; 37 | class OP_VariablePair; 38 | 39 | namespace HDK_Sample { 40 | 41 | enum { 42 | ROP_DOPFIELD_RENDER, 43 | ROP_DOPFIELD_RENDER_CTRL, 44 | ROP_DOPFIELD_TRANGE, 45 | ROP_DOPFIELD_FRANGE, 46 | ROP_DOPFIELD_TAKE, 47 | ROP_DOPFIELD_DOPPATH, 48 | ROP_DOPFIELD_DOPOUTPUT, 49 | ROP_DOPFIELD_DOPOBJECT, 50 | ROP_DOPFIELD_DOPDATA, 51 | ROP_DOPFIELD_INITSIM, 52 | ROP_DOPFIELD_ALFPROGRESS, 53 | ROP_DOPFIELD_TPRERENDER, 54 | ROP_DOPFIELD_PRERENDER, 55 | ROP_DOPFIELD_LPRERENDER, 56 | ROP_DOPFIELD_TPREFRAME, 57 | ROP_DOPFIELD_PREFRAME, 58 | ROP_DOPFIELD_LPREFRAME, 59 | ROP_DOPFIELD_TPOSTFRAME, 60 | ROP_DOPFIELD_POSTFRAME, 61 | ROP_DOPFIELD_LPOSTFRAME, 62 | ROP_DOPFIELD_TPOSTRENDER, 63 | ROP_DOPFIELD_POSTRENDER, 64 | ROP_DOPFIELD_LPOSTRENDER, 65 | 66 | ROP_DOPFIELD_MAXPARMS 67 | }; 68 | 69 | class ROP_DopField : public ROP_Node { 70 | public: 71 | 72 | /// Provides access to our parm templates. 73 | static OP_TemplatePair *getTemplatePair(); 74 | static OP_VariablePair *getVariablePair(); 75 | /// Creates an instance of this node. 76 | static OP_Node *myConstructor(OP_Network *net, const char*name, 77 | OP_Operator *op); 78 | 79 | protected: 80 | ROP_DopField(OP_Network *net, const char *name, OP_Operator *entry); 81 | virtual ~ROP_DopField(); 82 | 83 | /// Called at the beginning of rendering to perform any intialization 84 | /// necessary. 85 | /// @param nframes Number of frames being rendered. 86 | /// @param s Start time, in seconds. 87 | /// @param e End time, in seconds. 88 | /// @return True of success, false on failure (aborts the render). 89 | virtual int startRender(int nframes, fpreal s, fpreal e); 90 | 91 | /// Called once for every frame that is rendered. 92 | /// @param time The time to render at. 93 | /// @param boss Interrupt handler. 94 | /// @return Return a status code indicating whether to abort the 95 | /// render, continue, or retry the current frame. 96 | virtual ROP_RENDER_CODE renderFrame(fpreal time, UT_Interrupt *boss); 97 | 98 | /// Called after the rendering is done to perform any post-rendering steps 99 | /// required. 100 | /// @return Return a status code indicating whether to abort the 101 | /// render, continue, or retry. 102 | virtual ROP_RENDER_CODE endRender(); 103 | 104 | public: 105 | 106 | /// A convenience method to evaluate our custom file parameter. 107 | void OUTPUT(UT_String &str, fpreal t) 108 | { STR_PARM("file", 0, t) } 109 | int INITSIM(void) 110 | { INT_PARM("initsim", 0, 0) } 111 | bool ALFPROGRESS() 112 | { INT_PARM("alfprogress", 0, 0) } 113 | void DOPPATH(UT_String &str, fpreal t) 114 | { STR_PARM("doppath", 0, t)} 115 | void DOPOBJECT(UT_String &str, fpreal t) 116 | { STR_PARM("dopobject", 0, t)} 117 | void DOPDATA(UT_String &str, fpreal t) 118 | { STR_PARM("dopdata", 0, t)} 119 | 120 | 121 | private: 122 | fpreal myEndTime; 123 | fpreal myStartTime; 124 | }; 125 | 126 | } // End HDK_Sample namespace 127 | 128 | 129 | #undef STR_PARM 130 | #undef STR_SET 131 | #undef STR_GET 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /ROP/ROP_Dumper.C: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include "ROP_Dumper.h" 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | 41 | using namespace HDK_Sample; 42 | 43 | int *ROP_Dumper::ifdIndirect = 0; 44 | 45 | static PRM_Name theFileName("file", "Save to file"); 46 | static PRM_Default theFileDefault(0, "junk.out"); 47 | 48 | static PRM_Template * 49 | getTemplates() 50 | { 51 | static PRM_Template *theTemplate = 0; 52 | 53 | if (theTemplate) 54 | return theTemplate; 55 | 56 | theTemplate = new PRM_Template[14]; 57 | theTemplate[0] = PRM_Template(PRM_FILE, 1, &theFileName, &theFileDefault); 58 | theTemplate[1] = theRopTemplates[ROP_TPRERENDER_TPLATE]; 59 | theTemplate[2] = theRopTemplates[ROP_PRERENDER_TPLATE]; 60 | theTemplate[3] = theRopTemplates[ROP_LPRERENDER_TPLATE]; 61 | theTemplate[4] = theRopTemplates[ROP_TPREFRAME_TPLATE]; 62 | theTemplate[5] = theRopTemplates[ROP_PREFRAME_TPLATE]; 63 | theTemplate[6] = theRopTemplates[ROP_LPREFRAME_TPLATE]; 64 | theTemplate[7] = theRopTemplates[ROP_TPOSTFRAME_TPLATE]; 65 | theTemplate[8] = theRopTemplates[ROP_POSTFRAME_TPLATE]; 66 | theTemplate[9] = theRopTemplates[ROP_LPOSTFRAME_TPLATE]; 67 | theTemplate[10] = theRopTemplates[ROP_TPOSTRENDER_TPLATE]; 68 | theTemplate[11] = theRopTemplates[ROP_POSTRENDER_TPLATE]; 69 | theTemplate[12] = theRopTemplates[ROP_LPOSTRENDER_TPLATE]; 70 | theTemplate[13] = PRM_Template(); 71 | 72 | return theTemplate; 73 | } 74 | 75 | OP_TemplatePair * 76 | ROP_Dumper::getTemplatePair() 77 | { 78 | static OP_TemplatePair *ropPair = 0; 79 | if (!ropPair) 80 | { 81 | OP_TemplatePair *base; 82 | 83 | base = new OP_TemplatePair(getTemplates()); 84 | ropPair = new OP_TemplatePair(ROP_Node::getROPbaseTemplate(), base); 85 | } 86 | return ropPair; 87 | } 88 | 89 | OP_VariablePair * 90 | ROP_Dumper::getVariablePair() 91 | { 92 | static OP_VariablePair *pair = 0; 93 | if (!pair) 94 | pair = new OP_VariablePair(ROP_Node::myVariableList); 95 | return pair; 96 | } 97 | 98 | OP_Node * 99 | ROP_Dumper::myConstructor(OP_Network *net, const char *name, OP_Operator *op) 100 | { 101 | return new ROP_Dumper(net, name, op); 102 | } 103 | 104 | ROP_Dumper::ROP_Dumper(OP_Network *net, const char *name, OP_Operator *entry) 105 | : ROP_Node(net, name, entry) 106 | { 107 | 108 | if (!ifdIndirect) 109 | ifdIndirect = allocIndirect(16); 110 | } 111 | 112 | 113 | ROP_Dumper::~ROP_Dumper() 114 | { 115 | } 116 | 117 | //------------------------------------------------------------------------------ 118 | // The startRender(), renderFrame(), and endRender() render methods are 119 | // invoked by Houdini when the ROP runs. 120 | 121 | int 122 | ROP_Dumper::startRender(int /*nframes*/, fpreal tstart, fpreal tend) 123 | { 124 | myEndTime = tend; 125 | if (error() < UT_ERROR_ABORT) 126 | executePreRenderScript(tstart); 127 | 128 | return 1; 129 | } 130 | 131 | static void 132 | printNode(ostream &os, OP_Node *node, int indent) 133 | { 134 | UT_WorkBuffer wbuf; 135 | wbuf.sprintf("%*s", indent, ""); 136 | os << wbuf.buffer() << node->getName() << endl; 137 | 138 | for (int i=0; igetNchildren(); ++i) 139 | printNode(os, node->getChild(i), indent+2); 140 | } 141 | 142 | ROP_RENDER_CODE 143 | ROP_Dumper::renderFrame(fpreal time, UT_Interrupt *) 144 | { 145 | // Execute the pre-render script. 146 | executePreFrameScript(time); 147 | 148 | // Evaluate the parameter for the file name and write something to the 149 | // file. 150 | UT_String file_name; 151 | OUTPUT(file_name, time); 152 | 153 | UT_OFStream os(file_name); 154 | printNode(os, OPgetDirector(), 0); 155 | os.close(); 156 | 157 | // Execute the post-render script. 158 | if (error() < UT_ERROR_ABORT) 159 | executePostFrameScript(time); 160 | 161 | return ROP_CONTINUE_RENDER; 162 | } 163 | 164 | ROP_RENDER_CODE 165 | ROP_Dumper::endRender() 166 | { 167 | if (error() < UT_ERROR_ABORT) 168 | executePostRenderScript(myEndTime); 169 | return ROP_CONTINUE_RENDER; 170 | } 171 | 172 | void 173 | newDriverOperator(OP_OperatorTable *table) 174 | { 175 | table->addOperator(new OP_Operator("hdk_dumper", 176 | "Dump Tree", 177 | ROP_Dumper::myConstructor, 178 | ROP_Dumper::getTemplatePair(), 179 | 0, 180 | 0, 181 | ROP_Dumper::getVariablePair(), 182 | OP_FLAG_GENERATOR)); 183 | } 184 | 185 | -------------------------------------------------------------------------------- /ROP/ROP_Dumper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef __ROP_Dumper_h__ 27 | #define __ROP_Dumper_h__ 28 | 29 | #include 30 | 31 | #define STR_PARM(name, idx, vi, t) \ 32 | { evalString(str, name, &ifdIndirect[idx], vi, t); } 33 | #define INT_PARM(name, idx, vi, t) \ 34 | { return evalInt(name, &ifdIndirect[idx], vi, t); } 35 | 36 | #define STR_SET(name, idx, vi, t) \ 37 | { setString(str, name, ifdIndirect[idx], vi, t); } 38 | #define STR_GET(name, idx, vi, t) \ 39 | { evalStringRaw(str, name, &ifdIndirect[idx], vi, t); } 40 | 41 | class OP_TemplatePair; 42 | class OP_VariablePair; 43 | 44 | namespace HDK_Sample { 45 | 46 | class ROP_Dumper : public ROP_Node { 47 | public: 48 | 49 | /// Provides access to our parm templates. 50 | static OP_TemplatePair *getTemplatePair(); 51 | /// Provides access to our variables. 52 | static OP_VariablePair *getVariablePair(); 53 | /// Creates an instance of this node. 54 | static OP_Node *myConstructor(OP_Network *net, const char*name, 55 | OP_Operator *op); 56 | 57 | protected: 58 | ROP_Dumper(OP_Network *net, const char *name, OP_Operator *entry); 59 | virtual ~ROP_Dumper(); 60 | 61 | /// Called at the beginning of rendering to perform any intialization 62 | /// necessary. 63 | /// @param nframes Number of frames being rendered. 64 | /// @param s Start time, in seconds. 65 | /// @param e End time, in seconds. 66 | /// @return True of success, false on failure (aborts the render). 67 | virtual int startRender(int nframes, fpreal s, fpreal e); 68 | 69 | /// Called once for every frame that is rendered. 70 | /// @param time The time to render at. 71 | /// @param boss Interrupt handler. 72 | /// @return Return a status code indicating whether to abort the 73 | /// render, continue, or retry the current frame. 74 | virtual ROP_RENDER_CODE renderFrame(fpreal time, UT_Interrupt *boss); 75 | 76 | /// Called after the rendering is done to perform any post-rendering steps 77 | /// required. 78 | /// @return Return a status code indicating whether to abort the 79 | /// render, continue, or retry. 80 | virtual ROP_RENDER_CODE endRender(); 81 | 82 | public: 83 | 84 | /// A convenience method to evaluate our custom file parameter. 85 | void OUTPUT(UT_String &str, fpreal t) 86 | { STR_PARM("file", 0, 0, t) } 87 | 88 | private: 89 | static int *ifdIndirect; 90 | fpreal myEndTime; 91 | }; 92 | 93 | } // End HDK_Sample namespace 94 | 95 | 96 | #undef STR_PARM 97 | #undef STR_SET 98 | #undef STR_GET 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /ROP/ROP_Radiance.C: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include // ROP_TPRERENDER_TPLATE etc. 5 | #include // use for sesitag 6 | // header file 7 | #include "ROP_Radiance.h" 8 | 9 | static PRM_Name theFileName("file", "Save to file"); 10 | static PRM_Default theFileDefault(0, "houdini.rad"); 11 | 12 | // helper functions 13 | 14 | static PRM_Template* 15 | getBaseTemplates() { 16 | static PRM_Template* theTemplate = NULL; 17 | 18 | if (theTemplate) return theTemplate; 19 | 20 | theTemplate = new PRM_Template[14]; 21 | theTemplate[0] = PRM_Template(PRM_FILE, 1, &theFileName, &theFileDefault); 22 | theTemplate[1] = theRopTemplates[ROP_TPRERENDER_TPLATE]; 23 | theTemplate[2] = theRopTemplates[ROP_PRERENDER_TPLATE]; 24 | theTemplate[3] = theRopTemplates[ROP_LPRERENDER_TPLATE]; 25 | theTemplate[4] = theRopTemplates[ROP_TPREFRAME_TPLATE]; 26 | theTemplate[5] = theRopTemplates[ROP_PREFRAME_TPLATE]; 27 | theTemplate[6] = theRopTemplates[ROP_LPREFRAME_TPLATE]; 28 | theTemplate[7] = theRopTemplates[ROP_TPOSTFRAME_TPLATE]; 29 | theTemplate[8] = theRopTemplates[ROP_POSTFRAME_TPLATE]; 30 | theTemplate[9] = theRopTemplates[ROP_LPOSTFRAME_TPLATE]; 31 | theTemplate[10] = theRopTemplates[ROP_TPOSTRENDER_TPLATE]; 32 | theTemplate[11] = theRopTemplates[ROP_POSTRENDER_TPLATE]; 33 | theTemplate[12] = theRopTemplates[ROP_LPOSTRENDER_TPLATE]; 34 | theTemplate[13] = PRM_Template(); 35 | 36 | return theTemplate; 37 | } 38 | 39 | // class ROP_Radiance 40 | 41 | ROP_Radiance::ROP_Radiance(OP_Network* net, const char* name, OP_Operator* op) 42 | : ROP_Node(net, name, op) { 43 | // TODO: ifdIndirect ??? 44 | } 45 | 46 | OP_TemplatePair* 47 | ROP_Radiance::getTemplates() { 48 | static OP_TemplatePair* tPair = NULL; 49 | if (!tPair) { 50 | OP_TemplatePair* base; 51 | base = new OP_TemplatePair(getBaseTemplates()); 52 | tPair = new OP_TemplatePair(ROP_Node::getROPbaseTemplate(), base); 53 | } 54 | return tPair; 55 | } 56 | 57 | OP_VariablePair* 58 | ROP_Radiance::getVariables() { 59 | static OP_VariablePair* vPair = NULL; 60 | if (!vPair) vPair = new OP_VariablePair(ROP_Node::myVariableList); 61 | return vPair; 62 | } 63 | 64 | OP_Node* 65 | ROP_Radiance::construct(OP_Network* net, const char* name, OP_Operator* op) { 66 | return new ROP_Radiance(net, name, op); 67 | } 68 | 69 | int 70 | ROP_Radiance::startRender(int nframes, fpreal tstart, fpreal tend) { 71 | myEndTime = tend; 72 | if (error() < UT_ERROR_ABORT) { 73 | if (!executePreRenderScript(tstart)) return 0; 74 | } 75 | 76 | return 1; 77 | } 78 | 79 | ROP_RENDER_CODE 80 | ROP_Radiance::renderFrame(fpreal time, UT_Interrupt* boss) { 81 | if (!executePreFrameScript(time)) return ROP_ABORT_RENDER; 82 | // TODO: export a .rad file 83 | if (error() < UT_ERROR_ABORT) { 84 | if (!executePostFrameScript(time)) return ROP_ABORT_RENDER; 85 | } 86 | 87 | return ROP_CONTINUE_RENDER; 88 | } 89 | 90 | ROP_RENDER_CODE 91 | ROP_Radiance::endRender() { 92 | if (error() < UT_ERROR_ABORT) { 93 | if (!executePostRenderScript(myEndTime)) return ROP_ABORT_RENDER; 94 | } 95 | 96 | return ROP_CONTINUE_RENDER; 97 | } 98 | 99 | // entry point 100 | 101 | SYS_VISIBILITY_EXPORT void 102 | newDriverOperator(OP_OperatorTable* table) { 103 | table->addOperator(new OP_Operator("radiance", 104 | "Radiance", 105 | ROP_Radiance::construct, 106 | ROP_Radiance::getTemplates(), 107 | 0, // min_sources 108 | 0, // max_sources 109 | ROP_Radiance::getVariables(), 110 | OP_FLAG_GENERATOR)); 111 | } 112 | -------------------------------------------------------------------------------- /ROP/ROP_Radiance.h: -------------------------------------------------------------------------------- 1 | #ifndef __ROP_Radiance_h__ 2 | #define __ROP_Radiance_h__ 3 | 4 | #include 5 | 6 | class ROP_Radiance : public ROP_Node { 7 | public: 8 | // creates an instance of this node 9 | static OP_Node* construct(OP_Network* net, 10 | const char* name, 11 | OP_Operator* op); 12 | // provides access to our parm tempates 13 | static OP_TemplatePair* getTemplates(void); 14 | // provides access to our variables 15 | static OP_VariablePair* getVariables(void); 16 | 17 | protected: 18 | ROP_Radiance(OP_Network* net, const char* name, OP_Operator* op); 19 | // render methods 20 | virtual int startRender(int nframes, fpreal tstart, fpreal tend); 21 | virtual ROP_RENDER_CODE renderFrame(fpreal time, UT_Interrupt* boss = 0); 22 | virtual ROP_RENDER_CODE endRender(void); 23 | 24 | private: 25 | fpreal myEndTime; 26 | }; 27 | 28 | #endif // __ROP_Radiance_h__ 29 | -------------------------------------------------------------------------------- /SOP/SOP_Star.C: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | *---------------------------------------------------------------------------- 26 | * The Star SOP 27 | */ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "SOP_Star.h" 40 | 41 | using namespace HDK_Sample; 42 | 43 | // 44 | // Help is stored in a "wiki" style text file. This text file should be copied 45 | // to $HOUDINI_PATH/help/nodes/sop/star.txt 46 | // 47 | // See the sample_install.sh file for an example. 48 | // 49 | 50 | 51 | /// 52 | /// newSopOperator is the hook that Houdini grabs from this dll 53 | /// and invokes to register the SOP. In this case we add ourselves 54 | /// to the specified operator table. 55 | /// 56 | void 57 | newSopOperator(OP_OperatorTable *table) 58 | { 59 | table->addOperator( 60 | new OP_Operator("hdk_star", // Internal name 61 | "Star", // UI name 62 | SOP_Star::myConstructor, // How to build the SOP 63 | SOP_Star::myTemplateList, // My parameters 64 | 0, // Min # of sources 65 | 0, // Max # of sources 66 | SOP_Star::myVariables, // Local variables 67 | OP_FLAG_GENERATOR) // Flag it as generator 68 | ); 69 | } 70 | 71 | static PRM_Name negativeName("nradius", "Negative Radius"); 72 | // ^^^^^^^^ ^^^^^^^^^^^^^^^ 73 | // internal descriptive version 74 | 75 | static PRM_Default fiveDefault(5); // Default to 5 divisions 76 | static PRM_Default radiiDefaults[] = { 77 | PRM_Default(1), // Outside radius 78 | PRM_Default(0.3) // Inside radius 79 | }; 80 | 81 | PRM_Template 82 | SOP_Star::myTemplateList[] = { 83 | PRM_Template(PRM_INT, // Integer parameter. 84 | PRM_Template::PRM_EXPORT_TBX, // Export to top of viewer 85 | // when user selects this node 86 | 1, // One integer in this row/parameter 87 | &PRMdivName, // Name of this parameter - must be static 88 | &fiveDefault, // Default for this parameter - ditto 89 | 0, // Menu for this parameter 90 | &PRMdivision2Range // Valid range 91 | ), 92 | PRM_Template(PRM_XYZ, 2, &PRMradiusName, radiiDefaults), 93 | PRM_Template(PRM_TOGGLE, 1, &negativeName), 94 | PRM_Template(PRM_XYZ, 3, &PRMcenterName), 95 | PRM_Template(PRM_ORD, 1, &PRMorientName, 0, &PRMplaneMenu), 96 | PRM_Template() 97 | }; 98 | 99 | 100 | // Here's how we define local variables for the SOP. 101 | enum { 102 | VAR_PT, // Point number of the star 103 | VAR_NPT // Number of points in the star 104 | }; 105 | 106 | CH_LocalVariable 107 | SOP_Star::myVariables[] = { 108 | { "PT", VAR_PT, 0 }, // The table provides a mapping 109 | { "NPT", VAR_NPT, 0 }, // from text string to integer token 110 | { 0, 0, 0 }, 111 | }; 112 | 113 | bool 114 | SOP_Star::evalVariableValue(fpreal &val, int index, int thread) 115 | { 116 | // myCurrPoint will be negative when we're not cooking so only try to 117 | // handle the local variables when we have a valid myCurrPoint index. 118 | if (myCurrPoint >= 0) 119 | { 120 | // Note that "gdp" may be null here, so we do the safe thing 121 | // and cache values we are interested in. 122 | switch (index) 123 | { 124 | case VAR_PT: 125 | val = (fpreal) myCurrPoint; 126 | return true; 127 | case VAR_NPT: 128 | val = (fpreal) myTotalPoints; 129 | return true; 130 | default: 131 | /* do nothing */; 132 | } 133 | } 134 | // Not one of our variables, must delegate to the base class. 135 | return SOP_Node::evalVariableValue(val, index, thread); 136 | } 137 | 138 | OP_Node * 139 | SOP_Star::myConstructor(OP_Network *net, const char *name, OP_Operator *op) 140 | { 141 | return new SOP_Star(net, name, op); 142 | } 143 | 144 | SOP_Star::SOP_Star(OP_Network *net, const char *name, OP_Operator *op) 145 | : SOP_Node(net, name, op) 146 | { 147 | myCurrPoint = -1; // To prevent garbage values from being returned 148 | } 149 | 150 | SOP_Star::~SOP_Star() {} 151 | 152 | OP_ERROR 153 | SOP_Star::cookMySop(OP_Context &context) 154 | { 155 | fpreal now = context.getTime(); 156 | float rad, tx, ty, tz; 157 | int divisions, plane, negradius; 158 | int xcoord, ycoord, zcoord; 159 | float tmp, tinc; 160 | GU_PrimPoly *poly; 161 | UT_Interrupt *boss; 162 | 163 | // Since we don't have inputs, we don't need to lock them. 164 | 165 | divisions = DIVISIONS(now)*2; // We need twice our divisions of points 166 | myTotalPoints = divisions; // Set the NPT local variable value 167 | myCurrPoint = 0; // Initialize the PT local variable 168 | 169 | plane = ORIENT(); 170 | negradius = NEGRADIUS(); 171 | tx = CENTERX(now); 172 | ty = CENTERY(now); 173 | tz = CENTERZ(now); 174 | 175 | switch (plane) 176 | { 177 | case 0: // XY Plane 178 | xcoord = 0; 179 | ycoord = 1; 180 | zcoord = 2; 181 | break; 182 | case 1: // YZ Plane 183 | xcoord = 1; 184 | ycoord = 2; 185 | zcoord = 0; 186 | break; 187 | case 2: // XZ Plane 188 | xcoord = 0; 189 | ycoord = 2; 190 | zcoord = 1; 191 | break; 192 | } 193 | 194 | // Check to see that there hasn't been a critical error in cooking the SOP. 195 | if (error() < UT_ERROR_ABORT) 196 | { 197 | boss = UTgetInterrupt(); 198 | if (divisions < 4) 199 | { 200 | // With the range restriction we have on the divisions, this 201 | // is actually impossible, but it shows how to add an error 202 | // message or warning to the SOP. 203 | addWarning(SOP_MESSAGE, "Invalid divisions"); 204 | divisions = 4; 205 | } 206 | gdp->clearAndDestroy(); 207 | 208 | // Start the interrupt server 209 | if (boss->opStart("Building Star")) 210 | { 211 | // Build a polygon 212 | poly = GU_PrimPoly::build(gdp, divisions, GU_POLY_CLOSED); 213 | tinc = M_PI*2 / (float)divisions; 214 | 215 | // Now, set all the points of the polygon 216 | for (int i = 0; i < divisions; i++) 217 | { 218 | // Check to see if the user has interrupted us... 219 | if (boss->opInterrupt()) 220 | break; 221 | 222 | myCurrPoint = i; 223 | 224 | // Since we expect the local variables to be used in specifying 225 | // the radii, we have to evaluate the channels INSIDE the loop 226 | // through the points... 227 | 228 | tmp = (float)i * tinc; 229 | rad = (i & 1) ? XRADIUS(now) : YRADIUS(now); 230 | if (!negradius && rad < 0) 231 | rad = 0; 232 | 233 | UT_Vector3 pos; 234 | pos(xcoord) = SYScos(tmp) * rad + tx; 235 | pos(ycoord) = SYSsin(tmp) * rad + ty; 236 | pos(zcoord) = 0 + tz; 237 | 238 | GA_Offset ptoff = poly->getPointOffset(i); 239 | gdp->setPos3(ptoff, pos); 240 | } 241 | 242 | // Highlight the star which we have just generated. This routine 243 | // call clears any currently highlighted geometry, and then it 244 | // highlights every primitive for this SOP. 245 | select(GU_SPrimitive); 246 | } 247 | 248 | // Tell the interrupt server that we've completed. Must do this 249 | // regardless of what opStart() returns. 250 | boss->opEnd(); 251 | } 252 | 253 | myCurrPoint = -1; 254 | return error(); 255 | } 256 | -------------------------------------------------------------------------------- /SOP/SOP_Star.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | *---------------------------------------------------------------------------- 26 | * This SOP builds a star. 27 | */ 28 | 29 | #ifndef __SOP_Star_h__ 30 | #define __SOP_Star_h__ 31 | 32 | #include 33 | 34 | namespace HDK_Sample { 35 | class SOP_Star : public SOP_Node 36 | { 37 | public: 38 | static OP_Node *myConstructor(OP_Network*, const char *, 39 | OP_Operator *); 40 | 41 | /// Stores the description of the interface of the SOP in Houdini. 42 | /// Each parm template refers to a parameter. 43 | static PRM_Template myTemplateList[]; 44 | 45 | /// This optional data stores the list of local variables. 46 | static CH_LocalVariable myVariables[]; 47 | 48 | protected: 49 | SOP_Star(OP_Network *net, const char *name, OP_Operator *op); 50 | virtual ~SOP_Star(); 51 | 52 | 53 | /// cookMySop does the actual work of the SOP computing, in this 54 | /// case, a star shape. 55 | virtual OP_ERROR cookMySop(OP_Context &context); 56 | 57 | /// This function is used to lookup local variables that you have 58 | /// defined specific to your SOP. 59 | virtual bool evalVariableValue( 60 | fpreal &val, 61 | int index, 62 | int thread); 63 | // Add virtual overload that delegates to the super class to avoid 64 | // shadow warnings. 65 | virtual bool evalVariableValue( 66 | UT_String &v, 67 | int i, 68 | int thread) 69 | { 70 | return evalVariableValue(v, i, thread); 71 | } 72 | 73 | private: 74 | /// The following list of accessors simplify evaluating the parameters 75 | /// of the SOP. 76 | int DIVISIONS(fpreal t) { return evalInt ("divs", 0, t); } 77 | fpreal XRADIUS(fpreal t) { return evalFloat("rad", 0, t); } 78 | fpreal YRADIUS(fpreal t) { return evalFloat("rad", 1, t); } 79 | int NEGRADIUS() { return evalInt ("nradius", 0, 0); } 80 | fpreal CENTERX(fpreal t) { return evalFloat("t", 0, t); } 81 | fpreal CENTERY(fpreal t) { return evalFloat("t", 1, t); } 82 | fpreal CENTERZ(fpreal t) { return evalFloat("t", 2, t); } 83 | int ORIENT() { return evalInt ("orient", 0, 0); } 84 | 85 | /// Member variables are stored in the actual SOP, not with the geometry 86 | /// In this case these are just used to transfer data to the local 87 | /// variable callback. 88 | /// Another use for local data is a cache to store expensive calculations. 89 | int myCurrPoint; 90 | int myTotalPoints; 91 | }; 92 | } // End HDK_Sample namespace 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /SOP/SOP_hdk_star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wahn/Houdini_HDK_Examples/750cd7599e9eb9a979a78fee14537d7ad723e9af/SOP/SOP_hdk_star.png -------------------------------------------------------------------------------- /SOP/SOP_hdk_star.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | 25 | 27 | 31 | 35 | 36 | 43 | 54 | 55 | 75 | 77 | 78 | 80 | image/svg+xml 81 | 83 | 84 | 85 | 86 | 90 | 100 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /SOP/SOP_lotus.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | # This code is called when instances of this SOP cook. 4 | node = hou.pwd() 5 | geo = node.geometry() 6 | 7 | def bottom(num, vOffset, nOffset): 8 | z = 0.001 9 | # intersection point between ll_se and ll_ne 10 | a = 1 11 | b = -2 12 | c = -0.754999 13 | discriminant = b * b - 4.0 * a * c 14 | x1 = (2 + math.sqrt(discriminant)) / 2.0 15 | y1 = 0.0 16 | p1 = [x1, y1, z] # we need only one of them 17 | # intersection point between clip_base_m and ll_ne 18 | m = (z * z - 5 * z + 8.25) / 2.0 19 | a = 2 20 | b = -2 * m 21 | c = m * m - 9 22 | discriminant = b * b - 4.0 * a * c 23 | x2 = (2 * m + math.sqrt(discriminant)) / 4.0 24 | x3 = (2 * m - math.sqrt(discriminant)) / 4.0 25 | y2 = m - x2 26 | y3 = m - x3 27 | p2 = [x2, y2, z] 28 | p3 = [x3, y3, z] 29 | # cylinder top at bottom of the lotus 30 | vOffset, nOffset, part1 = cylinderTop(vOffset, nOffset, num, p1, p2) 31 | # cylinder sides at bottom of the lotus 32 | vOffset, nOffset, part2 = cylinderSides(vOffset, nOffset, num, p2, p3) 33 | # assemble parts for lower rim 34 | points = [] 35 | for point in part1: 36 | # simply copy 37 | points.append(point) 38 | for point in part2: 39 | # simply copy 40 | points.append(point) 41 | for index in xrange(len(part1)): 42 | rIndex = len(part1) - 1 - index 43 | point = part1[rIndex] # reverse order 44 | # swap x and y 45 | points.append([point[1], point[0], point[2]]) 46 | return vOffset, nOffset, points 47 | 48 | def cylinderSides(vOffset, nOffset, num, p1, p2): 49 | rim = [] # to return the rim 50 | nVertices = 0 51 | nNormals = 0 52 | # extract coords 53 | x1 = p1[0] 54 | y1 = p1[1] 55 | z1 = p1[2] 56 | x2 = p2[0] 57 | y2 = p2[1] 58 | z2 = p2[2] 59 | z = z2 60 | # angle between x-axis and p1 61 | rad = math.atan(y1 / x1) 62 | # how many points to intersection? 63 | num1 = int(num * (4.0 * rad) / math.pi) 64 | # how many points from intersection to second intersection? 65 | num2 = 2 * (num - num1) + 1 66 | # points on cylinder 67 | rad1 = math.atan(y1 / x1) 68 | rad2 = math.atan(y2 / x2) 69 | points = [] 70 | for i in xrange(num2): 71 | rad = rad1 + i * (rad2 - rad1) / float(num2 - 1) 72 | cos = math.cos(rad) 73 | sin = math.sin(rad) 74 | x = 3.0 * cos 75 | y = 3.0 * sin 76 | nVertices = nVertices + 1 77 | points.append([x, y, z]) 78 | # calculate points on cylinder (with z != 0.001) 79 | a = 1 80 | b = -5.0 81 | c = 8.25 - 2 * (x + y) 82 | discriminant = b * b - 4.0 * a * c 83 | z1 = (5.0 + math.sqrt(discriminant)) / 2.0 84 | z2 = (5.0 - math.sqrt(discriminant)) / 2.0 85 | if i != 0 and i != num2 - 1: 86 | nVertices = nVertices + 1 87 | points.append([x, y, z2]) 88 | rim.append([x, y, z2]) 89 | return vOffset + nVertices, nOffset + nNormals, rim 90 | 91 | def cylinderTop(vOffset, nOffset, num, p1, p2): 92 | rim = [] # to return the rim 93 | print "# cylinder top at bottom of the lotus" 94 | nVertices = 0 95 | nNormals = 0 96 | # extract coords 97 | x1 = p1[0] 98 | y1 = p1[1] 99 | z1 = p1[2] 100 | x2 = p2[0] 101 | y2 = p2[1] 102 | z2 = p2[2] 103 | if z1 == z2: 104 | z = z1 105 | # angle between x-axis and p1 106 | rad = math.atan(y2 / x2) 107 | # how many points to intersection? 108 | num1 = int(num * (4.0 * rad) / math.pi) 109 | # how many points from intersection to 45 degrees? 110 | num2 = num - num1 + 1 111 | # points on ll_ne with z = 0.001 112 | k2 = 9.0 - 6.245001 113 | k = math.sqrt(k2) 114 | rad1 = math.atan((y1 - 1.0) / (x1 - 1.0)) 115 | rad2 = math.atan((y2 - 1.0) / (x2 - 1.0)) 116 | nVertices = nVertices + 1 117 | for i in xrange(num1): 118 | rad = rad1 + i * (rad2 - rad1) / float(num1 - 1) 119 | cos = math.cos(rad) 120 | sin = math.sin(rad) 121 | x = 1.0 + k * cos 122 | y = 1.0 + k * sin 123 | nVertices = nVertices + 1 124 | rim.append([x, y, z]) 125 | rad1 = math.atan(y2 / x2) 126 | rad2 = math.pi / 4.0 127 | for i in xrange(1, num2): # omit first vertex (was written already above) 128 | rad = rad1 + i * (rad2 - rad1) / float(num2 - 1) 129 | cos = math.cos(rad) 130 | sin = math.sin(rad) 131 | x = 3.0 * cos 132 | y = 3.0 * sin 133 | nVertices = nVertices + 1 134 | return vOffset + nVertices, nOffset + nNormals, rim 135 | 136 | # Add code to modify the contents of geo. 137 | vOffset = 0 138 | nOffset = 0 139 | vOffset, nOffset, lowerRim = bottom(16, vOffset, nOffset) 140 | bottom = geo.createPolygon() 141 | for position in lowerRim: 142 | point = geo.createPoint() 143 | point.setPosition((position[0], position[1], position[2])) 144 | bottom.addVertex(point) 145 | -------------------------------------------------------------------------------- /SOP/hdk_star.txt: -------------------------------------------------------------------------------- 1 | #type: node 2 | #context: sop 3 | #internal: star 4 | #largeicon: /nodes/sop/SOP_hdk_star.png 5 | 6 | #tags: shape 7 | 8 | = Star = 9 | 10 | """ Builds an n-pointed star """ 11 | 12 | @parameters 13 | 14 | Divisions: 15 | #channels: /divs 16 | Number of points on the star 17 | 18 | Radius: 19 | #channels: /rad 20 | The radius of the star 21 | 22 | NegRadius: 23 | #channels: /nradius 24 | Allows the radius to be negative. This may result in bowtie 25 | polygons. 26 | 27 | Center: 28 | #channels: /tx /ty /tz 29 | The center of the star 30 | 31 | Orientation: 32 | #channels: /orient 33 | The orientation of the star 34 | 35 | @locals 36 | PT: 37 | current point number 38 | NPT: 39 | number of points in the star 40 | 41 | @related 42 | - [Node:sop/circle] 43 | -------------------------------------------------------------------------------- /packedsphere/GU_PackedSphere.C: -------------------------------------------------------------------------------- 1 | /* 2 | * PROPRIETARY INFORMATION. This software is proprietary to 3 | * Side Effects Software Inc., and is not to be reproduced, 4 | * transmitted, or disclosed in any way without written permission. 5 | * 6 | * Produced by: 7 | * Side Effects Software Inc 8 | * 123 Front Street West, Suite 1401 9 | * Toronto, Ontario 10 | * Canada M5J 2M2 11 | * 416-504-9876 12 | * 13 | * NAME: GU_PackedSphere.h (GU Library, C++) 14 | * 15 | * COMMENTS: 16 | */ 17 | 18 | #include "GU_PackedSphere.h" 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | using namespace HDK_Sample; 25 | 26 | namespace 27 | { 28 | class SphereFactory : public GU_PackedFactory 29 | { 30 | public: 31 | SphereFactory() 32 | : GU_PackedFactory("PackedSphere", "Packed Sphere") 33 | { 34 | registerIntrinsic("lod", 35 | IntGetterCast(&GU_PackedSphere::lod), 36 | IntSetterCast(&GU_PackedSphere::setLOD)); 37 | } 38 | virtual ~SphereFactory() {} 39 | 40 | virtual GU_PackedImpl *create() const 41 | { 42 | return new GU_PackedSphere(); 43 | } 44 | }; 45 | 46 | static SphereFactory *theFactory = NULL; 47 | 48 | /// Store spheres in a shared cache 49 | class CacheEntry 50 | { 51 | public: 52 | CacheEntry(int lod) 53 | : myGdp() 54 | , myRef(0) 55 | { 56 | GU_Detail *gdp = new GU_Detail(); 57 | GU_PrimSphereParms parms(gdp); 58 | parms.freq = lod; 59 | GU_PrimSphere::build(parms, GEO_PRIMPOLYSOUP); 60 | myGdp.allocateAndSet(gdp); 61 | }; 62 | ~CacheEntry() 63 | { 64 | } 65 | GU_ConstDetailHandle detail() const 66 | { 67 | return GU_ConstDetailHandle(myGdp); 68 | } 69 | 70 | void incref() { myRef++; } 71 | bool decref() { myRef--; return !myRef; } 72 | private: 73 | GU_DetailHandle myGdp; 74 | int myRef; 75 | }; 76 | // The cache is quite simple, we just support lod's between 1 and 32. 77 | #define MIN_LOD 1 78 | #define MAX_LOD 32 79 | static CacheEntry *theCache[MAX_LOD+1]; 80 | static UT_Lock theLock; 81 | 82 | static GU_ConstDetailHandle 83 | getSphere(int lod) 84 | { 85 | UT_AutoLock lock(theLock); 86 | lod = SYSclamp(lod, MIN_LOD, MAX_LOD); 87 | if (!theCache[lod]) 88 | theCache[lod] = new CacheEntry(lod); 89 | theCache[lod]->incref(); 90 | return theCache[lod]->detail(); 91 | } 92 | static void 93 | releaseSphere(int lod) 94 | { 95 | UT_AutoLock lock(theLock); 96 | UT_ASSERT(theCache[lod]); 97 | if (theCache[lod]->decref()) 98 | { 99 | delete theCache[lod]; 100 | theCache[lod] = NULL; 101 | } 102 | } 103 | } 104 | 105 | GU_PackedSphere::GU_PackedSphere() 106 | : GU_PackedImpl() 107 | , myDetail() 108 | , myLOD(2) 109 | { 110 | } 111 | 112 | GU_PackedSphere::GU_PackedSphere(const GU_PackedSphere &src) 113 | : GU_PackedImpl(src) 114 | , myDetail() 115 | , myLOD(src.myLOD) 116 | { 117 | } 118 | 119 | GU_PackedSphere::~GU_PackedSphere() 120 | { 121 | clearSphere(); 122 | } 123 | 124 | void 125 | GU_PackedSphere::install(GA_PrimitiveFactory *gafactory) 126 | { 127 | UT_ASSERT(!theFactory); 128 | if (theFactory) 129 | return; 130 | 131 | theFactory = new SphereFactory(); 132 | GU_PrimPacked::registerPacked(gafactory, theFactory); 133 | } 134 | 135 | void 136 | GU_PackedSphere::clearSphere() 137 | { 138 | if (myLOD > 0 && myDetail.isValid()) 139 | { 140 | releaseSphere(myLOD); 141 | myDetail = GU_ConstDetailHandle(); 142 | myLOD = 0; 143 | } 144 | } 145 | 146 | GU_PackedFactory * 147 | GU_PackedSphere::getFactory() const 148 | { 149 | return theFactory; 150 | } 151 | 152 | GU_PackedImpl * 153 | GU_PackedSphere::copy() const 154 | { 155 | return new GU_PackedSphere(*this); 156 | } 157 | 158 | void 159 | GU_PackedSphere::clearData() 160 | { 161 | clearSphere(); 162 | } 163 | 164 | bool 165 | GU_PackedSphere::isValid() const 166 | { 167 | return myDetail.isValid(); 168 | } 169 | 170 | #define LOD_TOKEN "lod" 171 | 172 | bool 173 | GU_PackedSphere::load(const UT_Options &options, const GA_LoadMap &) 174 | { 175 | update(options); 176 | return true; 177 | } 178 | 179 | void 180 | GU_PackedSphere::update(const UT_Options &options) 181 | { 182 | int ival; 183 | if (options.importOption(LOD_TOKEN, ival)) 184 | setLOD(ival); 185 | } 186 | 187 | bool 188 | GU_PackedSphere::save(UT_Options &options, const GA_SaveMap &map) const 189 | { 190 | options.setOptionI(LOD_TOKEN, myLOD); 191 | return true; 192 | } 193 | 194 | bool 195 | GU_PackedSphere::getBounds(UT_BoundingBox &box) const 196 | { 197 | // All spheres are unit spheres with transforms applied 198 | box.initBounds(-1, -1, -1); 199 | box.enlargeBounds(1, 1, 1); 200 | // If computing the bounding box is expensive, you may want to cache the 201 | // box by calling setBoxCache(box) 202 | return true; 203 | } 204 | 205 | bool 206 | GU_PackedSphere::getRenderingBounds(UT_BoundingBox &box) const 207 | { 208 | // When geometry contains points or curves, the width attributes need to be 209 | // taken into account when computing the rendering bounds. 210 | return getBounds(box); 211 | } 212 | 213 | void 214 | GU_PackedSphere::getVelocityRange(UT_Vector3 &min, UT_Vector3 &max) const 215 | { 216 | min = 0; // No velocity attribute on geometry 217 | max = 0; 218 | } 219 | 220 | void 221 | GU_PackedSphere::getWidthRange(fpreal &min, fpreal &max) const 222 | { 223 | min = max = 0; // Width is only important for curves/points. 224 | } 225 | 226 | bool 227 | GU_PackedSphere::unpack(GU_Detail &destgdp) const 228 | { 229 | // This may allocate geometry for the primitive 230 | GU_DetailHandleAutoReadLock rlock(getPackedDetail()); 231 | if (!rlock.getGdp()) 232 | return false; 233 | return unpackToDetail(destgdp, rlock.getGdp()); 234 | } 235 | 236 | GU_ConstDetailHandle 237 | GU_PackedSphere::getPackedDetail() const 238 | { 239 | if (!myDetail.isValid() && myLOD > 0) 240 | { 241 | /// We only get the sphere on demand. If the user only requests the 242 | /// bounding box (i.e. the viewport LOD is set to "box"), then we never 243 | /// have to actually create the sphere's geometry. 244 | GU_PackedSphere *me = const_cast(this); 245 | me->myDetail = getSphere(myLOD); 246 | } 247 | return myDetail; 248 | } 249 | 250 | void 251 | GU_PackedSphere::setLOD(exint l) 252 | { 253 | clearSphere(); 254 | myLOD = l; 255 | topologyDirty(); // Notify base primitive that topology has changed 256 | } 257 | 258 | /// DSO registration callback 259 | void 260 | newGeometryPrim(GA_PrimitiveFactory *f) 261 | { 262 | GU_PackedSphere::install(f); 263 | } 264 | -------------------------------------------------------------------------------- /packedsphere/GU_PackedSphere.h: -------------------------------------------------------------------------------- 1 | /* 2 | * PROPRIETARY INFORMATION. This software is proprietary to 3 | * Side Effects Software Inc., and is not to be reproduced, 4 | * transmitted, or disclosed in any way without written permission. 5 | * 6 | * Produced by: 7 | * Side Effects Software Inc 8 | * 123 Front Street West, Suite 1401 9 | * Toronto, Ontario 10 | * Canada M5J 2M2 11 | * 416-504-9876 12 | * 13 | * NAME: GU_PackedSphere.h (GU Library, C++) 14 | * 15 | * COMMENTS: 16 | */ 17 | 18 | #ifndef __GU_PackedSphere__ 19 | #define __GU_PackedSphere__ 20 | 21 | #include 22 | 23 | class GU_PrimPacked; 24 | 25 | namespace HDK_Sample 26 | { 27 | 28 | /// Example of a simple packed primitive 29 | /// 30 | /// The packed primitive created references a GU_Detail containing a polysoup 31 | /// of a sphere. The primitive has a single parameter: 32 | /// - LOD @n 33 | /// The level of detail (i.e. the level of refinement of the icosahedron) 34 | /// 35 | /// Each sphere primitive shares its geometry with other spheres of the same LOD 36 | class GU_PackedSphere : public GU_PackedImpl 37 | { 38 | public: 39 | GU_PackedSphere(); 40 | GU_PackedSphere(const GU_PackedSphere &src); 41 | virtual ~GU_PackedSphere(); 42 | 43 | static void install(GA_PrimitiveFactory *factory); 44 | 45 | /// @{ 46 | /// Virtual interface from GU_PackedImpl interface 47 | virtual GU_PackedFactory *getFactory() const; 48 | virtual GU_PackedImpl *copy() const; 49 | virtual void clearData(); 50 | 51 | virtual bool isValid() const; 52 | virtual bool load(const UT_Options &options, const GA_LoadMap &map); 53 | virtual void update(const UT_Options &options); 54 | virtual bool save(UT_Options &options, const GA_SaveMap &map) const; 55 | virtual bool getBounds(UT_BoundingBox &box) const; 56 | virtual bool getRenderingBounds(UT_BoundingBox &box) const; 57 | virtual void getVelocityRange(UT_Vector3 &min, UT_Vector3 &max) const; 58 | virtual void getWidthRange(fpreal &min, fpreal &max) const; 59 | virtual bool unpack(GU_Detail &destgdp) const; 60 | virtual GU_ConstDetailHandle getPackedDetail() const; 61 | /// @} 62 | 63 | /// @{ 64 | /// Member data accessors for intrinsics 65 | exint lod() const { return myLOD; } 66 | void setLOD(exint l); 67 | /// @} 68 | 69 | private: 70 | void clearSphere(); 71 | 72 | GU_ConstDetailHandle myDetail; 73 | exint myLOD; 74 | }; 75 | 76 | } // End namespace 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /packedsphere/README.TXT: -------------------------------------------------------------------------------- 1 | == What this is == 2 | 3 | A sample of adding a new primitive to Houdini using the simplified 4 | packed primitive interface. 5 | 6 | == Notes on how it works == 7 | 8 | The GU_PackedSphere implements the interface for a packed primitive. 9 | If you contrast this with the tetprim example, you'll see that this is 10 | a much simpler interface. In addition, the rendering of packed 11 | primitives is handled automatically. 12 | 13 | The packedsphere.C stand-alone application saves a single packed 14 | primitive to a disk file. 15 | 16 | == How to build == 17 | 18 | hcustom GU_PackedSphere.C 19 | hcustom -s packedsphere.C 20 | -------------------------------------------------------------------------------- /packedsphere/packedsphere.C: -------------------------------------------------------------------------------- 1 | /* 2 | * PROPRIETARY INFORMATION. This software is proprietary to 3 | * Side Effects Software Inc., and is not to be reproduced, 4 | * transmitted, or disclosed in any way without written permission. 5 | * 6 | * Produced by: 7 | * Side Effects Software Inc 8 | * 123 Front Street West, Suite 1401 9 | * Toronto, Ontario 10 | * Canada M5J 2M2 11 | * 416-504-9876 12 | * 13 | * NAME: packedsphere.C 14 | * 15 | * COMMENTS: 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | static void 24 | usage(const char *program) 25 | { 26 | fprintf(stderr, "Usage: %s [options]\n", program); 27 | fprintf(stderr, "Options:\n"); 28 | fprintf(stderr, " -l lod Sphere level of detail [default: 3]\n"); 29 | fprintf(stderr, " -o file Save geometry to file [default: stdout.geo]\n"); 30 | fprintf(stderr, " -v vlod Viewport level of detail [default: 'full']\n"); 31 | fprintf(stderr, " Choose one of:\n"); 32 | for (int i = 0; i < GEO_VIEWPORT_NUM_MODES; ++i) 33 | { 34 | fprintf(stderr, " - %s\n", GEOviewportLOD((GEO_ViewportLOD)i)); 35 | } 36 | } 37 | 38 | int 39 | main(int argc, char *argv[]) 40 | { 41 | // Make sure to install the GU plug-ins 42 | GU_Detail::loadIODSOs(); 43 | 44 | // Process command line arguments 45 | UT_Args args; 46 | args.initialize(argc, argv); 47 | args.stripOptions("l:o:v:h"); 48 | 49 | if (args.found('h')) 50 | { 51 | usage(argv[0]); 52 | return 1; 53 | } 54 | 55 | const char *output = args.found('o') ? args.argp('o') : "stdout.geo"; 56 | int lod = args.found('l') ? args.iargp('l') : 3; 57 | const char *viewportLOD = args.found('v') ? args.argp('v') : "full"; 58 | GU_Detail gdp; 59 | 60 | // Create a packed sphere primitive 61 | GU_PrimPacked *pack = GU_PrimPacked::build(gdp, "PackedSphere"); 62 | if (!pack) 63 | fprintf(stderr, "Can't create a packed sphere\n"); 64 | else 65 | { 66 | // Set the location of the packed primitive's point. 67 | UT_Vector3 pivot(0, 0, 0); 68 | pack->setPivot(pivot); 69 | gdp.setPos3(pack->getPointOffset(0), pivot); 70 | 71 | // Set the options on the sphere primitive 72 | UT_Options options; 73 | options.setOptionI("lod", lod); 74 | pack->implementation()->update(options); 75 | pack->setViewportLOD(GEOviewportLOD(viewportLOD)); 76 | 77 | // Save the geometry. With the .so file installed, this should load 78 | // into Houdini and should be rendered by mantra. 79 | if (!gdp.save(output, NULL).success()) 80 | fprintf(stderr, "Error saving to: %s\n", output); 81 | } 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /standalone/gengeovolume.C: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | *---------------------------------------------------------------------------- 26 | */ 27 | 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | static void 37 | usage(const char *program) 38 | { 39 | cerr << "Usage: " << program << "\n"; 40 | } 41 | 42 | static inline float 43 | sphereVal(int i, int j, int k, int xres, int yres, int zres) 44 | { 45 | float x, y, z; 46 | 47 | x = 2.0F * (i-0.5F*xres+0.5F) / xres; 48 | y = 2.0F * (j-0.5F*yres+0.5F) / yres; 49 | z = 2.0F * (k-0.5F*zres+0.5F) / zres; 50 | return SYSsqrt(x*x + y*y + z*z) < 1.0F ? 1.0F : 0; 51 | } 52 | 53 | // Generate a volume primitive with a resolution of 16x16x16. The volume 54 | // primitive will be dumped as binary output to standard output. 55 | // 56 | // Build using: 57 | // hcustom -s gengeovolume.C 58 | // 59 | // Example usage: 60 | // gengeovolume > volume.bgeo 61 | int 62 | main(int argc, char *argv[]) 63 | { 64 | CMD_Args args; 65 | GU_Detail gdp; 66 | GU_PrimVolume *volume; 67 | const int xres = 16; 68 | const int yres = 16; 69 | const int zres = 16; 70 | const int binary = 1; 71 | int i, j, k; 72 | 73 | args.initialize(argc, argv); 74 | 75 | if (args.argc() != 1) 76 | { 77 | usage(argv[0]); 78 | return 1; 79 | } 80 | 81 | volume = (GU_PrimVolume *)GU_PrimVolume::build(&gdp); 82 | 83 | // The COW handle will write data to the voxel array on destruction 84 | { 85 | UT_VoxelArrayWriteHandleF handle = volume->getVoxelWriteHandle(); 86 | 87 | handle->size(xres, yres, zres); 88 | for (i = 0; i < xres; i++) 89 | for (j = 0; j < yres; j++) 90 | for (k = 0; k < zres; k++) 91 | handle->setValue(i, j, k, 92 | sphereVal(i, j, k, xres, yres, zres)); 93 | } 94 | 95 | gdp.save(std::cout, binary, 0); 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /standalone/geoisosurface.C: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | *---------------------------------------------------------------------------- 26 | */ 27 | 28 | #include 29 | #include 30 | 31 | namespace HDK_Sample { 32 | 33 | static float 34 | densityFunction(const UT_Vector3 &P, void *data) 35 | { 36 | // Return the signed distance to the unit sphere 37 | return 1 - P.length(); 38 | } 39 | 40 | } 41 | 42 | int 43 | main(int argc, char *argv[]) 44 | { 45 | GU_Detail gdp; 46 | UT_BoundingBox bounds; 47 | 48 | // Evaluate the iso-surface inside this bounding box 49 | bounds.setBounds(-1, -1, -1, 1, 1, 1); 50 | 51 | // Create an iso-surface 52 | gdp.polyIsoSurface(HDK_Sample::densityFunction, NULL, bounds, 20, 20, 20); 53 | 54 | // Save to sphere.bgeo 55 | gdp.save("sphere.bgeo", NULL); 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /standalone/i3dsphere.C: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 3 | * Side Effects Software Inc. All rights reserved. 4 | * 5 | * Redistribution and use of Houdini Development Kit samples in source and 6 | * binary forms, with or without modification, are permitted provided that the 7 | * following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. The name of Side Effects Software may not be used to endorse or 11 | * promote products derived from this software without specific prior 12 | * written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 17 | * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 19 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 20 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 23 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | *---------------------------------------------------------------------------- 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | namespace HDK_Sample { 37 | 38 | static void 39 | error(const char *msg) 40 | { 41 | fprintf(stderr, "Error: %s\n", msg); 42 | UT_Exit::exit( UT_Exit::EXIT_GENERIC_ERROR ); 43 | } 44 | 45 | static void 46 | i3dSphere(int nvalues, 47 | const UT_Vector3 *P, 48 | fpreal32 *result[], 49 | const char *names[], 50 | int sizes[], 51 | int for_aa) 52 | { 53 | fpreal32 *density; 54 | fpreal32 *color; 55 | int i; 56 | fpreal d; 57 | 58 | // Verify correct channels 59 | UT_ASSERT(!strcmp(names[0], "density") && sizes[0] == 1); 60 | UT_ASSERT(!strcmp(names[1], "color") && sizes[1] == 3); 61 | density = result[0]; 62 | color = result[1]; 63 | 64 | for (i = 0; i < nvalues; i++) 65 | { 66 | // Density is 1 inside the sphere and 0 outside 67 | d = P[i].length() > 1 ? 0 : 1; 68 | *density = d; 69 | color[0] = d * SYSfit(P[i].x(), -1, 1, 0, 1); 70 | color[1] = d * SYSfit(P[i].y(), -1, 1, 0, 1); 71 | color[2] = d * SYSfit(P[i].z(), -1, 1, 0, 1); 72 | 73 | // Now, move the result buffers to the next pixel 74 | density += 1; // Skip to the next float 75 | color += 3; // Skip three floats 76 | } 77 | } 78 | 79 | } // End of HDK_Sample namespace 80 | 81 | using namespace HDK_Sample; 82 | 83 | int 84 | main(int argc, char *argv[]) 85 | { 86 | IMG3D_Manager fp; 87 | UT_BoundingBox bounds; 88 | const char *chnames[2] = { "density", "color" }; 89 | int chsizes[2] = { 1, 3 }; 90 | 91 | printf("Generating sphere.i3d\n"); 92 | bounds.initBounds(-1, -1, -1); 93 | bounds.enlargeBounds(1, 1, 1); 94 | if (!fp.createTexture("sphere.i3d", bounds, 10, 10, 10)) 95 | error("Unable to createTexture()"); 96 | 97 | if (!fp.fillTexture(2, chnames, chsizes, i3dSphere, 1)) 98 | error("Unable to fill the texture"); 99 | 100 | if (!fp.exportTag("software", "hdk_isosphere")) 101 | error("Unable to save software tag"); 102 | 103 | if (!fp.closeTexture()) 104 | error("Unable to close texture"); 105 | 106 | return 0; 107 | } 108 | --------------------------------------------------------------------------------