Continue Jolt integration

This commit is contained in:
SirLynix 2023-03-21 13:31:52 +01:00 committed by Jérôme Leclercq
parent 21e08798ce
commit 021801f02e
35 changed files with 612 additions and 214 deletions

View File

@ -102,7 +102,7 @@ int main()
cameraComponent.UpdateClearColor(Nz::Color(0.5f, 0.5f, 0.5f));
}
auto shipCollider = std::make_shared<Nz::ConvexCollider3D>(vertices, vertexMapper.GetVertexCount());
auto shipCollider = std::make_shared<Nz::BulletConvexCollider3D>(vertices, vertexMapper.GetVertexCount());
std::shared_ptr<Nz::MaterialInstance> colliderMat = Nz::Graphics::Instance()->GetDefaultMaterials().basicMaterial->Instantiate();
colliderMat->SetValueProperty("BaseColor", Nz::Color::Green());

View File

@ -1,6 +1,6 @@
// Sources pour https://github.com/NazaraEngine/NazaraEngine/wiki/(FR)-Tutoriel:-%5B01%5D-Hello-World
#define USE_JOLT 0
#define USE_JOLT 1
#include <Nazara/Core.hpp>
#include <Nazara/Graphics.hpp>
@ -22,7 +22,7 @@ int main()
try {
// Mise en place de l'application, de la fenêtre et du monde
Nz::Renderer::Config renderConfig;
//renderConfig.preferredAPI = Nz::RenderAPI::OpenGL;
renderConfig.validationLevel = Nz::RenderAPIValidationLevel::None;
#if USE_JOLT
Nz::Application<Nz::Graphics, Nz::JoltPhysics3D> app(renderConfig);
@ -150,7 +150,7 @@ int main()
std::uniform_real_distribution<float> colorDis(0.f, 360.f);
std::uniform_real_distribution<float> radiusDis(0.1f, 0.5f);
constexpr std::size_t SphereCount = 2000;
constexpr std::size_t SphereCount = 1000;
for (std::size_t i = 0; i < SphereCount; ++i)
{
float radius = radiusDis(rd);
@ -364,15 +364,15 @@ int main()
{
auto& cameraNode = cameraEntity.get<Nz::NodeComponent>();
//physSystem.GetPhysWorld().SetGravity(cameraNode.GetBackward() * 9.81f);
physSystem.GetPhysWorld().SetGravity(cameraNode.GetBackward() * 9.81f);
}
});
Nz::DegreeAnglef rotation = 0.f;
app.AddUpdater([&](Nz::Time elapsedTime)
{
rotation += elapsedTime.AsSeconds() * 30.f;
physSystem.GetPhysWorld().SetGravity(Nz::Quaternionf(Nz::EulerAnglesf(0.f, rotation, 0.f)) * Nz::Vector3f::Forward());
rotation += elapsedTime.AsSeconds() * 45.f;
//physSystem.GetPhysWorld().SetGravity(Nz::Quaternionf(Nz::EulerAnglesf(0.f, rotation, 0.f)) * Nz::Vector3f::Forward() * 10.f);
});
Nz::MillisecondClock fpsClock;

View File

@ -52,6 +52,8 @@ int main()
physSytem.GetPhysWorld().SetGravity({ 0.f, -9.81f, 0.f });
std::optional<Nz::JoltCharacter> character;
entt::handle playerEntity = world.CreateEntity();
entt::handle playerRotation = world.CreateEntity();
entt::handle playerCamera = world.CreateEntity();
@ -61,8 +63,18 @@ int main()
auto playerCollider = std::make_shared<Nz::JoltBoxCollider3D>(Nz::Vector3f(0.2f, 1.8f, 0.2f));
auto& playerBody = playerEntity.emplace<Nz::JoltRigidBody3DComponent>(physSytem.CreateRigidBody(playerCollider));
playerBody.SetMass(42.f);
//auto& playerBody = playerEntity.emplace<Nz::JoltRigidBody3DComponent>(physSytem.CreateRigidBody(playerCollider));
//playerBody.SetMass(42.f);
character.emplace(physSytem.GetPhysWorld(), playerCollider, Nz::Vector3f::Up() * 5.f);
app.AddUpdater([&](Nz::Time /*elapsedTime*/)
{
auto [position, rotation] = character->GetPositionAndRotation();
auto& playerNode = playerEntity.get<Nz::NodeComponent>();
playerNode.SetTransform(position, rotation, Nz::Vector3f::Unit());
});
std::shared_ptr<Nz::Mesh> colliderMesh = Nz::Mesh::Build(playerCollider->GenerateDebugMesh());
std::shared_ptr<Nz::GraphicalMesh> colliderGraphicalMesh = Nz::GraphicalMesh::BuildFromMesh(*colliderMesh);
@ -215,7 +227,7 @@ int main()
auto& bobGfx = bobEntity.emplace<Nz::GraphicsComponent>();
bobGfx.AttachRenderable(bobModel);
auto& sharedSkeleton = bobEntity.emplace<Nz::SharedSkeletonComponent>(skeleton);
bobEntity.emplace<Nz::SharedSkeletonComponent>(skeleton);
entt::handle sphereEntity = world.CreateEntity();
{
@ -333,7 +345,10 @@ int main()
floorEntity.emplace<Nz::NodeComponent>();
auto& planeBody = floorEntity.emplace<Nz::JoltRigidBody3DComponent>(physSytem.CreateRigidBody(std::make_shared<Nz::JoltBoxCollider3D>(Nz::Vector3f(planeSize.x, 0.5f, planeSize.y))));
auto floorCollider = std::make_shared<Nz::JoltBoxCollider3D>(Nz::Vector3f(planeSize.x, 1.f, planeSize.y));
auto translatedFloorCollider = std::make_shared<Nz::JoltTranslatedRotatedCollider3D>(std::move(floorCollider), Nz::Vector3f::Down() * 0.5f);
auto& planeBody = floorEntity.emplace<Nz::JoltRigidBody3DComponent>(physSytem.CreateRigidBody(translatedFloorCollider));
planeBody.SetMass(0.f);
std::shared_ptr<Nz::GraphicalMesh> boxMeshGfx = Nz::GraphicalMesh::Build(Nz::Primitive::Box(Nz::Vector3f(0.5f, 0.5f, 0.5f)), meshPrimitiveParams);
@ -344,6 +359,27 @@ int main()
entt::handle boxEntity = world.CreateEntity();
boxEntity.emplace<Nz::NodeComponent>();
boxEntity.emplace<Nz::GraphicsComponent>().AttachRenderable(boxModel);
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(translatedFloorCollider->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);
planeGfx.AttachRenderable(std::move(colliderModel));
}
}
Nz::MillisecondClock fpsClock, updateClock;
@ -385,25 +421,32 @@ int main()
{
float updateTime = deltaTime->AsSeconds();
auto& playerBody = playerEntity.get<Nz::JoltRigidBody3DComponent>();
//auto& playerBody = playerEntity.get<Nz::JoltRigidBody3DComponent>();
//playerBody.SetAngularDamping(std::numeric_limits<float>::max());
float mass = playerBody.GetMass();
Nz::Vector3f velocity = character->GetLinearVelocity();
velocity.x = 0.f;
velocity.z = 0.f;
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::RShift))
playerBody.AddForce(Nz::Vector3f(0.f, mass * 50.f, 0.f));
{
if (character->IsOnGround())
velocity += Nz::Vector3f::Up() * 2.f;
}
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Up))
playerBody.AddForce(Nz::Vector3f::Forward() * 25.f * mass, Nz::CoordSys::Local);
velocity += Nz::Vector3f::Forward();
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Down))
playerBody.AddForce(Nz::Vector3f::Backward() * 25.f * mass, Nz::CoordSys::Local);
velocity += Nz::Vector3f::Backward();
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Left))
playerBody.AddForce(Nz::Vector3f::Left() * 25.f * mass, Nz::CoordSys::Local);
velocity += Nz::Vector3f::Left();
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Right))
playerBody.AddForce(Nz::Vector3f::Right() * 25.f * mass, Nz::CoordSys::Local);
velocity += Nz::Vector3f::Right();
character->SetLinearVelocity(velocity);
float cameraSpeed = 2.f;

