From 021801f02ec7c2118567c1d966e9b72f1445cc15 Mon Sep 17 00:00:00 2001 From: SirLynix Date: Tue, 21 Mar 2023 13:31:52 +0100 Subject: [PATCH] Continue Jolt integration --- examples/PhysicsDemo/main.cpp | 2 +- examples/PhysicsPlayground/main.cpp | 12 +- examples/Showcase/main.cpp | 65 ++++++-- .../BulletPhysics3D/BulletConstraint3D.hpp | 2 +- .../BulletPhysics3D/BulletPhysics3D.hpp | 2 +- .../Components/BulletRigidBody3DComponent.hpp | 2 +- .../Systems/BulletPhysics3DSystem.hpp | 5 +- include/Nazara/JoltPhysics3D.hpp | 1 + .../Components/JoltRigidBody3DComponent.hpp | 2 +- include/Nazara/JoltPhysics3D/Enums.hpp | 3 + .../Nazara/JoltPhysics3D/JoltCharacter.hpp | 59 +++++++ .../Nazara/JoltPhysics3D/JoltCharacter.inl | 12 ++ .../Nazara/JoltPhysics3D/JoltCollider3D.hpp | 54 +++--- .../Nazara/JoltPhysics3D/JoltCollider3D.inl | 30 ++++ .../Nazara/JoltPhysics3D/JoltConstraint3D.hpp | 2 +- .../Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp | 24 ++- .../Nazara/JoltPhysics3D/JoltPhysWorld3D.inl | 31 ++++ .../Nazara/JoltPhysics3D/JoltPhysics3D.hpp | 2 +- .../Nazara/JoltPhysics3D/JoltRigidBody3D.hpp | 16 +- .../Nazara/JoltPhysics3D/JoltRigidBody3D.inl | 5 + .../Systems/JoltPhysics3DSystem.hpp | 4 +- .../BulletPhysics3D/BulletCollider3D.cpp | 2 +- src/Nazara/BulletPhysics3D/BulletHelper.hpp | 2 +- .../BulletPhysics3D/BulletPhysWorld3D.cpp | 4 +- .../BulletPhysics3D/BulletRigidBody3D.cpp | 2 +- .../Systems/BulletPhysics3DSystem.cpp | 11 +- src/Nazara/JoltPhysics3D/JoltCharacter.cpp | 78 +++++++++ src/Nazara/JoltPhysics3D/JoltCollider3D.cpp | 65 ++++---- src/Nazara/JoltPhysics3D/JoltHelper.hpp | 2 +- src/Nazara/JoltPhysics3D/JoltPhysWorld3D.cpp | 86 +++++++--- src/Nazara/JoltPhysics3D/JoltPhysics3D.cpp | 10 +- src/Nazara/JoltPhysics3D/JoltRigidBody3D.cpp | 156 +++++++++--------- .../Systems/JoltPhysics3DSystem.cpp | 33 +++- src/Nazara/Utility/Node.cpp | 38 +++++ xmake.lua | 2 +- 35 files changed, 612 insertions(+), 214 deletions(-) create mode 100644 include/Nazara/JoltPhysics3D/JoltCharacter.hpp create mode 100644 include/Nazara/JoltPhysics3D/JoltCharacter.inl create mode 100644 include/Nazara/JoltPhysics3D/JoltPhysWorld3D.inl create mode 100644 src/Nazara/JoltPhysics3D/JoltCharacter.cpp diff --git a/examples/PhysicsDemo/main.cpp b/examples/PhysicsDemo/main.cpp index a88a12b31..4450cca87 100644 --- a/examples/PhysicsDemo/main.cpp +++ b/examples/PhysicsDemo/main.cpp @@ -102,7 +102,7 @@ int main() cameraComponent.UpdateClearColor(Nz::Color(0.5f, 0.5f, 0.5f)); } - auto shipCollider = std::make_shared(vertices, vertexMapper.GetVertexCount()); + auto shipCollider = std::make_shared(vertices, vertexMapper.GetVertexCount()); std::shared_ptr colliderMat = Nz::Graphics::Instance()->GetDefaultMaterials().basicMaterial->Instantiate(); colliderMat->SetValueProperty("BaseColor", Nz::Color::Green()); diff --git a/examples/PhysicsPlayground/main.cpp b/examples/PhysicsPlayground/main.cpp index 3afaf6209..d67879509 100644 --- a/examples/PhysicsPlayground/main.cpp +++ b/examples/PhysicsPlayground/main.cpp @@ -1,6 +1,6 @@ // Sources pour https://github.com/NazaraEngine/NazaraEngine/wiki/(FR)-Tutoriel:-%5B01%5D-Hello-World -#define USE_JOLT 0 +#define USE_JOLT 1 #include #include @@ -22,7 +22,7 @@ int main() try { // Mise en place de l'application, de la fenêtre et du monde Nz::Renderer::Config renderConfig; - //renderConfig.preferredAPI = Nz::RenderAPI::OpenGL; + renderConfig.validationLevel = Nz::RenderAPIValidationLevel::None; #if USE_JOLT Nz::Application app(renderConfig); @@ -150,7 +150,7 @@ int main() std::uniform_real_distribution colorDis(0.f, 360.f); std::uniform_real_distribution radiusDis(0.1f, 0.5f); - constexpr std::size_t SphereCount = 2000; + constexpr std::size_t SphereCount = 1000; for (std::size_t i = 0; i < SphereCount; ++i) { float radius = radiusDis(rd); @@ -364,15 +364,15 @@ int main() { auto& cameraNode = cameraEntity.get(); - //physSystem.GetPhysWorld().SetGravity(cameraNode.GetBackward() * 9.81f); + physSystem.GetPhysWorld().SetGravity(cameraNode.GetBackward() * 9.81f); } }); Nz::DegreeAnglef rotation = 0.f; app.AddUpdater([&](Nz::Time elapsedTime) { - rotation += elapsedTime.AsSeconds() * 30.f; - physSystem.GetPhysWorld().SetGravity(Nz::Quaternionf(Nz::EulerAnglesf(0.f, rotation, 0.f)) * Nz::Vector3f::Forward()); + rotation += elapsedTime.AsSeconds() * 45.f; + //physSystem.GetPhysWorld().SetGravity(Nz::Quaternionf(Nz::EulerAnglesf(0.f, rotation, 0.f)) * Nz::Vector3f::Forward() * 10.f); }); Nz::MillisecondClock fpsClock; diff --git a/examples/Showcase/main.cpp b/examples/Showcase/main.cpp index 384a64932..aae753481 100644 --- a/examples/Showcase/main.cpp +++ b/examples/Showcase/main.cpp @@ -52,6 +52,8 @@ int main() physSytem.GetPhysWorld().SetGravity({ 0.f, -9.81f, 0.f }); + std::optional character; + entt::handle playerEntity = world.CreateEntity(); entt::handle playerRotation = world.CreateEntity(); entt::handle playerCamera = world.CreateEntity(); @@ -61,8 +63,18 @@ int main() auto playerCollider = std::make_shared(Nz::Vector3f(0.2f, 1.8f, 0.2f)); - auto& playerBody = playerEntity.emplace(physSytem.CreateRigidBody(playerCollider)); - playerBody.SetMass(42.f); + //auto& playerBody = playerEntity.emplace(physSytem.CreateRigidBody(playerCollider)); + //playerBody.SetMass(42.f); + + character.emplace(physSytem.GetPhysWorld(), playerCollider, Nz::Vector3f::Up() * 5.f); + + app.AddUpdater([&](Nz::Time /*elapsedTime*/) + { + auto [position, rotation] = character->GetPositionAndRotation(); + + auto& playerNode = playerEntity.get(); + playerNode.SetTransform(position, rotation, Nz::Vector3f::Unit()); + }); std::shared_ptr colliderMesh = Nz::Mesh::Build(playerCollider->GenerateDebugMesh()); std::shared_ptr colliderGraphicalMesh = Nz::GraphicalMesh::BuildFromMesh(*colliderMesh); @@ -215,7 +227,7 @@ int main() auto& bobGfx = bobEntity.emplace(); bobGfx.AttachRenderable(bobModel); - auto& sharedSkeleton = bobEntity.emplace(skeleton); + bobEntity.emplace(skeleton); entt::handle sphereEntity = world.CreateEntity(); { @@ -333,7 +345,10 @@ int main() floorEntity.emplace(); - auto& planeBody = floorEntity.emplace(physSytem.CreateRigidBody(std::make_shared(Nz::Vector3f(planeSize.x, 0.5f, planeSize.y)))); + auto floorCollider = std::make_shared(Nz::Vector3f(planeSize.x, 1.f, planeSize.y)); + auto translatedFloorCollider = std::make_shared(std::move(floorCollider), Nz::Vector3f::Down() * 0.5f); + + auto& planeBody = floorEntity.emplace(physSytem.CreateRigidBody(translatedFloorCollider)); planeBody.SetMass(0.f); std::shared_ptr boxMeshGfx = Nz::GraphicalMesh::Build(Nz::Primitive::Box(Nz::Vector3f(0.5f, 0.5f, 0.5f)), meshPrimitiveParams); @@ -344,6 +359,27 @@ int main() entt::handle boxEntity = world.CreateEntity(); boxEntity.emplace(); boxEntity.emplace().AttachRenderable(boxModel); + + + std::shared_ptr colliderModel; + { + std::shared_ptr colliderMat = Nz::Graphics::Instance()->GetDefaultMaterials().basicMaterial->Instantiate(); + colliderMat->SetValueProperty("BaseColor", Nz::Color::Green()); + colliderMat->UpdatePassesStates([](Nz::RenderStates& states) + { + states.primitiveMode = Nz::PrimitiveMode::LineList; + return true; + }); + + std::shared_ptr colliderMesh = Nz::Mesh::Build(translatedFloorCollider->GenerateDebugMesh()); + std::shared_ptr colliderGraphicalMesh = Nz::GraphicalMesh::BuildFromMesh(*colliderMesh); + + colliderModel = std::make_shared(colliderGraphicalMesh); + for (std::size_t i = 0; i < colliderModel->GetSubMeshCount(); ++i) + colliderModel->SetMaterial(i, colliderMat); + + planeGfx.AttachRenderable(std::move(colliderModel)); + } } Nz::MillisecondClock fpsClock, updateClock; @@ -385,25 +421,32 @@ int main() { float updateTime = deltaTime->AsSeconds(); - auto& playerBody = playerEntity.get(); + //auto& playerBody = playerEntity.get(); //playerBody.SetAngularDamping(std::numeric_limits::max()); - float mass = playerBody.GetMass(); + Nz::Vector3f velocity = character->GetLinearVelocity(); + velocity.x = 0.f; + velocity.z = 0.f; if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::RShift)) - playerBody.AddForce(Nz::Vector3f(0.f, mass * 50.f, 0.f)); + { + if (character->IsOnGround()) + velocity += Nz::Vector3f::Up() * 2.f; + } if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Up)) - playerBody.AddForce(Nz::Vector3f::Forward() * 25.f * mass, Nz::CoordSys::Local); + velocity += Nz::Vector3f::Forward(); if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Down)) - playerBody.AddForce(Nz::Vector3f::Backward() * 25.f * mass, Nz::CoordSys::Local); + velocity += Nz::Vector3f::Backward(); if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Left)) - playerBody.AddForce(Nz::Vector3f::Left() * 25.f * mass, Nz::CoordSys::Local); + velocity += Nz::Vector3f::Left(); if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Right)) - playerBody.AddForce(Nz::Vector3f::Right() * 25.f * mass, Nz::CoordSys::Local); + velocity += Nz::Vector3f::Right(); + + character->SetLinearVelocity(velocity); float cameraSpeed = 2.f; diff --git a/include/Nazara/BulletPhysics3D/BulletConstraint3D.hpp b/include/Nazara/BulletPhysics3D/BulletConstraint3D.hpp index d5afbe889..40e61a8c7 100644 --- a/include/Nazara/BulletPhysics3D/BulletConstraint3D.hpp +++ b/include/Nazara/BulletPhysics3D/BulletConstraint3D.hpp @@ -7,7 +7,7 @@ #ifndef NAZARA_BULLETPHYSICS3D_BULLETCONSTRAINT3D_HPP #define NAZARA_BULLETPHYSICS3D_BULLETCONSTRAINT3D_HPP -#include +#include #include #include #include diff --git a/include/Nazara/BulletPhysics3D/BulletPhysics3D.hpp b/include/Nazara/BulletPhysics3D/BulletPhysics3D.hpp index 14d96eb97..fcf3924f5 100644 --- a/include/Nazara/BulletPhysics3D/BulletPhysics3D.hpp +++ b/include/Nazara/BulletPhysics3D/BulletPhysics3D.hpp @@ -7,7 +7,7 @@ #ifndef NAZARA_BULLETPHYSICS3D_HPP #define NAZARA_BULLETPHYSICS3D_HPP -#include +#include #include #include diff --git a/include/Nazara/BulletPhysics3D/Components/BulletRigidBody3DComponent.hpp b/include/Nazara/BulletPhysics3D/Components/BulletRigidBody3DComponent.hpp index 0e901a44b..cfa241b90 100644 --- a/include/Nazara/BulletPhysics3D/Components/BulletRigidBody3DComponent.hpp +++ b/include/Nazara/BulletPhysics3D/Components/BulletRigidBody3DComponent.hpp @@ -7,7 +7,7 @@ #ifndef NAZARA_BULLETPHYSICS3D_COMPONENTS_BULLETRIGIDBODY3DCOMPONENT_HPP #define NAZARA_BULLETPHYSICS3D_COMPONENTS_BULLETRIGIDBODY3DCOMPONENT_HPP -#include +#include #include namespace Nz diff --git a/include/Nazara/BulletPhysics3D/Systems/BulletPhysics3DSystem.hpp b/include/Nazara/BulletPhysics3D/Systems/BulletPhysics3DSystem.hpp index 93b1dd113..0b58a4caf 100644 --- a/include/Nazara/BulletPhysics3D/Systems/BulletPhysics3DSystem.hpp +++ b/include/Nazara/BulletPhysics3D/Systems/BulletPhysics3DSystem.hpp @@ -7,12 +7,12 @@ #ifndef NAZARA_BULLETPHYSICS3D_SYSTEMS_BULLETPHYSICS3DSYSTEM_HPP #define NAZARA_BULLETPHYSICS3D_SYSTEMS_BULLETPHYSICS3DSYSTEM_HPP -#include +#include #include #include #include #include -#include +#include #include #include @@ -54,6 +54,7 @@ namespace Nz void OnConstruct(entt::registry& registry, entt::entity entity); void OnDestruct(entt::registry& registry, entt::entity entity); + std::size_t m_activeObjectCount; std::size_t m_stepCount; std::vector m_physicsEntities; entt::registry& m_registry; diff --git a/include/Nazara/JoltPhysics3D.hpp b/include/Nazara/JoltPhysics3D.hpp index 95a9585c5..8c27707b6 100644 --- a/include/Nazara/JoltPhysics3D.hpp +++ b/include/Nazara/JoltPhysics3D.hpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include diff --git a/include/Nazara/JoltPhysics3D/Components/JoltRigidBody3DComponent.hpp b/include/Nazara/JoltPhysics3D/Components/JoltRigidBody3DComponent.hpp index a1014952f..a32217d8f 100644 --- a/include/Nazara/JoltPhysics3D/Components/JoltRigidBody3DComponent.hpp +++ b/include/Nazara/JoltPhysics3D/Components/JoltRigidBody3DComponent.hpp @@ -7,7 +7,7 @@ #ifndef NAZARA_JOLTPHYSICS3D_COMPONENTS_JOLTRIGIDBODY3DCOMPONENT_HPP #define NAZARA_JOLTPHYSICS3D_COMPONENTS_JOLTRIGIDBODY3DCOMPONENT_HPP -#include +#include #include namespace Nz diff --git a/include/Nazara/JoltPhysics3D/Enums.hpp b/include/Nazara/JoltPhysics3D/Enums.hpp index 3fb74b4fe..0f57e9032 100644 --- a/include/Nazara/JoltPhysics3D/Enums.hpp +++ b/include/Nazara/JoltPhysics3D/Enums.hpp @@ -15,6 +15,9 @@ namespace Nz Compound, Sphere, + TranslatedRotatedDecoration, + ScaleDecoration, + Max = Sphere }; } diff --git a/include/Nazara/JoltPhysics3D/JoltCharacter.hpp b/include/Nazara/JoltPhysics3D/JoltCharacter.hpp new file mode 100644 index 000000000..813fd470f --- /dev/null +++ b/include/Nazara/JoltPhysics3D/JoltCharacter.hpp @@ -0,0 +1,59 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - JoltPhysics3D module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_JOLTPHYSICS3D_JOLTCHARACTER_HPP +#define NAZARA_JOLTPHYSICS3D_JOLTCHARACTER_HPP + +#include +#include +#include +#include +#include + +namespace JPH +{ + class Character; +} + +namespace Nz +{ + class JoltCollider3D; + class JoltPhysWorld3D; + + class NAZARA_JOLTPHYSICS3D_API JoltCharacter + { + friend JoltPhysWorld3D; + + public: + JoltCharacter(JoltPhysWorld3D& physWorld, std::shared_ptr collider, const Vector3f& position, const Quaternionf& rotation = Quaternionf::Identity()); + JoltCharacter(const JoltCharacter&) = delete; + JoltCharacter(JoltCharacter&&) = delete; + ~JoltCharacter(); + + Vector3f GetLinearVelocity() const; + Quaternionf GetRotation() const; + Vector3f GetPosition() const; + std::pair GetPositionAndRotation() const; + + bool IsOnGround() const; + + void SetLinearVelocity(const Vector3f& linearVel); + + JoltCharacter& operator=(const JoltCharacter&) = delete; + JoltCharacter& operator=(JoltCharacter&&) = delete; + + private: + void PostSimulate(); + + std::shared_ptr m_collider; + std::unique_ptr m_character; + JoltPhysWorld3D& m_physicsWorld; + }; +} + +#include + +#endif // NAZARA_JOLTPHYSICS3D_JOLTCHARACTER_HPP diff --git a/include/Nazara/JoltPhysics3D/JoltCharacter.inl b/include/Nazara/JoltPhysics3D/JoltCharacter.inl new file mode 100644 index 000000000..a64c97e3d --- /dev/null +++ b/include/Nazara/JoltPhysics3D/JoltCharacter.inl @@ -0,0 +1,12 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - JoltPhysics3D module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ +} + +#include diff --git a/include/Nazara/JoltPhysics3D/JoltCollider3D.hpp b/include/Nazara/JoltPhysics3D/JoltCollider3D.hpp index c596e4635..ed8fa0ba1 100644 --- a/include/Nazara/JoltPhysics3D/JoltCollider3D.hpp +++ b/include/Nazara/JoltPhysics3D/JoltCollider3D.hpp @@ -7,23 +7,21 @@ #ifndef NAZARA_JOLTPHYSICS3D_JOLTCOLLIDER3D_HPP #define NAZARA_JOLTPHYSICS3D_JOLTCOLLIDER3D_HPP -#include +#include #include #include #include #include #include #include -#include -#include +#include +#include #include namespace JPH { class ShapeSettings; class BoxShapeSettings; - class CompoundShapeSettings; - class SphereShapeSettings; } namespace Nz @@ -35,7 +33,7 @@ namespace Nz class NAZARA_JOLTPHYSICS3D_API JoltCollider3D { public: - JoltCollider3D() = default; + JoltCollider3D(); JoltCollider3D(const JoltCollider3D&) = delete; JoltCollider3D(JoltCollider3D&&) = delete; virtual ~JoltCollider3D(); @@ -44,7 +42,7 @@ namespace Nz virtual std::shared_ptr GenerateDebugMesh() const; - virtual JPH::ShapeSettings* GetShapeSettings() const = 0; + inline JPH::ShapeSettings* GetShapeSettings() const; virtual JoltColliderType3D GetType() const = 0; JoltCollider3D& operator=(const JoltCollider3D&) = delete; @@ -52,25 +50,28 @@ namespace Nz static std::shared_ptr Build(const PrimitiveList& list); + protected: + template const T* GetShapeSettingsAs() const; + template void SetupShapeSettings(std::unique_ptr shapeSettings); + private: static std::shared_ptr CreateGeomFromPrimitive(const Primitive& primitive); + + std::unique_ptr m_shapeSettings; }; + /*********************************** Shapes ******************************************/ + class NAZARA_JOLTPHYSICS3D_API JoltBoxCollider3D final : public JoltCollider3D { public: JoltBoxCollider3D(const Vector3f& lengths, float convexRadius = 0.f); - ~JoltBoxCollider3D(); + ~JoltBoxCollider3D() = default; void BuildDebugMesh(std::vector& vertices, std::vector& indices, const Matrix4f& offsetMatrix) const override; Vector3f GetLengths() const; - JPH::ShapeSettings* GetShapeSettings() const override; JoltColliderType3D GetType() const override; - - private: - std::unique_ptr m_shapeSettings; - Vector3f m_lengths; }; class NAZARA_JOLTPHYSICS3D_API JoltCompoundCollider3D final : public JoltCollider3D @@ -79,12 +80,11 @@ namespace Nz struct ChildCollider; JoltCompoundCollider3D(std::vector childs); - ~JoltCompoundCollider3D(); + ~JoltCompoundCollider3D() = default; void BuildDebugMesh(std::vector& vertices, std::vector& indices, const Matrix4f& offsetMatrix) const override; const std::vector& GetGeoms() const; - JPH::ShapeSettings* GetShapeSettings() const override; JoltColliderType3D GetType() const override; struct ChildCollider @@ -95,7 +95,6 @@ namespace Nz }; private: - std::unique_ptr m_shapeSettings; std::vector m_childs; }; @@ -103,19 +102,32 @@ namespace Nz { public: JoltSphereCollider3D(float radius); - ~JoltSphereCollider3D(); + ~JoltSphereCollider3D() = default; void BuildDebugMesh(std::vector& vertices, std::vector& indices, const Matrix4f& offsetMatrix) const override; float GetRadius() const; - JPH::ShapeSettings* GetShapeSettings() const override; + JoltColliderType3D GetType() const override; + }; + + /*********************************** Decorated ******************************************/ + + class NAZARA_JOLTPHYSICS3D_API JoltTranslatedRotatedCollider3D final : public JoltCollider3D + { + public: + inline JoltTranslatedRotatedCollider3D(std::shared_ptr collider, const Vector3f& translation); + inline JoltTranslatedRotatedCollider3D(std::shared_ptr collider, const Quaternionf& rotation); + JoltTranslatedRotatedCollider3D(std::shared_ptr collider, const Vector3f& translation, const Quaternionf& rotation); + ~JoltTranslatedRotatedCollider3D() = default; + + void BuildDebugMesh(std::vector& vertices, std::vector& indices, const Matrix4f& offsetMatrix) const override; + JoltColliderType3D GetType() const override; private: - std::unique_ptr m_shapeSettings; - Vector3f m_position; - float m_radius; + std::shared_ptr m_collider; }; + } #include diff --git a/include/Nazara/JoltPhysics3D/JoltCollider3D.inl b/include/Nazara/JoltPhysics3D/JoltCollider3D.inl index ea5c23f45..c4e202322 100644 --- a/include/Nazara/JoltPhysics3D/JoltCollider3D.inl +++ b/include/Nazara/JoltPhysics3D/JoltCollider3D.inl @@ -2,11 +2,41 @@ // This file is part of the "Nazara Engine - JoltPhysics3D module" // For conditions of distribution and use, see copyright notice in Config.hpp +#include #include #include namespace Nz { + inline JPH::ShapeSettings* JoltCollider3D::GetShapeSettings() const + { + return m_shapeSettings.get(); + } + + template + const T* JoltCollider3D::GetShapeSettingsAs() const + { + return SafeCast(m_shapeSettings.get()); + } + + template + void JoltCollider3D::SetupShapeSettings(std::unique_ptr shapeSettings) + { + assert(!m_shapeSettings); + shapeSettings->SetEmbedded(); // Call SetEmbedded on the template type to prevent compiler to resolve it outside of a file including Jolt + m_shapeSettings = std::move(shapeSettings); + } + + + inline JoltTranslatedRotatedCollider3D::JoltTranslatedRotatedCollider3D(std::shared_ptr collider, const Vector3f& translation) : + JoltTranslatedRotatedCollider3D(std::move(collider), translation, Quaternionf::Identity()) + { + } + + inline JoltTranslatedRotatedCollider3D::JoltTranslatedRotatedCollider3D(std::shared_ptr collider, const Quaternionf& rotation) : + JoltTranslatedRotatedCollider3D(std::move(collider), Vector3f::Zero(), rotation) + { + } } #include diff --git a/include/Nazara/JoltPhysics3D/JoltConstraint3D.hpp b/include/Nazara/JoltPhysics3D/JoltConstraint3D.hpp index d4ac31982..2144f480e 100644 --- a/include/Nazara/JoltPhysics3D/JoltConstraint3D.hpp +++ b/include/Nazara/JoltPhysics3D/JoltConstraint3D.hpp @@ -7,7 +7,7 @@ #ifndef NAZARA_JOLTPHYSICS3D_JOLTCONSTRAINT3D_HPP #define NAZARA_JOLTPHYSICS3D_JOLTCONSTRAINT3D_HPP -#include +#include #include #include #include diff --git a/include/Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp b/include/Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp index e87b81e17..c47ffa194 100644 --- a/include/Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp +++ b/include/Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp @@ -7,13 +7,15 @@ #ifndef NAZARA_JOLTPHYSICS3D_JOLTPHYSWORLD3D_HPP #define NAZARA_JOLTPHYSICS3D_JOLTPHYSWORLD3D_HPP -#include +#include #include #include #include #include -#include -#include +#include +#include +#include +#include namespace JPH { @@ -22,10 +24,13 @@ namespace JPH namespace Nz { + class JoltCharacter; class JoltRigidBody3D; class NAZARA_JOLTPHYSICS3D_API JoltPhysWorld3D { + friend JoltCharacter; + public: struct RaycastHit; @@ -34,11 +39,14 @@ namespace Nz JoltPhysWorld3D(JoltPhysWorld3D&& ph) = delete; ~JoltPhysWorld3D(); + UInt32 GetActiveBodyCount() const; Vector3f GetGravity() const; std::size_t GetMaxStepCount() const; JPH::PhysicsSystem* GetPhysicsSystem(); Time GetStepSize() const; + inline bool IsBodyActive(UInt32 bodyIndex) const; + bool RaycastQueryFirst(const Vector3f& from, const Vector3f& to, RaycastHit* hitInfo = nullptr); void SetGravity(const Vector3f& gravity); @@ -59,14 +67,24 @@ namespace Nz }; private: + class BodyActivationListener; + friend BodyActivationListener; + struct JoltWorld; + inline void RegisterCharacter(JoltCharacter* character); + inline void UnregisterCharacter(JoltCharacter* character); + std::size_t m_maxStepCount; + std::unique_ptr m_activeBodies; std::unique_ptr m_world; + std::vector m_characters; Vector3f m_gravity; Time m_stepSize; Time m_timestepAccumulator; }; } +#include + #endif // NAZARA_JOLTPHYSICS3D_JOLTPHYSWORLD3D_HPP diff --git a/include/Nazara/JoltPhysics3D/JoltPhysWorld3D.inl b/include/Nazara/JoltPhysics3D/JoltPhysWorld3D.inl new file mode 100644 index 000000000..b92fd4950 --- /dev/null +++ b/include/Nazara/JoltPhysics3D/JoltPhysWorld3D.inl @@ -0,0 +1,31 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - JoltPhysics3D module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include + +namespace Nz +{ + inline bool JoltPhysWorld3D::IsBodyActive(UInt32 bodyIndex) const + { + UInt32 blockIndex = bodyIndex / 64; + UInt32 localIndex = bodyIndex % 64; + + return m_activeBodies[blockIndex] & (UInt64(1u) << localIndex); + } + + inline void JoltPhysWorld3D::RegisterCharacter(JoltCharacter* character) + { + auto it = std::lower_bound(m_characters.begin(), m_characters.end(), character); + m_characters.insert(it, character); + } + + inline void JoltPhysWorld3D::UnregisterCharacter(JoltCharacter* character) + { + auto it = std::lower_bound(m_characters.begin(), m_characters.end(), character); + assert(*it == character); + m_characters.erase(it); + } +} + +#include diff --git a/include/Nazara/JoltPhysics3D/JoltPhysics3D.hpp b/include/Nazara/JoltPhysics3D/JoltPhysics3D.hpp index 2802ac60d..bf6028003 100644 --- a/include/Nazara/JoltPhysics3D/JoltPhysics3D.hpp +++ b/include/Nazara/JoltPhysics3D/JoltPhysics3D.hpp @@ -7,7 +7,7 @@ #ifndef NAZARA_JOLTPHYSICS3D_HPP #define NAZARA_JOLTPHYSICS3D_HPP -#include +#include #include #include #include diff --git a/include/Nazara/JoltPhysics3D/JoltRigidBody3D.hpp b/include/Nazara/JoltPhysics3D/JoltRigidBody3D.hpp index 04f430b6d..f0402ae15 100644 --- a/include/Nazara/JoltPhysics3D/JoltRigidBody3D.hpp +++ b/include/Nazara/JoltPhysics3D/JoltRigidBody3D.hpp @@ -7,14 +7,19 @@ #ifndef NAZARA_JOLTPHYSICS3D_JOLTRIGIDBODY3D_HPP #define NAZARA_JOLTPHYSICS3D_JOLTRIGIDBODY3D_HPP -#include +#include #include #include #include #include #include #include -#include +#include + +namespace JPH +{ + class Body; +} namespace Nz { @@ -41,6 +46,7 @@ namespace Nz Boxf GetAABB() const; float GetAngularDamping() const; Vector3f GetAngularVelocity() const; + inline UInt32 GetBodyIndex() const; inline const std::shared_ptr& GetGeom() const; float GetLinearDamping() const; Vector3f GetLinearVelocity() const; @@ -48,6 +54,7 @@ namespace Nz Vector3f GetMassCenter(CoordSys coordSys = CoordSys::Local) const; Matrix4f GetMatrix() const; Vector3f GetPosition() const; + std::pair GetPositionAndRotation() const; Quaternionf GetRotation() const; inline JoltPhysWorld3D* GetWorld() const; @@ -60,11 +67,13 @@ namespace Nz void SetGeom(std::shared_ptr geom, bool recomputeInertia = true); void SetLinearDamping(float damping); void SetLinearVelocity(const Vector3f& velocity); - void SetMass(float mass); + void SetMass(float mass, bool recomputeInertia = true); void SetMassCenter(const Vector3f& center); void SetPosition(const Vector3f& position); void SetRotation(const Quaternionf& rotation); + void TeleportTo(const Vector3f& position, const Quaternionf& rotation); + Quaternionf ToLocal(const Quaternionf& worldRotation); Vector3f ToLocal(const Vector3f& worldPosition); Quaternionf ToWorld(const Quaternionf& localRotation); @@ -80,6 +89,7 @@ namespace Nz private: std::shared_ptr m_geom; + JPH::Body* m_body; JoltPhysWorld3D* m_world; UInt32 m_bodyIndex; }; diff --git a/include/Nazara/JoltPhysics3D/JoltRigidBody3D.inl b/include/Nazara/JoltPhysics3D/JoltRigidBody3D.inl index 58b788b93..2f95a37da 100644 --- a/include/Nazara/JoltPhysics3D/JoltRigidBody3D.inl +++ b/include/Nazara/JoltPhysics3D/JoltRigidBody3D.inl @@ -11,6 +11,11 @@ namespace Nz return EnableSleeping(false); } + inline UInt32 JoltRigidBody3D::GetBodyIndex() const + { + return m_bodyIndex; + } + inline const std::shared_ptr& JoltRigidBody3D::GetGeom() const { return m_geom; diff --git a/include/Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.hpp b/include/Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.hpp index 6018b7355..1c70246e4 100644 --- a/include/Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.hpp +++ b/include/Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.hpp @@ -7,12 +7,12 @@ #ifndef NAZARA_JOLTPHYSICS3D_SYSTEMS_JOLTPHYSICS3DSYSTEM_HPP #define NAZARA_JOLTPHYSICS3D_SYSTEMS_JOLTPHYSICS3DSYSTEM_HPP -#include +#include #include #include #include #include -#include +#include #include #include diff --git a/src/Nazara/BulletPhysics3D/BulletCollider3D.cpp b/src/Nazara/BulletPhysics3D/BulletCollider3D.cpp index eeb017865..e5215076e 100644 --- a/src/Nazara/BulletPhysics3D/BulletCollider3D.cpp +++ b/src/Nazara/BulletPhysics3D/BulletCollider3D.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/Nazara/BulletPhysics3D/BulletHelper.hpp b/src/Nazara/BulletPhysics3D/BulletHelper.hpp index 19729d13d..d7aeefd9a 100644 --- a/src/Nazara/BulletPhysics3D/BulletHelper.hpp +++ b/src/Nazara/BulletPhysics3D/BulletHelper.hpp @@ -7,7 +7,7 @@ #ifndef NAZARA_BULLETPHYSICS3D_BULLETHELPER_HPP #define NAZARA_BULLETPHYSICS3D_BULLETHELPER_HPP -#include +#include #include #include #include diff --git a/src/Nazara/BulletPhysics3D/BulletPhysWorld3D.cpp b/src/Nazara/BulletPhysics3D/BulletPhysWorld3D.cpp index ec4cb7ce2..7e86f85fe 100644 --- a/src/Nazara/BulletPhysics3D/BulletPhysWorld3D.cpp +++ b/src/Nazara/BulletPhysics3D/BulletPhysWorld3D.cpp @@ -4,8 +4,8 @@ #include #include -#include -#include +#include +#include #include #include #include diff --git a/src/Nazara/BulletPhysics3D/BulletRigidBody3D.cpp b/src/Nazara/BulletPhysics3D/BulletRigidBody3D.cpp index 0b75b4c3b..e9d1cab7c 100644 --- a/src/Nazara/BulletPhysics3D/BulletRigidBody3D.cpp +++ b/src/Nazara/BulletPhysics3D/BulletRigidBody3D.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/Nazara/BulletPhysics3D/Systems/BulletPhysics3DSystem.cpp b/src/Nazara/BulletPhysics3D/Systems/BulletPhysics3DSystem.cpp index d491587a9..767c74fce 100644 --- a/src/Nazara/BulletPhysics3D/Systems/BulletPhysics3DSystem.cpp +++ b/src/Nazara/BulletPhysics3D/Systems/BulletPhysics3DSystem.cpp @@ -38,6 +38,7 @@ namespace Nz std::cout << "Physics time: " << (m_physicsTime / Time::Nanoseconds(m_stepCount)) << std::endl; std::cout << "Update time: " << (m_updateTime / Time::Nanoseconds(m_stepCount)) << std::endl; + std::cout << "Active body count: " << m_activeObjectCount << std::endl; std::cout << "--" << std::endl; m_stepCount = 0; @@ -81,14 +82,18 @@ namespace Nz // Replicate rigid body position to their node components // TODO: Only replicate active entities + m_activeObjectCount = 0; + auto view = m_registry.view(); - for (auto [entity, nodeComponent, rigidBodyComponent] : view.each()) + for (auto entity : view) { + auto& rigidBodyComponent = view.get(entity); if (rigidBodyComponent.IsSleeping()) continue; - nodeComponent.SetPosition(rigidBodyComponent.GetPosition(), CoordSys::Global); - nodeComponent.SetRotation(rigidBodyComponent.GetRotation(), CoordSys::Global); + auto& nodeComponent = view.get(entity); + nodeComponent.SetTransform(rigidBodyComponent.GetPosition(), rigidBodyComponent.GetRotation()); + m_activeObjectCount++; } Time t3 = GetElapsedNanoseconds(); diff --git a/src/Nazara/JoltPhysics3D/JoltCharacter.cpp b/src/Nazara/JoltPhysics3D/JoltCharacter.cpp new file mode 100644 index 000000000..210c7b780 --- /dev/null +++ b/src/Nazara/JoltPhysics3D/JoltCharacter.cpp @@ -0,0 +1,78 @@ +// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - JoltPhysics3D module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + JoltCharacter::JoltCharacter(JoltPhysWorld3D& physWorld, std::shared_ptr collider, const Vector3f& position, const Quaternionf& rotation) : + m_collider(std::move(collider)), + m_physicsWorld(physWorld) + { + auto shapeResult = m_collider->GetShapeSettings()->Create(); + if (!shapeResult.IsValid()) + throw std::runtime_error("invalid shape"); + + JPH::CharacterSettings settings; + settings.mShape = shapeResult.Get(); + + m_character = std::make_unique(&settings, ToJolt(position), ToJolt(rotation), 0, m_physicsWorld.GetPhysicsSystem()); + m_character->AddToPhysicsSystem(); + + m_physicsWorld.RegisterCharacter(this); + } + + JoltCharacter::~JoltCharacter() + { + m_character->RemoveFromPhysicsSystem(); + + m_physicsWorld.UnregisterCharacter(this); + } + + Vector3f JoltCharacter::GetLinearVelocity() const + { + return FromJolt(m_character->GetLinearVelocity()); + } + + Quaternionf JoltCharacter::GetRotation() const + { + return FromJolt(m_character->GetRotation()); + } + + Vector3f JoltCharacter::GetPosition() const + { + return FromJolt(m_character->GetPosition()); + } + + std::pair JoltCharacter::GetPositionAndRotation() const + { + JPH::Vec3 position; + JPH::Quat rotation; + m_character->GetPositionAndRotation(position, rotation); + + return { FromJolt(position), FromJolt(rotation) }; + } + + bool JoltCharacter::IsOnGround() const + { + return m_character->IsSupported(); + } + + void JoltCharacter::SetLinearVelocity(const Vector3f& linearVel) + { + m_character->SetLinearVelocity(ToJolt(linearVel)); + } + + void JoltCharacter::PostSimulate() + { + m_character->PostSimulation(0.05f); + } +} diff --git a/src/Nazara/JoltPhysics3D/JoltCollider3D.cpp b/src/Nazara/JoltPhysics3D/JoltCollider3D.cpp index 16a5e1ccf..7dd04ec78 100644 --- a/src/Nazara/JoltPhysics3D/JoltCollider3D.cpp +++ b/src/Nazara/JoltPhysics3D/JoltCollider3D.cpp @@ -10,15 +10,17 @@ #include #include #include -#include +#include #include #include +#include #include #include #include namespace Nz { + JoltCollider3D::JoltCollider3D() = default; JoltCollider3D::~JoltCollider3D() = default; std::shared_ptr JoltCollider3D::GenerateDebugMesh() const @@ -85,14 +87,11 @@ namespace Nz /********************************** BoxCollider3D **********************************/ - JoltBoxCollider3D::JoltBoxCollider3D(const Vector3f& lengths, float convexRadius) : - m_lengths(lengths) + JoltBoxCollider3D::JoltBoxCollider3D(const Vector3f& lengths, float convexRadius) { - m_shapeSettings = std::make_unique(ToJolt(m_lengths * 0.5f), convexRadius); + SetupShapeSettings(std::make_unique(ToJolt(lengths * 0.5f), convexRadius)); } - JoltBoxCollider3D::~JoltBoxCollider3D() = default; - void JoltBoxCollider3D::BuildDebugMesh(std::vector& vertices, std::vector& indices, const Matrix4f& offsetMatrix) const { auto InsertVertex = [&](float x, float y, float z) -> UInt16 @@ -102,7 +101,7 @@ namespace Nz return index; }; - Vector3f halfLengths = m_lengths * 0.5f; + Vector3f halfLengths = FromJolt(GetShapeSettingsAs()->mHalfExtent); UInt16 v0 = InsertVertex(-halfLengths.x, -halfLengths.y, -halfLengths.z); UInt16 v1 = InsertVertex(halfLengths.x, -halfLengths.y, -halfLengths.z); @@ -135,14 +134,9 @@ namespace Nz InsertEdge(v3, v7); } - JPH::ShapeSettings* JoltBoxCollider3D::GetShapeSettings() const - { - return m_shapeSettings.get(); - } - Vector3f JoltBoxCollider3D::GetLengths() const { - return m_lengths; + return FromJolt(GetShapeSettingsAs()->mHalfExtent) * 2.f; } JoltColliderType3D JoltBoxCollider3D::GetType() const @@ -155,12 +149,12 @@ namespace Nz JoltCompoundCollider3D::JoltCompoundCollider3D(std::vector childs) : m_childs(std::move(childs)) { - m_shapeSettings = std::make_unique(); + auto shapeSettings = std::make_unique(); for (const auto& child : m_childs) - m_shapeSettings->AddShape(ToJolt(child.offset), ToJolt(child.rotation), child.collider->GetShapeSettings()); - } + shapeSettings->AddShape(ToJolt(child.offset), ToJolt(child.rotation), child.collider->GetShapeSettings()); - JoltCompoundCollider3D::~JoltCompoundCollider3D() = default; + SetupShapeSettings(std::move(shapeSettings)); + } void JoltCompoundCollider3D::BuildDebugMesh(std::vector& vertices, std::vector& indices, const Matrix4f& offsetMatrix) const { @@ -173,11 +167,6 @@ namespace Nz return m_childs; } - JPH::ShapeSettings* JoltCompoundCollider3D::GetShapeSettings() const - { - return m_shapeSettings.get(); - } - JoltColliderType3D JoltCompoundCollider3D::GetType() const { return JoltColliderType3D::Compound; @@ -185,30 +174,40 @@ namespace Nz /******************************** JoltSphereCollider3D *********************************/ - JoltSphereCollider3D::JoltSphereCollider3D(float radius) : - m_radius(radius) + JoltSphereCollider3D::JoltSphereCollider3D(float radius) { - m_shapeSettings = std::make_unique(radius); + SetupShapeSettings(std::make_unique(radius)); } - JoltSphereCollider3D::~JoltSphereCollider3D() = default; - void JoltSphereCollider3D::BuildDebugMesh(std::vector& vertices, std::vector& indices, const Matrix4f& offsetMatrix) const { } float JoltSphereCollider3D::GetRadius() const { - return m_radius; - } - - JPH::ShapeSettings* JoltSphereCollider3D::GetShapeSettings() const - { - return m_shapeSettings.get(); + return GetShapeSettingsAs()->mRadius; } JoltColliderType3D JoltSphereCollider3D::GetType() const { return JoltColliderType3D::Sphere; } + + JoltTranslatedRotatedCollider3D::JoltTranslatedRotatedCollider3D(std::shared_ptr collider, const Vector3f& translation, const Quaternionf& rotation) : + m_collider(std::move(collider)) + { + SetupShapeSettings(std::make_unique(ToJolt(translation), ToJolt(rotation), m_collider->GetShapeSettings())); + } + + void JoltTranslatedRotatedCollider3D::BuildDebugMesh(std::vector& vertices, std::vector& indices, const Matrix4f& offsetMatrix) const + { + const JPH::RotatedTranslatedShapeSettings* settings = GetShapeSettingsAs(); + + m_collider->BuildDebugMesh(vertices, indices, offsetMatrix * Matrix4f::Transform(FromJolt(settings->mPosition), FromJolt(settings->mRotation))); + } + + JoltColliderType3D JoltTranslatedRotatedCollider3D::GetType() const + { + return JoltColliderType3D::TranslatedRotatedDecoration; + } } diff --git a/src/Nazara/JoltPhysics3D/JoltHelper.hpp b/src/Nazara/JoltPhysics3D/JoltHelper.hpp index 9725c77ed..ed9af2ba5 100644 --- a/src/Nazara/JoltPhysics3D/JoltHelper.hpp +++ b/src/Nazara/JoltPhysics3D/JoltHelper.hpp @@ -7,7 +7,7 @@ #ifndef NAZARA_JOLTPHYSICS3D_JOLTHELPER_HPP #define NAZARA_JOLTPHYSICS3D_JOLTHELPER_HPP -#include +#include #include #include #include diff --git a/src/Nazara/JoltPhysics3D/JoltPhysWorld3D.cpp b/src/Nazara/JoltPhysics3D/JoltPhysWorld3D.cpp index 1249b8bad..2f884ba1d 100644 --- a/src/Nazara/JoltPhysics3D/JoltPhysWorld3D.cpp +++ b/src/Nazara/JoltPhysics3D/JoltPhysWorld3D.cpp @@ -3,11 +3,12 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #include #include #include -#include -#include +#include +#include #include #include #include @@ -152,37 +153,59 @@ namespace DitchMeAsap cout << "A contact was removed" << endl; } }; - - // An example activation listener - class MyBodyActivationListener : public BodyActivationListener - { - public: - virtual void OnBodyActivated(const BodyID& inBodyID, uint64 inBodyUserData) override - { - cout << "A body got activated" << endl; - } - - virtual void OnBodyDeactivated(const BodyID& inBodyID, uint64 inBodyUserData) override - { - cout << "A body went to sleep" << endl; - } - }; } namespace Nz { + class JoltPhysWorld3D::BodyActivationListener : public JPH::BodyActivationListener + { + public: + static constexpr UInt32 BodyPerBlock = 64; + + BodyActivationListener(JoltPhysWorld3D& physWorld) : + m_physWorld(physWorld) + { + } + + void OnBodyActivated(const JPH::BodyID& inBodyID, UInt64 inBodyUserData) override + { + UInt32 bodyIndex = inBodyID.GetIndex(); + UInt32 blockIndex = bodyIndex / 64; + UInt32 localIndex = bodyIndex % 64; + + m_physWorld.m_activeBodies[blockIndex] |= UInt64(1u) << localIndex; + } + + void OnBodyDeactivated(const JPH::BodyID& inBodyID, UInt64 inBodyUserData) override + { + UInt32 bodyIndex = inBodyID.GetIndex(); + UInt32 blockIndex = bodyIndex / 64; + UInt32 localIndex = bodyIndex % 64; + + m_physWorld.m_activeBodies[blockIndex] &= ~(UInt64(1u) << localIndex); + } + + private: + JoltPhysWorld3D& m_physWorld; + }; + struct JoltPhysWorld3D::JoltWorld { - JPH::TempAllocatorMalloc tempAllocation; + JPH::TempAllocatorImpl tempAllocator; JPH::PhysicsSystem physicsSystem; + JoltPhysWorld3D::BodyActivationListener bodyActivationListener; + DitchMeAsap::BPLayerInterfaceImpl layerInterface; DitchMeAsap::ObjectLayerPairFilterImpl objectLayerFilter; DitchMeAsap::ObjectVsBroadPhaseLayerFilterImpl objectBroadphaseLayerFilter; - DitchMeAsap::MyBodyActivationListener bodyActivationListener; - DitchMeAsap::MyContactListener contactListener; - JoltWorld() = default; + JoltWorld(JoltPhysWorld3D& world, JPH::uint tempAllocatorSize) : + tempAllocator(tempAllocatorSize), + bodyActivationListener(world) + { + } + JoltWorld(const JoltWorld&) = delete; JoltWorld(JoltWorld&&) = delete; @@ -196,14 +219,23 @@ namespace Nz m_stepSize(Time::TickDuration(120)), m_timestepAccumulator(Time::Zero()) { - m_world = std::make_unique(); - m_world->physicsSystem.Init(0xFFFF, 0, 0xFFFF, 0xFFFF, m_world->layerInterface, m_world->objectBroadphaseLayerFilter, m_world->objectLayerFilter); + m_world = std::make_unique(*this, 10 * 1024 * 1024); + m_world->physicsSystem.Init(0xFFFF, 0, 0xFFFF, 10 * 1024, m_world->layerInterface, m_world->objectBroadphaseLayerFilter, m_world->objectLayerFilter); m_world->physicsSystem.SetBodyActivationListener(&m_world->bodyActivationListener); - //m_world->physicsSystem.SetContactListener(&m_world->contactListener); + + std::size_t blockCount = (m_world->physicsSystem.GetMaxBodies() - 1) / 64 + 1; + m_activeBodies = std::make_unique(blockCount); + for (std::size_t i = 0; i < blockCount; ++i) + m_activeBodies[i] = 0; } JoltPhysWorld3D::~JoltPhysWorld3D() = default; + UInt32 JoltPhysWorld3D::GetActiveBodyCount() const + { + return m_world->physicsSystem.GetNumActiveBodies(); + } + Vector3f JoltPhysWorld3D::GetGravity() const { return FromJolt(m_world->physicsSystem.GetGravity()); @@ -280,7 +312,11 @@ namespace Nz std::size_t stepCount = 0; while (m_timestepAccumulator >= m_stepSize && stepCount < m_maxStepCount) { - m_world->physicsSystem.Update(stepSize, 1, 1, &m_world->tempAllocation, &jobSystem); + m_world->physicsSystem.Update(stepSize, 1, 1, &m_world->tempAllocator, &jobSystem); + + for (JoltCharacter* character : m_characters) + character->PostSimulate(); + m_timestepAccumulator -= m_stepSize; stepCount++; } diff --git a/src/Nazara/JoltPhysics3D/JoltPhysics3D.cpp b/src/Nazara/JoltPhysics3D/JoltPhysics3D.cpp index 1bed046e0..03a327c14 100644 --- a/src/Nazara/JoltPhysics3D/JoltPhysics3D.cpp +++ b/src/Nazara/JoltPhysics3D/JoltPhysics3D.cpp @@ -40,14 +40,18 @@ namespace Nz JPH::Factory::sInstance = new JPH::Factory; JPH::RegisterTypes(); - m_threadPool = std::make_unique(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, /* Core::Instance()->GetHardwareInfo().GetCpuThreadCount()*/0); + int threadCount = -1; //< system CPU core count +#ifdef NAZARA_PLATFORM_WEB + threadCount = 0; // no thread on web for now +#endif + + m_threadPool = std::make_unique(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, threadCount); } JoltPhysics3D::~JoltPhysics3D() { m_threadPool.reset(); - // FIXME: Uncomment when next version of Jolt gets released - //JPH::UnregisterTypes(); + JPH::UnregisterTypes(); delete JPH::Factory::sInstance; JPH::Factory::sInstance = nullptr; diff --git a/src/Nazara/JoltPhysics3D/JoltRigidBody3D.cpp b/src/Nazara/JoltPhysics3D/JoltRigidBody3D.cpp index 739260621..30ee468cd 100644 --- a/src/Nazara/JoltPhysics3D/JoltRigidBody3D.cpp +++ b/src/Nazara/JoltPhysics3D/JoltRigidBody3D.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -29,28 +29,32 @@ namespace Nz NazaraAssert(m_world, "Invalid world"); if (!m_geom) - m_geom = std::make_shared(1.f); + m_geom = std::make_shared(std::numeric_limits::epsilon()); - JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); + JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface(); JPH::Vec3 position = ToJolt(mat.GetTranslation()); JPH::Quat rotation = ToJolt(mat.GetRotation().Normalize()); JPH::BodyCreationSettings settings(m_geom->GetShapeSettings(), position, rotation, JPH::EMotionType::Dynamic, 1); - JPH::Body* body = body_interface.CreateBody(settings); - body->SetUserData(SafeCast(reinterpret_cast(this))); + m_body = bodyInterface.CreateBody(settings); + m_body->SetUserData(SafeCast(reinterpret_cast(this))); - body_interface.AddBody(body->GetID(), JPH::EActivation::Activate); - m_bodyIndex = body->GetID().GetIndexAndSequenceNumber(); + JPH::BodyID bodyId = m_body->GetID(); + + bodyInterface.AddBody(bodyId, JPH::EActivation::Activate); + m_bodyIndex = bodyId.GetIndex(); } JoltRigidBody3D::JoltRigidBody3D(JoltRigidBody3D&& object) noexcept : m_geom(std::move(object.m_geom)), + m_body(object.m_body), m_bodyIndex(object.m_bodyIndex), m_world(object.m_world) { - object.m_bodyIndex = JPH::BodyID::cInvalidBodyID; + object.m_body = nullptr; + object.m_bodyIndex = std::numeric_limits::max(); } JoltRigidBody3D::~JoltRigidBody3D() @@ -64,16 +68,12 @@ namespace Nz { case CoordSys::Global: { - JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); - body_interface.AddForce(JPH::BodyID(m_bodyIndex), ToJolt(force)); - //WakeUp(); - //m_body->applyCentralForce(ToJolt(force)); + m_body->AddForce(ToJolt(force)); break; } case CoordSys::Local: - //WakeUp(); - //m_body->applyCentralForce(ToJolt(GetRotation() * force)); + m_body->AddForce(m_body->GetRotation() * ToJolt(force)); break; } } @@ -115,13 +115,7 @@ namespace Nz #endif void JoltRigidBody3D::EnableSleeping(bool enable) { - auto& body_interface = m_world->GetPhysicsSystem()->GetBodyLockInterface(); - JPH::BodyLockWrite lock(body_interface, JPH::BodyID(m_bodyIndex)); - if (lock.Succeeded()) - { - JPH::Body& body = lock.GetBody(); - body.SetAllowSleeping(enable); - } + m_body->SetAllowSleeping(enable); } #if 0 @@ -162,13 +156,7 @@ namespace Nz float JoltRigidBody3D::GetMass() const { - auto& body_interface = m_world->GetPhysicsSystem()->GetBodyLockInterface(); - JPH::BodyLockRead lock(body_interface, JPH::BodyID(m_bodyIndex)); - if (!lock.Succeeded()) - return 0.f; - - const JPH::Body& body = lock.GetBody(); - return 1.f / body.GetMotionProperties()->GetInverseMass(); + return 1.f / m_body->GetMotionProperties()->GetInverseMass(); } #if 0 Vector3f JoltRigidBody3D::GetMassCenter(CoordSys coordSys) const @@ -184,14 +172,20 @@ namespace Nz Vector3f JoltRigidBody3D::GetPosition() const { - JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); - return FromJolt(body_interface.GetPosition(JPH::BodyID(m_bodyIndex))); + return FromJolt(m_body->GetPosition()); + } + + std::pair JoltRigidBody3D::GetPositionAndRotation() const + { + JPH::Vec3 position = m_body->GetPosition(); + JPH::Quat rotation = m_body->GetRotation(); + + return { FromJolt(position), FromJolt(rotation) }; } Quaternionf JoltRigidBody3D::GetRotation() const { - JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); - return FromJolt(body_interface.GetRotation(JPH::BodyID(m_bodyIndex))); + return FromJolt(m_body->GetRotation()); } #if 0 @@ -203,19 +197,12 @@ namespace Nz bool JoltRigidBody3D::IsSleeping() const { - JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); - return !body_interface.IsActive(JPH::BodyID(m_bodyIndex)); + return m_body->IsActive(); } bool JoltRigidBody3D::IsSleepingEnabled() const { - auto& body_interface = m_world->GetPhysicsSystem()->GetBodyLockInterface(); - JPH::BodyLockRead lock(body_interface, JPH::BodyID(m_bodyIndex)); - if (!lock.Succeeded()) - return true; - - const JPH::Body& body = lock.GetBody(); - return body.GetAllowSleeping(); + return m_body->GetAllowSleeping(); } #if 0 @@ -233,72 +220,79 @@ namespace Nz { if (m_geom != geom) { + float mass = GetMass(); + if (geom) m_geom = std::move(geom); else - m_geom = std::make_shared(1.f); + m_geom = std::make_shared(std::numeric_limits::epsilon()); - JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); - body_interface.SetShape(JPH::BodyID(m_bodyIndex), m_geom->GetShapeSettings()->Create().Get(), true, JPH::EActivation::Activate); + JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface(); + bodyInterface.SetShape(m_body->GetID(), m_geom->GetShapeSettings()->Create().Get(), false, JPH::EActivation::Activate); + if (recomputeInertia) + { + JPH::MassProperties massProperties = m_body->GetShape()->GetMassProperties(); + massProperties.ScaleToMass(mass); + m_body->GetMotionProperties()->SetMassProperties(massProperties); + } } } -#if 0 + void JoltRigidBody3D::SetLinearDamping(float damping) { - m_body->setDamping(damping, m_body->getAngularDamping()); + m_body->GetMotionProperties()->SetLinearDamping(damping); } void JoltRigidBody3D::SetLinearVelocity(const Vector3f& velocity) { - m_body->setLinearVelocity(ToJolt(velocity)); + m_body->SetLinearVelocity(ToJolt(velocity)); } -#endif 0 - void JoltRigidBody3D::SetMass(float mass) + + void JoltRigidBody3D::SetMass(float mass, bool recomputeInertia) { NazaraAssert(mass >= 0.f, "Mass must be positive and finite"); NazaraAssert(std::isfinite(mass), "Mass must be positive and finite"); - auto& bodyLock = m_world->GetPhysicsSystem()->GetBodyLockInterface(); - JPH::BodyLockWrite lock(bodyLock, JPH::BodyID(m_bodyIndex)); - if (!lock.Succeeded()) - return; - - JPH::Body& body = lock.GetBody(); - if (mass > 0.f) { - body.SetMotionType(JPH::EMotionType::Dynamic); - body.GetMotionProperties()->SetInverseMass(1.f / mass); + m_body->SetMotionType(JPH::EMotionType::Dynamic); + if (recomputeInertia) + { + JPH::MassProperties massProperties = m_body->GetShape()->GetMassProperties(); + massProperties.ScaleToMass(mass); + m_body->GetMotionProperties()->SetMassProperties(massProperties); + } } else { - JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock(); + JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock(); + bodyInterface.DeactivateBody(m_body->GetID()); - body_interface.DeactivateBody(body.GetID()); - body.SetMotionType(JPH::EMotionType::Static); + m_body->SetMotionType(JPH::EMotionType::Static); } } -#if 0 void JoltRigidBody3D::SetMassCenter(const Vector3f& center) { - btTransform centerTransform; - centerTransform.setIdentity(); - centerTransform.setOrigin(ToJolt(center)); - - m_body->setCenterOfMassTransform(centerTransform); + //m_body->GetMotionProperties()->set } -#endif 0 + void JoltRigidBody3D::SetPosition(const Vector3f& position) { - JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); - body_interface.SetPosition(JPH::BodyID(m_bodyIndex), ToJolt(position), JPH::EActivation::Activate); + JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock(); + bodyInterface.SetPosition(m_body->GetID(), ToJolt(position), JPH::EActivation::Activate); } void JoltRigidBody3D::SetRotation(const Quaternionf& rotation) { - JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); - body_interface.SetRotation(JPH::BodyID(m_bodyIndex), ToJolt(rotation), JPH::EActivation::Activate); + JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock(); + body_interface.SetRotation(m_body->GetID(), ToJolt(rotation), JPH::EActivation::Activate); + } + + void JoltRigidBody3D::TeleportTo(const Vector3f& position, const Quaternionf& rotation) + { + JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock(); + bodyInterface.SetPositionAndRotation(m_body->GetID(), ToJolt(position), ToJolt(rotation), JPH::EActivation::Activate); } #if 0 @@ -327,30 +321,34 @@ namespace Nz void JoltRigidBody3D::WakeUp() { JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); - body_interface.ActivateBody(JPH::BodyID(m_bodyIndex)); + body_interface.ActivateBody(m_body->GetID()); } JoltRigidBody3D& JoltRigidBody3D::operator=(JoltRigidBody3D&& object) noexcept { Destroy(); + m_body = object.m_body; m_bodyIndex = object.m_bodyIndex; m_geom = std::move(object.m_geom); m_world = object.m_world; - object.m_bodyIndex = JPH::BodyID::cInvalidBodyID; + object.m_body = nullptr; + object.m_bodyIndex = std::numeric_limits::max(); return *this; } void JoltRigidBody3D::Destroy() { - if (m_bodyIndex != JPH::BodyID::cInvalidBodyID) + if (m_body) { - JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); - body_interface.RemoveBody(JPH::BodyID(m_bodyIndex)); - body_interface.DestroyBody(JPH::BodyID(m_bodyIndex)); - m_bodyIndex = JPH::BodyID::cInvalidBodyID; + JPH::BodyID bodyId = m_body->GetID(); + + JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface(); + bodyInterface.RemoveBody(bodyId); + bodyInterface.DestroyBody(bodyId); + m_body = nullptr; } m_geom.reset(); diff --git a/src/Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.cpp b/src/Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.cpp index 8d2184aa2..85f1f0aca 100644 --- a/src/Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.cpp +++ b/src/Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.cpp @@ -37,7 +37,8 @@ namespace Nz m_stepCount = 1; std::cout << "Physics time: " << (m_physicsTime / Time::Nanoseconds(m_stepCount)) << std::endl; - std::cout << "Update time: " << (m_updateTime / Time::Nanoseconds(m_stepCount)) << std::endl; + std::cout << "Replication time: " << (m_updateTime / Time::Nanoseconds(m_stepCount)) << std::endl; + std::cout << "Active entity count: " << m_physWorld.GetActiveBodyCount() << std::endl; std::cout << "--" << std::endl; m_stepCount = 0; @@ -68,8 +69,7 @@ namespace Nz JoltRigidBody3DComponent& entityPhysics = m_registry.get(entity); NodeComponent& entityNode = m_registry.get(entity); - entityPhysics.SetPosition(entityNode.GetPosition(CoordSys::Global)); - entityPhysics.SetRotation(entityNode.GetRotation(CoordSys::Global)); + entityPhysics.TeleportTo(entityNode.GetPosition(), entityNode.GetRotation()); }); Time t1 = GetElapsedNanoseconds(); @@ -80,16 +80,18 @@ namespace Nz Time t2 = GetElapsedNanoseconds(); - // Replicate rigid body position to their node components - // TODO: Only replicate active entities + // Replicate active rigid body position to their node components auto view = m_registry.view(); - for (auto [entity, nodeComponent, rigidBodyComponent] : view.each()) + for (auto entity : view) { - if (rigidBodyComponent.IsSleeping()) + auto& rigidBodyComponent = view.get(entity); + if (!m_physWorld.IsBodyActive(rigidBodyComponent.GetBodyIndex())) continue; - nodeComponent.SetPosition(rigidBodyComponent.GetPosition(), CoordSys::Global); - nodeComponent.SetRotation(rigidBodyComponent.GetRotation(), CoordSys::Global); + auto& nodeComponent = view.get(entity); + + auto [position, rotation] = rigidBodyComponent.GetPositionAndRotation(); + nodeComponent.SetTransform(position, rotation); } Time t3 = GetElapsedNanoseconds(); @@ -100,9 +102,22 @@ namespace Nz void JoltPhysics3DSystem::OnConstruct(entt::registry& registry, entt::entity entity) { + // Register rigid body owning entity + JoltRigidBody3DComponent& rigidBody = registry.get(entity); + std::size_t uniqueIndex = rigidBody.GetBodyIndex(); + if (uniqueIndex >= m_physicsEntities.size()) + m_physicsEntities.resize(uniqueIndex + 1); + + m_physicsEntities[uniqueIndex] = entity; } void JoltPhysics3DSystem::OnDestruct(entt::registry& registry, entt::entity entity) { + // Unregister owning entity + JoltRigidBody3DComponent& rigidBody = registry.get(entity); + std::size_t uniqueIndex = rigidBody.GetBodyIndex(); + assert(uniqueIndex <= m_physicsEntities.size()); + + m_physicsEntities[uniqueIndex] = entt::null; } } diff --git a/src/Nazara/Utility/Node.cpp b/src/Nazara/Utility/Node.cpp index d61d40253..1b70fa450 100644 --- a/src/Nazara/Utility/Node.cpp +++ b/src/Nazara/Utility/Node.cpp @@ -262,6 +262,44 @@ namespace Nz Invalidate(invalidation); } + void Node::SetTransform(const Vector3f& position, const Quaternionf& rotation, CoordSys coordSys, Invalidation invalidation) + { + switch (coordSys) + { + case CoordSys::Global: + { + // Position + if (m_parent && m_inheritPosition) + { + m_parent->EnsureDerivedUpdate(); + + m_position = (m_parent->m_derivedRotation.GetConjugate() * (position - m_parent->m_derivedPosition)) / m_parent->m_derivedScale - m_initialPosition; + } + else + m_position = position - m_initialPosition; + + // Rotation + if (m_parent && m_inheritRotation) + { + Quaternionf rot(m_parent->GetRotation() * m_initialRotation); + + m_rotation = rot.GetConjugate() * rotation; + } + else + m_rotation = rotation; + + break; + } + + case CoordSys::Local: + m_position = position; + m_rotation = rotation; + break; + } + + Invalidate(invalidation); + } + void Node::SetTransform(const Vector3f& position, const Quaternionf& rotation, const Vector3f& scale, CoordSys coordSys, Invalidation invalidation) { switch (coordSys) diff --git a/xmake.lua b/xmake.lua index c6feab35d..bbc803332 100644 --- a/xmake.lua +++ b/xmake.lua @@ -238,7 +238,7 @@ add_requires( "minimp3", "ordered_map", "stb") -add_requires("joltphysics master", { configs = { debug = is_mode("debug") } }) +add_requires("joltphysics 352550fdd562ce6034b27ab12d1470840e879b56", { configs = { debug = is_mode("debug") }}) add_requires("freetype", { configs = { bzip2 = true, png = true, woff2 = true, zlib = true, debug = is_mode("debug") } }) add_requires("libvorbis", { configs = { with_vorbisenc = false } })