# 6DOF movement for a space game

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

## Recommended Posts

Hello, I had a question on how to use 6DOF movement in my game. I currently, and very recently, know how to use matrix rotations with vectors but need the 6DOF movement to do what I want correctly. Any help on this subject, be it a link to a website with the math for it or how to make the movement, a post on how to do it, or what ever. Thanks for readin, hope to hear back soon.

##### Share on other sites
There was a good article online about this by Ron Levine, but I can't seem to find it at the moment. Meanwhile, here is source code that implements what you want; let me know if you have any questions about it, or need help converting it for a particular API or math library.

##### Share on other sites
thanks for the quick reply :) I'm working in JOGL so it'll be tricky to rewrite, but it might get me on my way :) if there is anymore information you or anyone else has, feel free to post. :D

##### Share on other sites
I don't know much about JOGL, but the thing about 6DOF motion (unlike Euler-angle based motions such as in a first-person shooter) is that you pretty much have to do some math on your side of things, whether it be with vectors, matrices, or quaternions.

What that translates to in Java I'm not sure, but in any case it can be fairly awkward to implement 6DOF motion exclusively via OpenGL function calls.

##### Share on other sites
lol, i dont want it in OpenGL functions. I want to write the constructors and functions of the vectors, matricies, and quaternions to do 6DOF. I like to be able to see it happening so I want everything in my own classes (compiled source files). I have a vector class written, I believe thats the basic start of a rotation system. If anyone has information on how to accomplish 6DOF using vectors, matrices, and quaternions (studying quaternions but dont comprehend yet). I dont care if you decide to show source code in a different language such as c, c++ because its easy enough to rewrite. Thanks for everyones help :) lookin forward to next post.

##### Share on other sites
I've never done 6DOF movement myself (just done the typical FPS camera which is pretty straightforward), but I have an idea as to how it might be done. Correct me anyone if i'm wrong here, i'm just speculating- but this is how I would approach it myself. This technique uses matrices, its probably easier to implement with quaternions seeing as they are very easy to rotate about any arbitrary axis, but since you are probably more familiar with matrices I'll describe how to do it with them...

Ok, so with 6DOF the basic idea is that for every rotation you rotate about the previous orientation or axes of the camera instead of just the normal xyz axes.

You may or may not be already be aware that the orientation of a camera, or indeed any rotation is made up of three separate vectors which form a 3x3 matrix. The names of these vectors are 'up' , 'left' and 'forward'. I'm using the openGL coordinate system here, so foward (or the positive side of the z axis) actually comes in from the screen, rather than going into it as we would normally think:

up (y)

|
|
|
|_______ left (x)
/
/
/ forward (z)

When the camera is at the default or natural orientation of the coordinate system (xyz axes) these three vectors would have the following x,y,z cooridinates:

left ( 1 , 0 , 0 )
up ( 0 , 1 , 0)
forward ( 0 , 0 , 1 )

Ok, so this is the default orientation of the camera. When we want to do the following movements in space we would do the following rotations about the following axes:

yaw ( turn camera left and right ) : rotate the left and forward vectors about the up vector by desired amount

pitch ( move camera up and down- like looking up and down in a FPS ) : rotate the up and forward vectors about the left vector by desired amount

roll ( like the circular camera movements in the original elite or how an aircraft turns ) : rotate the up and left vectors about the forward vector by the desired amount.

So this is how you would modify the 3 vectors that describe the orientation of the camera when you want to do each of the following movements. So the question is how do we rotate vectors about another arbritarty vector ? Doing rotations about the xyz axes is straight forward enough, and the matrices to do so are not too complicated, but rotation about any vector is slightly more difficult. Luckily there is a genralised matrix that can do this for you. This is taken directly from my own maths notes:

Where 'A' is the angle of rotation and 'V' is the vector to rotate about and Vx Vy Vz are the xyz components of this vector, the rows and columns of the 3x3 matrix which rotates by A around vector V is found by:

row1 col1: (1-cosA)(Vx)(Vx) + cosA
row1 col2: (1-cosA)(Vx)(Vy) - (Vz)(sinA)
row1 col3: (1-cosA)(Vx)(Vz) - (Vy)(sinA)
row2 col1: (1-cosA)(Vx)(Vy) + (Vz)(sinA)
row2 col2: (1-cosA)(Vy)(Vy) + cosA
row2 col3: (1-cosA)(Vy)(Vz) - (Vx)(sinA)
row3 col1: (1-cosA)(Vx)(Vz) - (Vy)(sinA)
row3 col2: (1-cosA)(Vy)(Vz) + (Vx)(sinA)
row3 col3: (1-cosA)(Vz)(Vz) + cosA

Phew.. Thats a lot of maths! [wink] But if you constuct the matrix as such, you can use it to transform any vector about the vector 'V' at the desired angle 'A'. Just mutiply the vector you want to be transformed by this matrix and it will be done.

So how do you incorporate this to make up a transform matrix which will orientate the view in OpenGL ? You may or may not be familar with 4x4 matrices and how openGL uses them to transform objects, but basically they are the same as 3x3 matrices except they also incorporate information about translation as well as rotation. The rows and columns of this matrix are made up of the following components:

leftVector_x , upVector_x , forwardVector_x , translationVector_x
leftVector_y , upVector_y , forwardVector_y , translationVector_y
leftVector_z , upVector_z , forwardVector_z , translationVector_z
0 , 0 , 0 , 1

As you can see your view vectors slot nicely into this matrix. But how do you incorporate translations as well as rotations ? Normally you would want to translate first (think about this in your head) and then rotate all the objects about the position the camera is in. Well first construct a matrix which just describes a translation as follows:

1 , 0 , 0 , translationVector_x
0 , 1 , 0 , translationVector_y
0 , 0 , 1 , translationVector_z
0 , 0 , 0 , 1

Then multiply it by the matrix which describes your camera orientation which is as follows:

leftVector_x , upVector_x , forwardVector_x , 0
leftVector_y , upVector_y , forwardVector_y , 0
leftVector_z , upVector_z , forwardVector_z , 0
0 , 0 , 0 , 1

This should cause the translation to be done first and then rotation. Once you have done this, you now have your final matrix which can be used to do transforms in OpenGL. Use glLoadMatrix() to load your matrix and set it as the current transform matrix.

