The question nobody can answer (3D math)

Started by
22 comments, last by FeelEvil 22 years, 3 months ago
quote:
"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.


You have those backwards. When you translate and then rotate, you achieve the effect of moving the object away from the origin, then rotating the object around the world''s origin, not that object''s origin. This is the orbiting effect. FinalMatrix = Scale * Trans * ZRot * YRot * XRot or FinalMatrix = Scale * Trans * XRot * YRot * ZRot (can''t remember off hand on the rotation order).

When you rotate and then translate, you are rotating an object around its origin and then moving the object to the exact position (determing by the translation coordinates) in the world. This is the method used to position meshes in the world. FinalMatrix = Scale * XRot * YRot * ZRot * Trans

Off the top of my head, I think the following will work for you:

// Calculate the rotation matrix of cameraD3DXMATRIX matRotation;D3DXMatrixRotationYawPitchRoll(&matRotation, CameraYRotation, CameraXRotation, CameraZRotation);// Set Speed to speed of camera movement forwardD3DXVECTOR3 vecDir(0.0f, 0.0f, Speed);// Calculate new camera coordinatesD3DXVECTOR3 vecCam;D3DXVec3TransformCoord(&vecCam, &vecDir, &matRotation);CameraXPos += vecCam.x;CameraYPos += vecCam.y;CameraZPos += vecCam.z; 



Jim Adams
Advertisement
quote:Original post by Jim Adams
You have those backwards.


With all respect, either we are arguing semantics, or you are incorrect.
EDIT: Read both of our posts again, our equations are the same.
"Translate and then Rotate" = R * T, you have S * R * R * R * T - basically the same thing, but arguing about it could prove confusing to the original poster.

Also, on the subject of confusing, I think many of the vector methods mentioned here might be over complicating the issues.

You can deal with everything as matrices. In the case of moving the camera, there's no reason to compute the direction vector if you are just going to use it as a transform. If you need the direction vector, it can be extracted from the view matrix without additional transformations (see the docs for D3DXMatrixLookAt). Some of the vector methods may be easier to see, but they are more work than is necessary.


Edited by - CrazedGenius on January 15, 2002 12:09:40 AM
Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces", A third book on advanced lighting and materials
quote:Original post by FeelEvil

The SDK says that the general formula to move and rotate the camera looks like this:

V = T * Rx * Ry *Rz;    


That SDK would be hopelessly flawed for 3D... (gimbal lock)

Here's a cut&paste from my avatar class - when you call MoveForward, it moves the avatar in the direction it's facing. It's not exactly efficent, but it gets the job done.
      			D3DXVECTOR3    m_v3Position;			float m_fMovementRate_mps;			float m_fStrafeRate_mps;			BOOL m_bMoved;						D3DXQUATERNION m_qFacing;			float m_fTurnRate_rps;			BOOL m_bTurned;			D3DXMATRIX m_matOrientation;	void CAvatar::MoveAhead(float fElapsed_sec)		{		float MoveRate = m_fMovementRate_mps * fElapsed_sec;			D3DXVECTOR3 v3Looking_At, v3Up, v3Left;				D3DI3D_QuaternionToOrthoV3(v3Left, v3Up, v3Looking_At, m_qFacing);		m_v3Position += MoveRate * v3Looking_At;		m_bMoved=TRUE;		}	void CAvatar::RotateRight(float fElapsed_sec)		{		D3DXQUATERNION dr;				float TurnRate = m_fTurnRate_rps * fElapsed_sec;				D3DMath_QuaternionFromAngles(dr.x, dr.y, dr.z, dr.w, 0.0f, -TurnRate, 0.0f);		m_qFacing = dr * m_qFacing;		m_bTurned = TRUE;		}    Depending on how you align the world matrix, you may need to twidle with the order or sign of x/y/z - it's all realtive, and I like to have my z axis go up&down not in&out like most 3D graphics.D3DXMatrixRotationQuaternion will take the quaterion and turn it into a rotation matrix, to use with the postion offset.  Set the camera to that orientation, and voila.Matrici multiplicate piles-up backwards, you want to multiply the translation by the rotation matrix - the effect of which is to rotating the object _then translate it.Orientation_Matrix = Translation_Matrix * Rotation_Matrix      	void QuaternionToOrthoV3(D3DXVECTOR3 &v3Left, D3DXVECTOR3 &v3Up, D3DXVECTOR3 &v3Dir, const D3DXQUATERNION& qRot)		{		__int64 Start = RDTSC();		// Credit goes to Succinct of GameDev		D3DXMATRIX matRot;		D3DXMatrixRotationQuaternion(&matRot, &qRot);		v3Left = D3DXVECTOR3(matRot(0,0), matRot(1,0), matRot(2,0));		v3Up   = D3DXVECTOR3(matRot(0,1), matRot(1,1), matRot(2,1));		v3Dir  = D3DXVECTOR3(matRot(0,2), matRot(1,2), matRot(2,2));					float x(qRot.x);		float y(qRot.y);		float z(qRot.z);		float w(qRot.w);				//*		v3Left.x = 1 - 2 * (y*y + z*z);		v3Left.y = 2 * (x*y + w*z);		v3Left.z = -2 * (x*z - w*y);				v3Up.x = 2 * (x*y - w*z);		v3Up.y = 1 - 2 * (x*x + z*z);		v3Up.z = 2 * (y*z + w*x);				v3Dir.x = -2 * (x*z + w*y);		v3Dir.y = 2 * (y*z - w*x);		v3Dir.z = 1 - 2 * (x*x + y*y);				__int64 End = RDTSC();		__int64 Ticks = End - Start;		}    

I always forget about that function...

