文档详情

OpenGL坐标与屏幕坐标的转化

小***
实名认证
店铺
DOC
34.50KB
约5页
文档ID:158217396
OpenGL坐标与屏幕坐标的转化_第1页
1/5

屏幕坐标向OpenGL坐标转换收藏越燈很多人用OpenGL绘图会遇到一个问题即屏幕坐标向OpenGL坐标转换,在网上流传着如下类似的代码:GLintviewport[4];GLdoublemodelview[16];GLdoubleprojection[16];GLfloatwinX,winY,winZ;GLdoubleposX,posY,posZ;glGetIntegerv(GL_VIEWPORT,viewport);glGetDoublev(GL_MODELVIEW_MATRIX,modelview);glGetDoublev(GL_PROJECTION_MATRIX,projection);winX=(float)x;winY=viewport[3]-(float)y;glReadPixels((int)winX,(int)winY,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&winZ);gluUnProject(winX,winY,winZ,modelview,projection,viewport,&posX,&posY,&posZ);注:(x,y)是屏幕坐标,(winX,winY,winZ)是视景体坐标及深度坐标,(posX,posY,posZ是OpenGL坐标。

上述代码并不保险,只针对一种特殊情况才好使,即glViewport(0,0,screenWidth,screenHeight),screenWidth、screenHeight分别是客户区的宽和高,视口左下角坐标恰好是(0,0),并且未经过任何模型变换从屏幕坐标向OpenGL坐标要经过两步,第一步是屏幕坐标向视景体坐标转换,第二步是视景体坐标向OpenGL坐标转换上述代码中winX=(float)x;winY=viewport[3]-(float)y;反映第一步,gluUnProject是第二步一般说来,gluUnProject的转换是不会出问题的如何进行正确的转换呢?首先,在glGetlntegerv之前添上模型变换的代码,和绘图时使用的模型变换代码一样,另外必须保证平移,缩放,旋转的顺序和绘图时的一样其次,屏幕坐标向视景体坐标转换有两种方式(注意!在多视口情况下,活动视应当最后绘制,它将作为当前的视口,保证glGetlntegerv等取值函数能得到正确的值)①winx=xviewport[0];winy=screenHeightviewport[1]-y;viewport[0]=viewport[1]=0;②winx=x;winy=screenHeighty;第一种比较直观,前两句是将屏幕坐标转换为视景体内的坐标,后两句将视景体的左下角点坐标改为(0,0),因为在设置裁剪视口时,使用glViewport设置视口的左下角点坐标不一定是(0,0),而在视景体内的点其视景体坐标与左下角点是相对的,即把视景体坐标看作是坐标系原点。

第二种方式比较简略,但是同样的道理,只不过是glUnproject函数对winx和winy又做了一次转换好了,现在给出完整的代码,如下:GLintviewport[4];GLdoublemodelview[16];GLdoubleprojection[16];GLfloatwinX,winY,winZ;GLdoubleposX,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);viewplaincopytoclipboardprint?1. /*2. Transformapoint(columnvector)bya4x4matrix.Then,out=m*in3. Input:mthe4x4matrix,inthe4x1vector4. Output:outtheresulting4x1vector5. */6. staticvoidtransform_point(GLdoubleout[4],constGLdoublem[16],constGLdoublein[4])7.8.#defineM(row,col)m[col*4+row]9.out[0]=[3];[3];10.11.out[1]=M(0,0)*in[0]+M(0,1)*in[1]+M(0,2)*in[2]+M(0,3)*in[3];12. M(1,0)*in[0]+M(1,1)*in[1]+M(1,2)*in[2]+M(1,3)*in[3];13. out[2]=14. M(2,0)*in[0]+M(2,1)*in[1]+M(2,2)*in[2]+M(2,3)*in[3];15. out[3]=16. M(3,0)*in[0]+M(3,1)*in[1]+M(3,2)*in[2]+M(3,3)*in[3];17. #undefM18. }19. //gluProjectsourcecode(说明见OpenGLAPI文档)20. GLintgluProject(GLdoubleobjx,GLdoubleobjy,GLdoubleobjz,constGLdoublemodelMatrix[16],constGLdoubleprojMatrix[16],constGLintviewport[4],GLdouble*winx,GLdouble*winy,GLdouble*winz)21. {22. //matricetransformation23. GLdoublein[4],out[4];24. //initializematriceandcolumnvectorasatransformer25. in[0]=objx;26. in[1]=objy;27. in[2]=objz;28. in[3]=1.0;29. transform_point(out,modelMatrix,in);//乘以模型视图矩阵30. transform_point(in,projMatrix,out);//乘以投影矩阵31.//齐次向量的第四项不能为032.if(in[3]==0.0)33.returnGL_FALSE;34.//向量齐次化标准化35. in[0]/=in[3];36. in[1]/=in[3];37. in[2]/=in[3];38.//视口向量的作用39. *winx=viewport[0]+(1+in[0])*viewport[2]/2;40. *winy=viewport[1]+(1+in[1])*viewport[3]/2;41. *winz=(1+in[2])/2;42. returnGL_TRUE;43. }。

下载提示
相关文档
正为您匹配相似的精品文档