Thats about it. There are some issues with this however you should be aware of, which are directly to do with floating point precision. Continious multiplications and additions will result in a build up of error, so you will need to take the following precautions:

(1) You should constantly be normalising your camera vectors to ensure they stay of unit lenght. Just figure out each vectors lenght and divide by it to normalise. View vectors must stay at unit lenght, its just the way the math works.

(2) All three of the view vectors should always be perpendicular to each other- in other words the dot product of any two of the view vectors should always be zero. You can pick a vector to make the others perpendicular against, and just solve a linear equation such that Vector 1 dot Vector 2 equals zero. If this is not done your transforms could get gradually skewed and distorted.

Well thats all I have to say about this. Hopefully this will help, but you should look elsewhere on the internet because my explantion alone will probably not be enough for you to completely understand what is happening.

Best of luck anyhows with your space game, send me some screenshots when its done [wink]

Regards,
Darragh

##### Share on other sites
oh wow :D this was more than I could of hoped for :) I'll get to it immediately, I hope it goes smoothly. thanks for your detailed reply :) if anyone else has any ideas, methods, source code, or anything that might help, dont hesitate :D

##### Share on other sites
Quote:
 Original post by MythProgrammeroh wow :D this was more than I could of hoped for :) I'll get to it immediately, I hope it goes smoothly. thanks for your detailed reply :) if anyone else has any ideas, methods, source code, or anything that might help, dont hesitate :D

No problem, your welcome. Coincidently I am also revising for a math exam at the moment (which comprises of a lot of this stuff) so it kinda doubles up as revision for me too! [smile] Ya hopefully it will work, like I said its untested but it sounds right- in theory at least... Communism is also supposed to work in theory too though, so don't take it as being 100% correct! [lol]

Ah sure give it a go anyhow, it may well do the trick.

Good luck!

##### Share on other sites
lol if this works, i dunno :P lol, i'll probably praise ur name and have it appear in the game somewhere :D lol thanks man, glad i didnt hesitate to ask for help when i needed it :)

##### Share on other sites
Quote:
 Original post by MythProgrammerlol, i dont want it in OpenGL functions. I want to write the constructors and functions of the vectors, matricies, and quaternions to do 6DOF. I like to be able to see it happening so I want everything in my own classes (compiled source files). I have a vector class written, I believe thats the basic start of a rotation system. If anyone has information on how to accomplish 6DOF using vectors, matrices, and quaternions (studying quaternions but dont comprehend yet). I dont care if you decide to show source code in a different language such as c, c++ because its easy enough to rewrite.
I imagine Darragh's post probably gave you all the necessary info, but I'd just like to clarify that the source code I directed you to does not implement 6DOF motion via OpenGL functions, but rather through vectors and matrices, exactly as you requested. The only gl function calls are (I believe) glMultMatrix() and the like, which are simply for getting your matrices to OpenGL. So for what it's worth, the linked code is in fact a working example of 6DOF motion using custom math classes, so if you find yourself needing another reference I encourage you to check it out.

[Edit: typo]

[Edited by - jyk on May 8, 2006 10:55:37 PM]

##### Share on other sites
lol, woot :D i have two things to cross refrence :) i have working code and a mathematical blueprint :) today got a whole lot better ;)

##### Share on other sites
lol, i was lookin through it and came across two things that made my blood run cold. I wasnt looking for 6DOF movement for the camera, im looking for 6DOF movement for the model itself (the space ship). Ive been trying to do tests using stationary models that only had roll pitch yaw to effect its orientation. I believe what i was offered here was for the rotation around the object, also helpful, but not meeting my needs at the moment. thanks for the help but looks like my search still isnt done.

