Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

chrono1081

macrumors G3
Original poster
Jan 26, 2008
8,922
6,640
Isla Nublar
Hi guys,

I am straight up confused. I have code that renders a utah teapot and moves it up and down the screen on the y axis while rotating it. For some reason its jerky on the Mac Pro in my sig and silky smooth on my Macbook Air. I am at a complete loss as to why. Does anyone have any suggestions on how I can improve this or to why its happening? I'm newish to OpenGL (I've used it but I'm not an expert by any means).

Here is the code that I have: (I know its full of bad programming practices but its just to learn the OpenGL concepts and none that I see should affect rendering but I could be wrong).

Any help would be greatly appreciated:) Also I've checked for vid card and cpu hogs like Maya running in the background of my Mac Pro and haven't found any. (Mayas rendered finished and nothing else is running)

Code:
//
//  main.cpp
//  NewGL2
//
//  Created by Scott Nelson on 5/6/11.
//  Copyright 2011 NA. All rights reserved.
//

#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <iostream>

//Arrays for key presses
bool* keyStates = new bool[256]; //Regular keys
bool* keySpecialStates = new bool[256]; //Special keys

//Globals for objects
bool movingUp = false; //Whether object is moving up or down
float yLocation = 0.0f; //Keep track of position on Y axis
float yRotationAngle = 0.0f; //The objects angle of rotation

//======================================================================
//                  Functions to manage windows and input
//======================================================================
//Function to handle character key down events
void keyDown(unsigned char key, int x, int y)
{
    //Set key to 'pressed'
    keyStates[key] = true;
    
    //Call to redraw the screen (this can be removed if an animation is present)
    glutPostRedisplay();
}

//Function to handle key up events
void keyUp(unsigned char key, int x, int y)
{
    //Set key to 'not pressed'
    keyStates[key] = false;
    
    //Call to redraw the screen (this can be removed if an animation is present)
    glutPostRedisplay();
}

//Function to handle special key down events
void keySpecialDown(int key, int x, int y)
{
    //Set key to 'pressed'
    keySpecialStates[key] = 1;
    
    //Call to redraw the screen (this can be removed if an animation is present)
    glutPostRedisplay();
}

//Function to handle special key up events
void keySpecialUp(int key, int x, int y)
{
    //Set key to 'not pressed'
    keySpecialStates[key] = 0;
    
    //Call to redraw the screen (this can be removed if an animation is present)
    //glutPostRedisplay();
}

//Function to control what happens on key state changes for regular keys
void keyOperations(void)
{
    //These can obviously be changed and added to to provide UI functionality
    if(keyStates['a']) {printf("A is pressed.\n");}
    //if(!keyStates['a']) {printf("A is not pressed.\n");}
    
    if(keyStates['b']) {printf("B is pressed.\n");}
    //if(!keyStates['b']) {printf("B is not pressed.\n");}
}

//Function to control what happens on special key state changes
void keySpecialOperations(void)
{
    //These can obviously be changed and added to to provide UI functionality
    if(keySpecialStates[GLUT_KEY_LEFT]) {printf("The Left Key was pressed.\n");}
    //if(!keySpecialStates[GLUT_KEY_LEFT]) {printf("The Left Key was not pressed.\n");}
    
    if(keySpecialStates[GLUT_KEY_RIGHT]) {printf("The Right Key was pressed.\n");}
    //if(!keySpecialStates[GLUT_KEY_RIGHT]) {printf("The Right Key was not pressed.\n");}
    
    if(keySpecialStates[GLUT_KEY_UP]) {printf("The Up Key was pressed.\n");}
    //if(!keySpecialStates[GLUT_KEY_UP]) {printf("The Up Key was not pressed.\n");}
    
    if(keySpecialStates[GLUT_KEY_DOWN]) {printf("The Down Key was pressed.\n");}
    //if(!keySpecialStates[GLUT_KEY_DOWN]) {printf("The Down Key was not pressed.\n");}
}

//Function to create shapes
void renderPrimitive(void)
{
    /*
    //SQUARE 
    glBegin(GL_LINE_LOOP); //Start drawing quad primitive
        glColor3f(1.0f, 0.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, 0.0f); //bottom left
        glColor3f(0.0f, 1.0f, 0.0f);
        glVertex3f(-1.0f, 1.0f, 0.f);   //top left
        glColor3f(0.0f, 0.0f, 1.0f);
        glVertex3f(1.0f, 1.0f, 0.0f);   // top right
        glColor3f(1.0f, 0.0f, 1.0f);
        glVertex3f(1.0f, -1.0f, 0.0f);  //bottom right
    glEnd(); */
    
    /*
    //SQUARE OUTLINE
    glBegin(GL_QUADS); //Start drawing quad primitive
        glColor3f(1.0f, 0.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, 0.0f); //bottom left
        glColor3f(0.0f, 1.0f, 0.0f);
        glVertex3f(-1.0f, 1.0f, 0.f);   //top left
        glColor3f(0.0f, 0.0f, 1.0f);
        glVertex3f(1.0f, 1.0f, 0.0f);   // top right
        glColor3f(1.0f, 0.0f, 1.0f);
        glVertex3f(1.0f, -1.0f, 0.0f);  //bottom right
    glEnd();*/
    
    /*
    //POINTS
    glPointSize(20.0f);
    glBegin(GL_POINTS);
        glVertex3f(-1.0f, -1.0f, 0.0f); //bottom left
        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
    glEnd(); */
    
    /*
    //SQUARE FROM TRIANGLE STRIPS
    glBegin(GL_TRIANGLE_STRIP); // Start drawing a triangle strip primitive  
        // The first triangle  
        glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner  
        glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner  
        glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner  
        // The end of the second triangle  
        glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner  
        glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner  
    glEnd(); */
    
    //glutWireSphere(2, 30, 30);
    //glutWireCube(2);
    //glutWireTorus(1, 2, 30, 30);
    glutWireTeapot(1);
}

