diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp
index b57249de..ae8c62b2 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp
@@ -207,6 +207,11 @@ namespace SHADE
drawSphere(getMeshBatch(true, depthTested), matrix, color);
}
+ void SHDebugDrawSystem::DrawWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color, bool depthTested)
+ {
+ drawWireCapsule(getLineBatch(depthTested), getMeshBatch(false, depthTested), position, rotation, height, radius, color);
+ }
+
/*-----------------------------------------------------------------------------------*/
/* Persistent Draw Functions */
/*-----------------------------------------------------------------------------------*/
@@ -264,6 +269,12 @@ namespace SHADE
markPersistentDrawsDirty();
}
+ void SHDebugDrawSystem::DrawPersistentWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color, bool depthTested)
+ {
+ drawWireCapsule(getPersistentLineBatch(depthTested), getPersistentMeshBatch(false, depthTested), position, rotation, height, radius, color);
+ markPersistentDrawsDirty();
+ }
+
void SHDebugDrawSystem::ClearPersistentDraws()
{
for (auto& batch : persistentLineBatches)
@@ -348,6 +359,53 @@ namespace SHADE
);
}
+ void SHDebugDrawSystem::drawWireCapsule(LinesBatch& lineBatch, MeshBatch& meshBatch, const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color)
+ {
+ // Get local axis vectors
+ const SHVec3 LOCAL_UP = SHVec3::Rotate(SHVec3::Up, rotation);
+ const SHVec3 LOCAL_RIGHT = SHVec3::Rotate(SHVec3::Right, rotation);
+ const SHVec3 LOCAL_FORWARD = SHVec3::Rotate(SHVec3::Forward, rotation);
+
+ // Rotate the circle
+ SHQuaternion circleOrientation = SHQuaternion::FromEuler(SHVec3(SHMath::DegreesToRadians(90.0), 0.0f, 0.0f)) * rotation;
+
+ // Compute top and bottom of the cylinder
+ const SHVec3 HALF_UP = LOCAL_UP * (height * 0.5f - radius);
+ const SHVec3 TOP_POS = position + HALF_UP;
+ const SHVec3 BOT_POS = position - HALF_UP;
+
+ // Render circles
+ const SHVec3 CIRCLE_SCALE = SHVec3(radius * 2.0f, radius * 2.0, radius * 2.0);
+ drawCircle(meshBatch, SHMatrix::Transform(TOP_POS, circleOrientation, CIRCLE_SCALE), color);
+ drawCircle(meshBatch, SHMatrix::Transform(BOT_POS, circleOrientation, CIRCLE_SCALE), color);
+
+ // Render connecting lines
+ drawLine(lineBatch, TOP_POS + LOCAL_RIGHT * radius, BOT_POS + LOCAL_RIGHT * radius, color);
+ drawLine(lineBatch, TOP_POS - LOCAL_RIGHT * radius, BOT_POS - LOCAL_RIGHT * radius, color);
+ drawLine(lineBatch, TOP_POS + LOCAL_FORWARD * radius, BOT_POS + LOCAL_FORWARD * radius, color);
+ drawLine(lineBatch, TOP_POS - LOCAL_FORWARD * radius, BOT_POS - LOCAL_FORWARD * radius, color);
+
+ // Render caps
+ const SHVec3 RADIUS_SCALE = SHVec3(radius * 2.0, radius * 2.0f, radius * 2.0);
+ const SHMatrix TOP_CAP_MAT = SHMatrix::Transform(TOP_POS, rotation, RADIUS_SCALE);
+ drawMesh
+ (
+ gfxSystem->GetMeshPrimitive(PrimitiveType::LineCapsuleCap),
+ meshBatch, TOP_CAP_MAT, color
+ );
+ const SHMatrix BOT_CAP_MAT = SHMatrix::Transform
+ (
+ BOT_POS,
+ SHQuaternion::FromEuler(SHVec3(SHMath::DegreesToRadians(180.0), 0.0f, 0.0f)) * rotation,
+ RADIUS_SCALE
+ );
+ drawMesh
+ (
+ gfxSystem->GetMeshPrimitive(PrimitiveType::LineCapsuleCap),
+ meshBatch, BOT_CAP_MAT, color
+ );
+ }
+
/*-----------------------------------------------------------------------------------*/
/* Helper Batch Functions - Lines */
/*-----------------------------------------------------------------------------------*/
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h
index 2978d68e..3997b6df 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h
@@ -163,6 +163,17 @@ namespace SHADE
/// Colour to draw with.
/// Whether or not drawn object will be occluded.
void DrawSphere(const SHMatrix& matrix, const SHColour& color = SHColour::WHITE, bool depthTested = false);
+ ///
+ /// Draws the outline of a capsule.
+ ///
+ /// Position of the wireframe capsule.
+ /// Rotation of the capsule.
+ /// Height of the overall capsule.
+ /// Radius of the capsule.
+ ///
+ /// Colour to draw with.
+ /// Whether or not drawn object will be occluded.
+ void DrawWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false);
/*---------------------------------------------------------------------------------*/
/* Persistent Draw Functions */
@@ -269,6 +280,17 @@ namespace SHADE
/// Whether or not drawn object will be occluded.
void DrawPersistentSphere(const SHMatrix& matrix, const SHColour& color = SHColour::WHITE, bool depthTested = false);
///
+ /// Draws a persistent outline of a capsule.
+ ///
+ /// Position of the wireframe capsule.
+ /// Rotation of the capsule.
+ /// Height of the overall capsule.
+ /// Radius of the capsule.
+ ///
+ /// Colour to draw with.
+ /// Whether or not drawn object will be occluded.
+ void DrawPersistentWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false);
+ ///
/// Clears any persistent drawn debug primitives.
///
void ClearPersistentDraws();
@@ -386,6 +408,7 @@ namespace SHADE
void drawCube(MeshBatch& batch, const SHMatrix& transformMatrix, const SHColour& color);
void drawSphere(MeshBatch& batch, const SHMatrix& transformMatrix, const SHColour& color);
void drawCircle(MeshBatch& batch, const SHMatrix& transformMatrix, const SHColour& color);
+ void drawWireCapsule(LinesBatch& lineBatch, MeshBatch& meshBatch, const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color);
/*---------------------------------------------------------------------------------*/
/* Helper Batch Functions - Lines */
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp
index b1256921..f3bcc8f7 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp
@@ -419,6 +419,7 @@ namespace SHADE
primitiveMeshes[static_cast(PrimitiveType::Sphere)] = SHPrimitiveGenerator::Sphere(meshLibrary);
primitiveMeshes[static_cast(PrimitiveType::LineCube)] = SHPrimitiveGenerator::LineCube(meshLibrary);
primitiveMeshes[static_cast(PrimitiveType::LineCircle)] = SHPrimitiveGenerator::LineCircle(meshLibrary);
+ primitiveMeshes[static_cast(PrimitiveType::LineCapsuleCap)] = SHPrimitiveGenerator::LineCapsuleCap(meshLibrary);
BuildMeshBuffers();
// Create default materials
@@ -819,6 +820,7 @@ namespace SHADE
case PrimitiveType::Sphere:
case PrimitiveType::LineCube:
case PrimitiveType::LineCircle:
+ case PrimitiveType::LineCapsuleCap:
return primitiveMeshes[static_cast(type)];
default:
return {};
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h
index 40148e05..707862f9 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h
@@ -72,9 +72,10 @@ namespace SHADE
Cube,
Sphere,
LineCube,
- LineCircle
+ LineCircle,
+ LineCapsuleCap
};
- static constexpr int MAX_PRIMITIVE_TYPES = 4;
+ static constexpr int MAX_PRIMITIVE_TYPES = 5;
enum class DebugDrawPipelineType
{
LineNoDepthTest,
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.cpp
index 444a6630..d5a0073f 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.cpp
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.cpp
@@ -29,6 +29,7 @@ namespace SHADE
SHMeshData SHPrimitiveGenerator::sphereMesh;
SHMeshData SHPrimitiveGenerator::lineCubeMesh;
SHMeshData SHPrimitiveGenerator::lineCircleMesh;
+ SHMeshData SHPrimitiveGenerator::lineCapsuleCapMesh;
/*-----------------------------------------------------------------------------------*/
/* Primitive Generation Functions */
@@ -392,6 +393,64 @@ namespace SHADE
return addMeshDataTo(lineCircleMesh, gfxSystem);
}
+ SHADE::SHMeshData SHPrimitiveGenerator::LineCapsuleCap() noexcept
+ {
+ SHMeshData mesh;
+
+ // Have multiple semi-circles for the cap
+ static constexpr int SPLITS = 36;
+ static constexpr float ANGLE_INCREMENTS = (std::numbers::pi_v * 2.0f) / static_cast(SPLITS);
+
+ /* X-Axis */
+ // Generate points of the circle
+ for (int i = 0; i <= SPLITS / 2; ++i)
+ {
+ const float ANGLE = ANGLE_INCREMENTS * i;
+ mesh.VertexPositions.emplace_back(cos(ANGLE) * 0.5f, sin(ANGLE) * 0.5f, 0.0f);
+ }
+
+ // Generate lines of the circle
+ for (int i = 1; i <= SPLITS / 2; ++i)
+ {
+ mesh.Indices.emplace_back(static_cast(i - 1));
+ mesh.Indices.emplace_back(static_cast(i));
+ }
+
+ /* Z-Axis */
+ // Generate points of the circle
+ for (int i = 0; i <= SPLITS / 2; ++i)
+ {
+ const float ANGLE = ANGLE_INCREMENTS * i;
+ mesh.VertexPositions.emplace_back(0.0f, sin(ANGLE) * 0.5f, cos(ANGLE) * 0.5f);
+ }
+
+ // Generate lines of the circle
+ for (int i = 2 + SPLITS / 2; i <= SPLITS + 1; ++i)
+ {
+ mesh.Indices.emplace_back(static_cast(i - 1));
+ mesh.Indices.emplace_back(static_cast(i));
+ }
+
+ mesh.VertexNormals.resize(mesh.VertexPositions.size());
+ mesh.VertexTangents.resize(mesh.VertexPositions.size());
+ mesh.VertexTexCoords.resize(mesh.VertexPositions.size());
+
+ return mesh;
+ }
+ Handle SHPrimitiveGenerator::LineCapsuleCap(SHMeshLibrary& meshLibrary) noexcept
+ {
+ if (lineCapsuleCapMesh.VertexPositions.empty())
+ lineCapsuleCapMesh = LineCapsuleCap();
+
+ return addMeshDataTo(lineCapsuleCapMesh, meshLibrary);
+ }
+ Handle SHPrimitiveGenerator::LineCapsuleCap(SHGraphicsSystem& gfxSystem) noexcept
+ {
+ if (lineCapsuleCapMesh.VertexPositions.empty())
+ lineCapsuleCapMesh = LineCapsuleCap();
+
+ return addMeshDataTo(lineCapsuleCapMesh, gfxSystem);
+ }
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*-----------------------------------------------------------------------------------*/
diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h b/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h
index 9bcd2f3c..839d0ef6 100644
--- a/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h
+++ b/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h
@@ -194,6 +194,46 @@ namespace SHADE
*/
/***********************************************************************************/
[[nodiscard]] static Handle LineCircle(SHGraphicsSystem& gfxSystem) noexcept;
+ /***********************************************************************************/
+ /*!
+ \brief
+ Produces a cap of a wireframe capsule that is comprised only of lines and
+ store the data in a SHMeshData object.
+
+ \return
+ SHMeshData object containing vertex data for the line circle.
+ */
+ /***********************************************************************************/
+ [[nodiscard]] static SHMeshData LineCapsuleCap() noexcept;
+ /***********************************************************************************/
+ /*!
+ \brief
+ Produces a cap of a wireframe capsule that is comprised only of lines and
+ constructs a SHMesh using the SHGraphicsSystem provided.
+
+ \param meshLibrary
+ Reference to the SHMeshLibrary to produce and store a line circle mesh in.
+
+ \return
+ SHMesh object that points to the generated line circle mesh in the SHMeshLibrary.
+ */
+ /***********************************************************************************/
+ [[nodiscard]] static Handle LineCapsuleCap(SHMeshLibrary& meshLibrary) noexcept;
+ /***********************************************************************************/
+ /*!
+ \brief
+ Produces a cap of a wireframe capsule that is comprised only of lines and
+ constructs a SHMesh using the SHGraphicsSystem provided.
+
+ \param gfxSystem
+ Reference to the SHGraphicsSystem to produce and store a line circle mesh in.
+
+ \return
+ SHMesh object that points to the generated line circle mesh in the
+ SHGraphicsSystem.
+ */
+ /***********************************************************************************/
+ [[nodiscard]] static Handle LineCapsuleCap(SHGraphicsSystem& gfxSystem) noexcept;
private:
/*---------------------------------------------------------------------------------*/
@@ -209,5 +249,6 @@ namespace SHADE
static SHMeshData sphereMesh;
static SHMeshData lineCubeMesh;
static SHMeshData lineCircleMesh;
+ static SHMeshData lineCapsuleCapMesh;
};
}
\ No newline at end of file
diff --git a/SHADE_Engine/src/Math/Transform/SHTransform.cpp b/SHADE_Engine/src/Math/Transform/SHTransform.cpp
index ef7c5fda..7be2a60c 100644
--- a/SHADE_Engine/src/Math/Transform/SHTransform.cpp
+++ b/SHADE_Engine/src/Math/Transform/SHTransform.cpp
@@ -35,7 +35,17 @@ namespace SHADE
: position { pos }
, orientation { SHQuaternion::FromEuler(rot) }
, scale { scl }
- {}
+ {
+ ComputeTRS();
+ }
+
+ SHTransform::SHTransform(const SHVec3& pos, const SHQuaternion& quat, const SHVec3& scl) noexcept
+ : position { pos }
+ , orientation { quat }
+ , scale { scl }
+ {
+ ComputeTRS();
+ }
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
diff --git a/SHADE_Engine/src/Tools/SHDebugDraw.cpp b/SHADE_Engine/src/Tools/SHDebugDraw.cpp
index 02eca592..ee040d8b 100644
--- a/SHADE_Engine/src/Tools/SHDebugDraw.cpp
+++ b/SHADE_Engine/src/Tools/SHDebugDraw.cpp
@@ -128,6 +128,10 @@ namespace SHADE
dbgDrawSys->DrawWireSphere(SHMatrix::Transform(center, SHQuaternion(), scale), color, depthTested);
}
+ void SHDebugDraw::WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color, bool depthTested)
+ {
+ dbgDrawSys->DrawWireCapsule(position, rotation, height, radius, color, depthTested);
+ }
/*-----------------------------------------------------------------------------------*/
/* Persistent Draw Functions */
/*-----------------------------------------------------------------------------------*/
@@ -216,6 +220,10 @@ namespace SHADE
dbgDrawSys->DrawPersistentWireSphere(SHMatrix::Transform(center, SHQuaternion(), scale), color, depthTested);
}
+ void SHDebugDraw::Persistent::WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color, bool depthTested)
+ {
+ dbgDrawSys->DrawPersistentWireCapsule(position, rotation, height, radius, color, depthTested);
+ }
void SHDebugDraw::Persistent::ClearDraws()
{
dbgDrawSys->ClearPersistentDraws();
diff --git a/SHADE_Engine/src/Tools/SHDebugDraw.h b/SHADE_Engine/src/Tools/SHDebugDraw.h
index c28b93e6..3d7bee2f 100644
--- a/SHADE_Engine/src/Tools/SHDebugDraw.h
+++ b/SHADE_Engine/src/Tools/SHDebugDraw.h
@@ -194,6 +194,18 @@ namespace SHADE
/// Colour to draw with.
/// Whether or not drawn object will be occluded.
static void WireSphere(const SHVec3& center, const SHVec3& scale, const SHVec4& color = SHColour::WHITE, bool depthTested = false);
+ ///
+ /// Draws the outline of a capsule.
+ /// This will remain drawn until ClearDraws() is called.
+ ///
+ /// Position of the wireframe capsule.
+ /// Rotation of the capsule.
+ /// Height of the overall capsule.
+ /// Radius of the capsule.
+ ///
+ /// Colour to draw with.
+ /// Whether or not drawn object will be occluded.
+ void WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false);
/*---------------------------------------------------------------------------------*/
/* Persistent Draw Function Class "Folder" */
@@ -366,6 +378,18 @@ namespace SHADE
/// Whether or not drawn object will be occluded.
static void WireSphere(const SHVec3& center, const SHVec3& scale, const SHVec4& color = SHColour::WHITE, bool depthTested = false);
///
+ /// Draws the outline of a capsule.
+ /// This will remain drawn until ClearDraws() is called.
+ ///
+ /// Position of the wireframe capsule.
+ /// Rotation of the capsule.
+ /// Height of the overall capsule.
+ /// Radius of the capsule.
+ ///
+ /// Colour to draw with.
+ /// Whether or not drawn object will be occluded.
+ void WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false);
+ ///
/// Clears any persistent drawn debug primitives.
///
static void ClearDraws();
diff --git a/SHADE_Managed/src/Components/Transform.cxx b/SHADE_Managed/src/Components/Transform.cxx
index bc61eff3..d5b38967 100644
--- a/SHADE_Managed/src/Components/Transform.cxx
+++ b/SHADE_Managed/src/Components/Transform.cxx
@@ -107,8 +107,7 @@ namespace SHADE
Vector3 Transform::Forward::get()
{
- const SHVec3 DIRECTION = SHVec3::Rotate(-SHVec3::UnitZ, Convert::ToNative(GlobalRotation));
- return Convert::ToCLI(DIRECTION);
+ return Vector3::Rotate(Vector3::Forward, GlobalRotation);
}
/*-----------------------------------------------------------------------------------*/
diff --git a/SHADE_Managed/src/Math/Vector3.cxx b/SHADE_Managed/src/Math/Vector3.cxx
index d2862ac7..647174a2 100644
--- a/SHADE_Managed/src/Math/Vector3.cxx
+++ b/SHADE_Managed/src/Math/Vector3.cxx
@@ -167,6 +167,10 @@ namespace SHADE
{
return Convert::ToCLI(SHVec3::Rotate(Convert::ToNative(vec), Convert::ToNative(axis), radians));
}
+ Vector3 Vector3::Rotate(Vector3 vec, Quaternion quat)
+ {
+ return Convert::ToCLI(SHVec3::Rotate(Convert::ToNative(vec), Convert::ToNative(quat)));
+ }
Vector3 Vector3::Min(Vector3 lhs, Vector3 rhs)
{
float lx = lhs.x, rx = rhs.x;
diff --git a/SHADE_Managed/src/Math/Vector3.hxx b/SHADE_Managed/src/Math/Vector3.hxx
index 76b11420..31a373ba 100644
--- a/SHADE_Managed/src/Math/Vector3.hxx
+++ b/SHADE_Managed/src/Math/Vector3.hxx
@@ -19,10 +19,17 @@ of DigiPen Institute of Technology is prohibited.
// Project Includes
#include "Vector2.hxx"
-value struct Quaternion;
-
namespace SHADE
{
+ /*---------------------------------------------------------------------------------*/
+ /* Forward Declarations */
+ /*-------------------------------------------------------------------------- --- */
+ value struct Quaternion;
+
+ /*---------------------------------------------------------------------------------*/
+ /* Type Definitions */
+ /*-------------------------------------------------------------------------- --- */
+
///
/// CLR version of SHADE Engine's Vector3 class that represents a 3-Dimensional Vector.
/// Designed to closely match Unity's Vector3 struct.
@@ -308,6 +315,12 @@ namespace SHADE
/// The Vector3 that represents the rotated vector.
static Vector3 Rotate(Vector3 vec, Vector3 axis, float radians);
///
+ /// Rotates a Vector3 using a Quaternion.
+ ///
+ /// A Vector3 to rotate.
+ /// A Quaternion to rotate the vector with.
+ static Vector3 Rotate(Vector3 vec, Quaternion quat);
+ ///
/// Computes and returns a Vector3 that is made from the smallest components of
/// the two specified Vector3s.
///