Triangle Bounce

Notes:

This code is for showing that calling "glutPostRedisplay()" can be called any time to redraw the screen.
When I saw a shape bouncing mindlessly around the screen I couldn't help but try to emulate the old DVD screen-saver. So here is my version of the assignment. This is my own code that uses a triangle instead of a cube and not the source provided from the webpage.
Enjoy!

Makefile

NAME = Bounce
SRCPATH = ./
SHAREDPATH = ../GLTools/src/
SHAREDINCPATH = ../GLTools/include/
LIBDIRS = -L/usr/local/lib
INCDIRS = -I/usr/include -I/usr/local/include -I/usr/include/GL -I$(SHAREDINCPATH)  -I$(SHAREDINCPATH)GL

CC = g++
CFLAGS = -g $(INCDIRS)
#LIBS = -lX11 -lglut -lGL -lGLU -lm
LIBS = -lGL -lglut -lGLU -lm

all: 
	$(CC) $(CFLAGS) $(LIBS) $(SRCPATH)$(NAME).cpp $(SHAREDPATH)glew.c $(SHAREDPATH)GLTools.cpp $(SHAREDPATH)GLBatch.cpp $(SHAREDPATH)GLTriangleBatch.cpp $(SHAREDPATH)GLShaderManager.cpp $(SHAREDPATH)math3d.cpp -o $(NAME)
clean:
	rm -f *.o

Source:

/*
 * OpenGL SuperBible exercise 2.3: Render a triangle and move automatically
 */
#include <GLTools.h>    // OpenGL toolkit
#include <GLShaderManager.h>    // Shader manager class

#ifdef __APPLE__
#include <glut/glew.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

// an assortment of needed classes
//GLBatch squareBatch;
GLBatch triangleBatch;
GLShaderManager shaderManager;

// more global variables
// triangle
GLfloat vVerts[] = {-0.5f, 0.0f, 0.0f,
                     0.5f, 0.0f, 0.0f,
                     0.0f, 0.5f, 0.0f};
// 0 stop, 1 NE, 2 SE, 3 SW, 4 NW 
int direction = 1;
int color = 1; // 0 black, 1 red, 2 green, 3 blue, 4 yellow

// Move the triangle around the screen
void BounceFunction(void)
{
GLfloat stepSize = 0.0025f;
GLfloat triangleSize = 0.5f;
GLfloat triangleX = vVerts[0] + triangleSize;   //X
GLfloat triangleY = vVerts[1];                  //Y

// 0 stop, 1 NE, 2 SE, 3 SW, 4 NW 
switch (direction)
{
    case 0: // stop
            break;
        case 1: // NE
            triangleY += stepSize;
            triangleX += stepSize;
            break;
        case 2: // SE
            triangleY -= stepSize;
            triangleX += stepSize;
            break;
        case 3: // SW
            triangleY -= stepSize;
            triangleX -= stepSize;
            break;
        case 4: // NW
            triangleY += stepSize;
            triangleX -= stepSize;
            break;
        default:
            break;
    }

    // Collision detection
    // 0 stop, 1 NE, 2 SE, 3 SW, 4 NW 
    if (direction != 0)
    {
        // left boundry
        if (triangleX < -0.5f) 
        {
            triangleX = -0.5f;
            if (direction == 4)
            {
                // add SOME deformation to make it intersting
                triangleY -= 0.04f;
                direction = 1;  
                color = 1;
            }
            else
            {
                // add SOME deformation to make it intersting
                triangleY -= 0.04f;
                direction = 2;  
                color  = 2;
            }
        }
        // right boundry
        if (triangleX >  0.5f) 
        {
            triangleX =  0.5f;

            if (direction == 1)
            {
                direction = 4;  
                color = 4;
            }
            else
            {
                direction = 3;  
                color = 3;
            }
        }
        // bottom boundry
        if (triangleY < -1.0f) 
        {
            triangleY = -1.0f;
            if (direction == 3)
            {
                direction = 4;
                color = 4;
            }
            else
            {
                direction = 1;
                color = 1;
            }
        }
        // top boundry
        if (triangleY >  0.5f) 
        {
            triangleY = 0.5f;
            if (direction == 1)
            {
                direction = 2;
                color = 2;
            }
            else
            {
                direction = 3;
                color = 3;
            }
        }
    }

    // Recalculate vertex positions
    vVerts[0] = triangleX - triangleSize;       // X
    vVerts[1] = triangleY;                      // Y
                                                // Z
                                        
    vVerts[3] = triangleX;                      // X
    vVerts[4] = triangleY + triangleSize;       // Y
                                                // Z
    
    vVerts[6] = triangleX + triangleSize;       // X
    vVerts[7] = triangleY;                      // Y
                                                // Z

    triangleBatch.CopyVertexData3f(vVerts);
    //printf("direction: %i\n", direction);
}



