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 ...
随机推荐
- js中如何取精度
js中如何取精度 一.总结 一句话总结:其实round()函数去经度会有误差,直接用num.toFixed(2)简单方便. toFixed()方法会按照指定的小数返回数值的字符串表示.var num ...
- 关于PHPExcel上传Excel单元格富文本和时间类型读取数据问题
当用PHPExcel做Excel上传文件读取数据时,print_r出来的数据,竟然发现其中有几个单元格返回的是PHPExcel富文本对象,而且时间类型的单元格返回的是一个不是时间戳的五位数.就像下图那 ...
- python shutil 模块 的剪切文件函数 shutil.movemove(src, dst),换用 os.rename(sourceFile, targetFile)
Google 一搜python 剪切文件,出来shutil 这模块,网上很多人也跟疯说shutil.move(src, dst)就是用来剪切文件的,结果一试,剪切毛线,文件都复制到另一个文件夹了,源文 ...
- 洛谷1019 单词接龙 字符串dfs
问题描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合 ...
- POJ2976 Dropping tests(01分数规划)
题意 给你n次测试的得分情况b[i]代表第i次测试的总分,a[i]代表实际得分. 你可以取消k次测试,得剩下的测试中的分数为 问分数的最大值为多少. 题解 裸的01规划. 然后ans没有清0坑我半天. ...
- [NOIP2013提高组]货车运输
题目:洛谷P1967.Vijos P1843.codevs3287. 题目大意:有n个城市m条道路,每条道路有一个限重,规定货车运货不能超过限重.有一些询问,问你两个城市之间一次最多能运多少重的货(可 ...
- 【J-meter】正则表达式提取
当获取的值中含有折行,可采用下面的办法解决:
- 【转】 基于C#.NET的高端智能化网络爬虫
[转] 基于C#.NET的高端智能化网络爬虫 前两天朋友发给我了一篇文章,是携程网反爬虫组的技术经理写的,大概讲的是如何用他的超高智商通过(挑衅.怜悯.嘲讽.猥琐)的方式来完美碾压爬虫开发者.今天我就 ...
- 【转】 HtmlAgilityPack使用——XPath注意事项
[转] HtmlAgilityPack使用——XPath注意事项 在使用HtmlAgilityPack这个开源的类库进行网页内容解析的时候是非常的方便(使用方法见另一篇博客<HTML解析:基于X ...
- Java实现断点续传。
http://www.cnblogs.com/liaojie970/p/5013790.html