Cameron White

cwhite

About Me

EXPERTISE
Developer

Connect

LOCATION
Canada
WEBSITE

Houdini Skills

Availability

Not Specified

My Badges

SideFX Staff
Since Oct 2012

My Tutorials

obj-image Masterclass
H19 Crowds
obj-image Masterclass
RBD Tools Update | H17 Masterclass
obj-image Masterclass
Masterclass | Crowds in Houdini 15.5
obj-image Masterclass
H15 Masterclass | Crowds

My Talks

obj-image HIVE
H20 Crowds | SOP-based Workflow
obj-image HIVE
Crowds

Recent Forum Posts

HDK create new AgentShapeDeformer July 8, 2025, 3:29 p.m.

No, that all is specific to OP nodes. It should be roughly something like:

class MyAgentDeformer : public GU_AgentShapeDeformer
{
    ...
};

void
GUregisterAgentShapeDeformer()
{
    GU_AgentLayer::registerDeformer(UTmakeIntrusive<MyAgentDeformer>());
}

// If you're also creating shape bindings from C++, use GU_AgentLayer::findDeformer(your_deformer_name) to access the deformer instance, or store the instance you passed to registerDeformer() somewhere

HDK create new AgentShapeDeformer July 8, 2025, 11:42 a.m.

redpaw
In this case, does "deform" still work similarly/replacing (cookMysop) at the sops level? or is it different? I see that you get access to a detail based on what "shape" is passed to it, which I assume is a standard detail gdp I can iterate thru the points of?

Yeah this would be essentially the same idea - the GU_Detail that's provided contains a copy of the shape's rest geometry, and your deform() method should modify it to apply your deformer
Unlike a SOP node, one thing to note is that there is only a single instance of your deformer and its deform() method might be called in parallel to deform multiple shapes. So you just need to be cautious about any caching anything in member variables of your deformer

redpaw
Also hoping that I can access the "rig" skeleton to get transforms/names etc.. from the GU_Agent that is passed?
I'm a bit fuzzy on what the "xform_idx" refers to, any better explanation for that? What data array is that an index into?
Yes, from the GU_Agent you can access the joint names etc via GU_Agent::getRig(), and methods like GU_Agent::computeWorldTransforms() will give you the agent's current pose

The `xform_idx` is from the shape binding [www.sidefx.com], and would be >= 0 if this shape was attached to a joint in the agent's skeleton. This would be an index into the agent rig's list of transforms
As the documentation notes, you may not need to do anything with this since the resulting geometry is always transformed for you afterwards by this joint's transform. But for certain deformers you might need this (e.g. the skinning deformer first needs to apply the inverse of this transform)

redpaw
There is only explanation in the docs.... "Deformers are registered by calling GU_AgentLayer::registerDeformer() from the GUregisterAgentShapeDeformer() entry point." but I'm not entirely sure what that entails? Are there other examples of "registering" nodes I could reference?

You would need to have a function named GUregisterAgentShapeDeformer() in your plugin, which will be called when it's loaded by Houdini - https://www.sidefx.com/docs/hdk/_h_d_k__intro__creating_plugins.html [www.sidefx.com] has some more information and an example for the newSopOperator entry point
The SOP_BouncyAgent HDK example also has an example for GUregisterAgentCustomDataItemType() which is essentially the same idea as GUregisterAgentShapeDeformer(), just with a different function name

HDK operate on chunks of points based on "path" June 25, 2025, 9:58 a.m.

Great!
One other note is that you might be able to use GA_Range to build the point range from the primitive offsets, something like (untested)
GA_Range prim_range(geo.getPrimitiveMap(), prim_offset_list);
GA_Range pt_range(geo, prim_range, GA_ATTRIB_POINT, GA_Range::primitiveref(), /*harden*/false);
for (GA_Offset ptoff : pt_range)
{
    ...
}