1 /********************************************************************************
2 * ReactPhysics3D physics library, http://www.reactphysics3d.com                 *
3 * Copyright (c) 2010-2020 Daniel Chappuis                                       *
4 *********************************************************************************
5 *                                                                               *
6 * This software is provided 'as-is', without any express or implied warranty.   *
7 * In no event will the authors be held liable for any damages arising from the  *
8 * use of this software.                                                         *
9 *                                                                               *
10 * Permission is granted to anyone to use this software for any purpose,         *
11 * including commercial applications, and to alter it and redistribute it        *
12 * freely, subject to the following restrictions:                                *
13 *                                                                               *
14 * 1. The origin of this software must not be misrepresented; you must not claim *
15 *    that you wrote the original software. If you use this software in a        *
16 *    product, an acknowledgment in the product documentation would be           *
17 *    appreciated but is not required.                                           *
18 *                                                                               *
19 * 2. Altered source versions must be plainly marked as such, and must not be    *
20 *    misrepresented as being the original software.                             *
21 *                                                                               *
22 * 3. This notice may not be removed or altered from any source distribution.    *
23 *                                                                               *
24 ********************************************************************************/
25 
26 // Libraries
27 #include <cassert>
28 #include <reactphysics3d/engine/OverlappingPairs.h>
29 #include <reactphysics3d/containers/containers_common.h>
30 #include <reactphysics3d/collision/ContactPointInfo.h>
31 #include <reactphysics3d/collision/narrowphase/NarrowPhaseAlgorithm.h>
32 #include <reactphysics3d/collision/narrowphase/CollisionDispatch.h>
33 
34 using namespace reactphysics3d;
35 
36 // Constructor
OverlappingPairs(MemoryAllocator & persistentMemoryAllocator,MemoryAllocator & temporaryMemoryAllocator,ColliderComponents & colliderComponents,CollisionBodyComponents & collisionBodyComponents,RigidBodyComponents & rigidBodyComponents,Set<bodypair> & noCollisionPairs,CollisionDispatch & collisionDispatch)37 OverlappingPairs::OverlappingPairs(MemoryAllocator& persistentMemoryAllocator, MemoryAllocator& temporaryMemoryAllocator, ColliderComponents &colliderComponents,
38                                    CollisionBodyComponents& collisionBodyComponents, RigidBodyComponents& rigidBodyComponents, Set<bodypair> &noCollisionPairs, CollisionDispatch &collisionDispatch)
39                 : mPersistentAllocator(persistentMemoryAllocator), mTempMemoryAllocator(temporaryMemoryAllocator),
40                   mNbPairs(0), mConcavePairsStartIndex(0), mPairDataSize(sizeof(uint64) + sizeof(int32) + sizeof(int32) + sizeof(Entity) +
41                                                                          sizeof(Entity) + sizeof(Map<uint64, LastFrameCollisionInfo*>) +
42                                                                          sizeof(bool) + sizeof(bool) + sizeof(NarrowPhaseAlgorithmType) +
43                                                                          sizeof(bool) + sizeof(bool) + sizeof(bool)),
44                   mNbAllocatedPairs(0), mBuffer(nullptr),
45                   mMapPairIdToPairIndex(persistentMemoryAllocator),
46                   mColliderComponents(colliderComponents), mCollisionBodyComponents(collisionBodyComponents),
47                   mRigidBodyComponents(rigidBodyComponents), mNoCollisionPairs(noCollisionPairs), mCollisionDispatch(collisionDispatch) {
48 
49     // Allocate memory for the components data
50     allocate(INIT_NB_ALLOCATED_PAIRS);
51 }
52 
53 // Destructor
~OverlappingPairs()54 OverlappingPairs::~OverlappingPairs() {
55 
56     // If there are allocated pairs
57     if (mNbAllocatedPairs > 0) {
58 
59         // Destroy all the remaining pairs
60         for (uint32 i = 0; i < mNbPairs; i++) {
61 
62             // Remove all the remaining last frame collision info
63             for (auto it = mLastFrameCollisionInfos[i].begin(); it != mLastFrameCollisionInfos[i].end(); ++it) {
64 
65                 // Call the constructor
66                 it->second->~LastFrameCollisionInfo();
67 
68                 // Release memory
69                 mPersistentAllocator.release(it->second, sizeof(LastFrameCollisionInfo));
70             }
71 
72             // Remove the involved overlapping pair to the two colliders
73             assert(mColliderComponents.getOverlappingPairs(mColliders1[i]).find(mPairIds[i]) != mColliderComponents.getOverlappingPairs(mColliders1[i]).end());
74             assert(mColliderComponents.getOverlappingPairs(mColliders2[i]).find(mPairIds[i]) != mColliderComponents.getOverlappingPairs(mColliders2[i]).end());
75             mColliderComponents.getOverlappingPairs(mColliders1[i]).remove(mPairIds[i]);
76             mColliderComponents.getOverlappingPairs(mColliders2[i]).remove(mPairIds[i]);
77 
78             destroyPair(i);
79         }
80 
81         // Size for the data of a single pair (in bytes)
82         const size_t totalSizeBytes = mNbAllocatedPairs * mPairDataSize;
83 
84         // Release the allocated memory
85         mPersistentAllocator.release(mBuffer, totalSizeBytes);
86     }
87 }
88 
89 // Compute the index where we need to insert the new pair
prepareAddPair(bool isConvexVsConvex)90 uint64 OverlappingPairs::prepareAddPair(bool isConvexVsConvex) {
91 
92     // If we need to allocate more components
93     if (mNbPairs == mNbAllocatedPairs) {
94         allocate(mNbAllocatedPairs * 2);
95     }
96 
97     uint64 index;
98 
99     // If the pair to add is not convex vs convex or there are no concave pairs yet
100     if (!isConvexVsConvex) {
101 
102         // Add the component at the end of the array
103         index = mNbPairs;
104     }
105     // If the pair to add is convex vs convex
106     else {
107 
108         // If there already are convex vs concave pairs
109         if (mConcavePairsStartIndex != mNbPairs) {
110 
111             // Move the first convex vs concave pair to the end of the array
112             movePairToIndex(mConcavePairsStartIndex, mNbPairs);
113         }
114 
115         index = mConcavePairsStartIndex;
116 
117         mConcavePairsStartIndex++;
118     }
119 
120     return index;
121 }
122 
123 // Remove a component at a given index
removePair(uint64 pairId)124 void OverlappingPairs::removePair(uint64 pairId) {
125 
126     RP3D_PROFILE("OverlappingPairs::removePair()", mProfiler);
127 
128     assert(mMapPairIdToPairIndex.containsKey(pairId));
129 
130     uint64 index = mMapPairIdToPairIndex[pairId];
131     assert(index < mNbPairs);
132 
133     // We want to keep the arrays tightly packed. Therefore, when a pair is removed,
134     // we replace it with the last element of the array. But we need to make sure that convex
135     // and concave pairs stay grouped together.
136 
137     // Remove all the remaining last frame collision info
138     for (auto it = mLastFrameCollisionInfos[index].begin(); it != mLastFrameCollisionInfos[index].end(); ++it) {
139 
140         // Call the constructor
141         it->second->~LastFrameCollisionInfo();
142 
143         // Release memory
144         mPersistentAllocator.release(it->second, sizeof(LastFrameCollisionInfo));
145     }
146 
147     // Remove the involved overlapping pair to the two colliders
148     assert(mColliderComponents.getOverlappingPairs(mColliders1[index]).find(pairId) != mColliderComponents.getOverlappingPairs(mColliders1[index]).end());
149     assert(mColliderComponents.getOverlappingPairs(mColliders2[index]).find(pairId) != mColliderComponents.getOverlappingPairs(mColliders2[index]).end());
150     mColliderComponents.getOverlappingPairs(mColliders1[index]).remove(pairId);
151     mColliderComponents.getOverlappingPairs(mColliders2[index]).remove(pairId);
152 
153     // Destroy the pair
154     destroyPair(index);
155 
156     // If the pair to remove is convex vs concave
157     if (index >= mConcavePairsStartIndex) {
158 
159         // If the pair is not the last one
160         if (index != mNbPairs - 1) {
161 
162             // We replace it by the last convex vs concave pair
163             movePairToIndex(mNbPairs - 1, index);
164         }
165     }
166     else {   // If the pair to remove is convex vs convex
167 
168         // If it not the last convex vs convex pair
169         if (index != mConcavePairsStartIndex - 1) {
170 
171             // We replace it by the last convex vs convex pair
172             movePairToIndex(mConcavePairsStartIndex - 1, index);
173         }
174 
175         // If there are convex vs concave pairs at the end
176         if (mConcavePairsStartIndex != mNbPairs) {
177 
178             // We replace the last convex vs convex pair by the last convex vs concave pair
179             movePairToIndex(mNbPairs - 1, mConcavePairsStartIndex - 1);
180         }
181 
182         mConcavePairsStartIndex--;
183     }
184 
185     mNbPairs--;
186 
187     assert(mConcavePairsStartIndex <= mNbPairs);
188     assert(mNbPairs == static_cast<uint32>(mMapPairIdToPairIndex.size()));
189 }
190 
191 // Allocate memory for a given number of pairs
allocate(uint64 nbPairsToAllocate)192 void OverlappingPairs::allocate(uint64 nbPairsToAllocate) {
193 
194     assert(nbPairsToAllocate > mNbAllocatedPairs);
195 
196     // Size for the data of a single component (in bytes)
197     const size_t totalSizeBytes = nbPairsToAllocate * mPairDataSize;
198 
199     // Allocate memory
200     void* newBuffer = mPersistentAllocator.allocate(totalSizeBytes);
201     assert(newBuffer != nullptr);
202 
203     // New pointers to components data
204     uint64* newPairIds = static_cast<uint64*>(newBuffer);
205     int32* newPairBroadPhaseId1 = reinterpret_cast<int32*>(newPairIds + nbPairsToAllocate);
206     int32* newPairBroadPhaseId2 = reinterpret_cast<int32*>(newPairBroadPhaseId1 + nbPairsToAllocate);
207     Entity* newColliders1 = reinterpret_cast<Entity*>(newPairBroadPhaseId2 + nbPairsToAllocate);
208     Entity* newColliders2 = reinterpret_cast<Entity*>(newColliders1 + nbPairsToAllocate);
209     Map<uint64, LastFrameCollisionInfo*>* newLastFrameCollisionInfos = reinterpret_cast<Map<uint64, LastFrameCollisionInfo*>*>(newColliders2 + nbPairsToAllocate);
210     bool* newNeedToTestOverlap = reinterpret_cast<bool*>(newLastFrameCollisionInfos + nbPairsToAllocate);
211     bool* newIsActive = reinterpret_cast<bool*>(newNeedToTestOverlap + nbPairsToAllocate);
212     NarrowPhaseAlgorithmType* newNarrowPhaseAlgorithmType = reinterpret_cast<NarrowPhaseAlgorithmType*>(newIsActive + nbPairsToAllocate);
213     bool* newIsShape1Convex = reinterpret_cast<bool*>(newNarrowPhaseAlgorithmType + nbPairsToAllocate);
214     bool* wereCollidingInPreviousFrame = reinterpret_cast<bool*>(newIsShape1Convex + nbPairsToAllocate);
215     bool* areCollidingInCurrentFrame = reinterpret_cast<bool*>(wereCollidingInPreviousFrame + nbPairsToAllocate);
216 
217     // If there was already pairs before
218     if (mNbPairs > 0) {
219 
220         // Copy component data from the previous buffer to the new one
221         memcpy(newPairIds, mPairIds, mNbPairs * sizeof(uint64));
222         memcpy(newPairBroadPhaseId1, mPairBroadPhaseId1, mNbPairs * sizeof(int32));
223         memcpy(newPairBroadPhaseId2, mPairBroadPhaseId2, mNbPairs * sizeof(int32));
224         memcpy(newColliders1, mColliders1, mNbPairs * sizeof(Entity));
225         memcpy(newColliders2, mColliders2, mNbPairs * sizeof(Entity));
226         memcpy(newLastFrameCollisionInfos, mLastFrameCollisionInfos, mNbPairs * sizeof(Map<uint64, LastFrameCollisionInfo*>));
227         memcpy(newNeedToTestOverlap, mNeedToTestOverlap, mNbPairs * sizeof(bool));
228         memcpy(newIsActive, mIsActive, mNbPairs * sizeof(bool));
229         memcpy(newNarrowPhaseAlgorithmType, mNarrowPhaseAlgorithmType, mNbPairs * sizeof(NarrowPhaseAlgorithmType));
230         memcpy(newIsShape1Convex, mIsShape1Convex, mNbPairs * sizeof(bool));
231         memcpy(wereCollidingInPreviousFrame, mCollidingInPreviousFrame, mNbPairs * sizeof(bool));
232         memcpy(areCollidingInCurrentFrame, mCollidingInCurrentFrame, mNbPairs * sizeof(bool));
233 
234         // Deallocate previous memory
235         mPersistentAllocator.release(mBuffer, mNbAllocatedPairs * mPairDataSize);
236     }
237 
238     mBuffer = newBuffer;
239     mPairIds = newPairIds;
240     mPairBroadPhaseId1 = newPairBroadPhaseId1;
241     mPairBroadPhaseId2 = newPairBroadPhaseId2;
242     mColliders1 = newColliders1;
243     mColliders2 = newColliders2;
244     mLastFrameCollisionInfos = newLastFrameCollisionInfos;
245     mNeedToTestOverlap = newNeedToTestOverlap;
246     mIsActive = newIsActive;
247     mNarrowPhaseAlgorithmType = newNarrowPhaseAlgorithmType;
248     mIsShape1Convex = newIsShape1Convex;
249     mCollidingInPreviousFrame = wereCollidingInPreviousFrame;
250     mCollidingInCurrentFrame = areCollidingInCurrentFrame;
251 
252     mNbAllocatedPairs = nbPairsToAllocate;
253 }
254 
255 // Add an overlapping pair
addPair(Collider * shape1,Collider * shape2)256 uint64 OverlappingPairs::addPair(Collider* shape1, Collider* shape2) {
257 
258     RP3D_PROFILE("OverlappingPairs::addPair()", mProfiler);
259 
260     const Entity collider1 = shape1->getEntity();
261     const Entity collider2 = shape2->getEntity();
262 
263     const uint collider1Index = mColliderComponents.getEntityIndex(collider1);
264     const uint collider2Index = mColliderComponents.getEntityIndex(collider2);
265 
266     const CollisionShape* collisionShape1 = mColliderComponents.mCollisionShapes[collider1Index];
267     const CollisionShape* collisionShape2 = mColliderComponents.mCollisionShapes[collider2Index];
268 
269     const bool isShape1Convex = collisionShape1->isConvex();
270     const bool isShape2Convex = collisionShape2->isConvex();
271     const bool isConvexVsConvex = isShape1Convex && isShape2Convex;
272 
273     // Prepare to add new pair (allocate memory if necessary and compute insertion index)
274     uint64 index = prepareAddPair(isConvexVsConvex);
275 
276     const uint32 broadPhase1Id = static_cast<uint32>(shape1->getBroadPhaseId());
277     const uint32 broadPhase2Id = static_cast<uint32>(shape2->getBroadPhaseId());
278 
279     // Compute a unique id for the overlapping pair
280     const uint64 pairId = pairNumbers(std::max(broadPhase1Id, broadPhase2Id), std::min(broadPhase1Id, broadPhase2Id));
281 
282     assert(!mMapPairIdToPairIndex.containsKey(pairId));
283 
284     // Select the narrow phase algorithm to use according to the two collision shapes
285     NarrowPhaseAlgorithmType algorithmType;
286     if (isConvexVsConvex) {
287 
288         algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(collisionShape1->getType(), collisionShape2->getType());
289     }
290     else {
291 
292         algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(isShape1Convex ? collisionShape1->getType() : collisionShape2->getType(),
293                                                                       CollisionShapeType::CONVEX_POLYHEDRON);
294     }
295 
296     // Insert the new component data
297     new (mPairIds + index) uint64(pairId);
298     new (mPairBroadPhaseId1 + index) int32(shape1->getBroadPhaseId());
299     new (mPairBroadPhaseId2 + index) int32(shape2->getBroadPhaseId());
300     new (mColliders1 + index) Entity(shape1->getEntity());
301     new (mColliders2 + index) Entity(shape2->getEntity());
302     new (mLastFrameCollisionInfos + index) Map<uint64, LastFrameCollisionInfo*>(mPersistentAllocator);
303     new (mNeedToTestOverlap + index) bool(false);
304     new (mIsActive + index) bool(true);
305     new (mNarrowPhaseAlgorithmType + index) NarrowPhaseAlgorithmType(algorithmType);
306     new (mIsShape1Convex + index) bool(isShape1Convex);
307     new (mCollidingInPreviousFrame + index) bool(false);
308     new (mCollidingInCurrentFrame + index) bool(false);
309 
310     // Map the entity with the new component lookup index
311     mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, index));
312 
313     // Add the involved overlapping pair to the two colliders
314     assert(mColliderComponents.mOverlappingPairs[collider1Index].find(pairId) == mColliderComponents.mOverlappingPairs[collider1Index].end());
315     assert(mColliderComponents.mOverlappingPairs[collider2Index].find(pairId) == mColliderComponents.mOverlappingPairs[collider2Index].end());
316     mColliderComponents.mOverlappingPairs[collider1Index].add(pairId);
317     mColliderComponents.mOverlappingPairs[collider2Index].add(pairId);
318 
319     mNbPairs++;
320 
321     assert(mConcavePairsStartIndex <= mNbPairs);
322     assert(mNbPairs == static_cast<uint64>(mMapPairIdToPairIndex.size()));
323 
324     updateOverlappingPairIsActive(pairId);
325 
326     return pairId;
327 }
328 
329 // Move a pair from a source to a destination index in the pairs array
330 // The destination location must contain a constructed object
movePairToIndex(uint64 srcIndex,uint64 destIndex)331 void OverlappingPairs::movePairToIndex(uint64 srcIndex, uint64 destIndex) {
332 
333     const uint64 pairId = mPairIds[srcIndex];
334 
335     // Copy the data of the source pair to the destination location
336     mPairIds[destIndex] = mPairIds[srcIndex];
337     mPairBroadPhaseId1[destIndex] = mPairBroadPhaseId1[srcIndex];
338     mPairBroadPhaseId2[destIndex] = mPairBroadPhaseId2[srcIndex];
339     new (mColliders1 + destIndex) Entity(mColliders1[srcIndex]);
340     new (mColliders2 + destIndex) Entity(mColliders2[srcIndex]);
341     new (mLastFrameCollisionInfos + destIndex) Map<uint64, LastFrameCollisionInfo*>(mLastFrameCollisionInfos[srcIndex]);
342     mNeedToTestOverlap[destIndex] = mNeedToTestOverlap[srcIndex];
343     mIsActive[destIndex] = mIsActive[srcIndex];
344     new (mNarrowPhaseAlgorithmType + destIndex) NarrowPhaseAlgorithmType(mNarrowPhaseAlgorithmType[srcIndex]);
345     mIsShape1Convex[destIndex] = mIsShape1Convex[srcIndex];
346     mCollidingInPreviousFrame[destIndex] = mCollidingInPreviousFrame[srcIndex];
347     mCollidingInCurrentFrame[destIndex] = mCollidingInCurrentFrame[srcIndex];
348 
349     // Destroy the source pair
350     destroyPair(srcIndex);
351 
352     assert(!mMapPairIdToPairIndex.containsKey(pairId));
353 
354     // Update the pairId to pair index mapping
355     mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, destIndex));
356 
357     assert(mMapPairIdToPairIndex[mPairIds[destIndex]] == destIndex);
358 }
359 
360 // Swap two pairs in the array
swapPairs(uint64 index1,uint64 index2)361 void OverlappingPairs::swapPairs(uint64 index1, uint64 index2) {
362 
363     // Copy pair 1 data
364     uint64 pairId = mPairIds[index1];
365     int32 pairBroadPhaseId1 = mPairBroadPhaseId1[index1];
366     int32 pairBroadPhaseId2 = mPairBroadPhaseId2[index1];
367     Entity collider1 = mColliders1[index1];
368     Entity collider2 = mColliders2[index1];
369     Map<uint64, LastFrameCollisionInfo*> lastFrameCollisionInfo(mLastFrameCollisionInfos[index1]);
370     bool needTestOverlap = mNeedToTestOverlap[index1];
371     bool isActive = mIsActive[index1];
372     NarrowPhaseAlgorithmType narrowPhaseAlgorithmType = mNarrowPhaseAlgorithmType[index1];
373     bool isShape1Convex = mIsShape1Convex[index1];
374     bool wereCollidingInPreviousFrame = mCollidingInPreviousFrame[index1];
375     bool areCollidingInCurrentFrame = mCollidingInCurrentFrame[index1];
376 
377     // Destroy pair 1
378     destroyPair(index1);
379 
380     movePairToIndex(index2, index1);
381 
382     // Reconstruct pair 1 at pair 2 location
383     mPairIds[index2] = pairId;
384     mPairBroadPhaseId1[index2] = pairBroadPhaseId1;
385     mPairBroadPhaseId2[index2] = pairBroadPhaseId2;
386     new (mColliders1 + index2) Entity(collider1);
387     new (mColliders2 + index2) Entity(collider2);
388     new (mLastFrameCollisionInfos + index2) Map<uint64, LastFrameCollisionInfo*>(lastFrameCollisionInfo);
389     mNeedToTestOverlap[index2] = needTestOverlap;
390     mIsActive[index2] = isActive;
391     new (mNarrowPhaseAlgorithmType + index2) NarrowPhaseAlgorithmType(narrowPhaseAlgorithmType);
392     mIsShape1Convex[index2] = isShape1Convex;
393     mCollidingInPreviousFrame[index2] = wereCollidingInPreviousFrame;
394     mCollidingInCurrentFrame[index2] = areCollidingInCurrentFrame;
395 
396     // Update the pairID to pair index mapping
397     mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, index2));
398 
399     assert(mMapPairIdToPairIndex[mPairIds[index1]] == index1);
400     assert(mMapPairIdToPairIndex[mPairIds[index2]] == index2);
401     assert(mNbPairs == static_cast<uint64>(mMapPairIdToPairIndex.size()));
402 }
403 
404 // Destroy a pair at a given index
destroyPair(uint64 index)405 void OverlappingPairs::destroyPair(uint64 index) {
406 
407     assert(index < mNbPairs);
408 
409     assert(mMapPairIdToPairIndex[mPairIds[index]] == index);
410 
411     mMapPairIdToPairIndex.remove(mPairIds[index]);
412 
413     mColliders1[index].~Entity();
414     mColliders2[index].~Entity();
415     mLastFrameCollisionInfos[index].~Map<uint64, LastFrameCollisionInfo*>();
416     mNarrowPhaseAlgorithmType[index].~NarrowPhaseAlgorithmType();
417 }
418 
419 // Update whether a given overlapping pair is active or not
updateOverlappingPairIsActive(uint64 pairId)420 void OverlappingPairs::updateOverlappingPairIsActive(uint64 pairId) {
421 
422     assert(mMapPairIdToPairIndex.containsKey(pairId));
423 
424     const uint64 pairIndex = mMapPairIdToPairIndex[pairId];
425 
426     const Entity collider1 = mColliders1[pairIndex];
427     const Entity collider2 = mColliders2[pairIndex];
428 
429     const Entity body1 = mColliderComponents.getBody(collider1);
430     const Entity body2 = mColliderComponents.getBody(collider2);
431 
432     const bool isBody1Enabled = !mCollisionBodyComponents.getIsEntityDisabled(body1);
433     const bool isBody2Enabled = !mCollisionBodyComponents.getIsEntityDisabled(body2);
434     const bool isBody1Static = mRigidBodyComponents.hasComponent(body1) &&
435                                mRigidBodyComponents.getBodyType(body1) == BodyType::STATIC;
436     const bool isBody2Static = mRigidBodyComponents.hasComponent(body2) &&
437                                mRigidBodyComponents.getBodyType(body2) == BodyType::STATIC;
438 
439     const bool isBody1Active = isBody1Enabled && !isBody1Static;
440     const bool isBody2Active = isBody2Enabled && !isBody2Static;
441 
442     // Check if the bodies are in the set of bodies that cannot collide between each other
443     bodypair bodiesIndex = OverlappingPairs::computeBodiesIndexPair(body1, body2);
444     bool bodiesCanCollide = !mNoCollisionPairs.contains(bodiesIndex);
445 
446     mIsActive[pairIndex] = bodiesCanCollide && (isBody1Active || isBody2Active);
447 }
448 
449 // Add a new last frame collision info if it does not exist for the given shapes already
addLastFrameInfoIfNecessary(uint64 pairIndex,uint32 shapeId1,uint32 shapeId2)450 LastFrameCollisionInfo* OverlappingPairs::addLastFrameInfoIfNecessary(uint64 pairIndex, uint32 shapeId1, uint32 shapeId2) {
451 
452     RP3D_PROFILE("OverlappingPairs::addLastFrameInfoIfNecessary()", mProfiler);
453 
454     assert(pairIndex < mNbPairs);
455 
456     uint32 maxShapeId = shapeId1;
457     uint32 minShapeId = shapeId2;
458     if (shapeId1 < shapeId2) {
459        maxShapeId = shapeId2;
460        minShapeId = shapeId1;
461     }
462 
463     // Try to get the corresponding last frame collision info
464     const uint64 shapesId = pairNumbers(maxShapeId, minShapeId);
465 
466     // If there is no collision info for those two shapes already
467     auto it = mLastFrameCollisionInfos[pairIndex].find(shapesId);
468     if (it == mLastFrameCollisionInfos[pairIndex].end()) {
469 
470         // Create a new collision info
471         LastFrameCollisionInfo* collisionInfo = new (mPersistentAllocator.allocate(sizeof(LastFrameCollisionInfo)))
472                                                 LastFrameCollisionInfo();
473 
474         // Add it into the map of collision infos
475         mLastFrameCollisionInfos[pairIndex].add(Pair<uint64, LastFrameCollisionInfo*>(shapesId, collisionInfo));
476 
477         return collisionInfo;
478     }
479     else {
480 
481        // The existing collision info is not obsolete
482        it->second->isObsolete = false;
483 
484        return it->second;
485     }
486 }
487 
488 // Delete all the obsolete last frame collision info
clearObsoleteLastFrameCollisionInfos()489 void OverlappingPairs::clearObsoleteLastFrameCollisionInfos() {
490 
491     RP3D_PROFILE("OverlappingPairs::clearObsoleteLastFrameCollisionInfos()", mProfiler);
492 
493     // For each overlapping pair
494     for (uint64 i=0; i < mNbPairs; i++) {
495 
496         // For each collision info
497         for (auto it = mLastFrameCollisionInfos[i].begin(); it != mLastFrameCollisionInfos[i].end(); ) {
498 
499             // If the collision info is obsolete
500             if (it->second->isObsolete) {
501 
502                 // Delete it
503                 it->second->~LastFrameCollisionInfo();
504                 mPersistentAllocator.release(it->second, sizeof(LastFrameCollisionInfo));
505 
506                 it = mLastFrameCollisionInfos[i].remove(it);
507             }
508             else {  // If the collision info is not obsolete
509 
510                 // Do not delete it but mark it as obsolete
511                 it->second->isObsolete = true;
512 
513                 ++it;
514             }
515         }
516     }
517 }
518 
519 // Set the collidingInPreviousFrame value with the collidinginCurrentFrame value for each pair
updateCollidingInPreviousFrame()520 void OverlappingPairs::updateCollidingInPreviousFrame() {
521 
522     // For each overlapping pair
523     for (uint64 i=0; i < mNbPairs; i++) {
524 
525         mCollidingInPreviousFrame[i] = mCollidingInCurrentFrame[i];
526     }
527 }
528