Add Transform component

This commit is contained in:
Daniel Chappuis 2018-12-26 23:33:36 +01:00
parent fa9b1817fe
commit 8b6249829a
10 changed files with 125 additions and 1185 deletions

View File

@ -39,8 +39,8 @@ using namespace reactphysics3d;
* @param world The physics world where the body is created
* @param id ID of the body
*/
CollisionBody::CollisionBody(const Transform& transform, CollisionWorld& world, Entity entity, bodyindex id)
: Body(entity, id), mType(BodyType::DYNAMIC), mTransform(transform), mProxyCollisionShapes(nullptr),
CollisionBody::CollisionBody(CollisionWorld& world, Entity entity, bodyindex id)
: Body(entity, id), mType(BodyType::DYNAMIC), mProxyCollisionShapes(nullptr),
mNbCollisionShapes(0), mContactManifoldsList(nullptr), mWorld(world) {
#ifdef IS_PROFILING_ACTIVE
@ -105,7 +105,7 @@ ProxyShape* CollisionBody::addCollisionShape(CollisionShape* collisionShape,
// Compute the world-space AABB of the new collision shape
AABB aabb;
collisionShape->computeAABB(aabb, mTransform * transform);
collisionShape->computeAABB(aabb, mWorld.mTransformComponents.getTransform(mEntity) * transform);
// Notify the collision detection about this new collision shape
mWorld.mCollisionDetection.addProxyCollisionShape(proxyShape, aabb);
@ -218,6 +218,18 @@ void CollisionBody::resetContactManifoldsList() {
mContactManifoldsList = nullptr;
}
// Return the current position and orientation
/**
* @return The current transformation of the body that transforms the local-space
* of the body into world-space
*/
const Transform& CollisionBody::getTransform() const {
// TODO : Make sure we do not call this method from the internal physics engine
return mWorld.mTransformComponents.getTransform(mEntity);
}
// Update the broad-phase state for this body (because it has moved for instance)
void CollisionBody::updateBroadPhaseState() const {
@ -232,11 +244,13 @@ void CollisionBody::updateBroadPhaseState() const {
// Update the broad-phase state of a proxy collision shape of the body
void CollisionBody::updateProxyShapeInBroadPhase(ProxyShape* proxyShape, bool forceReinsert) const {
const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
if (proxyShape->getBroadPhaseId() != -1) {
// Recompute the world-space AABB of the collision shape
AABB aabb;
proxyShape->getCollisionShape()->computeAABB(aabb, mTransform * proxyShape->getLocalToBodyTransform());
proxyShape->getCollisionShape()->computeAABB(aabb, transform * proxyShape->getLocalToBodyTransform());
// Update the broad-phase state for the proxy collision shape
mWorld.mCollisionDetection.updateProxyCollisionShape(proxyShape, aabb, Vector3(0, 0, 0), forceReinsert) ;
@ -257,12 +271,14 @@ void CollisionBody::setIsActive(bool isActive) {
// If we have to activate the body
if (isActive) {
const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
// For each proxy shape of the body
for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) {
// Compute the world-space AABB of the new collision shape
AABB aabb;
shape->getCollisionShape()->computeAABB(aabb, mTransform * shape->mLocalToBodyTransform);
shape->getCollisionShape()->computeAABB(aabb, transform * shape->mLocalToBodyTransform);
// Add the proxy shape to the collision detection
mWorld.mCollisionDetection.addProxyCollisionShape(shape, aabb);
@ -377,14 +393,18 @@ AABB CollisionBody::getAABB() const {
if (mProxyCollisionShapes == nullptr) return bodyAABB;
mProxyCollisionShapes->getCollisionShape()->computeAABB(bodyAABB, mTransform * mProxyCollisionShapes->getLocalToBodyTransform());
// TODO : Make sure we compute this in a system
const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
mProxyCollisionShapes->getCollisionShape()->computeAABB(bodyAABB, transform * mProxyCollisionShapes->getLocalToBodyTransform());
// For each proxy shape of the body
for (ProxyShape* shape = mProxyCollisionShapes->mNext; shape != nullptr; shape = shape->mNext) {
// Compute the world-space AABB of the collision shape
AABB aabb;
shape->getCollisionShape()->computeAABB(aabb, mTransform * shape->getLocalToBodyTransform());
shape->getCollisionShape()->computeAABB(aabb, transform * shape->getLocalToBodyTransform());
// Merge the proxy shape AABB with the current body AABB
bodyAABB.mergeWithAABB(aabb);
@ -401,16 +421,52 @@ AABB CollisionBody::getAABB() const {
void CollisionBody::setTransform(const Transform& transform) {
// Update the transform of the body
mTransform = transform;
mWorld.mTransformComponents.setTransform(mEntity, transform);
// Update the broad-phase state of the body
updateBroadPhaseState();
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set transform=" + mTransform.to_string());
"Body " + std::to_string(mID) + ": Set transform=" + transform.to_string());
}
// Return the world-space coordinates of a point given the local-space coordinates of the body
/**
* @param localPoint A point in the local-space coordinates of the body
* @return The point in world-space coordinates
*/
Vector3 CollisionBody::getWorldPoint(const Vector3& localPoint) const {
return mWorld.mTransformComponents.getTransform(mEntity) * localPoint;
}
// Return the world-space vector of a vector given in local-space coordinates of the body
/**
* @param localVector A vector in the local-space coordinates of the body
* @return The vector in world-space coordinates
*/
Vector3 CollisionBody::getWorldVector(const Vector3& localVector) const {
return mWorld.mTransformComponents.getTransform(mEntity).getOrientation() * localVector;
}
// Return the body local-space coordinates of a point given in the world-space coordinates
/**
* @param worldPoint A point in world-space coordinates
* @return The point in the local-space coordinates of the body
*/
Vector3 CollisionBody::getLocalPoint(const Vector3& worldPoint) const {
return mWorld.mTransformComponents.getTransform(mEntity).getInverse() * worldPoint;
}
// Return the body local-space coordinates of a vector given in the world-space coordinates
/**
* @param worldVector A vector in world-space coordinates
* @return The vector in the local-space coordinates of the body
*/
Vector3 CollisionBody::getLocalVector(const Vector3& worldVector) const {
return mWorld.mTransformComponents.getTransform(mEntity).getOrientation().getInverse() * worldVector;
}
// Set the type of the body
/// The type of the body can either STATIC, KINEMATIC or DYNAMIC as described bellow:
/// STATIC : A static body has infinite mass, zero velocity but the position can be

View File

@ -70,9 +70,6 @@ class CollisionBody : public Body {
/// Type of body (static, kinematic or dynamic)
BodyType mType;
/// Position and orientation of the body
Transform mTransform;
/// First element of the linked list of proxy collision shapes of this body
ProxyShape* mProxyCollisionShapes;
@ -118,7 +115,7 @@ class CollisionBody : public Body {
// -------------------- Methods -------------------- //
/// Constructor
CollisionBody(const Transform& transform, CollisionWorld& world, Entity entity, bodyindex id);
CollisionBody(CollisionWorld& world, Entity entity, bodyindex id);
/// Destructor
virtual ~CollisionBody() override;
@ -209,15 +206,6 @@ inline BodyType CollisionBody::getType() const {
return mType;
}
// Return the current position and orientation
/**
* @return The current transformation of the body that transforms the local-space
* of the body into world-space
*/
inline const Transform& CollisionBody::getTransform() const {
return mTransform;
}
// Return the first element of the linked list of contact manifolds involving this body
/**
* @return A pointer to the first element of the linked-list with the contact
@ -245,42 +233,6 @@ inline const ProxyShape* CollisionBody::getProxyShapesList() const {
return mProxyCollisionShapes;
}
// Return the world-space coordinates of a point given the local-space coordinates of the body
/**
* @param localPoint A point in the local-space coordinates of the body
* @return The point in world-space coordinates
*/
inline Vector3 CollisionBody::getWorldPoint(const Vector3& localPoint) const {
return mTransform * localPoint;
}
// Return the world-space vector of a vector given in local-space coordinates of the body
/**
* @param localVector A vector in the local-space coordinates of the body
* @return The vector in world-space coordinates
*/
inline Vector3 CollisionBody::getWorldVector(const Vector3& localVector) const {
return mTransform.getOrientation() * localVector;
}
// Return the body local-space coordinates of a point given in the world-space coordinates
/**
* @param worldPoint A point in world-space coordinates
* @return The point in the local-space coordinates of the body
*/
inline Vector3 CollisionBody::getLocalPoint(const Vector3& worldPoint) const {
return mTransform.getInverse() * worldPoint;
}
// Return the body local-space coordinates of a vector given in the world-space coordinates
/**
* @param worldVector A vector in world-space coordinates
* @return The vector in the local-space coordinates of the body
*/
inline Vector3 CollisionBody::getLocalVector(const Vector3& worldVector) const {
return mTransform.getOrientation().getInverse() * worldVector;
}
/// Test if the collision body overlaps with a given AABB
/**
* @param worldAABB The AABB (in world-space coordinates) that will be used to test overlap

View File

@ -40,7 +40,7 @@ using namespace reactphysics3d;
* @param id The ID of the body
*/
RigidBody::RigidBody(const Transform& transform, CollisionWorld& world, Entity entity, bodyindex id)
: CollisionBody(transform, world, entity, id), mArrayIndex(0), mInitMass(decimal(1.0)),
: CollisionBody(world, entity, id), mArrayIndex(0), mInitMass(decimal(1.0)),
mCenterOfMassLocal(0, 0, 0), mCenterOfMassWorld(transform.getPosition()),
mIsGravityEnabled(true), mMaterial(world.mConfig), mLinearDamping(decimal(0.0)), mAngularDamping(decimal(0.0)),
mJointsList(nullptr), mIsCenterOfMassSetByUser(false), mIsInertiaTensorSetByUser(false) {
@ -186,7 +186,7 @@ void RigidBody::setCenterOfMassLocal(const Vector3& centerOfMassLocal) {
mCenterOfMassLocal = centerOfMassLocal;
// Compute the center of mass in world-space coordinates
mCenterOfMassWorld = mTransform * mCenterOfMassLocal;
mCenterOfMassWorld = mWorld.mTransformComponents.getTransform(mEntity) * mCenterOfMassLocal;
// Update the linear velocity of the center of mass
mLinearVelocity += mAngularVelocity.cross(mCenterOfMassWorld - oldCenterOfMass);
@ -247,6 +247,20 @@ void RigidBody::removeJointFromJointsList(MemoryManager& memoryManager, const Jo
}
}
// Update the world inverse inertia tensor of the body
/// The inertia tensor I_w in world coordinates is computed with the
/// local inverse inertia tensor I_b^-1 in body coordinates
/// by I_w = R * I_b^-1 * R^T
/// where R is the rotation matrix (and R^T its transpose) of the
/// current orientation quaternion of the body
void RigidBody::updateInertiaTensorInverseWorld() {
// TODO : Make sure we do this in a system
Matrix3x3 orientation = mWorld.mTransformComponents.getTransform(mEntity).getOrientation().getMatrix();
mInertiaTensorInverseWorld = orientation * mInertiaTensorLocalInverse * orientation.getTranspose();
}
// Add a collision shape to the body.
/// When you add a collision shape to the body, an internal copy of this
/// collision shape will be created internally. Therefore, you can delete it
@ -297,7 +311,7 @@ ProxyShape* RigidBody::addCollisionShape(CollisionShape* collisionShape,
// Compute the world-space AABB of the new collision shape
AABB aabb;
collisionShape->computeAABB(aabb, mTransform * transform);
collisionShape->computeAABB(aabb, mWorld.mTransformComponents.getTransform(mEntity) * transform);
// Notify the collision detection about this new collision shape
mWorld.mCollisionDetection.addProxyCollisionShape(proxyShape, aabb);
@ -373,6 +387,16 @@ void RigidBody::setAngularDamping(decimal angularDamping) {
"Body " + std::to_string(mID) + ": Set angularDamping=" + std::to_string(mAngularDamping));
}
/// Update the transform of the body after a change of the center of mass
void RigidBody::updateTransformWithCenterOfMass() {
// TODO : Make sure we compute this in a system
// Translate the body according to the translation of the center of mass position
Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
transform.setPosition(mCenterOfMassWorld - transform.getOrientation() * mCenterOfMassLocal);
}
// Set a new material for this rigid body
/**
* @param material The material you want to set to the body
@ -434,12 +458,12 @@ void RigidBody::setAngularVelocity(const Vector3& angularVelocity) {
void RigidBody::setTransform(const Transform& transform) {
// Update the transform of the body
mTransform = transform;
mWorld.mTransformComponents.setTransform(mEntity, transform);
const Vector3 oldCenterOfMass = mCenterOfMassWorld;
// Compute the new center of mass in world-space coordinates
mCenterOfMassWorld = mTransform * mCenterOfMassLocal;
mCenterOfMassWorld = transform * mCenterOfMassLocal;
// Update the linear velocity of the center of mass
mLinearVelocity += mAngularVelocity.cross(mCenterOfMassWorld - oldCenterOfMass);
@ -451,7 +475,7 @@ void RigidBody::setTransform(const Transform& transform) {
updateBroadPhaseState();
RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body,
"Body " + std::to_string(mID) + ": Set transform=" + mTransform.to_string());
"Body " + std::to_string(mID) + ": Set transform=" + transform.to_string());
}
// Recompute the center of mass, total mass and inertia tensor of the body using all
@ -466,9 +490,11 @@ void RigidBody::recomputeMassInformation() {
Matrix3x3 inertiaTensorLocal;
inertiaTensorLocal.setToZero();
const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
// If it is a STATIC or a KINEMATIC body
if (mType == BodyType::STATIC || mType == BodyType::KINEMATIC) {
mCenterOfMassWorld = mTransform.getPosition();
mCenterOfMassWorld = transform.getPosition();
return;
}
@ -487,7 +513,7 @@ void RigidBody::recomputeMassInformation() {
mMassInverse = decimal(1.0) / mInitMass;
}
else {
mCenterOfMassWorld = mTransform.getPosition();
mCenterOfMassWorld = transform.getPosition();
return;
}
@ -498,7 +524,7 @@ void RigidBody::recomputeMassInformation() {
mCenterOfMassLocal *= mMassInverse;
}
mCenterOfMassWorld = mTransform * mCenterOfMassLocal;
mCenterOfMassWorld = transform * mCenterOfMassLocal;
if (!mIsInertiaTensorSetByUser) {
@ -546,6 +572,10 @@ void RigidBody::updateBroadPhaseState() const {
RP3D_PROFILE("RigidBody::updateBroadPhaseState()", mProfiler);
// TODO : Make sure we compute this in a system
const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity);
DynamicsWorld& world = static_cast<DynamicsWorld&>(mWorld);
const Vector3 displacement = world.mTimeStep * mLinearVelocity;
@ -554,7 +584,7 @@ void RigidBody::updateBroadPhaseState() const {
// Recompute the world-space AABB of the collision shape
AABB aabb;
shape->getCollisionShape()->computeAABB(aabb, mTransform * shape->getLocalToBodyTransform());
shape->getCollisionShape()->computeAABB(aabb, transform * shape->getLocalToBodyTransform());
// Update the broad-phase state for the proxy collision shape
mWorld.mCollisionDetection.updateProxyCollisionShape(shape, aabb, displacement);

View File

@ -300,17 +300,6 @@ inline Matrix3x3 RigidBody::getInertiaTensorInverseWorld() const {
return mInertiaTensorInverseWorld;
}
// Update the world inverse inertia tensor of the body
/// The inertia tensor I_w in world coordinates is computed with the
/// local inverse inertia tensor I_b^-1 in body coordinates
/// by I_w = R * I_b^-1 * R^T
/// where R is the rotation matrix (and R^T its transpose) of the
/// current orientation quaternion of the body
inline void RigidBody::updateInertiaTensorInverseWorld() {
Matrix3x3 orientation = mTransform.getOrientation().getMatrix();
mInertiaTensorInverseWorld = orientation * mInertiaTensorLocalInverse * orientation.getTranspose();
}
// Return true if the gravity needs to be applied to this rigid body
/**
* @return True if the gravity is applied to the body
@ -442,13 +431,6 @@ inline void RigidBody::applyTorque(const Vector3& torque) {
mExternalTorque += torque;
}
/// Update the transform of the body after a change of the center of mass
inline void RigidBody::updateTransformWithCenterOfMass() {
// Translate the body according to the translation of the center of mass position
mTransform.setPosition(mCenterOfMassWorld - mTransform.getOrientation() * mCenterOfMassLocal);
}
}
#endif

View File

@ -28,6 +28,7 @@
#include "utils/Logger.h"
#include "collision/RaycastInfo.h"
#include "memory/MemoryManager.h"
#include "engine/CollisionWorld.h"
using namespace reactphysics3d;
@ -55,7 +56,7 @@ ProxyShape::~ProxyShape() {
* @return True if the point is inside the collision shape
*/
bool ProxyShape::testPointInside(const Vector3& worldPoint) {
const Transform localToWorld = mBody->getTransform() * mLocalToBodyTransform;
const Transform localToWorld = mBody->mWorld.mTransformComponents.getTransform(mBody->getEntity()) * mLocalToBodyTransform;
const Vector3 localPoint = localToWorld.getInverse() * worldPoint;
return mCollisionShape->testPointInside(localPoint, this);
}
@ -127,3 +128,13 @@ bool ProxyShape::raycast(const Ray& ray, RaycastInfo& raycastInfo) {
return isHit;
}
// Return the local to world transform
/**
* @return The transformation that transforms the local-space of the collision
* shape to the world-space
*/
const Transform ProxyShape::getLocalToWorldTransform() const {
return mBody->mWorld.mTransformComponents.getTransform(mBody->getEntity()) * mLocalToBodyTransform;
}

View File

@ -267,15 +267,6 @@ inline const Transform& ProxyShape::getLocalToBodyTransform() const {
return mLocalToBodyTransform;
}
// Return the local to world transform
/**
* @return The transformation that transforms the local-space of the collision
* shape to the world-space
*/
inline const Transform ProxyShape::getLocalToWorldTransform() const {
return mBody->mTransform * mLocalToBodyTransform;
}
// Return the AABB of the proxy shape in world-space
/**
* @return The AABB of the proxy shape in world-space

View File

@ -74,10 +74,10 @@ void TransformComponents::allocate(uint32 nbComponentsToAllocate) {
// New pointers to components data
Entity* newEntities = static_cast<Entity*>(newBuffer);
Transform* newTransforms = reinterpret_cast<Transform*>(newEntities + mNbAllocatedComponents);
Transform* newTransforms = reinterpret_cast<Transform*>(newEntities + nbComponentsToAllocate);
// If there was already components before
if (mNbAllocatedComponents > 0) {
if (mNbComponents > 0) {
// Copy component data from the previous buffer to the new one
memcpy(newTransforms, mTransforms, mNbComponents * sizeof(Transform));

View File

@ -155,7 +155,7 @@ CollisionBody* CollisionWorld::createCollisionBody(const Transform& transform) {
// Create the collision body
CollisionBody* collisionBody = new (mMemoryManager.allocate(MemoryManager::AllocationType::Pool,
sizeof(CollisionBody)))
CollisionBody(transform, *this, entity, bodyID);
CollisionBody(*this, entity, bodyID);
assert(collisionBody != nullptr);

View File

@ -185,7 +185,7 @@ void DynamicsWorld::integrateRigidBodiesPositions() {
// Get current position and orientation of the body
const Vector3& currentPosition = bodies[b]->mCenterOfMassWorld;
const Quaternion& currentOrientation = bodies[b]->getTransform().getOrientation();
const Quaternion& currentOrientation = mTransformComponents.getTransform(bodies[b]->getEntity()).getOrientation();
// Update the new constrained position and orientation of the body
mConstrainedPositions[indexArray] = currentPosition + newLinVelocity * mTimeStep;
@ -201,6 +201,8 @@ void DynamicsWorld::updateBodiesState() {
RP3D_PROFILE("DynamicsWorld::updateBodiesState()", mProfiler);
// TODO : Make sure we compute this in a system
// For each island of the world
for (uint islandIndex = 0; islandIndex < mNbIslands; islandIndex++) {
@ -219,7 +221,7 @@ void DynamicsWorld::updateBodiesState() {
bodies[b]->mCenterOfMassWorld = mConstrainedPositions[index];
// Update the orientation of the body
bodies[b]->mTransform.setOrientation(mConstrainedOrientations[index].getUnit());
mTransformComponents.getTransform(bodies[b]->getEntity()).setOrientation(mConstrainedOrientations[index].getUnit());
// Update the transform of the body (using the new center of mass and new orientation)
bodies[b]->updateTransformWithCenterOfMass();