OpenGL坐标转换总结
2016-06-15 19:40
351 查看
前面整理过一个,不过后来感觉不是很对,这里重新写一下。先解释一下这个问题,在OpenGL编程中,经常会需要与用户的交互,比如对视图进行指定点旋转,获取模型坐标点等。而这些操作最方便的就是通过鼠标进行操作,但鼠标只能获得屏幕坐标,那么如何转换到OpenGL世界坐标就成了一个亟待解决的问题。
一、理论基础
主要需要的是一些OpenGL观察流程相关知识,但也不是十分必要,大致了解即可。
二、屏幕坐标转换成世界坐标
上面的函数的输入参数CPoint winpt可以由MFC的鼠标消息响应函数直接得到,当然,用其他语言应该也有相应的方法得到。
注意,网上有人认为需要增加视图已经做过的变换,个人认为不是很必要,因为modelview包含了需要的一切信息。
上面函数的关键语句是
gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
这就是通过模型变换矩阵,投影矩阵,视口矩阵,由窗口坐标得到GL世界坐标的方法。
三、世界坐标转换成屏幕坐标
语句类似,关键几句为
四、计算固定点经过模型变换后坐标
这也是一个常见的问题,这并不需要什么特别的函数,只要将modelview乘以固定点的齐次坐标即可,对于三维空间中的点,其齐次坐标为[x, y, z, 1],另外前面说过,modelvew是一个16个元素的数组,就是一个列序的4x4矩阵,因此正好可以进行矩阵相乘。
上面的m_mv获取是用
版权声明:本文为博主原创文章,未经博主允许不得转载。
[cpp] view
plain copy
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX, winY, winZ;
GLdouble posX, posY, posZ;
glPushMatrix();
// 变换要绘图函数里的顺序一样,否则坐标转换会产生错误
glScalef(m_srtMatrix[0], m_srtMatrix[1], m_srtMatrix[2]); // 缩放、平移、旋转变换
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); // 得到的是最后一个设置视口的参数
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);
http://www.opengl.org/sdk/docs/man/xhtml/gluUnProject.xml gluUnProject()
http://www.opengl.org/sdk/docs/man/xhtml/gluProject.xml gluProject()
http://blog.csdn.net/abcdef8c/article/details/6716737 屏幕坐标到opengl世界坐标转换
一、理论基础
主要需要的是一些OpenGL观察流程相关知识,但也不是十分必要,大致了解即可。
二、屏幕坐标转换成世界坐标
// 数据结构 struct Point3D { double x; double y; double z; }; // 函数体 Point3D CMultiViewerView::WinToGL(CPoint winpt) { Point3D glpt; GLint viewport[4]; GLdouble modelview[16]; GLdouble projection[16]; GLfloat winX, winY, winZ; GLdouble posX, posY, posZ; GLdouble last_posX, last_posY, last_posZ; GetGLContext(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushMatrix(); //缩放、平移、旋转等变换(不要加这些!!) // glMultMatrixf(m_mv); glGetIntegerv(GL_VIEWPORT, viewport); // 得到的是最后一个设置视口的参数 glGetDoublev(GL_MODELVIEW_MATRIX, modelview); glGetDoublev(GL_PROJECTION_MATRIX, projection); glPopMatrix(); winX = winpt.x; winY = viewport[3] - (float)winpt.y; glReadPixels((int)winX, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ); gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ); glpt.x = posX; glpt.y = posY; glpt.z = posZ; return glpt; } |
注意,网上有人认为需要增加视图已经做过的变换,个人认为不是很必要,因为modelview包含了需要的一切信息。
上面函数的关键语句是
gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
这就是通过模型变换矩阵,投影矩阵,视口矩阵,由窗口坐标得到GL世界坐标的方法。
三、世界坐标转换成屏幕坐标
语句类似,关键几句为
glPushMatrix(); glGetDoublev(GL_MODELVIEW_MATRIX, modelview); // 视图矩阵 glGetDoublev(GL_PROJECTION_MATRIX, projection); // 投影矩阵 glGetIntegerv(GL_VIEWPORT, viewport); // 视口 glPopMatrix(); gluProject( (GLdouble) x, (GLdouble) y, (GLdouble) z, modelview, projection, viewport, &posX, &posY, &posZ); |
这也是一个常见的问题,这并不需要什么特别的函数,只要将modelview乘以固定点的齐次坐标即可,对于三维空间中的点,其齐次坐标为[x, y, z, 1],另外前面说过,modelvew是一个16个元素的数组,就是一个列序的4x4矩阵,因此正好可以进行矩阵相乘。
struct Point3D { double x; double y; double z; }; glGetFloatv( GL_MODELVIEW_MATRIX, m_mv); Point3D CMecViewerView::TransPoint(Point3D centerpt) { Point3D transedpt; transedpt.x = m_mv[0]*centerpt.x + m_mv[4]*centerpt.y + m_mv[8]*centerpt.z + m_mv[12]*1; transedpt.y = m_mv[0+1]*centerpt.x + m_mv[4+1]*centerpt.y + m_mv[8+1]*centerpt.z + m_mv[12+1]*1; transedpt.z = m_mv[0+2]*centerpt.x + m_mv[4+2]*centerpt.y + m_mv[8+2]*centerpt.z + m_mv[12+2]*1; return transedpt; } |
版权声明:本文为博主原创文章,未经博主允许不得转载。
[cpp] view
plain copy
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLfloat winX, winY, winZ;
GLdouble posX, posY, posZ;
glPushMatrix();
// 变换要绘图函数里的顺序一样,否则坐标转换会产生错误
glScalef(m_srtMatrix[0], m_srtMatrix[1], m_srtMatrix[2]); // 缩放、平移、旋转变换
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); // 得到的是最后一个设置视口的参数
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);
http://www.opengl.org/sdk/docs/man/xhtml/gluUnProject.xml gluUnProject()
http://www.opengl.org/sdk/docs/man/xhtml/gluProject.xml gluProject()
http://blog.csdn.net/abcdef8c/article/details/6716737 屏幕坐标到opengl世界坐标转换
相关文章推荐
- Jenkins执行gradle任务提示Can't load log handler "4host-manager.org.apache.juli.FileHandler"
- APACHE默认模块功能说明
- 如何把一张照片用 Photoshop 做成动画背景效果?
- how to access and operate a binarry file ?
- Linux下使用libreoffice把doc转换成Pdf
- linux & windows porting
- docker 部署cassandra
- docker 部署cassandra
- linux内核研究(二)
- Linux实用工具(一)
- Centos中文输入法安装以及切换
- opencv内存管理器2-cvSeqPartition聚类
- OpenCV中IplImage图像格式与BYTE图像数据的转换
- 架构师之我见
- opensession和getCurrentSession区别
- Linux的启动过程或启动顺序
- 自定义注解实现AOP日志记录
- shell初涉
- Linux下ffmpeg安装与开发配置
- opencv 通道和深度和图像格式