From d3d962d05ac7a31ec4bbcb8919fae1b871f345ce Mon Sep 17 00:00:00 2001 From: Joseph Walton-Rivers <joseph@walton-rivers.uk> Date: Sun, 18 Jul 2021 11:36:32 +0100 Subject: [PATCH] Implement removal of unused verticies. Mesh now has a (fairly primative) method for removing unused and duplicated verticies. This means its possible to use conbined geometry without duplicate verticies. In my test scene, this halved the number of verticies in the combined mesh. There are plenty of other optimisations that could be implemented. Some that would be nice to have but I don't have time for: * Removal of internal faces in combined meshes * Optimise triangle order so GL_TRIANGLE_STRIP or the like can be used --- demo/main.cpp | 1 + fggl/data/model.cpp | 43 +++++++++++++++++++++++++++++++++++++++++++ fggl/data/model.hpp | 25 +++++++++++++++++++++++++ fggl/math/types.hpp | 13 +++++++++++++ 4 files changed, 82 insertions(+) diff --git a/demo/main.cpp b/demo/main.cpp index 677e31b..f38b2c1 100644 --- a/demo/main.cpp +++ b/demo/main.cpp @@ -107,6 +107,7 @@ int main(int argc, char* argv[]) { fggl::data::make_slope( mesh, rightSlope ); } + mesh.removeDups(); auto token = meshRenderer.upload( mesh ); token.pipeline = shaderPhong; ecs.addComponent<fggl::gfx::MeshToken>(entity, token); diff --git a/fggl/data/model.cpp b/fggl/data/model.cpp index e57c5c8..b6cb8e6 100644 --- a/fggl/data/model.cpp +++ b/fggl/data/model.cpp @@ -1,5 +1,8 @@ #include <fggl/data/model.hpp> +#include <map> +#include <stdexcept> + using namespace fggl::data; Mesh::Mesh() : m_verts(), m_index() { @@ -27,6 +30,46 @@ int Mesh::indexOf(Vertex vert) { return -1; } +void Mesh::removeDups() { + // lookups to make detecting duplicates easier + std::map<Vertex, unsigned int> mapping; + unsigned int nextID = 0; + + // new data + std::vector< Vertex > newVerts; + std::vector< unsigned int > newIndexes; + newIndexes.reserve( m_index.size() ); // newIndex will be same size as oldIndex + + for ( auto& idx : m_index ) { + auto& vertex = m_verts[idx]; + auto newID = nextID; + try { + newID = mapping.at( vertex ); + } catch ( std::out_of_range& e ){ + mapping[ vertex ] = newID; + newVerts.push_back( vertex ); + ++nextID; + } + newIndexes.push_back( newID ); + } + + // FIXME must be faster way to do this... + m_verts.clear(); + m_index.clear(); + + for ( auto& vert : newVerts ) { + m_verts.push_back( vert ); + } + + for ( auto& idx : newIndexes ) { + m_index.push_back( idx ); + } + + // ensure we're not wasting space + m_verts.shrink_to_fit(); + m_index.shrink_to_fit(); +} + Model::Model() { } diff --git a/fggl/data/model.hpp b/fggl/data/model.hpp index ed67945..2f57d00 100644 --- a/fggl/data/model.hpp +++ b/fggl/data/model.hpp @@ -1,6 +1,7 @@ #ifndef FGGL_DATA_MODEL_H #define FGGL_DATA_MODEL_H +#include <tuple> #include <vector> #include <fggl/math/types.hpp> @@ -12,6 +13,23 @@ namespace fggl::data { math::vec3 colour; }; + // comparison operators + + inline bool operator<(const Vertex& lhs, const Vertex& rhs) { + return std::tie( lhs.posititon, lhs.normal, lhs.colour ) + < std::tie( rhs.posititon, rhs.normal, rhs.colour ); + } + + inline bool operator==(const Vertex& lhs, const Vertex& rhs) { + return lhs.posititon == rhs.posititon + && lhs.colour == rhs.colour + && lhs.normal == rhs.normal; + } + + inline bool operator!=(const Vertex& lhs, const Vertex& rhs) { + return !(lhs==rhs); + } + class Mesh { public: Mesh(); @@ -45,6 +63,13 @@ namespace fggl::data { */ unsigned int pushVertex(Vertex vert); + /** + * remove Duplicate verticies + * + * If generated using the procedural system, the mesh data can get a little messy. + * This method will remove unused and duplicate verticies. + */ + void removeDups(); /** * Search for a vertex. diff --git a/fggl/math/types.hpp b/fggl/math/types.hpp index 32d45d3..e4b3c46 100644 --- a/fggl/math/types.hpp +++ b/fggl/math/types.hpp @@ -1,6 +1,8 @@ #ifndef FGGL_MATH_TYPES_H #define FGGL_MATH_TYPES_H +#include <tuple> + #include <glm/ext/matrix_transform.hpp> #include <glm/glm.hpp> #include <glm/gtc/quaternion.hpp> @@ -15,6 +17,7 @@ namespace fggl::math { using mat4 = glm::mat4; using quat = glm::quat; + // reference vectors constexpr vec3 UP { 0.0f, 1.0f, 0.0f }; constexpr vec3 FORWARD { 1.0f, 0.0f, 0.0f }; @@ -98,4 +101,14 @@ namespace fggl::math { } + +// feels a bit strange to be doing this... +namespace glm { + inline bool operator<(const vec3& lhs, const vec3& rhs) { + return std::tie( lhs.x, lhs.y, lhs.z ) + < std::tie( rhs.x, rhs.y, rhs.z ); + } +} + + #endif -- GitLab