见过没有用opengl camera的3d动画,看了一下,是用的camera实现的,内部机制实际上还是openg

29327人阅读
几何数据——顶点位置,和标准向量(normal vectors),在OpenGL 管道raterization 处理过程之前可通过顶点操作(Vertex Operation)和基本组合操作改变这些数据。
Object Coordinates
对象的本地坐标系——任何变换之前的最初位置.为了变换(transformation)这些对象,可以调用glRotate(),glTranslatef(),glScalef()这些方法。
Eye Coordinates
使用GL_MODELVIEW矩阵和Object 坐标相乘所得。在OpenGL中用GL_MODELVIEW将对象对象空间(Object Space)变换到视觉空间(eye space)。GL_MODELVIEW
矩阵是模型矩阵(Model Matrix)和视觉矩阵(View Matrix)的组合&()。其中,Model
变换指的是将Object &Space转换到World Space
(译注:World Space值得是OpenGL中的三维空间),而View 变换是将World space变换到eye space。
注意:在OpenGL中没有单独的camera(view) matrix。因此,为了模拟camera或者view的变换,其中的场景(3D物体和光照)必须通过和view相反的方向变换。也就是说,OpenGL总是将camera定义在(0,0,0)点,并且强制在eye space坐标系的-Z轴方向,而且不能变换。关于GL_MODELVIEW
Matrix的详细资料可以查看此处:http://www.songho.ca/opengl/gl_transform.html#modelview
标准向量(Normal vectors)——从对象坐标系(Object coordinates)变换到视觉坐标系(eye coordinates),它是用来计算光照(lighting calculation)的.注意标准向量(Normal vectors)的变换和顶点的不同。其中视觉矩阵(view matrix)是GL_MODELVIEW逆矩阵的转置矩阵和标准向量(Normal
vector是)相乘所得,即:
更多关于标准向量变换(Normal Vector Transformation)的资料可连接到此处:http://www.songho.ca/opengl/gl_normaltransform.html
剪切面坐标系(Clip Coordinates)
视觉坐标系和GL_PROJECTION矩阵相乘,得到剪切面坐标系。GL_PROJECTION矩阵定义了可视的空间(截头锥体)(译注:关于什么是截头锥体,我还查了下资料,发现它是这个样子的:
,这个就是投影的效果啦)以及顶点数据如何投影到屏幕上(视角或者正交化(orthogonal)),它被称为剪切面坐标系的原因是(x,y,z)变换之后
要和±w比较。更多关于GL_PROJECTION矩阵的资料可见:http://www.songho.ca/opengl/gl_transform.html#projection
标准化设备坐标系(NDC)
将剪切面坐标系除以w所得(关于w的讨论可见此处:,http://www.songho.ca/math/homogeneous/homogeneous.html),它被称为视角除法(perspective division)
.它更像是窗口坐标系,只是还没有转换或者缩小到屏幕像素。其中它取值范围在3个轴向从-1到1标准化了。
窗口坐标系(Window Coordinates)/屏幕坐标系(Screen Coordinates)
将标准化设备坐标系(NDC)应用于视口转换。NDC将缩小和平移以便适应屏幕的透视。窗口坐标系最终传递给OpenGL的管道处理变成了fragment。glViewPort()函数
用来定义最终图片映射的投影区域。同样,glDepthRange()用来决定窗口坐标系的z坐标。窗口坐标系由下面两个方法给出的参数计算出来
glViewPort(x,y,w,h);
glDepthRange(n,f);
视口转换公式很简单,通过NDC和窗口坐标系的线性关系得到:
OpenGL 转换矩阵
OpenGL使用4x4矩阵变换。注意,这16个元素存储在1D数组中,这些元素按列顺序排列。假如你想以行为顺序排列,你需要转置该矩阵。
OpenGL有4中不用的矩阵:GL_MODELVIEW,GL_PROJECTION,GL_TEXTURE和GL_COLOR.你可以在
代码中使用glMatrixMode()函数改变当前的类型。例如,为了选择GL_MODELVIEW矩阵,可以这样:
glMatrixMode(GL_MODELVIEW);
---------------------------------------------------------------------------------------------------------------------------------------------
Model-View 矩阵(GL_MODELVIEW)
GL_MODELVIEW矩阵在一个矩阵中包含view矩阵和model 矩阵,为了变换view(camera),你需要将整个
场景施以逆变换。gluLookAt()用来设置viewing变换。
最右边的三个矩阵元素&(m12,&m13,&m14)
是用作位移变换的。m15元素是齐次坐标。(何为齐次坐标,参见:http://www.songho.ca/math/homogeneous/homogeneous.html),该元素是用来投影变换的。
3个元素集(m0,&m1,&m2),(m4,&m5,&m6)和(m8,&m9,&m10)
是用作欧拉变换和仿射变换,例如glRotate(),缩放glScalef().
注意这三个元素集实际上指得是3个正交坐标系:
(m0,&m1,&m2):
+X 轴,向左的向量(left vector)(估计是相对屏幕自己来说),默认为(1,0,0)
(m4,&m5,&m6)
: & +Y轴,向上的向量(up vector),默认为(0,1,0)
(m8,&m9,&m10):
&+Z轴,向前的向量,默认为(0,0,1).
4 columns of GL_MODELVIEW matrix
我们能够不使用OpenGL变换函数,直接构造GL_MODELVIEW矩阵。下面有一些有用的代码构建
GL_MODELVIEW矩阵
1. Angles to Axes &
2. Lookat to Axes
3. Matrix4 class
注意,OpenGL在多种变换同时施加到顶点上时以相反的顺序矩阵相乘。例如,假如一个顶点先以MA
进行变换,然后再以MB&进行变换。OpenGL首先在乘以顶点之前运用MB&x&MA&。故最后的变换出现在矩阵相乘之前,最先的变换在最后出现。
投影矩阵Projection Matrix(GL_PROJECTION)
GL_PROJECTION矩阵用来定义截锥体。该截锥体决定了那些对象或者对象的哪些部分将会被裁剪掉。同样,它也决定着3D场景怎样投影到屏幕中
(关于怎样构建投影矩阵,请查看
http://www.songho.ca/opengl/gl_projectionmatrix.html
OpenGL提供2个函数用来GL_PROJECTION变换。glFrustum()产生投影视角。glOrtho()产生正交(或者平行)投影。
两个函数都需要6个参数决定6个剪切面:left, right, bottom, top, near, 和far 平面。截锥体的8个顶点如下所示:
OpenGL Perspective Viewing Frustum
远端平面(后面)的顶点能够简单地通过相似三角形的比率计算出来。例如,远端平面的左侧可以如下计算:
对于正交投影,ratio为1,所以远端平面的left,right,bottom和top值都与近端平面的值相同。
同样,你也可以使用gluPerspective()和gluOrtho2D()函数,但是传递更少的参数。gluPerspective()只需要4个参数:视图的垂直区域(vertical field of view(FOV)),
width/height的ratio,还有近端平面和远端平面的距离。下面代码使用gluPerspective()和glFrustum()实现同样的功能:
OpenGL正交的截锥体
OpenGL Orthographic Frustum
然而,假如你想要一个非对称的视觉空间,你可以直接使用glFrustum()。例如,
假如你想要呈现一个大的场景到2个相邻的屏幕,你可以截断截锥体变成2个不对称的截锥体(左和右)。然后,
呈现每个截锥体场景。
(这句话太不好翻译了,原位如下:
example, if you want to render a wide scene into 2 adjoining screens, you can break down the frustum into 2 asymmetric frustums (left and right). Then, render the scene with each frustum.
An example of an asymmetric frustum
纹理矩阵(GL_TEXTURE)
纹理坐标(s,t,r,q)在任何纹理映射之前乘以GL_TEXTURE矩阵所得,默认是恒等的。所以纹理映射到物体的位置将正好是你赋值给纹理坐标的位置。
通过改变GL_TEXTURE,你可以滑动,旋转,拉伸或者伸缩纹理。
颜色矩阵(GL_COLOR)
颜色部分是通过乘以GL_COLOR矩阵所得。该矩阵用于颜色空间和颜色组件的变换。(原位如下:It
can be used for color space conversion and color component swaping)
颜色矩阵并不是通用的,需要GL_ARB_imaging扩展(什么是GL_ARB_imaging扩展?求解)
其他矩阵例子
glPushMatrix()——将当前的矩阵压入矩阵栈
glPopMatrix()——从当前的矩阵栈中弹出当前的矩阵
glLoadIdentity()——设置当前矩阵为等同矩阵
glLoadMatrix{fd}(m)——将当前矩阵替换成矩阵m
glLoadTransposeMatrix{fd}(m)——将当前矩阵换成其转置矩阵
glMultMatrix{fd}(m)——将当前矩阵乘以矩阵m,并且更新当前矩阵
glMultTransposeMatrix{fd}(m)——将当前矩阵乘以其转置矩阵,并且更新当前矩阵
glGetFloatv(GL_MODELVIEW_MATRIX,&m)&——将GL_MODELVIEW矩阵的16个值加载到m中
例子1:ModelView
这个demo应用显示怎样使用glTranslatef()和glRotatef()操作GL_MODELVIEW
下载链接:
matrixModelView.zip: &&
http://www.songho.ca/opengl/files/matrixModelView.zip
(OS X 10.6+) matrixModelView_mac.zip: &&http://www.songho.ca/opengl/files/matrixModelView_mac.zip
注意所有的OpenGL函数在Mac和Windows下都在ModelGL.h和ModelGL.cpp中实现,在这些包中的这些文件是完全一样的。
该demo应用使用一个定制的4X4类(链接为:http://www.songho.ca/opengl/gl_matrix.html)作为默认的OpenGL矩阵例子,为了指定model和camera变换.
在ModelGL.cpp中有3中矩阵对象:matrixModel,matrixView和matrixModelView.每一种矩阵保存着预先计算好的变换。然后将这些矩阵元素传递给OpenGL的函数——glLoadMatrix().实际的画图程序应该向下面这个样子:
使用OpenGL默认的矩阵函数,相同的代码如下:
投影矩阵例子:
该 demo应用显示了如何使用glFrustum()和glOrtho()函数操作投影变换。
源码和二进制文件下载的链接:
matrixProjection.zip: &&
http://www.songho.ca/opengl/files/matrixProjection.zip
matrixProjection_mac.zip(OS X 10.6+): &&
http://www.songho.ca/opengl/files/matrixProjection_mac.zip
同样,ModelGL.h和ModelGL.cpp在两者的包中有同样的文件,且所有的OpenGL函数都置于这些文件中。
ModelGL类有一个定制的matrix对象:matrixProjection,两个成员函数:setFrustum()和setOrthoFrustum().
其功能与glFrustum()和glOrtho()函数相同
GL_PROJECTION矩阵构建的16个参数在这可以看到:
http://www.songho.ca/opengl/gl_projectionmatrix.html
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:108372次
积分:1584
积分:1584
排名:第15657名
原创:56篇
评论:39条
(1)(3)(1)(1)(1)(6)(2)(1)(1)(1)(3)(1)(1)(1)(8)(1)(5)(7)(9)(12)(2)//&=======================================================================//&function&:&UpdateOrientation//&purpose&&://&=======================================================================template&&typename&Elem_t&Graphic3d_Camera::TransformMatrices&Elem_t&&&&Graphic3d_Camera::UpdateOrientation&(TransformMatrices&Elem_t&&&theMatrices)&const{&&if&(theMatrices.IsOrientationValid())&&{&&&&return&theM&//&for&inline&accessors&&}&&theMatrices.InitOrientation();&&NCollection_Vec3&Elem_t&&anEye&(static_cast&Elem_t&&(myEye.X()),&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&static_cast&Elem_t&&(myEye.Y()),&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&static_cast&Elem_t&&(myEye.Z()));&&NCollection_Vec3&Elem_t&&aCenter&(static_cast&Elem_t&&(myCenter.X()),&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&static_cast&Elem_t&&(myCenter.Y()),&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&static_cast&Elem_t&&(myCenter.Z()));&&NCollection_Vec3&Elem_t&&anUp&(static_cast&Elem_t&&(myUp.X()),&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&static_cast&Elem_t&&(myUp.Y()),&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&static_cast&Elem_t&&(myUp.Z()));&&NCollection_Vec3&Elem_t&&anAxialScale&(static_cast&Elem_t&&(myAxialScale.X()),&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&static_cast&Elem_t&&(myAxialScale.Y()),&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&static_cast&Elem_t&&(myAxialScale.Z()));&&LookOrientation&(anEye,&aCenter,&anUp,&anAxialScale,&*theMatrices.Orientation);&&return&theM&//&for&inline&accessors}通过调用这个函数得到将世界坐标系变换到观察坐标系的变换矩阵。其实现步骤如下: v 平移观察坐标原点到世界坐标系原点; v 进行旋转,分别让观察坐标系的Vx, Vy, Vz轴对应到世界坐标的Wx,Wy,Wz轴。 OpenCASCADE中的实现代码如下所示: //&=======================================================================//&function&:&LookOrientation//&purpose&&://&=======================================================================template&&typename&Elem_t&void&Graphic3d_Camera::LookOrientation&(const&NCollection_Vec3&Elem_t&&&theEye,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&NCollection_Vec3&Elem_t&&&theLookAt,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&NCollection_Vec3&Elem_t&&&theUpDir,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&NCollection_Vec3&Elem_t&&&theAxialScale,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&NCollection_Mat4&Elem_t&&&theOutMx){&&NCollection_Vec3&Elem_t&&aForward&=&theLookAt&-&theE&&aForward.Normalize();&&//&side&=&forward&x&up&&NCollection_Vec3&Elem_t&&aSide&=&NCollection_Vec3&Elem_t&::Cross&(aForward,&theUpDir);&&aSide.Normalize();&&//&recompute&up&as:&up&=&side&x&forward&&NCollection_Vec3&Elem_t&&anUp&=&NCollection_Vec3&Elem_t&::Cross&(aSide,&aForward);&&NCollection_Mat4&Elem_t&&aLookMx;&&aLookMx.SetRow&(0,&aSide);&&aLookMx.SetRow&(1,&anUp);&&aLookMx.SetRow&(2,&-aForward);&&theOutMx.InitIdentity();&&theOutMx.Multiply&(aLookMx);&&theOutMx.Translate&(-theEye);&&NCollection_Mat4&Elem_t&&anAxialScaleMx;&&anAxialScaleMx.ChangeValue&(0,&0)&=&theAxialScale.x();&&anAxialScaleMx.ChangeValue&(1,&1)&=&theAxialScale.y();&&anAxialScaleMx.ChangeValue&(2,&2)&=&theAxialScale.z();&&theOutMx.Multiply&(anAxialScaleMx);}当指定投影变换类型后,可以得到投影变换矩阵,可以指定的类型如下: &&//!&Enumerates&supported&monographic&projections.&&//!&-&Projection_Orthographic&:&orthographic&projection.&&//!&-&Projection_Perspective&&:&perspective&projection.&&//!&-&Projection_Stere&&&&&&&&:&stereographic&projection.&&//!&-&Projection_MonoLeftEye&&:&mono&projection&for&stereo&left&eye.&&//!&-&Projection_MonoRightEye&:&mono&projection&for&stereo&right&eye.&&enum&Projection&&{&&&&Projection_Orthographic,&&&&Projection_Perspective,&&&&Projection_Stereo,&&&&Projection_MonoLeftEye,&&&&Projection_MonoRightEye&&};当指定为Projection_Orthographic时即为正投影变换。使用从坐标位置到观察平面的正投影变换,任意一点(x, y, z)的投影位置是(x, y)。因此在建立观察体的范围后,该矩形平行管道内部的坐标描述即为投影坐标,它们不需要另外的投影处理就可直接映射到规范化观察体normalized view volume。有些图形软件包使用单位立方体作为规范化观察体,其x,y,z坐标规范成0到1之间,另外的规范化变换方法使用坐标范围从-1到1的对称立方体。 由于屏幕坐标系经常指定为左手系,因此规范化观察体也常指定为左手系统。正投影观察体的规范化变换矩阵是:详细推导请参考《Computer Graphics with OpenGL》。 对应OpenCASCADE中实现代码如下所示: //&=======================================================================//&function&:&OrthoProj//&purpose&&://&=======================================================================template&&typename&Elem_t&void&Graphic3d_Camera::OrthoProj&(const&Elem_t&theLeft,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&Elem_t&theRight,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&Elem_t&theBottom,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&Elem_t&theTop,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&Elem_t&theNear,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&Elem_t&theFar,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&NCollection_Mat4&Elem_t&&&theOutMx){&&//&row&0&&theOutMx.ChangeValue&(0,&0)&=&Elem_t&(2.0)&/&(theRight&-&theLeft);&&theOutMx.ChangeValue&(0,&1)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(0,&2)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(0,&3)&=&-&(theRight&+&theLeft)&/&(theRight&-&theLeft);&&//&row&1&&theOutMx.ChangeValue&(1,&0)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(1,&1)&=&Elem_t&(2.0)&/&(theTop&-&theBottom);&&theOutMx.ChangeValue&(1,&2)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(1,&3)&=&-&(theTop&+&theBottom)&/&(theTop&-&theBottom);&&//&row&2&&theOutMx.ChangeValue&(2,&0)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(2,&1)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(2,&2)&=&Elem_t&(-2.0)&/&(theFar&-&theNear);&&theOutMx.ChangeValue&(2,&3)&=&-&(theFar&+&theNear)&/&(theFar&-&theNear);&&//&row&3&&theOutMx.ChangeValue&(3,&0)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(3,&1)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(3,&2)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(3,&3)&=&Elem_t&(1.0);}平行投影主要用于设计制图CAD,而透视投影更有真实感觉,即近大远小,所以在一些三维浏览或仿真程序中主要使用透视投影。当指定投影类型为Projection_Perspective时,即指定为场景的投影变换为透视变换。一般的透视投影规范化变换矩阵如下所示:详细推导请参考《Computer Graphics with OpenGL》。
OpenCASCADE中相关的实现代码如下所示: //&=======================================================================//&function&:&PerspectiveProj//&purpose&&://&=======================================================================template&&typename&Elem_t&void&Graphic3d_Camera::PerspectiveProj&(const&Elem_t&theLeft,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&Elem_t&theRight,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&Elem_t&theBottom,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&Elem_t&theTop,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&Elem_t&theNear,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&Elem_t&theFar,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&NCollection_Mat4&Elem_t&&&theOutMx){&&//&column&0&&theOutMx.ChangeValue&(0,&0)&=&(Elem_t&(2.0)&*&theNear)&/&(theRight&-&theLeft);&&theOutMx.ChangeValue&(1,&0)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(2,&0)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(3,&0)&=&Elem_t&(0.0);&&//&column&1&&theOutMx.ChangeValue&(0,&1)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(1,&1)&=&(Elem_t&(2.0)&*&theNear)&/&(theTop&-&theBottom);&&theOutMx.ChangeValue&(2,&1)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(3,&1)&=&Elem_t&(0.0);&&//&column&2&&theOutMx.ChangeValue&(0,&2)&=&(theRight&+&theLeft)&/&(theRight&-&theLeft);&&theOutMx.ChangeValue&(1,&2)&=&(theTop&+&theBottom)&/&(theTop&-&theBottom);&&theOutMx.ChangeValue&(2,&2)&=&-(theFar&+&theNear)&/&(theFar&-&theNear);&&theOutMx.ChangeValue&(3,&2)&=&Elem_t&(-1.0);&&//&column&3&&theOutMx.ChangeValue&(0,&3)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(1,&3)&=&Elem_t&(0.0);&&theOutMx.ChangeValue&(2,&3)&=&-(Elem_t&(2.0)&*&theFar&*&theNear)&/&(theFar&-&theNear);&&theOutMx.ChangeValue&(3,&3)&=&Elem_t&(0.0);}其中投影方式Projection_Stereo为立体投影,在网上搜了一下,这种投影可以应用到3D影片的播放。目前来看,相关应用还是很火爆的,可以用来在电视中播放立体影片。更多介绍可参考:
4.Test the Camera in GLUT OpenGL实用函数工具包(OpenGL Utility Toolkit, GLUT)提供了与任意屏幕窗口系统进行交互的函数库,可以用来快速演示OpenGL中的相关概念。其中设置投影变换矩阵的方法如下代码所示: //&projection&transformation.glMatrixMode(GL_PROJECTION);glLoadMatrixd(theCamera-&ProjectionMatrix().GetData()); 设置模型/视图变换矩阵代码如下所示: glMatrixMode(GL_MODELVIEW);glLoadMatrixd(theCamera-&OrientationMatrix().GetData());glutPostRedisplay(); 通过键盘按键o和p用来在平行投影和透视投影之间进行切换,切换效果如下图所示:
Figure 4.1 Orthographic and Perspective projection test 如上图所示,透视投影比平行投影更具立体感,但是在工程设计CAD或机械制图CAD软件中,平行投影更有利于设计人员使用。当处于平行投影模式时,视点的远近对模型在视图中的显示没有影响;当处于透视投影模式时,移动视点对视图是有影响的:当视点离模型较近时,模型在视图中显示较大,反之较小。 按下鼠标中键可以用来测试四元数Quaternion插值来对场景绕Y轴进行旋转,其实主要用来测试OpenCASCADE的quaternion插值类的插值效果。代码及效果图如下所示: &&&&static&gp_Quaternion&aStartQuat(gp_Vec(0.0,&1.0,&0.0),&0.0);&&&&static&gp_Quaternion&aEndQuat(gp_Vec(0.0,&1.0,&0.0),&M_PI);&&&&static&gp_QuaternionSLerp&aSlerp(aStartQuat,&aEndQuat);&&&&gp_Quaternion&aResultQ&&&&aSlerp.Interpolate(T,&aResultQuat); Figure 4.2 Test Quaternion SLERP 程序源代码见文后附件,可下载编译后自己修改一些参数来测试效果。 5.Conclusion OpenGL中的坐标变换涉及到对象空间,模型空间,世界空间,观察空间及相关的坐标变换,而所有的变换操作都可以统一为一个4X4的齐次矩阵的数学运算,如矩阵加法、矩阵乘法、求逆矩阵等。 OpenCASCADE用面向对象的思想封装了Grpahic3d_Camera用来方便对视图的变换控制,通过设置视点及投影类型等相关参数,即可得到相关的变换矩阵,进而可对模型/视图方便地进行变换。利用Camera的类,可以方便对视图进行缩放、旋转等变换操作。相关实现可参考OpenCASCADE中视图类中的代码。 最后,还测试了一下gp_Quaternion插值的算法。 6. References 1. Dave Shreiner. OpenGL Programming Guide(7th Edition). Addison-Wesley. 2010 2. Randi J. Rost. OpenGL Shading Language(2nd Edition). Addison-Wesley. 2006 3. Donald Hearn, M. Pauline Baker. Computer Graphics with OpenGL. 2004 4. Nate Robins. OpenGL Tutors.
5. Song Ho Ahn. OpenGL Transformation.
6. 孙家广等. 计算机图形学. 清华大学出版社. 2000 & PDF Version and Source Code:在进行3D场景渲染时,天空是必不可少的因素。对于3D天空的模拟在视景仿真系统、计算机游戏、三维动画中有着广泛的应用。但是,目前对于天空的仿真还存在很多不足,一些模拟方法中存在实现复杂、计算耗时、图像分辨力不高,真实感不强且只能生成静态图像等问题。本文在研究了前人仿真天空算法的基础上,利用目前3D图形行业中流行的OpenGL技术和有被誉为"大自然的几何学"美称的分形理论,提出了一种更加简单实用的仿真3D天空的方法,可以仿真出具有动态效果和不同天气的3D天空,绘制速度快,真实感强。
l构造天空模型
1.1 OpenGL技术[1.2]
OpenGL作为一套图形标准,由数百个功能函数组成,提供了访问图形硬件的所有特性,其严格按照计算机图形学原理设计而成,符合光学和视觉的原理,非常适合可视化仿真系。其优势在于:首先,在OpenGL中,允许视景对象用图形方式表达;其次,OpenGL通过光照处理能表达出物体的三维特性,其光照模型是整体光照模型。可视化仿真图像的颜色体现着物体与视点以及光源之间的空间位置关系,具有很强的三维效果。此外,为弥补图形方法难于生成复杂自然背景的不足,OpenGL提供了对图像数据的使用方法,即直接对图像数据读、写和拷贝,或者把图像数据定义为纹理与图形方法结合在一起生成视景图像以增强效果。本文研究了基于OpenGL技术的3D天空仿真,使得算法易于实现,并且有很好的可视化效果。
1.2 传统模型
在传统的3D游戏中,对于天空的仿真,程序员往往从实时简单的角度出发,采用非常简化的天空模型,通常包括以下3种方法[3-5]:用一种接近天空的淡蓝色来清除背景;采用天空盒(skyBox)的方法:即首先绘制一个多边形,然后进行立方体纹理贴图;八棱锥天空模型:定义一个天顶,以这个顶点为中心绘制一圈三角形扇,然后进行纹理映射。
这3种方法都具备了实时性,方法简单的优点,但同时也存在明显的不足,第一种方法绘制的天空效果看起来太平面化,简单粗糙,逼近度不高。第二种方法对纹理的要求非常高,如果纹理使用得不好,在一个比较大的多边形上的纹理就容易产生拉伸变形的副作用。此外,雾化设置也会产生问题,如果雾的设置靠近观察点,则天空的颜色会变淡甚至没有。第三种方法有明显的天顶。
显然,在如今这种对3D场景仿真要求越来越高的时代,这些方法已经不适应时代的要求,需要寻求一种渲染速度快,真实感强,有一定交互能力的3D天空模型。
1.3 半球型天空模型
地球是球型的,所以天空像半个球一样笼罩在大地之上。在用计算机仿真3D天空时,半球型天空模型显然符合真实世界的天空模型。利用数学中的球面方程,可以建立如下模型:
P是球面上一点,R为球的半径。在球面坐标系下方程改写为:
对于一个半球.&为纬度,其变化范围是O&&&90&;&为经度,其变化范围是O&&&360&。采用球型(DOme)的方法,比起采用盒子(BOx)的方法,有很多优点。首先由于球形方法绘制的天空具有更多的顶点,雾化效果可以绘制得更加均匀[5]。同时也可以实时改变单个顶点的颜色,这样可以获得一些非常好的效果,如一天不同时刻的太阳光。
半球型天空模型也存在不足:(1)顶点数目过多,影响渲染速度。
N为所需要绘制的顶点总数;△&,△&为绘制球型天顶的顶点经纬度间隔,值越小、网格越密,绘制越精细。由于采用OpenG技术中的三角形带绘制(GL-TRIANGLE一STRIP),每次绘制4个顶点,每个顶点被绘制4次,故需要乘以4。
(2)三角函数的运算过多。
在单一场景的渲染中不会影响渲染速度,但在复杂的3D场景中,渲染速度的劣势会体现出来。因为在计算机中三角函数的运算较之加、减、乘、除等运算要慢的多。
1.4 曲面天空模型
为保持球型天空模型的优势并弥补该算法的不足,本文研究了一种渲染速度更快的曲面天空模型,该模型如图1所示。
该模型类似于将一个经过细分的平面的4个角点向下拉,形状看上去像一个撑开的降落伞,将他罩在场景之上,可以模拟3D天空。曲面的长度为S为:
顶点坐标(x,y,z)的计算公式为:
其中△s为曲面细分间隔;j,i为循环参数。
曲面天空模型仍然可以用OpenGL技术中的三角形带((GLTRIANGLE_STRIP)绘制,但他避免了三角函数的运算,且顶点数目比相同精度的球型天空模型少,故增加了渲染速度。
2 天空云图
2.1 分形云图
分形[4]方法建造的物体模型结构精细、算法控制相对简单,适合于描绘云、树等结构精细的物体。本文利用分形理论中的插值算法产生静态天空云图纹理,算法如下:
(1)在平面上划分正方形网格n&n,随机给A1,A2,A3,A4这4个角点的颜色。如图2所示。
(2)计算中点值,B1=(A1+A2+A3+A4)&0.25+&&scale,其中&是一个随机量;Scale一(1/2)H(标度)H即Hurst指数,他也是分形维数D的度量:D一2一H,如图3所示。
(3)根据A1,A4,B1点和网格外一虚拟点,重复第(2)节,得到边中点c1的颜色值。同理,可计算出C2,C3,C4边中点的颜色值。
(4)递归步骤(2),(3),使其正方形网格不断细化,直到达到预期的递归深度。
以上步骤中,正方形初始点的颜色是随机赋予的,但正方形网格内的所有点不是随机分布的。通过采用分形插值算法,使得网格内相邻点之间建立了某种联系,从而使生成体内部过渡得更加自然。这样,通过分形插值算法,得到一个2维数组,将数组中的每一个元素值看成是云的不透明度数据。最小数组值代表最蓝色,天空中云最少的部分,最大的值代表最白色,天空中云最重的部分。分析数组并生成蓝天白云纹理图如图4所示。
2.2 纹理映射
纹理映射技术[1.2]也叫纹理贴图技术(Texture Map-ping),与建造模型的方法相比,在摸拟物体表面细节方面,纹理映射是一个较有效的方法。景物表面纹理细节的模拟在真实感图形合成技术中起着非常重要的作用,这种将景物表面纹理细节的模拟称为纹理映射技术。现在,纹理映射已经成为三维图形世界中最为常用的技术之一,其数学过程十分复杂,但OpenGL已对其进行处理,于是编程者可以利用几个函数就可以完成纹理贴图。
执行纹理贴图的步骤可以概括为:定义纹理贴图;控制纹理;说明纹理贴图方式;激活纹理映射;定义纹理坐标等。在一个球面上进行纹理映射是比较复杂的,采用不同的映射方式将产生不同的问题。如果采用平面映射的方式将在连续处产生纹理拉伸现象,如果采用球面映射,最大的问题是在球面的极点产生纹理的聚集现象,对于好的纹理,这种现象可以缩减到最小。根据球面几何知识,可以得到纹理坐标的具体计算公式:加上1/2的原因是为了使U,V坐标的值处于(0.0,1.0)范围内。
3 动态仿真
本文采用定时器技术和改变纹理矩阵坐标的方法实现云的流动效果。首先定义一个100 ms的定时器,每隔100ms纹理坐标改变一次。其次,使用多重纹理来添加一个单独的云彩贴图,通过变换纹理矩阵坐标实现流动。变换纹理坐标的方法是先将当前矩阵类型设置为纹理矩阵(GL-TEXTURE),然后调用glTranslate(),glRotate()和glScale()函数实现坐标的平移、旋转和缩放。这样,云就可以缓慢地在天空中移动。此外,通过添加按键响应函数,在函数体中利用()penGL的模型变换函数,如glRotate(),可以以任意角度旋转3D天空,达到用户与3D场景的交互的效果。
本仿真实验在CPU为P4,主频为1.7 GHz,内存为256 M,集成显卡上完成。仿真结果如图5~图8所示。天空中的云彩可以沿球形天空缓慢移动,客户可以通过上下左右键旋转3D天空。该模型在实时3D场景仿真中可以笼罩在场景之上,有很好的3D效果,并且真实感强。采用半球型天空模型的帧速率为250~285 f/s;采用曲面型天空模型的帧速率为324~340 f/s,在保证真实感和交互性的前提下,从渲染速度上看曲面天空模型优于半球型天空模型。
本仿真系统的软件平台为VC++6.O,通过OpenGL图形库函数实现可视化仿真。利用球形方程、平面方程、三角函数等几何原理建立各种3D天空模型,运用分形理论中的插值算法编写天空纹理,并通过OpenGL函数进行三角形带绘制天空框架,纹理映射技术,映射出具有真实效果的3D天空。从仿真结果来看,真实感强,实时性好,此外,通过按键响应函数,可以以任意角度旋转,任意高度升降3D天空,交互性强,非常适合3D游戏的户外场景仿真。
阅读(...) 评论()}

我要回帖

更多关于 opengl camera类 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信