【OpenGL】鼠标点击获取世界坐标
标签(空格分隔): OpenGL
起因
因为最近在做图形学相关毕设,需要时间鼠标交互获取三维坐标(世界坐标系)。于是在网上查了一些博客与资料,放进自己代码中,效果怎么都不对。于是才自己静下心来,好好研究。
OpenGL中的坐标系
OpenGL总共有5个坐标系,它们分别是:
- 局部空间或称物体空间
- 世界空间
- 观察空间或称视觉空间
- 裁剪空间
- 屏幕空间
下面我按照我自己的理解简单说明一下这5个空间。
局部空间:即所有的物体在创建时,都会处在坐标原点的位置。
世界空间:我们需要在将不同的物体指定到各自的位置,这时就是需要运用到平移,缩放,旋转等矩阵操作,就是为了将物体从局部空间变化到世界空间。
观察空间:世界空间中不仅有物体,还有观察点(视点),物体以视点为原点所得到的坐标就是物体在观察空间中的坐标。
裁剪空间:将投影范围通过插值转化为CVV(Clip Coordinate System)以便于裁剪
屏幕空间:裁剪后的物体通过插值,计算出在窗口中的坐标,从而绘制出来。
下图是坐标系的变换流程图:
从一个空间变换为另一个空间(即从一个基变化为另一个基)是由矩阵来实现的。
局部空间到世界空间的变化矩阵称为模型矩阵
世界空间到观察空间的变化矩阵称为观察矩阵,具体矩阵推导请看:【转载】推导相机变换矩阵
观察空间到裁剪空间的变化矩阵称为投影矩阵,具体矩阵推导请看:【转载】深入探索透视投影变换
通过鼠标点击获取三维坐标
网上百度的代码基本都是这样:
void Get3Dpos(int x, int y, fVector3* pp) {
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX, winY, winZ;
GLdouble object_x, object_y, object_z;
int mouse_x = x;
int mouse_y = y;
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
winX = (float)mouse_x;
winY = (float)viewport[3] - (float)mouse_y - 1.0f;
glReadBuffer(GL_BACK);
glReadPixels(mouse_x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
gluUnProject((GLdouble)winX, (GLdouble)winY, (GLdouble)winZ, modelview, projection, viewport, &object_x, &object_y, &object_z);
*pp.x = object_x;
*pp.y = object_y;
*pp.z = object_z;
}
经过我在程序中测试,得到的坐标应该是视点坐标。而我想实现的是获得世界坐标系。这里就需要用矩阵对坐标系进行变化,由视点坐标系变为世界坐标系。
根据博客推导相机变换矩阵,观察矩阵的表示形式为(TR)-1,因此,从视点坐标变为世界坐标需要进行的变换为(TR)。
设视点的是世界坐标为(Tx,Ty,Tz),视点的UVN系统的基为U、V、N。
则