diff --git a/include/Nazara/JoltPhysics3D/Enums.hpp b/include/Nazara/JoltPhysics3D/Enums.hpp index 0f57e9032..8423197c9 100644 --- a/include/Nazara/JoltPhysics3D/Enums.hpp +++ b/include/Nazara/JoltPhysics3D/Enums.hpp @@ -12,13 +12,14 @@ namespace Nz enum class JoltColliderType3D { Box, + Capsule, Compound, Sphere, - TranslatedRotatedDecoration, ScaleDecoration, + TranslatedRotatedDecoration, - Max = Sphere + Max = TranslatedRotatedDecoration }; } diff --git a/include/Nazara/JoltPhysics3D/JoltCollider3D.hpp b/include/Nazara/JoltPhysics3D/JoltCollider3D.hpp index 5fce14bb0..8e1360961 100644 --- a/include/Nazara/JoltPhysics3D/JoltCollider3D.hpp +++ b/include/Nazara/JoltPhysics3D/JoltCollider3D.hpp @@ -74,7 +74,20 @@ namespace Nz Vector3f GetLengths() const; JoltColliderType3D GetType() const override; }; - + + class NAZARA_JOLTPHYSICS3D_API JoltCapsuleCollider3D final : public JoltCollider3D + { + public: + JoltCapsuleCollider3D(float height, float radius); + ~JoltCapsuleCollider3D() = default; + + void BuildDebugMesh(std::vector& vertices, std::vector& indices, const Matrix4f& offsetMatrix) const override; + + float GetHeight() const; + float GetRadius() const; + JoltColliderType3D GetType() const override; + }; + class NAZARA_JOLTPHYSICS3D_API JoltCompoundCollider3D final : public JoltCollider3D { public: diff --git a/src/Nazara/JoltPhysics3D/JoltCollider3D.cpp b/src/Nazara/JoltPhysics3D/JoltCollider3D.cpp index eaf34a9df..b6c886b52 100644 --- a/src/Nazara/JoltPhysics3D/JoltCollider3D.cpp +++ b/src/Nazara/JoltPhysics3D/JoltCollider3D.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -90,7 +91,7 @@ namespace Nz return std::shared_ptr(); } - /********************************** BoxCollider3D **********************************/ + /********************************** JoltBoxCollider3D **********************************/ JoltBoxCollider3D::JoltBoxCollider3D(const Vector3f& lengths, float convexRadius) { @@ -149,6 +150,94 @@ namespace Nz return JoltColliderType3D::Box; } + /********************************** JoltCapsuleCollider3D **********************************/ + + JoltCapsuleCollider3D::JoltCapsuleCollider3D(float height, float radius) + { + SetupShapeSettings(std::make_unique(height * 0.5f, radius)); + } + + void JoltCapsuleCollider3D::BuildDebugMesh(std::vector& vertices, std::vector& indices, const Matrix4f& offsetMatrix) const + { + constexpr unsigned int cornerStepCount = 10; + constexpr unsigned int sliceCount = 4; + + const JPH::CapsuleShapeSettings* capsuleSettings = GetShapeSettingsAs(); + float radius = capsuleSettings->mRadius; + float halfHeight = capsuleSettings->mHalfHeightOfCylinder; + + std::optional firstVertex; + std::optional lastVertex; + + for (unsigned int slice = 0; slice < sliceCount; ++slice) + { + Quaternionf rot(RadianAnglef(2.f * Pi * 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 * 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 * 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()->mHalfHeightOfCylinder * 2.0f; + } + + float JoltCapsuleCollider3D::GetRadius() const + { + return GetShapeSettingsAs()->mRadius; + } + + JoltColliderType3D JoltCapsuleCollider3D::GetType() const + { + return JoltColliderType3D::Capsule; + } + /******************************* JoltCompoundCollider3D ********************************/ JoltCompoundCollider3D::JoltCompoundCollider3D(std::vector childs) :