Related Contents:
- OpenGL– An introduction to the graphics API
- OpenGL– Related terms explained
- OpenGL– Environment configuration
- OpenGL- Case 1- Draw a triangle
- OpenGL– Case 2 — Draw a square
- OpenGL– Image rip
- OpenGL–3D mathematics related (Vectors and Matrices)
- 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 ~