From c1d5ba7b320cc846869b60dda4e8ac680d77cd5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Tue, 31 Oct 2023 18:17:43 +0100 Subject: [PATCH] added support for ragdoll scaling --- Editor/HumanoidWindow.cpp | 13 ++++++--- WickedEngine/wiAudio_BindLua.cpp | 1 + WickedEngine/wiMath.h | 4 +++ WickedEngine/wiPhysics_Bullet.cpp | 44 +++++++++++++++++++++++-------- WickedEngine/wiVersion.cpp | 2 +- 5 files changed, 48 insertions(+), 16 deletions(-) diff --git a/Editor/HumanoidWindow.cpp b/Editor/HumanoidWindow.cpp index d726fc690..d17cd0448 100644 --- a/Editor/HumanoidWindow.cpp +++ b/Editor/HumanoidWindow.cpp @@ -56,7 +56,7 @@ void HumanoidWindow::Create(EditorComponent* _editor) lookatMouseCheckBox.SetCheck(true); ragdollCheckBox.Create("Ragdoll: "); - ragdollCheckBox.SetTooltip("Activate dynamic ragdoll physics. Note that kinematic ragdoll physics is always active (ragdoll is animation-driven/kinematic by default)."); + ragdollCheckBox.SetTooltip("Activate dynamic ragdoll physics.\nNote that kinematic ragdoll physics is always active (ragdoll is animation-driven/kinematic by default).\nNote that scaling humanoid will disable ragdoll physics and you need to re-enable if you want to."); ragdollCheckBox.SetSize(XMFLOAT2(hei, hei)); ragdollCheckBox.OnClick([=](wi::gui::EventArgs args) { wi::scene::Scene& scene = editor->GetCurrentScene(); @@ -214,13 +214,18 @@ void HumanoidWindow::Create(EditorComponent* _editor) void HumanoidWindow::SetEntity(Entity entity) { - if (this->entity == entity) - return; - Scene& scene = editor->GetCurrentScene(); const HumanoidComponent* humanoid = scene.humanoids.GetComponent(entity); + if (humanoid != nullptr) + { + ragdollCheckBox.SetCheck(humanoid->IsRagdollPhysicsEnabled()); // this is always force updated + } + + if (this->entity == entity) + return; + if (humanoid != nullptr || IsCollapsed()) { this->entity = entity; diff --git a/WickedEngine/wiAudio_BindLua.cpp b/WickedEngine/wiAudio_BindLua.cpp index da58e53e3..df3b8caa0 100644 --- a/WickedEngine/wiAudio_BindLua.cpp +++ b/WickedEngine/wiAudio_BindLua.cpp @@ -34,6 +34,7 @@ namespace wi::lua { bool result = wi::audio::CreateSound(wi::lua::SGetString(L, 1), &sound->sound); wi::lua::SSetBool(L, result); + return 1; } else { diff --git a/WickedEngine/wiMath.h b/WickedEngine/wiMath.h index 006f7b506..e0d4a7a6d 100644 --- a/WickedEngine/wiMath.h +++ b/WickedEngine/wiMath.h @@ -32,6 +32,10 @@ namespace wi::math static constexpr XMFLOAT4X4 IDENTITY_MATRIX = XMFLOAT4X4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); static constexpr float PI = XM_PI; + inline bool float_equal(float f1, float f2) { + return (std::abs(f1 - f2) <= std::numeric_limits::epsilon() * std::max(std::abs(f1), std::abs(f2))); + } + constexpr float saturate(float x) { return std::min(std::max(x, 0.0f), 1.0f); } inline float Length(const XMFLOAT2& v) diff --git a/WickedEngine/wiPhysics_Bullet.cpp b/WickedEngine/wiPhysics_Bullet.cpp index 1f590c1fb..7bcb31a23 100644 --- a/WickedEngine/wiPhysics_Bullet.cpp +++ b/WickedEngine/wiPhysics_Bullet.cpp @@ -556,8 +556,9 @@ namespace wi::physics btTypedConstraint* m_joints[JOINT_COUNT]; bool state_active = false; Entity saved_parents[BODYPART_COUNT] = {}; + float scale = 1; - Ragdoll(Scene& scene, HumanoidComponent& humanoid, Entity humanoidEntity) + Ragdoll(Scene& scene, HumanoidComponent& humanoid, Entity humanoidEntity, float scale) { physics_scene = scene.physics_scene; btSoftRigidDynamicsWorld& dynamicsWorld = ((PhysicsScene*)physics_scene.get())->dynamicsWorld; @@ -584,6 +585,10 @@ namespace wi::physics facing = -1; } + // Whole ragdoll will take a uniform scaling: + const XMMATRIX scaleMatrix = XMMatrixScaling(scale, scale, scale); + this->scale = scale; + // Calculate the bone lengths and radiuses in armature local space and create rigid bodies for bones: for (int c = 0; c < BODYPART_COUNT; ++c) { @@ -660,8 +665,9 @@ namespace wi::physics // Calculations here will be done in armature local space. // Unfortunately since humanoid can be separate from armature, we use a "find" utility to find bone rest matrix in armature - XMMATRIX restA = scene.FindBoneRestPose(entityA); - XMMATRIX restB = scene.FindBoneRestPose(entityB); + // Note that current scaling of character is applied here separately from rest pose + XMMATRIX restA = scene.FindBoneRestPose(entityA) * scaleMatrix; + XMMATRIX restB = scene.FindBoneRestPose(entityB) * scaleMatrix; XMVECTOR rootA = restA.r[3]; XMVECTOR rootB = restB.r[3]; @@ -670,15 +676,15 @@ namespace wi::physics RigidBody& physicsobject = *rigidbodies[c]; physicsobject.entity = entityA; - float mass = 1; - float capsule_height = 1; - float capsule_radius = 1; + float mass = scale; + float capsule_height = scale; + float capsule_radius = scale; if (c == BODYPART_HEAD) { // Head doesn't necessarily have a child, so make up something reasonable: - capsule_height = 0.05f; - capsule_radius = 0.1f; + capsule_height = 0.05f * scale; + capsule_radius = 0.1f * scale; } else { @@ -690,10 +696,10 @@ namespace wi::physics switch (c) { case BODYPART_PELVIS: - capsule_radius = 0.1f; + capsule_radius = 0.1f * scale; break; case BODYPART_SPINE: - capsule_radius = 0.1f; + capsule_radius = 0.1f * scale; capsule_height -= capsule_radius * 2; break; case BODYPART_LEFT_LOWER_ARM: @@ -1164,13 +1170,29 @@ namespace wi::physics btVector3 wind = btVector3(scene.weather.windDirection.x, scene.weather.windDirection.y, scene.weather.windDirection.z); + // Ragdoll management: for (size_t i = 0; i < scene.humanoids.GetCount(); ++i) { HumanoidComponent& humanoid = scene.humanoids[i]; Entity humanoidEntity = scene.humanoids.GetEntity(i); + float scale = 1; + if (scene.transforms.Contains(humanoidEntity)) + { + scale = scene.transforms.GetComponent(humanoidEntity)->GetScale().x; + } + if (humanoid.ragdoll != nullptr) + { + Ragdoll& ragdoll = *(Ragdoll*)humanoid.ragdoll.get(); + if (!wi::math::float_equal(ragdoll.scale, scale)) + { + humanoid.SetRagdollPhysicsEnabled(false); // while scaling ragdoll, it will be kinematic + ragdoll.Deactivate(scene); // recreate attached skeleton hierarchy structure + humanoid.ragdoll = {}; // delete ragdoll if scale changed, it will be recreated + } + } if (humanoid.ragdoll == nullptr) { - humanoid.ragdoll = std::make_shared(scene, humanoid, humanoidEntity); + humanoid.ragdoll = std::make_shared(scene, humanoid, humanoidEntity, scale); } Ragdoll& ragdoll = *(Ragdoll*)humanoid.ragdoll.get(); if (humanoid.IsRagdollPhysicsEnabled()) diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 9433f85eb..909bf04fb 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 333; + const int revision = 334; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);