Optimizations
This commit is contained in:
parent
130eb00136
commit
f991717cc1
|
@ -37,13 +37,15 @@ OverlappingPair::OverlappingPair(ProxyShape* shape1, ProxyShape* shape2,
|
|||
const WorldSettings& worldSettings)
|
||||
: mPairID(computeID(shape1->getBroadPhaseId(), shape2->getBroadPhaseId())), mProxyShape1(shape1->getEntity()), mProxyShape2(shape2->getEntity()),
|
||||
mPersistentAllocator(persistentMemoryAllocator), mTempMemoryAllocator(temporaryMemoryAllocator),
|
||||
mLastFrameCollisionInfos(mPersistentAllocator), mWorldSettings(worldSettings) {
|
||||
mLastFrameCollisionInfos(mPersistentAllocator), mWorldSettings(worldSettings), mNeedToTestOverlap(false) {
|
||||
|
||||
}
|
||||
|
||||
// Destructor
|
||||
OverlappingPair::~OverlappingPair() {
|
||||
|
||||
RP3D_PROFILE("OverlappingPair::~OverlappingPair()", mProfiler);
|
||||
|
||||
// Remove all the remaining last frame collision info
|
||||
for (auto it = mLastFrameCollisionInfos.begin(); it != mLastFrameCollisionInfos.end(); ++it) {
|
||||
|
||||
|
@ -58,6 +60,8 @@ OverlappingPair::~OverlappingPair() {
|
|||
// Add a new last frame collision info if it does not exist for the given shapes already
|
||||
LastFrameCollisionInfo* OverlappingPair::addLastFrameInfoIfNecessary(uint shapeId1, uint shapeId2) {
|
||||
|
||||
RP3D_PROFILE("OverlappingPair::addLastFrameInfoIfNecessary()", mProfiler);
|
||||
|
||||
// Try to get the corresponding last frame collision info
|
||||
const ShapeIdPair shapeIdPair(shapeId1, shapeId2);
|
||||
auto it = mLastFrameCollisionInfos.find(shapeIdPair);
|
||||
|
@ -83,10 +87,11 @@ LastFrameCollisionInfo* OverlappingPair::addLastFrameInfoIfNecessary(uint shapeI
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Delete all the obsolete last frame collision info
|
||||
void OverlappingPair::clearObsoleteLastFrameCollisionInfos() {
|
||||
|
||||
RP3D_PROFILE("OverlappingPair::clearObsoleteLastFrameCollisionInfos()", mProfiler);
|
||||
|
||||
// For each collision info
|
||||
for (auto it = mLastFrameCollisionInfos.begin(); it != mLastFrameCollisionInfos.end(); ) {
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "containers/Map.h"
|
||||
#include "containers/Pair.h"
|
||||
#include "containers/containers_common.h"
|
||||
#include "utils/Profiler.h"
|
||||
#include <cstddef>
|
||||
|
||||
/// ReactPhysics3D namespace
|
||||
|
@ -131,6 +132,16 @@ class OverlappingPair {
|
|||
/// World settings
|
||||
const WorldSettings& mWorldSettings;
|
||||
|
||||
/// True if we need to test if the overlapping pair of shapes still overlap
|
||||
bool mNeedToTestOverlap;
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
|
||||
/// Pointer to the profiler
|
||||
Profiler* mProfiler;
|
||||
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -163,6 +174,12 @@ class OverlappingPair {
|
|||
/// Return a reference to the temporary memory allocator
|
||||
MemoryAllocator& getTemporaryAllocator();
|
||||
|
||||
/// Return true if we need to test if the overlapping pair of shapes still overlap
|
||||
bool needToTestOverlap() const;
|
||||
|
||||
/// Set to true if we need to test if the overlapping pair of shapes still overlap
|
||||
void setNeedToTestOverlap(bool needToTestOverlap);
|
||||
|
||||
/// Add a new last frame collision info if it does not exist for the given shapes already
|
||||
LastFrameCollisionInfo* addLastFrameInfoIfNecessary(uint shapeId1, uint shapeId2);
|
||||
|
||||
|
@ -178,6 +195,13 @@ class OverlappingPair {
|
|||
/// Return the pair of bodies index of the pair
|
||||
static bodypair computeBodiesIndexPair(Entity body1Entity, Entity body2Entity);
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
|
||||
/// Set the profiler
|
||||
void setProfiler(Profiler* profiler);
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
friend class DynamicsWorld;
|
||||
|
@ -236,11 +260,29 @@ inline MemoryAllocator& OverlappingPair::getTemporaryAllocator() {
|
|||
return mTempMemoryAllocator;
|
||||
}
|
||||
|
||||
// Return true if we need to test if the overlapping pair of shapes still overlap
|
||||
inline bool OverlappingPair::needToTestOverlap() const {
|
||||
return mNeedToTestOverlap;
|
||||
}
|
||||
|
||||
// Set to true if we need to test if the overlapping pair of shapes still overlap
|
||||
inline void OverlappingPair::setNeedToTestOverlap(bool needToTestOverlap) {
|
||||
mNeedToTestOverlap = needToTestOverlap;
|
||||
}
|
||||
|
||||
// Return the last frame collision info for a given pair of shape ids
|
||||
inline LastFrameCollisionInfo* OverlappingPair::getLastFrameCollisionInfo(uint shapeId1, uint shapeId2) const {
|
||||
return mLastFrameCollisionInfos[ShapeIdPair(shapeId1, shapeId2)];
|
||||
}
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
|
||||
// Set the profiler
|
||||
inline void OverlappingPair::setProfiler(Profiler* profiler) {
|
||||
mProfiler = profiler;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -53,10 +53,12 @@ BroadPhaseSystem::BroadPhaseSystem(CollisionDetectionSystem& collisionDetection,
|
|||
// Return true if the two broad-phase collision shapes are overlapping
|
||||
bool BroadPhaseSystem::testOverlappingShapes(Entity proxyShape1Entity, Entity proxyShape2Entity) const {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::testOverlappingShapes()", mProfiler);
|
||||
|
||||
const int32 shape1BroadPhaseId = mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity);
|
||||
const int32 shape2BroadPhaseId = mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity);
|
||||
|
||||
if (shape1BroadPhaseId == -1 || shape2BroadPhaseId == -1) return false;
|
||||
assert(shape1BroadPhaseId != -1 && shape2BroadPhaseId != -1);
|
||||
|
||||
// Get the two AABBs of the collision shapes
|
||||
const AABB& aabb1 = mDynamicAABBTree.getFatAABB(shape1BroadPhaseId);
|
||||
|
@ -125,6 +127,8 @@ void BroadPhaseSystem::updateProxyShape(Entity proxyShapeEntity, decimal timeSte
|
|||
// Update the broad-phase state of all the enabled proxy-shapes
|
||||
void BroadPhaseSystem::updateProxyShapes(decimal timeStep) {
|
||||
|
||||
RP3D_PROFILE("BroadPhaseSystem::updateProxyShapes()", mProfiler);
|
||||
|
||||
// Update all the enabled proxy-shape components
|
||||
updateProxyShapesComponents(0, mProxyShapesComponents.getNbEnabledComponents(), timeStep);
|
||||
}
|
||||
|
@ -176,7 +180,6 @@ void BroadPhaseSystem::updateProxyShapesComponents(uint32 startIndex, uint32 nbI
|
|||
// Get the linear velocity from the dynamics component
|
||||
const Vector3& linearVelocity = mRigidBodyComponents.getLinearVelocity(bodyEntity);
|
||||
|
||||
// TODO : Use body linear velocity and compute displacement
|
||||
displacement = timeStep * linearVelocity;
|
||||
}
|
||||
|
||||
|
@ -193,6 +196,8 @@ void BroadPhaseSystem::updateProxyShapesComponents(uint32 startIndex, uint32 nbI
|
|||
// Compute all the overlapping pairs of collision shapes
|
||||
void BroadPhaseSystem::computeOverlappingPairs(MemoryManager& memoryManager, List<Pair<int, int>>& overlappingNodes) {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::computeOverlappingPairs()", mProfiler);
|
||||
|
||||
// Get the list of the proxy-shapes that have moved or have been created in the last frame
|
||||
List<int> shapesToTest = mMovedShapes.toList(memoryManager.getPoolAllocator());
|
||||
|
||||
|
|
|
@ -99,6 +99,8 @@ void CollisionDetectionSystem::computeBroadPhase() {
|
|||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::computeBroadPhase()", mProfiler);
|
||||
|
||||
resetNeedToTestOverlap();
|
||||
|
||||
// Ask the broad-phase to compute all the shapes overlapping the shapes that
|
||||
// have moved or have been added in the last frame. This call can only add new
|
||||
// overlapping pairs in the collision detection.
|
||||
|
@ -112,16 +114,31 @@ void CollisionDetectionSystem::computeBroadPhase() {
|
|||
removeNonOverlappingPairs();
|
||||
}
|
||||
|
||||
// Set the needToTestOverlap value of each overlapping pair to true
|
||||
void CollisionDetectionSystem::resetNeedToTestOverlap() {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::resetNeedToTestOverlap()", mProfiler);
|
||||
|
||||
// For each possible collision pair of bodies
|
||||
for (auto it = mOverlappingPairs.begin(); it != mOverlappingPairs.end(); ++it) {
|
||||
it->second->setNeedToTestOverlap(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove pairs that are not overlapping anymore
|
||||
void CollisionDetectionSystem::removeNonOverlappingPairs() {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::removeNonOverlappingPairs()", mProfiler);
|
||||
|
||||
// For each possible collision pair of bodies
|
||||
for (auto it = mOverlappingPairs.begin(); it != mOverlappingPairs.end(); ) {
|
||||
|
||||
OverlappingPair* pair = it->second;
|
||||
|
||||
// Check if the two shapes are still overlapping. Otherwise, we destroy the overlapping pair
|
||||
if (!mBroadPhaseSystem.testOverlappingShapes(pair->getProxyShape1(), pair->getProxyShape2())) {
|
||||
// Check if we need to test overlap. If so, test if the two shapes are still overlapping.
|
||||
// Otherwise, we destroy the overlapping pair
|
||||
if (pair->needToTestOverlap() &&
|
||||
!mBroadPhaseSystem.testOverlappingShapes(pair->getProxyShape1(), pair->getProxyShape2())) {
|
||||
|
||||
// Destroy the overlapping pair
|
||||
pair->~OverlappingPair();
|
||||
|
@ -139,6 +156,8 @@ void CollisionDetectionSystem::removeNonOverlappingPairs() {
|
|||
// Take a list of overlapping nodes in the broad-phase and create new overlapping pairs if necessary
|
||||
void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int, int>>& overlappingNodes) {
|
||||
|
||||
RP3D_PROFILE("CollisionDetectionSystem::updateOverlappingPairs()", mProfiler);
|
||||
|
||||
// For each overlapping pair of nodes
|
||||
for (uint i=0; i < overlappingNodes.size(); i++) {
|
||||
|
||||
|
@ -165,7 +184,8 @@ void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int, int>>
|
|||
Pair<uint, uint> pairID = OverlappingPair::computeID(nodePair.first, nodePair.second);
|
||||
|
||||
// Check if the overlapping pair already exists
|
||||
if (!mOverlappingPairs.containsKey(pairID)) {
|
||||
auto itPair = mOverlappingPairs.find(pairID);
|
||||
if (itPair == mOverlappingPairs.end()) {
|
||||
|
||||
unsigned short shape1CollideWithMaskBits = mProxyShapesComponents.getCollideWithMaskBits(proxyShape1Entity);
|
||||
unsigned short shape2CollideWithMaskBits = mProxyShapesComponents.getCollideWithMaskBits(proxyShape2Entity);
|
||||
|
@ -189,8 +209,18 @@ void CollisionDetectionSystem::updateOverlappingPairs(const List<Pair<int, int>>
|
|||
|
||||
// Add the new overlapping pair
|
||||
mOverlappingPairs.add(Pair<Pair<uint, uint>, OverlappingPair*>(pairID, newPair));
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
newPair->setProfiler(mProfiler);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// We do not need to test the pair for overlap because it has just been reported that they still overlap
|
||||
itPair->second->setNeedToTestOverlap(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -219,58 +249,53 @@ void CollisionDetectionSystem::computeMiddlePhase(OverlappingPairMap& overlappin
|
|||
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity) != -1);
|
||||
assert(mProxyShapesComponents.getBroadPhaseId(proxyShape1Entity) != mProxyShapesComponents.getBroadPhaseId(proxyShape2Entity));
|
||||
|
||||
// Check if the collision filtering allows collision between the two shapes
|
||||
if ((mProxyShapesComponents.getCollideWithMaskBits(proxyShape1Entity) & mProxyShapesComponents.getCollisionCategoryBits(proxyShape2Entity)) != 0 &&
|
||||
(mProxyShapesComponents.getCollisionCategoryBits(proxyShape1Entity) & mProxyShapesComponents.getCollideWithMaskBits(proxyShape2Entity)) != 0) {
|
||||
const Entity body1Entity = mProxyShapesComponents.getBody(proxyShape1Entity);
|
||||
const Entity body2Entity = mProxyShapesComponents.getBody(proxyShape2Entity);
|
||||
|
||||
const Entity body1Entity = mProxyShapesComponents.getBody(proxyShape1Entity);
|
||||
const Entity body2Entity = mProxyShapesComponents.getBody(proxyShape2Entity);
|
||||
const bool isStaticRigidBody1 = mWorld->mRigidBodyComponents.hasComponent(body1Entity) &&
|
||||
mWorld->mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC;
|
||||
const bool isStaticRigidBody2 = mWorld->mRigidBodyComponents.hasComponent(body2Entity) &&
|
||||
mWorld->mRigidBodyComponents.getBodyType(body2Entity) == BodyType::STATIC;
|
||||
|
||||
const bool isStaticRigidBody1 = mWorld->mRigidBodyComponents.hasComponent(body1Entity) &&
|
||||
mWorld->mRigidBodyComponents.getBodyType(body1Entity) == BodyType::STATIC;
|
||||
const bool isStaticRigidBody2 = mWorld->mRigidBodyComponents.hasComponent(body2Entity) &&
|
||||
mWorld->mRigidBodyComponents.getBodyType(body2Entity) == BodyType::STATIC;
|
||||
// Check that at least one body is enabled (active and awake) and not static
|
||||
bool isBody1Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1;
|
||||
bool isBody2Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2;
|
||||
if (!isBody1Active && !isBody2Active) continue;
|
||||
|
||||
// Check that at least one body is enabled (active and awake) and not static
|
||||
bool isBody1Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body1Entity) && !isStaticRigidBody1;
|
||||
bool isBody2Active = !mWorld->mCollisionBodyComponents.getIsEntityDisabled(body2Entity) && !isStaticRigidBody2;
|
||||
if (!isBody1Active && !isBody2Active) continue;
|
||||
// Check if the bodies are in the set of bodies that cannot collide between each other
|
||||
bodypair bodiesIndex = OverlappingPair::computeBodiesIndexPair(body1Entity, body2Entity);
|
||||
if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue;
|
||||
|
||||
// Check if the bodies are in the set of bodies that cannot collide between each other
|
||||
bodypair bodiesIndex = OverlappingPair::computeBodiesIndexPair(body1Entity, body2Entity);
|
||||
if (mNoCollisionPairs.contains(bodiesIndex) > 0) continue;
|
||||
CollisionShape* collisionShape1 = mProxyShapesComponents.getCollisionShape(proxyShape1Entity);
|
||||
CollisionShape* collisionShape2 = mProxyShapesComponents.getCollisionShape(proxyShape2Entity);
|
||||
|
||||
CollisionShape* collisionShape1 = mProxyShapesComponents.getCollisionShape(proxyShape1Entity);
|
||||
CollisionShape* collisionShape2 = mProxyShapesComponents.getCollisionShape(proxyShape2Entity);
|
||||
const bool isShape1Convex = collisionShape1->isConvex();
|
||||
const bool isShape2Convex = collisionShape2->isConvex();
|
||||
|
||||
const bool isShape1Convex = collisionShape1->isConvex();
|
||||
const bool isShape2Convex = collisionShape2->isConvex();
|
||||
// If both shapes are convex
|
||||
if (isShape1Convex && isShape2Convex) {
|
||||
|
||||
// If both shapes are convex
|
||||
if (isShape1Convex && isShape2Convex) {
|
||||
// Select the narrow phase algorithm to use according to the two collision shapes
|
||||
NarrowPhaseAlgorithmType algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(collisionShape1->getType(),
|
||||
collisionShape2->getType());
|
||||
|
||||
// Select the narrow phase algorithm to use according to the two collision shapes
|
||||
NarrowPhaseAlgorithmType algorithmType = mCollisionDispatch.selectNarrowPhaseAlgorithm(collisionShape1->getType(),
|
||||
collisionShape2->getType());
|
||||
// No middle-phase is necessary, simply create a narrow phase info
|
||||
// for the narrow-phase collision detection
|
||||
narrowPhaseInput.addNarrowPhaseTest(pair, collisionShape1, collisionShape2,
|
||||
mProxyShapesComponents.getLocalToWorldTransform(proxyShape1Entity),
|
||||
mProxyShapesComponents.getLocalToWorldTransform(proxyShape2Entity),
|
||||
algorithmType, mMemoryManager.getSingleFrameAllocator());
|
||||
|
||||
// No middle-phase is necessary, simply create a narrow phase info
|
||||
// for the narrow-phase collision detection
|
||||
narrowPhaseInput.addNarrowPhaseTest(pair, collisionShape1, collisionShape2,
|
||||
mProxyShapesComponents.getLocalToWorldTransform(proxyShape1Entity),
|
||||
mProxyShapesComponents.getLocalToWorldTransform(proxyShape2Entity),
|
||||
algorithmType, mMemoryManager.getSingleFrameAllocator());
|
||||
}
|
||||
// Concave vs Convex algorithm
|
||||
else if ((!isShape1Convex && isShape2Convex) || (!isShape2Convex && isShape1Convex)) {
|
||||
|
||||
}
|
||||
// Concave vs Convex algorithm
|
||||
else if ((!isShape1Convex && isShape2Convex) || (!isShape2Convex && isShape1Convex)) {
|
||||
|
||||
computeConvexVsConcaveMiddlePhase(pair, mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput);
|
||||
}
|
||||
// Concave vs Concave shape
|
||||
else {
|
||||
// Not handled
|
||||
continue;
|
||||
}
|
||||
computeConvexVsConcaveMiddlePhase(pair, mMemoryManager.getSingleFrameAllocator(), narrowPhaseInput);
|
||||
}
|
||||
// Concave vs Concave shape
|
||||
else {
|
||||
// Not handled
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -195,6 +195,9 @@ class CollisionDetectionSystem {
|
|||
/// Take a list of overlapping nodes in the broad-phase and create new overlapping pairs if necessary
|
||||
void updateOverlappingPairs(const List<Pair<int, int>>& overlappingNodes);
|
||||
|
||||
/// Set the needToTestOverlap value of each overlapping pair to true
|
||||
void resetNeedToTestOverlap();
|
||||
|
||||
/// Remove pairs that are not overlapping anymore
|
||||
void removeNonOverlappingPairs();
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user