首页 > 其他分享 >性能提升-BVH层次包围体

性能提升-BVH层次包围体

时间:2023-08-16 23:34:21浏览次数:27  
标签:const 层次 Standard return Boolean 包围 BVH

性能提升-BVH层次包围体

[email protected]

Abstract.  OpenCASCADE provides BVH to achieve high performance in AIS of visualization module. To understand BVH usage will help us to understand many code of opencascade.

Key Words. BVH, Bounding Volume Hierarchy, LBVH, SAH Algorithm

1 Introduction

层次包围体技术 (BVH) 指的是将所有包围体分层逐次地再次包围,获得一个更大的包围体,直到包围住所有物体。实际上,它是一个树形结构,因此可以仿照树的结构,将两个或三个小的包围体包围成一个更大的包围体,以此类推。

BVH是一种以物体BV为基础进行划分的结构。它由根节点、内部节点和叶子节点组成。其中叶子节点存放物体,每个非叶子节点都有包围体,父节点可以把子节点包围起来。每个非叶子节点的包围体大小,是它所包含的所有物体的包围体的总和,所以它在空间上比较紧凑,非常适用于需要大量求相交测试的应用场景,如光线追踪、碰撞检测、射线相交测试之类的应用场合中。

 

BVH在OpenCASCADE中也有广泛地应用,如开源版本中的模型快速碰撞检测,使用类BRepExtrema_ShapeProximity. 模型选择操作,光线跟踪等算法中都有应用。在

https://www.cnblogs.com/opencascade/p/6804446.html

中介绍如何遍历BVH树,本文主要介绍BVH使用方法。

2 BVH

OpenCASCADE中的BVH是相对独立的一个包,是作者根据论文实现的纯C++版本移植过来的。在DRAW中的QA品质保证Bugs中提供了BVH的使用示例。

2.1 BVH_Set

首先要定义层次包围盒的集合Set来构造BVH树,从BVH_Set基类派生的集合是可以直接使用的:

如可以直接使用BVH_Triangulation,也可以直接使用BVH_BoxSet:

从这些类名中,我们可以看出在求模型间极值距离Extrema,三维可视化Graphic3d及Select3D拾取及布尔操作BOPTools中都有BVH的应用。

将元素通过Add函数添加到BVH集合后,调用BVH()函数就可以构造BVH树。

2.2 BVH_Traverse

对于单个BVH的遍历提供类BVH_Traverse,一般的应用场景如求距离一点P最近的模型,或者位于某个空间范围内的所有模型。代码如下所示:

//=======================================================================
//function : ShapeSelector
//purpose : Implement the simplest shape's selector
//=======================================================================
class ShapeSelector :
  public BVH_Traverse <Standard_Real, 3, BVH_BoxSet <Standard_Real, 3, TopoDS_Shape>, Standard_Boolean>
{
public:
  //! Constructor
  ShapeSelector() {}

  //! Sets the Box for selection
  void SetBox (const Bnd_Box& theBox)
  {
    myBox = Bnd_Tools::Bnd2BVH (theBox);
  }

  //! Returns the selected shapes
  const NCollection_List<TopoDS_Shape>& Shapes () const { return myShapes; }

public:

  //! Defines the rules for node rejection by bounding box
  virtual Standard_Boolean RejectNode (const BVH_Vec3d& theCornerMin,
                                       const BVH_Vec3d& theCornerMax,
                                       Standard_Boolean& theIsInside) const Standard_OVERRIDE
  {
    Standard_Boolean hasOverlap;
    theIsInside = myBox.Contains (theCornerMin, theCornerMax, hasOverlap);
    return !hasOverlap;
  }

  //! Defines the rules for leaf acceptance
  virtual Standard_Boolean AcceptMetric (const Standard_Boolean& theIsInside) const Standard_OVERRIDE
  {
    return theIsInside;
  }

  //! Defines the rules for leaf acceptance
  virtual Standard_Boolean Accept (const Standard_Integer theIndex,
                                   const Standard_Boolean& theIsInside) Standard_OVERRIDE
  {
    if (theIsInside || !myBox.IsOut (myBVHSet->Box (theIndex)))
    {
      myShapes.Append (myBVHSet->Element (theIndex));
      return Standard_True;
    }
    return Standard_False;
  }

protected:

  BVH_Box <Standard_Real, 3> myBox;         //!< Selection box
  NCollection_List <TopoDS_Shape> myShapes; //!< Selected shapes
};

主要是从类BVH_Traverse派生并重写两个虚函数RejectNode()和Accept(),即在RejectNode()中定义排除结点的规则,在Accept()中处理满足条件的情况。

