From 648273573d9ef460fe4150fb5c33e56500ac008e Mon Sep 17 00:00:00 2001 From: SirLynix Date: Sun, 19 Mar 2023 11:47:35 +0100 Subject: [PATCH] Make Jolt work on web + update demo --- examples/PhysicsPlayground/main.cpp | 95 ++++++++++++++------ src/Nazara/JoltPhysics3D/JoltPhysWorld3D.cpp | 4 + src/Nazara/JoltPhysics3D/JoltPhysics3D.cpp | 2 +- src/Nazara/JoltPhysics3D/JoltRigidBody3D.cpp | 87 ++++++++++++------ 4 files changed, 131 insertions(+), 57 deletions(-) diff --git a/examples/PhysicsPlayground/main.cpp b/examples/PhysicsPlayground/main.cpp index a947cc2f7..3afaf6209 100644 --- a/examples/PhysicsPlayground/main.cpp +++ b/examples/PhysicsPlayground/main.cpp @@ -19,6 +19,7 @@ constexpr float BoxDims = 16.f; 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; @@ -50,8 +51,9 @@ int main() auto& physSystem = world.AddSystem(); #endif physSystem.GetPhysWorld().SetMaxStepCount(1); - //physSystem.GetPhysWorld().SetGravity(Nz::Vector3f::Down() * 9.81f); - physSystem.GetPhysWorld().SetGravity(Nz::Vector3f::Zero()); + physSystem.GetPhysWorld().SetStepSize(Nz::Time::TickDuration(30)); + physSystem.GetPhysWorld().SetGravity(Nz::Vector3f::Down() * 9.81f); + //physSystem.GetPhysWorld().SetGravity(Nz::Vector3f::Zero()); auto& renderSystem = world.AddSystem(); Nz::WindowSwapchain& windowSwapchain = renderSystem.CreateSwapchain(mainWindow); @@ -146,9 +148,9 @@ int main() //std::mt19937 rd(std::random_device{}()); std::mt19937 rd(42); std::uniform_real_distribution colorDis(0.f, 360.f); - std::uniform_real_distribution radiusDis(0.05f, 0.5f); + std::uniform_real_distribution radiusDis(0.1f, 0.5f); - constexpr std::size_t SphereCount = 3000; + constexpr std::size_t SphereCount = 2000; for (std::size_t i = 0; i < SphereCount; ++i) { float radius = radiusDis(rd); @@ -180,11 +182,11 @@ int main() #else auto& ballPhysics = ballEntity.emplace(physSystem.CreateRigidBody(sphereCollider)); #endif - //ballPhysics.SetMass(4.f / 3.f * Nz::Pi * Nz::IntegralPow(radius, 3)); - ballPhysics.DisableSleeping(); + ballPhysics.SetMass(4.f / 3.f * Nz::Pi * Nz::IntegralPow(radius, 3)); + //ballPhysics.DisableSleeping(); } - std::uniform_real_distribution lengthDis(0.1f, 1.f); + std::uniform_real_distribution lengthDis(0.2f, 1.5f); std::shared_ptr boxMesh = Nz::GraphicalMesh::Build(Nz::Primitive::Box(Nz::Vector3f(1.f))); constexpr std::size_t BoxCount = 100; @@ -224,8 +226,8 @@ int main() #else auto& ballPhysics = ballEntity.emplace(physSystem.CreateRigidBody(boxCollider)); #endif - //ballPhysics.SetMass(width * height * depth); - ballPhysics.DisableSleeping(); + ballPhysics.SetMass(width * height * depth); + //ballPhysics.DisableSleeping(); } // Lumière @@ -270,40 +272,58 @@ int main() NazaraSlot(Nz::WindowEventHandler, OnMouseMoved, cameraMove); NazaraSlot(Nz::WindowEventHandler, OnMouseMoved, grabbedObjectMove); - //std::optional grabConstraint; + //std::optional grabConstraint; + + auto mouseMoveCallback = [&](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseMoveEvent& event) + { + constexpr float sensitivity = 0.3f; + + camAngles.yaw -= event.deltaX * sensitivity; + camAngles.yaw.Normalize(); + + camAngles.pitch = Nz::Clamp(camAngles.pitch - event.deltaY * sensitivity, -89.f, 89.f); + UpdateCamera(); + }; Nz::WindowEventHandler& eventHandler = mainWindow.GetEventHandler(); eventHandler.OnMouseButtonPressed.Connect([&](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseButtonEvent& event) { if (event.button == Nz::Mouse::Middle) { - cameraMove.Connect(eventHandler.OnMouseMoved, [&](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseMoveEvent& event) - { - constexpr float sensitivity = 0.3f; - - camAngles.yaw -= event.deltaX * sensitivity; - camAngles.yaw.Normalize(); - - camAngles.pitch = Nz::Clamp(camAngles.pitch - event.deltaY * sensitivity, -89.f, 89.f); - UpdateCamera(); - }); + cameraMove.Connect(eventHandler.OnMouseMoved, mouseMoveCallback); } else if (event.button == Nz::Mouse::Left) { - auto& cameraNode = cameraEntity.get(); auto& cameraComponent = cameraEntity.get(); Nz::Vector3f from = cameraComponent.Unproject({ float(event.x), float(event.y), 0.f }); Nz::Vector3f to = cameraComponent.Unproject({ float(event.x), float(event.y), 1.f }); - /*Nz::JoltPhysics3DSystem::RaycastHit hitInfo; - if (physSystem.RaycastQueryFirst(from, to, &hitInfo)) + /*/Nz::Physics3DSystem::RaycastHit lastHitInfo; + auto callback = [&](const Nz::Physics3DSystem::RaycastHit& hitInfo) -> std::optional { - if (hitInfo.hitBody) + if (hitInfo.hitEntity == boxEntity) { - grabConstraint.emplace(*hitInfo.hitBody, hitInfo.hitPosition); + Nz::Vector3f dirToCenter = Nz::Vector3f::Zero() - hitInfo.hitPosition; + dirToCenter.Normalize(); - grabbedObjectMove.Connect(eventHandler.OnMouseMoved, [&, body = hitInfo.hitBody, distance = Nz::Vector3f::Distance(from, hitInfo.hitPosition)](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseMoveEvent& event) + if (Nz::Vector3f::DotProduct(dirToCenter, hitInfo.hitNormal) < 0.f) + return std::nullopt; + } + + lastHitInfo = hitInfo; + + return hitInfo.fraction; + }; + + if (physSystem.RaycastQuery(from, to, callback)) + { + if (lastHitInfo.hitBody && lastHitInfo.hitEntity != boxEntity) + { + grabConstraint.emplace(*lastHitInfo.hitBody, lastHitInfo.hitPosition); + grabConstraint->SetImpulseClamp(30.f); + + grabbedObjectMove.Connect(eventHandler.OnMouseMoved, [&, body = lastHitInfo.hitBody, distance = Nz::Vector3f::Distance(from, lastHitInfo.hitPosition)](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseMoveEvent& event) { Nz::Vector3f from = cameraComponent.Unproject({ float(event.x), float(event.y), 0.f }); Nz::Vector3f to = cameraComponent.Unproject({ float(event.x), float(event.y), 1.f }); @@ -312,7 +332,11 @@ int main() grabConstraint->SetSecondAnchor(newPosition); }); } - }*/ + else + cameraMove.Connect(eventHandler.OnMouseMoved, mouseMoveCallback); + } + else + cameraMove.Connect(eventHandler.OnMouseMoved, mouseMoveCallback);*/ } }); @@ -321,6 +345,7 @@ int main() if (event.button == Nz::Mouse::Left) { //grabConstraint.reset(); + cameraMove.Disconnect(); grabbedObjectMove.Disconnect(); } else if (event.button == Nz::Mouse::Middle) @@ -339,10 +364,17 @@ 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()); + }); + Nz::MillisecondClock fpsClock; unsigned int fps = 0; app.AddUpdater([&](Nz::Time /*elapsedTime*/) @@ -357,4 +389,9 @@ int main() }); return app.Run(); + } + catch (const std::exception& e) + { + std::cerr << e.what() << std::endl; + } } diff --git a/src/Nazara/JoltPhysics3D/JoltPhysWorld3D.cpp b/src/Nazara/JoltPhysics3D/JoltPhysWorld3D.cpp index 929804f35..1249b8bad 100644 --- a/src/Nazara/JoltPhysics3D/JoltPhysWorld3D.cpp +++ b/src/Nazara/JoltPhysics3D/JoltPhysWorld3D.cpp @@ -179,6 +179,8 @@ namespace Nz DitchMeAsap::BPLayerInterfaceImpl layerInterface; DitchMeAsap::ObjectLayerPairFilterImpl objectLayerFilter; DitchMeAsap::ObjectVsBroadPhaseLayerFilterImpl objectBroadphaseLayerFilter; + DitchMeAsap::MyBodyActivationListener bodyActivationListener; + DitchMeAsap::MyContactListener contactListener; JoltWorld() = default; JoltWorld(const JoltWorld&) = delete; @@ -196,6 +198,8 @@ namespace Nz { m_world = std::make_unique(); m_world->physicsSystem.Init(0xFFFF, 0, 0xFFFF, 0xFFFF, m_world->layerInterface, m_world->objectBroadphaseLayerFilter, m_world->objectLayerFilter); + m_world->physicsSystem.SetBodyActivationListener(&m_world->bodyActivationListener); + //m_world->physicsSystem.SetContactListener(&m_world->contactListener); } JoltPhysWorld3D::~JoltPhysWorld3D() = default; diff --git a/src/Nazara/JoltPhysics3D/JoltPhysics3D.cpp b/src/Nazara/JoltPhysics3D/JoltPhysics3D.cpp index 75fffedd7..1bed046e0 100644 --- a/src/Nazara/JoltPhysics3D/JoltPhysics3D.cpp +++ b/src/Nazara/JoltPhysics3D/JoltPhysics3D.cpp @@ -40,7 +40,7 @@ namespace Nz JPH::Factory::sInstance = new JPH::Factory; JPH::RegisterTypes(); - m_threadPool = std::make_unique(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, Core::Instance()->GetHardwareInfo().GetCpuThreadCount()); + m_threadPool = std::make_unique(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, /* Core::Instance()->GetHardwareInfo().GetCpuThreadCount()*/0); } JoltPhysics3D::~JoltPhysics3D() diff --git a/src/Nazara/JoltPhysics3D/JoltRigidBody3D.cpp b/src/Nazara/JoltPhysics3D/JoltRigidBody3D.cpp index 43d5d0096..739260621 100644 --- a/src/Nazara/JoltPhysics3D/JoltRigidBody3D.cpp +++ b/src/Nazara/JoltPhysics3D/JoltRigidBody3D.cpp @@ -37,7 +37,6 @@ namespace Nz JPH::Quat rotation = ToJolt(mat.GetRotation().Normalize()); JPH::BodyCreationSettings settings(m_geom->GetShapeSettings(), position, rotation, JPH::EMotionType::Dynamic, 1); - settings.mAllowSleeping = false; JPH::Body* body = body_interface.CreateBody(settings); body->SetUserData(SafeCast(reinterpret_cast(this))); @@ -59,23 +58,27 @@ namespace Nz Destroy(); } -#if 0 void JoltRigidBody3D::AddForce(const Vector3f& force, CoordSys coordSys) { switch (coordSys) { case CoordSys::Global: - WakeUp(); - m_body->applyCentralForce(ToJolt(force)); + { + JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); + body_interface.AddForce(JPH::BodyID(m_bodyIndex), ToJolt(force)); + //WakeUp(); + //m_body->applyCentralForce(ToJolt(force)); break; + } case CoordSys::Local: - WakeUp(); - m_body->applyCentralForce(ToJolt(GetRotation() * force)); + //WakeUp(); + //m_body->applyCentralForce(ToJolt(GetRotation() * force)); break; } } +#if 0 void JoltRigidBody3D::AddForce(const Vector3f& force, const Vector3f& point, CoordSys coordSys) { switch (coordSys) @@ -112,6 +115,13 @@ 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); + } } #if 0 @@ -148,12 +158,19 @@ namespace Nz { return FromJolt(m_body->getLinearVelocity()); } +#endif float JoltRigidBody3D::GetMass() const { - return m_body->getMass(); - } + 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(); + } +#if 0 Vector3f JoltRigidBody3D::GetMassCenter(CoordSys coordSys) const { return FromJolt(m_body->getCenterOfMassPosition()); @@ -190,12 +207,18 @@ namespace Nz return !body_interface.IsActive(JPH::BodyID(m_bodyIndex)); } -#if 0 bool JoltRigidBody3D::IsSleepingEnabled() const { - return m_body->getActivationState() != DISABLE_DEACTIVATION; + 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(); } +#if 0 void JoltRigidBody3D::SetAngularDamping(float angularDamping) { m_body->setDamping(m_body->getLinearDamping(), angularDamping); @@ -205,7 +228,7 @@ namespace Nz { m_body->setAngularVelocity(ToJolt(angularVelocity)); } - +#endif void JoltRigidBody3D::SetGeom(std::shared_ptr geom, bool recomputeInertia) { if (m_geom != geom) @@ -213,21 +236,13 @@ namespace Nz if (geom) m_geom = std::move(geom); else - m_geom = std::make_shared(); + m_geom = std::make_shared(1.f); - m_body->setCollisionShape(m_geom->GetShape()); - if (recomputeInertia) - { - float mass = GetMass(); - - Vector3f inertia; - m_geom->ComputeInertia(mass, &inertia); - - m_body->setMassProps(mass, ToJolt(inertia)); - } + JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); + body_interface.SetShape(JPH::BodyID(m_bodyIndex), m_geom->GetShapeSettings()->Create().Get(), true, JPH::EActivation::Activate); } } - +#if 0 void JoltRigidBody3D::SetLinearDamping(float damping) { m_body->setDamping(damping, m_body->getAngularDamping()); @@ -243,8 +258,25 @@ namespace Nz NazaraAssert(mass >= 0.f, "Mass must be positive and finite"); NazaraAssert(std::isfinite(mass), "Mass must be positive and finite"); - JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); - body_interface.SetMotionType(JPH::BodyID(m_bodyIndex), (mass > 0.f) ? JPH::EMotionType::Dynamic : JPH::EMotionType::Static, JPH::EActivation::Activate); + 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); + } + else + { + JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock(); + + body_interface.DeactivateBody(body.GetID()); + body.SetMotionType(JPH::EMotionType::Static); + } } #if 0 @@ -290,12 +322,13 @@ namespace Nz { return GetMatrix() * localPosition; } +#endif void JoltRigidBody3D::WakeUp() { - m_body->activate(); + JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface(); + body_interface.ActivateBody(JPH::BodyID(m_bodyIndex)); } -#endif JoltRigidBody3D& JoltRigidBody3D::operator=(JoltRigidBody3D&& object) noexcept {