PDA

View Full Version : My first matrix

gimp
02-26-2001, 03:06 PM
I've tried to create a matrix class that is useful and that i can understand (as I can't quite grasp anyone else's classes).

My matrix class is only designed to be used by opengl commands so I probably won't need to know a lot to make it work.

I've done a lot of groundwork before posting and have read a lot of matrix articles. I'm stuck on one point though.

So far I have a camera and an object matrix. The way I understand this is that the object matrix represents a local coordinate system. It's translation moves the local coordinate system around in world space. (Mhen multiplied).

I rotate my object around the Z axis(roll) by 45deg then rotate around the Y axis 45 deg(yaw) then tell it to move down the Z axis X units. This seems to squish the object at the object remains on the z plane.

Here are some code samples to show what I'm doing:

inline void CMatrix::Yaw(const float a_Degrees)
{

m[0] = c;
m[2] = -s;
m[8] = s;
m[10] = c;
}
and

inline void CMatrix::Forward(const float a_Units)
{
m[12] = m[8] * a_Units + m[12];
m[13] = m[9] * a_Units + m[13];
m[14] = m[10] * a_Units + m[14];
m[15] = m[11] * a_Units + m[15];
}

inline void CMatrix::Roll(const float a_Degrees)
{

m[0] = c;
m[1] = s;
m[4] = -s;
m[5] = c;
}

and this is how I'd like to use my matrix:

glMatrixMode(GL_MODELVIEW);
CMatrix Camera = -Viewer;

glPushMatrix();
glMultMatrixf(Object1);
glColor3f(0,0,1);
glRotatef(180,0,1,0); //Glut cone is back to front
glutWireCone(0.5,1,10,6);
glPopMatrix();

Can anyone see where I'm going wrong?

I also have another problem with that code while it's up, I can't seem to work out how to rotate multiple times. How do I take the rotation I have, then 'add' another rotation to it. I assume I'll need to renormalise at some point. Do I renormalise all the 9 elements together or each vector seperatly?