View File

@ -7,7 +7,7 @@
#ifndef NAZARA_BULLETPHYSICS3D_BULLETCONSTRAINT3D_HPP
#define NAZARA_BULLETPHYSICS3D_BULLETCONSTRAINT3D_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/BulletPhysics3D/BulletPhysWorld3D.hpp>
#include <Nazara/BulletPhysics3D/BulletRigidBody3D.hpp>
#include <Nazara/BulletPhysics3D/Config.hpp>

View File

@ -7,7 +7,7 @@
#ifndef NAZARA_BULLETPHYSICS3D_HPP
#define NAZARA_BULLETPHYSICS3D_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/BulletPhysics3D/Config.hpp>
#include <Nazara/Core/Core.hpp>

View File

@ -7,7 +7,7 @@
#ifndef NAZARA_BULLETPHYSICS3D_COMPONENTS_BULLETRIGIDBODY3DCOMPONENT_HPP
#define NAZARA_BULLETPHYSICS3D_COMPONENTS_BULLETRIGIDBODY3DCOMPONENT_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/BulletPhysics3D/BulletRigidBody3D.hpp>
namespace Nz

View File

@ -7,12 +7,12 @@
#ifndef NAZARA_BULLETPHYSICS3D_SYSTEMS_BULLETPHYSICS3DSYSTEM_HPP
#define NAZARA_BULLETPHYSICS3D_SYSTEMS_BULLETPHYSICS3DSYSTEM_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/BulletPhysics3D/BulletPhysWorld3D.hpp>
#include <Nazara/BulletPhysics3D/Components/BulletRigidBody3DComponent.hpp>
#include <Nazara/Core/Time.hpp>
#include <Nazara/Utils/TypeList.hpp>
#include <NazaraUtils/TypeList.hpp>
#include <entt/entt.hpp>
#include <vector>
@ -54,6 +54,7 @@ namespace Nz
void OnConstruct(entt::registry& registry, entt::entity entity);
void OnDestruct(entt::registry& registry, entt::entity entity);
std::size_t m_activeObjectCount;
std::size_t m_stepCount;
std::vector<entt::entity> m_physicsEntities;
entt::registry& m_registry;

View File

@ -31,6 +31,7 @@
#include <Nazara/JoltPhysics3D/Config.hpp>
#include <Nazara/JoltPhysics3D/Enums.hpp>
#include <Nazara/JoltPhysics3D/JoltCharacter.hpp>
#include <Nazara/JoltPhysics3D/JoltCollider3D.hpp>
#include <Nazara/JoltPhysics3D/JoltConstraint3D.hpp>
#include <Nazara/JoltPhysics3D/JoltPhysics3D.hpp>

View File

@ -7,7 +7,7 @@
#ifndef NAZARA_JOLTPHYSICS3D_COMPONENTS_JOLTRIGIDBODY3DCOMPONENT_HPP
#define NAZARA_JOLTPHYSICS3D_COMPONENTS_JOLTRIGIDBODY3DCOMPONENT_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/JoltPhysics3D/JoltRigidBody3D.hpp>
namespace Nz

View File

@ -15,6 +15,9 @@ namespace Nz
Compound,
Sphere,
TranslatedRotatedDecoration,
ScaleDecoration,
Max = Sphere
};
}

View File

@ -0,0 +1,59 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - JoltPhysics3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_JOLTPHYSICS3D_JOLTCHARACTER_HPP
#define NAZARA_JOLTPHYSICS3D_JOLTCHARACTER_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Math/Quaternion.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <Nazara/JoltPhysics3D/Config.hpp>
#include <memory>
namespace JPH
{
class Character;
}
namespace Nz
{
class JoltCollider3D;
class JoltPhysWorld3D;
class NAZARA_JOLTPHYSICS3D_API JoltCharacter
{
friend JoltPhysWorld3D;
public:
JoltCharacter(JoltPhysWorld3D& physWorld, std::shared_ptr<JoltCollider3D> collider, const Vector3f& position, const Quaternionf& rotation = Quaternionf::Identity());
JoltCharacter(const JoltCharacter&) = delete;
JoltCharacter(JoltCharacter&&) = delete;
~JoltCharacter();
Vector3f GetLinearVelocity() const;
Quaternionf GetRotation() const;
Vector3f GetPosition() const;
std::pair<Vector3f, Quaternionf> GetPositionAndRotation() const;
bool IsOnGround() const;
void SetLinearVelocity(const Vector3f& linearVel);
JoltCharacter& operator=(const JoltCharacter&) = delete;
JoltCharacter& operator=(JoltCharacter&&) = delete;
private:
void PostSimulate();
std::shared_ptr<JoltCollider3D> m_collider;
std::unique_ptr<JPH::Character> m_character;
JoltPhysWorld3D& m_physicsWorld;
};
}
#include <Nazara/JoltPhysics3D/JoltCharacter.inl>
#endif // NAZARA_JOLTPHYSICS3D_JOLTCHARACTER_HPP

View File

@ -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 <Nazara/JoltPhysics3D/JoltCharacter.hpp>
#include <Nazara/JoltPhysics3D/Debug.hpp>
namespace Nz
{
}
#include <Nazara/JoltPhysics3D/DebugOff.hpp>

View File

