Chapter 5 of OpenGL blue book code errata and inertial coordinate system to interpret model transformation, opengl Blue Book
If you also find that, when you follow the tutorial code to complete the texture, the coordinates of the bottom and normal vertices are positive and negative, such as-1.0f,-1.0f, -The 1.0f vertex corresponds to 1.0f,-1.0f, and 1.0f in the coordinates of the world.
Where exactly is the problem?
Originally: objectFrame. GetCameraMatrix (mObjectFrame); // the code in the original book is GetMatrix, which obtains the orientation of the objectFrame, resulting in the opposite relationship between the vertex and the texture object.
The orientation in objectFrame is opposite to the default orientation of OpenGL. The getMatrix operation causes modelViewMatrix to perform a 180 ° rotation virtually. In view of this, we only need to obtain its camera matrix. This camera matrix records the rotation, scaling, and displacement of the current model. The result of the modelViewMatrix multiplication is the matrix from the world origin to the vertices of the model.
Here comes a concept I almost forgot: Inertial coordinates.
The origin of the world coordinate system uses the transformation matrix to locate the displacement, rotation (including orientation and definition of the inertial square direction), scaling (which has little impact on the world's vertex transformation, only the model has a great influence on its inertial point ). The actual rendering process is: World origin, mobile image brush (this concept is very important), rotating image brush, drawing the vertices of the model based on scaling. The positions of the vertices of the model are relative to those of the image painter. In more cases, the image painter is named as the Inertial Coordinate System of the model. From the world coordinate system to the painting brush (Model Inertial Coordinate System) is a model transformation matrix, model vertices are drawn by the model editor or drawing algorithm definition. The camera affects the final visible area. In some cases, the origin of the model inertial coordinate system is the current position of the camera.
If you use
// ModelViewMatrix. Translate (0.0f,-1.0f,-7.0f );
In this case, instead of obtaining the relative displacement matrix from camera, the Inertial Coordinate System of the model is relative to the origin of the world coordinate space.
As a result, the st ing of the texture map is clearly different from the 2D pixel operation.
OpenGL's st is the origin from the lower left corner, while the pixel operation in memory is the origin from the upper left corner.
# Include <GLTools. h> # include <GLMatrixStack. h> # include <GLGeometryTransform. h> # include <GLFrustum. h> # include <GLFrame. h> # include <GLShaderManager. h> # include <iostream> # include <math. h> # ifdef _ APPLE __# include <glut/glut. h> # else # define FREEGLUT_STATIC # include <GL/glut. h> # endifGLMatrixStack mvpMatrix; GLMatrixStack projectionMatrix; GLMatrixStack modelViewMatrix; GLFrustum viewFrustum; GLGeometryTransfor M transformPipeLine; GLFrame cameraFrame; GLFrame objectFrame; GLBatch pyramidBatch; GLuint textureID; GLShaderManager shaderManager; void ChangeSize (int w, int h) {if (h <= 0) {h = 1;} glViewport (0, 0, w, h); viewFrustum. setPerspective (35, float (w)/float (h), 1.0f, 1000.0f); projectionMatrix. loadMatrix (viewFrustum. getProjectionMatrix (); transformPipeLine. setMatrixStacks (modelViewMatrix, projectionMatrix );} // Load a TGA as a 2D Texture. completely initialize the statebool LoadTGATexture (const char * szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode) {GLbyte * pBits; int nWidth, nHeight, nComponents; GLenum eFormat; // Read the texture bitspBits = gltReadTGABits (szFileName, & nWidth, & nHeight, & nComponents, & eFormat); if (pBits = NULL) return false; glTexParameteri (GL_TEXTURE_2D, callback _ S, wrapMode); glTexParameteri (GL_TEXTURE_2D, gradient, wrapMode); glTexParameteri (inflow, inflow, minFilter); glTexParameteri (inflow, inflow, magFilter); glPixelStorei (cost, 1 ); glTexImage2D (GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits); free (pBits); if (minFilter = GL_LINEAR_MIPMAP_LINEAR | minFil Ter = GL_LINEAR_MIPMAP_NEAREST | minFilter = percent) glGenerateMipmap (GL_TEXTURE_2D); return true;} void MakePyramid (GLBatch & pyramidBatch) {// draw a triangle pyramidBatch at every three points. begin (GL_TRIANGLES, 18, 1); // the origin point is in the geometric center of the pyramid (in short, it is a non-focal point, a location higher than the center, and a height of 1/2) // the bottom, the initial normal is down. Check the source texture for the texture ing vertices ?? // Todo // if you look at it against the normal, the following three points are surrounded by a counter-clockwise pyramidBatch. normal3f (0.0f,-1.0f, 0.0f); pyramidBatch. multiTexCoord2f (0, 0.0f, 0.0f); pyramidBatch. vertex3f (-1.0f,-1.0f,-1.0f); pyramidBatch. normal3f (0.0f,-1.0f, 0.0f); pyramidBatch. multiTexCoord2f (0, 1.0f, 0.0f); pyramidBatch. vertex3f (1.0f,-1.0f,-1.0f); pyramidBatch. normal3f (0.0f,-1.0f, 0.0f); pyramidBatch. multiTexCoord2f (0, 1.0f, 1.0f); pyramidBatch. vertex3f (1.0f,-1. 0f, 1.0f); // if you look at the normal, the following three points are surrounded by a counter-clockwise pyramidBatch. normal3f (0.0f,-1.0f, 0.0f); pyramidBatch. multiTexCoord2f (0, 0.0f, 1.0f); pyramidBatch. vertex3f (-1.0f,-1.0f, 1.0f); pyramidBatch. normal3f (0.0f,-1.0f, 0.0f); pyramidBatch. multiTexCoord2f (0, 0.0f, 0.0f); pyramidBatch. vertex3f (-1.0f,-1.0f,-1.0f); pyramidBatch. normal3f (0.0f,-1.0f, 0.0f); pyramidBatch. multiTexCoord2f (0, 1.0f, 1.0f); pyramidBatch. vertex3f (1.0f, -1.0f, 1.0f ); // The direction of front and back in the original author's code is not relative to the field of view obtained by the observer. // the "front" is actually the front of the pyramid, that is, the first angle cannot see this surface. // The coordinates are M3DVector3f vApex = {0.0f, 1.0f, 0.0f}; M3DVector3f vFrontLeft = {-1.0f,-1.0f, 1.0f }; m3DVector3f vFrontRight = {1.0f,-1.0f, 1.0f}; M3DVector3f vBackLeft = {-1.0f,-1.0f,-1.0f}; M3DVector3f vBackRight = {1.0f,-1.0f,-1.0f }; m3DVector3f n; // Method Line, front m3dFindNormal (n, vApex, vFrontLeft, vFrontRight); py RamidBatch. normal3fv (n); pyramidBatch. multiTexCoord2f (0, 0.5f, 1.0f); pyramidBatch. vertex3fv (vApex); pyramidBatch. normal3fv (n); pyramidBatch. multiTexCoord2f (0, 0.0f, 0.0f); pyramidBatch. vertex3fv (vFrontLeft); pyramidBatch. normal3fv (n); pyramidBatch. multiTexCoord2f (0, 1.0f, 0.0f); pyramidBatch. vertex3fv (vFrontRight); // Method Line, left // m3dFindNormal (n, vApex, vBackLeft, vFrontLeft); // pyramidBatch. normal3fv (n); // pyr AmidBatch. multiTexCoord2f (0, 0.5f, 1.0f); // pyramidBatch. vertex3fv (vApex); // pyramidBatch. normal3fv (n); // pyramidBatch. multiTexCoord2f (0, 1.0f, 0.0f); // pyramidBatch. vertex3fv (vBackLeft); // pyramidBatch. normal3fv (n); // pyramidBatch. multiTexCoord2f (0, 0.0f, 0.0f); // pyramidBatch. vertex3fv (vFrontLeft); // method line, right // m3dFindNormal (n, vApex, vFrontRight, vBackRight); // pyramidBatch. normal3fv (n); // pyramidBatch. mul TiTexCoord2f (0, 0.5f, 1.0f); // pyramidBatch. vertex3fv (vApex); // pyramidBatch. normal3fv (n); // pyramidBatch. multiTexCoord2f (0, 1.0f, 0.0f); // pyramidBatch. vertex3fv (vFrontRight); // pyramidBatch. normal3fv (n); // pyramidBatch. multiTexCoord2f (0, 0.0f, 0.0f); // pyramidBatch. vertex3fv (vBackRight); /// Method Line, followed by // m3dFindNormal (n, vApex, vBackRight, vBackLeft); // pyramidBatch. normal3fv (n); // pyramidBatch. multiTexCoord2f (0, 0.5f, 1.0f); // pyramidBatch. vertex3fv (vApex); // pyramidBatch. normal3fv (n); // pyramidBatch. multiTexCoord2f (0, 0.0f, 0.0f); // pyramidBatch. vertex3fv (vBackRight); // pyramidBatch. normal3fv (n); // pyramidBatch. multiTexCoord2f (0, 1.0f, 0.0f); // pyramidBatch. vertex3fv (vBackLeft); pyramidBatch. end ();} void SetupRC (void) {glClearColor (0.7f, 0.7f, 0.7f, 1.0f); shaderManager. initializeStockShaders (); glable (GL_DEPTH _ TEST); glGenTextures (1, & textureID); glBindTexture (GL_TEXTURE_2D, textureID); LoadTGATexture ("stone. tga ", GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE); MakePyramid (pyramidBatch); cameraFrame. moveForward (-7.0f );//?? What is the purpose ??} Void RenderScene (void) {static GLfloat vLightPos [] = {1.0f, 1.0f, 0.f}; static GLfloat vWhite [] = {1.0f, 1.0f, 1.0f, 1.0f }; glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); modelViewMatrix. pushMatrix (); // {// process the paint brush position, that is, the model relative to the camera location M3DMatrix44f mCamera; cameraFrame. getCameraMatrix (mCamera); modelViewMatrix. multMatrix (mCamera); // modelViewMatrix. translate (0.0f,-1.0f,-7.0f); // Process The model rotates or scales the M3DMatrix44f mObjectFrame; objectFrame. getCameraMatrix (mObjectFrame); // the code in the original book is GetMatrix, which obtains the orientation of the objectFrame. As a result, the relationship between the vertex and the texture object appears in the opposite content: modelViewMatrix. multMatrix (mObjectFrame); glBindTexture (GL_TEXTURE_2D, textureID); shaderManager. useStockShader (GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF, transformPipeLine. getModelViewMatrix (), transformPipeLine. getProjectionMatrix (), vLightPos, vWhite, 0); pyramidBatch. draw (); //} ModelViewMatrix. popMatrix (); fig ();} void ShutdownRC (void) {glDeleteTextures (1, & textureID);} void SpecialKeys (int key, int x, int y) {if (key = maid) {objectFrame. rotateWorld (m3dDegToRad (5.0f), 1.0f, 0.0f, 0.0f); // The operation of the model and camera is the opposite. The model is rotated up to 5.0f} if (key = glu_key_down) {objectFrame. rotateWorld (m3dDegToRad (-5.0f), 1.0f, 0.0f, 0.0f);} if (key = fig) {objectFrame. rotateWorld (m3dDe GToRad (5.0f), 0.0f, 1.0f, 0.0f);} if (key = fig) {objectFrame. rotateWorld (m3dDegToRad (-5.0f), 0.0f, 1.0f, 0.0f);} fig ();} int main (int argc, char * argv []) {values (argv [0]); gluinit (& argc, argv); gluinitdisplaymode (glu_double | glu_rgba | glu_depth | glu_stencer); gluinitwindowsize (800,600 "); glutReshapeFunc (ChangeSize ); LFunc (SpecialKeys); gludisplayfunc (RenderScene); GLenum err = glewInit (); if (GLEW_ OK! = Err) {fprintf (stderr, "GLEW Error: % s \ n", glewGetErrorString (err); return 1 ;}setuprc (); glumainloop (); ShutdownRC (); return 0 ;}
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.