OpenGL坐标转换总结

前面整理过一个,不过后来感觉不是很对,这里重新写一下。先解释一下这个问题,在OpenGL编程中,经常会需要与用户的交互,比如对视图进行指定点旋转,获取模型坐标点等。而这些操作最方便的就是通过鼠标进行操作,但鼠标只能获得屏幕坐标,那么如何转换到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 winXwinYwinZ  
    GLdouble posXposYposZ;
    GLdouble last_posXlast_posYlast_posZ;
    GetGLContext();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glPushMatrix();    
    //缩放、平移、旋转等变换(不要加这些!!)
    // glMultMatrixf(m_mv);
    glGetIntegerv(GL_VIEWPORTviewport); // 得到的是最后一个设置视口的参数  
    glGetDoublev(GL_MODELVIEW_MATRIXmodelview);   
    glGetDoublev(GL_PROJECTION_MATRIXprojection);   
    glPopMatrix();   
    winX winpt.x  
    winY viewport[3] (float)winpt.y  
    glReadPixels((int)winX(int)winY1, 1, GL_DEPTH_COMPONENTGL_FLOAT&winZ);   
    gluUnProject(winXwinYwinZmodelviewprojectionviewport&posX&posY&posZ);
    glpt.x posX;
    glpt.y posY;
    glpt.z posZ;
    return glpt;
}
上面的函数的输入参数CPoint winpt可以由MFC的鼠标消息响应函数直接得到,当然,用其他语言应该也有相应的方法得到。
注意,网上有人认为需要增加视图已经做过的变换,个人认为不是很必要,因为modelview包含了需要的一切信息。
上面函数的关键语句是
 gluUnProject(winXwinYwinZmodelviewprojectionviewport&posX&posY&posZ);
这就是通过模型变换矩阵,投影矩阵,视口矩阵,由窗口坐标得到GL世界坐标的方法。
三、世界坐标转换成屏幕坐标
语句类似,关键几句为
glPushMatrix();
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);    // 视图矩阵
glGetDoublev(GL_PROJECTION_MATRIXprojection); // 投影矩阵
glGetIntegerv(GL_VIEWPORT, viewport);            // 视口
glPopMatrix();
gluProject   (GLdoublex,
        (GLdoubley,
        (GLdoublez,
        modelview,
        projection,
        viewport,
        &posX,
        &posY,
        &posZ);
四、计算固定点经过模型变换后坐标
这也是一个常见的问题,这并不需要什么特别的函数,只要将modelview乘以固定点的齐次坐标即可,对于三维空间中的点,其齐次坐标为[x, y, z, 1],另外前面说过,modelvew是一个16个元素的数组,就是一个列序的4x4矩阵,因此正好可以进行矩阵相乘。
struct Point3D
{
    double x;
    double y;
    double z;
};
glGetFloatvGL_MODELVIEW_MATRIXm_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;
}
上面的m_mv获取是用


[cpp]  view plain  copy
  1. GLint    viewport[4];   
  2.  GLdouble modelview[16];   
  3.  GLdouble projection[16];   
  4.  GLfloat  winX, winY, winZ;   
  5.  GLdouble posX, posY, posZ;   
  6.   
  7.  glPushMatrix();  
  8.    
  9.  // 变换要绘图函数里的顺序一样,否则坐标转换会产生错误  
  10.  glScalef(m_srtMatrix[0], m_srtMatrix[1], m_srtMatrix[2]); // 缩放、平移、旋转变换  
  11.  glRotatef(m_srtMatrix[3], 1.0f, 0.0f, 0.0f);  
  12.  glRotatef(m_srtMatrix[4], 0.0f, 1.0f, 0.0f);  
  13.  glRotatef(m_srtMatrix[5], 0.0f, 0.0f, 1.0f);  
  14.  glTranslatef(m_srtMatrix[6], m_srtMatrix[7], m_srtMatrix[8]);  
  15.   
  16.   
  17.  glGetIntegerv(GL_VIEWPORT, viewport); // 得到的是最后一个设置视口的参数  
  18.  glGetDoublev(GL_MODELVIEW_MATRIX, modelview);   
  19.  glGetDoublev(GL_PROJECTION_MATRIX, projection);   
  20.   
  21.  glPopMatrix();  
  22.   
  23.  winX = x;   
  24.  winY = screenHeight - y;  
  25.  glReadPixels((int)winX, (int)winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);   
  26.  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世界坐标转换


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值