Multi-part Actor

Yes I am wondering how exactly do I set a Multi-part Actor up?

We have to be careful answering your question–there are multiple different things that might be called “multi-part actors”. I think you are referring to that which russ mentioned in your other thread, which is really just flagging the different pieces of you actor so you can adjust them individually, e.g. set a different texture on the different pieces.

To do this, you will need to pass your model’s egg file (as well as its associated animations) through egg-optchar before you load it, and use the -flag parameter to name the pieces of the geometry that you want to have individual control over. See this page in the manual.

Note that there is another meaning of “multi-part actor” which Panda uses, which means to load up completely different egg files into one composite actor, so that (for instance) your actor’s legs might come from one model file, while his torso and head comes from a different model file. This is much more complicated than simply flagging pieces of a model so you can color them differently.


Ok, so I gave it a try and something failed. Because I get this weird error message every time I try to reset the position of the joint I am trying to grab. I think that my model is not flagging it or something.

Here is the code that I use to flag the head.

egg-optchar -d outputDir -flag head=myHead person1-base.egg person1-panic.egg

And then in the code I try to grab it an move the position with this code

myheader = myActor.find("**/myHead")


And I get some error message refering to how something is empty. The error message talks about the error happening a like line 900 something on some file… any help is appreciated.

myheader = myActor.find("**/myHead")

The NodePath find() method will return an empty NodePath if you try to find something that isn’t there. Since an empty NodePath doesn’t reference a node, it is an error to try to call setPos() on an empty NodePath. Thus, if you are getting an error message about an empty NodePath on line 900 some odd–which I have to assume is your setPos() call, shown above–then it follows that myHead is not the name of a node under myActor.

Incidentally, you can research this yourself a little, with a bit of practice using the NodePath interface. You can do, for instance, to list all of the nodes under your myActor. This way you can confirm whether there is or is not a node called ‘myHead’, without having to guess based on an error message that you get after the fact.

You can also write code that is a little more defensive, for instance, you might write:

myheader = myActor.find("**/myHead")
if myheader.isEmpty():
  print "No myHead node found!"

Finally, you can check for this node in your egg file without even writing a single line of Python code. You can do this by loading it up in pview. When you are looking at your actor onscreen, press the shift-L key (while the mouse pointer is within the pview window) and then look in the console window from which you started pview–it will show output similar to there, and you can look for the myHead node.

In any case. Since we are assuming that myHead was not found within the actor’s hierarchy, it follows that egg-optchar didn’t create a myHead node. It would do this if there were no geometry pieces that were called “head”. I’m betting that “head” is the name of one of your joints, but not the name of one of your geometry pieces.

The -flag option to egg-optchar wants the name of a piece of geometry–this would be a polyset, or mesh, or whatever it’s called in your modeling package of choice. If you examine the egg file in a text editor, this will be the name of a that contains a bunch of entries.

In order to flag all of the pieces of geometry within the “head” joint, you will need to know what these pieces of geometry were called within the modeling package that created your model. They may have useful names like “nose”, “left_eye”, and “right_eye”, or they may have names like “polyset123”, “polyset124”, and “polyset125”. Whatever these names are, pass them to the -flag option of egg-optchar, e.g. -flag polyset123=myHead.

Then pview the resulting egg file and press shift-L, or load it up in Python and use, to confirm that a node called myHead does, indeed, exist.


So you are saying that you cannot use the you have to use one of these Because that is all I am doing right now trying to flag the head joint.

Also is there a way that I can manually enter a flag into an EGG file? If so what is the code?

Right. Joints and groups are different things. Remember, a joint is just an invisible transform that animates your character’s vertices, but the geometry itself isn’t contained within the joint; it’s contained within a group.

You can expose a joint, which means Panda will create a node that tracks the joint’s motion, so you can e.g. parent geometry to your character’s hand. But this only reveals the invisible transform of the joint; it has nothing to do with the geometry of your character. The geometry is contained in groups. If you flag a group, Panda will put the geometry of that group within a separate PandaNode so you can manipulate the geometry separately.

You can flag a group by hand, if you prefer. It means you should edit each entry to add a name in front of the curly brace, like this:

<Polygon> myObject {

This will create a node called “myObject” and put all of the polygons so flagged in that node.


Is there anyway that I can tell the the EGG softwear to grab all the polygons connected to the joint I am trying to grab?

That’s what egg-optchar does when you specify the -flag option. Except that it flags the polygons associated with a particular group (polyset), not a particular joint.

You can’t flag the polygons associated with a particular joint, because there is not a clearly-defined set of polygons associated with a joint. Some polygons might be 20% associated with a particular joint, for instance–how should these polygons be flagged?


I want them to be flagged like “head” it flages the head. “Body” flags the torso “lArm” flags the left arm and so on and so forth.

Yes, I understand what you want. But consider: “Body” flags the torso and “lArm” flags the left arm, fine. But what about the polygons that connect the torso to the left arm? Unless your character is built like a robot or a plastic toy, there will be some polygons whose vertices are partially in the torso and partially in the left arm. Which color should those polygons be?

A joint is not a unique handle to a group of polygons. But a mesh is. If you want to color the left arm separately from the torso, you will need to make your model with two different meshes, one for the torso, and one for the left arm. That way you can decide exactly where the line between the torso and the arm lies. And then you can use the -flag option to to egg-optchar to ensure that each mesh is individually accessible in Panda.


I see, so I guess my question would be is there anyway that panda can detect these polygon groups for me? You know so I don’t have to manually go in and read them?

You can write a program that uses the egg library to read in your model, examine each polygon, and decide what the predominant joint assignment of that polygon is. Then you can assign the polygon to a corresponding group if you like. (Or just name the polygon; this is what -flag does, after all. All polygons with a common name will be put into a common GeomNode at load time.)

You will have to write this program; it doesn’t exist already. It can be a Python program. It need not be a complex program, but you will need to learn to use the egg library.


totally agreed with you

Ahhh I see thanks. Once I understand more about 3-D models and have the time to do something like that I will. Thanks for the help.