2.3 BVH_PairTraverse

对于两个BVH的遍历提供类BVH_PairTraverse,一般的应用场景有求两个Mesh之间的最近距离,判断两个Mesh之间是否有碰撞等。

//=======================================================================
//function : MeshMeshDistance
//purpose : Class to compute the distance between two meshes
//=======================================================================
class MeshMeshDistance : public BVH_PairDistance<Standard_Real, 3, BVH_BoxSet<Standard_Real, 3, Triangle>>
{
public:
  //! Constructor
  MeshMeshDistance() {}

public:
  //! Defines the rules for leaf acceptance
  virtual Standard_Boolean Accept (const Standard_Integer theIndex1,
                                   const Standard_Integer theIndex2) Standard_OVERRIDE
  {
    const Triangle& aTri1 = myBVHSet1->Element (theIndex1);
    const Triangle& aTri2 = myBVHSet2->Element (theIndex2);

    Standard_Real aDistance = TriangleTriangleSqDistance (aTri1._Node1, aTri1._Node2, aTri1._Node3,
                                                          aTri2._Node1, aTri2._Node2, aTri2._Node3);
    if (aDistance < myDistance)
    {
      myDistance = aDistance;
      return Standard_True;
    }
    return Standard_False;
  }
};

主要也是从BVH_PairTraverse派生并重写两个虚函数RejectNode()和Accept()。

2.4 BVH_Builder

关于BVH的构造提供多种Builder,默认是使用基于SAH算法的BVH_BinnedBuilder来构造BVH树,如果要切换不同的构造器,可以在BVH集合的构造函数中传入一个。

下面给出求两个Mesh之间最近距离的示例代码:

 

 // Define BVH Builder
  opencascade::handle <BVH_LinearBuilder <Standard_Real, 3> > aLBuilder =
      new BVH_LinearBuilder <Standard_Real, 3>();

  // Create the ShapeSet
  opencascade::handle <BVH_BoxSet <Standard_Real, 3, Triangle> > aTriangleBoxSet[2];

  for (Standard_Integer i = 0; i < 2; ++i)
  {
    aTriangleBoxSet[i] = new BVH_BoxSet <Standard_Real, 3, Triangle> (aLBuilder);

    TopTools_IndexedMapOfShape aMapShapes;
    TopExp::MapShapes (aShape[i], TopAbs_FACE,   aMapShapes);

    for (Standard_Integer iS = 1; iS <= aMapShapes.Extent(); ++iS)
    {
      const TopoDS_Face& aF = TopoDS::Face (aMapShapes(iS));
      TopLoc_Location aLoc;
      const Handle(Poly_Triangulation)& aTriangulation = BRep_Tool::Triangulation(aF, aLoc);

      const int aNbTriangles = aTriangulation->NbTriangles();
      for (int iT = 1; iT <= aNbTriangles; ++iT)
      {
        const Poly_Triangle aTriangle = aTriangulation->Triangle (iT);
        // Nodes indices
        Standard_Integer id1, id2, id3;
        aTriangle.Get (id1, id2, id3);

        const gp_Pnt aP1 = aTriangulation->Node (id1).Transformed (aLoc.Transformation());
        const gp_Pnt aP2 = aTriangulation->Node (id2).Transformed (aLoc.Transformation());
        const gp_Pnt aP3 = aTriangulation->Node (id3).Transformed (aLoc.Transformation());

        BVH_Vec3d aBVHP1 (aP1.X(), aP1.Y(), aP1.Z());
        BVH_Vec3d aBVHP2 (aP2.X(), aP2.Y(), aP2.Z());
        BVH_Vec3d aBVHP3 (aP3.X(), aP3.Y(), aP3.Z());

        BVH_Box<Standard_Real, 3> aBox;
        aBox.Add (aBVHP1);
        aBox.Add (aBVHP2);
        aBox.Add (aBVHP3);

        aTriangleBoxSet[i]->Add (Triangle (aBVHP1, aBVHP2, aBVHP3), aBox);
      }
    }
    // Build BVH
    aTriangleBoxSet[i]->Build();
  }

  // Initialize selector
  MeshMeshDistance aDistTool;
  // Select the elements
  aDistTool.SetBVHSets (aTriangleBoxSet[0].get(), aTriangleBoxSet[1].get());
  Standard_Real aSqDist = aDistTool.ComputeDistance();
  if (!aDistTool.IsDone())
    std::cout << "Not Done" << std::endl;
  else
    theDI << "Distance " << sqrt (aSqDist) << "\n";

