空间划分(real time collision detection chapter 7)
来源:互联网 发布:淘宝在线客服在哪里 编辑:程序博客网 时间:2024/06/01 08:52
本章介绍三种空间划分方法:均匀网格划分、分层网格划分、树划分
7.1 均匀网格划分
7.1.1 链表存储
定义一个数组,然后将网格单元(grid cell)与数组元素一一对应。当一个单元中有对象(object)时,数组元素就是一个链表,保存在该单元内的所有对象,否则指NULL。
最简单维持对象链表的办法是,在对象类型(结构体)中包含链表成员变量。该方法既可以提高数据缓存并发又能避免链表声明而简化代码
由于每个数组元素都是一个链表(密集数组),对于具有大量单元的网格,其每个单元对应的(数组)元素都存储一个链表(表头),也需要很大的存储开销。而为此通过增大单个单元的尺寸以减少单元数量也不好,因为当对象呈聚集状时(而且是非常重要的应用情形),这样粗糙的划分没有了意义。后续几节给出几种低存储要求的可行办法。
7.1.2 哈希存储
上述链表存储的问题可由哈希方法解决。将网格单元映射到桶数目固定的哈希表。指定单元所含的对象链表就存在于某个桶里。下面给了一个简单的乘法哈希函数,其将单元坐标位置与桶索引对应:
struct Cell { Cell(int32 px, int32 py, int32 pz) {x=px; y=py; z=pz;} int32 x, y, z;}#define NUM_BUCKETS 1024// computes hash bucket index in range [0, NUM_BUCKETS-1]int32 ComputeHashBucketIndex(Cell cellPos) { const int32 h1=0x8da6b343; // large multiplicative constants const int32 h2=0xd8163841; // here arbitrarialy chosen primes const int32 h3=0xcb1ab31f; int32 n=h1*cellPos.x+h2*cellPos.y+h3*cellPos.z; n=n%NUM_BUCKETS; IF(n<0) n+=NUM_BUCKETS return n; }
哈希存储有个好处是单元数目不做限制。映射函数将全局坐标封装到有限个单元里(这样为抵达邻域而进行的边界检测也不必要了)。虽然全局范围内可能包含无限多单元,但每个给定时刻都对象只“占据”(overlapped)有限数目的单元。即散列存储仅与对象的数目相关而与网格单元数目无关。
为避免哈希表查找空的网格单元,再使用一个密集位数组来快速检测某个单元是否为空。当然,这一优化仅当单元尺寸固定时可用。
解决哈希表冲突问题,常见开散列、闭散列方法,具体参考哈希相关资料。
7.1.3 静态数据存储
静态网格数据,比如多边形单元数据,存储不需要链表,而采用储连续数组。下图阐释链表存储和数组存储:
单元数据(即单元内对象个数)分配到数组可分为两个传入步骤。首先,遍历所有对象数据:当某个对象落入某个单元,并不直接将该对象数据加入该单元,而仅对该单元的对象计数器进行加1操作。当所有对象走完一遍后,每个单元的计数器就知道了各个单元Ck里有ak个对象。这样共需分配的数组大小m:
M=sum(ak) k=0,n
每个单元还有一个全局索引号B(k):
B(0)=0
B(k)=b(k-1)+a(k-1)
这时就进行第二遍遍历。对含有a(k)个对象的单元c(k),对象编号采用全局索引就表示成b(k)到b(k)+a(k)-1。因为每个单元中的数据都是连续存储在数组中的,这样基于数组存储的网格单元使用了更少的内存,相比链表存储具有更高的cache效率。
7.1.4 隐式存储
间接地采用笛卡尔坐标形式。对平面网格使用两个数组(3D需要三个数组),其中一个记录网格的行信息,另一个记录网格的列信息。同链表存储,数组的每个元素都是对象链表,存储了所在行或列"具有“(overlapped by)哪些对象。当一个对象”占据“(overlap)某些单元时,需要根据其”占据“单元的位置将该对象分别加入行、列数组对应的位置。这样两对象是否重叠/碰撞就只需检测其所”占据“的行、列是否有重叠。
与链表存储相比,该策略可能造成更少或更多的链表插入操作。当对象完全"落入"某一个单元,需要两次插入操作,即分别插入行链、列链。但在链表存储中只需要一次插入操作。但当对象“占据”,比如4*4个单元,它共需对8个数组元素进行插入操作而链表存储就需要16次插入操作。可见,该方法较适合对象尺寸大于单元尺寸的情形。
另一种新意的存储方法是为网格每行每列分配一个位数组,一个对象就用一位来表示。对象插入过程就可以简化为对该对象的位操作。当且仅当某个单元在行、列位数组中的位值与对象的位值对应,该对象才“占据”该单元。即对象是否“占据”某个单元的测试,简化为行位数组和列位数组的AND位操作。
当对象"占据"多个单元时,可(利用位操作的分配律)如下操作:假设某个对象“占据”行r(i), r(i+1); 列 c(j), c(j+1),即该对象”占据“四个单元 (r(i), c(j)), (r(i),c(j+1)),(r(i+1),c(j+1)), (r(i+1),c(j)).
B=(r(i) &c(j)) |(r(i+1)&c(j))| (r(i+1) &c(j+1))| (r(i) &c(j+1));
上式进一步简化:
B=(r(i)|r(i+1)) &(c(j) |c(j+1))
概括如下:首先对所有“重叠”单元的行、列执行OR位操作,然后对OR位操作的结果执行AND位操作即得到结果。代码如下://define the two global bit arraysconst int NUM_OBJECTS_DIV_32=(NUM_OBJECTS+31)/32; // Round upint32 rowBitArray[GRID_HEIGHT][NUM_OBJECTS_DIV_32];int32 columnBitArray[GRID_WIDTH][NUM_OBJECTS_DIV_32];void TestObjectAgainstGrid(Object *pObject) {// allocate temporary bit arrays for all objects and clear them int32 mergedRowArray[NUM_OBJECTS_DIV_32]; int32 mergedColumnArray[NUM_OBJECTS_DIV_32]; memset(mergedRowArray, 0, NUM_OBJECTS_DIV_32*sizeof(int32)); memset(mergedColumnArray, 0, NUM_OBJECTS_DIV_32*sizeof(int32));// //Compute the extent of grid cells the bounding sphere of A overlaps//test assumes objects have been inserted in all rows/columns overlapped float ooCellWidth=1.0f/CELL_WIDTH; int x1=(int) floorf((pObject->x-pObject->radius)*ooCellWidth); int x2=(int) floorf((pObject->x+pObject->radius)*ooCellWidth); int y1=(int) floorf((pObject->y-pObject->radius)*ooCellWidth); int y2=(int) floorf((pObject->y+pObject->radius)*ooCellWidth); assert(x1>=0 && y1>=0 && x2<GRID_WIDTH && x2<GRID_HEIGHT);//// compute the merged(bitwise or/ and) bit array of all overlapped grid rows// ditto for all overlapped grid columns for (int y=y1; y<=y2; y++)for(int i=0; i<NUM_OBJECTS_DIV_32;i++) mergedRowArray[i] |=rowBitArray[y][i]; for(int x=x1; x<=x2; x++) for(int i=0; i<NUM_OBJECTS_DIV_32;i++)mergedColumnArray[i] |=ColumnBitArray[y][i];//// now go through the intersection of the merged bit arrays and collision test those // objects having their corresponding bit set for (int i=0; i<NUM_OBJECTS_DIV_32; i++) { int objectsMask=mergedRowArray[i] & mergedColumnArray[i]; while(objectsMask) {// clear all but lowest bit set (eg. 01101010 -> 00000010)int32 objectsMask=objectsMask &(objectsMaskk-1);// get index number of set bit, test against corresponding object// GetBitIndex(v) returns log_2(v). (i.e. 2^n=v)int32 objectIndex=GetBitIndex(objectMask)+i*32;TestCollisionAgainstObjectNumber(objectIndex);// mask out tested object, and continue with any remaining objectsobjectsMask ^=objectMask; } }}
网格单元存储的三种方法中隐式位操作最高效。
7.1.5 碰撞测试 /下一篇 next
- 空间划分(real time collision detection chapter 7)
- 碰撞测试 (Real Time Collision Detection Chapter 7)
- Real Time Collision Detection
- Real-Time Rendering (9) - 碰撞检测(Collision Detection)
- YOLO: Real-Time Object Detection
- YOLO: Real-Time Object Detection
- YOLO: Real-Time Object Detection
- YOLO: Real-Time Object Detection
- Robust Real-time Face Detection
- collision detection
- YOLO: Real-Time Object Detection解读
- YOLO:Real-Time Object Detection学习笔记
- Tensorflow API + OpenCV (Real Time Object Detection)
- Real-Time Rendering Chapter 1~6 读书笔记
- RCNN学习笔记(7):You Only Look Once(YOLO):Unified, Real-Time Object Detection
- Demo version of the real-time face detection program
- Pan JiaPu/ A real-time QRS detection algorithm
- 10年后再看Robust Real-Time Face Detection(一)
- 【Android工具】被忽略的UI检视利器:Hierarchy Viewer
- Office 2010提示:您正试图运行的函数包含有宏或需要宏语言支持的内容的解决方法
- hdu 2767 Proving Equivalences 等价性证明 强连通分量
- linux下vmware的安装与卸载
- 浅谈SOCKET字节流和字符流的区别
- 空间划分(real time collision detection chapter 7)
- C++编写服务程序
- cognos展示技巧(三)动态排序
- Delphi7 尚未调用CoInitialize 与 Application 的图标丢失
- CSS3 Box-shadow
- linux-2.6.35内核版本中class_create()和device_create的使用
- C#调用外部exe作为子窗体或UI? VC++如何实现呢呢?...札记plus
- 敏捷外包工程之五:报价管理(一)
- ENSURE_COLUMN