OpenGL帮助翻译立方体

时间:2014-03-13 06:45:35

标签: opengl translate

我有绘制立方体的示例代码。如何在不同的位置(使用平移矩阵)绘制其他立方体,以便能够绘制我所拥有的引擎的俄罗斯方块。

#include <glf.hpp>
#include <GL/freeglut.h>
#include <camera.h>

#define kEpsilon    1.0e-6f
#define kPI         3.1415926535897932384626433832795f
#define kHalfPI     1.5707963267948966192313216916398f
#define kTwoPI      2.0f*kPI
#define BUFFER_OFFSET(i) ((char *)NULL + (i))

namespace
{
    //path to shader files
    std::string const SHADER_VERT_SOURCE("../GL3_init/Basic.vsh"); //// relative to
    std::string const SHADER_FRAG_SOURCE("../GL3_init/Basic.fsh"); //// the executable path
    //cube data
    namespace cube {
        // (6 faces)(2 triangles/face)(3 vertices/triangle)
        const int NumVertices = 36;
        glm::vec4 points[NumVertices];
        glm::vec4 colors[NumVertices];

        // Vertices positions of a unit cube centered at origin
        glm::vec4 vertex_positions[8] = {
            glm::vec4( -0.5, -0.5, 0.5, 1.0),
            glm::vec4( -0.5, 0.5, 0.5, 1.0),
            glm::vec4( 0.5, 0.5, 0.5, 1.0),
            glm::vec4( 0.5, -0.5, 0.5, 1.0),
            glm::vec4( -0.5, -0.5, -0.5, 1.0),
            glm::vec4( -0.5, 0.5, -0.5, 1.0),
            glm::vec4( 0.5, 0.5, -0.5, 1.0),
            glm::vec4( 0.5, -0.5, -0.5, 1.0)
        };

        // RGBA colors
        glm::vec4 vertex_colors[8] = {
            glm::vec4( 0.0, 0.0, 0.0, 1.0),//black
            glm::vec4( 1.0, 0.0, 0.0, 1.0),//red
            glm::vec4( 1.0, 1.0, 0.0, 1.0),//yellow
            glm::vec4( 0.0, 1.0, 0.0, 1.0),//green
            glm::vec4( 0.0, 0.0, 1.0, 1.0),//blue
            glm::vec4( 1.0, 0.0, 1.0, 1.0),//magenta
            glm::vec4( 1.0, 1.0, 1.0, 1.0),//white
            glm::vec4( 0.0, 1.0, 1.0, 1.0) //cyan
        };

        // quad() generates two triangles for each face and assigns colors to the vertices
        int Index = 0;
        void quad( int a, int b, int c, int d )
        {
            colors[Index] = vertex_colors[a]; points[Index] = vertex_positions[a]; Index++;
            colors[Index] = vertex_colors[b]; points[Index] = vertex_positions[b]; Index++;
            colors[Index] = vertex_colors[c]; points[Index] = vertex_positions[c]; Index++;
            colors[Index] = vertex_colors[a]; points[Index] = vertex_positions[a]; Index++;
            colors[Index] = vertex_colors[c]; points[Index] = vertex_positions[c]; Index++;
            colors[Index] = vertex_colors[d]; points[Index] = vertex_positions[d]; Index++;
        }

        // generate 12 triangles: 36 vertices and 36 colors
        void colorcube()
        {
            quad( 1, 0, 3, 2 );
            quad( 2, 3, 7, 6 );
            quad( 3, 0, 4, 7 );
            quad( 6, 5, 1, 2 );
            quad( 4, 5, 6, 7 );
            quad( 5, 4, 0, 1 );
        }
    }

    //OpenGL Objects
    GLuint vao;
    GLuint buffer;
    GLuint program;
    //window
    int width = 800;
    int height = 600;
    //MVP
    glm::mat4 mProjection = glm::perspective(60.0f, float(width) / height, 0.1f, 1000.0f);
    Camera camera(glm::vec3(0.0f, 1.0f,-3.0f), glm::vec3(0.0f,0.0f,0.0f), glm::vec3(0.0f,1.0f,0.0f), mProjection);
    //uniform variables
    GLuint uMVP;
}

//create, compile and link shaders
bool initProgram()
{
    bool Validated(true);
    GLuint VertShaderName = glf::createShader(GL_VERTEX_SHADER, SHADER_VERT_SOURCE);
    GLuint FragShaderName = glf::createShader(GL_FRAGMENT_SHADER, SHADER_FRAG_SOURCE);
    program = glCreateProgram();
    glAttachShader(program, VertShaderName);
    glAttachShader(program, FragShaderName);
    glLinkProgram(program);
    glDeleteShader(VertShaderName);
    glDeleteShader(FragShaderName);    
    Validated = Validated && glf::checkProgram(program);

    if(Validated)
    {
        glUseProgram(program);
        //Associate  uniforms
        uMVP = glGetUniformLocation( program, "MVP");
        Validated = Validated && glf::checkError("initProgram - stage");
    }
}

