From 7161d9884a2b47ff1ee5bbb36880767c8d33d0ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Thu, 23 Jan 2025 08:15:14 +0100 Subject: [PATCH] physics: parented rigid body is detached only temporarlily during simulation to not modify real hierarchy system --- WickedEngine/wiPhysics_Jolt.cpp | 43 ++++++++++++++++++++++----------- WickedEngine/wiScene.cpp | 9 +++++++ WickedEngine/wiScene.h | 5 +++- WickedEngine/wiVersion.cpp | 2 +- 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/WickedEngine/wiPhysics_Jolt.cpp b/WickedEngine/wiPhysics_Jolt.cpp index 54d8a088de..97645ad1f0 100644 --- a/WickedEngine/wiPhysics_Jolt.cpp +++ b/WickedEngine/wiPhysics_Jolt.cpp @@ -240,6 +240,10 @@ namespace wi::physics BodyID bodyID; Entity entity = INVALID_ENTITY; + // Things for parented objects: + XMFLOAT4X4 parentMatrix = wi::math::IDENTITY_MATRIX; + XMFLOAT4X4 parentMatrixInverse = wi::math::IDENTITY_MATRIX; + // Interpolation state: Vec3 prev_position = Vec3::sZero(); Quat prev_rotation = Quat::sIdentity(); @@ -317,12 +321,21 @@ namespace wi::physics wi::scene::Scene& scene, Entity entity, wi::scene::RigidBodyPhysicsComponent& physicscomponent, - const wi::scene::TransformComponent& transform, + const wi::scene::TransformComponent& _transform, const wi::scene::MeshComponent* mesh ) { ShapeSettings::ShapeResult shape_result; + TransformComponent transform = _transform; + + scene.locker.lock(); + XMMATRIX parentMatrix = scene.ComputeParentMatrixRecursive(entity); + scene.locker.unlock(); + + XMStoreFloat4x4(&transform.world, parentMatrix * transform.GetLocalMatrix()); + transform.ApplyTransform(); + // The default convex radius caused issues when creating small box shape, etc, so I decrease it: const float convexRadius = 0.001f; @@ -422,6 +435,8 @@ namespace wi::physics RigidBody& physicsobject = GetRigidBody(physicscomponent); physicsobject.physics_scene = scene.physics_scene; physicsobject.entity = entity; + XMStoreFloat4x4(&physicsobject.parentMatrix, parentMatrix); + XMStoreFloat4x4(&physicsobject.parentMatrixInverse, XMMatrixInverse(nullptr, parentMatrix)); PhysicsScene& physics_scene = GetPhysicsScene(scene); physicsobject.shape = shape_result.Get(); @@ -471,15 +486,6 @@ namespace wi::physics wi::backlog::post("AddRigidBody failed: body couldn't be created! This could mean that there are too many physics objects.", wi::backlog::LogLevel::Error); return; } - - if (motionType == EMotionType::Dynamic) - { - // We must detach dynamic objects, because their physics object is created in world space - // and attachment would apply double transformation to the transform - scene.locker.lock(); - scene.Component_Detach(entity); - scene.locker.unlock(); - } } } void AddSoftBody( @@ -1223,11 +1229,12 @@ namespace wi::physics if (currentMotionType == EMotionType::Dynamic) { - // We must detach dynamic objects, because their physics object is created in world space - // and attachment would apply double transformation to the transform + // Changed to dynamic, remember attachment matrices at this point: scene.locker.lock(); - scene.Component_Detach(entity); + XMMATRIX parentMatrix = scene.ComputeParentMatrixRecursive(entity); scene.locker.unlock(); + XMStoreFloat4x4(&physicsobject.parentMatrix, parentMatrix); + XMStoreFloat4x4(&physicsobject.parentMatrixInverse, XMMatrixInverse(nullptr, parentMatrix)); } } @@ -1235,6 +1242,12 @@ namespace wi::physics if (transform == nullptr) return; + if (currentMotionType == EMotionType::Dynamic) + { + // Detaching object manually before the physics simulation: + transform->MatrixTransform(physicsobject.parentMatrix); + } + if (physics_scene.activate_all_rigid_bodies) { body_interface.ActivateBody(physicsobject.bodyID); @@ -1596,7 +1609,9 @@ namespace wi::physics transform->translation_local = cast(position); transform->rotation_local = cast(rotation); - transform->SetDirty(); + + // Back to local space of parent: + transform->MatrixTransform(physicsobject.parentMatrixInverse); }); wi::jobsystem::Dispatch(ctx, (uint32_t)scene.softbodies.GetCount(), 1, [&scene, &physics_scene](wi::jobsystem::JobArgs args) { diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 339a131790..f96bccc749 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -7360,6 +7360,15 @@ namespace wi::scene } + XMMATRIX Scene::ComputeEntityMatrixRecursive(wi::ecs::Entity entity) const + { + const TransformComponent* transform = transforms.GetComponent(entity); + if (transform == nullptr) + return XMMatrixIdentity(); + + return transform->GetLocalMatrix() * ComputeParentMatrixRecursive(entity); + } + XMMATRIX Scene::ComputeParentMatrixRecursive(Entity entity) const { XMMATRIX parentMatrix = XMMatrixIdentity(); diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index 9ba39e0e0f..eaf1862fcd 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -528,6 +528,9 @@ namespace wi::scene using CapsuleIntersectionResult = SphereIntersectionResult; CapsuleIntersectionResult Intersects(const wi::primitive::Capsule& capsule, uint32_t filterMask = wi::enums::FILTER_OPAQUE, uint32_t layerMask = ~0, uint32_t lod = 0) const; + // Goes through the hierarchy backwards and computes entity's world space matrix: + XMMATRIX ComputeEntityMatrixRecursive(wi::ecs::Entity entity) const; + // Goes through the hierarchy backwards and computes parent's world space matrix: XMMATRIX ComputeParentMatrixRecursive(wi::ecs::Entity entity) const; @@ -542,7 +545,7 @@ namespace wi::scene // returns entity ID of the new animation or INVALID_ENTITY if retargeting was not successful wi::ecs::Entity RetargetAnimation(wi::ecs::Entity dst, wi::ecs::Entity src, bool bake_data, const Scene* src_scene = nullptr); - // If you don't know which armature the bone is contained int, this function can be used to find the first such armature and return the bone's rest matrix + // If you don't know which armature the bone is contained in, this function can be used to find the first such armature and return the bone's rest matrix // If not found, and entity has a transform, it returns transform matrix // Otherwise, returns identity matrix XMMATRIX GetRestPose(wi::ecs::Entity entity) const; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index ec9681b1eb..e765804f82 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 = 662; + const int revision = 663; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);