Question

I don't know very much about openGL/glut, but I've used it before successfully for some exceedingly simple things in 2D. Now I want to be able to draw spheres in 3D. I'm trying to simulate particle collisions, so all I'm really going to need to do on the graphics end is draw spheres. Here's my abortive attempt

void renderScene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glLoadIdentity();
            // Set the camera
    gluLookAt(1.0f, 1.0f, 1.0f,
              0.0f, 0.0f, 0.0f,
              0.0f, 1.0f, 0.0f);

    glutSwapBuffers();
}

void timerProc(int arg)
{
    glutTimerFunc(50,timerProc,0);

    // Reset transformations
    glLoadIdentity();
    // Set the camera
    gluLookAt(1.0f, 1.0f, 1.0f,
              0.0f, 0.0f, 0.0f,
              0.0f, 1.0f, 0.0f);

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    glColor3f(0.0,0.0,0.0);  //color = black
    glPushMatrix();
        glTranslated(0,0,0);
        glutSolidSphere(.74, 500, 500);
    glPopMatrix();

    glutSwapBuffers();
}

int main(int argc, char **argv)
{
    srand(time(NULL));
    init();

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(50,30);
    glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH)-80,glutGet(GLUT_SCREEN_HEIGHT)-60);

    mainWindow=glutCreateWindow("New Window"); //global variable

    WIDTH=glutGet(GLUT_WINDOW_WIDTH); //global variable
    HEIGHT=glutGet(GLUT_WINDOW_HEIGHT); //global variable

    glutDisplayFunc(renderScene);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

    glutTimerFunc(50,timerProc,0);
    glutMainLoop();
    return 0;
}

Hopefully all of my problems stem from one really basic mistake... For some reason, this creates an oval. And, though the oval is pretty big (maybe about an 1/8th of the screen wide and tall), if I lower the radius down to .73 it vanishes, I'm guessing because it's too small to see. How would I make it so that this sphere would show up circular like you'd expect, and so that as I can see everything that's happening in a given volume, say a 10x10x10 box, the way you would if you were just standing next to a box of particles that were flying around and peering into it, or a reasonable approximation. Right now it's hard to tell what exactly I'm looking at (I know that I'm standing at 1,1,1 and looking at the origin, but it's hard to grasp exactly what I'm seeing) Also, occasionally when I run it the whole screen is just black. Then when I clean and build and run again it's fine. Not really a huge concern, but annoying, and I'd love to understand what was going on. Also, when I the number of slices and stacks was lower, it would look fine if the radius was large, but become extremely distorted when the radius was small, which I thought was very strange...

Was it helpful?

Solution

The main problem you are having here is Z clipping. The initial Z range for the scene is (-1, 1) so you only see a part of the actual sphere and by change in its size you go out of z range.

Image

There are several problems I see in the code. It is good to get a grasp of how the GLUT workflow actually works.

Lets see what the code does wrong.

Main

int main(int argc, char **argv)
{
    srand(time(NULL));
    init();

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(50, 30);
    glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH) - 80, 
                       glutGet(GLUT_SCREEN_HEIGHT) - 60);

    mainWindow = glutCreateWindow("New Window"); //global variable

    WIDTH = glutGet(GLUT_WINDOW_WIDTH); //global variable
    HEIGHT = glutGet(GLUT_WINDOW_HEIGHT); //global variable

    glutDisplayFunc(renderScene);

Here you define the display function. It is called every time the window contents has to be invalidated. In this case it is invalidated only at start. The renderScene function does not do anything awesome, just clears the screen. So you get a black screen at the beginning.

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

No need for blending at the moment. You can skip that part altogether.

    glutTimerFunc(50, timerProc, 0);

Now you set up the timerProc function to be called in 50 milliseconds.

    glutMainLoop();

As the documentation states: glutMainLoop enters the GLUT event processing loop. This routine should be called at most once in a GLUT program. Once called, this routine will never return. It will call as necessary any callbacks that have been registered.

    return 0;
}

Render Scene

void renderScene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

This is the only place where you clear the screen. Timer Func does not do this.

    glLoadIdentity();

You are reseting the matrices.

    // Set the camera
    gluLookAt(1.0f, 1.0f, 1.0f,
        0.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f);

Setting up the matrices. (One matrix to be precise)

    glutSwapBuffers();

And without drawing anything you swap buffers.

}

Scene rendering function is called each time the window frame has to be redrawn.

Timer

This function does rely on the screen being cleared at first by the renderScene. void timerProc(int arg) { glutTimerFunc(50, timerProc, 0);

    // Reset transformations
    glLoadIdentity();
    // Set the camera
    gluLookAt(1.0f, 1.0f, 1.0f,
        0.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f);

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

Not clearing this time. Only setting the color.

    glColor3f(0.0, 0.0, 0.0);  //color = black
    glPushMatrix();
    glTranslated(0, 0, 0);
    glutSolidSphere(.74, 500, 500);
    glPopMatrix();

    glutSwapBuffers();
}

How to fix it?

Just setup the matrices. With proper Z range.

void resetTransformations() {
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1, 1, -1, 1, -1000, 1000);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(1.0f, 1.0f, 1.0f,
        0.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f);
}

void renderScene()
{
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Reset transformations
    resetTransformations();

    // Just to see some triangles
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    glColor3f(0.0, 0.0, 0.0);  //color = black
    glPushMatrix();
    glTranslated(0, 0, 0);
    glutSolidSphere(0.74, 500, 500);
    glPopMatrix();

    glutSwapBuffers();
}

int main(int argc, char **argv)
{
    srand(time(NULL));

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowPosition(50, 30);
    glutInitWindowSize(256, 256);

    mainWindow = glutCreateWindow("New Window"); //global variable

    WIDTH = glutGet(GLUT_WINDOW_WIDTH); //global variable
    HEIGHT = glutGet(GLUT_WINDOW_HEIGHT); //global variable

    glutDisplayFunc(renderScene);
    glutIdleFunc(renderScene);

    glutMainLoop();
    return 0;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top