Physics simulation for character hair

Anything in direct.* is a Python class. Anything in panda3d.* is a C++ class.

I’m not really sure what the best approach is, sorry. But I’ve thought a tiny bit of a vaguely similar problem in the past (IK), so maybe sharing a bit of thoughts on one possible approach I thought of might give you some ideas.
As you may know, the way characters work in Panda is that each Actor really is a wrapper around the C++ class PartBundleNode (or rather, a derived class called Character) which stores a bunch of PartBundles, each of which is the root of a hierarchy of MovingPart objects, which itself is a base class representing, well, a moving part. A common example of a MovingPart is a CharacterJoint.

(The way this actually links up to the geometry is that each vertex stores an index into a table of VertexTransform objects stored on the Geom, which is an abstract base class that represents a particular source of transformations that may be applied to a vertex. One particular implementation of VertexTransform is a JointVertexTransform, which takes its transformation from the CharacterJoint in the PartGroup hierarchy.)

Now there is also AnimBundleNode and AnimBundle, which have a very similar hierarchy, but represent a bunch of animations. Instead of MovingParts this hierarchy stores AnimChannels, which provide a virtual interface for querying the position and orientation of the channel for a given frame. The most common type of AnimChannel is of course the one that takes its transform from a predetermined table, as defined by an animation file.

Now, when you bind an animation, Panda basically walks through an AnimBundle hierarchy and the corresponding PartBundle hierarchy, and basically connects each MovingPart to the appropriate AnimChannel. The AnimChannel basically provides the source for the local transformation matrix of the joint in the hierarchy.

The way Actor.controlJoint function works is that it creates a different type of AnimChannel that doesn’t take its value from an animation table, but instead reads out the position of a node in the scene graph. It assigns this to as a special “forced channel” onto the MovingPart, so that it overrides any bound animation.

Knowing all this, it sounds like it might be an idea to try implementing your own type of AnimChannel, one that takes its value from whatever fancy algorithm you have there. This means you don’t really have to worry creating a task that updates all the joints - instead, you just have to create your hierarchy and bind it once, and Panda’s animation system would be “asking” your channels (by means of a virtual method call) to update their transform appropriately whenever it needs the next animation frame. You would basically be providing local transformations and Panda would automatically calculate the net transformation based on the joint hierarchy.

This isn’t really speaking from experience, though, these are just ideas, and it could be that Panda’s AnimChannel abstraction is a poor fit for what you’re trying to do here.