Add JoltPhysics3D for a performance test
This commit is contained in:
parent
bd4c2d6ee7
commit
c5ac142888
|
|
@ -0,0 +1,360 @@
|
|||
// Sources pour https://github.com/NazaraEngine/NazaraEngine/wiki/(FR)-Tutoriel:-%5B01%5D-Hello-World
|
||||
|
||||
#define USE_JOLT 0
|
||||
|
||||
#include <Nazara/Core.hpp>
|
||||
#include <Nazara/Graphics.hpp>
|
||||
#include <Nazara/Platform/AppWindowingComponent.hpp>
|
||||
#if USE_JOLT
|
||||
#include <Nazara/JoltPhysics3D.hpp>
|
||||
#else
|
||||
#include <Nazara/BulletPhysics3D.hpp>
|
||||
#endif
|
||||
#include <Nazara/Renderer.hpp>
|
||||
#include <Nazara/Utility.hpp>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
|
||||
constexpr float BoxDims = 16.f;
|
||||
|
||||
int main()
|
||||
{
|
||||
// Mise en place de l'application, de la fenêtre et du monde
|
||||
Nz::Renderer::Config renderConfig;
|
||||
//renderConfig.preferredAPI = Nz::RenderAPI::OpenGL;
|
||||
|
||||
#if USE_JOLT
|
||||
Nz::Application<Nz::Graphics, Nz::JoltPhysics3D> app(renderConfig);
|
||||
#else
|
||||
Nz::Application<Nz::Graphics, Nz::BulletPhysics3D> app(renderConfig);
|
||||
#endif
|
||||
|
||||
auto& windowing = app.AddComponent<Nz::AppWindowingComponent>();
|
||||
Nz::Window& mainWindow = windowing.CreateWindow(Nz::VideoMode(1920, 1080), "Physics playground");
|
||||
|
||||
auto& fs = app.AddComponent<Nz::AppFilesystemComponent>();
|
||||
{
|
||||
std::filesystem::path resourceDir = "assets/examples";
|
||||
if (!std::filesystem::is_directory(resourceDir) && std::filesystem::is_directory("../.." / resourceDir))
|
||||
resourceDir = "../.." / resourceDir;
|
||||
|
||||
fs.Mount("assets", resourceDir);
|
||||
}
|
||||
|
||||
auto& ecs = app.AddComponent<Nz::AppEntitySystemComponent>();
|
||||
auto& world = ecs.AddWorld<Nz::EnttWorld>();
|
||||
|
||||
#if USE_JOLT
|
||||
auto& physSystem = world.AddSystem<Nz::JoltPhysics3DSystem>();
|
||||
#else
|
||||
auto& physSystem = world.AddSystem<Nz::BulletPhysics3DSystem>();
|
||||
#endif
|
||||
physSystem.GetPhysWorld().SetMaxStepCount(1);
|
||||
//physSystem.GetPhysWorld().SetGravity(Nz::Vector3f::Down() * 9.81f);
|
||||
physSystem.GetPhysWorld().SetGravity(Nz::Vector3f::Zero());
|
||||
|
||||
auto& renderSystem = world.AddSystem<Nz::RenderSystem>();
|
||||
Nz::WindowSwapchain& windowSwapchain = renderSystem.CreateSwapchain(mainWindow);
|
||||
|
||||
Nz::Vector3f target = Nz::Vector3f::Zero();
|
||||
|
||||
entt::handle boxEntity = world.CreateEntity();
|
||||
{
|
||||
std::shared_ptr<Nz::GraphicalMesh> boxMesh = Nz::GraphicalMesh::Build(Nz::Primitive::Box(Nz::Vector3f(BoxDims), Nz::Vector3ui::Zero(), Nz::Matrix4f::Scale(Nz::Vector3f(-1.f)), Nz::Rectf(0.f, 0.f, 2.f, 2.f)));
|
||||
|
||||
Nz::TextureSamplerInfo planeSampler;
|
||||
planeSampler.anisotropyLevel = 16;
|
||||
planeSampler.wrapModeU = Nz::SamplerWrap::Repeat;
|
||||
planeSampler.wrapModeV = Nz::SamplerWrap::Repeat;
|
||||
|
||||
std::shared_ptr<Nz::MaterialInstance> boxMat = Nz::Graphics::Instance()->GetDefaultMaterials().phongMaterial->Instantiate();
|
||||
boxMat->SetTextureProperty("BaseColorMap", fs.Load<Nz::Texture>("assets/dev_grey.png"), planeSampler);
|
||||
boxMat->DisablePass("ShadowPass");
|
||||
boxMat->UpdatePassesStates([&](Nz::RenderStates& states)
|
||||
{
|
||||
states.frontFace = Nz::FrontFace::Clockwise;
|
||||
});
|
||||
|
||||
std::shared_ptr<Nz::Model> boxModel = std::make_shared<Nz::Model>(std::move(boxMesh));
|
||||
boxModel->SetMaterial(0, std::move(boxMat));
|
||||
|
||||
auto& boxGfx = boxEntity.emplace<Nz::GraphicsComponent>();
|
||||
boxGfx.AttachRenderable(std::move(boxModel));
|
||||
|
||||
boxEntity.emplace<Nz::NodeComponent>();
|
||||
|
||||
#if USE_JOLT
|
||||
std::shared_ptr<Nz::JoltBoxCollider3D> wallCollider = std::make_shared<Nz::JoltBoxCollider3D>(Nz::Vector3f(BoxDims, BoxDims, 1.f));
|
||||
#else
|
||||
std::shared_ptr<Nz::BulletBoxCollider3D> wallCollider = std::make_shared<Nz::BulletBoxCollider3D>(Nz::Vector3f(BoxDims, BoxDims, 1.f));
|
||||
#endif
|
||||
|
||||
#if USE_JOLT
|
||||
std::vector<Nz::JoltCompoundCollider3D::ChildCollider> colliders;
|
||||
#else
|
||||
std::vector<Nz::BulletCompoundCollider3D::ChildCollider> colliders;
|
||||
#endif
|
||||
|
||||
for (Nz::Vector3f normal : { Nz::Vector3f::Forward(), Nz::Vector3f::Backward(), Nz::Vector3f::Left(), Nz::Vector3f::Right(), Nz::Vector3f::Up(), Nz::Vector3f::Down() })
|
||||
{
|
||||
auto& colliderEntry = colliders.emplace_back();
|
||||
colliderEntry.collider = wallCollider;
|
||||
#if USE_JOLT
|
||||
colliderEntry.rotation = Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), normal);
|
||||
colliderEntry.offset = normal * BoxDims * 0.5f + normal * 0.5f;
|
||||
#else
|
||||
colliderEntry.offsetMatrix = Nz::Matrix4f::Transform(normal * BoxDims * 0.5f + normal * 0.5f, Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), normal));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if USE_JOLT
|
||||
std::shared_ptr<Nz::JoltCompoundCollider3D> boxCollider = std::make_shared<Nz::JoltCompoundCollider3D>(std::move(colliders));
|
||||
#else
|
||||
std::shared_ptr<Nz::BulletCompoundCollider3D> boxCollider = std::make_shared<Nz::BulletCompoundCollider3D>(std::move(colliders));
|
||||
#endif
|
||||
|
||||
#if USE_JOLT
|
||||
auto& ballPhysics = boxEntity.emplace<Nz::JoltRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
|
||||
#else
|
||||
auto& ballPhysics = boxEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
|
||||
#endif
|
||||
ballPhysics.SetMass(0.f);
|
||||
|
||||
std::shared_ptr<Nz::Model> colliderModel;
|
||||
{
|
||||
std::shared_ptr<Nz::MaterialInstance> 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<Nz::Mesh> colliderMesh = Nz::Mesh::Build(boxCollider->GenerateDebugMesh());
|
||||
std::shared_ptr<Nz::GraphicalMesh> colliderGraphicalMesh = Nz::GraphicalMesh::BuildFromMesh(*colliderMesh);
|
||||
|
||||
colliderModel = std::make_shared<Nz::Model>(colliderGraphicalMesh);
|
||||
for (std::size_t i = 0; i < colliderModel->GetSubMeshCount(); ++i)
|
||||
colliderModel->SetMaterial(i, colliderMat);
|
||||
|
||||
boxGfx.AttachRenderable(std::move(colliderModel));*/
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Nz::GraphicalMesh> sphereMesh = Nz::GraphicalMesh::Build(Nz::Primitive::IcoSphere(1.f));
|
||||
|
||||
//std::mt19937 rd(std::random_device{}());
|
||||
std::mt19937 rd(42);
|
||||
std::uniform_real_distribution<float> colorDis(0.f, 360.f);
|
||||
std::uniform_real_distribution<float> radiusDis(0.05f, 0.5f);
|
||||
|
||||
constexpr std::size_t SphereCount = 3000;
|
||||
for (std::size_t i = 0; i < SphereCount; ++i)
|
||||
{
|
||||
float radius = radiusDis(rd);
|
||||
std::uniform_real_distribution<float> positionRandom(-BoxDims * 0.5f + radius, BoxDims * 0.5f - radius);
|
||||
|
||||
#if USE_JOLT
|
||||
std::shared_ptr<Nz::JoltSphereCollider3D> sphereCollider = std::make_shared<Nz::JoltSphereCollider3D>(radius);
|
||||
#else
|
||||
std::shared_ptr<Nz::BulletSphereCollider3D> sphereCollider = std::make_shared<Nz::BulletSphereCollider3D>(radius);
|
||||
#endif
|
||||
|
||||
entt::handle ballEntity = world.CreateEntity();
|
||||
|
||||
std::shared_ptr<Nz::MaterialInstance> ballMaterial = Nz::Graphics::Instance()->GetDefaultMaterials().phongMaterial->Instantiate();
|
||||
ballMaterial->SetValueProperty("BaseColor", Nz::Color::FromHSV(colorDis(rd), 1.f, 1.f));
|
||||
|
||||
std::shared_ptr<Nz::Model> sphereModel = std::make_shared<Nz::Model>(sphereMesh);
|
||||
sphereModel->SetMaterial(0, std::move(ballMaterial));
|
||||
|
||||
auto& ballGfx = ballEntity.emplace<Nz::GraphicsComponent>();
|
||||
ballGfx.AttachRenderable(std::move(sphereModel));
|
||||
|
||||
auto& ballNode = ballEntity.emplace<Nz::NodeComponent>();
|
||||
ballNode.SetPosition(positionRandom(rd), positionRandom(rd), positionRandom(rd));
|
||||
ballNode.SetScale(radius);
|
||||
|
||||
#if USE_JOLT
|
||||
auto& ballPhysics = ballEntity.emplace<Nz::JoltRigidBody3DComponent>(physSystem.CreateRigidBody(sphereCollider));
|
||||
#else
|
||||
auto& ballPhysics = ballEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(sphereCollider));
|
||||
#endif
|
||||
//ballPhysics.SetMass(4.f / 3.f * Nz::Pi<float> * Nz::IntegralPow(radius, 3));
|
||||
ballPhysics.DisableSleeping();
|
||||
}
|
||||
|
||||
std::uniform_real_distribution<float> lengthDis(0.1f, 1.f);
|
||||
std::shared_ptr<Nz::GraphicalMesh> boxMesh = Nz::GraphicalMesh::Build(Nz::Primitive::Box(Nz::Vector3f(1.f)));
|
||||
|
||||
constexpr std::size_t BoxCount = 100;
|
||||
for (std::size_t i = 0; i < BoxCount; ++i)
|
||||
{
|
||||
float width = lengthDis(rd);
|
||||
float height = lengthDis(rd);
|
||||
float depth = lengthDis(rd);
|
||||
|
||||
std::uniform_real_distribution<float> xRandom(-BoxDims * 0.5f + width, BoxDims * 0.5f - width);
|
||||
std::uniform_real_distribution<float> yRandom(-BoxDims * 0.5f + height, BoxDims * 0.5f - height);
|
||||
std::uniform_real_distribution<float> zRandom(-BoxDims * 0.5f + depth, BoxDims * 0.5f - depth);
|
||||
|
||||
entt::handle ballEntity = world.CreateEntity();
|
||||
|
||||
std::shared_ptr<Nz::MaterialInstance> boxMaterial = Nz::Graphics::Instance()->GetDefaultMaterials().phongMaterial->Instantiate();
|
||||
boxMaterial->SetValueProperty("BaseColor", Nz::Color::FromHSV(colorDis(rd), 1.f, 1.f));
|
||||
|
||||
std::shared_ptr<Nz::Model> sphereModel = std::make_shared<Nz::Model>(boxMesh);
|
||||
sphereModel->SetMaterial(0, std::move(boxMaterial));
|
||||
|
||||
auto& ballGfx = ballEntity.emplace<Nz::GraphicsComponent>();
|
||||
ballGfx.AttachRenderable(std::move(sphereModel));
|
||||
|
||||
auto& ballNode = ballEntity.emplace<Nz::NodeComponent>();
|
||||
ballNode.SetPosition(xRandom(rd), yRandom(rd), zRandom(rd));
|
||||
ballNode.SetScale(width, height, depth);
|
||||
|
||||
#if USE_JOLT
|
||||
std::shared_ptr<Nz::JoltBoxCollider3D> boxCollider = std::make_shared<Nz::JoltBoxCollider3D>(Nz::Vector3f(width, height, depth));
|
||||
#else
|
||||
std::shared_ptr<Nz::BulletBoxCollider3D> boxCollider = std::make_shared<Nz::BulletBoxCollider3D>(Nz::Vector3f(width, height, depth));
|
||||
#endif
|
||||
|
||||
#if USE_JOLT
|
||||
auto& ballPhysics = ballEntity.emplace<Nz::JoltRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
|
||||
#else
|
||||
auto& ballPhysics = ballEntity.emplace<Nz::BulletRigidBody3DComponent>(physSystem.CreateRigidBody(boxCollider));
|
||||
#endif
|
||||
//ballPhysics.SetMass(width * height * depth);
|
||||
ballPhysics.DisableSleeping();
|
||||
}
|
||||
|
||||
// Lumière
|
||||
entt::handle lightEntity = world.CreateEntity();
|
||||
{
|
||||
auto& lightNode = lightEntity.emplace<Nz::NodeComponent>();
|
||||
//lightNode.SetPosition(Nz::Vector3f(-20.f, 20.f, -20.f));
|
||||
//lightNode.SetRotation(Nz::EulerAnglesf(-45.f, -135.f, 0.f));
|
||||
lightNode.SetPosition(Nz::Vector3f::Up() * 15.f);
|
||||
lightNode.SetRotation(Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), Nz::Vector3f::Down()));
|
||||
|
||||
auto& lightComp = lightEntity.emplace<Nz::LightComponent>();
|
||||
auto& spotLight = lightComp.AddLight<Nz::SpotLight>();
|
||||
spotLight.EnableShadowCasting(true);
|
||||
spotLight.UpdateInnerAngle(Nz::DegreeAnglef(30.f));
|
||||
spotLight.UpdateOuterAngle(Nz::DegreeAnglef(40.f));
|
||||
spotLight.UpdateRadius(30.f);
|
||||
spotLight.UpdateShadowMapSize(2048);
|
||||
spotLight.UpdateAmbientFactor(0.5f);
|
||||
}
|
||||
|
||||
Nz::EulerAnglesf camAngles(-45.f, -135.f, 0.f);
|
||||
float camDistance = 12.f;
|
||||
|
||||
// Création de la caméra
|
||||
entt::handle cameraEntity = world.CreateEntity();
|
||||
{
|
||||
cameraEntity.emplace<Nz::NodeComponent>();
|
||||
|
||||
auto& cameraComponent = cameraEntity.emplace<Nz::CameraComponent>(&windowSwapchain, Nz::ProjectionType::Perspective);
|
||||
cameraComponent.UpdateFOV(70.f);
|
||||
cameraComponent.UpdateClearColor(Nz::Color(0.46f, 0.48f, 0.84f, 1.f));
|
||||
}
|
||||
|
||||
auto UpdateCamera = [&]
|
||||
{
|
||||
auto& cameraNode = cameraEntity.get<Nz::NodeComponent>();
|
||||
cameraNode.SetRotation(camAngles);
|
||||
cameraNode.SetPosition(target - cameraNode.GetForward() * camDistance);
|
||||
};
|
||||
UpdateCamera();
|
||||
|
||||
NazaraSlot(Nz::WindowEventHandler, OnMouseMoved, cameraMove);
|
||||
NazaraSlot(Nz::WindowEventHandler, OnMouseMoved, grabbedObjectMove);
|
||||
//std::optional<Nz::JoltPivotConstraint3D> grabConstraint;
|
||||
|
||||
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();
|
||||
});
|
||||
}
|
||||
else if (event.button == Nz::Mouse::Left)
|
||||
{
|
||||
auto& cameraNode = cameraEntity.get<Nz::NodeComponent>();
|
||||
auto& cameraComponent = cameraEntity.get<Nz::CameraComponent>();
|
||||
|
||||
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))
|
||||
{
|
||||
if (hitInfo.hitBody)
|
||||
{
|
||||
grabConstraint.emplace(*hitInfo.hitBody, hitInfo.hitPosition);
|
||||
|
||||
grabbedObjectMove.Connect(eventHandler.OnMouseMoved, [&, body = hitInfo.hitBody, distance = Nz::Vector3f::Distance(from, hitInfo.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 });
|
||||
|
||||
Nz::Vector3f newPosition = from + (to - from).Normalize() * distance;
|
||||
grabConstraint->SetSecondAnchor(newPosition);
|
||||
});
|
||||
}
|
||||
}*/
|
||||
}
|
||||
});
|
||||
|
||||
eventHandler.OnMouseButtonReleased.Connect([&](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseButtonEvent& event)
|
||||
{
|
||||
if (event.button == Nz::Mouse::Left)
|
||||
{
|
||||
//grabConstraint.reset();
|
||||
grabbedObjectMove.Disconnect();
|
||||
}
|
||||
else if (event.button == Nz::Mouse::Middle)
|
||||
cameraMove.Disconnect();
|
||||
});
|
||||
|
||||
eventHandler.OnMouseWheelMoved.Connect([&](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseWheelEvent& event)
|
||||
{
|
||||
camDistance = Nz::Clamp(camDistance - event.delta, 5.f, 20.f);
|
||||
UpdateCamera();
|
||||
});
|
||||
|
||||
eventHandler.OnKeyReleased.Connect([&](const Nz::WindowEventHandler*, const Nz::WindowEvent::KeyEvent& event)
|
||||
{
|
||||
if (event.virtualKey == Nz::Keyboard::VKey::G)
|
||||
{
|
||||
auto& cameraNode = cameraEntity.get<Nz::NodeComponent>();
|
||||
|
||||
physSystem.GetPhysWorld().SetGravity(cameraNode.GetBackward() * 9.81f);
|
||||
}
|
||||
});
|
||||
|
||||
Nz::MillisecondClock fpsClock;
|
||||
unsigned int fps = 0;
|
||||
app.AddUpdater([&](Nz::Time /*elapsedTime*/)
|
||||
{
|
||||
fps++;
|
||||
if (fpsClock.RestartIfOver(Nz::Time::Second()))
|
||||
{
|
||||
mainWindow.SetTitle("Physics playground - " + Nz::NumberToString(fps) + " FPS" + " - " + Nz::NumberToString(world.GetRegistry().alive()) + " entities");
|
||||
physSystem.Dump();
|
||||
fps = 0;
|
||||
}
|
||||
});
|
||||
|
||||
return app.Run();
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
target("PhysicsPlayground")
|
||||
add_deps("NazaraGraphics", "NazaraBulletPhysics3D", "NazaraJoltPhysics3D")
|
||||
add_packages("entt")
|
||||
add_files("main.cpp")
|
||||
add_defines("NAZARA_ENTT")
|
||||
|
|
@ -26,16 +26,16 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_GLOBAL_PHYSICS3D_HPP
|
||||
#define NAZARA_GLOBAL_PHYSICS3D_HPP
|
||||
#ifndef NAZARA_GLOBAL_BULLETPHYSICS3D_HPP
|
||||
#define NAZARA_GLOBAL_BULLETPHYSICS3D_HPP
|
||||
|
||||
#include <Nazara/BulletPhysics3D/BulletCollider3D.hpp>
|
||||
#include <Nazara/BulletPhysics3D/Config.hpp>
|
||||
#include <Nazara/BulletPhysics3D/BulletConstraint3D.hpp>
|
||||
#include <Nazara/BulletPhysics3D/Enums.hpp>
|
||||
#include <Nazara/BulletPhysics3D/BulletPhysics3D.hpp>
|
||||
#include <Nazara/BulletPhysics3D/BulletPhysWorld3D.hpp>
|
||||
#include <Nazara/BulletPhysics3D/BulletRigidBody3D.hpp>
|
||||
#include <Nazara/BulletPhysics3D/Config.hpp>
|
||||
#include <Nazara/BulletPhysics3D/Enums.hpp>
|
||||
|
||||
#ifdef NAZARA_ENTT
|
||||
|
||||
|
|
@ -44,4 +44,4 @@
|
|||
|
||||
#endif
|
||||
|
||||
#endif // NAZARA_GLOBAL_PHYSICS3D_HPP
|
||||
#endif // NAZARA_GLOBAL_BULLETPHYSICS3D_HPP
|
||||
|
|
|
|||
|
|
@ -62,11 +62,11 @@ namespace Nz
|
|||
static std::shared_ptr<BulletCollider3D> CreateGeomFromPrimitive(const Primitive& primitive);
|
||||
};
|
||||
|
||||
class NAZARA_BULLETPHYSICS3D_API BoxCollider3D final : public BulletCollider3D
|
||||
class NAZARA_BULLETPHYSICS3D_API BulletBoxCollider3D final : public BulletCollider3D
|
||||
{
|
||||
public:
|
||||
BoxCollider3D(const Vector3f& lengths);
|
||||
~BoxCollider3D();
|
||||
BulletBoxCollider3D(const Vector3f& lengths);
|
||||
~BulletBoxCollider3D();
|
||||
|
||||
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
|
||||
|
||||
|
|
@ -79,11 +79,11 @@ namespace Nz
|
|||
Vector3f m_lengths;
|
||||
};
|
||||
|
||||
class NAZARA_BULLETPHYSICS3D_API CapsuleCollider3D final : public BulletCollider3D
|
||||
class NAZARA_BULLETPHYSICS3D_API BulletCapsuleCollider3D final : public BulletCollider3D
|
||||
{
|
||||
public:
|
||||
CapsuleCollider3D(float length, float radius);
|
||||
~CapsuleCollider3D();
|
||||
BulletCapsuleCollider3D(float length, float radius);
|
||||
~BulletCapsuleCollider3D();
|
||||
|
||||
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
|
||||
|
||||
|
|
@ -98,13 +98,13 @@ namespace Nz
|
|||
float m_radius;
|
||||
};
|
||||
|
||||
class NAZARA_BULLETPHYSICS3D_API CompoundCollider3D final : public BulletCollider3D
|
||||
class NAZARA_BULLETPHYSICS3D_API BulletCompoundCollider3D final : public BulletCollider3D
|
||||
{
|
||||
public:
|
||||
struct ChildCollider;
|
||||
|
||||
CompoundCollider3D(std::vector<ChildCollider> childs);
|
||||
~CompoundCollider3D();
|
||||
BulletCompoundCollider3D(std::vector<ChildCollider> childs);
|
||||
~BulletCompoundCollider3D();
|
||||
|
||||
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
|
||||
|
||||
|
|
@ -123,11 +123,11 @@ namespace Nz
|
|||
std::vector<ChildCollider> m_childs;
|
||||
};
|
||||
|
||||
class NAZARA_BULLETPHYSICS3D_API ConeCollider3D final : public BulletCollider3D
|
||||
class NAZARA_BULLETPHYSICS3D_API BulletConeCollider3D final : public BulletCollider3D
|
||||
{
|
||||
public:
|
||||
ConeCollider3D(float length, float radius);
|
||||
~ConeCollider3D();
|
||||
BulletConeCollider3D(float length, float radius);
|
||||
~BulletConeCollider3D();
|
||||
|
||||
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
|
||||
|
||||
|
|
@ -142,11 +142,11 @@ namespace Nz
|
|||
float m_radius;
|
||||
};
|
||||
|
||||
class NAZARA_BULLETPHYSICS3D_API ConvexCollider3D final : public BulletCollider3D
|
||||
class NAZARA_BULLETPHYSICS3D_API BulletConvexCollider3D final : public BulletCollider3D
|
||||
{
|
||||
public:
|
||||
ConvexCollider3D(SparsePtr<const Vector3f> vertices, unsigned int vertexCount);
|
||||
~ConvexCollider3D();
|
||||
BulletConvexCollider3D(SparsePtr<const Vector3f> vertices, unsigned int vertexCount);
|
||||
~BulletConvexCollider3D();
|
||||
|
||||
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
|
||||
|
||||
|
|
@ -157,11 +157,11 @@ namespace Nz
|
|||
std::unique_ptr<btConvexHullShape> m_shape;
|
||||
};
|
||||
|
||||
class NAZARA_BULLETPHYSICS3D_API CylinderCollider3D final : public BulletCollider3D
|
||||
class NAZARA_BULLETPHYSICS3D_API BulletCylinderCollider3D final : public BulletCollider3D
|
||||
{
|
||||
public:
|
||||
CylinderCollider3D(float length, float radius);
|
||||
~CylinderCollider3D();
|
||||
BulletCylinderCollider3D(float length, float radius);
|
||||
~BulletCylinderCollider3D();
|
||||
|
||||
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
|
||||
|
||||
|
|
@ -177,11 +177,11 @@ namespace Nz
|
|||
float m_radius;
|
||||
};
|
||||
|
||||
class NAZARA_BULLETPHYSICS3D_API NullCollider3D final : public BulletCollider3D
|
||||
class NAZARA_BULLETPHYSICS3D_API BulletNullCollider3D final : public BulletCollider3D
|
||||
{
|
||||
public:
|
||||
NullCollider3D();
|
||||
~NullCollider3D();
|
||||
BulletNullCollider3D();
|
||||
~BulletNullCollider3D();
|
||||
|
||||
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
|
||||
|
||||
|
|
@ -194,11 +194,11 @@ namespace Nz
|
|||
std::unique_ptr<btEmptyShape> m_shape;
|
||||
};
|
||||
|
||||
class NAZARA_BULLETPHYSICS3D_API SphereCollider3D final : public BulletCollider3D
|
||||
class NAZARA_BULLETPHYSICS3D_API BulletSphereCollider3D final : public BulletCollider3D
|
||||
{
|
||||
public:
|
||||
SphereCollider3D(float radius);
|
||||
~SphereCollider3D();
|
||||
BulletSphereCollider3D(float radius);
|
||||
~BulletSphereCollider3D();
|
||||
|
||||
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ namespace Nz
|
|||
void SetMass(float mass);
|
||||
void SetMassCenter(const Vector3f& center);
|
||||
void SetPosition(const Vector3f& position);
|
||||
void SetPositionAndRotation(const Vector3f& position, const Quaternionf& rotation);
|
||||
void SetRotation(const Quaternionf& rotation);
|
||||
|
||||
Quaternionf ToLocal(const Quaternionf& worldRotation);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#define NAZARA_BULLETPHYSICS3D_SYSTEMS_BULLETPHYSICS3DSYSTEM_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Clock.hpp>
|
||||
#include <Nazara/BulletPhysics3D/BulletPhysWorld3D.hpp>
|
||||
#include <Nazara/BulletPhysics3D/Components/BulletRigidBody3DComponent.hpp>
|
||||
#include <Nazara/Core/Time.hpp>
|
||||
|
|
@ -32,6 +33,8 @@ namespace Nz
|
|||
|
||||
template<typename... Args> BulletRigidBody3DComponent CreateRigidBody(Args&&... args);
|
||||
|
||||
void Dump();
|
||||
|
||||
inline BulletPhysWorld3D& GetPhysWorld();
|
||||
inline const BulletPhysWorld3D& GetPhysWorld() const;
|
||||
|
||||
|
|
@ -51,12 +54,15 @@ namespace Nz
|
|||
void OnConstruct(entt::registry& registry, entt::entity entity);
|
||||
void OnDestruct(entt::registry& registry, entt::entity entity);
|
||||
|
||||
std::size_t m_stepCount;
|
||||
std::vector<entt::entity> m_physicsEntities;
|
||||
entt::registry& m_registry;
|
||||
entt::observer m_physicsConstructObserver;
|
||||
entt::scoped_connection m_constructConnection;
|
||||
entt::scoped_connection m_destructConnection;
|
||||
BulletPhysWorld3D m_physWorld;
|
||||
Time m_physicsTime;
|
||||
Time m_updateTime;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
// this file was automatically generated and should not be edited
|
||||
|
||||
/*
|
||||
Nazara Engine - BulletPhysics3D module
|
||||
|
||||
Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_GLOBAL_JOLTPHYSICS3D_HPP
|
||||
#define NAZARA_GLOBAL_JOLTPHYSICS3D_HPP
|
||||
|
||||
#include <Nazara/JoltPhysics3D/Config.hpp>
|
||||
#include <Nazara/JoltPhysics3D/Enums.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltCollider3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltConstraint3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltPhysics3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltRigidBody3D.hpp>
|
||||
|
||||
#ifdef NAZARA_ENTT
|
||||
|
||||
#include <Nazara/JoltPhysics3D/Components.hpp>
|
||||
#include <Nazara/JoltPhysics3D/Systems.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
#endif // NAZARA_GLOBAL_JOLTPHYSICS3D_HPP
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// this file was automatically generated and should not be edited
|
||||
|
||||
/*
|
||||
Nazara Engine - BulletPhysics3D module
|
||||
|
||||
Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_JOLTPHYSICS3D_COMPONENTS_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_COMPONENTS_HPP
|
||||
|
||||
#include <Nazara/JoltPhysics3D/Components/JoltRigidBody3DComponent.hpp>
|
||||
|
||||
#endif // NAZARA_JOLTPHYSICS3D_COMPONENTS_HPP
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// 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_COMPONENTS_JOLTRIGIDBODY3DCOMPONENT_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_COMPONENTS_JOLTRIGIDBODY3DCOMPONENT_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltRigidBody3D.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltRigidBody3DComponent : public JoltRigidBody3D
|
||||
{
|
||||
friend class JoltPhysics3DSystem;
|
||||
|
||||
public:
|
||||
using JoltRigidBody3D::JoltRigidBody3D;
|
||||
JoltRigidBody3DComponent(const JoltRigidBody3DComponent&) = default;
|
||||
JoltRigidBody3DComponent(JoltRigidBody3DComponent&&) noexcept = default;
|
||||
~JoltRigidBody3DComponent() = default;
|
||||
|
||||
JoltRigidBody3DComponent& operator=(const JoltRigidBody3DComponent&) = default;
|
||||
JoltRigidBody3DComponent& operator=(JoltRigidBody3DComponent&&) noexcept = default;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/JoltPhysics3D/Components/JoltRigidBody3DComponent.inl>
|
||||
|
||||
#endif // NAZARA_JOLTPHYSICS3D_COMPONENTS_JOLTRIGIDBODY3DCOMPONENT_HPP
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// 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 <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
#include <Nazara/JoltPhysics3D/DebugOff.hpp>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
Nazara Engine - BulletPhysics3D module
|
||||
|
||||
Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_JOLTPHYSICS3D_CONFIG_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_CONFIG_HPP
|
||||
|
||||
/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci
|
||||
|
||||
// Active les tests de sécurité basés sur le code (Conseillé pour le développement)
|
||||
#define NAZARA_JOLTPHYSICS3D_SAFE 1
|
||||
|
||||
/// Vérification des valeurs et types de certaines constantes
|
||||
#include <Nazara/JoltPhysics3D/ConfigCheck.hpp>
|
||||
|
||||
#if defined(NAZARA_STATIC)
|
||||
#define NAZARA_JOLTPHYSICS3D_API
|
||||
#else
|
||||
#ifdef NAZARA_JOLTPHYSICS3D_BUILD
|
||||
#define NAZARA_JOLTPHYSICS3D_API NAZARA_EXPORT
|
||||
#else
|
||||
#define NAZARA_JOLTPHYSICS3D_API NAZARA_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // NAZARA_JOLTPHYSICS3D_CONFIG_HPP
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// 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_CONFIGCHECK_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_CONFIGCHECK_HPP
|
||||
|
||||
#endif // NAZARA_JOLTPHYSICS3D_CONFIGCHECK_HPP
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
// 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
|
||||
|
||||
// no header guards
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
// 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
|
||||
|
||||
// no header guards
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// 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_ENUMS_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_ENUMS_HPP
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
enum class JoltColliderType3D
|
||||
{
|
||||
Box,
|
||||
Compound,
|
||||
Sphere,
|
||||
|
||||
Max = Sphere
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_JOLTPHYSICS3D_ENUMS_HPP
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
// 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_JOLTCOLLIDER3D_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_JOLTCOLLIDER3D_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/ObjectLibrary.hpp>
|
||||
#include <Nazara/JoltPhysics3D/Config.hpp>
|
||||
#include <Nazara/JoltPhysics3D/Enums.hpp>
|
||||
#include <Nazara/Math/Box.hpp>
|
||||
#include <Nazara/Math/Quaternion.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
#include <Nazara/Utils/Signal.hpp>
|
||||
#include <Nazara/Utils/SparsePtr.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace JPH
|
||||
{
|
||||
class ShapeSettings;
|
||||
class BoxShapeSettings;
|
||||
class CompoundShapeSettings;
|
||||
class SphereShapeSettings;
|
||||
}
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class PrimitiveList;
|
||||
class StaticMesh;
|
||||
struct Primitive;
|
||||
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltCollider3D
|
||||
{
|
||||
public:
|
||||
JoltCollider3D() = default;
|
||||
JoltCollider3D(const JoltCollider3D&) = delete;
|
||||
JoltCollider3D(JoltCollider3D&&) = delete;
|
||||
virtual ~JoltCollider3D();
|
||||
|
||||
virtual void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix = Matrix4f::Identity()) const = 0;
|
||||
|
||||
virtual std::shared_ptr<StaticMesh> GenerateDebugMesh() const;
|
||||
|
||||
virtual JPH::ShapeSettings* GetShapeSettings() const = 0;
|
||||
virtual JoltColliderType3D GetType() const = 0;
|
||||
|
||||
JoltCollider3D& operator=(const JoltCollider3D&) = delete;
|
||||
JoltCollider3D& operator=(JoltCollider3D&&) = delete;
|
||||
|
||||
static std::shared_ptr<JoltCollider3D> Build(const PrimitiveList& list);
|
||||
|
||||
private:
|
||||
static std::shared_ptr<JoltCollider3D> CreateGeomFromPrimitive(const Primitive& primitive);
|
||||
};
|
||||
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltBoxCollider3D final : public JoltCollider3D
|
||||
{
|
||||
public:
|
||||
JoltBoxCollider3D(const Vector3f& lengths, float convexRadius = 0.f);
|
||||
~JoltBoxCollider3D();
|
||||
|
||||
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
|
||||
|
||||
Vector3f GetLengths() const;
|
||||
JPH::ShapeSettings* GetShapeSettings() const override;
|
||||
JoltColliderType3D GetType() const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<JPH::BoxShapeSettings> m_shapeSettings;
|
||||
Vector3f m_lengths;
|
||||
};
|
||||
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltCompoundCollider3D final : public JoltCollider3D
|
||||
{
|
||||
public:
|
||||
struct ChildCollider;
|
||||
|
||||
JoltCompoundCollider3D(std::vector<ChildCollider> childs);
|
||||
~JoltCompoundCollider3D();
|
||||
|
||||
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
|
||||
|
||||
const std::vector<ChildCollider>& GetGeoms() const;
|
||||
JPH::ShapeSettings* GetShapeSettings() const override;
|
||||
JoltColliderType3D GetType() const override;
|
||||
|
||||
struct ChildCollider
|
||||
{
|
||||
std::shared_ptr<JoltCollider3D> collider;
|
||||
Quaternionf rotation = Quaternionf::Identity();
|
||||
Vector3f offset = Vector3f::Zero();
|
||||
};
|
||||
|
||||
private:
|
||||
std::unique_ptr<JPH::CompoundShapeSettings> m_shapeSettings;
|
||||
std::vector<ChildCollider> m_childs;
|
||||
};
|
||||
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltSphereCollider3D final : public JoltCollider3D
|
||||
{
|
||||
public:
|
||||
JoltSphereCollider3D(float radius);
|
||||
~JoltSphereCollider3D();
|
||||
|
||||
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
|
||||
|
||||
float GetRadius() const;
|
||||
JPH::ShapeSettings* GetShapeSettings() const override;
|
||||
JoltColliderType3D GetType() const override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<JPH::SphereShapeSettings> m_shapeSettings;
|
||||
Vector3f m_position;
|
||||
float m_radius;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/JoltPhysics3D/JoltCollider3D.inl>
|
||||
|
||||
#endif // NAZARA_JOLTPHYSICS3D_JOLTCOLLIDER3D_HPP
|
||||
|
|
@ -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 <memory>
|
||||
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
#include <Nazara/JoltPhysics3D/DebugOff.hpp>
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
// 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
|
||||
#if 0
|
||||
#ifndef NAZARA_JOLTPHYSICS3D_JOLTCONSTRAINT3D_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_JOLTCONSTRAINT3D_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/BulletPhysics3D/BulletPhysWorld3D.hpp>
|
||||
#include <Nazara/BulletPhysics3D/BulletRigidBody3D.hpp>
|
||||
#include <Nazara/BulletPhysics3D/Config.hpp>
|
||||
#include <Nazara/Core/HandledObject.hpp>
|
||||
#include <Nazara/Core/ObjectHandle.hpp>
|
||||
|
||||
class btTypedConstraint;
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class BulletConstraint3D;
|
||||
|
||||
using BulletConstraint3DHandle = ObjectHandle<BulletConstraint3D>;
|
||||
|
||||
class NAZARA_BULLETPHYSICS3D_API BulletConstraint3D : public HandledObject<BulletConstraint3D>
|
||||
{
|
||||
public:
|
||||
BulletConstraint3D(const BulletConstraint3D&) = delete;
|
||||
BulletConstraint3D(BulletConstraint3D&& constraint) noexcept;
|
||||
virtual ~BulletConstraint3D();
|
||||
|
||||
BulletRigidBody3D& GetBodyA();
|
||||
const BulletRigidBody3D& GetBodyA() const;
|
||||
BulletRigidBody3D& GetBodyB();
|
||||
const BulletRigidBody3D& GetBodyB() const;
|
||||
BulletPhysWorld3D& GetWorld();
|
||||
const BulletPhysWorld3D& GetWorld() const;
|
||||
|
||||
inline bool IsBodyCollisionEnabled() const;
|
||||
bool IsSingleBody() const;
|
||||
|
||||
BulletConstraint3D& operator=(const BulletConstraint3D&) = delete;
|
||||
BulletConstraint3D& operator=(BulletConstraint3D&& constraint) noexcept;
|
||||
|
||||
protected:
|
||||
BulletConstraint3D(std::unique_ptr<btTypedConstraint> constraint, bool disableCollisions = false);
|
||||
|
||||
template<typename T> T* GetConstraint();
|
||||
template<typename T> const T* GetConstraint() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<btTypedConstraint> m_constraint;
|
||||
bool m_bodyCollisionEnabled;
|
||||
};
|
||||
|
||||
class NAZARA_BULLETPHYSICS3D_API BulletPivotConstraint3D : public BulletConstraint3D
|
||||
{
|
||||
public:
|
||||
BulletPivotConstraint3D(BulletRigidBody3D& first, const Vector3f& pivot);
|
||||
BulletPivotConstraint3D(BulletRigidBody3D& first, BulletRigidBody3D& second, const Vector3f& pivot, bool disableCollisions = false);
|
||||
BulletPivotConstraint3D(BulletRigidBody3D& first, BulletRigidBody3D& second, const Vector3f& firstAnchor, const Vector3f& secondAnchor, bool disableCollisions = false);
|
||||
~BulletPivotConstraint3D() = default;
|
||||
|
||||
Vector3f GetFirstAnchor() const;
|
||||
Vector3f GetSecondAnchor() const;
|
||||
|
||||
void SetFirstAnchor(const Vector3f& firstAnchor);
|
||||
void SetSecondAnchor(const Vector3f& secondAnchor);
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/BulletPhysics3D/BulletConstraint3D.inl>
|
||||
|
||||
#endif // NAZARA_BULLETPHYSICS3D_BULLETCONSTRAINT3D_HPP
|
||||
#endif // NAZARA_JOLTPHYSICS3D_JOLTCONSTRAINT3D_HPP
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// 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 <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline bool BulletConstraint3D::IsBodyCollisionEnabled() const
|
||||
{
|
||||
return m_bodyCollisionEnabled;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* BulletConstraint3D::GetConstraint()
|
||||
{
|
||||
return SafeCast<T*>(m_constraint.get());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T* BulletConstraint3D::GetConstraint() const
|
||||
{
|
||||
return SafeCast<const T*>(m_constraint.get());
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/JoltPhysics3D/DebugOff.hpp>
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
// 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_JOLTPHYSWORLD3D_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_JOLTPHYSWORLD3D_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/JoltPhysics3D/Config.hpp>
|
||||
#include <Nazara/Core/Time.hpp>
|
||||
#include <Nazara/Math/Box.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
#include <Nazara/Utils/FunctionRef.hpp>
|
||||
#include <Nazara/Utils/MovablePtr.hpp>
|
||||
|
||||
namespace JPH
|
||||
{
|
||||
class PhysicsSystem;
|
||||
}
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class JoltRigidBody3D;
|
||||
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltPhysWorld3D
|
||||
{
|
||||
public:
|
||||
struct RaycastHit;
|
||||
|
||||
JoltPhysWorld3D();
|
||||
JoltPhysWorld3D(const JoltPhysWorld3D&) = delete;
|
||||
JoltPhysWorld3D(JoltPhysWorld3D&& ph) = delete;
|
||||
~JoltPhysWorld3D();
|
||||
|
||||
Vector3f GetGravity() const;
|
||||
std::size_t GetMaxStepCount() const;
|
||||
JPH::PhysicsSystem* GetPhysicsSystem();
|
||||
Time GetStepSize() const;
|
||||
|
||||
bool RaycastQueryFirst(const Vector3f& from, const Vector3f& to, RaycastHit* hitInfo = nullptr);
|
||||
|
||||
void SetGravity(const Vector3f& gravity);
|
||||
void SetMaxStepCount(std::size_t maxStepCount);
|
||||
void SetStepSize(Time stepSize);
|
||||
|
||||
void Step(Time timestep);
|
||||
|
||||
JoltPhysWorld3D& operator=(const JoltPhysWorld3D&) = delete;
|
||||
JoltPhysWorld3D& operator=(JoltPhysWorld3D&&) = delete;
|
||||
|
||||
struct RaycastHit
|
||||
{
|
||||
float fraction;
|
||||
JoltRigidBody3D* hitBody = nullptr;
|
||||
Vector3f hitPosition;
|
||||
Vector3f hitNormal;
|
||||
};
|
||||
|
||||
private:
|
||||
struct JoltWorld;
|
||||
|
||||
std::size_t m_maxStepCount;
|
||||
std::unique_ptr<JoltWorld> m_world;
|
||||
Vector3f m_gravity;
|
||||
Time m_stepSize;
|
||||
Time m_timestepAccumulator;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_JOLTPHYSICS3D_JOLTPHYSWORLD3D_HPP
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
// 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_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/JoltPhysics3D/Config.hpp>
|
||||
#include <Nazara/Core/Core.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace JPH
|
||||
{
|
||||
class JobSystem;
|
||||
class JobSystemThreadPool;
|
||||
}
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltPhysics3D : public ModuleBase<JoltPhysics3D>
|
||||
{
|
||||
friend ModuleBase;
|
||||
|
||||
public:
|
||||
using Dependencies = TypeList<Core>;
|
||||
|
||||
struct Config {};
|
||||
|
||||
JoltPhysics3D(Config /*config*/);
|
||||
~JoltPhysics3D();
|
||||
|
||||
JPH::JobSystem& GetThreadPool();
|
||||
|
||||
private:
|
||||
std::unique_ptr<JPH::JobSystemThreadPool> m_threadPool;
|
||||
|
||||
static JoltPhysics3D* s_instance;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_JOLTPHYSICS3D_HPP
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
// 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_JOLTRIGIDBODY3D_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_JOLTRIGIDBODY3D_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltCollider3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/Config.hpp>
|
||||
#include <Nazara/Core/Enums.hpp>
|
||||
#include <Nazara/Math/Matrix4.hpp>
|
||||
#include <Nazara/Math/Quaternion.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
#include <Nazara/Utils/MovablePtr.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class JoltPhysWorld3D;
|
||||
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltRigidBody3D
|
||||
{
|
||||
public:
|
||||
JoltRigidBody3D(JoltPhysWorld3D* world, const Matrix4f& mat = Matrix4f::Identity());
|
||||
JoltRigidBody3D(JoltPhysWorld3D* world, std::shared_ptr<JoltCollider3D> geom, const Matrix4f& mat = Matrix4f::Identity());
|
||||
JoltRigidBody3D(const JoltRigidBody3D& object) = delete;
|
||||
JoltRigidBody3D(JoltRigidBody3D&& object) noexcept;
|
||||
~JoltRigidBody3D();
|
||||
|
||||
void AddForce(const Vector3f& force, CoordSys coordSys = CoordSys::Global);
|
||||
void AddForce(const Vector3f& force, const Vector3f& point, CoordSys coordSys = CoordSys::Global);
|
||||
void AddTorque(const Vector3f& torque, CoordSys coordSys = CoordSys::Global);
|
||||
|
||||
inline void DisableSleeping();
|
||||
void EnableSleeping(bool enable);
|
||||
|
||||
void FallAsleep();
|
||||
|
||||
Boxf GetAABB() const;
|
||||
float GetAngularDamping() const;
|
||||
Vector3f GetAngularVelocity() const;
|
||||
inline const std::shared_ptr<JoltCollider3D>& GetGeom() const;
|
||||
float GetLinearDamping() const;
|
||||
Vector3f GetLinearVelocity() const;
|
||||
float GetMass() const;
|
||||
Vector3f GetMassCenter(CoordSys coordSys = CoordSys::Local) const;
|
||||
Matrix4f GetMatrix() const;
|
||||
Vector3f GetPosition() const;
|
||||
Quaternionf GetRotation() const;
|
||||
inline JoltPhysWorld3D* GetWorld() const;
|
||||
|
||||
bool IsSimulationEnabled() const;
|
||||
bool IsSleeping() const;
|
||||
bool IsSleepingEnabled() const;
|
||||
|
||||
void SetAngularDamping(float angularDamping);
|
||||
void SetAngularVelocity(const Vector3f& angularVelocity);
|
||||
void SetGeom(std::shared_ptr<JoltCollider3D> geom, bool recomputeInertia = true);
|
||||
void SetLinearDamping(float damping);
|
||||
void SetLinearVelocity(const Vector3f& velocity);
|
||||
void SetMass(float mass);
|
||||
void SetMassCenter(const Vector3f& center);
|
||||
void SetPosition(const Vector3f& position);
|
||||
void SetRotation(const Quaternionf& rotation);
|
||||
|
||||
Quaternionf ToLocal(const Quaternionf& worldRotation);
|
||||
Vector3f ToLocal(const Vector3f& worldPosition);
|
||||
Quaternionf ToWorld(const Quaternionf& localRotation);
|
||||
Vector3f ToWorld(const Vector3f& localPosition);
|
||||
|
||||
void WakeUp();
|
||||
|
||||
JoltRigidBody3D& operator=(const JoltRigidBody3D& object) = delete;
|
||||
JoltRigidBody3D& operator=(JoltRigidBody3D&& object) noexcept;
|
||||
|
||||
protected:
|
||||
void Destroy();
|
||||
|
||||
private:
|
||||
std::shared_ptr<JoltCollider3D> m_geom;
|
||||
JoltPhysWorld3D* m_world;
|
||||
UInt32 m_bodyIndex;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/JoltPhysics3D/JoltRigidBody3D.inl>
|
||||
|
||||
#endif // NAZARA_JOLTPHYSICS3D_JOLTRIGIDBODY3D_HPP
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// 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 <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline void JoltRigidBody3D::DisableSleeping()
|
||||
{
|
||||
return EnableSleeping(false);
|
||||
}
|
||||
|
||||
inline const std::shared_ptr<JoltCollider3D>& JoltRigidBody3D::GetGeom() const
|
||||
{
|
||||
return m_geom;
|
||||
}
|
||||
|
||||
inline JoltPhysWorld3D* JoltRigidBody3D::GetWorld() const
|
||||
{
|
||||
return m_world;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/JoltPhysics3D/DebugOff.hpp>
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
// this file was automatically generated and should not be edited
|
||||
|
||||
/*
|
||||
Nazara Engine - BulletPhysics3D module
|
||||
|
||||
Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_JOLTPHYSICS3D_SYSTEMS_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_SYSTEMS_HPP
|
||||
|
||||
#include <Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.hpp>
|
||||
|
||||
#endif // NAZARA_JOLTPHYSICS3D_SYSTEMS_HPP
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
// 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_SYSTEMS_JOLTPHYSICS3DSYSTEM_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_SYSTEMS_JOLTPHYSICS3DSYSTEM_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Core/Clock.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/Components/JoltRigidBody3DComponent.hpp>
|
||||
#include <Nazara/Core/Time.hpp>
|
||||
#include <Nazara/Utils/TypeList.hpp>
|
||||
#include <entt/entt.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class NAZARA_JOLTPHYSICS3D_API JoltPhysics3DSystem
|
||||
{
|
||||
public:
|
||||
static constexpr Int64 ExecutionOrder = 0;
|
||||
using Components = TypeList<JoltRigidBody3DComponent, class NodeComponent>;
|
||||
|
||||
struct RaycastHit;
|
||||
|
||||
JoltPhysics3DSystem(entt::registry& registry);
|
||||
JoltPhysics3DSystem(const JoltPhysics3DSystem&) = delete;
|
||||
JoltPhysics3DSystem(JoltPhysics3DSystem&&) = delete;
|
||||
~JoltPhysics3DSystem();
|
||||
|
||||
template<typename... Args> JoltRigidBody3DComponent CreateRigidBody(Args&&... args);
|
||||
|
||||
void Dump();
|
||||
|
||||
inline JoltPhysWorld3D& GetPhysWorld();
|
||||
inline const JoltPhysWorld3D& GetPhysWorld() const;
|
||||
|
||||
bool RaycastQueryFirst(const Vector3f& from, const Vector3f& to, RaycastHit* hitInfo = nullptr);
|
||||
|
||||
void Update(Time elapsedTime);
|
||||
|
||||
JoltPhysics3DSystem& operator=(const JoltPhysics3DSystem&) = delete;
|
||||
JoltPhysics3DSystem& operator=(JoltPhysics3DSystem&&) = delete;
|
||||
|
||||
struct RaycastHit : JoltPhysWorld3D::RaycastHit
|
||||
{
|
||||
entt::handle hitEntity;
|
||||
};
|
||||
|
||||
private:
|
||||
void OnConstruct(entt::registry& registry, entt::entity entity);
|
||||
void OnDestruct(entt::registry& registry, entt::entity entity);
|
||||
|
||||
std::size_t m_stepCount;
|
||||
std::vector<entt::entity> m_physicsEntities;
|
||||
entt::registry& m_registry;
|
||||
entt::observer m_physicsConstructObserver;
|
||||
entt::scoped_connection m_constructConnection;
|
||||
entt::scoped_connection m_destructConnection;
|
||||
JoltPhysWorld3D m_physWorld;
|
||||
Time m_physicsTime;
|
||||
Time m_updateTime;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.inl>
|
||||
|
||||
#endif // NAZARA_JOLTPHYSICS3D_SYSTEMS_JOLTPHYSICS3DSYSTEM_HPP
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// 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 <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
template<typename... Args>
|
||||
JoltRigidBody3DComponent JoltPhysics3DSystem::CreateRigidBody(Args&&... args)
|
||||
{
|
||||
return JoltRigidBody3DComponent(&m_physWorld, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
inline JoltPhysWorld3D& JoltPhysics3DSystem::GetPhysWorld()
|
||||
{
|
||||
return m_physWorld;
|
||||
}
|
||||
|
||||
inline const JoltPhysWorld3D& JoltPhysics3DSystem::GetPhysWorld() const
|
||||
{
|
||||
return m_physWorld;
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/JoltPhysics3D/DebugOff.hpp>
|
||||
|
|
@ -72,7 +72,7 @@ namespace Nz
|
|||
std::size_t primitiveCount = list.GetSize();
|
||||
if (primitiveCount > 1)
|
||||
{
|
||||
std::vector<CompoundCollider3D::ChildCollider> childColliders(primitiveCount);
|
||||
std::vector<BulletCompoundCollider3D::ChildCollider> childColliders(primitiveCount);
|
||||
|
||||
for (unsigned int i = 0; i < primitiveCount; ++i)
|
||||
{
|
||||
|
|
@ -81,12 +81,12 @@ namespace Nz
|
|||
childColliders[i].offsetMatrix = primitive.matrix;
|
||||
}
|
||||
|
||||
return std::make_shared<CompoundCollider3D>(std::move(childColliders));
|
||||
return std::make_shared<BulletCompoundCollider3D>(std::move(childColliders));
|
||||
}
|
||||
else if (primitiveCount > 0)
|
||||
return CreateGeomFromPrimitive(list.GetPrimitive(0));
|
||||
else
|
||||
return std::make_shared<NullCollider3D>();
|
||||
return std::make_shared<BulletNullCollider3D>();
|
||||
}
|
||||
|
||||
std::shared_ptr<BulletCollider3D> BulletCollider3D::CreateGeomFromPrimitive(const Primitive& primitive)
|
||||
|
|
@ -94,17 +94,17 @@ namespace Nz
|
|||
switch (primitive.type)
|
||||
{
|
||||
case PrimitiveType::Box:
|
||||
return std::make_shared<BoxCollider3D>(primitive.box.lengths);
|
||||
return std::make_shared<BulletBoxCollider3D>(primitive.box.lengths);
|
||||
|
||||
case PrimitiveType::Cone:
|
||||
return std::make_shared<ConeCollider3D>(primitive.cone.length, primitive.cone.radius);
|
||||
return std::make_shared<BulletConeCollider3D>(primitive.cone.length, primitive.cone.radius);
|
||||
|
||||
case PrimitiveType::Plane:
|
||||
return std::make_shared<BoxCollider3D>(Vector3f(primitive.plane.size.x, 0.01f, primitive.plane.size.y));
|
||||
return std::make_shared<BulletBoxCollider3D>(Vector3f(primitive.plane.size.x, 0.01f, primitive.plane.size.y));
|
||||
///TODO: PlaneGeom?
|
||||
|
||||
case PrimitiveType::Sphere:
|
||||
return std::make_shared<SphereCollider3D>(primitive.sphere.size);
|
||||
return std::make_shared<BulletSphereCollider3D>(primitive.sphere.size);
|
||||
}
|
||||
|
||||
NazaraError("Primitive type not handled (0x" + NumberToString(UnderlyingCast(primitive.type), 16) + ')');
|
||||
|
|
@ -113,15 +113,15 @@ namespace Nz
|
|||
|
||||
/********************************** BoxCollider3D **********************************/
|
||||
|
||||
BoxCollider3D::BoxCollider3D(const Vector3f& lengths) :
|
||||
BulletBoxCollider3D::BulletBoxCollider3D(const Vector3f& lengths) :
|
||||
m_lengths(lengths)
|
||||
{
|
||||
m_shape = std::make_unique<btBoxShape>(ToBullet(m_lengths * 0.5f));
|
||||
}
|
||||
|
||||
BoxCollider3D::~BoxCollider3D() = default;
|
||||
BulletBoxCollider3D::~BulletBoxCollider3D() = default;
|
||||
|
||||
void BoxCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
void BulletBoxCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
{
|
||||
auto InsertVertex = [&](float x, float y, float z) -> UInt16
|
||||
{
|
||||
|
|
@ -163,59 +163,59 @@ namespace Nz
|
|||
InsertEdge(v3, v7);
|
||||
}
|
||||
|
||||
btCollisionShape* BoxCollider3D::GetShape() const
|
||||
btCollisionShape* BulletBoxCollider3D::GetShape() const
|
||||
{
|
||||
return m_shape.get();
|
||||
}
|
||||
|
||||
Vector3f BoxCollider3D::GetLengths() const
|
||||
Vector3f BulletBoxCollider3D::GetLengths() const
|
||||
{
|
||||
return m_lengths;
|
||||
}
|
||||
|
||||
ColliderType3D BoxCollider3D::GetType() const
|
||||
ColliderType3D BulletBoxCollider3D::GetType() const
|
||||
{
|
||||
return ColliderType3D::Box;
|
||||
}
|
||||
|
||||
/******************************** CapsuleCollider3D ********************************/
|
||||
|
||||
CapsuleCollider3D::CapsuleCollider3D(float length, float radius) :
|
||||
BulletCapsuleCollider3D::BulletCapsuleCollider3D(float length, float radius) :
|
||||
m_length(length),
|
||||
m_radius(radius)
|
||||
{
|
||||
m_shape = std::make_unique<btCapsuleShape>(radius, length);
|
||||
}
|
||||
|
||||
CapsuleCollider3D::~CapsuleCollider3D() = default;
|
||||
BulletCapsuleCollider3D::~BulletCapsuleCollider3D() = default;
|
||||
|
||||
void CapsuleCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
void BulletCapsuleCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
{
|
||||
}
|
||||
|
||||
float CapsuleCollider3D::GetLength() const
|
||||
float BulletCapsuleCollider3D::GetLength() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
float CapsuleCollider3D::GetRadius() const
|
||||
float BulletCapsuleCollider3D::GetRadius() const
|
||||
{
|
||||
return m_radius;
|
||||
}
|
||||
|
||||
btCollisionShape* CapsuleCollider3D::GetShape() const
|
||||
btCollisionShape* BulletCapsuleCollider3D::GetShape() const
|
||||
{
|
||||
return m_shape.get();
|
||||
}
|
||||
|
||||
ColliderType3D CapsuleCollider3D::GetType() const
|
||||
ColliderType3D BulletCapsuleCollider3D::GetType() const
|
||||
{
|
||||
return ColliderType3D::Capsule;
|
||||
}
|
||||
|
||||
/******************************* CompoundCollider3D ********************************/
|
||||
|
||||
CompoundCollider3D::CompoundCollider3D(std::vector<ChildCollider> childs) :
|
||||
BulletCompoundCollider3D::BulletCompoundCollider3D(std::vector<ChildCollider> childs) :
|
||||
m_childs(std::move(childs))
|
||||
{
|
||||
m_shape = std::make_unique<btCompoundShape>();
|
||||
|
|
@ -226,67 +226,67 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
CompoundCollider3D::~CompoundCollider3D() = default;
|
||||
BulletCompoundCollider3D::~BulletCompoundCollider3D() = default;
|
||||
|
||||
void CompoundCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
void BulletCompoundCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
{
|
||||
for (const auto& child : m_childs)
|
||||
child.collider->BuildDebugMesh(vertices, indices, offsetMatrix * child.offsetMatrix);
|
||||
}
|
||||
|
||||
auto CompoundCollider3D::GetGeoms() const -> const std::vector<ChildCollider>&
|
||||
auto BulletCompoundCollider3D::GetGeoms() const -> const std::vector<ChildCollider>&
|
||||
{
|
||||
return m_childs;
|
||||
}
|
||||
|
||||
btCollisionShape* CompoundCollider3D::GetShape() const
|
||||
btCollisionShape* BulletCompoundCollider3D::GetShape() const
|
||||
{
|
||||
return m_shape.get();
|
||||
}
|
||||
|
||||
ColliderType3D CompoundCollider3D::GetType() const
|
||||
ColliderType3D BulletCompoundCollider3D::GetType() const
|
||||
{
|
||||
return ColliderType3D::Compound;
|
||||
}
|
||||
|
||||
/********************************* ConeCollider3D **********************************/
|
||||
|
||||
ConeCollider3D::ConeCollider3D(float length, float radius) :
|
||||
BulletConeCollider3D::BulletConeCollider3D(float length, float radius) :
|
||||
m_length(length),
|
||||
m_radius(radius)
|
||||
{
|
||||
m_shape = std::make_unique<btConeShape>(radius, length);
|
||||
}
|
||||
|
||||
ConeCollider3D::~ConeCollider3D() = default;
|
||||
BulletConeCollider3D::~BulletConeCollider3D() = default;
|
||||
|
||||
void ConeCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
void BulletConeCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
{
|
||||
}
|
||||
|
||||
float ConeCollider3D::GetLength() const
|
||||
float BulletConeCollider3D::GetLength() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
float ConeCollider3D::GetRadius() const
|
||||
float BulletConeCollider3D::GetRadius() const
|
||||
{
|
||||
return m_radius;
|
||||
}
|
||||
|
||||
btCollisionShape* ConeCollider3D::GetShape() const
|
||||
btCollisionShape* BulletConeCollider3D::GetShape() const
|
||||
{
|
||||
return m_shape.get();
|
||||
}
|
||||
|
||||
ColliderType3D ConeCollider3D::GetType() const
|
||||
ColliderType3D BulletConeCollider3D::GetType() const
|
||||
{
|
||||
return ColliderType3D::Cone;
|
||||
}
|
||||
|
||||
/****************************** ConvexCollider3D *******************************/
|
||||
|
||||
ConvexCollider3D::ConvexCollider3D(SparsePtr<const Vector3f> vertices, unsigned int vertexCount)
|
||||
BulletConvexCollider3D::BulletConvexCollider3D(SparsePtr<const Vector3f> vertices, unsigned int vertexCount)
|
||||
{
|
||||
static_assert(std::is_same_v<btScalar, float>);
|
||||
|
||||
|
|
@ -294,9 +294,9 @@ namespace Nz
|
|||
m_shape->optimizeConvexHull();
|
||||
}
|
||||
|
||||
ConvexCollider3D::~ConvexCollider3D() = default;
|
||||
BulletConvexCollider3D::~BulletConvexCollider3D() = default;
|
||||
|
||||
void ConvexCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
void BulletConvexCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
{
|
||||
tsl::ordered_map<Vector3f, UInt16> vertexCache;
|
||||
auto InsertVertex = [&](const Vector3f& position) -> UInt16
|
||||
|
|
@ -324,19 +324,19 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
btCollisionShape* ConvexCollider3D::GetShape() const
|
||||
btCollisionShape* BulletConvexCollider3D::GetShape() const
|
||||
{
|
||||
return m_shape.get();
|
||||
}
|
||||
|
||||
ColliderType3D ConvexCollider3D::GetType() const
|
||||
ColliderType3D BulletConvexCollider3D::GetType() const
|
||||
{
|
||||
return ColliderType3D::ConvexHull;
|
||||
}
|
||||
|
||||
/******************************* CylinderCollider3D ********************************/
|
||||
|
||||
CylinderCollider3D::CylinderCollider3D(float length, float radius) :
|
||||
BulletCylinderCollider3D::BulletCylinderCollider3D(float length, float radius) :
|
||||
m_length(length),
|
||||
m_radius(radius)
|
||||
{
|
||||
|
|
@ -344,85 +344,85 @@ namespace Nz
|
|||
m_shape = std::make_unique<btCylinderShape>(btVector3{ radius, length, radius });
|
||||
}
|
||||
|
||||
CylinderCollider3D::~CylinderCollider3D() = default;
|
||||
BulletCylinderCollider3D::~BulletCylinderCollider3D() = default;
|
||||
|
||||
void CylinderCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
void BulletCylinderCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
{
|
||||
}
|
||||
|
||||
float CylinderCollider3D::GetLength() const
|
||||
float BulletCylinderCollider3D::GetLength() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
float CylinderCollider3D::GetRadius() const
|
||||
float BulletCylinderCollider3D::GetRadius() const
|
||||
{
|
||||
return m_radius;
|
||||
}
|
||||
|
||||
btCollisionShape* CylinderCollider3D::GetShape() const
|
||||
btCollisionShape* BulletCylinderCollider3D::GetShape() const
|
||||
{
|
||||
return m_shape.get();
|
||||
}
|
||||
|
||||
ColliderType3D CylinderCollider3D::GetType() const
|
||||
ColliderType3D BulletCylinderCollider3D::GetType() const
|
||||
{
|
||||
return ColliderType3D::Cylinder;
|
||||
}
|
||||
|
||||
/********************************* NullCollider3D **********************************/
|
||||
|
||||
NullCollider3D::NullCollider3D()
|
||||
BulletNullCollider3D::BulletNullCollider3D()
|
||||
{
|
||||
m_shape = std::make_unique<btEmptyShape>();
|
||||
}
|
||||
|
||||
NullCollider3D::~NullCollider3D() = default;
|
||||
BulletNullCollider3D::~BulletNullCollider3D() = default;
|
||||
|
||||
void NullCollider3D::BuildDebugMesh(std::vector<Vector3f>& /*vertices*/, std::vector<UInt16>& /*indices*/, const Matrix4f& /*offsetMatrix*/) const
|
||||
void BulletNullCollider3D::BuildDebugMesh(std::vector<Vector3f>& /*vertices*/, std::vector<UInt16>& /*indices*/, const Matrix4f& /*offsetMatrix*/) const
|
||||
{
|
||||
}
|
||||
|
||||
void NullCollider3D::ComputeInertia(float /*mass*/, Vector3f* inertia) const
|
||||
void BulletNullCollider3D::ComputeInertia(float /*mass*/, Vector3f* inertia) const
|
||||
{
|
||||
inertia->Set(1.f, 1.f, 1.f);
|
||||
}
|
||||
|
||||
btCollisionShape* NullCollider3D::GetShape() const
|
||||
btCollisionShape* BulletNullCollider3D::GetShape() const
|
||||
{
|
||||
return m_shape.get();
|
||||
}
|
||||
|
||||
ColliderType3D NullCollider3D::GetType() const
|
||||
ColliderType3D BulletNullCollider3D::GetType() const
|
||||
{
|
||||
return ColliderType3D::Null;
|
||||
}
|
||||
|
||||
/******************************** SphereCollider3D *********************************/
|
||||
|
||||
SphereCollider3D::SphereCollider3D(float radius) :
|
||||
BulletSphereCollider3D::BulletSphereCollider3D(float radius) :
|
||||
m_radius(radius)
|
||||
{
|
||||
m_shape = std::make_unique<btSphereShape>(radius);
|
||||
}
|
||||
|
||||
SphereCollider3D::~SphereCollider3D() = default;
|
||||
BulletSphereCollider3D::~BulletSphereCollider3D() = default;
|
||||
|
||||
void SphereCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
void BulletSphereCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
{
|
||||
}
|
||||
|
||||
float SphereCollider3D::GetRadius() const
|
||||
float BulletSphereCollider3D::GetRadius() const
|
||||
{
|
||||
return m_radius;
|
||||
}
|
||||
|
||||
btCollisionShape* SphereCollider3D::GetShape() const
|
||||
btCollisionShape* BulletSphereCollider3D::GetShape() const
|
||||
{
|
||||
return m_shape.get();
|
||||
}
|
||||
|
||||
ColliderType3D SphereCollider3D::GetType() const
|
||||
ColliderType3D BulletSphereCollider3D::GetType() const
|
||||
{
|
||||
return ColliderType3D::Sphere;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,11 +121,19 @@ namespace Nz
|
|||
}
|
||||
}
|
||||
|
||||
#define HACK 0
|
||||
|
||||
btRigidBody* BulletPhysWorld3D::AddRigidBody(std::size_t& rigidBodyIndex, FunctionRef<void(btRigidBody* body)> constructor)
|
||||
{
|
||||
#if HACK
|
||||
static std::size_t index = 0;
|
||||
rigidBodyIndex = index++;
|
||||
btRigidBody* rigidBody = (btRigidBody*) ::operator new(sizeof(btRigidBody));
|
||||
constructor(rigidBody);
|
||||
m_world->dynamicWorld.addRigidBody(rigidBody);
|
||||
#else
|
||||
btRigidBody* rigidBody = m_world->rigidBodyPool.Allocate(m_world->rigidBodyPool.DeferConstruct, rigidBodyIndex);
|
||||
constructor(rigidBody);
|
||||
|
||||
m_world->dynamicWorld.addRigidBody(rigidBody);
|
||||
|
||||
// Small hack to order rigid bodies to make it cache friendly
|
||||
|
|
@ -144,6 +152,7 @@ namespace Nz
|
|||
*it = rigidBody;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return rigidBody;
|
||||
}
|
||||
|
|
@ -152,6 +161,10 @@ namespace Nz
|
|||
{
|
||||
// TODO: Improve deletion (since rigid bodies are sorted)
|
||||
m_world->dynamicWorld.removeRigidBody(rigidBody); //< this does a linear search
|
||||
#if HACK
|
||||
::operator delete(rigidBody);
|
||||
#else
|
||||
m_world->rigidBodyPool.Free(rigidBodyIndex);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace Nz
|
|||
NazaraAssert(m_world, "Invalid world");
|
||||
|
||||
if (!m_geom)
|
||||
m_geom = std::make_shared<NullCollider3D>();
|
||||
m_geom = std::make_shared<BulletNullCollider3D>();
|
||||
|
||||
Vector3f inertia;
|
||||
m_geom->ComputeInertia(1.f, &inertia);
|
||||
|
|
@ -214,7 +214,7 @@ namespace Nz
|
|||
if (geom)
|
||||
m_geom = std::move(geom);
|
||||
else
|
||||
m_geom = std::make_shared<NullCollider3D>();
|
||||
m_geom = std::make_shared<BulletNullCollider3D>();
|
||||
|
||||
m_body->setCollisionShape(m_geom->GetShape());
|
||||
if (recomputeInertia)
|
||||
|
|
@ -267,6 +267,15 @@ namespace Nz
|
|||
m_body->setWorldTransform(worldTransform);
|
||||
}
|
||||
|
||||
void BulletRigidBody3D::SetPositionAndRotation(const Vector3f& position, const Quaternionf& rotation)
|
||||
{
|
||||
btTransform worldTransform;
|
||||
worldTransform.setOrigin(ToBullet(position));
|
||||
worldTransform.setRotation(ToBullet(rotation));
|
||||
|
||||
m_body->setWorldTransform(worldTransform);
|
||||
}
|
||||
|
||||
void BulletRigidBody3D::SetRotation(const Quaternionf& rotation)
|
||||
{
|
||||
btTransform worldTransform = m_body->getWorldTransform();
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <Nazara/BulletPhysics3D/Systems/BulletPhysics3DSystem.hpp>
|
||||
#include <Nazara/Utility/Components/NodeComponent.hpp>
|
||||
#include <iostream>
|
||||
#include <Nazara/BulletPhysics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
|
|
@ -14,6 +15,10 @@ namespace Nz
|
|||
{
|
||||
m_constructConnection = registry.on_construct<BulletRigidBody3DComponent>().connect<&BulletPhysics3DSystem::OnConstruct>(this);
|
||||
m_destructConnection = registry.on_destroy<BulletRigidBody3DComponent>().connect<&BulletPhysics3DSystem::OnDestruct>(this);
|
||||
|
||||
m_stepCount = 0;
|
||||
m_physicsTime = Time::Zero();
|
||||
m_updateTime = Time::Zero();
|
||||
}
|
||||
|
||||
BulletPhysics3DSystem::~BulletPhysics3DSystem()
|
||||
|
|
@ -26,6 +31,20 @@ namespace Nz
|
|||
rigidBodyComponent.Destroy();
|
||||
}
|
||||
|
||||
void BulletPhysics3DSystem::Dump()
|
||||
{
|
||||
if (m_stepCount == 0)
|
||||
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 << "--" << std::endl;
|
||||
|
||||
m_stepCount = 0;
|
||||
m_physicsTime = Time::Zero();
|
||||
m_updateTime = Time::Zero();
|
||||
}
|
||||
|
||||
bool BulletPhysics3DSystem::RaycastQueryFirst(const Vector3f& from, const Vector3f& to, RaycastHit* hitInfo)
|
||||
{
|
||||
if (!m_physWorld.RaycastQueryFirst(from, to, hitInfo))
|
||||
|
|
@ -49,12 +68,16 @@ namespace Nz
|
|||
BulletRigidBody3DComponent& entityPhysics = m_registry.get<BulletRigidBody3DComponent>(entity);
|
||||
NodeComponent& entityNode = m_registry.get<NodeComponent>(entity);
|
||||
|
||||
entityPhysics.SetPosition(entityNode.GetPosition(CoordSys::Global));
|
||||
entityPhysics.SetRotation(entityNode.GetRotation(CoordSys::Global));
|
||||
entityPhysics.SetPositionAndRotation(entityNode.GetPosition(CoordSys::Global), entityNode.GetRotation(CoordSys::Global));
|
||||
});
|
||||
|
||||
Time t1 = GetElapsedNanoseconds();
|
||||
|
||||
// Update the physics world
|
||||
m_physWorld.Step(elapsedTime);
|
||||
m_stepCount++;
|
||||
|
||||
Time t2 = GetElapsedNanoseconds();
|
||||
|
||||
// Replicate rigid body position to their node components
|
||||
// TODO: Only replicate active entities
|
||||
|
|
@ -67,6 +90,11 @@ namespace Nz
|
|||
nodeComponent.SetPosition(rigidBodyComponent.GetPosition(), CoordSys::Global);
|
||||
nodeComponent.SetRotation(rigidBodyComponent.GetRotation(), CoordSys::Global);
|
||||
}
|
||||
|
||||
Time t3 = GetElapsedNanoseconds();
|
||||
|
||||
m_physicsTime += (t2 - t1);
|
||||
m_updateTime += (t3 - t2);
|
||||
}
|
||||
|
||||
void BulletPhysics3DSystem::OnConstruct(entt::registry& registry, entt::entity entity)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
// 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 <Nazara/JoltPhysics3D/Components/JoltRigidBody3DComponent.hpp>
|
||||
#include <Nazara/BulletPhysics3D/Components/BulletRigidBody3DComponent.hpp>
|
||||
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
// 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 <Nazara/JoltPhysics3D/JoltCollider3D.hpp>
|
||||
#include <Nazara/Core/PrimitiveList.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltHelper.hpp>
|
||||
#include <Nazara/Utility/Algorithm.hpp>
|
||||
#include <Nazara/Utility/IndexBuffer.hpp>
|
||||
#include <Nazara/Utility/SoftwareBuffer.hpp>
|
||||
#include <Nazara/Utility/StaticMesh.hpp>
|
||||
#include <Nazara/Utility/VertexBuffer.hpp>
|
||||
#include <Nazara/Utils/MemoryHelper.hpp>
|
||||
#include <Jolt/Core/Core.h>
|
||||
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/StaticCompoundShape.h>
|
||||
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
|
||||
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
JoltCollider3D::~JoltCollider3D() = default;
|
||||
|
||||
std::shared_ptr<StaticMesh> JoltCollider3D::GenerateDebugMesh() const
|
||||
{
|
||||
std::vector<Vector3f> colliderVertices;
|
||||
std::vector<UInt16> colliderIndices;
|
||||
BuildDebugMesh(colliderVertices, colliderIndices);
|
||||
|
||||
std::shared_ptr<VertexBuffer> colliderVB = std::make_shared<VertexBuffer>(VertexDeclaration::Get(VertexLayout::XYZ), SafeCast<UInt32>(colliderVertices.size()), BufferUsage::Write, SoftwareBufferFactory, colliderVertices.data());
|
||||
std::shared_ptr<IndexBuffer> colliderIB = std::make_shared<IndexBuffer>(IndexType::U16, colliderIndices.size(), BufferUsage::Write, SoftwareBufferFactory, colliderIndices.data());
|
||||
|
||||
std::shared_ptr<StaticMesh> colliderSubMesh = std::make_shared<StaticMesh>(std::move(colliderVB), std::move(colliderIB));
|
||||
colliderSubMesh->GenerateAABB();
|
||||
colliderSubMesh->SetPrimitiveMode(PrimitiveMode::LineList);
|
||||
|
||||
return colliderSubMesh;
|
||||
}
|
||||
|
||||
std::shared_ptr<JoltCollider3D> JoltCollider3D::Build(const PrimitiveList& list)
|
||||
{
|
||||
std::size_t primitiveCount = list.GetSize();
|
||||
if (primitiveCount > 1)
|
||||
{
|
||||
std::vector<JoltCompoundCollider3D::ChildCollider> childColliders(primitiveCount);
|
||||
|
||||
for (unsigned int i = 0; i < primitiveCount; ++i)
|
||||
{
|
||||
const Primitive& primitive = list.GetPrimitive(i);
|
||||
childColliders[i].collider = CreateGeomFromPrimitive(primitive);
|
||||
childColliders[i].offset = primitive.matrix.GetTranslation();
|
||||
childColliders[i].rotation = primitive.matrix.GetRotation();
|
||||
}
|
||||
|
||||
return std::make_shared<JoltCompoundCollider3D>(std::move(childColliders));
|
||||
}
|
||||
else if (primitiveCount > 0)
|
||||
return CreateGeomFromPrimitive(list.GetPrimitive(0));
|
||||
else
|
||||
return nullptr;// std::make_shared<NullCollider3D>(); //< TODO
|
||||
}
|
||||
|
||||
std::shared_ptr<JoltCollider3D> JoltCollider3D::CreateGeomFromPrimitive(const Primitive& primitive)
|
||||
{
|
||||
switch (primitive.type)
|
||||
{
|
||||
case PrimitiveType::Box:
|
||||
return std::make_shared<JoltBoxCollider3D>(primitive.box.lengths);
|
||||
|
||||
case PrimitiveType::Cone:
|
||||
return nullptr; //< TODO
|
||||
//return std::make_shared<ConeCollider3D>(primitive.cone.length, primitive.cone.radius);
|
||||
|
||||
case PrimitiveType::Plane:
|
||||
return std::make_shared<JoltBoxCollider3D>(Vector3f(primitive.plane.size.x, 0.01f, primitive.plane.size.y));
|
||||
///TODO: PlaneGeom?
|
||||
|
||||
case PrimitiveType::Sphere:
|
||||
return std::make_shared<JoltSphereCollider3D>(primitive.sphere.size);
|
||||
}
|
||||
|
||||
NazaraError("Primitive type not handled (0x" + NumberToString(UnderlyingCast(primitive.type), 16) + ')');
|
||||
return std::shared_ptr<JoltCollider3D>();
|
||||
}
|
||||
|
||||
/********************************** BoxCollider3D **********************************/
|
||||
|
||||
JoltBoxCollider3D::JoltBoxCollider3D(const Vector3f& lengths, float convexRadius) :
|
||||
m_lengths(lengths)
|
||||
{
|
||||
m_shapeSettings = std::make_unique<JPH::BoxShapeSettings>(ToJolt(m_lengths * 0.5f), convexRadius);
|
||||
}
|
||||
|
||||
JoltBoxCollider3D::~JoltBoxCollider3D() = default;
|
||||
|
||||
void JoltBoxCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
{
|
||||
auto InsertVertex = [&](float x, float y, float z) -> UInt16
|
||||
{
|
||||
UInt16 index = SafeCast<UInt16>(vertices.size());
|
||||
vertices.push_back(offsetMatrix * Vector3f(x, y, z));
|
||||
return index;
|
||||
};
|
||||
|
||||
Vector3f halfLengths = m_lengths * 0.5f;
|
||||
|
||||
UInt16 v0 = InsertVertex(-halfLengths.x, -halfLengths.y, -halfLengths.z);
|
||||
UInt16 v1 = InsertVertex(halfLengths.x, -halfLengths.y, -halfLengths.z);
|
||||
UInt16 v2 = InsertVertex(halfLengths.x, -halfLengths.y, halfLengths.z);
|
||||
UInt16 v3 = InsertVertex(-halfLengths.x, -halfLengths.y, halfLengths.z);
|
||||
|
||||
UInt16 v4 = InsertVertex(-halfLengths.x, halfLengths.y, -halfLengths.z);
|
||||
UInt16 v5 = InsertVertex(halfLengths.x, halfLengths.y, -halfLengths.z);
|
||||
UInt16 v6 = InsertVertex(halfLengths.x, halfLengths.y, halfLengths.z);
|
||||
UInt16 v7 = InsertVertex(-halfLengths.x, halfLengths.y, halfLengths.z);
|
||||
|
||||
auto InsertEdge = [&](UInt16 from, UInt16 to)
|
||||
{
|
||||
indices.push_back(from);
|
||||
indices.push_back(to);
|
||||
};
|
||||
InsertEdge(v0, v1);
|
||||
InsertEdge(v1, v2);
|
||||
InsertEdge(v2, v3);
|
||||
InsertEdge(v3, v0);
|
||||
|
||||
InsertEdge(v4, v5);
|
||||
InsertEdge(v5, v6);
|
||||
InsertEdge(v6, v7);
|
||||
InsertEdge(v7, v4);
|
||||
|
||||
InsertEdge(v0, v4);
|
||||
InsertEdge(v1, v5);
|
||||
InsertEdge(v2, v6);
|
||||
InsertEdge(v3, v7);
|
||||
}
|
||||
|
||||
JPH::ShapeSettings* JoltBoxCollider3D::GetShapeSettings() const
|
||||
{
|
||||
return m_shapeSettings.get();
|
||||
}
|
||||
|
||||
Vector3f JoltBoxCollider3D::GetLengths() const
|
||||
{
|
||||
return m_lengths;
|
||||
}
|
||||
|
||||
JoltColliderType3D JoltBoxCollider3D::GetType() const
|
||||
{
|
||||
return JoltColliderType3D::Box;
|
||||
}
|
||||
|
||||
/******************************* JoltCompoundCollider3D ********************************/
|
||||
|
||||
JoltCompoundCollider3D::JoltCompoundCollider3D(std::vector<ChildCollider> childs) :
|
||||
m_childs(std::move(childs))
|
||||
{
|
||||
m_shapeSettings = std::make_unique<JPH::StaticCompoundShapeSettings>();
|
||||
for (const auto& child : m_childs)
|
||||
m_shapeSettings->AddShape(ToJolt(child.offset), ToJolt(child.rotation), child.collider->GetShapeSettings());
|
||||
}
|
||||
|
||||
JoltCompoundCollider3D::~JoltCompoundCollider3D() = default;
|
||||
|
||||
void JoltCompoundCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
{
|
||||
for (const auto& child : m_childs)
|
||||
child.collider->BuildDebugMesh(vertices, indices, offsetMatrix * Matrix4f::Transform(child.offset, child.rotation));
|
||||
}
|
||||
|
||||
auto JoltCompoundCollider3D::GetGeoms() const -> const std::vector<ChildCollider>&
|
||||
{
|
||||
return m_childs;
|
||||
}
|
||||
|
||||
JPH::ShapeSettings* JoltCompoundCollider3D::GetShapeSettings() const
|
||||
{
|
||||
return m_shapeSettings.get();
|
||||
}
|
||||
|
||||
JoltColliderType3D JoltCompoundCollider3D::GetType() const
|
||||
{
|
||||
return JoltColliderType3D::Compound;
|
||||
}
|
||||
|
||||
/******************************** JoltSphereCollider3D *********************************/
|
||||
|
||||
JoltSphereCollider3D::JoltSphereCollider3D(float radius) :
|
||||
m_radius(radius)
|
||||
{
|
||||
m_shapeSettings = std::make_unique<JPH::SphereShapeSettings>(radius);
|
||||
}
|
||||
|
||||
JoltSphereCollider3D::~JoltSphereCollider3D() = default;
|
||||
|
||||
void JoltSphereCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
|
||||
{
|
||||
}
|
||||
|
||||
float JoltSphereCollider3D::GetRadius() const
|
||||
{
|
||||
return m_radius;
|
||||
}
|
||||
|
||||
JPH::ShapeSettings* JoltSphereCollider3D::GetShapeSettings() const
|
||||
{
|
||||
return m_shapeSettings.get();
|
||||
}
|
||||
|
||||
JoltColliderType3D JoltSphereCollider3D::GetType() const
|
||||
{
|
||||
return JoltColliderType3D::Sphere;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
// 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
|
||||
#if 0
|
||||
#include <Nazara/JoltPhysics3D/JoltConstraint3D.hpp>
|
||||
#include <Nazara/BulletPhysics3D/BulletConstraint3D.hpp>
|
||||
#include <Nazara/BulletPhysics3D/BulletHelper.hpp>
|
||||
#include <BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h>
|
||||
#include <BulletDynamics/Dynamics/btDynamicsWorld.h>
|
||||
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
BulletConstraint3D::BulletConstraint3D(std::unique_ptr<btTypedConstraint> constraint, bool disableCollisions) :
|
||||
m_constraint(std::move(constraint)),
|
||||
m_bodyCollisionEnabled(!disableCollisions)
|
||||
{
|
||||
btDynamicsWorld* world = GetWorld().GetDynamicsWorld();
|
||||
world->addConstraint(m_constraint.get(), disableCollisions);
|
||||
}
|
||||
|
||||
BulletConstraint3D::BulletConstraint3D(BulletConstraint3D&& constraint) noexcept :
|
||||
m_constraint(std::move(constraint.m_constraint)),
|
||||
m_bodyCollisionEnabled(constraint.m_bodyCollisionEnabled)
|
||||
{
|
||||
if (m_constraint)
|
||||
m_constraint->setUserConstraintPtr(this);
|
||||
}
|
||||
|
||||
BulletConstraint3D::~BulletConstraint3D()
|
||||
{
|
||||
if (m_constraint)
|
||||
{
|
||||
btDynamicsWorld* world = GetWorld().GetDynamicsWorld();
|
||||
world->removeConstraint(m_constraint.get());
|
||||
}
|
||||
}
|
||||
|
||||
BulletRigidBody3D& BulletConstraint3D::GetBodyA()
|
||||
{
|
||||
return *static_cast<BulletRigidBody3D*>(m_constraint->getRigidBodyA().getUserPointer());
|
||||
}
|
||||
|
||||
const BulletRigidBody3D& BulletConstraint3D::GetBodyA() const
|
||||
{
|
||||
return *static_cast<BulletRigidBody3D*>(m_constraint->getRigidBodyA().getUserPointer());
|
||||
}
|
||||
|
||||
BulletRigidBody3D& BulletConstraint3D::GetBodyB()
|
||||
{
|
||||
NazaraAssert(!IsSingleBody(), "constraint is not attached to a second body");
|
||||
return *static_cast<BulletRigidBody3D*>(m_constraint->getRigidBodyB().getUserPointer());
|
||||
}
|
||||
|
||||
const BulletRigidBody3D& BulletConstraint3D::GetBodyB() const
|
||||
{
|
||||
NazaraAssert(!IsSingleBody(), "constraint is not attached to a second body");
|
||||
return *static_cast<BulletRigidBody3D*>(m_constraint->getRigidBodyB().getUserPointer());
|
||||
}
|
||||
|
||||
BulletPhysWorld3D& BulletConstraint3D::GetWorld()
|
||||
{
|
||||
return *GetBodyA().GetWorld();
|
||||
}
|
||||
|
||||
const BulletPhysWorld3D& BulletConstraint3D::GetWorld() const
|
||||
{
|
||||
return *GetBodyA().GetWorld();
|
||||
}
|
||||
|
||||
bool BulletConstraint3D::IsSingleBody() const
|
||||
{
|
||||
return &m_constraint->getRigidBodyB() == &btTypedConstraint::getFixedBody();
|
||||
}
|
||||
|
||||
BulletConstraint3D& BulletConstraint3D::operator=(BulletConstraint3D&& constraint) noexcept
|
||||
{
|
||||
m_constraint.reset();
|
||||
|
||||
m_constraint = std::move(constraint.m_constraint);
|
||||
m_bodyCollisionEnabled = constraint.m_bodyCollisionEnabled;
|
||||
|
||||
if (m_constraint)
|
||||
m_constraint->setUserConstraintPtr(this);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
BulletPivotConstraint3D::BulletPivotConstraint3D(BulletRigidBody3D& first, const Vector3f& pivot) :
|
||||
BulletConstraint3D(std::make_unique<btPoint2PointConstraint>(*first.GetRigidBody(), ToBullet(first.ToLocal(pivot))))
|
||||
{
|
||||
}
|
||||
|
||||
BulletPivotConstraint3D::BulletPivotConstraint3D(BulletRigidBody3D& first, BulletRigidBody3D& second, const Vector3f& pivot, bool disableCollisions) :
|
||||
BulletConstraint3D(std::make_unique<btPoint2PointConstraint>(*first.GetRigidBody(), *second.GetRigidBody(), ToBullet(first.ToLocal(pivot)), ToBullet(second.ToLocal(pivot))), disableCollisions)
|
||||
{
|
||||
}
|
||||
|
||||
BulletPivotConstraint3D::BulletPivotConstraint3D(BulletRigidBody3D& first, BulletRigidBody3D& second, const Vector3f& firstAnchor, const Vector3f& secondAnchor, bool disableCollisions) :
|
||||
BulletConstraint3D(std::make_unique<btPoint2PointConstraint>(*first.GetRigidBody(), *second.GetRigidBody(), ToBullet(firstAnchor), ToBullet(secondAnchor)), disableCollisions)
|
||||
{
|
||||
}
|
||||
|
||||
Vector3f BulletPivotConstraint3D::GetFirstAnchor() const
|
||||
{
|
||||
return FromBullet(GetConstraint<btPoint2PointConstraint>()->getPivotInA());
|
||||
}
|
||||
|
||||
Vector3f BulletPivotConstraint3D::GetSecondAnchor() const
|
||||
{
|
||||
return FromBullet(GetConstraint<btPoint2PointConstraint>()->getPivotInB());
|
||||
}
|
||||
|
||||
void BulletPivotConstraint3D::SetFirstAnchor(const Vector3f& firstAnchor)
|
||||
{
|
||||
GetConstraint<btPoint2PointConstraint>()->setPivotA(ToBullet(firstAnchor));
|
||||
}
|
||||
|
||||
void BulletPivotConstraint3D::SetSecondAnchor(const Vector3f& secondAnchor)
|
||||
{
|
||||
GetConstraint<btPoint2PointConstraint>()->setPivotB(ToBullet(secondAnchor));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -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
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_JOLTPHYSICS3D_JOLTHELPER_HPP
|
||||
#define NAZARA_JOLTPHYSICS3D_JOLTHELPER_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/BulletPhysics3D/Config.hpp>
|
||||
#include <Nazara/Math/Matrix4.hpp>
|
||||
#include <Nazara/Math/Quaternion.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
#include <Jolt/Jolt.h>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
inline Quaternionf FromJolt(const JPH::Quat& quat);
|
||||
inline Matrix4f FromJolt(const JPH::Mat44& matrix);
|
||||
inline Vector3f FromJolt(const JPH::Vec3& vec);
|
||||
|
||||
inline JPH::Mat44 ToJolt(const Matrix4f& transformMatrix);
|
||||
inline JPH::Quat ToJolt(const Quaternionf& quaternion);
|
||||
inline JPH::Vec3 ToJolt(const Vector3f& vec);
|
||||
inline JPH::Vec4 ToJolt(const Vector4f& vec);
|
||||
}
|
||||
|
||||
#include <Nazara/JoltPhysics3D/JoltHelper.inl>
|
||||
|
||||
#endif // NAZARA_JOLTPHYSICS3D_JOLTHELPER_HPP
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
// 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 <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
Quaternionf FromJolt(const JPH::Quat& quat)
|
||||
{
|
||||
return Quaternionf(quat.GetW(), quat.GetX(), quat.GetY(), quat.GetZ());
|
||||
}
|
||||
|
||||
Matrix4f FromJolt(const JPH::Mat44& transform)
|
||||
{
|
||||
const JPH::Vec4& row1 = transform.GetColumn4(0);
|
||||
const JPH::Vec4& row2 = transform.GetColumn4(1);
|
||||
const JPH::Vec4& row3 = transform.GetColumn4(2);
|
||||
const JPH::Vec4& row4 = transform.GetColumn4(3);
|
||||
|
||||
return Matrix4f(
|
||||
row1.GetX(), row1.GetY(), row1.GetZ(), row1.GetW(),
|
||||
row2.GetX(), row2.GetY(), row2.GetZ(), row2.GetW(),
|
||||
row3.GetX(), row3.GetY(), row3.GetZ(), row3.GetW(),
|
||||
row4.GetX(), row4.GetY(), row4.GetZ(), row4.GetW());
|
||||
}
|
||||
|
||||
inline Vector3f FromJolt(const JPH::Vec3& vec)
|
||||
{
|
||||
return Vector3f(vec.GetX(), vec.GetY(), vec.GetZ());
|
||||
}
|
||||
|
||||
inline JPH::Mat44 ToJolt(const Matrix4f& transformMatrix)
|
||||
{
|
||||
JPH::Mat44 transform;
|
||||
transform.SetColumn4(0, JPH::Vec4{ transformMatrix.m11, transformMatrix.m12, transformMatrix.m13, transformMatrix.m14 });
|
||||
transform.SetColumn4(1, JPH::Vec4{ transformMatrix.m21, transformMatrix.m22, transformMatrix.m23, transformMatrix.m24 });
|
||||
transform.SetColumn4(2, JPH::Vec4{ transformMatrix.m31, transformMatrix.m32, transformMatrix.m33, transformMatrix.m34 });
|
||||
transform.SetColumn4(3, JPH::Vec4{ transformMatrix.m41, transformMatrix.m42, transformMatrix.m43, transformMatrix.m44 });
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
inline JPH::Quat ToJolt(const Quaternionf& quaternion)
|
||||
{
|
||||
return JPH::Quat(quaternion.x, quaternion.y, quaternion.z, quaternion.w);
|
||||
}
|
||||
|
||||
inline JPH::Vec3 ToJolt(const Vector3f& vec)
|
||||
{
|
||||
return JPH::Vec3(vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
inline JPH::Vec4 ToJolt(const Vector4f& vec)
|
||||
{
|
||||
return JPH::Vec4(vec.x, vec.y, vec.z, vec.w);
|
||||
}
|
||||
}
|
||||
|
||||
#include <Nazara/JoltPhysics3D/DebugOff.hpp>
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
// 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 <Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltHelper.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltPhysics3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp>
|
||||
#include <Nazara/Utils/MemoryPool.hpp>
|
||||
#include <Nazara/Utils/StackVector.hpp>
|
||||
#include <Jolt/Jolt.h>
|
||||
#include <Jolt/Core/TempAllocator.h>
|
||||
#include <Jolt/Physics/Collision/ObjectLayer.h>
|
||||
#include <Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h>
|
||||
#include <Jolt/Physics/PhysicsSettings.h>
|
||||
#include <Jolt/Physics/PhysicsSystem.h>
|
||||
#include <Jolt/Physics/Body/BodyActivationListener.h>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
namespace DitchMeAsap
|
||||
{
|
||||
using namespace JPH;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
// Layer that objects can be in, determines which other objects it can collide with
|
||||
// Typically you at least want to have 1 layer for moving bodies and 1 layer for static bodies, but you can have more
|
||||
// layers if you want. E.g. you could have a layer for high detail collision (which is not used by the physics simulation
|
||||
// but only if you do collision testing).
|
||||
namespace Layers
|
||||
{
|
||||
static constexpr uint8 NON_MOVING = 0;
|
||||
static constexpr uint8 MOVING = 1;
|
||||
static constexpr uint8 NUM_LAYERS = 2;
|
||||
};
|
||||
|
||||
/// Class that determines if two object layers can collide
|
||||
class ObjectLayerPairFilterImpl : public ObjectLayerPairFilter
|
||||
{
|
||||
public:
|
||||
virtual bool ShouldCollide(ObjectLayer inObject1, ObjectLayer inObject2) const override
|
||||
{
|
||||
switch (inObject1)
|
||||
{
|
||||
case Layers::NON_MOVING:
|
||||
return inObject2 == Layers::MOVING; // Non moving only collides with moving
|
||||
case Layers::MOVING:
|
||||
return true; // Moving collides with everything
|
||||
default:
|
||||
JPH_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Each broadphase layer results in a separate bounding volume tree in the broad phase. You at least want to have
|
||||
// a layer for non-moving and moving objects to avoid having to update a tree full of static objects every frame.
|
||||
// You can have a 1-on-1 mapping between object layers and broadphase layers (like in this case) but if you have
|
||||
// many object layers you'll be creating many broad phase trees, which is not efficient. If you want to fine tune
|
||||
// your broadphase layers define JPH_TRACK_BROADPHASE_STATS and look at the stats reported on the TTY.
|
||||
namespace BroadPhaseLayers
|
||||
{
|
||||
static constexpr BroadPhaseLayer NON_MOVING(0);
|
||||
static constexpr BroadPhaseLayer MOVING(1);
|
||||
static constexpr uint NUM_LAYERS(2);
|
||||
};
|
||||
|
||||
// BroadPhaseLayerInterface implementation
|
||||
// This defines a mapping between object and broadphase layers.
|
||||
class BPLayerInterfaceImpl final : public BroadPhaseLayerInterface
|
||||
{
|
||||
public:
|
||||
BPLayerInterfaceImpl()
|
||||
{
|
||||
// Create a mapping table from object to broad phase layer
|
||||
mObjectToBroadPhase[Layers::NON_MOVING] = BroadPhaseLayers::NON_MOVING;
|
||||
mObjectToBroadPhase[Layers::MOVING] = BroadPhaseLayers::MOVING;
|
||||
}
|
||||
|
||||
virtual uint GetNumBroadPhaseLayers() const override
|
||||
{
|
||||
return BroadPhaseLayers::NUM_LAYERS;
|
||||
}
|
||||
|
||||
virtual BroadPhaseLayer GetBroadPhaseLayer(ObjectLayer inLayer) const override
|
||||
{
|
||||
JPH_ASSERT(inLayer < Layers::NUM_LAYERS);
|
||||
return mObjectToBroadPhase[inLayer];
|
||||
}
|
||||
|
||||
#if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED)
|
||||
virtual const char* GetBroadPhaseLayerName(BroadPhaseLayer inLayer) const override
|
||||
{
|
||||
switch ((BroadPhaseLayer::Type)inLayer)
|
||||
{
|
||||
case (BroadPhaseLayer::Type)BroadPhaseLayers::NON_MOVING: return "NON_MOVING";
|
||||
case (BroadPhaseLayer::Type)BroadPhaseLayers::MOVING: return "MOVING";
|
||||
default: JPH_ASSERT(false); return "INVALID";
|
||||
}
|
||||
}
|
||||
#endif // JPH_EXTERNAL_PROFILE || JPH_PROFILE_ENABLED
|
||||
|
||||
private:
|
||||
BroadPhaseLayer mObjectToBroadPhase[Layers::NUM_LAYERS];
|
||||
};
|
||||
/// Class that determines if an object layer can collide with a broadphase layer
|
||||
class ObjectVsBroadPhaseLayerFilterImpl : public ObjectVsBroadPhaseLayerFilter
|
||||
{
|
||||
public:
|
||||
virtual bool ShouldCollide(ObjectLayer inLayer1, BroadPhaseLayer inLayer2) const override
|
||||
{
|
||||
switch (inLayer1)
|
||||
{
|
||||
case Layers::NON_MOVING:
|
||||
return inLayer2 == BroadPhaseLayers::MOVING;
|
||||
case Layers::MOVING:
|
||||
return true;
|
||||
default:
|
||||
JPH_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// An example contact listener
|
||||
class MyContactListener : public ContactListener
|
||||
{
|
||||
public:
|
||||
// See: ContactListener
|
||||
virtual ValidateResult OnContactValidate(const Body& inBody1, const Body& inBody2, RVec3Arg inBaseOffset, const CollideShapeResult& inCollisionResult) override
|
||||
{
|
||||
cout << "Contact validate callback" << endl;
|
||||
|
||||
// Allows you to ignore a contact before it is created (using layers to not make objects collide is cheaper!)
|
||||
return ValidateResult::AcceptAllContactsForThisBodyPair;
|
||||
}
|
||||
|
||||
virtual void OnContactAdded(const Body& inBody1, const Body& inBody2, const ContactManifold& inManifold, ContactSettings& ioSettings) override
|
||||
{
|
||||
cout << "A contact was added" << endl;
|
||||
}
|
||||
|
||||
virtual void OnContactPersisted(const Body& inBody1, const Body& inBody2, const ContactManifold& inManifold, ContactSettings& ioSettings) override
|
||||
{
|
||||
cout << "A contact was persisted" << endl;
|
||||
}
|
||||
|
||||
virtual void OnContactRemoved(const SubShapeIDPair& inSubShapePair) override
|
||||
{
|
||||
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
|
||||
{
|
||||
struct JoltPhysWorld3D::JoltWorld
|
||||
{
|
||||
JPH::TempAllocatorMalloc tempAllocation;
|
||||
JPH::PhysicsSystem physicsSystem;
|
||||
|
||||
DitchMeAsap::BPLayerInterfaceImpl layerInterface;
|
||||
DitchMeAsap::ObjectLayerPairFilterImpl objectLayerFilter;
|
||||
DitchMeAsap::ObjectVsBroadPhaseLayerFilterImpl objectBroadphaseLayerFilter;
|
||||
|
||||
JoltWorld() = default;
|
||||
JoltWorld(const JoltWorld&) = delete;
|
||||
JoltWorld(JoltWorld&&) = delete;
|
||||
|
||||
JoltWorld& operator=(const JoltWorld&) = delete;
|
||||
JoltWorld& operator=(JoltWorld&&) = delete;
|
||||
};
|
||||
|
||||
JoltPhysWorld3D::JoltPhysWorld3D() :
|
||||
m_maxStepCount(50),
|
||||
m_gravity(Vector3f::Zero()),
|
||||
m_stepSize(Time::TickDuration(120)),
|
||||
m_timestepAccumulator(Time::Zero())
|
||||
{
|
||||
m_world = std::make_unique<JoltWorld>();
|
||||
m_world->physicsSystem.Init(0xFFFF, 0, 0xFFFF, 0xFFFF, m_world->layerInterface, m_world->objectBroadphaseLayerFilter, m_world->objectLayerFilter);
|
||||
}
|
||||
|
||||
JoltPhysWorld3D::~JoltPhysWorld3D() = default;
|
||||
|
||||
Vector3f JoltPhysWorld3D::GetGravity() const
|
||||
{
|
||||
return FromJolt(m_world->physicsSystem.GetGravity());
|
||||
}
|
||||
|
||||
std::size_t JoltPhysWorld3D::GetMaxStepCount() const
|
||||
{
|
||||
return m_maxStepCount;
|
||||
}
|
||||
|
||||
JPH::PhysicsSystem* JoltPhysWorld3D::GetPhysicsSystem()
|
||||
{
|
||||
return &m_world->physicsSystem;
|
||||
}
|
||||
|
||||
Time JoltPhysWorld3D::GetStepSize() const
|
||||
{
|
||||
return m_stepSize;
|
||||
}
|
||||
|
||||
bool JoltPhysWorld3D::RaycastQueryFirst(const Vector3f& from, const Vector3f& to, RaycastHit* hitInfo)
|
||||
{
|
||||
return false;
|
||||
/*
|
||||
btCollisionWorld::ClosestRayResultCallback callback(ToBullet(from), ToBullet(to));
|
||||
m_world->dynamicWorld.rayTest(ToBullet(from), ToBullet(to), callback);
|
||||
|
||||
if (!callback.hasHit())
|
||||
return false;
|
||||
|
||||
if (hitInfo)
|
||||
{
|
||||
hitInfo->fraction = callback.m_closestHitFraction;
|
||||
hitInfo->hitNormal = FromBullet(callback.m_hitNormalWorld);
|
||||
hitInfo->hitPosition = FromBullet(callback.m_hitPointWorld);
|
||||
|
||||
if (const btRigidBody* body = btRigidBody::upcast(callback.m_collisionObject))
|
||||
hitInfo->hitBody = static_cast<BulletRigidBody3D*>(body->getUserPointer());
|
||||
}
|
||||
|
||||
return true;*/
|
||||
}
|
||||
|
||||
void JoltPhysWorld3D::SetGravity(const Vector3f& gravity)
|
||||
{
|
||||
m_world->physicsSystem.SetGravity(ToJolt(gravity));
|
||||
}
|
||||
|
||||
void JoltPhysWorld3D::SetMaxStepCount(std::size_t maxStepCount)
|
||||
{
|
||||
m_maxStepCount = maxStepCount;
|
||||
}
|
||||
|
||||
void JoltPhysWorld3D::SetStepSize(Time stepSize)
|
||||
{
|
||||
m_stepSize = stepSize;
|
||||
}
|
||||
|
||||
void JoltPhysWorld3D::Step(Time timestep)
|
||||
{
|
||||
JPH::JobSystem& jobSystem = JoltPhysics3D::Instance()->GetThreadPool();
|
||||
|
||||
m_timestepAccumulator += timestep;
|
||||
|
||||
float stepSize = m_stepSize.AsSeconds<float>();
|
||||
|
||||
static bool firstStep = true;
|
||||
if (firstStep)
|
||||
{
|
||||
m_world->physicsSystem.OptimizeBroadPhase();
|
||||
firstStep = false;
|
||||
}
|
||||
|
||||
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_timestepAccumulator -= m_stepSize;
|
||||
stepCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
// 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 <Nazara/JoltPhysics3D/JoltPhysics3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/Config.hpp>
|
||||
#include <Nazara/Core/Core.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <Jolt/Jolt.h>
|
||||
#include <Jolt/RegisterTypes.h>
|
||||
#include <Jolt/Core/Factory.h>
|
||||
#include <Jolt/Core/JobSystemThreadPool.h>
|
||||
#include <Jolt/Physics/PhysicsSettings.h>
|
||||
#include <cstdarg>
|
||||
#include <iostream>
|
||||
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
// Callback for traces, connect this to your own trace function if you have one
|
||||
static void TraceImpl(const char* inFMT, ...)
|
||||
{
|
||||
// Format the message
|
||||
va_list list;
|
||||
va_start(list, inFMT);
|
||||
char buffer[1024];
|
||||
vsnprintf(buffer, sizeof(buffer), inFMT, list);
|
||||
va_end(list);
|
||||
|
||||
// Print to the TTY
|
||||
std::cout << buffer << std::endl;
|
||||
}
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
JoltPhysics3D::JoltPhysics3D(Config /*config*/) :
|
||||
ModuleBase("JoltPhysics3D", this)
|
||||
{
|
||||
JPH::RegisterDefaultAllocator();
|
||||
JPH::Trace = TraceImpl;
|
||||
JPH::Factory::sInstance = new JPH::Factory;
|
||||
JPH::RegisterTypes();
|
||||
|
||||
m_threadPool = std::make_unique<JPH::JobSystemThreadPool>(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, Core::Instance()->GetHardwareInfo().GetCpuThreadCount());
|
||||
}
|
||||
|
||||
JoltPhysics3D::~JoltPhysics3D()
|
||||
{
|
||||
m_threadPool.reset();
|
||||
// FIXME: Uncomment when next version of Jolt gets released
|
||||
//JPH::UnregisterTypes();
|
||||
|
||||
delete JPH::Factory::sInstance;
|
||||
JPH::Factory::sInstance = nullptr;
|
||||
}
|
||||
|
||||
JPH::JobSystem& JoltPhysics3D::GetThreadPool()
|
||||
{
|
||||
return *m_threadPool;
|
||||
}
|
||||
|
||||
JoltPhysics3D* JoltPhysics3D::s_instance;
|
||||
}
|
||||
|
|
@ -0,0 +1,325 @@
|
|||
// 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 <Nazara/JoltPhysics3D/JoltRigidBody3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltHelper.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp>
|
||||
#include <Nazara/JoltPhysics3D/JoltRigidBody3D.hpp>
|
||||
#include <Nazara/Utils/MemoryHelper.hpp>
|
||||
#include <Jolt/Jolt.h>
|
||||
#include <Jolt/Physics/PhysicsSystem.h>
|
||||
#include <Jolt/Physics/Body/BodyCreationSettings.h>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
JoltRigidBody3D::JoltRigidBody3D(JoltPhysWorld3D* world, const Matrix4f& mat) :
|
||||
JoltRigidBody3D(world, nullptr, mat)
|
||||
{
|
||||
}
|
||||
|
||||
JoltRigidBody3D::JoltRigidBody3D(JoltPhysWorld3D* world, std::shared_ptr<JoltCollider3D> geom, const Matrix4f& mat) :
|
||||
m_geom(std::move(geom)),
|
||||
m_world(world)
|
||||
{
|
||||
NazaraAssert(m_world, "Invalid world");
|
||||
|
||||
if (!m_geom)
|
||||
m_geom = std::make_shared<JoltSphereCollider3D>(1.f);
|
||||
|
||||
JPH::BodyInterface& body_interface = 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);
|
||||
settings.mAllowSleeping = false;
|
||||
|
||||
JPH::Body* body = body_interface.CreateBody(settings);
|
||||
body->SetUserData(SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
|
||||
|
||||
body_interface.AddBody(body->GetID(), JPH::EActivation::Activate);
|
||||
m_bodyIndex = body->GetID().GetIndexAndSequenceNumber();
|
||||
}
|
||||
|
||||
JoltRigidBody3D::JoltRigidBody3D(JoltRigidBody3D&& object) noexcept :
|
||||
m_geom(std::move(object.m_geom)),
|
||||
m_bodyIndex(object.m_bodyIndex),
|
||||
m_world(object.m_world)
|
||||
{
|
||||
object.m_bodyIndex = JPH::BodyID::cInvalidBodyID;
|
||||
}
|
||||
|
||||
JoltRigidBody3D::~JoltRigidBody3D()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
#if 0
|
||||
void JoltRigidBody3D::AddForce(const Vector3f& force, CoordSys coordSys)
|
||||
{
|
||||
switch (coordSys)
|
||||
{
|
||||
case CoordSys::Global:
|
||||
WakeUp();
|
||||
m_body->applyCentralForce(ToJolt(force));
|
||||
break;
|
||||
|
||||
case CoordSys::Local:
|
||||
WakeUp();
|
||||
m_body->applyCentralForce(ToJolt(GetRotation() * force));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JoltRigidBody3D::AddForce(const Vector3f& force, const Vector3f& point, CoordSys coordSys)
|
||||
{
|
||||
switch (coordSys)
|
||||
{
|
||||
case CoordSys::Global:
|
||||
WakeUp();
|
||||
m_body->applyForce(ToJolt(force), ToJolt(point));
|
||||
break;
|
||||
|
||||
case CoordSys::Local:
|
||||
{
|
||||
Matrix4f transformMatrix = GetMatrix();
|
||||
return AddForce(transformMatrix.Transform(force, 0.f), point, CoordSys::Global);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JoltRigidBody3D::AddTorque(const Vector3f& torque, CoordSys coordSys)
|
||||
{
|
||||
switch (coordSys)
|
||||
{
|
||||
case CoordSys::Global:
|
||||
WakeUp();
|
||||
m_body->applyTorque(ToJolt(torque));
|
||||
break;
|
||||
|
||||
case CoordSys::Local:
|
||||
Matrix4f transformMatrix = GetMatrix();
|
||||
WakeUp();
|
||||
m_body->applyTorque(ToJolt(transformMatrix.Transform(torque, 0.f)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void JoltRigidBody3D::EnableSleeping(bool enable)
|
||||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
void JoltRigidBody3D::FallAsleep()
|
||||
{
|
||||
if (m_body->getActivationState() != DISABLE_DEACTIVATION)
|
||||
m_body->setActivationState(ISLAND_SLEEPING);
|
||||
}
|
||||
|
||||
Boxf JoltRigidBody3D::GetAABB() const
|
||||
{
|
||||
btVector3 min, max;
|
||||
m_body->getAabb(min, max);
|
||||
|
||||
return Boxf(FromJolt(min), FromJolt(max));
|
||||
}
|
||||
|
||||
float JoltRigidBody3D::GetAngularDamping() const
|
||||
{
|
||||
return m_body->getAngularDamping();
|
||||
}
|
||||
|
||||
Vector3f JoltRigidBody3D::GetAngularVelocity() const
|
||||
{
|
||||
return FromJolt(m_body->getAngularVelocity());
|
||||
}
|
||||
|
||||
float JoltRigidBody3D::GetLinearDamping() const
|
||||
{
|
||||
return m_body->getLinearDamping();
|
||||
}
|
||||
|
||||
Vector3f JoltRigidBody3D::GetLinearVelocity() const
|
||||
{
|
||||
return FromJolt(m_body->getLinearVelocity());
|
||||
}
|
||||
|
||||
float JoltRigidBody3D::GetMass() const
|
||||
{
|
||||
return m_body->getMass();
|
||||
}
|
||||
|
||||
Vector3f JoltRigidBody3D::GetMassCenter(CoordSys coordSys) const
|
||||
{
|
||||
return FromJolt(m_body->getCenterOfMassPosition());
|
||||
}
|
||||
|
||||
Matrix4f JoltRigidBody3D::GetMatrix() const
|
||||
{
|
||||
return FromJolt(m_body->getWorldTransform());
|
||||
}
|
||||
#endif
|
||||
|
||||
Vector3f JoltRigidBody3D::GetPosition() const
|
||||
{
|
||||
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
||||
return FromJolt(body_interface.GetPosition(JPH::BodyID(m_bodyIndex)));
|
||||
}
|
||||
|
||||
Quaternionf JoltRigidBody3D::GetRotation() const
|
||||
{
|
||||
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
||||
return FromJolt(body_interface.GetRotation(JPH::BodyID(m_bodyIndex)));
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool JoltRigidBody3D::IsSimulationEnabled() const
|
||||
{
|
||||
return m_body->isActive();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool JoltRigidBody3D::IsSleeping() const
|
||||
{
|
||||
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
|
||||
return !body_interface.IsActive(JPH::BodyID(m_bodyIndex));
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool JoltRigidBody3D::IsSleepingEnabled() const
|
||||
{
|
||||
return m_body->getActivationState() != DISABLE_DEACTIVATION;
|
||||
}
|
||||
|
||||
void JoltRigidBody3D::SetAngularDamping(float angularDamping)
|
||||
{
|
||||
m_body->setDamping(m_body->getLinearDamping(), angularDamping);
|
||||
}
|
||||
|
||||
void JoltRigidBody3D::SetAngularVelocity(const Vector3f& angularVelocity)
|
||||
{
|
||||
m_body->setAngularVelocity(ToJolt(angularVelocity));
|
||||
}
|
||||
|
||||
void JoltRigidBody3D::SetGeom(std::shared_ptr<JoltCollider3D> geom, bool recomputeInertia)
|
||||
{
|
||||
if (m_geom != geom)
|
||||
{
|
||||
if (geom)
|
||||
m_geom = std::move(geom);
|
||||
else
|
||||
m_geom = std::make_shared<NullCollider3D>();
|
||||
|
||||
m_body->setCollisionShape(m_geom->GetShape());
|
||||
if (recomputeInertia)
|
||||
{
|
||||
float mass = GetMass();
|
||||
|
||||
Vector3f inertia;
|
||||
m_geom->ComputeInertia(mass, &inertia);
|
||||
|
||||
m_body->setMassProps(mass, ToJolt(inertia));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JoltRigidBody3D::SetLinearDamping(float damping)
|
||||
{
|
||||
m_body->setDamping(damping, m_body->getAngularDamping());
|
||||
}
|
||||
|
||||
void JoltRigidBody3D::SetLinearVelocity(const Vector3f& velocity)
|
||||
{
|
||||
m_body->setLinearVelocity(ToJolt(velocity));
|
||||
}
|
||||
#endif 0
|
||||
void JoltRigidBody3D::SetMass(float mass)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void JoltRigidBody3D::SetMassCenter(const Vector3f& center)
|
||||
{
|
||||
btTransform centerTransform;
|
||||
centerTransform.setIdentity();
|
||||
centerTransform.setOrigin(ToJolt(center));
|
||||
|
||||
m_body->setCenterOfMassTransform(centerTransform);
|
||||
}
|
||||
#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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#if 0
|
||||
Quaternionf JoltRigidBody3D::ToLocal(const Quaternionf& worldRotation)
|
||||
{
|
||||
return GetRotation().Conjugate() * worldRotation;
|
||||
}
|
||||
|
||||
Vector3f JoltRigidBody3D::ToLocal(const Vector3f& worldPosition)
|
||||
{
|
||||
btTransform worldTransform = m_body->getWorldTransform();
|
||||
return GetMatrix().InverseTransform() * worldPosition;
|
||||
}
|
||||
|
||||
Quaternionf JoltRigidBody3D::ToWorld(const Quaternionf& localRotation)
|
||||
{
|
||||
return GetRotation() * localRotation;
|
||||
}
|
||||
|
||||
Vector3f JoltRigidBody3D::ToWorld(const Vector3f& localPosition)
|
||||
{
|
||||
return GetMatrix() * localPosition;
|
||||
}
|
||||
|
||||
void JoltRigidBody3D::WakeUp()
|
||||
{
|
||||
m_body->activate();
|
||||
}
|
||||
#endif
|
||||
|
||||
JoltRigidBody3D& JoltRigidBody3D::operator=(JoltRigidBody3D&& object) noexcept
|
||||
{
|
||||
Destroy();
|
||||
|
||||
m_bodyIndex = object.m_bodyIndex;
|
||||
m_geom = std::move(object.m_geom);
|
||||
m_world = object.m_world;
|
||||
|
||||
object.m_bodyIndex = JPH::BodyID::cInvalidBodyID;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void JoltRigidBody3D::Destroy()
|
||||
{
|
||||
if (m_bodyIndex != JPH::BodyID::cInvalidBodyID)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
m_geom.reset();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
// 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 <Nazara/JoltPhysics3D/Systems/JoltPhysics3DSystem.hpp>
|
||||
#include <Nazara/Utility/Components/NodeComponent.hpp>
|
||||
#include <iostream>
|
||||
#include <Nazara/JoltPhysics3D/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
JoltPhysics3DSystem::JoltPhysics3DSystem(entt::registry& registry) :
|
||||
m_registry(registry),
|
||||
m_physicsConstructObserver(m_registry, entt::collector.group<JoltRigidBody3DComponent, NodeComponent>())
|
||||
{
|
||||
m_constructConnection = registry.on_construct<JoltRigidBody3DComponent>().connect<&JoltPhysics3DSystem::OnConstruct>(this);
|
||||
m_destructConnection = registry.on_destroy<JoltRigidBody3DComponent>().connect<&JoltPhysics3DSystem::OnDestruct>(this);
|
||||
|
||||
m_stepCount = 0;
|
||||
m_physicsTime = Time::Zero();
|
||||
m_updateTime = Time::Zero();
|
||||
}
|
||||
|
||||
JoltPhysics3DSystem::~JoltPhysics3DSystem()
|
||||
{
|
||||
m_physicsConstructObserver.disconnect();
|
||||
|
||||
// Ensure every RigidBody3D is destroyed before world is
|
||||
auto rigidBodyView = m_registry.view<JoltRigidBody3DComponent>();
|
||||
for (auto [entity, rigidBodyComponent] : rigidBodyView.each())
|
||||
rigidBodyComponent.Destroy();
|
||||
}
|
||||
|
||||
void JoltPhysics3DSystem::Dump()
|
||||
{
|
||||
if (m_stepCount == 0)
|
||||
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 << "--" << std::endl;
|
||||
|
||||
m_stepCount = 0;
|
||||
m_physicsTime = Time::Zero();
|
||||
m_updateTime = Time::Zero();
|
||||
}
|
||||
|
||||
bool JoltPhysics3DSystem::RaycastQueryFirst(const Vector3f& from, const Vector3f& to, RaycastHit* hitInfo)
|
||||
{
|
||||
if (!m_physWorld.RaycastQueryFirst(from, to, hitInfo))
|
||||
return false;
|
||||
|
||||
/*if (hitInfo->hitBody)
|
||||
{
|
||||
std::size_t uniqueIndex = hitInfo->hitBody->GetUniqueIndex();
|
||||
if (uniqueIndex < m_physicsEntities.size())
|
||||
hitInfo->hitEntity = entt::handle(m_registry, m_physicsEntities[uniqueIndex]);
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JoltPhysics3DSystem::Update(Time elapsedTime)
|
||||
{
|
||||
// Move newly-created physics entities to their node position/rotation
|
||||
m_physicsConstructObserver.each([&](entt::entity entity)
|
||||
{
|
||||
JoltRigidBody3DComponent& entityPhysics = m_registry.get<JoltRigidBody3DComponent>(entity);
|
||||
NodeComponent& entityNode = m_registry.get<NodeComponent>(entity);
|
||||
|
||||
entityPhysics.SetPosition(entityNode.GetPosition(CoordSys::Global));
|
||||
entityPhysics.SetRotation(entityNode.GetRotation(CoordSys::Global));
|
||||
});
|
||||
|
||||
Time t1 = GetElapsedNanoseconds();
|
||||
|
||||
// Update the physics world
|
||||
m_physWorld.Step(elapsedTime);
|
||||
m_stepCount++;
|
||||
|
||||
Time t2 = GetElapsedNanoseconds();
|
||||
|
||||
// Replicate rigid body position to their node components
|
||||
// TODO: Only replicate active entities
|
||||
auto view = m_registry.view<NodeComponent, const JoltRigidBody3DComponent>();
|
||||
for (auto [entity, nodeComponent, rigidBodyComponent] : view.each())
|
||||
{
|
||||
if (rigidBodyComponent.IsSleeping())
|
||||
continue;
|
||||
|
||||
nodeComponent.SetPosition(rigidBodyComponent.GetPosition(), CoordSys::Global);
|
||||
nodeComponent.SetRotation(rigidBodyComponent.GetRotation(), CoordSys::Global);
|
||||
}
|
||||
|
||||
Time t3 = GetElapsedNanoseconds();
|
||||
|
||||
m_physicsTime += (t2 - t1);
|
||||
m_updateTime += (t3 - t2);
|
||||
}
|
||||
|
||||
void JoltPhysics3DSystem::OnConstruct(entt::registry& registry, entt::entity entity)
|
||||
{
|
||||
}
|
||||
|
||||
void JoltPhysics3DSystem::OnDestruct(entt::registry& registry, entt::entity entity)
|
||||
{
|
||||
}
|
||||
}
|
||||
13
xmake.lua
13
xmake.lua
|
|
@ -66,6 +66,10 @@ local modules = {
|
|||
end
|
||||
end
|
||||
},
|
||||
BulletPhysics3D = {
|
||||
Deps = {"NazaraUtility"},
|
||||
Packages = { "bullet3", "entt", "ordered_map" }
|
||||
},
|
||||
Core = {
|
||||
Custom = function ()
|
||||
add_headerfiles("include/(Nazara/*.hpp)")
|
||||
|
|
@ -105,6 +109,10 @@ local modules = {
|
|||
Deps = {"NazaraRenderer"},
|
||||
Packages = {"entt"}
|
||||
},
|
||||
JoltPhysics3D = {
|
||||
Deps = {"NazaraUtility"},
|
||||
Packages = { "joltphysics", "entt" }
|
||||
},
|
||||
Network = {
|
||||
Deps = {"NazaraCore"},
|
||||
Custom = function()
|
||||
|
|
@ -122,10 +130,6 @@ local modules = {
|
|||
Deps = {"NazaraUtility"},
|
||||
Packages = { "chipmunk2d", "entt" }
|
||||
},
|
||||
BulletPhysics3D = {
|
||||
Deps = {"NazaraUtility"},
|
||||
Packages = { "bullet3", "entt", "ordered_map" }
|
||||
},
|
||||
Platform = {
|
||||
Deps = {"NazaraUtility"},
|
||||
Custom = function()
|
||||
|
|
@ -234,6 +238,7 @@ add_requires(
|
|||
"minimp3",
|
||||
"ordered_map",
|
||||
"stb")
|
||||
add_requires("joltphysics master", { 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 } })
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue