Hi,I have encountered a problem while doing the animation for my program. I wanted keep adding a another shape on top of another. But for evry second image the background changes to black. Can you point out what I've done wrong. Thanks.

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <GL/glut.h>
#include <windows.h>



void myinit(void)
{
    //glEnable(GL_BLEND);
    glClearColor(1.0, 1.0, 1.0, 0.0); /* white background */
    /* set up viewing */
    glColor3f(0.0,0.0,0.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(-110.0, 110.0, -110.0, 110.0);
}

void display( void )
{
    glutSwapBuffers();
        glFlush(); /* clear buffers */
}


void displayAnim( void )
{
    glLoadIdentity();
    glClear(GL_COLOR_BUFFER_BIT);  /*clear the window */
    int i = 0;
    /* define a point data type */
        typedef GLfloat point2[2];
    point2 vertices[4]={{20,20},{20,-20},{-20,-20},{-20,20}}; // A square

    glMatrixMode(GL_MODELVIEW);
    for(i=1;i<=30;i++)
            {
        glMatrixMode(GL_MODELVIEW);
        glColor3f(((float)rand())/RAND_MAX, ((float)rand())/RAND_MAX,((float)rand())/RAND_MAX); // Random color
        glBegin(GL_LINE_LOOP);
                glVertex2f(vertices[0][0],vertices[0][1]);
                glVertex2f(vertices[1][0],vertices[1][1]);
                glVertex2f(vertices[2][0],vertices[2][1]);
                glVertex2f(vertices[3][0],vertices[3][1]);
            glEnd();
        glRotatef(9,0,0, 1);
        glScalef(1.09,1.09,1);
        glMatrixMode(GL_PROJECTION);
        glutSwapBuffers();
        Sleep(500);
        }
    glMatrixMode(GL_PROJECTION);
    glutSwapBuffers();
        glFlush(); /* clear buffers */
 }

void displayNoAnim( void )
{
    glLoadIdentity();
    glClear(GL_COLOR_BUFFER_BIT);  /*clear the window */
    int i = 0;
    /* define a point data type */

        typedef GLfloat point2[2];
    point2 vertices[4]={{20,20},{20,-20},{-20,-20},{-20,20}}; // A square

    glMatrixMode(GL_MODELVIEW);
    for(i=1;i<=30;i++)
            {
        glColor3f(((float)rand())/RAND_MAX, ((float)rand())/RAND_MAX,((float)rand())/RAND_MAX); // Random color
        glBegin(GL_LINE_LOOP);
                glVertex2f(vertices[0][0],vertices[0][1]);
                glVertex2f(vertices[1][0],vertices[1][1]);
                glVertex2f(vertices[2][0],vertices[2][1]);
                glVertex2f(vertices[3][0],vertices[3][1]);
            glEnd();
        glRotatef(9,0,0, 1);
        glScalef(1.09,1.09,1);
        }
    glMatrixMode(GL_PROJECTION);
    glutSwapBuffers();
        glFlush(); /* clear buffers */
 }

void popupmenu(int id)
{
    glMatrixMode(GL_MODELVIEW);
    if(id==3){
        exit(0);
    }
    else if(id==2){
        displayNoAnim();
    }
    else if(id==1){
        displayAnim();
    }
}

int main(int argc, char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); /* default, not needed */
    glutInitWindowSize(500,500); /* 650 x 650 pixel window */
    glutInitWindowPosition(100,100); /* place window top left on display */
    glutCreateWindow("Images"); /* window title */
    glutDisplayFunc(display);/* display callback invoked when window opened */
    srand(time(NULL));
        myinit(); /* set attributes */
    glutCreateMenu(popupmenu);
    glutAddMenuEntry("animated display mode",1);
    glutAddMenuEntry("non-animated display mode",2);
    glutAddMenuEntry("exit",3);
    glutAttachMenu(GLUT_RIGHT_BUTTON);
    glutMainLoop(); /* enter event loop */
    return 1;
}

