基于视锥包含的不可见物体消除算法

类别:编程语言 点击:0 评论:0 推荐:
基于视锥包含的不可见物体消除算法 出 处: 中国游戏开发者  
  目 录
  1 含义
  2 原理
  3 方法


1、不可见物体消除的含义
  虚拟现实系统中涉及的物体(图元)数量很大。如果把这些图元原封不动地提交给OpenGL渲染,有很多实际上不会出现在场景中的图元耗费了宝贵的资源。因为OpenGL只是一种过程型渲染器,它会把所有提交的渲染命令一一执行,而不管那些图元是否是可见的。因此,需要在提交渲染命令之前进行可见性判断。针对多种应用条件已经有了很多解决方法,如后向面判别、A缓冲器算法、画家算法、BSP(Binary Space Partitional)树算法等。
  如果地形的范围很大,观察点也常常位于离地面很高的位置,那么此可以看到的地面、空中物体数目也非常多。而对于其中的每一个物体,我们能观察到的细节并不很多。因此在这类应用中,比图元的可见性重要的概念是:整个物体的可见性,地面块的可见性。在减少有效物体数的同时,结合LOD方法,降低构成有效物体图元数,也能达到简化场景、提高渲染速率的目的。对于可延伸的地形,也要根据可见性尽量减少块数。

2、视锥包含算法的基本原理
  所谓视锥包含,就是判断一个世界坐标系下的三维点是否包含在当前的视锥内,也就是可见性。视锥的大小、形状、位置如下图所示。

图1
aspect = w / h
  视锥的大小和形状:

  gluPerspective(fovy, aspect, near, far)

  视锥的位置:

  gluLookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz)

  为了叙述的方便,我们定义以下一些参数:
  视锥在x轴方向的夹角xfovy:也就是视锥在其水平方向的夹角。
  目标点pos:目标点的坐标。{pos.x, pos.x, pos.z}。
  视线View:视锥中心线的方向向量。
  {View.x, View.y, Viewz} = {center.x, center.y, center.z} - {eye.x, eye.y, eye.z}
  视向量Pos:需要判断的目标点到视点的向量。
  {Posx, Posy, Posz} = {posx, posy, posz} - {eyex, eyey, eyez}。
  视平面:图中垂直于视线的一组平面,这些平面上的点最终都要透视投影到视口(Viewport)中。
  视锥右向Right:面向视平面,观察者伸出右手所指的方向。
  {Rightx, Righty, Rightz} = {Viewx, Viewy, Viewz} X {up.x, up.y, up.z}
  视锥正向Up:经过正交修正的视平面向上的方向向量。
  {Upx, Upy, Upz} = {Right.x, Right.y, Right.z} X {View.x, View.y, View.z}
  我们的判断过程全部都基于视锥坐标系考虑。上面求出的视锥右向Right、视线View、视锥正向Up就是这个坐标系中的x、y、z坐标轴在世界坐标系中的方向向量。具体步骤如下:

  function InSight (pos)
  begin

  1)如果视向量朝向视线的背面,则剔除。这一点是基于视角不可能大于180度的估计。具体的表示为:

    if cos (View ^ Pos) <= 0
    then return 0;

  这样,后面的一系列参数都可以不用计算了。

  2)剔除超过视线范围的点。通过计算目标点到Right ^ View平面的距离,得到其在视锥坐标系中的z坐标。由于视锥具有轴对称对称和中心对称的性质,因此我们只需要计算第一卦限中的情况,所有的坐标都可以取其绝对值。具体剔除条件为:

    if z>far or z < near
    then return 0;

  3)剔除视向量超出视锥的点。如果目标点通过了上面两部的检验,就继续计算其在视锥坐标系中的x,y坐标。计算方法和z相似。由于视锥的界面是一个四边形,所以不能简单地计算视向量和视线之间的夹角,而要在x和y轴方向分别计算夹角。也就是:

    if atan (y / z) > 视锥的y向张角fovy的一半
    or atan (x / z) > 视锥的x向张角xfovy的一半
    then return 0;
  end

3、判断物体可见性及地形绘制范围的方法
  有了判断目标点与视锥位置关系的方法,就可以进行可见物体及地形的简化了。
  在飞行模拟中,因为飞机的巡航高度很高的缘故,我们完全可以把地面物体看作点目标。即:

  if InSight (objpos)
  then Draw Object

  对于可扩展的地形,也要根据地形块的可见性进行增减。由于它不能被看作点,所以对每一个地形块都只能根据顶点的位置判断是否需要画。

  if InSight (any apex)
  then Draw Terrain Block

本文地址:http://com.8s8s.com/it/it24729.htm