From 2dffdf757c2a7f842a89884dadcfdb2ef99c8f31 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 30 Jun 2024 22:05:12 +0300 Subject: [PATCH] add atlases support --- src/coders/png.cpp | 12 ++++-------- src/graphics/core/Batch2D.cpp | 15 +++++++++++---- src/graphics/core/Batch2D.hpp | 4 +++- src/graphics/core/GLTexture.hpp | 4 ++++ src/graphics/core/Texture.hpp | 2 ++ src/graphics/ui/elements/Image.cpp | 26 ++++++++++++++++++++++---- src/maths/UVRegion.hpp | 10 ++++++++++ 7 files changed, 56 insertions(+), 17 deletions(-) diff --git a/src/coders/png.cpp b/src/coders/png.cpp index 9b3eb726..08adb5c9 100644 --- a/src/coders/png.cpp +++ b/src/coders/png.cpp @@ -235,7 +235,6 @@ std::unique_ptr _png_load(const char* file){ FILE *png = nullptr; char *pngbuf = nullptr; spng_ctx *ctx = nullptr; - unsigned char *out = nullptr; png = fopen(file, "rb"); if (png == nullptr){ @@ -297,27 +296,24 @@ std::unique_ptr _png_load(const char* file){ logger.error() << "spng_decoded_image_size(): " << spng_strerror(r); return nullptr; } - out = new unsigned char[out_size]; - r = spng_decode_image(ctx, out, out_size, SPNG_FMT_RGBA8, 0); + auto out = std::make_unique(out_size); + r = spng_decode_image(ctx, out.get(), out_size, SPNG_FMT_RGBA8, 0); if (r != SPNG_SUCCESS){ - delete[] out; delete[] pngbuf; spng_ctx_free(ctx); logger.error() << "spng_decode_image(): " << spng_strerror(r); return nullptr; } - unsigned char* flipped = new unsigned char[out_size]; - + auto flipped = std::make_unique(out_size); for (size_t i = 0; i < ihdr.height; i+=1){ size_t rowsize = ihdr.width*4; for (size_t j = 0; j < rowsize; j++){ flipped[(ihdr.height-i-1)*rowsize+j] = out[i*rowsize+j]; } } - delete[] out; // <- finally delete out // no, delete spng usage - auto image = std::make_unique(ImageFormat::rgba8888, ihdr.width, ihdr.height, (void*)flipped); + auto image = std::make_unique(ImageFormat::rgba8888, ihdr.width, ihdr.height, std::move(flipped)); delete[] pngbuf; spng_ctx_free(ctx); diff --git a/src/graphics/core/Batch2D.cpp b/src/graphics/core/Batch2D.cpp index 4fb5cf70..387fa4da 100644 --- a/src/graphics/core/Batch2D.cpp +++ b/src/graphics/core/Batch2D.cpp @@ -39,6 +39,7 @@ void Batch2D::setPrimitive(DrawPrimitive primitive) { void Batch2D::begin(){ currentTexture = nullptr; blank->bind(); + region = blank->getUVRegion(); color = glm::vec4(1.0f); primitive = DrawPrimitive::triangle; } @@ -50,8 +51,8 @@ void Batch2D::vertex( ) { buffer[index++] = x; buffer[index++] = y; - buffer[index++] = u; - buffer[index++] = v; + buffer[index++] = u * region.getWidth() + region.u1; + buffer[index++] = v * region.getHeight() + region.v1; buffer[index++] = r; buffer[index++] = g; buffer[index++] = b; @@ -64,8 +65,8 @@ void Batch2D::vertex( ) { buffer[index++] = point.x; buffer[index++] = point.y; - buffer[index++] = uvpoint.x; - buffer[index++] = uvpoint.y; + buffer[index++] = uvpoint.x * region.getWidth() + region.u1; + buffer[index++] = uvpoint.y * region.getHeight() + region.v1; buffer[index++] = r; buffer[index++] = g; buffer[index++] = b; @@ -80,8 +81,10 @@ void Batch2D::texture(Texture* new_texture){ currentTexture = new_texture; if (new_texture == nullptr) { blank->bind(); + region = blank->getUVRegion(); } else { new_texture->bind(); + region = currentTexture->getUVRegion(); } } @@ -89,6 +92,10 @@ void Batch2D::untexture() { texture(nullptr); } +void Batch2D::setRegion(UVRegion region) { + this->region = region; +} + void Batch2D::point(float x, float y, float r, float g, float b, float a){ if (index + 6*B2D_VERTEX_SIZE >= capacity) flush(); diff --git a/src/graphics/core/Batch2D.hpp b/src/graphics/core/Batch2D.hpp index 18095cff..a1a1b308 100644 --- a/src/graphics/core/Batch2D.hpp +++ b/src/graphics/core/Batch2D.hpp @@ -6,10 +6,10 @@ #include #include "commons.hpp" +#include "../../maths/UVRegion.hpp" class Mesh; class Texture; -struct UVRegion; class Batch2D { std::unique_ptr buffer; @@ -20,6 +20,7 @@ class Batch2D { glm::vec4 color; Texture* currentTexture; DrawPrimitive primitive = DrawPrimitive::triangle; + UVRegion region {0.0f, 0.0f, 1.0f, 1.0f}; void setPrimitive(DrawPrimitive primitive); @@ -42,6 +43,7 @@ public: void begin(); void texture(Texture* texture); void untexture(); + void setRegion(UVRegion region); void sprite(float x, float y, float w, float h, const UVRegion& region, glm::vec4 tint); void sprite(float x, float y, float w, float h, int atlasRes, int index, glm::vec4 tint); void point(float x, float y, float r, float g, float b, float a); diff --git a/src/graphics/core/GLTexture.hpp b/src/graphics/core/GLTexture.hpp index f001c26e..8274c202 100644 --- a/src/graphics/core/GLTexture.hpp +++ b/src/graphics/core/GLTexture.hpp @@ -20,6 +20,10 @@ public: virtual std::unique_ptr readData() override; virtual uint getId() const override; + virtual UVRegion getUVRegion() const override { + return UVRegion(0.0f, 0.0f, 1.0f, 1.0f); + } + static std::unique_ptr from(const ImageData* image); }; diff --git a/src/graphics/core/Texture.hpp b/src/graphics/core/Texture.hpp index a71cb240..62cbae43 100644 --- a/src/graphics/core/Texture.hpp +++ b/src/graphics/core/Texture.hpp @@ -2,6 +2,7 @@ #define GRAPHICS_CORE_TEXTURE_HPP_ #include "../../typedefs.hpp" +#include "../../maths/UVRegion.hpp" #include "ImageData.hpp" #include @@ -28,6 +29,7 @@ public: virtual uint getHeight() const { return height; } + virtual UVRegion getUVRegion() const = 0; virtual uint getId() const = 0; diff --git a/src/graphics/ui/elements/Image.cpp b/src/graphics/ui/elements/Image.cpp index e3b7243e..11c61470 100644 --- a/src/graphics/ui/elements/Image.cpp +++ b/src/graphics/ui/elements/Image.cpp @@ -5,6 +5,7 @@ #include "../../core/DrawContext.hpp" #include "../../core/Batch2D.hpp" #include "../../core/Texture.hpp" +#include "../../core/Atlas.hpp" #include "../../../assets/Assets.hpp" #include "../../../maths/UVRegion.hpp" @@ -18,11 +19,28 @@ void Image::draw(const DrawContext* pctx, Assets* assets) { glm::vec2 pos = calcPos(); auto batch = pctx->getBatch2D(); - auto texture = assets->get(this->texture); - if (texture && autoresize) { - setSize(glm::vec2(texture->getWidth(), texture->getHeight())); + Texture* texture = nullptr; + auto separator = this->texture.find(':'); + if (separator == std::string::npos) { + texture = assets->get(this->texture); + batch->texture(texture); + if (texture && autoresize) { + setSize(glm::vec2(texture->getWidth(), texture->getHeight())); + } + } else { + auto atlasName = this->texture.substr(0, separator); + if (auto atlas = assets->get(atlasName)) { + texture = atlas->getTexture(); + batch->texture(atlas->getTexture()); + auto& region = atlas->get(this->texture.substr(separator+1)); + batch->setRegion(region); + if (autoresize) { + setSize(glm::vec2( + texture->getWidth()*region.getWidth(), + texture->getHeight()*region.getHeight())); + } + } } - batch->texture(texture); batch->rect( pos.x, pos.y, size.x, size.y, 0, 0, 0, UVRegion(), false, true, calcColor() diff --git a/src/maths/UVRegion.hpp b/src/maths/UVRegion.hpp index fd3bb31b..85833ba4 100644 --- a/src/maths/UVRegion.hpp +++ b/src/maths/UVRegion.hpp @@ -1,6 +1,8 @@ #ifndef MATHS_UVREGION_HPP_ #define MATHS_UVREGION_HPP_ +#include + struct UVRegion { float u1; float v1; @@ -11,6 +13,14 @@ struct UVRegion { : u1(u1), v1(v1), u2(u2), v2(v2){} UVRegion() : u1(0.0f), v1(0.0f), u2(1.0f), v2(1.0f){} + + inline float getWidth() const { + return fabs(u2-u1); + } + + inline float getHeight() const { + return fabs(v2-v1); + } }; #endif // MATHS_UVREGION_HPP_