The effect picture is as follows:

The overall flow chart is as follows

The following two parts are mainly needed:

  • Draw a square
  • Special key position movement function

Draw a square

In the previous triangle drawing, we have learned a basic process of graph drawing, so the square drawing is natural, just need to make the following modifications on the basis of the triangle code:

  • Defines the vertex to primordial distance, i.eSquare side length = blockSize * 2
GLfloat blockSize = 0.1 f;Copy the code
  • Modifying the vertex array
// verts GLfloat vVerts[] = {-blocksize, -blocksize, 0.0f, blockSize, -blocksize, 0.0f, blockSize, blockSize, 0.0f, - blockSize blockSize and 0.0 f,};Copy the code
  • Modify the connection mode of primitives in setupRC function
// Change GL_TRIANGLES to GL_TRIANGLE_FAN, using four vertices triangleBatch.begin (GL_TRIANGLE_FAN, 4);Copy the code

At this point, the square is drawn, and then we need to complete the square key control effect

Key control effect

Basically means that the square moves according to the up, down, left and right keys of the selection keyboard.

This effect can be implemented in two ways

  • Coordinate update mode
  • The matrix way

For example, if you have 100 pieces of clothing that need to be dyed the same color, you can choose to dye them one by one, or you can put 100 pieces into the VAT at the same time and dye them all together.

  • One of the things color-by-color refers to is coordinate updating, which works for graphs with fewer vertices,
  • When there are too many vertices in the graph, it is not appropriate to use coordinate update, so we need to use matrix to update at the same time.

Coordinate update mode

Vertices update their vertex coordinates relative to each other. This is done in SpecialKeys when the key is moved, and render is manually called.

The flow chart of the three custom functions is as follows:

I’m not going to explain the ChangeSize and RenderScene, we’ve already done that when we draw, but we’re going to focus on SpecialKeys

  • First you need to define a step size

  • Define x and y values for a relative vertex suppose the square is shown below, with D as the relative vertex

  • Update x and Y respectively according to the key direction

  • Without this step, when the graph moves to the edge, it will move to an area that is not visible on the screen. The following figure shows how the edge collision processing is calculated in four directions. I will not elaborate here

The specific code is as follows:

Void SpecialKeys(int key, int x, int y){GLfloat stepSize = 0.025f; // set the coordinates of the relative points GLfloat blockX = vVerts[0]; GLfloat blockY = vVerts[10]; printf("v[0] = %f\n",blockX); printf("v[10] = %f\n",blockY); 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; } // If (blockX < -1.0f) {blockX = -1.0f; If (blockX > (1.0f - blockSize * 2)) {blockX = 1.0f - if (blockX > (1.0f - blockSize * 2)) {blockX = 1.0f - blockSize * 2; If (blockY < -1.0f + blockSize * 2) {blockY = -1.0f if (blockY < -1.0f + blockSize * 2) {blockY = -1.0f + blockSize * 2; } if (blockY > 1.0f) {blockY = 1.0f; } printf("blockX = %f\n",blockX); printf("blockY = %f\n",blockY); // a vertex is more like x, y, and z vVerts[0] = blockX; vVerts[1] = blockY - blockSize * 2; printf("(%f,%f)\n",vVerts[0],vVerts[1]); vVerts[3] = blockX + blockSize * 2; vVerts[4] = blockY - blockSize * 2; printf("(%f,%f)\n",vVerts[3],vVerts[4]); vVerts[6] = blockX + blockSize * 2; vVerts[7] = blockY; printf("(%f,%f)\n",vVerts[6],vVerts[7]); vVerts[9] = blockX; vVerts[10] = blockY; printf("(%f,%f)\n",vVerts[9],vVerts[10]); / / update the vertex data triangleBatch. CopyVertexData3f (vVerts); RenderScene glutPostRedisplay(); }Copy the code

The matrix way

Mainly according to the x axis, y axis moving distance, generate a translation matrix, through the graph * translation matrix = moved graph, get the final effect

There are two functions involved: RenderScene and SpecialKeys

The flow of a custom function in matrix mode is as follows:

SpecialKeys function

  • Define the step size and two global variables (translation distance relative to x and y axes)
GLfloat xPos = 0.0f; GLfloat yPos = 0.0f; GLfloat yPos = 0.0f; GLfloat stepSize = 0.025 f;Copy the code
  • According to the moving direction, calculate the moving distance

  • The initial translation distance can be understood as the center of the square, i.e., the origin. When the graph moves, its center point also moves, so the edge movement distance we want to calculate is the translation distance between the two center stores

  • Manually trigger rerender

The concrete implementation is as follows:

Void SpecialKeys(int key, int x, int y){GLfloat stepSize = 0.025f; if (key == GLUT_KEY_UP) { yPos += stepSize; } if (key == GLUT_KEY_DOWN) { yPos -= stepSize; } if (key == GLUT_KEY_LEFT) { xPos -= stepSize; } if (key == GLUT_KEY_RIGHT) { xPos += stepSize; If (xPos < (-1.0f + blockSize)) {xPos = -1.0f + blockSize; } if (xPos > (1.0f-blocksize)) {xPos = 1.0f-blocksize; } if (yPos < (-1.0f + blockSize)) {yPos = -1.0f + blockSize; } if (yPos > (1.0f-blocksize)) {yPos = 1.0f-blocksize; } glutPostRedisplay(); }Copy the code

The main steps of RenderScene are as follows:

  • Clear a specific cache
  • The translation matrix is calculated according to the translation distance
  • In the position update mode, the cell shader is used. In the matrix mode, the matrix is 4 by 4. The cell shader is not enough, so the plane shader is used

The specific code is as follows

Void RenderScene(void) {//1. Remove one or a set of specific buffer glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); RGBA GLfloat vRed[] = {1.0f, 0.5f, 0.0f, 1.0f}; // Define matrix M3DMatrix44f mTransformMatrix; // m3dTranslationMatrix44(mTransformMatrix, xPos, yPos, 0.0f); // When cell shaders are not enough, use flat shaders // Parameter 1: storage shader type // Parameter 2: what matrix transformation to use // parameter 3: Color shaderManager. UseStockShader (GLT_SHADER_FLAT mTransformMatrix, vRed); // Submit the shader triangleBatch.draw (); glutSwapBuffers(); }Copy the code

See GithuB-02_ square key control for complete code