//Function to draw the scene
void display(void)
{
    //Check for key operations each frame to avoid multiple keypresses per frame
    keyOperations();
    keySpecialOperations();
    
    //Handle drawing
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); //Clear background of window
    glClear(GL_COLOR_BUFFER_BIT); //Clear the color buffer
    glLoadIdentity(); //Load identity matrix to reset drawing locations
    
    //Translate scene back
    glTranslatef(0.0f, 0.0f, -6.0f);
    
    //Move objects in scene
    glTranslatef(0.0f, yLocation, 0.0f); //Translate object along y-axis.
    glRotatef(yRotationAngle, 0.0f, 1.0f, 0.0f); //Rotate object along y-axis
    
    renderPrimitive();
    
    glutSwapBuffers(); //Swap buffers to the window
    
    //Control object movement
    
    //Control speed
    if(movingUp) //If object is moving up
        yLocation -= 0.005f; //Move up along yLocation
    
    else
        yLocation += 0.005f; //Moving down along yLocation
    
    //Control up or down direction
    if(yLocation < -3.0f) //If we went up to far
        movingUp = false; //Reverse direction
   
    else if(yLocation > 3.0f) //If we went down to far
        movingUp = true; //Reverse direction
    
    //Control rotation angle
    yRotationAngle += 0.05f; //Increment rotation value
    
    if(yRotationAngle > 360.0f) //If rotation is beyond bounds
        yRotationAngle -= 360.0f; //Subtract 360 from rotation
}

//Function to reshape the window when dragged
void reshape(int width, int height)
{
    //Set viewport to window size
    glViewport(0, 0, (GLsizei)width, (GLsizei)height); 
    
    // Switch to projection matrix to manipulate how scene is viewed
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); //Reset projection matrix to avoid artifacts
    
    //Set FOV, + Near and Far clip planes
    gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0);
    
    //Switch back to modelview matrix
    glMatrixMode(GL_MODELVIEW);
}
//----------------------------------------------------------------------

//======================================================================
//                              Main Function
//======================================================================
int main(int argc, char** argv)
{
	glutInit(&argc, argv); //Initialize GLUT
    
    //Initialize key state arrays
    for(int i = 0; i < 256; ++i)
    {  
        keyStates[i] = false;
        keySpecialStates[i] = false;
    }
	
    //Set display properties
    glutInitDisplayMode(GLUT_DOUBLE); //Set up a double display buffer
    glutInitWindowSize(500, 500); //Set the width and height of the window
    glutInitWindowPosition(100, 100); //Set window position
    glutCreateWindow("GSP 420"); //Set window caption
    
    //Window Control Functions
    glutDisplayFunc(display); //Tell glut to draw window based on function
    glutIdleFunc(display);    //Tell glut to use display as idle method as well
    glutReshapeFunc(reshape); //Tell glut to reshape the window when dragged
    
    //Keyboard Control Functions
    glutKeyboardFunc(keyDown); //Tell glut to use keyDown function to handle key presses
    glutKeyboardUpFunc(keyUp); //Tell glut to use keyUp function to handle key releases
    glutSpecialFunc(keySpecialDown); //Tell glut to use keySpecialDown function to handle special key events
    glutSpecialUpFunc(keySpecialUp); //Tell glut to use keySpecialUp function to handle special key up events
    
    
    //Glutloop to keep program running
    glutMainLoop();
	
	
	return 0;
}
 
You really shouldn't use immediate mode in OpenGL. Stick to using VBOs and PBOs if you want to use modern features. I doubt driver writers bother doing too much optimisation in regards to immediate mode.

This is the number one reason why OpenGL 4+ support is so important in Mac OS X. It is the first version (OpenGL 3.3 does as well to some degree) that deprecates all the old cruft that has built up in OpenGL over the years. Alas unless things have changed since I last looked it appears that we will be stuck with OpenGL 3.2 on Mac OS X Lion.

The OpenGL Red book doesn't help much either (I have the OpenGL 2.1 version) as it literally describes everything without much of an indication of best practices.
 
Further to what cromulent says, it seems the NVidia drivers are optimised better than the ATI drivers for immediate mode. On my 2.93 Ghz iMac9,1 with an NVidia GT 120 it runs smooth.
 
Thanks guys!

I'm not really sure what your responses mean yet (I'm still really new to OpenGL) but it will give me a starting point to look at. Thank you :)
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.