The question nobody can answer (3D math)

Started by
22 comments, last by FeelEvil 22 years, 2 months ago
I have a 3D world. In this 3D world I have a camera that I want to move around. A rotation can only occur around an identity matrix. OK, so there is no problem to rotate the camera exactly how I want (around the x, y, and z axis). But! How do I move the camera forward/backward (ALWAYS to/from the direction of the look-at point no matter the rotation of the camera)? And don''t give me a picture of yet another matrix with some ones and zeros, because I need the actual math. I''m sure it''s really simple - just some sin and cos stuff on the camera''s x, y, and z values. But I can''t figure it out anyway. Please share the formula if you have it. The SDK says that the general formula to move and rotate the camera looks like this:
V = T * Rx * Ry *Rz; 
V is the new matrix created. T is the translation matrix (and I don''t know how to calculate it, and I can''t find any info about it). Rx, Ry, Rz are the rotation matrices.
Advertisement
I *think* this is the answer you're looking for...

Create one matrix for the body orientation using the D3DXMatrixRotation... functions. Call this BodyRot.

Create another matrix for the eye orientation using the D3DX functions. Call this EyeRot.

Create another matrix with D3DXMatrixTranslation and use the parameters (0.0f, 0.0f, WalkingDistance). Call it WalkDistance.

Now, concatenate the matrices as follows (order is very important):

FinalMatrix = EyeRot * WalkDistance * BodyRot.

It makes sense if you read it backwards:

Rotate the body to a new direction. Walk X units along the new Z direction (changed by the rotation). Then, turn your head by a certain rotation. If you draw it out on paper (with transformed axes) it makes sense.

This is the disadvantage of using LookAt. LookAt is easier, and you can retrieve these components from the matrix, but this is a much better approach, especially if you ever get into the "face one way, but fire the gun in the walking direction" kind of thing.

Is that what you were looking for?

Edited by - CrazedGenius on January 15, 2002 3:00:51 PM
Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces", A third book on advanced lighting and materials
Rather then rotate your camera around the world basis, maintain a local basis around your camera. Then when the camera rotates you adjust the camera''s local basis accordingly. This also solves the gimbal lock problem. Gary Simmons had an article on this topic so your best bet is to head over to www.Mr-Gamemaker.com and post a message asking for the old tutorials. Also search for "Vector Camera".

ECKILLER
ECKILLER
quote:Rather then rotate your camera around the world basis, maintain a local basis around your camera.


Isn''t that what I''m doing?

CrazedGenius,

I think the same problem remains.

Rotation: First you need to rotate the camera. One matrix is used for each axis (x, y, z). z is not used though unless you want to roll the camera. I only use x and y rotations.

Translation: Next you need to calculate the translation matrix depending on the angles of the camera . If I just add to the z element, as people are telling me to do everywhere, the camera will only move in the z direction. And I need to be able to walk in all directions (I want to walk in the direction I am looking). As it is now I just move on the z axis no matter the rotation of the camera.

Next you need to do:

FinalMatrix = Translation * RotX * RotY * RotZ;

That''s basically what the SDK says. Except that I don''t have a valid translation matrix! I don''t understand how to make one. That''s the problem.

quote:Create one matrix for the body orientation using the D3DXMatrixRotation... functions. Call this BodyRot.

Create another matrix for the eye orientation using the D3DX functions. Call this EyeRot.

FinalMatrix = EyeRot * WalkDistance * BodyRot.


Maybe you method will work (I don''t know because I don''t really understand what''s happening in those matrices)... In that case, how do I set up BodyRot and EyeRot? I guess I could just rotate BodyRot with D3DXMatrixRotationYawPitchRoll, what about EyeRot? What should the difference between those two matrices be?
OK admittidely i''m a 3D novice however couldn''t you do something like involving some kind of simultaneous moves vector.

something like, i''m currently rotating and also translating. then before each draw you do all the relative "simultaneous" transforms on the vectors.

so in your example, for instance you are translating and rotating at the "same time". so you first do a transform for rotation and then transform the resultant for a translate.

i suppose that works out to be the same as the EyeRot * WalkDistance * BodyRot thing but is a way to actually implement the idea?

-me
This could be totally completely wrong, but I''ve always thought that an easy way to solve this problem is to do camera.position += camera.lookat, where position is a vector representing the camera''s position, and lookat being a vector representing where the camera is looking.
quote:Original post by FeelEvil
Translation: Next you need to calculate the translation matrix depending on the angles of the camera . If I just add to the z element, as people are telling me to do everywhere, the camera will only move in the z direction.


I think this is the point of confusion...

Get out a sheet of paper. Draw an X and Z axis (Y points out of the page). Draw a vector travelling straight down the Z axis. So far, so good.

