Matrices....

Ok, I have an app which draws a square 50px x 50px, However, I don’t understand how it achieves this. App = 500x500px

glLoadIdentity();
glTranslatef(-1.5f,0.0f,-6.0f);

glVertex3f(-1.0f, 1.0f, 0.0f);

//So each 1.0f represents a unit 1/10 of the window size. Where was this set?

//And why, is the Z arg in glTranslate = -6??

Any help would really be appreciated, im trying to understand the basics of this app, this isn’t for homework or anything…
Here is the code in case you need a reference:

/*
When creating your project, uncheck OWL,
uncheck Class Library, select Static
instead of Dynamic and change the target
model to Console from GUI.
Also link glut.lib to your project once its done.
*/
#include “Stdafx.h”
#include <windows.h> // Standard Header For Most Programs
#include <gl/gl.h> // The GL Header File
#include <gl/glut.h> // The GL Utility Toolkit (Glut) Header

void init ( GLvoid ) // Create Some Everyday Functions
{

glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glEnable ( GL_COLOR_MATERIAL );
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}

void display ( void ) // Create The Display Function
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glBegin(GL_TRIANGLES); // Drawing Using Triangles
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glEnd(); // Finished Drawing The Triangle
glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units
glBegin(GL_QUADS); // Draw A Quad
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd();

glutSwapBuffers ( );
// Swap The Buffers To Not Be Left With A Clear Screen
}

void reshape ( int w, int h ) // Create The Reshape Function (the viewport)
{
glViewport ( 0, 0, w, h );
glMatrixMode ( GL_PROJECTION ); // Select The Projection Matrix
glLoadIdentity ( ); // Reset The Projection Matrix
if ( h==0 ) // Calculate The Aspect Ratio Of The Window
gluPerspective ( 80, ( float ) w, 1.0, 5000.0 );
else
gluPerspective ( 80, ( float ) w / ( float ) h, 1.0, 5000.0 );
glMatrixMode ( GL_MODELVIEW ); // Select The Model View Matrix
glLoadIdentity ( ); // Reset The Model View Matrix
}

void keyboard ( unsigned char key, int x, int y ) // Create Keyboard Function
{
switch ( key ) {
case 27: // When Escape Is Pressed…
exit ( 0 ); // Exit The Program
break; // Ready For Next Case
default: // Now Wrap It Up
break;
}
}

void arrow_keys ( int a_keys, int x, int y ) // Create Special Function (required for arrow keys)
{
switch ( a_keys ) {
case GLUT_KEY_UP: // When Up Arrow Is Pressed…
glutFullScreen ( ); // Go Into Full Screen Mode
break;
case GLUT_KEY_DOWN: // When Down Arrow Is Pressed…
glutReshapeWindow ( 500, 500 ); // Go Into A 500 By 500 Window
break;
default:
break;
}
}

void main ( int argc, char** argv ) // Create Main Function For Bringing It All Together
{
glutInit ( &argc, argv ); // Erm Just Write It =)
init ();
glutInitDisplayMode ( GLUT_RGB | GLUT_DOUBLE ); // Display Mode
glutInitWindowSize ( 500, 500 ); // If glutFullScreen wasn’t called this is the window size
glutCreateWindow ( “NeHe’s OpenGL Framework” ); // Window Title (argv[0] for current directory as title)
glutFullScreen ( ); // Put Into Full Screen
glutDisplayFunc ( display ); // Matching Earlier Functions To Their Counterparts
glutReshapeFunc ( reshape );
glutKeyboardFunc ( keyboard );
glutSpecialFunc ( arrow_keys );
glutMainLoop ( ); // Initialize The Main Loop

}

//So each 1.0f represents a unit 1/10 of the window size. Where was this set?

The fact that 1.0f ended up being a square 1/10 the size of the window is just a coincidence based on the values you gave to:
gluPerspective
glViewport
glTranslate
and glVertex.

Watch - change the glTranslate to… say… (-1.5f, 0.0f, -3000.0f) and it won’t be 1/10 of the size.

The big thing to wrap your head around is what gluPerspective does (it took me a while, just starting out myself). gluPerspective(80, w/h, 1, 5000) is saying this:
You want to see everything that would end up within 80 degrees of eye level within a box shaped like your window that is between 1 and 5000 units away from your eye. It should look like real-life, where things look smaller the farther they are.
This leads into your second question:

//And why, is the Z arg in glTranslate = -6??
-6 is fairly arbitrary. The items have to be somewhere, so -6 seemed good. Do keep in mind my above note that if it were at 0 or -6000, you couldn’t see the items, since you told gluPerspective not to show you anything that close/far away. And since things farther away seem smaller, if you put the item farther away by setting z to -1000, it’ll look smaller. Set z to -2 and it’ll look bigger.

The real story of what’s going on is of course a bit more complicated, but we’ll pick that up as we learn more…

Anyone sees any major blunders in my explanation, chime in.