@ -7,23 +7,21 @@
#ifndef NAZARA_JOLTPHYSICS3D_JOLTCOLLIDER3D_HPP
#define NAZARA_JOLTPHYSICS3D_JOLTCOLLIDER3D_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/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 <NazaraUtils/Signal.hpp>
#include <NazaraUtils/SparsePtr.hpp>
#include <memory>
namespace JPH
{
class ShapeSettings;
class BoxShapeSettings;
class CompoundShapeSettings;
class SphereShapeSettings;
}
namespace Nz
@ -35,7 +33,7 @@ namespace Nz
class NAZARA_JOLTPHYSICS3D_API JoltCollider3D
{
public:
JoltCollider3D() = default;
JoltCollider3D();
JoltCollider3D(const JoltCollider3D&) = delete;
JoltCollider3D(JoltCollider3D&&) = delete;
virtual ~JoltCollider3D();
@ -44,7 +42,7 @@ namespace Nz
virtual std::shared_ptr<StaticMesh> GenerateDebugMesh() const;
virtual JPH::ShapeSettings* GetShapeSettings() const = 0;
inline JPH::ShapeSettings* GetShapeSettings() const;
virtual JoltColliderType3D GetType() const = 0;
JoltCollider3D& operator=(const JoltCollider3D&) = delete;
@ -52,25 +50,28 @@ namespace Nz
static std::shared_ptr<JoltCollider3D> Build(const PrimitiveList& list);
protected:
template<typename T> const T* GetShapeSettingsAs() const;
template<typename T> void SetupShapeSettings(std::unique_ptr<T> shapeSettings);
private:
static std::shared_ptr<JoltCollider3D> CreateGeomFromPrimitive(const Primitive& primitive);
std::unique_ptr<JPH::ShapeSettings> m_shapeSettings;
};
/*********************************** Shapes ******************************************/
class NAZARA_JOLTPHYSICS3D_API JoltBoxCollider3D final : public JoltCollider3D
{
public:
JoltBoxCollider3D(const Vector3f& lengths, float convexRadius = 0.f);
~JoltBoxCollider3D();
~JoltBoxCollider3D() = default;
void BuildDebugMesh(std::vector<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
@ -79,12 +80,11 @@ namespace Nz
struct ChildCollider;
JoltCompoundCollider3D(std::vector<ChildCollider> childs);
~JoltCompoundCollider3D();
~JoltCompoundCollider3D() = default;
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
@ -95,7 +95,6 @@ namespace Nz
};
private:
std::unique_ptr<JPH::CompoundShapeSettings> m_shapeSettings;
std::vector<ChildCollider> m_childs;
};
@ -103,19 +102,32 @@ namespace Nz
{
public:
JoltSphereCollider3D(float radius);
~JoltSphereCollider3D();
~JoltSphereCollider3D() = default;
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;
};
/*********************************** Decorated ******************************************/
class NAZARA_JOLTPHYSICS3D_API JoltTranslatedRotatedCollider3D final : public JoltCollider3D
{
public:
inline JoltTranslatedRotatedCollider3D(std::shared_ptr<JoltCollider3D> collider, const Vector3f& translation);
inline JoltTranslatedRotatedCollider3D(std::shared_ptr<JoltCollider3D> collider, const Quaternionf& rotation);
JoltTranslatedRotatedCollider3D(std::shared_ptr<JoltCollider3D> collider, const Vector3f& translation, const Quaternionf& rotation);
~JoltTranslatedRotatedCollider3D() = default;
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
JoltColliderType3D GetType() const override;
private:
std::unique_ptr<JPH::SphereShapeSettings> m_shapeSettings;
Vector3f m_position;
float m_radius;
std::shared_ptr<JoltCollider3D> m_collider;
};
}
#include <Nazara/JoltPhysics3D/JoltCollider3D.inl>

View File

@ -2,11 +2,41 @@
// This file is part of the "Nazara Engine - JoltPhysics3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <NazaraUtils/Algorithm.hpp>
#include <memory>
#include <Nazara/JoltPhysics3D/Debug.hpp>
namespace Nz
{
inline JPH::ShapeSettings* JoltCollider3D::GetShapeSettings() const
{
return m_shapeSettings.get();
}
template<typename T>
const T* JoltCollider3D::GetShapeSettingsAs() const
{
return SafeCast<T*>(m_shapeSettings.get());
}
template<typename T>
void JoltCollider3D::SetupShapeSettings(std::unique_ptr<T> shapeSettings)
{
assert(!m_shapeSettings);
shapeSettings->SetEmbedded(); // Call SetEmbedded on the template type to prevent compiler to resolve it outside of a file including Jolt
m_shapeSettings = std::move(shapeSettings);
}
inline JoltTranslatedRotatedCollider3D::JoltTranslatedRotatedCollider3D(std::shared_ptr<JoltCollider3D> collider, const Vector3f& translation) :
JoltTranslatedRotatedCollider3D(std::move(collider), translation, Quaternionf::Identity())
{
}
inline JoltTranslatedRotatedCollider3D::JoltTranslatedRotatedCollider3D(std::shared_ptr<JoltCollider3D> collider, const Quaternionf& rotation) :
JoltTranslatedRotatedCollider3D(std::move(collider), Vector3f::Zero(), rotation)
{
}
}
#include <Nazara/JoltPhysics3D/DebugOff.hpp>

View File

@ -7,7 +7,7 @@
#ifndef NAZARA_JOLTPHYSICS3D_JOLTCONSTRAINT3D_HPP
#define NAZARA_JOLTPHYSICS3D_JOLTCONSTRAINT3D_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/BulletPhysics3D/BulletPhysWorld3D.hpp>
#include <Nazara/BulletPhysics3D/BulletRigidBody3D.hpp>
#include <Nazara/BulletPhysics3D/Config.hpp>

View File

@ -7,13 +7,15 @@
#ifndef NAZARA_JOLTPHYSICS3D_JOLTPHYSWORLD3D_HPP
#define NAZARA_JOLTPHYSICS3D_JOLTPHYSWORLD3D_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/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>
#include <NazaraUtils/FunctionRef.hpp>
#include <NazaraUtils/MovablePtr.hpp>
#include <atomic>
#include <vector>
namespace JPH
{
@ -22,10 +24,13 @@ namespace JPH
namespace Nz
{
class JoltCharacter;
class JoltRigidBody3D;
class NAZARA_JOLTPHYSICS3D_API JoltPhysWorld3D
{
friend JoltCharacter;
public:
struct RaycastHit;
@ -34,11 +39,14 @@ namespace Nz
JoltPhysWorld3D(JoltPhysWorld3D&& ph) = delete;
~JoltPhysWorld3D();
UInt32 GetActiveBodyCount() const;
Vector3f GetGravity() const;
std::size_t GetMaxStepCount() const;
JPH::PhysicsSystem* GetPhysicsSystem();
Time GetStepSize() const;
inline bool IsBodyActive(UInt32 bodyIndex) const;
bool RaycastQueryFirst(const Vector3f& from, const Vector3f& to, RaycastHit* hitInfo = nullptr);
void SetGravity(const Vector3f& gravity);
@ -59,14 +67,24 @@ namespace Nz
};
private:
class BodyActivationListener;
friend BodyActivationListener;
struct JoltWorld;
inline void RegisterCharacter(JoltCharacter* character);
inline void UnregisterCharacter(JoltCharacter* character);
std::size_t m_maxStepCount;
std::unique_ptr<std::atomic_uint64_t[]> m_activeBodies;
std::unique_ptr<JoltWorld> m_world;
std::vector<JoltCharacter*> m_characters;
Vector3f m_gravity;
Time m_stepSize;
Time m_timestepAccumulator;
};
}
#include <Nazara/JoltPhysics3D/JoltPhysWorld3D.inl>
#endif // NAZARA_JOLTPHYSICS3D_JOLTPHYSWORLD3D_HPP

View File

@ -0,0 +1,31 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - JoltPhysics3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/JoltPhysics3D/Debug.hpp>
namespace Nz
{
inline bool JoltPhysWorld3D::IsBodyActive(UInt32 bodyIndex) const
{
UInt32 blockIndex = bodyIndex / 64;
UInt32 localIndex = bodyIndex % 64;
return m_activeBodies[blockIndex] & (UInt64(1u) << localIndex);
}
inline void JoltPhysWorld3D::RegisterCharacter(JoltCharacter* character)
{
auto it = std::lower_bound(m_characters.begin(), m_characters.end(), character);
m_characters.insert(it, character);
}
inline void JoltPhysWorld3D::UnregisterCharacter(JoltCharacter* character)
{
auto it = std::lower_bound(m_characters.begin(), m_characters.end(), character);
assert(*it == character);
m_characters.erase(it);
}
}
#include <Nazara/JoltPhysics3D/DebugOff.hpp>

