Glint viewport [4];
Gldouble modelview [16];
Gldouble projection [16];
Glfloat winx, winy, WINZ;
Gldouble posx, Posy, posz;
Glgetintegerv (gl_viewport, viewport );
Glgetdoublev( gl_modelview_matrix, modelview );
Glgetdoublev( gl_projection_matrix, projection );
Winx = (float) X;
Winy = viewport [3]-(float) y;
Glreadpixels (INT) winx, (INT) winy, 1, 1, gl_depth_component, gl_float, & WINZ );
Gluunproject (winx, winy, WINZ, modelview, projection, viewport, & posx, & Posy, & posz );
Note: (x, y) is the screen coordinate, (winx, winy, WINZ) is the visual object coordinate and depth coordinate, (posx, Posy, posz is the OpenGL coordinate.
The above code is not safe. It can only be used in a special case, that is, glviewport (0, 0, screenwidth, screenheight). screenwidth and screenheight indicate the width and height of the customer zone respectively, the coordinates in the lower left corner of the view are (0, 0) without any model transformation.
Two steps are taken from the screen coordinate to the OpenGL coordinate. The first step is the screen coordinate to the visual body coordinate conversion, and the second step is the visual body coordinate to the OpenGL coordinate conversion. In the above Code, winx = (float) x; winy = viewport [3]-(float) y; indicates the first step. gluunproject is the second step. In general, the conversion of gluunproject is normal.
How can we perform the correct conversion? First, add the model transformation code before glgetintegerv, which is the same as the model transformation code used for drawing. In addition, you must ensure that the translation, scaling, and rotation order are the same as those used for drawing. Second, there are two ways to convert screen coordinates to Visual Object coordinates (note! In the case of multiple views, the motion view should be drawn at the end, and it will be used as the current view, ensuring that value functions such as glgetintegerv can get the correct value ). ① Winx = x-viewport [0]; winy = screenheight-viewport [1]-y; viewport [0] = viewport [1] = 0; ② winx = X; winy = screenheight-y ), when you set the cropping view, you can use glviewport to set the coordinate of the lower-left corner of the view, which is not necessarily (). the coordinate of the visual body is relative to that of the lower-left corner, that is, the visual object coordinate is considered as the coordinate system origin. The second method is relatively simple, but the same principle is that the glunproject function implements another conversion for winx and winy.
Now the complete code is provided as follows:
Glint viewport [4];
Gldouble modelview [16];
Gldouble projection [16];
Glfloat winx, winy, WINZ;
Gldouble posx, Posy, posz;
Glpushmatrix ();
// Transform the order in the drawing function is the same, otherwise the coordinate conversion will produce an error
Glscalef (m_srtmatrix [0], m_srtmatrix [1], m_srtmatrix [2]); // scaling, translation, rotation, and transformation
Glrotatef (m_srtmatrix [3], 1.0f, 0.0f, 0.0f );
Glrotatef (m_srtmatrix [4], 0.0f, 1.0f, 0.0f );
Glrotatef (m_srtmatrix [5], 0.0f, 0.0f, 1.0f );
Gltranslatef (m_srtmatrix [6], m_srtmatrix [7], m_srtmatrix [8]);
Glgetintegerv (gl_viewport, viewport); // you can obtain the last parameter for setting the view.
Glgetdoublev( gl_modelview_matrix, modelview );
Glgetdoublev( gl_projection_matrix, projection );
Glpopmatrix ();
Winx = X;
Winy = screenheight-y;
Glreadpixels (INT) winx, (INT) winy, 1, 1, gl_depth_component, gl_float, & WINZ );
Gluunproject (winx, winy, WINZ, modelview, projection, viewport, & posx, & Posy, & posz );