From 8a8cf0aa2ead688289c8c3a8faff64ea0e74d8c7 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 16 Jan 2011 10:13:34 +0000 Subject: [PATCH] Fix mesh buffer merging with multiple chunks --- src/Map.cpp | 14 ++----- src/Mesh.cpp | 102 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 65 insertions(+), 51 deletions(-) diff --git a/src/Map.cpp b/src/Map.cpp index deba71f..dc0a7e5 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -692,7 +692,6 @@ void Map::build_mesh(int id, Point bot_left, Point top_right) } } -#if 0 // Merge any static scenery for (int x = top_right.x-1; x >= bot_left.x; x--) { for (int y = bot_left.y; y < top_right.y; y++) { @@ -719,6 +718,8 @@ void Map::build_mesh(int id, Point bot_left, Point top_right) const Colour brown = make_rgb(104, 57, 12); const float depth = -3.0f; + + buf->bind(ITexturePtr()); // No texture on sides int index[4]; @@ -816,16 +817,7 @@ void Map::build_mesh(int id, Point bot_left, Point top_right) if (sea_sectors.size() < min_size) sea_sectors.resize(min_size); sea_sectors.at(id) = below_sea_level; - -#else - - terrain_meshes[id] = make_mesh(buf); - - size_t min_size = id + 1; - if (sea_sectors.size() < min_size) - sea_sectors.resize(min_size); - sea_sectors.at(id) = false; -#endif + // Make sure we don't rebuild this mesh if any of the tiles are dirty have_mesh(id, bot_left, top_right); } diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 69f8395..27a542f 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -41,6 +41,17 @@ struct MeshBuffer : IMeshBuffer { MeshBuffer(); ~MeshBuffer() {} + // A chunk is a subset of the mesh bound to a particular texture + struct Chunk { + vector vertices; + vector normals; + vector colours; + vector indices; + vector tex_coords; + ITexturePtr texture; + }; + typedef shared_ptr ChunkPtr; + size_t vertex_count() const; size_t index_count() const; @@ -59,6 +70,8 @@ struct MeshBuffer : IMeshBuffer { void merge(IMeshBufferPtr other, Vector off, float y_angle); void print_stats() const; + + ChunkPtr find_chunk(ITexturePtr tex) const; static MeshBuffer* get(IMeshBufferPtr a_ptr) { @@ -70,17 +83,6 @@ struct MeshBuffer : IMeshBuffer { return v1 == v2; } - // A chunk is a subset of the mesh bound to a particular texture - struct Chunk { - vector vertices; - vector normals; - vector colours; - vector indices; - vector tex_coords; - ITexturePtr texture; - }; - typedef shared_ptr ChunkPtr; - vector chunks; ChunkPtr active_chunk; @@ -132,47 +134,67 @@ size_t MeshBuffer::index_count() const return sum; } +MeshBuffer::ChunkPtr MeshBuffer::find_chunk(ITexturePtr tex) const +{ + for (vector::const_iterator it = chunks.begin(); + it != chunks.end(); ++it) { + if ((*it)->texture == tex) + return *it; + } + + return ChunkPtr(); +} + void MeshBuffer::merge(IMeshBufferPtr other, Vector off, float y_angle) { -#if 0 - // XXX const MeshBuffer& obuf = dynamic_cast(*other); - - const size_t ibase = active_chunk->vertices.size(); - const Matrix translate = - Matrix::translation(off.x, off.y, off.z); - const Matrix rotate = - Matrix::rotation(y_angle, 0.0f, 1.0f, 0.0f); + for (vector::const_iterator it = obuf.chunks.begin(); + it != obuf.chunks.end(); ++it) { + + ChunkPtr target_chunk = find_chunk((*it)->texture); + if (!target_chunk) { + target_chunk = ChunkPtr(new Chunk); + target_chunk->texture = (*it)->texture; + + chunks.push_back(target_chunk); + } + + const size_t ibase = target_chunk->vertices.size(); - const Matrix compose = translate * rotate; + const Matrix translate = + Matrix::translation(off.x, off.y, off.z); + const Matrix rotate = + Matrix::rotation(y_angle, 0.0f, 1.0f, 0.0f); + + const Matrix compose = translate * rotate; - for (size_t i = 0; i < obuf.vertices.size(); i++) { - const Vertex& v = obuf.vertices[i]; - const Normal& n = obuf.normals[i]; + for (size_t i = 0; i < (*it)->vertices.size(); i++) { + const Vertex& v = (*it)->vertices[i]; + const Normal& n = (*it)->normals[i]; - active_chunk->vertices.push_back(compose.transform(v)); - active_chunk->normals.push_back(rotate.transform(n).normalise()); + target_chunk->vertices.push_back(compose.transform(v)); + target_chunk->normals.push_back(rotate.transform(n).normalise()); + + const TexCoord& tc = (*it)->tex_coords[i]; + target_chunk->tex_coords.push_back(tc); - if (obuf.texture) { - colours.push_back(colour::WHITE); + const Colour& c = (*it)->colours[i]; + target_chunk->colours.push_back(c); } - else { - const Colour& c = obuf.colours[i]; - colours.push_back(c); + + for (size_t i = 0; i < (*it)->indices.size(); i++) { + Index orig = (*it)->indices[i]; + Index merged = orig + ibase; + + assert(orig < (*it)->vertices.size()); + assert(merged < target_chunk->vertices.size()); + + target_chunk->indices.push_back(merged); } } - for (size_t i = 0; i < obuf.indices.size(); i++) { - Index orig = obuf.indices[i]; - Index merged = orig + ibase; - - assert(orig < obuf.vertices.size()); - assert(merged < vertices.size()); - - indices.push_back(merged); - } -#endif + reused += obuf.reused; } void MeshBuffer::print_stats() const -- 2.39.2