Jump to content
  • Advertisement
Sign in to follow this  
openglJunkie

OpenGL What I learned about OpenGL Matrices! Updated

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Please comment and tell me how informative this is.
Updates
- Render() Description Updated - Better layout. - Information updated. Paragraphs rephrased and code re-commented. - Description of gluLookAt() updated Last Updated November 30, 2008.
Introduction
The information was given to me about matrices, but it took some trial and error to actually understand what was going on with them. Hopefully the information I provide will give you a clearer insight to having a basic understanding of OpenGL matrices and help you understand the order in which code is placed.

Setting Up The Drawing Area

How do we tell OpenGL what we want to draw and where we want to draw it? We use OpenGL's matrices. There are two main matrices that will be used, GL_PROJECTION and GL_MODELVIEW. First is the GL_PROJECTION matrix, which allows you to alter the drawing area of the window. You have two options here depending on how you want your models to be displayed: Orthographic: Orthographic projection is used for drawing 2D scenes or GUI's.
{
glMatrixMode(GL_PROJECTION);
// Tell OpenGL we want to change how we view things.   
     
glLoadIdentity();
// Clear the matrix in case any previous transformations, etc were made and
// not cleared.
// *** This also sets the max coordinates of the window to be (-1, 1, -1, 1),
// therefore, using the values in gluOrtho2D below is redundant.

glViewport(0,0,windowWidth, windowHeight);
// Tells OpenGL the "box" area where stuff will be drawn in the window.
// Since we want to draw to the entire window, the window's width and height
// were passed.

gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
// This tells OpenGL the maximum coordinates to use in the (negative and
// positive) x and y axis.
}





Perspective: Perspective projection has more of a realistic feel to it. The further objects are in the zAxis, the smaller they get.
{
glMatrixMode(GL_PROJECTION);
// We're still modifying the PROJECTION matrix, despite were adding perspective.
glLoadIdentity();

glViewport(0, 0, w, h);
// This remains the same because we want to render to the entire window.

gluPerspective(45.0f, (windowWidth/windowHeight), 1.0f, 100.0f);
//   This function sets up a view and tells OpenGL as objects move further away,
// to make them smaller.
//   The first parameter is the Field of View.  It gives the angle in the y
// axis that determines how much you can see.  Humans have almost a 180* fov,
// but don't do it here because it just works differently.
//   I don't have a full understanding of it, but download OpenGL Tutor
// by Nate Robins here:
//
// http://files.filefront.com/GL+Tutorrar/;12504017;/fileinfo.html
//
//   After downloading OpenGL Tutor, run the tutorial Projection.exe and
// change the Field of View to 180 and observer what happens.  You have to
// click on the text and drag up or down to change the values.
//
//   The second parameter is the aspect ratio.  It's obtained by dividing
// the windowWidth/windowHeight, generally, and should come out to be near 1.0
// You can specify other values and it will squash or stretch your objects as
// if they were looking in a funny mirror at a circus, but it only affects
// them horizontally making them look more bloated or narrow.
//
//   The last two parameters specify the zNear and zFar, which tells the range
// at which objects are visible.  zNear should never be set to zero.
}


Positioning The Camera

Now that you have your drawing area set up, you need to position your camera so that you can see your objects. NOTE: You can move your objects first and then adjust your camera instead.
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

gluLookAt(
//    X     Y    Z
     0.0, 0.0, 2.0,  // Eye Coordinates
     0.0, 0.0, 0.0,  // Center Coordinates
     0.0, 1.0, 0.0); // Up/Down?
}


This first part is very important: Notice how gluLookAt() is placed after the GL_MODELVIEW matrix and NOT the GL_PROJECTION matrix. This is because the PROJECTION matrix is only used when setting up the area of your drawing window or adding perspective. Under very certain circumstances it is possible to store the location of the camera under the PROJECTION matrix, such as if you plan on only using it for rasterization. The golden rule when using the PROJECTION matrix is to make calls only to glLoadIdentity(), glPerspective/gluFrustum/gluOrtho/gluOrtho2D. Eye Coordinates - These tell OpenGL how far (in and out) you are on a given axis. In this case we are zoomed out 2 units because the positive zAxis is towards you and the negative zAxis goes inside the computer unless you flip it. Center Coordinates - These tell OpenGL where on your defined coordinate system where the camera will be centered on. In this case the camera faces the origin at (0,0,0). Up/Down? - These values tell whether the camera should be facing up or down on the given axis. A value of zero or greater means up, while less than zero means negative.

Rendering

