Add JoltPhysics3D for a performance test

This commit is contained in:
SirLynix
2023-03-15 13:44:58 +01:00
committed by Jérôme Leclercq
parent bd4c2d6ee7
commit c5ac142888
40 changed files with 2555 additions and 95 deletions

View File

@@ -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;
}

View File

@@ -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
}
}

View File

@@ -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();

View File

@@ -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)