Camera movement with added actors

Notes:

We modify the last exercise to add more spheres using an extra frame of reference.

Source:

// Actors.cpp
// Draw extra spheres using a frame of reference

#include <GLTools.h>	// OpenGL toolkit
#include <GLMatrixStack.h>
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>
#include <GLBatch.h>
#include <StopWatch.h>
#include <math.h>

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

GLFrustum           viewFrustum;        // View frustum
GLShaderManager     shaderManager;      // Shader manager
GLMatrixStack       modelViewMatrix;    // Model view matrix
GLMatrixStack       projectionMatrix;   // Projection matrix
GLGeometryTransform transformPipeline;  // Geometry transfor pipeline

//GLTriangleBatch     torusBatch;       // torus
GLTriangleBatch     cylinderBatch;      // cylinder
GLTriangleBatch     sphereBatch;        // sphere
GLBatch             floorBatch;         // floor
GLFrame             cameraFrame;        // camera frame of reference
#define NUM_SPHERES 50
GLFrame             spheres[NUM_SPHERES];

// Set up the viewport and the projection matrix
void ChangeSize(int w, int h)
{
    // Prevent a divide by zero
    if(h == 0)
    {
        h = 1;
    }
    
    // Set Viewport to window dimensions
    glViewport(0, 0, w, h);
    
    viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 1000.0f);
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());

    // Set the projection pipeline to use the two matrix stacks
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}

void SpecialKeys(int key, int x, int y)
{
    float linear = 0.1f;
    float angular = float(m3dDegToRad(5.0f));

    if (key == GLUT_KEY_UP)
    {
        cameraFrame.MoveForward(linear);
    }
    if (key == GLUT_KEY_DOWN)
    {
        cameraFrame.MoveForward(-linear);
    }
    if (key == GLUT_KEY_LEFT)
    {
        cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
    }
    if (key == GLUT_KEY_RIGHT)
    {
        cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
    }
}

// Called to draw scene
void RenderScene(void)
{
    // colors
    GLfloat vRed[]      =   { 1.0f, 0.0f, 0.0f, 1.0f };
    GLfloat vMaroon[]   =   { 0.5f, 0.0f, 0.0f, 1.0f };
    GLfloat vBlue[]     =   { 0.0f, 0.0f, 1.0f, 1.0f };
    GLfloat vDBlue[]    =   { 0.0f, 0.0f, 0.5f, 1.0f };
    GLfloat vLGrey[]    =   { 0.3f, 0.3f, 0.3f, 1.0f };
    GLfloat vGrey[]     =   { 0.8f, 0.8f, 0.8f, 1.0f };

    // Set up time based animation
    static CStopWatch rotTimer;
    float yRot = rotTimer.GetElapsedSeconds() * 60.0f;
    
    // Clear the window and the depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Save the current model view matrix 
    modelViewMatrix.PushMatrix();

    // create a camera matrix
    M3DMatrix44f mCamera;
    cameraFrame.GetCameraMatrix(mCamera);
    modelViewMatrix.PushMatrix(mCamera);

    // Draw the ground 
    shaderManager.UseStockShader(GLT_SHADER_FLAT,
                                 transformPipeline.GetModelViewProjectionMatrix(),
                                 vGrey);
    floorBatch.Draw();

    // Draw the static spheres
    for (int i = 0; i < NUM_SPHERES; ++i)
    {
        modelViewMatrix.PushMatrix();
        modelViewMatrix.MultMatrix(spheres[i]);
        shaderManager.UseStockShader(GLT_SHADER_FLAT,
                                     transformPipeline.GetModelViewProjectionMatrix(),
                                     vBlue);
        sphereBatch.Draw();
        // Draw the sphere's wireframe
        glPolygonOffset(-1.0f, -1.0f);      // Shift depth values
        glEnable(GL_POLYGON_OFFSET_LINE);   // our important offset
        glEnable(GL_LINE_SMOOTH);           // fancy smooth lines
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        glLineWidth(1.5f);

        shaderManager.UseStockShader(GLT_SHADER_FLAT,
                                     transformPipeline.GetModelViewProjectionMatrix(),
                                     vDBlue);
        sphereBatch.Draw();
        // put everything back
        glDisable(GL_LINE_SMOOTH);
        glDisable(GL_BLEND);
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glDisable(GL_POLYGON_OFFSET_LINE);
        glLineWidth(4.0f);

        modelViewMatrix.PopMatrix();
    }

    // Move our objects into the screen and up, above the floor
    modelViewMatrix.Translate(0.0f, 0.5f, -4.5f);   // move it
    // and save
    modelViewMatrix.PushMatrix();

    // Position the cylinder
    modelViewMatrix.Rotate(90, 1.0f, 0.0, 0.0f);    // make the cylinder stand up
    modelViewMatrix.Rotate(yRot, 0.0f, 0.0, 1.0f);  // spin it
    // Draw the cylinder
    shaderManager.UseStockShader(GLT_SHADER_FLAT,
                                 transformPipeline.GetModelViewProjectionMatrix(),
                                 vRed);
    cylinderBatch.Draw();

    // Draw the cylinder wireframe
    glPolygonOffset(-1.0f, -1.0f);      // Shift depth values
    glEnable(GL_POLYGON_OFFSET_LINE);   // our important offset
    glEnable(GL_LINE_SMOOTH);           // fancy smooth lines
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glLineWidth(2.5f);

    shaderManager.UseStockShader(GLT_SHADER_FLAT,
                                 transformPipeline.GetModelViewProjectionMatrix(),
                                 vMaroon);
    cylinderBatch.Draw();
    // Put everything back the way we found it
    glDisable(GL_LINE_SMOOTH);
    glDisable(GL_BLEND);
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glDisable(GL_POLYGON_OFFSET_LINE);
    glLineWidth(1.0f);

    // Position the orbiting sphere
    // clear the last rotations
    modelViewMatrix.PopMatrix();

    // apply our new rotation and translation
    modelViewMatrix.Rotate(yRot, 0.0f, 1.0, 0.0f);  // spin it
    modelViewMatrix.Translate(0.8f,-0.5f, 0.0f);   // move it
    // Draw our sphere
    shaderManager.UseStockShader(GLT_SHADER_FLAT,
                                 transformPipeline.GetModelViewProjectionMatrix(),
                                 vBlue);
    sphereBatch.Draw();

    // Draw the sphere wireframe
    glPolygonOffset(-1.0f, -1.0f);      // Shift depth values
    glEnable(GL_POLYGON_OFFSET_LINE);   // our important offset
    glEnable(GL_LINE_SMOOTH);           // fancy smooth lines
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    glLineWidth(1.5f);

    shaderManager.UseStockShader(GLT_SHADER_FLAT,
                                 transformPipeline.GetModelViewProjectionMatrix(),
                                 vDBlue);
    sphereBatch.Draw();
    // Put everything back the way we found it
    glDisable(GL_LINE_SMOOTH);
    glDisable(GL_BLEND);
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glDisable(GL_POLYGON_OFFSET_LINE);
    glLineWidth(1.0f);

    // restore from camera matrix
    modelViewMatrix.PopMatrix();
    // restore the previous model view matrix
    modelViewMatrix.PopMatrix();

    // Swap buffers, and immediately refresh
    glutSwapBuffers();
    glutPostRedisplay();
}