Can you please elaborate what the problem is? I am able to get squares one on top of the other. I have attached a screenshot, and i don't see the black screen you're referring to.

Edited 4 Years Ago by myk45

Attachments image.PNG 28.52 KB

Just looking at your code makes me wonder if your scene is animated correctly. I found this after a little Googling: http://www.opengl.org/resources/libraries/glut/spec3/node46.html. Thats a pretty interesting example of an alternate way of animating your glut scene. I suspect that your problem lies with your use of glutSwapBuffers();.

You could try to use the same technique as mentioned in the example above:

void InitGraphics(void)
{
    // Initiate your GL-stuff here
}

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

   // Set up viewing transformation, looking down -Z axis
   glLoadIdentity();

   // Twist and turn

   // Render your squares or whatever

   // Make sure changes appear onscreen
   glutSwapBuffers();
}


void AnimateScene(void)
{
    // Limit your fps and such here

    // Force redraw
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    // Initializations
    InitGraphics();

    glutIdleFunc (AnimateScene);

    // Add the spark
    glutMainLoop ();
    return 0;
}

You can read about idle func here: http://www.opengl.org/resources/libraries/glut/spec3/node63.html

Good luck on your animations!

Regards,
Emil Olofsson

Thanks Emil, I've tried using the glutIdleFunc function. The animation works, but when it gets to the end its start flicking. Is is how i've used the glutSwapBuffers?

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <GL/glut.h>
#include <windows.h>

int frame=0;

void myinit(void)
{
    int i;
    //glEnable(GL_BLEND);
    glClearColor(1.0, 1.0, 1.0, 0.0); /* white background */
    /* set up viewing */
    glColor3f(0.0,0.0,0.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(-120.0, 120.0, -120.0, 120.0);
}

void clear(void)
{glClear(GL_COLOR_BUFFER_BIT);  /*clear the window */}



void AnimateImg1(void)
{
    /* define a point data type */
        typedef GLfloat point2[2];
    point2 vertices[4]={{20,20},{20,-20},{-20,-20},{-20,20}}; // A square

    if(frame++<=30)
        {
        glMatrixMode(GL_MODELVIEW);
        glColor3f(((float)rand())/RAND_MAX, ((float)rand())/RAND_MAX,((float)rand())/RAND_MAX); // Random color
        glBegin(GL_LINE_LOOP);
                glVertex2f(vertices[0][0],vertices[0][1]);
                glVertex2f(vertices[1][0],vertices[1][1]);
                glVertex2f(vertices[2][0],vertices[2][1]);
                glVertex2f(vertices[3][0],vertices[3][1]);
            glEnd();
        glRotatef(9,0,0, 1);
        glScalef(1.09,1.09,1);
        glMatrixMode(GL_PROJECTION);
        glutSwapBuffers();
        Sleep(1000);
    }
    glutSwapBuffers();
    glFlush();
}

void display( void )
{
    glClear(GL_COLOR_BUFFER_BIT);  /*clear the window */
    frame=0;
    glutIdleFunc(AnimateImg1);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    frame=0;
 }

int main(int argc, char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); /* default, not needed */
    glutInitWindowSize(500,500); /* 650 x 650 pixel window */
    glutInitWindowPosition(100,100); /* place window top left on display */
    glutCreateWindow("Images"); /* window title */
    glutDisplayFunc(display);/* display callback invoked when window opened */
    srand(time(NULL));
        myinit(); /* set attributes */

    glutMainLoop(); /* enter event loop */
}

Edited 4 Years Ago by jinglylime

With this method you're not supposed to need this buffer swap at all:

if(frame++<=30)
{
...

glutSwapBuffers();
}

glutDisplayFunc(animationFunc) is called whenever a redraw is posted. This happens once when your program starts. Instead of running a loop inside your rendering function (display), which may cause bufferswaps before the system is done painting, you should create a new animationFunc() and bind it to glutIdleFunc(animationFunc). This is why:

