From 4deaa3cb477ea134a4e84e488b01159bdbf1c161 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 30 May 2010 14:02:35 +0100 Subject: [PATCH] Merge scenery into map quad mesh buffers --- include/IMesh.hpp | 14 +++--- include/IModel.hpp | 2 + include/IScenery.hpp | 2 + src/Building.cpp | 8 +++- src/Map.cpp | 15 +++++- src/Mesh.cpp | 112 +++++++++++++++++++++++++++---------------- src/Model.cpp | 12 ++++- src/Tree.cpp | 6 +++ 8 files changed, 119 insertions(+), 52 deletions(-) diff --git a/include/IMesh.hpp b/include/IMesh.hpp index 1bfec4a..eb1697c 100644 --- a/include/IMesh.hpp +++ b/include/IMesh.hpp @@ -46,22 +46,24 @@ struct IMeshBuffer { virtual size_t vertexCount() const = 0; - virtual void add(const Vertex& aVertex, const Normal& aNormal) = 0; - virtual void add(const Vertex& aVertex, const Normal& aNormal, + virtual void add(const Vertex& vertex, const Normal& normal) = 0; + virtual void add(const Vertex& vertex, const Normal& normal, const TexCoord& aTexCoord) = 0; - virtual void add(const Vertex& aVertex, const Normal& aNormal, - const Colour& aColour) = 0; + virtual void add(const Vertex& vertex, const Normal& normal, + const Colour& colour) = 0; // Convenience functions virtual void addQuad(Vertex a, Vertex b, Vertex c, Vertex d, - Colour aColour) = 0; + Colour colour) = 0; virtual void addQuad(Vertex a, Vertex b, Vertex c, Vertex d, Normal na, Normal nb, Normal nc, Normal nd, - Colour aColour) = 0; + Colour colour) = 0; virtual void bindMaterial(const Material& aMaterial) = 0; virtual void printStats() const = 0; + + virtual void merge(shared_ptr other, Vector off) = 0; }; typedef shared_ptr IMeshBufferPtr; diff --git a/include/IModel.hpp b/include/IModel.hpp index fe642a3..876cb3d 100644 --- a/include/IModel.hpp +++ b/include/IModel.hpp @@ -21,6 +21,7 @@ #include "Platform.hpp" #include "Maths.hpp" #include "IResource.hpp" +#include "IMesh.hpp" #include @@ -29,6 +30,7 @@ struct IModel { virtual void render() const = 0; virtual void cache() = 0; + virtual void merge(IMeshBufferPtr buf, Vector off) const = 0; virtual Vector dimensions() const = 0; }; diff --git a/include/IScenery.hpp b/include/IScenery.hpp index 4c26e75..9f458f8 100644 --- a/include/IScenery.hpp +++ b/include/IScenery.hpp @@ -20,6 +20,7 @@ #include "Platform.hpp" #include "IXMLSerialisable.hpp" +#include "IMesh.hpp" // Static scenery such as trees struct IScenery : IXMLSerialisable { @@ -28,6 +29,7 @@ struct IScenery : IXMLSerialisable { virtual void render() const = 0; virtual void setPosition(float x, float y, float z) = 0; virtual void setAngle(float angle) = 0; + virtual void merge(IMeshBufferPtr buf) = 0; virtual const string& name() const = 0; }; diff --git a/src/Building.cpp b/src/Building.cpp index d914729..b7f86a3 100644 --- a/src/Building.cpp +++ b/src/Building.cpp @@ -29,11 +29,12 @@ class Building : public IScenery, public IXMLCallback { public: Building(IResourcePtr aRes); - // IBuildingInterface + // ISceneryInterface const string& name() const { return name_; } void render() const; void setAngle(float a) { angle = a; } void setPosition(float x, float y, float z); + void merge(IMeshBufferPtr buf); // IXMLSerialisable interface xml::element toXml() const; @@ -87,6 +88,11 @@ void Building::render() const glPopMatrix(); } +void Building::merge(IMeshBufferPtr buf) +{ + model_->merge(buf, position); +} + void Building::text(const string& localName, const string& aString) { if (localName == "name") diff --git a/src/Map.cpp b/src/Map.cpp index ff356f8..c61db22 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -613,6 +613,16 @@ void Map::buildMesh(int id, Point botLeft, Point topRight) } } + // Merge any static scenery + for (int x = topRight.x-1; x >= botLeft.x; x--) { + for (int y = botLeft.y; y < topRight.y; y++) { + Tile& tile = tileAt(x, y); + + if (tile.scenery) + tile.scenery->merge(buf); + } + } + // Draw the sides of the map if this is an edge sector const float x1 = static_cast(botLeft.x) - 0.5f; const float x2 = static_cast(topRight.x) - 0.5f; @@ -692,6 +702,7 @@ void Map::buildMesh(int id, Point botLeft, Point topRight) } } + buf->printStats(); terrainMeshes[id] = makeMesh(buf); } @@ -791,8 +802,8 @@ void Map::renderSector(IGraphicsPtr aContext, int id, drawStartLocation(); // Draw any scenery - if (tile.scenery) - tile.scenery->render(); + //if (tile.scenery) + // tile.scenery->render(); } } } diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 95ad959..542d1c5 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -42,19 +42,20 @@ struct MeshBuffer : IMeshBuffer { size_t vertexCount() const { return vertices.size(); } - void add(const Vertex& aVertex, const Normal& aNormal); - void add(const Vertex& aVertex, const Normal& aNormal, + void add(const Vertex& vertex, const Normal& normal); + void add(const Vertex& vertex, const Normal& normal, const TexCoord& aTexCoord); - void add(const Vertex& aVertex, const Normal& aNormal, - const Colour& aColour); + void add(const Vertex& vertex, const Normal& normal, + const Colour& colour); void addQuad(Vertex a, Vertex b, Vertex c, Vertex d, - Colour aColour); + Colour colour); void addQuad(Vertex a, Vertex b, Vertex c, Vertex d, Normal na, Normal nb, Normal nc, Normal nd, - Colour aColour); + Colour colour); void bindMaterial(const Material& aMaterial); + void merge(IMeshBufferPtr other, Vector off); void printStats() const; @@ -95,13 +96,41 @@ void MeshBuffer::bindMaterial(const Material& aMaterial) hasMaterial = true; } +void MeshBuffer::merge(IMeshBufferPtr other, Vector off) +{ + const MeshBuffer& obuf = dynamic_cast(*other); + + const size_t ibase = vertices.size(); + + for (size_t i = 0; i < obuf.vertices.size(); i++) { + const Vertex& v = obuf.vertices[i]; + const Normal& n = obuf.normals[i]; + + vertices.push_back(v + off); + normals.push_back(n); + + if (obuf.hasTexture) { + colours.push_back(colour::WHITE); + } + else { + const Colour& c = obuf.colours[i]; + colours.push_back(c); + } + } + + for (size_t i = 0; i < obuf.indices.size(); i++) { + Index orig = obuf.indices[i]; + indices.push_back(orig + ibase); + } +} + void MeshBuffer::printStats() const { debug() << "Mesh: " << vertices.size() << " vertices, " << reused << " reused"; } -void MeshBuffer::add(const Vertex& aVertex, const Normal& aNormal) +void MeshBuffer::add(const Vertex& vertex, const Normal& normal) { if (hasTexture) throw runtime_error("MeshBuffer::add called without texture coordinate " @@ -114,8 +143,8 @@ void MeshBuffer::add(const Vertex& aVertex, const Normal& aNormal) // See if this vertex has already been added for (vector::iterator it = indices.begin(); it != indices.end(); ++it) { - if (mergeVector(aVertex, vertices[*it]) - && mergeVector(aNormal, normals[*it])) { + if (mergeVector(vertex, vertices[*it]) + && mergeVector(normal, normals[*it])) { indices.push_back(*it); reused++; return; @@ -123,8 +152,8 @@ void MeshBuffer::add(const Vertex& aVertex, const Normal& aNormal) } const size_t index = vertices.size(); - vertices.push_back(aVertex); - normals.push_back(aNormal); + vertices.push_back(vertex); + normals.push_back(normal); indices.push_back(index); colours.push_back( makeColour(material.diffuseR, @@ -132,8 +161,8 @@ void MeshBuffer::add(const Vertex& aVertex, const Normal& aNormal) material.diffuseB)); } -void MeshBuffer::add(const Vertex& aVertex, const Normal& aNormal, - const Colour& aColour) +void MeshBuffer::add(const Vertex& vertex, const Normal& normal, + const Colour& colour) { if (hasTexture) @@ -147,13 +176,13 @@ void MeshBuffer::add(const Vertex& aVertex, const Normal& aNormal, // See if this vertex has already been added for (vector::iterator it = indices.begin(); it != indices.end(); ++it) { - if (mergeVector(aVertex, vertices[*it]) - && mergeVector(aNormal, normals[*it])) { + if (mergeVector(vertex, vertices[*it]) + && mergeVector(normal, normals[*it])) { const Colour& other = colours[*it]; - if (abs(other.r - aColour.r) < 0.01f - && abs(other.g - aColour.g) < 0.01f - && abs(other.b - aColour.b) < 0.01f) { + if (abs(other.r - colour.r) < 0.01f + && abs(other.g - colour.g) < 0.01f + && abs(other.b - colour.b) < 0.01f) { indices.push_back(*it); reused++; @@ -163,13 +192,13 @@ void MeshBuffer::add(const Vertex& aVertex, const Normal& aNormal, } const size_t index = vertices.size(); - vertices.push_back(aVertex); - normals.push_back(aNormal); - colours.push_back(aColour); + vertices.push_back(vertex); + normals.push_back(normal); + colours.push_back(colour); indices.push_back(index); } -void MeshBuffer::add(const Vertex& aVertex, const Normal& aNormal, +void MeshBuffer::add(const Vertex& vertex, const Normal& normal, const TexCoord& aTexCoord) { if (!hasTexture) @@ -180,8 +209,8 @@ void MeshBuffer::add(const Vertex& aVertex, const Normal& aNormal, // See if this vertex has already been added for (vector::iterator it = indices.begin(); it != indices.end(); ++it) { - if (mergeVector(aVertex, vertices[*it]) - && mergeVector(aNormal, normals[*it])) { + if (mergeVector(vertex, vertices[*it]) + && mergeVector(normal, normals[*it])) { TexCoord& tc = texCoords[*it]; if (abs(tc.x - aTexCoord.x) < 0.001f && abs(tc.y - aTexCoord.y) < 0.001f) { @@ -193,39 +222,39 @@ void MeshBuffer::add(const Vertex& aVertex, const Normal& aNormal, } const size_t index = vertices.size(); - vertices.push_back(aVertex); - normals.push_back(aNormal); + vertices.push_back(vertex); + normals.push_back(normal); texCoords.push_back(aTexCoord); indices.push_back(index); } void MeshBuffer::addQuad(Vertex a, Vertex b, Vertex c, - Vertex d, Colour aColour) + Vertex d, Colour colour) { Vector n1 = surfaceNormal(b, c, d); Vector n2 = surfaceNormal(d, a, b); - add(b, n1, aColour); - add(c, n1, aColour); - add(d, n1, aColour); + add(b, n1, colour); + add(c, n1, colour); + add(d, n1, colour); - add(d, n2, aColour); - add(a, n2, aColour); - add(b, n2, aColour); + add(d, n2, colour); + add(a, n2, colour); + add(b, n2, colour); } void MeshBuffer::addQuad(Vertex a, Vertex b, Vertex c, Vertex d, Normal na, Normal nb, Normal nc, Normal nd, - Colour aColour) + Colour colour) { - add(b, na, aColour); - add(c, nb, aColour); - add(d, nc, aColour); + add(b, na, colour); + add(c, nb, colour); + add(d, nc, colour); - add(d, nd, aColour); - add(a, na, aColour); - add(b, nb, aColour); + add(d, nd, colour); + add(a, na, colour); + add(b, nb, colour); } // Default material @@ -519,7 +548,8 @@ void VBOMesh::render() const glPushAttrib(GL_ENABLE_BIT); glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); - assert(glIsEnabled(GL_CULL_FACE)); + if (!glIsEnabled(GL_CULL_FACE)) + glEnable(GL_CULL_FACE); glBindBufferARB(GL_ARRAY_BUFFER, vboBuf); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, indexBuf); diff --git a/src/Model.cpp b/src/Model.cpp index 3a94ec1..0b88613 100644 --- a/src/Model.cpp +++ b/src/Model.cpp @@ -56,7 +56,7 @@ private: MaterialSet myMaterials; }; -typedef shared_ptr MaterialFilePtr; +typedef std::tr1::shared_ptr MaterialFilePtr; MaterialFile::MaterialFile(const string& aFileName, IResourcePtr aRes) { @@ -122,10 +122,13 @@ public: : dimensions_(dim), buffer(buf) {} ~Model(); - + + // IModel interface void render() const; void cache(); + void merge(IMeshBufferPtr into, Vector off) const; Vector dimensions() const { return dimensions_; } + private: void compileMesh() const; @@ -153,6 +156,11 @@ void Model::render() const mesh->render(); } +void Model::merge(IMeshBufferPtr into, Vector off) const +{ + into->merge(buffer, off); +} + void Model::compileMesh() const { // Const as may be called during render diff --git a/src/Tree.cpp b/src/Tree.cpp index 419bf45..e89dc0b 100644 --- a/src/Tree.cpp +++ b/src/Tree.cpp @@ -39,6 +39,7 @@ public: void setPosition(float x, float y, float z); void setAngle(float a) { angle = a; } const string& name() const { return name_; } + void merge(IMeshBufferPtr buf); // IXMLCallback interface void text(const string& localName, const string& content); @@ -106,6 +107,11 @@ void Tree::render() const glPopMatrix(); } +void Tree::merge(IMeshBufferPtr buf) +{ + model->merge(buf, position); +} + xml::element Tree::toXml() const { return xml::element("tree") -- 2.39.2