Rotations with respect to other nodepaths

import direct.directbase.DirectStart

firstPath = render.attachNewNode("first")
secondPath = render.attachNewNode("second")

#I chose these numbers randomly
firstPath.setHpr(35.0, 76.8, 134.3)
secondPath.setH(firstPath, 55.0)

print secondPath.getHpr()

The output I get from this is:
[VBase3 at: 108531200]
-21.8548 1.19006 95.6434

This seems strange since all I tried to change on secondPath was the heading, but the pitch and roll were also changed. I attached some models to the nodepaths, thinking that I could see that the secondPath heading was somehow 55 degrees of the firstPath, but what I saw did not make any sense. Is this supposed to happen? I realize that rotations aren’t completely straightforward, but I would not expect a setH command to change all 3 dimensions.

The interpretation of secondPath.setH(firstPath, 55.0) is to set the heading of secondPath in the relative space of firstPath–not in the space of secondPath. To illustrate:

firstPath = render.attachNewNode("first")
secondPath = render.attachNewNode("second")
firstPath.setHpr(35.0, 76.8, 134.3)
print secondPath.getHpr(firstPath)
-42.2951 75.3519 -129.099
secondPath.setH(firstPath, 55.0)
print secondPath.getHpr(firstPath)
55 75.3519 -129.099

There’s some room for debate about the way this ought to be interpreted, but at the end of the day we decided that this interpretation is the most useful.

Still, there is always danger of misbehavior when you set just h in absence of p and r, especially with a relative operation like this, since p and r might flip around 180 degrees without warning–which will make h do strange things if you separate it from p and r. For this reason, unless you are sure that p and r are both zero, it’s usually best always to set all three components at once by using setHpr() instead of just setH().

David

Right, thanks David. I was just thinking that it should set the secondPath heading and only the heading with respect to the space of the firstPath. But I see how this works better. In my case however, I would want to set the h in the relative space and set the p and r later separately. If I called a setHpr(firstPath, 55.0, 0.0, 0.0) I would still transfer extra information from the firstPath space to the secondPath.
(tested it out: -92.5504 43.8121 -102.768)

so I guess I would want something like:


firstPath = render.attachNewNode("first")
secondPath = render.attachNewNode("second")

firstPath.setHpr(35.0, 76.8, 134.3)

secondPath.setH(firstPath, 55.0)
secondPath.setP(0)
secondPath.setR(0)

maybe secondPath.setH could be changed to secondPath.setHpr and use zeros for the other two values, but I would still have to set them to zero again afterwards.

Right, that would do the trick. But let me reiterate my warning: Euler angles, by their nature, are dangerous to handle componentwise. If you always control all three values explicitly, you can safely deal with the components individually; but if one or two of the components is getting computed indirectly, you might be in for some surprises.

For instance, (135, 180, 180) and (45, 0, 0) represent the same rotation. But (135, 0, 0) is something completely different. Whenever you compute a relative hpr, there is some danger that the answer will come back as something like (135, 180, 180), and then if you blindly zero out p and r, your h will be left facing in the wrong direction.

If your goal is to rotate the object to a particular direction and then level it out, consider using headsUp(), or creating a CompassEffect, rather than explicitly setting the p and r to zero.

David

Is it as dangerous to do

setHpr(node, 90,0,0)

than to do
setH(node,90)
setP(0)
setR(0)?

No, in fact, either of those is perfectly safe–because you are directly specifying all three components of hpr in both cases.

The danger only lies in computing one of the three components indirectly, for instance from a relative operation with another node, and specifying the other two directly.

David

Oh, whoops–in my haste, I misread Manakel’s post. I overlooked the relative operation. Sorry about that!

So to answer your question correctly, the following is perfectly safe:


setHpr(node, 90,0,0)

while this is a little dangerous (it is subject to ambiguity):

setH(node,90)
setP(0)
setR(0)

David