From 27c770b9ccc32e88be73ebf526cc09ec9fe63186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Sun, 6 Apr 2025 08:16:25 +0200 Subject: [PATCH] physics teleport --- .../ScriptingAPI-Documentation.md | 2 + WickedEngine/wiPhysics.h | 11 ++ WickedEngine/wiPhysics_BindLua.cpp | 61 +++++++++ WickedEngine/wiPhysics_BindLua.h | 2 + WickedEngine/wiPhysics_Jolt.cpp | 121 +++++++++++++----- WickedEngine/wiVersion.cpp | 2 +- 6 files changed, 168 insertions(+), 31 deletions(-) diff --git a/Content/Documentation/ScriptingAPI-Documentation.md b/Content/Documentation/ScriptingAPI-Documentation.md index ba9657be9..7202d8da9 100644 --- a/Content/Documentation/ScriptingAPI-Documentation.md +++ b/Content/Documentation/ScriptingAPI-Documentation.md @@ -2091,6 +2091,8 @@ Playstation button codes: - GetVelocity() : Vector-- returns linear velocity of a body - SetGhostMode(RigidBodyPhysicsComponent|HumanoidComponent component, bool value) -- enable/disable ghost mode for rigid body or ragdoll (all collision disabled) - SetRagdollGhostMode(HumanoidComponent humanoid, bool value) -- enable/disable ghost mode for a ragdoll. In ghost mode, the ragdoll will not collide with anything. Enable this if the humanoid sits inside a vehicle for example. +- SetPosition(RigidBodyPhysicsComponent component, Vector position) -- teleport a dynamic body +- SetPositionAndRotation(RigidBodyPhysicsComponent component, Vector position, Vector rotationQuaternion) -- teleport a dynamic body - SetLinearVelocity(RigidBodyPhysicsComponent component, Vector velocity) -- Set the linear velocity manually - SetAngularVelocity(RigidBodyPhysicsComponent component, Vector velocity) -- Set the angular velocity manually - ApplyForce(RigidBodyPhysicsComponent component, Vector force) -- Apply force at body center diff --git a/WickedEngine/wiPhysics.h b/WickedEngine/wiPhysics.h index b2b357c3a..1e1e39ed8 100644 --- a/WickedEngine/wiPhysics.h +++ b/WickedEngine/wiPhysics.h @@ -47,6 +47,17 @@ namespace wi::physics float dt ); + // Teleport a dynamic rigid body: + void SetPosition( + wi::scene::RigidBodyPhysicsComponent& physicscomponent, + const XMFLOAT3& position + ); + void SetPositionAndRotation( + wi::scene::RigidBodyPhysicsComponent& physicscomponent, + const XMFLOAT3& position, + const XMFLOAT4& rotation + ); + // Set linear velocity to rigid body void SetLinearVelocity( wi::scene::RigidBodyPhysicsComponent& physicscomponent, diff --git a/WickedEngine/wiPhysics_BindLua.cpp b/WickedEngine/wiPhysics_BindLua.cpp index c1faab999..988bc3c65 100644 --- a/WickedEngine/wiPhysics_BindLua.cpp +++ b/WickedEngine/wiPhysics_BindLua.cpp @@ -19,6 +19,8 @@ namespace wi::lua lunamethod(Physics_BindLua, GetAccuracy), lunamethod(Physics_BindLua, SetFrameRate), lunamethod(Physics_BindLua, GetFrameRate), + lunamethod(Physics_BindLua, SetPosition), + lunamethod(Physics_BindLua, SetPositionAndRotation), lunamethod(Physics_BindLua, SetLinearVelocity), lunamethod(Physics_BindLua, SetAngularVelocity), lunamethod(Physics_BindLua, ApplyForceAt), @@ -141,6 +143,65 @@ namespace wi::lua return 1; } + int Physics_BindLua::SetPosition(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc > 1) + { + scene::RigidBodyPhysicsComponent_BindLua* component = Luna::lightcheck(L, 1); + if (component == nullptr) + { + wi::lua::SError(L, "SetPosition(RigidBodyPhysicsComponent component, Vector position) first argument is not a RigidBodyPhysicsComponent!"); + return 0; + } + Vector_BindLua* vec = Luna::lightcheck(L, 2); + if (vec == nullptr) + { + wi::lua::SError(L, "SetPosition(RigidBodyPhysicsComponent component, Vector position) second argument is not a Vector!"); + return 0; + } + wi::physics::SetPosition( + *component->component, + *(XMFLOAT3*)vec + ); + } + else + wi::lua::SError(L, "SetPosition(RigidBodyPhysicsComponent component, Vector position) not enough arguments!"); + return 0; + } + int Physics_BindLua::SetPositionAndRotation(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc > 2) + { + scene::RigidBodyPhysicsComponent_BindLua* component = Luna::lightcheck(L, 1); + if (component == nullptr) + { + wi::lua::SError(L, "SetPositionAndRotation(RigidBodyPhysicsComponent component, Vector position, Vector rotationQuaternion) first argument is not a RigidBodyPhysicsComponent!"); + return 0; + } + Vector_BindLua* vec = Luna::lightcheck(L, 2); + if (vec == nullptr) + { + wi::lua::SError(L, "SetPositionAndRotation(RigidBodyPhysicsComponent component, Vector position, Vector rotationQuaternion) second argument is not a Vector!"); + return 0; + } + Vector_BindLua* vec2 = Luna::lightcheck(L, 3); + if (vec2 == nullptr) + { + wi::lua::SError(L, "SetPositionAndRotation(RigidBodyPhysicsComponent component, Vector position, Vector rotationQuaternion) third argument is not a Vector!"); + return 0; + } + wi::physics::SetPositionAndRotation( + *component->component, + vec->GetFloat3(), + vec2->data + ); + } + else + wi::lua::SError(L, "SetPositionAndRotation(RigidBodyPhysicsComponent component, Vector position, Vector rotationQuaternion) not enough arguments!"); + return 0; + } int Physics_BindLua::SetLinearVelocity(lua_State* L) { int argc = wi::lua::SGetArgCount(L); diff --git a/WickedEngine/wiPhysics_BindLua.h b/WickedEngine/wiPhysics_BindLua.h index 4fa98c73f..4422ea7b3 100644 --- a/WickedEngine/wiPhysics_BindLua.h +++ b/WickedEngine/wiPhysics_BindLua.h @@ -28,6 +28,8 @@ namespace wi::lua int SetFrameRate(lua_State* L); int GetFrameRate(lua_State* L); + int SetPosition(lua_State* L); + int SetPositionAndRotation(lua_State* L); int SetLinearVelocity(lua_State* L); int SetAngularVelocity(lua_State* L); int ApplyForce(lua_State* L); diff --git a/WickedEngine/wiPhysics_Jolt.cpp b/WickedEngine/wiPhysics_Jolt.cpp index 3cc814cc6..c4e2ed561 100644 --- a/WickedEngine/wiPhysics_Jolt.cpp +++ b/WickedEngine/wiPhysics_Jolt.cpp @@ -266,9 +266,10 @@ namespace wi::physics float friction = 0; float restitution = 0; EMotionType motiontype = EMotionType::Static; - bool start_deactivated = false; - bool was_underwater = false; - bool was_active_prev_frame = false; + uint8_t start_deactivated : 1; + uint8_t was_underwater : 1; + uint8_t was_active_prev_frame : 1; + uint8_t teleporting : 1; Vec3 initial_position = Vec3::sZero(); Quat initial_rotation = Quat::sIdentity(); @@ -316,6 +317,13 @@ namespace wi::physics shape = nullptr; } + RigidBody() + { + start_deactivated = 0; + was_underwater = 0; + was_active_prev_frame = 0; + teleporting = 0; + } ~RigidBody() { Delete(); @@ -2040,25 +2048,44 @@ namespace wi::physics } } - const Vec3 position = cast(transform->GetPosition()); - const Quat rotation = cast(transform->GetRotation()); - Mat44 m = Mat44::sTranslation(position) * Mat44::sRotation(rotation); - m = m * physicsobject.additionalTransform; - - if (IsSimulationEnabled()) + if (physicsobject.teleporting) { - // Feedback system transform to kinematic and static physics objects: - if (currentMotionType == EMotionType::Kinematic) + physicsobject.teleporting = false; + } + else + { + const Vec3 position = cast(transform->GetPosition()); + const Quat rotation = cast(transform->GetRotation()); + Mat44 m = Mat44::sTranslation(position) * Mat44::sRotation(rotation); + m = m * physicsobject.additionalTransform; + + if (IsSimulationEnabled()) { - body_interface.MoveKinematic( - physicsobject.bodyID, - m.GetTranslation(), - m.GetQuaternion().Normalized(), - physics_scene.GetKinematicDT(scene.dt) - ); + // Feedback system transform to kinematic and static physics objects: + if (currentMotionType == EMotionType::Kinematic) + { + body_interface.MoveKinematic( + physicsobject.bodyID, + m.GetTranslation(), + m.GetQuaternion().Normalized(), + physics_scene.GetKinematicDT(scene.dt) + ); + } + else if (currentMotionType == EMotionType::Static || !is_active) + { + body_interface.SetPositionAndRotation( + physicsobject.bodyID, + m.GetTranslation(), + m.GetQuaternion().Normalized(), + EActivation::DontActivate + ); + } } - else if (currentMotionType == EMotionType::Static || !is_active) + else { + // Simulation is disabled, update physics state immediately: + physicsobject.prev_position = position; + physicsobject.prev_rotation = rotation; body_interface.SetPositionAndRotation( physicsobject.bodyID, m.GetTranslation(), @@ -2067,18 +2094,6 @@ namespace wi::physics ); } } - else - { - // Simulation is disabled, update physics state immediately: - physicsobject.prev_position = position; - physicsobject.prev_rotation = rotation; - body_interface.SetPositionAndRotation( - physicsobject.bodyID, - m.GetTranslation(), - m.GetQuaternion().Normalized(), - EActivation::DontActivate - ); - } }); // System will register softbodies to meshes and update physics engine state: @@ -2617,6 +2632,52 @@ namespace wi::physics wi::profiler::EndRange(range); // Physics } + + void SetPosition( + wi::scene::RigidBodyPhysicsComponent& physicscomponent, + const XMFLOAT3& position + ) + { + if (physicscomponent.physicsobject == nullptr) + return; + RigidBody& physicsobject = GetRigidBody(physicscomponent); + PhysicsScene& physics_scene = *(PhysicsScene*)physicsobject.physics_scene.get(); + BodyInterface& body_interface = physics_scene.physics_system.GetBodyInterfaceNoLock(); + physicsobject.prev_position = cast(position); + Mat44 m = Mat44::sTranslation(physicsobject.prev_position) * Mat44::sRotation(physicsobject.prev_rotation); + m = m * physicsobject.additionalTransform; + body_interface.SetPosition( + physicsobject.bodyID, + m.GetTranslation(), + EActivation::DontActivate + ); + physicsobject.teleporting = true; + } + + void SetPositionAndRotation( + wi::scene::RigidBodyPhysicsComponent& physicscomponent, + const XMFLOAT3& position, + const XMFLOAT4& rotation + ) + { + if (physicscomponent.physicsobject == nullptr) + return; + RigidBody& physicsobject = GetRigidBody(physicscomponent); + PhysicsScene& physics_scene = *(PhysicsScene*)physicsobject.physics_scene.get(); + BodyInterface& body_interface = physics_scene.physics_system.GetBodyInterfaceNoLock(); + physicsobject.prev_position = cast(position); + physicsobject.prev_rotation = cast(rotation).Normalized(); + Mat44 m = Mat44::sTranslation(physicsobject.prev_position) * Mat44::sRotation(physicsobject.prev_rotation); + m = m * physicsobject.additionalTransform; + body_interface.SetPositionAndRotation( + physicsobject.bodyID, + m.GetTranslation(), + m.GetQuaternion().Normalized(), + EActivation::DontActivate + ); + physicsobject.teleporting = true; + } + void SetLinearVelocity( wi::scene::RigidBodyPhysicsComponent& physicscomponent, const XMFLOAT3& velocity diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 9872cabe7..a7a8fa1eb 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 = 730; + const int revision = 731; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);