欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MFC+OpenGL 屏幕坐标转OpenGL坐标

程序员文章站 2022-07-04 09:09:10
...

    最近在写一个例子用到了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();