diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp index 2ff4def5f..3a40dbf46 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.cpp +++ b/Source/Engine/Level/Actors/AnimatedModel.cpp @@ -549,33 +549,7 @@ void AnimatedModel::ApplyRootMotion(const Transform& rootMotionDelta) // Apply movement Actor* target = RootMotionTarget ? RootMotionTarget.Get() : this; - // filter rotation according to constraints if the target is a rigidbody - const auto rigidBody = dynamic_cast(target); - auto rotation = rootMotionDelta.Orientation; - if (rigidBody) - { - if (static_cast(rigidBody->GetConstraints()) & static_cast(RigidbodyConstraints::LockRotation)) - rotation = Quaternion::Identity; - else - { - Float3 euler = rotation.GetEuler(); - const auto constraints = static_cast(rigidBody->GetConstraints()); - if (constraints & static_cast(RigidbodyConstraints::LockRotationX)) - { - euler.X = 0; - } - if (constraints & static_cast(RigidbodyConstraints::LockRotationY)) - { - euler.Y = 0; - } - if (constraints & static_cast(RigidbodyConstraints::LockRotationZ)) - { - euler.Z = 0; - } - rotation = Quaternion::Euler(euler); - } - } - target->AddMovement(translation, rotation); + target->AddMovement(translation, rootMotionDelta.Orientation); } void AnimatedModel::SyncParameters() diff --git a/Source/Engine/Physics/Actors/RigidBody.cpp b/Source/Engine/Physics/Actors/RigidBody.cpp index afbac6611..15ea95075 100644 --- a/Source/Engine/Physics/Actors/RigidBody.cpp +++ b/Source/Engine/Physics/Actors/RigidBody.cpp @@ -300,6 +300,46 @@ void RigidBody::ClosestPoint(const Vector3& position, Vector3& result) const } } +void RigidBody::AddMovement(const Vector3& translation, const Quaternion& rotation) +{ + // filter rotation according to constraints + Quaternion allowedRotation; + if (static_cast(GetConstraints()) & static_cast(RigidbodyConstraints::LockRotation)) + allowedRotation = Quaternion::Identity; + else + { + Float3 euler = rotation.GetEuler(); + const auto constraints = static_cast(GetConstraints()); + if (constraints & static_cast(RigidbodyConstraints::LockRotationX)) + euler.X = 0; + if (constraints & static_cast(RigidbodyConstraints::LockRotationY)) + euler.Y = 0; + if (constraints & static_cast(RigidbodyConstraints::LockRotationZ)) + euler.Z = 0; + allowedRotation = Quaternion::Euler(euler); + } + + // filter translation according to the constraints + auto allowedTranslation = translation; + if (static_cast(GetConstraints()) & static_cast(RigidbodyConstraints::LockPosition)) + allowedTranslation = Vector3::Zero; + else + { + const auto constraints = static_cast(GetConstraints()); + if (constraints & static_cast(RigidbodyConstraints::LockPositionX)) + allowedTranslation.X = 0; + if (constraints & static_cast(RigidbodyConstraints::LockPositionY)) + allowedTranslation.Y = 0; + if (constraints & static_cast(RigidbodyConstraints::LockPositionZ)) + allowedTranslation.Z = 0; + } + Transform t; + t.Translation = _transform.Translation + allowedTranslation; + t.Orientation = _transform.Orientation * allowedRotation; + t.Scale = _transform.Scale; + SetTransform(t); +} + void RigidBody::OnCollisionEnter(const Collision& c) { CollisionEnter(c); diff --git a/Source/Engine/Physics/Actors/RigidBody.h b/Source/Engine/Physics/Actors/RigidBody.h index 2ef50ca7a..b8c7d0208 100644 --- a/Source/Engine/Physics/Actors/RigidBody.h +++ b/Source/Engine/Physics/Actors/RigidBody.h @@ -430,6 +430,12 @@ public: /// The result point on the rigidbody shape that is closest to the specified location. API_FUNCTION() void ClosestPoint(const Vector3& position, API_PARAM(Out) Vector3& result) const; + /// + /// Moves and rotates the rigidbody in world space within the limits of defined constraints. + /// + /// The translation vector. + /// The rotation quaternion. + API_FUNCTION() void AddMovement(const Vector3& translation, const Quaternion& rotation) override; public: /// /// Occurs when a collision start gets registered for this rigidbody (it collides with something).