diff --git a/src/body/Body.h b/src/body/Body.h index 00cccac7..bdee42c6 100644 --- a/src/body/Body.h +++ b/src/body/Body.h @@ -71,6 +71,7 @@ class Body { /// removed from the broad-phase. If you set this value to "true", /// all the proxy shapes will be added to the broad-phase. A joint /// connected to an inactive body will also be inactive. + // TODO : Make sure we correctly use this field with ECS bool mIsActive; /// True if the body is sleeping (for sleeping technique) diff --git a/src/body/CollisionBody.cpp b/src/body/CollisionBody.cpp index 33a70b27..912ceeb6 100644 --- a/src/body/CollisionBody.cpp +++ b/src/body/CollisionBody.cpp @@ -40,8 +40,8 @@ using namespace reactphysics3d; * @param id ID of the body */ CollisionBody::CollisionBody(CollisionWorld& world, Entity entity, bodyindex id) - : Body(entity, id), mType(BodyType::DYNAMIC), mProxyCollisionShapes(nullptr), - mNbCollisionShapes(0), mContactManifoldsList(nullptr), mWorld(world) { + : Body(entity, id), mType(BodyType::DYNAMIC), + mContactManifoldsList(nullptr), mWorld(world) { #ifdef IS_PROFILING_ACTIVE mProfiler = nullptr; @@ -52,9 +52,6 @@ CollisionBody::CollisionBody(CollisionWorld& world, Entity entity, bodyindex id) // Destructor CollisionBody::~CollisionBody() { assert(mContactManifoldsList == nullptr); - - // Remove all the proxy collision shapes of the body - removeAllCollisionShapes(); } // Add a collision shape to the body. Note that you can share a collision @@ -104,15 +101,6 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape, #endif - // Add it to the list of proxy collision shapes of the body - if (mProxyCollisionShapes == nullptr) { - mProxyCollisionShapes = proxyShape; - } - else { - proxyShape->mNext = mProxyCollisionShapes; - mProxyCollisionShapes = proxyShape; - } - // Compute the world-space AABB of the new collision shape AABB aabb; collisionShape->computeAABB(aabb, mWorld.mTransformComponents.getTransform(mEntity) * transform); @@ -120,8 +108,6 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape, // Notify the collision detection about this new collision shape mWorld.mCollisionDetection.addProxyCollisionShape(proxyShape, aabb); - mNbCollisionShapes++; - RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, "Body " + std::to_string(mID) + ": Proxy shape " + std::to_string(proxyShape->getBroadPhaseId()) + " added to body"); @@ -133,6 +119,24 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape, return proxyShape; } +// Return the linked list of proxy shapes of that body +/** +* @return The pointer of the first proxy shape of the linked-list of all the +* proxy shapes of the body +*/ +ProxyShape* CollisionBody::getProxyShapesList() { + return mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); +} + +// Return the linked list of proxy shapes of that body +/** +* @return The pointer of the first proxy shape of the linked-list of all the +* proxy shapes of the body +*/ +const ProxyShape* CollisionBody::getProxyShapesList() const { + return mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); +} + // Remove a collision shape from the body /// To remove a collision shape, you need to specify the pointer to the proxy /// shape that has been returned when you have added the collision shape to the @@ -140,75 +144,50 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape, /** * @param proxyShape The pointer of the proxy shape you want to remove */ -void CollisionBody::removeCollisionShape(const ProxyShape* proxyShape) { - - ProxyShape* current = mProxyCollisionShapes; +void CollisionBody::removeCollisionShape(ProxyShape* proxyShape) { RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, "Body " + std::to_string(mID) + ": Proxy shape " + std::to_string(proxyShape->getBroadPhaseId()) + " removed from body"); - // If the the first proxy shape is the one to remove - if (current == proxyShape) { - mProxyCollisionShapes = current->mNext; + // Remove the proxy-shape component + mWorld.mProxyShapesComponents.removeComponent(proxyShape); - if (mIsActive && proxyShape->getBroadPhaseId() != -1) { - mWorld.mCollisionDetection.removeProxyCollisionShape(current); - } - - current->~ProxyShape(); - mWorld.mMemoryManager.release(MemoryManager::AllocationType::Pool, current, sizeof(ProxyShape)); - mNbCollisionShapes--; - return; + // Remove the proxy-shape from the broad-phase + if (mIsActive && proxyShape->getBroadPhaseId() != -1) { + mWorld.mCollisionDetection.removeProxyCollisionShape(proxyShape); } - // Look for the proxy shape that contains the collision shape in parameter - while(current->mNext != nullptr) { + // Call the constructor of the proxy-shape + proxyShape->~ProxyShape(); - // If we have found the collision shape to remove - if (current->mNext == proxyShape) { - - // Remove the proxy collision shape - ProxyShape* elementToRemove = current->mNext; - current->mNext = elementToRemove->mNext; - - if (mIsActive && proxyShape->getBroadPhaseId() != -1) { - mWorld.mCollisionDetection.removeProxyCollisionShape(elementToRemove); - } - - elementToRemove->~ProxyShape(); - mWorld.mMemoryManager.release(MemoryManager::AllocationType::Pool, elementToRemove, sizeof(ProxyShape)); - mNbCollisionShapes--; - return; - } - - // Get the next element in the list - current = current->mNext; - } + // Release allocated memory for the proxy-shape + mWorld.mMemoryManager.release(MemoryManager::AllocationType::Pool, proxyShape, sizeof(ProxyShape)); } // Remove all the collision shapes void CollisionBody::removeAllCollisionShapes() { - ProxyShape* current = mProxyCollisionShapes; + ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); // Look for the proxy shape that contains the collision shape in parameter - while(current != nullptr) { + while(proxyShape != nullptr) { - // Remove the proxy collision shape - ProxyShape* nextElement = current->mNext; + if (mIsActive && proxyShape->getBroadPhaseId() != -1) { - if (mIsActive && current->getBroadPhaseId() != -1) { - mWorld.mCollisionDetection.removeProxyCollisionShape(current); + mWorld.mCollisionDetection.removeProxyCollisionShape(proxyShape); } - current->~ProxyShape(); - mWorld.mMemoryManager.release(MemoryManager::AllocationType::Pool, current, sizeof(ProxyShape)); + // Destroy the proxy-shape + proxyShape->~ProxyShape(); + + mWorld.mMemoryManager.release(MemoryManager::AllocationType::Pool, proxyShape, sizeof(ProxyShape)); // Get the next element in the list - current = nextElement; + proxyShape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(proxyShape); } - mProxyCollisionShapes = nullptr; + // Remove all the proxy-shapes components + mWorld.mProxyShapesComponents.removeComponents(mEntity); } // Reset the contact manifold lists @@ -244,7 +223,7 @@ const Transform& CollisionBody::getTransform() const { void CollisionBody::updateBroadPhaseState() const { // For all the proxy collision shapes of the body - for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) { + for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { // Update the proxy updateProxyShapeInBroadPhase(shape); @@ -284,7 +263,7 @@ void CollisionBody::setIsActive(bool isActive) { const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity); // For each proxy shape of the body - for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) { + for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { // Compute the world-space AABB of the new collision shape AABB aabb; @@ -297,7 +276,7 @@ void CollisionBody::setIsActive(bool isActive) { else { // If we have to deactivate the body // For each proxy shape of the body - for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) { + for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { if (shape->getBroadPhaseId() != -1) { @@ -320,7 +299,7 @@ void CollisionBody::setIsActive(bool isActive) { void CollisionBody::askForBroadPhaseCollisionCheck() const { // For all the proxy collision shapes of the body - for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) { + for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { mWorld.mCollisionDetection.askForBroadPhaseCollisionCheck(shape); } @@ -355,7 +334,7 @@ int CollisionBody::resetIsAlreadyInIslandAndCountManifolds() { bool CollisionBody::testPointInside(const Vector3& worldPoint) const { // For each collision shape of the body - for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) { + for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { // Test if the point is inside the collision shape if (shape->testPointInside(worldPoint)) return true; @@ -381,7 +360,7 @@ bool CollisionBody::raycast(const Ray& ray, RaycastInfo& raycastInfo) { Ray rayTemp(ray); // For each collision shape of the body - for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) { + for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { // Test if the ray hits the collision shape if (shape->raycast(rayTemp, raycastInfo)) { @@ -401,16 +380,17 @@ AABB CollisionBody::getAABB() const { AABB bodyAABB; - if (mProxyCollisionShapes == nullptr) return bodyAABB; + if (mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity) == nullptr) return bodyAABB; // TODO : Make sure we compute this in a system const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity); - mProxyCollisionShapes->getCollisionShape()->computeAABB(bodyAABB, transform * mProxyCollisionShapes->getLocalToBodyTransform()); + ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); + proxyShape->getCollisionShape()->computeAABB(bodyAABB, transform * proxyShape->getLocalToBodyTransform()); // For each proxy shape of the body - for (ProxyShape* shape = mProxyCollisionShapes->mNext; shape != nullptr; shape = shape->mNext) { + for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { // Compute the world-space AABB of the collision shape AABB aabb; diff --git a/src/body/CollisionBody.h b/src/body/CollisionBody.h index 2a5e3b52..6d6d35df 100644 --- a/src/body/CollisionBody.h +++ b/src/body/CollisionBody.h @@ -71,10 +71,10 @@ class CollisionBody : public Body { BodyType mType; /// First element of the linked list of proxy collision shapes of this body - ProxyShape* mProxyCollisionShapes; + //ProxyShape* mProxyCollisionShapes; /// Number of collision shapes - uint mNbCollisionShapes; + //uint mNbCollisionShapes; /// First element of the linked list of contact manifolds involving this body ContactManifoldListElement* mContactManifoldsList; @@ -149,7 +149,7 @@ class CollisionBody : public Body { const Transform& transform); /// Remove a collision shape from the body - virtual void removeCollisionShape(const ProxyShape* proxyShape); + virtual void removeCollisionShape(ProxyShape *proxyShape); /// Return the first element of the linked list of contact manifolds involving this body const ContactManifoldListElement* getContactManifoldsList() const; @@ -218,24 +218,6 @@ inline const ContactManifoldListElement* CollisionBody::getContactManifoldsList( return mContactManifoldsList; } -// Return the linked list of proxy shapes of that body -/** -* @return The pointer of the first proxy shape of the linked-list of all the -* proxy shapes of the body -*/ -inline ProxyShape* CollisionBody::getProxyShapesList() { - return mProxyCollisionShapes; -} - -// Return the linked list of proxy shapes of that body -/** -* @return The pointer of the first proxy shape of the linked-list of all the -* proxy shapes of the body -*/ -inline const ProxyShape* CollisionBody::getProxyShapesList() const { - return mProxyCollisionShapes; -} - /// Test if the collision body overlaps with a given AABB /** * @param worldAABB The AABB (in world-space coordinates) that will be used to test overlap diff --git a/src/body/RigidBody.cpp b/src/body/RigidBody.cpp index 7b175c38..6f62dc8b 100644 --- a/src/body/RigidBody.cpp +++ b/src/body/RigidBody.cpp @@ -310,15 +310,6 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape, #endif - // Add it to the list of proxy collision shapes of the body - if (mProxyCollisionShapes == nullptr) { - mProxyCollisionShapes = proxyShape; - } - else { - proxyShape->mNext = mProxyCollisionShapes; - mProxyCollisionShapes = proxyShape; - } - // Compute the world-space AABB of the new collision shape AABB aabb; collisionShape->computeAABB(aabb, mWorld.mTransformComponents.getTransform(mEntity) * transform); @@ -326,8 +317,6 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape, // Notify the collision detection about this new collision shape mWorld.mCollisionDetection.addProxyCollisionShape(proxyShape, aabb); - mNbCollisionShapes++; - // Recompute the center of mass, total mass and inertia tensor of the body with the new // collision shape recomputeMassInformation(); @@ -350,7 +339,7 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape, /** * @param proxyShape The pointer of the proxy shape you want to remove */ -void RigidBody::removeCollisionShape(const ProxyShape* proxyShape) { +void RigidBody::removeCollisionShape(ProxyShape* proxyShape) { // Remove the collision shape CollisionBody::removeCollisionShape(proxyShape); @@ -511,7 +500,7 @@ void RigidBody::recomputeMassInformation() { assert(mType == BodyType::DYNAMIC); // Compute the total mass of the body - for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) { + for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { mInitMass += shape->getMass(); if (!mIsCenterOfMassSetByUser) { @@ -539,7 +528,7 @@ void RigidBody::recomputeMassInformation() { if (!mIsInertiaTensorSetByUser) { // Compute the inertia tensor using all the collision shapes - for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) { + for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { // Get the inertia tensor of the collision shape in its local-space Matrix3x3 inertiaTensor; @@ -590,7 +579,7 @@ void RigidBody::updateBroadPhaseState() const { const Vector3 displacement = world.mTimeStep * mLinearVelocity; // For all the proxy collision shapes of the body - for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) { + for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) { // Recompute the world-space AABB of the collision shape AABB aabb; diff --git a/src/body/RigidBody.h b/src/body/RigidBody.h index 4ce9da2f..0491a3b3 100644 --- a/src/body/RigidBody.h +++ b/src/body/RigidBody.h @@ -232,7 +232,7 @@ class RigidBody : public CollisionBody { decimal mass); /// Remove a collision shape from the body - virtual void removeCollisionShape(const ProxyShape* proxyShape) override; + virtual void removeCollisionShape(ProxyShape* proxyShape) override; /// Recompute the center of mass, total mass and inertia tensor of the body using all /// the collision shapes attached to the body. diff --git a/src/collision/ProxyShape.cpp b/src/collision/ProxyShape.cpp index 2d7fe5da..658555cc 100644 --- a/src/collision/ProxyShape.cpp +++ b/src/collision/ProxyShape.cpp @@ -41,7 +41,7 @@ using namespace reactphysics3d; */ ProxyShape::ProxyShape(CollisionBody* body, MemoryManager& memoryManager) :mMemoryManager(memoryManager), mBody(body), - mNext(nullptr), mUserData(nullptr), mCollisionCategoryBits(0x0001), mCollideWithMaskBits(0xFFFF) { + mUserData(nullptr), mCollisionCategoryBits(0x0001), mCollideWithMaskBits(0xFFFF) { } @@ -159,6 +159,24 @@ const Transform& ProxyShape::getLocalToBodyTransform() const { return mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(this); } +// Return the next proxy shape in the linked list of proxy shapes +/** + * @return Pointer to the next proxy shape in the linked list of proxy shapes + */ +ProxyShape* ProxyShape::getNext() { + // TODO : Delete this method + return mBody->mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(this); +} + +// Return the next proxy shape in the linked list of proxy shapes +/** + * @return Pointer to the next proxy shape in the linked list of proxy shapes + */ +const ProxyShape* ProxyShape::getNext() const { + // TODO : Delete this method + return mBody->mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(this); +} + // Raycast method with feedback information /** * @param ray Ray to use for the raycasting diff --git a/src/collision/ProxyShape.h b/src/collision/ProxyShape.h index bd2bb8bf..17ee0c72 100644 --- a/src/collision/ProxyShape.h +++ b/src/collision/ProxyShape.h @@ -67,7 +67,7 @@ class ProxyShape { //decimal mMass; /// Pointer to the next proxy shape of the body (linked list) - ProxyShape* mNext; + //ProxyShape* mNext; /// Broad-phase ID (node ID in the dynamic AABB tree) //int mBroadPhaseID; @@ -233,22 +233,6 @@ inline void ProxyShape::setUserData(void* userData) { mUserData = userData; } -// Return the next proxy shape in the linked list of proxy shapes -/** - * @return Pointer to the next proxy shape in the linked list of proxy shapes - */ -inline ProxyShape* ProxyShape::getNext() { - return mNext; -} - -// Return the next proxy shape in the linked list of proxy shapes -/** - * @return Pointer to the next proxy shape in the linked list of proxy shapes - */ -inline const ProxyShape* ProxyShape::getNext() const { - return mNext; -} - // Return the collision category bits /** * @return The collision category bits mask of the proxy shape diff --git a/src/components/ProxyShapesComponents.cpp b/src/components/ProxyShapesComponents.cpp index 3d38be19..627690d5 100644 --- a/src/components/ProxyShapesComponents.cpp +++ b/src/components/ProxyShapesComponents.cpp @@ -498,3 +498,11 @@ void ProxyShapesComponents::removeComponents(Entity entity) { assert(!mMapEntityToComponentIndex.containsKey(entity)); } + +// Remove a given proxy-shape +void ProxyShapesComponents::removeComponent(const ProxyShape* proxyShape) { + + uint32 index = mMapProxyShapeToComponentIndex[proxyShape]; + + removeComponent(index); +} diff --git a/src/components/ProxyShapesComponents.h b/src/components/ProxyShapesComponents.h index 92d7b795..98368627 100644 --- a/src/components/ProxyShapesComponents.h +++ b/src/components/ProxyShapesComponents.h @@ -180,6 +180,9 @@ class ProxyShapesComponents { /// Remove all the components of a given entity void removeComponents(Entity entity); + /// Remove a given proxy-shape + void removeComponent(const ProxyShape* proxyShape); + /// Notify if a given entity is sleeping or not void setIsEntitySleeping(Entity entity, bool isSleeping); @@ -200,6 +203,12 @@ class ProxyShapesComponents { /// Set the broad-phase id of a given proxy shape void setBroadPhaseId(const ProxyShape* proxyShape, int broadPhaseId); + + /// Return the next proxy-shape in the linked-list of all proxy-shapes of a body + ProxyShape* getNextProxyShapeOfBody(const ProxyShape* proxyShape) const; + + /// Return the first proxy-shape in the linked-list of all proxy-shapes of a body + ProxyShape* getFirstProxyShapeOfBody(Entity entity) const; }; // Return the mass of a proxy-shape @@ -250,6 +259,34 @@ inline void ProxyShapesComponents::setBroadPhaseId(const ProxyShape* proxyShape, mBroadPhaseIds[mMapProxyShapeToComponentIndex[proxyShape]] = broadPhaseId; } +// Return the next proxy-shape in the linked-list of all proxy-shapes of a body +inline ProxyShape* ProxyShapesComponents::getNextProxyShapeOfBody(const ProxyShape* proxyShape) const { + + assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape)); + + uint32 proxyShapeIndex = mMapProxyShapeToComponentIndex[proxyShape]; + uint32 nextProxyShapeIndex = mNextBodyProxyShapes[proxyShapeIndex]; + + // If the current proxy-shape has a next one + if (proxyShapeIndex != nextProxyShapeIndex) { + return mProxyShapes[nextProxyShapeIndex]; + } + + return nullptr; +} + +// Return the first proxy-shape in the linked-list of all proxy-shapes of a body +inline ProxyShape* ProxyShapesComponents::getFirstProxyShapeOfBody(Entity entity) const { + + auto it = mMapEntityToComponentIndex.find(entity); + + if (it != mMapEntityToComponentIndex.end()) { + return mProxyShapes[it->second]; + } + + return nullptr; +} + } #endif