a

Hi… I still don’t understand. I am still only drawing a 1x1 square, how does this end up being 50px? There must be some mathmatical way to show how it ends up being this number.

So if it only shows me stuff between 1 & 5000, then -4999 would be ok?

What do you mean by ‘within 80 degrees of eyelevel’ ?

Ok Basically I have poured through the code really thoroughly for the past hour, and still have some questions. There is alot here I know, but I am really excited about this, and it would be really swell if someone could decipher my confusion…

Firstly with regards to the unsolved problem above. The reason I do not understand how the image drawn is 50px wide. Is because the args for width & height in glVertex are only 1.0f. I take this to mean either 1.0 pixels or 1.0 units. Which one? And how does this displayed image end up being 50 pixels wide, e.g what perspective, matrix or transformation achieves this?

Ok so now thats covered heres a few other things I don’t quite understand.

GL_COLOR_MATERIAL : what does this achieve exactly, in layman’s terms?

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
:::Apparently this runs a bit wise OR [is that just the term for an OR operation?] on these 2 args. So i take it, it only clears one of these buffers, how does it know which one to clear?

Ok I have a reshape function set in glutReshapeFunc(). This function is specified below.

Firstly: Does glLoadIdentiy() set the current matrix to the matrix specified in the last glMatrixMode call?

So is the resulting matrix of this function the product of the (GL_PROJECTION) & gluPerspective() , or is it just gluPerspective() ?

I read that, gluPerspective multiplies the current matrix by its own matrix, but if you want to set the new matrix to the gluPerspective matrix by itself (without multiplying with old one) you call glLoadIdentity() before.

void reshape ( int w, int h ) {

glMatrixMode ( GL_PROJECTION );
glLoadIdentity ( );

//if fullscreen

gluPerspective ( 80, ( float ) w, 1.0, 5000.0 ); // fs

//if window

gluPerspective ( 80, ( float ) w / ( float ) h, 1.0, 5000.0 );
glMatrixMode ( GL_MODELVIEW );
glLoadIdentity ( );

}

And finally, why use MODELVIEW in window & Perspective in fullscreen?

================

I’ll try to address each of your questions on its own. There is some overlapping, so be patient if I repeat myself though.

  1. How does 1.0f end up being 50 pixels?
    (NB: the numbers sent to glVertex, glTranslate, glPerspective, et al. are ‘units’. You can think of them as anything you like: inches, meters, furlongs, AUs, whatever. What they are is not important. It’s their relative sizes that matter.)
    With the calls to glVertex, you give it four coplanar vertices, so you are drawing a square. glTranslate(-1.5, 0.0, -6.0) moves this square 1.5 units left and 6 units away from the ‘camera’. glPerspective tells OGL to set things up so you are seeing a perspective view of things within a certain box. glViewport tells it to show this so it looks right in your window. So it ends up being 50 pixels because a square 1 ‘unit’ big, 6 ‘units’ away in a window your size ends up being 50 pixels because that’s how big it should look to match those values. It’s basically the same question as “Why does a car that’s 5 feet high by 7 feet long look two inches tall when I stand thirty feet away? That’s just how long it looks based on its size and distance.”

  2. Is -4999 ok?
    It should be. Your square will be so far away it probably won’t even show up, but it should be there.

  3. What did I mean by within 80 degrees of eye level?
    Imagine you’re looking at a point in space. You can see a certain amount above and below the point you’re looking at (unless you have serious vision problems ;). How much above and below you can see can be measured by the angle it forms with the straight line from your eye. So 80 degrees up and 80 degrees down is ‘within 80 degrees of eye level’.

  4. GL_COLOR_MATERIAL
    This stores the characteristics (color and what aspect: specular, diffuse, etc.) of a material and applies it to all vertices you define after you make it. You can change what it’s storing with glColorMaterial. You gotta understand state machines and read about material properties to really get this one.

  5. glClear(…)
    Yes, it does a bitwise OR. Read about bitmasks to learn more, but the short answer it its clears both the color buffer and depth buffer. If you want to think about it another way, it clears a buffer if the buffer is the color buffer OR the depth buffer.

  6. glLoadIdentity
    glLoadIdentity sets the current matrix (whatever you last put in glMatrixMode) to the identity matrix (1 on the main diagonal). That is all it does. Brush up on matrix algebra, you’ll need it!

  7. your code snippet
    The reason you do glMatrixMode(GL_PROJECTION); glLoadIdentity; is to work on the projection matrix and clean it up just in case there’s something funky in it (you never know). Then you set a projection based on your window, then switch back to GL_MODELVIEW mode because if you don’t, your images will be really really messed up. Remember that if/else only works until the end of the block or for one statement if there is no block. So glMatrixMode(GL_MODELVIEW) is not in the if/else and gets done no matter what.

Some of that probably didn’t make sense but ask again if you need clarification on anything.

a

