Added Debug Drawing for Colliders (wonk) and Trigger checkbox to Colldiers

Press space to toggle debug draw. Does not work until you press play, then it can be toggled on and off.
This commit is contained in:
Diren D Bharwani 2022-11-02 15:44:24 +08:00
parent 8c666ef236
commit 02c79b4cc4
7 changed files with 220 additions and 26 deletions

View File

@ -91,6 +91,7 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsDebugDraw>();
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
@ -148,6 +149,13 @@ namespace Sandbox
#endif
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
editor->PollPicking();
static bool drawColliders = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::SPACE))
{
drawColliders = !drawColliders;
SHSystemManager::GetSystem<SHPhysicsSystem>()->SetDrawColliders(drawColliders);
}
}
// Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution();

View File

@ -273,6 +273,7 @@ namespace SHADE
{
}
{
SHEditorWidgets::BeginPanel("Offsets",{ ImGui::GetContentRegionAvail().x, 30.0f });
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider->GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider->SetPositionOffset(vec); });
@ -297,6 +298,9 @@ namespace SHADE
});
SHEditorWidgets::EndPanel();
}
SHEditorWidgets::CheckBox("Is Trigger", [collider] { return collider->IsTrigger(); }, [collider](bool value) { collider->SetIsTrigger(value); });
if (ImGui::Button(std::format("{} Remove Collider #{}", ICON_MD_REMOVE, i).data()))
{
colliderToDelete = i;

View File

@ -118,6 +118,17 @@ namespace SHADE
}
{}
SHColour::SHColour(uint32_t rgba) noexcept
: XMFLOAT4 { 0.0f, 0.0f, 0.0f, 1.0f }
{
const SHColour32 TMP { ._32bitValue = rgba };
x = static_cast<float>(TMP._8bitValues[0]) / 255.0f;
y = static_cast<float>(TMP._8bitValues[1]) / 255.0f;
z = static_cast<float>(TMP._8bitValues[2]) / 255.0f;
w = static_cast<float>(TMP._8bitValues[3]) / 255.0f;
}
SHColour::SHColour(const SHVec3& rgb) noexcept
: XMFLOAT4 { rgb.x, rgb.y, rgb.z, 1.0f }
{}

View File

