1. The official statement is as follows
Https://www.opengl.org/sdk/docs/man2/xhtml/gluProject.xml
Name
gluproject -map Object coordinates to window Coordinatesc, matching "Object coordinate system" "Win window coordinate system (coordinates origin at bottom left)"
Specification
Glint Gluproject (gldouble objx, gldouble objy, gldouble objz, const gldouble * model, const GLDOUBLE * proj, const GLin T * view, gldouble* WinX, gldouble* winy, gldouble* Winz);
Parameters
objx, objy, OBJZ
Specify the object coordinates.
Model
Specifies the current Modelview matrix (as from a Glgetdoublev call).
proj
Specifies the current projection matrix (as from a Glgetdoublev call).
View
Specifies the current viewport (as from a glgetintegerv call).
WinX, Winy, Winz
Return the computed window coordinates.
Description
Gluproject transforms the specified object coordinates into window coordinates using model, proj, and view. The result is stored in WinX, Winy, and Winz. A return value of Glu_true indicates success, a return value of Glu_false indicates failure.
2. Introduction to use
Convert a three-dimensional coordinate in space into two-dimensional coordinates, using this gluproject function
3. Original Code Analysis
The original code is very good, nice, first by looking at the code, to step-by-step analysis of its mathematical principles! Learn the code, but also to master the principles of mathematics, here is the key to growth!
Static voidTransform_point (gldouble out[4],ConstGldouble m[ -],ConstGldoubleinch[4]){#defineM (Row,col) M[col*4+row] out[0] = M (0,0) *inch[0] + M (0,1) *inch[1] + M (0,2) *inch[2] + M (0,3) *inch[3]; out[1] = M (1,0) *inch[0] + M (1,1) *inch[1] + M (1,2) *inch[2] + M (1,3) *inch[3]; out[2] = M (2,0) *inch[0] + M (2,1) *inch[1] + M (2,2) *inch[2] + M (2,3) *inch[3]; out[3] = M (3,0) *inch[0] + M (3,1) *inch[1] + M (3,2) *inch[2] + M (3,3) *inch[3];#undefM}//Gluproject Source code (instructions see OpenGL API documentation)Glint Gluproject (gldouble objx, gldouble objy, gldouble objz,ConstGldouble modelmatrix[ -],ConstGldouble projmatrix[ -], ConstGlint viewport[4], gldouble *winx, gldouble *winy, gldouble *Winz) { //Matrice TransformationGldoubleinch[4], out[4]; //initialize matrice and column vector as a transformer inch[0] =OBJX; inch[1] =objy; inch[2] =OBJZ; inch[3] =1.0; Transform_point ( out, Modelmatrix,inch);//Multiply model View matrixTransform_point (inch, Projmatrix, out);//multiply the projection matrix//the fourth item of the homogeneous vector cannot be 0 if(inch[3] ==0.0) returnGl_false; //Normalization of vector homogeneous inch[0] /=inch[3]; inch[1] /=inch[3]; inch[2] /=inch[3]; //the role of a viewport vector*winx = viewport[0] +(1 + in[0]) * viewport[2]/2; *winy = viewport[1] + (1+inch[1]) * viewport[3] /2; *winz = (1+inch[2]) /2; returnGl_true;}
The above source code can be seen:
(1) Observing the multiplication process of the matrix element and the column vector in the Transform_point function, it is known that the matrix is transferred and then multiplied by the column vectors. This is why the matrix multiplication of OpenGL follows the column principal, and the matrix parameter that we input when we use the Gluproject function is in the way of the row principal.
(2) from the sequence of the column vectors can be seen, a homogeneous representation of the 3D point is the Model matrix transformation (containing the camera's displacement, rotation, scaling and other geometric transformations), in the projection transformation (containing the camera's internal parameters, which is its own parameters), Finally, the 2D point represented by the homogeneous is limited to the current viewport using a viewport vector.
(3) According to the input and output of the function can be seen, the input 3D point is directly the fourth element of the vector in[3] is assigned to 1 and homogeneous, the output of the homogeneous representation is actually (winx,winy,1). Winz is not a third element of the homogeneous representation of a 2D coordinate projected in the viewport, and it carries a manifold meaning: on the surface, it represents the depth value on the viewport, and in fact it is due to the inaccuracy of the camera parameters (all camera models are simulations of the actual camera, Thus, it is impossible to completely accurately express the camera itself) and the calculation error in the matrix multiplication process; So if camera parameters are perfect for camera modeling and the computational process is error-free, then the Winz end result should be 0, The value returned by this parameter in the actual calculation should also be a number that approximates 0, and the size of the number reflects the total error. So we usually don't have to care about the parameters returned by Winz when using Gluproject.
(4) for the return (Winx,winy), the forum has a friend asked why the projection point and the actual point is about the image upside down. This is because the OpenGL window coordinate system default (0,0) point is the lower-left corner of the window, and usually the Windows window and general image coordinate systems (0,0) points default to the upper-left corner, so when we perform a point operation between this inconsistent coordinate system, one step winy = height –winy; The conversion.
Another source code explanation
Glint Gluproject (gldouble objx, gldouble objy, gldouble objz,ConstGldouble model[ -],ConstGldouble proj[ -],ConstGlint viewport[4], gldouble* Winx, gldouble * winy, gldouble *Winz) { /*Transformation Matrix*/gldouble objcoor[4]; Gldouble objproj[4], objmodel[4]; /*initilise Matrix and vector transform*/ //4x4 matrix must is multi to a 4 dimension vector (it a 1 x 4 matrix)//So we need to put the original vertex to a 4D vectorobjcoor[0] =OBJX; objcoor[1] =objy; objcoor[2] =OBJZ; objcoor[3] =1.0; //since the original vectors are in the standard base vectors (1, 0, 0), (0, 1, 0), (0, 0, 1), you need to first convert to the current model matrixTransform_point (Objmodel, model, Objcoor); //The vertices in the model matrix are then transformed into the matrix of the coordinate system in which the projection matrix is locatedTransform_point (Objproj, Proj, Objmodel); //Scale Matrix /*gldouble Scalemat[4][4] = {{0.5, 0, 0, Objpr0j[3]}, {0, 0.5, 0, objproj[3]}, {0, 0, 0.5, objproj[3]}, {1, 1, 1, 1}}; Gldouble Objprojtemp[4]; memcpy (objprojtemp, objproj, sizeof (OBJPROJTEMP); Transfrom_point (Objproj, Scalemat, objprojtemp); */ /*or the result of normalized between-1 and 1*/ if(objproj[3] ==0.0) returnGl_false; objproj[0]/= objproj[3]; objproj[1]/= objproj[3]; objproj[2]/= objproj[3]; /*In screen coordinates*/ //since the projection matrix is projected between [-1, 1], it is necessary to place the converted projection coordinates between [0, 1]//Finally, you can convert to screen coordinates in an offset rectangle (viewport[4] can simply think of an offset rectangle) #defineScale_from_0_to_1 (_pt) (((_pt) + 1)/2)objproj[0] = Scale_from_0_to_1 (objproj[0]); objproj[1] = Scale_from_0_to_1 (objproj[1]); objproj[2] = Scale_from_0_to_1 (objproj[2]); #undefScale_from_0_to_1 *winx = viewport[0] + objproj[0] * viewport[2]; *winy = viewport[1] + objproj[1] * viewport[3]; /*between 0 and 1*/*winz = objproj[2]; returngl_true; }
The basic idea is:
(1) The input vertex is transformed into the coordinate system of the Model View matrix through the model view matrix;
(2) The vertex in the Model view matrix is transformed into the projection matrix ;
(3) The Vertex is scaled to the mapping interval [0, 1]; it should be [-1, 1].
(4) The screen coordinates (2D coordinates) in the current 3D vertex are calculated by the position and size of the viewport;
Where, since the vertex is scaled to [0, 1],(1 + in[0]) * viewport[2]/2; the pixel of the width in the window coordinates is computed, one possible explanation is that the vertex coordinates are scaled to the range of [-1, 1].
In fact, Gluunproject and Gluproject are very similar, in fact, is gluporject the reverse process, but there are some mathematical operations to note:
(1) First, the input vertices need to be transformed from the viewport to [0, 1] ;
(2) The vertex is then scaled to [-1, 1] , which is the inverse matrix of the Scalemat matrix in the above code.
(3) then multiply the inverse matrix of the projection matrix;
(4) The last is to multiply the inverse matrix of the model view matrix;
Cognition of Gluproject function in OpenGL