diff --git a/CMakeLists.txt b/CMakeLists.txt index 7850396b..b52047ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,7 +142,7 @@ SET (REACTPHYSICS3D_HEADERS "src/components/Components.h" "src/components/BodyComponents.h" "src/components/TransformComponents.h" - "src/components/ProxyShapesComponents.h" + "src/components/ProxyShapeComponents.h" "src/collision/CollisionCallback.h" "src/collision/OverlapCallback.h" "src/mathematics/mathematics.h" @@ -234,7 +234,7 @@ SET (REACTPHYSICS3D_SOURCES "src/components/Components.cpp" "src/components/BodyComponents.cpp" "src/components/TransformComponents.cpp" - "src/components/ProxyShapesComponents.cpp" + "src/components/ProxyShapeComponents.cpp" "src/collision/CollisionCallback.cpp" "src/mathematics/mathematics_functions.cpp" "src/mathematics/Matrix2x2.cpp" diff --git a/src/body/CollisionBody.cpp b/src/body/CollisionBody.cpp index 84397665..0af2cd25 100644 --- a/src/body/CollisionBody.cpp +++ b/src/body/CollisionBody.cpp @@ -84,7 +84,7 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape, Vector3 localBoundsMax; // TODO : Maybe this method can directly returns an AABB collisionShape->getLocalBounds(localBoundsMin, localBoundsMax); - ProxyShapesComponents::ProxyShapeComponent proxyShapeComponent(mEntity, proxyShape, -1, + ProxyShapeComponents::ProxyShapeComponent proxyShapeComponent(mEntity, proxyShape, -1, AABB(localBoundsMin, localBoundsMax), transform, collisionShape, decimal(1), 0x0001, 0xFFFF); mWorld.mProxyShapesComponents.addComponent(proxyShapeEntity, mIsSleeping, proxyShapeComponent); @@ -234,26 +234,8 @@ void CollisionBody::updateBroadPhaseState() const { const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); for (uint i=0; i < proxyShapesEntities.size(); i++) { - ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]); - // Update the proxy - updateProxyShapeInBroadPhase(proxyShape); - } -} - -// Update the broad-phase state of a proxy collision shape of the body -void CollisionBody::updateProxyShapeInBroadPhase(ProxyShape* proxyShape, bool forceReinsert) const { - - const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity); - - if (proxyShape->getBroadPhaseId() != -1) { - - // Recompute the world-space AABB of the collision shape - AABB aabb; - proxyShape->getCollisionShape()->computeAABB(aabb, transform * proxyShape->getLocalToBodyTransform()); - - // Update the broad-phase state for the proxy collision shape - mWorld.mCollisionDetection.updateProxyCollisionShape(proxyShape, aabb, Vector3(0, 0, 0), forceReinsert) ; + mWorld.mCollisionDetection.updateProxyShape(proxyShapesEntities[i]); } } @@ -442,6 +424,8 @@ AABB CollisionBody::getAABB() const { */ void CollisionBody::setTransform(const Transform& transform) { + // TODO : Make sure this method is never called from the internal physics engine + // Update the transform of the body mWorld.mTransformComponents.setTransform(mEntity, transform); diff --git a/src/body/CollisionBody.h b/src/body/CollisionBody.h index 461062ad..9f20de8b 100644 --- a/src/body/CollisionBody.h +++ b/src/body/CollisionBody.h @@ -92,10 +92,7 @@ class CollisionBody : public Body { void removeAllCollisionShapes(); /// Update the broad-phase state for this body (because it has moved for instance) - virtual void updateBroadPhaseState() const; - - /// Update the broad-phase state of a proxy collision shape of the body - void updateProxyShapeInBroadPhase(ProxyShape* proxyShape, bool forceReinsert = false) const; + void updateBroadPhaseState() const; /// Ask the broad-phase to test again the collision shapes of the body for collision /// (as if the body has moved). diff --git a/src/body/RigidBody.cpp b/src/body/RigidBody.cpp index 384682d1..ad47335d 100644 --- a/src/body/RigidBody.cpp +++ b/src/body/RigidBody.cpp @@ -294,7 +294,7 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape, // TODO : Maybe this method can directly returns an AABB collisionShape->getLocalBounds(localBoundsMin, localBoundsMax); - ProxyShapesComponents::ProxyShapeComponent proxyShapeComponent(mEntity, proxyShape, -1, + ProxyShapeComponents::ProxyShapeComponent proxyShapeComponent(mEntity, proxyShape, -1, AABB(localBoundsMin, localBoundsMax), transform, collisionShape, mass, 0x0001, 0xFFFF); mWorld.mProxyShapesComponents.addComponent(proxyShapeEntity, mIsSleeping, proxyShapeComponent); @@ -576,36 +576,6 @@ void RigidBody::recomputeMassInformation() { mLinearVelocity += mAngularVelocity.cross(mCenterOfMassWorld - oldCenterOfMass); } -// Update the broad-phase state for this body (because it has moved for instance) -void RigidBody::updateBroadPhaseState() const { - - RP3D_PROFILE("RigidBody::updateBroadPhaseState()", mProfiler); - - // TODO : Make sure we compute this in a system - - const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity); - - DynamicsWorld& world = static_cast(mWorld); - const Vector3 displacement = world.mTimeStep * mLinearVelocity; - - // For all the proxy collision shapes of the body - const List& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity); - for (uint i=0; i < proxyShapesEntities.size(); i++) { - - ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]); - - if (proxyShape->getBroadPhaseId() != -1) { - - // Recompute the world-space AABB of the collision shape - AABB aabb; - proxyShape->getCollisionShape()->computeAABB(aabb, transform * proxyShape->getLocalToBodyTransform()); - - // Update the broad-phase state for the proxy collision shape - mWorld.mCollisionDetection.updateProxyCollisionShape(proxyShape, aabb, displacement); - } - } -} - #ifdef IS_PROFILING_ACTIVE // Set the profiler diff --git a/src/body/RigidBody.h b/src/body/RigidBody.h index 0491a3b3..c23d0356 100644 --- a/src/body/RigidBody.h +++ b/src/body/RigidBody.h @@ -123,9 +123,6 @@ class RigidBody : public CollisionBody { /// Update the transform of the body after a change of the center of mass void updateTransformWithCenterOfMass(); - /// Update the broad-phase state for this body (because it has moved for instance) - virtual void updateBroadPhaseState() const override; - /// Update the world inverse inertia tensor of the body void updateInertiaTensorInverseWorld(); diff --git a/src/collision/CollisionDetection.cpp b/src/collision/CollisionDetection.cpp index dd541c44..af17bd42 100644 --- a/src/collision/CollisionDetection.cpp +++ b/src/collision/CollisionDetection.cpp @@ -48,9 +48,11 @@ using namespace std; // Constructor -CollisionDetection::CollisionDetection(CollisionWorld* world, ProxyShapesComponents& proxyShapesComponents, MemoryManager& memoryManager) - : mMemoryManager(memoryManager), mProxyShapesComponents(proxyShapesComponents), mCollisionDispatch(mMemoryManager.getPoolAllocator()), mWorld(world), - mOverlappingPairs(mMemoryManager.getPoolAllocator()), mBroadPhaseSystem(*this, mProxyShapesComponents), +CollisionDetection::CollisionDetection(CollisionWorld* world, ProxyShapeComponents& proxyShapesComponents, TransformComponents &transformComponents, + MemoryManager& memoryManager) + : mMemoryManager(memoryManager), mProxyShapesComponents(proxyShapesComponents), mTransformComponents(transformComponents), + mCollisionDispatch(mMemoryManager.getPoolAllocator()), mWorld(world), + mOverlappingPairs(mMemoryManager.getPoolAllocator()), mBroadPhaseSystem(*this, mProxyShapesComponents, mTransformComponents), mNoCollisionPairs(mMemoryManager.getPoolAllocator()), mIsCollisionShapesAdded(false), mNarrowPhaseInput(mMemoryManager.getSingleFrameAllocator()) { diff --git a/src/collision/CollisionDetection.h b/src/collision/CollisionDetection.h index 976932ef..9357c0fe 100644 --- a/src/collision/CollisionDetection.h +++ b/src/collision/CollisionDetection.h @@ -35,7 +35,8 @@ #include "collision/narrowphase/CollisionDispatch.h" #include "containers/Map.h" #include "containers/Set.h" -#include "components/ProxyShapesComponents.h" +#include "components/ProxyShapeComponents.h" +#include "components/TransformComponents.h" /// ReactPhysics3D namespace namespace reactphysics3d { @@ -68,8 +69,11 @@ class CollisionDetection { /// Memory manager MemoryManager& mMemoryManager; - /// Reference the the proxy-shapes components - ProxyShapesComponents& mProxyShapesComponents; + /// Reference the proxy-shape components + ProxyShapeComponents& mProxyShapesComponents; + + /// Reference the transform components + TransformComponents& mTransformComponents; /// Collision Detection Dispatch configuration CollisionDispatch mCollisionDispatch; @@ -149,7 +153,8 @@ class CollisionDetection { // -------------------- Methods -------------------- // /// Constructor - CollisionDetection(CollisionWorld* world, ProxyShapesComponents& proxyShapesComponents, MemoryManager& memoryManager); + CollisionDetection(CollisionWorld* world, ProxyShapeComponents& proxyShapesComponents, + TransformComponents& transformComponents, MemoryManager& memoryManager); /// Destructor ~CollisionDetection() = default; @@ -170,8 +175,10 @@ class CollisionDetection { void removeProxyCollisionShape(ProxyShape* proxyShape); /// Update a proxy collision shape (that has moved for instance) - void updateProxyCollisionShape(ProxyShape* shape, const AABB& aabb, - const Vector3& displacement = Vector3(0, 0, 0), bool forceReinsert = false); + void updateProxyShape(Entity proxyShapeEntity); + + /// Update all the enabled proxy-shapes + void updateProxyShapes(); /// Add a pair of bodies that cannot collide with each other void addNoCollisionPair(CollisionBody* body1, CollisionBody* body2); @@ -272,13 +279,6 @@ inline void CollisionDetection::askForBroadPhaseCollisionCheck(ProxyShape* shape } } -// Update a proxy collision shape (that has moved for instance) -inline void CollisionDetection::updateProxyCollisionShape(ProxyShape* shape, const AABB& aabb, - const Vector3& displacement, bool forceReinsert) { - mBroadPhaseSystem.updateProxyCollisionShape(shape, aabb, displacement); -} - - // Return a pointer to the world inline CollisionWorld* CollisionDetection::getWorld() { return mWorld; @@ -289,6 +289,18 @@ inline MemoryManager& CollisionDetection::getMemoryManager() const { return mMemoryManager; } +// Update a proxy collision shape (that has moved for instance) +inline void CollisionDetection::updateProxyShape(Entity proxyShapeEntity) { + + // Update the proxy-shape component + mBroadPhaseSystem.updateProxyShape(proxyShapeEntity); +} + +// Update all the enabled proxy-shapes +inline void CollisionDetection::updateProxyShapes() { + mBroadPhaseSystem.updateProxyShapes(); +} + #ifdef IS_PROFILING_ACTIVE // Set the profiler diff --git a/src/collision/ProxyShape.cpp b/src/collision/ProxyShape.cpp index df3a2fe0..d8dbeacd 100644 --- a/src/collision/ProxyShape.cpp +++ b/src/collision/ProxyShape.cpp @@ -105,13 +105,14 @@ void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBits) { // Set the local to parent body transform void ProxyShape::setLocalToBodyTransform(const Transform& transform) { + // TODO : Make sure this method is never called by the internal physics engine + //mLocalToBodyTransform = transform; mBody->mWorld.mProxyShapesComponents.setLocalToBodyTransform(mEntity, transform); mBody->setIsSleeping(false); - // Notify the body that the proxy shape has to be updated in the broad-phase - mBody->updateProxyShapeInBroadPhase(this, true); + mBody->mWorld.mCollisionDetection.updateProxyShape(mEntity); int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(mEntity); diff --git a/src/collision/broadphase/DynamicAABBTree.cpp b/src/collision/broadphase/DynamicAABBTree.cpp index 58639fc9..bdc85b5e 100644 --- a/src/collision/broadphase/DynamicAABBTree.cpp +++ b/src/collision/broadphase/DynamicAABBTree.cpp @@ -169,9 +169,8 @@ void DynamicAABBTree::removeObject(int nodeID) { /// nothing is done. Otherwise, the corresponding node is removed and reinserted into the tree. /// The method returns true if the object has been reinserted into the tree. The "displacement" /// argument is the linear velocity of the AABB multiplied by the elapsed time between two -/// frames. If the "forceReinsert" parameter is true, we force a removal and reinsertion of the node -/// (this can be useful if the shape AABB has become much smaller than the previous one for instance). -bool DynamicAABBTree::updateObject(int nodeID, const AABB& newAABB, const Vector3& displacement, bool forceReinsert) { +/// frames. +bool DynamicAABBTree::updateObject(int nodeID, const AABB& newAABB, const Vector3& displacement) { RP3D_PROFILE("DynamicAABBTree::updateObject()", mProfiler); @@ -180,7 +179,7 @@ bool DynamicAABBTree::updateObject(int nodeID, const AABB& newAABB, const Vector assert(mNodes[nodeID].height >= 0); // If the new AABB is still inside the fat AABB of the node - if (!forceReinsert && mNodes[nodeID].aabb.contains(newAABB)) { + if (mNodes[nodeID].aabb.contains(newAABB)) { return false; } diff --git a/src/collision/broadphase/DynamicAABBTree.h b/src/collision/broadphase/DynamicAABBTree.h index 1939594f..0b0a5828 100644 --- a/src/collision/broadphase/DynamicAABBTree.h +++ b/src/collision/broadphase/DynamicAABBTree.h @@ -225,7 +225,7 @@ class DynamicAABBTree { void removeObject(int nodeID); /// Update the dynamic tree after an object has moved. - bool updateObject(int nodeID, const AABB& newAABB, const Vector3& displacement, bool forceReinsert = false); + bool updateObject(int nodeID, const AABB& newAABB, const Vector3& displacement); /// Return the fat AABB corresponding to a given node ID const AABB& getFatAABB(int nodeID) const; diff --git a/src/components/Components.h b/src/components/Components.h index 4eb40ffe..cd5dcc56 100644 --- a/src/components/Components.h +++ b/src/components/Components.h @@ -112,6 +112,9 @@ class Components { /// Return the number of components uint32 getNbComponents() const; + + /// Return the number of enabled components + uint32 getNbEnabledComponents() const; }; // Return the number of components @@ -119,6 +122,11 @@ inline uint32 Components::getNbComponents() const { return mNbComponents; } +// Return the number of enabled components +inline uint32 Components::getNbEnabledComponents() const { + return mDisabledStartIndex; +} + } #endif diff --git a/src/components/ProxyShapesComponents.cpp b/src/components/ProxyShapeComponents.cpp similarity index 95% rename from src/components/ProxyShapesComponents.cpp rename to src/components/ProxyShapeComponents.cpp index 62915c8b..965d0bde 100644 --- a/src/components/ProxyShapesComponents.cpp +++ b/src/components/ProxyShapeComponents.cpp @@ -24,7 +24,7 @@ ********************************************************************************/ // Libraries -#include "ProxyShapesComponents.h" +#include "ProxyShapeComponents.h" #include "engine/EntityManager.h" #include "collision/ProxyShape.h" #include @@ -34,7 +34,7 @@ using namespace reactphysics3d; // Constructor -ProxyShapesComponents::ProxyShapesComponents(MemoryAllocator& allocator) +ProxyShapeComponents::ProxyShapeComponents(MemoryAllocator& allocator) :Components(allocator, sizeof(Entity) + sizeof(Entity) + sizeof(ProxyShape*) + sizeof(int) + sizeof(AABB) + sizeof(Transform) + sizeof(CollisionShape*) + sizeof(decimal) + sizeof(unsigned short) + sizeof(unsigned short)) { @@ -44,7 +44,7 @@ ProxyShapesComponents::ProxyShapesComponents(MemoryAllocator& allocator) } // Allocate memory for a given number of components -void ProxyShapesComponents::allocate(uint32 nbComponentsToAllocate) { +void ProxyShapeComponents::allocate(uint32 nbComponentsToAllocate) { assert(nbComponentsToAllocate > mNbAllocatedComponents); @@ -103,7 +103,7 @@ void ProxyShapesComponents::allocate(uint32 nbComponentsToAllocate) { } // Add a component -void ProxyShapesComponents::addComponent(Entity proxyShapeEntity, bool isSleeping, const ProxyShapeComponent& component) { +void ProxyShapeComponents::addComponent(Entity proxyShapeEntity, bool isSleeping, const ProxyShapeComponent& component) { // Prepare to add new component (allocate memory if necessary and compute insertion index) uint32 index = prepareAddComponent(isSleeping); @@ -130,7 +130,7 @@ void ProxyShapesComponents::addComponent(Entity proxyShapeEntity, bool isSleepin // Move a component from a source to a destination index in the components array // The destination location must contain a constructed object -void ProxyShapesComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) { +void ProxyShapeComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) { const Entity proxyShapeEntity = mProxyShapesEntities[srcIndex]; @@ -158,7 +158,7 @@ void ProxyShapesComponents::moveComponentToIndex(uint32 srcIndex, uint32 destInd } // Swap two components in the array -void ProxyShapesComponents::swapComponents(uint32 index1, uint32 index2) { +void ProxyShapeComponents::swapComponents(uint32 index1, uint32 index2) { // Copy component 1 data Entity proxyShapeEntity1(mProxyShapesEntities[index1]); @@ -198,7 +198,7 @@ void ProxyShapesComponents::swapComponents(uint32 index1, uint32 index2) { } // Destroy a component at a given index -void ProxyShapesComponents::destroyComponent(uint32 index) { +void ProxyShapeComponents::destroyComponent(uint32 index) { Components::destroyComponent(index); diff --git a/src/components/ProxyShapesComponents.h b/src/components/ProxyShapeComponents.h similarity index 88% rename from src/components/ProxyShapesComponents.h rename to src/components/ProxyShapeComponents.h index add72c28..5282e2fc 100644 --- a/src/components/ProxyShapesComponents.h +++ b/src/components/ProxyShapeComponents.h @@ -49,7 +49,7 @@ class ProxyShape; * different bodies. We also make sure that proxy shapes of sleeping entities (bodies) are * always stored at the end of the array. */ -class ProxyShapesComponents : public Components { +class ProxyShapeComponents : public Components { private: @@ -135,10 +135,10 @@ class ProxyShapesComponents : public Components { // -------------------- Methods -------------------- // /// Constructor - ProxyShapesComponents(MemoryAllocator& allocator); + ProxyShapeComponents(MemoryAllocator& allocator); /// Destructor - virtual ~ProxyShapesComponents() override = default; + virtual ~ProxyShapeComponents() override = default; /// Add a component void addComponent(Entity proxyShapeEntity, bool isSleeping, const ProxyShapeComponent& component); @@ -175,10 +175,14 @@ class ProxyShapesComponents : public Components { /// Set the "collide with" mask bits of a given proxy-shape void setCollideWithMaskBits(Entity proxyShapeEntity, unsigned short collideWithMaskBits); + + // -------------------- Friendship -------------------- // + + friend class BroadPhaseSystem; }; // Return the mass of a proxy-shape -inline decimal ProxyShapesComponents::getMass(Entity proxyShapeEntity) const { +inline decimal ProxyShapeComponents::getMass(Entity proxyShapeEntity) const { assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity)); @@ -186,7 +190,7 @@ inline decimal ProxyShapesComponents::getMass(Entity proxyShapeEntity) const { } // Return a pointer to a given proxy-shape -inline ProxyShape* ProxyShapesComponents::getProxyShape(Entity proxyShapeEntity) const { +inline ProxyShape* ProxyShapeComponents::getProxyShape(Entity proxyShapeEntity) const { assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity)); @@ -194,7 +198,7 @@ inline ProxyShape* ProxyShapesComponents::getProxyShape(Entity proxyShapeEntity) } // Return the local-to-body transform of a proxy-shape -inline const Transform& ProxyShapesComponents::getLocalToBodyTransform(Entity proxyShapeEntity) const { +inline const Transform& ProxyShapeComponents::getLocalToBodyTransform(Entity proxyShapeEntity) const { assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity)); @@ -202,7 +206,7 @@ inline const Transform& ProxyShapesComponents::getLocalToBodyTransform(Entity pr } // Set the local-to-body transform of a proxy-shape -inline void ProxyShapesComponents::setLocalToBodyTransform(Entity proxyShapeEntity, const Transform& transform) { +inline void ProxyShapeComponents::setLocalToBodyTransform(Entity proxyShapeEntity, const Transform& transform) { assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity)); @@ -210,7 +214,7 @@ inline void ProxyShapesComponents::setLocalToBodyTransform(Entity proxyShapeEnti } // Return a pointer to the collision shape of a proxy-shape -inline CollisionShape* ProxyShapesComponents::getCollisionShape(Entity proxyShapeEntity) const { +inline CollisionShape* ProxyShapeComponents::getCollisionShape(Entity proxyShapeEntity) const { assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity)); @@ -218,7 +222,7 @@ inline CollisionShape* ProxyShapesComponents::getCollisionShape(Entity proxyShap } // Return the broad-phase id of a given proxy shape -inline int ProxyShapesComponents::getBroadPhaseId(Entity proxyShapeEntity) const { +inline int ProxyShapeComponents::getBroadPhaseId(Entity proxyShapeEntity) const { assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity)); @@ -226,7 +230,7 @@ inline int ProxyShapesComponents::getBroadPhaseId(Entity proxyShapeEntity) const } // Set the broad-phase id of a given proxy shape -inline void ProxyShapesComponents::setBroadPhaseId(Entity proxyShapeEntity, int broadPhaseId) { +inline void ProxyShapeComponents::setBroadPhaseId(Entity proxyShapeEntity, int broadPhaseId) { assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity)); @@ -234,7 +238,7 @@ inline void ProxyShapesComponents::setBroadPhaseId(Entity proxyShapeEntity, int } // Return the collision category bits of a given proxy-shape -inline unsigned short ProxyShapesComponents::getCollisionCategoryBits(Entity proxyShapeEntity) const { +inline unsigned short ProxyShapeComponents::getCollisionCategoryBits(Entity proxyShapeEntity) const { assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity)); @@ -242,7 +246,7 @@ inline unsigned short ProxyShapesComponents::getCollisionCategoryBits(Entity pro } // Return the "collide with" mask bits of a given proxy-shape -inline unsigned short ProxyShapesComponents::getCollideWithMaskBits(Entity proxyShapeEntity) const { +inline unsigned short ProxyShapeComponents::getCollideWithMaskBits(Entity proxyShapeEntity) const { assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity)); @@ -250,7 +254,7 @@ inline unsigned short ProxyShapesComponents::getCollideWithMaskBits(Entity proxy } // Set the collision category bits of a given proxy-shape -inline void ProxyShapesComponents::setCollisionCategoryBits(Entity proxyShapeEntity, unsigned short collisionCategoryBits) { +inline void ProxyShapeComponents::setCollisionCategoryBits(Entity proxyShapeEntity, unsigned short collisionCategoryBits) { assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity)); @@ -258,7 +262,7 @@ inline void ProxyShapesComponents::setCollisionCategoryBits(Entity proxyShapeEnt } // Set the "collide with" mask bits of a given proxy-shape -inline void ProxyShapesComponents::setCollideWithMaskBits(Entity proxyShapeEntity, unsigned short collideWithMaskBits) { +inline void ProxyShapeComponents::setCollideWithMaskBits(Entity proxyShapeEntity, unsigned short collideWithMaskBits) { assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity)); diff --git a/src/components/TransformComponents.h b/src/components/TransformComponents.h index 925a2ab7..f50c52b5 100644 --- a/src/components/TransformComponents.h +++ b/src/components/TransformComponents.h @@ -100,6 +100,10 @@ class TransformComponents : public Components { /// Set the transform of an entity void setTransform(Entity bodyEntity, const Transform& transform); + + // -------------------- Friendship -------------------- // + + friend class BroadPhaseSystem; }; // Return the transform of an entity diff --git a/src/engine/CollisionWorld.cpp b/src/engine/CollisionWorld.cpp index b3ad3864..36ef4b33 100644 --- a/src/engine/CollisionWorld.cpp +++ b/src/engine/CollisionWorld.cpp @@ -39,7 +39,7 @@ uint CollisionWorld::mNbWorlds = 0; CollisionWorld::CollisionWorld(const WorldSettings& worldSettings, Logger* logger, Profiler* profiler) : mConfig(worldSettings), mEntityManager(mMemoryManager.getPoolAllocator()), mBodyComponents(mMemoryManager.getBaseAllocator()), mTransformComponents(mMemoryManager.getBaseAllocator()), - mProxyShapesComponents(mMemoryManager.getBaseAllocator()), mCollisionDetection(this, mProxyShapesComponents, mMemoryManager), + mProxyShapesComponents(mMemoryManager.getBaseAllocator()), mCollisionDetection(this, mProxyShapesComponents, mTransformComponents, mMemoryManager), mBodies(mMemoryManager.getPoolAllocator()), mCurrentBodyId(0), mFreeBodiesIds(mMemoryManager.getPoolAllocator()), mEventListener(nullptr), mName(worldSettings.worldName), mIsProfilerCreatedByUser(profiler != nullptr), diff --git a/src/engine/CollisionWorld.h b/src/engine/CollisionWorld.h index 910cbaee..87ebebce 100644 --- a/src/engine/CollisionWorld.h +++ b/src/engine/CollisionWorld.h @@ -35,7 +35,7 @@ #include "engine/EntityManager.h" #include "components/BodyComponents.h" #include "components/TransformComponents.h" -#include "components/ProxyShapesComponents.h" +#include "components/ProxyShapeComponents.h" /// Namespace reactphysics3d namespace reactphysics3d { @@ -80,7 +80,7 @@ class CollisionWorld { TransformComponents mTransformComponents; /// Proxy-Shapes Components - ProxyShapesComponents mProxyShapesComponents; + ProxyShapeComponents mProxyShapesComponents; /// Reference to the collision detection CollisionDetection mCollisionDetection; diff --git a/src/engine/DynamicsWorld.cpp b/src/engine/DynamicsWorld.cpp index 2025e461..b14d250a 100644 --- a/src/engine/DynamicsWorld.cpp +++ b/src/engine/DynamicsWorld.cpp @@ -228,11 +228,11 @@ void DynamicsWorld::updateBodiesState() { // Update the world inverse inertia tensor of the body bodies[b]->updateInertiaTensorInverseWorld(); - - // Update the broad-phase state of the body - bodies[b]->updateBroadPhaseState(); } } + + // Update the proxy-shapes components + mCollisionDetection.updateProxyShapes(); } // Initialize the bodies velocities arrays for the next simulation step. diff --git a/src/systems/BroadPhaseSystem.cpp b/src/systems/BroadPhaseSystem.cpp index 9c47fd95..51c986f3 100644 --- a/src/systems/BroadPhaseSystem.cpp +++ b/src/systems/BroadPhaseSystem.cpp @@ -35,9 +35,10 @@ using namespace reactphysics3d; // Constructor -BroadPhaseSystem::BroadPhaseSystem(CollisionDetection& collisionDetection, ProxyShapesComponents& proxyShapesComponents) +BroadPhaseSystem::BroadPhaseSystem(CollisionDetection& collisionDetection, ProxyShapeComponents& proxyShapesComponents, + TransformComponents& transformComponents) :mDynamicAABBTree(collisionDetection.getMemoryManager().getPoolAllocator(), DYNAMIC_TREE_AABB_GAP), - mProxyShapesComponents(proxyShapesComponents), + mProxyShapesComponents(proxyShapesComponents), mTransformsComponents(transformComponents), mMovedShapes(collisionDetection.getMemoryManager().getPoolAllocator()), mPotentialPairs(collisionDetection.getMemoryManager().getPoolAllocator()), mCollisionDetection(collisionDetection) { @@ -108,16 +109,32 @@ void BroadPhaseSystem::removeProxyCollisionShape(ProxyShape* proxyShape) { removeMovedCollisionShape(broadPhaseID); } +// Update the broad-phase state of a single proxy-shape +void BroadPhaseSystem::updateProxyShape(Entity proxyShapeEntity) { + + assert(mProxyShapesComponents.mMapEntityToComponentIndex.containsKey(proxyShapeEntity)); + + // Get the index of the proxy-shape component in the array + uint32 index = mProxyShapesComponents.mMapEntityToComponentIndex[proxyShapeEntity]; + + // Update the proxy-shape component + updateProxyShapesComponents(index, index + 1); +} + +// Update the broad-phase state of all the enabled proxy-shapes +void BroadPhaseSystem::updateProxyShapes() { + + // Update all the enabled proxy-shape components + updateProxyShapesComponents(0, mProxyShapesComponents.getNbEnabledComponents()); +} + // Notify the broad-phase that a collision shape has moved and need to be updated -void BroadPhaseSystem::updateProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb, - const Vector3& displacement, bool forceReinsert) { +void BroadPhaseSystem::updateProxyShapeInternal(int broadPhaseId, const AABB& aabb, const Vector3& displacement) { - int broadPhaseID = proxyShape->getBroadPhaseId(); - - assert(broadPhaseID >= 0); + assert(broadPhaseId >= 0); // Update the dynamic AABB tree according to the movement of the collision shape - bool hasBeenReInserted = mDynamicAABBTree.updateObject(broadPhaseID, aabb, displacement, forceReinsert); + bool hasBeenReInserted = mDynamicAABBTree.updateObject(broadPhaseId, aabb, displacement); // If the collision shape has moved out of its fat AABB (and therefore has been reinserted // into the tree). @@ -125,7 +142,41 @@ void BroadPhaseSystem::updateProxyCollisionShape(ProxyShape* proxyShape, const A // Add the collision shape into the array of shapes that have moved (or have been created) // during the last simulation step - addMovedCollisionShape(broadPhaseID); + addMovedCollisionShape(broadPhaseId); + } +} + +// Update the broad-phase state of some proxy-shapes components +void BroadPhaseSystem::updateProxyShapesComponents(uint32 startIndex, uint32 endIndex) { + + assert(startIndex <= endIndex); + assert(startIndex < mProxyShapesComponents.getNbComponents()); + assert(endIndex <= mProxyShapesComponents.getNbComponents()); + + // Make sure we do not update disabled components + startIndex = std::min(startIndex, mProxyShapesComponents.getNbEnabledComponents()); + endIndex = std::min(endIndex, mProxyShapesComponents.getNbEnabledComponents()); + + // For each proxy-shape component to update + for (uint32 i = startIndex; i < endIndex; i++) { + + const int broadPhaseId = mProxyShapesComponents.mBroadPhaseIds[i]; + if (broadPhaseId != -1) { + + const Entity& bodyEntity = mProxyShapesComponents.mBodiesEntities[i]; + const Transform& transform = mTransformsComponents.getTransform(bodyEntity); + + // TODO : Use body linear velocity and compute displacement + const Vector3 displacement = Vector3::zero(); + //const Vector3 displacement = world.mTimeStep * mLinearVelocity; + + // Recompute the world-space AABB of the collision shape + AABB aabb; + mProxyShapesComponents.mCollisionShapes[i]->computeAABB(aabb, transform * mProxyShapesComponents.mLocalToBodyTransforms[i]); + + // Update the broad-phase state for the proxy collision shape + updateProxyShapeInternal(broadPhaseId, aabb, displacement); + } } } diff --git a/src/systems/BroadPhaseSystem.h b/src/systems/BroadPhaseSystem.h index 4d2bbd5b..e4ca273a 100644 --- a/src/systems/BroadPhaseSystem.h +++ b/src/systems/BroadPhaseSystem.h @@ -30,7 +30,8 @@ #include "collision/broadphase/DynamicAABBTree.h" #include "containers/LinkedList.h" #include "containers/Set.h" -#include "components/ProxyShapesComponents.h" +#include "components/ProxyShapeComponents.h" +#include "components/TransformComponents.h" /// Namespace ReactPhysics3D namespace reactphysics3d { @@ -142,7 +143,10 @@ class BroadPhaseSystem { DynamicAABBTree mDynamicAABBTree; /// Reference to the proxy-shapes components - ProxyShapesComponents& mProxyShapesComponents; + ProxyShapeComponents& mProxyShapesComponents; + + /// Reference to the transform components + TransformComponents& mTransformsComponents; /// Set with the broad-phase IDs of all collision shapes that have moved (or have been /// created) during the last simulation step. Those are the shapes that need to be tested @@ -161,13 +165,21 @@ class BroadPhaseSystem { Profiler* mProfiler; #endif + // -------------------- Methods -------------------- // + + /// Notify the Dynamic AABB tree that a proxy-shape needs to be updated + void updateProxyShapeInternal(int broadPhaseId, const AABB& aabb, const Vector3& displacement); + + /// Update the broad-phase state of some proxy-shapes components + void updateProxyShapesComponents(uint32 startIndex, uint32 endIndex); public : // -------------------- Methods -------------------- // /// Constructor - BroadPhaseSystem(CollisionDetection& collisionDetection, ProxyShapesComponents& proxyShapesComponents); + BroadPhaseSystem(CollisionDetection& collisionDetection, ProxyShapeComponents& proxyShapesComponents, + TransformComponents &transformComponents); /// Destructor ~BroadPhaseSystem() = default; @@ -184,9 +196,11 @@ class BroadPhaseSystem { /// Remove a proxy collision shape from the broad-phase collision detection void removeProxyCollisionShape(ProxyShape* proxyShape); - /// Notify the broad-phase that a collision shape has moved and need to be updated - void updateProxyCollisionShape(ProxyShape* proxyShape, const AABB& aabb, - const Vector3& displacement, bool forceReinsert = false); + /// Update the broad-phase state of a single proxy-shape + void updateProxyShape(Entity proxyShapeEntity); + + /// Update the broad-phase state of all the enabled proxy-shapes + void updateProxyShapes(); /// Add a collision shape in the array of shapes that have moved in the last simulation step /// and that need to be tested again for broad-phase overlapping. diff --git a/test/tests/collision/TestDynamicAABBTree.h b/test/tests/collision/TestDynamicAABBTree.h index d7912630..6878955d 100755 --- a/test/tests/collision/TestDynamicAABBTree.h +++ b/test/tests/collision/TestDynamicAABBTree.h @@ -243,10 +243,10 @@ class TestDynamicAABBTree : public Test { // ---- Update the object AABBs with the initial AABBs (no reinsertion) ----- // - tree.updateObject(object1Id, aabb1, Vector3::zero(), false); - tree.updateObject(object2Id, aabb2, Vector3::zero(), false); - tree.updateObject(object3Id, aabb3, Vector3::zero(), false); - tree.updateObject(object4Id, aabb4, Vector3::zero(), false); + tree.updateObject(object1Id, aabb1, Vector3::zero()); + tree.updateObject(object2Id, aabb2, Vector3::zero()); + tree.updateObject(object3Id, aabb3, Vector3::zero()); + tree.updateObject(object4Id, aabb4, Vector3::zero()); // AABB overlapping nothing mOverlapCallback.reset(); @@ -290,10 +290,10 @@ class TestDynamicAABBTree : public Test { // ---- Update the object AABBs with the initial AABBs (with reinsertion) ----- // - tree.updateObject(object1Id, aabb1, Vector3::zero(), true); - tree.updateObject(object2Id, aabb2, Vector3::zero(), true); - tree.updateObject(object3Id, aabb3, Vector3::zero(), true); - tree.updateObject(object4Id, aabb4, Vector3::zero(), true); + tree.updateObject(object1Id, aabb1, Vector3::zero()); + tree.updateObject(object2Id, aabb2, Vector3::zero()); + tree.updateObject(object3Id, aabb3, Vector3::zero()); + tree.updateObject(object4Id, aabb4, Vector3::zero()); // AABB overlapping nothing mOverlapCallback.reset(); @@ -438,10 +438,10 @@ class TestDynamicAABBTree : public Test { // ---- Update the object AABBs with the initial AABBs (no reinsertion) ----- // - tree.updateObject(object1Id, aabb1, Vector3::zero(), false); - tree.updateObject(object2Id, aabb2, Vector3::zero(), false); - tree.updateObject(object3Id, aabb3, Vector3::zero(), false); - tree.updateObject(object4Id, aabb4, Vector3::zero(), false); + tree.updateObject(object1Id, aabb1, Vector3::zero()); + tree.updateObject(object2Id, aabb2, Vector3::zero()); + tree.updateObject(object3Id, aabb3, Vector3::zero()); + tree.updateObject(object4Id, aabb4, Vector3::zero()); // Ray with no hits mRaycastCallback.reset(); @@ -477,10 +477,10 @@ class TestDynamicAABBTree : public Test { // ---- Update the object AABBs with the initial AABBs (with reinsertion) ----- // - tree.updateObject(object1Id, aabb1, Vector3::zero(), true); - tree.updateObject(object2Id, aabb2, Vector3::zero(), true); - tree.updateObject(object3Id, aabb3, Vector3::zero(), true); - tree.updateObject(object4Id, aabb4, Vector3::zero(), true); + tree.updateObject(object1Id, aabb1, Vector3::zero()); + tree.updateObject(object2Id, aabb2, Vector3::zero()); + tree.updateObject(object3Id, aabb3, Vector3::zero()); + tree.updateObject(object4Id, aabb4, Vector3::zero()); // Ray with no hits mRaycastCallback.reset();