Now, apply a rotation around the Y axis, say 45 degrees. Redraw the X and Z axes at this new 45 degree orientation. Redraw the vector straight down the Z axis. This vector should be 45 degrees from the old one, yet the translation (straight down Z) is the same in both cases. This is the direction of the body motion and of the eye vector.

Now, apply some final rotation, but no translation. This will affect the eye vector without "moving the body"

To put it another way, start over and draw the X and Z axis on the paper. Rotate 90 degrees. Now, after that rotation, a +Z translation will actually translate the object in either the -X or +X "universal" direction (depending on which direction you rotated.

As far as code, it's the same as I said before. A quick proof of this involves writing your paper experiment as code. Try different matrix multiplication orders, BUT USE THE EXACT SAME MATRICES (caps for emphasis, not yelling)

"Translate and then rotate" (R * T) = move to a new position and spin.

"Rotate and then translate" (T * R) = an orbitting effect because the object is rotated to a new angle and then moved along that angle.

Two different effects with the same matrices.

Please keep asking if it doesn't make sense.

Edited by - CrazedGenius on January 15, 2002 5:33:19 PM
Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces", A third book on advanced lighting and materials
This is taken directly from some of my old working DOS code. So, it's NOT neat but it will show you the math. Here ya go:

tempX = pntX;
pntX = (pntZ * sinDir) +
(pntX * cosDir);
pntZ = (pntZ * cosDir) -
(tempX * sinDir);

ltrans[_a].z = (pntY * sinPitch) +
(pntZ * cosPitch);
pntY = (pntY * cosPitch) -
(pntZ * sinPitch);

if (roll) {
ltrans[_a].x = (pntX * cosRoll) -
(pntY * sinRoll);
ltrans[_a].y = (pntX * sinRoll) +
(pntY * cosRoll);
}
else {
ltrans[_a].x = pntX;
ltrans[_a].y = pntY;
}

Man, that is hideous... but I'll try to explain. This is really just doing a 3D transformation based on Direction, Pitch and Roll... yes, I KNOW it's unorthadox... this was from my 1st attempt at a 3D engine years ago. ltrans is an array of points containing x, y and z coordinates and PntX, PntY and PntZ contain the temporary coordinates to be translated. The values, such as sinDir and cosDir, are double precision values containing the cosine and sin values for Dir, Pitch and Roll.

Now I know this isn't *exactly* what you are looking for but you can use this math to find the point that is ahead of the camera and move the camera to that point. In this case you could exclude the calculations for "roll" You should be able to transform the point (0, 0, x) where x is the distance you want the camera to move, and add that to your camera coordinates.

- Jay


Many of the truths we cling to depend greatly on our own point of view

Get Tranced!


Edited by - coderx75 on January 15, 2002 5:35:50 PM
Quit screwin' around! - Brock Samson
Hey, I''ve got an answer for you. I just solved this problem a few weeks ago using the knowledge from my grade 12 math class.


void CAMERA::MoveX(float distancex)
{
//if you''re looking at this trying to figure it out, you''re screwed
//do the movement for the x position
float A,B;//angles
float zmovement;
float xmovement;

A = ((int)(totalrotationy)/90)*90 - ((((int)(totalrotationy)/90)*90) - totalrotationy) - 270;
B = totalrotationy+180;


zmovement = sin(A * D3DX_PI / 180);
zmovement *= (distancex / sin(90));
xmovement = sin(B * D3DX_PI / 180) * (distancex / sin(90));

xpos+=xmovement;
zpos+=zmovement;

xtar+=xmovement;
ztar+=zmovement;
}


void CAMERA::MoveZ(float distance)
{
float xdistance;//the distance along the x axis from the target to the position
xdistance = xtar - xpos;
float zdistance;//the distance along the z axis from the target to the position
zdistance = ztar - zpos;

float zaxisdis = sqrt( xdistance * xdistance + zdistance * zdistance );
float distozratio = zdistance / zaxisdis ;
float distoxratio = xdistance / zaxisdis ;

if(zdistance == 0)
distozratio=0;

if(xdistance == 0)
distoxratio =0;

zpos += distozratio * distance;
ztar += distozratio * distance;
xpos += distoxratio * distance;
xtar += distoxratio * distance;


}




I don''t really feel like explaining this code. I actually commented in that this is unexplainable

rest assured this code works (for me) quite perfectly
Oh yeah, I don''t have rotationx or rotation y matrices, I used a target and a camera position, and did all of my calculations around these. Then I used the D3DXMatrixLookAtLH after updating the position and rotation and everything

This topic is closed to new replies.

Advertisement