View File

@ -7,7 +7,7 @@
#ifndef NAZARA_JOLTPHYSICS3D_HPP
#define NAZARA_JOLTPHYSICS3D_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/JoltPhysics3D/Config.hpp>
#include <Nazara/Core/Core.hpp>
#include <memory>

View File

@ -7,14 +7,19 @@
#ifndef NAZARA_JOLTPHYSICS3D_JOLTRIGIDBODY3D_HPP
#define NAZARA_JOLTPHYSICS3D_JOLTRIGIDBODY3D_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/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>
#include <NazaraUtils/MovablePtr.hpp>
namespace JPH
{
class Body;
}
namespace Nz
{
@ -41,6 +46,7 @@ namespace Nz
Boxf GetAABB() const;
float GetAngularDamping() const;
Vector3f GetAngularVelocity() const;
inline UInt32 GetBodyIndex() const;
inline const std::shared_ptr<JoltCollider3D>& GetGeom() const;
float GetLinearDamping() const;
Vector3f GetLinearVelocity() const;
@ -48,6 +54,7 @@ namespace Nz
Vector3f GetMassCenter(CoordSys coordSys = CoordSys::Local) const;
Matrix4f GetMatrix() const;
Vector3f GetPosition() const;
std::pair<Vector3f, Quaternionf> GetPositionAndRotation() const;
Quaternionf GetRotation() const;
inline JoltPhysWorld3D* GetWorld() const;
@ -60,11 +67,13 @@ namespace Nz
void SetGeom(std::shared_ptr<JoltCollider3D> geom, bool recomputeInertia = true);
void SetLinearDamping(float damping);
void SetLinearVelocity(const Vector3f& velocity);
void SetMass(float mass);
void SetMass(float mass, bool recomputeInertia = true);
void SetMassCenter(const Vector3f& center);
void SetPosition(const Vector3f& position);
void SetRotation(const Quaternionf& rotation);
void TeleportTo(const Vector3f& position, const Quaternionf& rotation);
Quaternionf ToLocal(const Quaternionf& worldRotation);
Vector3f ToLocal(const Vector3f& worldPosition);
Quaternionf ToWorld(const Quaternionf& localRotation);
@ -80,6 +89,7 @@ namespace Nz
private:
std::shared_ptr<JoltCollider3D> m_geom;
JPH::Body* m_body;
JoltPhysWorld3D* m_world;
UInt32 m_bodyIndex;
};

View File

