Matrix Stack

Notes:

We modify the last exercise to use a matrix stack.

Source:

// MatrixStack.cpp
// Example of using a matrix stack

#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
GLBatch             floorBatch;         // floor

// 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);
}

// 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 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();

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

    // Draw the cylinder
    modelViewMatrix.Translate(0.0f, 0.5f, -4.5f);
    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
    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);

    // 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

    // 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("Matrix Stack");
    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