From cc9da45dc3f7a97d8c0edd69e74c032026c95a4e Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Fri, 16 Jul 2021 17:01:58 +0200 Subject: [PATCH] Add and rename methods to apply forces to a RigidBody --- CHANGELOG.md | 6 +++ include/reactphysics3d/body/RigidBody.h | 21 +++++--- src/body/RigidBody.cpp | 70 ++++++++++++++++++++++--- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b29b4a16..caa0352f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ do not hesitate to take a look at the user manual. - Method Joint::getReactionTorque() has been added to retrieve the current reaction torque of a joint - Method RigidBody::setLinearLockAxisFactor() to lock the translational movement of a body along the world-space x, y and z axes - Method RigidBody::setAngularLockAxisFactor() to lock the rotational movement of a body around the world-space x, y and z axes + - Method RigidBody::applyLocalForceAtWorldPosition() + - Method RigidBody::applyLocalForceAtLocalPosition() + - Method RigidBody::applyLocalForceToCenterOfMass() - A cone limit can now be set to the ball-and-socket joint (this is useful for ragdolls) - Bridge scene has been added to the testbed application - Ragdoll scene has been added to the testbed application @@ -26,6 +29,9 @@ do not hesitate to take a look at the user manual. - The List class has been renamed to Array - The default number of iterations for the velocity solver is now 6 instead of 10 - The default number of iterations for the position solver is now 3 instead of 5 + - Rename method RigidBody::applyForceAtWorldPosition() into RigidBody::applyWorldForceAtWorldPosition() + - Rename method RigidBody::applyForceAtLocalPosition() into RigidBody::applyWorldForceAtLocalPosition() + - Rename method RigidBody::applyForceToCenterOfMass() into RigidBody::applyWorldForceAtCenterOfMass() - The raycasting broad-phase performance has been improved - The raycasting performance against HeighFieldShape has been improved (better middle-phase algorithm) - Robustness of polyhedron vs polyhedron collision detection has been improved in SAT algorithm (face contacts are favored over edge-edge contacts for better stability) diff --git a/include/reactphysics3d/body/RigidBody.h b/include/reactphysics3d/body/RigidBody.h index 4c2873fc..2172bacf 100644 --- a/include/reactphysics3d/body/RigidBody.h +++ b/include/reactphysics3d/body/RigidBody.h @@ -165,14 +165,23 @@ class RigidBody : public CollisionBody { /// Set the lock rotation factor void setAngularLockAxisFactor(const Vector3& angularLockAxisFactor) const; - /// Apply an external force to the body at its center of mass. - void applyForceToCenterOfMass(const Vector3& force); + /// Apply an external force (in local-space) to the body at its center of mass. + void applyLocalForceAtCenterOfMass(const Vector3& force); - /// Apply an external force to the body at a given point (in local-space coordinates). - void applyForceAtLocalPosition(const Vector3& force, const Vector3& point); + /// Apply an external force (in world-space) to the body at its center of mass. + void applyWorldForceAtCenterOfMass(const Vector3& force); - /// Apply an external force to the body at a given point (in world-space coordinates). - void applyForceAtWorldPosition(const Vector3& force, const Vector3& point); + /// Apply an external force (in local-space) to the body at a given point (in local-space). + void applyLocalForceAtLocalPosition(const Vector3& force, const Vector3& point); + + /// Apply an external force (in world-space) to the body at a given point (in local-space). + void applyWorldForceAtLocalPosition(const Vector3& force, const Vector3& point); + + /// Apply an external force (in local-space) to the body at a given point (in world-space). + void applyLocalForceAtWorldPosition(const Vector3& force, const Vector3& point); + + /// Apply an external force (in world-space) to the body at a given point (in world-space). + void applyWorldForceAtWorldPosition(const Vector3& force, const Vector3& point); /// Apply an external torque to the body. void applyTorque(const Vector3& torque); diff --git a/src/body/RigidBody.cpp b/src/body/RigidBody.cpp index 4b7af32b..6a66b463 100644 --- a/src/body/RigidBody.cpp +++ b/src/body/RigidBody.cpp @@ -127,7 +127,26 @@ decimal RigidBody::getMass() const { return mWorld.mRigidBodyComponents.getMass(mEntity); } -// Apply an external force to the body at a given point (in local-space coordinates). +// Apply an external force (in local-space) to the body at a given point (in local-space). +/// If the point is not at the center of mass of the body, it will also +/// generate some torque and therefore, change the angular velocity of the body. +/// If the body is sleeping, calling this method will wake it up. Note that the +/// force will we added to the sum of the applied forces and that this sum will be +/// reset to zero at the end of each call of the PhyscisWorld::update() method. +/// You can only apply a force to a dynamic body otherwise, this method will do nothing. +/** + * @param force The force (in local-space of the body) to apply on the body (in Newtons) + * @param point The point where the force is applied (in local-space of the body) + */ +void RigidBody::applyLocalForceAtLocalPosition(const Vector3& force, const Vector3& point) { + + // Convert the local-space force to world-space + const Vector3 worldForce = mWorld.mTransformComponents.getTransform(mEntity).getOrientation() * force; + + applyWorldForceAtLocalPosition(worldForce, point); +} + +// Apply an external force (in world-space) to the body at a given point (in local-space). /// If the point is not at the center of mass of the body, it will also /// generate some torque and therefore, change the angular velocity of the body. /// If the body is sleeping, calling this method will wake it up. Note that the @@ -136,9 +155,9 @@ decimal RigidBody::getMass() const { /// You can only apply a force to a dynamic body otherwise, this method will do nothing. /** * @param force The force (in world-space) to apply on the body (in Newtons) - * @param point The point where the force is applied (in local-space coordinates) + * @param point The point where the force is applied (in local-space) */ -void RigidBody::applyForceAtLocalPosition(const Vector3& force, const Vector3& point) { +void RigidBody::applyWorldForceAtLocalPosition(const Vector3& force, const Vector3& point) { // If it is not a dynamic body, we do nothing if (mWorld.mRigidBodyComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; @@ -159,7 +178,26 @@ void RigidBody::applyForceAtLocalPosition(const Vector3& force, const Vector3& p mWorld.mRigidBodyComponents.setExternalTorque(mEntity, externalTorque + (worldPoint - centerOfMassWorld).cross(force)); } -// Apply an external force to the body at a given point (in world-space coordinates). +// Apply an external force (in local-space) to the body at a given point (in world-space). +/// If the point is not at the center of mass of the body, it will also +/// generate some torque and therefore, change the angular velocity of the body. +/// If the body is sleeping, calling this method will wake it up. Note that the +/// force will we added to the sum of the applied forces and that this sum will be +/// reset to zero at the end of each call of the PhyscisWorld::update() method. +/// You can only apply a force to a dynamic body otherwise, this method will do nothing. +/** + * @param force The force (in local-space of the body) to apply on the body (in Newtons) + * @param point The point where the force is applied (in world-space) + */ +void RigidBody::applyLocalForceAtWorldPosition(const Vector3& force, const Vector3& point) { + + // Convert the local-space force to world-space + const Vector3 worldForce = mWorld.mTransformComponents.getTransform(mEntity).getOrientation() * force; + + applyWorldForceAtWorldPosition(worldForce, point); +} + +// Apply an external force (in world-space) to the body at a given point (in world-space). /// If the point is not at the center of mass of the body, it will also /// generate some torque and therefore, change the angular velocity of the body. /// If the body is sleeping, calling this method will wake it up. Note that the @@ -168,9 +206,9 @@ void RigidBody::applyForceAtLocalPosition(const Vector3& force, const Vector3& p /// You can only apply a force to a dynamic body otherwise, this method will do nothing. /** * @param force The force (in world-space) to apply on the body (in Newtons) - * @param point The point where the force is applied (in world-space coordinates) + * @param point The point where the force is applied (in world-space) */ -void RigidBody::applyForceAtWorldPosition(const Vector3& force, const Vector3& point) { +void RigidBody::applyWorldForceAtWorldPosition(const Vector3& force, const Vector3& point) { // If it is not a dynamic body, we do nothing if (mWorld.mRigidBodyComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return; @@ -223,7 +261,23 @@ void RigidBody::setLocalInertiaTensor(const Vector3& inertiaTensorLocal) { "Body " + std::to_string(mEntity.id) + ": Set inertiaTensorLocal=" + inertiaTensorLocal.to_string(), __FILE__, __LINE__); } -// Apply an external force to the body at its center of mass. +// Apply an external force (in local-space) to the body at its center of mass. +/// If the body is sleeping, calling this method will wake it up. Note that the +/// force will we added to the sum of the applied forces and that this sum will be +/// reset to zero at the end of each call of the PhyscisWorld::update() method. +/// You can only apply a force to a dynamic body otherwise, this method will do nothing. +/** + * @param force The external force (in local-space of the body) to apply on the center of mass of the body (in Newtons) + */ +void RigidBody::applyLocalForceAtCenterOfMass(const Vector3& force) { + + // Convert the local-space force to world-space + const Vector3 worldForce = mWorld.mTransformComponents.getTransform(mEntity).getOrientation() * force; + + applyWorldForceAtCenterOfMass(worldForce); +} + +// Apply an external force (in world-space) to the body at its center of mass. /// If the body is sleeping, calling this method will wake it up. Note that the /// force will we added to the sum of the applied forces and that this sum will be /// reset to zero at the end of each call of the PhyscisWorld::update() method. @@ -231,7 +285,7 @@ void RigidBody::setLocalInertiaTensor(const Vector3& inertiaTensorLocal) { /** * @param force The external force (in world-space) to apply on the center of mass of the body (in Newtons) */ -void RigidBody::applyForceToCenterOfMass(const Vector3& force) { +void RigidBody::applyWorldForceAtCenterOfMass(const Vector3& force) { // If it is not a dynamic body, we do nothing if (mWorld.mRigidBodyComponents.getBodyType(mEntity) != BodyType::DYNAMIC) return;