Many, many thanks. (I really need to work this out.

Chris

[This message has been edited by gimp (edited 02-26-2001).]

Cardinal
02-26-2001, 08:18 PM
My best estimation is that you are not using correct translation matrixes. I don't understand where you got the whole:

inline void CMatrix::Forward(const float a_Units)
{
m[12] = m[8] * a_Units + m[12];
m[13] = m[9] * a_Units + m[13];
m[14] = m[10] * a_Units + m[14];
m[15] = m[11] * a_Units + m[15];
}

function from... all the translation matrixes I have seen are in the form:

1 0 0 0;
0 1 0 0;
0 0 1 0;
x y z 1;

so if you m[8]-m[11] are anything but 0's or 1's, you have some odd sort of matrix. Your code looks good as far as theory goes. If you want multiply translation/rotations/ect to affect you camera, you simply need to multiply your camera matrix by each in order.

Please note: that camera motion is inverse of percieved motion, meaning you need to translate/rotate it like a normal object, then invert it before passing it to glLoadMatrixf to get correct motion.

GL (goodluck)

Elixer
02-26-2001, 10:05 PM
Yeah, why are you using m[15]? Do a search on multmatrix on this board, and you will find a ~90 thread message that has all this stuff in it. Your modifying the wrong elements is your first problem. For rotations, after you have your rotation matrix made, you could use that again, or just rebuild one again. It depends what you want done.

Michael Steinberg
02-27-2001, 07:26 AM
Elixer, should we just run a faked discussion here?

Elixer
02-27-2001, 03:14 PM
LOL http://www.opengl.org/discussion_boards/ubb/smile.gif

It is too bad we can't "flag" certain messages that are helpfull to lots of people. Maybe the board operator can make a "FAQ" section, and then move all the helpfull messages to that area?

gimp
02-27-2001, 11:41 PM
I'm sorry I only partialy get what your talking about... Are you suggesting keeping this thread running so you don't see it appear again by a different person in a few days?

I have missed the point when it comes to m15, I have no idea as to what it's for. I think the 4th member of a vector normally has something to do with scaling... No idea with matricies.

I DID have a look for the 90 post thread, though the search engine doesn't show how many posts each topic has, does anyone know a word that would be in there other than 'matrix' ?

I've also been reading as much as I can relating to this subject though books I have like "3D Game Engine Design","Real time rendering","OpenGL(Red Book)","3D Graphics Programming" + a few other books all seem to jump from basics to advanced. I know how to invert(transpose?) a matrix but not move a local coordinate system.

My forward example was trying to simplfy my case, obviously a local transform can be handled just as easily(in fact Forward should probably reimplement a generic local transform)

A faq would be great that covers in detail the structure of a matrix, I've seen nothing on the net that does this. (Yes, I also have hexapods matrix & Quat faq)

I'd really love to learn this stuff, My curiosity has been awakened to all this cool math stuff I've been getting in to recently to the point where I'm thinking about finaly going to uni(after 10+ years since HS).

The reason I'm asking about this is I'm building a scene graph and want each object to store it's matrix so I can transform them quickly (ie a turret on a tank is easily positioned relative to the tank). I'd also like to be able to jump my camera between objects so at some point I'll probably need to learn how to apply projective transforms, but http://www.opengl.org/discussion_boards/ubb/smile.gif one step at a time huh?

I have found many Matrix Class example but non have a member function that does transform that are affected by local rotations. Am I missing something?

Many thanks

Chris

Can someone help me find that 90 post thread?

02-28-2001, 02:28 PM
Do search multmatrix. I find there.

DaViper
03-01-2001, 12:24 AM
try this for the old thread
http://www.opengl.org/discussion_boards/ubb/Forum2/HTML/002537.html

Punchey
03-01-2001, 09:42 AM
As far as:

inline void CMatrix::Forward(const float a_Units)
{
m[12] = m[8] * a_Units + m[12];
m[13] = m[9] * a_Units + m[13];
m[14] = m[10] * a_Units + m[14];
m[15] = m[11] * a_Units + m[15];
}

It makes perfect sense to me... why doesn't it make sense to anyone else? He's moving the center (local origin) of the matrix (12,13,14 but 15 I'm not so sure) in the direction of the "front" vector (8,9,10 and again I'm not sure about 11) multiplied by a certain distance. If he wanted to do the same only move it in the "up" direction, he'd do the same except instead of 8,9, and 10, he'd use 4,5, and 6. What's so wrong with that? I realize it may not be what most people do and is a bit unusual but it should work.

DaViper
03-02-2001, 01:37 AM

Punchey
03-02-2001, 06:28 AM
Yes, have you? I made several posts in it. Why do you ask?

DaViper
03-02-2001, 06:53 AM
Sorry Punchey, didn't mean to sound so harsh, i was just wondering if you wanted to restart the thread http://www.opengl.org/discussion_boards/ubb/wink.gif
btw i agree with your statemnt above it should work like that...

[This message has been edited by DaViper (edited 03-02-2001).]

Punchey
03-02-2001, 09:51 AM
Sorry. Yeah, I don't think that part is the problem because that should translate an object "forward" just fine. I think we might should not "restart" the ~90 post thread as such but rather consolodate all this info into a FAQ of sorts. Because it's VERY confusing to follow all the posts in that thread, IMHO. Alot of going back and forth. So I think people would probably get more confused than anything. In fact, that's what one of my posts to that thread was about. There was alot of bickering about the layout of the matrix. And some people just can't understand why others (less-mathematically minded people) might be confused by representing a matrix by writing it out like you would in a math book and then arguing about how OpenGL represents it. They don't understand how some people might read their representations a column at a time or a row at a time yielding different results. So, I suggest that whenever we're reffering to actual OpenGL use of matrices (not purely mathematical discussions) that we use actual array indeces or something more absolute that cannot be mistaken.

gimp
03-05-2001, 03:32 AM
Ok, I've read the ~90 posts, most of it was a waste of time, a small number came close to what I was after but never hit exactly what I was looking for (unless I'm mistaken). I've spent the last week downloading every simple looking matrix class I can find to find one that work that I can disect to see how it works.

What I found :
-Most libraries don't include rotate\translate functions as its 'based on implementation'
-Those that do have working copies require other files that arn't supplied
-Some seem incomprehensible as they support order of M*N matricies and are generally written as templates
-Other like David Eberly's are hard to get going without including half his core library then still don't supply the functions I'm looking for.
-Nate Miller had a simple class but when rotating objects them moving them I get squashed object's... H hasn't replied to my mail in 4 days.
-glvelocity had 3 classes, none of which I can get working...

