getHpr returning (0,0,0) - lookAt doesn't work

I’m trying to paint a set of blocks with a paint brush and it is important that I can find the Hpr of each block or get lookAt to work so the brush is at the right angle so it looks like it is painting the block.

I’ve flagged individual shapes in my egg file via egg-optchar -flag block1 -flag block2 … etc.

I can find the position for each “block”, but the Hpr is returning (0,0,0).

blockGroup = Actor(...)

paintBrush = Actor(...)

block1 = blockGroup.find("**/block1")
print block1.getHpr() #returns (0,0,0)
#also tried:
# block1.getHpr(render)
# block1.getHpr(blockGroup)

paintBrush.lookAt(block1)  #does not work
ival = paintBrush.posInterval(...) #pos found via getBounds().getCenter()


I’m fairly new to Panda so if I’m way off then I’m sorry, but from my experience parenting the paintBrush node to the blockGroup node will give it the same rotation/position/etc as the parent without changing the actual value… if that is really what it is doing. You might have to parent a dummyNode to the blockGroup as a placeholder and then have your paintBrush parented to the dummyNode to allow it free movement.


I do have a dummy setup because my model origin / orientation isn’t correct.

So it more looks like:
Blockgroup <- dummy <- paintbrush.

So block1 is part of blockGroup, does an internal node have an Hpr?

All nodes have a hpr, but I think you are misunderstanding what hpr means. The hpr is the rotation of the node relative to its parent, specified as a three-coordinate tuple in Euler coordinates. It is usually (0,0,0) unless you explicitly set it to something else. Also, it has nothing to do with rotating to point at particular object.

lookAt() is a function which will compute the correct hpr necessary for one object to point at another object. But it computes it for the Y axis only: this means you can use brush.lookAt(block) to rotate the Y axis of your brush to face any block you like. This doesn’t necessarily mean it will point your brush at the block; that depends on how you have modeled your brush. If you have created the brush model so that the bristles point down the Y axis, then brush.lookAt() will have the desired effect. Oh, and you also have to create your block model so that (0,0,0) is in the center of the block, since brush.lookAt(block) will rotate the Y axis of the brush to face the (0,0,0) point of the block.


Thanks David.

So it sounds like there isn’t a way to get the direction that block1’s face is pointing? (block1 is part of blockgroup with multiple blocks that can be pointing in different directions.)

Sure, you just have to clarify precisely what you’re asking. When you say “the direction block1’s face is pointing”, what do you want to know? Do you want a vector that corresponds to block1’s Y axis, as expressed in the coordinate space of some different node? Do you want a HPR rotation that corresponds to block1’s rotation as seen in some node’s coordinate space? Or something else entirely?


block1, block2, etc are all part of the blockgroup egg file and the blocks are oriented in different directions. I’m finding them via blockGroup.find("**/block1"). So I’d assume that all blocks are part of blockgroup’s coordinate space.

I want to find the Y direction for block1 so then I can use that to orient my paintbrush node correctly (probably rotated 180 degrees).


Whenever you ask “what is the Y direction for block1” the answer is always (0, 1, 0) in block1’s own coordinate space, because that’s the Y axis. The more interesting question is “what is the Y direction for block1 in the coordinate space of N”, where N is some other node.

In this case, since you’re talking about rotating your brush to match the block’s orientation, perhaps you mean you want to know the Y direction of block1 in the coordinate space of the brush’s parent node, which is the same coordinate space in which you will need to rotate the brush. To ask this question, you can ask Panda:

v = brush.getParent().getRelativeVector(block1, (0, 1, 0))

But I don’t honestly know you are going to do with that vector. It’s just a direction; it’s not a rotation. If you want to rotate the brush to the same orientation as the block, you have to ask for the block’s HPR rotation in the coordinate space of the brush’s parent:

hpr = block1.getHpr(brush.getParent())

A shorter way to do the same thing is with:

brush.setHpr(block1, 0, 0, 0)

which asks the brush to set itself to hpr (0, 0, 0) in block1’s coordinate space, which is the same thing as block1’s hpr expressed in the brush’s parent’s coordinate space.

But all of this relies on the assumption that the rotations you speak of are expressed in scene graph transforms. I don’t know where your blocks came from, but if you created the stack of blocks in a modeling package such as Blender, and then exported the whole scene into Panda via an egg file, then the individual transforms of the blocks may be baked into the vertices, and no longer available to you. In this case, block1.getHpr() will always return (0, 0, 0) no matter which coordinate space you ask it to switch to, since all blocks will have the same coordinate space. If this is your case, then you will need to use more caution when converting your scene to Panda, and add the appropriate tags to each block so that Panda knows not to bake out the transforms.


Thanks for the great explanation. I’m still getting (0,0,0) out of the node’s hpr.

I’m using Maya for the model. Do I have to tag the shape in Maya somehow so the tag is retained or can I just edit the egg file? (DCS does not show up now)

block1 {
polySurfaceShape51.verts {
0 {
17.145 -0.802888 5.70154
{ 0.0990109 0.797354 }
{ 0.414127 0.0886166 -0.905895 }
{ 1 1 1 1 }
{ 1 } #go here on each Vertex?

If you edit the egg file, you should add { 1 } within each entry that corresponds to a block. It should be alongside a entry that will also appear in the same group. (If there is not a entry there, then the entry will have little effect.)

You don’t have to edit the egg file, though; you can add a DCS flag via Maya if you import the eggObjectFlags.mel script which can be found in the source code in pandatool/src/maya. This script will add a pull-down menu to the node attributes list; you can use this pull-down menu to add the “dcs” property to each of your blocks.


I have the DCS tag in there by following these steps: … 0635#20635

The DCS shows up in the egg file and I am now getting a transform by maya2egg -a none (-a model did not work). The transform matrix looks like it only has translational values in it and not rotational (hpr still isn’t working). What am I missing here to get the rotation into the transform?

block2 {
{ 1 }
1 0 0 0
0 1 0 0
0 0 1 0
-3.42055 0 -0.0242086 1
polySurfaceShape56.verts {
0 {
13.9575 -0.758591 8.45089
{ 0.243344 0.574419 }
{ 0.51279 -0.274708 0.813377 }
{ 1 1 1 1 }

That transform is coming directly from Maya, so for some reason there is no rotational transform in Maya. Do you see a rotation on your block2 node in Maya?


There is no rotation explicitly set. I guess I figured that it would have exported a rotation based off of the origin of the model.

Do I have to have my modeler explicitly set them in Maya for the DCS flag to export them out?

I don’t understand. What do you mean by “the origin of the model”? To me, the origin of the model means the (0, 0, 0) point within the model, and has nothing to do with rotation. What rotation value do you expect to see in Panda if there isn’t one set in Maya?


The model is oriented down one axis (what I was calling the origin) and I figured that I could get the transform or rotation off of that axis.

Does that sound familiar as something I can set in Maya to be able to extract the rotation of each block?

Still not following you. But note that the arrangement of the vertices of a model, or the shape of the model, may have nothing to do with its “rotation”. “Rotation” is an explicit property applied after the model has been created, and it rotates the model’s vertices from their original position.

But if the model’s vertices happen to lie along one axis in its original position, there’s no way to ask anything about that axis.

So if you have a bunch of boxes that happen to have different orientations, but those orientations are just baked into their vertices instead of reflected in an explicit rotation value, there’s no way to ask what their relative orientations are (not without painstakingly inspecting each vertex and trying to do some kind of crazy-difficult analysis).