Rotations & coord space problem

Started by
1 comment, last by Buckeye 10 years, 2 months ago

Suppose I have a first person camera and a model. The camera is placed where the head is, as a placeholder.

Suppose I want to rotate the camera about the model's z axis(imagine a first person game where you tilt your head slightly to the right to see if there are enemies after the corner).

BUT the camera's position AND coordonate axes must be rotated.

So,I just have to create a rotation matrix that rotates around the model's z axis:

D3DXMatrixRotationAxis( &mtxRotate, &m_model->zAxis, D3DXToRadian( degrees to rotate ) );

Now,what I don't understand is: the answer says that in order for everything to work properly, I have to subtract the model's position from the camera position,so they end up at the same origin,rotate that new position from which i subtracted,and then add the model position back to the camera position,thus,the rotation will work correctly.

BUT I don't understand,didn't I create a matrix that rotates around a certain vector? Why isn't that enough?

And if I have a model at: 1,2,4 and a camera at 1,6,4, the subtraction will only give me: 0,4,0 how is that the same origin?

Advertisement

The axis of rotation is build of all lined up points that do not change their position when the rotation is performed. You can see easily that [0,0,0] ever belongs to the axis, because regardless of what rotation matrix you apply to [0,0,0], the result will ever be [0,0,0]. In other words, every and each axis of rotation passes through [0,0,0].

Now, well, perhaps you don't want this. Perhaps you want an axis that passes through [1,2,3], but if you apply a rotation to [1,2,3] it will in general result in something differing from [1,2,3]. To solve this, you do the following:

1. translate by [1,2,3] * (-1)

2. rotate

3. translate by [1,2,3] * (+1)

Look at the desired point and observe what happens (I'm using row vectors here):

p1 := [1,2,3]

p2 := p1 * T(-1,-2,-3) = p1 + [-1,-2,-3] = [0,0,0] // application of first translation

p3 := p2 * R = [0,0,0] * R = [0,0,0] // application of rotation gives always [0,0,0] for input [0,0,0]

p4 := p3 * T(1,2,3) = [0,0,0] + [1,2,3] = [1,2,3] // application of second translation

Notice that due to the surrounding translations the desired origin of rotation is temporarily shifted to [0,0,0] so that is guaranteed fixed during rotation.

You may observe that if you don't apply any translation (I mean as part of the model or camera transform here), then the local origin is still at the world's [0,0,0]. That is the reason why, when computing a model's world transform matrix, the rotation is done before the translation. (Similarly, the scaling is done before the rotation, before scaling does neither change point [0,0,0] nor the direction of any of the principal axes, which is important for the rotation afterwards.)

Now, if your camera's transform is already set to a copy of the model's head transform, then in general both a translation and a rotation are already applied. If you want to rotate the camera around a local axis of something, you need to temporarily not only undo the translation but also the rotation. If the copied world transform is named M, you need to apply its inverse

M-1

then do the rotation, so in summary:

R * M-1

then redo the former undo, so in summary:

M * R * M-1

With a given transform of the camera C you have then the new world transform of the camera as:

C' := M * R * M-1 * C

In your case C is the copy of the world transform of the head. M is the world transform of the head, too, because you want to apply the rotation R in the head's local space. That means that C == M and hence due to

C' := M * R * M-1 * C = M * R * M-1 * M = M * R

you get M-1 * M canceling out on the right side, leaving the equation of a simple parenting (a.k.a. forward kinematic). Et voila: All you need is to rotate the camera locally and handle it as child of the model's head.

To perhaps answer your question more simply, the rotation matrix you construct will rotate the camera about the WORLD Z-axis (as you have used it), not the camera Z-axis. The D3DX function to create a rotation about an axis interprets the camera z-axis ONLY as a set of numbers. As mentioned above, you probably don't want to rotate the position of the camera, just the axes. That assumes you want it to appear as if (for instance) the head is rotating at the end of the neck, without the head otherwise moving (translating.)

world_rotation.jpg

You need to move the camera axes to the WORLD origin, rotate the axes and move the camera axes back to the head position. NOTE: you'll only get the results you expect IF the camera Z axis is in the same direction as the WORLD Z axis. Otherwise, for instance, if the head is tilted forward, the camera Z-axis itself will also rotate.

IF you have the camera axes as just unit vectors (or as a single direction vector), then it would be easier to use D3DXVec3TransformNormal with the transpose of the inverse of the rotation matrix.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This topic is closed to new replies.

Advertisement