From afe30a5dbd9a3d2e9ac93f3ffb782d8c6f154e8c Mon Sep 17 00:00:00 2001 From: tobid7 Date: Thu, 19 Mar 2026 22:06:58 +0100 Subject: [PATCH] Add Drawlist - Add Pool iterator support - Add Pool Expandability - Add Pool::Push - Add Lithium Maths API - Remove InitPools - update spirv-helper --- CMakeLists.txt | 2 + include/pd/core/pool.hpp | 37 +++-- include/pd/drivers/gfx.hpp | 18 +- include/pd/lithium/drawlist.hpp | 116 +++++++++++++ include/pd/lithium/lithium.hpp | 4 +- include/pd/lithium/math.hpp | 18 ++ include/pd/lithium/pools.hpp | 2 +- include/pd/lithium/texture.hpp | 1 + source/lithium/drawlist.cpp | 285 ++++++++++++++++++++++++++++++++ source/lithium/math.cpp | 65 ++++++++ source/lithium/pools.cpp | 5 - tests/gfx/source/main.cpp | 28 +--- vendor/spirv-helper | 2 +- 13 files changed, 541 insertions(+), 42 deletions(-) create mode 100644 include/pd/lithium/drawlist.hpp create mode 100644 include/pd/lithium/math.hpp create mode 100644 source/lithium/drawlist.cpp create mode 100644 source/lithium/math.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 96d7a45..3ab9a6a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,8 @@ set(PD_SOURCES # Lithium source/lithium/pools.cpp + source/lithium/math.cpp + source/lithium/drawlist.cpp ) if(${PD_BUILD_SHARED}) diff --git a/include/pd/core/pool.hpp b/include/pd/core/pool.hpp index 391b494..968106c 100644 --- a/include/pd/core/pool.hpp +++ b/include/pd/core/pool.hpp @@ -8,7 +8,7 @@ class Pool { public: using value_type = T; using iterator = T*; - using const_iterator = const iterator*; + using const_iterator = const T*; Pool() = default; ~Pool() { @@ -36,21 +36,34 @@ class Pool { Pool& operator=(Pool&&) = delete; T* Allocate(size_t num = 1) { - if (CheckLimits(num)) return nullptr; + ExpandIf(num); T* ret = &pData[pPos]; pPos += num; return ret; } - bool CheckLimits(size_t num) { - if ((pPos + num) >= pCap) { - throw std::runtime_error( - std::format("[PD::Pool]: Trying to allocate {} elements but this is " - "going out of range ({}/{})", - num, pPos + num, pCap)); - return true; + void Push(const T& elem) { + T* e = Allocate(1); + *e = elem; + } + + void ExpandIf(size_t req) { + if ((pPos + req) <= pCap) return; + size_t ncap = std::max(pCap * 2, pPos + req); + T* nu = pAlloc.allocate(ncap); + if (pData) { + for (size_t i = 0; i < pPos; i++) { + std::allocator_traits::construct( + pAlloc, &nu[i], std::move_if_noexcept(pData[i])); + } + pAlloc.deallocate(pData, pCap); } - return false; + for (size_t i = pPos; i < ncap; i++) { + std::allocator_traits::construct(pAlloc, &nu[i]); + } + PDLOG("Pool::ExpandIf({}): {} -> {}", req, pCap, ncap); + pData = nu; + pCap = ncap; } void Reset() { @@ -67,6 +80,10 @@ class Pool { size_t capacity() const { return pCap; } T& at(size_t idx) { return pData[idx]; } const T& at(size_t idx) const { return pData[idx]; } + iterator begin() { return pData; } + iterator end() { return pData + pPos; } + const_iterator begin() const { return pData; } + const_iterator end() const { return pData + pPos; } T& operator[](size_t idx) { return at(idx); } const T& operator[](size_t idx) const { return at(idx); } diff --git a/include/pd/drivers/gfx.hpp b/include/pd/drivers/gfx.hpp index 6cf6e43..080fb4a 100755 --- a/include/pd/drivers/gfx.hpp +++ b/include/pd/drivers/gfx.hpp @@ -34,6 +34,7 @@ class PD_API GfxDriver : public DriverInterface { } virtual void DeleteTexture(const Li::Texture& tex) {} virtual void Draw(const Pool& commands) {} + Li::Texture::Ptr GetWhiteTexture() { return &pWhite; } protected: virtual void SysDeinit() {} @@ -55,6 +56,7 @@ class PD_API GfxDriver : public DriverInterface { Mat4 Projection; ivec2 ViewPort; std::unordered_map pTextureRegestry; + Li::Texture pWhite; }; struct DefaultGfxConfig { @@ -79,9 +81,11 @@ class GfxDriverBase : public GfxDriver { virtual ~GfxDriverBase() {} void Init() override { - pVtxPool.Init(Config::NumVertices); - pIdxPool.Init(Config::NumIndices); + // pVtxPool.Init(Config::NumVertices); + // pIdxPool.Init(Config::NumIndices); SysInit(); + std::vector img(16 * 16 * 4, 0xff); + pWhite = LoadTexture(img, 16, 16); } void Draw(const Pool& commands) override { @@ -90,11 +94,12 @@ class GfxDriverBase : public GfxDriver { while (index < commands.size()) { CurrentTex = commands[index].Tex; if (!CurrentTex) { - index++; - continue; + CurrentTex = pWhite.GetID(); } size_t startidx = CurrentIndex; - while (index < commands.size() && CurrentTex == commands[index].Tex) { + while (index < commands.size() && + (CurrentTex == commands[index].Tex || + (CurrentTex == pWhite.GetID() && commands[index].Tex == 0))) { const auto& c = commands[index]; CountVertices += c.VertexCount; CountIndices += c.IndexCount; @@ -155,6 +160,9 @@ class PD_API Gfx { static void DeleteTexture(const Li::Texture& tex) { driver->DeleteTexture(tex); } + static Li::Texture::Ptr GetWhiteTexture() { + return driver->GetWhiteTexture(); + } static const char* GetDriverName() { return driver->GetName(); } diff --git a/include/pd/lithium/drawlist.hpp b/include/pd/lithium/drawlist.hpp new file mode 100644 index 0000000..d8d0754 --- /dev/null +++ b/include/pd/lithium/drawlist.hpp @@ -0,0 +1,116 @@ +#pragma once + +#include +#include + +using LiPathRectFlags = PD::u32; + +enum LiPathRectFlags_ : PD::u32 { + LiPathRectFlags_None = 0, + LiPathRectFlags_KeepTopLeft = 1 << 0, + LiPathRectFlags_KeepTopRight = 1 << 1, + LiPathRectFlags_KeepBotRight = 1 << 2, + LiPathRectFlags_KeepBotLeft = 1 << 3, + LiPathRectFlags_KeepTop = + LiPathRectFlags_KeepTopLeft | LiPathRectFlags_KeepTopRight, + LiPathRectFlags_KeepBot = + LiPathRectFlags_KeepBotLeft | LiPathRectFlags_KeepBotRight, + LiPathRectFlags_KeepLeft = + LiPathRectFlags_KeepTopLeft | LiPathRectFlags_KeepBotLeft, + LiPathRectFlags_KeepRight = + LiPathRectFlags_KeepTopRight | LiPathRectFlags_KeepBotRight, +}; + +using LiDrawFlags = PD::u32; +enum LiDrawFlags_ : PD::u32 { + LiDrawFlags_None = 0, + LiDrawFlags_Close = 1 << 0, +}; + +using LiTextFlags = PD::u32; +enum LiTextFlags_ : PD::u32 { + LiTextFlags_None = 0, ///< Do nothing + LiTextFlags_AlignRight = 1 << 0, ///< Align Right of position + LiTextFlags_AlignMid = 1 << 1, ///< Align in the middle of pos and box + LiTextFlags_Shaddow = 1 << 2, ///< Draws the text twice to create shaddow + LiTextFlags_Wrap = 1 << 3, ///< Wrap Text: May be runs better with TMS + LiTextFlags_Short = 1 << 4, ///< Short Text: May be runs better with TMS + LiTextFlags_Scroll = 1 << 5, ///< Not implemented [scoll text if to long] + LiTextFlags_NoOOS = 1 << 6, ///< No Out of Screen Rendering +}; + +namespace PD { +namespace Li { +class PD_API Drawlist { + public: + Drawlist(); + ~Drawlist(); + + /** Baisc */ + + void Merge(Drawlist& other); + void Copy(Drawlist& other); + void Optimize(); + void Clear(); + + /** Command Allocation */ + Command& NewCommand(); + + /** Path API */ + void PathAdd(const fvec2& point) { pPath.Push(point); } + void PathAdd(float x, float y) { pPath.Push(fvec2(x, y)); } + void PathClear() { pPath.Reset(); } + /** + * @brief Reserve memory for the next PathAdd uses + * @note As path will autoexpant and keep the size this func is + * only for special use cases + */ + void PathReserve(size_t num) { pPath.ExpandIf(num); } + void PathStroke(u32 color, int t = 1, LiDrawFlags flags = LiDrawFlags_None); + void PathFill(u32 color); + void PathArcToN(const fvec2& c, float r, float amin, float amax, int s); + void PathFastArcToN(const fvec2& c, float r, float amin, float amax, int s); + void PathRect(const fvec2& tl, const fvec2& br, float r = 0.f); + void PathRectEx(const fvec2& tl, const fvec2& br, float r = 0.f, + LiPathRectFlags flags = LiPathRectFlags_None); + + /** Texture Handling */ + void BindTexture(const Texture& tex); + void UnbindTexture() { pCurrentTexture = Texture(); } + + /** Data geters */ + const Pool& Data() const { return pCommands; } + operator const Pool&() const { return pCommands; } + + /** Drawing functions */ + void DrawRect(const fvec2& pos, const fvec2& size, u32 color, int t = 1); + void DrawRectFilled(const fvec2& pos, const fvec2& size, u32 color); + void DrawTriangle(const fvec2& a, const fvec2& b, const fvec2& c, u32 color, + int t = 1); + void DrawTriangleFilled(const fvec2& a, const fvec2& b, const fvec2& c, + u32 color); + void DrawCircle(const fvec2& center, float rad, u32 color, int num_segments, + int t = 1); + void DrawCircleFilled(const fvec2& center, float rad, u32 color, + int num_segments); + void DrawText(const fvec2& p, const char* text, u32 color); + void DrawTextEx(const fvec2& p, const char* text, u32 color, + LiTextFlags flags, const fvec2& box = fvec2(0.f)); + + void DrawPolyLine(const Pool& points, u32 color, + LiDrawFlags flags = LiDrawFlags_None, int t = 1); + void DrawConvexPolyFilled(const Pool& points, u32 color); + + void PrimQuad(Command& cmd, const Rect& quad, const Rect& uv, u32 color); + void PrimTriangle(Command& cmd, const fvec2& a, const fvec2& b, + const fvec2& c, u32 color); + + private: + Texture pCurrentTexture; + Pool pCommands; + Pool pPath; + Pool pVertices; + Pool pIndices; +}; +} // namespace Li +} // namespace PD \ No newline at end of file diff --git a/include/pd/lithium/lithium.hpp b/include/pd/lithium/lithium.hpp index 73e316e..0fc3cd3 100644 --- a/include/pd/lithium/lithium.hpp +++ b/include/pd/lithium/lithium.hpp @@ -1,5 +1,7 @@ #pragma once #include +#include +#include #include -#include \ No newline at end of file +#include diff --git a/include/pd/lithium/math.hpp b/include/pd/lithium/math.hpp new file mode 100644 index 0000000..5bade85 --- /dev/null +++ b/include/pd/lithium/math.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +namespace PD { +namespace Li { +namespace Math { +PD_API bool InBounds(const fvec2& pos, const fvec2& size, const fvec4& rect); +PD_API bool InBounds(const fvec2& pos, const fvec4& rect); +PD_API bool InBounds(const fvec2& a, const fvec2& b, const fvec2& c, + const fvec4& rect); +PD_API void RotateCorner(fvec2& pos, float sinus, float cosinus); +PD_API Rect PrimRect(const fvec2& pos, const fvec2& size, float angle = 0.f); +PD_API Rect PrimLine(const fvec2& a, const fvec2& b, int t = 1); +} // namespace Math +} // namespace Li +} // namespace PD \ No newline at end of file diff --git a/include/pd/lithium/pools.hpp b/include/pd/lithium/pools.hpp index 9887562..0664382 100644 --- a/include/pd/lithium/pools.hpp +++ b/include/pd/lithium/pools.hpp @@ -5,8 +5,8 @@ namespace PD { namespace Li { -PD_API void InitPools(size_t max_vertices = 32768); PD_API Vertex* AllocateVertices(size_t count); PD_API u16* AllocateIndices(size_t count); +PD_API void ResetPools(); } // namespace Li } // namespace PD \ No newline at end of file diff --git a/include/pd/lithium/texture.hpp b/include/pd/lithium/texture.hpp index 9b476e8..ebb0499 100644 --- a/include/pd/lithium/texture.hpp +++ b/include/pd/lithium/texture.hpp @@ -18,6 +18,7 @@ enum class TextureFormat { namespace Li { class Texture { public: + using Ptr = Texture*; Texture() : pID(0), pSize(0, 0), pUV(fvec4(0, 0, 1, 1)) {} Texture(TextureID id, ivec2 size) : pID(id), pSize(size), pUV(fvec4(0, 0, 1, 1)) {} diff --git a/source/lithium/drawlist.cpp b/source/lithium/drawlist.cpp new file mode 100644 index 0000000..5f6f925 --- /dev/null +++ b/source/lithium/drawlist.cpp @@ -0,0 +1,285 @@ +#include +#include +#include + +namespace PD { +namespace Li { +PD_API Drawlist::Drawlist() { Clear(); } + +PD_API Drawlist::~Drawlist() { Clear(); } + +PD_API void Drawlist::Merge(Drawlist& other) {} + +PD_API void Drawlist::Copy(Drawlist& other) {} + +PD_API void Drawlist::Optimize() {} + +PD_API void Drawlist::Clear() { + UnbindTexture(); + pPath.Reset(); + pVertices.Reset(); + pIndices.Reset(); +} + +/** Command Allocation */ +PD_API Command& Drawlist::NewCommand() { + auto cmd = pCommands.Allocate(1); + cmd->Tex = pCurrentTexture.GetID(); + return *cmd; +} + +PD_API void Drawlist::BindTexture(const Texture& tex) { pCurrentTexture = tex; } + +/** Path API */ +PD_API void Drawlist::PathStroke(u32 color, int t, LiDrawFlags flags) { + DrawPolyLine(pPath, color, flags, t); + PathClear(); +} + +PD_API void Drawlist::PathFill(u32 color) { + DrawConvexPolyFilled(pPath, color); + PathClear(); +} + +PD_API void Drawlist::PathArcToN(const fvec2& c, float r, float amin, + float amax, int s) { + // Path.push_back(c); + PathReserve(s + 1); + for (int i = 0; i < s; i++) { + float a = amin + ((float)i / (float)s) * (amax - amin); + PathAdd(vec2(c.x + std::cos(a) * r, c.y + std::sin(a) * r)); + } +} + +PD_API void Drawlist::PathFastArcToN(const fvec2& c, float r, float amin, + float amax, int s) { + /** + * Funcion with less division overhead + * Usefull for stuff where a lot of calculations are required + */ + float d = (amax - amin) / s; + PathReserve(s + 1); + for (int i = 0; i <= s; i++) { + float a = amin + i * d; + PathAdd(fvec2(c.x + std::cos(a) * r, c.y + std::sin(a) * r)); + } +} + +PD_API void Drawlist::PathRect(const fvec2& tl, const fvec2& br, float r) { + if (r == 0.f) { + PathAdd(tl); + PathAdd(vec2(br.x, tl.y)); + PathAdd(br); + PathAdd(vec2(tl.x, br.y)); + } else { + float r = std::min({r, (br.x - tl.x) * 0.5f, (br.y - tl.y) * 0.5f}); + /** Calculate Optimal segment count automatically */ + float corner = M_PI * 0.5f; + int segments = std::max(3, int(std::ceil(corner / (6.0f * M_PI / 180.0f)))); + + /** + * To Correctly render filled shapes with Paths API + * The Commands need to be setup clockwise + */ + /** Top Left */ + PathAdd(vec2(tl.x + r, tl.y)); + PathFastArcToN(vec2(br.x - r, tl.y + r), r, -M_PI / 2.0f, 0.0f, segments); + /** Top Right */ + PathAdd(vec2(br.x, br.y - r)); + PathFastArcToN(vec2(br.x - r, br.y - r), r, 0.0f, M_PI / 2.0f, segments); + /** Bottom Right */ + PathAdd(vec2(tl.x + r, br.y)); + PathFastArcToN(vec2(tl.x + r, br.y - r), r, M_PI / 2.0f, M_PI, segments); + /** Bottom Left */ + PathAdd(vec2(tl.x, tl.y + r)); + PathFastArcToN(vec2(tl.x + r, tl.y + r), r, M_PI, 3.0f * M_PI / 2.0f, + segments); + } +} + +PD_API void Drawlist::PathRectEx(const fvec2& tl, const fvec2& br, float r, + LiPathRectFlags flags) { + if (r == 0.f) { + PathAdd(tl); + PathAdd(vec2(br.x, tl.y)); + PathAdd(br); + PathAdd(vec2(tl.x, br.y)); + } else { + float r = std::min({r, (br.x - tl.x) * 0.5f, (br.y - tl.y) * 0.5f}); + /** Calculate Optimal segment count automatically */ + float corner = M_PI * 0.5f; + int segments = std::max(3, int(std::ceil(corner / (6.0f * M_PI / 180.0f)))); + + /** + * To Correctly render filled shapes with Paths API + * The Commands need to be setup clockwise + */ + /** Top Left */ + if (flags & LiPathRectFlags_KeepTopLeft) { + PathAdd(tl); + } else { + PathAdd(vec2(tl.x + r, tl.y)); + PathFastArcToN(vec2(br.x - r, tl.y + r), r, -M_PI / 2.0f, 0.0f, segments); + } + + /** Top Right */ + if (flags & LiPathRectFlags_KeepTopRight) { + PathAdd(vec2(br.x, tl.y)); + } else { + PathAdd(vec2(br.x, br.y - r)); + PathFastArcToN(vec2(br.x - r, br.y - r), r, 0.0f, M_PI / 2.0f, segments); + } + /** Bottom Right */ + if (flags & LiPathRectFlags_KeepBotRight) { + PathAdd(br); + } else { + PathAdd(vec2(tl.x + r, br.y)); + PathFastArcToN(vec2(tl.x + r, br.y - r), r, M_PI / 2.0f, M_PI, segments); + } + /** Bottom Left */ + if (flags & LiPathRectFlags_KeepBotLeft) { + PathAdd(vec2(tl.x, br.y)); + } else { + PathAdd(vec2(tl.x, tl.y + r)); + PathFastArcToN(vec2(tl.x + r, tl.y + r), r, M_PI, 3.0f * M_PI / 2.0f, + segments); + } + } +} + +/** Drawing functions */ +PD_API void Drawlist::DrawRect(const fvec2& pos, const fvec2& size, u32 color, + int t) { + PathRect(pos, pos + size); + PathStroke(color, t, LiDrawFlags_Close); +} + +PD_API void Drawlist::DrawRectFilled(const fvec2& pos, const fvec2& size, + u32 color) { + PathRect(pos, pos + size); + PathFill(color); +} + +PD_API void Drawlist::DrawTriangle(const fvec2& a, const fvec2& b, + const fvec2& c, u32 color, int t) { + PathAdd(a); + PathAdd(b); + PathAdd(c); + PathStroke(color, t, LiDrawFlags_Close); +} + +PD_API void Drawlist::DrawTriangleFilled(const fvec2& a, const fvec2& b, + const fvec2& c, u32 color) { + PathAdd(a); + PathAdd(b); + PathAdd(c); + PathFill(color); +} + +PD_API void Drawlist::DrawCircle(const fvec2& center, float rad, u32 color, + int num_segments, int t) { + if (num_segments <= 0) { + // Auto Segment + } else { + float am = (M_PI * 2.0f) * ((float)num_segments) / (float)num_segments; + PathArcToN(center, rad, 0.f, am, num_segments); + } + UnbindTexture(); // Only Solid Color Supported + PathStroke(color, t, LiDrawFlags_Close); +} + +PD_API void Drawlist::DrawCircleFilled(const fvec2& center, float rad, + u32 color, int num_segments) { + if (num_segments <= 0) { + // Auto Segment + } else { + float am = (M_PI * 2.0f) * ((float)num_segments) / (float)num_segments; + PathArcToN(center, rad, 0.f, am, num_segments); + } + PathFill(color); +} + +PD_API void Drawlist::DrawText(const fvec2& p, const char* text, u32 color) {} + +PD_API void Drawlist::DrawTextEx(const fvec2& p, const char* text, u32 color, + LiTextFlags flags, const fvec2& box) {} + +PD_API void Drawlist::DrawPolyLine(const Pool& points, u32 color, + LiDrawFlags flags, int t) { + if (points.size() < 2) { + return; + } + UnbindTexture(); + auto& cmd = NewCommand(); + bool close = (flags & (1 << 0)); + int num_points = close ? (int)points.size() : (int)points.size() - 1; + if (flags & (1 << 1)) { + // TODO: Find a way to draw less garbage looking lines + } else { + // Non antialiased lines look awful when rendering with thickness != 1 + for (int i = 0; i < num_points; i++) { + int j = (i + 1) == (int)points.size() ? 0 : (i + 1); + auto line = Math::PrimLine(points[i], points[j], t); + this->PrimQuad(cmd, line, vec4(0.f, 1.f, 1.f, 0.f), color); + } + } +} + +PD_API void Drawlist::DrawConvexPolyFilled(const Pool& points, + u32 color) { + if (points.size() < 3) { + return; // Need at least three points + } + + // Support for Custom Textures (UV calculation) + float minX = points[0].x, minY = points[0].y; + float maxX = minX, maxY = minY; + // Check for the max and min Positions + for (const auto& it : points) { + if (it.x < minX) minX = it.x; + if (it.y < minY) minY = it.y; + if (it.x > maxX) maxX = it.x; + if (it.y > maxY) maxY = it.y; + } + // Get Short defines for UV + // (Bottom Right is not required) + auto uv_tl = pCurrentTexture.GetUV().TopLeft(); + auto uv_tr = pCurrentTexture.GetUV().TopRight(); + auto uv_bl = pCurrentTexture.GetUV().BotLeft(); + + auto& cmd = NewCommand(); + cmd.Reserve(points.size(), (points.size() - 2) * 3); + // Render + for (int i = 2; i < (int)points.size(); i++) { + cmd.Add(0, i, i - 1); + } + + for (int i = 0; i < (int)points.size(); i++) { + // Calculate U and V coords + float u = + uv_tl.x + ((points[i].x - minX) / (maxX - minX)) * (uv_tr.x - uv_tl.x); + float v = + uv_tl.y + ((points[i].y - minY) / (maxY - minY)) * (uv_bl.y - uv_tl.y); + cmd.Add(Vertex(points[i], fvec2(u, v), color)); + } +} + +PD_API void Drawlist::PrimQuad(Command& cmd, const Rect& quad, const Rect& uv, + u32 color) { + cmd.Add(2, 1, 0); + cmd.Add(3, 2, 0); + cmd.Add(Vertex(quad.TopLeft(), uv.TopLeft(), color)); + cmd.Add(Vertex(quad.TopRight(), uv.TopRight(), color)); + cmd.Add(Vertex(quad.BotRight(), uv.BotRight(), color)); + cmd.Add(Vertex(quad.BotLeft(), uv.BotLeft(), color)); +} + +PD_API void Drawlist::PrimTriangle(Command& cmd, const fvec2& a, const fvec2& b, + const fvec2& c, u32 color) { + cmd.Add(2, 1, 0); + cmd.Add(Vertex(a, vec2(0.f, 1.f), color)); + cmd.Add(Vertex(b, vec2(1.f, 1.f), color)); + cmd.Add(Vertex(c, vec2(1.f, 0.f), color)); +} +} // namespace Li +} // namespace PD \ No newline at end of file diff --git a/source/lithium/math.cpp b/source/lithium/math.cpp new file mode 100644 index 0000000..1417320 --- /dev/null +++ b/source/lithium/math.cpp @@ -0,0 +1,65 @@ +#include + +namespace PD { +namespace Li { +namespace Math { +PD_API bool InBounds(const fvec2& pos, const fvec2& size, const fvec4& rect) { + return (pos.x + size.x >= rect.x && pos.y + size.y >= rect.y && + pos.x <= rect.z && pos.y <= rect.w); +} + +PD_API bool InBounds(const fvec2& pos, const fvec4& rect) { + return (pos.x > rect.x && pos.x < rect.x + rect.z && pos.y > rect.y && + pos.y < rect.y + rect.w); +} + +PD_API bool InBounds(const fvec2& a, const fvec2& b, const fvec2& c, + const fvec4& rect) { + return ((a.x < rect.z && b.x < rect.z && c.x < rect.z) || + (a.y < rect.w && b.y < rect.w && c.y < rect.w) || + (a.x > 0 && b.x > 0 && c.x > 0) || (a.y > 0 && b.y > 0 && c.y > 0)); +} + +PD_API void RotateCorner(fvec2& pos, float sinus, float cosinus) { + float x = pos.x * cosinus - pos.y * sinus; + float y = pos.y * cosinus - pos.x * sinus; + pos = fvec2(x, y); +} + +PD_API Rect PrimRect(const fvec2& pos, const fvec2& size, float a) { + fvec2 c = size * 0.5f; // Center + fvec2 corner[4] = { + fvec2(-c.x, -c.y), + fvec2(-c.x + size.x, -c.y), + fvec2(-c.x, -c.y + size.y), + fvec2(-c.x + size.x, -c.y + size.y), + }; + + // Only rotate if required + if (a != 0.f) { + float s = std::sin(a); + float co = std::cos(a); + for (int i = 0; i < 4; i++) { + RotateCorner(corner[i], s, co); + } + } + + // Return Result + return Rect(corner[0] + pos + c, corner[1] + pos + c, corner[2] + pos + c, + corner[3] + pos + c); +} + +PD_API Rect PrimLine(const fvec2& a, const fvec2& b, int t) { + // Using the vec maths api makes the code as short as it is + vec2 dir = a - b; + float len = dir.Len(); + vec2 unit_dir = dir / len; + vec2 perpendicular(-unit_dir.y, unit_dir.x); + vec2 off = perpendicular * ((float)t * 0.5f); + + return Rect(a + off, b + off, a - off, b - off); +} + +} // namespace Math +} // namespace Li +} // namespace PD \ No newline at end of file diff --git a/source/lithium/pools.cpp b/source/lithium/pools.cpp index 2bb21c2..d3722e3 100644 --- a/source/lithium/pools.cpp +++ b/source/lithium/pools.cpp @@ -6,11 +6,6 @@ namespace Li { PD::Pool pVtxPool; PD::Pool pIdxPool; -PD_API void InitPools(size_t max_vertices) { - pVtxPool.Init(max_vertices); - pIdxPool.Init(max_vertices * 2); -} - PD_API Vertex* AllocateVertices(size_t count) { return pVtxPool.Allocate(count); } diff --git a/tests/gfx/source/main.cpp b/tests/gfx/source/main.cpp index 7aa3261..a545b09 100644 --- a/tests/gfx/source/main.cpp +++ b/tests/gfx/source/main.cpp @@ -96,6 +96,7 @@ class App { glfwSwapInterval(1); #else gfxInitDefault(); + consoleInit(GFX_BOTTOM, nullptr); C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); Top = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); @@ -107,29 +108,18 @@ class App { PD::Gfx::UseDriver(); #endif PD::Gfx::Init(); - PD::Li::InitPools(8192); #ifdef __3DS__ pTex = LoadTex("sdmc:/icon.png"); #else pTex = LoadTex("icon.png"); #endif - /*std::vector img(16 * 16 * 4, 0xff); - pTex = PD::Gfx::LoadTexture(img, 16, 16);*/ + pList.DrawRectFilled(0, 50, 0xff00ffff); + pList.BindTexture(pTex); + pList.DrawRectFilled(50, pTex.GetSize(), 0xffffffff); + pList.DrawCircleFilled(500, 100, 0xffffffff, 50); + // pList.PathRect(300, 700, 40.f); + // pList.PathFill(0xffffffff); std::cout << "GfxDriver: " << PD::Gfx::GetDriverName() << std::endl; - pPool.Init(10); - auto cmd = pPool.Allocate(1); - cmd->Reserve(4, 6); - cmd->Add(0, 1, 2); - cmd->Add(0, 2, 3); - cmd->Add( - PD::Li::Vertex(PD::fvec2(0, 0), pTex.GetUV().TopLeft(), 0xffffffff)); - cmd->Add(PD::Li::Vertex(PD::fvec2(pTex.GetSize().x, 0), - pTex.GetUV().TopRight(), 0xffffffff)); - cmd->Add(PD::Li::Vertex(PD::fvec2(pTex.GetSize().x, pTex.GetSize().y), - pTex.GetUV().BotRight(), 0xffffffff)); - cmd->Add(PD::Li::Vertex(PD::fvec2(0, pTex.GetSize().y), - pTex.GetUV().BotLeft(), 0xffffffff)); - cmd->Tex = pTex.GetID(); } ~App() { PD::Gfx::DeleteTexture(pTex); @@ -168,7 +158,7 @@ class App { #endif PD::Gfx::Reset(); - PD::Gfx::Draw(pPool); + PD::Gfx::Draw(pList); #ifdef __3DS__ C3D_FrameEnd(0); #else @@ -194,7 +184,7 @@ class App { #else GLFWwindow* window = nullptr; #endif - PD::Pool pPool; + PD::Li::Drawlist pList; PD::Li::Texture pTex; Driver pDriver; #ifdef _WIN32 diff --git a/vendor/spirv-helper b/vendor/spirv-helper index 681ab8a..e05a0a4 160000 --- a/vendor/spirv-helper +++ b/vendor/spirv-helper @@ -1 +1 @@ -Subproject commit 681ab8a8b3626ff3788cd33d92a67002d513a4d9 +Subproject commit e05a0a45c21b65f7f4daf0dd64f0ae60c155d86a