| 542 | } |
| 543 | |
| 544 | bool BucketPrunerCore::addObject(const PrunerPayload& object, const PxBounds3& worldAABB, PxU32 timeStamp) |
| 545 | { |
| 546 | /* |
| 547 | We should probably use a bigger Payload struct here, which would also contains the external handle. |
| 548 | (EDIT: we can't even do that, because of the setExternalMemory function) |
| 549 | When asked to update/remove an object it would be O(n) to find the proper object in the mSortedObjects array. |
| 550 | |
| 551 | - |
| 552 | |
| 553 | For removing it we can simply empty the corresponding box, and the object will never be returned from queries. |
| 554 | Maybe this isn't even true, since boxes are sorted along one axis. So marking a box as empty could break the code relying on a sorted order. |
| 555 | An alternative is to mark the external handle as invalid, and ignore the object when a hit is found. |
| 556 | |
| 557 | (EDIT: the sorting is now tested via data0/data1 anyway so we could mark the box as empty without breaking this) |
| 558 | |
| 559 | - |
| 560 | |
| 561 | For updating an object we would need to keep the (sub) array sorted (not the whole thing, only the array within a bucket). |
| 562 | We don't know the range (what part of the array maps to our bucket) but we may have the bucket ID somewhere? If we'd have this |
| 563 | we could parse the array left/right and resort just the right boxes. If we don't have this we may be able to "quickly" find the |
| 564 | range by traversing the tree, looking for the proper bucket. In any case I don't think there's a mapping to update within a bucket, |
| 565 | unlike in SAP or MBP. So we should be able to shuffle a bucket without having to update anything. For example there's no mapping |
| 566 | between the Core array and the Sorted array. It's a shame in a way because we'd need one, but it's not there - and in fact I think |
| 567 | we can free the Core array once Sorted is created, we don't need it at all. |
| 568 | |
| 569 | If we don't want to re-sort the full bucket we can just mark it as dirty and ignore the sort-based early exits in the queries. Then we |
| 570 | can incrementally resort it over N frames or something. |
| 571 | |
| 572 | This only works if the updated object remains in the same bucket though. If it moves to another bucket it becomes tempting to just remove |
| 573 | the object and re-insert it. |
| 574 | |
| 575 | - |
| 576 | |
| 577 | Now for adding an object, we can first have a "free pruner" and do the 16 next entries brute-force. Rebuilding every 16 objects might |
| 578 | give a good speedup already. Otherwise we need to do something more complicated. |
| 579 | */ |
| 580 | |
| 581 | PX_ASSERT(mOwnMemory); |
| 582 | PX_ASSERT(!mDirty || !mNbFree); |
| 583 | if(!mDirty) |
| 584 | { |
| 585 | // In this path the structure is marked as valid. We do not want to invalidate it for each new object... |
| 586 | if(mNbFree<FREE_PRUNER_SIZE) |
| 587 | { |
| 588 | // ...so as long as there is space in the "free array", we store the newly added object there and |
| 589 | // return immediately. Subsequent queries will parse the free array as if it was a free pruner. |
| 590 | const PxU32 index = mNbFree++; |
| 591 | mFreeObjects[index] = object; |
| 592 | mFreeBounds[index] = worldAABB; |
| 593 | mFreeStamps[index] = timeStamp; |
| 594 | return true; |
| 595 | } |
| 596 | |
| 597 | // If we reach this place, the free array is full. We must transfer the objects from the free array to |
| 598 | // the main (core) arrays, mark the structure as invalid, and still deal with the incoming object. |
| 599 | |
| 600 | // First we transfer free objects, reset the number of free objects, and mark the structure as |
| 601 | // invalid/dirty (the core arrays will need rebuilding). |
no outgoing calls
no test coverage detected