从零开始学习导航网格#5 rcChunkyTriMesh与BVH

本篇单独来讲recast项目中的一个重要数据结构:BVH
在计算几何中有一个基础的问题:判断一个点是否在场景中的某个几何体内部
如果我们通过枚举场景内的所有几何体,然后依次判断,这显然太暴力了
一种优化思路是将空间划分成若干区域,首先找到目标点所在的区域,这样就可以剔除掉不在这个区域的几何体,从而减少判断次数
BVH(Bounding volume hierarchy)即包围体层次结构,就是一种用树形结构组织管理空间内物体(几何体)的方法
wiki上的例子:

BVH

大致可以看出树和原场景包围盒的对应关系:
1.根节点是一个大的包围盒,包含所有的几何体
2.每个叶子节点对应一个独立的几何体
3.每个非叶子节点有若干个子节点,表示这个大的包围盒内部包含了若干个小的包围盒

如何建树:

建树的过程也就是划分空间的过程
首先根节点就是包含所有几何体的最大包围盒,叶子节点是只包含单个几何体的最小包围盒,这是可以预先确定的,也是建树的起点和递归边界
那么我们就需要制定一种策略来进行划分,主要有三种策略:
1.取某一条轴的中点划分
2.按左右子树几何体数量相等的规则划分
3.按表面积启发式算法划分

Recast项目中是采用了第二种策略

下面来看一下Recast是怎么实现BVH的
先说明一下几个重要的参数和数据结构类型

const float* verts;///输入的顶点集合
const int* tris;///输入的三角形集合
int ntris;///输入的三角形个数

///三角形在xz平面投影的包围盒
struct BoundsItem
{
    float bmin[2];
    float bmax[2];
    int i;///由于会对包围盒按坐标排序,id记录了这个包围盒对应的输入三角形的id
};

///BVH的节点
struct rcChunkyTriMeshNode
{
    float bmin[2];///包含区域内所有三角形的包围盒
    float bmax[2];
    int i;///i为正表示是叶子节点;i为负表示是非叶子节点,大小等于在数组内的覆盖范围
    int n;///节点内包含的三角形个数
};

///一棵BVH树
struct rcChunkyTriMesh
{
    rcChunkyTriMeshNode* nodes;///根节点
    int nnodes;///节点个数
    int* tris;///按区域划分排序后的三角形集合
    int ntris;///三角形个数
    int maxTrisPerChunk;///叶子节点最多包含的三角形数
}

另外recast在实现的时候还对树的存储方式进行了优化,即用一维数组+节点记录偏移值来实现树形结构(类似于线段树的非指针实现)
首先建树和查找都是dfs的顺序,所以在生成节点时按dfs顺序依次向数组里插入就可以了,另外当发现一颗子树中没有与目标点相交的几何体,需要立即跨过这颗子树下的所有节点,
所以在非叶子节点上(即子树的根节点)会记录子树节点总个数,这样遍历时只要加上这个值作为偏移,就能立即跳过这棵子树

最后的实现其实就很简单了(如果你经常写树形数据结构的话)
1.计算所有三角形在xz平面投影的包围盒,并记录与初始三角形的对应关系,放入BoundsItem* items数组中

2.递归建树
对于当前区域,创建一个节点,并生成一个包含区域内所有三角形的包围盒
a.若当前区域内的三角形数量已经不超过允许包含的数量(trisPerChunk),则表示到达了递归边界
b.否则取一条较长的轴,将所有三角形按轴坐标排序后,作一条垂直于轴的分割线,使得分割线分成的两个区域内的三角形个数相等,然后继续递归处理两个区域

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容