Compare commits

..

7 Commits

Author SHA1 Message Date
8b308db058 Audio Engine Fixes 2025-10-03 03:16:40 +05:30
6a87771d8f Fixes 2025-10-01 23:14:11 +05:30
f6c022f38e Fixes 2025-09-30 01:41:48 +05:30
0d5c2e639e Fixes 2025-09-29 19:04:14 +05:30
ae20f51e9a Fixes 2025-09-29 16:12:19 +05:30
9038fa54b0 Final Collisions 2025-09-29 15:52:27 +05:30
9269306146 Physics Debug Draw 2025-09-29 14:53:06 +05:30
13 changed files with 164 additions and 195 deletions

View File

@ -35,6 +35,7 @@ namespace ia::iae::game
t->BakeAnimations(); t->BakeAnimations();
} }
g_playerPhysics = g_player->AddComponent<PhysicsComponent>(); g_playerPhysics = g_player->AddComponent<PhysicsComponent>();
g_playerPhysics->IsDynamic() = true;
g_playerPhysics->AddCollider({ g_playerPhysics->AddCollider({
.IsTrigger = false, .IsTrigger = false,
.Position = { .Position = {

View File

@ -19,12 +19,26 @@
#include <SDL3/SDL_iostream.h> #include <SDL3/SDL_iostream.h>
#include <SDL3_mixer/SDL_mixer.h> #include <SDL3_mixer/SDL_mixer.h>
#include <condition_variable>
#include <thread> #include <thread>
namespace ia::iae namespace ia::iae
{ {
struct TrackData
{
BOOL IsActive{};
MIX_Track *Track{};
INT32 LoopTimes{};
TimePeriod LoopDelay{};
std::thread *PlaybackThread;
std::mutex Mutex;
std::condition_variable CV;
};
MIX_Mixer *g_mixer{}; MIX_Mixer *g_mixer{};
Vector<MIX_Track *> g_tracks; Vector<TrackData*> g_tracks;
Vector<INT64> g_destroyQueue;
Vector<MIX_Audio *> g_audioData; Vector<MIX_Audio *> g_audioData;
VOID Audio::Initialize() VOID Audio::Initialize()
@ -38,7 +52,48 @@ namespace ia::iae
VOID Audio::Terminate() VOID Audio::Terminate()
{ {
for (SIZE_T i = 0; i < g_tracks.size(); i++)
{
{
std::lock_guard<std::mutex> lock(g_tracks[i]->Mutex);
g_tracks[i]->IsActive = false;
}
g_tracks[i]->CV.notify_one();
g_tracks[i]->PlaybackThread->join();
delete g_tracks[i];
}
MIX_StopAllTracks(g_mixer, 0);
g_audioData.clear(); g_audioData.clear();
g_tracks.clear();
}
VOID Audio::Update()
{
for (SIZE_T i = 0; i < g_tracks.size(); i++)
{
auto &t = g_tracks[i];
if (!t->IsActive && !MIX_TrackPlaying(t->Track))
DestroyTrack(i);
}
// [IATODO]: IMPL: Destroy queue
}
INT64 Audio::CreateTrack()
{
g_tracks.pushBack(new TrackData{true, MIX_CreateTrack(g_mixer)});
return g_tracks.size() - 1;
}
VOID Audio::DestroyTrack(IN INT64 trackHandle)
{
if(trackHandle >= g_tracks.size())
return;
auto& t = g_tracks[trackHandle];
ClearTrack(trackHandle);
MIX_StopTrack(t->Track, 0);
t->IsActive = false;
g_destroyQueue.pushBack(trackHandle);
} }
Sound Audio::CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize) Sound Audio::CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize)
@ -47,62 +102,55 @@ namespace ia::iae
return Sound(g_audioData.size() - 1); return Sound(g_audioData.size() - 1);
} }
INT64 Audio::CreateTrack()
{
g_tracks.pushBack(MIX_CreateTrack(g_mixer));
return g_tracks.size() - 1;
}
VOID Audio::DestroyTrack(IN INT64 trackHandle)
{
ClearTrack(trackHandle);
}
VOID Audio::QueueTrackData(IN INT64 trackHandle, IN INT64 dataHandle) VOID Audio::QueueTrackData(IN INT64 trackHandle, IN INT64 dataHandle)
{ {
MIX_SetTrackAudio(g_tracks[trackHandle], g_audioData[dataHandle]); MIX_SetTrackAudio(g_tracks[trackHandle]->Track, g_audioData[dataHandle]);
} }
VOID Audio::PlayTrack(IN INT64 trackHandle, IN INT32 loopTimes, IN TimePeriod loopDelay) VOID Audio::PlayTrack(IN INT64 trackHandle, IN INT32 loopTimes, IN TimePeriod loopDelay)
{ {
struct __callback_data auto &t = g_tracks[trackHandle];
{ t->LoopTimes = loopTimes;
INT32 loopTimes; t->LoopDelay = loopDelay;
TimePeriod loopDelay; if (t->LoopTimes == 0)
}; t->IsActive = false;
else
const auto callbackData = new __callback_data{.loopTimes = loopTimes, .loopDelay = loopDelay}; t->PlaybackThread = new std::thread([trackHandle]() {
auto &t = g_tracks[trackHandle];
MIX_PlayTrack(g_tracks[trackHandle], 0); while (t->IsActive)
MIX_SetTrackStoppedCallback( {
g_tracks[trackHandle], if (MIX_TrackPlaying(t->Track))
[](PVOID _callbackData, MIX_Track *track) { continue;
const auto callbackData = (__callback_data *) _callbackData; if (t->LoopTimes < 0)
if (callbackData->loopTimes < 0) goto loop_next_iteration;
goto loop_next_iteration; else if (!t->LoopTimes)
else if (callbackData->loopTimes == 0) {
return; t->IsActive = false;
else return;
callbackData->loopTimes -= 1; }
loop_next_iteration: t->LoopTimes--;
std::this_thread::sleep_for(std::chrono::milliseconds((INT32) (callbackData->loopDelay.GetValue() * 1000))); loop_next_iteration:
MIX_PlayTrack(track, 0); std::unique_lock<std::mutex> lock(t->Mutex);
}, t->CV.wait_for(lock, std::chrono::milliseconds((INT32) (t->LoopDelay.GetValue() * 1000)),
callbackData); [t]() { return !t->IsActive; });
MIX_PlayTrack(t->Track, 0);
}
});
MIX_PlayTrack(t->Track, 0);
} }
VOID Audio::ClearTrack(IN INT64 trackHandle) VOID Audio::ClearTrack(IN INT64 trackHandle)
{ {
MIX_StopTrack(g_tracks[trackHandle], 0); MIX_StopTrack(g_tracks[trackHandle]->Track, 0);
} }
VOID Audio::PauseTrack(IN INT64 trackHandle) VOID Audio::PauseTrack(IN INT64 trackHandle)
{ {
MIX_PauseTrack(g_tracks[trackHandle]); MIX_PauseTrack(g_tracks[trackHandle]->Track);
} }
VOID Audio::ResumeTrack(IN INT64 trackHandle) VOID Audio::ResumeTrack(IN INT64 trackHandle)
{ {
MIX_ResumeTrack(g_tracks[trackHandle]); MIX_ResumeTrack(g_tracks[trackHandle]->Track);
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -35,6 +35,7 @@ namespace ia::iae
VOID PhysicsComponent::Update() VOID PhysicsComponent::Update()
{ {
m_velocity = {};
} }
Handle PhysicsComponent::CreateCollider() Handle PhysicsComponent::CreateCollider()
@ -56,7 +57,9 @@ namespace ia::iae
VOID PhysicsComponent::Move(IN glm::vec2 direction) VOID PhysicsComponent::Move(IN glm::vec2 direction)
{ {
IA_ASSERT(m_isDynamic);
const auto v = direction * m_movementSpeed; const auto v = direction * m_movementSpeed;
m_velocity += v;
for(const auto& t: m_colliders) for(const auto& t: m_colliders)
{ {
if(!Physics::CanMove(m_physicsHandle, t, v)) if(!Physics::CanMove(m_physicsHandle, t, v))

View File

@ -36,6 +36,8 @@ namespace ia::iae
{ {
CONSTEXPR FLOAT32 GAME_UPDATE_INTERVAL = 1000.0f / 60.0f; CONSTEXPR FLOAT32 GAME_UPDATE_INTERVAL = 1000.0f / 60.0f;
EXTERN BOOL g_physicsDebugDrawEnabled;
SDL_Event g_event{}; SDL_Event g_event{};
FLOAT32 g_updateTimer{}; FLOAT32 g_updateTimer{};
BOOL g_shouldClose{false}; BOOL g_shouldClose{false};
@ -132,7 +134,11 @@ namespace ia::iae
VOID Engine::UpdateGame() VOID Engine::UpdateGame()
{ {
if(Input::WasKeyPressed(Input::KEY_F6))
g_physicsDebugDrawEnabled = !g_physicsDebugDrawEnabled;
Physics::Update(); Physics::Update();
Audio::Update();
if B_LIKELY (g_activeScene) if B_LIKELY (g_activeScene)
g_activeScene->Update(); g_activeScene->Update();

View File

@ -72,9 +72,10 @@ namespace ia::iae
c->Disable(); c->Disable();
} }
VOID Node::AddChild(IN RefPtr<Node> node) Node* Node::AddChild(IN RefPtr<Node> node)
{ {
m_children.pushBack(node); m_children.pushBack(node);
return node.get();
} }
VOID Node::AddComponent(IN RefPtr<IComponent> component) VOID Node::AddComponent(IN RefPtr<IComponent> component)

View File

@ -16,6 +16,9 @@
#include <IAEngine/IAEngine.hpp> #include <IAEngine/IAEngine.hpp>
#include <IAEngine/Physics/Physics.hpp> #include <IAEngine/Physics/Physics.hpp>
#include <IAEngine/Rendering/DebugDraw.hpp>
#include <IAEngine/Rendering/Camera.hpp>
#include <IAEngine/Rendering/Renderer.hpp>
#include <IAEngine/Nodes/Node.hpp> #include <IAEngine/Nodes/Node.hpp>
@ -23,51 +26,10 @@
namespace ia::iae namespace ia::iae
{ {
BOOL g_physicsDebugDrawEnabled = false;
Vector<PhysicsComponent *> g_physicsComponents; Vector<PhysicsComponent *> g_physicsComponents;
FLOAT32 Sq(IN FLOAT32 v)
{
return v * v;
}
enum class RectSide
{
NONE,
LEFT,
RIGHT,
TOP,
BOTTOM,
};
RectSide GetRectSide(IN glm::vec2 d)
{
const auto dX = abs(d.x);
const auto dY = abs(d.y);
if (d.x >= 0)
{
if (dX >= dY)
{
return RectSide::RIGHT;
}
else
{
return (d.y < 0) ? RectSide::TOP : RectSide::BOTTOM;
}
}
else
{
if (dX >= dY)
{
return RectSide::LEFT;
}
else
{
return (d.y < 0) ? RectSide::TOP : RectSide::BOTTOM;
}
}
return RectSide::NONE;
}
VOID Physics::Initialize() VOID Physics::Initialize()
{ {
} }
@ -80,6 +42,23 @@ namespace ia::iae
{ {
} }
VOID Physics::DebugDraw()
{
if(!g_physicsDebugDrawEnabled)
return;
for(const auto& t: g_physicsComponents)
{
for(const auto& c: t->Colliders())
{
auto color = glm::vec4{0.75f, 0.0f, 0.0f, 1.0f};
if(c.IsTrigger)
color = {0.25f, 0.45f, 0.75f, 0.75f};
DebugDraw::DrawRect(t->GetNode()->GetPosition() + c.Position - Renderer::GetCamera()->Position(), c.Size, color, 2.0f);
}
}
}
Handle Physics::RegisterComponent(IN PhysicsComponent *component) Handle Physics::RegisterComponent(IN PhysicsComponent *component)
{ {
g_physicsComponents.pushBack(component); g_physicsComponents.pushBack(component);
@ -89,36 +68,17 @@ namespace ia::iae
BOOL Physics::CanMove(IN Handle handle, IN CONST PhysicsComponent::Collider &collider, IN glm::vec2 movement) BOOL Physics::CanMove(IN Handle handle, IN CONST PhysicsComponent::Collider &collider, IN glm::vec2 movement)
{ {
const auto comp = g_physicsComponents[handle]; const auto comp = g_physicsComponents[handle];
const auto middle = comp->GetNode()->GetPosition() + movement + collider.Position + collider.Size / 2.0f; const auto pos = comp->GetNode()->GetPosition() + movement + collider.Position;
const auto halfSize = collider.Size / 2.0f;
for (const auto &t : g_physicsComponents) for (const auto &t : g_physicsComponents)
{ {
if (t == comp) if (t == comp)
continue; continue;
for (const auto &tc : t->Colliders()) for (const auto &tc : t->Colliders())
{ {
BOOL isColliding = false; const auto tPos = t->GetNode()->GetPosition() + tc.Position;
const auto tMiddle = t->GetNode()->GetPosition() + tc.Position + tc.Size / 2.0f; const auto xColliding = ((pos.x + collider.Size.x) >= tPos.x) && ((tPos.x + tc.Size.x) >= pos.x);
const auto tHalfSize = tc.Size / 2.0f; const auto yColliding = ((pos.y + collider.Size.y) >= tPos.y) && ((tPos.y + tc.Size.y) >= pos.y);
const auto rectSide = GetRectSide(tMiddle - middle); if (xColliding && yColliding)
const auto distance = Sq(tMiddle.x - middle.x) + Sq(tMiddle.y - middle.y);
switch (rectSide)
{
case RectSide::LEFT:
case RectSide::RIGHT:
isColliding = (Sq(tHalfSize.x + halfSize.x) >= distance);
break;
case RectSide::TOP:
case RectSide::BOTTOM:
isColliding = (Sq(tHalfSize.y + halfSize.y) >= distance);
break;
default:
isColliding = false;
break;
}
if (isColliding)
{ {
// Collision callback // Collision callback
comp->OnCollision(t); comp->OnCollision(t);

View File

@ -21,6 +21,7 @@
#include <IAEngine/Rendering/GPUTexture.hpp> #include <IAEngine/Rendering/GPUTexture.hpp>
#include <IAEngine/Rendering/Pipeline/UnlitMesh.hpp> #include <IAEngine/Rendering/Pipeline/UnlitMesh.hpp>
#include <IAEngine/Rendering/Renderer.hpp> #include <IAEngine/Rendering/Renderer.hpp>
#include <IAEngine/Physics/Physics.hpp>
#include <SDL3/SDL_gpu.h> #include <SDL3/SDL_gpu.h>
@ -34,23 +35,6 @@ namespace ia::iae
ImGuiIO g_imGUIIO{}; ImGuiIO g_imGUIIO{};
struct ShapeLine
{
ImVec2 To{};
ImVec2 From{};
ImColor Color{};
FLOAT32 Thickness{1.0f};
BOOL Visibility{true};
};
struct ShapeRect
{
ImVec2 TopLeft{};
ImVec2 BottomRight{};
ImColor Color{};
BOOL Visibility{true};
};
struct UIWindow struct UIWindow
{ {
PCCHAR Title{""}; PCCHAR Title{""};
@ -61,8 +45,6 @@ namespace ia::iae
}; };
Vector<UIWindow> g_debugUIWindows; Vector<UIWindow> g_debugUIWindows;
Vector<ShapeLine> g_lineShapes;
Vector<ShapeRect> g_rectShapes;
VOID DebugDraw::Initailize() VOID DebugDraw::Initailize()
{ {
@ -107,47 +89,26 @@ namespace ia::iae
w.ContentDrawCallback(); w.ContentDrawCallback();
ImGui::End(); ImGui::End();
} }
Physics::DebugDraw();
}
VOID DebugDraw::DrawLine(IN CONST glm::vec2 &from, IN CONST glm::vec2 &to, IN CONST glm::vec4 &color,
IN FLOAT32 thickness)
{
const auto drawList = ImGui::GetForegroundDrawList(); const auto drawList = ImGui::GetForegroundDrawList();
for (const auto &t : g_lineShapes) drawList->AddLine(ImVec2(from.x, from.y), ImVec2(to.x, to.y), IM_COL32(color.x * 255, color.y * 255, color.z * 255, color.w * 255), thickness);
{
if (!t.Visibility)
continue;
drawList->AddLine(t.From, t.To, t.Color, t.Thickness);
}
for (const auto &t : g_rectShapes)
{
if (!t.Visibility)
continue;
drawList->AddRectFilled(t.TopLeft, t.BottomRight, t.Color);
}
} }
Handle DebugDraw::AddLine(IN CONST glm::vec2 &from, IN CONST glm::vec2 &to, IN CONST glm::vec4 &color, VOID DebugDraw::DrawRect(IN CONST glm::vec2 &position, IN CONST glm::vec2 &size, IN CONST glm::vec4 &color, IN FLOAT32 thickness)
IN FLOAT32 thickness)
{ {
g_lineShapes.pushBack(ShapeLine{.To = ImVec2{to.x, to.y}, const auto drawList = ImGui::GetForegroundDrawList();
.From = ImVec2{from.x, from.y}, drawList->AddRect(ImVec2(position.x, position.y), ImVec2(position.x + size.x, position.y + size.y), IM_COL32(color.x * 255, color.y * 255, color.z * 255, color.w * 255), 0.0f, 0, thickness);
.Color = IM_COL32(color.x * 255, color.y * 255, color.z * 255, color.w * 255),
.Thickness = thickness});
return g_lineShapes.size() - 1;
} }
Handle DebugDraw::AddRect(IN CONST glm::vec2 &position, IN CONST glm::vec2 &size, IN CONST glm::vec4 &color) VOID DebugDraw::DrawRectFilled(IN CONST glm::vec2 &position, IN CONST glm::vec2 &size, IN CONST glm::vec4 &color)
{ {
g_rectShapes.pushBack({ const auto drawList = ImGui::GetForegroundDrawList();
.TopLeft = drawList->AddRectFilled(ImVec2(position.x, position.y), ImVec2(position.x + size.x, position.y + size.y), IM_COL32(color.x * 255, color.y * 255, color.z * 255, color.w * 255));
ImVec2{
position.x,
position.y,
},
.BottomRight =
ImVec2{
position.x + size.x,
position.y + size.y,
},
.Color = IM_COL32(color.x * 255, color.y * 255, color.z * 255, color.w * 255),
});
return g_rectShapes.size() - 1;
} }
Handle DebugDraw::AddUIWindow(IN PCCHAR title, IN CONST glm::vec2 &position, IN CONST glm::vec2 &size, Handle DebugDraw::AddUIWindow(IN PCCHAR title, IN CONST glm::vec2 &position, IN CONST glm::vec2 &size,
@ -157,31 +118,11 @@ namespace ia::iae
return g_debugUIWindows.size() - 1; return g_debugUIWindows.size() - 1;
} }
VOID DebugDraw::SetLineVisibility(IN Handle handle, IN BOOL visible)
{
g_lineShapes[handle].Visibility = visible;
}
VOID DebugDraw::SetRectVisibility(IN Handle handle, IN BOOL visible)
{
g_rectShapes[handle].Visibility = visible;
}
VOID DebugDraw::SetUIWindowVisibility(IN Handle handle, IN BOOL visible) VOID DebugDraw::SetUIWindowVisibility(IN Handle handle, IN BOOL visible)
{ {
g_debugUIWindows[handle].Visibility = visible; g_debugUIWindows[handle].Visibility = visible;
} }
VOID DebugDraw::ToggleLineVisibility(IN Handle handle)
{
g_lineShapes[handle].Visibility = !g_lineShapes[handle].Visibility;
}
VOID DebugDraw::ToggleRectVisibility(IN Handle handle)
{
g_rectShapes[handle].Visibility = !g_rectShapes[handle].Visibility;
}
VOID DebugDraw::ToggleUIWindowVisibility(IN Handle handle) VOID DebugDraw::ToggleUIWindowVisibility(IN Handle handle)
{ {
g_debugUIWindows[handle].Visibility = !g_debugUIWindows[handle].Visibility; g_debugUIWindows[handle].Visibility = !g_debugUIWindows[handle].Visibility;

View File

@ -64,11 +64,13 @@ namespace ia::iae
STATIC VOID Initialize(); STATIC VOID Initialize();
STATIC VOID Terminate(); STATIC VOID Terminate();
STATIC Sound CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize); STATIC VOID Update();
STATIC INT64 CreateTrack(); STATIC INT64 CreateTrack();
STATIC VOID DestroyTrack(IN INT64 trackHandle); STATIC VOID DestroyTrack(IN INT64 trackHandle);
STATIC Sound CreateSound(IN PCUINT8 audioData, IN SIZE_T audioDataSize);
STATIC VOID QueueTrackData(IN INT64 trackHandle, IN INT64 dataHandle); STATIC VOID QueueTrackData(IN INT64 trackHandle, IN INT64 dataHandle);
STATIC VOID PlayTrack(IN INT64 trackHandle, IN INT32 loopTimes, IN TimePeriod loopDelay); STATIC VOID PlayTrack(IN INT64 trackHandle, IN INT32 loopTimes, IN TimePeriod loopDelay);
STATIC VOID ClearTrack(IN INT64 trackHandle); STATIC VOID ClearTrack(IN INT64 trackHandle);

View File

@ -58,14 +58,20 @@ namespace ia::iae
return m_colliders; return m_colliders;
} }
CONST glm::vec2& GetVelocity() CONST
{
return m_velocity;
}
public: public:
VOID Draw(); VOID Draw();
VOID Update(); VOID Update();
private: private:
glm::vec2 m_velocity{};
BOOL m_isDynamic{false}; BOOL m_isDynamic{false};
FLOAT32 m_movementSpeed{2.0f};
Vector<Collider> m_colliders; Vector<Collider> m_colliders;
FLOAT32 m_movementSpeed{1.0f};
Handle m_physicsHandle{INVALID_HANDLE}; Handle m_physicsHandle{INVALID_HANDLE};
VOID OnCollision(IN PhysicsComponent *other); VOID OnCollision(IN PhysicsComponent *other);

View File

@ -255,8 +255,8 @@ namespace ia::iae
enum class DirectionalInput: UINT8 enum class DirectionalInput: UINT8
{ {
NONE = 0, NONE = 255,
DOWN, DOWN = 0,
DOWN_LEFT, DOWN_LEFT,
LEFT, LEFT,
UP_LEFT, UP_LEFT,

View File

@ -39,7 +39,7 @@ namespace ia::iae
VIRTUAL VOID Disable(); VIRTUAL VOID Disable();
public: public:
VOID AddChild(IN RefPtr<Node> node); Node* AddChild(IN RefPtr<Node> node);
template<typename _component_type> _component_type *AddComponent(); template<typename _component_type> _component_type *AddComponent();

View File

@ -33,7 +33,9 @@ namespace ia::iae
STATIC VOID Terminate(); STATIC VOID Terminate();
STATIC VOID Update(); STATIC VOID Update();
STATIC VOID DebugDraw();
friend class Engine; friend class Engine;
friend class DebugDraw;
}; };
} }

View File

@ -23,18 +23,17 @@ namespace ia::iae
class DebugDraw class DebugDraw
{ {
public: public:
STATIC Handle AddLine(IN CONST glm::vec2& from, IN CONST glm::vec2& to, IN CONST glm::vec4& color, IN FLOAT32 thickness = 1.0f);
STATIC Handle AddRect(IN CONST glm::vec2& position, IN CONST glm::vec2& size, IN CONST glm::vec4& color);
STATIC Handle AddUIWindow(IN PCCHAR title, IN CONST glm::vec2 &position, IN CONST glm::vec2 &size, STATIC Handle AddUIWindow(IN PCCHAR title, IN CONST glm::vec2 &position, IN CONST glm::vec2 &size,
IN std::function<VOID()> contentDrawCallback); IN std::function<VOID()> contentDrawCallback);
STATIC VOID SetLineVisibility(IN Handle handle, IN BOOL visible); STATIC VOID ToggleUIWindowVisibility(IN Handle handle);
STATIC VOID SetRectVisibility(IN Handle handle, IN BOOL visible);
STATIC VOID SetUIWindowVisibility(IN Handle handle, IN BOOL visible); STATIC VOID SetUIWindowVisibility(IN Handle handle, IN BOOL visible);
STATIC VOID ToggleLineVisibility(IN Handle handle); public:
STATIC VOID ToggleRectVisibility(IN Handle handle); STATIC VOID DrawLine(IN CONST glm::vec2 &from, IN CONST glm::vec2 &to, IN CONST glm::vec4 &color,
STATIC VOID ToggleUIWindowVisibility(IN Handle handle); IN FLOAT32 thickness = 1.0f);
STATIC VOID DrawRect(IN CONST glm::vec2 &position, IN CONST glm::vec2 &size, IN CONST glm::vec4 &color, IN FLOAT32 thickness = 1.0f);
STATIC VOID DrawRectFilled(IN CONST glm::vec2 &position, IN CONST glm::vec2 &size, IN CONST glm::vec4 &color);
private: private:
STATIC VOID Initailize(); STATIC VOID Initailize();