ok first of all, thanks a lot for the post, its really helpful. and its great to know other people are willing to help me out when i get stupified.

  1. -4999… Cool

  2. So 80 degrees seems pretty big in this case. I mean if I look at a point ahead of me, depending on its distance from me, I’d summise i can only see about 30 degrees above it. I don’t quite see how this effects the scaling of objects e.t.c, but I’d imagine for most apps, 80 is pretty common?

  3. yep i dont understand materials yet, but will use this answer as a reference when i do.

  4. got it, cool.

  5. I thought the only types of matrixes were : modelview, projection & TEXTURE?

  6. There is no block in my code. ok wow i never knew that!!! that makes more sense, even though i do not understand the difference between matrices yet.

  7. This is the main thing i still don’t get so hence its position in the list.

How do we know how many units will span the window size? Surely there must be a way to figure out how big a 1 unit object will appear, mathmatically through the values given in perspective & translate e.t.c?

If we use gluOrth, then we cant have a depth factor in our elements, this is correct? So therefore the values in vertex() e.t.c represent pixels in that scenario…?

It frustrates me, that just because I want a depth dimension in my program, I can’t determine exactly how big I want a element to be, instead i have to estimate? I would have thought that for each unit fruther away (3rd arg)an object is, there would be a formula to figure out how much smaller it will be drawn…

if there is no way to determine precisely how big an object will be drawn, then it seems like a really redundant method of drawing…

I’ve tried throwing in a positive float for the 3rd arg, in translate, and it doesn’t draw, im assuming this is because of :


glClearDepth(1.0f); 
glEnable(GL_DEPTH_TEST); 
glDepthFunc(GL_LEQUAL); 

ALso i noticed that the original origin of drawing is in the center of the window, is this always the case when using gluPerspective?

Also, how become the shapes are solid blocks of color, i would ahve thought them to be just the lines?

wow thats a lot of incomprehension for the 2nd nehe tutorial lol :stuck_out_tongue:

You’re welcome. I’m just learning OpenGL myself and I’m hoping to build up some karma for when I have questions…

  1. 80 degrees does seem big. In fact, I think this overlaps question 1 - I think if you lowered it to 30 degrees the square would be bigger. Can’t confirm this at the moment since I’m not on my usual computer. The stuff I’ve seen says that these type of settings are the kind you experiment with and won’t really be able to predict how it will look until you’ve had lots (and lots)of practice. The way it effects scaling is: imagine a fisheye lens, where you have a higher field of vision. Things look smaller than if you looked at them normally. This is because things take up a smaller proportion of your vision so your brain translates this to looking smaller.

  2. Those are the only matrix modes in OpenGL. Identity matrix is not a type of matrix, just a nickname for the matrix that looks like:
    1 0 0 0
    0 1 0 0
    0 0 1 0
    0 0 0 1
    which in matrix algebra means that it does not modify any points or vectors multiplied by it. So if the matrix stack has the identity matrix on top, vertices you add will be exactly where you say.

  3. Well, there is a way to determine how big something will look mathematically like you want. Look at the actual matrix generated by gluPerspective. Do you want to do that math yourself to find out where things are? If so, you’re braver than I. Again, this is a get-lots-of-practice-and-you-'ll-be-able-to-predict-better thing.

Other:
Well, glOrtho does have a depth element. It just does not do the perspective trick so things don’t get smaller with distance. So for instance:
If you use glOrtho(-2.0, 2.0, -2.0, 2.0, 0.0, 2.0); (Set up a 4 wide by 4 high by 2 deep box) and draw a 1.0 by 1.0 square within those boundaries and use a 400x400 window, I think (again, can’t confirm this at the moment) it will look 100 pixels by 100 pixels.

The positive third point in glTranslate made the square move behind your viewpoint, that’s why you couldn’t see it. It was outside the volume you told gluPerspective to show (which must be in front of the viewpoint for one thing). Depth test has to do with drawing two objects that overlap each other but are at different depths. It makes sure the closer one is drawn so that it obscures the parts of the farther one that it should.

The origin:
When you start OpenGL stuff, the origin is at the center of the screen. Unless you move it with glTranslate, it’ll stay there. (NB: gluLookAt does move it like glTranslate)

Solid polys:
OGL defaults to filled polygon mode. If you want lines, use glStart(GL_LINE_LOOP) or glPolygonMode(<whatever>, GL_LINE);

Yeah, I looked at the NeHe tutorials and though they moved kinda fast. I used the red book and understood that a bit better myself.

Aaron

Thanks Aaron, sorry was a bit slow responding, I have exams ATM. This is very informative thank you, I definitely understand things better, will continue with the NeHe tutorials as best I can see, and maybe I will have a better grasp of things after the 3D tutorial.

It feels good to know now that its all about guess work and experience rather than me just not seeing the links [with regards to depth].

I think once I understand how the other matrices manipulate verticies I will feel alot better, will go read a whole llist of tutorials on matrices that I have stored away.

Thanks mate, ttyl.