OpenGL Universe size

Hi all, I have been busting my brains trying to figure out OpenGL so that I can finish my assignment for my games unit at uni. I think I understand the basics of OpenGL and how it all works but I’m having a small problem understanding something:

At the moment I have written a header in ‘c’ to parse and load a .obj file which works and I can buffer any 3D model of that file extension into my program. Trouble is that my model has vertex values between -20 and 20 (or there abouts), and as I understand it the OpenGL won’t register/display anything outside of the OpenGL universe (-1 to 1 along the x, y, and z axis).

Maybe I’m not explaining this problem very well, I’ll try and put it in one sentence:

How can I resize the OpenGL universe so that I can position an object at z = -100 for example, and it will still display on the screen?

That still sounds funny lol, hope you guys can decipher my problem description.

Thanks in advance,

Ryan

take a look at Projection Transformations.. Basically you can set your view volume to anything you like by setting the PROJECTION MATRIX and setting the camera position in MODELVIEW_MATRIX:


glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(left, right, bottom, top,  near, far);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyeX,eyeY,eyeZ,
          centerX,centerY,centerZ,
          upX,upY,upZ);
// place your drawing code here

In your case of a 20x20x20 object at x,y,z=0,0,-100 you could set -left=right=-bottom=top=20/21.8 and near=0, far=220/21.8 (1.8x so viewing volume is larger than your object). And set camera at eyeX,eyeY,eyeZ=0,0,-100+220/2*1.8 looking towards centerX,centerY,centerZ=0,0,-100, with upX,upY,upZ=0,1,0. See code below for details …

Another good resource to look at is the matrixModelView.zip and matrixProjection.zip at the bottom of songho tutorials.


#include <GL/gl.h>
#include <GL/glut.h>

GLfloat gAngle = 0.0;

void timer(int value)
{
  const int desiredFPS=120;
  glutTimerFunc(1000/desiredFPS, timer, ++value);
  GLfloat dt = 1./desiredFPS;

  //put your specific idle code here
  //... this code will run at desiredFPS
	gAngle += dt*360./8.; //rotate 360 degrees every 8 seconds
  //end your specific idle code here

  glutPostRedisplay(); // initiate display() call at desiredFPS rate
}

void display() {
  // Will be called at FPS rate, ok to use global values now to rener scene
  glClear(GL_COLOR_BUFFER_BIT);

  glPushMatrix();
    glTranslatef(0,0,-100);
    glRotatef(gAngle,1.,1.,1.);
    glutWireCube(20.); //cube of size 20x20x20
  glPopMatrix();

  glutSwapBuffers();
}

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

	GLdouble Vol = 10*1.8;
	GLdouble Left=-Vol;
	GLdouble Right=Vol;
	GLdouble Bottom=-Vol;
	GLdouble Top=Vol;
	GLdouble Near=0; 
	GLdouble Far=2*Vol;

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(Left, Right, Bottom, Top,  Near, Far);

	GLdouble eyeX=0;
	GLdouble eyeY=0;
	GLdouble eyeZ=-100+Vol;
	GLdouble centerX=0;
	GLdouble centerY=0;
	GLdouble centerZ=-100;
	GLdouble upX=0;
	GLdouble upY=1;
	GLdouble upZ=0;

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(eyeX,eyeY,eyeZ,
            centerX,centerY,centerZ,
            upX,upY,upZ);
}

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

int main(int argc, char** argv) {
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DOUBLE);
   glutCreateWindow("FPS test /w glutTimerFunc");

   glutTimerFunc(0,timer,0);
   glutDisplayFunc(display);
   glutKeyboardFunc(keyboard);

   init();

   glutMainLoop();
   return 0;
}

Where have you read that? :slight_smile:

You can model your scene in any units, and models can be expressed in any numbers as long as your computer can understand that numbers and store them into registers. So, don’t worry about size of your models. Only adjust viewing transformation (so that your camera is oriented toward them) and projection (so that they are in the viewing frustum).

[What you have heard about is normalized space which is automatically created after projection and perspective division. But you don’t have to model your scene in that space. Take a look at the description of 3D pipeline to understand what is happening…]

Thanks for your reply marshats,

Currently my simple display function looks like this:

void display()
{
// Clear the screen and the depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Set up projection mode (perspective)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40,1,0.5,3.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// Draw the Alien
DrawAlien();

// Swap buffer to update screen smoothly
glFlush();
glutSwapBuffers();

}

I know this is a really bad way of understanding things (I hate to copy and paste code without th eproper understanding),
but are you saying I should replace the following:

gluPerspective(40,1,0.5,3.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

with the modified version of your code as follows:

glOrtho(left, right, bottom, top, near, far);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyeX,eyeY,eyeZ,
centerX,centerY,centerZ,
upX,upY,upZ);

And it will work as long as I pass the correct paramaters?

Or is there a way to modify my gluPerspective(40,1,0.5,3.0); code to get the job done?

You can modify gluPerspective but you will still need to add the gluLookAt to place your camera in relation to your object at z=-100

Here is an example code using gluPerspective instead of glOrtho.


#include <GL/gl.h>
#include <GL/glut.h>

GLfloat gAngle = 0.0;

void timer(int value)
{
  const int desiredFPS=120;
  glutTimerFunc(1000/desiredFPS, timer, ++value);
  GLfloat dt = 1./desiredFPS;

  //put your specific idle code here
  //... this code will run at desiredFPS
  gAngle += dt*360./8.; //rotate 360 degrees every 8 seconds
  //end your specific idle code here

  glutPostRedisplay(); // initiate display() call at desiredFPS rate
}

void display() {
  // Will be called at FPS rate, ok to use global values now to rener scene
  glClear(GL_COLOR_BUFFER_BIT);

  glPushMatrix();
    glTranslatef(0,0,-100);
    glRotatef(gAngle,1.,1.,1.);
    glutWireCube(20.); //cube of size 20x20x20
  glPopMatrix();

  glutSwapBuffers();
}

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

  GLdouble Vol = 10*1.8;

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(40,1,0.1,4*Vol); //fovy, aspect, zNear, zFar


  GLdouble eyeX=0;
  GLdouble eyeY=0;
  GLdouble eyeZ=-100+2.9*Vol;
  GLdouble centerX=0;
  GLdouble centerY=0;
  GLdouble centerZ=-100;
  GLdouble upX=0;
  GLdouble upY=1;
  GLdouble upZ=0;

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(eyeX,eyeY,eyeZ,
            centerX,centerY,centerZ,
            upX,upY,upZ);
}

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

int main(int argc, char** argv) {
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DOUBLE);
   glutCreateWindow("FPS test /w glutTimerFunc");

   glutTimerFunc(0,timer,0);
   glutDisplayFunc(display);
   glutKeyboardFunc(keyboard);

   init();

   glutMainLoop();
   return 0;
}

Note, you only need to set the projection matrix once so there is no need to reset with each display – hence it is moved to the init() function. If the camera is not dynamically moving then the same can be said of gluLookAt.

Thanks very much :smiley:

I have a lot of research to do before I ‘get it’ but so far it works.

Thanks