[Edit: I may have jumped the boat a bit when i said it dosnt fully meet my needs yet. i'll test a bit more but it seems i may need more help than i thought :P]

##### Share on other sites
Quote:
 Original post by MythProgrammerlol, i was lookin through it and came across two things that made my blood run cold. I wasnt looking for 6DOF movement for the camera, im looking for 6DOF movement for the model itself (the space ship). Ive been trying to do tests using stationary models that only had roll pitch yaw to effect its orientation. I believe what i was offered here was for the rotation around the object, also helpful, but not meeting my needs at the moment. thanks for the help but looks like my search still isnt done.[Edit: I may have jumped the boat a bit when i said it dosnt fully meet my needs yet. i'll test a bit more but it seems i may need more help than i thought :P]
I shall further attempt to clarify the code I linked to :-) It implements both FPS-style and 6DOF motion for either a model or a camera; all you have to do is set it up correctly and use the correct functions. The only caveat is that the view matrix is constructed as if +z were forward in model space, but this can easily be changed.

If it's not working for you, feel free to ask any questions you might have. Based on what you've posted I'm almost certain that the code will do what you need; it's just a matter of adapting it appropriately.

##### Share on other sites
Ah right, so you want the model to rotate about its own origin rather than everything to rotate about the camera ? Thats no biggie, don't sweat it! [wink]

Again I'm talking in theory here because I haven't actually put this into practice yet, but I would take the following steps:

(1) At the start of each draw you will set up your camera orientation and position and orientation using the appropriate OpenGL commands glTranslate, glRotate etc... These all affect the currently used transform matrix and do the hard work of modifying the matrix for you. Normally, for a camera you would translate all objects first and then rotate about the camera.
(2) When you are rotating the object about itself, use three vectors to describe its orientation as described previously and rotate these about each other as previously described for yaw,pitch and roll movements.
(3) Upon drawing the object, construct the 4x4 matrix as explained previously which describes both the orientation and translation of the object- the very same as what you had done for the camera.
(4) Save the current OpenGL transform matrix (i.e the one that describes the camera) and keep it handy- you'll need it.
(5) Now we have a matrix that first rotates and then translates the model within its own space, we also have one which describes the camera's orientation and position.. Both affect the final position of the object and both are equally important. What we need to do is to combine these two transforms such that the object is first rotated about its origin, and then translated, and finally is translated by the camera position and rotated about the camera. All these transforms can be combined into the one matrix by doing a simple matrix multiplication. Just multiply the camera matrix (the one you got from OpenGL) by your objects own transform matrix (the 4x4 matrix you figured out yourself) in order to combine the two transforms. Note that the order of multiplication is *very* important here- since it determines which transform is 'done first'. The matrix which is on the left when multiplying is the first operation to be done I think- but if not then just reverse the order. So construct a new and final transform matrix for the object by doing the following multiplication:

finalMatrix = objectTransformMatrix*cameraTransformMatrix

This should transform the object into the correct position, taking into account the models own orientation and position as well as that of the camera.

(6) Once you have calculated this 'final matrix' then set it as the currently used matrix in openGL and render the object as normal.
(7) When you finished rendering just restore the previous camera matrix as the current openGL transform matrix. You will need it again if you are to render any more models.

That should be it.. I probably could have made this explanation a little shorter but there ya go- I'm full of s**t.. [lol]

Good luck!

##### Share on other sites
lol thanks for the help again, but one more thing came to mind :P (its never ending with me) pitch roll and yaw is used to tell the orientation but in the matrix u gave...

row1 col1: (1-cosA)(Vx)(Vx) + cosA
row1 col2: (1-cosA)(Vx)(Vy) - (Vz)(sinA)
row1 col3: (1-cosA)(Vx)(Vz) - (Vy)(sinA)
row2 col1: (1-cosA)(Vx)(Vy) + (Vz)(sinA)
row2 col2: (1-cosA)(Vy)(Vy) + cosA
row2 col3: (1-cosA)(Vy)(Vz) - (Vx)(sinA)
row3 col1: (1-cosA)(Vx)(Vz) - (Vy)(sinA)
row3 col2: (1-cosA)(Vy)(Vz) + (Vx)(sinA)
row3 col3: (1-cosA)(Vz)(Vz) + cosA

... there is only A. Im just a little confused on how to use pitch roll and yaw when only one angle is used. (im probably looking over something simple and not catching it :P, sorry to be a bothersome)

##### Share on other sites
Quote:
 Original post by MythProgrammerlol thanks for the help again, but one more thing came to mind :P (its never ending with me) pitch roll and yaw is used to tell the orientation but in the matrix u gave...row1 col1: (1-cosA)(Vx)(Vx) + cosA row1 col2: (1-cosA)(Vx)(Vy) - (Vz)(sinA)row1 col3: (1-cosA)(Vx)(Vz) - (Vy)(sinA)row2 col1: (1-cosA)(Vx)(Vy) + (Vz)(sinA)row2 col2: (1-cosA)(Vy)(Vy) + cosArow2 col3: (1-cosA)(Vy)(Vz) - (Vx)(sinA)row3 col1: (1-cosA)(Vx)(Vz) - (Vy)(sinA)row3 col2: (1-cosA)(Vy)(Vz) + (Vx)(sinA)row3 col3: (1-cosA)(Vz)(Vz) + cosA... there is only A. Im just a little confused on how to use pitch roll and yaw when only one angle is used. (im probably looking over something simple and not catching it :P, sorry to be a bothersome)
Part of the point here is that you don't use pitch, roll and yaw (or more specifically, a from-scratch Euler angle construction) for 6DOF.

The above is the construction for an axis-angle matrix; A is the angle, and (Vx, Vy, Vz) is the (unit-length) axis. The resulting matrix has the effect of rotating a vector about the given axis, by the given angle.

One way to implement 6DOF orientation is to apply local-axis rotations using the above matrix form.

##### Share on other sites
ah k lol, thanks for that, :P knew i was overlookin somethin XD lol, :) alright... gotta try to implement it now :P wish me luck. thanks everyone for their help :D