3 Conclusion

准确、稳定、高效是高品质几何内核的目标,我们在开发软件时,也要时刻追求这个目标。而BVH层次包围盒技术是提升性能的一种方式,理解BVH的使用,我们可以理解opencascade中快速求极值Extrema,交互选择SelectMgr等很多代码。甚至我们也可以参与贡献,如将

Standard_Boolean BRepExtrema_Poly::Distance (const TopoDS_Shape& S1, const TopoDS_Shape& S2,
                                             gp_Pnt& P1, gp_Pnt& P2, Standard_Real& dist)

这个O(N^2)的改造成BVH的来对比一下性能。

 

标签:const,层次,Standard,return,Boolean,包围,BVH
From: https://www.cnblogs.com/opencascade/p/occt_bvh.html

相关文章

  • Redis 7的入门到精通的学习路线可以分为三个层次:入门、进阶和精通
    Redis7的入门到精通的学习路线可以分为三个层次:入门、进阶和精通学习Redis7的入门到精通的学习路线可以分为三个层次:入门、进阶和精通。下面是每个层次的学习内容和示例代码讲解。##入门阶段:1.**安装和配置Redis**:了解如何下载、安装和配置Redis的基本参数。可以使用Redis......
  • 二叉树:自下而上,从左到右的层次遍历
    利用栈先进后出的特性,将出队元素依次进栈,然后依次出栈即可完成。#include<stdio.h>#include<stdlib.h>#defineMaxSize100//二叉树的结点类型typedefstructNode{intdata;structNode*lchild,*rchild;}TreeNode,*Tree;//队列的结点类型typedefstru......
  • 二叉树的层次遍历
    #include<stdio.h>#include<stdlib.h>#defineMaxSize100typedefstructTreeNode{ intdata; structTreeNode*lchild,*rchild;}TreeNode,*Tree;typedefstruct{ TreeNode*data[MaxSize]; intfront; intrear;}Queue;voidInitQueue(Queue......
  • oracle 设置数据层次
    OracleLevel函数:简单易用的多层级查询利器在数据库操作中,常常需要查询多层级的数据,比如树形菜单、组织架构等等。在Oracle数据库中,我们可以利用Level函数来实现多层级查询,这个函数的使用非常简单,下面就让我们来了解一下。1.什么是Level函数?Level函数是Oracle数据库中内置的一种函......
  • 高层次人才业务申报系统建设方案
    需求分析:确立系统建设的目标和需求,明确高层次人才业务的各个环节和流程,了解用户需求和功能要求。系统设计:根据需求分析结果,设计系统的架构和模块划分,确定数据流程和界面设计,制定数据库结构和数据管理方案。开发与测试:根据系统设计,进行系统开发和编码工作,实现各项功能和模块。在开发......
  • 机器学习方面各层次书籍推荐
    1基础强数学型1.1FoundationsofMachineLearning豆瓣评分9.0(103人)有大量的数学公式推到和课后习题,用来提升对于机器学习原理公式的理解 1.2统计学习方法李航+b站带读  2入门型漫画机器学习入门零基础机器学习 ......
  • 层次分析法
    课程PPT:层次分析法.pdf方法流程:总共3次一致性检验确定题目类型属于评价类题目确定评价目标,评价标准,可选方案画出层级结构图对于对于一致性矩阵:对于非一致性矩阵:对每一个方案的权重矩阵进行一致性检验对于每个方案,将其指标得分与指标权重相乘(EXCEL),最终进行......
  • 论文解读:《基于提示学习的多层次蛋白质结构预训练》
    ICLR会议论文TItle:MULTI-LEVELPROTEINSTRUCTUREPRE-TRAININGWITHPROMPTLEARNING王泽源 1,2,7*张强 1,2*†余浩然2,3 胡双伟4     1 浙江大学计算机科学与技术学院2浙江大学-杭州全球科技创新中心3浙江大学化学与生物工程学院4Vecx生物医药股份有限公司,5敏......
  • AcWing 847. 图中点的层次
    题目给定一个$n$个点$m$条边的有向图,图中可能存在重边和自环。所有边的长度都是$1$,点的编号为$1∼n$。请你求出$1$号点到$n$号点的最短距离,如果从$1$号点无法走到$n$号点,输出$−1$。输入格式第一行包含两个整数$n$和$m$。接下来$m$行,每行包含两个整数$......
  • 1.2.3 计算机系统的层次结构
    计算机系统的层次结构下层是上层的基础,上层是下层的扩展三种级别的语言注:编译、汇编、解释程序,可统称“翻译程序”......