This is what glutIdleFunc does:

If enabled, the idle callback is continuously called when events are not being received.
http://www.opengl.org/resources/libraries/glut/spec3/node63.html

This means that display will be called over and over again.

Now if you add this line: glutPostRedisplay(); to the end of animationFunc(), every time you enter your idle function animationFunc() this will cause your program to post a redraw. This makes your program call the glutDisplayFunc() again.

Hehe, I hope you understand what I mean :) Also I have never worked with glut, so my claims may even be wrong, but I think I got it right, this is what a proper game loop should look like.

Regards,
Emil Olofsson

I kinda understand what you are saying.So I did this but it only shows one shape and not all of it. Sorry, I've just started learning opengl.

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <GL/glut.h>
#include <windows.h>


int frame=0;

void myinit(void)
{
    int i;
    //glEnable(GL_BLEND);
    glClearColor(1.0, 1.0, 1.0, 0.0); /* white background */
    /* set up viewing */
    glColor3f(0.0,0.0,0.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(-120.0, 120.0, -120.0, 120.0);
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    /* define a point data type */
        typedef GLfloat point2[2];
    point2 vertices[4]={{20,20},{20,-20},{-20,-20},{-20,20}}; // A square

        glColor3f(((float)rand())/RAND_MAX, ((float)rand())/RAND_MAX,((float)rand())/RAND_MAX); // Random color

        glBegin(GL_LINE_LOOP);
            glVertex2f(vertices[0][0],vertices[0][1]);
            glVertex2f(vertices[1][0],vertices[1][1]);
            glVertex2f(vertices[2][0],vertices[2][1]);
            glVertex2f(vertices[3][0],vertices[3][1]);
        glEnd();

        glRotatef(9,0,0, 1);
        glScalef(1.09,1.09,1);

    glutSwapBuffers();
}

void animationFunc(void){
    if(frame++<=30){
        Sleep(1000);
    }
    glutPostRedisplay();
}

int main(int argc, char** argv)
{
    glutInit(&argc,argv);
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); /* default, not needed */
    glutInitWindowSize(500,500); /* 650 x 650 pixel window */
    glutInitWindowPosition(100,100); /* place window top left on display */
    glutCreateWindow("Images"); /* window title */
    srand(time(NULL));
        myinit(); /* set attributes */
    glutDisplayFunc(display);/* display callback invoked when window opened */
    glutIdleFunc(animationFunc);
    glutMainLoop(); /* enter event loop */
}

Hmm yeah, now your display function draws only one square each iteration. Im not really sure what you want your final output to look like, but you could try changing your display and animation functions like this:

const int kFramesMax = 30;

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();

    /* define a point data type */
    typedef GLfloat point2[2];
    point2 vertices[4]={{20,20},{20,-20},{-20,-20},{-20,20}}; // A square

    // Draw all squares up to current frame number
    for(int i = 0; i < frame; i++)
    {
        // Random color
        glColor3f(((float)rand())/RAND_MAX, ((float)rand())/RAND_MAX,((float)rand())/RAND_MAX);
        glBegin(GL_LINE_LOOP);
        glVertex2f(vertices[0][0],vertices[0][1]);
        glVertex2f(vertices[1][0],vertices[1][1]);
        glVertex2f(vertices[2][0],vertices[2][1]);
        glVertex2f(vertices[3][0],vertices[3][1]);
        glEnd();

        glRotatef(9,0,0, 1);
        glScalef(1.09,1.09,1);
    }

    glutSwapBuffers();
}

void animationFunc(void){
    Sleep(1000);
    glutPostRedisplay();
    if(frame < kFramesMax)
    {
        frame++;
    }
}

Now it should add one square at a time until there are kFramesMax squares on the screen. However, all colors should keep changing since the color information is never stored anywhere. Please tell me your results!

Regards,
Emil Olofsson

Edited 4 Years Ago by emilo35: Corrected an error in sample code

This article has been dead for over six months. Start a new discussion instead.