Following is a hunk of code that I'm trying to get working as a basic test, once that works I can start picking the code apart to find out how it works (my usual method of learning)

#include "Matrix.h"
#include <GL/glut.h>

CMatrix Object1;
CMatrix Object2;

void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);

//Pull camera back
Object2.Identity();
Object2.Transform(0,0,6);

//Start object at origin
Object1.Identity();
Object1.RotateY(45);
Object1.Transform(0,0,-2);
Object1.RotateZ(45);
Object1.Transform(0,0,-2);

}

void display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f (1.0, 1.0, 1.0);

//Camera
glMatrixMode(GL_MODELVIEW);
matrix Camera;
Camera = !Object2;

//Objects
glPushMatrix();
glMultMatrixf(Object1.m_mat);
glColor3f(0,0,1);
glRotatef(180,0,1,0); //Glut cone is back to front
glutWireCone(0.5,1,10,6);
glPopMatrix();

glutSwapBuffers();
}

void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 1000.0);
glMatrixMode(GL_MODELVIEW);
}

void keyboard (unsigned char key, int x, int y)
{
switch (key)
{
case 27:
exit(0);
break;
default:
break;
}
}

int main(int argc, char** argv)
{
glutInit(&amp;argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);

glutMainLoop();
return 0;
}

As you can see it's just a simple little glut app to show what the transforms do. My own class which has evolved a little since the original question seems to fail when doing anything but a single rotation. Once I rotate twice in different directions the glutCone starts getting distorted.