##### Share on other sites
And because you will certainly come to the point where you want to move/rotate using world axes (because something is pushing the ship around or whatever), the simple thing to keep in mind is:
Mat*Transf applies the translation/rotation in Transf in local/object space an
Transf*Mat does the same in world space (or the other way round, depending on your matrices). The easy way to explain is that one way applies it AFTER all transformations that happened before (ie, when local x,y,z,origin aren't the same as for the world anymore) and doing it BEFORE means... well, the other thing.

And if you don't want to do matrix mults for simple translation, just translate along the row/column (again depends on your matrices) of the transposed Mat.

##### Share on other sites
i think something is a lil miswired or somethin in my program. right now it rotates but its not rotating around the object, its rotating around the camera view that is at default of (0,0,0) and its rotating in a circle thats 15 units away when it should be 15 units infront of the camera and rotating around its own axis.

Here are snips of what im doing [The vector, Matrix3x3, Matrix4x4, AxisAngleRotation are my own classes but ive run tests to make sure the functions worked correctly. I think im implementing incorrectly though.]:

Vector vector[] = new Vector[3];
vector[0] = new Vector(1,0,0,vector0Color);
vector[1] = new Vector(0,1,0,vector1Color);
vector[2] = new Vector(0,0,1,vector2Color);

private Matrix4x4 dof6Movement() {
AxisAngleRotation axisAngleRotation = new AxisAngleRotation();
double[][] matrix = {
{1,0,0,0},
{0,1,0,0},
{0,0,1,15},
{0,0,0,1}
};
Matrix4x4 tranMatrix = new Matrix4x4(matrix);

Matrix3x3 matrixResultA = axisAngleRotation.performRotationAroundAxis(roll, vector[1]);
Matrix3x3 matrixResultB = axisAngleRotation.performRotationAroundAxis(roll, vector[0]);

Matrix4x4 matrixResult = tranMatrix.multiply(new Matrix4x4(matrixResultA.multiply(matrixResultA, matrixResultB).getMatrix()), matrix4x4);
Matrix4x4 matrixConversion = matrixResult;

return matrixConversion;
}

public void display(GLDrawable gLDrawable) {
final GL gl = gLDrawable.getGL();
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

gl.glPointSize(10);
gl.glLineWidth(5);

Matrix4x4 matrix4x4 = dof6Movement();
double[] glHold = new double[16];
for (int a = 0; a < 4; a++){
for (int b = 0; b < 4; b++){
glHold[a*4 + b] = matrix4x4.getMatrixElement(b,a);
}
}
gl.glTranslated(0,0,-15);

gl.glBegin(GL.GL_LINES);
gl.glColor3d(1,0,0); gl.glVertex3d(vector[0].getX(), vector[0].getY(), vector[0].getZ()); gl.glVertex3d(0,0,0);
gl.glColor3d(0,1,0); gl.glVertex3d(vector[1].getX(), vector[1].getY(), vector[1].getZ()); gl.glVertex3d(0,0,0);
gl.glColor3d(0,0,1); gl.glVertex3d(vector[2].getX(), vector[2].getY(), vector[2].getZ()); gl.glVertex3d(0,0,0);
gl.glEnd();

gl.glBegin(GL.GL_POINTS);
gl.glColor3d(1,1,1); gl.glVertex3d(0,0,0);
gl.glColor3d(1,0,0); gl.glVertex3d(vector[0].getX(), vector[0].getY(), vector[0].getZ());
gl.glColor3d(0,1,0); gl.glVertex3d(vector[1].getX(), vector[1].getY(), vector[1].getZ());
gl.glColor3d(0,0,1); gl.glVertex3d(vector[2].getX(), vector[2].getY(), vector[2].getZ());
gl.glEnd();

roll++;
}

[Edit: It should be indented but the forum dosnt support it i suppose. Sorry for the inconvience]

##### Share on other sites
Quote:
 Original post by MythProgrammer[Edit: It should be indented but the forum dosnt support it i suppose. Sorry for the inconvience]
Just put it in [ source ][ /source ] tags (without the spaces). I'd be happy to look through it then.

##### Share on other sites
	Vector vector[] = new Vector[3];	vector[0] = new Vector(1,0,0);	vector[1] = new Vector(0,1,0);	vector[2] = new Vector(0,0,1);	double roll = 0;	double pitch = 0;	double yaw = 0;	public void display(GLDrawable gLDrawable) {		final GL gl = gLDrawable.getGL();		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);		gl.glLoadIdentity();				gl.glPointSize(10);		gl.glLineWidth(5);				Matrix4x4 matrix4x4 = dof6Movement();		double[] glHold = new double[16];		for (int a = 0; a < 4; a++){			for (int b = 0; b < 4; b++){				glHold[a*4 + b] = matrix4x4.getMatrixElement(b,a);			}		}		gl.glLoadMatrixd(glHold);		gl.glTranslated(0,0,-15);				gl.glBegin(GL.GL_LINES);			gl.glColor3d(1,0,0); gl.glVertex3d(vector[0].getX(), vector[0].getY(), vector[0].getZ()); gl.glVertex3d(0,0,0);			gl.glColor3d(0,1,0); gl.glVertex3d(vector[1].getX(), vector[1].getY(), vector[1].getZ()); gl.glVertex3d(0,0,0);			gl.glColor3d(0,0,1); gl.glVertex3d(vector[2].getX(), vector[2].getY(), vector[2].getZ()); gl.glVertex3d(0,0,0);		gl.glEnd();				gl.glBegin(GL.GL_POINTS);			gl.glColor3d(1,1,1); gl.glVertex3d(0,0,0);			gl.glColor3d(1,0,0); gl.glVertex3d(vector[0].getX(), vector[0].getY(), vector[0].getZ());			gl.glColor3d(0,1,0); gl.glVertex3d(vector[1].getX(), vector[1].getY(), vector[1].getZ());			gl.glColor3d(0,0,1); gl.glVertex3d(vector[2].getX(), vector[2].getY(), vector[2].getZ());		gl.glEnd();				roll++;	}		private Matrix4x4 dof6Movement() {		AxisAngleRotation axisAngleRotation = new AxisAngleRotation();		double[][] matrix = {			{1,0,0,0},			{0,1,0,0},			{0,0,1,15},			{0,0,0,1}		};		Matrix4x4 tranMatrix = new Matrix4x4(matrix);				Matrix3x3 matrixResultA = axisAngleRotation.performRotationAroundAxis(roll, vector[1]);		Matrix3x3 matrixResultB = axisAngleRotation.performRotationAroundAxis(roll, vector[0]);				Matrix4x4 matrixResult = tranMatrix.multiply(new Matrix4x4(matrixResultA.multiply(matrixResultA, matrixResultB).getMatrix()), tranMatrix); 		Matrix4x4 matrixConversion = matrixResult;				return matrixConversion;	}

##### Share on other sites
Quote:
 its rotating around the camera view that is at default of (0,0,0) and its rotating in a circle thats 15 units away when it should be 15 units infront of the camera and rotating around its own axis.

Then most likely you should simply move the object to its position, BEFORE you start rotating it. As I mentioned above, that makes the different beween using the local or the world coordinate system and you obviously move it along the OBJECTs z, which isn't the z you want.

replace
for bla {for blub {glHold[a*4 + b] = matrix4x4.getMatrixElement(b,a);}}
gl.glTranslated(0,0,-15);

with
glTranslated(0,0,-15);
glMultMatrixd(glHold); //MULT, especially later on you don't want to throw away whatever you did to set up the view

Quote:
 Vector vector[] = new Vector[3];vector[0] = new Vector(1,0,0,vector0Color);vector[1] = new Vector(0,1,0,vector1Color);vector[2] = new Vector(0,0,1,vector2Color);

If that is supposed to be a vertex, it would be MUCH less confusing to actually call it that, because vectors generally don't have a color.

Quote:
 Matrix4x4 tranMatrix = new Matrix4x4(matrix); Matrix3x3 matrixResultA = axisAngleRotation.performRotationAroundAxis(roll, vector[1]);Matrix3x3 matrixResultB = axisAngleRotation.performRotationAroundAxis(roll, vector[0]);Matrix4x4 matrixResult = tranMatrix.multiply(new Matrix4x4(matrixResultA.multiply(matrixResultA, matrixResultB).getMatrix()), matrix4x4); Matrix4x4 matrixConversion = matrixResult;return matrixConversion;}