// Create and initialize buffer object
bool initBuffer()
{
    bool Validated(true);
    glGenBuffers(1,&buffer);
    glBindBuffer( GL_ARRAY_BUFFER, buffer );
    glBufferData( GL_ARRAY_BUFFER, sizeof(cube::points) + sizeof(cube::colors),NULL,GL_STATIC_DRAW);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(cube::points), cube::points);
    glBufferSubData(GL_ARRAY_BUFFER, sizeof(cube::points), sizeof(cube::colors), cube::colors);
    return Validated;
}
// Create and bind vertex array object. Set pointer to vertex attributes
bool initVertexArray()
{
    bool Validated(true);
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    GLuint vPosition = glGetAttribLocation( program,"vPosition" );
    glEnableVertexAttribArray(vPosition);
    glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, 0);
    GLuint vColor = glGetAttribLocation( program, "vColor" );
    glEnableVertexAttribArray( vColor );
    glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(cube::points)) );
    return Validated;
}
// Setup GL state
bool beginGL()
{
    bool Validated(true);
    //setup the cube
    cube::colorcube();
    Validated = initProgram();
    if(Validated)
        Validated = initBuffer();
    if(Validated)
        Validated = initVertexArray();
    return Validated;
}
// Free memory
void endGL()
{
    glDeleteBuffers(1,&buffer);
    glDeleteProgram(program);
    glDeleteVertexArrays(1, &vao);    
}

///////////////////////////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
{
    // Clear the window with current clearing color
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    glClearBufferfv(GL_COLOR, 0, &glm::vec4(0.4f, 0.4f, 0.4f, 1.0f)[0]);
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);
    glEnable(GL_CULL_FACE);
    glEnable(GL_MULTISAMPLE);
    //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE);
    //setup Model View Projection

    glm::mat4 mMVP = camera.getprojection()*camera.ViewMatrix();

    glProgramUniformMatrix4fv(program, uMVP, 1, GL_FALSE, glm::value_ptr(mMVP));
    //Draw Cube


    glDrawArrays(GL_TRIANGLES,0,cube::NumVertices);

    // Flush drawing commands
    glutSwapBuffers();
    // Refresh the Window
    glutPostRedisplay();
    glDisable(GL_MULTISAMPLE);
}

///////////////////////////////////////////////////////////////////////////////
// A normal ASCII key has been pressed.
// In this case, space bar is pressed
void KeyPressFunc(unsigned char key, int x, int y)
{
    switch(key)
     {
       // controls for camera
       // add up/down and left/right controls
       case 'L':      camera.slide(.2, 0, 0); break;// slide camera right
       case 'L' + 32: camera.slide(-0.2, 0, 0); break; // slide camera left

       case 'U':      camera.slide(0, -0.2, 0); break;// slide camera down
       case 'U' + 32: camera.slide(0, 0.2, 0); break; // slide camera up

       case 'F':    camera.slide(0,0, 0.2); break; // slide camera forward
       case 'F' + 32: camera.slide(0,0,-0.2); break; //slide camera back
       // add pitch controls
       case 'P':      camera.pitch(-1.0); break;
       case 'P' + 32: camera.pitch( 1.0); break;
       // add yaw controls
       case 'Y':      camera.yaw(-1.0); break;
       case 'Y' + 32: camera.yaw( 1.0); break;
       // add roll controls
       case 'R':      camera.roll(1.0); break;
       case 'R' + 32: camera.roll(-1.0); break;
       // close with Esc
       case 27: exit(0); break;
     }
}

//////////////////////////////////////////////////////////////////////////////
// Window has changed size, or has just been created. In either case, we need
// to use the window dimensions to set the viewport and the projection matrix.
void ChangeSize(int w, int h)
{
    width = w; height = h;
    glViewport(0, 0, w, h);
    mProjection = glm::perspective(60.0f, float(width) / height, 0.1f, 1000.0f);
    camera.setprojection(mProjection);
}

// Main entry point for GLUT based programs
int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(width, height);
    glutCreateWindow("3D Demo");

    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        /* Problem: glewInit failed, something is seriously wrong. */
        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
        return 1;
    }

    if(beginGL()){
        glutReshapeFunc(ChangeSize);
        glutKeyboardFunc(KeyPressFunc);
        glutDisplayFunc(RenderScene);
        glutCloseFunc(endGL);
        glutMainLoop();
        return 0;
    }
    return 1;
}

1 个答案:

答案 0 :(得分:1)

RenderScene中,您可以使用以下行来绘制多个立方体:

glm::mat4 mMVP = camera.getprojection()*camera.ViewMatrix();

for(int i = 0; i < 10; i++)
{
   glm::mat4 finalM = mMVP * a_function_that_creates_a_translation_matrix(x, y, z);

   glProgramUniformMatrix4fv(program, uMVP, 1, GL_FALSE, glm::value_ptr(finalM));

   glDrawArrays(GL_TRIANGLES,0,cube::NumVertices);
}