Sign in to follow this  
ctaclas

linear algebra/matrix question

Recommended Posts

i was playing around with direct3d, and i looked at a first person perspective tutorial on gametutorials.com. in my personal sample program, i've already got it so you can rotate the view left and right, i haven't made up and down, but i can do that pretty easily i think. anyways, in the gametutorials page they do it differently than me, and i don't understand how their one works because they use a matrix, and i completely forgot everything i learned in linear algebra :( they have a function that rotates the view vector around an axis, either the x, y, or z, by an angle theta. they give 3 matrixes to do the rotation: X-Axis [1 0 0 ] [0 cos(theta) sin(theta)] [0 -sin(theta) cos(theta)] Y-Axis [cos(theta) 0 -sin(theta)] [ 0 1 0 ] [sin(theta) 0 cos(theta)] Z-axis [ cos(theta) sin(theta) 0] [-sin(theta) cos(theta) 0] [ 0 0 1] my problem is i don't understand how the author came up with these matrices, and i don't understand how to use them to rotate the view vector. if anybody knows a lot about this sort of thing and wants to explain it, or if someone can point me to a tutorial that will explain it that would be cool. i thought there was a tutorial on gamedev that explains it but i can't seem to find it, so i don't know if it answers my question. heres the function i'm asking about if anybody wants to see it:
// Here is where most of the magic happens.  This function takes an
// arbitrary  axis and rotates the view vector (the forward axis) of the 
// camera around this axis by "angle" radians.  So how do we rotate around
// an arbitrary axis?  Well lets first look at a couple of matrices that will
// rotate us around the world X, Y, and Z axis respectively.  We use 't' as 
// an angle theta to rotate around the axis.

//////////////////////////////////////////////////////////////////////////
//		X-Axis						Y-Axis					Z-Axis			
// [1    0	    0   ]		 [cos(t) 0 -sin(t)]		 [ cos(t) sin(t)  0]
// [0  cos(t) sin(t)]		 [  0	 1    0	  ]		 [-sin(t) cos(t)  0]
// [0 -sin(t) cos(t)]		 [sin(t) 0  cos(t)]		 [   0	    0	  1]
//////////////////////////////////////////////////////////////////////////

// Using the above matrices for rotation around a "known" axis, and a little
// bit (well maybe a lot) of math, we can come up with the matrix that will
// allow us to rotate around ANY axis.  Sparing the gritty math details, which
// feel free to look up if you're in to S&M :), you get the following:

// **NOTE**
// x = X component of arbitrary normalized axis
// y = Y component of arbitrary normalized axis
// z = Z component of arbitrary normalized axis
// t = angle theta to rotate by
// Oh and prepare to scroll over, this puppy is long :)

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// [(x * x * (1 - cos(t)) + cos(t))			(x * y * (1 - cos(t)) + z * sin(t))		(x * z * (1 - cos(t)) - y * sin(t))]
// [(x * y * (1 - cos(t)) - z * sin(t))		(y * y * (1 - cos(t)) + cos(t))			(y * z * (1 - cos(t)) + x * sin(t))]
// [(x * z * (1 - cos(t)) + y * sin(t))		(y * z * (1 - cos(t)) - x * sin(t))		(z * z * (1 - cos(t)) + cos(t))	   ]
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// With the above matrix and a tad more linear algebra we can now implement
// this function which takes "axis" as the axis to rotate the camera around
// by "angle" amount in radians