Ok, I generally avoid Java like the plague (because I'm a biased sob), so I assume it still doesn't allow overloading/overwriting operators (I'll use them anyway).
Isn't that exactly the same as: return matrixResultA*matrixResultB;

Just with a lot of pointless temporary matrices? Or am I missing a major reason to hate Java that really enforces doing it like this?

In C++ I'd probably have something like
return Matrix44::rotMatZ(roll)*Matrix44:rotMatX(pitch);

Also note, that unless your angles are really small, you will get entirely different results, based on whether you do A*B or B*A. You are also wasting a generic "rotate around any axis"-matrix creation on rotations around coordinate axes, which can be created a lot simpler and more efficient.

Quote:
 for (int a = 0; a < 4; a++){ for (int b = 0; b < 4; b++){ glHold[a*4 + b] = matrix4x4.getMatrixElement(b,a); }}

Aside from not being sure WHY you seem to transpose the matrix, you really shouldn't transpose the WHOLE 4x4 matrix. The translation part needs to stay where it is, so this should only work because you don't have a translation in it. Plus, the only reason I could see for transposing is if the rotation is supposed to be applied to your "camera" (which doesn't exist and just means "apply the opposite transformation").

But as you obviously want to keep the "camera" at its default and move the object, FIRST translate, THEN apply the rotation. If you have to transpose the rotation, you should try to do your matrix multiplication the other way round.

Also, PLEASE don't end up storing yaw/pitch/roll as angles and building a completely new transformation matrix every frame. That would be about as pointless as calculating a hundred random square roots and only using the last one. Every object should have its own matrix (storing rotation AND translation), which is updated every frame, not rebuild from the very crappy Euler Angles that should be avoided in the first place. Alternatively you can store a position and a quaternion, but unless you apply a lot of rotations to the same object every frame OR desperately need the memory, you will just end up doing lots of quaternion-matrix conversions to setup OpenGL.

What you probably want to do each frame is:
object.rotate(whatever);
object.translate(in some direction); (in some update function)

It's also useful, if you either have seperate functions for world/local transformations or an optional parameter, so for example some explosion at X would push the ship in direction D with object.translateWORLD(D).

for each object
-glPushMatrix
-glMultMatrix(object[x].matrix)
-glPopMatrix

##### Share on other sites
thanks for the help everyone :) i believe its working now :D lol, just have to find a way to pull out the x,y, and z values and im golden :) i can manage that part, just need my matrix multiplication working. thanks for everything everyone :D i really couldnt of done it without you all :)

##### Share on other sites
Since everyone helped :) i had figured it should be available for anyone to use incase they had questions. It did work :D and the first words out of my mouth was "Oh my god..." :-P heres source code for all the classes involved in simplest form. Hopefuly they help someone else that tries to do 6DOF movement :)

Couldnt of done it without you guys :D

