Double Buffer makes things disappear

Edit: I solved this problem on my own =)

Hello,

I’m new at OpenGL and 3D programming in general, so I don’t really know how to figure out a lot of things on my own yet.

I’m learning from the Red Book 7th edition, and I got my stuff to work with single buffering, but when I tried to change to double buffering, I ran into an issue.

First, I’m using freeglut for windowing. Second, I’m working in Vista at the moment. And third, the issue I’m hitting is that after maybe a second, my drawing disappears. I’m coding in C++, trying to make things Object Oriented. Once again, I don’t really know anything about OpenGL yet, so if you see anything that looks wrong, it might be wrong. Here’s the code:

Main.cpp

#include <GL/freeglut.h>
#include "Lego.h"

static GLfloat spin = 0.0;
Lego lego1(1.0, 0.0, 0.0, 4.0, 2.0, 1.0);

//Initialize the program
void init() {
    glClearColor(0.0, 0.0, 0.0, 0.0);    // Set default background color

    glShadeModel(GL_FLAT);                // Dunno yet    <--
}

// The magic
void display() {
    glClear(GL_COLOR_BUFFER_BIT);    // Clear Pixels
    glPushMatrix();                    // Dunno Yet    <--

    spin += 2.0;

    glRotatef(spin, 0.0, 0.0, 1.0);
    lego1.draw();

    glPopMatrix();                    // Dunno yet    <--
    glutSwapBuffers();                // Switch to drawing next buffer when time is up
}

// Command what happens when window is resized
void reshape(int w, int h) {
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);    // Change viewing area to continue to be the whole window
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-w/2, w/2, -h/2, h/2, -100.0, 100.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

// Function for mouse input
void mouse(int button, int state, int x, int y) {
    switch(button) {
        case GLUT_LEFT_BUTTON:
            if(state == GLUT_DOWN) {
                //glutIdleFunc(spinDisplay);
            }
            break;

        case GLUT_RIGHT_BUTTON:
            if(state == GLUT_DOWN) {
                //glutIdleFunc(NULL);
            }
            break;

        default:
            break;
    }
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);                                        // Any commad line related stuff
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);    // Sets display properties
    glutInitWindowSize(250, 250);                                // Initial window size
    glutInitWindowPosition(100, 100);                            // Initial window position
    glutInitContextVersion(3, 0);                                // Use version 3.0
    glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);                // Make forward compatible
    glutCreateWindow("Hello World");                            // Create (but not display) window

     init();                                            // Launch initializing function
    glutDisplayFunc(display);                        // Set the display function
    glutReshapeFunc(reshape);                        // Sets what happens when reshaped
    glutMouseFunc(mouse);                            // Sets what happens with mouse input
    glutMainLoop();                                    // Start the program
    return 0;
}

Lego.h

#ifndef _LEGO_H

#define _LEGO_H_

class Lego {
    float r, g, b;
    float l, w, h;    // Each 1 unit = ?
    float x, y, z;
    float xRot, yRot, zRot;

    public:
        Lego(float, float, float, float, float, float);
        void draw();
        bool isMouseDown();
};

#endif

Lego.cpp

#include <GL/freeglut.h>

#include "Lego.h"

Lego::Lego(float r, float g, float b, float l, float w, float h) {
    this->r = r;
    this->g = g;
    this->b = b;
    this->l = l;
    this->w = w;
    this->h = h;

    this->xRot = 0.0;
    this->yRot = 0.0;
    this->zRot = 0.0;

    // Temporary
    this->x = 0.0;
    this->y = 0.0;
    this->z = 0.0;
}

void Lego::draw() {
    glTranslatef(x, y, z);

    GLfloat vertices[] =   {-80, -80,  30, 1.0, 0.0, 0.0,
                             40, -80,  30, 1.0, 0.0, 0.0,
                             40,  40,  30, 1.0, 0.0, 0.0,
                            -80,  40,  30, 1.0, 0.0, 0.0,
                            -60, -60, -30, 0.0, 1.0, 0.0,
                             60, -60, -30, 0.0, 1.0, 0.0,
                             60,  60, -30, 0.0, 1.0, 0.0,
                            -60,  60, -30, 0.0, 1.0, 0.0,
                            };

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    glVertexPointer(3, GL_FLOAT, 6*sizeof(GL_FLOAT), &vertices[0]);
    glColorPointer(3, GL_FLOAT, 6*sizeof(GL_FLOAT), &vertices[3]);

    glDrawArrays(GL_QUADS, 0, 8);

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);

    glTranslatef(0, 0, 0);

    glutSwapBuffers();
}

As I said, after like a second, maybe less, the boxes disappear. My question is why does it do this?

Glad you solved it alone :slight_smile:
Next time please explain in a few words what was the mistake and how you solved it, to help others.

Well,

The display function isn’t continuously called, like I thought. Instead, you apparently refresh the display with glutPostRedisplay() (given I remember the function name correctly).

Well, the disappearing issue happened when the Lego.draw() function switched buffers, then the display() function switched buffers after that. Since nothing was is the other buffer (as nothing was told to be drawn), it resulted in an empty screen.

What I did was take the buffer swapping out of the draw() function, and left the buffer swap up to the display function. Every time I want it to be updated (due to mouse events or whatever), I have to have glutPostRedisplay() at the end of the function that updates things (like an angle, or position of the object, etc.) for the updates to actually be made.

There might be more technical things happening that I don’t know about yet, but that’s what I figured out and it works now.