我画了一个四边形,把相机移到一个位置,然后点取四边形,根据点取的坐标,
我想获得它在世界坐标系的坐标,但是对返回的值有点疑惑。
代码如下:#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>int MOUSE_BUTTON = -1;
int MOUSE_POS_X = 0;
int MOUSE_POS_Y = 0;void display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity (); /* clear the matrix */
glColor3f (1.0, 1.0, 1.0); glTranslatef(0.0f, 0.0f, -3.0f);
glPushMatrix();
{
glTranslatef(0.0f, 0.0f, -2.0f);
glBegin( GL_QUADS );
{
glVertex3f( 0.0f, 0.0f, 0.0f );
glVertex3f( 1.0f, 0.0f, 0.0f );
glVertex3f( 1.0f, 1.0f, 0.0f );
glVertex3f( 0.0f, 1.0f, 0.0f );
}
glEnd();
}
glPopMatrix(); if ( MOUSE_BUTTON == GLUT_LEFT_BUTTON )
{
GLint viewport[ 4 ];
GLdouble projection[ 16 ];
GLdouble modelview[ 16 ];
GLfloat winX,winY,winZ;
GLdouble posX,posY,posZ; glGetIntegerv( GL_VIEWPORT, viewport );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetDoublev( GL_MODELVIEW_MATRIX, modelview ); winX = (GLfloat)MOUSE_POS_X;
winY = (GLfloat)( viewport[3] - MOUSE_POS_Y );
glReadBuffer(GL_BACK);
glReadPixels( winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ ); gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ ); printf( "screen = %f,%f,%f\n", winX, winY, winZ );
printf( "world = %f,%f,%f\n", posX, posY, posZ ); MOUSE_BUTTON = -1;
}
glutSwapBuffers();
}void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
glEnable( GL_DEPTH_TEST );
}
void mouse_func(int button, int state, int x, int y)
{
if ( state == GLUT_UP )
{
MOUSE_BUTTON = button;
MOUSE_POS_X = x;
MOUSE_POS_Y = y;
display();
}
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective( 45.0f, w/h, 0.1, 100.0 );
glMatrixMode (GL_MODELVIEW);
}void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
}
}int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (500, 400);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse_func);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
从上面看,我觉得四边形的z值应该是-5吧,
但是得到的是-2,第一个translate的z值无论怎么改,得到的值都是-2,
如果把glPushMatrix和glPopMatrix去掉,取得的永远是0
应该怎么理解呢?谢谢
我想获得它在世界坐标系的坐标,但是对返回的值有点疑惑。
代码如下:#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>int MOUSE_BUTTON = -1;
int MOUSE_POS_X = 0;
int MOUSE_POS_Y = 0;void display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity (); /* clear the matrix */
glColor3f (1.0, 1.0, 1.0); glTranslatef(0.0f, 0.0f, -3.0f);
glPushMatrix();
{
glTranslatef(0.0f, 0.0f, -2.0f);
glBegin( GL_QUADS );
{
glVertex3f( 0.0f, 0.0f, 0.0f );
glVertex3f( 1.0f, 0.0f, 0.0f );
glVertex3f( 1.0f, 1.0f, 0.0f );
glVertex3f( 0.0f, 1.0f, 0.0f );
}
glEnd();
}
glPopMatrix(); if ( MOUSE_BUTTON == GLUT_LEFT_BUTTON )
{
GLint viewport[ 4 ];
GLdouble projection[ 16 ];
GLdouble modelview[ 16 ];
GLfloat winX,winY,winZ;
GLdouble posX,posY,posZ; glGetIntegerv( GL_VIEWPORT, viewport );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetDoublev( GL_MODELVIEW_MATRIX, modelview ); winX = (GLfloat)MOUSE_POS_X;
winY = (GLfloat)( viewport[3] - MOUSE_POS_Y );
glReadBuffer(GL_BACK);
glReadPixels( winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ ); gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ ); printf( "screen = %f,%f,%f\n", winX, winY, winZ );
printf( "world = %f,%f,%f\n", posX, posY, posZ ); MOUSE_BUTTON = -1;
}
glutSwapBuffers();
}void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
glEnable( GL_DEPTH_TEST );
}
void mouse_func(int button, int state, int x, int y)
{
if ( state == GLUT_UP )
{
MOUSE_BUTTON = button;
MOUSE_POS_X = x;
MOUSE_POS_Y = y;
display();
}
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective( 45.0f, w/h, 0.1, 100.0 );
glMatrixMode (GL_MODELVIEW);
}void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
break;
}
}int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize (500, 400);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(mouse_func);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
从上面看,我觉得四边形的z值应该是-5吧,
但是得到的是-2,第一个translate的z值无论怎么改,得到的值都是-2,
如果把glPushMatrix和glPopMatrix去掉,取得的永远是0
应该怎么理解呢?谢谢
你把glTranslatef(0.0f, 0.0f, -3.0f);放到glPushMatrix();里面试试
看过它的源码,看不懂,
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity (); glColor3f (1.0, 1.0, 1.0);
glPointSize(3.0f); //第一次位移,得到矩阵M1
glTranslatef(0.0f, 0.0f, -5.0f); //绘制一个点
glPushMatrix();
{
glTranslatef(1.0f, 2.0f, -2.0f);//第二次位移,得到矩阵M2 glBegin( GL_POINTS );
glVertex3f( 0.0f, 0.0f, 0.0f );
glEnd();
}
glPopMatrix(); //鼠标单击上面绘制的点,由屏幕坐标转化为世界坐标,有一下几点疑惑:
//1. 无论我怎么改第一个glTranslate的z值,这个地方取得的世界坐标都是(0.0, 0.0, -2.0),
//2. 如果去掉glPushmatirx和glpopmatrix,得到的结果是(0.0, 0.0, 0.0)
//3. 为什么gluUnProject要用M1才能得到正确的结果?而且M1任意改变都不会影响结果
//请给我讲讲这里面的原理,谢谢 if ( MOUSE_BUTTON == GLUT_LEFT_BUTTON )
{
double posX,posY,posZ;
screen2world( MOUSE_POS_X, MOUSE_POS_Y, &posX, &posY, &posZ );
MOUSE_BUTTON = -1;
}
glutSwapBuffers();
}
void screen2world( int x, int y, double * posX, double * posY, double * posZ )
{
GLint viewport[ 4 ];
GLdouble projection[ 16 ];
GLdouble modelview[ 16 ];
GLfloat winX,winY,winZ;
glGetIntegerv( GL_VIEWPORT, viewport );
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
winX = (GLfloat)x;
winY = (GLfloat)( viewport[3] - y );
glReadBuffer(GL_BACK);
glReadPixels( winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
gluUnProject( winX, winY, winZ, modelview, projection, viewport, posX, posY, posZ );
printf( "screen = %f,%f,%f\n", winX, winY, winZ );
printf( "world = %f,%f,%f\n", *posX, *posY, *posZ );}
GLint GLAPIENTRY
gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz,
const GLdouble modelMatrix[16],
const GLdouble projMatrix[16],
const GLint viewport[4],
GLdouble *objx, GLdouble *objy, GLdouble *objz)
{
double finalMatrix[16]; //最终矩阵
double in[4];
double out[4]; __gluMultMatricesd(modelMatrix, projMatrix, finalMatrix); //finalMatrix = 世界变换*相机变换*投影变换
if (!__gluInvertMatrixd(finalMatrix, finalMatrix)) return(GL_FALSE); 逆矩阵(从投影坐标到世界坐标) in[0]=winx;//客户区窗口坐标x
in[1]=winy;//客户区窗口坐标y
in[2]=winz;//坐标z(深度)
in[3]=1.0; //w分量
//viewport[0] = 窗口左端坐标(在以ScreenCoordinate作坐标系的时候有用)viewport[2] = width viewport[3] = height
/* Map x and y from window coordinates */
in[0] = (in[0] - viewport[0]) / viewport[2]; // x([-1,+1]) = 2 *(screenPosX - screenLeft) / screenWidth - 1
in[1] = (in[1] - viewport[1]) / viewport[3]; // x([-1,+1]) = 2 *(screenPosY - screenTop) / screenHeight - 1
/* Map to range -1 to 1 */
in[0] = in[0] * 2 - 1;
in[1] = in[1] * 2 - 1;
in[2] = in[2] * 2 - 1; __gluMultMatrixVecd(finalMatrix, in, out); //将已经转化到标准设备空间的坐标*逆矩阵 = 世界空间坐标
if (out[3] == 0.0) return(GL_FALSE);
out[0] /= out[3]; out[3]为w分量,除w分量投影到三维空间
out[1] /= out[3];
out[2] /= out[3];
*objx = out[0]; //[objx,objy,objz] =[x,y,z]
*objy = out[1];
*objz = out[2];
return(GL_TRUE);
}
任何时刻都有个当前矩阵,pushmatrix是把当前矩阵压入栈,popmatrix把栈顶弹出替换当前矩阵,
变换函数gltranslate是把当前矩阵M * trans_V,它不会去操作栈。
MSDN: glPopMatrixError Codes
It is an error to push a full matrix stack, or to pop a matrix stack that contains only a single matrix. In either case, the error flag is set and no other change is made to the OpenGL state.The following are the error codes generated and their conditions.Error code Condition
GL_STACK_OVERFLOW glPushMatrix was called while the current matrix stack was full.
GL_STACK_UNDERFLOW glPopMatrix was called while the current matrix stack contained only a single matrix.
GL_INVALID_OPERATION glPushMatrix was called between a call to glBegin and the corresponding call to glEnd.
弹出栈的时候有下溢错误
用glGetDoublef( GL_MODELVIEW_MATRIX, modelview )取得当前矩阵。glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity (); glTranslatef(0.0f, 0.0f, -5.0f);
//得到矩阵1如下:
1.0, 0.0, 0.0, 0.0
0.0, 1.0, 0.0, 0.0
0.0, 0.0, 1.0, 0.0
0.0, 0.0, -5.0, 1.0//绘制一个点
//glPushMatrix();
{
glTranslatef(0.0f, 0.0f, -2.0f);
//得到矩阵2如下:
1.0, 0.0, 0.0, 0.0
0.0, 1.0, 0.0, 0.0
0.0, 0.0, 1.0, 0.0
0.0, 0.0, -7.0, 1.0 glBegin( GL_POINTS );
glVertex3f( 0.0f, 0.0f, 0.0f );
glEnd();
}
//glPopMatrix(); //鼠标单击上面绘制的点,由屏幕坐标转化为世界坐标
//屏蔽push和pop后,这里取得的modelview_matrix是矩阵2,
//但是unproject的z值一直是0.0
if ( MOUSE_BUTTON == GLUT_LEFT_BUTTON )
{
double posX,posY,posZ;
screen2world( MOUSE_POS_X, MOUSE_POS_Y, &posX, &posY, &posZ );
MOUSE_BUTTON = -1;
}