Edited by - Magmai Kai Holmlor on January 15, 2002 12:24:15 AM
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
To be honest I have gotten nowhere at all.

I tried the code Jim Addams provided and it doesn't seem to work. Or maybe I did something wrong.

I would prefer to do this with only matrices, but I guess it's just to forget that.

This is what I have, and I can't get past this point:


  // Calculate the translation matrix of cameraD3DXMatrixTranslation ( &matMov, 0, 0, speed ); // Apply translation to camera (move along the z axis) matFinal *= matMov; // Calculate the rotation matrix of cameraD3DXMatrixRotationYawPitchRoll( &matRot, D3DXToRadian(x), D3DXToRadian(y), 0 ); // Apply rotation matFinal *= matRot; g_pD3DDev->SetTransform ( D3DTS_VIEW, &matFinal );   



And now when I walk, the camera can only move at along the z axis.
But everything looks alright.

So the only way I can think of that would solve this problem is to change the line

  D3DXMatrixTranslation ( matMov, 0, 0, speed );       


to something else. Of course, I do have the angles the camera is rotated...
So in some way I need to calculate the translation matrix depending on those angles.

Will that work?

Anyway, now I'll check out all the other things people have posted.


Edited by - FeelEvil on January 16, 2002 9:10:57 AM
Multiplication order matters. That''s the problem with using *= with matrices. Expand it to F = R * T

then, switch it to F = T * R. This should get you further.
Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces", A third book on advanced lighting and materials
Sorry - I''ve been out a couple days.

quote:
"Translate and then Rotate" = R * T, you have S * R * R * R * T - basically the same thing, but arguing about it could prove confusing to the original poster.


No argument here - just pointing out that your equations were correct, just the text was backwards. Translate and then rotate = T * R, not R * T. You''ll see I corrected the order of the equations to match.

Now, to avoid further confusion - the original poster was not asking for a viewing transformation, which is what most of the posts are discussing. The original question is asking for a directional vector in which to move the camera based on a rotational matrix (or at least that''s what I take of it):
quote:
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.


To FeelEvil -
The problem you are facing is that you are trying to use a 4x4 translation matrix as a vector matrix - won''t work. I still haven''t had a chance to check those calculations I gave you, but I believe it should work.
Basically, you are setting up a direction vector that moves the camera forward if there are no rotations. By appying a rotational matrix to the vector, you are changing the direction based on the rotational values.

Jim Adams
Sorry - hate to argumentative, but I think you are confusing the issue (in my mind at least)

"Translate and then rotate" is the same (to me) as saying "Walk across the room and spin". This is expressed with the equation "R * T" for mathematical reasons - it has nothing to do with the order of the words in the sentence. I''m being picky about this because the matrix multiplication order thing comes up so often. Maybe I''m off base here, but if people agree with my "walk across the room" example they will be misled by your explanations.

Perhaps it''s just semantics. The bottom line is that matrix multiplication is expressed from right to left. "Translate, rotate, and then scale" becomes "S * R * T".

I disagree more strongly with some of your other comments. It sounds like he has a (rotation) matrix to start with, and we know he needs a matrix at the very end of everything so that he can call SetTransform. You seem to be advocating taking the matrix, transforming a vector, and then presumably using that to rebuild a matrix. These seems slower, more complicated, and more convoluted than an all matrix approach.

FeelEvil - your original question seems to be "For any rotation matrix, how do I move along the look at vector". Add/replace the following code to the FrameMove function in the Pick Sample:

D3DXMATRIX matView;
D3DXMATRIX Trans;

D3DXMatrixTranslation(&Trans, 0.0f, 0.0f, 5.0f - fabs(sinf(m_fTime/3.0f)) * 4.0f);

D3DXMatrixLookAtLH( &matView, &vFromPt, &vLookatPt, &vUpVec );

matView = matView * Trans;

m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

The LookAt function creates a matrix that orbits the camera around the tiger, always facing inward. Imagine the camera is on a circular rail, facing the center. The added lines create a translation matrix that always moves back and forth in the Z ("look at" in this case) direction. Notice that I never change the vector - it''s always on the Z axis.

The LookAt function essentially changes the Z axis and the translation matrix moves back and forth along that *new* Z axis.

Please tell me if this is not what you were looking for, but this is easier/faster/less error prone than extracting vectors and rebuilding matrices, IMHO.
Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces", A third book on advanced lighting and materials
Complete answer.......


Normalise your lookat vector (so that it is a unit vector).

Then multiply that by the speed you wish to move.

Then add to camera pos.

That easy! (If I read your problem correctly anyway).
JonnyBoy has the same answer - my example built a directional vector you use to position the camera. Remember - the original question was not to build a matrix, but to move the camera in the position it was pointed.

Jim Adams
quote:Original post by Jim Adams
...but to move the camera in the position it was pointed.


and the best way to do that is build a matrix!

I'll stop now, normally I don't like to harp on people, but I'm really surprised this is even a point of contention. His original question did have to do with matrices:

quote:The SDK says that the general formula to move and rotate the camera looks like this:
...
T is the translation matrix (and I don't know how to calculate it, and I can't find any info about it).


and we all know that the end result *must* be a matrix (for SetTransform), yet you are doing everything you can to introduce more steps (my translation is the one line equivalent to 6 lines of your original answer). That's the part I find so strange.

But like I said, I'll stop...

FeelEvil (If you're even still reading this ) - Jim's answer is perhaps more illustrative of what's going on within the math. Once you get a feel for things, my method can be used with less fuss.

Edited by - CrazedGenius on January 19, 2002 12:05:28 PM
Author, "Real Time Rendering Tricks and Techniques in DirectX", "Focus on Curves and Surfaces", A third book on advanced lighting and materials

This topic is closed to new replies.

Advertisement