// This function does any needed initialization on the rendering
// context. 
void SetupRC()
{
    // initialize our shaders
    shaderManager.InitializeStockShaders();

    // Enable depth testing
    glEnable(GL_DEPTH_TEST);
    // render the front and back of the polygons, and fill
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    // Background color
    glClearColor(0.9f, 0.9f, 0.9f, 1.0f );
  
    // This makes a torus
    //gltMakeTorus(torusBatch, 0.4f, 0.15f, 30, 30);
    // This generates a cylinder
    gltMakeCylinder(cylinderBatch,
                    0.5,    // base radius
                    0.5,    // top radius
                    1.0,    // length
                    16,     // slices
                    1);     // stacks
    // Generate a sphere
    gltMakeSphere(sphereBatch, 
                  0.1f,     // radius?
                  8,        // slices
                  8);       // stacks

    // Randomly place the spheres
    for (int i = 0; i < NUM_SPHERES; ++i)
    {
        GLfloat x = ((GLfloat)((rand() % 400) - 200) * 0.1f);
        GLfloat z = ((GLfloat)((rand() % 400) - 200) * 0.1f);
        GLfloat y = ((GLfloat)(rand() % 50) * 0.1f);

        spheres[i].SetOrigin(x, y, z);
    }

    // our floor
    floorBatch.Begin(GL_LINES, 324);
    for (GLfloat x = -20.0f; x <= 20.0f; x += 0.5)
    {
        floorBatch.Vertex3f(x, -0.55, 20.0f);
        floorBatch.Vertex3f(x, -0.55,-20.0f);
        floorBatch.Vertex3f( 20.00,-0.55f, x);
        floorBatch.Vertex3f(-20.00,-0.55f, x);
    }
    floorBatch.End();
}

///////////////////////////////////////////////////////////////////////////////
// Main entry point for GLUT based programs
int main(int argc, char* argv[])
{
    gltSetWorkingDirectory(argv[0]);
	
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(360, 360);
    glutCreateWindow("Actors");
    glutSpecialFunc(SpecialKeys);
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    
    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