Replacing ProxyShape data by corresponding component data

This commit is contained in:
Daniel Chappuis 2019-01-12 18:56:55 +01:00
parent 449beaf7a6
commit 7d8f043cdb
9 changed files with 125 additions and 126 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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