Related Contents:

  1. OpenGL– An introduction to the graphics API
  2. OpenGL– Related terms explained
  3. OpenGL– Environment configuration
  4. OpenGL- Case 1- Draw a triangle
  5. OpenGL– Case 2 — Draw a square
  6. OpenGL– Image rip
  7. OpenGL–3D mathematics related (Vectors and Matrices)
  8. OpenGL– Matrix transformations and matrix stacks

In previous example 1, we drew a triangle using OpenGL. Next, we draw a square together, and control the square through the keyboard to move up, down, left and right. Let’s play

implementation

First of all, the preparation work here does not do redundant elaboration, you can go to case 1- Drawing a triangle to view, here mainly introduces how to draw a square, and then how to achieve the keyboard control of its movement up, down, left and right.

Draw a square

1. Set the square side lengths and vertex coordinates

//
GLfloat blockSize = 0.2 f;

// 4 points of the square
GLfloat vVerts[] = {
        -blockSize,-blockSize,0.0 f,
        blockSize,-blockSize,0.0 f,
        blockSize,blockSize,0.0 f,
        -blockSize,blockSize,0.0 f
};
Copy the code

2. Render Settings

The method is the same as the previous method of drawing triangles, but the metalinkage method is changed to GL_TRIANGLE_FAN

void setupRC(a){
    // Set the clear screen color (background color)
    glClearColor(0.0 f.0.0 f.0.7 f.1);
    // No rendering can be done in the OpenGL core framework without shaders. Initialize a render manager.
    //
    shaderManager.InitializeStockShaders();
    
    // Change to GL_TRIANGLE_FAN with 4 vertices
    triangleBatch.Begin(GL_TRIANGLE_FAN, 4);
    triangleBatch.CopyVertexData3f(vVerts);
    triangleBatch.End();
}
Copy the code

Meta link mode (Supplement)

Figure yuan describe
GL_POINTS Each vertex is a separate point on the screen
GL_LINES Each pair of vertices defines a line segment
GL_LINE_STRIP A line drawn from the first vertex through each successive vertex
GL_LINE_LOOP Same as GL_LINE_STRIP, but the last vertex is connected to the first vertex
GL_TRIANGLES A new triangle is defined for every three vertices
GL_TRIANGLE_STRIP A group of triangles that share vertices on a strip
GL_TRIANGLE_FAN A group of triangles fan-shaped around a dot and sharing adjacent vertices

The following is an example:

3. Rendering effect

The code similar to that in case 1 has been omitted, so let’s see what happens:

We can see that the square we want has been drawn successfully, so we can proceed to the next step, how to control the square movement through the keyboard?

Realize keyboard control movement

In case 1, we use the ChangeSize callback registered by the glutReshapeFunc function to redraw the window when it changes. Now let’s look at this new function

GLUT_KEY_UP, GLUT_KEY_DOWN, GLUT_KEY_LEFT and GLUT_KEY_RIGHT // x and y capture the position of the mouse point on the display window when the button event occurs. Note that x and y start at the top left corner (0,0) and end at the bottom right corner (windowWidth, Extern void APIENTRY glutSpecialFunc(void (*func)(int key, int x, int y)) OPENGL_DEPRECATED(10_0, 10_9); Extern void APIENTRY glutMouseFunc(void (*func)(int button, int state, int x, int y)) OPENGL_DEPRECATED(10_0, 10_9); Extern void APIENTRY glutKeyboardFunc(void (*func)(unsigned char key, int x, int y)) OPENGL_DEPRECATED(10_0, 10_9);Copy the code

Let’s implement the following callback function SpecialKeys:

