q3 bsp随笔
阅读q3的bsp实现,做一些随笔记录,免得自己也忘了。
首先谈到的是brush概念。
笔者用最通俗的方法来解释一下brush
用q3场景编缉,画一个六面体(长方体),观察得到的map文件
会看到里面记录了一个brush信息,其实就是记录了brush的六个面!
这就是brush。
假设我们的场景都是由长方体构成,那么场景里有brush信息就都是长方体的信息
(q3的brush当然不止长方体,但在理解bsp代码之前,就认为brush是一个长方体,这里能更容易地理解代码)
接下来是winding,
简单的说
brush是记录长方体的六个平面,winding就是根据这六个平面参数,得到的8个顶点
在q3里,长方体的每个"面"被称为side,每个side有一个winding,这个winding就是该"面"的4个点
winding就是brush信息的另一种展现显示
接下来q3就开始分割空间。
记录下当前场景里所有brush的平面,去重,根据这些平面划分空间,就会得到一棵bsp树
这是一棵完全的bsp树,场景中所有的brush平面均参与了空间分割。
接下来抛弃一个实心空间?比如,一个brush长方体,它的内部空间,有分割时,会形成一个叶子节点
这个节点是要抛弃的,因为玩家不会出现在一个实力长方体里面。
有了bsp树,就可以根据玩家的位置,找到玩家所有的叶子节点。
绘制当前叶子节点,也就是玩家可以看见的面,这里就涉及到pvs的预计算
生成port,就是为了预计算pvs。
假设玩家在一个房间里,这个房间有一个门,这个门就是port,玩家除了看到房间的四面墙,还会通过门到看外面的一些面。
这些面,是需要预计算,保存下来的。
可以想像,port一定是在生成bsp树时,分割空间的平面上,随着空间的分割,port也被分割。
所以q3遍历bsp树,用bsp树的分割平面,被port依次分割,最后得到port 的winding.
因为bsp是完全的,场景中所有的平面都参与了bsp分割,这样q3的计算每个port的可见性时
就不用再考虑场景中的多边形对port的切割了,只根据port的winding信息,来计算port之间的可见性。
先写到着,代码看完再接着写。
基本上,q3代码要分两部分看,只看游戏运行时的那部分代码,会觉得一头雾水,但多少能猜出bsp的大概。
完成领会q3的bsp,场影编缉器的代码是一定要看的。
这也是为什么光看ogre与鬼火,完全无法看懂bsp,开源引擎只负责解析q3生成的文件,没有相应的生成代码。
ps:q3生成pvs的时候,使用了多线程,算是最早的map reduce了吧,呵呵(单机版的)