#ifndef Magnum_MeshBuilder_h #define Magnum_MeshBuilder_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš This file is part of Magnum. Magnum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 only, as published by the Free Software Foundation. Magnum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License version 3 for more details. */ /** @file * @brief Class Magnum::MeshBuilder */ #include #include #include #include #include "Buffer.h" #include "IndexedMesh.h" #include "SizeTraits.h" namespace Magnum { namespace MeshTools { template class AbstractTool; class AbstractIndexTool; } /** @brief Mesh builder @tparam Vertex Vertex data Class for building meshes with triangle primitive from scratch or from prefabricated data and modifying them using MeshBuilder alone or tools from MeshTools namespace. @todo Make it more generic for meshes with texture coordinates etc. */ template class MeshBuilder { friend class MeshTools::AbstractTool; friend class MeshTools::AbstractIndexTool; public: /** * @brief Destructor * * Removed all vertices and faces. */ inline virtual ~MeshBuilder() { clear(); } /** * @brief Clear mesh data * * The data are cleared automatically in destructor and when calling * setData(). If you don't want to use the data after building the mesh, * destroy the MeshBuilder or call this function. */ void clear() { _vertices.clear(); _indices.clear(); } /** @brief Vertex count */ inline unsigned int vertexCount() const { return _vertices.size(); } /** @brief Array with vertices */ inline const std::vector& vertices() const { return _vertices; } /** @brief Index count */ inline unsigned int indexCount() const { return _indices.size(); } /** @brief Array with indices */ inline const std::vector& indices() const { return _indices; } /** * @brief Set mesh data * @param vertexData Vertex data * @param indices Vertex indices * @param vertexCount Vertex count * @param indexCount Index count * * Replaces mesh builder data with given data. Type of indices is * detected from given pointer. */ template void setData(const Vertex* vertexData, const IndexType* indices, unsigned int vertexCount, unsigned int indexCount) { clear(); /* Vertex array */ std::vector vertices; vertices.reserve(vertexCount); /* Using TypeTraits::IndexType to ensure we have allowed type for indexing */ for(typename TypeTraits::IndexType i = 0; i != vertexCount; ++i) addVertex(Vertex(vertexData[i])); /* Index array */ _indices.reserve(indexCount); for(unsigned int i = 0; i != indexCount; ++i) _indices.push_back(indices[i]); } /** @brief Add vertex */ inline unsigned int addVertex(const Vertex& v) { _vertices.push_back(v); return _vertices.size()-1; } /** @brief Add face */ inline void addFace(unsigned int first, unsigned int second, unsigned int third) { _indices.push_back(first); _indices.push_back(second); _indices.push_back(third); } /** * @brief Build indexed mesh and fill existing buffers with it * @param mesh Mesh. The mesh primitive is set to * Mesh::Triangles, if it is not already, vertex and index count * is updated to values from the builder. * @param vertexBuffer Vertex buffer created as interleaved * with Mesh::addBuffer(). Otherwise the behaviour is undefined. * @param vertexBufferUsage Usage of the vertex buffer. * @param indexBufferUsage Usage of the index buffer. * * Builds indexed mesh from the data and fills given mesh buffers with * them. * @note The mesh is @b not cleaned before building. */ void build(IndexedMesh* mesh, Buffer* vertexBuffer, Buffer::Usage vertexBufferUsage, Buffer::Usage indexBufferUsage) { mesh->setPrimitive(Mesh::Primitive::Triangles); mesh->setVertexCount(_vertices.size()); vertexBuffer->setData(sizeof(Vertex)*_vertices.size(), _vertices.data(), vertexBufferUsage); SizeBasedCall(_vertices.size())(mesh, _indices, indexBufferUsage); } /** * @brief Build indexed data and create new mesh from them * @param vertexBufferUsage Usage of the vertex buffer. * @param indexBufferUsage Usage of the index buffer. * * @see build(IndexedMesh*, Buffer*, Buffer::Usage, Buffer::Usage) */ IndexedMesh* build(Buffer::Usage vertexBufferUsage, Buffer::Usage indexBufferUsage) { IndexedMesh mesh = new IndexedMesh; Buffer* vertexBuffer = mesh.addBuffer(true); build(mesh, vertexBuffer, vertexBufferUsage, indexBufferUsage); return mesh; } private: std::vector _indices; std::vector _vertices; struct IndexBuilder { template static void run(IndexedMesh* mesh, const std::vector& _indices, Buffer::Usage indexBufferUsage) { /* Compress face array to index array. Using TypeTraits::IndexType to ensure we have allowed type for indexing */ std::vector::IndexType> indices; indices.reserve(_indices.size()); for(auto it = _indices.cbegin(); it != _indices.cend(); ++it) indices.push_back(*it); /* Update mesh parameters and fill index buffer */ mesh->setIndexCount(indices.size()); mesh->setIndexType(TypeTraits::glType()); mesh->indexBuffer()->setData(sizeof(IndexType)*indices.size(), indices.data(), indexBufferUsage); } }; }; } #endif