1 module Engine.Tree.BBTree; 2 3 import Engine.math; 4 alias ulong TimeStamp; 5 alias ulong Hash; 6 import std.stdio; 7 import Engine.Allocator; 8 import std.parallelism; 9 import std.concurrency; 10 import core.atomic; 11 12 alias ulong delegate(Indexable a,Indexable b, ulong collisionID) SpatialIndexQueryFunc; 13 alias void delegate(Node* node) HashSetIterator; 14 15 shared class Stack(T) { 16 private shared struct Node { 17 T _payload; 18 Node * _next; 19 } 20 private Node * _root; 21 22 void push(T value) { 23 auto n = cast(shared)new Node(value); 24 n._payload = value; 25 shared(Node)* oldRoot; 26 do { 27 oldRoot = _root; 28 n._next = oldRoot; 29 } while (!cas(&_root, oldRoot, n)); 30 } 31 32 shared(T)* pop() { 33 typeof(return) result; 34 shared(Node)* oldRoot; 35 do { 36 oldRoot = _root; 37 if (!oldRoot) return null; 38 result = & oldRoot._payload; 39 } while (!cas(&_root, oldRoot, oldRoot._next)); 40 return result; 41 } 42 43 bool empty() { 44 if (atomicLoad(_root)) 45 return false; 46 return true; 47 } 48 } 49 50 class BBTree : Tree 51 { 52 ChunkAllocator!(Node, 100) nodeAllocator; 53 int allocatedNodes = 0; 54 int freedNodes = 0; 55 56 Node*[Indexable] leaves; 57 Node* root; 58 59 @property ref TimeStamp stamp() { 60 return stamp_; 61 } 62 TimeStamp stamp_; 63 64 Tree staticTree; 65 Tree dynamicTree; 66 67 this(Tree staticTree) 68 { 69 if (staticTree !is null) { 70 this.staticTree = staticTree; 71 } 72 stamp_ = 0; 73 } 74 75 @property size_t length() const { 76 return leaves.length; 77 } 78 79 void Each(HashSetIterator func) { 80 foreach (Node* node; leaves) { 81 func(node); 82 } 83 } 84 85 void Insert(Indexable obj ) { 86 auto leaf = NewLeaf(obj); 87 leaves[obj] = leaf; 88 this.root = this.SubtreeInsert(this.root, leaf); 89 leaf.stamp = GetMasterTree().stamp; 90 IncrementStamp(); 91 } 92 93 94 void Query(Indexable obj, rect bb, SpatialIndexQueryFunc func) { 95 if(root) 96 SubtreeQuery(root, obj, bb, func); 97 } 98 99 void SubtreeQuery(Node *subtree, Indexable obj, rect bb, SpatialIndexQueryFunc func) 100 { 101 if(rect.Intersects(subtree.bb, bb)){ 102 if(subtree.NodeIsLeaf()){ 103 func(obj, subtree.obj, 0); 104 } else { 105 SubtreeQuery(subtree.a, obj, bb, func); 106 SubtreeQuery(subtree.b, obj, bb, func); 107 } 108 } 109 } 110 111 void LeafQuery()(Node *subtree, Node *leaf, SpatialIndexQueryFunc func) 112 { 113 if(rect.Intersects(leaf.bb, subtree.bb)){ 114 if(subtree.NodeIsLeaf()) { 115 if (func !is null) { 116 func(leaf.obj, subtree.obj, 0); 117 } 118 } else { 119 LeafQuery(subtree.a, leaf,func); 120 LeafQuery(subtree.b, leaf,func); 121 } 122 } 123 } 124 125 void NodeQuery()(Node *leaf, Node *staticRoot, SpatialIndexQueryFunc func) 126 { 127 if(staticRoot !is null) 128 LeafQuery(staticRoot, leaf, func); 129 130 for(Node *node = leaf; node.parent !is null; node = node.parent){ 131 if(node == node.parent.a){ 132 LeafQuery(node.parent.b, leaf, func); 133 } 134 } 135 } 136 137 138 void SubtreeSelfQuery()(Node *subtree, Node *staticRoot, SpatialIndexQueryFunc func) { 139 if(subtree.NodeIsLeaf()){ 140 NodeQuery(subtree,staticRoot,func); 141 } else { 142 SubtreeSelfQuery(subtree.a,staticRoot,func); 143 SubtreeSelfQuery(subtree.b,staticRoot,func); // TODO: Force TCO here? 144 } 145 } 146 147 bool LeafUpdate(Node *leaf) 148 { 149 auto rt = root; 150 if(!rect.Contains(leaf.bb, leaf.obj.BB())){ 151 leaf.bb = BB(leaf.obj); 152 153 rt = SubtreeRemove(rt, leaf); 154 root = SubtreeInsert(rt, leaf); 155 156 leaf.stamp = GetMasterTree.stamp; 157 158 return true; 159 } else { 160 return false; 161 } 162 } 163 164 Node* NodeFromPool() { 165 allocatedNodes++; 166 return nodeAllocator.allocate(); 167 } 168 169 void NodeRecycle(Node *node) 170 { 171 freedNodes++; 172 node.parent = null; 173 nodeAllocator.free(node); 174 } 175 176 Node* SubtreeRemove(Node *subtree, Node *leaf) 177 { 178 if(leaf == subtree){ 179 return null; 180 } else { 181 Node *parent = leaf.parent; 182 if(parent == subtree){ 183 Node *other = subtree.NodeOther(leaf); 184 other.parent = subtree.parent; 185 NodeRecycle(subtree); 186 return other; 187 } else { 188 NodeReplaceChild(parent.parent, parent, parent.NodeOther(leaf)); 189 return subtree; 190 } 191 } 192 } 193 194 void NodeReplaceChild(Node *parent, Node *child, Node *value) 195 { 196 assert(!parent.NodeIsLeaf(), "Internal Error: Cannot replace child of a leaf."); 197 assert(child == parent.a || child == parent.b, "Internal Error: Node is not a child of parent."); 198 199 if(parent.a == child){ 200 NodeRecycle(parent.a); 201 parent.NodeSetA(value); 202 } else { 203 NodeRecycle(parent.b); 204 parent.NodeSetB(value); 205 } 206 207 for(Node *node=parent; node; node = node.parent){ 208 node.bb = rect.Merge(node.a.bb, node.b.bb); 209 } 210 } 211 212 void ReindexQuery(SpatialIndexQueryFunc func) 213 { 214 if(root is null) return; 215 216 // LeafUpdate() may modify tree->root. Don't cache it. 217 foreach (ref leaf ; leaves) { 218 LeafUpdate(leaf); 219 } 220 221 auto staticIndex = cast(BBTree)staticTree; 222 Node *staticRoot = staticIndex !is null ? staticIndex.root : null; 223 224 SubtreeSelfQuery(root,staticRoot,func); 225 226 if(staticIndex && !staticRoot) 227 SpatialIndexCollideStatic(this, staticIndex, func); 228 229 IncrementStamp(); 230 } 231 232 static void SpatialIndexCollideStatic(Tree tree, Tree staticIndex, SpatialIndexQueryFunc func) { 233 if (staticIndex.length > 0) { 234 tree.Each((Node* node) { 235 staticIndex.Query(node.obj, node.obj.BB(), func); 236 }); 237 } 238 } 239 240 void IncrementStamp()() 241 { 242 if (dynamicTree !is null) { 243 dynamicTree.stamp++; 244 } else { 245 stamp++; 246 } 247 } 248 249 Tree GetMasterTree()() { 250 if (dynamicTree !is null) { 251 return dynamicTree; 252 } 253 return this; 254 } 255 256 Node * SubtreeInsert(Node *subtree, Node *leaf) 257 { 258 if(subtree is null){ 259 return leaf; 260 } else if(subtree.NodeIsLeaf()){ 261 return NodeNew(leaf, subtree); 262 } else { 263 auto cost_a = subtree.b.bb.Area() + rect.MergedArea(subtree.a.bb, leaf.bb); 264 auto cost_b = subtree.a.bb.Area() + rect.MergedArea(subtree.b.bb, leaf.bb); 265 266 if(cost_a == cost_b){ 267 cost_a = rect.Proximity(subtree.a.bb, leaf.bb); 268 cost_b = rect.Proximity(subtree.b.bb, leaf.bb); 269 } 270 271 if(cost_b < cost_a){ 272 subtree.NodeSetB(SubtreeInsert(subtree.b, leaf)); 273 } else { 274 subtree.NodeSetA(SubtreeInsert(subtree.a, leaf)); 275 } 276 subtree.bb = rect.Merge(subtree.bb, leaf.bb); 277 278 return subtree; 279 } 280 } 281 282 Node* NodeNew(Node* a, Node* b) 283 { 284 Node *node = NodeFromPool(); 285 286 node.obj = null; 287 node.bb = rect.Merge(a.bb, b.bb); 288 node.parent = null; 289 290 node.NodeSetA(a); 291 node.NodeSetB(b); 292 293 return node; 294 } 295 296 rect BB(Indexable obj ) 297 { 298 auto bb = obj.BB(); 299 300 /* 301 cpBBTreeVelocityFunc velocityFunc = tree->velocityFunc; 302 if(velocityFunc){ 303 cpFloat coef = 0.1f; 304 cpFloat x = (bb.r - bb.l)*coef; 305 cpFloat y = (bb.t - bb.b)*coef; 306 307 cpVect v = cpvmult(velocityFunc(obj), 0.1f); 308 return cpBBNew(bb.l + cpfmin(-x, v.x), bb.b + cpfmin(-y, v.y), bb.r + cpfmax(x, v.x), bb.t + cpfmax(y, v.y)); 309 } else { 310 return bb; 311 } 312 */ 313 return bb; 314 } 315 316 Node* NewLeaf(Indexable obj ){ 317 auto node = NodeFromPool(); 318 node.obj = obj; 319 node.bb = BB(obj); 320 321 node.parent = null; 322 node.stamp = 0; 323 324 return node; 325 } 326 } 327 328 interface Tree { 329 330 @property ref TimeStamp stamp(); 331 @property size_t length() const; 332 333 void Each(HashSetIterator fnc); 334 335 //Contains(obj Indexable) bool 336 void Insert(Indexable obj); 337 //Remove(obj Indexable) 338 339 //Reindex() 340 //ReindexObject(obj Indexable) 341 //ReindexQuery(fnc SpatialIndexQueryFunc) 342 343 //TimeStamp Stamp(); 344 345 void Query(Indexable obj, rect aabb, SpatialIndexQueryFunc fnc); 346 //SegmentQuery(obj Indexable, a, b vect.Vect, t_exit vect.Float, fnc func()) 347 } 348 349 interface Indexable { 350 //Hash GetHash(); 351 rect BB(); 352 } 353 354 private struct Node { 355 public Indexable obj; 356 rect bb; 357 Node *parent; 358 359 bool NodeIsLeaf() 360 { 361 return obj !is null; 362 } 363 364 Node* NodeOther(Node *child) 365 { 366 return (a == child ? b : a); 367 } 368 369 void NodeSetA()(Node *value) 370 { 371 a = value; 372 value.parent = &this; 373 } 374 375 void NodeSetB()(Node *value) 376 { 377 b = value; 378 value.parent = &this; 379 } 380 381 //children 382 Node* a, b; 383 384 //leaf 385 TimeStamp stamp; 386 };