DirectX 3D_基础之外接体 外接体的类型

来源:互联网 发布:淘宝拧盖器 编辑:程序博客网 时间:2024/06/10 02:04

                  每日一语:   

   

                  既然,目标定了,就要坚持的往下走下去。我们可以容许些许的迷茫,暂时的休息,但前进的方向应该明确。所以,有了自己的目标后,就应该不停的奋斗,努力。记得马云说过一句话,任何一个梦想,用10年的时间,沉下去,去努力实现。最终必将“实现”。当然这个实现,未必是真的绝对的实现,但有时你获得的,肯定比这还多。

 

                  正文:

                                   

                 外接体:


                  有时,我们需要计算一个网格的外接体。两种常见的外接体是外接球和外接体。其他的外接体还有圆柱体,椭球体,菱形体以及胶囊容器。


                  外接球和外接体常用于加速可见性检测和碰撞检测。例如,如果一个网格的外接体或外接球不可见。我们就可认为该网格不可见。检测外接体的可见性要比检测网格中每个面片的可见性的代价低得多。下面距离来说,假定场景中有一个发射体,我们想要确定该发射体是否会击中场景中的某一物体。由于物体是由三角形面片构成的,所以我们需要遍历每个物体的每个面片,并检测发射物体(其数学模型为射线)是否会击中某一个面片。该方法需要进行大量的射线/三角形相交测试,即场景中每个物体的每个三角形面片都需要进行一次。一种更高效的途径是计算出每个网格(物体)的外接体,然后再对每个物体进行射线/外接体相交测试。如果射线与某一物体的外接体相交,我们就认为该物体被击中。这是一种很好的近似。如果希望提高检测精度,我们可借助外接体快速排除那些显然不可能被击中的物体,然后再对极有可能被击中的物体使用更精确的方法来检测。极有可能被击中的物体就是其外接体被击中的物体。
                  D3DX库提供了一些函数用来计算一个网格的外接体和外接球。这些函数接收一个顶点数组,然后依据这些顶点计算出外接球和外接体。这些函数具有很大的灵活性,可适应多种顶点格式。


                  HRESULT WINAPI D3DXComputeBoundingSphere(
                                       const D3DXVECTOR3 *pFirstPosition,
                                       DWORD NumVertices,
                                       DWORD dwStride,
                                       D3DXVECTOR3 *pCenter,
                                       FLOAT *pRadius
                   );

                     

                   下面就其参数进行说明:


                   pFirstPosition 指向顶点数组(该数组的每个元素都描述了对应顶点)中第一个顶点的位置向量的指针。

 

                  NumVertices 指顶点数组中顶点的个数。


                   dwStride 每个顶点的大小,单位为字节。该值很重要,因为一种顶点结构可能包含了许多该函数所不需要的附加信息,如法向量和纹理坐标等。这样该函数就需要知道应跳过多少字节才能找到下一个顶点的位置。


                   pCenter 返回外接球的球心位置。


                   pRadius 返回外接球的半径。


                   HRESULT WINAPI D3DXComputeBoundingBox(
                              const D3DXVECTOR3 *pFirstPosition,
                              DWORD NumVertices,
                              DWORD dwStride,
                              D3DXVECTOR3 *pMin,
                              D3DXVECTOR3 *pMax   
                   )
     
                   该函数的前3个参数与D3DXComputeBoundingSphere函数中的前3个参数相同。最后两个参数分别表示返回外接体的最大值和最小值。


                   一些新的特殊常量:


                   现在我们来介绍两个在本书后续章节十分有用的两个常量。我们将这两个常量添加在d3d命名空间中。
                  

                             namespace d3d
                             {
                                 ....
                                 const float INFINITY = FLT_MAX;


                                 const float EPSILON = 0.001f;


                             }


                  常量INFINITY用于表示float类型所能存储的最大浮点数。由于我们不可能取得一个比FLT_MAX更大的float类型的数,我们可将该值概念化为无穷大,这样可使表达了无穷大概念的代码更具可读性。常量EPSILON是我们定义的一个很小的值。如果某个数小于该值,我们可认为该数为0,这样做是很有必要的,因为浮点运算具有不精确性,一个本应为0的数在计算机中表示时可能会出现微小的偏差。这样,就会得出该数与0不相等的结果。这样,我们就将判断某个数是否为0转化为判断某个数是否小于EPSILON。


                                bool Equals(float lhs,float rhs)
                               {
                                       return fabs(lhs - rhs) < EPSILON ? true:false;
                               }
    
                  外接体的类型:


                  为了给外接体的使用提供便利,很自然我们可为每种外接体实现一个类。我们将这些类实现在d3d命名空间中。
                  struct BoundingBox
                 {
                          BoundingBox();
                          bool isPointInside(D3DXVECTOR3& p);
                          D3DXVECTOR3 _min;
                          D3DXVECTOR3 _max;
                  };


                 struct BoundingSphere
                 {
                          BoundingSphere();
                          D3DXVECTOR3 _center;
                          float _radius;
                 };
    
 
                BoundingBox::BoundingBox()
                 {
                          _min.x = FLT_MAX;  
                          _min.y = FLT_MAX;
                          _min.z = FLT_MAX;
                          _max.x = -FLT_MAX;
                          _max.y = -FLT_MAX;
                          _max.z = -FLT_MAX;
                 }

 

                 bool BoundingBox::isPointInside(D3DXVECTOR3& p)
                {
                           if (p.x >= _min.x && p.y >= _min.y && p.z >= _min.z && p.x <= _max.x&&p.y <=_max.y&& p.z <= _max.z)
                          {
                                  return true;
                          }
                          else
                         {
                                   return false;
                          }
                }
                BoundingSphere::BoundingSphere()
                {
                          _radius = 0.0f;
                }

原创粉丝点击