From 9a752c84d81a4f404ce7c01fe5e8aa5f1948733c Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Thu, 28 Mar 2013 00:38:55 +0000 Subject: [PATCH] tileset: refactor the tile generation code. --- src/scene.cpp | 2 +- src/tileset.cpp | 115 ++++++++++++++++++++++++++++++------------------ src/tileset.h | 7 ++- 3 files changed, 77 insertions(+), 47 deletions(-) diff --git a/src/scene.cpp b/src/scene.cpp index 5d7e9361..413e2621 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -272,7 +272,7 @@ void Scene::Render() // XXX: rename to Blit() /* Bind texture */ data->m_tiles[i].tileset->Bind(); data->m_tile_shader->SetUniform(uni_texsize, - data->m_tiles[i].tileset->GetImageSize()); + (vec2)data->m_tiles[i].tileset->GetTextureSize()); /* Bind vertex and texture coordinate buffers */ data->m_tile_vdecl->Bind(); diff --git a/src/tileset.cpp b/src/tileset.cpp index 961c0123..579ff42b 100644 --- a/src/tileset.cpp +++ b/src/tileset.cpp @@ -50,11 +50,12 @@ class TileSetData private: String m_name; - int ntiles; - ivec2 m_tile_size, m_image_size, count; - vec2 m_texcoord; - Image *m_img; + /* Pixels, then texture coordinates */ + Array m_tiles; + ivec2 m_tile_size, m_image_size, m_texture_size; + + Image *m_image; Texture *m_texture; }; @@ -62,37 +63,61 @@ private: * Public TileSet class */ -TileSet::TileSet(char const *path, ivec2 size, ivec2 count) +TileSet::TileSet(char const *path) : m_data(new TileSetData()) { - m_data->m_name = String(" ") + path; + Init(path); - m_data->m_texture = 0; - m_data->m_img = Image::Create(path); - m_data->m_image_size = m_data->m_img->GetSize(); + m_drawgroup = DRAWGROUP_BEFORE; +} +TileSet::TileSet(char const *path, ivec2 size, ivec2 count) + : m_data(new TileSetData()) +{ + Init(path); + + /* If count is valid, fix size; otherwise, fix count. */ if (count.x > 0 && count.y > 0) { - m_data->count = count; - m_data->m_tile_size = m_data->m_image_size / count; + size = m_data->m_image_size / count; } else { if (size.x <= 0 || size.y <= 0) size = ivec2(32, 32); - m_data->count.x = m_data->m_image_size.x / min(size.x, m_data->m_image_size.x); - m_data->count.y = m_data->m_image_size.y / min(size.y, m_data->m_image_size.y); - m_data->m_tile_size = size; + count = ivec2(max(1, m_data->m_image_size.x / size.x), + max(1, m_data->m_image_size.y / size.y)); } - m_data->m_texcoord.x = (float)m_data->m_tile_size.x / PotUp(m_data->m_image_size.x); - m_data->m_texcoord.y = (float)m_data->m_tile_size.y / PotUp(m_data->m_image_size.y); - - m_data->ntiles = m_data->count.x * m_data->count.y; + for (int j = 0; j < count.y; ++j) + for (int i = 0; i < count.x; ++i) + { + AddTile(ibox2(size * ivec2(i, j), + size * ivec2(i + 1, j + 1))); + } m_drawgroup = DRAWGROUP_BEFORE; } +void TileSet::Init(char const *path) +{ + m_data->m_name = String(" ") + path; + + m_data->m_texture = 0; + m_data->m_image = Image::Create(path); + m_data->m_image_size = m_data->m_image->GetSize(); + m_data->m_texture_size = ivec2(PotUp(m_data->m_image_size.x), + PotUp(m_data->m_image_size.y)); +} + +int TileSet::AddTile(ibox2 rect) +{ + m_data->m_tiles.Push(rect, + box2((vec2)rect.A / (vec2)m_data->m_texture_size, + (vec2)rect.B / (vec2)m_data->m_texture_size)); + return m_data->m_tiles.Count() - 1; +} + TileSet::~TileSet() { delete m_data; @@ -104,10 +129,10 @@ void TileSet::TickDraw(float seconds) if (IsDestroying()) { - if (m_data->m_img) + if (m_data->m_image) { - Image::Destroy(m_data->m_img); - m_data->m_img = nullptr; + Image::Destroy(m_data->m_image); + m_data->m_image = nullptr; } else { @@ -115,10 +140,10 @@ void TileSet::TickDraw(float seconds) m_data->m_texture = nullptr; } } - else if (m_data->m_img) + else if (m_data->m_image) { int planes; - PixelFormat format = m_data->m_img->GetFormat(); + PixelFormat format = m_data->m_image->GetFormat(); switch (format) { @@ -133,10 +158,10 @@ void TileSet::TickDraw(float seconds) break; } - int w = PotUp(m_data->m_image_size.x); - int h = PotUp(m_data->m_image_size.y); + int w = m_data->m_texture_size.x; + int h = m_data->m_texture_size.y; - uint8_t *pixels = m_data->m_img->GetData(); + uint8_t *pixels = m_data->m_image->GetData(); if (w != m_data->m_image_size.x || h != m_data->m_image_size.y) { uint8_t *tmp = new uint8_t[planes * w * h]; @@ -150,10 +175,10 @@ void TileSet::TickDraw(float seconds) m_data->m_texture = new Texture(ivec2(w, h), format); m_data->m_texture->SetData(pixels); - if (pixels != m_data->m_img->GetData()) + if (pixels != m_data->m_image->GetData()) delete[] pixels; - Image::Destroy(m_data->m_img); - m_data->m_img = nullptr; + Image::Destroy(m_data->m_image); + m_data->m_image = nullptr; } } @@ -162,22 +187,22 @@ char const *TileSet::GetName() return m_data->m_name.C(); } -ivec2 TileSet::GetTileCount() const +int TileSet::GetTileCount() const { - return m_data->count; + return m_data->m_tiles.Count(); } ivec2 TileSet::GetTileSize(int tileid) const { (void)tileid; - return m_data->m_tile_size; + ibox2 const &box = m_data->m_tiles[tileid].m1; + return box.B - box.A; } -vec2 TileSet::GetImageSize() const +ivec2 TileSet::GetTextureSize() const { - return vec2(PotUp(m_data->m_image_size.x), - PotUp(m_data->m_image_size.y)); + return m_data->m_texture_size; } ShaderTexture TileSet::GetTexture() const @@ -187,7 +212,7 @@ ShaderTexture TileSet::GetTexture() const void TileSet::Bind() { - if (!m_data->m_img && m_data->m_texture) + if (!m_data->m_image && m_data->m_texture) m_data->m_texture->Bind(); } @@ -199,14 +224,16 @@ void TileSet::Unbind() void TileSet::BlitTile(uint32_t id, vec3 pos, int o, vec2 scale, float *vertex, float *texture) { - float dtx = m_data->m_texcoord.x; - float dty = m_data->m_texcoord.y; - float tx = dtx * ((id & 0xffff) % m_data->count.x); - float ty = dty * ((id & 0xffff) / m_data->count.x); + ibox2 pixels = m_data->m_tiles[id].m1; + box2 texels = m_data->m_tiles[id].m2; + float dtx = texels.B.x - texels.A.x; + float dty = texels.B.y - texels.A.y; + float tx = texels.A.x; + float ty = texels.A.y; - int dx = m_data->m_tile_size.x * scale.x; - int dy = o ? 0 : m_data->m_tile_size.y * scale.y; - int dz = o ? m_data->m_tile_size.y * scale.y : 0; + int dx = (pixels.B.x - pixels.A.x) * scale.x; + int dy = o ? 0 : (pixels.B.y - pixels.A.y) * scale.y; + int dz = o ? (pixels.B.y - pixels.A.y) * scale.y : 0; /* If scaling is negative, switch triangle winding */ if (scale.x * scale.y < 0.0f) @@ -226,7 +253,7 @@ void TileSet::BlitTile(uint32_t id, vec3 pos, int o, vec2 scale, dty *= 126.f / 128.f; #endif - if (!m_data->m_img && m_data->m_texture) + if (!m_data->m_image && m_data->m_texture) { float tmp[10]; diff --git a/src/tileset.h b/src/tileset.h index 60c8dcdb..44dd5ff2 100644 --- a/src/tileset.h +++ b/src/tileset.h @@ -44,9 +44,9 @@ protected: public: /* New methods */ - ivec2 GetTileCount() const; + int GetTileCount() const; ivec2 GetTileSize(int tileid) const; - vec2 GetImageSize() const; + ivec2 GetTextureSize() const; ShaderTexture GetTexture() const; void Bind(); void Unbind(); @@ -54,6 +54,9 @@ public: float *vertex, float *texture); private: + void Init(char const *path); + int AddTile(ibox2 rect); + TileSetData *m_data; };