Physics simulation for character hair

It doesn’t sound to me like the two things you mention are mutually exclusive. You could have an encompassing class that inherits from PandaNode (directly or indirectly), which binds the appropriate AnimChannels to the joints, just as we have both Character as well as CharacterJoint.

Since you’re working in C++ and don’t have controlJoint, keep in mind that there is no escaping from using AnimChannel with that approach either. As I said before, the way controlJoint works is by assigning an AnimChannelMatrixDynamic to the joint, which takes its input from an assigned dummy node. The only difference in what I’m proposing would be that you assign your own version of AnimChannel that computes its value from your algorithm whenever Panda asks for it, rather than having to use a task to assign values to dummy nodes each frame. So whether you make a custom PandaNode implementation or not, you’re going to end up assigning an AnimChannel of some sort to the joint.

Now, it gets a bit tricky if (as you say) you need the global coordinates of the parent joints. As far as I know, an AnimChannel does not have access to the transform of the parent joint - it just delivers a local transform. You could of course use the exposeJoint mechanism, which on the C++ side would have you set a flag on MovingPart to update an external node position when the transform changes. It sounds a bit unnecessarily expensive to be relying on the scene graph for this. One idea might be that you just replace the joint itself with your own MovingPart derivative (ie. inheriting from CharacterJoint), which does have access to this information.

Or maybe we should just extend the AnimChannel mechanism so that it is passed the matrix of the parent joint so that the AnimChannel might take that into account when calculating its matrix. I don’t think the AnimChannel mechanism was designed to be used in this way, but maybe this would be the neatest way.