[OpenGL] AABB包围盒

来源:互联网 发布:淘宝全屏宝贝推荐代码 编辑:程序博客网 时间:2024/04/29 16:52

      前段时间,我想用OpenGL做一些小游戏。最开始,我是把AABB包围盒的计算集成在我的程序中的。但是这样无疑会增加加载资源的时间。然后我就干脆单独做了这样的一个小工具,用来计算Obj模型的包围盒。这样我就可以在外部提前计算好包围盒的尺寸,然后再应用到我的其他游戏中去。


我实现的小工具的详细信息:

    程序名:  AABB Calculator V1.0

    开发平台: Qt + OpenGL

    程序的下载链接: http://download.csdn.net/detail/mahabharata_/9847987

    程序截图如下:

       1. 效果图:读取单纹理的人物模型:

               

       2. 程序的主界面:读取单纹理的人物模型:

         


     3. 程序主界面:读取含大量纹理的场景模型(32个纹理)

        


      这个“AABB提取工具”能够支持绝大多数的obj模型(支持多纹理),用户可以在右下角的输出区域获取该模型的有关信息,并可选择四种显示模式,分别是采用不同方法计算得到的包围球和AABB包围盒。

      其具体原理其实很简单,我在接下来的文章中会介绍~


AABB包围盒的原理

      在实现碰撞检测(Collision Detection)时,不可避免地需要知道场景中物体的尺寸或者边界。我们称之为“包围盒技术”(Bounding Box)。常见的包围盒有:Sphere、AABB、OBB、FDH等。

1. Bounding Sphere(包围球):

       以mesh的中心为球心,以距离中心最远的点为半径画球。其中,中心坐标可以通过求mesh中所有点的均值获得。伪代码如下:

vec3 center = vec3(0,0,0);// mesh的所有点的向量和for(int i=0; i< mesh.size(); i++){center+= mesh[i];  }// 除以点数,求得中心坐标(向量和的均值)center = center/mesh.size();

      这是一种非常简单但是粗糙的方法,这种方法计算出的包围球内有很大的空洞,对碰撞检测过为敏感。我实现的一个效果图如下:(下图的模型前方、上方都有很大的空洞,在进行碰撞检测、射线拾取时,会非常不准确)

         


2. AABB包围盒(Axis-aligned bounding box)

       AABB包围盒的本质是一个非常贴近物体的长方体。其实当我们看到英文——“对齐坐标轴的包围盒”时,也能够理解出一些含义来。AABB包围盒需要计算两个重要的点来确定包围盒的大小:

            pMax:(xmax, ymax, zmax)

      pMin:(xmin, ymin, zmin)

      这两个点的六个值,分别为mesh中出现的x、y、z轴的最大/最小值。我们先找到在X,Y和Z的轴向投影最近和最远的6个点,然后分别取他们相应的轴向上的坐标值来构成pMax和pMin,这样我们通过就可以得出一个以pMax和pMin连线为对角线的紧凑的包围盒。其代码示意如下:


float xmax = ymax = zmax = -9999999;float xmin = ymin = zmin = +9999999;for(int i=0; i<mesh.size(); i++){// 计算pMaxif( xmax < mesh[i].x )xmax = mesh[i].x;if( ymax < mesh[i].y )ymax = mesh[i].y;if( zmax < mesh[i].z )zmax = mesh[i].z;    // 计算pMinif(xmin > mesh[i].x )xmin = mesh[i].x;if(ymin > mesh[i].y )ymin = mesh[i].y;if(zmin > mesh[i].z )zmin = mesh[i].z;}

     虽然这个方法也是很简单的操作就可以求得,但是从下面我实现的这个效果图可以看出,效果要比第一种Bounding Sphere的方法要紧凑的多。也正因为它实现简单的同时也具有较好的特性,因此在游戏设计中用的最为广泛。

             

3. OBB包围盒(Oriented Bounding Box)

        OBB包围盒,即 有向包围盒。 它的本质还是一种最贴近物体的长方体,只不过它可以根据物体的形状而旋转。与AABB相比,AABB包围盒平行于坐标轴而不可旋转,但OBB可以根据需要进行旋转。因此OBB比AABB要更加的逼近物体。三种方法的关系示意图如下:

                 

      我没有进一步去做OBB方法,因为对于用OpenGL的模拟碰撞检测等已经足以,不过相关资料网上还是有很多的,这里给出我找到的一篇英文文献(感觉很不错,不管是原理还是C++的伪代码都很清晰):

       https://www.geometrictools.com/Documentation/DynamicCollisionDetection.pdf


4.  我实现的小工具的所有效果:

4.1 仅显示模型:

     

4.2 (Sphere)显示上述方法计算得到的包围球:

    

4.3 (Sphere)以包围球半径为基础的包围盒(假包围盒)

    

4.4 (AABB)显示上述方法得到的AABB包围盒(真包围盒)

    

4.4 (AABB)以AABB中最远的轴向距离的1/2为半径做的假包围球(虽然少数有跑到圈外的点,但是作为粗略计算也可以)

    


     最后,程序是我的娱乐作品,如果有疑问或者发现了bug的话,可以私信或者评论我,我会及时更新。