@ -34,6 +34,12 @@ namespace SHADE
float v = 0.0f;
};
union SH_API SHColour32
{
uint32_t _32bitValue;
uint8_t _8bitValues[4];
};
class SH_API SHColour : public DirectX::XMFLOAT4
{
public:
@ -46,6 +52,7 @@ namespace SHADE
SHColour (float r, float g, float b, float a) noexcept;
SHColour (uint8_t r, uint8_t g, uint8_t b) noexcept;
SHColour (uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept;
SHColour (uint32_t rgba) noexcept;
SHColour (const SHVec3& rgb) noexcept;
SHColour (const SHVec4& rgba) noexcept;

View File

@ -17,10 +17,12 @@
#include "ECS_Base/Managers/SHComponentManager.h"
#include "ECS_Base/Managers/SHEntityManager.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
#include "Math/SHMathHelpers.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Scene/SHSceneManager.h"
#include "Scripting/SHScriptEngine.h"
#include "Tools/SHUtilities.h"
namespace SHADE
{
@ -30,6 +32,7 @@ namespace SHADE
SHPhysicsSystem::SHPhysicsSystem()
: worldUpdated { false }
, debugDrawFlags { 0 }
, interpolationFactor { 0.0 }
, fixedDT { 60.0 }
, world { nullptr }
@ -47,6 +50,11 @@ namespace SHADE
: SHSystemRoutine { "Physics PostUpdate", false }
{}
SHPhysicsSystem::PhysicsDebugDraw::PhysicsDebugDraw()
: SHSystemRoutine { "Physics DebugDraw", true }
{}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
@ -99,6 +107,31 @@ namespace SHADE
return 0;
}
bool SHPhysicsSystem::GetDrawColliders() const noexcept
{
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER);
}
bool SHPhysicsSystem::GetDrawColliderAABBs() const noexcept
{
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB);
}
bool SHPhysicsSystem::GetDrawBroadPhase() const noexcept
{
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB);
}
bool SHPhysicsSystem::GetDrawContactPoints() const noexcept
{
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS);
}
bool SHPhysicsSystem::GetDrawContactNormals() const noexcept
{
return debugDrawFlags & SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS);
}
const SHPhysicsSystem::CollisionEvents& SHPhysicsSystem::GetCollisionInfo() const noexcept
{
return collisionInfo;
@ -181,6 +214,96 @@ namespace SHADE
}
}
void SHPhysicsSystem::SetDrawColliders(bool shouldDraw) noexcept
{
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER);
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
if (world == nullptr)
{
SHLOGV_WARNING("No physics world has been initialised!")
return;
}
world->getDebugRenderer().setIsDebugItemDisplayed
(
rp3d::DebugRenderer::DebugItem::COLLISION_SHAPE,
shouldDraw
);
}
void SHPhysicsSystem::SetDrawColliderAABBs(bool shouldDraw) noexcept
{
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB);
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
if (world == nullptr)
{
SHLOGV_WARNING("No physics world has been initialised!")
return;
}
world->getDebugRenderer().setIsDebugItemDisplayed
(
rp3d::DebugRenderer::DebugItem::COLLIDER_AABB,
shouldDraw
);
}
void SHPhysicsSystem::SetDrawBroadPhase(bool shouldDraw) noexcept
{
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB);
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
if (world == nullptr)
{
SHLOGV_WARNING("No physics world has been initialised!")
return;
}
world->getDebugRenderer().setIsDebugItemDisplayed
(
rp3d::DebugRenderer::DebugItem::COLLIDER_BROADPHASE_AABB,
shouldDraw
);
}
void SHPhysicsSystem::SetDrawContactPoints(bool shouldDraw) noexcept
{
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS);
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
if (world == nullptr)
{
SHLOGV_WARNING("No physics world has been initialised!")
return;
}
world->getDebugRenderer().setIsDebugItemDisplayed
(
rp3d::DebugRenderer::DebugItem::CONTACT_POINT,
shouldDraw
);
}
void SHPhysicsSystem::SetDrawContactNormals(bool shouldDraw) noexcept
{
static constexpr auto FLAG_VALUE = SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS);
shouldDraw ? debugDrawFlags |= FLAG_VALUE : debugDrawFlags &= ~(FLAG_VALUE);
if (world == nullptr)
{
SHLOGV_WARNING("No physics world has been initialised!")
return;
}
world->getDebugRenderer().setIsDebugItemDisplayed
(
rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL,
shouldDraw
);
}
/*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/
@ -198,6 +321,7 @@ namespace SHADE
world = factory.createPhysicsWorld(settings);
world->setEventListener(this);
world->setIsDebugRenderingEnabled(true);
// Set up solvers
world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::SPLIT_IMPULSES);
@ -323,7 +447,7 @@ namespace SHADE
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
if (scriptingSystem == nullptr)
{
SHLOGV_WARNING("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
}
fixedTimeStep = 1.0 / physicsSystem->fixedDT;
@ -353,7 +477,7 @@ namespace SHADE
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
if (scriptingSystem == nullptr)
{
SHLOGV_WARNING("Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
SHLOGV_ERROR("Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
}
// Interpolate transforms for rendering
@ -369,6 +493,40 @@ namespace SHADE
}
}
void SHPhysicsSystem::PhysicsDebugDraw::Execute(double) noexcept
{
const auto* PHYSICS_SYSTEM = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
if (PHYSICS_SYSTEM->debugDrawFlags == 0)
return;
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
if (debugDrawSystem == nullptr)
{
SHLOGV_ERROR("Unable to debug draw physics objects due to missing SHDebugDrawSystem!");
return;
}
const auto& RP3D_DEBUG_RENDERER = PHYSICS_SYSTEM->world->getDebugRenderer();
const auto& LINES = RP3D_DEBUG_RENDERER.getLines();
const auto& TRIANGLES = RP3D_DEBUG_RENDERER.getTriangles();
// Draw all lines
for (uint32_t i = 0; i < RP3D_DEBUG_RENDERER.getNbLines(); ++i)
{
const auto& LINE = LINES[i];
debugDrawSystem->DrawLine(SHColour{ LINE.color1 }, LINE.point1, LINE.point2);
}
for (uint32_t i = 0; i < RP3D_DEBUG_RENDERER.getNbTriangles(); ++i)
{
const auto& TRIANGLE = TRIANGLES[i];
SHColour triColour{ TRIANGLE.color1 };
triColour.a() = 1.0f;
debugDrawSystem->DrawTri(triColour, TRIANGLE.point1, TRIANGLE.point2, TRIANGLE.point3);
}
}
void SHPhysicsSystem::onContact(const CallbackData& callbackData)
{
for (uint32_t i = 0; i < callbackData.getNbContactPairs(); ++i)

View File

@ -51,6 +51,15 @@ namespace SHADE
using CollisionEvents = std::vector<SHCollisionEvent>;
enum class DebugDrawFlags : uint8_t
{
COLLIDER = 1
, COLLIDER_AABB = 2
, BROAD_PHASE_AABB = 4
, CONTACT_POINTS = 8
, CONTACT_NORMALS = 16
};
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
@ -69,6 +78,12 @@ namespace SHADE
[[nodiscard]] uint16_t GetNumberVelocityIterations () const noexcept;
[[nodiscard]] uint16_t GetNumberPositionIterations () const noexcept;
[[nodiscard]] bool GetDrawColliders () const noexcept;
[[nodiscard]] bool GetDrawColliderAABBs () const noexcept;
[[nodiscard]] bool GetDrawBroadPhase () const noexcept;
[[nodiscard]] bool GetDrawContactPoints () const noexcept;
[[nodiscard]] bool GetDrawContactNormals () const noexcept;
[[nodiscard]] const CollisionEvents& GetCollisionInfo () const noexcept;
[[nodiscard]] const CollisionEvents& GetTriggerInfo () const noexcept;
@ -85,6 +100,13 @@ namespace SHADE
void SetWorldSettings (const WorldSettings& settings) const noexcept;
// TODO(Diren): Can the debug draw flags be done through an enum?
void SetDrawColliders (bool shouldDraw) noexcept;
void SetDrawColliderAABBs (bool shouldDraw) noexcept;
void SetDrawBroadPhase (bool shouldDraw) noexcept;
void SetDrawContactPoints (bool shouldDraw) noexcept;
void SetDrawContactNormals (bool shouldDraw) noexcept;
/*---------------------------------------------------------------------------------*/
/* Function Members */
/*---------------------------------------------------------------------------------*/
@ -105,48 +127,31 @@ namespace SHADE
class SH_API PhysicsPreUpdate final : public SHSystemRoutine
{
public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
PhysicsPreUpdate();
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
void Execute(double dt) noexcept override;
};
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
{
public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
PhysicsFixedUpdate();
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
void Execute (double dt) noexcept override;
};
class SH_API PhysicsPostUpdate final : public SHSystemRoutine
{
public:
/*-------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*-------------------------------------------------------------------------------*/
PhysicsPostUpdate();
void Execute(double dt) noexcept override;
};
/*-------------------------------------------------------------------------------*/
/* Function Members */
/*-------------------------------------------------------------------------------*/
class SH_API PhysicsDebugDraw final : public SHSystemRoutine
{
public:
PhysicsDebugDraw();
void Execute(double dt) noexcept override;
};
@ -162,6 +167,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
bool worldUpdated;
uint8_t debugDrawFlags;
double interpolationFactor;
double fixedDT;

View File

@ -39,7 +39,7 @@ namespace SHADE
* @param[in] enumClassMember A member of the specified enum class.
* @returns The value of the enum class member in the output type.
*/
template <IsEnum InputType, IsIntegral OutputType = int>
template <IsEnum InputType, IsIntegral OutputType = std::underlying_type_t<InputType>>
static constexpr OutputType ConvertEnum(InputType enumClassMember) noexcept;
/**