Changing Coordinate Orientation

Started by
5 comments, last by eeinor 13 years, 3 months ago
What changes do I have to make so the Z-axis is the up vector and the Y-axis is the forward vector? Do I have to change how my Matrix class looks like? Do I have to change the projection matrix and/or view matrix? How do I update the forward and up vector of the camera according to the rotation of the camera?
Advertisement
Quote:Original post by eeinor
What changes do I have to make so the Z-axis is the up vector and the Y-axis is the forward vector? Do I have to change how my Matrix class looks like? Do I have to change the projection matrix and/or view matrix? How do I update the forward and up vector of the camera according to the rotation of the camera?
A matrix class should be unaffected by which axis is considered to be 'up'. If there are functions that identify axes by name - e.g. GetForward() and so on - those would have to be changed, but I'd recommend not including such functions in a matrix class to begin with.

Projection matrices will be unaffected. The view matrix will likely be affected in the sense that it needs to transform geometry from the local space of the object with which it's associated to view space, and therefore needs to reflect what is considered to be 'up' and 'forward' for the object in question.

As for updating the forward and up vector of the camera, I'd recommend not doing it that way. (As for how you *should* do it, that depends on what type of camera motion you're looking for.)

Post back if you have any other questions about how to do this.
Thanks for your help!

If I multiply the view matrix with [ 1 0 0 0, 0 0 1 0, 0 1 0 0, 0 0 0 1 ], then I get the correct result for the view. But I want to avoid the extra matrix multiplication if possible.

This is how I update my camera when Y is up. This is a 3rd person camera view. How should I do it instead? Forward would in this case be ( 0, 0, 1 ).
void Camera::Forward( float force ){	m_velocity += m_forward * force;}void Camera::Rotate( float x, float y, float z ){	m_rotation.m_x += x;	m_rotation.m_y += y;	m_rotation.m_z += z;	Matrix rotationX, rotationY, rotationZ;	rotationX.RotateX( -m_rotation.m_x );	rotationY.RotateY( -m_rotation.m_y );	rotationZ.RotateZ( -m_rotation.m_z );	m_matrixRotation = rotationZ * rotationY * rotationX;}void Camera::Update( float dt ){	float friction = 1.0f - m_friction * dt;	m_velocity *= friction;	m_position += m_velocity * dt;	m_matrixPosition.Translate( -m_position.m_x, -m_position.m_y, -m_position.m_z );	m_view = m_matrixPosition * m_matrixRotation;	m_forward.m_x = (float) sin( m_rotation.m_y );	m_forward.m_y = (float)-tan( m_rotation.m_x );	m_forward.m_z = (float) cos( m_rotation.m_y );	m_forward.Normalize();	m_right.m_x = (float) cos( m_rotation.m_y );	m_right.m_y = (float) tan( m_rotation.m_z );	m_right.m_z = (float)-sin( m_rotation.m_y );	m_right.Normalize();}[/Source]
Quote:Original post by eeinor
If I multiply the view matrix with [ 1 0 0 0, 0 0 1 0, 0 1 0 0, 0 0 0 1 ], then I get the correct result for the view. But I want to avoid the extra matrix multiplication if possible.

Multiply the concrete swap matrix with a general view matrix on paper and observe what happens; compare the resulting matrix with the original view matrix:
for S * V rows 2 and 3 are swapped, and
for V * S columns 2 and 3 are swapped.
However, this has to be performed once per frame, so it is barely a bottleneck.

As jyk has already mentioned, computing the forward and sideway vector that way isn't a Good Thing. You're using the tangent function which will result in +/-infinity for +/-90°. However, make yourself clear what the roles of the column/row vectors of a rotation matrix play w.r.t. the orientation., and you'll be probably able to drop using trigonometric for that case totally.
I'm not entirely sure what you mean. Do you mean that I should create the translation and rotation directly to the view matrix instead of having separate matrices for those?
Quote:Original post by eeinor
I'm not entirely sure what you mean. Do you mean that I should create the translation and rotation directly to the view matrix instead of having separate matrices for those?
I assume that this question belongs to the 2nd half of my previous post...

After computing a (3D, homogeneous) matrix from rotations and translations, you've something like
[ x_x y_x z_x p_x ][ x_y y_y z_y p_y ][ x_z y_z z_z p_z ][  0   0   0   1  ]
what can be seen as 4 column vectors (I use column vectors here; you may need to use row vectors instead), written as
[ x y z p ]
Such a matrix defines the transformation from the local space to the parental space. Assume that you have used the camera as object and that the camera is placed in the world, then the above matrix is the camera-to-global transformation matrix. (BTW, its inverse is often called the view matrix.)

Now assume that, for example, the forward vector in local space is along the principal z axis, [ 0 0 1 0 ]t. When you want to know this direction in global space, you've to apply the local-to-global transformation matrix:
[ x y z p ] * [ 0 0 1 0 ]t == z
You see that you just have picked the 3rd column vector from the matrix.

Similarly, if you use the principal x axis as right vector, you'll see
[ x y z p ] * [ 1 0 0 0 ]t == x

Hence, there is no need to explicitly compute the principal direction vectors if the matrix is known, because the directions can be read directly from the matrix.
Thanks a lot both of you. I understand the concept now. I've fixed the camera and it works now with correct orientation. I removed the trigonometric calculations in the update.

This topic is closed to new replies.

Advertisement