Archived

This topic is now archived and is closed to further replies.

UnknownPlayer

The view matrix and "Up"

Recommended Posts

I''ve got a simple third person camera working using D3DXMatrixLookAtLH and some quaternion rotations to calculate the movements of the camera position, and it works very well. However, when I have it attached to an object rotating forward or backwards on the x-axis (pitching) at some point the camera causes all objects to flip upside down. Now I''m guessing this is to do with the fact I don''t presently alter what the Up vector is. The problem is, I''m not sure how I should alter it - ideally it would be rotated through the same rotations so that Up is always relative to the player''s object (its in space so this would be convenient), but when I apply the camera quaternion rotation to the Up vector, all I get is objects flipping out all over the place very quickly. So, can anyone give me some advice here? Ideally I''d like to know more about what exactly the Up vector does, but also any hints on my specific problem are appreciated. ##UnknownPlayer##

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Hi. The up vector is 90 degrees up from the foward vector, and there is also a right vector which is 90 degrees right of the foward vector. You have to cross multiply the vectors to recalculate the up and right, but seeing as they are based on matrix maths, you just need to multiply 2 of them to get the third one.
vb code:

''get other variables like right vector
''right = foward * up
''foward = right * up
''up = foward * right

ryan@pcsoftware.co.nz

Share this post


Link to post
Share on other sites
i assume it works just like glulookat (never used it in dx, a matrix camera felt more comfortable).

what you specify as up doesnt really matter. if your camera cant roll you can use either 0,1,0 or 0,-1,0.. might screw up if you look exactly 90deg up/down though. up is meant to be the cameras up. imagine your head and look down at the floor, now your up-vector would be 0,0,1 . but as i said, if your cam wont roll, use 0,1,0 for orientiations between 270 and 90 deg (with 0 being straight ahead) and 0,-1,0 for 90 to 270

Share this post


Link to post
Share on other sites
Well, I can basically guarantee my camera will roll - (another thing I was going to ask) so in this case what should my Up vector be? I imagine I need to make it something that points off in the direction of the roll.

##UnknownPlayer##

Share this post


Link to post
Share on other sites
in that case: save yourself the trouble and headache and use a matrix, just in case you later decide that your cam needs more than just following an object. store 2 angles and a distance to the object, then set the cam matrix to the matrix for the object your following, rotate around y and x, translate backwards and that should be it.

Share this post


Link to post
Share on other sites
Hmm...ok I'll give that a shot - hope it works because then I can get on to some content (this was one of the last things I wanted to do engine-wise).

But I do have a question - isn't 'translate backwards' somewhat more difficult to do then say since its gotta be relative to the objects forward?

##UnknownPlayer##

[edited by - UnknownPlayer on January 31, 2003 9:09:31 PM]

Share this post


Link to post
Share on other sites
why should it? instead of translating it -x units along (0,0,1) you translate it -x units along its local z-axis (which is the first three elements of the third line of its matrix).

Share this post


Link to post
Share on other sites
So my code would essentially be a thing of ratios i.e. -x gets broken up into x, y, z components for the local z-axis? I''ll gonna give it a shot (plenty about matrix maths I don''t already know).

Share this post


Link to post
Share on other sites
I think I''m doing something similar to what you are. What I have is two static vectors, vDir and vUp, that I transform every frame by the change in Theta (roll) and phi (pitch).


D3DXMatrixRotationAxis (&mTrans, &vDir, dTheta);
D3DXVec3Transform (&vRes, &vUp, &mTrans);
vUp.x = vRes.x; vUp.y = vRes.y; vUp.z = vRes.z;
D3DXVec3Cross (&vRight, &vDir, &vUp);
// vRight = -vRight;
D3DXMatrixRotationAxis (&mTrans, &vRight, dPhi);
D3DXVec3Transform (&vRes, &vDir, &mTrans);
vDir.x = vRes.x; vDir.y = vRes.y; vDir.z = vRes.z;
D3DXVec3Transform (&vRes, &vUp, &mTrans);
vUp.x = vRes.x; vUp.y = vRes.y; vUp.z = vRes.z;
D3DXVec3Cross (&vRight, &vDir, &vUp);

// Create View Matrix
vAt = vPos - (vDir * 20.0f);
D3DXMatrixLookAtLH (&mView, &vAt, &vPos, &vUp);


-Zims

Share this post


Link to post
Share on other sites
What your doing seems more involved then my current system which exploits the quaternion functions of D3DX, but only can deal currently with the rotations on x and y axes.


  
LookAtPoint = Subject->GetPosition();

