对OCTREE的描述
OCTREE 是对3D空间进行划分,也可以叫空间分割。他允许你只对你的3D世界中摄象机照射的区域进行作画。他也能用于冲突检测。下面讲一下为什么要进行空间分割。假设你建立了一个游戏世界,这个世界有超过100,000个多边形要画。如果你建立一个循环并传递这些多边形,那速度是很慢的。即使你有一块很好的显示卡,他也会有很大的麻烦。但是玩你游戏的玩家的显示卡不会超过300$。有没有一种方法只渲染摄象机看见的多边形?那就是美丽的OCTREE。他允许你快速的找到你要渲染的多边形。
OCTREE是怎样工作的
OCTREE工作在立方体中。最初,OCTREE从根接点开始,这个根接点对齐于立方体中整个世界,水平或场景的axis中心线。因此,把我们的整个世界想象成一个不可见的立方体。
现在根接点存储了世界中的全部顶点。这是,他还是不能给我们任何好处,因为他还会画所有的东西。我们想把这个接点分成8个部分。一次,我们划分时,有8个立方体包含那最初的根接点的立方体。那意味着有4个立方体在上面,4个立方体在下面。请看下图:
记住图中黄色轮廓线没有。
我们刚刚把这个世界分成8个部分。想象一下如果我们有2,3,4个部分,我们的世界将是怎样?我们的摄象机在世界的中间,向着后面靠右的角落。如果你看这些线,你将注意到在OCTREE中8个结点中的第4个。这些结点包含2个后面的顶和底结点。这意味着我们只用画存储在这些结点中的顶点。
我们如何检测出我们要画的结点?如果你学过破片拣选(frustum culling),这将是很简单的。你能得到这些破片的大小并检测每个结点,看他是否被截断或在你的视觉破片中。有一个关于破片拣选的教程在http://www.gametutorials.com. 如果一个立方体截断破片,我们就将画这些结点。在这个例子中,我们切的数量是我们需要画的50%。记住,这只是我们世界中的一个部分。部分越多,我们就将越精确。当然,我们不会需要太多的点。下面,我们来看一下下面的图:
现在,我们明白了如何细分,但是我们也需要知道怎样停止细分。有许多的方法:
//这个函数取走立方体(X,Y,Z)的中心点和他的大小(width/2)
bool CubeInFrustum(float x,float y,float z,float size);
有阴影的立方体是在破片中。白色的立方体不是在破片中。这里显示了细分的2层。
OCTREE 不是用于渲染,但是用于冲突检测很好。随着游戏的发展,冲突检测也在改变,你将不得不在游戏世界中运用自己的算式检测你的角色或目标是否冲突。下面是一些冲突检测的例子:
//这个函数取走角色/目标(X,Y,Z)的中心点并返回靠近他的顶点
CVector3 *GetVerticesFromPoint(float x,float y,float z);
//这个函数取走角色/目标(X,Y,Z)的中心点和半径,然后返回和他冲突的结点中的顶点
CVector3 *GetVerticesFromPointAndRadius(float x,float y,float z,float radius);
//这个函数取走角色/目标(X,Y,Z)的中心点和立方体的大小,然后返回和他冲突的结点中的顶点
CVector3 *GetVerticesFromPointAndCube(float x,float y,float z,float size);
这篇教程只是给你讲截如何建立自己的OCTREE。关于这篇文章中的代码在www.gametutorials.com,我希望这篇文章对你有用。
源文档 <http://dev.gameres.com/Program/Visual/3D/OCTREETutorial.htm>