From cda466f9daed4c71a7d93d0005a194ad942456cf Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Sun, 1 Mar 2020 16:39:16 +0100 Subject: [PATCH] Refactor the way to set/update the center of mass, mass and inertia tensor of a rigid body --- CHANGELOG.md | 17 +- src/body/CollisionBody.cpp | 6 +- src/body/CollisionBody.h | 2 +- src/body/RigidBody.cpp | 469 +++++++++++------- src/body/RigidBody.h | 57 +-- src/collision/Collider.cpp | 9 - src/collision/Collider.h | 3 - src/collision/PolyhedronMesh.cpp | 46 ++ src/collision/PolyhedronMesh.h | 6 + src/collision/shapes/BoxShape.h | 8 + src/collision/shapes/CapsuleShape.h | 8 + src/collision/shapes/CollisionShape.h | 4 + src/collision/shapes/ConcaveShape.cpp | 16 + src/collision/shapes/ConcaveShape.h | 4 + src/collision/shapes/ConvexMeshShape.h | 9 + src/collision/shapes/SphereShape.h | 8 + src/collision/shapes/TriangleShape.h | 8 + src/components/ColliderComponents.cpp | 13 +- src/components/ColliderComponents.h | 19 +- src/components/RigidBodyComponents.cpp | 28 +- src/components/RigidBodyComponents.h | 58 ++- src/engine/Material.cpp | 5 +- src/engine/Material.h | 27 +- src/engine/PhysicsCommon.cpp | 45 ++ src/engine/PhysicsCommon.h | 11 + src/engine/PhysicsWorld.cpp | 6 +- src/systems/DynamicsSystem.cpp | 4 +- test/tests/collision/TestCollisionWorld.h | 3 +- test/tests/collision/TestPointInside.h | 2 +- test/tests/collision/TestRaycast.h | 2 +- testbed/common/Box.cpp | 59 +-- testbed/common/Box.h | 5 +- testbed/common/Capsule.cpp | 10 +- testbed/common/Capsule.h | 2 +- testbed/common/ConcaveMesh.cpp | 5 +- testbed/common/ConcaveMesh.h | 2 +- testbed/common/ConvexMesh.cpp | 8 +- testbed/common/ConvexMesh.h | 2 +- testbed/common/Dumbbell.cpp | 20 +- testbed/common/HeightField.cpp | 6 +- testbed/common/HeightField.h | 2 +- testbed/common/Sphere.cpp | 52 +- testbed/common/Sphere.h | 5 +- .../CollisionDetectionScene.cpp | 18 +- .../collisionshapes/CollisionShapesScene.cpp | 10 +- .../collisionshapes/CollisionShapesScene.h | 6 - .../scenes/concavemesh/ConcaveMeshScene.cpp | 13 +- testbed/scenes/concavemesh/ConcaveMeshScene.h | 5 - testbed/scenes/cubes/CubesScene.cpp | 6 +- testbed/scenes/cubes/CubesScene.h | 4 +- testbed/scenes/cubestack/CubeStackScene.cpp | 4 +- testbed/scenes/cubestack/CubeStackScene.h | 2 - .../scenes/heightfield/HeightFieldScene.cpp | 14 +- testbed/scenes/heightfield/HeightFieldScene.h | 6 - testbed/scenes/joints/JointsScene.cpp | 15 +- testbed/scenes/joints/JointsScene.h | 2 - testbed/scenes/pile/PileScene.cpp | 10 +- testbed/scenes/pile/PileScene.h | 6 - testbed/scenes/raycast/RaycastScene.cpp | 12 +- 59 files changed, 708 insertions(+), 506 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29b8b182..097bce98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,14 @@ - It is now possible to change the scale of a HeightFieldShape using the HeightFieldShape::setScale() method - A method PhysicsWorld::getCollisionBody(uint index) has been added on a physics world to retrieve a given CollisionBody - A method PhysicsWorld::getRigidBody(uint index) has been added on a physics world to retrieve a given RigidBody + - The Material of a Collider now has a mass density parameter that is used to compute its mass + - A RigidBody::getLocalCenterOfMass() method has been added to retrieve the current center of mass of a rigid body + - Add PhysicsCommon class that needs to be instanciated at the beginning and is used as a factory for other objects of the library + - The RigidBody::updateLocalCenterOfMassFromColliders() method has been added to compute and set the center of mass of a body using its colliders + - The RigidBody::updateLocalInertiaTensorFromColliders() method has been added to compute and set the local inertia tensor of a body using its colliders + - The RigidBody::getLocalInertiaTensor() method has been added to retrieve the local-space inertia tensor of a rigid body. + - The RigidBody::updateMassFromColliders() method has been added to compute and set the mass of a body using its colliders + - A Material nows has a mass density parameter that can be set using the Material::setMassDensity() method. The mass density is used to compute the mass of a collider when computing the mass of a rigid body ### Changed @@ -37,6 +45,11 @@ - An instance of the PolyhedronMesh class cannot be instanciated directly anymore. You need to use the PhysicsCommon::createPolyhedronMesh() method. - An instance of the TriangleMesh class cannot be instanciated directly anymore. You need to use the PhysicsCommon::createTriangleMesh() method. - The ProxyShape class has been renamed to Collider. The CollisionBody::addCollider(), RigidBody::addCollider() methods have to be used to create and add a collider to a body. Then methods CollisionBody::removeCollider(), RigidBody::removeCollider() need to be used to remove a collider. + - The RigidBody::addCollider() method (previously addProxyShape() method) does not take a "mass" parameter anymore. + - The RigidBody::setCenterOfMassLocal() method has been renamed to RigidBody::setLocalCenterOfMass() + - The RigidBody::setInertiaTensorLocal() method has been renamed to RigidBody::setLocalInertiaTensor() + - The RigidBody::recomputeMassInformation() method has been renamed to RigidBody::updateMassPropertiesFromColliders. + - Now, you need to manually call the RigidBody::recomputeMassInformation() method after adding colliders to a rigid body to recompute its inertia tensor, center of mass and mass - The rendering in the testbed application has been improved ### Removed @@ -48,6 +61,9 @@ - The EventListener::endInternalTick() method has been removed (because internal ticks do not exist anymore). - The RigidBody::getJointsList() method has been removed. - It is not possible anymore to set custom pool and stack frame allocators. Only the base allocator can be customized when creating a PhysicsCommon instance. + - The RigidBody::setInverseInertiaTensorLocal() method has been removed. The RigidBody::setInertiaTensorLocal() has to be used instead. + - The RigidBody::getInverseInertiaTensorWorld() method has been removed. + - The Collider::getMass() method has been removed. ## Version 0.7.1 (July 01, 2019) @@ -55,7 +71,6 @@ - Make possible for the user to get vertices, normals and triangle indices of a ConcaveMeshShape - Make possible for the user to get vertices and height values of the HeightFieldShape - - Add PhysicsCommon class that needs to be instanciated at the beginning and is used as a factory for other objects of the library ### Fixed diff --git a/src/body/CollisionBody.cpp b/src/body/CollisionBody.cpp index fdd8b12b..e21884e4 100644 --- a/src/body/CollisionBody.cpp +++ b/src/body/CollisionBody.cpp @@ -86,7 +86,7 @@ Collider* CollisionBody::addCollider(CollisionShape* collisionShape, const Trans const Transform localToWorldTransform = mWorld.mTransformComponents.getTransform(mEntity) * transform; ColliderComponents::ColliderComponent colliderComponent(mEntity, collider, AABB(localBoundsMin, localBoundsMax), - transform, collisionShape, decimal(1), 0x0001, 0xFFFF, localToWorldTransform); + transform, collisionShape, 0x0001, 0xFFFF, localToWorldTransform); bool isActive = mWorld.mCollisionBodyComponents.getIsActive(mEntity); mWorld.mCollidersComponents.addComponent(colliderEntity, !isActive, colliderComponent); @@ -196,8 +196,8 @@ void CollisionBody::removeCollider(Collider* collider) { mWorld.mMemoryManager.release(MemoryManager::AllocationType::Pool, collider, sizeof(Collider)); } -// Remove all the collision shapes -void CollisionBody::removeAllCollisionShapes() { +// Remove all the colliders +void CollisionBody::removeAllColliders() { // Look for the collider that contains the collision shape in parameter. // Note that we need to copy the list of collider entities because we are deleting them in a loop. diff --git a/src/body/CollisionBody.h b/src/body/CollisionBody.h index 5c6c7f8c..402b2169 100644 --- a/src/body/CollisionBody.h +++ b/src/body/CollisionBody.h @@ -79,7 +79,7 @@ class CollisionBody { // -------------------- Methods -------------------- // /// Remove all the collision shapes - void removeAllCollisionShapes(); + void removeAllColliders(); /// Update the broad-phase state for this body (because it has moved for instance) void updateBroadPhaseState(decimal timeStep) const; diff --git a/src/body/RigidBody.cpp b/src/body/RigidBody.cpp index f68ad07b..f7e83dec 100644 --- a/src/body/RigidBody.cpp +++ b/src/body/RigidBody.cpp @@ -38,8 +38,7 @@ using namespace reactphysics3d; * @param world The world where the body has been added * @param id The ID of the body */ -RigidBody::RigidBody(PhysicsWorld& world, Entity entity) - : CollisionBody(world, entity), mIsCenterOfMassSetByUser(false), mIsInertiaTensorSetByUser(false) { +RigidBody::RigidBody(PhysicsWorld& world, Entity entity) : CollisionBody(world, entity) { } @@ -50,12 +49,12 @@ BodyType RigidBody::getType() const { // 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 +/// STATIC : A static body is simulated as if it has infinite mass, zero velocity but its position can be /// changed manually. A static body does not collide with other static or kinematic bodies. -/// KINEMATIC : A kinematic body has infinite mass, the velocity can be changed manually and its +/// KINEMATIC : A kinematic body is simulated as if it has infinite mass, its velocity can be changed manually and its /// position is computed by the physics engine. A kinematic body does not collide with /// other static or kinematic bodies. -/// DYNAMIC : A dynamic body has non-zero mass, non-zero velocity determined by forces and its +/// DYNAMIC : A dynamic body has non-zero mass, its velocity is determined by forces and its /// position is determined by the physics engine. A dynamic body can collide with other /// dynamic, static or kinematic bodies. /** @@ -67,9 +66,6 @@ void RigidBody::setType(BodyType type) { mWorld.mRigidBodyComponents.setBodyType(mEntity, type); - // Recompute the total mass, center of mass and inertia tensor - recomputeMassInformation(); - // If it is a static body if (type == BodyType::STATIC) { @@ -86,10 +82,23 @@ void RigidBody::setType(BodyType type) { mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, Matrix3x3::zero()); } else { // If it is a dynamic body - mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(1.0) / mWorld.mRigidBodyComponents.getInitMass(mEntity)); - if (mIsInertiaTensorSetByUser) { - mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, mUserInertiaTensorLocalInverse); + const decimal mass = mWorld.mRigidBodyComponents.getMass(mEntity); + + if (mass > decimal(0.0)) { + mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(1.0) / mass) ; + } + else { + mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(0.0)); + } + + // Compute the inverse local inertia tensor + const Matrix3x3& inertiaTensorLocal = mWorld.mRigidBodyComponents.getLocalInertiaTensor(mEntity); + if (approxEqual(inertiaTensorLocal.getDeterminant(), decimal(0.0))) { + mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, Matrix3x3::zero()); + } + else { + mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, inertiaTensorLocal.getInverse()); } } @@ -112,32 +121,12 @@ void RigidBody::setType(BodyType type) { (type == BodyType::STATIC ? "Static" : (type == BodyType::DYNAMIC ? "Dynamic" : "Kinematic"))); } -// Get the inverse local inertia tensor of the body (in body coordinates) -const Matrix3x3& RigidBody::getInverseInertiaTensorLocal() const { - return mWorld.mRigidBodyComponents.getInertiaTensorLocalInverse(mEntity); -} - -// Return the inverse of the inertia tensor in world coordinates. -/// 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 -/** - * @return The 3x3 inverse inertia tensor matrix of the body in world-space - * coordinates - */ -const Matrix3x3 RigidBody::getInertiaTensorInverseWorld() const { - - return getInertiaTensorInverseWorld(mWorld, mEntity); -} - // Method that return the mass of the body /** * @return The mass (in kilograms) of the body */ decimal RigidBody::getMass() const { - return mWorld.mRigidBodyComponents.getInitMass(mEntity); + return mWorld.mRigidBodyComponents.getMass(mEntity); } // Apply an external force to the body at a given point (in world-space coordinates). @@ -171,22 +160,29 @@ void RigidBody::applyForce(const Vector3& force, const Vector3& point) { mWorld.mRigidBodyComponents.setExternalTorque(mEntity, externalTorque + (point - centerOfMassWorld).cross(force)); } +// Return the local inertia tensor of the body (in body coordinates) +const Matrix3x3& RigidBody::getLocalInertiaTensor() const { + + return mWorld.mRigidBodyComponents.getLocalInertiaTensor(mEntity); +} + // 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. +/// Note that an inertia tensor with a zero value on its diagonal is interpreted as infinite inertia. /** * @param inertiaTensorLocal The 3x3 inertia tensor matrix of the body in local-space * coordinates */ -void RigidBody::setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal) { +void RigidBody::setLocalInertiaTensor(const Matrix3x3& inertiaTensorLocal) { - mUserInertiaTensorLocalInverse = inertiaTensorLocal.getInverse(); - mIsInertiaTensorSetByUser = true; - - if (mWorld.mRigidBodyComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; + mWorld.mRigidBodyComponents.setLocalInertiaTensor(mEntity, inertiaTensorLocal); // Compute the inverse local inertia tensor - mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, mUserInertiaTensorLocalInverse); + if (approxEqual(inertiaTensorLocal.getDeterminant(), decimal(0.0))) { + mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, Matrix3x3::zero()); + } + else { + mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, inertiaTensorLocal.getInverse()); + } RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, "Body " + std::to_string(mEntity.id) + ": Set inertiaTensorLocal=" + inertiaTensorLocal.to_string()); @@ -231,45 +227,18 @@ decimal RigidBody::getAngularDamping() const { return mWorld.mRigidBodyComponents.getAngularDamping(mEntity); } -// 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. +// Set the center of mass of the body (in local-space coordinates) +/// This method does not move the rigid body in the world. /** - * @param inverseInertiaTensorLocal The 3x3 inverse inertia tensor matrix of the body in local-space - * coordinates + * @param centerOfMass The center of mass of the body in local-space coordinates */ -void RigidBody::setInverseInertiaTensorLocal(const Matrix3x3& inverseInertiaTensorLocal) { - - mUserInertiaTensorLocalInverse = inverseInertiaTensorLocal; - mIsInertiaTensorSetByUser = true; - - if (mWorld.mRigidBodyComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; - - // Compute the inverse local inertia tensor - mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, mUserInertiaTensorLocalInverse); - - RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, - "Body " + std::to_string(mEntity.id) + ": Set inverseInertiaTensorLocal=" + inverseInertiaTensorLocal.to_string()); -} - -// 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 - * coordinates - */ -void RigidBody::setCenterOfMassLocal(const Vector3& centerOfMassLocal) { - - if (mWorld.mRigidBodyComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; - - mIsCenterOfMassSetByUser = true; +void RigidBody::setLocalCenterOfMass(const Vector3& centerOfMass) { const Vector3 oldCenterOfMass = mWorld.mRigidBodyComponents.getCenterOfMassWorld(mEntity); - mWorld.mRigidBodyComponents.setCenterOfMassLocal(mEntity, centerOfMassLocal); + mWorld.mRigidBodyComponents.setCenterOfMassLocal(mEntity, centerOfMass); // Compute the center of mass in world-space coordinates - mWorld.mRigidBodyComponents.setCenterOfMassWorld(mEntity, mWorld.mTransformComponents.getTransform(mEntity) * centerOfMassLocal); + mWorld.mRigidBodyComponents.setCenterOfMassWorld(mEntity, mWorld.mTransformComponents.getTransform(mEntity) * centerOfMass); // Update the linear velocity of the center of mass Vector3 linearVelocity = mWorld.mRigidBodyComponents.getAngularVelocity(mEntity); @@ -278,26 +247,258 @@ void RigidBody::setCenterOfMassLocal(const Vector3& centerOfMassLocal) { linearVelocity += angularVelocity.cross(centerOfMassWorld - oldCenterOfMass); mWorld.mRigidBodyComponents.setLinearVelocity(mEntity, linearVelocity); + RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, + "Body " + std::to_string(mEntity.id) + ": Set centerOfMassLocal=" + centerOfMass.to_string()); +} + +// Return the center of mass of the body (in local-space coordinates) +const Vector3& RigidBody::getLocalCenterOfMass() const { + return mWorld.mRigidBodyComponents.getCenterOfMassLocal(mEntity); +} + +// Compute and set the local-space center of mass of the body using its colliders +/// This method uses the shape, mass density and transforms of the colliders to set +/// the center of mass of the body. Note that calling this method will overwrite the +/// mass that has been previously set with the RigidBody::setCenterOfMass() method. Moreover, this method +/// does not use the mass set by the user with the RigidBody::setMass() method to compute the center +/// of mass but only the mass density and volume of the colliders. +void RigidBody::updateLocalCenterOfMassFromColliders() { + + const Vector3 oldCenterOfMassWorld = mWorld.mRigidBodyComponents.getCenterOfMassWorld(mEntity); + + Vector3 centerOfMassLocal = computeCenterOfMass(); + + const Vector3 centerOfMassWorld = mWorld.mTransformComponents.getTransform(mEntity) * centerOfMassLocal; + + // Set the center of mass + mWorld.mRigidBodyComponents.setCenterOfMassLocal(mEntity, centerOfMassLocal); + mWorld.mRigidBodyComponents.setCenterOfMassWorld(mEntity, centerOfMassWorld); + + // Update the linear velocity of the center of mass + Vector3 linearVelocity = mWorld.mRigidBodyComponents.getAngularVelocity(mEntity); + const Vector3& angularVelocity = mWorld.mRigidBodyComponents.getAngularVelocity(mEntity); + linearVelocity += angularVelocity.cross(centerOfMassWorld - oldCenterOfMassWorld); + mWorld.mRigidBodyComponents.setLinearVelocity(mEntity, linearVelocity); + RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, "Body " + std::to_string(mEntity.id) + ": Set centerOfMassLocal=" + centerOfMassLocal.to_string()); } +// Compute and return the local-space center of mass of the body using its colliders +Vector3 RigidBody::computeCenterOfMass() const { + + decimal totalMass = decimal(0.0); + Vector3 centerOfMassLocal(0, 0, 0); + + // Compute the local center of mass + const List& colliderEntities = mWorld.mCollisionBodyComponents.getColliders(mEntity); + for (uint i=0; i < colliderEntities.size(); i++) { + + Collider* collider = mWorld.mCollidersComponents.getCollider(colliderEntities[i]); + + const decimal colliderVolume = mWorld.mCollidersComponents.getCollisionShape(colliderEntities[i])->getVolume(); + const decimal colliderMassDensity = collider->getMaterial().getMassDensity(); + + const decimal colliderMass = colliderVolume * colliderMassDensity; + + totalMass += colliderMass; + centerOfMassLocal += colliderMass * mWorld.mCollidersComponents.getLocalToBodyTransform(colliderEntities[i]).getPosition(); + } + + if (totalMass > decimal(0.0)) { + centerOfMassLocal /= totalMass; + } + + return centerOfMassLocal; +} + +// Compute the local-space inertia tensor and total mass of the body using its colliders +void RigidBody::computeMassAndInertiaTensorLocal(Matrix3x3& inertiaTensorLocal, decimal& totalMass) const { + + inertiaTensorLocal.setToZero(); + totalMass = decimal(0.0); + + const Vector3 centerOfMassLocal = mWorld.mRigidBodyComponents.getCenterOfMassLocal(mEntity); + + // Compute the inertia tensor using all the colliders + const List& colliderEntities = mWorld.mCollisionBodyComponents.getColliders(mEntity); + for (uint i=0; i < colliderEntities.size(); i++) { + + Collider* collider = mWorld.mCollidersComponents.getCollider(colliderEntities[i]); + + const decimal colliderVolume = mWorld.mCollidersComponents.getCollisionShape(colliderEntities[i])->getVolume(); + const decimal colliderMassDensity = collider->getMaterial().getMassDensity(); + const decimal colliderMass = colliderVolume * colliderMassDensity; + + totalMass += colliderMass; + + // Get the inertia tensor of the collider in its local-space + Matrix3x3 inertiaTensor; + collider->getCollisionShape()->computeLocalInertiaTensor(inertiaTensor, colliderMass); + + // Convert the collider inertia tensor into the local-space of the body + const Transform& shapeTransform = collider->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 collider + // center into a inertia tensor w.r.t to the body origin. + Vector3 offset = shapeTransform.getPosition() - centerOfMassLocal; + 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 *= colliderMass; + + inertiaTensorLocal += inertiaTensor + offsetMatrix; + } +} + +// Compute and set the local-space inertia tensor of the body using its colliders +/// This method uses the shape, mass density and transforms of the colliders to set +/// the local-space inertia tensor of the body. Note that calling this method will overwrite the +/// mass that has been set with the RigidBody::setInertiaTensorLocal() method. +void RigidBody::updateLocalInertiaTensorFromColliders() { + + const Vector3 centerOfMassLocal = mWorld.mRigidBodyComponents.getCenterOfMassLocal(mEntity); + + // Compute the local-space inertia tensor + Matrix3x3 inertiaTensorLocal; + decimal totalMass; + computeMassAndInertiaTensorLocal(inertiaTensorLocal, totalMass); + + mWorld.mRigidBodyComponents.setLocalInertiaTensor(mEntity, inertiaTensorLocal); + + // Compute the inverse local inertia tensor + if (approxEqual(inertiaTensorLocal.getDeterminant(), decimal(0.0))) { + mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, Matrix3x3::zero()); + } + else { + mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, inertiaTensorLocal.getInverse()); + } + + RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, + "Body " + std::to_string(mEntity.id) + ": Set inertiaTensorLocal=" + inertiaTensorLocal.to_string()); +} + +// Compute and set the mass of the body using its colliders +/// This method uses the shape, mass density and transforms of the colliders to set +/// the total mass of the body. Note that calling this method will overwrite the +/// mass that has been set with the RigidBody::setMass() method +void RigidBody::updateMassFromColliders() { + + decimal totalMass = decimal(0.0); + + // Compute the total mass of the body + const List& colliderEntities = mWorld.mCollisionBodyComponents.getColliders(mEntity); + for (uint i=0; i < colliderEntities.size(); i++) { + Collider* collider = mWorld.mCollidersComponents.getCollider(colliderEntities[i]); + + const decimal colliderVolume = mWorld.mCollidersComponents.getCollisionShape(colliderEntities[i])->getVolume(); + const decimal colliderMassDensity = collider->getMaterial().getMassDensity(); + + const decimal colliderMass = colliderVolume * colliderMassDensity; + + totalMass += colliderMass; + } + + // Set the mass + mWorld.mRigidBodyComponents.setMass(mEntity, totalMass); + + // Compute the inverse mass + if (totalMass > decimal(0.0)) { + mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(1.0) / totalMass); + } + else { + mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(0.0)); + } + + RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, + "Body " + std::to_string(mEntity.id) + ": Set mass=" + std::to_string(totalMass)); +} + +// Compute and set the center of mass, the mass and the local-space inertia tensor of the body using its colliders +/// This method uses the shape, mass density and transform of the colliders of the body to set +/// the total mass, the center of mass and the local inertia tensor of the body. +/// Note that calling this method will overwrite the +/// mass that has been set with the RigidBody::setMass(), the center of mass that has been +/// set with RigidBody::setCenterOfMass() and the local inertia tensor that has been set with +/// RigidBody::setInertiaTensorLocal(). +void RigidBody::updateMassPropertiesFromColliders() { + + const Vector3 oldCenterOfMassWorld = mWorld.mRigidBodyComponents.getCenterOfMassWorld(mEntity); + + // Compute the local center of mass + Vector3 centerOfMassLocal = computeCenterOfMass(); + + const Vector3 centerOfMassWorld = mWorld.mTransformComponents.getTransform(mEntity) * centerOfMassLocal; + + // Set the center of mass + mWorld.mRigidBodyComponents.setCenterOfMassLocal(mEntity, centerOfMassLocal); + mWorld.mRigidBodyComponents.setCenterOfMassWorld(mEntity, centerOfMassWorld); + + // Update the linear velocity of the center of mass + Vector3 linearVelocity = mWorld.mRigidBodyComponents.getAngularVelocity(mEntity); + const Vector3& angularVelocity = mWorld.mRigidBodyComponents.getAngularVelocity(mEntity); + linearVelocity += angularVelocity.cross(centerOfMassWorld - oldCenterOfMassWorld); + mWorld.mRigidBodyComponents.setLinearVelocity(mEntity, linearVelocity); + + RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, + "Body " + std::to_string(mEntity.id) + ": Set centerOfMassLocal=" + centerOfMassLocal.to_string()); + + // Compute the mass and local-space inertia tensor + Matrix3x3 inertiaTensorLocal; + decimal totalMass; + computeMassAndInertiaTensorLocal(inertiaTensorLocal, totalMass); + + mWorld.mRigidBodyComponents.setLocalInertiaTensor(mEntity, inertiaTensorLocal); + + // Compute the inverse local inertia tensor + if (approxEqual(inertiaTensorLocal.getDeterminant(), decimal(0.0))) { + mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, Matrix3x3::zero()); + } + else { + mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, inertiaTensorLocal.getInverse()); + } + + RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, + "Body " + std::to_string(mEntity.id) + ": Set inertiaTensorLocal=" + inertiaTensorLocal.to_string()); + + // Set the mass + mWorld.mRigidBodyComponents.setMass(mEntity, totalMass); + + // Compute the inverse mass + if (totalMass > decimal(0.0)) { + mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(1.0) / totalMass); + } + else { + mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(0.0)); + } + + RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, + "Body " + std::to_string(mEntity.id) + ": Set mass=" + std::to_string(totalMass)); +} + // Set the mass of the rigid body +/// Note that a mass of zero is interpreted as infinite mass. /** * @param mass The mass (in kilograms) of the body */ void RigidBody::setMass(decimal mass) { - if (mWorld.mRigidBodyComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; + mWorld.mRigidBodyComponents.setMass(mEntity, mass); - mWorld.mRigidBodyComponents.setInitMass(mEntity, mass); + // TODO : Report error if mass is negative - if (mWorld.mRigidBodyComponents.getInitMass(mEntity) > decimal(0.0)) { - mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(1.0) / mWorld.mRigidBodyComponents.getInitMass(mEntity)); + if (mWorld.mRigidBodyComponents.getMass(mEntity) > decimal(0.0)) { + mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(1.0) / mass); } else { - mWorld.mRigidBodyComponents.setInitMass(mEntity, decimal(1.0)); - mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(1.0)); + mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(0.0)); } RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, @@ -315,10 +516,9 @@ void RigidBody::setMass(decimal mass) { * @param collisionShape The collision shape of the new collider * @param transform The transformation of the collider that transforms the * local-space of the collider into the local-space of the body - * @param mass Mass (in kilograms) of the collider you want to add * @return A pointer to the collider that has been created */ -Collider* RigidBody::addCollider(CollisionShape* collisionShape, const Transform& transform, decimal mass) { +Collider* RigidBody::addCollider(CollisionShape* collisionShape, const Transform& transform) { // Create a new entity for the collider Entity colliderEntity = mWorld.mEntityManager.createEntity(); @@ -333,9 +533,8 @@ Collider* RigidBody::addCollider(CollisionShape* collisionShape, const Transform // TODO : Maybe this method can directly returns an AABB collisionShape->getLocalBounds(localBoundsMin, localBoundsMax); const Transform localToWorldTransform = mWorld.mTransformComponents.getTransform(mEntity) * transform; - ColliderComponents::ColliderComponent colliderComponent(mEntity, collider, - AABB(localBoundsMin, localBoundsMax), - transform, collisionShape, mass, 0x0001, 0xFFFF, localToWorldTransform); + ColliderComponents::ColliderComponent colliderComponent(mEntity, collider, AABB(localBoundsMin, localBoundsMax), + transform, collisionShape, 0x0001, 0xFFFF, localToWorldTransform); bool isSleeping = mWorld.mRigidBodyComponents.getIsSleeping(mEntity); mWorld.mCollidersComponents.addComponent(colliderEntity, isSleeping, colliderComponent); @@ -365,10 +564,6 @@ Collider* RigidBody::addCollider(CollisionShape* collisionShape, const Transform // Notify the collision detection about this new collision shape mWorld.mCollisionDetection.addCollider(collider, aabb); - // Recompute the center of mass, total mass and inertia tensor of the body with the new - // collision shape - recomputeMassInformation(); - RP3D_LOG(mLogger, Logger::Level::Information, Logger::Category::Body, "Body " + std::to_string(mEntity.id) + ": Collider " + std::to_string(collider->getBroadPhaseId()) + " added to body"); @@ -389,9 +584,6 @@ void RigidBody::removeCollider(Collider* collider) { // Remove the collision shape CollisionBody::removeCollider(collider); - - // Recompute the total mass, center of mass and inertia tensor - recomputeMassInformation(); } // Set the variable to know if the gravity is applied to this rigid body @@ -500,101 +692,6 @@ void RigidBody::setTransform(const Transform& transform) { setIsSleeping(false); } -// Recompute the center of mass, total mass and inertia tensor of the body using all -// the collision shapes attached to the body. -void RigidBody::recomputeMassInformation() { - - mWorld.mRigidBodyComponents.setInitMass(mEntity, decimal(0.0)); - mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(0.0)); - if (!mIsInertiaTensorSetByUser) mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, Matrix3x3::zero()); - if (!mIsCenterOfMassSetByUser) mWorld.mRigidBodyComponents.setCenterOfMassLocal(mEntity, Vector3::zero()); - Matrix3x3 inertiaTensorLocal; - inertiaTensorLocal.setToZero(); - - const Transform& transform = mWorld.mTransformComponents.getTransform(mEntity); - - // If it is a STATIC or a KINEMATIC body - BodyType type = mWorld.mRigidBodyComponents.getBodyType(mEntity); - if (type == BodyType::STATIC || type == BodyType::KINEMATIC) { - mWorld.mRigidBodyComponents.setCenterOfMassWorld(mEntity, transform.getPosition()); - return; - } - - assert(mWorld.mRigidBodyComponents.getBodyType(mEntity) == BodyType::DYNAMIC); - - // Compute the total mass of the body - const List& colliderEntities = mWorld.mCollisionBodyComponents.getColliders(mEntity); - for (uint i=0; i < colliderEntities.size(); i++) { - Collider* collider = mWorld.mCollidersComponents.getCollider(colliderEntities[i]); - mWorld.mRigidBodyComponents.setInitMass(mEntity, mWorld.mRigidBodyComponents.getInitMass(mEntity) + collider->getMass()); - - if (!mIsCenterOfMassSetByUser) { - mWorld.mRigidBodyComponents.setCenterOfMassLocal(mEntity, mWorld.mRigidBodyComponents.getCenterOfMassLocal(mEntity) + - collider->getLocalToBodyTransform().getPosition() * collider->getMass()); - } - } - - if (mWorld.mRigidBodyComponents.getInitMass(mEntity) > decimal(0.0)) { - mWorld.mRigidBodyComponents.setMassInverse(mEntity, decimal(1.0) / mWorld.mRigidBodyComponents.getInitMass(mEntity)); - } - else { - mWorld.mRigidBodyComponents.setCenterOfMassWorld(mEntity, transform.getPosition()); - return; - } - - // Compute the center of mass - const Vector3 oldCenterOfMass = mWorld.mRigidBodyComponents.getCenterOfMassWorld(mEntity); - - if (!mIsCenterOfMassSetByUser) { - mWorld.mRigidBodyComponents.setCenterOfMassLocal(mEntity, mWorld.mRigidBodyComponents.getCenterOfMassLocal(mEntity) * mWorld.mRigidBodyComponents.getMassInverse(mEntity)); - } - - mWorld.mRigidBodyComponents.setCenterOfMassWorld(mEntity, transform * mWorld.mRigidBodyComponents.getCenterOfMassLocal(mEntity)); - - if (!mIsInertiaTensorSetByUser) { - - // Compute the inertia tensor using all the colliders - const List& colliderEntities = mWorld.mCollisionBodyComponents.getColliders(mEntity); - for (uint i=0; i < colliderEntities.size(); i++) { - - Collider* collider = mWorld.mCollidersComponents.getCollider(colliderEntities[i]); - - // Get the inertia tensor of the collider in its local-space - Matrix3x3 inertiaTensor; - collider->getCollisionShape()->computeLocalInertiaTensor(inertiaTensor, collider->getMass()); - - // Convert the collider inertia tensor into the local-space of the body - const Transform& shapeTransform = collider->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 collider - // center into a inertia tensor w.r.t to the body origin. - Vector3 offset = shapeTransform.getPosition() - mWorld.mRigidBodyComponents.getCenterOfMassLocal(mEntity); - 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 *= collider->getMass(); - - inertiaTensorLocal += inertiaTensor + offsetMatrix; - } - - // Compute the local inverse inertia tensor - mWorld.mRigidBodyComponents.setInverseInertiaTensorLocal(mEntity, inertiaTensorLocal.getInverse()); - } - - // Update the linear velocity of the center of mass - Vector3 linearVelocity = mWorld.mRigidBodyComponents.getLinearVelocity(mEntity); - Vector3 angularVelocity = mWorld.mRigidBodyComponents.getAngularVelocity(mEntity); - linearVelocity += angularVelocity.cross(mWorld.mRigidBodyComponents.getCenterOfMassWorld(mEntity) - oldCenterOfMass); - mWorld.mRigidBodyComponents.setLinearVelocity(mEntity, linearVelocity); -} - // Return the linear velocity /** * @return The linear velocity vector of the body diff --git a/src/body/RigidBody.h b/src/body/RigidBody.h index 5f1b780a..2ecee142 100644 --- a/src/body/RigidBody.h +++ b/src/body/RigidBody.h @@ -51,18 +51,6 @@ class RigidBody : public CollisionBody { protected : - // -------------------- Attributes -------------------- // - - /// Inverse Local inertia tensor of the body (in local-space) set - /// by the user with respect to the center of mass of the body - Matrix3x3 mUserInertiaTensorLocalInverse; - - /// 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 -------------------- // /// Set the variable to know whether or not the body is sleeping @@ -71,6 +59,12 @@ class RigidBody : public CollisionBody { /// Update whether the current overlapping pairs where this body is involed are active or not void updateOverlappingPairs(); + /// Compute and return the local-space center of mass of the body using its colliders + Vector3 computeCenterOfMass() const; + + /// Compute the local-space inertia tensor and total mass of the body using its colliders + void computeMassAndInertiaTensorLocal(Matrix3x3& inertiaTensorLocal, decimal& totalMass) const; + /// Return the inverse of the inertia tensor in world coordinates. static const Matrix3x3 getInertiaTensorInverseWorld(PhysicsWorld& world, Entity bodyEntity); @@ -96,6 +90,9 @@ class RigidBody : public CollisionBody { /// Return the mass of the body decimal getMass() const; + /// Set the mass of the rigid body + void setMass(decimal mass); + /// Return the linear velocity Vector3 getLinearVelocity() const; @@ -108,23 +105,29 @@ class RigidBody : public CollisionBody { /// Set the angular velocity. void setAngularVelocity(const Vector3& angularVelocity); + /// Return the local inertia tensor of the body (in body coordinates) + const Matrix3x3& getLocalInertiaTensor() const; + /// Set the local inertia tensor of the body (in body coordinates) - void setInertiaTensorLocal(const Matrix3x3& inertiaTensorLocal); + void setLocalInertiaTensor(const Matrix3x3& inertiaTensorLocal); - /// Set the inverse local inertia tensor of the body (in body coordinates) - void setInverseInertiaTensorLocal(const Matrix3x3& inverseInertiaTensorLocal); + /// Return the center of mass of the body (in local-space coordinates) + const Vector3& getLocalCenterOfMass() const; - /// Get the inverse local inertia tensor of the body (in body coordinates) - const Matrix3x3& getInverseInertiaTensorLocal() const; + /// Set the center of mass of the body (in local-space coordinates) + void setLocalCenterOfMass(const Vector3& centerOfMass); - /// Return the inverse of the inertia tensor in world coordinates. - const Matrix3x3 getInertiaTensorInverseWorld() const; + /// Compute and set the local-space center of mass of the body using its colliders + void updateLocalCenterOfMassFromColliders(); - /// Set the local center of mass of the body (in local-space coordinates) - void setCenterOfMassLocal(const Vector3& centerOfMassLocal); + /// Compute and set the local-space inertia tensor of the body using its colliders + void updateLocalInertiaTensorFromColliders(); - /// Set the mass of the rigid body - void setMass(decimal mass); + /// Compute and set the mass of the body using its colliders + void updateMassFromColliders(); + + /// Compute and set the center of mass, the mass and the local-space inertia tensor of the body using its colliders + void updateMassPropertiesFromColliders(); /// Return the type of the body BodyType getType() const; @@ -172,17 +175,11 @@ class RigidBody : public CollisionBody { virtual void setIsActive(bool isActive) override; /// Create a new collider and add it to the body - // TODO : Remove the mass from this parameter so that we can correctly use inheritance here - // The user will then need to call Collider->setMass() to set the mass of the shape - virtual Collider* addCollider(CollisionShape* collisionShape, const Transform& transform, decimal mass); + virtual Collider* addCollider(CollisionShape* collisionShape, const Transform& transform) override; /// Remove a collider from the body virtual void removeCollider(Collider* collider) override; - /// Recompute the center of mass, total mass and inertia tensor of the body using all - /// the collision shapes attached to the body. - void recomputeMassInformation(); - #ifdef IS_PROFILING_ACTIVE /// Set the profiler diff --git a/src/collision/Collider.cpp b/src/collision/Collider.cpp index d2c24076..2ada633a 100644 --- a/src/collision/Collider.cpp +++ b/src/collision/Collider.cpp @@ -51,15 +51,6 @@ Collider::~Collider() { } -// Return the mass of the collision shape -/** - * @return Mass of the collision shape (in kilograms) - */ -decimal Collider::getMass() const { - return mBody->mWorld.mCollidersComponents.getMass(mEntity); -} - - // Return true if a point is inside the collision shape /** * @param worldPoint Point to test in world-space coordinates diff --git a/src/collision/Collider.h b/src/collision/Collider.h index 66f9f818..fd849800 100644 --- a/src/collision/Collider.h +++ b/src/collision/Collider.h @@ -112,9 +112,6 @@ class Collider { /// Return the parent body CollisionBody* getBody() const; - /// Return the mass of the collision shape - decimal getMass() const; - /// Return a pointer to the user data attached to this body void* getUserData() const; diff --git a/src/collision/PolyhedronMesh.cpp b/src/collision/PolyhedronMesh.cpp index 3245ff19..e4f53ed3 100644 --- a/src/collision/PolyhedronMesh.cpp +++ b/src/collision/PolyhedronMesh.cpp @@ -27,6 +27,7 @@ #include "PolyhedronMesh.h" #include "memory/MemoryManager.h" #include "collision/PolygonVertexArray.h" +#include using namespace reactphysics3d; @@ -153,3 +154,48 @@ void PolyhedronMesh::computeCentroid() { mCentroid /= getNbVertices(); } + +// Compute and return the area of a face +decimal PolyhedronMesh::getFaceArea(uint faceIndex) const { + + Vector3 sumCrossProducts(0, 0, 0); + + const HalfEdgeStructure::Face& face = mHalfEdgeStructure.getFace(faceIndex); + assert(face.faceVertices.size() >= 3); + + Vector3 v1 = getVertex(face.faceVertices[0]); + + // For each vertex of the face + for (uint i=2; i < face.faceVertices.size(); i++) { + + const Vector3 v2 = getVertex(face.faceVertices[i-1]); + const Vector3 v3 = getVertex(face.faceVertices[i]); + + const Vector3 v1v2 = v2 - v1; + const Vector3 v1v3 = v3 - v1; + + sumCrossProducts += v1v2.cross(v1v3); + } + + return decimal(0.5) * sumCrossProducts.length(); +} + +// Compute and return the volume of the polyhedron +/// We use the divergence theorem to compute the volume of the polyhedron using a sum over its faces. +decimal PolyhedronMesh::getVolume() const { + + decimal sum = 0.0; + + // For each face of the polyhedron + for (uint f=0; f < getNbFaces(); f++) { + + const HalfEdgeStructure::Face& face = mHalfEdgeStructure.getFace(f); + const decimal faceArea = getFaceArea(f); + const Vector3 faceNormal = mFacesNormals[f]; + const Vector3 faceVertex = getVertex(face.faceVertices[0]); + + sum += faceVertex.dot(faceNormal) * faceArea; + } + + return std::abs(sum) / decimal(3.0); +} diff --git a/src/collision/PolyhedronMesh.h b/src/collision/PolyhedronMesh.h index a5ae6114..4b3696f4 100644 --- a/src/collision/PolyhedronMesh.h +++ b/src/collision/PolyhedronMesh.h @@ -77,6 +77,9 @@ class PolyhedronMesh { /// Compute the centroid of the polyhedron void computeCentroid() ; + /// Compute and return the area of a face + decimal getFaceArea(uint faceIndex) const; + public: // -------------------- Methods -------------------- // @@ -102,6 +105,9 @@ class PolyhedronMesh { /// Return the centroid of the polyhedron Vector3 getCentroid() const; + /// Compute and return the volume of the polyhedron + decimal getVolume() const; + // ---------- Friendship ---------- // friend class PhysicsCommon; diff --git a/src/collision/shapes/BoxShape.h b/src/collision/shapes/BoxShape.h index ded03c63..a885662a 100644 --- a/src/collision/shapes/BoxShape.h +++ b/src/collision/shapes/BoxShape.h @@ -98,6 +98,9 @@ class BoxShape : public ConvexPolyhedronShape { /// Return the local inertia tensor of the collision shape virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const override; + /// Compute and return the volume of the collision shape + virtual decimal getVolume() const override; + /// Return the number of faces of the polyhedron virtual uint getNbFaces() const override; @@ -253,6 +256,11 @@ inline Vector3 BoxShape::getCentroid() const { return Vector3::zero(); } +// Compute and return the volume of the collision shape +inline decimal BoxShape::getVolume() const { + return 8 * mHalfExtents.x * mHalfExtents.y * mHalfExtents.z; +} + // Return the string representation of the shape inline std::string BoxShape::to_string() const { return "BoxShape{extents=" + mHalfExtents.to_string() + "}"; diff --git a/src/collision/shapes/CapsuleShape.h b/src/collision/shapes/CapsuleShape.h index 4b37bdc5..0e8565c1 100644 --- a/src/collision/shapes/CapsuleShape.h +++ b/src/collision/shapes/CapsuleShape.h @@ -105,6 +105,9 @@ class CapsuleShape : public ConvexShape { /// Return the local bounds of the shape in x, y and z directions virtual void getLocalBounds(Vector3& min, Vector3& max) const override; + /// Compute and return the volume of the collision shape + virtual decimal getVolume() const override; + /// Return true if the collision shape is a polyhedron virtual bool isPolyhedron() const override; @@ -188,6 +191,11 @@ inline void CapsuleShape::getLocalBounds(Vector3& min, Vector3& max) const { min.z = min.x; } +// Compute and return the volume of the collision shape +inline decimal CapsuleShape::getVolume() const { + return reactphysics3d::PI * mMargin * mMargin * (decimal(4.0) * mMargin / decimal(3.0) + decimal(2.0) * mHalfHeight); +} + // Return true if the collision shape is a polyhedron inline bool CapsuleShape::isPolyhedron() const { return false; diff --git a/src/collision/shapes/CollisionShape.h b/src/collision/shapes/CollisionShape.h index 853de58a..8d609946 100644 --- a/src/collision/shapes/CollisionShape.h +++ b/src/collision/shapes/CollisionShape.h @@ -30,6 +30,7 @@ #include #include "configuration.h" #include "utils/Profiler.h" +#include "containers/List.h" /// ReactPhysics3D namespace namespace reactphysics3d { @@ -142,6 +143,9 @@ class CollisionShape { /// Return the local inertia tensor of the collision shapes virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const=0; + /// Compute and return the volume of the collision shape + virtual decimal getVolume() const=0; + /// Compute the world-space AABB of the collision shape given a transform virtual void computeAABB(AABB& aabb, const Transform& transform) const; diff --git a/src/collision/shapes/ConcaveShape.cpp b/src/collision/shapes/ConcaveShape.cpp index 41f4069b..d60862d0 100644 --- a/src/collision/shapes/ConcaveShape.cpp +++ b/src/collision/shapes/ConcaveShape.cpp @@ -36,3 +36,19 @@ ConcaveShape::ConcaveShape(CollisionShapeName name, MemoryAllocator& allocator, mScale(scaling) { } + +// Compute and return the volume of the collision shape +/// Note that we approximate the volume of a concave shape with the volume of its AABB +decimal ConcaveShape::getVolume() const { + Vector3 minBounds, maxBounds; + + // Compute the local bounds + getLocalBounds(minBounds, maxBounds); + + const decimal lengthX = maxBounds.x - minBounds.x; + const decimal lengthY = maxBounds.y - minBounds.y; + const decimal lengthZ = maxBounds.z - minBounds.z; + + // Approximate the volume of the concave shape as the volume of its AABB + return lengthX * lengthY * lengthZ; +} diff --git a/src/collision/shapes/ConcaveShape.h b/src/collision/shapes/ConcaveShape.h index 421a57ea..3eeb5285 100644 --- a/src/collision/shapes/ConcaveShape.h +++ b/src/collision/shapes/ConcaveShape.h @@ -111,6 +111,9 @@ class ConcaveShape : public CollisionShape { virtual void computeOverlappingTriangles(const AABB& localAABB, List& triangleVertices, List& triangleVerticesNormals, List& shapeIds, MemoryAllocator& allocator) const=0; + + /// Compute and return the volume of the collision shape + virtual decimal getVolume() const override; }; // Return true if the collision shape is convex, false if it is concave @@ -155,6 +158,7 @@ inline void ConcaveShape::setScale(const Vector3& scale) { notifyColliderAboutChangedSize(); } + } #endif diff --git a/src/collision/shapes/ConvexMeshShape.h b/src/collision/shapes/ConvexMeshShape.h index 8313fe92..af2c4e4d 100644 --- a/src/collision/shapes/ConvexMeshShape.h +++ b/src/collision/shapes/ConvexMeshShape.h @@ -135,6 +135,9 @@ class ConvexMeshShape : public ConvexPolyhedronShape { /// Return the centroid of the polyhedron virtual Vector3 getCentroid() const override; + /// Compute and return the volume of the collision shape + virtual decimal getVolume() const override; + /// Return the string representation of the shape virtual std::string to_string() const override; @@ -242,6 +245,12 @@ inline Vector3 ConvexMeshShape::getCentroid() const { return mPolyhedronMesh->getCentroid() * mScale; } + +// Compute and return the volume of the collision shape +inline decimal ConvexMeshShape::getVolume() const { + return mPolyhedronMesh->getVolume(); +} + } #endif diff --git a/src/collision/shapes/SphereShape.h b/src/collision/shapes/SphereShape.h index a5d7bd95..6f2cd086 100644 --- a/src/collision/shapes/SphereShape.h +++ b/src/collision/shapes/SphereShape.h @@ -93,6 +93,9 @@ class SphereShape : public ConvexShape { /// Return the local inertia tensor of the collision shape virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const override; + /// Compute and return the volume of the collision shape + virtual decimal getVolume() const override; + /// Update the AABB of a body using its collision shape virtual void computeAABB(AABB& aabb, const Transform& transform) const override; @@ -180,6 +183,11 @@ inline void SphereShape::computeLocalInertiaTensor(Matrix3x3& tensor, decimal ma 0.0, 0.0, diag); } +// Compute and return the volume of the collision shape +inline decimal SphereShape::getVolume() const { + return decimal(4.0) / decimal(3.0) * reactphysics3d::PI * mMargin * mMargin * mMargin; +} + // Return true if a point is inside the collision shape inline bool SphereShape::testPointInside(const Vector3& localPoint, Collider* collider) const { return (localPoint.lengthSquare() < mMargin * mMargin); diff --git a/src/collision/shapes/TriangleShape.h b/src/collision/shapes/TriangleShape.h index e7a40882..9d2a827c 100644 --- a/src/collision/shapes/TriangleShape.h +++ b/src/collision/shapes/TriangleShape.h @@ -166,6 +166,9 @@ class TriangleShape : public ConvexPolyhedronShape { /// Return the centroid of the polyhedron virtual Vector3 getCentroid() const override; + /// Compute and return the volume of the collision shape + virtual decimal getVolume() const override; + /// This method compute the smooth mesh contact with a triangle in case one of the two collision shapes is a triangle. The idea in this case is to use a smooth vertex normal of the triangle mesh static void computeSmoothTriangleMeshContact(const CollisionShape* shape1, const CollisionShape* shape2, Vector3& localContactPointShape1, Vector3& localContactPointShape2, @@ -304,6 +307,11 @@ inline std::string TriangleShape::to_string() const { "v3=" + mPoints[2].to_string() + "}"; } +// Compute and return the volume of the collision shape +inline decimal TriangleShape::getVolume() const { + return decimal(0.0); +} + } #endif diff --git a/src/components/ColliderComponents.cpp b/src/components/ColliderComponents.cpp index 7cd9de62..7d890e39 100644 --- a/src/components/ColliderComponents.cpp +++ b/src/components/ColliderComponents.cpp @@ -35,8 +35,8 @@ using namespace reactphysics3d; // Constructor ColliderComponents::ColliderComponents(MemoryAllocator& allocator) - :Components(allocator, sizeof(Entity) + sizeof(Entity) + sizeof(Collider*) + sizeof(int) + - sizeof(Transform) + sizeof(CollisionShape*) + sizeof(decimal) + sizeof(unsigned short) + + :Components(allocator, sizeof(Entity) + sizeof(Entity) + sizeof(Collider*) + sizeof(int32) + + sizeof(Transform) + sizeof(CollisionShape*) + sizeof(unsigned short) + sizeof(unsigned short) + sizeof(Transform) + sizeof(List) + sizeof(bool)) { // Allocate memory for the components data @@ -62,8 +62,7 @@ void ColliderComponents::allocate(uint32 nbComponentsToAllocate) { int32* newBroadPhaseIds = reinterpret_cast(newColliders + nbComponentsToAllocate); Transform* newLocalToBodyTransforms = reinterpret_cast(newBroadPhaseIds + nbComponentsToAllocate); CollisionShape** newCollisionShapes = reinterpret_cast(newLocalToBodyTransforms + nbComponentsToAllocate); - decimal* newMasses = reinterpret_cast(newCollisionShapes + nbComponentsToAllocate); - unsigned short* newCollisionCategoryBits = reinterpret_cast(newMasses + nbComponentsToAllocate); + unsigned short* newCollisionCategoryBits = reinterpret_cast(newCollisionShapes + nbComponentsToAllocate); unsigned short* newCollideWithMaskBits = reinterpret_cast(newCollisionCategoryBits + nbComponentsToAllocate); Transform* newLocalToWorldTransforms = reinterpret_cast(newCollideWithMaskBits + nbComponentsToAllocate); List* newOverlappingPairs = reinterpret_cast*>(newLocalToWorldTransforms + nbComponentsToAllocate); @@ -79,7 +78,6 @@ void ColliderComponents::allocate(uint32 nbComponentsToAllocate) { memcpy(newBroadPhaseIds, mBroadPhaseIds, mNbComponents * sizeof(int32)); memcpy(newLocalToBodyTransforms, mLocalToBodyTransforms, mNbComponents * sizeof(Transform)); memcpy(newCollisionShapes, mCollisionShapes, mNbComponents * sizeof(CollisionShape*)); - memcpy(newMasses, mMasses, mNbComponents * sizeof(decimal)); memcpy(newCollisionCategoryBits, mCollisionCategoryBits, mNbComponents * sizeof(unsigned short)); memcpy(newCollideWithMaskBits, mCollideWithMaskBits, mNbComponents * sizeof(unsigned short)); memcpy(newLocalToWorldTransforms, mLocalToWorldTransforms, mNbComponents * sizeof(Transform)); @@ -98,7 +96,6 @@ void ColliderComponents::allocate(uint32 nbComponentsToAllocate) { mBroadPhaseIds = newBroadPhaseIds; mLocalToBodyTransforms = newLocalToBodyTransforms; mCollisionShapes = newCollisionShapes; - mMasses = newMasses; mCollisionCategoryBits = newCollisionCategoryBits; mCollideWithMaskBits = newCollideWithMaskBits; mLocalToWorldTransforms = newLocalToWorldTransforms; @@ -121,7 +118,6 @@ void ColliderComponents::addComponent(Entity colliderEntity, bool isSleeping, co new (mBroadPhaseIds + index) int32(-1); new (mLocalToBodyTransforms + index) Transform(component.localToBodyTransform); mCollisionShapes[index] = component.collisionShape; - new (mMasses + index) decimal(component.mass); new (mCollisionCategoryBits + index) unsigned short(component.collisionCategoryBits); new (mCollideWithMaskBits + index) unsigned short(component.collideWithMaskBits); new (mLocalToWorldTransforms + index) Transform(component.localToWorldTransform); @@ -149,7 +145,6 @@ void ColliderComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex) new (mBroadPhaseIds + destIndex) int32(mBroadPhaseIds[srcIndex]); new (mLocalToBodyTransforms + destIndex) Transform(mLocalToBodyTransforms[srcIndex]); mCollisionShapes[destIndex] = mCollisionShapes[srcIndex]; - new (mMasses + destIndex) decimal(mMasses[srcIndex]); new (mCollisionCategoryBits + destIndex) unsigned short(mCollisionCategoryBits[srcIndex]); new (mCollideWithMaskBits + destIndex) unsigned short(mCollideWithMaskBits[srcIndex]); new (mLocalToWorldTransforms + destIndex) Transform(mLocalToWorldTransforms[srcIndex]); @@ -177,7 +172,6 @@ void ColliderComponents::swapComponents(uint32 index1, uint32 index2) { int32 broadPhaseId1 = mBroadPhaseIds[index1]; Transform localToBodyTransform1 = mLocalToBodyTransforms[index1]; CollisionShape* collisionShape1 = mCollisionShapes[index1]; - decimal mass1 = mMasses[index1]; unsigned short collisionCategoryBits1 = mCollisionCategoryBits[index1]; unsigned short collideWithMaskBits1 = mCollideWithMaskBits[index1]; Transform localToWorldTransform1 = mLocalToWorldTransforms[index1]; @@ -196,7 +190,6 @@ void ColliderComponents::swapComponents(uint32 index1, uint32 index2) { new (mBroadPhaseIds + index2) int32(broadPhaseId1); new (mLocalToBodyTransforms + index2) Transform(localToBodyTransform1); mCollisionShapes[index2] = collisionShape1; - new (mMasses + index2) decimal(mass1); new (mCollisionCategoryBits + index2) unsigned short(collisionCategoryBits1); new (mCollideWithMaskBits + index2) unsigned short(collideWithMaskBits1); new (mLocalToWorldTransforms + index2) Transform(localToWorldTransform1); diff --git a/src/components/ColliderComponents.h b/src/components/ColliderComponents.h index e30a844b..e96d72c1 100644 --- a/src/components/ColliderComponents.h +++ b/src/components/ColliderComponents.h @@ -73,9 +73,6 @@ class ColliderComponents : public Components { /// Pointers to the collision shapes of the colliders CollisionShape** mCollisionShapes; - /// Masses (in kilogramms) of the colliders - decimal* mMasses; - /// 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 /// shape. This value is one (0x0001) by default. This variable can be used @@ -124,17 +121,16 @@ class ColliderComponents : public Components { AABB localBounds; const Transform& localToBodyTransform; CollisionShape* collisionShape; - decimal mass; unsigned short collisionCategoryBits; unsigned short collideWithMaskBits; const Transform& localToWorldTransform; /// Constructor ColliderComponent(Entity bodyEntity, Collider* collider, AABB localBounds, const Transform& localToBodyTransform, - CollisionShape* collisionShape, decimal mass, unsigned short collisionCategoryBits, + CollisionShape* collisionShape, unsigned short collisionCategoryBits, unsigned short collideWithMaskBits, const Transform& localToWorldTransform) :bodyEntity(bodyEntity), collider(collider), localBounds(localBounds), localToBodyTransform(localToBodyTransform), - collisionShape(collisionShape), mass(mass), collisionCategoryBits(collisionCategoryBits), collideWithMaskBits(collideWithMaskBits), + collisionShape(collisionShape), collisionCategoryBits(collisionCategoryBits), collideWithMaskBits(collideWithMaskBits), localToWorldTransform(localToWorldTransform) { } @@ -154,9 +150,6 @@ class ColliderComponents : public Components { /// Return the body entity of a given collider Entity getBody(Entity colliderEntity) const; - /// Return the mass of a collider - decimal getMass(Entity colliderEntity) const; - /// Return a pointer to a given collider Collider* getCollider(Entity colliderEntity) const; @@ -218,14 +211,6 @@ inline Entity ColliderComponents::getBody(Entity colliderEntity) const { return mBodiesEntities[mMapEntityToComponentIndex[colliderEntity]]; } -// Return the mass of a collider -inline decimal ColliderComponents::getMass(Entity colliderEntity) const { - - assert(mMapEntityToComponentIndex.containsKey(colliderEntity)); - - return mMasses[mMapEntityToComponentIndex[colliderEntity]]; -} - // Return a pointer to a given collider inline Collider *ColliderComponents::getCollider(Entity colliderEntity) const { diff --git a/src/components/RigidBodyComponents.cpp b/src/components/RigidBodyComponents.cpp index ae15df20..7e12fc5c 100644 --- a/src/components/RigidBodyComponents.cpp +++ b/src/components/RigidBodyComponents.cpp @@ -40,7 +40,7 @@ RigidBodyComponents::RigidBodyComponents(MemoryAllocator& allocator) sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(decimal) + sizeof(decimal) + sizeof(decimal) + sizeof(decimal) + sizeof(Matrix3x3) + - sizeof(Vector3) + sizeof(Vector3) + + sizeof(Matrix3x3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(Vector3) + sizeof(Quaternion) + sizeof(Vector3) + sizeof(Vector3) + sizeof(bool) + sizeof(bool) + sizeof(List)) { @@ -74,9 +74,10 @@ void RigidBodyComponents::allocate(uint32 nbComponentsToAllocate) { Vector3* newExternalTorques = reinterpret_cast(newExternalForces + nbComponentsToAllocate); decimal* newLinearDampings = reinterpret_cast(newExternalTorques + nbComponentsToAllocate); decimal* newAngularDampings = reinterpret_cast(newLinearDampings + nbComponentsToAllocate); - decimal* newInitMasses = reinterpret_cast(newAngularDampings + nbComponentsToAllocate); - decimal* newInverseMasses = reinterpret_cast(newInitMasses + nbComponentsToAllocate); - Matrix3x3* newInertiaTensorLocalInverses = reinterpret_cast(newInverseMasses + nbComponentsToAllocate); + decimal* newMasses = reinterpret_cast(newAngularDampings + nbComponentsToAllocate); + decimal* newInverseMasses = reinterpret_cast(newMasses + nbComponentsToAllocate); + Matrix3x3* newInertiaTensorLocal = reinterpret_cast(newInverseMasses + nbComponentsToAllocate); + Matrix3x3* newInertiaTensorLocalInverses = reinterpret_cast(newInertiaTensorLocal + nbComponentsToAllocate); Vector3* newConstrainedLinearVelocities = reinterpret_cast(newInertiaTensorLocalInverses + nbComponentsToAllocate); Vector3* newConstrainedAngularVelocities = reinterpret_cast(newConstrainedLinearVelocities + nbComponentsToAllocate); Vector3* newSplitLinearVelocities = reinterpret_cast(newConstrainedAngularVelocities + nbComponentsToAllocate); @@ -105,8 +106,9 @@ void RigidBodyComponents::allocate(uint32 nbComponentsToAllocate) { memcpy(newExternalTorques, mExternalTorques, mNbComponents * sizeof(Vector3)); memcpy(newLinearDampings, mLinearDampings, mNbComponents * sizeof(decimal)); memcpy(newAngularDampings, mAngularDampings, mNbComponents * sizeof(decimal)); - memcpy(newInitMasses, mInitMasses, mNbComponents * sizeof(decimal)); + memcpy(newMasses, mMasses, mNbComponents * sizeof(decimal)); memcpy(newInverseMasses, mInverseMasses, mNbComponents * sizeof(decimal)); + memcpy(newInertiaTensorLocal, mLocalInertiaTensors, mNbComponents * sizeof(Matrix3x3)); memcpy(newInertiaTensorLocalInverses, mInverseInertiaTensorsLocal, mNbComponents * sizeof(Matrix3x3)); memcpy(newConstrainedLinearVelocities, mConstrainedLinearVelocities, mNbComponents * sizeof(Vector3)); memcpy(newConstrainedAngularVelocities, mConstrainedAngularVelocities, mNbComponents * sizeof(Vector3)); @@ -138,8 +140,9 @@ void RigidBodyComponents::allocate(uint32 nbComponentsToAllocate) { mExternalTorques = newExternalTorques; mLinearDampings = newLinearDampings; mAngularDampings = newAngularDampings; - mInitMasses = newInitMasses; + mMasses = newMasses; mInverseMasses = newInverseMasses; + mLocalInertiaTensors = newInertiaTensorLocal; mInverseInertiaTensorsLocal = newInertiaTensorLocalInverses; mConstrainedLinearVelocities = newConstrainedLinearVelocities; mConstrainedAngularVelocities = newConstrainedAngularVelocities; @@ -173,8 +176,9 @@ void RigidBodyComponents::addComponent(Entity bodyEntity, bool isSleeping, const new (mExternalTorques + index) Vector3(0, 0, 0); mLinearDampings[index] = decimal(0.0); mAngularDampings[index] = decimal(0.0); - mInitMasses[index] = decimal(1.0); + mMasses[index] = decimal(1.0); mInverseMasses[index] = decimal(1.0); + new (mLocalInertiaTensors + index) Matrix3x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0); new (mInverseInertiaTensorsLocal + index) Matrix3x3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0); new (mConstrainedLinearVelocities + index) Vector3(0, 0, 0); new (mConstrainedAngularVelocities + index) Vector3(0, 0, 0); @@ -216,8 +220,9 @@ void RigidBodyComponents::moveComponentToIndex(uint32 srcIndex, uint32 destIndex new (mExternalTorques + destIndex) Vector3(mExternalTorques[srcIndex]); mLinearDampings[destIndex] = mLinearDampings[srcIndex]; mAngularDampings[destIndex] = mAngularDampings[srcIndex]; - mInitMasses[destIndex] = mInitMasses[srcIndex]; + mMasses[destIndex] = mMasses[srcIndex]; mInverseMasses[destIndex] = mInverseMasses[srcIndex]; + new (mLocalInertiaTensors + destIndex) Matrix3x3(mLocalInertiaTensors[srcIndex]); new (mInverseInertiaTensorsLocal + destIndex) Matrix3x3(mInverseInertiaTensorsLocal[srcIndex]); new (mConstrainedLinearVelocities + destIndex) Vector3(mConstrainedLinearVelocities[srcIndex]); new (mConstrainedAngularVelocities + destIndex) Vector3(mConstrainedAngularVelocities[srcIndex]); @@ -258,8 +263,9 @@ void RigidBodyComponents::swapComponents(uint32 index1, uint32 index2) { Vector3 externalTorque1(mExternalTorques[index1]); decimal linearDamping1 = mLinearDampings[index1]; decimal angularDamping1 = mAngularDampings[index1]; - decimal initMass1 = mInitMasses[index1]; + decimal mass1 = mMasses[index1]; decimal inverseMass1 = mInverseMasses[index1]; + Matrix3x3 inertiaTensorLocal1 = mLocalInertiaTensors[index1]; Matrix3x3 inertiaTensorLocalInverse1 = mInverseInertiaTensorsLocal[index1]; Vector3 constrainedLinearVelocity1(mConstrainedLinearVelocities[index1]); Vector3 constrainedAngularVelocity1(mConstrainedAngularVelocities[index1]); @@ -291,8 +297,9 @@ void RigidBodyComponents::swapComponents(uint32 index1, uint32 index2) { new (mExternalTorques + index2) Vector3(externalTorque1); mLinearDampings[index2] = linearDamping1; mAngularDampings[index2] = angularDamping1; - mInitMasses[index2] = initMass1; + mMasses[index2] = mass1; mInverseMasses[index2] = inverseMass1; + mLocalInertiaTensors[index2] = inertiaTensorLocal1; mInverseInertiaTensorsLocal[index2] = inertiaTensorLocalInverse1; new (mConstrainedLinearVelocities + index2) Vector3(constrainedLinearVelocity1); new (mConstrainedAngularVelocities + index2) Vector3(constrainedAngularVelocity1); @@ -329,6 +336,7 @@ void RigidBodyComponents::destroyComponent(uint32 index) { mAngularVelocities[index].~Vector3(); mExternalForces[index].~Vector3(); mExternalTorques[index].~Vector3(); + mLocalInertiaTensors[index].~Matrix3x3(); mInverseInertiaTensorsLocal[index].~Matrix3x3(); mConstrainedLinearVelocities[index].~Vector3(); mConstrainedAngularVelocities[index].~Vector3(); diff --git a/src/components/RigidBodyComponents.h b/src/components/RigidBodyComponents.h index ef000b3c..12fbb425 100644 --- a/src/components/RigidBodyComponents.h +++ b/src/components/RigidBodyComponents.h @@ -100,13 +100,17 @@ class RigidBodyComponents : public Components { /// Array with the angular damping factor of each component decimal* mAngularDampings; - /// Array with the initial mass of each component - decimal* mInitMasses; + /// Array with the mass of each component + decimal* mMasses; /// Array with the inverse mass of each component decimal* mInverseMasses; + /// Array with the inertia tensor of each component + Matrix3x3* mLocalInertiaTensors; + /// Array with the inverse of the inertia tensor of each component + // TODO : We should use a Vector3 here for the diagonal instead of a Matrix3x3 Matrix3x3* mInverseInertiaTensorsLocal; /// Array with the constrained linear velocity of each component @@ -234,12 +238,24 @@ class RigidBodyComponents : public Components { /// Return the angular damping factor of an entity decimal getAngularDamping(Entity bodyEntity) const; - /// Return the initial mass of an entity - decimal getInitMass(Entity bodyEntity) const; + /// Return the mass of an entity + decimal getMass(Entity bodyEntity) const; + + /// Set the mass of an entity + void setMass(Entity bodyEntity, decimal mass); /// Return the mass inverse of an entity decimal getMassInverse(Entity bodyEntity) const; + /// Set the inverse mass of an entity + void setMassInverse(Entity bodyEntity, decimal inverseMass); + + /// Return the local inertia tensor of an entity + const Matrix3x3& getLocalInertiaTensor(Entity bodyEntity); + + /// Set the local inertia tensor of an entity + void setLocalInertiaTensor(Entity bodyEntity, const Matrix3x3& inertiaTensorLocal); + /// Return the inverse local inertia tensor of an entity const Matrix3x3& getInertiaTensorLocalInverse(Entity bodyEntity); @@ -255,12 +271,6 @@ class RigidBodyComponents : public Components { /// Set the angular damping factor of an entity void setAngularDamping(Entity bodyEntity, decimal angularDamping); - /// Set the initial mass of an entity - void setInitMass(Entity bodyEntity, decimal initMass); - - /// Set the inverse mass of an entity - void setMassInverse(Entity bodyEntity, decimal inverseMass); - /// Set the inverse local inertia tensor of an entity void setInverseInertiaTensorLocal(Entity bodyEntity, const Matrix3x3& inertiaTensorLocalInverse); @@ -484,12 +494,12 @@ inline decimal RigidBodyComponents::getAngularDamping(Entity bodyEntity) const { return mAngularDampings[mMapEntityToComponentIndex[bodyEntity]]; } -// Return the initial mass of an entity -inline decimal RigidBodyComponents::getInitMass(Entity bodyEntity) const { +// Return the mass of an entity +inline decimal RigidBodyComponents::getMass(Entity bodyEntity) const { assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); - return mInitMasses[mMapEntityToComponentIndex[bodyEntity]]; + return mMasses[mMapEntityToComponentIndex[bodyEntity]]; } // Return the inverse mass of an entity @@ -540,12 +550,12 @@ inline void RigidBodyComponents::setAngularDamping(Entity bodyEntity, decimal an mAngularDampings[mMapEntityToComponentIndex[bodyEntity]] = angularDamping; } -// Set the initial mass of an entity -inline void RigidBodyComponents::setInitMass(Entity bodyEntity, decimal initMass) { +// Set the mass of an entity +inline void RigidBodyComponents::setMass(Entity bodyEntity, decimal mass) { assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); - mInitMasses[mMapEntityToComponentIndex[bodyEntity]] = initMass; + mMasses[mMapEntityToComponentIndex[bodyEntity]] = mass; } // Set the mass inverse of an entity @@ -556,6 +566,22 @@ inline void RigidBodyComponents::setMassInverse(Entity bodyEntity, decimal inver mInverseMasses[mMapEntityToComponentIndex[bodyEntity]] = inverseMass; } +// Return the local inertia tensor of an entity +inline const Matrix3x3& RigidBodyComponents::getLocalInertiaTensor(Entity bodyEntity) { + + assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); + + return mLocalInertiaTensors[mMapEntityToComponentIndex[bodyEntity]]; +} + +// Set the local inertia tensor of an entity +inline void RigidBodyComponents::setLocalInertiaTensor(Entity bodyEntity, const Matrix3x3& inertiaTensorLocal) { + + assert(mMapEntityToComponentIndex.containsKey(bodyEntity)); + + mLocalInertiaTensors[mMapEntityToComponentIndex[bodyEntity]] = inertiaTensorLocal; +} + // Set the inverse local inertia tensor of an entity inline void RigidBodyComponents::setInverseInertiaTensorLocal(Entity bodyEntity, const Matrix3x3& inertiaTensorLocalInverse) { diff --git a/src/engine/Material.cpp b/src/engine/Material.cpp index 22a751e5..f121c589 100644 --- a/src/engine/Material.cpp +++ b/src/engine/Material.cpp @@ -29,8 +29,9 @@ using namespace reactphysics3d; // Constructor -Material::Material(decimal frictionCoefficient, decimal rollingResistance, decimal bounciness) - : mFrictionCoefficient(frictionCoefficient), mRollingResistance(rollingResistance), mBounciness(bounciness) { +Material::Material(decimal frictionCoefficient, decimal rollingResistance, decimal bounciness, decimal massDensity) + : mFrictionCoefficient(frictionCoefficient), mRollingResistance(rollingResistance), mBounciness(bounciness), + mMassDensity(massDensity) { } diff --git a/src/engine/Material.h b/src/engine/Material.h index a989f4bc..342beec4 100644 --- a/src/engine/Material.h +++ b/src/engine/Material.h @@ -34,7 +34,7 @@ namespace reactphysics3d { // Class Material /** - * This class contains the material properties of a rigid body that will be use for + * This class contains the material properties of a collider that will be use for * the dynamics simulation like the friction coefficient or the bounciness of the rigid * body. */ @@ -53,10 +53,14 @@ class Material { /// Bounciness during collisions (between 0 and 1) where 1 is for a very bouncy body decimal mBounciness; + /// Density of mass used to compute the mass of the collider + decimal mMassDensity; + // -------------------- Methods -------------------- // /// Constructor - Material(decimal frictionCoefficient, decimal rollingResistance, decimal bounciness); + Material(decimal frictionCoefficient, decimal rollingResistance, decimal bounciness, + decimal massDensity = decimal(1.0)); /// Copy-constructor Material(const Material& material); @@ -86,6 +90,12 @@ class Material { /// Set the rolling resistance factor void setRollingResistance(decimal rollingResistance); + /// Return the mass density of the collider + decimal getMassDensity() const; + + /// Set the mass density of the collider + void setMassDensity(decimal massDensity); + /// Return a string representation for the material std::string to_string() const; @@ -156,6 +166,19 @@ inline void Material::setRollingResistance(decimal rollingResistance) { mRollingResistance = rollingResistance; } +// Return the mass density of the collider +inline decimal Material::getMassDensity() const { + return mMassDensity; +} + +// Set the mass density of the collider +/** + * @param massDensity The mass density of the collider + */ +inline void Material::setMassDensity(decimal massDensity) { + mMassDensity = massDensity; +} + // Return a string representation for the material inline std::string Material::to_string() const { diff --git a/src/engine/PhysicsCommon.cpp b/src/engine/PhysicsCommon.cpp index e2d93fe6..fb2b9d90 100644 --- a/src/engine/PhysicsCommon.cpp +++ b/src/engine/PhysicsCommon.cpp @@ -95,15 +95,26 @@ void PhysicsCommon::release() { destroyTriangleMesh(*it); } +// If logging is enabled +#ifdef IS_LOGGING_ACTIVE + // Destroy the loggers for (auto it = mLoggers.begin(); it != mLoggers.end(); ++it) { destroyLogger(*it); } +#endif + +// If profiling is enabled +#ifdef IS_PROFILING_ACTIVE + // Destroy the profilers for (auto it = mProfilers.begin(); it != mProfilers.end(); ++it) { destroyProfiler(*it); } + +#endif + } // Create and return an instance of PhysicsWorld @@ -168,6 +179,10 @@ SphereShape* PhysicsCommon::createSphereShape(const decimal radius) { // Destroy a sphere collision shape void PhysicsCommon::destroySphereShape(SphereShape* sphereShape) { + // TODO Test if collision shape is still part of some colliders, if so throw error + + assert(sphereShape->mColliders.size() == 0); + // Call the destructor of the shape sphereShape->~SphereShape(); @@ -190,6 +205,10 @@ BoxShape* PhysicsCommon::createBoxShape(const Vector3& extent) { // Destroy a box collision shape void PhysicsCommon::destroyBoxShape(BoxShape* boxShape) { + // TODO Test if collision shape is still part of some colliders, if so throw error + + assert(boxShape->mColliders.size() == 0); + // Call the destructor of the shape boxShape->~BoxShape(); @@ -212,6 +231,10 @@ CapsuleShape* PhysicsCommon::createCapsuleShape(decimal radius, decimal height) // Destroy a capsule collision shape void PhysicsCommon::destroyCapsuleShape(CapsuleShape* capsuleShape) { + // TODO Test if collision shape is still part of some colliders, if so throw error + + assert(capsuleShape->mColliders.size() == 0); + // Call the destructor of the shape capsuleShape->~CapsuleShape(); @@ -234,6 +257,10 @@ ConvexMeshShape* PhysicsCommon::createConvexMeshShape(PolyhedronMesh* polyhedron // Destroy a convex mesh shape void PhysicsCommon::destroyConvexMeshShape(ConvexMeshShape* convexMeshShape) { + // TODO Test if collision shape is still part of some colliders, if so throw error + + assert(convexMeshShape->mColliders.size() == 0); + // Call the destructor of the shape convexMeshShape->~ConvexMeshShape(); @@ -259,6 +286,10 @@ HeightFieldShape* PhysicsCommon::createHeightFieldShape(int nbGridColumns, int n // Destroy a height-field shape void PhysicsCommon::destroyHeightFieldShape(HeightFieldShape* heightFieldShape) { + // TODO Test if collision shape is still part of some colliders, if so throw error + + assert(heightFieldShape->mColliders.size() == 0); + // Call the destructor of the shape heightFieldShape->~HeightFieldShape(); @@ -281,6 +312,10 @@ ConcaveMeshShape* PhysicsCommon::createConcaveMeshShape(TriangleMesh* triangleMe // Destroy a concave mesh shape void PhysicsCommon::destroyConcaveMeshShape(ConcaveMeshShape* concaveMeshShape) { + // TODO Test if collision shape is still part of some colliders, if so throw error + + assert(concaveMeshShape->mColliders.size() == 0); + // Call the destructor of the shape concaveMeshShape->~ConcaveMeshShape(); @@ -334,6 +369,9 @@ void PhysicsCommon::destroyTriangleMesh(TriangleMesh* triangleMesh) { mTriangleMeshes.remove(triangleMesh); } +// If logging is enabled +#ifdef IS_LOGGING_ACTIVE + // Create and return a new logger Logger* PhysicsCommon::createLogger() { @@ -356,6 +394,11 @@ void PhysicsCommon::destroyLogger(Logger* logger) { mLoggers.remove(logger); } +#endif + +// If profiling is enabled +#ifdef IS_PROFILING_ACTIVE + // Create and return a new profiler /// Note that you need to use a different profiler for each PhysicsWorld. Profiler* PhysicsCommon::createProfiler() { @@ -378,3 +421,5 @@ void PhysicsCommon::destroyProfiler(Profiler* profiler) { mProfilers.remove(profiler); } + +#endif diff --git a/src/engine/PhysicsCommon.h b/src/engine/PhysicsCommon.h index 8d1dc977..a983ec86 100644 --- a/src/engine/PhysicsCommon.h +++ b/src/engine/PhysicsCommon.h @@ -167,17 +167,28 @@ class PhysicsCommon { /// Destroy a triangle mesh void destroyTriangleMesh(TriangleMesh* triangleMesh); +// If logging is enabled +#ifdef IS_LOGGING_ACTIVE + /// Create and return a new logger Logger* createLogger(); /// Destroy a logger void destroyLogger(Logger* logger); +#endif + +// If profiling is enabled +#ifdef IS_PROFILING_ACTIVE + /// Create and return a new profiler Profiler* createProfiler(); /// Destroy a profiler void destroyProfiler(Profiler* profiler); + +#endif + }; } diff --git a/src/engine/PhysicsWorld.cpp b/src/engine/PhysicsWorld.cpp index efe1ec73..4a600efd 100644 --- a/src/engine/PhysicsWorld.cpp +++ b/src/engine/PhysicsWorld.cpp @@ -209,7 +209,7 @@ void PhysicsWorld::destroyCollisionBody(CollisionBody* collisionBody) { "Body " + std::to_string(collisionBody->getEntity().id) + ": collision body destroyed"); // Remove all the collision shapes of the body - collisionBody->removeAllCollisionShapes(); + collisionBody->removeAllColliders(); mCollisionBodyComponents.removeComponent(collisionBody->getEntity()); mTransformComponents.removeComponent(collisionBody->getEntity()); @@ -458,7 +458,7 @@ RigidBody* PhysicsWorld::createRigidBody(const Transform& transform) { mRigidBodyComponents.addComponent(entity, false, rigidBodyComponent); // Compute the inverse mass - mRigidBodyComponents.setMassInverse(entity, decimal(1.0) / mRigidBodyComponents.getInitMass(entity)); + mRigidBodyComponents.setMassInverse(entity, decimal(1.0) / mRigidBodyComponents.getMass(entity)); // Add the rigid body to the physics world mRigidBodies.add(rigidBody); @@ -488,7 +488,7 @@ void PhysicsWorld::destroyRigidBody(RigidBody* rigidBody) { "Body " + std::to_string(rigidBody->getEntity().id) + ": rigid body destroyed"); // Remove all the collision shapes of the body - rigidBody->removeAllCollisionShapes(); + rigidBody->removeAllColliders(); // Destroy all the joints in which the rigid body to be destroyed is involved const List& joints = mRigidBodyComponents.getJoints(rigidBody->getEntity()); diff --git a/src/systems/DynamicsSystem.cpp b/src/systems/DynamicsSystem.cpp index 071adb7a..1539add2 100644 --- a/src/systems/DynamicsSystem.cpp +++ b/src/systems/DynamicsSystem.cpp @@ -88,7 +88,7 @@ void DynamicsSystem::updateBodiesState() { mTransformComponents.getTransform(mRigidBodyComponents.mBodiesEntities[i]).setOrientation(constrainedOrientation.getUnit()); } - // Update the transform of the body (using the new center of mass and new orientation) + // Update the position of the body (using the new center of mass and new orientation) for (uint32 i=0; i < mRigidBodyComponents.getNbEnabledComponents(); i++) { Transform& transform = mTransformComponents.getTransform(mRigidBodyComponents.mBodiesEntities[i]); @@ -144,7 +144,7 @@ void DynamicsSystem::integrateRigidBodiesVelocities(decimal timeStep) { // Integrate the gravity force mRigidBodyComponents.mConstrainedLinearVelocities[i] = mRigidBodyComponents.mConstrainedLinearVelocities[i] + timeStep * - mRigidBodyComponents.mInverseMasses[i] * mRigidBodyComponents.mInitMasses[i] * mGravity; + mRigidBodyComponents.mInverseMasses[i] * mRigidBodyComponents.mMasses[i] * mGravity; } } } diff --git a/test/tests/collision/TestCollisionWorld.h b/test/tests/collision/TestCollisionWorld.h index c2ce10d9..3b89d777 100644 --- a/test/tests/collision/TestCollisionWorld.h +++ b/test/tests/collision/TestCollisionWorld.h @@ -461,6 +461,8 @@ class TestCollisionWorld : public Test { /// Destructor virtual ~TestCollisionWorld() { + mPhysicsCommon.destroyPhysicsWorld(mWorld); + mPhysicsCommon.destroyBoxShape(mBoxShape1); mPhysicsCommon.destroyBoxShape(mBoxShape2); @@ -486,7 +488,6 @@ class TestCollisionWorld : public Test { delete mConcaveMeshTriangleVertexArray; - mPhysicsCommon.destroyPhysicsWorld(mWorld); } /// Run the tests diff --git a/test/tests/collision/TestPointInside.h b/test/tests/collision/TestPointInside.h index f5398f02..9606898d 100644 --- a/test/tests/collision/TestPointInside.h +++ b/test/tests/collision/TestPointInside.h @@ -176,11 +176,11 @@ class TestPointInside : public Test { /// Destructor virtual ~TestPointInside() { + mPhysicsCommon.destroyPhysicsWorld(mWorld); mPhysicsCommon.destroyBoxShape(mBoxShape); mPhysicsCommon.destroySphereShape(mSphereShape); mPhysicsCommon.destroyCapsuleShape(mCapsuleShape); mPhysicsCommon.destroyConvexMeshShape(mConvexMeshShape); - mPhysicsCommon.destroyPhysicsWorld(mWorld); mPhysicsCommon.destroyPolyhedronMesh(mConvexMeshPolyhedronMesh); delete[] mConvexMeshPolygonFaces; delete mConvexMeshPolygonVertexArray; diff --git a/test/tests/collision/TestRaycast.h b/test/tests/collision/TestRaycast.h index 20afac7a..4b876df1 100644 --- a/test/tests/collision/TestRaycast.h +++ b/test/tests/collision/TestRaycast.h @@ -304,6 +304,7 @@ class TestRaycast : public Test { /// Destructor virtual ~TestRaycast() { + mPhysicsCommon.destroyPhysicsWorld(mWorld); mPhysicsCommon.destroyBoxShape(mBoxShape); mPhysicsCommon.destroySphereShape(mSphereShape); mPhysicsCommon.destroyCapsuleShape(mCapsuleShape); @@ -311,7 +312,6 @@ class TestRaycast : public Test { mPhysicsCommon.destroyConcaveMeshShape(mConcaveMeshShape); mPhysicsCommon.destroyHeightFieldShape(mHeightFieldShape); - mPhysicsCommon.destroyPhysicsWorld(mWorld); delete mConcaveMeshVertexArray; delete mPolygonVertexArray; diff --git a/testbed/common/Box.cpp b/testbed/common/Box.cpp index a4bbc95f..4e8bd28a 100644 --- a/testbed/common/Box.cpp +++ b/testbed/common/Box.cpp @@ -38,7 +38,7 @@ openglframework::VertexArrayObject Box::mVAO; int Box::totalNbBoxes = 0; // Constructor -Box::Box(const openglframework::Vector3& size, reactphysics3d::PhysicsCommon& physicsCommon, reactphysics3d::PhysicsWorld* world, +Box::Box(bool createRigidBody, const openglframework::Vector3& size, reactphysics3d::PhysicsCommon& physicsCommon, reactphysics3d::PhysicsWorld* world, const std::string& meshFolderPath) : PhysicsObject(physicsCommon, meshFolderPath + "cube.obj") { @@ -57,58 +57,23 @@ Box::Box(const openglframework::Vector3& size, reactphysics3d::PhysicsCommon& ph // ReactPhysics3D will clone this object to create an internal one. Therefore, // it is OK if this object is destroyed right after calling RigidBody::addCollisionShape() mBoxShape = mPhysicsCommon.createBoxShape(rp3d::Vector3(mSize[0], mSize[1], mSize[2])); - //mBoxShape->setLocalScaling(rp3d::Vector3(2, 2, 2)); mPreviousTransform = rp3d::Transform::identity(); - // Create a rigid body in the physics world - mBody = world->createCollisionBody(mPreviousTransform); + if (createRigidBody) { - // Add the collision shape to the body - mCollider = mBody->addCollider(mBoxShape, rp3d::Transform::identity()); - - // If the Vertex Buffer object has not been created yet - if (totalNbBoxes == 0) { - - // Create the Vertex Buffer - createVBOAndVAO(); + // Create a rigid body in the physics world + rp3d::RigidBody* body = world->createRigidBody(mPreviousTransform); + mCollider = body->addCollider(mBoxShape, rp3d::Transform::identity()); + body->updateMassPropertiesFromColliders(); + mBody = body; } + else { - totalNbBoxes++; - - mTransformMatrix = mTransformMatrix * mScalingMatrix; -} - -// Constructor -Box::Box(const openglframework::Vector3& size, float mass, reactphysics3d::PhysicsCommon &physicsCommon, reactphysics3d::PhysicsWorld* world, - const std::string& meshFolderPath) - : PhysicsObject(physicsCommon, meshFolderPath + "cube.obj") { - - // Initialize the size of the box - mSize[0] = size.x * 0.5f; - mSize[1] = size.y * 0.5f; - mSize[2] = size.z * 0.5f; - - // Compute the scaling matrix - mScalingMatrix = openglframework::Matrix4(mSize[0], 0, 0, 0, - 0, mSize[1], 0, 0, - 0, 0, mSize[2], 0, - 0, 0, 0, 1); - - // Create the collision shape for the rigid body (box shape) - // ReactPhysics3D will clone this object to create an internal one. Therefore, - // it is OK if this object is destroyed right after calling RigidBody::addCollisionShape() - mBoxShape = mPhysicsCommon.createBoxShape(rp3d::Vector3(mSize[0], mSize[1], mSize[2])); - - mPreviousTransform = rp3d::Transform::identity(); - - // Create a rigid body in the physics world - rp3d::RigidBody* body = world->createRigidBody(mPreviousTransform); - - // Add the collision shape to the body - mCollider = body->addCollider(mBoxShape, rp3d::Transform::identity(), mass); - - mBody = body; + // Create a body in the physics world + mBody = world->createCollisionBody(mPreviousTransform); + mCollider = mBody->addCollider(mBoxShape, rp3d::Transform::identity()); + } // If the Vertex Buffer object has not been created yet if (totalNbBoxes == 0) { diff --git a/testbed/common/Box.h b/testbed/common/Box.h index 9ff20b1d..9564bf6f 100644 --- a/testbed/common/Box.h +++ b/testbed/common/Box.h @@ -75,12 +75,9 @@ class Box : public PhysicsObject { // -------------------- Methods -------------------- // /// Constructor - Box(const openglframework::Vector3& size, reactphysics3d::PhysicsCommon& physicsCommon, + Box(bool createRigidBody, const openglframework::Vector3& size, reactphysics3d::PhysicsCommon& physicsCommon, reactphysics3d::PhysicsWorld* world, const std::string& meshFolderPath); - /// Constructor - Box(const openglframework::Vector3& size, float mass, reactphysics3d::PhysicsCommon& physicsCommon, reactphysics3d::PhysicsWorld *world, const std::string& meshFolderPath); - /// Destructor virtual ~Box() override; diff --git a/testbed/common/Capsule.cpp b/testbed/common/Capsule.cpp index faca6239..4d7a46a9 100644 --- a/testbed/common/Capsule.cpp +++ b/testbed/common/Capsule.cpp @@ -34,7 +34,7 @@ openglframework::VertexArrayObject Capsule::mVAO; int Capsule::totalNbCapsules = 0; // Constructor -Capsule::Capsule(bool createRigidBody, float radius, float height, float mass, reactphysics3d::PhysicsCommon &physicsCommon, rp3d::PhysicsWorld* physicsWorld, +Capsule::Capsule(bool createRigidBody, float radius, float height, reactphysics3d::PhysicsCommon &physicsCommon, rp3d::PhysicsWorld* physicsWorld, const std::string& meshFolderPath) : PhysicsObject(physicsCommon, meshFolderPath + "capsule.obj"), mRadius(radius), mHeight(height) { @@ -55,18 +55,14 @@ Capsule::Capsule(bool createRigidBody, float radius, float height, float mass, r if (createRigidBody) { rp3d::RigidBody* body = physicsWorld->createRigidBody(mPreviousTransform); - - // Add a collision shape to the body and specify the mass of the shape - mCollider = body->addCollider(mCapsuleShape, rp3d::Transform::identity(), mass); - + mCollider = body->addCollider(mCapsuleShape, rp3d::Transform::identity()); + body->updateMassPropertiesFromColliders(); mBody = body; } else { // Create a rigid body corresponding in the physics world mBody = physicsWorld->createCollisionBody(mPreviousTransform); - - // Add a collision shape to the body and specify the mass of the shape mCollider = mBody->addCollider(mCapsuleShape, rp3d::Transform::identity()); } diff --git a/testbed/common/Capsule.h b/testbed/common/Capsule.h index 92f11066..289b0b9f 100644 --- a/testbed/common/Capsule.h +++ b/testbed/common/Capsule.h @@ -79,7 +79,7 @@ class Capsule : public PhysicsObject { // -------------------- Methods -------------------- // /// Constructor - Capsule(bool createRigidBody, float radius, float height, float mass, reactphysics3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld, + Capsule(bool createRigidBody, float radius, float height, reactphysics3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld, const std::string& meshFolderPath); /// Destructor diff --git a/testbed/common/ConcaveMesh.cpp b/testbed/common/ConcaveMesh.cpp index e3d1e81b..16a2226f 100644 --- a/testbed/common/ConcaveMesh.cpp +++ b/testbed/common/ConcaveMesh.cpp @@ -27,7 +27,7 @@ #include "ConcaveMesh.h" // Constructor -ConcaveMesh::ConcaveMesh(bool createRigidBody, float mass, reactphysics3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld, const std::string& meshPath) +ConcaveMesh::ConcaveMesh(bool createRigidBody, reactphysics3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld, const std::string& meshPath) : PhysicsObject(physicsCommon, meshPath), mVBOVertices(GL_ARRAY_BUFFER), mVBONormals(GL_ARRAY_BUFFER), mVBOTextureCoords(GL_ARRAY_BUFFER), mVBOIndices(GL_ELEMENT_ARRAY_BUFFER) { @@ -60,7 +60,8 @@ ConcaveMesh::ConcaveMesh(bool createRigidBody, float mass, reactphysics3d::Physi // Create the body if (createRigidBody) { rp3d::RigidBody* body = physicsWorld->createRigidBody(mPreviousTransform); - mCollider = body->addCollider(mConcaveShape, rp3d::Transform::identity(), mass); + mCollider = body->addCollider(mConcaveShape, rp3d::Transform::identity()); + body->updateMassPropertiesFromColliders(); mBody = body; } else { diff --git a/testbed/common/ConcaveMesh.h b/testbed/common/ConcaveMesh.h index 8fadf835..9fdc3271 100644 --- a/testbed/common/ConcaveMesh.h +++ b/testbed/common/ConcaveMesh.h @@ -73,7 +73,7 @@ class ConcaveMesh : public PhysicsObject { // -------------------- Methods -------------------- // /// Constructor - ConcaveMesh(bool createRigidBody, float mass, reactphysics3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld, const std::string& meshPath); + ConcaveMesh(bool createRigidBody, reactphysics3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld, const std::string& meshPath); /// Destructor virtual ~ConcaveMesh() override; diff --git a/testbed/common/ConvexMesh.cpp b/testbed/common/ConvexMesh.cpp index 77d4f5c5..38178b23 100644 --- a/testbed/common/ConvexMesh.cpp +++ b/testbed/common/ConvexMesh.cpp @@ -28,7 +28,7 @@ #include // Constructor -ConvexMesh::ConvexMesh(bool createRigidBody, float mass, rp3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld, const std::string& meshPath) +ConvexMesh::ConvexMesh(bool createRigidBody, rp3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld, const std::string& meshPath) : PhysicsObject(physicsCommon, meshPath), mVBOVertices(GL_ARRAY_BUFFER), mVBONormals(GL_ARRAY_BUFFER), mVBOTextureCoords(GL_ARRAY_BUFFER), mVBOIndices(GL_ELEMENT_ARRAY_BUFFER) { @@ -39,7 +39,7 @@ ConvexMesh::ConvexMesh(bool createRigidBody, float mass, rp3d::PhysicsCommon& ph // Polygon faces descriptions for the polyhedron mPolygonFaces = new rp3d::PolygonVertexArray::PolygonFace[getNbFaces(0)]; rp3d::PolygonVertexArray::PolygonFace* face = mPolygonFaces; - for (int f=0; f < getNbFaces(0); f++) { + for (uint f=0; f < getNbFaces(0); f++) { for (int v = 0; v < 3; v++) { @@ -78,7 +78,8 @@ ConvexMesh::ConvexMesh(bool createRigidBody, float mass, rp3d::PhysicsCommon& ph // Create a rigid body corresponding to the sphere in the physics world if (createRigidBody) { rp3d::RigidBody* body = physicsWorld->createRigidBody(mPreviousTransform); - mCollider = body->addCollider(mConvexShape, rp3d::Transform::identity(), mass); + mCollider = body->addCollider(mConvexShape, rp3d::Transform::identity()); + body->updateMassPropertiesFromColliders(); mBody = body; } else { @@ -87,6 +88,7 @@ ConvexMesh::ConvexMesh(bool createRigidBody, float mass, rp3d::PhysicsCommon& ph mCollider = mBody->addCollider(mConvexShape, rp3d::Transform::identity()); } + // Create the VBOs and VAO createVBOAndVAO(); diff --git a/testbed/common/ConvexMesh.h b/testbed/common/ConvexMesh.h index eac1e86c..0060ca5b 100644 --- a/testbed/common/ConvexMesh.h +++ b/testbed/common/ConvexMesh.h @@ -86,7 +86,7 @@ class ConvexMesh : public PhysicsObject { // -------------------- Methods -------------------- // /// Constructor - ConvexMesh(bool createRigidBody, float mass, rp3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld, const std::string& meshPath); + ConvexMesh(bool createRigidBody, rp3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld, const std::string& meshPath); /// Destructor virtual ~ConvexMesh() override; diff --git a/testbed/common/Dumbbell.cpp b/testbed/common/Dumbbell.cpp index 1dda496e..6dcff269 100644 --- a/testbed/common/Dumbbell.cpp +++ b/testbed/common/Dumbbell.cpp @@ -46,7 +46,6 @@ Dumbbell::Dumbbell(bool createRigidBody, rp3d::PhysicsCommon& physicsCommon, rp3 // ReactPhysics3D will clone this object to create an internal one. Therefore, // it is OK if this object is destroyed right after calling RigidBody::addCollisionShape() const rp3d::decimal radiusSphere = rp3d::decimal(1.5); - const rp3d::decimal massSphere = rp3d::decimal(2.0); mSphereShape = mPhysicsCommon.createSphereShape(radiusSphere); // Create a capsule collision shape for the middle of the dumbbell @@ -54,7 +53,6 @@ Dumbbell::Dumbbell(bool createRigidBody, rp3d::PhysicsCommon& physicsCommon, rp3 // it is OK if this object is destroyed right after calling RigidBody::addCollisionShape() const rp3d::decimal radiusCapsule = rp3d::decimal(0.5); const rp3d::decimal heightCapsule = rp3d::decimal(7.0); - const rp3d::decimal massCylinder = rp3d::decimal(1.0); mCapsuleShape = mPhysicsCommon.createCapsuleShape(radiusCapsule, heightCapsule); mPreviousTransform = rp3d::Transform::identity(); @@ -71,26 +69,24 @@ Dumbbell::Dumbbell(bool createRigidBody, rp3d::PhysicsCommon& physicsCommon, rp3 // Create a body corresponding to the dumbbell in the physics world if (createRigidBody) { - rp3d::RigidBody* body; - body = physicsWorld->createRigidBody(mPreviousTransform); - - // Add the three collision shapes to the body and specify the mass and transform of the shapes - mColliderSphere1 = body->addCollider(mSphereShape, transformSphereShape1, massSphere); - mColliderSphere2 = body->addCollider(mSphereShape, transformSphereShape2, massSphere); - mColliderCapsule = body->addCollider(mCapsuleShape, transformCylinderShape, massCylinder); - + rp3d::RigidBody* body = physicsWorld->createRigidBody(mPreviousTransform); + mColliderSphere1 = body->addCollider(mSphereShape, transformSphereShape1); + mColliderSphere2 = body->addCollider(mSphereShape, transformSphereShape2); + mColliderCapsule = body->addCollider(mCapsuleShape, transformCylinderShape); + mColliderSphere1->getMaterial().setMassDensity(2); + mColliderSphere2->getMaterial().setMassDensity(2); + body->updateMassPropertiesFromColliders(); mBody = body; } else { mBody = physicsWorld->createCollisionBody(mPreviousTransform); - - // Add the three collision shapes to the body and specify the mass and transform of the shapes mColliderSphere1 = mBody->addCollider(mSphereShape, transformSphereShape1); mColliderSphere2 = mBody->addCollider(mSphereShape, transformSphereShape2); mColliderCapsule = mBody->addCollider(mCapsuleShape, transformCylinderShape); } + mTransformMatrix = mTransformMatrix * mScalingMatrix; // Create the VBOs and VAO diff --git a/testbed/common/HeightField.cpp b/testbed/common/HeightField.cpp index 0238d6b8..a03e9d2f 100644 --- a/testbed/common/HeightField.cpp +++ b/testbed/common/HeightField.cpp @@ -28,7 +28,7 @@ #include "PerlinNoise.h" // Constructor -HeightField::HeightField(bool createRigidBody, float mass, reactphysics3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld) +HeightField::HeightField(bool createRigidBody, reactphysics3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld) : PhysicsObject(physicsCommon), mVBOVertices(GL_ARRAY_BUFFER), mVBONormals(GL_ARRAY_BUFFER), mVBOTextureCoords(GL_ARRAY_BUFFER), mVBOIndices(GL_ELEMENT_ARRAY_BUFFER) { @@ -54,7 +54,8 @@ HeightField::HeightField(bool createRigidBody, float mass, reactphysics3d::Physi // Create a body if (createRigidBody) { rp3d::RigidBody* body = physicsWorld->createRigidBody(mPreviousTransform); - mCollider = body->addCollider(mHeightFieldShape, rp3d::Transform::identity(), mass); + mCollider = body->addCollider(mHeightFieldShape, rp3d::Transform::identity()); + body->updateMassPropertiesFromColliders(); mBody = body; } else { @@ -62,6 +63,7 @@ HeightField::HeightField(bool createRigidBody, float mass, reactphysics3d::Physi mCollider = mBody->addCollider(mHeightFieldShape, rp3d::Transform::identity()); } + // Create the VBOs and VAO createVBOAndVAO(); diff --git a/testbed/common/HeightField.h b/testbed/common/HeightField.h index fde7c026..c896a593 100644 --- a/testbed/common/HeightField.h +++ b/testbed/common/HeightField.h @@ -86,7 +86,7 @@ class HeightField : public PhysicsObject { // -------------------- Methods -------------------- // /// Constructor - HeightField(bool createRigidBody, float mass, rp3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld); + HeightField(bool createRigidBody, rp3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* physicsWorld); /// Destructor virtual ~HeightField() override; diff --git a/testbed/common/Sphere.cpp b/testbed/common/Sphere.cpp index ba46f143..016511a2 100644 --- a/testbed/common/Sphere.cpp +++ b/testbed/common/Sphere.cpp @@ -34,7 +34,7 @@ openglframework::VertexArrayObject Sphere::mVAO; int Sphere::totalNbSpheres = 0; // Constructor -Sphere::Sphere(float radius, rp3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* world, +Sphere::Sphere(bool createRigidBody, float radius, rp3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWorld* world, const std::string& meshFolderPath) : PhysicsObject(physicsCommon, meshFolderPath + "sphere.obj"), mRadius(radius) { @@ -48,51 +48,23 @@ Sphere::Sphere(float radius, rp3d::PhysicsCommon& physicsCommon, rp3d::PhysicsWo // ReactPhysics3D will clone this object to create an internal one. Therefore, // it is OK if this object is destroyed right after calling RigidBody::addCollisionShape() mCollisionShape = mPhysicsCommon.createSphereShape(mRadius); - //mCollisionShape->setLocalScaling(rp3d::Vector3(2, 2, 2)); mPreviousTransform = rp3d::Transform::identity(); - // Create a rigid body corresponding to the sphere in the physics world - mBody = world->createCollisionBody(mPreviousTransform); + if (createRigidBody) { - // Add a collision shape to the body and specify the mass of the shape - mCollider = mBody->addCollider(mCollisionShape, rp3d::Transform::identity()); - - mTransformMatrix = mTransformMatrix * mScalingMatrix; - - // Create the VBOs and VAO - if (totalNbSpheres == 0) { - createVBOAndVAO(); + // Create a rigid body corresponding to the sphere in the physics world + rp3d::RigidBody* body = world->createRigidBody(mPreviousTransform); + mCollider = body->addCollider(mCollisionShape, rp3d::Transform::identity()); + body->updateMassPropertiesFromColliders(); + mBody = body; } + else { - totalNbSpheres++; -} - -// Constructor -Sphere::Sphere(float radius, float mass, rp3d::PhysicsCommon& physicsCommon,reactphysics3d::PhysicsWorld* world, - const std::string& meshFolderPath) - : PhysicsObject(physicsCommon, meshFolderPath + "sphere.obj"), mRadius(radius) { - - // Compute the scaling matrix - mScalingMatrix = openglframework::Matrix4(mRadius, 0, 0, 0, - 0, mRadius, 0, 0, - 0, 0, mRadius, 0, - 0, 0, 0, 1); - - // Create the collision shape for the rigid body (sphere shape) - // ReactPhysics3D will clone this object to create an internal one. Therefore, - // it is OK if this object is destroyed right after calling RigidBody::addCollisionShape() - mCollisionShape = mPhysicsCommon.createSphereShape(mRadius); - - mPreviousTransform = rp3d::Transform::identity(); - - // Create a rigid body corresponding to the sphere in the physics world - rp3d::RigidBody* body = world->createRigidBody(mPreviousTransform); - - // Add a collision shape to the body and specify the mass of the shape - mCollider = body->addCollider(mCollisionShape, rp3d::Transform::identity(), mass); - - mBody = body; + // Create a body corresponding to the sphere in the physics world + mBody = world->createCollisionBody(mPreviousTransform); + mCollider = mBody->addCollider(mCollisionShape, rp3d::Transform::identity()); + } mTransformMatrix = mTransformMatrix * mScalingMatrix; diff --git a/testbed/common/Sphere.h b/testbed/common/Sphere.h index a31d287c..8cdfdd1e 100644 --- a/testbed/common/Sphere.h +++ b/testbed/common/Sphere.h @@ -76,10 +76,7 @@ class Sphere : public PhysicsObject { // -------------------- Methods -------------------- // /// Constructor - Sphere(float radius, rp3d::PhysicsCommon& physicsCommon, reactphysics3d::PhysicsWorld* world, const std::string& meshFolderPath); - - /// Constructor - Sphere(float radius, float mass, reactphysics3d::PhysicsCommon &physicsCommon, rp3d::PhysicsWorld* physicsWorld, const std::string& meshFolderPath); + Sphere(bool createRigidBody, float radius, rp3d::PhysicsCommon& physicsCommon, reactphysics3d::PhysicsWorld* world, const std::string& meshFolderPath); /// Destructor virtual ~Sphere() override; diff --git a/testbed/scenes/collisiondetection/CollisionDetectionScene.cpp b/testbed/scenes/collisiondetection/CollisionDetectionScene.cpp index 542adfaf..6b1f54e0 100644 --- a/testbed/scenes/collisiondetection/CollisionDetectionScene.cpp +++ b/testbed/scenes/collisiondetection/CollisionDetectionScene.cpp @@ -57,7 +57,7 @@ CollisionDetectionScene::CollisionDetectionScene(const std::string& name, Engine // ---------- Sphere 1 ---------- // // Create a sphere and a corresponding collision body in the physics world - mSphere1 = new Sphere(4, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mSphere1 = new Sphere(false, 4, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mAllShapes.push_back(mSphere1); // Set the color @@ -69,7 +69,7 @@ CollisionDetectionScene::CollisionDetectionScene(const std::string& name, Engine // ---------- Sphere 2 ---------- // // Create a sphere and a corresponding collision body in the physics world - mSphere2 = new Sphere(2, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mSphere2 = new Sphere(false, 2, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mAllShapes.push_back(mSphere2); // Set the color @@ -81,7 +81,7 @@ CollisionDetectionScene::CollisionDetectionScene(const std::string& name, Engine // ---------- Capsule 1 ---------- // // Create a cylinder and a corresponding collision body in the physics world - mCapsule1 = new Capsule(false, CAPSULE_RADIUS, CAPSULE_HEIGHT, 1.0, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mCapsule1 = new Capsule(false, CAPSULE_RADIUS, CAPSULE_HEIGHT, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mAllShapes.push_back(mCapsule1); // Set the color @@ -92,7 +92,7 @@ CollisionDetectionScene::CollisionDetectionScene(const std::string& name, Engine // ---------- Capsule 2 ---------- // // Create a cylinder and a corresponding collision body in the physics world - mCapsule2 = new Capsule(false, CAPSULE_RADIUS, CAPSULE_HEIGHT, 1.0, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mCapsule2 = new Capsule(false, CAPSULE_RADIUS, CAPSULE_HEIGHT, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mAllShapes.push_back(mCapsule2); // Set the color @@ -103,7 +103,7 @@ CollisionDetectionScene::CollisionDetectionScene(const std::string& name, Engine // ---------- Concave Mesh ---------- // // Create a convex mesh and a corresponding collision body in the physics world - mConcaveMesh = new ConcaveMesh(false, 1.0f, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath + "city.obj"); + mConcaveMesh = new ConcaveMesh(false, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath + "city.obj"); mAllShapes.push_back(mConcaveMesh); // Set the color @@ -114,7 +114,7 @@ CollisionDetectionScene::CollisionDetectionScene(const std::string& name, Engine // ---------- Box 1 ---------- // // Create a cylinder and a corresponding collision body in the physics world - mBox1 = new Box(BOX_SIZE, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mBox1 = new Box(false, BOX_SIZE, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mAllShapes.push_back(mBox1); // Set the color @@ -125,7 +125,7 @@ CollisionDetectionScene::CollisionDetectionScene(const std::string& name, Engine // ---------- Box 2 ---------- // // Create a cylinder and a corresponding collision body in the physics world - mBox2 = new Box(openglframework::Vector3(3, 2, 5), mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mBox2 = new Box(false, openglframework::Vector3(3, 2, 5), mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mAllShapes.push_back(mBox2); // Set the color @@ -136,7 +136,7 @@ CollisionDetectionScene::CollisionDetectionScene(const std::string& name, Engine // ---------- Convex Mesh ---------- // // Create a convex mesh and a corresponding collision body in the physics world - mConvexMesh = new ConvexMesh(false, 1.0f, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath + "convexmesh.obj"); + mConvexMesh = new ConvexMesh(false, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath + "convexmesh.obj"); mAllShapes.push_back(mConvexMesh); // Set the color @@ -147,7 +147,7 @@ CollisionDetectionScene::CollisionDetectionScene(const std::string& name, Engine // ---------- Heightfield ---------- // // Create a convex mesh and a corresponding collision body in the physics world - mHeightField = new HeightField(false, 1.0f, mPhysicsCommon, mPhysicsWorld); + mHeightField = new HeightField(false, mPhysicsCommon, mPhysicsWorld); // Set the color mHeightField->setColor(mObjectColorDemo); diff --git a/testbed/scenes/collisionshapes/CollisionShapesScene.cpp b/testbed/scenes/collisionshapes/CollisionShapesScene.cpp index 07fb1b0d..d4aac4b3 100644 --- a/testbed/scenes/collisionshapes/CollisionShapesScene.cpp +++ b/testbed/scenes/collisionshapes/CollisionShapesScene.cpp @@ -79,7 +79,7 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin for (int i=0; isetColor(mObjectColorDemo); @@ -98,7 +98,7 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin for (int i=0; igetCollider()->getMaterial().setRollingResistance(rp3d::decimal(0.08)); @@ -120,7 +120,7 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin for (int i=0; igetCollider()->getMaterial().setRollingResistance(rp3d::decimal(0.08f)); @@ -142,7 +142,7 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin for (int i=0; isetColor(mObjectColorDemo); @@ -159,7 +159,7 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin // ---------- Create the floor --------- - mFloor = new Box(FLOOR_SIZE, FLOOR_MASS, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mFloor = new Box(true, FLOOR_SIZE, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mPhysicsObjects.push_back(mFloor); // Set the box color diff --git a/testbed/scenes/collisionshapes/CollisionShapesScene.h b/testbed/scenes/collisionshapes/CollisionShapesScene.h index d10b3644..2b074a9e 100644 --- a/testbed/scenes/collisionshapes/CollisionShapesScene.h +++ b/testbed/scenes/collisionshapes/CollisionShapesScene.h @@ -57,12 +57,6 @@ const float CAPSULE_RADIUS = 1.0f; const float CAPSULE_HEIGHT = 1.0f; const float DUMBBELL_HEIGHT = 1.0f; const openglframework::Vector3 FLOOR_SIZE(50, 0.5f, 50); // Floor dimensions in meters -const float BOX_MASS = 1.0f; -const float CONE_MASS = 1.0f; -const float CYLINDER_MASS = 1.0f; -const float CAPSULE_MASS = 1.0f; -const float MESH_MASS = 1.0f; -const float FLOOR_MASS = 100.0f; // Floor mass in kilograms // Class CollisionShapesScene class CollisionShapesScene : public SceneDemo { diff --git a/testbed/scenes/concavemesh/ConcaveMeshScene.cpp b/testbed/scenes/concavemesh/ConcaveMeshScene.cpp index fcbd925a..7139de6f 100644 --- a/testbed/scenes/concavemesh/ConcaveMeshScene.cpp +++ b/testbed/scenes/concavemesh/ConcaveMeshScene.cpp @@ -80,7 +80,7 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett for (int i = 0; isetColor(mObjectColorDemo); @@ -99,7 +99,7 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett for (int i = 0; igetCollider()->getMaterial().setRollingResistance(rp3d::decimal(0.08)); @@ -121,7 +121,7 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett for (int i = 0; igetCollider()->getMaterial().setRollingResistance(rp3d::decimal(0.08)); @@ -143,7 +143,7 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett for (int i = 0; isetColor(mObjectColorDemo); @@ -160,11 +160,8 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett // ---------- Create the triangular mesh ---------- // - // Position - rp3d::decimal mass = 1.0; - // Create a convex mesh and a corresponding rigid in the physics world - mConcaveMesh = new ConcaveMesh(true, mass, mPhysicsCommon, mPhysicsWorld, meshFolderPath + "city.obj"); + mConcaveMesh = new ConcaveMesh(true, mPhysicsCommon, mPhysicsWorld, meshFolderPath + "city.obj"); // Set the mesh as beeing static mConcaveMesh->getRigidBody()->setType(rp3d::BodyType::STATIC); diff --git a/testbed/scenes/concavemesh/ConcaveMeshScene.h b/testbed/scenes/concavemesh/ConcaveMeshScene.h index 16dcb753..e3e450a3 100644 --- a/testbed/scenes/concavemesh/ConcaveMeshScene.h +++ b/testbed/scenes/concavemesh/ConcaveMeshScene.h @@ -56,11 +56,6 @@ const float CYLINDER_HEIGHT = 5.0f; const float CAPSULE_RADIUS = 1.0f; const float CAPSULE_HEIGHT = 1.0f; const float DUMBBELL_HEIGHT = 1.0f; -const float BOX_MASS = 1.0f; -const float CONE_MASS = 1.0f; -const float CYLINDER_MASS = 1.0f; -const float CAPSULE_MASS = 1.0f; -const float MESH_MASS = 1.0f; // Class TriangleMeshScene class ConcaveMeshScene : public SceneDemo { diff --git a/testbed/scenes/cubes/CubesScene.cpp b/testbed/scenes/cubes/CubesScene.cpp index c1283c2d..228aff4f 100644 --- a/testbed/scenes/cubes/CubesScene.cpp +++ b/testbed/scenes/cubes/CubesScene.cpp @@ -34,6 +34,8 @@ using namespace cubesscene; CubesScene::CubesScene(const std::string& name, EngineSettings& settings) : SceneDemo(name, settings, true, SCENE_RADIUS) { + iter = 0; + // Compute the radius and the center of the scene openglframework::Vector3 center(0, 5, 0); @@ -55,7 +57,7 @@ CubesScene::CubesScene(const std::string& name, EngineSettings& settings) for (int i=0; isetColor(mObjectColorDemo); @@ -73,7 +75,7 @@ CubesScene::CubesScene(const std::string& name, EngineSettings& settings) // ------------------------- FLOOR ----------------------- // // Create the floor - mFloor = new Box(FLOOR_SIZE, FLOOR_MASS, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mFloor = new Box(true, FLOOR_SIZE, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mFloor->setColor(mFloorColorDemo); mFloor->setSleepingColor(mFloorColorDemo); diff --git a/testbed/scenes/cubes/CubesScene.h b/testbed/scenes/cubes/CubesScene.h index 4e39637a..dcd2a71a 100755 --- a/testbed/scenes/cubes/CubesScene.h +++ b/testbed/scenes/cubes/CubesScene.h @@ -39,8 +39,6 @@ const float SCENE_RADIUS = 30.0f; // Radius of the sce const int NB_CUBES = 30; // Number of boxes in the scene const openglframework::Vector3 BOX_SIZE(2, 2, 2); // Box dimensions in meters const openglframework::Vector3 FLOOR_SIZE(50, 1, 50); // Floor dimensions in meters -const float BOX_MASS = 1.0f; // Box mass in kilograms -const float FLOOR_MASS = 100.0f; // Floor mass in kilograms // Class CubesScene class CubesScene : public SceneDemo { @@ -55,6 +53,8 @@ class CubesScene : public SceneDemo { /// Box for the floor Box* mFloor; + uint iter; + public: // -------------------- Methods -------------------- // diff --git a/testbed/scenes/cubestack/CubeStackScene.cpp b/testbed/scenes/cubestack/CubeStackScene.cpp index 4df85758..c03fa1c7 100644 --- a/testbed/scenes/cubestack/CubeStackScene.cpp +++ b/testbed/scenes/cubestack/CubeStackScene.cpp @@ -57,7 +57,7 @@ CubeStackScene::CubeStackScene(const std::string& name, EngineSettings& settings for (int j=0; jsetColor(mObjectColorDemo); @@ -76,7 +76,7 @@ CubeStackScene::CubeStackScene(const std::string& name, EngineSettings& settings // ------------------------- FLOOR ----------------------- // // Create the floor - mFloor = new Box(FLOOR_SIZE, FLOOR_MASS, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mFloor = new Box(true, FLOOR_SIZE, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mFloor->setColor(mFloorColorDemo); mFloor->setSleepingColor(mFloorColorDemo); diff --git a/testbed/scenes/cubestack/CubeStackScene.h b/testbed/scenes/cubestack/CubeStackScene.h index 3e3abd2e..2bd25a70 100644 --- a/testbed/scenes/cubestack/CubeStackScene.h +++ b/testbed/scenes/cubestack/CubeStackScene.h @@ -39,8 +39,6 @@ const float SCENE_RADIUS = 30.0f; // Radius of the sce const int NB_FLOORS = 15; // Number of boxes in the scene const openglframework::Vector3 BOX_SIZE(2, 2, 2); // Box dimensions in meters const openglframework::Vector3 FLOOR_SIZE(50, 1, 50); // Floor dimensions in meters -const float BOX_MASS = 1.0f; // Box mass in kilograms -const float FLOOR_MASS = 100.0f; // Floor mass in kilograms // Class CubeStackScene class CubeStackScene : public SceneDemo { diff --git a/testbed/scenes/heightfield/HeightFieldScene.cpp b/testbed/scenes/heightfield/HeightFieldScene.cpp index 27d8e97e..593a4675 100644 --- a/testbed/scenes/heightfield/HeightFieldScene.cpp +++ b/testbed/scenes/heightfield/HeightFieldScene.cpp @@ -79,7 +79,7 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett for (int i = 0; isetColor(mObjectColorDemo); @@ -98,7 +98,7 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett for (int i = 0; igetCollider()->getMaterial().setRollingResistance(0.08f); @@ -120,8 +120,7 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett for (int i = 0; igetCollider()->getMaterial().setRollingResistance(0.08f); @@ -142,7 +141,7 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett for (int i = 0; isetColor(mObjectColorDemo); @@ -159,11 +158,8 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett // ---------- Create the height field ---------- // - // Position - rp3d::decimal mass = 1.0; - // Create a convex mesh and a corresponding rigid in the physics world - mHeightField = new HeightField(true, mass, mPhysicsCommon, mPhysicsWorld); + mHeightField = new HeightField(true, mPhysicsCommon, mPhysicsWorld); // Set the mesh as beeing static mHeightField->getRigidBody()->setType(rp3d::BodyType::STATIC); diff --git a/testbed/scenes/heightfield/HeightFieldScene.h b/testbed/scenes/heightfield/HeightFieldScene.h index 5ceee07c..c427f349 100644 --- a/testbed/scenes/heightfield/HeightFieldScene.h +++ b/testbed/scenes/heightfield/HeightFieldScene.h @@ -56,12 +56,6 @@ const float CAPSULE_RADIUS = 1.0f; const float CAPSULE_HEIGHT = 1.0f; const float DUMBBELL_HEIGHT = 1.0f; const openglframework::Vector3 FLOOR_SIZE(50, 0.5f, 50); // Floor dimensions in meters -const float BOX_MASS = 1.0f; -const float CONE_MASS = 1.0f; -const float CYLINDER_MASS = 1.0f; -const float CAPSULE_MASS = 1.0f; -const float MESH_MASS = 1.0f; -const float FLOOR_MASS = 100.0f; // Class HeightFieldScene class HeightFieldScene : public SceneDemo { diff --git a/testbed/scenes/joints/JointsScene.cpp b/testbed/scenes/joints/JointsScene.cpp index c8f03ce7..e6bbd067 100644 --- a/testbed/scenes/joints/JointsScene.cpp +++ b/testbed/scenes/joints/JointsScene.cpp @@ -213,8 +213,7 @@ void JointsScene::createBallAndSocketJoints() { for (int i=0; isetTransform(rp3d::Transform(positionBox, rp3d::Quaternion::identity())); // Set the box color @@ -266,7 +265,7 @@ void JointsScene::createSliderJoint() { // Create a box and a corresponding rigid in the physics world openglframework::Vector3 box1Dimension(2, 4, 2); - mSliderJointBottomBox = new Box(box1Dimension , BOX_MASS, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mSliderJointBottomBox = new Box(true, box1Dimension, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mSliderJointBottomBox->setTransform(rp3d::Transform(positionBox1, rp3d::Quaternion::identity())); // Set the box color @@ -288,7 +287,7 @@ void JointsScene::createSliderJoint() { // Create a box and a corresponding rigid in the physics world openglframework::Vector3 box2Dimension(1.5f, 4, 1.5f); - mSliderJointTopBox = new Box(box2Dimension, BOX_MASS, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mSliderJointTopBox = new Box(true, box2Dimension, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mSliderJointTopBox->setTransform(rp3d::Transform(positionBox2, rp3d::Quaternion::identity())); // Set the box color @@ -330,7 +329,7 @@ void JointsScene::createPropellerHingeJoint() { // Create a box and a corresponding rigid in the physics world openglframework::Vector3 boxDimension(10, 1, 1); - mPropellerBox = new Box(boxDimension, BOX_MASS, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mPropellerBox = new Box(true, boxDimension, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mPropellerBox->setTransform(rp3d::Transform(positionBox1, rp3d::Quaternion::identity())); // Set the box color @@ -371,7 +370,7 @@ void JointsScene::createFixedJoints() { // Create a box and a corresponding rigid in the physics world openglframework::Vector3 boxDimension(1.5, 1.5, 1.5); - mFixedJointBox1 = new Box(boxDimension, BOX_MASS, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mFixedJointBox1 = new Box(true, boxDimension, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mFixedJointBox1->setTransform(rp3d::Transform(positionBox1, rp3d::Quaternion::identity())); // Set the box color @@ -389,7 +388,7 @@ void JointsScene::createFixedJoints() { rp3d::Vector3 positionBox2(-5, 7, 0); // Create a box and a corresponding rigid in the physics world - mFixedJointBox2 = new Box(boxDimension, BOX_MASS, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mFixedJointBox2 = new Box(true, boxDimension, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mFixedJointBox2->setTransform(rp3d::Transform(positionBox2, rp3d::Quaternion::identity())); // Set the box color @@ -430,7 +429,7 @@ void JointsScene::createFloor() { // Create the floor rp3d::Vector3 floorPosition(0, 0, 0); - mFloor = new Box(FLOOR_SIZE, FLOOR_MASS, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mFloor = new Box(true, FLOOR_SIZE, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); // Set the box color mFloor->setColor(mFloorColorDemo); diff --git a/testbed/scenes/joints/JointsScene.h b/testbed/scenes/joints/JointsScene.h index 4a4d1c2d..c1567904 100644 --- a/testbed/scenes/joints/JointsScene.h +++ b/testbed/scenes/joints/JointsScene.h @@ -38,8 +38,6 @@ namespace jointsscene { const float SCENE_RADIUS = 30.0f; const openglframework::Vector3 BOX_SIZE(2, 2, 2); // Box dimensions in meters const openglframework::Vector3 FLOOR_SIZE(50, 0.5f, 50); // Floor dimensions in meters -const float BOX_MASS = 1.0f; // Box mass in kilograms -const float FLOOR_MASS = 100.0f; // Floor mass in kilograms const int NB_BALLSOCKETJOINT_BOXES = 7; // Number of Ball-And-Socket chain boxes const int NB_HINGE_BOXES = 7; // Number of Hinge chain boxes diff --git a/testbed/scenes/pile/PileScene.cpp b/testbed/scenes/pile/PileScene.cpp index 83ad00ce..da5bfd26 100644 --- a/testbed/scenes/pile/PileScene.cpp +++ b/testbed/scenes/pile/PileScene.cpp @@ -77,7 +77,7 @@ PileScene::PileScene(const std::string& name, EngineSettings& settings) for (int i=0; isetColor(mObjectColorDemo); @@ -96,7 +96,7 @@ PileScene::PileScene(const std::string& name, EngineSettings& settings) for (int i=0; igetCollider()->getMaterial().setRollingResistance(rp3d::decimal(0.08)); @@ -118,7 +118,7 @@ PileScene::PileScene(const std::string& name, EngineSettings& settings) for (int i=0; igetCollider()->getMaterial().setRollingResistance(rp3d::decimal(0.08f)); @@ -140,7 +140,7 @@ PileScene::PileScene(const std::string& name, EngineSettings& settings) for (int i=0; isetColor(mObjectColorDemo); @@ -161,7 +161,7 @@ PileScene::PileScene(const std::string& name, EngineSettings& settings) rp3d::decimal mass = 1.0; // Create a convex mesh and a corresponding rigid in the physics world - mSandbox = new ConcaveMesh(true, mass, mPhysicsCommon, mPhysicsWorld, meshFolderPath + "sandbox.obj"); + mSandbox = new ConcaveMesh(true, mPhysicsCommon, mPhysicsWorld, meshFolderPath + "sandbox.obj"); // Set the mesh as beeing static mSandbox->getRigidBody()->setType(rp3d::BodyType::STATIC); diff --git a/testbed/scenes/pile/PileScene.h b/testbed/scenes/pile/PileScene.h index d199f663..e85b747d 100644 --- a/testbed/scenes/pile/PileScene.h +++ b/testbed/scenes/pile/PileScene.h @@ -57,12 +57,6 @@ const float CAPSULE_RADIUS = 1.0f; const float CAPSULE_HEIGHT = 1.0f; const float DUMBBELL_HEIGHT = 1.0f; const openglframework::Vector3 FLOOR_SIZE(50, 0.5f, 50); // Floor dimensions in meters -const float BOX_MASS = 1.0f; -const float CONE_MASS = 1.0f; -const float CYLINDER_MASS = 1.0f; -const float CAPSULE_MASS = 1.0f; -const float MESH_MASS = 1.0f; -const float FLOOR_MASS = 100.0f; // Floor mass in kilograms // Class PileScene class PileScene : public SceneDemo { diff --git a/testbed/scenes/raycast/RaycastScene.cpp b/testbed/scenes/raycast/RaycastScene.cpp index 02d3a114..98c1f62c 100644 --- a/testbed/scenes/raycast/RaycastScene.cpp +++ b/testbed/scenes/raycast/RaycastScene.cpp @@ -63,7 +63,7 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings) // ---------- Box ---------- // // Create a box and a corresponding collision body in the physics world - mBox = new Box(BOX_SIZE, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mBox = new Box(false, BOX_SIZE, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); mBox->getCollisionBody()->setIsActive(false); // Set the box color @@ -74,7 +74,7 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings) // ---------- Sphere ---------- // // Create a sphere and a corresponding collision body in the physics world - mSphere = new Sphere(SPHERE_RADIUS, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mSphere = new Sphere(false, SPHERE_RADIUS, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); // Set the color mSphere->setColor(mObjectColorDemo); @@ -85,7 +85,7 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings) openglframework::Vector3 position6(0, 0, 0); // Create a cylinder and a corresponding collision body in the physics world - mCapsule = new Capsule(false, CAPSULE_RADIUS, CAPSULE_HEIGHT, 1.0, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); + mCapsule = new Capsule(false, CAPSULE_RADIUS, CAPSULE_HEIGHT, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath); // Set the color mCapsule->setColor(mObjectColorDemo); @@ -95,7 +95,7 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings) // ---------- Convex Mesh ---------- // // Create a convex mesh and a corresponding collision body in the physics world - mConvexMesh = new ConvexMesh(false, 1.0f, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath + "convexmesh.obj"); + mConvexMesh = new ConvexMesh(false, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath + "convexmesh.obj"); // Set the color mConvexMesh->setColor(mObjectColorDemo); @@ -105,7 +105,7 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings) // ---------- Concave Mesh ---------- // // Create a convex mesh and a corresponding collision body in the physics world - mConcaveMesh = new ConcaveMesh(false, 1.0f, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath + "city.obj"); + mConcaveMesh = new ConcaveMesh(false, mPhysicsCommon, mPhysicsWorld, mMeshFolderPath + "city.obj"); // Set the color mConcaveMesh->setColor(mObjectColorDemo); @@ -115,7 +115,7 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings) // ---------- Heightfield ---------- // // Create a convex mesh and a corresponding collision body in the physics world - mHeightField = new HeightField(false, 1.0f, mPhysicsCommon, mPhysicsWorld); + mHeightField = new HeightField(false, mPhysicsCommon, mPhysicsWorld); // Set the color mHeightField->setColor(mObjectColorDemo);