I recently started to learn OpenGL. Right now I finished the first chapter of the "OpenGL SuperBible". There were two examples. The first had the complete code and showed how to draw a simple triangle. The second example is supposed to show how to move a rectangle using SpecialKeys. The only code provided for this example was the SpecialKeys method. I still tried to implement it but I had two problems.
In the previous example I declared and instaciated vVerts in the SetupRC() method. Now as it is also used in the SpecialKeys() method, I moved the declaration and instantiation to the top of the code. Is this proper c++ practice?
I copied the part where vertex positions are recalculated from the book, but I had to pick the vertices for the rectangle on my own. So now every time I press a key for the first time the rectangle's upper left vertex is moved to (-0,5:-0.5). This ok because of
GLfloat blockX = vVerts[0]; //Upper left X
GLfloat blockY = vVerts[7]; // Upper left Y
But I also think that this is the reason why my rectangle is shifted in the beginning. After the first time a key was pressed everything works just fine. Here is my complete code I hope you can help me on those two points.
GLBatch squareBatch;
GLShaderManager shaderManager;
//Load up a triangle
GLfloat vVerts[] = {-0.5f,0.5f,0.0f,
0.5f,0.5f,0.0f,
0.5f,-0.5f,0.0f,
-0.5f,-0.5f,0.0f};
//Window has changed size, or has just been created.
//We need to use the window dimensions to set the viewport and the projection matrix.
void ChangeSize(int w, int h)
{
glViewport(0,0,w,h);
}
//Called to draw the scene.
void RenderScene(void)
{
//Clear the window with the 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};
shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);
squareBatch.Draw();
//perform the buffer swap to display the back buffer
glutSwapBuffers();
}
//This function does any needed initialization on the rendering context.
//This is the first opportunity to do any OpenGL related Tasks.
void SetupRC()
{
//Blue Background
glClearColor(0.0f,0.0f,1.0f,1.0f);
shaderManager.InitializeStockShaders();
squareBatch.Begin(GL_QUADS,4);
squareBatch.CopyVertexData3f(vVerts);
squareBatch.End();
}
//Respond to arrow keys by moving the camera frame of reference
void SpecialKeys(int key,int x,int y)
{
GLfloat stepSize = 0.025f;
GLfloat blockSize = 0.5f;
GLfloat blockX = vVerts[0]; //Upper left X
GLfloat blockY = vVerts[7]; // Upper left Y
if(key == GLUT_KEY_UP)
{
blockY += stepSize;
}
if(key == GLUT_KEY_DOWN){blockY -= stepSize;}
if(key == GLUT_KEY_LEFT){blockX -= stepSize;}
if(key == GLUT_KEY_RIGHT){blockX += stepSize;}
//Recalculate vertex positions
vVerts[0] = blockX;
vVerts[1] = blockY - blockSize*2;
vVerts[3] = blockX + blockSize * 2;
vVerts[4] = blockY - blockSize *2;
vVerts[6] = blockX+blockSize*2;
vVerts[7] = blockY;
vVerts[9] = blockX;
vVerts[10] = blockY;
squareBatch.CopyVertexData3f(vVerts);
glutPostRedisplay();
}
//Main entry point for GLUT based programs
int main(int argc, char** argv)
{
//Sets the working directory. Not really needed
gltSetWorkingDirectory(argv[0]);
//Passes along the command-line parameters and initializes the GLUT library.
glutInit(&argc,argv);
//Tells the GLUT library what type of display mode to use, when creating the window.
//Double buffered window, RGBA-Color mode,depth-buffer as part of our display, stencil buffer also available
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
//Window size
glutInitWindowSize(800,600);
glutCreateWindow("MoveRect");
glutReshapeFunc(ChangeSize);
glutDisplayFunc(RenderScene);
glutSpecialFunc(SpecialKeys);
//initialize GLEW library
GLenum err = glewInit();
//Check that nothing goes wrong with the driver initialization before we try and do any rendering.
if(GLEW_OK != err)
{
fprintf(stderr,"Glew Error: %s\n",glewGetErrorString);
return 1;
}
SetupRC();
glutMainLoop();
return 0;
}