diff --git a/src/body/CollisionBody.cpp b/src/body/CollisionBody.cpp index 6929a6c0..e9354080 100644 --- a/src/body/CollisionBody.cpp +++ b/src/body/CollisionBody.cpp @@ -92,6 +92,9 @@ Collider* CollisionBody::addCollider(CollisionShape* collisionShape, const Trans mWorld.mCollisionBodyComponents.addColliderToBody(mEntity, colliderEntity); + // Assign the collider with the collision shape + collisionShape->addCollider(collider); + #ifdef IS_PROFILING_ACTIVE // Set the profiler @@ -175,6 +178,9 @@ void CollisionBody::removeCollider(Collider* collider) { mWorld.mCollisionBodyComponents.removeColliderFromBody(mEntity, collider->getEntity()); + // Unassign the collider from the collision shape + collider->getCollisionShape()->removeCollider(collider); + // Remove the collider component mWorld.mCollidersComponents.removeComponent(collider->getEntity()); diff --git a/src/body/RigidBody.cpp b/src/body/RigidBody.cpp index 165ebe10..f68ad07b 100644 --- a/src/body/RigidBody.cpp +++ b/src/body/RigidBody.cpp @@ -341,6 +341,9 @@ Collider* RigidBody::addCollider(CollisionShape* collisionShape, const Transform mWorld.mCollisionBodyComponents.addColliderToBody(mEntity, colliderEntity); + // Assign the collider with the collision shape + collisionShape->addCollider(collider); + #ifdef IS_PROFILING_ACTIVE // Set the profiler diff --git a/src/collision/Collider.cpp b/src/collision/Collider.cpp index 8f2afaf7..14176b29 100644 --- a/src/collision/Collider.cpp +++ b/src/collision/Collider.cpp @@ -42,8 +42,7 @@ using namespace reactphysics3d; Collider::Collider(Entity entity, CollisionBody* body, MemoryManager& memoryManager) :mMemoryManager(memoryManager), mEntity(entity), mBody(body), mMaterial(body->mWorld.mConfig.defaultFrictionCoefficient, body->mWorld.mConfig.defaultRollingRestistance, - body->mWorld.mConfig.defaultBounciness), - mUserData(nullptr) { + body->mWorld.mConfig.defaultBounciness), mUserData(nullptr) { } @@ -144,19 +143,11 @@ const AABB Collider::getWorldAABB() const { return aabb; } -// Return the collision shape +// Return a pointer to the collision shape /** * @return Pointer to the internal collision shape */ -const CollisionShape* Collider::getCollisionShape() const { - return mBody->mWorld.mCollidersComponents.getCollisionShape(mEntity); -} - -// Return the collision shape -/** -* @return Pointer to the internal collision shape -*/ -CollisionShape* Collider::getCollisionShape() { +CollisionShape* Collider::getCollisionShape() const { return mBody->mWorld.mCollidersComponents.getCollisionShape(mEntity); } @@ -220,6 +211,11 @@ unsigned short Collider::getCollideWithMaskBits() const { return mBody->mWorld.mCollidersComponents.getCollideWithMaskBits(mEntity); } +// Notify the collider that the size of the collision shape has been changed by the user +void Collider::setHasCollisionShapeChangedSize(bool hasCollisionShapeChangedSize) { + mBody->mWorld.mCollidersComponents.setHasCollisionShapeChangedSize(mEntity, hasCollisionShapeChangedSize); +} + // Return the local to world transform /** * @return The transformation that transforms the local-space of the collision diff --git a/src/collision/Collider.h b/src/collision/Collider.h index 7d2b46f0..50599103 100644 --- a/src/collision/Collider.h +++ b/src/collision/Collider.h @@ -80,8 +80,9 @@ class Collider { // -------------------- Methods -------------------- // - /// Return the collision shape - CollisionShape* getCollisionShape(); + /// Notify the collider that the size of the collision shape has been + /// changed by the user + void setHasCollisionShapeChangedSize(bool hasCollisionShapeChangedSize); public: @@ -102,8 +103,8 @@ class Collider { /// Return the corresponding entity of the collider Entity getEntity() const; - /// Return the collision shape - const CollisionShape* getCollisionShape() const; + /// Return a pointer to the collision shape + CollisionShape* getCollisionShape() const; /// Return the parent body CollisionBody* getBody() const; @@ -183,7 +184,8 @@ class Collider { friend class PhysicsWorld; friend class GJKAlgorithm; friend class ConvexMeshShape; - friend class ContactManifoldSet; + friend class CollisionShape; + friend class ContactManifoldSet; friend class MiddlePhaseTriangleCallback; }; diff --git a/src/collision/broadphase/DynamicAABBTree.cpp b/src/collision/broadphase/DynamicAABBTree.cpp index 17c3f83e..60d2c568 100644 --- a/src/collision/broadphase/DynamicAABBTree.cpp +++ b/src/collision/broadphase/DynamicAABBTree.cpp @@ -169,8 +169,10 @@ void DynamicAABBTree::removeObject(int32 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. -bool DynamicAABBTree::updateObject(int32 nodeID, const AABB& newAABB, const Vector3& displacement) { +/// frames. If the "forceReInsert" parameter is true, we force the existing AABB to take the size +/// of the "newAABB" parameter even if it is larger than "newAABB". This can be used to shrink the +/// AABB in the tree for instance if the corresponding collision shape has been shrunk. +bool DynamicAABBTree::updateObject(int32 nodeID, const AABB& newAABB, const Vector3& displacement, bool forceReinsert) { RP3D_PROFILE("DynamicAABBTree::updateObject()", mProfiler); @@ -179,7 +181,7 @@ bool DynamicAABBTree::updateObject(int32 nodeID, const AABB& newAABB, const Vect assert(mNodes[nodeID].height >= 0); // If the new AABB is still inside the fat AABB of the node - if (mNodes[nodeID].aabb.contains(newAABB)) { + if (!forceReinsert && mNodes[nodeID].aabb.contains(newAABB)) { return false; } @@ -194,22 +196,22 @@ bool DynamicAABBTree::updateObject(int32 nodeID, const AABB& newAABB, const Vect // Inflate the fat AABB in direction of the linear motion of the AABB if (displacement.x < decimal(0.0)) { - mNodes[nodeID].aabb.mMinCoordinates.x += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.x; + mNodes[nodeID].aabb.mMinCoordinates.x += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER * displacement.x; } else { - mNodes[nodeID].aabb.mMaxCoordinates.x += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.x; + mNodes[nodeID].aabb.mMaxCoordinates.x += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER * displacement.x; } if (displacement.y < decimal(0.0)) { - mNodes[nodeID].aabb.mMinCoordinates.y += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.y; + mNodes[nodeID].aabb.mMinCoordinates.y += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER * displacement.y; } else { - mNodes[nodeID].aabb.mMaxCoordinates.y += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.y; + mNodes[nodeID].aabb.mMaxCoordinates.y += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER * displacement.y; } if (displacement.z < decimal(0.0)) { - mNodes[nodeID].aabb.mMinCoordinates.z += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.z; + mNodes[nodeID].aabb.mMinCoordinates.z += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER * displacement.z; } else { - mNodes[nodeID].aabb.mMaxCoordinates.z += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER *displacement.z; + mNodes[nodeID].aabb.mMaxCoordinates.z += DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER * displacement.z; } assert(mNodes[nodeID].aabb.contains(newAABB)); diff --git a/src/collision/broadphase/DynamicAABBTree.h b/src/collision/broadphase/DynamicAABBTree.h index a2919ada..3f6415b5 100644 --- a/src/collision/broadphase/DynamicAABBTree.h +++ b/src/collision/broadphase/DynamicAABBTree.h @@ -225,7 +225,8 @@ class DynamicAABBTree { void removeObject(int32 nodeID); /// Update the dynamic tree after an object has moved. - bool updateObject(int32 nodeID, const AABB& newAABB, const Vector3& displacement); + bool updateObject(int32 nodeID, const AABB& newAABB, const Vector3& displacement, + bool forceReinsert = false); /// Return the fat AABB corresponding to a given node ID const AABB& getFatAABB(int32 nodeID) const; diff --git a/src/collision/shapes/BoxShape.cpp b/src/collision/shapes/BoxShape.cpp index 01b3c08c..7f4c410f 100644 --- a/src/collision/shapes/BoxShape.cpp +++ b/src/collision/shapes/BoxShape.cpp @@ -38,7 +38,7 @@ using namespace reactphysics3d; * @param halfExtents The vector with the three half-extents of the box */ BoxShape::BoxShape(const Vector3& halfExtents, MemoryAllocator& allocator) - : ConvexPolyhedronShape(CollisionShapeName::BOX), mHalfExtents(halfExtents), + : ConvexPolyhedronShape(CollisionShapeName::BOX, allocator), mHalfExtents(halfExtents), mHalfEdgeStructure(allocator, 6, 8, 24) { assert(halfExtents.x > decimal(0.0)); diff --git a/src/collision/shapes/BoxShape.h b/src/collision/shapes/BoxShape.h index ebec551c..ded03c63 100644 --- a/src/collision/shapes/BoxShape.h +++ b/src/collision/shapes/BoxShape.h @@ -149,6 +149,8 @@ inline Vector3 BoxShape::getHalfExtents() const { */ inline void BoxShape::setHalfExtents(const Vector3& halfExtents) { mHalfExtents = halfExtents; + + notifyColliderAboutChangedSize(); } // Return the local bounds of the shape in x, y and z directions diff --git a/src/collision/shapes/CapsuleShape.cpp b/src/collision/shapes/CapsuleShape.cpp index 7730c5fa..d7cf2189 100644 --- a/src/collision/shapes/CapsuleShape.cpp +++ b/src/collision/shapes/CapsuleShape.cpp @@ -37,8 +37,8 @@ using namespace reactphysics3d; * @param radius The radius of the capsule (in meters) * @param height The height of the capsule (in meters) */ -CapsuleShape::CapsuleShape(decimal radius, decimal height) - : ConvexShape(CollisionShapeName::CAPSULE, CollisionShapeType::CAPSULE, radius), mHalfHeight(height * decimal(0.5)) { +CapsuleShape::CapsuleShape(decimal radius, decimal height, MemoryAllocator& allocator) + : ConvexShape(CollisionShapeName::CAPSULE, CollisionShapeType::CAPSULE, allocator, radius), mHalfHeight(height * decimal(0.5)) { // TODO : Throw a library error here if radius or height is not larger than zero assert(radius > decimal(0.0)); assert(height > decimal(0.0)); diff --git a/src/collision/shapes/CapsuleShape.h b/src/collision/shapes/CapsuleShape.h index 37d87d55..4b37bdc5 100644 --- a/src/collision/shapes/CapsuleShape.h +++ b/src/collision/shapes/CapsuleShape.h @@ -58,7 +58,7 @@ class CapsuleShape : public ConvexShape { // -------------------- Methods -------------------- // /// Constructor - CapsuleShape(decimal radius, decimal height); + CapsuleShape(decimal radius, decimal height, MemoryAllocator& allocator); /// Return a local support point in a given direction without the object margin virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction) const override; @@ -137,6 +137,8 @@ inline void CapsuleShape::setRadius(decimal radius) { // TODO : Throw a library error here if radius is not larger than zero assert(radius > decimal(0.0)); mMargin = radius; + + notifyColliderAboutChangedSize(); } // Return the height of the capsule @@ -158,6 +160,8 @@ inline void CapsuleShape::setHeight(decimal height) { // TODO : Throw a library error here if radius is not larger than zero assert(height > decimal(0.0)); mHalfHeight = height * decimal(0.5); + + notifyColliderAboutChangedSize(); } // Return the number of bytes used by the collision shape diff --git a/src/collision/shapes/CollisionShape.cpp b/src/collision/shapes/CollisionShape.cpp index 0acfcc34..576e6ff4 100644 --- a/src/collision/shapes/CollisionShape.cpp +++ b/src/collision/shapes/CollisionShape.cpp @@ -27,13 +27,14 @@ #include "CollisionShape.h" #include "utils/Profiler.h" #include "body/CollisionBody.h" +#include "collision/Collider.h" // We want to use the ReactPhysics3D namespace using namespace reactphysics3d; // Constructor -CollisionShape::CollisionShape(CollisionShapeName name, CollisionShapeType type) - : mType(type), mName(name), mId(0) { +CollisionShape::CollisionShape(CollisionShapeName name, CollisionShapeType type, MemoryAllocator &allocator) + : mType(type), mName(name), mId(0), mColliders(allocator) { #ifdef IS_PROFILING_ACTIVE mProfiler = nullptr; @@ -90,3 +91,11 @@ void CollisionShape::computeAABB(AABB& aabb, const Transform& transform) const { aabb.setMin(resultMin); aabb.setMax(resultMax); } + +/// Notify all the assign colliders that the size of the collision shape has changed +void CollisionShape::notifyColliderAboutChangedSize() { + + for (uint i=0; i < mColliders.size(); i++) { + mColliders[i]->setHasCollisionShapeChangedSize(true); + } +} diff --git a/src/collision/shapes/CollisionShape.h b/src/collision/shapes/CollisionShape.h index ea0beb8c..853de58a 100644 --- a/src/collision/shapes/CollisionShape.h +++ b/src/collision/shapes/CollisionShape.h @@ -75,6 +75,9 @@ class CollisionShape { /// Unique identifier of the shape inside an overlapping pair uint32 mId; + /// List of the colliders associated with this shape + List mColliders; + #ifdef IS_PROFILING_ACTIVE /// Pointer to the profiler @@ -93,12 +96,21 @@ class CollisionShape { /// Return the number of bytes used by the collision shape virtual size_t getSizeInBytes() const = 0; + /// Assign a new collider to the collision shape + void addCollider(Collider* collider); + + /// Remove an assigned collider from the collision shape + void removeCollider(Collider* collider); + + /// Notify all the assign colliders that the size of the collision shape has changed + void notifyColliderAboutChangedSize(); + public : // -------------------- Methods -------------------- // /// Constructor - CollisionShape(CollisionShapeName name, CollisionShapeType type); + CollisionShape(CollisionShapeName name, CollisionShapeType type, MemoryAllocator& allocator); /// Destructor virtual ~CollisionShape() = default; @@ -146,7 +158,10 @@ class CollisionShape { // -------------------- Friendship -------------------- // friend class Collider; + friend class CollisionBody; + friend class RigidBody; friend class PhyscisWorld; + friend class BroadPhaseSystem; }; // Return the name of the collision shape @@ -170,6 +185,16 @@ inline uint32 CollisionShape::getId() const { return mId; } +// Assign a new collider to the collision shape +inline void CollisionShape::addCollider(Collider* collider) { + mColliders.add(collider); +} + +// Remove an assigned collider from the collision shape +inline void CollisionShape::removeCollider(Collider* collider) { + mColliders.remove(collider); +} + #ifdef IS_PROFILING_ACTIVE // Set the profiler diff --git a/src/collision/shapes/ConcaveMeshShape.cpp b/src/collision/shapes/ConcaveMeshShape.cpp index 0a332914..a5f873fc 100644 --- a/src/collision/shapes/ConcaveMeshShape.cpp +++ b/src/collision/shapes/ConcaveMeshShape.cpp @@ -35,7 +35,7 @@ using namespace reactphysics3d; // Constructor ConcaveMeshShape::ConcaveMeshShape(TriangleMesh* triangleMesh, MemoryAllocator& allocator, const Vector3& scaling) - : ConcaveShape(CollisionShapeName::TRIANGLE_MESH, scaling), mDynamicAABBTree(allocator) { + : ConcaveShape(CollisionShapeName::TRIANGLE_MESH, allocator, scaling), mDynamicAABBTree(allocator) { mTriangleMesh = triangleMesh; mRaycastTestType = TriangleRaycastSide::FRONT; diff --git a/src/collision/shapes/ConcaveShape.cpp b/src/collision/shapes/ConcaveShape.cpp index de8dae05..41f4069b 100644 --- a/src/collision/shapes/ConcaveShape.cpp +++ b/src/collision/shapes/ConcaveShape.cpp @@ -31,8 +31,8 @@ using namespace reactphysics3d; // Constructor -ConcaveShape::ConcaveShape(CollisionShapeName name, const Vector3& scaling) - : CollisionShape(name, CollisionShapeType::CONCAVE_SHAPE), mRaycastTestType(TriangleRaycastSide::FRONT), +ConcaveShape::ConcaveShape(CollisionShapeName name, MemoryAllocator& allocator, const Vector3& scaling) + : CollisionShape(name, CollisionShapeType::CONCAVE_SHAPE, allocator), mRaycastTestType(TriangleRaycastSide::FRONT), mScale(scaling) { } diff --git a/src/collision/shapes/ConcaveShape.h b/src/collision/shapes/ConcaveShape.h index bebf12f2..421a57ea 100644 --- a/src/collision/shapes/ConcaveShape.h +++ b/src/collision/shapes/ConcaveShape.h @@ -78,7 +78,7 @@ class ConcaveShape : public CollisionShape { // -------------------- Methods -------------------- // /// Constructor - ConcaveShape(CollisionShapeName name, const Vector3& scaling); + ConcaveShape(CollisionShapeName name, MemoryAllocator& allocator, const Vector3& scaling); /// Destructor virtual ~ConcaveShape() override = default; @@ -151,6 +151,8 @@ inline const Vector3& ConcaveShape::getScale() const { /// after changing the scale of a collision shape inline void ConcaveShape::setScale(const Vector3& scale) { mScale = scale; + + notifyColliderAboutChangedSize(); } } diff --git a/src/collision/shapes/ConvexMeshShape.cpp b/src/collision/shapes/ConvexMeshShape.cpp index 6cc1322f..df105a5e 100644 --- a/src/collision/shapes/ConvexMeshShape.cpp +++ b/src/collision/shapes/ConvexMeshShape.cpp @@ -39,8 +39,8 @@ using namespace reactphysics3d; * @param stride Stride between the beginning of two elements in the vertices array * @param margin Collision margin (in meters) around the collision shape */ -ConvexMeshShape::ConvexMeshShape(PolyhedronMesh* polyhedronMesh, const Vector3& scale) - : ConvexPolyhedronShape(CollisionShapeName::CONVEX_MESH), mPolyhedronMesh(polyhedronMesh), +ConvexMeshShape::ConvexMeshShape(PolyhedronMesh* polyhedronMesh, MemoryAllocator& allocator, const Vector3& scale) + : ConvexPolyhedronShape(CollisionShapeName::CONVEX_MESH, allocator), mPolyhedronMesh(polyhedronMesh), mMinBounds(0, 0, 0), mMaxBounds(0, 0, 0), mScale(scale) { // Recalculate the bounds of the mesh diff --git a/src/collision/shapes/ConvexMeshShape.h b/src/collision/shapes/ConvexMeshShape.h index bbcc8319..8313fe92 100644 --- a/src/collision/shapes/ConvexMeshShape.h +++ b/src/collision/shapes/ConvexMeshShape.h @@ -66,7 +66,7 @@ class ConvexMeshShape : public ConvexPolyhedronShape { // -------------------- Methods -------------------- // /// Constructor - ConvexMeshShape(PolyhedronMesh* polyhedronMesh, const Vector3& scale = Vector3(1,1,1)); + ConvexMeshShape(PolyhedronMesh* polyhedronMesh, MemoryAllocator& allocator, const Vector3& scale = Vector3(1,1,1)); /// Recompute the bounds of the mesh void recalculateBounds(); @@ -159,6 +159,7 @@ inline const Vector3& ConvexMeshShape::getScale() const { inline void ConvexMeshShape::setScale(const Vector3& scale) { mScale = scale; recalculateBounds(); + notifyColliderAboutChangedSize(); } // Return the local bounds of the shape in x, y and z directions diff --git a/src/collision/shapes/ConvexPolyhedronShape.cpp b/src/collision/shapes/ConvexPolyhedronShape.cpp index f4df61d8..53bb92c8 100644 --- a/src/collision/shapes/ConvexPolyhedronShape.cpp +++ b/src/collision/shapes/ConvexPolyhedronShape.cpp @@ -31,8 +31,8 @@ using namespace reactphysics3d; // Constructor -ConvexPolyhedronShape::ConvexPolyhedronShape(CollisionShapeName name) - : ConvexShape(name, CollisionShapeType::CONVEX_POLYHEDRON) { +ConvexPolyhedronShape::ConvexPolyhedronShape(CollisionShapeName name, MemoryAllocator& allocator) + : ConvexShape(name, CollisionShapeType::CONVEX_POLYHEDRON, allocator) { } diff --git a/src/collision/shapes/ConvexPolyhedronShape.h b/src/collision/shapes/ConvexPolyhedronShape.h index c316d4bf..2bd41437 100644 --- a/src/collision/shapes/ConvexPolyhedronShape.h +++ b/src/collision/shapes/ConvexPolyhedronShape.h @@ -47,7 +47,7 @@ class ConvexPolyhedronShape : public ConvexShape { // -------------------- Methods -------------------- // /// Constructor - ConvexPolyhedronShape(CollisionShapeName name); + ConvexPolyhedronShape(CollisionShapeName name, MemoryAllocator& allocator); /// Destructor virtual ~ConvexPolyhedronShape() override = default; diff --git a/src/collision/shapes/ConvexShape.cpp b/src/collision/shapes/ConvexShape.cpp index e93a1d06..2b9c3d81 100644 --- a/src/collision/shapes/ConvexShape.cpp +++ b/src/collision/shapes/ConvexShape.cpp @@ -31,8 +31,8 @@ using namespace reactphysics3d; // Constructor -ConvexShape::ConvexShape(CollisionShapeName name, CollisionShapeType type, decimal margin) - : CollisionShape(name, type), mMargin(margin) { +ConvexShape::ConvexShape(CollisionShapeName name, CollisionShapeType type, MemoryAllocator& allocator, decimal margin) + : CollisionShape(name, type, allocator), mMargin(margin) { } diff --git a/src/collision/shapes/ConvexShape.h b/src/collision/shapes/ConvexShape.h index 7e5484bf..49266389 100644 --- a/src/collision/shapes/ConvexShape.h +++ b/src/collision/shapes/ConvexShape.h @@ -59,7 +59,7 @@ class ConvexShape : public CollisionShape { // -------------------- Methods -------------------- // /// Constructor - ConvexShape(CollisionShapeName name, CollisionShapeType type, decimal margin = decimal(0.0)); + ConvexShape(CollisionShapeName name, CollisionShapeType type, MemoryAllocator& allocator, decimal margin = decimal(0.0)); /// Destructor virtual ~ConvexShape() override = default; diff --git a/src/collision/shapes/HeightFieldShape.cpp b/src/collision/shapes/HeightFieldShape.cpp index e038d6a1..f2ffa0b5 100644 --- a/src/collision/shapes/HeightFieldShape.cpp +++ b/src/collision/shapes/HeightFieldShape.cpp @@ -42,9 +42,9 @@ using namespace reactphysics3d; * @param integerHeightScale Scaling factor used to scale the height values (only when height values type is integer) */ HeightFieldShape::HeightFieldShape(int nbGridColumns, int nbGridRows, decimal minHeight, decimal maxHeight, - const void* heightFieldData, HeightDataType dataType, int upAxis, + const void* heightFieldData, HeightDataType dataType, MemoryAllocator& allocator, int upAxis, decimal integerHeightScale, const Vector3& scaling) - : ConcaveShape(CollisionShapeName::HEIGHTFIELD, scaling), mNbColumns(nbGridColumns), mNbRows(nbGridRows), + : ConcaveShape(CollisionShapeName::HEIGHTFIELD, allocator, scaling), mNbColumns(nbGridColumns), mNbRows(nbGridRows), mWidth(nbGridColumns - 1), mLength(nbGridRows - 1), mMinHeight(minHeight), mMaxHeight(maxHeight), mUpAxis(upAxis), mIntegerHeightScale(integerHeightScale), mHeightDataType(dataType) { diff --git a/src/collision/shapes/HeightFieldShape.h b/src/collision/shapes/HeightFieldShape.h index c2044349..d3092dd8 100644 --- a/src/collision/shapes/HeightFieldShape.h +++ b/src/collision/shapes/HeightFieldShape.h @@ -95,7 +95,7 @@ class HeightFieldShape : public ConcaveShape { /// Constructor HeightFieldShape(int nbGridColumns, int nbGridRows, decimal minHeight, decimal maxHeight, - const void* heightFieldData, HeightDataType dataType, + const void* heightFieldData, HeightDataType dataType, MemoryAllocator& allocator, int upAxis = 1, decimal integerHeightScale = 1.0f, const Vector3& scaling = Vector3(1,1,1)); diff --git a/src/collision/shapes/SphereShape.cpp b/src/collision/shapes/SphereShape.cpp index 613ded67..db3955bc 100644 --- a/src/collision/shapes/SphereShape.cpp +++ b/src/collision/shapes/SphereShape.cpp @@ -36,8 +36,8 @@ using namespace reactphysics3d; /** * @param radius Radius of the sphere */ -SphereShape::SphereShape(decimal radius) - : ConvexShape(CollisionShapeName::SPHERE, CollisionShapeType::SPHERE, radius) { +SphereShape::SphereShape(decimal radius, MemoryAllocator& allocator) + : ConvexShape(CollisionShapeName::SPHERE, CollisionShapeType::SPHERE, allocator, radius) { assert(radius > decimal(0.0)); } diff --git a/src/collision/shapes/SphereShape.h b/src/collision/shapes/SphereShape.h index 61f18eeb..a5d7bd95 100644 --- a/src/collision/shapes/SphereShape.h +++ b/src/collision/shapes/SphereShape.h @@ -51,7 +51,7 @@ class SphereShape : public ConvexShape { // -------------------- Methods -------------------- // /// Constructor - SphereShape(decimal radius); + SphereShape(decimal radius, MemoryAllocator& allocator); /// Return a local support point in a given direction without the object margin virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction) const override; @@ -121,6 +121,8 @@ inline decimal SphereShape::getRadius() const { inline void SphereShape::setRadius(decimal radius) { assert(radius > decimal(0.0)); mMargin = radius; + + notifyColliderAboutChangedSize(); } // Return true if the collision shape is a polyhedron diff --git a/src/collision/shapes/TriangleShape.cpp b/src/collision/shapes/TriangleShape.cpp index 4163057f..fda8c200 100644 --- a/src/collision/shapes/TriangleShape.cpp +++ b/src/collision/shapes/TriangleShape.cpp @@ -47,7 +47,7 @@ using namespace reactphysics3d; */ TriangleShape::TriangleShape(const Vector3* vertices, const Vector3* verticesNormals, uint shapeId, MemoryAllocator& allocator) - : ConvexPolyhedronShape(CollisionShapeName::TRIANGLE), mFaces{HalfEdgeStructure::Face(allocator), HalfEdgeStructure::Face(allocator)} { + : ConvexPolyhedronShape(CollisionShapeName::TRIANGLE, allocator), mFaces{HalfEdgeStructure::Face(allocator), HalfEdgeStructure::Face(allocator)} { mPoints[0] = vertices[0]; mPoints[1] = vertices[1]; diff --git a/src/components/ColliderComponents.cpp b/src/components/ColliderComponents.cpp index 24bff83f..7cd9de62 100644 --- a/src/components/ColliderComponents.cpp +++ b/src/components/ColliderComponents.cpp @@ -37,7 +37,7 @@ using namespace reactphysics3d; ColliderComponents::ColliderComponents(MemoryAllocator& allocator) :Components(allocator, sizeof(Entity) + sizeof(Entity) + sizeof(Collider*) + sizeof(int) + sizeof(Transform) + sizeof(CollisionShape*) + sizeof(decimal) + sizeof(unsigned short) + - sizeof(unsigned short) + sizeof(Transform) + sizeof(List)) { + sizeof(unsigned short) + sizeof(Transform) + sizeof(List) + sizeof(bool)) { // Allocate memory for the components data allocate(INIT_NB_ALLOCATED_COMPONENTS); @@ -67,6 +67,7 @@ void ColliderComponents::allocate(uint32 nbComponentsToAllocate) { unsigned short* newCollideWithMaskBits = reinterpret_cast(newCollisionCategoryBits + nbComponentsToAllocate); Transform* newLocalToWorldTransforms = reinterpret_cast(newCollideWithMaskBits + nbComponentsToAllocate); List* newOverlappingPairs = reinterpret_cast*>(newLocalToWorldTransforms + nbComponentsToAllocate); + bool* hasCollisionShapeChangedSize = reinterpret_cast(newOverlappingPairs + nbComponentsToAllocate); // If there was already components before if (mNbComponents > 0) { @@ -83,6 +84,7 @@ void ColliderComponents::allocate(uint32 nbComponentsToAllocate) { memcpy(newCollideWithMaskBits, mCollideWithMaskBits, mNbComponents * sizeof(unsigned short)); memcpy(newLocalToWorldTransforms, mLocalToWorldTransforms, mNbComponents * sizeof(Transform)); memcpy(newOverlappingPairs, mOverlappingPairs, mNbComponents * sizeof(List)); + memcpy(hasCollisionShapeChangedSize, mHasCollisionShapeChangedSize, mNbComponents * sizeof(bool)); // Deallocate previous memory mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * mComponentDataSize); @@ -101,6 +103,7 @@ void ColliderComponents::allocate(uint32 nbComponentsToAllocate) { mCollideWithMaskBits = newCollideWithMaskBits; mLocalToWorldTransforms = newLocalToWorldTransforms; mOverlappingPairs = newOverlappingPairs; + mHasCollisionShapeChangedSize = hasCollisionShapeChangedSize; mNbAllocatedComponents = nbComponentsToAllocate; } @@ -123,6 +126,7 @@ void ColliderComponents::addComponent(Entity colliderEntity, bool isSleeping, co new (mCollideWithMaskBits + index) unsigned short(component.collideWithMaskBits); new (mLocalToWorldTransforms + index) Transform(component.localToWorldTransform); new (mOverlappingPairs + index) List(mMemoryAllocator); + mHasCollisionShapeChangedSize[index] = false; // Map the entity with the new component lookup index mMapEntityToComponentIndex.add(Pair(colliderEntity, index)); @@ -150,6 +154,7 @@ void ColliderComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) new (mCollideWithMaskBits + destIndex) unsigned short(mCollideWithMaskBits[srcIndex]); new (mLocalToWorldTransforms + destIndex) Transform(mLocalToWorldTransforms[srcIndex]); new (mOverlappingPairs + destIndex) List(mOverlappingPairs[srcIndex]); + mHasCollisionShapeChangedSize[destIndex] = mHasCollisionShapeChangedSize[srcIndex]; // Destroy the source component destroyComponent(srcIndex); @@ -177,6 +182,7 @@ void ColliderComponents::swapComponents(uint32 index1, uint32 index2) { unsigned short collideWithMaskBits1 = mCollideWithMaskBits[index1]; Transform localToWorldTransform1 = mLocalToWorldTransforms[index1]; List overlappingPairs = mOverlappingPairs[index1]; + bool hasCollisionShapeChangedSize = mHasCollisionShapeChangedSize[index1]; // Destroy component 1 destroyComponent(index1); @@ -195,6 +201,7 @@ void ColliderComponents::swapComponents(uint32 index1, uint32 index2) { new (mCollideWithMaskBits + index2) unsigned short(collideWithMaskBits1); new (mLocalToWorldTransforms + index2) Transform(localToWorldTransform1); new (mOverlappingPairs + index2) List(overlappingPairs); + mHasCollisionShapeChangedSize[index2] = hasCollisionShapeChangedSize; // Update the entity to component index mapping mMapEntityToComponentIndex.add(Pair(colliderEntity1, index2)); diff --git a/src/components/ColliderComponents.h b/src/components/ColliderComponents.h index 0c16a6a3..e30a844b 100644 --- a/src/components/ColliderComponents.h +++ b/src/components/ColliderComponents.h @@ -95,6 +95,11 @@ class ColliderComponents : public Components { /// Array with the list of involved overlapping pairs for each collider List* mOverlappingPairs; + /// True if the size of the collision shape associated with the collider + /// has been changed by the user + bool* mHasCollisionShapeChangedSize; + + // -------------------- Methods -------------------- // /// Allocate memory for a given number of components @@ -191,6 +196,12 @@ class ColliderComponents : public Components { /// Return a reference to the list of overlapping pairs for a given collider List& getOverlappingPairs(Entity colliderEntity); + /// Return true if the size of collision shape of the collider has been changed by the user + bool getHasCollisionShapeChangedSize(Entity colliderEntity) const; + + /// Return true if the size of collision shape of the collider has been changed by the user + void setHasCollisionShapeChangedSize(Entity colliderEntity, bool hasCollisionShapeChangedSize); + // -------------------- Friendship -------------------- // friend class BroadPhaseSystem; @@ -319,6 +330,22 @@ inline List& ColliderComponents::getOverlappingPairs(Entity colliderEnti return mOverlappingPairs[mMapEntityToComponentIndex[colliderEntity]]; } +// Return true if the size of collision shape of the collider has been changed by the user +inline bool ColliderComponents::getHasCollisionShapeChangedSize(Entity colliderEntity) const { + + assert(mMapEntityToComponentIndex.containsKey(colliderEntity)); + + return mHasCollisionShapeChangedSize[mMapEntityToComponentIndex[colliderEntity]]; +} + +// Return true if the size of collision shape of the collider has been changed by the user +inline void ColliderComponents::setHasCollisionShapeChangedSize(Entity colliderEntity, bool hasCollisionShapeChangedSize) { + + assert(mMapEntityToComponentIndex.containsKey(colliderEntity)); + + mHasCollisionShapeChangedSize[mMapEntityToComponentIndex[colliderEntity]] = hasCollisionShapeChangedSize; +} + } #endif diff --git a/src/engine/PhysicsCommon.cpp b/src/engine/PhysicsCommon.cpp index 3f4a256e..e2d93fe6 100644 --- a/src/engine/PhysicsCommon.cpp +++ b/src/engine/PhysicsCommon.cpp @@ -159,7 +159,7 @@ void PhysicsCommon::destroyPhysicsWorld(PhysicsWorld* world) { // Create and return a sphere collision shape SphereShape* PhysicsCommon::createSphereShape(const decimal radius) { - SphereShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(SphereShape))) SphereShape(radius); + SphereShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(SphereShape))) SphereShape(radius, mMemoryManager.getHeapAllocator()); mSphereShapes.add(shape); return shape; @@ -202,7 +202,7 @@ void PhysicsCommon::destroyBoxShape(BoxShape* boxShape) { // Create and return a capsule shape CapsuleShape* PhysicsCommon::createCapsuleShape(decimal radius, decimal height) { - CapsuleShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(CapsuleShape))) CapsuleShape(radius, height); + CapsuleShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(CapsuleShape))) CapsuleShape(radius, height, mMemoryManager.getHeapAllocator()); mCapsuleShapes.add(shape); @@ -224,7 +224,7 @@ void PhysicsCommon::destroyCapsuleShape(CapsuleShape* capsuleShape) { // Create and return a convex mesh shape ConvexMeshShape* PhysicsCommon::createConvexMeshShape(PolyhedronMesh* polyhedronMesh, const Vector3& scaling) { - ConvexMeshShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(ConvexMeshShape))) ConvexMeshShape(polyhedronMesh, scaling); + ConvexMeshShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(ConvexMeshShape))) ConvexMeshShape(polyhedronMesh, mMemoryManager.getHeapAllocator(), scaling); mConvexMeshShapes.add(shape); @@ -249,7 +249,7 @@ HeightFieldShape* PhysicsCommon::createHeightFieldShape(int nbGridColumns, int n int upAxis, decimal integerHeightScale, const Vector3& scaling) { HeightFieldShape* shape = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool, sizeof(HeightFieldShape))) HeightFieldShape(nbGridColumns, nbGridRows, minHeight, maxHeight, - heightFieldData, dataType, upAxis, integerHeightScale, scaling); + heightFieldData, dataType, mMemoryManager.getHeapAllocator(), upAxis, integerHeightScale, scaling); mHeightFieldShapes.add(shape); diff --git a/src/systems/BroadPhaseSystem.cpp b/src/systems/BroadPhaseSystem.cpp index 2135080d..2e6cb7bd 100644 --- a/src/systems/BroadPhaseSystem.cpp +++ b/src/systems/BroadPhaseSystem.cpp @@ -89,7 +89,7 @@ void BroadPhaseSystem::addCollider(Collider* collider, const AABB& aabb) { // Add the collision shape into the array of bodies that have moved (or have been created) // during the last simulation step - addMovedCollisionShape(collider->getBroadPhaseId(), collider); + addMovedCollider(collider->getBroadPhaseId(), collider); } // Remove a collider from the broad-phase collision detection @@ -106,7 +106,7 @@ void BroadPhaseSystem::removeCollider(Collider* collider) { // Remove the collision shape into the array of shapes that have moved (or have been created) // during the last simulation step - removeMovedCollisionShape(broadPhaseID); + removeMovedCollider(broadPhaseID); } // Update the broad-phase state of a single collider @@ -133,12 +133,13 @@ void BroadPhaseSystem::updateColliders(decimal timeStep) { } // Notify the broad-phase that a collision shape has moved and need to be updated -void BroadPhaseSystem::updateColliderInternal(int32 broadPhaseId, Collider* collider, const AABB& aabb, const Vector3& displacement) { +void BroadPhaseSystem::updateColliderInternal(int32 broadPhaseId, Collider* collider, const AABB& aabb, const Vector3& displacement, + bool forceReInsert) { assert(broadPhaseId >= 0); // Update the dynamic AABB tree according to the movement of the collision shape - bool hasBeenReInserted = mDynamicAABBTree.updateObject(broadPhaseId, aabb, displacement); + bool hasBeenReInserted = mDynamicAABBTree.updateObject(broadPhaseId, aabb, displacement, forceReInsert); // If the collision shape has moved out of its fat AABB (and therefore has been reinserted // into the tree). @@ -146,7 +147,7 @@ void BroadPhaseSystem::updateColliderInternal(int32 broadPhaseId, Collider* coll // Add the collision shape into the array of shapes that have moved (or have been created) // during the last simulation step - addMovedCollisionShape(broadPhaseId, collider); + addMovedCollider(broadPhaseId, collider); } } @@ -189,16 +190,22 @@ void BroadPhaseSystem::updateCollidersComponents(uint32 startIndex, uint32 nbIte AABB aabb; mCollidersComponents.mCollisionShapes[i]->computeAABB(aabb, transform * mCollidersComponents.mLocalToBodyTransforms[i]); - // Update the broad-phase state for the collider - updateColliderInternal(broadPhaseId, mCollidersComponents.mColliders[i], aabb, displacement); + // If the size of the collision shape has been changed by the user, + // we need to reset the broad-phase AABB to its new size + const bool forceReInsert = mCollidersComponents.mHasCollisionShapeChangedSize[i]; + + // Update the broad-phase state of the collider + updateColliderInternal(broadPhaseId, mCollidersComponents.mColliders[i], aabb, displacement, forceReInsert); + + mCollidersComponents.mHasCollisionShapeChangedSize[i] = false; } } } -// Add a collision shape in the array of shapes that have moved in the last simulation step +// Add a collider in the array of colliders that have moved in the last simulation step // and that need to be tested again for broad-phase overlapping. -void BroadPhaseSystem::addMovedCollisionShape(int broadPhaseID, Collider* collider) { +void BroadPhaseSystem::addMovedCollider(int broadPhaseID, Collider* collider) { assert(broadPhaseID != -1); diff --git a/src/systems/BroadPhaseSystem.h b/src/systems/BroadPhaseSystem.h index 710527c9..b550b62f 100644 --- a/src/systems/BroadPhaseSystem.h +++ b/src/systems/BroadPhaseSystem.h @@ -140,7 +140,8 @@ class BroadPhaseSystem { // -------------------- Methods -------------------- // /// Notify the Dynamic AABB tree that a collider needs to be updated - void updateColliderInternal(int32 broadPhaseId, Collider* collider, const AABB& aabb, const Vector3& displacement); + void updateColliderInternal(int32 broadPhaseId, Collider* collider, const AABB& aabb, const Vector3& displacement, + bool forceReInsert); /// Update the broad-phase state of some colliders components void updateCollidersComponents(uint32 startIndex, uint32 nbItems, decimal timeStep); @@ -174,13 +175,13 @@ class BroadPhaseSystem { /// Update the broad-phase state of all the enabled colliders void updateColliders(decimal timeStep); - /// Add a collision shape in the array of shapes that have moved in the last simulation step + /// Add a collider in the array of colliders that have moved in the last simulation step /// and that need to be tested again for broad-phase overlapping. - void addMovedCollisionShape(int broadPhaseID, Collider* collider); + void addMovedCollider(int broadPhaseID, Collider* collider); - /// Remove a collision shape from the array of shapes that have moved in the last simulation + /// Remove a collider from the array of colliders that have moved in the last simulation /// step and that need to be tested again for broad-phase overlapping. - void removeMovedCollisionShape(int broadPhaseID); + void removeMovedCollider(int broadPhaseID); /// Compute all the overlapping pairs of collision shapes void computeOverlappingPairs(MemoryManager& memoryManager, List>& overlappingNodes); @@ -211,9 +212,9 @@ inline const AABB& BroadPhaseSystem::getFatAABB(int broadPhaseId) const { return mDynamicAABBTree.getFatAABB(broadPhaseId); } -// Remove a collision shape from the array of shapes that have moved in the last simulation step +// Remove a collider from the array of colliders that have moved in the last simulation step // and that need to be tested again for broad-phase overlapping. -inline void BroadPhaseSystem::removeMovedCollisionShape(int broadPhaseID) { +inline void BroadPhaseSystem::removeMovedCollider(int broadPhaseID) { // Remove the broad-phase ID from the set mMovedShapes.remove(broadPhaseID); diff --git a/src/systems/CollisionDetectionSystem.cpp b/src/systems/CollisionDetectionSystem.cpp index a9ba5357..9f872399 100644 --- a/src/systems/CollisionDetectionSystem.cpp +++ b/src/systems/CollisionDetectionSystem.cpp @@ -99,7 +99,7 @@ void CollisionDetectionSystem::computeBroadPhase() { RP3D_PROFILE("CollisionDetectionSystem::computeBroadPhase()", mProfiler); - // Ask the broad-phase to compute all the shapes overlapping the shapes that + // Ask the broad-phase to compute all the shapes overlapping with 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. List> overlappingNodes(mMemoryManager.getPoolAllocator(), 32); diff --git a/src/systems/CollisionDetectionSystem.h b/src/systems/CollisionDetectionSystem.h index 48d982c1..bb56d0d5 100644 --- a/src/systems/CollisionDetectionSystem.h +++ b/src/systems/CollisionDetectionSystem.h @@ -396,7 +396,7 @@ inline void CollisionDetectionSystem::removeNoCollisionPair(Entity body1Entity, inline void CollisionDetectionSystem::askForBroadPhaseCollisionCheck(Collider* shape) { if (shape->getBroadPhaseId() != -1) { - mBroadPhaseSystem.addMovedCollisionShape(shape->getBroadPhaseId(), shape); + mBroadPhaseSystem.addMovedCollider(shape->getBroadPhaseId(), shape); } }