7.1.6.1 one test at a time
考虑当一个对象完整"落入"某单元里。对其碰撞测试不仅要包含同一单元内的其他对象还有该单元邻居单元内的对象。哪些邻居单元需要测试取决于对象是如何“占据”邻居单元的,以及采用对象的何种特征定义对象“占据”(在..内)某个单元。可选的对象特征:对象包围球球心(object bounding sphere center)以及轴对齐包围盒的最小顶点值(minimum corner of axis-aligned bounding box)
任何对象只要与单元的边界发生“重叠”,就可能与该单元内的对象发生碰撞。故采用OBS特征,需要测试当前对象与所有邻域内的其他对象碰撞。
//objects placed in single cell based on their bounding sphere center
//checking object's cell and all 8 neighboring grid cells
check object's cell
check northwest neighor cell
check north neighor cell
check northeast neighor cell
check west neighor cell
check east neighor cell
check southwest neighor cell
check south neighor cell
check southeast neighor cel
共需测试9个邻域单元(3D空间共27个),这显然不好。而采用”AABB最小顶点值”,那么只有在当前对象确实与某个邻居单元内的对象“重叠“才需要测试。2D伪代码如下:
//objects placed in single cell based on AABB minimum corner vertex
//checking object's "minimum corner" cell and up to all 8 neighboring grid cells
check object's "minimum corner" cell
check north neighor cell
check northwest neighor cell
check west neighor cell
if(object overlaps east cell border) {
check northeast neighbor cell
check east neighbor cell
}
if(object overlaps south cell border) {
check southwest neighbor cell
check south neighbor cell
if(object overlaps east cell border)
check southeast neighbor cell
上述最坏情况下也需要测试九个单元,但最好的情况下仅需测试4个单元。这使得“AABB”策略优于OBS。另外,对象是完全处于其所“落入”的所有单元中,one test at a time方法每次只需要测试AABB确实“占据”的单元,因为所有碰撞只会在这些单元里发生.
//objects placed in all cells overlapped by their AABB
//checking objects's "minimum corner" cell and up to 3 neighboring grid cells
check object's "minimum corner" cell
if(object overlaps east cell border)
check east neighbor cell
if(object overlaps south cell border) {
check south neighbor cell
if(object overlaps east cell border)
check southeast neighbor cell
此时最坏的情况需要测4个单元,最好的情况只需要测试1个单元。当然对于运动对象,该测试需要使用较复杂的代码以及更多内存。另外,此时两个对象间的碰撞可能被记录多次,所以还需要引入“碰撞对”标记。
7.1.6.2 all tests at a time
即同时对所有对象进行碰撞测试。考虑将对象放在一个单元里,注意这时构成"碰撞对"的两个对象是可交换的。即测试对象A与对象B的碰撞等价测试对象B与对象A的碰撞。例如,当前单元CA里的对象与东边邻接单元CB内的对象进行碰撞检测;CB的对象与CA的对象碰撞测试就可以忽略。其结果就是所有对象都需要检测是否与其他对象碰撞。
换句话说,该检测策略不允许只对网格里的一个运动对象进行测试,所有可能“重叠”都需要同时进行测试。另外,往往还会误认为处于对位单元内的对象不需要测试。但比如分别属于NE单元和SW单元的对象a, b 却可能在第三个单元C里碰撞啊.
再考虑OBS策略。某个单元内的对象测试就可以只测试一半的邻居单元,因为另一半单元里的测试通过交换性实现了。
//objects placed in single cell based on their bounding shpere center
//all objects are checked for collisions at the same time, so collisions
//in the opposite direction will be handled when checking the objects
//existing in those cells
check object's cell
check east neighbor cell
check southwest neighbor cell
check south neighbor cell
check southeast neighbor cell
该方法要求所有对象都必须检测,因而上述五个check不能与包围球边界重叠测试联合。比如:虽然对象A不“占据”东边的邻居单元EC的边界,但有可能在EC里存在对象B,且B”占据”了A所在单元WC的边界。但因为EC没进行碰撞测试,那么任何可能的BA之间“重叠“都可能检测不到。而且由于部分碰撞会被检测到两次,该方法将需要使用碰撞对矩阵来记录”重叠状态“。
在考虑AABB策略,类似简化。
//objects placed in single cell based on AABB minimum corner vertex
//all objects are checked for collisions at the same time, so collisions
//in the opposite direction will be handled when checking the objects
//existing in those cells
check object's "minimum corner" cell
check southwest neighbor cell
if(object overlaps east cell border)
check east neighbor cell
if(object overlaps south cell border) {
check south neighbor cell
if(object overlaps east cell border)
check southeast neighbor cell