八叉树
来源:互联网 发布:g20对杭州的影响 知乎 编辑:程序博客网 时间:2024/05/21 21:34
在写Ambient Occlusion时需要进行射线与物体的各个三角形的碰撞检测
但是逐个三角形进行判断需要进行大量的无意义计算
可以通过一个八叉树管理物体的包围盒空间
通过八叉树对物体的包围盒进行空间管理
这样判断射线是否与物体相交时可以省去大量的计算
当射线与某一个空间有相交的话,则进一步判断子空间与射线的相交性
算法描述:
判断当前节点空间中的三角形数是否小于我们设置的一个阀值,若小于则该节点设置为叶子节点(即无子节点)
若大于该阀值,则将该空间分为8份,并判断出在各子空间中的三角形,然后再对其子节点进行判断
将节点所在空间为分8份比较简单,假设当前节点所表示空间的包围盒为Bound
则Bound.Center为该包围盒的中心,Bound.Extents为该包围盒中心到各边的距离
八个子空间的长宽高都为父空间的一半,
八个子空间中心的坐标分别为Bound.Center向八个方向移动0.5f * Bound.Extents的距离
首先我们先分析下节点的结构体:
我们要通过八叉树管理空间,则所有的节点都需要维护一个包围盒,表示节点所表示的空间
且每个叶子空间中都应该维护一份索引列表,以便我们通过八叉树对物体进行碰撞检测等操作
结构体如下:
struct OctreeNode{ #pragma region Properties DirectX::BoundingBox Bounds; std::vector<UINT> indices; OctreeNode* Children[8]; //子节点 bool Isleaf; //是否为叶子节点 #pragma endregion //......};
并且定义一个函数将空间分为8份:
struct OctreeNode{ //..... void Subdivide( DirectX::BoundingBox box[8] ) { // the half lenght of width , height , depth DirectX::XMFLOAT3 HalfExtent( 0.5f * Bounds.Extents.x , 0.5f * Bounds.Extents.y , 0.5f * Bounds.Extents.z ); // // cacluate eight children node // // Top four quadrants box[0].Center = DirectX::XMFLOAT3( Bounds.Center.x + HalfExtent.x , Bounds.Center.y + HalfExtent.y , Bounds.Center.z + HalfExtent.z ); box[0].Extents = HalfExtent; box[1].Center = DirectX::XMFLOAT3( Bounds.Center.x - HalfExtent.x , Bounds.Center.y + HalfExtent.y , Bounds.Center.z + HalfExtent.z ); box[1].Extents = HalfExtent; box[2].Center = DirectX::XMFLOAT3( Bounds.Center.x - HalfExtent.x , Bounds.Center.y + HalfExtent.y , Bounds.Center.z - HalfExtent.z ); box[2].Extents = HalfExtent; box[3].Center = DirectX::XMFLOAT3( Bounds.Center.x + HalfExtent.x , Bounds.Center.y + HalfExtent.y , Bounds.Center.z - HalfExtent.z ); box[3].Extents = HalfExtent; // bottom for quadrants box[4].Center = DirectX::XMFLOAT3( Bounds.Center.x + HalfExtent.x , Bounds.Center.y - HalfExtent.y , Bounds.Center.z + HalfExtent.z ); box[4].Extents = HalfExtent; box[5].Center = DirectX::XMFLOAT3( Bounds.Center.x - HalfExtent.x , Bounds.Center.y - HalfExtent.y , Bounds.Center.z + HalfExtent.z ); box[5].Extents = HalfExtent; box[6].Center = DirectX::XMFLOAT3( Bounds.Center.x - HalfExtent.x , Bounds.Center.y - HalfExtent.y , Bounds.Center.z - HalfExtent.z ); box[6].Extents = HalfExtent; box[7].Center = DirectX::XMFLOAT3( Bounds.Center.x + HalfExtent.x , Bounds.Center.y - HalfExtent.y , Bounds.Center.z - HalfExtent.z ); box[7].Extents = HalfExtent; }};
然后我们需要定义一个八叉树类为物体生成一棵八叉树,并且添加一些碰撞检测函数
class Octress{public:Octress();~Octress();public:void Build(std::vector<DirectX::XMFLOAT3> vertices , std::vector<UINT> indices);void RayIntersect(DirectX::XMFLOAT3 RayPos , DirectX::XMFLOAT3 RayDir);private:// 以该节点一棵生成八叉树void BuildOctree(OctreeNode* parent , std::vector<UINT> indices);// 判断光线是否与当前节点所表示空间相交bool RayOctreeIntersect(OctreeNode* parent , DirectX::XMFLOAT3 RayPos , DirectX::XMFLOAT3 RayDir);private:// 根节点OctreeNode* mRoot;// 维护一份顶点拷贝std::vector<DirectX::XMFLOAT3> mVertices;}
void Octree::Build(std::vector<DirectX::XMFLOAT3> vertices , std::vector<UINT> indices){// 保存一份顶点拷贝mVertices = vertices;// 首先根据顶点列表计算出该物体的包围盒...// 创建并填充root节点...// 通过根节点生成一棵八叉树BuildOctree(mRoot , indices);}bool BuildOctree(OctreeNode* parent , std::vector<UINT> indices){// 判断当前节点的三角形数是否小于设定的阀值// 若小于,则设置该节点为叶子节点,不再分解if((indices.size() / 3) < threshold){parent->indices = indices;parent->Isleaf = true;}else{// 继续分解空间DirectX::BoundingBox box[8];parent->Subdivide(box);// 将父空间的索引分配到相应的子空间中for(int i = 0; i < 8; i++){parent->Children[i] = new OctreeNode;parent->Children[i]->Bounds = box[i];// 遍历各个三角形,若与子空间相交// 则认为该三角形属于该子空间std::vector<UINT> IntersectIndices;for(int j = 0; j < indices.size() / 3; j++){// 得到当前三角形的三个顶点...// 判断该三角形是否与该子空间相交...//若相交,则将索引入栈IntersectIndices.push_back(...);...//递归分解该子节点BuildOctree(parent->Children[i] , IntersectIndices);}}}}
0 0
- 八叉树
- 八叉树
- 八叉树
- 八叉树
- 八叉树
- 八叉树
- 八叉树
- 八叉树
- 八叉树入门
- 八叉树 ( 1 )
- 八叉树 ( 2 )
- 八叉树 Octree
- 八叉树 Octree
- OcTree 八叉树
- 八叉树 Octree
- 八叉树算法
- 八叉树 Octree
- 八叉树Octree
- 第三周项目1-三角形类1
- 最近点对(Java实现)
- webbench源码分析
- 消息创建过程
- C++容器/迭代器
- 八叉树
- [华为机试]朋友圈信息转发
- Android 自定义ImageView支持缩放,拖拽,方便复用
- Maurits Cornelis Escher
- IOS系统反射
- 自己创建maven项目工程说明,参考别人的
- WF 系列--WF基础
- 京东2013研发笔试卷
- 黑马程序员——OC热身——NSString、NSMutableString