Finally you can begin drawing. This is done by using the MODELVIEW matrix, which tells OpenGL that any transformations you make will apply directly to the model.
void render()
{
glClear(GL_COLOR_BUFFER_BITS|GL_DEPTH_BUFFER_BITS);
//  You should know what this means.  If not, visit:
//  http://www.zeuscmd.com/tutorials/opengl/index.php

glMatrixMode(GL_MODELVIEW);
//  Tell OpenGL we want to modify the objects that we draw.  Not the camera.

glLoadIdentity();
//  Clears any previous transformations applied.

// Draw a triangle
glColor3f(0.0f, 0.0f, 1.0f);
glBegin(GL_TRIANGLES);
     glVertex3f(0.0f, 0.5f, 0.0f);
     glVertex3f(0.5f, 0.0f, 0.0f);
     glVertex3f(-0.5f, 0.0f, 0.0f);
glEnd();

// Draw a cube
glColor3f(0.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
	glVertex3f(0.0f, 0.0f, 0.0f);
	glVertex3f(0.5f, 0.0f, 0.0f);
	glVertex3f(0.5f, 0.5f, 0.0f);
	glVertex3f(0.0f, 0.5f, 0.0f);
glEnd();
}







This was a simple introduction to the display or rendering function. Note that in this example no transformations were made. This was because OpenGL is a state machine and any transformation you would have applied would have remained in effect unless if we had a way to tell it otherwise. So how do we do this? You could have made a transformation to the triangle and then made a call to glLoadIdentity() after it was drawn. However, if you wanted to save the previous transformation so the next one would be relative to the first, then you need to use glPushMatrix() and glPopMatrix(), which "save and restore" the matrix respectively. PushMatrix and PopMatrix
void render()
{
glClear(GL_COLOR_BUFFER_BITS|GL_DEPTH_BUFFER_BITS);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// Draw a Planet
glTranslatef(0.0, 0.0, -1000.0); // Move the planet really far away.
DrawPlanet();

// Draw a Moon, which Orbits the above Planet
glPushMatrix();  // The above translation was stored.

glTranslatef(5.0, 0.0, 0.0);
// Move the moon 5 units on the x axis relative to the Planet. Because we stored
// the previous translation it will be relative to that location.
DrawMoon();

glPopMatrix();
// Return back to the center of the universe or spaceship or wherever
// you originated from in your 3D universe.
}





You should note that every call to glPushMatrix() requires a call to glPopMatrix! With that being said, you should know there is a limit to how many times you can use this feature. For the PROJECTION and TEXTURE matrix, there is a cap of two matrices that you can Push or Pop. This shouldn't really be an issue, though, which may be why they left it so small. Also, for the PROJECTION matrix the minimum according to SGI, the people who created OpenGL, is 32. These numbers vary depending on which graphics card you're using and some may be more and some may be less. You may want to stick with 32 (supposedly more than enough) or you can call an OpenGL function which can return the maximum for you, though, I think it's not advised. Sources of Information, although, not directly cited: http://sjbaker.org/steve/omniv/projection_abuse.html http://www.zeuscmd.com/tutorials/opengl/index.php http://videotutorialsrock.com/ http://www.sjbaker.org/steve/omniv/matrices_can_be_your_friends.html http://www.gamedev.net/community/forums/topic.asp?topic_id=82596 If there any errors, I apologize, correct them and I will update this. [Edited by - openglJunkie on November 30, 2008 1:05:36 PM]

Share this post


Link to post
Share on other sites
Advertisement
Nicely clarified =D . Detailed and easy to follow.

I've already figured this stuff out for myself, but if I had this post at the time it would have made things much easier.

Share this post


Link to post
Share on other sites
Original post by openglJunkie

void render()
{
glClear(GL_COLOR_BUFFER_BITS|GL_DEPTH_BUFFER_BITS);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

/*
This might be how you've seen your display or render function start out, but can you
tell what's wrong here and tell what would happen if you started to draw stuff? Yes, because you called
glLoadIdentity() on the MODELVIEW matrix the transformations you applied from the above code samples were cleared!!!
Now your objects want get smaller as they move away in the zaxis and your Camera is reset to its default position so you may not see your objects.
What you do after here is entirely up to you. You can put the Orthographic and Perspective code from above
right here or you could put them in a function and call them, which might be a wise idea, but you have to be careful of what you put in there.
*/

}



[/quote]

I allways thought transformation calls only affect the current matrix? So the projection matrix would be left untouched as the current matrix has changed before calling glLoadIdentity?


glMatrixMode(GL_PROJECTION);
// setup projection matrix

glMatrixMode(GL_MODELVIEW);
// setup model view matrix





I may be wrong however, I've only just picked up the OpenGL Super Bible so I'm still new to the OpenGL API.

Share this post


Link to post
Share on other sites
Thank you for the correction cNoob. I was quickly typing this up and had confused one of my previous screwups with the correct way to do it. I'll correct this now.

[Edited by - openglJunkie on November 29, 2008 9:38:54 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!