diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index f8125d2b..576a6b65 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -73,7 +73,6 @@ bool _load_atlas(Assets* assets, const std::string& filename, const std::string& if (file.extension() == ".png") { std::string name = file.stem().string(); std::unique_ptr image (png::load_image(file.string())); - //image->flipY(); image->fixAlphaColor(); builder.add(name, image.release()); } diff --git a/src/frontend/ContentGfxCache.cpp b/src/frontend/ContentGfxCache.cpp new file mode 100644 index 00000000..2cf1affe --- /dev/null +++ b/src/frontend/ContentGfxCache.cpp @@ -0,0 +1,26 @@ +#include "ContentGfxCache.h" + +#include + +#include "../assets/Assets.h" +#include "../content/Content.h" +#include "../graphics/Atlas.h" +#include "../voxels/Block.h" + +using std::string; + +ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets) { + const ContentIndices* contentIds = content->indices; + sideregions = new UVRegion[contentIds->countBlockDefs() * 6]; + Atlas* atlas = assets->getAtlas("blocks"); + + for (uint i = 0; i < contentIds->countBlockDefs(); i++) { + Block* def = contentIds->getBlockDef(i); + for (uint side = 0; side < 6; side++) { + string tex = def->textureFaces[side]; + if (atlas->has(tex)) { + sideregions[i * 6 + side] = atlas->get(tex); + } + } + } +} \ No newline at end of file diff --git a/src/frontend/ContentGfxCache.h b/src/frontend/ContentGfxCache.h new file mode 100644 index 00000000..81c709d8 --- /dev/null +++ b/src/frontend/ContentGfxCache.h @@ -0,0 +1,21 @@ +#ifndef FRONTEND_BLOCKS_GFX_CACHE_H_ +#define FRONTEND_BLOCKS_GFX_CACHE_H_ + +#include "../graphics/UVRegion.h" +#include "../typedefs.h" + +class Content; +class Assets; + +class ContentGfxCache { + // array of block sides uv regions (6 per block) + UVRegion* sideregions; +public: + ContentGfxCache(const Content* content, Assets* assets); + + inline const UVRegion& getRegion(blockid_t id, int side) const { + return sideregions[id * 6 + side]; + } +}; + +#endif // FRONTEND_BLOCKS_GFX_CACHE_H_ \ No newline at end of file diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index c65751df..9c6eac80 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -32,6 +32,7 @@ #include "gui/panels.h" #include "gui/UINode.h" #include "gui/GUI.h" +#include "ContentGfxCache.h" #include "screens.h" #include "../engine.h" #include "../core_defs.h" @@ -49,10 +50,11 @@ inline Label* create_label(gui::wstringsupplier supplier) { return label; } -HudRenderer::HudRenderer(Engine* engine, Level* level) +HudRenderer::HudRenderer(Engine* engine, Level* level, const ContentGfxCache* cache) : level(level), assets(engine->getAssets()), - gui(engine->getGUI()) { + gui(engine->getGUI()), + cache(cache) { auto menu = gui->getMenu(); batch = new Batch2D(1024); uicamera = new Camera(vec3(), 1); @@ -192,10 +194,9 @@ void HudRenderer::drawContentAccess(const GfxContext& ctx, Player* player) { } if (cblock->model == BlockModel::block){ - batch->blockSprite(x, y, icon_size, icon_size, (const UVRegion*)cblock->uvdata, tint); + batch->blockSprite(x, y, icon_size, icon_size, &cache->getRegion(cblock->id, 0), tint); } else if (cblock->model == BlockModel::xsprite){ - const UVRegion& region = (reinterpret_cast(cblock->uvdata))[3]; - batch->sprite(x, y, icon_size, icon_size, region, tint); + batch->sprite(x, y, icon_size, icon_size, cache->getRegion(cblock->id, 3), tint); } } } @@ -267,10 +268,9 @@ void HudRenderer::draw(const GfxContext& ctx){ Block* cblock = contentIds->getBlockDef(player->choosenBlock); assert(cblock != nullptr); if (cblock->model == BlockModel::block){ - batch->blockSprite(width-56, uicamera->fov - 56, 48, 48, (const UVRegion*)cblock->uvdata, vec4(1.0f)); + batch->blockSprite(width-56, uicamera->fov - 56, 48, 48, &cache->getRegion(cblock->id, 0), vec4(1.0f)); } else if (cblock->model == BlockModel::xsprite){ - const UVRegion& region = (reinterpret_cast(cblock->uvdata))[3]; - batch->sprite(width-56, uicamera->fov - 56, 48, 48, region, vec4(1.0f)); + batch->sprite(width-56, uicamera->fov - 56, 48, 48, cache->getRegion(cblock->id, 3), vec4(1.0f)); } } diff --git a/src/frontend/hud.h b/src/frontend/hud.h index 68f1d668..148e5210 100644 --- a/src/frontend/hud.h +++ b/src/frontend/hud.h @@ -13,6 +13,7 @@ class Assets; class Player; class Level; class Engine; +class ContentGfxCache; namespace gui { class GUI; @@ -35,8 +36,9 @@ class HudRenderer { std::shared_ptr debugPanel; gui::GUI* gui; + const ContentGfxCache* const cache; public: - HudRenderer(Engine* engine, Level* level); + HudRenderer(Engine* engine, Level* level, const ContentGfxCache* cache); ~HudRenderer(); void update(); diff --git a/src/frontend/screens.cpp b/src/frontend/screens.cpp index 75280e41..6dc63ab3 100644 --- a/src/frontend/screens.cpp +++ b/src/frontend/screens.cpp @@ -23,6 +23,7 @@ #include "../voxels/Chunk.h" #include "world_render.h" #include "hud.h" +#include "ContentGfxCache.h" #include "gui/GUI.h" #include "gui/panels.h" #include "../engine.h" @@ -89,13 +90,15 @@ void MenuScreen::draw(float delta) { LevelScreen::LevelScreen(Engine* engine, Level* level) : Screen(engine), level(level) { - worldRenderer = new WorldRenderer(engine, level); - hud = new HudRenderer(engine, level); + cache = new ContentGfxCache(level->content, engine->getAssets()); + worldRenderer = new WorldRenderer(engine, level, cache); + hud = new HudRenderer(engine, level, cache); } LevelScreen::~LevelScreen() { delete hud; delete worldRenderer; + delete cache; std::cout << "-- writing world" << std::endl; World* world = level->world; diff --git a/src/frontend/screens.h b/src/frontend/screens.h index 2ea6c3e9..8ac45b1f 100644 --- a/src/frontend/screens.h +++ b/src/frontend/screens.h @@ -11,6 +11,7 @@ class HudRenderer; class Engine; class Camera; class Batch2D; +class ContentGfxCache; /* Screen is a mainloop state */ class Screen { @@ -38,6 +39,7 @@ class LevelScreen : public Screen { Level* level; WorldRenderer* worldRenderer; HudRenderer* hud; + ContentGfxCache* cache; bool occlusion = true; void updateHotkeys(); public: diff --git a/src/frontend/world_render.cpp b/src/frontend/world_render.cpp index 73862e8f..63545d43 100644 --- a/src/frontend/world_render.cpp +++ b/src/frontend/world_render.cpp @@ -26,39 +26,20 @@ #include "../maths/FrustumCulling.h" #include "../settings.h" #include "../engine.h" +#include "ContentGfxCache.h" using glm::vec3; using std::string; using std::shared_ptr; -WorldRenderer::WorldRenderer(Engine* engine, Level* level) +WorldRenderer::WorldRenderer(Engine* engine, Level* level, const ContentGfxCache* cache) : engine(engine), level(level) { lineBatch = new LineBatch(4096); - renderer = new ChunksRenderer(level); + renderer = new ChunksRenderer(level, cache); frustumCulling = new Frustum(); level->events->listen(EVT_CHUNK_HIDDEN, [this](lvl_event_type type, Chunk* chunk) { renderer->unload(chunk); }); - - // TODO: move to some proper place - // otrefactoryu dnem - Assets* assets = engine->getAssets(); - Atlas* atlas = assets->getAtlas("blocks"); - const Content* content = level->content; - const ContentIndices* contentIds = content->indices; - for (uint i = 0; i < contentIds->countBlockDefs(); i++) { - Block* def = contentIds->getBlockDef(i); - for (uint side = 0; side < 6; side++) { - string tex = def->textureFaces[side]; - if (atlas->has(tex)) { - UVRegion region = atlas->get(tex); - float* data = reinterpret_cast(®ion); - for (uint j = 0; j < 4; j++) { - def->uvdata[side * 4 + j] = data[j]; - } - } - } - } } WorldRenderer::~WorldRenderer() { diff --git a/src/frontend/world_render.h b/src/frontend/world_render.h index 3ff65c19..00391159 100644 --- a/src/frontend/world_render.h +++ b/src/frontend/world_render.h @@ -21,6 +21,7 @@ class Texture; class Frustum; class Engine; class Chunks; +class ContentGfxCache; class WorldRenderer { Engine* engine; @@ -32,7 +33,7 @@ class WorldRenderer { void drawChunks(Chunks* chunks, Camera* camera, Shader* shader, bool occlusion); public: - WorldRenderer(Engine* engine, Level* level); + WorldRenderer(Engine* engine, Level* level, const ContentGfxCache* cache); ~WorldRenderer(); void draw(const GfxContext& context, Camera* camera, bool occlusion); diff --git a/src/graphics/BlocksRenderer.cpp b/src/graphics/BlocksRenderer.cpp index 5067f23d..e7126a3d 100644 --- a/src/graphics/BlocksRenderer.cpp +++ b/src/graphics/BlocksRenderer.cpp @@ -11,6 +11,7 @@ #include "../voxels/VoxelsVolume.h" #include "../voxels/ChunksStorage.h" #include "../lighting/Lightmap.h" +#include "../frontend/ContentGfxCache.h" using glm::ivec3; using glm::vec3; @@ -18,12 +19,15 @@ using glm::vec4; #define VERTEX_SIZE 9 -BlocksRenderer::BlocksRenderer(size_t capacity, const Content* content) +BlocksRenderer::BlocksRenderer(size_t capacity, + const Content* content, + const ContentGfxCache* cache) : content(content), vertexOffset(0), indexOffset(0), indexSize(0), - capacity(capacity) { + capacity(capacity), + cache(cache) { vertexBuffer = new float[capacity]; indexBuffer = new int[capacity]; voxelsBuffer = new VoxelsVolume(CHUNK_W + 2, CHUNK_H, CHUNK_D + 2); @@ -301,11 +305,6 @@ vec4 BlocksRenderer::pickSoftLight(int x, int y, int z, const ivec3& right, cons pickLight(x - right.x, y - right.y, z - right.z)) * 0.25f; } -// Get texture atlas UV region for block face -inline UVRegion uvfor(const Block& def, uint face, int atlas_size) { - return *reinterpret_cast(def.uvdata + face * 4); -} - void BlocksRenderer::render(const voxel* voxels, int atlas_size) { int begin = chunk->bottom * (CHUNK_W * CHUNK_D); int end = chunk->top * (CHUNK_W * CHUNK_D); @@ -316,9 +315,9 @@ void BlocksRenderer::render(const voxel* voxels, int atlas_size) { const Block& def = *blockDefsCache[id]; if (!id || def.drawGroup != group) continue; - const UVRegion texfaces[6]{ uvfor(def, 0, atlas_size), uvfor(def, 1, atlas_size), - uvfor(def, 2, atlas_size), uvfor(def, 3, atlas_size), - uvfor(def, 4, atlas_size), uvfor(def, 5, atlas_size) }; + const UVRegion texfaces[6]{ cache->getRegion(id, 0), cache->getRegion(id, 1), + cache->getRegion(id, 2), cache->getRegion(id, 3), + cache->getRegion(id, 4), cache->getRegion(id, 5)}; int x = i % CHUNK_W; int y = i / (CHUNK_D * CHUNK_W); int z = (i / CHUNK_D) % CHUNK_W; diff --git a/src/graphics/BlocksRenderer.h b/src/graphics/BlocksRenderer.h index 3c956d41..0363bf74 100644 --- a/src/graphics/BlocksRenderer.h +++ b/src/graphics/BlocksRenderer.h @@ -14,6 +14,7 @@ class Chunk; class Chunks; class VoxelsVolume; class ChunksStorage; +class ContentGfxCache; class BlocksRenderer { const Content* const content; @@ -29,6 +30,7 @@ class BlocksRenderer { VoxelsVolume* voxelsBuffer; const Block* const* blockDefsCache; + const ContentGfxCache* const cache; void vertex(const glm::vec3& coord, float u, float v, const glm::vec4& light); void index(int a, int b, int c, int d, int e, int f); @@ -68,7 +70,7 @@ class BlocksRenderer { glm::vec4 pickSoftLight(int x, int y, int z, const glm::ivec3& right, const glm::ivec3& up) const; void render(const voxel* voxels, int atlas_size); public: - BlocksRenderer(size_t capacity, const Content* content); + BlocksRenderer(size_t capacity, const Content* content, const ContentGfxCache* cache); virtual ~BlocksRenderer(); Mesh* render(const Chunk* chunk, int atlas_size, const ChunksStorage* chunks); diff --git a/src/graphics/ChunksRenderer.cpp b/src/graphics/ChunksRenderer.cpp index 2e14a496..b6ca82fd 100644 --- a/src/graphics/ChunksRenderer.cpp +++ b/src/graphics/ChunksRenderer.cpp @@ -11,9 +11,9 @@ using glm::ivec2; using std::shared_ptr; -ChunksRenderer::ChunksRenderer(Level* level) : level(level) { +ChunksRenderer::ChunksRenderer(Level* level, const ContentGfxCache* cache) : level(level) { const int MAX_FULL_CUBES = 3000; - renderer = new BlocksRenderer(9 * 6 * 6 * MAX_FULL_CUBES, level->content); + renderer = new BlocksRenderer(9 * 6 * 6 * MAX_FULL_CUBES, level->content, cache); } ChunksRenderer::~ChunksRenderer() { diff --git a/src/graphics/ChunksRenderer.h b/src/graphics/ChunksRenderer.h index 7f066263..1e45cf75 100644 --- a/src/graphics/ChunksRenderer.h +++ b/src/graphics/ChunksRenderer.h @@ -11,13 +11,14 @@ class Mesh; class Chunk; class Level; class BlocksRenderer; +class ContentGfxCache; class ChunksRenderer { BlocksRenderer* renderer; Level* level; std::unordered_map> meshes; public: - ChunksRenderer(Level* level); + ChunksRenderer(Level* level, const ContentGfxCache* cache); virtual ~ChunksRenderer(); std::shared_ptr render(Chunk* chunk); diff --git a/src/voxels/Block.h b/src/voxels/Block.h index f579ff1d..2cade46e 100644 --- a/src/voxels/Block.h +++ b/src/voxels/Block.h @@ -31,8 +31,6 @@ public: bool rotatable = false; float hitboxScale = 1; - float uvdata[4*6]; - Block(std::string name, std::string texture); };