Obtaining direction vectors from a rotated object

Is there a way to obtain the direction vectors from a rotated object? I mean the up, forward and right side vectors.

I realize that if we can use getHpr from the NodePath to obtain the angles but then how do we obtain a direction vector and then how do we compute the up and side vectors?

I don’t know how to use the hpr vector with the up method. Those methods are static and take a CoordinateSystem as argument.

What i really wanted to do is to have a the WASD keys associated to local movement so that A and D rotates the object around it’s up vector (Z axis) and W and S moves the object backwards or forwards in the direction of it’s local forward vector (Y axis).

The rotation part is easy, i just use obj.setH(obj.getH()+angle). What im having difficulties is the forward/backward movement.

did you keep in mind that all positions and rotations are relative to the objects parent?
so if you rotat your object you wont rotate its xyz coord system. if you move it it’ll still move along the parents x.y.z axis
(in case this is your problem,… couldn’t really say for sure whats troubleing you)

There was a brilliant trick shown to me by one of the TAs of the Building Virtual Worlds class, back in the day (where’ve you been, zpavlov? We miss you) :wink:

Create a new empty NodePath to use as a reference. Attach it to the node you wish to be moving forward, and set its y-coordinate to 1. Do your rotations as you normally would. To move the object forward, simply set its position to the reference node’s position in the coordinate space of the object’s parent.

# assume myModel is the model you wish to move forward and you 
# have already rotated it the way you want to, etc.

navigationNP=NodePath('navigator')
navigationNP.reparentTo(myModel)
navigationNP.setY()

onMoveForward(myModel):
  myModel.setPos(navigationNP.getPos(myModel.getParent()))

This may not be the absolute fastest way to translate a model forward, but it’s conceptually fairly intuitive and you can change your motive direction by changing the position of the navigationNP.

Thanks for the tutorials.

I’m not sure about Python since i’m new to the language but i believe that if the method is static we cannot use instances and must use the class name only, like this: Vec.up() or LVector3f.up() which is the same.

“Remember, every thing in Python is an object. And no, you can use instances because they are an instance or specific version of the general class description.”

You’re right. We can use both the class and the instance symbol.

"When I tested this code, my model was set to the origin and it printed out [0,0,1] which would be the positive z axis which is indeed up. "

I tried it with objects with different rotations and it seams that the result doesn’t depend on the instance. It looks like it just uses the instance to obtain the class then call the class method which always gives the same result no mater what instance we use.

It would be useful if these methods were defined in a node path. That is:

ship_np = getShip()
ship_np.up() #gives the local up vector
ship_np.forward() #gives the local forward vector
ship_np.right() #gives the local right vector

Unless i haven’t read the manual properly i didn’t find an easy way to do this.

This way to move a ship forward we would just write:

offset = ship_np.forward().normalize()
offset *= 0.1
ship_np.setPos(ship_np.getPos()+offset)

This would simplify things a lot.

That’s a problem I had to deal with at the beginning of my game.
I am still writing the space shooter. The code can be found in the Showcase.
It’ll show the code for the desired movement.

I didn’t use the upvector thing, though. I’ve just reparented a node in front of my model and calculated a vector.
You’ll only need this one vector for forward/backward movement. For the correct rotation relative to your curent rotation you just write:

model.setHpr(model, HPR)

There is a bit of confusion in some of the above advice. getHpr() does not return a 3-D vector. It returns a set of three angles, named H, P, R, which are expressed in degrees.

A HPR value has nothing to do with a 3-D vector, which is an X, Y, Z triple that expresses a relative direction in space.

The up(), forward(), down() methods of Vec3 are indeed class methods. Although you can call them using an instance of a Vec3, the instance is ignored. These methods do not convert any data, they are just constant methods: up() always returns (0, 0, 1), for instance, and forward always returns (0, 1, 0).

There are several ways to return the rotated vectors from an object. They all involve relative scene graph operations. What you are really asking is “what is the forward vector of node A, expressed in the coordinate space of node B.” Methods such as NodePath.getRelativeVector() can compute this answer for you.

David

I noticed that (from another post) we can get the relative forward vector by extracting this info from the matrix, like this:

np.getNetTransform().getRow3(1)

This gives exactly the same result as using:

render.getRelativeVector(np,Vec3(0,1,0))

This is not a coincidence right?

Also getPos() returns the absolute position and getHpr() the local rotation.

Finding the position relative to another node is easy with getRelativeVector but what if we need the rotation relative to another node or the absolute rotation. How can this result be calculated?

You can use getRow3(1) to extract the forward vector, but in my mind this is much less clear than getRelativeVector(), since you have to know how matrices work to understand how it works. Also, it isn’t as general, since you can only do this trick to get the rotation vector of a node relative to its parent, or to global space.

You use getRelativePoint() to extract the relative position to any other node (or to global space, which is render). You use getRelativeVector() to extract the relative direction to another node (or to render).

For instance, the call:

render.getRelativeVector(np,Vec3(0,1,0))

returns the forward vector of np, expressed in global coordinates. Is that not what you’re asking for?

Or by “rotation” do you mean a rotation expressed as a HPR trio, or as a quaternion? These are also trivial to compute in the coordinate space of any node, including render, e.g.: np.getHpr(render) .

David

"Is that not what you’re asking for? "

Certainly.

“Or by “rotation” do you mean a rotation expressed as a HPR trio, or as a quaternion?”

The Hpr trio. Is there any easy and intuitive way to understand quaternions?

“These are also trivial to compute in the coordinate space of any node, including render, e.g.: np.getHpr(render).”

I didn’t know we could pass an argument to getHpr. The documentation only refers to a function with zero arguments. But if that is the case then my problem is solved.

getHpr
LVecBase3f NodePath::get_hpr(void) const;

Description: Retrieves the rotation component of the transform.
Description: Returns the relative orientation of the bottom node as seen from the other node.

Some claim so. I haven’t found one that sits well in my head yet, though. Quaternions are mostly good for certain nice properties involving relative rotations; not so good for humans to visualize them. That’s why we also have HPR.

Hmm, so it does. It looks like the generated API specs are pulling out only one of the two prototypes. The two different Description: lines refer to the two different variations on the method, though.

Also, don’t overlook the manual, which makes at least a passing reference to this ability, on this page. It is true that the whole chapter on the scene graph in the manual could use a lot more detail.

David

Thanks.