// Rotates around an arbritrary axis
CVector CCamera::rotateAroundAxis(const CVector &vec, const CVector &axis, float angle)
{
	float aX = axis.x; // Axis X
	float aY = axis.y; // Axis Y
	float aZ = axis.z; // Axis Z
	
	// Compute the sin and cos of the angle 
	float sinAng = sinf(angle);
	float cosAng = cosf(angle);

	// Calculate X component
	float xxx = (aX * aX * (1.0f - cosAng) + cosAng) * vec.x +
			    (aX * aY * (1.0f - cosAng) + aZ * sinAng) * vec.y +
			    (aX * aZ * (1.0f - cosAng) - aY * sinAng) * vec.z;
	
	// Calculate Y component	   
	float yyy = (aX * aY * (1.0f - cosAng) - aZ * sinAng) * vec.x +
			    (aY * aY * (1.0f - cosAng) + cosAng) * vec.y +
			    (aY * aZ * (1.0f - cosAng) + aX * sinAng) * vec.z;
			   
	// Calculate Z component
	float zzz = (aX * aZ * (1.0f - cosAng) + aY * sinAng) * vec.x +
			    (aY * aZ * (1.0f - cosAng) - aX * sinAng) * vec.y +
			    (aZ * aZ * (1.0f - cosAng) + cosAng) * vec.z;
			    
	return CVector(xxx, yyy, zzz); // Return result
}

Share this post


Link to post
Share on other sites
it looks like they took the 3 matrices i listed above and combine them into one huge monster matrix and multiply the vector with it or something. i guess my question is, how did they get the three matrices, and how did they make that big monster matrix?

Share this post


Link to post
Share on other sites
It's rotational matrices. The different slots set in the 3 are just so when they're multiplied against a vector you get a transformed vector from it. For why certain slots get certain things you'll just have to read up on that. Too lengthy to make a post on (at least for me, I'm lazy) and you should be able to find info all over.

And the final "monster matrix" is just the 3 matrices multiplied together. look up how to do matrix multiplies for this one. That one isn't difficult. Basically though, you get the effects of all 3 matrices in one handy dandy matrix. For example, if you have a large group of objects to transform by translating, and rotating 3 angles, you can stick all that in one matrix so you're only doing one thing instead of translate rotate, rotate, rotate.

hope that helps a little?

btw, how are you doing your rotating and moving around if not with matrices in direct3d? using angles and then generating the matrices? if so, you're doing the same thing just not manually like him is all.

Share this post


Link to post
Share on other sites
A matrix in D3D is 4x4... lets name the entries
A B C D
E F G H
I J K L
M N O P

How is this interpreted? Well, when you multiply a vector (such as vertex position) by a matrix (such as world or view transform) it does this:

X = A * Vx + E * Vy + I * Vz + M * Vw
Y = B * Vx + F * Vy + J * Vz + N * Vw
Z = C * Vx + G * Vy + K * Vz + O * Vw
W = D * Vx + H * Vy + L * Vz + P * Vw

However, usually in a vertex you include only a three element vector. For position you assume W is 1, and for a normal you assume W is 0... giving you this:

Position:
X = A * Vx + E * Vy + I * Vz + M
Y = B * Vx + F * Vy + J * Vz + N
Z = C * Vx + G * Vy + K * Vz + O
W = D * Vx + H * Vy + L * Vz + P

This is what D3DXVec3Transform does... and why it needs to write to a 4 element vector. If you pay close attention, you'll notice that it's just a dot product of a vector by each column of the matrix.

D3DXVec3TransformCoord does this too, then divides by W... X/=W, Y/=W, Z/=W and stores this in a 3 element vector.



Normal:
X = A * Vx + E * Vy + I * Vz
Y = B * Vx + F * Vy + J * Vz
Z = C * Vx + G * Vy + K * Vz
W = D * Vx + H * Vy + L * Vz

This is what D3DXVec3TransformNormal does.


Also important... Matrices can be multiplied, which has the effect of combining transformations...

Share this post


Link to post
Share on other sites
thanks guys, i'll spend some time reading up on all that stuff :)


the way i did it was i kind of imagined like a circle of radius 1 was around the camera position. pushing left or right arrow increments or decrements a float that reppresents angle (0-360). before drawing i set the view matrix to look at a point on the unit circle by converting my angle into radians, and setting the x and z coords of the view target to be sin(angle) and cos(angle), or something like that. i played around with it to get it to work, i don't have my code in front of me but i think that's how i got it to work

i still haven't made it look up and down yet, i happened to see a tutorial on what i was doing and wanted to see how others do it. do you guys think using vectors and matrices would be better than what i did? at the moment i can't think of any real disadvantages, but i can imagine once i actually start implementing things, problems might surface that i hadn't forseen :)

thanks again

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this