Make sure we do not recompute automatically center of mass and inertia tensor when they are set by the user
This commit is contained in:
parent
c7f7a169f8
commit
010d7876ef
|
@ -42,7 +42,7 @@ RigidBody::RigidBody(const Transform& transform, CollisionWorld& world, bodyinde
|
||||||
: CollisionBody(transform, world, id), mArrayIndex(0), mInitMass(decimal(1.0)),
|
: CollisionBody(transform, world, id), mArrayIndex(0), mInitMass(decimal(1.0)),
|
||||||
mCenterOfMassLocal(0, 0, 0), mCenterOfMassWorld(transform.getPosition()),
|
mCenterOfMassLocal(0, 0, 0), mCenterOfMassWorld(transform.getPosition()),
|
||||||
mIsGravityEnabled(true), mLinearDamping(decimal(0.0)), mAngularDamping(decimal(0.0)),
|
mIsGravityEnabled(true), mLinearDamping(decimal(0.0)), mAngularDamping(decimal(0.0)),
|
||||||
mJointsList(nullptr) {
|
mJointsList(nullptr), mIsCenterOfMassSetByUser(false), mIsInertiaTensorSetByUser(false) {
|
||||||
|
|
||||||
// Compute the inverse mass
|
// Compute the inverse mass
|
||||||
mMassInverse = decimal(1.0) / mInitMass;
|
mMassInverse = decimal(1.0) / mInitMass;
|
||||||
|
@ -93,16 +93,18 @@ void RigidBody::setType(BodyType type) {
|
||||||
mMassInverse = decimal(0.0);
|
mMassInverse = decimal(0.0);
|
||||||
mInertiaTensorLocalInverse.setToZero();
|
mInertiaTensorLocalInverse.setToZero();
|
||||||
mInertiaTensorInverseWorld.setToZero();
|
mInertiaTensorInverseWorld.setToZero();
|
||||||
|
|
||||||
}
|
}
|
||||||
else { // If it is a dynamic body
|
else { // If it is a dynamic body
|
||||||
mMassInverse = decimal(1.0) / mInitMass;
|
mMassInverse = decimal(1.0) / mInitMass;
|
||||||
mInertiaTensorLocalInverse = mUserInertiaTensorLocalInverse;
|
|
||||||
|
|
||||||
// Update the world inverse inertia tensor
|
if (mIsInertiaTensorSetByUser) {
|
||||||
updateInertiaTensorInverseWorld();
|
mInertiaTensorLocalInverse = mUserInertiaTensorLocalInverse;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the world inverse inertia tensor
|
||||||
|
updateInertiaTensorInverseWorld();
|
||||||
|
|
||||||
// Awake the body
|
// Awake the body
|
||||||
setIsSleeping(false);
|
setIsSleeping(false);
|
||||||
|
|
||||||
|
@ -119,6 +121,8 @@ void RigidBody::setType(BodyType type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the local inertia tensor of the body (in local-space coordinates)
|
// Set the local inertia tensor of the body (in local-space coordinates)
|
||||||
|
/// If the inertia tensor is set with this method, it will not be computed
|
||||||
|
/// using the collision shapes of the body.
|
||||||
/**
|
/**
|
||||||
* @param inertiaTensorLocal The 3x3 inertia tensor matrix of the body in local-space
|
* @param inertiaTensorLocal The 3x3 inertia tensor matrix of the body in local-space
|
||||||
* coordinates
|
* coordinates
|
||||||
|
@ -126,6 +130,7 @@ void RigidBody::setType(BodyType type) {
|
||||||
void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal) {
|
void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal) {
|
||||||
|
|
||||||
mUserInertiaTensorLocalInverse = inertiaTensorLocal.getInverse();
|
mUserInertiaTensorLocalInverse = inertiaTensorLocal.getInverse();
|
||||||
|
mIsInertiaTensorSetByUser = true;
|
||||||
|
|
||||||
if (mType != BodyType::DYNAMIC) return;
|
if (mType != BodyType::DYNAMIC) return;
|
||||||
|
|
||||||
|
@ -136,10 +141,17 @@ void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal) {
|
||||||
updateInertiaTensorInverseWorld();
|
updateInertiaTensorInverseWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the inverse local inertia tensor of the body (in body coordinates)
|
// Set the inverse local inertia tensor of the body (in local-space coordinates)
|
||||||
|
/// If the inverse inertia tensor is set with this method, it will not be computed
|
||||||
|
/// using the collision shapes of the body.
|
||||||
|
/**
|
||||||
|
* @param inverseInertiaTensorLocal The 3x3 inverse inertia tensor matrix of the body in local-space
|
||||||
|
* coordinates
|
||||||
|
*/
|
||||||
void RigidBody::setInverseInertiaTensorLocal(const Matrix3x3& inverseInertiaTensorLocal) {
|
void RigidBody::setInverseInertiaTensorLocal(const Matrix3x3& inverseInertiaTensorLocal) {
|
||||||
|
|
||||||
mUserInertiaTensorLocalInverse = inverseInertiaTensorLocal;
|
mUserInertiaTensorLocalInverse = inverseInertiaTensorLocal;
|
||||||
|
mIsInertiaTensorSetByUser = true;
|
||||||
|
|
||||||
if (mType != BodyType::DYNAMIC) return;
|
if (mType != BodyType::DYNAMIC) return;
|
||||||
|
|
||||||
|
@ -151,6 +163,8 @@ void RigidBody::setInverseInertiaTensorLocal(const Matrix3x3& inverseInertiaTens
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the local center of mass of the body (in local-space coordinates)
|
// Set the local center of mass of the body (in local-space coordinates)
|
||||||
|
/// If you set the center of mass with the method, it will not be computed
|
||||||
|
/// automatically using collision shapes.
|
||||||
/**
|
/**
|
||||||
* @param centerOfMassLocal The center of mass of the body in local-space
|
* @param centerOfMassLocal The center of mass of the body in local-space
|
||||||
* coordinates
|
* coordinates
|
||||||
|
@ -159,6 +173,8 @@ void RigidBody::setCenterOfMassLocal(const Vector3& centerOfMassLocal) {
|
||||||
|
|
||||||
if (mType != BodyType::DYNAMIC) return;
|
if (mType != BodyType::DYNAMIC) return;
|
||||||
|
|
||||||
|
mIsCenterOfMassSetByUser = true;
|
||||||
|
|
||||||
const Vector3 oldCenterOfMass = mCenterOfMassWorld;
|
const Vector3 oldCenterOfMass = mCenterOfMassWorld;
|
||||||
mCenterOfMassLocal = centerOfMassLocal;
|
mCenterOfMassLocal = centerOfMassLocal;
|
||||||
|
|
||||||
|
@ -359,9 +375,9 @@ void RigidBody::recomputeMassInformation() {
|
||||||
|
|
||||||
mInitMass = decimal(0.0);
|
mInitMass = decimal(0.0);
|
||||||
mMassInverse = decimal(0.0);
|
mMassInverse = decimal(0.0);
|
||||||
mInertiaTensorLocalInverse.setToZero();
|
if (!mIsInertiaTensorSetByUser) mInertiaTensorLocalInverse.setToZero();
|
||||||
mInertiaTensorInverseWorld.setToZero();
|
if (!mIsInertiaTensorSetByUser) mInertiaTensorInverseWorld.setToZero();
|
||||||
mCenterOfMassLocal.setToZero();
|
if (!mIsCenterOfMassSetByUser) mCenterOfMassLocal.setToZero();
|
||||||
Matrix3x3 inertiaTensorLocal;
|
Matrix3x3 inertiaTensorLocal;
|
||||||
inertiaTensorLocal.setToZero();
|
inertiaTensorLocal.setToZero();
|
||||||
|
|
||||||
|
@ -376,7 +392,10 @@ void RigidBody::recomputeMassInformation() {
|
||||||
// Compute the total mass of the body
|
// Compute the total mass of the body
|
||||||
for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) {
|
for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) {
|
||||||
mInitMass += shape->getMass();
|
mInitMass += shape->getMass();
|
||||||
mCenterOfMassLocal += shape->getLocalToBodyTransform().getPosition() * shape->getMass();
|
|
||||||
|
if (!mIsCenterOfMassSetByUser) {
|
||||||
|
mCenterOfMassLocal += shape->getLocalToBodyTransform().getPosition() * shape->getMass();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mInitMass > decimal(0.0)) {
|
if (mInitMass > decimal(0.0)) {
|
||||||
|
@ -389,39 +408,46 @@ void RigidBody::recomputeMassInformation() {
|
||||||
|
|
||||||
// Compute the center of mass
|
// Compute the center of mass
|
||||||
const Vector3 oldCenterOfMass = mCenterOfMassWorld;
|
const Vector3 oldCenterOfMass = mCenterOfMassWorld;
|
||||||
mCenterOfMassLocal *= mMassInverse;
|
|
||||||
mCenterOfMassWorld = mTransform * mCenterOfMassLocal;
|
|
||||||
|
|
||||||
// Compute the total mass and inertia tensor using all the collision shapes
|
if (!mIsCenterOfMassSetByUser) {
|
||||||
for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) {
|
mCenterOfMassLocal *= mMassInverse;
|
||||||
|
|
||||||
// Get the inertia tensor of the collision shape in its local-space
|
|
||||||
Matrix3x3 inertiaTensor;
|
|
||||||
shape->getCollisionShape()->computeLocalInertiaTensor(inertiaTensor, shape->getMass());
|
|
||||||
|
|
||||||
// Convert the collision shape inertia tensor into the local-space of the body
|
|
||||||
const Transform& shapeTransform = shape->getLocalToBodyTransform();
|
|
||||||
Matrix3x3 rotationMatrix = shapeTransform.getOrientation().getMatrix();
|
|
||||||
inertiaTensor = rotationMatrix * inertiaTensor * rotationMatrix.getTranspose();
|
|
||||||
|
|
||||||
// Use the parallel axis theorem to convert the inertia tensor w.r.t the collision shape
|
|
||||||
// center into a inertia tensor w.r.t to the body origin.
|
|
||||||
Vector3 offset = shapeTransform.getPosition() - mCenterOfMassLocal;
|
|
||||||
decimal offsetSquare = offset.lengthSquare();
|
|
||||||
Matrix3x3 offsetMatrix;
|
|
||||||
offsetMatrix[0].setAllValues(offsetSquare, decimal(0.0), decimal(0.0));
|
|
||||||
offsetMatrix[1].setAllValues(decimal(0.0), offsetSquare, decimal(0.0));
|
|
||||||
offsetMatrix[2].setAllValues(decimal(0.0), decimal(0.0), offsetSquare);
|
|
||||||
offsetMatrix[0] += offset * (-offset.x);
|
|
||||||
offsetMatrix[1] += offset * (-offset.y);
|
|
||||||
offsetMatrix[2] += offset * (-offset.z);
|
|
||||||
offsetMatrix *= shape->getMass();
|
|
||||||
|
|
||||||
inertiaTensorLocal += inertiaTensor + offsetMatrix;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the local inverse inertia tensor
|
mCenterOfMassWorld = mTransform * mCenterOfMassLocal;
|
||||||
mInertiaTensorLocalInverse = inertiaTensorLocal.getInverse();
|
|
||||||
|
if (!mIsInertiaTensorSetByUser) {
|
||||||
|
|
||||||
|
// Compute the inertia tensor using all the collision shapes
|
||||||
|
for (ProxyShape* shape = mProxyCollisionShapes; shape != nullptr; shape = shape->mNext) {
|
||||||
|
|
||||||
|
// Get the inertia tensor of the collision shape in its local-space
|
||||||
|
Matrix3x3 inertiaTensor;
|
||||||
|
shape->getCollisionShape()->computeLocalInertiaTensor(inertiaTensor, shape->getMass());
|
||||||
|
|
||||||
|
// Convert the collision shape inertia tensor into the local-space of the body
|
||||||
|
const Transform& shapeTransform = shape->getLocalToBodyTransform();
|
||||||
|
Matrix3x3 rotationMatrix = shapeTransform.getOrientation().getMatrix();
|
||||||
|
inertiaTensor = rotationMatrix * inertiaTensor * rotationMatrix.getTranspose();
|
||||||
|
|
||||||
|
// Use the parallel axis theorem to convert the inertia tensor w.r.t the collision shape
|
||||||
|
// center into a inertia tensor w.r.t to the body origin.
|
||||||
|
Vector3 offset = shapeTransform.getPosition() - mCenterOfMassLocal;
|
||||||
|
decimal offsetSquare = offset.lengthSquare();
|
||||||
|
Matrix3x3 offsetMatrix;
|
||||||
|
offsetMatrix[0].setAllValues(offsetSquare, decimal(0.0), decimal(0.0));
|
||||||
|
offsetMatrix[1].setAllValues(decimal(0.0), offsetSquare, decimal(0.0));
|
||||||
|
offsetMatrix[2].setAllValues(decimal(0.0), decimal(0.0), offsetSquare);
|
||||||
|
offsetMatrix[0] += offset * (-offset.x);
|
||||||
|
offsetMatrix[1] += offset * (-offset.y);
|
||||||
|
offsetMatrix[2] += offset * (-offset.z);
|
||||||
|
offsetMatrix *= shape->getMass();
|
||||||
|
|
||||||
|
inertiaTensorLocal += inertiaTensor + offsetMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the local inverse inertia tensor
|
||||||
|
mInertiaTensorLocalInverse = inertiaTensorLocal.getInverse();
|
||||||
|
}
|
||||||
|
|
||||||
// Update the world inverse inertia tensor
|
// Update the world inverse inertia tensor
|
||||||
updateInertiaTensorInverseWorld();
|
updateInertiaTensorInverseWorld();
|
||||||
|
|
|
@ -109,6 +109,12 @@ class RigidBody : public CollisionBody {
|
||||||
/// First element of the linked list of joints involving this body
|
/// First element of the linked list of joints involving this body
|
||||||
JointListElement* mJointsList;
|
JointListElement* mJointsList;
|
||||||
|
|
||||||
|
/// True if the center of mass is set by the user
|
||||||
|
bool mIsCenterOfMassSetByUser;
|
||||||
|
|
||||||
|
/// True if the inertia tensor is set by the user
|
||||||
|
bool mIsInertiaTensorSetByUser;
|
||||||
|
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
/// Remove a joint from the joints list
|
/// Remove a joint from the joints list
|
||||||
|
|
Loading…
Reference in New Issue
Block a user