// Special function callback
void SpecialKeys(int key, int x, int y){
    // Set the distance of each step, that is, the distance that the graph moves once the keyboard is pressed
    GLfloat stepSize = 0.05 f;
    
    // Take the x and y coordinates of any point as the initial coordinates
    // Take the coordinates of the upper left corner of the square
    GLfloat startX = vVerts[9];
    GLfloat startY = vVerts[10];
    
    // Key: up
    if (key == GLUT_KEY_UP) {
        startY += stepSize;
    }
    // Button: down
    if (key == GLUT_KEY_DOWN) {
        startY -= stepSize;
    }
    // Key: left
    if (key == GLUT_KEY_LEFT) {
        startX -= stepSize;
    }
    // Key: right
    if (key == GLUT_KEY_RIGHT) {
        startX += stepSize;
    }
      
    // Update the coordinates of four vertices
    / / the top left corner
    vVerts[9] = startX;
    vVerts[10] = startY;
    / / the bottom left corner
    vVerts[0] = vVerts[9];
    vVerts[1] = vVerts[10] - blockSize*2;
    / / the bottom right hand corner
    vVerts[3] = vVerts[0] + blockSize*2;
    vVerts[4] = vVerts[1];
    / / the top right corner
    vVerts[6] = vVerts[3];
    vVerts[7] = vVerts[10];
    
    printf("startX = %f, startY = %f\n", startX, startY);
    
    triangleBatch.CopyVertexData3f(vVerts);
    // The tag currently needs to be redrawn
    glutPostRedisplay();
}
Copy the code

Operation effect:

Optimization scheme

The boundary issue

Moving up, down, left, and right is already done, but if you keep moving in one direction you can move the square out of the boundary. Now do a little edge processing and add a judgment before SpecialKeys() updates the vertex coordinates:

// Edge collision processing
// When the square moves past the leftmost point
if (startX < 1.0 f) {
  startX = 1.0 f;
}
// When the square moves to the right
//1.0 - blockSize * 2 = Total side length - Square side length = position of leftmost point
if (startX > (1.0 - blockSize * 2)) {
  startX = 1.0 f - blockSize * 2;
}
// When the square moves to the bottom
//-1.0 - blockSize * 2 = Y (negative axis boundary) - square side length = the position of the lowest point
if (startY < 1.0 f + blockSize * 2 ) {
  startY = 1.0 f + blockSize * 2;
}
// When the square moves to the top
if (startY > 1.0 f) {
  startY = 1.0 f;
}
Copy the code

Execution effect:

Translation matrix

  • Defines a global variable to store the distance moved
// Matrix update is needed
GLfloat xPos = 0.0 f;
GLfloat yPos = 0.0 f;
Copy the code
  • Update xPos and yPos locations, collision detection
void SpecialKeys(int key, int x, int y) {
    GLfloat stepSize = 0.025 f;
    
    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;
    }
    
    // Collision detection
    if (xPos < (1.0 f + blockSize)) {
        xPos = 1.0 f + blockSize;
    }
    
    if (xPos > (1.0 f - blockSize)) {
        xPos = 1.0 f - blockSize;
    }
    
    if (yPos < (1.0 f + blockSize)) {
        yPos = 1.0 f + blockSize;
    }
    
    if (yPos > (1.0 f - blockSize)) {
        yPos = 1.0 f - blockSize;
    }
    glutPostRedisplay();
}
Copy the code
  • RenderScene method, set the matrix update
void RenderScene(void) {

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    
    GLfloat vRed[] = {1.0 f.0.0 f.0.0 f.0.0 f};
    
    M3DMatrix44f mFinalTransform,mTransfromMatrix,mRotationMartix;
    
    / / translation
    m3dTranslationMatrix44(mTransfromMatrix, xPos, yPos, 0.0 f);
    
    // Rotate 5 degrees for each translation
    static float yRot = 0.0 f;
    yRot += 5.0 f;
    m3dRotationMatrix44(mRotationMartix, m3dDegToRad(yRot), 0.0 f.0.0 f.1.0 f);
    
    // Merge the matrix results of rotation and movement into mFinalTransform
    m3dMatrixMultiply44(mFinalTransform, mTransfromMatrix, mRotationMartix);
    
    // Submit the matrix result to a fixed shader (flat shader) to draw
    shaderManager.UseStockShader(GLT_SHADER_FLAT,mFinalTransform,vRed);
    triangleBatch.Draw();
    
    // Execute swap cache
    glutSwapBuffers();
}
Copy the code

Case 2 – Demo Download

The last

The above content is about the two cases of OpenGL, you can download the demo to understand, do not understand the place welcome to communicate together in the following. We will continue to update OpenGL content, thanks for watching ~

Harmonious learning, not impatient ~