MFC之OpenGL 屏幕坐标转OpenGL坐标

    最近在写一个例子用到了OpenGL,OpenGL的中心点(0, 0)点刚好是我们屏幕的中心点。因为我是需要动态的作图(画点、线、圆、弧...)需要平移 缩放图形,所以我在坐标转换这个问题上卡住了。

    鼠标点击屏幕上的一点可以很方便的获得通过OnLButtonDown(),但是把取到的屏幕点转到OpenGL对应点却需要做相应的计算。用到的核心函数是gluUnProject(),如下:

glPushMatrix();	//与之相对应的glPopMatrix()也一定不能少

//这里的变换需要和绘图时一致,否则坐标会产生错误
glScalef(...);		//缩放
glRotatef(...);		//旋转
glTranslatef(...);	//平移

glGetIntegerv( GL_VIEWPORT,viewport );	//得到的是最后一个设置视口的参数
glGetDoublev( GL_MODELVIEW_MATRIX, modelview ); 
glGetDoublev( GL_PROJECTION_MATRIX, projection ); 

glPopMatrix();  

winX = (float)point.x;
winY = (float)viewport[3] - (float)point.y;
glReadPixels(point.x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);

 

    从屏幕坐标向OpenGL坐标转换需要经过两步:第一步是屏幕坐标向视景体坐标转换,第二步是视景体坐标向OpenGL坐标转换。上述代码中winX = (float)point.x; winY = (float)viewport[3] - (float)point.y;反映第一步,gluUnProject()是第二步。一般说来,gluUnProject()的转换是不会出问题的。

 

    想要不出现问题就必须:

1. 在glGetIntegerv()之前必须添上模型变换的代码,即和绘图时使用的模型变换代码一样;

2. 必须保证平移、缩放、旋转的顺序和绘图时的一致;另外,屏幕坐标向视景体坐标转换要正确;

3. 在多视口情况下,活动视口必须最后绘制,使它作为当前的视口,这样才能保证glGetIntegerv()等取值函数能够得到正确的值;

    以下是我绘图时的代码,注意各种变换的顺序要和左边转换时一致

glPushMatrix();

glLoadIdentity();
glScalef(...);
glRotatef(...);
glTranslatef(...);

//两条坐标轴
glBegin(GL_LINES );
glColor3f(0.5f,1.0f,1.0f);
glVertex2f(ptStartX, ptStartY);
glVertex2f(ptEndX, ptEndY);
glEnd();

glPopMatrix();

 

你可能感兴趣的:(MFC,OpenGL)