在BlackBerry上使用OpenGL绘图(七):视图变换:观察点的运动

来源:互联网 发布:塔吉特大数据营销 编辑:程序博客网 时间:2024/04/30 23:04
 

7 视图变换:观察点的运动

对视图的操作主要表现为对观察点的操作,形象的比喻就是在3D世界中摆放“相机”,你可以指定“相机”的位置,也可以指定“相机”镜头的朝向,还可以指定“相机”机身的朝向。在OpenGL中,开发人员可以通过gluLookAt方法设置观察点,不过在标准的OpenGL ES中并没有提供gluLookAt方法的支持。也就是说在标准的OpenGL ES中开发人员不能简单地设置观察点位置和朝向。

 

OpenGL ES中之所之不提供gluLookAt方法,是因为观察点的运动可以通过模型的运动来模拟。回到现实中照相的例子,如果拍照的人希望离所拍的物体更近一些,一种方式是移动照相机,让它更接近物体,另一种效果相同的方式是移动所拍摄的物体,让它们更接近照相机。同样,如果希望拍摄物体的左侧,一种方式是将照相机以物体为原点向左转动90度,另一方式是将物体以自身为原点向右旋转90度,两种方式的效果是相同的。也就是说,在不能对观察点进行调整的情况下,开发人员可以通过模型的调整实现相同的效果。这也是视图变换和模型变换都是通过“GL_MODELVIEW”模式指定的原因。

 

虽然观察点的运动可以通过模型的运动来模拟,但是在很多情况下这种模拟会变得很复杂,而且对开发人员来讲会变得很不直观。幸运的是BlackBerry在net.rim.device.api.opengles包中提供一个OpenGL ES的扩展类,名为GLUtils,可以提供gluLookAt方法的支持。开发人员可以在BlackBerry平台上通过GLUtils.gluLookAt方法直接指定观察点的位置和朝向。

 

gluLookAt方法接受10个参数。第一个参数为需要处理的GL实例。第二个到第四个参数为观察点的X,Y,Z坐标,通过这三个参数可以指定观察点在坐标中的位置。第五个到第七个参数为目标的X,Y,Z坐标,通过这三个参数可以指定观察点的方向,观察点的方向是由观察点自身的坐标位置指向目标的坐标的位置,可以理解为从观察点坐标出发,穿过目标坐标的一条射线。第八个到第十个参数组成一个向量,指定哪个方向为朝上的方向。不指定朝上的方向系统无法确定如何生成图像。比如现实中照相,虽然镜头指向同一个方向,拍摄者可以横着相机拍,也可以竖着相机拍,为了让拍摄者明确拍摄意图,还需要指定相机自身的方向。

 

以下为gluLookAt方法调用的样例:

            net.rim.device.api.opengles.GLUtils.gluLookAt(gl, 0, 0, 3.5f, 0,0, 0, 0, 1, 0);

 

该方法将观察点设置在{0,0,3.5}坐标位置上,观察方向指向坐标{0,0,0},向上的向量为{0,1,0}。就是将相机放在Z轴的3.5的位置上,镜头指向Z轴的负方向,Y轴正方向为相机朝上的方向。

 

为了改变简化样例中的观察点,可以将gluLookAt方法加入简化样例的render方法中,代码如代码清单18-9:

 

代码清单18-9

gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

            gl.glMatrixMode(GL10.GL_MODELVIEW);

            gl.glLoadIdentity();

            net.rim.device.api.opengles.GLUtils.gluLookAt(gl, 0, 0, 3.5f, 0,0, 0, 0, 1, 0);

 

           

            gl.glTranslatef(0, 0, -3.5f);

            gl.glRotatef(_angle, 1.0f, 1.0f, 0.0f);

            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

         gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);

      //...

运行结果如图18-8,从结果中可以看到三角形变小了,之所以变小是因为模型离观察点更远了。

图18-8,简化样例,设置观察点之后

如果开发人员希望实现观察点不断飞离模型的动画,可以用一个变量代替gluLookAt中的第四个参数3.5f,在每次更新的时候将该变量设置成一个更大的数。这样观察点坐标在Z轴上的值不断变大,距离模型就越来越远。

 

虽然这个方法实现的是让观察点不断飞离模型,但对用户而言效果和模型飞离观察点是相同的,事实上用户分不清是模型在运动还是观察点在运动。这里不再给出完整实现的代码,读者可以将它作为一个练习对OpenGLDemo样例进行修改,主要需要完成的工作是定义一个和变量_angle类似的成员变量,在update方法中更新该变量,最后在gluLookAt方法中使用这一变量。要注意的是该变量应该作用在观察点坐标的Z值,如果作用于X值或者是Y值的话会让观察点横着飞或者是竖着飞,最终无法观察到模型。

原创粉丝点击