SOPs without inputs usually generate their own geometry when they cook, such as SOP_Circle. All other SOPs, when asked to cook, first ask their relevant input SOPs for their cooked geometry, only cooking own detail afterward, thus recursively traversing up the hierarchy tree along all node input connections.
This has the effect of cooking the most remote nodes first, passing the detail data to its children, and gradually approaching the display or render SOP node which initiated the cook request.
HDK provides several useful function to access input geometry in a SOP while cooking:
If the SOP is interested in receiving both primitive and point group information then parseGroups should be used. It will return both a point and primitive group based on the incoming pattern.
If you are just interested in one type then parsePrimitiveGroups or parsePointGroups may be used. They return a pointer to a GB_PrimitiveGroup or a GB_PointGroup respectively. If nothing was found (nil) is returned.
If isPrim is 1 then it parses only primitive groups. If isPrim is 0 then it parses only point groups.
parseEachGroup takes in the pattern, determines what the groups are and then iterates for each group calling the operation method. GroupOperation is a typedef of a member function that passes in the group and void *data pointer.
typedef void (SOP_Node::*GroupOperation)(GB_Group *, void *);
In addition, setting the bypass flag on a SOP node (using OP_Node::setBypass()) will avoid cooking that node, and will pass its input geometry to the node connected to its output unmodified.
Finally, locking the node (OP_Node::setLock()) will preserve its geometry, and leave it unmodified regardless of whether input geometry changes or not.
void accessGeometry(SOP_Node* sop_node, fpreal cook_time) { // Get our parent. OP_Node *parent_node = sop_node->getParent(); // Store the cooking status of our parent node. bool was_cooking = false; if(parent_node) { was_cooking = parent_node->isCookingRender(); parent_node->setCookingRender(true); } // Create a context with the time we want the geometry at. OP_Context context(cook_time); // Get a handle to the geometry. GU_DetailHandle gd_handle = sop_node->getCookedGeoHandle(context); // Restore the cooking flag, if we changed it. if(parent_node) parent_node->setCookingRender(was_cooking); // Check if we have a valid detail handle. if(!gd_handle.isNull()) { // Lock it for reading. GU_DetailHandleAutoReadLock gd_lock(gd_handle); // Finally, get at the actual GU_Detail. const GU_Detail* gdp = gd_lock.getGdp(); // Do something with our geometry. // ... } }
bool getWorldTransform(SOP_Node* sop_node, fpreal cook_time, UT_DMatrix4 &xform) { OP_Context context(cook_time); OBJ_Node * creator = CAST_OBJNODE(sop_node->getCreator()); return creator->getLocalToWorldTransform(context, xform); }
1.5.9