@ -11,6 +11,11 @@ namespace Nz
return EnableSleeping(false);
}
inline UInt32 JoltRigidBody3D::GetBodyIndex() const
{
return m_bodyIndex;
}
inline const std::shared_ptr<JoltCollider3D>& JoltRigidBody3D::GetGeom() const
{
return m_geom;

View File

@ -7,12 +7,12 @@
#ifndef NAZARA_JOLTPHYSICS3D_SYSTEMS_JOLTPHYSICS3DSYSTEM_HPP
#define NAZARA_JOLTPHYSICS3D_SYSTEMS_JOLTPHYSICS3DSYSTEM_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/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 <NazaraUtils/TypeList.hpp>
#include <entt/entt.hpp>
#include <vector>

View File

@ -10,7 +10,7 @@
#include <Nazara/Utility/SoftwareBuffer.hpp>
#include <Nazara/Utility/StaticMesh.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>
#include <Nazara/Utils/MemoryHelper.hpp>
#include <NazaraUtils/MemoryHelper.hpp>
#include <tsl/ordered_map.h>
#include <BulletCollision/CollisionShapes/btBoxShape.h>
#include <BulletCollision/CollisionShapes/btCapsuleShape.h>

View File

@ -7,7 +7,7 @@
#ifndef NAZARA_BULLETPHYSICS3D_BULLETHELPER_HPP
#define NAZARA_BULLETPHYSICS3D_BULLETHELPER_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/BulletPhysics3D/Config.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Math/Quaternion.hpp>

View File

@ -4,8 +4,8 @@
#include <Nazara/BulletPhysics3D/BulletPhysWorld3D.hpp>
#include <Nazara/BulletPhysics3D/BulletHelper.hpp>
#include <Nazara/Utils/MemoryPool.hpp>
#include <Nazara/Utils/StackVector.hpp>
#include <NazaraUtils/MemoryPool.hpp>
#include <NazaraUtils/StackVector.hpp>
#include <BulletCollision/BroadphaseCollision/btDbvtBroadphase.h>
#include <BulletCollision/CollisionDispatch/btCollisionDispatcher.h>
#include <BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h>

View File

@ -5,7 +5,7 @@
#include <Nazara/BulletPhysics3D/BulletRigidBody3D.hpp>
#include <Nazara/BulletPhysics3D/BulletHelper.hpp>
#include <Nazara/BulletPhysics3D/BulletPhysWorld3D.hpp>
#include <Nazara/Utils/MemoryHelper.hpp>
#include <NazaraUtils/MemoryHelper.hpp>
#include <BulletDynamics/Dynamics/btDynamicsWorld.h>
#include <BulletDynamics/Dynamics/btRigidBody.h>
#include <algorithm>

View File

@ -38,6 +38,7 @@ namespace Nz
std::cout << "Physics time: " << (m_physicsTime / Time::Nanoseconds(m_stepCount)) << std::endl;
std::cout << "Update time: " << (m_updateTime / Time::Nanoseconds(m_stepCount)) << std::endl;
std::cout << "Active body count: " << m_activeObjectCount << std::endl;
std::cout << "--" << std::endl;
m_stepCount = 0;
@ -81,14 +82,18 @@ namespace Nz
// Replicate rigid body position to their node components
// TODO: Only replicate active entities
m_activeObjectCount = 0;
auto view = m_registry.view<NodeComponent, const BulletRigidBody3DComponent>();
for (auto [entity, nodeComponent, rigidBodyComponent] : view.each())
for (auto entity : view)
{
auto& rigidBodyComponent = view.get<const BulletRigidBody3DComponent>(entity);
if (rigidBodyComponent.IsSleeping())
continue;
nodeComponent.SetPosition(rigidBodyComponent.GetPosition(), CoordSys::Global);
nodeComponent.SetRotation(rigidBodyComponent.GetRotation(), CoordSys::Global);
auto& nodeComponent = view.get<NodeComponent>(entity);
nodeComponent.SetTransform(rigidBodyComponent.GetPosition(), rigidBodyComponent.GetRotation());
m_activeObjectCount++;
}
Time t3 = GetElapsedNanoseconds();

View File

@ -0,0 +1,78 @@
// Copyright (C) 2023 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
// This file is part of the "Nazara Engine - JoltPhysics3D module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/JoltPhysics3D/JoltCharacter.hpp>
#include <Nazara/JoltPhysics3D/JoltCollider3D.hpp>
#include <Nazara/JoltPhysics3D/JoltHelper.hpp>
#include <Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp>
#include <Jolt/Jolt.h>
#include <Jolt/Physics/Collision/ObjectLayer.h>
#include <Jolt/Physics/Character/Character.h>
#include <Nazara/JoltPhysics3D/Debug.hpp>
namespace Nz
{
JoltCharacter::JoltCharacter(JoltPhysWorld3D& physWorld, std::shared_ptr<JoltCollider3D> collider, const Vector3f& position, const Quaternionf& rotation) :
m_collider(std::move(collider)),
m_physicsWorld(physWorld)
{
auto shapeResult = m_collider->GetShapeSettings()->Create();
if (!shapeResult.IsValid())
throw std::runtime_error("invalid shape");
JPH::CharacterSettings settings;
settings.mShape = shapeResult.Get();
m_character = std::make_unique<JPH::Character>(&settings, ToJolt(position), ToJolt(rotation), 0, m_physicsWorld.GetPhysicsSystem());
m_character->AddToPhysicsSystem();
m_physicsWorld.RegisterCharacter(this);
}
JoltCharacter::~JoltCharacter()
{
m_character->RemoveFromPhysicsSystem();
m_physicsWorld.UnregisterCharacter(this);
}
Vector3f JoltCharacter::GetLinearVelocity() const
{
return FromJolt(m_character->GetLinearVelocity());
}
Quaternionf JoltCharacter::GetRotation() const
{
return FromJolt(m_character->GetRotation());
}
Vector3f JoltCharacter::GetPosition() const
{
return FromJolt(m_character->GetPosition());
}
std::pair<Vector3f, Quaternionf> JoltCharacter::GetPositionAndRotation() const
{
JPH::Vec3 position;
JPH::Quat rotation;
m_character->GetPositionAndRotation(position, rotation);
return { FromJolt(position), FromJolt(rotation) };
}
bool JoltCharacter::IsOnGround() const
{
return m_character->IsSupported();
}
void JoltCharacter::SetLinearVelocity(const Vector3f& linearVel)
{
m_character->SetLinearVelocity(ToJolt(linearVel));
}
void JoltCharacter::PostSimulate()
{
m_character->PostSimulation(0.05f);
}
}

View File

@ -10,15 +10,17 @@
#include <Nazara/Utility/SoftwareBuffer.hpp>
#include <Nazara/Utility/StaticMesh.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>
#include <Nazara/Utils/MemoryHelper.hpp>
#include <NazaraUtils/MemoryHelper.hpp>
#include <Jolt/Core/Core.h>
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
#include <Jolt/Physics/Collision/Shape/RotatedTranslatedShape.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;
JoltCollider3D::~JoltCollider3D() = default;
std::shared_ptr<StaticMesh> JoltCollider3D::GenerateDebugMesh() const
@ -85,14 +87,11 @@ namespace Nz
/********************************** BoxCollider3D **********************************/
JoltBoxCollider3D::JoltBoxCollider3D(const Vector3f& lengths, float convexRadius) :
m_lengths(lengths)
JoltBoxCollider3D::JoltBoxCollider3D(const Vector3f& lengths, float convexRadius)
{
m_shapeSettings = std::make_unique<JPH::BoxShapeSettings>(ToJolt(m_lengths * 0.5f), convexRadius);
SetupShapeSettings(std::make_unique<JPH::BoxShapeSettings>(ToJolt(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
@ -102,7 +101,7 @@ namespace Nz
return index;
};
Vector3f halfLengths = m_lengths * 0.5f;
Vector3f halfLengths = FromJolt(GetShapeSettingsAs<JPH::BoxShapeSettings>()->mHalfExtent);
UInt16 v0 = InsertVertex(-halfLengths.x, -halfLengths.y, -halfLengths.z);
UInt16 v1 = InsertVertex(halfLengths.x, -halfLengths.y, -halfLengths.z);
@ -135,14 +134,9 @@ namespace Nz
InsertEdge(v3, v7);
}
JPH::ShapeSettings* JoltBoxCollider3D::GetShapeSettings() const
{
return m_shapeSettings.get();
}
Vector3f JoltBoxCollider3D::GetLengths() const
{
return m_lengths;
return FromJolt(GetShapeSettingsAs<JPH::BoxShapeSettings>()->mHalfExtent) * 2.f;
}
JoltColliderType3D JoltBoxCollider3D::GetType() const
@ -155,12 +149,12 @@ namespace Nz
JoltCompoundCollider3D::JoltCompoundCollider3D(std::vector<ChildCollider> childs) :
m_childs(std::move(childs))
{
m_shapeSettings = std::make_unique<JPH::StaticCompoundShapeSettings>();
auto shapeSettings = std::make_unique<JPH::StaticCompoundShapeSettings>();
for (const auto& child : m_childs)
m_shapeSettings->AddShape(ToJolt(child.offset), ToJolt(child.rotation), child.collider->GetShapeSettings());
}
shapeSettings->AddShape(ToJolt(child.offset), ToJolt(child.rotation), child.collider->GetShapeSettings());
JoltCompoundCollider3D::~JoltCompoundCollider3D() = default;
SetupShapeSettings(std::move(shapeSettings));
}
void JoltCompoundCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
{
@ -173,11 +167,6 @@ namespace Nz
return m_childs;
}
JPH::ShapeSettings* JoltCompoundCollider3D::GetShapeSettings() const
{
return m_shapeSettings.get();
}
JoltColliderType3D JoltCompoundCollider3D::GetType() const
{
return JoltColliderType3D::Compound;
@ -185,30 +174,40 @@ namespace Nz
/******************************** JoltSphereCollider3D *********************************/
JoltSphereCollider3D::JoltSphereCollider3D(float radius) :
m_radius(radius)
JoltSphereCollider3D::JoltSphereCollider3D(float radius)
{
m_shapeSettings = std::make_unique<JPH::SphereShapeSettings>(radius);
SetupShapeSettings(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();
return GetShapeSettingsAs<JPH::SphereShapeSettings>()->mRadius;
}
JoltColliderType3D JoltSphereCollider3D::GetType() const
{
return JoltColliderType3D::Sphere;
}
JoltTranslatedRotatedCollider3D::JoltTranslatedRotatedCollider3D(std::shared_ptr<JoltCollider3D> collider, const Vector3f& translation, const Quaternionf& rotation) :
m_collider(std::move(collider))
{
SetupShapeSettings(std::make_unique<JPH::RotatedTranslatedShapeSettings>(ToJolt(translation), ToJolt(rotation), m_collider->GetShapeSettings()));
}
void JoltTranslatedRotatedCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
{
const JPH::RotatedTranslatedShapeSettings* settings = GetShapeSettingsAs<JPH::RotatedTranslatedShapeSettings>();
m_collider->BuildDebugMesh(vertices, indices, offsetMatrix * Matrix4f::Transform(FromJolt(settings->mPosition), FromJolt(settings->mRotation)));
}
JoltColliderType3D JoltTranslatedRotatedCollider3D::GetType() const
{
return JoltColliderType3D::TranslatedRotatedDecoration;
}
}

View File

@ -7,7 +7,7 @@
#ifndef NAZARA_JOLTPHYSICS3D_JOLTHELPER_HPP
#define NAZARA_JOLTPHYSICS3D_JOLTHELPER_HPP
#include <Nazara/Prerequisites.hpp>
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/BulletPhysics3D/Config.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Math/Quaternion.hpp>

View File

@ -3,11 +3,12 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp>
#include <Nazara/JoltPhysics3D/JoltCharacter.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 <NazaraUtils/MemoryPool.hpp>
#include <NazaraUtils/StackVector.hpp>
#include <Jolt/Jolt.h>
#include <Jolt/Core/TempAllocator.h>
#include <Jolt/Physics/Collision/ObjectLayer.h>
@ -152,37 +153,59 @@ namespace DitchMeAsap
cout << "A contact was removed" << endl;
}
};
// An example activation listener
class MyBodyActivationListener : public BodyActivationListener
{
public:
virtual void OnBodyActivated(const BodyID& inBodyID, uint64 inBodyUserData) override
{
cout << "A body got activated" << endl;
}
virtual void OnBodyDeactivated(const BodyID& inBodyID, uint64 inBodyUserData) override
{
cout << "A body went to sleep" << endl;
}
};
}
namespace Nz
{
class JoltPhysWorld3D::BodyActivationListener : public JPH::BodyActivationListener
{
public:
static constexpr UInt32 BodyPerBlock = 64;
BodyActivationListener(JoltPhysWorld3D& physWorld) :
m_physWorld(physWorld)
{
}
void OnBodyActivated(const JPH::BodyID& inBodyID, UInt64 inBodyUserData) override
{
UInt32 bodyIndex = inBodyID.GetIndex();
UInt32 blockIndex = bodyIndex / 64;
UInt32 localIndex = bodyIndex % 64;
m_physWorld.m_activeBodies[blockIndex] |= UInt64(1u) << localIndex;
}
void OnBodyDeactivated(const JPH::BodyID& inBodyID, UInt64 inBodyUserData) override
{
UInt32 bodyIndex = inBodyID.GetIndex();
UInt32 blockIndex = bodyIndex / 64;
UInt32 localIndex = bodyIndex % 64;
m_physWorld.m_activeBodies[blockIndex] &= ~(UInt64(1u) << localIndex);
}
private:
JoltPhysWorld3D& m_physWorld;
};
struct JoltPhysWorld3D::JoltWorld
{
JPH::TempAllocatorMalloc tempAllocation;
JPH::TempAllocatorImpl tempAllocator;
JPH::PhysicsSystem physicsSystem;
JoltPhysWorld3D::BodyActivationListener bodyActivationListener;
DitchMeAsap::BPLayerInterfaceImpl layerInterface;
DitchMeAsap::ObjectLayerPairFilterImpl objectLayerFilter;
DitchMeAsap::ObjectVsBroadPhaseLayerFilterImpl objectBroadphaseLayerFilter;
DitchMeAsap::MyBodyActivationListener bodyActivationListener;
DitchMeAsap::MyContactListener contactListener;
JoltWorld() = default;
JoltWorld(JoltPhysWorld3D& world, JPH::uint tempAllocatorSize) :
tempAllocator(tempAllocatorSize),
bodyActivationListener(world)
{
}
JoltWorld(const JoltWorld&) = delete;
JoltWorld(JoltWorld&&) = delete;
@ -196,14 +219,23 @@ namespace Nz
m_stepSize(Time::TickDuration(120)),
m_timestepAccumulator(Time::Zero())
{
m_world = std::make_unique<JoltWorld>();
m_world->physicsSystem.Init(0xFFFF, 0, 0xFFFF, 0xFFFF, m_world->layerInterface, m_world->objectBroadphaseLayerFilter, m_world->objectLayerFilter);
m_world = std::make_unique<JoltWorld>(*this, 10 * 1024 * 1024);
m_world->physicsSystem.Init(0xFFFF, 0, 0xFFFF, 10 * 1024, m_world->layerInterface, m_world->objectBroadphaseLayerFilter, m_world->objectLayerFilter);
m_world->physicsSystem.SetBodyActivationListener(&m_world->bodyActivationListener);
//m_world->physicsSystem.SetContactListener(&m_world->contactListener);
std::size_t blockCount = (m_world->physicsSystem.GetMaxBodies() - 1) / 64 + 1;
m_activeBodies = std::make_unique<std::atomic_uint64_t[]>(blockCount);
for (std::size_t i = 0; i < blockCount; ++i)
m_activeBodies[i] = 0;
}
JoltPhysWorld3D::~JoltPhysWorld3D() = default;
UInt32 JoltPhysWorld3D::GetActiveBodyCount() const
{
return m_world->physicsSystem.GetNumActiveBodies();
}
Vector3f JoltPhysWorld3D::GetGravity() const
{
return FromJolt(m_world->physicsSystem.GetGravity());
@ -280,7 +312,11 @@ namespace Nz
std::size_t stepCount = 0;
while (m_timestepAccumulator >= m_stepSize && stepCount < m_maxStepCount)
{
m_world->physicsSystem.Update(stepSize, 1, 1, &m_world->tempAllocation, &jobSystem);
m_world->physicsSystem.Update(stepSize, 1, 1, &m_world->tempAllocator, &jobSystem);
for (JoltCharacter* character : m_characters)
character->PostSimulate();
m_timestepAccumulator -= m_stepSize;
stepCount++;
}

View File

@ -40,14 +40,18 @@ namespace Nz
JPH::Factory::sInstance = new JPH::Factory;
JPH::RegisterTypes();
m_threadPool = std::make_unique<JPH::JobSystemThreadPool>(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, /* Core::Instance()->GetHardwareInfo().GetCpuThreadCount()*/0);
int threadCount = -1; //< system CPU core count
#ifdef NAZARA_PLATFORM_WEB
threadCount = 0; // no thread on web for now
#endif
m_threadPool = std::make_unique<JPH::JobSystemThreadPool>(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, threadCount);
}
JoltPhysics3D::~JoltPhysics3D()
{
m_threadPool.reset();
// FIXME: Uncomment when next version of Jolt gets released
//JPH::UnregisterTypes();
JPH::UnregisterTypes();
delete JPH::Factory::sInstance;
JPH::Factory::sInstance = nullptr;

View File

@ -6,7 +6,7 @@
#include <Nazara/JoltPhysics3D/JoltHelper.hpp>
#include <Nazara/JoltPhysics3D/JoltPhysWorld3D.hpp>
#include <Nazara/JoltPhysics3D/JoltRigidBody3D.hpp>
#include <Nazara/Utils/MemoryHelper.hpp>
#include <NazaraUtils/MemoryHelper.hpp>
#include <Jolt/Jolt.h>
#include <Jolt/Physics/PhysicsSystem.h>
#include <Jolt/Physics/Body/BodyCreationSettings.h>
@ -29,28 +29,32 @@ namespace Nz
NazaraAssert(m_world, "Invalid world");
if (!m_geom)
m_geom = std::make_shared<JoltSphereCollider3D>(1.f);
m_geom = std::make_shared<JoltSphereCollider3D>(std::numeric_limits<float>::epsilon());
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface();
JPH::Vec3 position = ToJolt(mat.GetTranslation());
JPH::Quat rotation = ToJolt(mat.GetRotation().Normalize());
JPH::BodyCreationSettings settings(m_geom->GetShapeSettings(), position, rotation, JPH::EMotionType::Dynamic, 1);
JPH::Body* body = body_interface.CreateBody(settings);
body->SetUserData(SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
m_body = bodyInterface.CreateBody(settings);
m_body->SetUserData(SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
body_interface.AddBody(body->GetID(), JPH::EActivation::Activate);
m_bodyIndex = body->GetID().GetIndexAndSequenceNumber();
JPH::BodyID bodyId = m_body->GetID();
bodyInterface.AddBody(bodyId, JPH::EActivation::Activate);
m_bodyIndex = bodyId.GetIndex();
}
JoltRigidBody3D::JoltRigidBody3D(JoltRigidBody3D&& object) noexcept :
m_geom(std::move(object.m_geom)),
m_body(object.m_body),
m_bodyIndex(object.m_bodyIndex),
m_world(object.m_world)
{
object.m_bodyIndex = JPH::BodyID::cInvalidBodyID;
object.m_body = nullptr;
object.m_bodyIndex = std::numeric_limits<UInt32>::max();
}
JoltRigidBody3D::~JoltRigidBody3D()
@ -64,16 +68,12 @@ namespace Nz
{
case CoordSys::Global:
{
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
body_interface.AddForce(JPH::BodyID(m_bodyIndex), ToJolt(force));
//WakeUp();
//m_body->applyCentralForce(ToJolt(force));
m_body->AddForce(ToJolt(force));
break;
}
case CoordSys::Local:
//WakeUp();
//m_body->applyCentralForce(ToJolt(GetRotation() * force));
m_body->AddForce(m_body->GetRotation() * ToJolt(force));
break;
}
}
@ -115,13 +115,7 @@ namespace Nz
#endif
void JoltRigidBody3D::EnableSleeping(bool enable)
{
auto& body_interface = m_world->GetPhysicsSystem()->GetBodyLockInterface();
JPH::BodyLockWrite lock(body_interface, JPH::BodyID(m_bodyIndex));
if (lock.Succeeded())
{
JPH::Body& body = lock.GetBody();
body.SetAllowSleeping(enable);
}
m_body->SetAllowSleeping(enable);
}
#if 0
@ -162,13 +156,7 @@ namespace Nz
float JoltRigidBody3D::GetMass() const
{
auto& body_interface = m_world->GetPhysicsSystem()->GetBodyLockInterface();
JPH::BodyLockRead lock(body_interface, JPH::BodyID(m_bodyIndex));
if (!lock.Succeeded())
return 0.f;
const JPH::Body& body = lock.GetBody();
return 1.f / body.GetMotionProperties()->GetInverseMass();
return 1.f / m_body->GetMotionProperties()->GetInverseMass();
}
#if 0
Vector3f JoltRigidBody3D::GetMassCenter(CoordSys coordSys) const
@ -184,14 +172,20 @@ namespace Nz
Vector3f JoltRigidBody3D::GetPosition() const
{
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
return FromJolt(body_interface.GetPosition(JPH::BodyID(m_bodyIndex)));
return FromJolt(m_body->GetPosition());
}
std::pair<Vector3f, Quaternionf> JoltRigidBody3D::GetPositionAndRotation() const
{
JPH::Vec3 position = m_body->GetPosition();
JPH::Quat rotation = m_body->GetRotation();
return { FromJolt(position), FromJolt(rotation) };
}
Quaternionf JoltRigidBody3D::GetRotation() const
{
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
return FromJolt(body_interface.GetRotation(JPH::BodyID(m_bodyIndex)));
return FromJolt(m_body->GetRotation());
}
#if 0
@ -203,19 +197,12 @@ namespace Nz
bool JoltRigidBody3D::IsSleeping() const
{
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
return !body_interface.IsActive(JPH::BodyID(m_bodyIndex));
return m_body->IsActive();
}
bool JoltRigidBody3D::IsSleepingEnabled() const
{
auto& body_interface = m_world->GetPhysicsSystem()->GetBodyLockInterface();
JPH::BodyLockRead lock(body_interface, JPH::BodyID(m_bodyIndex));
if (!lock.Succeeded())
return true;
const JPH::Body& body = lock.GetBody();
return body.GetAllowSleeping();
return m_body->GetAllowSleeping();
}
#if 0
@ -233,72 +220,79 @@ namespace Nz
{
if (m_geom != geom)
{
float mass = GetMass();
if (geom)
m_geom = std::move(geom);
else
m_geom = std::make_shared<JoltSphereCollider3D>(1.f);
m_geom = std::make_shared<JoltSphereCollider3D>(std::numeric_limits<float>::epsilon());
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
body_interface.SetShape(JPH::BodyID(m_bodyIndex), m_geom->GetShapeSettings()->Create().Get(), true, JPH::EActivation::Activate);
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface();
bodyInterface.SetShape(m_body->GetID(), m_geom->GetShapeSettings()->Create().Get(), false, JPH::EActivation::Activate);
if (recomputeInertia)
{
JPH::MassProperties massProperties = m_body->GetShape()->GetMassProperties();
massProperties.ScaleToMass(mass);
m_body->GetMotionProperties()->SetMassProperties(massProperties);
}
}
}
#if 0
void JoltRigidBody3D::SetLinearDamping(float damping)
{
m_body->setDamping(damping, m_body->getAngularDamping());
m_body->GetMotionProperties()->SetLinearDamping(damping);
}
void JoltRigidBody3D::SetLinearVelocity(const Vector3f& velocity)
{
m_body->setLinearVelocity(ToJolt(velocity));
m_body->SetLinearVelocity(ToJolt(velocity));
}
#endif 0
void JoltRigidBody3D::SetMass(float mass)
void JoltRigidBody3D::SetMass(float mass, bool recomputeInertia)
{
NazaraAssert(mass >= 0.f, "Mass must be positive and finite");
NazaraAssert(std::isfinite(mass), "Mass must be positive and finite");
auto& bodyLock = m_world->GetPhysicsSystem()->GetBodyLockInterface();
JPH::BodyLockWrite lock(bodyLock, JPH::BodyID(m_bodyIndex));
if (!lock.Succeeded())
return;
JPH::Body& body = lock.GetBody();
if (mass > 0.f)
{
body.SetMotionType(JPH::EMotionType::Dynamic);
body.GetMotionProperties()->SetInverseMass(1.f / mass);
m_body->SetMotionType(JPH::EMotionType::Dynamic);
if (recomputeInertia)
{
JPH::MassProperties massProperties = m_body->GetShape()->GetMassProperties();
massProperties.ScaleToMass(mass);
m_body->GetMotionProperties()->SetMassProperties(massProperties);
}
}
else
{
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
bodyInterface.DeactivateBody(m_body->GetID());
body_interface.DeactivateBody(body.GetID());
body.SetMotionType(JPH::EMotionType::Static);
m_body->SetMotionType(JPH::EMotionType::Static);
}
}
#if 0
void JoltRigidBody3D::SetMassCenter(const Vector3f& center)
{
btTransform centerTransform;
centerTransform.setIdentity();
centerTransform.setOrigin(ToJolt(center));
m_body->setCenterOfMassTransform(centerTransform);
//m_body->GetMotionProperties()->set
}
#endif 0
void JoltRigidBody3D::SetPosition(const Vector3f& position)
{
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
body_interface.SetPosition(JPH::BodyID(m_bodyIndex), ToJolt(position), JPH::EActivation::Activate);
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
bodyInterface.SetPosition(m_body->GetID(), ToJolt(position), JPH::EActivation::Activate);
}
void JoltRigidBody3D::SetRotation(const Quaternionf& rotation)
{
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
body_interface.SetRotation(JPH::BodyID(m_bodyIndex), ToJolt(rotation), JPH::EActivation::Activate);
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
body_interface.SetRotation(m_body->GetID(), ToJolt(rotation), JPH::EActivation::Activate);
}
void JoltRigidBody3D::TeleportTo(const Vector3f& position, const Quaternionf& rotation)
{
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterfaceNoLock();
bodyInterface.SetPositionAndRotation(m_body->GetID(), ToJolt(position), ToJolt(rotation), JPH::EActivation::Activate);
}
#if 0
@ -327,30 +321,34 @@ namespace Nz
void JoltRigidBody3D::WakeUp()
{
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
body_interface.ActivateBody(JPH::BodyID(m_bodyIndex));
body_interface.ActivateBody(m_body->GetID());
}
JoltRigidBody3D& JoltRigidBody3D::operator=(JoltRigidBody3D&& object) noexcept
{
Destroy();
m_body = object.m_body;
m_bodyIndex = object.m_bodyIndex;
m_geom = std::move(object.m_geom);
m_world = object.m_world;
object.m_bodyIndex = JPH::BodyID::cInvalidBodyID;
object.m_body = nullptr;
object.m_bodyIndex = std::numeric_limits<UInt32>::max();
return *this;
}
void JoltRigidBody3D::Destroy()
{
if (m_bodyIndex != JPH::BodyID::cInvalidBodyID)
if (m_body)
{
JPH::BodyInterface& body_interface = m_world->GetPhysicsSystem()->GetBodyInterface();
body_interface.RemoveBody(JPH::BodyID(m_bodyIndex));
body_interface.DestroyBody(JPH::BodyID(m_bodyIndex));
m_bodyIndex = JPH::BodyID::cInvalidBodyID;
JPH::BodyID bodyId = m_body->GetID();
JPH::BodyInterface& bodyInterface = m_world->GetPhysicsSystem()->GetBodyInterface();
bodyInterface.RemoveBody(bodyId);
bodyInterface.DestroyBody(bodyId);
m_body = nullptr;
}
m_geom.reset();

View File

@ -37,7 +37,8 @@ namespace Nz
m_stepCount = 1;
std::cout << "Physics time: " << (m_physicsTime / Time::Nanoseconds(m_stepCount)) << std::endl;
std::cout << "Update time: " << (m_updateTime / Time::Nanoseconds(m_stepCount)) << std::endl;
std::cout << "Replication time: " << (m_updateTime / Time::Nanoseconds(m_stepCount)) << std::endl;
std::cout << "Active entity count: " << m_physWorld.GetActiveBodyCount() << std::endl;
std::cout << "--" << std::endl;
m_stepCount = 0;
@ -68,8 +69,7 @@ namespace Nz
JoltRigidBody3DComponent& entityPhysics = m_registry.get<JoltRigidBody3DComponent>(entity);
NodeComponent& entityNode = m_registry.get<NodeComponent>(entity);
entityPhysics.SetPosition(entityNode.GetPosition(CoordSys::Global));
entityPhysics.SetRotation(entityNode.GetRotation(CoordSys::Global));
entityPhysics.TeleportTo(entityNode.GetPosition(), entityNode.GetRotation());
});
Time t1 = GetElapsedNanoseconds();
@ -80,16 +80,18 @@ namespace Nz
Time t2 = GetElapsedNanoseconds();
// Replicate rigid body position to their node components
// TODO: Only replicate active entities
// Replicate active rigid body position to their node components
auto view = m_registry.view<NodeComponent, const JoltRigidBody3DComponent>();
for (auto [entity, nodeComponent, rigidBodyComponent] : view.each())
for (auto entity : view)
{
if (rigidBodyComponent.IsSleeping())
auto& rigidBodyComponent = view.get<const JoltRigidBody3DComponent>(entity);
if (!m_physWorld.IsBodyActive(rigidBodyComponent.GetBodyIndex()))
continue;
nodeComponent.SetPosition(rigidBodyComponent.GetPosition(), CoordSys::Global);
nodeComponent.SetRotation(rigidBodyComponent.GetRotation(), CoordSys::Global);
auto& nodeComponent = view.get<NodeComponent>(entity);
auto [position, rotation] = rigidBodyComponent.GetPositionAndRotation();
nodeComponent.SetTransform(position, rotation);
}
Time t3 = GetElapsedNanoseconds();
@ -100,9 +102,22 @@ namespace Nz
void JoltPhysics3DSystem::OnConstruct(entt::registry& registry, entt::entity entity)
{
// Register rigid body owning entity
JoltRigidBody3DComponent& rigidBody = registry.get<JoltRigidBody3DComponent>(entity);
std::size_t uniqueIndex = rigidBody.GetBodyIndex();
if (uniqueIndex >= m_physicsEntities.size())
m_physicsEntities.resize(uniqueIndex + 1);
m_physicsEntities[uniqueIndex] = entity;
}
void JoltPhysics3DSystem::OnDestruct(entt::registry& registry, entt::entity entity)
{
// Unregister owning entity
JoltRigidBody3DComponent& rigidBody = registry.get<JoltRigidBody3DComponent>(entity);
std::size_t uniqueIndex = rigidBody.GetBodyIndex();
assert(uniqueIndex <= m_physicsEntities.size());
m_physicsEntities[uniqueIndex] = entt::null;
}
}

View File

@ -262,6 +262,44 @@ namespace Nz
Invalidate(invalidation);
}
void Node::SetTransform(const Vector3f& position, const Quaternionf& rotation, CoordSys coordSys, Invalidation invalidation)
{
switch (coordSys)
{
case CoordSys::Global:
{
// Position
if (m_parent && m_inheritPosition)
{
m_parent->EnsureDerivedUpdate();
m_position = (m_parent->m_derivedRotation.GetConjugate() * (position - m_parent->m_derivedPosition)) / m_parent->m_derivedScale - m_initialPosition;
}
else
m_position = position - m_initialPosition;
// Rotation
if (m_parent && m_inheritRotation)
{
Quaternionf rot(m_parent->GetRotation() * m_initialRotation);
m_rotation = rot.GetConjugate() * rotation;
}
else
m_rotation = rotation;
break;
}
case CoordSys::Local:
m_position = position;
m_rotation = rotation;
break;
}
Invalidate(invalidation);
}
void Node::SetTransform(const Vector3f& position, const Quaternionf& rotation, const Vector3f& scale, CoordSys coordSys, Invalidation invalidation)
{
switch (coordSys)

View File

@ -238,7 +238,7 @@ add_requires(
"minimp3",
"ordered_map",
"stb")
add_requires("joltphysics master", { configs = { debug = is_mode("debug") } })
add_requires("joltphysics 352550fdd562ce6034b27ab12d1470840e879b56", { configs = { debug = is_mode("debug") }})
add_requires("freetype", { configs = { bzip2 = true, png = true, woff2 = true, zlib = true, debug = is_mode("debug") } })
add_requires("libvorbis", { configs = { with_vorbisenc = false } })