Some optimizations and fix issues in collision detection

This commit is contained in:
Daniel Chappuis 2019-11-25 21:22:25 +01:00
parent acb5e0e51e
commit b94fbf7874
4 changed files with 41 additions and 39 deletions

View File

@ -196,6 +196,7 @@ class ProxyShapeComponents : public Components {
friend class BroadPhaseSystem;
friend class CollisionDetectionSystem;
friend class DynamicsSystem;
friend class OverlappingPairs;
};
// Return the body entity of a given proxy-shape

View File

@ -353,27 +353,6 @@ class List {
return Iterator(mBuffer, index, mSize);
}
/// Remove an element from the list at a given index (the deleted item will be replaced by the last one of the list)
void removeAtAndReplaceWithLast(uint index) {
assert(index >= 0 && index < mSize);
// Call the destructor on the item to remove
(static_cast<T*>(mBuffer)[index]).~T();
// If the item to remove is not the last one
if (index < mSize - 1) {
// Copy the last item of the array to the location of the deleted item
new (static_cast<char*>(mBuffer) + index * sizeof(T)) T(static_cast<T*>(mBuffer)[mSize - 1]);
// Call the destructor of the last item of the array
(static_cast<T*>(mBuffer)[mSize - 1]).~T();
}
mSize--;
}
/// Append another list at the end of the current one
void addRange(const List<T>& list) {

View File

@ -251,8 +251,14 @@ uint64 OverlappingPairs::addPair(ProxyShape* shape1, ProxyShape* shape2) {
RP3D_PROFILE("OverlappingPairs::addPair()", mProfiler);
const CollisionShape* collisionShape1 = mProxyShapeComponents.getCollisionShape(shape1->getEntity());
const CollisionShape* collisionShape2 = mProxyShapeComponents.getCollisionShape(shape2->getEntity());
const Entity proxyShape1 = shape1->getEntity();
const Entity proxyShape2 = shape2->getEntity();
const uint proxyShape1Index = mProxyShapeComponents.getEntityIndex(proxyShape1);
const uint proxyShape2Index = mProxyShapeComponents.getEntityIndex(proxyShape2);
const CollisionShape* collisionShape1 = mProxyShapeComponents.mCollisionShapes[proxyShape1Index];
const CollisionShape* collisionShape2 = mProxyShapeComponents.mCollisionShapes[proxyShape2Index];
const bool isShape1Convex = collisionShape1->isConvex();
const bool isShape2Convex = collisionShape2->isConvex();
@ -297,10 +303,10 @@ uint64 OverlappingPairs::addPair(ProxyShape* shape1, ProxyShape* shape2) {
mMapPairIdToPairIndex.add(Pair<uint64, uint64>(pairId, index));
// Add the involved overlapping pair to the two proxy-shapes
assert(mProxyShapeComponents.getOverlappingPairs(shape1->getEntity()).find(pairId) == mProxyShapeComponents.getOverlappingPairs(shape1->getEntity()).end());
assert(mProxyShapeComponents.getOverlappingPairs(shape2->getEntity()).find(pairId) == mProxyShapeComponents.getOverlappingPairs(shape2->getEntity()).end());
mProxyShapeComponents.getOverlappingPairs(shape1->getEntity()).add(pairId);
mProxyShapeComponents.getOverlappingPairs(shape2->getEntity()).add(pairId);
assert(mProxyShapeComponents.mOverlappingPairs[proxyShape1Index].find(pairId) == mProxyShapeComponents.mOverlappingPairs[proxyShape1Index].end());
assert(mProxyShapeComponents.mOverlappingPairs[proxyShape2Index].find(pairId) == mProxyShapeComponents.mOverlappingPairs[proxyShape2Index].end());
mProxyShapeComponents.mOverlappingPairs[proxyShape1Index].add(pairId);
mProxyShapeComponents.mOverlappingPairs[proxyShape2Index].add(pairId);
mNbPairs++;

View File

@ -158,9 +158,12 @@ void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int32, int
const Entity proxyShape1Entity = mMapBroadPhaseIdToProxyShapeEntity[nodePair.first];
const Entity proxyShape2Entity = mMapBroadPhaseIdToProxyShapeEntity[nodePair.second];
const uint proxyShape1Index = mProxyShapesComponents.getEntityIndex(proxyShape1Entity);
const uint proxyShape2Index = mProxyShapesComponents.getEntityIndex(proxyShape2Entity);
// Get the two bodies
const Entity body1Entity = mProxyShapesComponents.getBody(proxyShape1Entity);
const Entity body2Entity = mProxyShapesComponents.getBody(proxyShape2Entity);
const Entity body1Entity = mProxyShapesComponents.mBodiesEntities[proxyShape1Index];
const Entity body2Entity = mProxyShapesComponents.mBodiesEntities[proxyShape2Index];
// If the two proxy collision shapes are from the same body, skip it
if (body1Entity != body2Entity) {
@ -172,18 +175,18 @@ void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int32, int
auto it = mOverlappingPairs.mMapPairIdToPairIndex.find(pairId);
if (it == mOverlappingPairs.mMapPairIdToPairIndex.end()) {
unsigned short shape1CollideWithMaskBits = mProxyShapesComponents.getCollideWithMaskBits(proxyShape1Entity);
unsigned short shape2CollideWithMaskBits = mProxyShapesComponents.getCollideWithMaskBits(proxyShape2Entity);
const unsigned short shape1CollideWithMaskBits = mProxyShapesComponents.mCollideWithMaskBits[proxyShape1Index];
const unsigned short shape2CollideWithMaskBits = mProxyShapesComponents.mCollideWithMaskBits[proxyShape2Index];
unsigned short shape1CollisionCategoryBits = mProxyShapesComponents.getCollisionCategoryBits(proxyShape1Entity);
unsigned short shape2CollisionCategoryBits = mProxyShapesComponents.getCollisionCategoryBits(proxyShape2Entity);
const unsigned short shape1CollisionCategoryBits = mProxyShapesComponents.mCollisionCategoryBits[proxyShape1Index];
const unsigned short shape2CollisionCategoryBits = mProxyShapesComponents.mCollisionCategoryBits[proxyShape2Index];
// Check if the collision filtering allows collision between the two shapes
if ((shape1CollideWithMaskBits & shape2CollisionCategoryBits) != 0 &&
(shape1CollisionCategoryBits & shape2CollideWithMaskBits) != 0) {
ProxyShape* shape1 = mProxyShapesComponents.getProxyShape(proxyShape1Entity);
ProxyShape* shape2 = mProxyShapesComponents.getProxyShape(proxyShape2Entity);
ProxyShape* shape1 = mProxyShapesComponents.mProxyShapes[proxyShape1Index];
ProxyShape* shape2 = mProxyShapesComponents.mProxyShapes[proxyShape2Index];
// Check that at least one collision shape is convex
if (shape1->getCollisionShape()->isConvex() || shape2->getCollisionShape()->isConvex()) {
@ -1459,7 +1462,12 @@ void CollisionDetectionSystem::filterOverlappingPairs(Entity bodyEntity, List<ui
if (mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes1[i]) == bodyEntity ||
mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes2[i]) == bodyEntity) {
convexPairs.add(mOverlappingPairs.mPairIds[i]);
if (i < mOverlappingPairs.getNbConvexVsConvexPairs()) {
convexPairs.add(mOverlappingPairs.mPairIds[i]);
}
else {
concavePairs.add(mOverlappingPairs.mPairIds[i]);
}
}
}
}
@ -1472,10 +1480,18 @@ void CollisionDetectionSystem::filterOverlappingPairs(Entity body1Entity, Entity
// For each possible collision pair of bodies
for (uint i=0; i < mOverlappingPairs.getNbPairs(); i++) {
if ((mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes1[i]) == body1Entity && mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes1[i]) == body2Entity) ||
(mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes2[i]) == body2Entity && mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes2[i]) == body1Entity)) {
const Entity proxyShape1Body = mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes1[i]);
const Entity proxyShape2Body = mProxyShapesComponents.getBody(mOverlappingPairs.mProxyShapes2[i]);
convexPairs.add(mOverlappingPairs.mPairIds[i]);
if ((proxyShape1Body == body1Entity && proxyShape2Body == body2Entity) ||
(proxyShape1Body == body2Entity && proxyShape2Body == body1Entity)) {
if (i < mOverlappingPairs.getNbConvexVsConvexPairs()) {
convexPairs.add(mOverlappingPairs.mPairIds[i]);
}
else {
concavePairs.add(mOverlappingPairs.mPairIds[i]);
}
}
}
}