我有绘制立方体的示例代码。如何在不同的位置(使用平移矩阵)绘制其他立方体,以便能够绘制我所拥有的引擎的俄罗斯方块。
#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;
}
答案 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);
}