[AxisAngleRotation.java]:
package dof6.primitives;public class AxisAngleRotation {		public Matrix3x3 rotateLocalCoordinateSystemOfModel(Matrix3x3 rotationMatrix, Matrix3x3 up_foward_left_vectors){		Matrix3x3 resultMatrix = rotationMatrix.multiply(rotationMatrix, up_foward_left_vectors);				return resultMatrix;	}		public Matrix3x3 performRotationAroundAxis(double angle, Vector vector){		double angleRadians = Math.toRadians(angle);		double x = vector.getX();		double y = vector.getY();		double z = vector.getZ();				double[][] matrixToMultiplyTo = 		{			{				(((1-Math.cos(angleRadians))*(x*x)) + Math.cos(angleRadians)), 				(((1-Math.cos(angleRadians))*(x*y)) - (z*Math.sin(angleRadians))), 				(((1-Math.cos(angleRadians))*(x*z)) + (y*Math.sin(angleRadians))),			},			{				(((1-Math.cos(angleRadians))*(x*y)) + (z*Math.sin(angleRadians))), 				(((1-Math.cos(angleRadians))*(y*y)) + Math.cos(angleRadians)), 				(((1-Math.cos(angleRadians))*(y*z)) - (x*Math.sin(angleRadians))),			},			{				(((1-Math.cos(angleRadians))*(x*z)) - (y*Math.sin(angleRadians))), 				(((1-Math.cos(angleRadians))*(y*z)) + (x*Math.sin(angleRadians))), 				(((1-Math.cos(angleRadians))*(z*z)) + Math.cos(angleRadians)) 			}		};				Matrix3x3 matrix = new Matrix3x3(matrixToMultiplyTo);				return matrix;	}	}{/source][Matrix4x4.java]:package dof6.primitives;public class Matrix4x4 {		//Variables-----\	double[][] matrix = {		{1,0,0,0},		{0,1,0,0},		{0,0,1,0},		{0,0,0,1}	};	//Variables-----/		//Constructor-----\	public Matrix4x4() {}	public Matrix4x4(double[][] matrix) {		for (int a = 0; a < this.matrix.length; a++){			for (int b = 0; b < this.matrix[a].length; b++){				try {this.matrix[a][b] = matrix[a][b];} catch (Exception e) {}			}		}	}	//Constructor-----/		//Processing-----\	public Matrix4x4 multiply(Matrix4x4 matrixA, Matrix4x4 matrixB) {		double[][] matrix = new double[4][4];		for (int i = 0; i < matrix.length; i++)			for (int j = 0; j < matrix[i].length; j++)				matrix[i][j] = 0;		//cycle through answer matrix		for(int i = 0; i < matrix.length; i++){			for(int j = 0; j < matrix[i].length; j++){				matrix[i][j] = calculateRowColumnProduct(matrixA, i, matrixB, j);			}		}				return new Matrix4x4(matrix);	}	public float calculateRowColumnProduct(Matrix4x4 matrixA, int row, Matrix4x4 matrixB, int col){		float product = 0;		for(int i = 0; i < 4; i++)			product += matrixA.getMatrixElement(row,i) * matrixB.getMatrixElement(i,col);		return product;	}	//Processing-----/		//Getters/Setters-----\	public void addToMatrixElement(int row, int column, double value) {matrix[row][column] += value;}	public void subToMatrixElement(int row, int column, double value) {matrix[row][column] -= value;}		public double[][] getMatrix() {return matrix;}	public double getMatrixElement(int row, int column) {return matrix[row][column];}		public void setMatrix(double[][] matrix) {this.matrix = matrix;}	public void setMatrixElement(int row, int column, double value) {matrix[row][column] = value;}	//Getters/Setters-----/}

[Matrix3x3.java]:
package dof6.primitives;public class Matrix3x3 {		//Variables-----\	double[][] matrix = {		{1,0,0},		{0,1,0},		{0,0,1}	};	//Variables-----/		//Constructor-----\	public Matrix3x3() {}	public Matrix3x3(double[][] matrix) {		for (int a = 0; a < this.matrix.length; a++){			for (int b = 0; b < this.matrix[a].length; b++){				try {					this.matrix[a][b] = matrix[a][b];				} catch (Exception e) {					System.err.println("Matrix Element ["+a+"]["+b+"] is invalid in a 3x3 matrix.");				}			}		}	}	//Constructor-----/		//Processing-----\	public Matrix3x3 multiply(Matrix3x3 matrixA, Matrix3x3 matrixB) {		double[][] matrix = new double[3][3];				for (int i = 0; i < matrix.length; i++)			for (int j = 0; j < matrix[i].length; j++)				matrix[i][j] = 0;		//cycle through answer matrix		for(int i = 0; i < matrix.length; i++){			for(int j = 0; j < matrix[i].length; j++){				matrix[i][j] = calculateRowColumnProduct(matrixA, i, matrixB, j);			}		}				return new Matrix3x3(matrix);	}	public float calculateRowColumnProduct(Matrix3x3 matrixA, int row, Matrix3x3 matrixB, int col){		float product = 0;		for(int i = 0; i < matrixA.getMatrix().length; i++)			product += matrixA.getMatrixElement(row,i) * matrixB.getMatrixElement(i,col);		return product;	}	//Processing-----/		//Getters/Setters-----\	public void addToMatrixElement(int row, int column, double value) {matrix[row][column] += value;}	public void subToMatrixElement(int row, int column, double value) {matrix[row][column] -= value;}	public double[][] getMatrix() {return matrix;}	public double getMatrixElement(int row, int column) {return matrix[row][column];}		public void setMatrix(double[][] matrix) {this.matrix = matrix;}	public void setMatrixElement(int row, int column, double value) {matrix[row][column] = value;}	//Getters/Setters-----/}

[Matrix4x4.java]:
package dof6.primitives;public class Matrix4x4 {		//Variables-----\	double[][] matrix = {		{1,0,0,0},		{0,1,0,0},		{0,0,1,0},		{0,0,0,1}	};	//Variables-----/		//Constructor-----\	public Matrix4x4() {}	public Matrix4x4(double[][] matrix) {		for (int a = 0; a < this.matrix.length; a++){			for (int b = 0; b < this.matrix[a].length; b++){				try {this.matrix[a][b] = matrix[a][b];} catch (Exception e) {}			}		}	}	//Constructor-----/		//Processing-----\	public Matrix4x4 multiply(Matrix4x4 matrixA, Matrix4x4 matrixB) {		double[][] matrix = new double[4][4];		for (int i = 0; i < matrix.length; i++)			for (int j = 0; j < matrix[i].length; j++)				matrix[i][j] = 0;		//cycle through answer matrix		for(int i = 0; i < matrix.length; i++){			for(int j = 0; j < matrix[i].length; j++){				matrix[i][j] = calculateRowColumnProduct(matrixA, i, matrixB, j);			}		}				return new Matrix4x4(matrix);	}	public float calculateRowColumnProduct(Matrix4x4 matrixA, int row, Matrix4x4 matrixB, int col){		float product = 0;		for(int i = 0; i < 4; i++)			product += matrixA.getMatrixElement(row,i) * matrixB.getMatrixElement(i,col);		return product;	}	//Processing-----/		//Getters/Setters-----\	public void addToMatrixElement(int row, int column, double value) {matrix[row][column] += value;}	public void subToMatrixElement(int row, int column, double value) {matrix[row][column] -= value;}		public double[][] getMatrix() {return matrix;}	public double getMatrixElement(int row, int column) {return matrix[row][column];}		public void setMatrix(double[][] matrix) {this.matrix = matrix;}	public void setMatrixElement(int row, int column, double value) {matrix[row][column] = value;}	//Getters/Setters-----/}

[Vector.java]:
package dof6.primitives;public class Vector {		//Variables-----\	private double x = 0;	private double y = 0; 	private double z = 0;	//Variables-----/		//Constructor-----\	public Vector() {}	public Vector(double x, double y, double z) {		this.x = x;		this.y = y;		this.z = z;	}	//Constructor-----/		//Processing-----\	public void normalize(){		double distance = Math.sqrt(Math.pow(x,2) + Math.pow(y,2) + Math.pow(z,2));				this.x = x / distance;		this.y = y / distance;		this.z = z / distance;	}	//Processing-----/		//Getters/Setters-----\	public double getX() {return x;}	public double getY() {return y;}	public double getZ() {return z;}		public void setX(double x) {this.x = x;}	public void setY(double y) {this.y = y;}	public void setZ(double z) {this.z = z;}	//Getters/Setters-----/}

[Initializer.java]:
package dof6.test001;import java.awt.Toolkit;import javax.swing.JFrame;import net.java.games.jogl.Animator;import net.java.games.jogl.GLCanvas;import net.java.games.jogl.GLCapabilities;import net.java.games.jogl.GLDrawableFactory;public class Initialize extends JFrame{		//Variables-----\	private static final long serialVersionUID = -3774027917127157321L;    Animator animator;	//Variables-----/		//Start Of Program-----\	public static void main(String[] args) {new Initialize();}	//Start Of Program-----/		//Constructors-----\	public Initialize() {	    GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new GLCapabilities());	    animator = new Animator(canvas);	    canvas.addGLEventListener(new Renderer(animator));	    getContentPane().add(canvas);				setSize(640,480);		setLocation(			(int)(Toolkit.getDefaultToolkit().getScreenSize().getWidth()/2 - getWidth()/2), 			(int)(Toolkit.getDefaultToolkit().getScreenSize().getHeight()/2 - getHeight()/2)		);		setVisible(true);	    animator.start();	    canvas.requestFocus();		setDefaultCloseOperation(EXIT_ON_CLOSE);	}	//Constructors-----/	}

[Renderer.java]:
package dof6.test001;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import net.java.games.jogl.Animator;import net.java.games.jogl.DebugGL;import net.java.games.jogl.GL;import net.java.games.jogl.GLDrawable;import net.java.games.jogl.GLEventListener;import net.java.games.jogl.GLU;public class Renderer implements GLEventListener, KeyListener {	//Variables-----\		boolean keyActivated[] = new boolean[256];	Animator animator;	//	Vector vector[] = new Vector[3];//	double roll = 0;//	double pitch = 0;//	double yaw = 0;	Model model = new Model();	//Variables-----/		//Constructor-----\	public Renderer(Animator animator) {		this.animator = animator;//		vector[0] = new Vector(5,0,0);//		vector[1] = new Vector(0,5,0);//		vector[2] = new Vector(0,0,5);	}	//Constructor-----/		//Drawing-----\	public void init(GLDrawable glDrawable) {        GL gl = glDrawable.getGL();        glDrawable.setGL( new DebugGL(glDrawable.getGL()));                gl.glShadeModel(GL.GL_SMOOTH);        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);    // Black Background        gl.glClearDepth(1.0f);                      // Depth Buffer Setup        gl.glEnable(GL.GL_DEPTH_TEST);              // Enables Depth Testing        gl.glDepthFunc(GL.GL_LEQUAL);               // The Type Of Depth Testing To Do        gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);	// Really Nice Perspective Calculations        gl.glEnable(GL.GL_TEXTURE_2D);        glDrawable.addKeyListener(this);            // Listening for key events    }		public void displayChanged(GLDrawable glDrawable, boolean modeChanged, boolean deviceChanged){	}		public void display(GLDrawable gLDrawable) {		final GL gl = gLDrawable.getGL();		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);		gl.glLoadIdentity();		processKeys();				gl.glPointSize(10);		gl.glLineWidth(5);				gl.glTranslated(0,0,-15);		model.drawModel(gLDrawable);		//		Matrix4x4 matrix4x4 = dof6Movement();//		double[] matrix = new double[16];//		for (int a = 0; a < 4; a++){//			for (int b = 0; b < 4; b++){//				matrix[a*4+b] = matrix4x4.getMatrixElement(b,a);//			}//		}//		gl.glTranslated(0,0,-15);//		//gl.glMultMatrixd(matrix);//		//		gl.glBegin(GL.GL_LINES);//			gl.glColor3d(1,0,0); gl.glVertex3d(vector[0].getX(), vector[0].getY(), vector[0].getZ()); gl.glVertex3d(0,0,0);//			gl.glColor3d(0,1,0); gl.glVertex3d(vector[1].getX(), vector[1].getY(), vector[1].getZ()); gl.glVertex3d(0,0,0);//			gl.glColor3d(0,0,1); gl.glVertex3d(vector[2].getX(), vector[2].getY(), vector[2].getZ()); gl.glVertex3d(0,0,0);//		gl.glEnd();//		//		gl.glBegin(GL.GL_POINTS);//			gl.glColor3d(1,1,1); gl.glVertex3d(0,0,0);//			gl.glColor3d(1,0,0); gl.glVertex3d(vector[0].getX(), vector[0].getY(), vector[0].getZ());//			gl.glColor3d(0,1,0); gl.glVertex3d(vector[1].getX(), vector[1].getY(), vector[1].getZ());//			gl.glColor3d(0,0,1); gl.glVertex3d(vector[2].getX(), vector[2].getY(), vector[2].getZ());//		gl.glEnd();	}	//	private Matrix4x4 dof6Movement() {//		AxisAngleRotation axisAngleRotation = new AxisAngleRotation();////		Matrix3x3 matrixResultA = axisAngleRotation.performRotationAroundAxis(roll, vector[0]);//		//---------//		for (int column = 0; column < 3; column++){//			for (int row = 0; row < 3; row++){//				if (row == 0) vector[column].setX(matrixResultA.getMatrixElement(row, column));//				if (row == 1) vector[column].setY(matrixResultA.getMatrixElement(row, column));//				if (row == 2) vector[column].setZ(matrixResultA.getMatrixElement(row, column));//			}//			vector[column].normalize();//		}//		//---------		//		Matrix3x3 matrixResultB = axisAngleRotation.performRotationAroundAxis(pitch, vector[1]);//		//---------//		for (int column = 0; column < 3; column++){//			for (int row = 0; row < 3; row++){//				if (row == 0) vector[column].setX(matrixResultB.getMatrixElement(row, column));//				if (row == 1) vector[column].setY(matrixResultB.getMatrixElement(row, column));//				if (row == 2) vector[column].setZ(matrixResultB.getMatrixElement(row, column));//			}//			vector[column].normalize();//		}//		//---------		//		//		Matrix4x4 matrixConversion = new Matrix4x4(matrixResultA.multiply(matrixResultA, matrixResultB).getMatrix());//		//		for (int i = 0; i < 3; i++)//			vector[i].normalize();//		//		return matrixConversion;//	}	//Drawing-----/    	//Processing-----\	public void reshape(GLDrawable glDrawable, int x, int y, int width, int height) {		final GL gl = glDrawable.getGL();		final GLU glu = glDrawable.getGLU();				if (height <= 0) height = 1;		        float h = (float)width / (float)height;        gl.glViewport(0, 0, width, height);        gl.glMatrixMode(GL.GL_PROJECTION);        gl.glLoadIdentity();        glu.gluPerspective(45.0f, h, 1, 1000);        gl.glMatrixMode(GL.GL_MODELVIEW);        gl.glLoadIdentity();    }		private void processKeys() {		if (keyActivated[KeyEvent.VK_ESCAPE]) System.exit(0);//		if (keyActivated[KeyEvent.VK_LEFT]) roll++;//		if (keyActivated[KeyEvent.VK_RIGHT]) roll--;//		if (keyActivated[KeyEvent.VK_UP]) pitch++;//		if (keyActivated[KeyEvent.VK_DOWN]) pitch--;		if (keyActivated[KeyEvent.VK_RIGHT]) model.rollIncreaseOrDecrease(1);		else if (keyActivated[KeyEvent.VK_LEFT]) model.rollIncreaseOrDecrease(-1);		else model.rollIncreaseOrDecrease(0);		if (keyActivated[KeyEvent.VK_UP]) model.pitchIncreaseOrDecrease(1);		else if (keyActivated[KeyEvent.VK_DOWN]) model.pitchIncreaseOrDecrease(-1);		else model.pitchIncreaseOrDecrease(0);	}	//Processing-----/		//Event Listeners-----\	public void keyTyped(KeyEvent arg0) {}	public void keyPressed(KeyEvent arg0) {keyActivated[arg0.getKeyCode()] = true;}	public void keyReleased(KeyEvent arg0) {keyActivated[arg0.getKeyCode()] = false;}	//Event Listeners-----/		//Getters/Setters-----\	//Getters/Setters-----/		//Undecided-----\	//Undecided-----/	}

[Model.java]:
package dof6.test001;import net.java.games.jogl.GL;import net.java.games.jogl.GLDrawable;import dof6.primitives.AxisAngleRotation;import dof6.primitives.Matrix3x3;import dof6.primitives.Matrix4x4;import dof6.primitives.Vector;public class Model {	//Variables-----\	AxisAngleRotation axisAngleRotation = new AxisAngleRotation();	Vector vector[] = {		new Vector(1,0,0),		new Vector(0,1,0),		new Vector(0,0,1)	};	double roll = 0;	double pitch = 0;	double yaw = 0;	Matrix3x3 rollMatrix = axisAngleRotation.performRotationAroundAxis(roll, vector[0]);		Matrix3x3 yawMatrix = axisAngleRotation.performRotationAroundAxis(yaw, vector[1]);	Matrix3x3 pitchMatrix = axisAngleRotation.performRotationAroundAxis(pitch, vector[2]);	//Variables-----/		//Constructor-----\	public Model() {}	//Constructor-----/		//Drawing-----\	public void drawModel(GLDrawable glDrawable){		GL gl = glDrawable.getGL();				/*double[] matrix = new double[16];		for (int a = 0; a < 4; a++)			for (int b = 0; b < 4; b++)				matrix[a*4+b] = new Matrix4x4(pitchMatrix.getMatrix()).getMatrixElement(b,a);		gl.glMultMatrixd(matrix);*/		/*for (int a = 0; a < 4; a++)			for (int b = 0; b < 4; b++)				matrix[a*4+b] = new Matrix4x4(rollMatrix.getMatrix()).getMatrixElement(b,a);		gl.glMultMatrixd(matrix);*/				{			Matrix3x3 matrixAll = new Matrix3x3(pitchMatrix.multiply(pitchMatrix, rollMatrix).getMatrix());						double[][] vectorsN = {				{vector[0].getX(), vector[1].getX(), vector[2].getX()},				{vector[0].getY(), vector[1].getY(), vector[2].getY()},				{vector[0].getZ(), vector[1].getZ(), vector[2].getZ()},			};			Matrix3x3 vectors = new Matrix3x3(vectorsN);						Matrix3x3 result = axisAngleRotation.rotateLocalCoordinateSystemOfModel(matrixAll, vectors);						for (int column = 0; column < 3; column++){				for (int row = 0; row < 3; row++){					if (row == 0) vector[column].setX(result.getMatrixElement(row, column));					if (row == 1) vector[column].setY(result.getMatrixElement(row, column));					if (row == 2) vector[column].setZ(result.getMatrixElement(row, column));				}				vector[column].normalize();			}		}						gl.glBegin(GL.GL_LINES);			gl.glColor3d(1,0,0); gl.glVertex3d(vector[0].getX(), vector[0].getY(), vector[0].getZ()); gl.glVertex3d(0,0,0);			gl.glColor3d(0,1,0); gl.glVertex3d(vector[1].getX(), vector[1].getY(), vector[1].getZ()); gl.glVertex3d(0,0,0);			gl.glColor3d(0,0,1); gl.glVertex3d(vector[2].getX(), vector[2].getY(), vector[2].getZ()); gl.glVertex3d(0,0,0);		gl.glEnd();				gl.glBegin(GL.GL_POINTS);			gl.glColor3d(1,1,1); gl.glVertex3d(0,0,0);			gl.glColor3d(1,0,0); gl.glVertex3d(vector[0].getX(), vector[0].getY(), vector[0].getZ());			gl.glColor3d(0,1,0); gl.glVertex3d(vector[1].getX(), vector[1].getY(), vector[1].getZ());			gl.glColor3d(0,0,1); gl.glVertex3d(vector[2].getX(), vector[2].getY(), vector[2].getZ());		gl.glEnd();	}	//Drawing-----/		//Processing-----\	public void rollIncreaseOrDecrease(int switchValue){		if (switchValue==1) roll=1;		else if (switchValue==-1) roll=-1;		else roll = 0;				rollMatrix = axisAngleRotation.performRotationAroundAxis(roll, vector[0]);				/*for (int column = 0; column < 3; column++){			for (int row = 0; row < 3; row++){				if (row == 0) vector[column].setX(vector[column].getX() + rollMatrix.getMatrixElement(row, column));				if (row == 1) vector[column].setY(vector[column].getY() + rollMatrix.getMatrixElement(row, column));				if (row == 2) vector[column].setZ(vector[column].getZ() + rollMatrix.getMatrixElement(row, column));			}			vector[column].normalize();		}*/	}	public void pitchIncreaseOrDecrease(int switchValue){		if (switchValue==1) pitch=1;		else if (switchValue==-1) pitch=-1;		else pitch = 0;				pitchMatrix = axisAngleRotation.performRotationAroundAxis(pitch, vector[2]);				/*for (int column = 0; column < 3; column++){			for (int row = 0; row < 3; row++){				if (row == 0) vector[column].setX(vector[column].getX() + pitchMatrix.getMatrixElement(row, column));				if (row == 1) vector[column].setY(vector[column].getY() + pitchMatrix.getMatrixElement(row, column));				if (row == 2) vector[column].setZ(vector[column].getZ() + pitchMatrix.getMatrixElement(row, column));			}			vector[column].normalize();		}*/	}	public void yawIncreaseOrDecrease(boolean increaseIsTrue){//		if (increaseIsTrue) yaw++;//		else if (!increaseIsTrue) yaw--;		if (increaseIsTrue) yaw=1;		else if (!increaseIsTrue) yaw=-1;				yawMatrix = axisAngleRotation.performRotationAroundAxis(yaw, vector[1]);				/*for (int column = 0; column < 3; column++){			for (int row = 0; row < 3; row++){				if (row == 0) vector[column].setX(vector[column].getX() + yawMatrix.getMatrixElement(row, column));				if (row == 1) vector[column].setY(vector[column].getY() + yawMatrix.getMatrixElement(row, column));				if (row == 2) vector[column].setZ(vector[column].getZ() + yawMatrix.getMatrixElement(row, column));			}			vector[column].normalize();		}*/	}	//Processing-----/}