用BSP来对游戏中的室内场景进行分割是一个传统但却有效的手段,BSP创建的质量决定了BSP在使用时的健壮性,因为之后要使用BSP进行渲染、物理交互等操作。创建一个BSP的过程即简单又烦琐,虽然逻辑简单,但是在分割结点的过程中也会产生不少问题,以下是本人创建BSP时的一些简单经验总结。
BSP树创建流程:
1. 得到场景的多边形列表(多边形何种方式组织无关紧要,只要含有足够信息即可,我用的是索引。注:此多边形列表要求有正向面的法线信息或正反面的标识)。
2. 判断当前结点处的多边形集合是否为凸集,若是则标记当前结点为叶子,否则继续进行下述操作(判断凸集的方法应该选择分割面的方法相一致,否则相互矛盾容易出现无限分割的情况)。
3. 遍历当前结点多边形集合中的所有多边形所在的平面找到最优的分割面(分割平面的选取原则也有很多种,可以自己根据情况选取,我用的是保证BSP树的均衡的选取原则)。
4. 标记所有与分割平面处于同一平面上的多边形为已使用,子结点中不再使用这些多边形进行分割操作
5. 用最优分割面对当前结点的多边形集合进行归类,将对应的集合存放到子结点中(具体的操作应与多边形列表的组织关系相结合)。
需要注意的问题:
1. 若当前多边形集合为凸集则其应该找不到分割平面,对于一个非凸集的多边形集合则必能找到了下分割平面(此处情况常出现在分割面的选择与凸集的判断不一致的时候)。
2. 对与当前分割平面重叠的多边形的处理:若与当前分割面同向,则放于前结点集合,若与当前分割面反向,则放于后结点集合。
3. 对于一个凸集多边形集合,则遍历统计后(对于每个多边形,与其余的多边形进行位置判断):front >= 0 , back = 0 , split = 0 , overlap_samedir >= 0 , overlap_diffdir = 0
4. 最优分割面的选择条件应与凸集的判断条件相一致,否则会出现对于一个非凸集而找不到分割面的错误情况。
下图为一个场景的BSP分割结果(用面来渲染,不同的颜色表示不同的叶子结点):
BSP创建之后即可进行Portal的添加操作,待续。。。