JoltPhysics3D: Add capsule collider

This commit is contained in:
SirLynix 2023-03-30 13:22:40 +02:00 committed by Jérôme Leclercq
parent a4ba7d6115
commit 1387ac6e35
3 changed files with 107 additions and 4 deletions

View File

@ -12,13 +12,14 @@ namespace Nz
enum class JoltColliderType3D enum class JoltColliderType3D
{ {
Box, Box,
Capsule,
Compound, Compound,
Sphere, Sphere,
TranslatedRotatedDecoration,
ScaleDecoration, ScaleDecoration,
TranslatedRotatedDecoration,
Max = Sphere Max = TranslatedRotatedDecoration
}; };
} }

View File

@ -75,6 +75,19 @@ namespace Nz
JoltColliderType3D GetType() const override; JoltColliderType3D GetType() const override;
}; };
class NAZARA_JOLTPHYSICS3D_API JoltCapsuleCollider3D final : public JoltCollider3D
{
public:
JoltCapsuleCollider3D(float height, float radius);
~JoltCapsuleCollider3D() = default;
void BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const override;
float GetHeight() const;
float GetRadius() const;
JoltColliderType3D GetType() const override;
};
class NAZARA_JOLTPHYSICS3D_API JoltCompoundCollider3D final : public JoltCollider3D class NAZARA_JOLTPHYSICS3D_API JoltCompoundCollider3D final : public JoltCollider3D
{ {
public: public:

View File

@ -13,6 +13,7 @@
#include <NazaraUtils/MemoryHelper.hpp> #include <NazaraUtils/MemoryHelper.hpp>
#include <Jolt/Core/Core.h> #include <Jolt/Core/Core.h>
#include <Jolt/Physics/Collision/Shape/BoxShape.h> #include <Jolt/Physics/Collision/Shape/BoxShape.h>
#include <Jolt/Physics/Collision/Shape/CapsuleShape.h>
#include <Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h> #include <Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h>
#include <Jolt/Physics/Collision/Shape/StaticCompoundShape.h> #include <Jolt/Physics/Collision/Shape/StaticCompoundShape.h>
#include <Jolt/Physics/Collision/Shape/SphereShape.h> #include <Jolt/Physics/Collision/Shape/SphereShape.h>
@ -90,7 +91,7 @@ namespace Nz
return std::shared_ptr<JoltCollider3D>(); return std::shared_ptr<JoltCollider3D>();
} }
/********************************** BoxCollider3D **********************************/ /********************************** JoltBoxCollider3D **********************************/
JoltBoxCollider3D::JoltBoxCollider3D(const Vector3f& lengths, float convexRadius) JoltBoxCollider3D::JoltBoxCollider3D(const Vector3f& lengths, float convexRadius)
{ {
@ -149,6 +150,94 @@ namespace Nz
return JoltColliderType3D::Box; return JoltColliderType3D::Box;
} }
/********************************** JoltCapsuleCollider3D **********************************/
JoltCapsuleCollider3D::JoltCapsuleCollider3D(float height, float radius)
{
SetupShapeSettings(std::make_unique<JPH::CapsuleShapeSettings>(height * 0.5f, radius));
}
void JoltCapsuleCollider3D::BuildDebugMesh(std::vector<Vector3f>& vertices, std::vector<UInt16>& indices, const Matrix4f& offsetMatrix) const
{
constexpr unsigned int cornerStepCount = 10;
constexpr unsigned int sliceCount = 4;
const JPH::CapsuleShapeSettings* capsuleSettings = GetShapeSettingsAs<JPH::CapsuleShapeSettings>();
float radius = capsuleSettings->mRadius;
float halfHeight = capsuleSettings->mHalfHeightOfCylinder;
std::optional<std::size_t> firstVertex;
std::optional<std::size_t> lastVertex;
for (unsigned int slice = 0; slice < sliceCount; ++slice)
{
Quaternionf rot(RadianAnglef(2.f * Pi<float> * slice / sliceCount), Nz::Vector3f::Down());
Vector3f top(0.f, halfHeight, 0.f);
for (unsigned int i = 0; i < cornerStepCount; ++i)
{
auto [sin, cos] = RadianAnglef(0.5f * Pi<float> * i / cornerStepCount).GetSinCos();
std::size_t index;
if (firstVertex && i == 0)
index = *firstVertex;
else
{
index = vertices.size();
vertices.push_back(top + rot * (radius * Vector3f(sin, cos, 0.f)));
if (i == 0)
firstVertex = index;
}
if (i > 1)
{
indices.push_back(index - 1);
indices.push_back(index);
}
else if (i == 1)
{
indices.push_back(*firstVertex);
indices.push_back(index);
}
}
Vector3f bottom(0.f, -halfHeight, 0.f);
for (unsigned int i = 0; i < cornerStepCount; ++i)
{
auto [sin, cos] = RadianAnglef(0.5f * Pi<float> * i / cornerStepCount).GetSinCos();
std::size_t index;
if (lastVertex && i == sliceCount - 1)
index = *lastVertex;
else
{
index = vertices.size();
vertices.push_back(bottom - rot * (radius * Vector3f(-cos, sin, 0.f)));
if (i == sliceCount - 1)
lastVertex = index;
}
indices.push_back(index - 1);
indices.push_back(index);
}
}
}
float JoltCapsuleCollider3D::GetHeight() const
{
return GetShapeSettingsAs<JPH::CapsuleShapeSettings>()->mHalfHeightOfCylinder * 2.0f;
}
float JoltCapsuleCollider3D::GetRadius() const
{
return GetShapeSettingsAs<JPH::CapsuleShapeSettings>()->mRadius;
}
JoltColliderType3D JoltCapsuleCollider3D::GetType() const
{
return JoltColliderType3D::Capsule;
}
/******************************* JoltCompoundCollider3D ********************************/ /******************************* JoltCompoundCollider3D ********************************/
JoltCompoundCollider3D::JoltCompoundCollider3D(std::vector<ChildCollider> childs) : JoltCompoundCollider3D::JoltCompoundCollider3D(std::vector<ChildCollider> childs) :