ModelView Matrix question

Started by
8 comments, last by Kalidor 18 years, 6 months ago
Alright, I am having a little trouble with my model view matrix stuff. I am trying to implement frustum culling, and it is scaling that is throwing off my culling. What I am doing is basically reading in vertex data, finding the largest possible radius, and then when it comes time to draw, scale the radius by the largest scaling factor, so that the radius covers the widest possible area. Now, here is basically what I have set up:

glPushMatrix()
   glScalef(0.01, 0.01, 0.01)

   float m[16];
   glGetFloatv(GL_MODELVIEW_MATRIX, m);
   cout << "scale x, y, z: " << m[0] << ", " << m[5] << ", " << m[10] << endl;
   
   glPushMatrix()
      glScalef(100.0, 100.0, 100.0);
      glRotate( ... );
      glTranslate( ... );

      float m2[16];
      glGetFloatv(GL_MODELVIEW_MATRIX, m2);
      cout << "scale x, y, z: " << m2[0] << ", " << m2[5] << ", " << m2[10] << endl;
   glPopMatrix();
glPopMatrix();      

That is almost exactly how my code breaks down. Now, I would expect the first values to spit out 0.01, 0.01, 0.01 -- instead, I get some pretty whack stuff. And the second, I expected 1.0, 1.0, 1.0. What is the deal? Any thoughts? Thanks!
Advertisement
This probably seems obvious, but is your modelview matrix set to identity prior to scaling?
the rug - funpowered.com
Well if you're doing stuff to the view matrix as well (ie, gluLookAt or similar) it's going to affect the values in the modelview matrix (since they're one and the same).

But yeah, its clearly a case of there already being data in the modelview matrix. Calling glLoadIdentity() before your tests should make it yield the expected results, and prove that this existing data that its being multiplied with is the villian.

EDIT: I need to learn to type faster :(
Also that glRotate after the second scale will probably be altering at least two of the diagonals of the matrix, so that will also affect the second outcome.
Herm, okay. Well, I am trying to achieve scene graph like relativity. So I am trying to make the second draw be influenced by the scale of the first draw (hence why I expec the second one to display "1").

I did just realize that gluLookAt changes the model view, so is there a way to "unproject" if I retrieve the projection matrix to find just the scale and x,y,z values without the projected...shit? Thanks.

Thanks.
Quote:Original post by visage
Herm, okay. Well, I am trying to achieve scene graph like relativity. So I am trying to make the second draw be influenced by the scale of the first draw (hence why I expec the second one to display "1").
Assuming the modelview matrix (or at least the top-left 3x3 part of it) was set to identity before you first scale it, and without the glRotate call in there, then you are right expect to see 1 (or very close to 1 because of floating-point precision issues). What I meant was that rotating and scaling affect the same part of the matrix, so if you are rotating after the second scale it will most likely alter the diagonal's of the matrix so that you won't get 1 for all of them.
Quote:Original post by visage
I did just realize that gluLookAt changes the model view, so is there a way to "unproject" if I retrieve the projection matrix to find just the scale and x,y,z values without the projected...shit? Thanks.
To be more specific, gluLookAt changes whichever the current matrix is. It is meant to be used on the modelview matrix though. It's probably not possible to get the overall "scaling value" of a matrix that has arbitrary transformations applied to it (such as while recursing down a scenegraph). If you need the specific scaling information then perhaps you should store each node's transformation as rotation, scale, and translation instead of in one matrix, just remember that order of operations matters for matrix multiplication though, so when it comes time to get the transform matrix you must consistently apply them in the same order.

What are you trying to do, if you don't mind my asking? You usually don't need to know just scaling information for some random node in a scenegraph. We may be able to recommend a better way of going about it.
I am trying to perform frustum culling. I have "GeometryNode"s and "Geometry" classes. Geometry defines the actual vertices, et cetera, while GeometryNode draws. So the Geometry class has everything relative to origin 0,0,0, and maintains the largest possible radius value for a bounding sphere. Now, when I go to draw, the object has been scaled, rotated, and translated. I want to basically take the information from the ModelView matrix and remove the x,y,z location where the object is being drawn and at what size. I then take the maximum scaling value and multiply it by the radius, so that the radius is proportional to the size of how it is being drawn. I then pass the x,y,z and radius to the culling method. All transformations are applied prior to drawing in an external method, by looping through Transformation derived classes and simply calling "performTransformation()" -- so it would be tough to extract specific transformation information without RTTI or something like that.

The more that I think about it though, would I necessarily want the specific scale value?

Ideas? Thanks.
edit: I'm really not sure if this is right or not, maybe someone can clarify? [grin]

Couldn't you get the scaling factors for x,y and z by getting the magnitudes of the vectors (m[0], m[1], m[2]), (m[4], m[5], m[6]), and (m[8], m[9], m[10]) respectively?

[Edited by - The Rug on October 7, 2005 3:24:47 PM]
the rug - funpowered.com
There is an article on gamedev called 'Matrix math demystified'. I read it quickly, but something that 'The Rug' wrote made me recall it. It might be relevant, although I'm not sure what you're exactly trying to do. It sounds like you want to apply transformations for all of your objects to the modelview matrix, and then extract information about how large your viewing volume should be(?)
Quote:Original post by visage
I am trying to perform frustum culling. I have "GeometryNode"s and "Geometry" classes. Geometry defines the actual vertices, et cetera, while GeometryNode draws. So the Geometry class has everything relative to origin 0,0,0, and maintains the largest possible radius value for a bounding sphere. Now, when I go to draw, the object has been scaled, rotated, and translated. I want to basically take the information from the ModelView matrix and remove the x,y,z location where the object is being drawn and at what size. I then take the maximum scaling value and multiply it by the radius, so that the radius is proportional to the size of how it is being drawn. I then pass the x,y,z and radius to the culling method. All transformations are applied prior to drawing in an external method, by looping through Transformation derived classes and simply calling "performTransformation()" -- so it would be tough to extract specific transformation information without RTTI or something like that.

The more that I think about it though, would I necessarily want the specific scale value?

Ideas? Thanks.
Ah sorry, you did say what it was for in the opening post but I forgot.

Anyway, I think the best way would be to just transform your bounding volume by the same matrix you use to transform your geometry. Say for a bounding sphere, you multiply the center by the matrix (duh) to get the transformed center and to get the transformed radius you could multiply any vector with magnitude=radius [ie: (radius, 0, 0)] by the matrix and then the magnitude of the resulting vector will be the transformed radius. There might be a better way (if there is hopefully someone will post it) but I think that is the simplest.

Hope that helps and good luck.

This topic is closed to new replies.

Advertisement