Jump to content
  • Advertisement
Sign in to follow this  
Providence

Quickly Extracting Angles from Vectors

This topic is 4869 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm currently using D3DXMatrixLookAtLH() to create my view transform because the code, even though I don't understand it, looks so much simpler and faster than the complicated nonsense I was using to construct my view matrix^[1]. Unfortunately, I can't figure out how to determine the direction the camera is pointing in world space so that I can then have my player object (3rd person view) also face that direction (or left/right/backward/etc relative to the camera direction) when walking. [1] Here's what I called "complicated nonsense". This was quickly reproduced, as it has been long since deleted, so it may not be functional. float xo,yo,zo,rx,ry,rz; /* update these when the camera moves */ D3DXMATRIX view,trans,rotx,roty,rotz,temp1,temp2; D3DXMatrixTranslation(&trans,xo,yo,zo); D3DXMatrixRotationX(&rotx,rx); D3DXMatrixRotationY(&roty,ry); D3DXMatrixRotationZ(&rotz,rz); D3DXMatrixMultiply(&temp1,&trans,&rotx); D3DXMatrixMultiply(&temp2,&temp1,&roty); D3DXMatrixMultiply(&view,&temp2,rotz); D3Ddevice->SetTransform(D3DTS_VIEW,&view);

Share this post


Link to post
Share on other sites
Advertisement
The view matrix transforms objects from world space to view space. You have the camera's forward (or look_at) vector in viewspace as <0,0,1>. You want to transform it from view space to world space. That means you want the inverse of the world-to-view transformation, i.e. the inverse of the view matrix.

So, invert your view matrix, transform <0,0,1> by it, and you have your camera's look_at vector in world-space. Of course, transforming a <0,0,1> vector by a matrix will produce a vector whose components are matrix._31, matrix._32 and matrix._33, so you can just extract it directly.

Alternatively, if you have the camera's orientation in angles, you can also construct the vector with some sines and cosines. Sketch it on a piece of paper and it should be obvious. If not, and you'd like to go down this path, just say so.

EDIT: Wait a minute. You're using D3DXMatrixLookAtLH, so you already know your look_at vector in world space. What's the problem then?

[Edited by - Coder on May 23, 2005 10:27:17 AM]

Share this post


Link to post
Share on other sites
My problem is that I'm trying to use D3DXMatrixRotationY() to face the character in the right direction. But that function takes an angle and not a vector. So I can get the direction from the eye point and look at point in vector form, but then I'd need to convert it into an angle in order to use it, which I seem to be failing at (my character faces the wrong way for half the angles). I was hoping that I could somehow skip this step (converting vector direction to angle) and just use the vector directions.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The direction where the camera is pointing is "vLookAt - vEye", so you need define/update these vectors to get the right direction.

Suppose that the camera's target (vLookAt vector) is always the character's position. So, the idea is to move the character (and the vLookAt, consequently) and to make the camera's eye (vEye vector) to follow vLookAt. For that, you could define a "directional vector" and to transform it, like this:

D3DXVECTOR3 vEyeLookAt ( ... , ... , ... ); // define a initial directional vector

D3DXMatrixRotationY( &matRotY, ang ); // get a rotation matrix based on the input angle

D3DXVec3TransformCoord( &vEyeLookAt, &vEyeLookAt, matRotY); // rotate vEyeLookAt

D3DXVECTOR3 vLookAt = vCharacter; // update the position of the character

D3DXVECTOR3 vEye = vLookAt - vEyeLookAt; // calculate the position of the camera's eye

Now, just pass vEye and vLookAt vectors to D3DXMatrixLookAtLH() function.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Also, to extract the angle between two vectors you must normalize these vectors and to calculate the dot product of them:

D3DXVec3Normalize( &V1, &V1 );
D3DXVec3Normalize( &V2, &V2 );
angle = D3DXVec3Dot( &V1, &V2 );

Share this post


Link to post
Share on other sites
You can just pull the xz direction of your camera from the view matrix:
Vector cam_forward( view._13, 0.0f, view._33 );
cam_forward.Normalize();

If your camera is looking mostly up or down, you may need to replace z with y (change view._33 to view._23).

The vector's Y angle can be computed by doing something like this:

FLOAT y_angle;
if( cam_forward.z >= 1.0f )
{
y_angle = 0.0f; // already facing forward
}
else if( cam_forward.z <= -1.0f )
{
y_angle = PI; // full 180
}
else
{
y_angle = acosf( cam_forward.z );
if( cam_forward.x < 0.0f ) // need to turn left
y_angle = -y_angle;
}



Let me know if you have any problems.

Share this post


Link to post
Share on other sites
Quote:
Original post by Providence
My problem is that I'm trying to use D3DXMatrixRotationY() to face the character in the right direction. But that function takes an angle and not a vector. So I can get the direction from the eye point and look at point in vector form, but then I'd need to convert it into an angle in order to use it, which I seem to be failing at (my character faces the wrong way for half the angles). I was hoping that I could somehow skip this step (converting vector direction to angle) and just use the vector directions.

With your look_at vector, character's "up" vector (typically <0,1,0>):
right = up cross look_at
up = look_at cross right

Stick these into a matrix as follows:
right.x   right.y   right.z    0
up.x up.y up.z 0
look_at.x look_at.y look_at.z 0
pos.x pos.y pos.z 1

Use this as the character's world matrix.

EDIT: This will orient your character completely, like a plane does for example. If your character is a human or something (you only want it to turn left/right), before you do any calculations with look_at, zero its y component and normalize it.

[Edited by - Coder on May 24, 2005 9:43:26 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Coder
With your look_at vector, character's "up" vector (typically <0,1,0>):
right = up cross look_at
up = look_at cross right

Stick these into a matrix as follows:
right.x   right.y   right.z    0
up.x up.y up.z 0
look_at.x look_at.y look_at.z 0
pos.x pos.y pos.z 1

Use this as the character's world matrix.

EDIT: This will orient your character completely, like a plane does for example. If your character is a human or something (you only want it to turn left/right), before you do any calculations with look_at, zero its y component and normalize it.


Thank you! That is just the thing I was looking for.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!