As an example is anyone able to provide a simple matrix class that would work something along these lines? If need be I can post my matrix class for you all to pick apart if thats easier (or just the bits that are related to the problem

Many thanks, I'm getting quite desperate

Chris
(I can't side step this problem my scenegraph depends on me storing transforms. In the meanwhile I bought a few schaum's books on trig and linear algebra, but it's slow going learning all that for such a specific problem)

DaViper
03-05-2001, 03:46 AM
I'm not sure i understand why you want to create your own matrix manipulation class and not just use the opengl transformation glTranslate and glRotate...... http://www.opengl.org/discussion_boards/ubb/confused.gif

[This message has been edited by DaViper (edited 03-05-2001).]

Gavin
03-05-2001, 03:50 AM
Well I was wondering that but for instance I have an app that returns a transformation/rotation/scale matrix and I use matrix mult as I assumed that opengl would be more efficient at doing this rather than me extract the necessary rotations etc and then use glrotate etc?

gav

DaViper
03-05-2001, 04:42 AM
well Red Book says under OpenGL Performance Tips

Use specific matrix calls such as glRotate*(), glTranslate*(), and glScale*(), rather than composing your own rotation, translation, and scale matrices and calling glMultMatrix().

harsman
03-05-2001, 05:13 AM
First of all your method "Transform" actually translates right? Translation moves the origin, transformation multiplies by a transformation matrix and includes both translation and rotation (it might include scaling and shearing as well, but that is generally bad for various reasons). Try using the gl commands for translation and rotation and see if the problem persists (remember that you're supposed to invert the camera transform though). If it goes away you can blame your matrix code.

Elixer
03-05-2001, 08:53 AM
Do this:
struct {
VECTOR right;
float t1;
VECTOR up;
float t2;
VECTOR dir;
float t3;
VECTOR pos;
float t4;}

Now, VECTOR has 3 elements, x,y,z or v[0],v[1],v[2] whatever you pick is fine.
Now, to do transforms, you modify the pos vector. To do rotations, you modify the other vectors. The t1-t4 are basically there for fillers, and are 99.9% of the time not used.
So take the 3x3 matrix (made up of right,up, and dir) and do rotations on that. I don't have time right now, but you should be able to figure out how, or if you want, post you matrix class, and when I get back, I can have a look.

Note, you can also union that struct to m[16], so you can also access the same elements via array calls if you want.

Oh also, the glvelocity matrix code does work, I have used it. What is it not doing for you? Also remember that if you are using a "camera", everything it sees is a ~mirror image of what is happening.

gimp
03-05-2001, 02:34 PM
I was under the impression that the majority of professional coders did it this way. (ie retain the matrix , do the rotations themselveves then just plugged the value in when they neded to transform an object.

Yes that used to say translate, this hunk of code has been hacked to peices, the last matrix class I tried called 'translate' 'transform' and as I was only testing I decided to just use their code to see if it worked.

Camera = !Object2;

In this line I was taking the inverse of the matrix. I have no problem understanding this peice of code. This is set to ! to denote inverse by the last matrix class I tried to get working. (I can't remeber but it might have been a glvelocity class (nick carpens from my bad memory.

I could just use a 3*4 array to represent the three rotations + position but except for the 4 redundant members isn't that exactly the same? A matrix vs individual rot\trans I mean. Loading the matrix or calling multmatrix make the client code much easier to understand.

Why havent I just used individual rotations? Well I was, and when I rotated a few times I realised that all three local axis will need to be recalculated(well 2 out of 3) for each rotation, and to me this kind of seem just what a matrix does.

To me doing the individual ones is the same thing but just not calling it a matrix.

Second, I wanted to be able to easily move my camera to an objects matrix(ie take control of another vehicle). Copying the matrix to the camera seems very easy...

I had the same problem with my old CMovement class, turn up to the left and move forward 5 units...

Many thanks to all

Chris

PS : I'll take another shot at the matrix class on glvelocity tonight and return the code that doesn't work for me.

gimp
03-06-2001, 03:25 AM
Ok, I thought it might b more educational if I presented my matrix class + a test program that demonstartes the 'object squashing' problem I'm having.

I put together a fairly minimal workspace with pretty much the test app above + my matrix class (+my supporting math class).

The simple test draws a cone and just rotates it twice along different axis to squash the cone, x,y axis(plural?) seems most affected.

Code is here-

http:\\members.pnc.com.au\~gimp\GraphicsLibrary Test.zip

7Kb zipped, including workspace

The sample code should compile and show the problem without any problems.

Chris

Elixer
03-06-2001, 08:37 PM
This is wrong and should not be in your inline void CMatrix::Forward(const float a_Units) call:
m[15] = m[11] * a_Units + m[15];

Your inverse routine looks long. (it may be wrong, dunno really, don't have much time to look in detail. (heh) )
I have no idea why you are doing all that, for a simple thing like inverse. Just copy matrix to a temp matrix, transpose the temp, then reassign the primary, and negate the position like this...
m[12] *= -1.0f;
m[13] *= -1.0f;
m[14] *= -1.0f;
...

The other routines look wrong also. For example your roll is using 0,1,4,5?? Why? If you roll about z axis, then it should use 8,9,10.

Again, this is a very quick look, since I am pressed for time. But they do look wrong, unless your doing something I am not seeing right away.

Elixer
03-06-2001, 08:44 PM
Forgot to mention, you should add what it should look like to the right/left of the object you are modifying, using glrotate/translate calls, so it would be easier to compare.

Gavin
03-07-2001, 12:29 AM
Viper...

posted 03-05-2001 05:42 AM *** **** **
------------------------------------------------------------------------
well Red Book says under OpenGL Performance Tips

quote:
------------------------------------------------------------------------
Use specific matrix calls such as glRotate*(), glTranslate*(), and glScale*(), rather than composing your own rotation, translation, and scale matrices and calling glMultMatrix().
----------------------------------------------

I know that they are faster than the actual multmatrix call but...... That assumes that you have the rotations, translations, scales etc already. In my case I had it all in a matrix and so would have to preprocess the matrix (in the same way as matrix mult I assume) to extract these values before sending them to glrotate etc. I though matrix mult's extraction process would be quicker than mine, and it saves a bit of coding! :-)

gav

DaViper
03-07-2001, 07:04 AM
Gavin:
hmm you might have a point there, I never tested it.

Deiussum
03-07-2001, 09:26 AM
I could be wrong about this, but I think that the Red Book is saying that the process of composing your own matrix AS WELL AS glMultMatrix would be slower than using the glScale/glRotate/glTranslate calls individually. I wouldn't imagine that glMultMatrix itself would be that much slower since it just does a single matrix multiplication. Each of the glScale/glRotate/glTranslate also do a matrix multiplication. So... if you already have a matrix, I'd guess that using glMultMatrix would probably give you better performance.