Make possible to resize the collision shapes after their creation

This commit is contained in:
Daniel Chappuis 2020-02-11 21:56:42 +01:00
parent 9d776e32dc
commit 7477460e4f
33 changed files with 174 additions and 77 deletions

View File

@ -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());

View File

@ -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

View File

@ -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

View File

@ -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;
};

View File

@ -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));

View File

@ -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;

View File

@ -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));

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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);
}
}

View File

@ -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<Collider*> 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

View File

@ -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;

View File

@ -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) {
}

View File

@ -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();
}
}

View File

@ -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

View File

@ -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

View File

@ -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) {
}

View File

@ -47,7 +47,7 @@ class ConvexPolyhedronShape : public ConvexShape {
// -------------------- Methods -------------------- //
/// Constructor
ConvexPolyhedronShape(CollisionShapeName name);
ConvexPolyhedronShape(CollisionShapeName name, MemoryAllocator& allocator);
/// Destructor
virtual ~ConvexPolyhedronShape() override = default;

View File

@ -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) {
}

View File

@ -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;

View File

@ -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) {

View File

@ -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));

View File

@ -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));
}

View File

@ -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

View File

@ -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];

View File

@ -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<uint64>)) {
sizeof(unsigned short) + sizeof(Transform) + sizeof(List<uint64>) + 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<unsigned short*>(newCollisionCategoryBits + nbComponentsToAllocate);
Transform* newLocalToWorldTransforms = reinterpret_cast<Transform*>(newCollideWithMaskBits + nbComponentsToAllocate);
List<uint64>* newOverlappingPairs = reinterpret_cast<List<uint64>*>(newLocalToWorldTransforms + nbComponentsToAllocate);
bool* hasCollisionShapeChangedSize = reinterpret_cast<bool*>(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<uint64>));
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<uint64>(mMemoryAllocator);
mHasCollisionShapeChangedSize[index] = false;
// Map the entity with the new component lookup index
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(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<uint64>(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<uint64> 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<uint64>(overlappingPairs);
mHasCollisionShapeChangedSize[index2] = hasCollisionShapeChangedSize;
// Update the entity to component index mapping
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(colliderEntity1, index2));

View File

@ -95,6 +95,11 @@ class ColliderComponents : public Components {
/// Array with the list of involved overlapping pairs for each collider
List<uint64>* 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<uint64>& 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<uint64>& 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

View File

@ -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);

View File

@ -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);

View File

@ -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<Pair<int32, int32>>& 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);

View File

@ -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<Pair<int32, int32>> overlappingNodes(mMemoryManager.getPoolAllocator(), 32);

View File

@ -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);
}
}