From a09fc404699ffb269c5638c1ba6cad3427d25c2d Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Sun, 24 Sep 2023 00:40:37 -0400 Subject: [PATCH] Added ability to lock rotation axis of a rigidbody --- Editor/src/ComponentsPanel/RigidbodyPanel.h | 31 ++++++++++++++ Nuake/src/Core/Physics/DynamicWorld.cpp | 23 +++++++++-- Nuake/src/Core/Physics/Rigibody.h | 11 +++++ Nuake/src/Rendering/Renderer.cpp | 12 +++--- .../src/Scene/Components/RigidbodyComponent.h | 22 ++++++++++ Nuake/src/Scene/Systems/PhysicsSystem.cpp | 40 ++++++++----------- 6 files changed, 106 insertions(+), 33 deletions(-) diff --git a/Editor/src/ComponentsPanel/RigidbodyPanel.h b/Editor/src/ComponentsPanel/RigidbodyPanel.h index 1803fbd4..5e5c2280 100644 --- a/Editor/src/ComponentsPanel/RigidbodyPanel.h +++ b/Editor/src/ComponentsPanel/RigidbodyPanel.h @@ -25,6 +25,37 @@ public: ImGui::TableNextColumn(); ComponentTableReset(component.Mass, 0.0f); } + ImGui::TableNextColumn(); + { + ImGui::Text("Lock X axis"); + ImGui::TableNextColumn(); + + ImGui::Checkbox("##lockx", &component.LockX); + + ImGui::TableNextColumn(); + ComponentTableReset(component.LockX, false); + } + ImGui::TableNextColumn(); + { + ImGui::Text("Lock Y axis"); + ImGui::TableNextColumn(); + + ImGui::Checkbox("##locky", &component.LockY); + + ImGui::TableNextColumn(); + ComponentTableReset(component.LockY, false); + } + ImGui::TableNextColumn(); + { + ImGui::Text("Lock Z axis"); + ImGui::TableNextColumn(); + + ImGui::Checkbox("##lockz", &component.LockZ); + + ImGui::TableNextColumn(); + ComponentTableReset(component.LockZ, false); + } + ImGui::TableNextColumn(); } EndComponentTable(); } diff --git a/Nuake/src/Core/Physics/DynamicWorld.cpp b/Nuake/src/Core/Physics/DynamicWorld.cpp index cae5ccc1..a46deb53 100644 --- a/Nuake/src/Core/Physics/DynamicWorld.cpp +++ b/Nuake/src/Core/Physics/DynamicWorld.cpp @@ -85,7 +85,7 @@ namespace Nuake case Layers::MOVING: return true; // Moving collides with everything case Layers::KINEMATIC: - return inObject2 == Layers::NON_MOVING; // Only collides with static + return inObject2 == Layers::NON_MOVING || inObject2 == Layers::MOVING; // Only collides with non moving default: //JPH_ASSERT(false); return false; @@ -306,7 +306,7 @@ namespace Nuake if (mass > 0.0f && !isMeshShape) { motionType = JPH::EMotionType::Dynamic; - layer = Layers::NON_MOVING; + layer = Layers::MOVING; } const auto& startPos = rb->GetPosition(); @@ -316,6 +316,23 @@ namespace Nuake auto joltShape = GetJoltShape(rb->GetShape()); JPH::BodyCreationSettings bodySettings(joltShape, joltPos, joltRotation, motionType, layer); + bodySettings.mAllowedDOFs = (JPH::EAllowedDOFs::All); + + if (rb->GetLockXAxis()) + { + bodySettings.mAllowedDOFs ^= JPH::EAllowedDOFs::RotationX; + } + + if (rb->GetLockYAxis()) + { + bodySettings.mAllowedDOFs ^= JPH::EAllowedDOFs::RotationY; + } + + if (rb->GetLockZAxis()) + { + bodySettings.mAllowedDOFs ^= JPH::EAllowedDOFs::RotationZ; + } + if (mass > 0.0f) { bodySettings.mOverrideMassProperties = JPH::EOverrideMassProperties::CalculateInertia; @@ -349,8 +366,6 @@ namespace Nuake const auto& joltRotation = JPH::Quat(bodyRotation.x, bodyRotation.y, bodyRotation.z, bodyRotation.w); auto character = new JPH::CharacterVirtual(settings, std::move(joltPosition), std::move(joltRotation), _JoltPhysicsSystem.get()); - //character->AddToPhysicsSystem(JPH::EActivation::Activate); - // To get the jolt character control from a scene entity. _registeredCharacters[cc->Owner.GetHandle()] = character; } diff --git a/Nuake/src/Core/Physics/Rigibody.h b/Nuake/src/Core/Physics/Rigibody.h index 354dd84f..8344a9b0 100644 --- a/Nuake/src/Core/Physics/Rigibody.h +++ b/Nuake/src/Core/Physics/Rigibody.h @@ -20,6 +20,9 @@ namespace Nuake Quat _rotation; Entity _entity; + bool m_LockXAxis = false; + bool m_LockYAxis = false; + bool m_LockZAxis = false; public: float _mass; Matrix4 _transform; @@ -30,6 +33,14 @@ namespace Nuake void UpdateTransform(); + bool GetLockXAxis() const { return m_LockXAxis; } + bool GetLockYAxis() const { return m_LockYAxis; } + bool GetLockZAxis() const { return m_LockZAxis; } + + void setLockXAxis(bool lock) { m_LockXAxis = lock; } + void setLockYAxis(bool lock) { m_LockYAxis = lock; } + void setLockZAxis(bool lock) { m_LockZAxis = lock; } + void SetEntityID(Entity ent); Vector3 GetPosition() const { return _position; } Quat GetRotation() const { return _rotation; } diff --git a/Nuake/src/Rendering/Renderer.cpp b/Nuake/src/Rendering/Renderer.cpp index 7e5d955f..7d79c2d0 100644 --- a/Nuake/src/Rendering/Renderer.cpp +++ b/Nuake/src/Rendering/Renderer.cpp @@ -67,12 +67,12 @@ namespace Nuake std::vector QuadVertices { - { Vector3(-1.0f, 1.0f, 0.0f), Vector2(0.0f, 1.0f), Vector3(0, 0, -1) }, - { Vector3(1.0f, 1.0f, 0.0f), Vector2(1.0f, 1.0f), Vector3(0, 0, -1) }, - { Vector3(-1.0f, -1.0f, 0.0f), Vector2(0, 0), Vector3(0, 0, -1) }, - { Vector3(1.0f, -1.0f, 0.0f), Vector2(1.0f, 0.0f), Vector3(0, 0, -1) }, - { Vector3(-1.0f, -1.0f, 0.0f), Vector2(0.0f, 0.0f), Vector3(0, 0, -1) }, - { Vector3(1.0f, 1.0f, 0.0f), Vector2(1.0f, 1.0f), Vector3(0, 0, -1) } + { Vector3(-1.0f, 1.0f, 0.0f), Vector2(0.0f, 1.0f), Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, 1, 0) }, + { Vector3(1.0f, 1.0f, 0.0f), Vector2(1.0f, 1.0f), Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, 1, 0) }, + { Vector3(-1.0f, -1.0f, 0.0f), Vector2(0, 0), Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, 1, 0) }, + { Vector3(1.0f, -1.0f, 0.0f), Vector2(1.0f, 0.0f), Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, 1, 0) }, + { Vector3(-1.0f, -1.0f, 0.0f), Vector2(0.0f, 0.0f), Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, 1, 0) }, + { Vector3(1.0f, 1.0f, 0.0f), Vector2(1.0f, 1.0f), Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, 1, 0) } }; diff --git a/Nuake/src/Scene/Components/RigidbodyComponent.h b/Nuake/src/Scene/Components/RigidbodyComponent.h index 90c36ef9..837dd84a 100644 --- a/Nuake/src/Scene/Components/RigidbodyComponent.h +++ b/Nuake/src/Scene/Components/RigidbodyComponent.h @@ -13,6 +13,9 @@ namespace Nuake { { public: float Mass; + bool LockX = false; + bool LockY = false; + bool LockZ = false; Ref Rigidbody; Vector3 QueuedForce = Vector3(); @@ -31,12 +34,31 @@ namespace Nuake { { BEGIN_SERIALIZE(); SERIALIZE_VAL_LBL("Mass", Mass); + SERIALIZE_VAL(LockX); + SERIALIZE_VAL(LockY); + SERIALIZE_VAL(LockZ); END_SERIALIZE(); } bool Deserialize(const json& j) { Mass = j["Mass"]; + + if (j.contains("LockX")) + { + LockX = j["LockX"]; + } + + if (j.contains("LockY")) + { + LockY = j["LockY"]; + } + + if (j.contains("LockZ")) + { + LockZ = j["LockZ"]; + } + return true; } }; diff --git a/Nuake/src/Scene/Systems/PhysicsSystem.cpp b/Nuake/src/Scene/Systems/PhysicsSystem.cpp index dba4dcf4..7c0d6434 100644 --- a/Nuake/src/Scene/Systems/PhysicsSystem.cpp +++ b/Nuake/src/Scene/Systems/PhysicsSystem.cpp @@ -218,7 +218,7 @@ namespace Nuake auto [transform, rigidBodyComponent] = view.get(e); Entity ent = Entity({ e, m_Scene }); Ref rigidBody; - + Ref shape; if (rigidBodyComponent.GetRigidBody()) { continue; @@ -226,12 +226,8 @@ namespace Nuake if (ent.HasComponent()) { - float mass = rigidBodyComponent.Mass; - BoxColliderComponent& boxComponent = ent.GetComponent(); - Ref boxShape = CreateRef(boxComponent.Size); - rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalRotation(), transform.GetGlobalTransform(), boxShape, ent); - PhysicsManager::Get().RegisterBody(rigidBody); + shape = CreateRef(boxComponent.Size); } if (ent.HasComponent()) @@ -239,10 +235,7 @@ namespace Nuake auto& capsuleComponent = ent.GetComponent(); float radius = capsuleComponent.Radius; float height = capsuleComponent.Height; - auto capsuleShape = CreateRef(radius, height); - - rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalRotation(), transform.GetGlobalTransform(), capsuleShape, ent); - PhysicsManager::Get().RegisterBody(rigidBody); + shape = CreateRef(radius, height); } if (ent.HasComponent()) @@ -250,21 +243,13 @@ namespace Nuake auto& cylinderComponent = ent.GetComponent(); float radius = cylinderComponent.Radius; float height = cylinderComponent.Height; - auto cylinderShape = CreateRef(radius, height); - - rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalRotation(), transform.GetGlobalTransform(), cylinderShape, ent); - PhysicsManager::Get().RegisterBody(rigidBody); + shape = CreateRef(radius, height); } if (ent.HasComponent()) { - float mass = rigidBodyComponent.Mass; - const auto& component = ent.GetComponent(); - auto shape = CreateRef(component.Radius); - - rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalRotation(), transform.GetGlobalTransform(), shape, ent); - PhysicsManager::Get().RegisterBody(rigidBody); + shape = CreateRef(component.Radius); } if (ent.HasComponent()) @@ -285,13 +270,22 @@ namespace Nuake { Logger::Log("Cannot create mesh collider, invalid submesh ID", "physics", WARNING); } + Ref mesh = submeshes[subMeshId]; - auto shape = CreateRef(mesh); - rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalRotation(), transform.GetGlobalTransform(), shape, ent); - PhysicsManager::Get().RegisterBody(rigidBody); + shape = CreateRef(mesh); } } + if (!shape) + { + continue; + } + + rigidBody = CreateRef(rigidBodyComponent.Mass, transform.GetGlobalPosition(), transform.GetGlobalRotation(), transform.GetGlobalTransform(), shape, ent); + rigidBody->setLockXAxis(rigidBodyComponent.LockX); + rigidBody->setLockYAxis(rigidBodyComponent.LockY); + rigidBody->setLockZAxis(rigidBodyComponent.LockZ); + PhysicsManager::Get().RegisterBody(rigidBody); rigidBodyComponent.Rigidbody = rigidBody; } }