Bounding Volume Hierarchy BVH in OpenCASCADE
Bounding Volume Hierarchy BVH in OpenCASCADE
Abstract. Bounding Volume Hierarchy(BVH) organizes geometric objects in the tree based on spatial relationships. Each node in the tree contains an axis-aligned bounding box of all the objects below it. Bounding volume hierarchies are used in many algorithms to support efficient operations on the sets of geometric objects, such as collision detection, ray-tracing, searching of nearest objects, and view frustum culling. The paper focus on the usage of BVH on TopoDS_Shape, and its application.
Key Words. BVH, Bounding Volume Hierarchy, Collision Detection
1.Introduction
层次包围盒(Bounding Volume Hierarchy, BVH)是一种基于物体的场景管理技术,广泛用于碰撞检测,光线追踪,视锥体物体剔除等场合。对于三维场景的实时渲染来说,BVH是最常用的数据结构。场景以层次树形结构进行组织,包含一个根节点、内部节点、叶子节点。树中的每个节点,包括叶子节点都有一个包围体,可以将其子树的所有几何体包围起来,这就是BVH名字的由来。如下图所示:
Figure 1. Simple Scene(left), BVH Scene Graph(right)
本文主要介绍OpenCASCADE中的BVH包及其应用,如碰撞检测。
2.Build BVH
在BVH包中的头文件里面找到BVH的作者:Denis BOGOLEPOV, Danila ULYANOV,在网上搜到他们的一篇论文:Real-Time SAH BVH Construction for Ray Tracing Dynamic Scenes. 因此,可知BVH中是应用SAH(Surface Area Heuristic)策略来构造BVH树的。根据BVH_BinnedBuilder头文件中的注释可知:
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->//! Performs construction of BVH tree using binned SAH algorithm. Number
//! of bins controls BVH quality in cost of construction time (greater
//! better). For optimal results, use 32 - 48 bins. However, reasonable
//! performance is provided even for 4 - 8 bins (it is only 10-20% lower
//! in comparison with optimal settings). Note that multiple threads can
//! be used only with thread safe BVH primitive sets.
OpenCASCADE中也提供了其他的构造方法,如类BVH_LinearBuilder中使用了Spatial Morton codes方法:
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->//! Performs fast BVH construction using LBVH building approach.
//! Algorithm uses spatial Morton codes to reduce the BVH construction
//! problem to a sorting problem (radix sort -- O(N) complexity). This
//! Linear Bounding Volume Hierarchy (LBVH) builder produces BVH trees
//! of lower quality compared to SAH-based BVH builders but it is over
//! an order of magnitude faster (up to 3M triangles per second).
//!
//! For more details see:
//! C. Lauterbach, M. Garland, S. Sengupta, D. Luebke, and D. Manocha.
//! Fast BVH construction on GPUs. Eurographics, 2009.
3.Traversal BVH
由类BVH_TreeBase可知,当得到BVH树后,可以取出节点索引的数组。下面给出将TopoDS_Shape的BVH树显示出来的示例代码:
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
-->/*
Copyright(C) 2017 Shing Liu(eryar@163.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Visual Studio 2013 & OpenCASCADE7.1.0
// 2017-04-18 20:52
#include <BRepExtrema_TriangleSet.hxx>
#include <BRepTools.hxx>
#include <BRep_Builder.hxx>
#include <TopoDS.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#pragma comment(lib, "TKernel.lib")
#pragma comment(lib, "TKMath.lib")
#pragma comment(lib, "TKG2d.lib")
#pragma comment(lib, "TKG3d.lib")
#pragma comment(lib, "TKGeomBase.lib")
#pragma comment(lib, "TKGeomAlgo.lib")
#pragma comment(lib, "TKBRep.lib")
#pragma comment(lib, "TKPrim.lib")
#pragma comment(lib, "TKMesh.lib")
#pragma comment(lib, "TKTopAlgo.lib")
void testBvh(const std::string& theFileName)
{
BRep_Builder aBuilder;
TopoDS_Compound aCompound;
TopoDS_Shape aShape;
BRepTools::Read(aShape, theFileName.c_str(), aBuilder);
BRepExtrema_ShapeList aFaceList;
for (TopExp_Explorer i(aShape, TopAbs_FACE); i.More(); i.Next())
{
aFaceList.Append(TopoDS::Face(i.Current()));
}
aBuilder.MakeCompound(aCompound);
BRepMesh_IncrementalMesh aMesher(aShape, 1.0);
BRepExtrema_TriangleSet aTriangleSet(aFaceList);
const NCollection_Handle<BVH_Tree<Standard_Real, 3> >& aBvh = aTriangleSet.BVH();
for (int i = 0; i < aBvh->Length(); i++)
{
const BVH_Vec4i& aNodeData = aBvh->NodeInfoBuffer()[i];
if (aNodeData.x() == 0)
{
// inner node.
const BVH_Vec3d& aP1 = aBvh->MinPoint(aNodeData.y());
const BVH_Vec3d& aP2 = aBvh->MaxPoint(aNodeData.y());
const BVH_Vec3d& aQ1 = aBvh->MinPoint(aNodeData.z());
const BVH_Vec3d& aQ2 = aBvh->MaxPoint(aNodeData.z());
try
{
BRepPrimAPI_MakeBox aBoxMaker(gp_Pnt(aP1.x(), aP1.y(), aP1.z()),
gp_Pnt(aP2.x(), aP2.y(), aP2.z()));
for (TopExp_Explorer i(aBoxMaker.Shape(), TopAbs_EDGE); i.More(); i.Next())
{
aBuilder.Add(aCompound, i.Current());
}
}
catch (Standard_Failure f)
{
}
try
{
BRepPrimAPI_MakeBox aBoxMaker(gp_Pnt(aQ1.x(), aQ1.y(), aQ1.z()),
gp_Pnt(aQ2.x(), aQ2.y(), aQ2.z()));
for (TopExp_Explorer i(aBoxMaker.Shape(), TopAbs_EDGE); i.More(); i.Next())
{
aBuilder.Add(aCompound, i.Current());
}
}
catch (Standard_Failure f)
{
}
}
else
{
// leaves node.
const BVH_Vec3d& aP1 = aBvh->MinPoint(i);
const BVH_Vec3d& aP2 = aBvh->MaxPoint(i);
try
{
BRepPrimAPI_MakeBox aBoxMaker(gp_Pnt(aP1.x(), aP1.y(), aP1.z()),
gp_Pnt(aP2.x(), aP2.y(), aP2.z()));
aBuilder.Add(aCompound, aBoxMaker.Shape());
}
catch (Standard_Failure f)
{
}
}
}
BRepTools::Write(aCompound, "d:/bvh.brep");
}
int main(int argc, char* argv[])
{
if (argc > 1)
{
testBvh(argv[1]);
}
return 0;
}
由上述代码可知,当得到节点信息
const BVH_Vec4i& aNodeData = aBvh->NodeInfoBuffer()[i];
后,通过判断aNodeData.x()分量来确定此节点是内部节点还是叶子节点。显示OCC自带的螺旋桨模型的BVH如下图所示:
其中红色线框为内部节点,黄色实体模型是叶子节点。
4.BVH Application
BVH在OpenCASCADE中也有广泛地应用,如开源版本中的模型快速碰撞检测,使用类BRepExtrema_ShapeProximity. 模型选择操作,光线跟踪等算法中都有应用。
5.Conclusion
因为OpenCASCADE中构造BVH时依赖模型的网格三角形,所以BVH算法的应用的结果就依赖于网格化算法的质量了。如两个Topo形状碰撞检测时,网格化的质量越高,结果精度越高。如果用解析算法去对两个Topo形状做碰撞检测,也会涉及到解析算法的精度问题。
BVH结构广泛应用于碰撞检测、光线跟踪等算法中,大大提高程序性能。本文只是抛砖引玉,对BVH感兴趣的童鞋可以参考相关资料及OpenCASCADE中的代码实现,去深入学习应用。
6.References
1. Dmitry Sopin, Denis Bogolepov, Danila Ulyanov. Real-Time SAH BVH Construction for Ray Tracing Dynamic Scenes. http://graphicon.ru/html/2011/conference/gc2011Sopin.pdf
2. BVH with SAH. http://www.cnblogs.com/lookof/p/3546320.html
3. 3D游戏引擎中常见的三维场景管理方法. http://www.cnblogs.com/wangchengfeng/p/3495954.html
PDF Version: BVH in OpenCASCADE.pdf
Bounding Volume Hierarchy BVH in OpenCASCADE的更多相关文章
- BVH with SAH (Bounding Volume Hierarchy with Surface Area Heuristic)
- BVH with SAH (Bounding Volume Hierarchy with Surface Area Heuristic) - 0. Overview 包围层次盒(B ...
- Bounding Volume Hierarchies 加速结构
背景 光线与物体求交是光线追踪的主要时间瓶颈. 如果不进行优化,则对每条光线,我们都需要遍历场景中的全部物体并求交.而现在想建模一个小物体的表面,往往要几千甚至几万个三角形,一个商业级产品,屏 ...
- Opencascade术语笔记。
1. chamfer 倒角 vs fillet 圆角: 2.boolean operatiron(布尔操作): common(相加),fuse(相交),cut(相减): 3.depressions( ...
- 【Notes_9】现代图形学入门——光线追踪(基本原理)
跟着闫令琪老师的课程学习,总结自己学习到的知识点 课程网址GAMES101 B站课程地址GAMES101 课程资料百度网盘[提取码:0000] 目录 光线追踪 为什么要光线追踪 soft shadow ...
- games101 - 4 - Ray Tracing
games101 - 4 - Ray Tracing 目录 games101 - 4 - Ray Tracing 为什么需要Ray Tracing Recursive (Whitted-Style) ...
- PBRT笔记(2)——BVH
BVH 构建BVH树分三步: 计算每个图元的边界信息并且存储在数组中 使用指定的方法构建树 优化树,使得树更加紧凑 //BVH边界信息,存储了图元号,包围盒以及中心点 struct BVHPrimit ...
- 空间划分的数据结构(网格/四叉树/八叉树/BSP树/k-d树/BVH/自定义划分)
目录 网格 (Grid) 网格的应用 四叉树/八叉树 (Quadtree/Octree) 四叉树/八叉树的应用 BSP树 (Binary Space Partitioning Tree) 判断点在平面 ...
- 对pathtracing的一些个人理解
本人水平有限,若有错误也请指正~ 上面说到pathtracing(pt)的一些优点和缺点,优点即其实现很简单,这就是大概为什么当今市面上流行的很多渲染器如今都相继采用pathtracing算法为核心进 ...
- 探究光线追踪技术及UE4的实现
目录 一.光线追踪概述 1.1 光线追踪是什么 1.2 光线追踪的特点 1.3 光线追踪的历史 1.4 光线追踪的应用 二.光线追踪的原理 2.1 光线追踪的物理原理 2.2 光线追踪算法 2.3 R ...
随机推荐
- Autofac依赖注入框架
最近使用Autofac框架做项目的依赖注入,感觉挺好用的. 没有深入研究,只是拿来用用,具体可以去官网看看:https://autofac.org/. 这里只是贴一下最近项目的配置: public p ...
- POJ 1274 二分图匹配
匈牙利算法 裸题 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> ...
- 设置和获取Android中各种音量
通过程序获取android系统手机的铃声和音量.同样,设置铃声和音量的方法也很简单! AudioManager am = (AudioManager) getSystemService(Context ...
- MyBatis的架构设计以及实例分析--转
原文地址:http://blog.csdn.net/luanlouis/article/details/40422941 MyBatis是目前非常流行的ORM框架,它的功能很强大,然而其实现却比较简单 ...
- windows下python3 使用cx_Oracle,xlrd插件进行excel数据清洗录入
我们在做数据分析,清洗的过程中,很多时候会面对各种各样的数据源,要针对不同的数据源进行清洗,入库的工作.当然python这个语言,我比较喜欢,开发效率高,基本上怎么写都能运行,而且安装配置简单,基本上 ...
- CUDA笔记(六)
dim3是NVIDIA的CUDA编程中一种自定义的整型向量类型,基于用于指定维度的uint3 忽然发现需要再搞多机MPI的配置,多机GPU集群.好麻烦.. 这两天考完两门了,还剩下三门,并行计算太多了 ...
- vue中计算小数保留两位小数
代码
- Linux 运维笔试题(一)
试题: 1.说出下列服务对应的端口或者端口对应的服务 21 23 25 873 161 111 110 53 123 2049 2.文件atime,ctime,mtime的区 ...
- 用 while 循环做个小游戏
import random #可输入次数 flag = 0 #生成一个1到10之间的随机整数 res = random.randint(1,10) #判读三次输入机会 while(flag<3) ...
- hdu 1423 最长公共递增子序列 LCIS
最长公共上升子序列(LCIS)的O(n^2)算法 预备知识:动态规划的基本思想,LCS,LIS. 问题:字符串a,字符串b,求a和b的LCIS(最长公共上升子序列). 首先我们可以看到,这个问题具有相 ...