// Deal with rotation of the camera - define a quaternion and give it the appropriate rotations

D3DXQUATERNION CamRotation;
D3DXQuaternionRotationYawPitchRoll(&CamRotation, radians(Subject->GetRotationalPosition().y), radians(Subject->GetRotationalPosition().x), radians(Subject->GetRotationalPosition().z));
// Define a matrix from the quaternion to transform the points

D3DXMATRIX CameraPosTransform;
D3DXMatrixAffineTransformation(&CameraPosTransform, 1.0f, &Subject->GetPosition(), &CamRotation, null);
D3DXVec3TransformCoord(&CameraPosition, &Distance, &CameraPosTransform);

// Build matrix etc



Does your system properly deal with x, y and z rotations and if so can I borrow it then, because it would be exactly what I need.

##UnknownPlayer##

Share this post


Link to post
Share on other sites
In my application I do not use Yaw, but I think it could easily be added. Qurtenions would probably do this as well, but i''m not quite up to speed on them, so i''m just rotating vectors.

I start with a vDir pointing directly forward (in my case +x), and vUp pointing in +z. I then rotate vUp about vDir by the change in theta. This accomplishes roll. If you wanted yaw then you would rotate the vDir along the vUp vector by the change in yaw. Lastly you cross up and dir to get vRight, then rotate vDir and vUp about vRight for pitch. This should always work.

I''m not sure if yaw comes before or after roll, as they will produce different results. It seems to me that you roll first cause that adjusts your horizon, then yaw and pitch.

The code I posted is what I use to create the view matrix to follow a ship in space.

Hope this helps.
-Zims

Share this post


Link to post
Share on other sites
Hmm - your way sounds like what I originally was trying to do, only I couldn''t quite wrap my head around it (actually I didn''t really have much knowledge of view matrices), but thanks for the code - some form of it might make it into my final implementation.

##UnknownPlayer##

Share this post


Link to post
Share on other sites
Don''t feel bad. It took me a couple days of scratching my head and staring at my hand (twisted into the usual Right Hand Rule pose) to get it right. I originally started with Euler angles, but soon learned that those are horrible... Then I started using vectors and it all started making sense.

Now I''m scratching my head on a different topic, but at least I''m not staring at my hand. (It was creepin out my flat mates)

-Zims

Share this post


Link to post
Share on other sites
Normally the up vector is generated by the cross product from the UP and RIGHT. BUT this is not always good. Start by having your look vector and generate the up and right vector from that.

D3DXVec3Normalize(&Look,&Look);

double theta = acos(Look.y);
float phi = 0.0;

double LookLength=sin(theta);
if (LookLength != 0.0)
{
phi = (float)acos(-Look.z/LookLength);

if (Look.x/LookLength < 0)
phi = -phi;
}

double UpLength=theta-PI/2;

now create your up vector

D3DXVECTOR3 Up;
// Find camera up vector:
Up.x = (float)sin(UpLength)*(float)sin(phi);
Up.y = (float)cos(UpLength);
Up.z = (float)-sin(UpLength)*(float)cos(phi);

now find the Right vector from the cross product of the other 2.

D3DXVECTOR3 Right;

D3DXVec3Cross(&Right,&Up,&Look);


then transform each coordinate. No more need to cross anything!

D3DXMATRIX Pitch,Yaw;

D3DXMatrixRotationAxis(&Pitch,&Right,RotationY);
D3DXMatrixRotationAxis(&Yaw,&Up,RotationX);

D3DXVec3TransformCoord(&Look,&Look,&Yaw);
D3DXVec3TransformCoord(&Right,&Right,&Yaw);

D3DXVec3TransformCoord(&Up,&Up,&Pitch);
D3DXVec3TransformCoord(&Look,&Look,&Pitch);

Finally create the view matrix.

D3DXMATRIX view;


view._11 = Right.x; view._12 = Up.x; view._13 = Look.x;view._14=0;
view._21 = Right.y; view._22 = Up.y; view._23 = Look.y;view._24=0;
view._31 = Right.z; view._32 = Up.z; view._33 = Look.z;view._34=0;
view._41 = - D3DXVec3Dot(&Position,&Right);
view._42 = - D3DXVec3Dot(&Position,&Up);
view._43 = - D3DXVec3Dot(&Position,&Look);
view._44=1;


Device->SetTransform(D3DTS_VIEW,&view);

Techlead
www.myran.com/enilno

Share this post


Link to post
Share on other sites