The proxy-shapes are now entities
This commit is contained in:
parent
4b919fb4fc
commit
d02b25d32a
|
@ -22,6 +22,9 @@
|
||||||
- The CollisionWorld::setCollisionDispatch() method has been removed. In order to use a custom collision
|
- The CollisionWorld::setCollisionDispatch() method has been removed. In order to use a custom collision
|
||||||
algorithm, you must not get the collision dispatch object with the
|
algorithm, you must not get the collision dispatch object with the
|
||||||
CollisionWorld::getCollisionDispatch() method and set a collision algorithm to this object.
|
CollisionWorld::getCollisionDispatch() method and set a collision algorithm to this object.
|
||||||
|
- The methods CollisionBody::getProxyShapesList() has been remove. You can now use the
|
||||||
|
CollisionBody::getNbProxyShapes() method to know the number of proxy-shapes of a body and the
|
||||||
|
CollisionBody::getProxyShape(uint proxyShapeIndex) method to get a given proxy-shape of the body.
|
||||||
|
|
||||||
## Version 0.7.0 (May 1, 2018)
|
## Version 0.7.0 (May 1, 2018)
|
||||||
|
|
||||||
|
|
|
@ -140,6 +140,7 @@ SET (REACTPHYSICS3D_HEADERS
|
||||||
"src/engine/Timer.h"
|
"src/engine/Timer.h"
|
||||||
"src/systems/BroadPhaseSystem.h"
|
"src/systems/BroadPhaseSystem.h"
|
||||||
"src/components/Components.h"
|
"src/components/Components.h"
|
||||||
|
"src/components/BodyComponents.h"
|
||||||
"src/components/TransformComponents.h"
|
"src/components/TransformComponents.h"
|
||||||
"src/components/ProxyShapesComponents.h"
|
"src/components/ProxyShapesComponents.h"
|
||||||
"src/collision/CollisionCallback.h"
|
"src/collision/CollisionCallback.h"
|
||||||
|
@ -230,6 +231,7 @@ SET (REACTPHYSICS3D_SOURCES
|
||||||
"src/engine/Entity.cpp"
|
"src/engine/Entity.cpp"
|
||||||
"src/engine/EntityManager.cpp"
|
"src/engine/EntityManager.cpp"
|
||||||
"src/systems/BroadPhaseSystem.cpp"
|
"src/systems/BroadPhaseSystem.cpp"
|
||||||
|
"src/components/BodyComponents.cpp"
|
||||||
"src/components/TransformComponents.cpp"
|
"src/components/TransformComponents.cpp"
|
||||||
"src/components/ProxyShapesComponents.cpp"
|
"src/components/ProxyShapesComponents.cpp"
|
||||||
"src/collision/CollisionCallback.cpp"
|
"src/collision/CollisionCallback.cpp"
|
||||||
|
|
|
@ -72,19 +72,24 @@ CollisionBody::~CollisionBody() {
|
||||||
ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape,
|
ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape,
|
||||||
const Transform& transform) {
|
const Transform& transform) {
|
||||||
|
|
||||||
|
// Create a new entity for the proxy-shape
|
||||||
|
Entity proxyShapeEntity = mWorld.mEntityManager.createEntity();
|
||||||
|
|
||||||
// Create a new proxy collision shape to attach the collision shape to the body
|
// Create a new proxy collision shape to attach the collision shape to the body
|
||||||
ProxyShape* proxyShape = new (mWorld.mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
|
ProxyShape* proxyShape = new (mWorld.mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
|
||||||
sizeof(ProxyShape))) ProxyShape(this, mWorld.mMemoryManager);
|
sizeof(ProxyShape))) ProxyShape(proxyShapeEntity, this, mWorld.mMemoryManager);
|
||||||
|
|
||||||
// Add the proxy-shape component to the entity of the body
|
// Add the proxy-shape component to the entity of the body
|
||||||
Vector3 localBoundsMin;
|
Vector3 localBoundsMin;
|
||||||
Vector3 localBoundsMax;
|
Vector3 localBoundsMax;
|
||||||
// TODO : Maybe this method can directly returns an AABB
|
// TODO : Maybe this method can directly returns an AABB
|
||||||
collisionShape->getLocalBounds(localBoundsMin, localBoundsMax);
|
collisionShape->getLocalBounds(localBoundsMin, localBoundsMax);
|
||||||
ProxyShapesComponents::ProxyShapeComponent proxyShapeComponent(proxyShape, -1,
|
ProxyShapesComponents::ProxyShapeComponent proxyShapeComponent(mEntity, proxyShape, -1,
|
||||||
AABB(localBoundsMin, localBoundsMax),
|
AABB(localBoundsMin, localBoundsMax),
|
||||||
transform, collisionShape, decimal(1), 0x0001, 0xFFFF);
|
transform, collisionShape, decimal(1), 0x0001, 0xFFFF);
|
||||||
mWorld.mProxyShapesComponents.addComponent(mEntity, mIsSleeping, proxyShapeComponent);
|
mWorld.mProxyShapesComponents.addComponent(proxyShapeEntity, mIsSleeping, proxyShapeComponent);
|
||||||
|
|
||||||
|
mWorld.mBodyComponents.addProxyShapeToBody(mEntity, proxyShapeEntity);
|
||||||
|
|
||||||
#ifdef IS_PROFILING_ACTIVE
|
#ifdef IS_PROFILING_ACTIVE
|
||||||
|
|
||||||
|
@ -118,22 +123,38 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape,
|
||||||
return proxyShape;
|
return proxyShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the linked list of proxy shapes of that body
|
// Return the number of proxy-shapes associated with this body
|
||||||
/**
|
/**
|
||||||
* @return The pointer of the first proxy shape of the linked-list of all the
|
* @return The number of proxy-shapes associated with this body
|
||||||
* proxy shapes of the body
|
|
||||||
*/
|
*/
|
||||||
ProxyShape* CollisionBody::getProxyShapesList() {
|
uint CollisionBody::getNbProxyShapes() const {
|
||||||
return mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity);
|
return static_cast<uint>(mWorld.mBodyComponents.getProxyShapes(mEntity).size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the linked list of proxy shapes of that body
|
// Return a const pointer to a given proxy-shape of the body
|
||||||
/**
|
/**
|
||||||
* @return The pointer of the first proxy shape of the linked-list of all the
|
* @return The const pointer of a given proxy-shape of the body
|
||||||
* proxy shapes of the body
|
|
||||||
*/
|
*/
|
||||||
const ProxyShape* CollisionBody::getProxyShapesList() const {
|
const ProxyShape* CollisionBody::getProxyShape(uint proxyShapeIndex) const {
|
||||||
return mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity);
|
|
||||||
|
assert(proxyShapeIndex < getNbProxyShapes());
|
||||||
|
|
||||||
|
Entity proxyShapeEntity = mWorld.mBodyComponents.getProxyShapes(mEntity)[proxyShapeIndex];
|
||||||
|
|
||||||
|
return mWorld.mProxyShapesComponents.getProxyShape(proxyShapeEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a pointer to a given proxy-shape of the body
|
||||||
|
/**
|
||||||
|
* @return The pointer of a given proxy-shape of the body
|
||||||
|
*/
|
||||||
|
ProxyShape* CollisionBody::getProxyShape(uint proxyShapeIndex) {
|
||||||
|
|
||||||
|
assert(proxyShapeIndex < getNbProxyShapes());
|
||||||
|
|
||||||
|
Entity proxyShapeEntity = mWorld.mBodyComponents.getProxyShapes(mEntity)[proxyShapeIndex];
|
||||||
|
|
||||||
|
return mWorld.mProxyShapesComponents.getProxyShape(proxyShapeEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a collision shape from the body
|
// Remove a collision shape from the body
|
||||||
|
@ -148,14 +169,16 @@ void CollisionBody::removeCollisionShape(ProxyShape* proxyShape) {
|
||||||
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
|
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
|
||||||
"Body " + std::to_string(mID) + ": Proxy shape " + std::to_string(proxyShape->getBroadPhaseId()) + " removed from body");
|
"Body " + std::to_string(mID) + ": Proxy shape " + std::to_string(proxyShape->getBroadPhaseId()) + " removed from body");
|
||||||
|
|
||||||
// Remove the proxy-shape component
|
|
||||||
mWorld.mProxyShapesComponents.removeComponent(proxyShape);
|
|
||||||
|
|
||||||
// Remove the proxy-shape from the broad-phase
|
// Remove the proxy-shape from the broad-phase
|
||||||
if (mIsActive && proxyShape->getBroadPhaseId() != -1) {
|
if (proxyShape->getBroadPhaseId() != -1) {
|
||||||
mWorld.mCollisionDetection.removeProxyCollisionShape(proxyShape);
|
mWorld.mCollisionDetection.removeProxyCollisionShape(proxyShape);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mWorld.mBodyComponents.removeProxyShapeFromBody(mEntity, proxyShape->getEntity());
|
||||||
|
|
||||||
|
// Remove the proxy-shape component
|
||||||
|
mWorld.mProxyShapesComponents.removeComponent(proxyShape->getEntity());
|
||||||
|
|
||||||
// Call the constructor of the proxy-shape
|
// Call the constructor of the proxy-shape
|
||||||
proxyShape->~ProxyShape();
|
proxyShape->~ProxyShape();
|
||||||
|
|
||||||
|
@ -166,27 +189,13 @@ void CollisionBody::removeCollisionShape(ProxyShape* proxyShape) {
|
||||||
// Remove all the collision shapes
|
// Remove all the collision shapes
|
||||||
void CollisionBody::removeAllCollisionShapes() {
|
void CollisionBody::removeAllCollisionShapes() {
|
||||||
|
|
||||||
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity);
|
// Look for the proxy shape that contains the collision shape in parameter.
|
||||||
|
// Note that we need to copy the list of proxy shapes entities because we are deleting them in a loop.
|
||||||
|
const List<Entity> proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
|
||||||
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
// Look for the proxy shape that contains the collision shape in parameter
|
removeCollisionShape(mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]));
|
||||||
while(proxyShape != nullptr) {
|
|
||||||
|
|
||||||
if (mIsActive && proxyShape->getBroadPhaseId() != -1) {
|
|
||||||
|
|
||||||
mWorld.mCollisionDetection.removeProxyCollisionShape(proxyShape);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy the proxy-shape
|
|
||||||
proxyShape->~ProxyShape();
|
|
||||||
|
|
||||||
mWorld.mMemoryManager.release(MemoryManager::AllocationType::Pool, proxyShape, sizeof(ProxyShape));
|
|
||||||
|
|
||||||
// Get the next element in the list
|
|
||||||
proxyShape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(proxyShape);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove all the proxy-shapes components
|
|
||||||
mWorld.mProxyShapesComponents.removeComponents(mEntity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the contact manifold lists
|
// Reset the contact manifold lists
|
||||||
|
@ -222,10 +231,13 @@ const Transform& CollisionBody::getTransform() const {
|
||||||
void CollisionBody::updateBroadPhaseState() const {
|
void CollisionBody::updateBroadPhaseState() const {
|
||||||
|
|
||||||
// For all the proxy collision shapes of the body
|
// For all the proxy collision shapes of the body
|
||||||
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) {
|
const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
|
||||||
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
|
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
|
||||||
// Update the proxy
|
// Update the proxy
|
||||||
updateProxyShapeInBroadPhase(shape);
|
updateProxyShapeInBroadPhase(proxyShape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,25 +274,31 @@ void CollisionBody::setIsActive(bool isActive) {
|
||||||
const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
|
const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
|
||||||
|
|
||||||
// For each proxy shape of the body
|
// For each proxy shape of the body
|
||||||
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) {
|
const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
|
||||||
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
|
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
|
||||||
// Compute the world-space AABB of the new collision shape
|
// Compute the world-space AABB of the new collision shape
|
||||||
AABB aabb;
|
AABB aabb;
|
||||||
shape->getCollisionShape()->computeAABB(aabb, transform * mWorld.mProxyShapesComponents.getLocalToBodyTransform(shape));
|
proxyShape->getCollisionShape()->computeAABB(aabb, transform * mWorld.mProxyShapesComponents.getLocalToBodyTransform(proxyShape->getEntity()));
|
||||||
|
|
||||||
// Add the proxy shape to the collision detection
|
// Add the proxy shape to the collision detection
|
||||||
mWorld.mCollisionDetection.addProxyCollisionShape(shape, aabb);
|
mWorld.mCollisionDetection.addProxyCollisionShape(proxyShape, aabb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // If we have to deactivate the body
|
else { // If we have to deactivate the body
|
||||||
|
|
||||||
// For each proxy shape of the body
|
// For each proxy shape of the body
|
||||||
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) {
|
const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
|
||||||
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
if (shape->getBroadPhaseId() != -1) {
|
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
|
||||||
|
if (proxyShape->getBroadPhaseId() != -1) {
|
||||||
|
|
||||||
// Remove the proxy shape from the collision detection
|
// Remove the proxy shape from the collision detection
|
||||||
mWorld.mCollisionDetection.removeProxyCollisionShape(shape);
|
mWorld.mCollisionDetection.removeProxyCollisionShape(proxyShape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,9 +316,12 @@ void CollisionBody::setIsActive(bool isActive) {
|
||||||
void CollisionBody::askForBroadPhaseCollisionCheck() const {
|
void CollisionBody::askForBroadPhaseCollisionCheck() const {
|
||||||
|
|
||||||
// For all the proxy collision shapes of the body
|
// For all the proxy collision shapes of the body
|
||||||
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) {
|
const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
|
||||||
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
mWorld.mCollisionDetection.askForBroadPhaseCollisionCheck(shape);
|
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
|
||||||
|
mWorld.mCollisionDetection.askForBroadPhaseCollisionCheck(proxyShape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,10 +354,13 @@ int CollisionBody::resetIsAlreadyInIslandAndCountManifolds() {
|
||||||
bool CollisionBody::testPointInside(const Vector3& worldPoint) const {
|
bool CollisionBody::testPointInside(const Vector3& worldPoint) const {
|
||||||
|
|
||||||
// For each collision shape of the body
|
// For each collision shape of the body
|
||||||
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) {
|
const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
|
||||||
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
|
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
|
||||||
// Test if the point is inside the collision shape
|
// Test if the point is inside the collision shape
|
||||||
if (shape->testPointInside(worldPoint)) return true;
|
if (proxyShape->testPointInside(worldPoint)) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -359,10 +383,13 @@ bool CollisionBody::raycast(const Ray& ray, RaycastInfo& raycastInfo) {
|
||||||
Ray rayTemp(ray);
|
Ray rayTemp(ray);
|
||||||
|
|
||||||
// For each collision shape of the body
|
// For each collision shape of the body
|
||||||
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) {
|
const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
|
||||||
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
|
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
|
||||||
// Test if the ray hits the collision shape
|
// Test if the ray hits the collision shape
|
||||||
if (shape->raycast(rayTemp, raycastInfo)) {
|
if (proxyShape->raycast(rayTemp, raycastInfo)) {
|
||||||
rayTemp.maxFraction = raycastInfo.hitFraction;
|
rayTemp.maxFraction = raycastInfo.hitFraction;
|
||||||
isHit = true;
|
isHit = true;
|
||||||
}
|
}
|
||||||
|
@ -379,21 +406,24 @@ AABB CollisionBody::getAABB() const {
|
||||||
|
|
||||||
AABB bodyAABB;
|
AABB bodyAABB;
|
||||||
|
|
||||||
if (mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity) == nullptr) return bodyAABB;
|
const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
|
||||||
|
if (proxyShapesEntities.size() == 0) return bodyAABB;
|
||||||
|
|
||||||
// TODO : Make sure we compute this in a system
|
// TODO : Make sure we compute this in a system
|
||||||
|
|
||||||
const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
|
const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
|
||||||
|
|
||||||
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity);
|
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[0]);
|
||||||
proxyShape->getCollisionShape()->computeAABB(bodyAABB, transform * proxyShape->getLocalToBodyTransform());
|
proxyShape->getCollisionShape()->computeAABB(bodyAABB, transform * proxyShape->getLocalToBodyTransform());
|
||||||
|
|
||||||
// For each proxy shape of the body
|
// For each proxy shape of the body
|
||||||
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) {
|
for (uint i=1; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
|
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
|
||||||
// Compute the world-space AABB of the collision shape
|
// Compute the world-space AABB of the collision shape
|
||||||
AABB aabb;
|
AABB aabb;
|
||||||
shape->getCollisionShape()->computeAABB(aabb, transform * shape->getLocalToBodyTransform());
|
proxyShape->getCollisionShape()->computeAABB(aabb, transform * proxyShape->getLocalToBodyTransform());
|
||||||
|
|
||||||
// Merge the proxy shape AABB with the current body AABB
|
// Merge the proxy shape AABB with the current body AABB
|
||||||
bodyAABB.mergeWithAABB(aabb);
|
bodyAABB.mergeWithAABB(aabb);
|
||||||
|
|
|
@ -166,12 +166,18 @@ class CollisionBody : public Body {
|
||||||
/// Compute and return the AABB of the body by merging all proxy shapes AABBs
|
/// Compute and return the AABB of the body by merging all proxy shapes AABBs
|
||||||
AABB getAABB() const;
|
AABB getAABB() const;
|
||||||
|
|
||||||
/// Return the linked list of proxy shapes of that body
|
/// Return a const pointer to a given proxy-shape of the body
|
||||||
ProxyShape* getProxyShapesList();
|
const ProxyShape* getProxyShape(uint proxyShapeIndex) const;
|
||||||
|
|
||||||
|
/// Return a pointer to a given proxy-shape of the body
|
||||||
|
ProxyShape* getProxyShape(uint proxyShapeIndex);
|
||||||
|
|
||||||
/// Return the linked list of proxy shapes of that body
|
/// Return the linked list of proxy shapes of that body
|
||||||
const ProxyShape* getProxyShapesList() const;
|
const ProxyShape* getProxyShapesList() const;
|
||||||
|
|
||||||
|
/// Return the number of proxy-shapes associated with this body
|
||||||
|
uint getNbProxyShapes() const;
|
||||||
|
|
||||||
/// Return the world-space coordinates of a point given the local-space coordinates of the body
|
/// Return the world-space coordinates of a point given the local-space coordinates of the body
|
||||||
Vector3 getWorldPoint(const Vector3& localPoint) const;
|
Vector3 getWorldPoint(const Vector3& localPoint) const;
|
||||||
|
|
||||||
|
|
|
@ -281,9 +281,12 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape,
|
||||||
const Transform& transform,
|
const Transform& transform,
|
||||||
decimal mass) {
|
decimal mass) {
|
||||||
|
|
||||||
|
// Create a new entity for the proxy-shape
|
||||||
|
Entity proxyShapeEntity = mWorld.mEntityManager.createEntity();
|
||||||
|
|
||||||
// Create a new proxy collision shape to attach the collision shape to the body
|
// Create a new proxy collision shape to attach the collision shape to the body
|
||||||
ProxyShape* proxyShape = new (mWorld.mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
|
ProxyShape* proxyShape = new (mWorld.mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
|
||||||
sizeof(ProxyShape))) ProxyShape(this, mWorld.mMemoryManager);
|
sizeof(ProxyShape))) ProxyShape(proxyShapeEntity, this, mWorld.mMemoryManager);
|
||||||
|
|
||||||
// Add the proxy-shape component to the entity of the body
|
// Add the proxy-shape component to the entity of the body
|
||||||
Vector3 localBoundsMin;
|
Vector3 localBoundsMin;
|
||||||
|
@ -291,10 +294,12 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape,
|
||||||
// TODO : Maybe this method can directly returns an AABB
|
// TODO : Maybe this method can directly returns an AABB
|
||||||
collisionShape->getLocalBounds(localBoundsMin, localBoundsMax);
|
collisionShape->getLocalBounds(localBoundsMin, localBoundsMax);
|
||||||
|
|
||||||
ProxyShapesComponents::ProxyShapeComponent proxyShapeComponent(proxyShape, -1,
|
ProxyShapesComponents::ProxyShapeComponent proxyShapeComponent(mEntity, proxyShape, -1,
|
||||||
AABB(localBoundsMin, localBoundsMax),
|
AABB(localBoundsMin, localBoundsMax),
|
||||||
transform, collisionShape, mass, 0x0001, 0xFFFF);
|
transform, collisionShape, mass, 0x0001, 0xFFFF);
|
||||||
mWorld.mProxyShapesComponents.addComponent(mEntity, mIsSleeping, proxyShapeComponent);
|
mWorld.mProxyShapesComponents.addComponent(proxyShapeEntity, mIsSleeping, proxyShapeComponent);
|
||||||
|
|
||||||
|
mWorld.mBodyComponents.addProxyShapeToBody(mEntity, proxyShapeEntity);
|
||||||
|
|
||||||
#ifdef IS_PROFILING_ACTIVE
|
#ifdef IS_PROFILING_ACTIVE
|
||||||
|
|
||||||
|
@ -500,11 +505,13 @@ void RigidBody::recomputeMassInformation() {
|
||||||
assert(mType == BodyType::DYNAMIC);
|
assert(mType == BodyType::DYNAMIC);
|
||||||
|
|
||||||
// Compute the total mass of the body
|
// Compute the total mass of the body
|
||||||
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) {
|
const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
|
||||||
mInitMass += shape->getMass();
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
mInitMass += proxyShape->getMass();
|
||||||
|
|
||||||
if (!mIsCenterOfMassSetByUser) {
|
if (!mIsCenterOfMassSetByUser) {
|
||||||
mCenterOfMassLocal += shape->getLocalToBodyTransform().getPosition() * shape->getMass();
|
mCenterOfMassLocal += proxyShape->getLocalToBodyTransform().getPosition() * proxyShape->getMass();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,14 +535,17 @@ void RigidBody::recomputeMassInformation() {
|
||||||
if (!mIsInertiaTensorSetByUser) {
|
if (!mIsInertiaTensorSetByUser) {
|
||||||
|
|
||||||
// Compute the inertia tensor using all the collision shapes
|
// Compute the inertia tensor using all the collision shapes
|
||||||
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) {
|
const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
|
||||||
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
|
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
|
||||||
// Get the inertia tensor of the collision shape in its local-space
|
// Get the inertia tensor of the collision shape in its local-space
|
||||||
Matrix3x3 inertiaTensor;
|
Matrix3x3 inertiaTensor;
|
||||||
shape->getCollisionShape()->computeLocalInertiaTensor(inertiaTensor, shape->getMass());
|
proxyShape->getCollisionShape()->computeLocalInertiaTensor(inertiaTensor, proxyShape->getMass());
|
||||||
|
|
||||||
// Convert the collision shape inertia tensor into the local-space of the body
|
// Convert the collision shape inertia tensor into the local-space of the body
|
||||||
const Transform& shapeTransform = shape->getLocalToBodyTransform();
|
const Transform& shapeTransform = proxyShape->getLocalToBodyTransform();
|
||||||
Matrix3x3 rotationMatrix = shapeTransform.getOrientation().getMatrix();
|
Matrix3x3 rotationMatrix = shapeTransform.getOrientation().getMatrix();
|
||||||
inertiaTensor = rotationMatrix * inertiaTensor * rotationMatrix.getTranspose();
|
inertiaTensor = rotationMatrix * inertiaTensor * rotationMatrix.getTranspose();
|
||||||
|
|
||||||
|
@ -550,7 +560,7 @@ void RigidBody::recomputeMassInformation() {
|
||||||
offsetMatrix[0] += offset * (-offset.x);
|
offsetMatrix[0] += offset * (-offset.x);
|
||||||
offsetMatrix[1] += offset * (-offset.y);
|
offsetMatrix[1] += offset * (-offset.y);
|
||||||
offsetMatrix[2] += offset * (-offset.z);
|
offsetMatrix[2] += offset * (-offset.z);
|
||||||
offsetMatrix *= shape->getMass();
|
offsetMatrix *= proxyShape->getMass();
|
||||||
|
|
||||||
inertiaTensorLocal += inertiaTensor + offsetMatrix;
|
inertiaTensorLocal += inertiaTensor + offsetMatrix;
|
||||||
}
|
}
|
||||||
|
@ -579,14 +589,20 @@ void RigidBody::updateBroadPhaseState() const {
|
||||||
const Vector3 displacement = world.mTimeStep * mLinearVelocity;
|
const Vector3 displacement = world.mTimeStep * mLinearVelocity;
|
||||||
|
|
||||||
// For all the proxy collision shapes of the body
|
// For all the proxy collision shapes of the body
|
||||||
for (ProxyShape* shape = mWorld.mProxyShapesComponents.getFirstProxyShapeOfBody(mEntity); shape != nullptr; shape = mWorld.mProxyShapesComponents.getNextProxyShapeOfBody(shape)) {
|
const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
|
||||||
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
|
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
|
||||||
|
if (proxyShape->getBroadPhaseId() != -1) {
|
||||||
|
|
||||||
// Recompute the world-space AABB of the collision shape
|
// Recompute the world-space AABB of the collision shape
|
||||||
AABB aabb;
|
AABB aabb;
|
||||||
shape->getCollisionShape()->computeAABB(aabb, transform * shape->getLocalToBodyTransform());
|
proxyShape->getCollisionShape()->computeAABB(aabb, transform * proxyShape->getLocalToBodyTransform());
|
||||||
|
|
||||||
// Update the broad-phase state for the proxy collision shape
|
// Update the broad-phase state for the proxy collision shape
|
||||||
mWorld.mCollisionDetection.updateProxyCollisionShape(shape, aabb, displacement);
|
mWorld.mCollisionDetection.updateProxyCollisionShape(proxyShape, aabb, displacement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,12 +614,12 @@ void RigidBody::setProfiler(Profiler* profiler) {
|
||||||
CollisionBody::setProfiler(profiler);
|
CollisionBody::setProfiler(profiler);
|
||||||
|
|
||||||
// Set the profiler for each proxy shape
|
// Set the profiler for each proxy shape
|
||||||
ProxyShape* proxyShape = getProxyShapesList();
|
const List<Entity>& proxyShapesEntities = mWorld.mBodyComponents.getProxyShapes(mEntity);
|
||||||
while (proxyShape != nullptr) {
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
|
ProxyShape* proxyShape = mWorld.mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
|
||||||
proxyShape->setProfiler(profiler);
|
proxyShape->setProfiler(profiler);
|
||||||
|
|
||||||
proxyShape = proxyShape->getNext();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -608,14 +608,18 @@ bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2)
|
||||||
NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator());
|
NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator());
|
||||||
|
|
||||||
// For each proxy shape proxy shape of the first body
|
// For each proxy shape proxy shape of the first body
|
||||||
ProxyShape* body1ProxyShape = body1->getProxyShapesList();
|
const List<Entity>& body1ProxyShapesEntities = mWorld->mBodyComponents.getProxyShapes(body1->getEntity());
|
||||||
while (body1ProxyShape != nullptr) {
|
const List<Entity>& body2ProxyShapesEntities = mWorld->mBodyComponents.getProxyShapes(body2->getEntity());
|
||||||
|
for (uint i=0; i < body1ProxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
|
ProxyShape* body1ProxyShape = mWorld->mProxyShapesComponents.getProxyShape(body1ProxyShapesEntities[i]);
|
||||||
|
|
||||||
AABB aabb1 = body1ProxyShape->getWorldAABB();
|
AABB aabb1 = body1ProxyShape->getWorldAABB();
|
||||||
|
|
||||||
// For each proxy shape of the second body
|
// For each proxy shape of the second body
|
||||||
ProxyShape* body2ProxyShape = body2->getProxyShapesList();
|
for (uint j=0; j < body2ProxyShapesEntities.size(); j++) {
|
||||||
while (body2ProxyShape != nullptr) {
|
|
||||||
|
ProxyShape* body2ProxyShape = mWorld->mProxyShapesComponents.getProxyShape(body2ProxyShapesEntities[j]);
|
||||||
|
|
||||||
AABB aabb2 = body2ProxyShape->getWorldAABB();
|
AABB aabb2 = body2ProxyShape->getWorldAABB();
|
||||||
|
|
||||||
|
@ -630,13 +634,7 @@ bool CollisionDetection::testOverlap(CollisionBody* body1, CollisionBody* body2)
|
||||||
computeMiddlePhaseForProxyShapes(&pair, narrowPhaseInput);
|
computeMiddlePhaseForProxyShapes(&pair, narrowPhaseInput);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go to the next proxy shape
|
|
||||||
body2ProxyShape = body2ProxyShape->getNext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go to the next proxy shape
|
|
||||||
body1ProxyShape = body1ProxyShape->getNext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test narrow-phase collision
|
// Test narrow-phase collision
|
||||||
|
@ -656,8 +654,10 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl
|
||||||
NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator());
|
NarrowPhaseInput narrowPhaseInput(mMemoryManager.getPoolAllocator());
|
||||||
|
|
||||||
// For each proxy shape proxy shape of the body
|
// For each proxy shape proxy shape of the body
|
||||||
ProxyShape* bodyProxyShape = body->getProxyShapesList();
|
const List<Entity>& proxyShapesEntities = mWorld->mBodyComponents.getProxyShapes(body->getEntity());
|
||||||
while (bodyProxyShape != nullptr) {
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
|
ProxyShape* bodyProxyShape = mWorld->mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
|
||||||
if (bodyProxyShape->getBroadPhaseId() != -1) {
|
if (bodyProxyShape->getBroadPhaseId() != -1) {
|
||||||
|
|
||||||
|
@ -713,9 +713,6 @@ void CollisionDetection::testOverlap(CollisionBody* body, OverlapCallback* overl
|
||||||
element = element->next;
|
element = element->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go to the next proxy shape
|
|
||||||
bodyProxyShape = bodyProxyShape->getNext();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,14 +725,18 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body
|
||||||
OverlappingPairMap overlappingPairs(mMemoryManager.getPoolAllocator());
|
OverlappingPairMap overlappingPairs(mMemoryManager.getPoolAllocator());
|
||||||
|
|
||||||
// For each proxy shape proxy shape of the first body
|
// For each proxy shape proxy shape of the first body
|
||||||
ProxyShape* body1ProxyShape = body1->getProxyShapesList();
|
const List<Entity>& body1ProxyShapesEntities = mWorld->mBodyComponents.getProxyShapes(body1->getEntity());
|
||||||
while (body1ProxyShape != nullptr) {
|
const List<Entity>& body2ProxyShapesEntities = mWorld->mBodyComponents.getProxyShapes(body2->getEntity());
|
||||||
|
for (uint i=0; i < body1ProxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
|
ProxyShape* body1ProxyShape = mWorld->mProxyShapesComponents.getProxyShape(body1ProxyShapesEntities[i]);
|
||||||
|
|
||||||
AABB aabb1 = body1ProxyShape->getWorldAABB();
|
AABB aabb1 = body1ProxyShape->getWorldAABB();
|
||||||
|
|
||||||
// For each proxy shape of the second body
|
// For each proxy shape of the second body
|
||||||
ProxyShape* body2ProxyShape = body2->getProxyShapesList();
|
for (uint j=0; j < body2ProxyShapesEntities.size(); j++) {
|
||||||
while (body2ProxyShape != nullptr) {
|
|
||||||
|
ProxyShape* body2ProxyShape = mWorld->mProxyShapesComponents.getProxyShape(body2ProxyShapesEntities[i]);
|
||||||
|
|
||||||
AABB aabb2 = body2ProxyShape->getWorldAABB();
|
AABB aabb2 = body2ProxyShape->getWorldAABB();
|
||||||
|
|
||||||
|
@ -767,13 +768,7 @@ void CollisionDetection::testCollision(CollisionBody* body1, CollisionBody* body
|
||||||
// Compute the middle-phase collision detection between the two shapes
|
// Compute the middle-phase collision detection between the two shapes
|
||||||
computeMiddlePhaseForProxyShapes(pair, narrowPhaseInput);
|
computeMiddlePhaseForProxyShapes(pair, narrowPhaseInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go to the next proxy shape
|
|
||||||
body2ProxyShape = body2ProxyShape->getNext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go to the next proxy shape
|
|
||||||
body1ProxyShape = body1ProxyShape->getNext();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test narrow-phase collision
|
// Test narrow-phase collision
|
||||||
|
@ -812,8 +807,10 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c
|
||||||
OverlappingPairMap overlappingPairs(mMemoryManager.getPoolAllocator());
|
OverlappingPairMap overlappingPairs(mMemoryManager.getPoolAllocator());
|
||||||
|
|
||||||
// For each proxy shape proxy shape of the body
|
// For each proxy shape proxy shape of the body
|
||||||
ProxyShape* bodyProxyShape = body->getProxyShapesList();
|
const List<Entity>& proxyShapesEntities = mWorld->mBodyComponents.getProxyShapes(body->getEntity());
|
||||||
while (bodyProxyShape != nullptr) {
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
|
ProxyShape* bodyProxyShape = mWorld->mProxyShapesComponents.getProxyShape(proxyShapesEntities[i]);
|
||||||
|
|
||||||
if (bodyProxyShape->getBroadPhaseId() != -1) {
|
if (bodyProxyShape->getBroadPhaseId() != -1) {
|
||||||
|
|
||||||
|
@ -870,9 +867,6 @@ void CollisionDetection::testCollision(CollisionBody* body, CollisionCallback* c
|
||||||
// Go to the next overlapping proxy shape
|
// Go to the next overlapping proxy shape
|
||||||
element = element->next;
|
element = element->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go to the next proxy shape
|
|
||||||
bodyProxyShape = bodyProxyShape->getNext();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,8 @@ using namespace reactphysics3d;
|
||||||
* @param transform Transformation from collision shape local-space to body local-space
|
* @param transform Transformation from collision shape local-space to body local-space
|
||||||
* @param mass Mass of the collision shape (in kilograms)
|
* @param mass Mass of the collision shape (in kilograms)
|
||||||
*/
|
*/
|
||||||
ProxyShape::ProxyShape(CollisionBody* body, MemoryManager& memoryManager)
|
ProxyShape::ProxyShape(Entity entity, CollisionBody* body, MemoryManager& memoryManager)
|
||||||
:mMemoryManager(memoryManager), mBody(body),
|
:mMemoryManager(memoryManager), mEntity(entity), mBody(body),
|
||||||
mUserData(nullptr) {
|
mUserData(nullptr) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ ProxyShape::~ProxyShape() {
|
||||||
* @return Mass of the collision shape (in kilograms)
|
* @return Mass of the collision shape (in kilograms)
|
||||||
*/
|
*/
|
||||||
decimal ProxyShape::getMass() const {
|
decimal ProxyShape::getMass() const {
|
||||||
return mBody->mWorld.mProxyShapesComponents.getMass(this);
|
return mBody->mWorld.mProxyShapesComponents.getMass(mEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,9 +66,9 @@ decimal ProxyShape::getMass() const {
|
||||||
*/
|
*/
|
||||||
bool ProxyShape::testPointInside(const Vector3& worldPoint) {
|
bool ProxyShape::testPointInside(const Vector3& worldPoint) {
|
||||||
const Transform localToWorld = mBody->mWorld.mTransformComponents.getTransform(mBody->getEntity()) *
|
const Transform localToWorld = mBody->mWorld.mTransformComponents.getTransform(mBody->getEntity()) *
|
||||||
mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(this);
|
mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(mEntity);
|
||||||
const Vector3 localPoint = localToWorld.getInverse() * worldPoint;
|
const Vector3 localPoint = localToWorld.getInverse() * worldPoint;
|
||||||
const CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(this);
|
const CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(mEntity);
|
||||||
return collisionShape->testPointInside(localPoint, this);
|
return collisionShape->testPointInside(localPoint, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,9 +78,9 @@ bool ProxyShape::testPointInside(const Vector3& worldPoint) {
|
||||||
*/
|
*/
|
||||||
void ProxyShape::setCollisionCategoryBits(unsigned short collisionCategoryBits) {
|
void ProxyShape::setCollisionCategoryBits(unsigned short collisionCategoryBits) {
|
||||||
|
|
||||||
mBody->mWorld.mProxyShapesComponents.setCollisionCategoryBits(this, collisionCategoryBits);
|
mBody->mWorld.mProxyShapesComponents.setCollisionCategoryBits(mEntity, collisionCategoryBits);
|
||||||
|
|
||||||
int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(this);
|
int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(mEntity);
|
||||||
|
|
||||||
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
|
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
|
||||||
"ProxyShape " + std::to_string(broadPhaseId) + ": Set collisionCategoryBits=" +
|
"ProxyShape " + std::to_string(broadPhaseId) + ": Set collisionCategoryBits=" +
|
||||||
|
@ -93,9 +93,9 @@ void ProxyShape::setCollisionCategoryBits(unsigned short collisionCategoryBits)
|
||||||
*/
|
*/
|
||||||
void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBits) {
|
void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBits) {
|
||||||
|
|
||||||
mBody->mWorld.mProxyShapesComponents.setCollideWithMaskBits(this, collideWithMaskBits);
|
mBody->mWorld.mProxyShapesComponents.setCollideWithMaskBits(mEntity, collideWithMaskBits);
|
||||||
|
|
||||||
int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(this);
|
int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(mEntity);
|
||||||
|
|
||||||
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
|
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
|
||||||
"ProxyShape " + std::to_string(broadPhaseId) + ": Set collideWithMaskBits=" +
|
"ProxyShape " + std::to_string(broadPhaseId) + ": Set collideWithMaskBits=" +
|
||||||
|
@ -106,14 +106,14 @@ void ProxyShape::setCollideWithMaskBits(unsigned short collideWithMaskBits) {
|
||||||
void ProxyShape::setLocalToBodyTransform(const Transform& transform) {
|
void ProxyShape::setLocalToBodyTransform(const Transform& transform) {
|
||||||
|
|
||||||
//mLocalToBodyTransform = transform;
|
//mLocalToBodyTransform = transform;
|
||||||
mBody->mWorld.mProxyShapesComponents.setLocalToBodyTransform(this, transform);
|
mBody->mWorld.mProxyShapesComponents.setLocalToBodyTransform(mEntity, transform);
|
||||||
|
|
||||||
mBody->setIsSleeping(false);
|
mBody->setIsSleeping(false);
|
||||||
|
|
||||||
// Notify the body that the proxy shape has to be updated in the broad-phase
|
// Notify the body that the proxy shape has to be updated in the broad-phase
|
||||||
mBody->updateProxyShapeInBroadPhase(this, true);
|
mBody->updateProxyShapeInBroadPhase(this, true);
|
||||||
|
|
||||||
int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(this);
|
int broadPhaseId = mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(mEntity);
|
||||||
|
|
||||||
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
|
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::ProxyShape,
|
||||||
"ProxyShape " + std::to_string(broadPhaseId) + ": Set localToBodyTransform=" +
|
"ProxyShape " + std::to_string(broadPhaseId) + ": Set localToBodyTransform=" +
|
||||||
|
@ -126,7 +126,7 @@ void ProxyShape::setLocalToBodyTransform(const Transform& transform) {
|
||||||
*/
|
*/
|
||||||
const AABB ProxyShape::getWorldAABB() const {
|
const AABB ProxyShape::getWorldAABB() const {
|
||||||
AABB aabb;
|
AABB aabb;
|
||||||
CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(this);
|
CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(mEntity);
|
||||||
collisionShape->computeAABB(aabb, getLocalToWorldTransform());
|
collisionShape->computeAABB(aabb, getLocalToWorldTransform());
|
||||||
return aabb;
|
return aabb;
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ const AABB ProxyShape::getWorldAABB() const {
|
||||||
* @return Pointer to the internal collision shape
|
* @return Pointer to the internal collision shape
|
||||||
*/
|
*/
|
||||||
const CollisionShape* ProxyShape::getCollisionShape() const {
|
const CollisionShape* ProxyShape::getCollisionShape() const {
|
||||||
return mBody->mWorld.mProxyShapesComponents.getCollisionShape(this);
|
return mBody->mWorld.mProxyShapesComponents.getCollisionShape(mEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the collision shape
|
// Return the collision shape
|
||||||
|
@ -144,12 +144,12 @@ const CollisionShape* ProxyShape::getCollisionShape() const {
|
||||||
* @return Pointer to the internal collision shape
|
* @return Pointer to the internal collision shape
|
||||||
*/
|
*/
|
||||||
CollisionShape* ProxyShape::getCollisionShape() {
|
CollisionShape* ProxyShape::getCollisionShape() {
|
||||||
return mBody->mWorld.mProxyShapesComponents.getCollisionShape(this);
|
return mBody->mWorld.mProxyShapesComponents.getCollisionShape(mEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the broad-phase id
|
// Return the broad-phase id
|
||||||
int ProxyShape::getBroadPhaseId() const {
|
int ProxyShape::getBroadPhaseId() const {
|
||||||
return mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(this);
|
return mBody->mWorld.mProxyShapesComponents.getBroadPhaseId(mEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the local to parent body transform
|
// Return the local to parent body transform
|
||||||
|
@ -158,25 +158,7 @@ int ProxyShape::getBroadPhaseId() const {
|
||||||
* to the local-space of the parent body
|
* to the local-space of the parent body
|
||||||
*/
|
*/
|
||||||
const Transform& ProxyShape::getLocalToBodyTransform() const {
|
const Transform& ProxyShape::getLocalToBodyTransform() const {
|
||||||
return mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(this);
|
return mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(mEntity);
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
// Raycast method with feedback information
|
||||||
|
@ -198,7 +180,7 @@ bool ProxyShape::raycast(const Ray& ray, RaycastInfo& raycastInfo) {
|
||||||
worldToLocalTransform * ray.point2,
|
worldToLocalTransform * ray.point2,
|
||||||
ray.maxFraction);
|
ray.maxFraction);
|
||||||
|
|
||||||
const CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(this);
|
const CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(mEntity);
|
||||||
bool isHit = collisionShape->raycast(rayLocal, raycastInfo, this, mMemoryManager.getPoolAllocator());
|
bool isHit = collisionShape->raycast(rayLocal, raycastInfo, this, mMemoryManager.getPoolAllocator());
|
||||||
|
|
||||||
// Convert the raycast info into world-space
|
// Convert the raycast info into world-space
|
||||||
|
@ -214,7 +196,7 @@ bool ProxyShape::raycast(const Ray& ray, RaycastInfo& raycastInfo) {
|
||||||
* @return The collision category bits mask of the proxy shape
|
* @return The collision category bits mask of the proxy shape
|
||||||
*/
|
*/
|
||||||
unsigned short ProxyShape::getCollisionCategoryBits() const {
|
unsigned short ProxyShape::getCollisionCategoryBits() const {
|
||||||
return mBody->mWorld.mProxyShapesComponents.getCollisionCategoryBits(this);
|
return mBody->mWorld.mProxyShapesComponents.getCollisionCategoryBits(mEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the collision bits mask
|
// Return the collision bits mask
|
||||||
|
@ -222,7 +204,7 @@ unsigned short ProxyShape::getCollisionCategoryBits() const {
|
||||||
* @return The bits mask that specifies with which collision category this shape will collide
|
* @return The bits mask that specifies with which collision category this shape will collide
|
||||||
*/
|
*/
|
||||||
unsigned short ProxyShape::getCollideWithMaskBits() const {
|
unsigned short ProxyShape::getCollideWithMaskBits() const {
|
||||||
return mBody->mWorld.mProxyShapesComponents.getCollideWithMaskBits(this);
|
return mBody->mWorld.mProxyShapesComponents.getCollideWithMaskBits(mEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the local to world transform
|
// Return the local to world transform
|
||||||
|
@ -232,7 +214,7 @@ unsigned short ProxyShape::getCollideWithMaskBits() const {
|
||||||
*/
|
*/
|
||||||
const Transform ProxyShape::getLocalToWorldTransform() const {
|
const Transform ProxyShape::getLocalToWorldTransform() const {
|
||||||
return mBody->mWorld.mTransformComponents.getTransform(mBody->getEntity()) *
|
return mBody->mWorld.mTransformComponents.getTransform(mBody->getEntity()) *
|
||||||
mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(this);
|
mBody->mWorld.mProxyShapesComponents.getLocalToBodyTransform(mEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IS_PROFILING_ACTIVE
|
#ifdef IS_PROFILING_ACTIVE
|
||||||
|
@ -242,7 +224,7 @@ void ProxyShape::setProfiler(Profiler* profiler) {
|
||||||
|
|
||||||
mProfiler = profiler;
|
mProfiler = profiler;
|
||||||
|
|
||||||
CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(this);
|
CollisionShape* collisionShape = mBody->mWorld.mProxyShapesComponents.getCollisionShape(mEntity);
|
||||||
collisionShape->setProfiler(profiler);
|
collisionShape->setProfiler(profiler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,9 @@ class ProxyShape {
|
||||||
/// Reference to the memory manager
|
/// Reference to the memory manager
|
||||||
MemoryManager& mMemoryManager;
|
MemoryManager& mMemoryManager;
|
||||||
|
|
||||||
|
/// Identifier of the entity in the ECS
|
||||||
|
Entity mEntity;
|
||||||
|
|
||||||
/// Pointer to the parent body
|
/// Pointer to the parent body
|
||||||
CollisionBody* mBody;
|
CollisionBody* mBody;
|
||||||
|
|
||||||
|
@ -111,7 +114,7 @@ class ProxyShape {
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
ProxyShape(CollisionBody* body, MemoryManager& memoryManager);
|
ProxyShape(Entity entity, CollisionBody* body, MemoryManager& memoryManager);
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
virtual ~ProxyShape();
|
virtual ~ProxyShape();
|
||||||
|
@ -122,6 +125,9 @@ class ProxyShape {
|
||||||
/// Deleted assignment operator
|
/// Deleted assignment operator
|
||||||
ProxyShape& operator=(const ProxyShape& proxyShape) = delete;
|
ProxyShape& operator=(const ProxyShape& proxyShape) = delete;
|
||||||
|
|
||||||
|
/// Return the corresponding entity of the proxy-shape
|
||||||
|
Entity getEntity() const;
|
||||||
|
|
||||||
/// Return the collision shape
|
/// Return the collision shape
|
||||||
const CollisionShape* getCollisionShape() const;
|
const CollisionShape* getCollisionShape() const;
|
||||||
|
|
||||||
|
@ -170,12 +176,6 @@ class ProxyShape {
|
||||||
/// Set the collision category bits
|
/// Set the collision category bits
|
||||||
void setCollisionCategoryBits(unsigned short collisionCategoryBits);
|
void setCollisionCategoryBits(unsigned short collisionCategoryBits);
|
||||||
|
|
||||||
/// Return the next proxy shape in the linked list of proxy shapes
|
|
||||||
ProxyShape* getNext();
|
|
||||||
|
|
||||||
/// Return the next proxy shape in the linked list of proxy shapes
|
|
||||||
const ProxyShape* getNext() const;
|
|
||||||
|
|
||||||
/// Return the broad-phase id
|
/// Return the broad-phase id
|
||||||
int getBroadPhaseId() const;
|
int getBroadPhaseId() const;
|
||||||
|
|
||||||
|
@ -209,6 +209,14 @@ class ProxyShape {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Return the corresponding entity of the proxy-shape
|
||||||
|
/**
|
||||||
|
* @return The entity of the proxy-shape
|
||||||
|
*/
|
||||||
|
inline Entity ProxyShape::getEntity() const {
|
||||||
|
return mEntity;
|
||||||
|
}
|
||||||
|
|
||||||
// Return the parent body
|
// Return the parent body
|
||||||
/**
|
/**
|
||||||
* @return Pointer to the parent body
|
* @return Pointer to the parent body
|
||||||
|
|
294
src/components/BodyComponents.cpp
Normal file
294
src/components/BodyComponents.cpp
Normal file
|
@ -0,0 +1,294 @@
|
||||||
|
/********************************************************************************
|
||||||
|
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
|
||||||
|
* Copyright (c) 2010-2018 Daniel Chappuis *
|
||||||
|
*********************************************************************************
|
||||||
|
* *
|
||||||
|
* This software is provided 'as-is', without any express or implied warranty. *
|
||||||
|
* In no event will the authors be held liable for any damages arising from the *
|
||||||
|
* use of this software. *
|
||||||
|
* *
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, *
|
||||||
|
* including commercial applications, and to alter it and redistribute it *
|
||||||
|
* freely, subject to the following restrictions: *
|
||||||
|
* *
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim *
|
||||||
|
* that you wrote the original software. If you use this software in a *
|
||||||
|
* product, an acknowledgment in the product documentation would be *
|
||||||
|
* appreciated but is not required. *
|
||||||
|
* *
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be *
|
||||||
|
* misrepresented as being the original software. *
|
||||||
|
* *
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
// Libraries
|
||||||
|
#include "BodyComponents.h"
|
||||||
|
#include "engine/EntityManager.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
// We want to use the ReactPhysics3D namespace
|
||||||
|
using namespace reactphysics3d;
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
BodyComponents::BodyComponents(MemoryAllocator& allocator)
|
||||||
|
:Components(allocator), mSleepingStartIndex(0){
|
||||||
|
|
||||||
|
// Allocate memory for the components data
|
||||||
|
allocate(INIT_ALLOCATED_COMPONENTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
BodyComponents::~BodyComponents() {
|
||||||
|
|
||||||
|
if (mNbAllocatedComponents > 0) {
|
||||||
|
|
||||||
|
// Destroy all the remaining components
|
||||||
|
for (uint32 i = 0; i < mNbComponents; i++) {
|
||||||
|
|
||||||
|
// TODO : MAke sure we do not delete already deleted components
|
||||||
|
destroyComponent(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size for the data of a single component (in bytes)
|
||||||
|
const size_t totalSizeBytes = mNbAllocatedComponents * COMPONENT_DATA_SIZE;
|
||||||
|
|
||||||
|
// Release the allocated memory
|
||||||
|
mMemoryAllocator.release(mBuffer, totalSizeBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate memory for a given number of components
|
||||||
|
void BodyComponents::allocate(uint32 nbComponentsToAllocate) {
|
||||||
|
|
||||||
|
assert(nbComponentsToAllocate > mNbAllocatedComponents);
|
||||||
|
|
||||||
|
// Size for the data of a single component (in bytes)
|
||||||
|
const size_t totalSizeBytes = nbComponentsToAllocate * COMPONENT_DATA_SIZE;
|
||||||
|
|
||||||
|
// Allocate memory
|
||||||
|
void* newBuffer = mMemoryAllocator.allocate(totalSizeBytes);
|
||||||
|
assert(newBuffer != nullptr);
|
||||||
|
|
||||||
|
// New pointers to components data
|
||||||
|
Entity* newBodiesEntities = static_cast<Entity*>(newBuffer);
|
||||||
|
Body** newBodies = reinterpret_cast<Body**>(newBodiesEntities + nbComponentsToAllocate);
|
||||||
|
List<Entity>* newProxyShapes = reinterpret_cast<List<Entity>*>(newBodies + nbComponentsToAllocate);
|
||||||
|
|
||||||
|
// If there was already components before
|
||||||
|
if (mNbComponents > 0) {
|
||||||
|
|
||||||
|
// Copy component data from the previous buffer to the new one
|
||||||
|
memcpy(newBodiesEntities, mBodiesEntities, mNbComponents * sizeof(Entity));
|
||||||
|
memcpy(newBodies, mBodies, mNbComponents * sizeof(Body*));
|
||||||
|
memcpy(newProxyShapes, mProxyShapes, mNbComponents * sizeof(List<Entity>));
|
||||||
|
|
||||||
|
// Deallocate previous memory
|
||||||
|
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * COMPONENT_DATA_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mBuffer = newBuffer;
|
||||||
|
mBodiesEntities = newBodiesEntities;
|
||||||
|
mBodies = newBodies;
|
||||||
|
mProxyShapes = newProxyShapes;
|
||||||
|
mNbAllocatedComponents = nbComponentsToAllocate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a component
|
||||||
|
void BodyComponents::addComponent(Entity bodyEntity, bool isSleeping, const BodyComponent& component) {
|
||||||
|
|
||||||
|
// If we need to allocate more components
|
||||||
|
if (mNbComponents == mNbAllocatedComponents) {
|
||||||
|
allocate(mNbAllocatedComponents * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 index;
|
||||||
|
|
||||||
|
// If the component to add is part of a sleeping entity or there are no sleeping entity
|
||||||
|
if (isSleeping) {
|
||||||
|
|
||||||
|
// Add the component at the end of the array
|
||||||
|
index = mNbComponents;
|
||||||
|
|
||||||
|
mSleepingStartIndex = index;
|
||||||
|
}
|
||||||
|
// If the component to add is not part of a sleeping entity
|
||||||
|
else {
|
||||||
|
|
||||||
|
// If there already are sleeping components
|
||||||
|
if (mSleepingStartIndex != mNbComponents) {
|
||||||
|
|
||||||
|
// Move the first sleeping component to the end of the array
|
||||||
|
moveComponentToIndex(mSleepingStartIndex, mNbComponents);
|
||||||
|
}
|
||||||
|
|
||||||
|
index = mSleepingStartIndex;
|
||||||
|
|
||||||
|
mSleepingStartIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert the new component data
|
||||||
|
new (mBodiesEntities + index) Entity(bodyEntity);
|
||||||
|
mBodies[index] = component.body;
|
||||||
|
new (mProxyShapes + index) List<Entity>(mMemoryAllocator);
|
||||||
|
|
||||||
|
// Map the entity with the new component lookup index
|
||||||
|
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(bodyEntity, index));
|
||||||
|
|
||||||
|
mNbComponents++;
|
||||||
|
|
||||||
|
assert(mSleepingStartIndex <= mNbComponents);
|
||||||
|
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove a component at a given index
|
||||||
|
void BodyComponents::removeComponent(Entity bodyEntity) {
|
||||||
|
|
||||||
|
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
|
||||||
|
|
||||||
|
uint index = mMapEntityToComponentIndex[bodyEntity];
|
||||||
|
|
||||||
|
assert(index < mNbComponents);
|
||||||
|
|
||||||
|
// We want to keep the arrays tightly packed. Therefore, when a component is removed,
|
||||||
|
// we replace it with the last element of the array. But we need to make sure that sleeping
|
||||||
|
// and non-sleeping components stay grouped together.
|
||||||
|
|
||||||
|
// Destroy the component
|
||||||
|
destroyComponent(index);
|
||||||
|
|
||||||
|
// If the component to remove is sleeping
|
||||||
|
if (index >= mSleepingStartIndex) {
|
||||||
|
|
||||||
|
// If the component is not the last one
|
||||||
|
if (index != mNbComponents - 1) {
|
||||||
|
|
||||||
|
// We replace it by the last sleeping component
|
||||||
|
moveComponentToIndex(mNbComponents - 1, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // If the component to remove is not sleeping
|
||||||
|
|
||||||
|
// If it not the last awake component
|
||||||
|
if (index != mSleepingStartIndex - 1) {
|
||||||
|
|
||||||
|
// We replace it by the last awake component
|
||||||
|
moveComponentToIndex(mSleepingStartIndex - 1, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are sleeping components at the end
|
||||||
|
if (mSleepingStartIndex != mNbComponents) {
|
||||||
|
|
||||||
|
// We replace the last awake component by the last sleeping component
|
||||||
|
moveComponentToIndex(mNbComponents - 1, mSleepingStartIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
mSleepingStartIndex--;
|
||||||
|
}
|
||||||
|
|
||||||
|
mNbComponents--;
|
||||||
|
|
||||||
|
assert(mSleepingStartIndex <= mNbComponents);
|
||||||
|
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify if a given entity is sleeping or not
|
||||||
|
void BodyComponents::setIsEntitySleeping(Entity entity, bool isSleeping) {
|
||||||
|
|
||||||
|
const uint32 index = mMapEntityToComponentIndex[entity];
|
||||||
|
|
||||||
|
// If the component was sleeping and is not sleeping anymore
|
||||||
|
if (!isSleeping && index >= mSleepingStartIndex) {
|
||||||
|
|
||||||
|
assert(mSleepingStartIndex < mNbComponents);
|
||||||
|
|
||||||
|
// If the sleeping component is not the first sleeping component
|
||||||
|
if (mSleepingStartIndex != index) {
|
||||||
|
|
||||||
|
// Swap the first sleeping component with the one we need to wake up
|
||||||
|
swapComponents(index, mSleepingStartIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
mSleepingStartIndex++;
|
||||||
|
}
|
||||||
|
// If the component was awake and must now go to sleep
|
||||||
|
else if (isSleeping && index < mSleepingStartIndex) {
|
||||||
|
|
||||||
|
assert(mSleepingStartIndex > 0);
|
||||||
|
|
||||||
|
// If the awake component is not the only awake component
|
||||||
|
if (index != mSleepingStartIndex - 1) {
|
||||||
|
|
||||||
|
// Swap the last awake component with the one we need to put to sleep
|
||||||
|
swapComponents(index, mSleepingStartIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
mSleepingStartIndex--;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(mSleepingStartIndex <= mNbComponents);
|
||||||
|
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move a component from a source to a destination index in the components array
|
||||||
|
// The destination location must contain a constructed object
|
||||||
|
void BodyComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) {
|
||||||
|
|
||||||
|
const Entity entity = mBodiesEntities[srcIndex];
|
||||||
|
|
||||||
|
// Copy the data of the source component to the destination location
|
||||||
|
new (mBodiesEntities + destIndex) Entity(mBodiesEntities[srcIndex]);
|
||||||
|
mBodies[destIndex] = mBodies[srcIndex];
|
||||||
|
new (mProxyShapes + destIndex) List<Entity>(mProxyShapes[srcIndex]);
|
||||||
|
|
||||||
|
// Destroy the source component
|
||||||
|
destroyComponent(srcIndex);
|
||||||
|
|
||||||
|
assert(!mMapEntityToComponentIndex.containsKey(entity));
|
||||||
|
|
||||||
|
// Update the entity to component index mapping
|
||||||
|
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, destIndex));
|
||||||
|
|
||||||
|
assert(mMapEntityToComponentIndex[mBodiesEntities[destIndex]] == destIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap two components in the array
|
||||||
|
void BodyComponents::swapComponents(uint32 index1, uint32 index2) {
|
||||||
|
|
||||||
|
// Copy component 1 data
|
||||||
|
Entity entity1(mBodiesEntities[index1]);
|
||||||
|
Body* body1 = mBodies[index1];
|
||||||
|
List<Entity> proxyShapes1(mProxyShapes[index1]);
|
||||||
|
|
||||||
|
// Destroy component 1
|
||||||
|
destroyComponent(index1);
|
||||||
|
|
||||||
|
moveComponentToIndex(index2, index1);
|
||||||
|
|
||||||
|
// Reconstruct component 1 at component 2 location
|
||||||
|
new (mBodiesEntities + index2) Entity(entity1);
|
||||||
|
new (mProxyShapes + index2) List<Entity>(proxyShapes1);
|
||||||
|
mBodies[index2] = body1;
|
||||||
|
|
||||||
|
// Update the entity to component index mapping
|
||||||
|
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity1, index2));
|
||||||
|
|
||||||
|
assert(mMapEntityToComponentIndex[mBodiesEntities[index1]] == index1);
|
||||||
|
assert(mMapEntityToComponentIndex[mBodiesEntities[index2]] == index2);
|
||||||
|
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy a component at a given index
|
||||||
|
void BodyComponents::destroyComponent(uint32 index) {
|
||||||
|
|
||||||
|
assert(index < mNbComponents);
|
||||||
|
assert(mMapEntityToComponentIndex[mBodiesEntities[index]] == index);
|
||||||
|
|
||||||
|
mMapEntityToComponentIndex.remove(mBodiesEntities[index]);
|
||||||
|
|
||||||
|
mBodiesEntities[index].~Entity();
|
||||||
|
mBodies[index] = nullptr;
|
||||||
|
mProxyShapes[index].~List<Entity>();
|
||||||
|
}
|
161
src/components/BodyComponents.h
Normal file
161
src/components/BodyComponents.h
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
/********************************************************************************
|
||||||
|
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
|
||||||
|
* Copyright (c) 2010-2018 Daniel Chappuis *
|
||||||
|
*********************************************************************************
|
||||||
|
* *
|
||||||
|
* This software is provided 'as-is', without any express or implied warranty. *
|
||||||
|
* In no event will the authors be held liable for any damages arising from the *
|
||||||
|
* use of this software. *
|
||||||
|
* *
|
||||||
|
* Permission is granted to anyone to use this software for any purpose, *
|
||||||
|
* including commercial applications, and to alter it and redistribute it *
|
||||||
|
* freely, subject to the following restrictions: *
|
||||||
|
* *
|
||||||
|
* 1. The origin of this software must not be misrepresented; you must not claim *
|
||||||
|
* that you wrote the original software. If you use this software in a *
|
||||||
|
* product, an acknowledgment in the product documentation would be *
|
||||||
|
* appreciated but is not required. *
|
||||||
|
* *
|
||||||
|
* 2. Altered source versions must be plainly marked as such, and must not be *
|
||||||
|
* misrepresented as being the original software. *
|
||||||
|
* *
|
||||||
|
* 3. This notice may not be removed or altered from any source distribution. *
|
||||||
|
* *
|
||||||
|
********************************************************************************/
|
||||||
|
|
||||||
|
#ifndef REACTPHYSICS3D_BODY_COMPONENTS_H
|
||||||
|
#define REACTPHYSICS3D_BODY_COMPONENTS_H
|
||||||
|
|
||||||
|
// Libraries
|
||||||
|
#include "mathematics/Transform.h"
|
||||||
|
#include "engine/Entity.h"
|
||||||
|
#include "components/Components.h"
|
||||||
|
#include "containers/Map.h"
|
||||||
|
|
||||||
|
// ReactPhysics3D namespace
|
||||||
|
namespace reactphysics3d {
|
||||||
|
|
||||||
|
// Class declarations
|
||||||
|
class MemoryAllocator;
|
||||||
|
class EntityManager;
|
||||||
|
class Body;
|
||||||
|
|
||||||
|
// Class BodyComponents
|
||||||
|
/**
|
||||||
|
* This class represent the component of the ECS that contains data about a physics body.
|
||||||
|
* The components of the sleeping entities (bodies) are always stored at the end of the array.
|
||||||
|
*/
|
||||||
|
class BodyComponents : public Components {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// -------------------- Constants -------------------- //
|
||||||
|
|
||||||
|
const size_t COMPONENT_DATA_SIZE = sizeof(Entity) + sizeof(Body*) + sizeof(List<Entity>);
|
||||||
|
|
||||||
|
// -------------------- Attributes -------------------- //
|
||||||
|
|
||||||
|
/// Index of the first component of a sleeping entity (sleeping components are stored at the end)
|
||||||
|
uint32 mSleepingStartIndex;
|
||||||
|
|
||||||
|
/// Array of body entities of each component
|
||||||
|
Entity* mBodiesEntities;
|
||||||
|
|
||||||
|
/// Array of pointers to the corresponding bodies
|
||||||
|
Body** mBodies;
|
||||||
|
|
||||||
|
/// Array with the list of proxy-shapes of each body
|
||||||
|
List<Entity>* mProxyShapes;
|
||||||
|
|
||||||
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
|
/// Destroy a component at a given index
|
||||||
|
void destroyComponent(uint32 index);
|
||||||
|
|
||||||
|
/// Move a component from a source to a destination index in the components array
|
||||||
|
void moveComponentToIndex(uint32 srcIndex, uint32 destIndex);
|
||||||
|
|
||||||
|
/// Swap two components in the array
|
||||||
|
void swapComponents(uint32 index1, uint32 index2);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// Structure for the data of a body component
|
||||||
|
struct BodyComponent {
|
||||||
|
|
||||||
|
Body* body;
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
BodyComponent(Body* body) : body(body) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
BodyComponents(MemoryAllocator& allocator);
|
||||||
|
|
||||||
|
/// Destructor
|
||||||
|
virtual ~BodyComponents();
|
||||||
|
|
||||||
|
/// Allocate memory for a given number of components
|
||||||
|
void allocate(uint32 nbComponentsToAllocate);
|
||||||
|
|
||||||
|
/// Add a component
|
||||||
|
void addComponent(Entity bodyEntity, bool isSleeping, const BodyComponent& component);
|
||||||
|
|
||||||
|
/// Remove a component at a given index
|
||||||
|
void removeComponent(Entity bodyEntity);
|
||||||
|
|
||||||
|
/// Add a proxy-shape to a body component
|
||||||
|
void addProxyShapeToBody(Entity bodyEntity, Entity proxyShapeEntity);
|
||||||
|
|
||||||
|
/// Set the transform of an entity
|
||||||
|
void removeProxyShapeFromBody(Entity bodyEntity, Entity proxyShapeEntity);
|
||||||
|
|
||||||
|
/// Return a pointer to a body
|
||||||
|
Body* getBody(Entity bodyEntity);
|
||||||
|
|
||||||
|
/// Return the list of proxy-shapes of a body
|
||||||
|
const List<Entity>& getProxyShapes(Entity bodyEntity) const;
|
||||||
|
|
||||||
|
/// Notify if a given entity is sleeping or not
|
||||||
|
void setIsEntitySleeping(Entity bodyEntity, bool isSleeping);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add a proxy-shape to a body component
|
||||||
|
inline void BodyComponents::addProxyShapeToBody(Entity bodyEntity, Entity proxyShapeEntity) {
|
||||||
|
|
||||||
|
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
|
||||||
|
|
||||||
|
mProxyShapes[mMapEntityToComponentIndex[bodyEntity]].add(proxyShapeEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the transform of an entity
|
||||||
|
inline void BodyComponents::removeProxyShapeFromBody(Entity bodyEntity, Entity proxyShapeEntity) {
|
||||||
|
|
||||||
|
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
|
||||||
|
|
||||||
|
mProxyShapes[mMapEntityToComponentIndex[bodyEntity]].remove(proxyShapeEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a pointer to a body
|
||||||
|
inline Body* BodyComponents::getBody(Entity bodyEntity) {
|
||||||
|
|
||||||
|
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
|
||||||
|
|
||||||
|
return mBodies[mMapEntityToComponentIndex[bodyEntity]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the list of proxy-shapes of a body
|
||||||
|
inline const List<Entity>& BodyComponents::getProxyShapes(Entity bodyEntity) const {
|
||||||
|
|
||||||
|
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
|
||||||
|
|
||||||
|
return mProxyShapes[mMapEntityToComponentIndex[bodyEntity]];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -86,6 +86,11 @@ class Components {
|
||||||
virtual ~Components() {
|
virtual ~Components() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the number of components
|
||||||
|
uint32 getNbComponents() const {
|
||||||
|
return mNbComponents;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,7 @@ using namespace reactphysics3d;
|
||||||
// Constructor
|
// Constructor
|
||||||
ProxyShapesComponents::ProxyShapesComponents(MemoryAllocator& allocator)
|
ProxyShapesComponents::ProxyShapesComponents(MemoryAllocator& allocator)
|
||||||
:Components(allocator),
|
:Components(allocator),
|
||||||
mSleepingStartIndex(0),
|
mSleepingStartIndex(0) {
|
||||||
mMapProxyShapeToComponentIndex(allocator) {
|
|
||||||
|
|
||||||
// Allocate memory for the components data
|
// Allocate memory for the components data
|
||||||
allocate(INIT_ALLOCATED_COMPONENTS);
|
allocate(INIT_ALLOCATED_COMPONENTS);
|
||||||
|
@ -76,31 +75,29 @@ void ProxyShapesComponents::allocate(uint32 nbComponentsToAllocate) {
|
||||||
assert(newBuffer != nullptr);
|
assert(newBuffer != nullptr);
|
||||||
|
|
||||||
// New pointers to components data
|
// New pointers to components data
|
||||||
Entity* newEntities = static_cast<Entity*>(newBuffer);
|
Entity* newProxyShapesEntities = static_cast<Entity*>(newBuffer);
|
||||||
ProxyShape** newProxyShapes = reinterpret_cast<ProxyShape**>(newEntities + nbComponentsToAllocate);
|
Entity* newBodiesEntities = reinterpret_cast<Entity*>(newProxyShapesEntities + nbComponentsToAllocate);
|
||||||
|
ProxyShape** newProxyShapes = reinterpret_cast<ProxyShape**>(newBodiesEntities + nbComponentsToAllocate);
|
||||||
int* newBroadPhaseIds = reinterpret_cast<int*>(newProxyShapes + nbComponentsToAllocate);
|
int* newBroadPhaseIds = reinterpret_cast<int*>(newProxyShapes + nbComponentsToAllocate);
|
||||||
AABB* newLocalBounds = reinterpret_cast<AABB*>(newBroadPhaseIds + nbComponentsToAllocate);
|
AABB* newLocalBounds = reinterpret_cast<AABB*>(newBroadPhaseIds + nbComponentsToAllocate);
|
||||||
Transform* newLocalToBodyTransforms = reinterpret_cast<Transform*>(newLocalBounds + nbComponentsToAllocate);
|
Transform* newLocalToBodyTransforms = reinterpret_cast<Transform*>(newLocalBounds + nbComponentsToAllocate);
|
||||||
CollisionShape** newCollisionShapes = reinterpret_cast<CollisionShape**>(newLocalToBodyTransforms + nbComponentsToAllocate);
|
CollisionShape** newCollisionShapes = reinterpret_cast<CollisionShape**>(newLocalToBodyTransforms + nbComponentsToAllocate);
|
||||||
decimal* newMasses = reinterpret_cast<decimal*>(newCollisionShapes + nbComponentsToAllocate);
|
decimal* newMasses = reinterpret_cast<decimal*>(newCollisionShapes + nbComponentsToAllocate);
|
||||||
uint32* newPreviousBodyProxyShapes = reinterpret_cast<uint32*>(newMasses + nbComponentsToAllocate);
|
unsigned short* newCollisionCategoryBits = reinterpret_cast<unsigned short*>(newMasses + nbComponentsToAllocate);
|
||||||
uint32* newNextBodyProxyShapes = reinterpret_cast<uint32*>(newPreviousBodyProxyShapes + nbComponentsToAllocate);
|
|
||||||
unsigned short* newCollisionCategoryBits = reinterpret_cast<unsigned short*>(newNextBodyProxyShapes + nbComponentsToAllocate);
|
|
||||||
unsigned short* newCollideWithMaskBits = reinterpret_cast<unsigned short*>(newCollisionCategoryBits + nbComponentsToAllocate);
|
unsigned short* newCollideWithMaskBits = reinterpret_cast<unsigned short*>(newCollisionCategoryBits + nbComponentsToAllocate);
|
||||||
|
|
||||||
// If there was already components before
|
// If there was already components before
|
||||||
if (mNbComponents > 0) {
|
if (mNbComponents > 0) {
|
||||||
|
|
||||||
// Copy component data from the previous buffer to the new one
|
// Copy component data from the previous buffer to the new one
|
||||||
memcpy(newEntities, mEntities, mNbComponents * sizeof(Entity));
|
memcpy(newProxyShapesEntities, mProxyShapesEntities, mNbComponents * sizeof(Entity));
|
||||||
|
memcpy(newBodiesEntities, mBodiesEntities, mNbComponents * sizeof(Entity));
|
||||||
memcpy(newProxyShapes, mProxyShapes, mNbComponents * sizeof(ProxyShape*));
|
memcpy(newProxyShapes, mProxyShapes, mNbComponents * sizeof(ProxyShape*));
|
||||||
memcpy(newBroadPhaseIds, mBroadPhaseIds, mNbComponents * sizeof(int));
|
memcpy(newBroadPhaseIds, mBroadPhaseIds, mNbComponents * sizeof(int));
|
||||||
memcpy(newLocalBounds, mLocalBounds, mNbComponents * sizeof(AABB));
|
memcpy(newLocalBounds, mLocalBounds, mNbComponents * sizeof(AABB));
|
||||||
memcpy(newLocalToBodyTransforms, mLocalToBodyTransforms, mNbComponents * sizeof(Transform));
|
memcpy(newLocalToBodyTransforms, mLocalToBodyTransforms, mNbComponents * sizeof(Transform));
|
||||||
memcpy(newCollisionShapes, mCollisionShapes, mNbComponents * sizeof(CollisionShape*));
|
memcpy(newCollisionShapes, mCollisionShapes, mNbComponents * sizeof(CollisionShape*));
|
||||||
memcpy(newMasses, mMasses, mNbComponents * sizeof(decimal));
|
memcpy(newMasses, mMasses, mNbComponents * sizeof(decimal));
|
||||||
memcpy(newPreviousBodyProxyShapes, mPreviousBodyProxyShapes, mNbComponents * sizeof(uint32));
|
|
||||||
memcpy(newNextBodyProxyShapes, mNextBodyProxyShapes, mNbComponents * sizeof(uint32));
|
|
||||||
memcpy(newCollisionCategoryBits, mCollisionCategoryBits, mNbComponents * sizeof(unsigned short));
|
memcpy(newCollisionCategoryBits, mCollisionCategoryBits, mNbComponents * sizeof(unsigned short));
|
||||||
memcpy(newCollideWithMaskBits, mCollideWithMaskBits, mNbComponents * sizeof(unsigned short));
|
memcpy(newCollideWithMaskBits, mCollideWithMaskBits, mNbComponents * sizeof(unsigned short));
|
||||||
|
|
||||||
|
@ -109,63 +106,23 @@ void ProxyShapesComponents::allocate(uint32 nbComponentsToAllocate) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mBuffer = newBuffer;
|
mBuffer = newBuffer;
|
||||||
mEntities = newEntities;
|
mProxyShapesEntities = newProxyShapesEntities;
|
||||||
|
mBodiesEntities = newBodiesEntities;
|
||||||
|
mProxyShapesEntities = newProxyShapesEntities;
|
||||||
mProxyShapes = newProxyShapes;
|
mProxyShapes = newProxyShapes;
|
||||||
mBroadPhaseIds = newBroadPhaseIds;
|
mBroadPhaseIds = newBroadPhaseIds;
|
||||||
mLocalBounds = newLocalBounds;
|
mLocalBounds = newLocalBounds;
|
||||||
mLocalToBodyTransforms = newLocalToBodyTransforms;
|
mLocalToBodyTransforms = newLocalToBodyTransforms;
|
||||||
mCollisionShapes = newCollisionShapes;
|
mCollisionShapes = newCollisionShapes;
|
||||||
mMasses = newMasses;
|
mMasses = newMasses;
|
||||||
mPreviousBodyProxyShapes = newPreviousBodyProxyShapes;
|
|
||||||
mNextBodyProxyShapes = newNextBodyProxyShapes;
|
|
||||||
mCollisionCategoryBits = newCollisionCategoryBits;
|
mCollisionCategoryBits = newCollisionCategoryBits;
|
||||||
mCollideWithMaskBits = newCollideWithMaskBits;
|
mCollideWithMaskBits = newCollideWithMaskBits;
|
||||||
|
|
||||||
mNbAllocatedComponents = nbComponentsToAllocate;
|
mNbAllocatedComponents = nbComponentsToAllocate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new proxy-shape at the beginning of the linked-list of proxy-shapes of a given entity
|
|
||||||
// If it is the first proxy-shape for the entity, it will create the first item of the linked-list
|
|
||||||
void ProxyShapesComponents::linkProxyShapeWithEntity(Entity entity, uint32 proxyShapeComponentIndex) {
|
|
||||||
|
|
||||||
auto it = mMapEntityToComponentIndex.find(entity);
|
|
||||||
if (it != mMapEntityToComponentIndex.end()) {
|
|
||||||
|
|
||||||
// Get the first proxy-shape of the linked-list
|
|
||||||
uint32 firstProxyShapeIndex = (*it).second;
|
|
||||||
|
|
||||||
assert(!hasPreviousProxyShape(firstProxyShapeIndex));
|
|
||||||
|
|
||||||
// Update the previous index of the first item of the list
|
|
||||||
mPreviousBodyProxyShapes[firstProxyShapeIndex] = proxyShapeComponentIndex;
|
|
||||||
|
|
||||||
// Map the entity to the new head of the linked-list
|
|
||||||
mMapEntityToComponentIndex[entity] = proxyShapeComponentIndex;
|
|
||||||
|
|
||||||
// Add the new proxy-shape at the beginning of the linked-list
|
|
||||||
const uint32 nextIndex = firstProxyShapeIndex;
|
|
||||||
const uint32 previousIndex = proxyShapeComponentIndex;
|
|
||||||
new (mNextBodyProxyShapes + proxyShapeComponentIndex) uint32(nextIndex);
|
|
||||||
new (mPreviousBodyProxyShapes + proxyShapeComponentIndex) uint32(previousIndex);
|
|
||||||
|
|
||||||
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[proxyShapeComponentIndex]] == proxyShapeComponentIndex);
|
|
||||||
}
|
|
||||||
else { // If the entity does not have a proxy-shape yet
|
|
||||||
|
|
||||||
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, proxyShapeComponentIndex));
|
|
||||||
|
|
||||||
// The new proxy-shape has no previous/next components in the linked-list
|
|
||||||
new (mNextBodyProxyShapes + proxyShapeComponentIndex) uint32(proxyShapeComponentIndex);
|
|
||||||
new (mPreviousBodyProxyShapes + proxyShapeComponentIndex) uint32(proxyShapeComponentIndex);
|
|
||||||
|
|
||||||
assert(!hasNextProxyShape(proxyShapeComponentIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!hasPreviousProxyShape(proxyShapeComponentIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a component
|
// Add a component
|
||||||
void ProxyShapesComponents::addComponent(Entity entity, bool isSleeping, const ProxyShapeComponent& component) {
|
void ProxyShapesComponents::addComponent(Entity proxyShapeEntity, bool isSleeping, const ProxyShapeComponent& component) {
|
||||||
|
|
||||||
// If we need to allocate more components
|
// If we need to allocate more components
|
||||||
if (mNbComponents == mNbAllocatedComponents) {
|
if (mNbComponents == mNbAllocatedComponents) {
|
||||||
|
@ -198,8 +155,9 @@ void ProxyShapesComponents::addComponent(Entity entity, bool isSleeping, const P
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the new component data
|
// Insert the new component data
|
||||||
new (mEntities + index) Entity(entity);
|
new (mProxyShapesEntities + index) Entity(proxyShapeEntity);
|
||||||
mProxyShapes[index] = (component.proxyShape);
|
new (mBodiesEntities + index) Entity(component.bodyEntity);
|
||||||
|
mProxyShapes[index] = component.proxyShape;
|
||||||
new (mBroadPhaseIds + index) int(component.broadPhaseId);
|
new (mBroadPhaseIds + index) int(component.broadPhaseId);
|
||||||
new (mLocalBounds + index) AABB(component.localBounds);
|
new (mLocalBounds + index) AABB(component.localBounds);
|
||||||
new (mLocalToBodyTransforms + index) Transform(component.localToBodyTransform);
|
new (mLocalToBodyTransforms + index) Transform(component.localToBodyTransform);
|
||||||
|
@ -208,133 +166,89 @@ void ProxyShapesComponents::addComponent(Entity entity, bool isSleeping, const P
|
||||||
new (mCollisionCategoryBits + index) unsigned short(component.collisionCategoryBits);
|
new (mCollisionCategoryBits + index) unsigned short(component.collisionCategoryBits);
|
||||||
new (mCollideWithMaskBits + index) unsigned short(component.collideWithMaskBits);
|
new (mCollideWithMaskBits + index) unsigned short(component.collideWithMaskBits);
|
||||||
|
|
||||||
mMapProxyShapeToComponentIndex.add(Pair<const ProxyShape*, uint32>(component.proxyShape, index));
|
// Map the entity with the new component lookup index
|
||||||
|
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(proxyShapeEntity, index));
|
||||||
|
|
||||||
mNbComponents++;
|
mNbComponents++;
|
||||||
|
|
||||||
// Map the entity with the new component lookup index
|
|
||||||
linkProxyShapeWithEntity(entity, index);
|
|
||||||
|
|
||||||
assert(mSleepingStartIndex <= mNbComponents);
|
assert(mSleepingStartIndex <= mNbComponents);
|
||||||
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index || !hasNextProxyShape(index));
|
|
||||||
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] == index || !hasPreviousProxyShape(index));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move a component from a source to a destination index in the components array
|
// Move a component from a source to a destination index in the components array
|
||||||
// The destination location must contain a constructed object
|
// The destination location must contain a constructed object
|
||||||
void ProxyShapesComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) {
|
void ProxyShapesComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) {
|
||||||
|
|
||||||
const Entity entity = mEntities[srcIndex];
|
const Entity proxyShapeEntity = mProxyShapesEntities[srcIndex];
|
||||||
|
|
||||||
const bool isFirstProxyShapeOfBody = mMapEntityToComponentIndex[entity] == srcIndex;
|
|
||||||
|
|
||||||
assert(isFirstProxyShapeOfBody || hasPreviousProxyShape(srcIndex));
|
|
||||||
|
|
||||||
// Copy the data of the source component to the destination location
|
// Copy the data of the source component to the destination location
|
||||||
new (mEntities + destIndex) Entity(mEntities[srcIndex]);
|
new (mProxyShapesEntities + destIndex) Entity(mProxyShapesEntities[srcIndex]);
|
||||||
|
new (mBodiesEntities + destIndex) Entity(mBodiesEntities[srcIndex]);
|
||||||
mProxyShapes[destIndex] = mProxyShapes[srcIndex];
|
mProxyShapes[destIndex] = mProxyShapes[srcIndex];
|
||||||
new (mBroadPhaseIds + destIndex) int(mBroadPhaseIds[srcIndex]);
|
new (mBroadPhaseIds + destIndex) int(mBroadPhaseIds[srcIndex]);
|
||||||
new (mLocalBounds + destIndex) AABB(mLocalBounds[srcIndex]);
|
new (mLocalBounds + destIndex) AABB(mLocalBounds[srcIndex]);
|
||||||
new (mLocalToBodyTransforms + destIndex) Transform(mLocalToBodyTransforms[srcIndex]);
|
new (mLocalToBodyTransforms + destIndex) Transform(mLocalToBodyTransforms[srcIndex]);
|
||||||
mCollisionShapes[destIndex] = mCollisionShapes[srcIndex];
|
mCollisionShapes[destIndex] = mCollisionShapes[srcIndex];
|
||||||
new (mMasses + destIndex) decimal(mMasses[srcIndex]);
|
new (mMasses + destIndex) decimal(mMasses[srcIndex]);
|
||||||
new (mPreviousBodyProxyShapes + destIndex) uint32(hasPreviousProxyShape(srcIndex) ? mPreviousBodyProxyShapes[srcIndex] : destIndex);
|
|
||||||
new (mNextBodyProxyShapes + destIndex) uint32(hasNextProxyShape(srcIndex) ? mNextBodyProxyShapes[srcIndex] : destIndex);
|
|
||||||
new (mCollisionCategoryBits + destIndex) unsigned short(mCollisionCategoryBits[srcIndex]);
|
new (mCollisionCategoryBits + destIndex) unsigned short(mCollisionCategoryBits[srcIndex]);
|
||||||
new (mCollideWithMaskBits + destIndex) unsigned short(mCollideWithMaskBits[srcIndex]);
|
new (mCollideWithMaskBits + destIndex) unsigned short(mCollideWithMaskBits[srcIndex]);
|
||||||
|
|
||||||
// Update the the next proxy-shape index of the previous proxy-shape
|
|
||||||
if (hasPreviousProxyShape(destIndex)) {
|
|
||||||
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[destIndex]] == srcIndex);
|
|
||||||
mNextBodyProxyShapes[mPreviousBodyProxyShapes[destIndex]] = destIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the the previous proxy-shape index of the next proxy-shape
|
|
||||||
if (hasNextProxyShape(destIndex)) {
|
|
||||||
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[destIndex]] == srcIndex);
|
|
||||||
mPreviousBodyProxyShapes[mNextBodyProxyShapes[destIndex]] = destIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy the source component
|
// Destroy the source component
|
||||||
destroyComponent(srcIndex);
|
destroyComponent(srcIndex);
|
||||||
|
|
||||||
// Update the entity to component index mapping if it is the first proxy-shape of the body
|
assert(!mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
if (isFirstProxyShapeOfBody) {
|
|
||||||
|
|
||||||
mMapEntityToComponentIndex[entity] = destIndex;
|
// Update the entity to component index mapping
|
||||||
assert(mMapEntityToComponentIndex[mEntities[destIndex]] == destIndex);
|
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(proxyShapeEntity, destIndex));
|
||||||
}
|
|
||||||
|
|
||||||
mMapProxyShapeToComponentIndex.add(Pair<const ProxyShape*, uint32>(mProxyShapes[destIndex], destIndex));
|
assert(mMapEntityToComponentIndex[mProxyShapesEntities[destIndex]] == destIndex);
|
||||||
|
|
||||||
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[destIndex]] == destIndex || !hasNextProxyShape(destIndex));
|
|
||||||
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[destIndex]] == destIndex || !hasPreviousProxyShape(destIndex));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap two components in the array
|
// Swap two components in the array
|
||||||
void ProxyShapesComponents::swapComponents(uint32 index1, uint32 index2) {
|
void ProxyShapesComponents::swapComponents(uint32 index1, uint32 index2) {
|
||||||
|
|
||||||
// Copy component 1 data
|
// Copy component 1 data
|
||||||
Entity entity1(mEntities[index1]);
|
Entity proxyShapeEntity1(mProxyShapesEntities[index1]);
|
||||||
|
Entity bodyEntity1(mBodiesEntities[index1]);
|
||||||
ProxyShape* proxyShape1 = mProxyShapes[index1];
|
ProxyShape* proxyShape1 = mProxyShapes[index1];
|
||||||
int broadPhaseId1 = mBroadPhaseIds[index1];
|
int broadPhaseId1 = mBroadPhaseIds[index1];
|
||||||
AABB localBounds1 = mLocalBounds[index1];
|
AABB localBounds1 = mLocalBounds[index1];
|
||||||
Transform localToBodyTransform1 = mLocalToBodyTransforms[index1];
|
Transform localToBodyTransform1 = mLocalToBodyTransforms[index1];
|
||||||
CollisionShape* collisionShape1 = mCollisionShapes[index1];
|
CollisionShape* collisionShape1 = mCollisionShapes[index1];
|
||||||
decimal mass1 = mMasses[index1];
|
decimal mass1 = mMasses[index1];
|
||||||
uint32 previousProxyShape1 = hasPreviousProxyShape(index1) ? mPreviousBodyProxyShapes[index1] : index2;
|
|
||||||
uint32 nextProxyShape1 = hasNextProxyShape(index1) ? mNextBodyProxyShapes[index1] : index2;
|
|
||||||
unsigned short collisionCategoryBits1 = mCollisionCategoryBits[index1];
|
unsigned short collisionCategoryBits1 = mCollisionCategoryBits[index1];
|
||||||
unsigned short collideWithMaskBits1 = mCollideWithMaskBits[index1];
|
unsigned short collideWithMaskBits1 = mCollideWithMaskBits[index1];
|
||||||
|
|
||||||
const bool isFirstBodyProxyShape1 = mMapEntityToComponentIndex[mEntities[index1]] == index1;
|
|
||||||
|
|
||||||
// Destroy component 1
|
// Destroy component 1
|
||||||
destroyComponent(index1);
|
destroyComponent(index1);
|
||||||
|
|
||||||
moveComponentToIndex(index2, index1);
|
moveComponentToIndex(index2, index1);
|
||||||
|
|
||||||
// Reconstruct component 1 at component 2 location
|
// Reconstruct component 1 at component 2 location
|
||||||
new (mEntities + index2) Entity(entity1);
|
new (mProxyShapesEntities + index2) Entity(proxyShapeEntity1);
|
||||||
|
new (mBodiesEntities + index2) Entity(bodyEntity1);
|
||||||
mProxyShapes[index2] = proxyShape1;
|
mProxyShapes[index2] = proxyShape1;
|
||||||
new (mBroadPhaseIds + index2) int(broadPhaseId1);
|
new (mBroadPhaseIds + index2) int(broadPhaseId1);
|
||||||
new (mLocalBounds + index2) AABB(localBounds1);
|
new (mLocalBounds + index2) AABB(localBounds1);
|
||||||
new (mLocalToBodyTransforms + index2) Transform(localToBodyTransform1);
|
new (mLocalToBodyTransforms + index2) Transform(localToBodyTransform1);
|
||||||
mCollisionShapes[index2] = collisionShape1;
|
mCollisionShapes[index2] = collisionShape1;
|
||||||
new (mMasses + index2) decimal(mass1);
|
new (mMasses + index2) decimal(mass1);
|
||||||
new (mPreviousBodyProxyShapes + index2) uint32(previousProxyShape1);
|
|
||||||
new (mNextBodyProxyShapes + index2) uint32(nextProxyShape1);
|
|
||||||
new (mCollisionCategoryBits + index2) unsigned short(collisionCategoryBits1);
|
new (mCollisionCategoryBits + index2) unsigned short(collisionCategoryBits1);
|
||||||
new (mCollideWithMaskBits + index2) unsigned short(collideWithMaskBits1);
|
new (mCollideWithMaskBits + index2) unsigned short(collideWithMaskBits1);
|
||||||
|
|
||||||
// Update the the next proxy-shape index of the previous proxy-shape
|
// Update the entity to component index mapping
|
||||||
if (hasPreviousProxyShape(index2)) {
|
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(proxyShapeEntity1, index2));
|
||||||
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index2]] == index1);
|
|
||||||
mNextBodyProxyShapes[mPreviousBodyProxyShapes[index2]] = index2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the the previous proxy-shape index of the next proxy-shape
|
assert(mMapEntityToComponentIndex[mProxyShapesEntities[index1]] == index1);
|
||||||
if (hasNextProxyShape(index2)) {
|
assert(mMapEntityToComponentIndex[mProxyShapesEntities[index2]] == index2);
|
||||||
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index2]] == index1);
|
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||||
mPreviousBodyProxyShapes[mNextBodyProxyShapes[index2]] = index2;
|
|
||||||
}
|
|
||||||
|
|
||||||
mMapProxyShapeToComponentIndex.add(Pair<const ProxyShape*, uint32>(mProxyShapes[index2], index2));
|
|
||||||
|
|
||||||
// Update the entity to component index mapping if it is the first body proxy-shape
|
|
||||||
if (isFirstBodyProxyShape1) {
|
|
||||||
assert(!hasPreviousProxyShape(index2));
|
|
||||||
mMapEntityToComponentIndex[entity1] = index2;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index1]] == index1 || !hasNextProxyShape(index1));
|
|
||||||
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index2]] == index2 || !hasNextProxyShape(index2));
|
|
||||||
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index1]] == index1 || !hasPreviousProxyShape(index1));
|
|
||||||
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index2]] == index2 || !hasPreviousProxyShape(index2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a component at a given index
|
// Remove a component at a given index
|
||||||
void ProxyShapesComponents::removeComponent(uint32 index) {
|
void ProxyShapesComponents::removeComponent(Entity proxyShapeEntity) {
|
||||||
|
|
||||||
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
|
uint index = mMapEntityToComponentIndex[proxyShapeEntity];
|
||||||
|
|
||||||
assert(index < mNbComponents);
|
assert(index < mNbComponents);
|
||||||
|
|
||||||
|
@ -342,59 +256,6 @@ void ProxyShapesComponents::removeComponent(uint32 index) {
|
||||||
// we replace it with the last element of the array. But we need to make sure that sleeping
|
// we replace it with the last element of the array. But we need to make sure that sleeping
|
||||||
// and non-sleeping components stay grouped together.
|
// and non-sleeping components stay grouped together.
|
||||||
|
|
||||||
// If the proxy-shape to destroy does not have a previous proxy-shape in the linked-list of proxy-shapes of its body
|
|
||||||
if (!hasPreviousProxyShape(index)) {
|
|
||||||
|
|
||||||
// Remove the mapping from entity to component index
|
|
||||||
mMapEntityToComponentIndex.remove(mEntities[index]);
|
|
||||||
|
|
||||||
// If the proxy-shape has a next proxy-shape in the linked-list
|
|
||||||
if (hasNextProxyShape(index)) {
|
|
||||||
|
|
||||||
assert(mEntities[index] == mEntities[mNextBodyProxyShapes[index]]);
|
|
||||||
|
|
||||||
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(mEntities[mNextBodyProxyShapes[index]], mNextBodyProxyShapes[index]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the linked-list of proxy-shapes of a body when a proxy-shape is removed
|
|
||||||
if (hasPreviousProxyShape(index)) {
|
|
||||||
|
|
||||||
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] == index);
|
|
||||||
assert(mEntities[index] == mEntities[mPreviousBodyProxyShapes[index]]);
|
|
||||||
|
|
||||||
// If the current proxy-shape to remove has a next proxy-shape in the linked-list
|
|
||||||
if (hasNextProxyShape(index)) {
|
|
||||||
|
|
||||||
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index);
|
|
||||||
|
|
||||||
// Make sure the next proxy-shape will follow the previous proxy-shape in the linked-list
|
|
||||||
mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] = mNextBodyProxyShapes[index];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] = mPreviousBodyProxyShapes[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the linked-list of proxy-shapes of a body when a proxy-shape is removed
|
|
||||||
if (hasNextProxyShape(index)) {
|
|
||||||
|
|
||||||
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index);
|
|
||||||
assert(mEntities[index] == mEntities[mNextBodyProxyShapes[index]]);
|
|
||||||
|
|
||||||
// If the current proxy-shape to remove has a previous proxy-shape in the linked-list
|
|
||||||
if (hasPreviousProxyShape(index)) {
|
|
||||||
|
|
||||||
// Make sure the previous proxy-shape will precede the next proxy-shape in the linked-list
|
|
||||||
mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] = mPreviousBodyProxyShapes[index];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] = mNextBodyProxyShapes[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy the component
|
// Destroy the component
|
||||||
destroyComponent(index);
|
destroyComponent(index);
|
||||||
|
|
||||||
|
@ -427,30 +288,22 @@ void ProxyShapesComponents::removeComponent(uint32 index) {
|
||||||
mSleepingStartIndex--;
|
mSleepingStartIndex--;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(mSleepingStartIndex <= mNbComponents);
|
|
||||||
mNbComponents--;
|
mNbComponents--;
|
||||||
}
|
|
||||||
|
|
||||||
// Return true if a given proxy-shape component has a previous proxy-shape in the linked-list of proxy-shapes of a body
|
assert(mSleepingStartIndex <= mNbComponents);
|
||||||
bool ProxyShapesComponents::hasPreviousProxyShape(uint32 index) const {
|
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||||
assert(index < mNbComponents);
|
|
||||||
return mPreviousBodyProxyShapes[index] != index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return true if a given proxy-shape component has a next proxy-shape in the linked-list of proxy-shapes of a body
|
|
||||||
bool ProxyShapesComponents::hasNextProxyShape(uint32 index) const {
|
|
||||||
assert(index < mNbComponents);
|
|
||||||
return mNextBodyProxyShapes[index] != index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy a component at a given index
|
// Destroy a component at a given index
|
||||||
void ProxyShapesComponents::destroyComponent(uint32 index) {
|
void ProxyShapesComponents::destroyComponent(uint32 index) {
|
||||||
|
|
||||||
assert(index < mNbComponents);
|
assert(index < mNbComponents);
|
||||||
|
assert(mMapEntityToComponentIndex[mProxyShapesEntities[index]] == index);
|
||||||
|
|
||||||
mMapProxyShapeToComponentIndex.remove(mProxyShapes[index]);
|
mMapEntityToComponentIndex.remove(mProxyShapesEntities[index]);
|
||||||
|
|
||||||
mEntities[index].~Entity();
|
mProxyShapesEntities[index].~Entity();
|
||||||
|
mBodiesEntities[index].~Entity();
|
||||||
mProxyShapes[index] = nullptr;
|
mProxyShapes[index] = nullptr;
|
||||||
mLocalBounds[index].~AABB();
|
mLocalBounds[index].~AABB();
|
||||||
mLocalToBodyTransforms[index].~Transform();
|
mLocalToBodyTransforms[index].~Transform();
|
||||||
|
@ -492,31 +345,4 @@ void ProxyShapesComponents::setIsEntitySleeping(Entity entity, bool isSleeping)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(mSleepingStartIndex <= mNbComponents);
|
assert(mSleepingStartIndex <= mNbComponents);
|
||||||
assert(mPreviousBodyProxyShapes[mNextBodyProxyShapes[index]] == index || !hasNextProxyShape(index));
|
|
||||||
assert(mNextBodyProxyShapes[mPreviousBodyProxyShapes[index]] == index || !hasPreviousProxyShape(index));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove all the components of a given entity
|
|
||||||
void ProxyShapesComponents::removeComponents(Entity entity) {
|
|
||||||
|
|
||||||
auto it = mMapEntityToComponentIndex.find(entity);
|
|
||||||
|
|
||||||
// While there are components for this entity
|
|
||||||
while (it != mMapEntityToComponentIndex.end()) {
|
|
||||||
|
|
||||||
// Remove the component
|
|
||||||
removeComponent(it->second);
|
|
||||||
|
|
||||||
it = mMapEntityToComponentIndex.find(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!mMapEntityToComponentIndex.containsKey(entity));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove a given proxy-shape
|
|
||||||
void ProxyShapesComponents::removeComponent(const ProxyShape* proxyShape) {
|
|
||||||
|
|
||||||
uint32 index = mMapProxyShapeToComponentIndex[proxyShape];
|
|
||||||
|
|
||||||
removeComponent(index);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,11 +45,9 @@ class ProxyShape;
|
||||||
|
|
||||||
// Class ProxyShapesComponents
|
// Class ProxyShapesComponents
|
||||||
/**
|
/**
|
||||||
* This class represent the component of the ECS that contains the proxy-shapes of the
|
* This class represent the component of the ECS that contains data about the the proxy-shapes of the
|
||||||
* different entities. There can be several proxy shapes for each entity (body). We store
|
* different bodies. We also make sure that proxy shapes of sleeping entities (bodies) are
|
||||||
* the proxy shapes in a flat array but we keep two arrays with previous/next proxy shapes
|
* always stored at the end of the array.
|
||||||
* link information to quickly know all the proxy shapes of a given entity (body). We also make
|
|
||||||
* sure that proxy shapes of sleeping entities (bodies) are always stored at the end of the array.
|
|
||||||
*/
|
*/
|
||||||
class ProxyShapesComponents : public Components {
|
class ProxyShapesComponents : public Components {
|
||||||
|
|
||||||
|
@ -57,22 +55,22 @@ class ProxyShapesComponents : public Components {
|
||||||
|
|
||||||
// -------------------- Constants -------------------- //
|
// -------------------- Constants -------------------- //
|
||||||
|
|
||||||
const size_t COMPONENT_DATA_SIZE = sizeof(Entity) + sizeof(ProxyShape*) + sizeof(int) + sizeof(AABB) +
|
const size_t COMPONENT_DATA_SIZE = sizeof(Entity) + sizeof(Entity) + sizeof(ProxyShape*) + sizeof(int) + sizeof(AABB) +
|
||||||
sizeof(Transform) + sizeof(CollisionShape*) + sizeof(decimal) + sizeof(uint32) +
|
sizeof(Transform) + sizeof(CollisionShape*) + sizeof(decimal) + sizeof(unsigned short) +
|
||||||
sizeof(uint32) + sizeof(unsigned short) + sizeof(unsigned short);
|
sizeof(unsigned short);
|
||||||
|
|
||||||
// -------------------- Attributes -------------------- //
|
// -------------------- Attributes -------------------- //
|
||||||
|
|
||||||
/// Index of the first component of a sleeping entity (sleeping components are stored at the end)
|
/// Index of the first component of a sleeping entity (sleeping components are stored at the end)
|
||||||
uint32 mSleepingStartIndex;
|
uint32 mSleepingStartIndex;
|
||||||
|
|
||||||
/// Map a proxy shape to the index of the corresponding component in the array
|
/// Array of entities of each component
|
||||||
Map<const ProxyShape*, uint32> mMapProxyShapeToComponentIndex;
|
Entity* mBodiesEntities;
|
||||||
|
|
||||||
/// Array of entities of each component
|
/// Array of entities of each component
|
||||||
Entity* mEntities;
|
Entity* mProxyShapesEntities;
|
||||||
|
|
||||||
/// Array of pointers to the proxy-shapes
|
/// Array of pointer to the proxy-shapes
|
||||||
ProxyShape** mProxyShapes;
|
ProxyShape** mProxyShapes;
|
||||||
|
|
||||||
/// Ids of the proxy-shapes for the broad-phase algorithm
|
/// Ids of the proxy-shapes for the broad-phase algorithm
|
||||||
|
@ -91,14 +89,6 @@ class ProxyShapesComponents : public Components {
|
||||||
/// Masses (in kilogramms) of the proxy-shapes
|
/// Masses (in kilogramms) of the proxy-shapes
|
||||||
decimal* mMasses;
|
decimal* mMasses;
|
||||||
|
|
||||||
/// Index of the previous proxy-shape in the same body
|
|
||||||
/// mPreviousBodyProxyShapes[i] == i means that the proxy-shape component has no previous proxy-shape
|
|
||||||
uint32* mPreviousBodyProxyShapes;
|
|
||||||
|
|
||||||
/// Index of the next proxy-shape in the same body
|
|
||||||
/// mNextBodyProxyShapes[i] == i means that the proxy-shape component has no next proxy-shape
|
|
||||||
uint32* mNextBodyProxyShapes;
|
|
||||||
|
|
||||||
/// Array of bits used to define the collision category of this shape.
|
/// Array of bits used to define the collision category of this shape.
|
||||||
/// You can set a single bit to one to define a category value for this
|
/// You can set a single bit to one to define a category value for this
|
||||||
/// shape. This value is one (0x0001) by default. This variable can be used
|
/// shape. This value is one (0x0001) by default. This variable can be used
|
||||||
|
@ -114,9 +104,6 @@ class ProxyShapesComponents : public Components {
|
||||||
|
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
/// Remove a component at a given index
|
|
||||||
void removeComponent(uint32 index);
|
|
||||||
|
|
||||||
/// Destroy a component at a given index
|
/// Destroy a component at a given index
|
||||||
void destroyComponent(uint32 index);
|
void destroyComponent(uint32 index);
|
||||||
|
|
||||||
|
@ -126,20 +113,12 @@ class ProxyShapesComponents : public Components {
|
||||||
/// Swap two components in the array
|
/// Swap two components in the array
|
||||||
void swapComponents(uint32 index1, uint32 index2);
|
void swapComponents(uint32 index1, uint32 index2);
|
||||||
|
|
||||||
/// Add a new proxy-shape at the end of the linked-list of proxy-shapes of a given entity
|
|
||||||
void linkProxyShapeWithEntity(Entity entity, uint32 proxyShapeComponentIndex);
|
|
||||||
|
|
||||||
/// Return true if a given proxy-shape component has a previous proxy-shape in the linked-list of proxy-shapes of a body
|
|
||||||
bool hasPreviousProxyShape(uint32 index) const;
|
|
||||||
|
|
||||||
/// Return true if a given proxy-shape component has a next proxy-shape in the linked-list of proxy-shapes of a body
|
|
||||||
bool hasNextProxyShape(uint32 index) const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Structure for the data of a proxy shape component
|
/// Structure for the data of a proxy shape component
|
||||||
struct ProxyShapeComponent {
|
struct ProxyShapeComponent {
|
||||||
|
|
||||||
|
Entity bodyEntity;
|
||||||
ProxyShape* proxyShape;
|
ProxyShape* proxyShape;
|
||||||
int broadPhaseId;
|
int broadPhaseId;
|
||||||
AABB localBounds;
|
AABB localBounds;
|
||||||
|
@ -150,10 +129,10 @@ class ProxyShapesComponents : public Components {
|
||||||
unsigned short collideWithMaskBits;
|
unsigned short collideWithMaskBits;
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
ProxyShapeComponent(ProxyShape* proxyShape, int broadPhaseId, AABB localBounds, Transform localToBodyTransform,
|
ProxyShapeComponent(Entity bodyEntity, ProxyShape* proxyShape, int broadPhaseId, AABB localBounds, Transform localToBodyTransform,
|
||||||
CollisionShape* collisionShape, decimal mass, unsigned short collisionCategoryBits,
|
CollisionShape* collisionShape, decimal mass, unsigned short collisionCategoryBits,
|
||||||
unsigned short collideWithMaskBits)
|
unsigned short collideWithMaskBits)
|
||||||
:proxyShape(proxyShape), broadPhaseId(broadPhaseId), localBounds(localBounds), localToBodyTransform(localToBodyTransform),
|
:bodyEntity(bodyEntity), proxyShape(proxyShape), broadPhaseId(broadPhaseId), localBounds(localBounds), localToBodyTransform(localToBodyTransform),
|
||||||
collisionShape(collisionShape), mass(mass), collisionCategoryBits(collisionCategoryBits), collideWithMaskBits(collideWithMaskBits) {
|
collisionShape(collisionShape), mass(mass), collisionCategoryBits(collisionCategoryBits), collideWithMaskBits(collideWithMaskBits) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -165,166 +144,140 @@ class ProxyShapesComponents : public Components {
|
||||||
ProxyShapesComponents(MemoryAllocator& allocator);
|
ProxyShapesComponents(MemoryAllocator& allocator);
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~ProxyShapesComponents();
|
virtual ~ProxyShapesComponents();
|
||||||
|
|
||||||
/// Allocate memory for a given number of components
|
/// Allocate memory for a given number of components
|
||||||
void allocate(uint32 nbComponentsToAllocate);
|
void allocate(uint32 nbComponentsToAllocate);
|
||||||
|
|
||||||
/// Add a component
|
/// Add a component
|
||||||
void addComponent(Entity entity, bool isSleeping, const ProxyShapeComponent& component);
|
void addComponent(Entity proxyShapeEntity, bool isSleeping, const ProxyShapeComponent& component);
|
||||||
|
|
||||||
/// Remove all the components of a given entity
|
/// Remove a component at a given index
|
||||||
void removeComponents(Entity entity);
|
void removeComponent(Entity proxyShapeEntity);
|
||||||
|
|
||||||
/// Remove a given proxy-shape
|
|
||||||
void removeComponent(const ProxyShape* proxyShape);
|
|
||||||
|
|
||||||
/// Notify if a given entity is sleeping or not
|
/// Notify if a given entity is sleeping or not
|
||||||
void setIsEntitySleeping(Entity entity, bool isSleeping);
|
void setIsEntitySleeping(Entity entity, bool isSleeping);
|
||||||
|
|
||||||
/// Return the mass of a proxy-shape
|
/// Return the mass of a proxy-shape
|
||||||
decimal getMass(const ProxyShape* proxyShape) const;
|
decimal getMass(Entity proxyShapeEntity) const;
|
||||||
|
|
||||||
|
/// Return a pointer to a given proxy-shape
|
||||||
|
ProxyShape* getProxyShape(Entity proxyShapeEntity) const;
|
||||||
|
|
||||||
/// Return the local-to-body transform of a proxy-shape
|
/// Return the local-to-body transform of a proxy-shape
|
||||||
const Transform& getLocalToBodyTransform(const ProxyShape* proxyShape) const;
|
const Transform& getLocalToBodyTransform(Entity proxyShapeEntity) const;
|
||||||
|
|
||||||
/// Set the local-to-body transform of a proxy-shape
|
/// Set the local-to-body transform of a proxy-shape
|
||||||
void setLocalToBodyTransform(const ProxyShape* proxyShape, const Transform& transform);
|
void setLocalToBodyTransform(Entity proxyShapeEntity, const Transform& transform);
|
||||||
|
|
||||||
/// Return a pointer to the collision shape of a proxy-shape
|
/// Return a pointer to the collision shape of a proxy-shape
|
||||||
CollisionShape* getCollisionShape(const ProxyShape* proxyShape) const;
|
CollisionShape* getCollisionShape(Entity proxyShapeEntity) const;
|
||||||
|
|
||||||
/// Return the broad-phase id of a given proxy shape
|
/// Return the broad-phase id of a given proxy shape
|
||||||
int getBroadPhaseId(const ProxyShape* proxyShape) const;
|
int getBroadPhaseId(Entity proxyShapeEntity) const;
|
||||||
|
|
||||||
/// Set the broad-phase id of a given proxy shape
|
/// Set the broad-phase id of a given proxy shape
|
||||||
void setBroadPhaseId(const ProxyShape* proxyShape, int broadPhaseId);
|
void setBroadPhaseId(Entity proxyShapeEntity, 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 collision category bits of a given proxy-shape
|
/// Return the collision category bits of a given proxy-shape
|
||||||
unsigned short getCollisionCategoryBits(const ProxyShape* proxyShape) const;
|
unsigned short getCollisionCategoryBits(Entity proxyShapeEntity) const;
|
||||||
|
|
||||||
/// Set the collision category bits of a given proxy-shape
|
/// Set the collision category bits of a given proxy-shape
|
||||||
void setCollisionCategoryBits(const ProxyShape* proxyShape, unsigned short collisionCategoryBits);
|
void setCollisionCategoryBits(Entity proxyShapeEntity, unsigned short collisionCategoryBits);
|
||||||
|
|
||||||
/// Return the "collide with" mask bits of a given proxy-shape
|
/// Return the "collide with" mask bits of a given proxy-shape
|
||||||
unsigned short getCollideWithMaskBits(const ProxyShape* proxyShape) const;
|
unsigned short getCollideWithMaskBits(Entity proxyShapeEntity) const;
|
||||||
|
|
||||||
/// Set the "collide with" mask bits of a given proxy-shape
|
/// Set the "collide with" mask bits of a given proxy-shape
|
||||||
void setCollideWithMaskBits(const ProxyShape* proxyShape, unsigned short collideWithMaskBits);
|
void setCollideWithMaskBits(Entity proxyShapeEntity, unsigned short collideWithMaskBits);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the mass of a proxy-shape
|
// Return the mass of a proxy-shape
|
||||||
inline decimal ProxyShapesComponents::getMass(const ProxyShape* proxyShape) const {
|
inline decimal ProxyShapesComponents::getMass(Entity proxyShapeEntity) const {
|
||||||
|
|
||||||
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape));
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
return mMasses[mMapProxyShapeToComponentIndex[proxyShape]];
|
return mMasses[mMapEntityToComponentIndex[proxyShapeEntity]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a pointer to a given proxy-shape
|
||||||
|
inline ProxyShape* ProxyShapesComponents::getProxyShape(Entity proxyShapeEntity) const {
|
||||||
|
|
||||||
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
|
return mProxyShapes[mMapEntityToComponentIndex[proxyShapeEntity]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the local-to-body transform of a proxy-shape
|
// Return the local-to-body transform of a proxy-shape
|
||||||
inline const Transform& ProxyShapesComponents::getLocalToBodyTransform(const ProxyShape* proxyShape) const {
|
inline const Transform& ProxyShapesComponents::getLocalToBodyTransform(Entity proxyShapeEntity) const {
|
||||||
|
|
||||||
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape));
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
return mLocalToBodyTransforms[mMapProxyShapeToComponentIndex[proxyShape]];
|
return mLocalToBodyTransforms[mMapEntityToComponentIndex[proxyShapeEntity]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the local-to-body transform of a proxy-shape
|
// Set the local-to-body transform of a proxy-shape
|
||||||
inline void ProxyShapesComponents::setLocalToBodyTransform(const ProxyShape* proxyShape, const Transform& transform) {
|
inline void ProxyShapesComponents::setLocalToBodyTransform(Entity proxyShapeEntity, const Transform& transform) {
|
||||||
|
|
||||||
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape));
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
mLocalToBodyTransforms[mMapProxyShapeToComponentIndex[proxyShape]] = transform;
|
mLocalToBodyTransforms[mMapEntityToComponentIndex[proxyShapeEntity]] = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a pointer to the collision shape of a proxy-shape
|
// Return a pointer to the collision shape of a proxy-shape
|
||||||
inline CollisionShape* ProxyShapesComponents::getCollisionShape(const ProxyShape* proxyShape) const {
|
inline CollisionShape* ProxyShapesComponents::getCollisionShape(Entity proxyShapeEntity) const {
|
||||||
|
|
||||||
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape));
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
return mCollisionShapes[mMapProxyShapeToComponentIndex[proxyShape]];
|
return mCollisionShapes[mMapEntityToComponentIndex[proxyShapeEntity]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the broad-phase id of a given proxy shape
|
// Return the broad-phase id of a given proxy shape
|
||||||
inline int ProxyShapesComponents::getBroadPhaseId(const ProxyShape* proxyShape) const {
|
inline int ProxyShapesComponents::getBroadPhaseId(Entity proxyShapeEntity) const {
|
||||||
|
|
||||||
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape));
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
return mBroadPhaseIds[mMapProxyShapeToComponentIndex[proxyShape]];
|
return mBroadPhaseIds[mMapEntityToComponentIndex[proxyShapeEntity]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the broad-phase id of a given proxy shape
|
// Set the broad-phase id of a given proxy shape
|
||||||
inline void ProxyShapesComponents::setBroadPhaseId(const ProxyShape* proxyShape, int broadPhaseId) {
|
inline void ProxyShapesComponents::setBroadPhaseId(Entity proxyShapeEntity, int broadPhaseId) {
|
||||||
|
|
||||||
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape));
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
mBroadPhaseIds[mMapProxyShapeToComponentIndex[proxyShape]] = broadPhaseId;
|
mBroadPhaseIds[mMapEntityToComponentIndex[proxyShapeEntity]] = 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the collision category bits of a given proxy-shape
|
// Return the collision category bits of a given proxy-shape
|
||||||
inline unsigned short ProxyShapesComponents::getCollisionCategoryBits(const ProxyShape* proxyShape) const {
|
inline unsigned short ProxyShapesComponents::getCollisionCategoryBits(Entity proxyShapeEntity) const {
|
||||||
|
|
||||||
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape));
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
return mCollisionCategoryBits[mMapProxyShapeToComponentIndex[proxyShape]];
|
return mCollisionCategoryBits[mMapEntityToComponentIndex[proxyShapeEntity]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the "collide with" mask bits of a given proxy-shape
|
// Return the "collide with" mask bits of a given proxy-shape
|
||||||
inline unsigned short ProxyShapesComponents::getCollideWithMaskBits(const ProxyShape* proxyShape) const {
|
inline unsigned short ProxyShapesComponents::getCollideWithMaskBits(Entity proxyShapeEntity) const {
|
||||||
|
|
||||||
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape));
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
return mCollideWithMaskBits[mMapProxyShapeToComponentIndex[proxyShape]];
|
return mCollideWithMaskBits[mMapEntityToComponentIndex[proxyShapeEntity]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the collision category bits of a given proxy-shape
|
// Set the collision category bits of a given proxy-shape
|
||||||
inline void ProxyShapesComponents::setCollisionCategoryBits(const ProxyShape* proxyShape, unsigned short collisionCategoryBits) {
|
inline void ProxyShapesComponents::setCollisionCategoryBits(Entity proxyShapeEntity, unsigned short collisionCategoryBits) {
|
||||||
|
|
||||||
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape));
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
mCollisionCategoryBits[mMapProxyShapeToComponentIndex[proxyShape]] = collisionCategoryBits;
|
mCollisionCategoryBits[mMapEntityToComponentIndex[proxyShapeEntity]] = collisionCategoryBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the "collide with" mask bits of a given proxy-shape
|
// Set the "collide with" mask bits of a given proxy-shape
|
||||||
inline void ProxyShapesComponents::setCollideWithMaskBits(const ProxyShape* proxyShape, unsigned short collideWithMaskBits) {
|
inline void ProxyShapesComponents::setCollideWithMaskBits(Entity proxyShapeEntity, unsigned short collideWithMaskBits) {
|
||||||
|
|
||||||
assert(mMapProxyShapeToComponentIndex.containsKey(proxyShape));
|
assert(mMapEntityToComponentIndex.containsKey(proxyShapeEntity));
|
||||||
|
|
||||||
mCollideWithMaskBits[mMapProxyShapeToComponentIndex[proxyShape]] = collideWithMaskBits;
|
mCollideWithMaskBits[mMapEntityToComponentIndex[proxyShapeEntity]] = collideWithMaskBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,20 +82,20 @@ void TransformComponents::allocate(uint32 nbComponentsToAllocate) {
|
||||||
|
|
||||||
// Copy component data from the previous buffer to the new one
|
// Copy component data from the previous buffer to the new one
|
||||||
memcpy(newTransforms, mTransforms, mNbComponents * sizeof(Transform));
|
memcpy(newTransforms, mTransforms, mNbComponents * sizeof(Transform));
|
||||||
memcpy(newEntities, mEntities, mNbComponents * sizeof(Entity));
|
memcpy(newEntities, mBodies, mNbComponents * sizeof(Entity));
|
||||||
|
|
||||||
// Deallocate previous memory
|
// Deallocate previous memory
|
||||||
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * COMPONENT_DATA_SIZE);
|
mMemoryAllocator.release(mBuffer, mNbAllocatedComponents * COMPONENT_DATA_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mBuffer = newBuffer;
|
mBuffer = newBuffer;
|
||||||
mEntities = newEntities;
|
mBodies = newEntities;
|
||||||
mTransforms = newTransforms;
|
mTransforms = newTransforms;
|
||||||
mNbAllocatedComponents = nbComponentsToAllocate;
|
mNbAllocatedComponents = nbComponentsToAllocate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a component
|
// Add a component
|
||||||
void TransformComponents::addComponent(Entity entity, bool isSleeping, const TransformComponent& component) {
|
void TransformComponents::addComponent(Entity bodyEntity, bool isSleeping, const TransformComponent& component) {
|
||||||
|
|
||||||
// If we need to allocate more components
|
// If we need to allocate more components
|
||||||
if (mNbComponents == mNbAllocatedComponents) {
|
if (mNbComponents == mNbAllocatedComponents) {
|
||||||
|
@ -128,11 +128,11 @@ void TransformComponents::addComponent(Entity entity, bool isSleeping, const Tra
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the new component data
|
// Insert the new component data
|
||||||
new (mEntities + index) Entity(entity);
|
new (mBodies + index) Entity(bodyEntity);
|
||||||
new (mTransforms + index) Transform(component.transform);
|
new (mTransforms + index) Transform(component.transform);
|
||||||
|
|
||||||
// Map the entity with the new component lookup index
|
// Map the entity with the new component lookup index
|
||||||
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, index));
|
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(bodyEntity, index));
|
||||||
|
|
||||||
mNbComponents++;
|
mNbComponents++;
|
||||||
|
|
||||||
|
@ -141,7 +141,11 @@ void TransformComponents::addComponent(Entity entity, bool isSleeping, const Tra
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a component at a given index
|
// Remove a component at a given index
|
||||||
void TransformComponents::removeComponent(uint32 index) {
|
void TransformComponents::removeComponent(Entity bodyEntity) {
|
||||||
|
|
||||||
|
assert(mMapEntityToComponentIndex.containsKey(bodyEntity));
|
||||||
|
|
||||||
|
uint index = mMapEntityToComponentIndex[bodyEntity];
|
||||||
|
|
||||||
assert(index < mNbComponents);
|
assert(index < mNbComponents);
|
||||||
|
|
||||||
|
@ -229,26 +233,28 @@ void TransformComponents::setIsEntitySleeping(Entity entity, bool isSleeping) {
|
||||||
// The destination location must contain a constructed object
|
// The destination location must contain a constructed object
|
||||||
void TransformComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) {
|
void TransformComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) {
|
||||||
|
|
||||||
// Copy the data of the source component to the destination location
|
const Entity entity = mBodies[srcIndex];
|
||||||
new (mEntities + destIndex) Entity(mEntities[srcIndex]);
|
|
||||||
new (mTransforms + destIndex) Transform(mTransforms[srcIndex]);
|
|
||||||
|
|
||||||
const Entity entity = mEntities[srcIndex];
|
// Copy the data of the source component to the destination location
|
||||||
|
new (mBodies + destIndex) Entity(mBodies[srcIndex]);
|
||||||
|
new (mTransforms + destIndex) Transform(mTransforms[srcIndex]);
|
||||||
|
|
||||||
// Destroy the source component
|
// Destroy the source component
|
||||||
destroyComponent(srcIndex);
|
destroyComponent(srcIndex);
|
||||||
|
|
||||||
|
assert(!mMapEntityToComponentIndex.containsKey(entity));
|
||||||
|
|
||||||
// Update the entity to component index mapping
|
// Update the entity to component index mapping
|
||||||
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, destIndex));
|
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity, destIndex));
|
||||||
|
|
||||||
assert(mMapEntityToComponentIndex[mEntities[destIndex]] == destIndex);
|
assert(mMapEntityToComponentIndex[mBodies[destIndex]] == destIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap two components in the array
|
// Swap two components in the array
|
||||||
void TransformComponents::swapComponents(uint32 index1, uint32 index2) {
|
void TransformComponents::swapComponents(uint32 index1, uint32 index2) {
|
||||||
|
|
||||||
// Copy component 1 data
|
// Copy component 1 data
|
||||||
Entity entity1(mEntities[index1]);
|
Entity entity1(mBodies[index1]);
|
||||||
Transform transform1(mTransforms[index1]);
|
Transform transform1(mTransforms[index1]);
|
||||||
|
|
||||||
// Destroy component 1
|
// Destroy component 1
|
||||||
|
@ -257,14 +263,14 @@ void TransformComponents::swapComponents(uint32 index1, uint32 index2) {
|
||||||
moveComponentToIndex(index2, index1);
|
moveComponentToIndex(index2, index1);
|
||||||
|
|
||||||
// Reconstruct component 1 at component 2 location
|
// Reconstruct component 1 at component 2 location
|
||||||
new (mEntities + index2) Entity(entity1);
|
new (mBodies + index2) Entity(entity1);
|
||||||
new (mTransforms + index2) Transform(transform1);
|
new (mTransforms + index2) Transform(transform1);
|
||||||
|
|
||||||
// Update the entity to component index mapping
|
// Update the entity to component index mapping
|
||||||
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity1, index2));
|
mMapEntityToComponentIndex.add(Pair<Entity, uint32>(entity1, index2));
|
||||||
|
|
||||||
assert(mMapEntityToComponentIndex[mEntities[index1]] == index1);
|
assert(mMapEntityToComponentIndex[mBodies[index1]] == index1);
|
||||||
assert(mMapEntityToComponentIndex[mEntities[index2]] == index2);
|
assert(mMapEntityToComponentIndex[mBodies[index2]] == index2);
|
||||||
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
assert(mNbComponents == static_cast<uint32>(mMapEntityToComponentIndex.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,25 +278,10 @@ void TransformComponents::swapComponents(uint32 index1, uint32 index2) {
|
||||||
void TransformComponents::destroyComponent(uint32 index) {
|
void TransformComponents::destroyComponent(uint32 index) {
|
||||||
|
|
||||||
assert(index < mNbComponents);
|
assert(index < mNbComponents);
|
||||||
assert(mMapEntityToComponentIndex[mEntities[index]] == index);
|
assert(mMapEntityToComponentIndex[mBodies[index]] == index);
|
||||||
|
|
||||||
mMapEntityToComponentIndex.remove(mEntities[index]);
|
mMapEntityToComponentIndex.remove(mBodies[index]);
|
||||||
|
|
||||||
mEntities[index].~Entity();
|
mBodies[index].~Entity();
|
||||||
mTransforms[index].~Transform();
|
mTransforms[index].~Transform();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all the components of a given entity
|
|
||||||
void TransformComponents::removeComponents(Entity entity) {
|
|
||||||
|
|
||||||
auto it = mMapEntityToComponentIndex.find(entity);
|
|
||||||
|
|
||||||
// If there is a component for this entity
|
|
||||||
if (it != mMapEntityToComponentIndex.end()) {
|
|
||||||
|
|
||||||
// Remove the component
|
|
||||||
removeComponent(it->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(!mMapEntityToComponentIndex.containsKey(entity));
|
|
||||||
}
|
|
||||||
|
|
|
@ -58,17 +58,14 @@ class TransformComponents : public Components {
|
||||||
/// Index of the first component of a sleeping entity (sleeping components are stored at the end)
|
/// Index of the first component of a sleeping entity (sleeping components are stored at the end)
|
||||||
uint32 mSleepingStartIndex;
|
uint32 mSleepingStartIndex;
|
||||||
|
|
||||||
/// Array of entities of each component
|
/// Array of body entities of each component
|
||||||
Entity* mEntities;
|
Entity* mBodies;
|
||||||
|
|
||||||
/// Array of transform of each component
|
/// Array of transform of each component
|
||||||
Transform* mTransforms;
|
Transform* mTransforms;
|
||||||
|
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
/// Remove a component at a given index
|
|
||||||
void removeComponent(uint32 index);
|
|
||||||
|
|
||||||
/// Destroy a component at a given index
|
/// Destroy a component at a given index
|
||||||
void destroyComponent(uint32 index);
|
void destroyComponent(uint32 index);
|
||||||
|
|
||||||
|
@ -103,29 +100,29 @@ class TransformComponents : public Components {
|
||||||
void allocate(uint32 nbComponentsToAllocate);
|
void allocate(uint32 nbComponentsToAllocate);
|
||||||
|
|
||||||
/// Add a component
|
/// Add a component
|
||||||
void addComponent(Entity entity, bool isSleeping, const TransformComponent& component);
|
void addComponent(Entity bodyEntity, bool isSleeping, const TransformComponent& component);
|
||||||
|
|
||||||
/// Remove all the components of a given entity
|
/// Remove a component at a given index
|
||||||
void removeComponents(Entity entity);
|
void removeComponent(Entity bodyEntity);
|
||||||
|
|
||||||
/// Return the transform of an entity
|
/// Return the transform of an entity
|
||||||
Transform& getTransform(Entity entity) const;
|
Transform& getTransform(Entity bodyEntity) const;
|
||||||
|
|
||||||
/// Set the transform of an entity
|
/// Set the transform of an entity
|
||||||
void setTransform(Entity entity, const Transform& transform);
|
void setTransform(Entity bodyEntity, const Transform& transform);
|
||||||
|
|
||||||
/// Notify if a given entity is sleeping or not
|
/// Notify if a given entity is sleeping or not
|
||||||
void setIsEntitySleeping(Entity entity, bool isSleeping);
|
void setIsEntitySleeping(Entity bodyEntity, bool isSleeping);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the transform of an entity
|
// Return the transform of an entity
|
||||||
inline Transform& TransformComponents::getTransform(Entity entity) const {
|
inline Transform& TransformComponents::getTransform(Entity bodyEntity) const {
|
||||||
return mTransforms[mMapEntityToComponentIndex[entity]];
|
return mTransforms[mMapEntityToComponentIndex[bodyEntity]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the transform of an entity
|
// Set the transform of an entity
|
||||||
inline void TransformComponents::setTransform(Entity entity, const Transform& transform) {
|
inline void TransformComponents::setTransform(Entity bodyEntity, const Transform& transform) {
|
||||||
mTransforms[mMapEntityToComponentIndex[entity]] = transform;
|
mTransforms[mMapEntityToComponentIndex[bodyEntity]] = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,9 +38,10 @@ uint CollisionWorld::mNbWorlds = 0;
|
||||||
// Constructor
|
// Constructor
|
||||||
CollisionWorld::CollisionWorld(const WorldSettings& worldSettings, Logger* logger, Profiler* profiler)
|
CollisionWorld::CollisionWorld(const WorldSettings& worldSettings, Logger* logger, Profiler* profiler)
|
||||||
: mConfig(worldSettings), mEntityManager(mMemoryManager.getPoolAllocator()),
|
: mConfig(worldSettings), mEntityManager(mMemoryManager.getPoolAllocator()),
|
||||||
mTransformComponents(mMemoryManager.getBaseAllocator()), mProxyShapesComponents(mMemoryManager.getBaseAllocator()),
|
mBodyComponents(mMemoryManager.getBaseAllocator()), mTransformComponents(mMemoryManager.getBaseAllocator()),
|
||||||
mCollisionDetection(this, mProxyShapesComponents, mMemoryManager), mBodies(mMemoryManager.getPoolAllocator()), mCurrentBodyId(0),
|
mProxyShapesComponents(mMemoryManager.getBaseAllocator()), mCollisionDetection(this, mProxyShapesComponents, mMemoryManager),
|
||||||
mFreeBodiesIds(mMemoryManager.getPoolAllocator()), mEventListener(nullptr), mName(worldSettings.worldName),
|
mBodies(mMemoryManager.getPoolAllocator()), mCurrentBodyId(0), mFreeBodiesIds(mMemoryManager.getPoolAllocator()),
|
||||||
|
mEventListener(nullptr), mName(worldSettings.worldName),
|
||||||
mIsProfilerCreatedByUser(profiler != nullptr),
|
mIsProfilerCreatedByUser(profiler != nullptr),
|
||||||
mIsLoggerCreatedByUser(logger != nullptr) {
|
mIsLoggerCreatedByUser(logger != nullptr) {
|
||||||
|
|
||||||
|
@ -131,6 +132,9 @@ CollisionWorld::~CollisionWorld() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(mBodies.size() == 0);
|
assert(mBodies.size() == 0);
|
||||||
|
assert(mBodyComponents.getNbComponents() == 0);
|
||||||
|
assert(mTransformComponents.getNbComponents() == 0);
|
||||||
|
assert(mProxyShapesComponents.getNbComponents() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a collision body and add it to the world
|
// Create a collision body and add it to the world
|
||||||
|
@ -149,7 +153,6 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
|
||||||
// Largest index cannot be used (it is used for invalid index)
|
// Largest index cannot be used (it is used for invalid index)
|
||||||
assert(bodyID < std::numeric_limits<reactphysics3d::bodyindex>::max());
|
assert(bodyID < std::numeric_limits<reactphysics3d::bodyindex>::max());
|
||||||
|
|
||||||
// Add a transform component
|
|
||||||
mTransformComponents.addComponent(entity, false, TransformComponents::TransformComponent(transform));
|
mTransformComponents.addComponent(entity, false, TransformComponents::TransformComponent(transform));
|
||||||
|
|
||||||
// Create the collision body
|
// Create the collision body
|
||||||
|
@ -159,6 +162,10 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
|
||||||
|
|
||||||
assert(collisionBody != nullptr);
|
assert(collisionBody != nullptr);
|
||||||
|
|
||||||
|
// Add the components
|
||||||
|
BodyComponents::BodyComponent bodyComponent(collisionBody);
|
||||||
|
mBodyComponents.addComponent(entity, false, bodyComponent);
|
||||||
|
|
||||||
// Add the collision body to the world
|
// Add the collision body to the world
|
||||||
mBodies.add(collisionBody);
|
mBodies.add(collisionBody);
|
||||||
|
|
||||||
|
@ -197,8 +204,9 @@ void CollisionWorld::destroyCollisionBody(CollisionBody* collisionBody) {
|
||||||
// Reset the contact manifold list of the body
|
// Reset the contact manifold list of the body
|
||||||
collisionBody->resetContactManifoldsList();
|
collisionBody->resetContactManifoldsList();
|
||||||
|
|
||||||
// Destroy the entity and its components
|
mBodyComponents.removeComponent(collisionBody->getEntity());
|
||||||
destroyEntity(collisionBody->getEntity());
|
mTransformComponents.removeComponent(collisionBody->getEntity());
|
||||||
|
mEntityManager.destroyEntity(collisionBody->getEntity());
|
||||||
|
|
||||||
// Call the destructor of the collision body
|
// Call the destructor of the collision body
|
||||||
collisionBody->~CollisionBody();
|
collisionBody->~CollisionBody();
|
||||||
|
@ -239,26 +247,19 @@ void CollisionWorld::resetContactManifoldListsOfBodies() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify the world if a body is sleeping or not
|
// Notify the world if a body is sleeping or not
|
||||||
void CollisionWorld::notifyBodySleeping(Entity entity, bool isSleeping) {
|
void CollisionWorld::notifyBodySleeping(Entity bodyEntity, bool isSleeping) {
|
||||||
|
|
||||||
// TODO : Make sure we notify all the components here ...
|
// TODO : Make sure we notify all the components here ...
|
||||||
|
|
||||||
// Notify all the components
|
// Notify all the components
|
||||||
mTransformComponents.setIsEntitySleeping(entity, isSleeping);
|
mTransformComponents.setIsEntitySleeping(bodyEntity, isSleeping);
|
||||||
mProxyShapesComponents.setIsEntitySleeping(entity, isSleeping);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy an entity and all the associated components
|
// For each proxy-shape of the body
|
||||||
void CollisionWorld::destroyEntity(Entity entity) {
|
const List<Entity>& proxyShapesEntities = mBodyComponents.getProxyShapes(bodyEntity);
|
||||||
|
for (uint i=0; i < proxyShapesEntities.size(); i++) {
|
||||||
|
|
||||||
// Destroy the corresponding entity
|
mProxyShapesComponents.setIsEntitySleeping(proxyShapesEntities[i], isSleeping);
|
||||||
mEntityManager.destroyEntity(entity);
|
}
|
||||||
|
|
||||||
// TODO : Make sure we notify all the components here ...
|
|
||||||
|
|
||||||
// Notify all the components
|
|
||||||
mTransformComponents.removeComponents(entity);
|
|
||||||
mProxyShapesComponents.removeComponents(entity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if the AABBs of two bodies overlap
|
// Test if the AABBs of two bodies overlap
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "constraint/Joint.h"
|
#include "constraint/Joint.h"
|
||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "engine/EntityManager.h"
|
#include "engine/EntityManager.h"
|
||||||
|
#include "components/BodyComponents.h"
|
||||||
#include "components/TransformComponents.h"
|
#include "components/TransformComponents.h"
|
||||||
#include "components/ProxyShapesComponents.h"
|
#include "components/ProxyShapesComponents.h"
|
||||||
|
|
||||||
|
@ -72,6 +73,9 @@ class CollisionWorld {
|
||||||
/// Entity Manager for the ECS
|
/// Entity Manager for the ECS
|
||||||
EntityManager mEntityManager;
|
EntityManager mEntityManager;
|
||||||
|
|
||||||
|
/// Body Components
|
||||||
|
BodyComponents mBodyComponents;
|
||||||
|
|
||||||
/// Transform Components
|
/// Transform Components
|
||||||
TransformComponents mTransformComponents;
|
TransformComponents mTransformComponents;
|
||||||
|
|
||||||
|
@ -128,9 +132,6 @@ class CollisionWorld {
|
||||||
/// Notify the world if a body is sleeping or not
|
/// Notify the world if a body is sleeping or not
|
||||||
void notifyBodySleeping(Entity entity, bool isSleeping);
|
void notifyBodySleeping(Entity entity, bool isSleeping);
|
||||||
|
|
||||||
/// Destroy an entity and all the associated components
|
|
||||||
void destroyEntity(Entity entity);
|
|
||||||
|
|
||||||
public :
|
public :
|
||||||
|
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
|
@ -428,7 +428,6 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
|
||||||
// Largest index cannot be used (it is used for invalid index)
|
// Largest index cannot be used (it is used for invalid index)
|
||||||
assert(bodyID < std::numeric_limits<reactphysics3d::bodyindex>::max());
|
assert(bodyID < std::numeric_limits<reactphysics3d::bodyindex>::max());
|
||||||
|
|
||||||
// Add a transform component
|
|
||||||
mTransformComponents.addComponent(entity, false, TransformComponents::TransformComponent(transform));
|
mTransformComponents.addComponent(entity, false, TransformComponents::TransformComponent(transform));
|
||||||
|
|
||||||
// Create the rigid body
|
// Create the rigid body
|
||||||
|
@ -436,6 +435,9 @@ RigidBody* DynamicsWorld::createRigidBody(const Transform& transform) {
|
||||||
sizeof(RigidBody))) RigidBody(transform, *this, entity, bodyID);
|
sizeof(RigidBody))) RigidBody(transform, *this, entity, bodyID);
|
||||||
assert(rigidBody != nullptr);
|
assert(rigidBody != nullptr);
|
||||||
|
|
||||||
|
BodyComponents::BodyComponent bodyComponent(rigidBody);
|
||||||
|
mBodyComponents.addComponent(entity, false, bodyComponent);
|
||||||
|
|
||||||
// Add the rigid body to the physics world
|
// Add the rigid body to the physics world
|
||||||
mBodies.add(rigidBody);
|
mBodies.add(rigidBody);
|
||||||
mRigidBodies.add(rigidBody);
|
mRigidBodies.add(rigidBody);
|
||||||
|
@ -480,7 +482,9 @@ void DynamicsWorld::destroyRigidBody(RigidBody* rigidBody) {
|
||||||
rigidBody->resetContactManifoldsList();
|
rigidBody->resetContactManifoldsList();
|
||||||
|
|
||||||
// Destroy the corresponding entity and its components
|
// Destroy the corresponding entity and its components
|
||||||
destroyEntity(rigidBody->getEntity());
|
mBodyComponents.removeComponent(rigidBody->getEntity());
|
||||||
|
mTransformComponents.removeComponent(rigidBody->getEntity());
|
||||||
|
mEntityManager.destroyEntity(rigidBody->getEntity());
|
||||||
|
|
||||||
// Call the destructor of the rigid body
|
// Call the destructor of the rigid body
|
||||||
rigidBody->~RigidBody();
|
rigidBody->~RigidBody();
|
||||||
|
|
|
@ -84,7 +84,7 @@ void BroadPhaseSystem::addProxyCollisionShape(ProxyShape* proxyShape, const AABB
|
||||||
int nodeId = mDynamicAABBTree.addObject(aabb, proxyShape);
|
int nodeId = mDynamicAABBTree.addObject(aabb, proxyShape);
|
||||||
|
|
||||||
// Set the broad-phase ID of the proxy shape
|
// Set the broad-phase ID of the proxy shape
|
||||||
mProxyShapesComponents.setBroadPhaseId(proxyShape, nodeId);
|
mProxyShapesComponents.setBroadPhaseId(proxyShape->getEntity(), nodeId);
|
||||||
|
|
||||||
// Add the collision shape into the array of bodies that have moved (or have been created)
|
// Add the collision shape into the array of bodies that have moved (or have been created)
|
||||||
// during the last simulation step
|
// during the last simulation step
|
||||||
|
@ -98,7 +98,7 @@ void BroadPhaseSystem::removeProxyCollisionShape(ProxyShape* proxyShape) {
|
||||||
|
|
||||||
int broadPhaseID = proxyShape->getBroadPhaseId();
|
int broadPhaseID = proxyShape->getBroadPhaseId();
|
||||||
|
|
||||||
mProxyShapesComponents.setBroadPhaseId(proxyShape, -1);
|
mProxyShapesComponents.setBroadPhaseId(proxyShape->getEntity(), -1);
|
||||||
|
|
||||||
// Remove the collision shape from the dynamic AABB tree
|
// Remove the collision shape from the dynamic AABB tree
|
||||||
mDynamicAABBTree.removeObject(broadPhaseID);
|
mDynamicAABBTree.removeObject(broadPhaseID);
|
||||||
|
|
|
@ -380,8 +380,9 @@ void SceneDemo::renderAABBs(const openglframework::Matrix4& worldToCameraMatrix)
|
||||||
for (std::vector<PhysicsObject*>::iterator it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) {
|
for (std::vector<PhysicsObject*>::iterator it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) {
|
||||||
|
|
||||||
// For each proxy shape of the object
|
// For each proxy shape of the object
|
||||||
rp3d::ProxyShape* proxyShape = (*it)->getCollisionBody()->getProxyShapesList();
|
for (uint i=0; i < (*it)->getCollisionBody()->getNbProxyShapes(); i++) {
|
||||||
while (proxyShape != nullptr) {
|
|
||||||
|
rp3d::ProxyShape* proxyShape = (*it)->getCollisionBody()->getProxyShape(i);
|
||||||
|
|
||||||
// Get the broad-phase AABB corresponding to the proxy shape
|
// Get the broad-phase AABB corresponding to the proxy shape
|
||||||
rp3d::AABB aabb = mPhysicsWorld->getWorldAABB(proxyShape);
|
rp3d::AABB aabb = mPhysicsWorld->getWorldAABB(proxyShape);
|
||||||
|
@ -392,8 +393,6 @@ void SceneDemo::renderAABBs(const openglframework::Matrix4& worldToCameraMatrix)
|
||||||
|
|
||||||
// Render the AABB
|
// Render the AABB
|
||||||
AABB::render(aabbCenter, aabbMax - aabbMin, Color::green(), mColorShader, worldToCameraMatrix);
|
AABB::render(aabbCenter, aabbMax - aabbMin, Color::green(), mColorShader, worldToCameraMatrix);
|
||||||
|
|
||||||
proxyShape = proxyShape->getNext();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user