// Resize the viewport on window creation or resize
void ChangeSize(int w, int h)
{
    glViewport(0,0, w, h);
}

// setup the rendering context
void SetupRC()
{
    // Black background
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    shaderManager.InitializeStockShaders();

    triangleBatch.Begin(GL_TRIANGLES, 3);
    triangleBatch.CopyVertexData3f(vVerts);
    triangleBatch.End();
}

// render the scene
void RenderScene(void)
{
    // Clear the window with current clearing color
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    GLfloat vRed[]      = { 1.0f, 0.0f, 0.0f, 1.0f};
    GLfloat vGreen[]    = { 0.0f, 1.0f, 0.0f, 1.0f};
    GLfloat vBlue[]     = { 0.0f, 0.0f, 1.0f, 1.0f};
    GLfloat vYellow[]   = { 1.0f, 1.0f, 0.0f, 1.0f};
 
    switch (color)
    {
        case 1:
            shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
            break;
        case 2:
            shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vGreen);
            break;
        case 3:
            shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vBlue);
            break;
        case 4:
            shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vYellow);
            break;
        default:
            break;
    }
    triangleBatch.Draw();

    // Perform the buffer swap to display the back buffer
    glutSwapBuffers();

    // Move our shape
    BounceFunction();

    // Redraw
    glutPostRedisplay();
}

// handle key input
void SpecialKeys(unsigned char key, int x, int y)
{
    GLfloat stepSize = 0.025f;
    GLfloat triangleSize = 0.5f;

    GLfloat triangleX = vVerts[0] + triangleSize; //X
    GLfloat triangleY = vVerts[1]; //Y


    if (key == GLUT_KEY_UP)
    {
        triangleY += stepSize;
        printf("key up\n");
        printf("Y: %f\n", triangleY);
    }
    if (key == GLUT_KEY_DOWN)
    {
        triangleY -= stepSize;
        printf("key down\n");
        printf("Y: %f\n", triangleY);
    }
    if (key == GLUT_KEY_LEFT)
    {
        triangleX -= stepSize;
        printf("key left\n");
        printf("X: %f\n", triangleX);
    }
    if (key == GLUT_KEY_RIGHT)
    {
        triangleX += stepSize;
        printf("key right\n");
        printf("X: %f\n", triangleX);
    }

    // Recalculate vertex positions
    vVerts[0] = triangleX - triangleSize;       // X
    vVerts[1] = triangleY;                      // Y
                                                // Z
                                        
    vVerts[3] = triangleX;                      // X
    vVerts[4] = triangleY + triangleSize;       // Y
                                                // Z
    
    vVerts[6] = triangleX + triangleSize;       // X
    vVerts[7] = triangleY;                      // Y
                                                // Z

    triangleBatch.CopyVertexData3f(vVerts);

    glutPostRedisplay();
}

// main entry point for GLUT based games
int main(int argc, char *argv[])
{
    gltSetWorkingDirectory(argv[0]);

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(480, 480);
    glutCreateWindow("Triangle Bounce");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    glutKeyboardFunc(SpecialKeys);

    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
        return 1;
    }

    SetupRC();

    glutMainLoop();
    return 0;
}

Answer:


Back to index