# How to move a rectangle properly?

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.

1. 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?
2. 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;
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};

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

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


If you want to move the rectangle as whole all you need to do is adding an offset to every vertex -which is also equivalent to multiplying each vertex with a translation matrix. What you need to do is simply, given that Vertex and Offset are both of type Vector3 which is something you can easily achieve (and will save a lot of headache

struct Vector3
{
float x;
float y;
float z;

// you also need to overload some arithmetic operators
}

for (int i=0; i < vertexCount; ++i)
vVerts += offset;


and for key hits you only set the offset value,

 if(key == GLUT_KEY_DOWN){offset.y -= 1;} // make sure to reset offset on key up


Keep in mind that this is not how vertices are usually transformed in OpenGL, eventhough it's acceptable it doesn't give you the advantage of using matrices and shaders.

From your question, it seems you are learning using OpenGL Super Bible 5th/6th which is something I don't recommend for a beginner please check my answer here for the reason, I recommend 4th edition for beginners and then learning the buffers and the more advanced stuff from 5th/6th.

• Actually the posts sounds like you recommend SB_5th/6th. If not what would you recommend? – チーズパン Oct 10 '13 at 14:51
• I recommend 4th edition for beginners.. and 5th/6th for upgrading from openGL 2.0 or DirectX – concept3d Oct 10 '13 at 15:21
• What are the diffrences? – チーズパン Oct 10 '13 at 21:56
• well with openGL 2 which is covered by 4th edition it will cover alot of the basic stuff that are deperecated but usually nececcary to understand the basic staff, while openGL 3 which covered by later versions is really designed for more experienced people (most of the features were actually deprecated because the industry doesn't need them for whatever reasons).. for example in your above code the super bible really writes almost all of the important classes to even begin drawing while in openGL 2 it's much easier to get started and understand the basic concepts – concept3d Oct 10 '13 at 22:06
• like transformations and textures without dealing with all the buffers and shaders, once you got a grasp of how openGL works it's safe to say you can get going with more advanced features. – concept3d Oct 10 '13 at 22:07