using the "find" command to find joints

Ok david I took your advice and I am using find instead of exposeJoints this time around so i don’t have to play a null animation on my whole scene.

I am having trouble finding the position of a joint in my entire scene.

Here’s my code:


           # get the tv joint
            tvJoint = self.model.find("**/tv_joint")
            tvJointPos = tvJoint.getPos()

            # make the camera look at the tv joint
            base.camList[1].lookAt(tvJointPos)

            # move the camera toward the tv joint slowly
            base.camList[1].posInterval(14, tvJointPos).start()

im getting the error:

AssertionError: !is_empty() at line 851 of panda/src/pgraph/nodePath.cxx

when I try to get the position of tvJoint, which I assume means that the tv_joint is not being found correctly, which makes tvJoint an unitialized variable, or an empty nodepath?

Any suggestions?

Thanks in advance,

Adam

Right, that means that there was no node called tv_joint in your converted scene. Try typing the interactive command:


myObj.model.ls()

to list the nodes that you actually have.

I’d be willing to bet that there are very few nodes, and that one of them is of type Character–indicating that you are converting your model as an animated character, rather than as a static model. The two kinds of models are very different things in Panda3D.

David

well I was the one who asked you before about exposing joints in our penguin game. I wanted to use the find command this time so I wouldn’t have to run a null animation on the whole scene. I created the model as a model, not as an actor.

And I got “tv_joint” directly from the .egg file, so I don’t understand why it wouldn’t exist…

ok i tried self.sceneModel.ls() in a temp file with the same .egg loaded as a model, and you were right, one of the nodes is type Character.

How do I export the model as a static scene and not as a character?

If you are exporting from maya6, you can explicitly set no animations with:

maya2egg6 -a none mymodel.mb mymodel.egg

This is the default so if you don’t specify the -a parameter, it should work the same way. To see all of the options for an exporter use:

maya2egg6 -h

The -h should work for all exporters included with panda (maya2egg5, x2egg)

Also, I think you can go into the egg and delete the lines that say . I am not sure if this will have any side effects though.

How are you exporting it now? If you are using maya2egg, don’t include the -a option. If you are using the 3DSMax exporter, which I’m not as familiar with, I’m sure there’s a check box that you should uncheck or an animation option that you should set to “none”.

David

I had my modeler export the environment in both the following ways:

I was looking through the egg file for the joint names I needed to find, and I noticed that in both files the joints are there, but there is no coordinate information about them. It’s like they are null joints. Here’s a sample from the egg file:


<Joint> pitc_01 {
}
<Joint> pitc_02 {
}
<Joint> pitc_03 {
}
<Joint> pitc_04 {
}
<Joint> pita_01 {
}
<Joint> pita_02 {
}
<Joint> pita_03 {
}
<Joint> pita_04 {
}

As you can see there’s no coordinate info, so even if the find command DOES work, the joints have no positions in the world.

Any ideas?

You shouldn’t use skeletal joints if you export as a static model. Try using locators where you have the joints placed. You should be able to find and extract position/rotation information from those.

ok I had my modeler export the file the way russ said and I got locators to work instead of joints.

I’m having a small issue with getting the locations of the locators.

The modeler places 4 locators in the same plane to signify an event (like a volumetric trigger), and when our vehicle hits the polygon it does something. In this case, it’s supposed to jump. Here’s my code:

# find the jump in the scene graph
        self.jumpJoint1 = self.worldModel.find("**/jump1_01")
        self.jumpJoint2 = self.worldModel.find("**/jump1_02")
        self.jumpJoint3 = self.worldModel.find("**/jump1_03")
        self.jumpJoint4 = self.worldModel.find("**/jump1_04")
 
        # create a collision polygon at the jump
        self.collisionPoly = CollisionPolygon(self.jumpJoint1.getNetTransform().getPos(),
                                              self.jumpJoint2.getNetTransform().getPos(),
                                              self.jumpJoint3.getNetTransform().getPos(),
                                              self.jumpJoint4.getNetTransform().getPos() )
        
        self.collisionNodePath = render.attachNewNode(CollisionNode('jump'))
        self.collisionNodePath.node().addSolid(self.collisionPoly)

        self.collisionNodePath.show()

I’m getting an error with the getNetTransform().getPos(). The error is: "TypeError: Invalid Argument 0, expected ".

When I use self.jumpJoint.getPos() it works but the joints are not in the correct location, which is why I opted to use getNetTransform().getPos(). I don’t understand why this doesn’t work, because getNetTransform().getPos() is supposed to return a Point3 type.

Any suggestions?

I solved my own problem, but the solution is kind of funny.

Here’s the new code:


        # find the jump in the scene graph
        self.jumpJoint1 = self.worldModel.find("**/jump1_01")
        self.jumpJoint2 = self.worldModel.find("**/jump1_02")
        self.jumpJoint3 = self.worldModel.find("**/jump1_03")
        self.jumpJoint4 = self.worldModel.find("**/jump1_04")

        # create jump dummy nodes and place them at the locator positions
        self.jumpDummy1 = render.attachNewNode('jumpDummy1')
        self.jumpDummy1.setPos(self.jumpJoint1.getNetTransform().getPos())
        self.jumpDummy2 = render.attachNewNode('jumpDummy2')
        self.jumpDummy2.setPos(self.jumpJoint2.getNetTransform().getPos())
        self.jumpDummy3 = render.attachNewNode('jumpDummy3')
        self.jumpDummy3.setPos(self.jumpJoint3.getNetTransform().getPos())
        self.jumpDummy4 = render.attachNewNode('jumpDummy4')
        self.jumpDummy4.setPos(self.jumpJoint4.getNetTransform().getPos())
 
        # create a collision polygon at the jump
        self.collisionPoly = CollisionPolygon(self.jumpDummy1.getPos(),
                                              self.jumpDummy2.getPos(),
                                              self.jumpDummy3.getPos(),
                                              self.jumpDummy4.getPos() )
        
        self.collisionNodePath = render.attachNewNode(CollisionNode('jump'))
        self.collisionNodePath.node().addSolid(self.collisionPoly)

        self.collisionNodePath.show()

So panda doesn’t recognize getNetTransform().getPos() as a point3 by itself, but once I place a dummy node at each locator’s location (using getNetTransform, by the way) then I can getPos() for each locatorDummy and it works fine.

Weird.

This is the difference between a Point3 and a VBase3. getNetTransform().getPos() actually returns a VBase3, which is a base class for Point3. NodePath.getPos() returns a Point3.

Arguably, getNetTransform().getPos() should really return a Point3, and the CollisionPolygon constructor should accept a VBase3 if one is given. But these are minor quibbles with the interface.

You workaround does the trick, but a simpler workaround is to wrap the return value in a Point3 constructor, like this:


self.collisionPoly = \
CollisionPolygon(Point3(self.jumpJoint1.getNetTransform().getPos()),
   Point3(self.jumpJoint2.getNetTransform().getPos()),
   Point3(self.jumpJoint3.getNetTransform().getPos()),
   Point3(self.jumpJoint4.getNetTransform().getPos()) )

David