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