From 26e7c9ce340455335fdf1f7af74bf9d21ba8617b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 6 Mar 2014 22:38:46 +0100 Subject: [PATCH] MeshTools: added compile() function. All-in-one solution for preparing generic meshes with optional normals and texture coordinates, configured for use with Shaders::Generic. --- src/Magnum/MeshTools/CMakeLists.txt | 2 + src/Magnum/MeshTools/Compile.cpp | 160 +++++++++++++++++++++++++ src/Magnum/MeshTools/Compile.h | 81 +++++++++++++ src/Magnum/MeshTools/CompressIndices.h | 2 +- 4 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 src/Magnum/MeshTools/Compile.cpp create mode 100644 src/Magnum/MeshTools/Compile.h diff --git a/src/Magnum/MeshTools/CMakeLists.txt b/src/Magnum/MeshTools/CMakeLists.txt index f4e9587e2..fb2b324ca 100644 --- a/src/Magnum/MeshTools/CMakeLists.txt +++ b/src/Magnum/MeshTools/CMakeLists.txt @@ -25,6 +25,7 @@ # Files shared between main library and unit test library set(MagnumMeshTools_SRCS + Compile.cpp CompressIndices.cpp FullScreenTriangle.cpp Tipsify.cpp) @@ -37,6 +38,7 @@ set(MagnumMeshTools_GracefulAssert_SRCS set(MagnumMeshTools_HEADERS CombineIndexedArrays.h + Compile.h CompressIndices.h Duplicate.h FlipNormals.h diff --git a/src/Magnum/MeshTools/Compile.cpp b/src/Magnum/MeshTools/Compile.cpp new file mode 100644 index 000000000..b1372acfd --- /dev/null +++ b/src/Magnum/MeshTools/Compile.cpp @@ -0,0 +1,160 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Compile.h" + +#include "Magnum/Math/Vector3.h" +#include "Magnum/MeshTools/CompressIndices.h" +#include "Magnum/MeshTools/Interleave.h" +#include "Magnum/Trade/MeshData2D.h" +#include "Magnum/Trade/MeshData3D.h" + +/* This header is included only privately and doesn't introduce any linker + dependency, thus it's completely safe */ +#include "Magnum/Shaders/Generic.h" + +namespace Magnum { namespace MeshTools { + +std::tuple, std::unique_ptr> compile(const Trade::MeshData2D& meshData, const BufferUsage usage) { + Mesh mesh; + mesh.setPrimitive(meshData.primitive()); + + /* Decide about stride and offsets */ + UnsignedInt stride = sizeof(Shaders::Generic2D::Position::Type); + const UnsignedInt normalOffset = sizeof(Shaders::Generic2D::Position::Type); + if(meshData.hasTextureCoords2D()) + stride += sizeof(Shaders::Generic2D::TextureCoordinates::Type); + + /* Create vertex buffer */ + std::unique_ptr vertexBuffer{new Buffer{Buffer::Target::Array}}; + + /* Interleave positions */ + std::size_t vertexCount; + Containers::Array data; + std::tie(vertexCount, std::ignore, data) = MeshTools::interleave( + meshData.positions(0), + stride - sizeof(Shaders::Generic2D::Position::Type)); + mesh.addVertexBuffer(*vertexBuffer, 0, + Shaders::Generic2D::Position(), + stride - sizeof(Shaders::Generic2D::Position::Type)); + + /* Add also texture coordinates, if present */ + if(meshData.hasTextureCoords2D()) { + MeshTools::interleaveInto(data, + normalOffset, + meshData.textureCoords2D(0), + stride - normalOffset - sizeof(Shaders::Generic2D::TextureCoordinates::Type)); + mesh.addVertexBuffer(*vertexBuffer, 0, + normalOffset, + Shaders::Generic2D::TextureCoordinates(), + stride - normalOffset - sizeof(Shaders::Generic2D::TextureCoordinates::Type)); + } + + /* Fill vertex buffer with interleaved data and finalize mesh + configuration */ + vertexBuffer->setData(data, BufferUsage::StaticDraw); + mesh.setVertexCount(vertexCount); + + /* Fill index buffer */ + std::unique_ptr indexBuffer; + if(meshData.isIndexed()) { + indexBuffer.reset(new Buffer{Buffer::Target::ElementArray}); + MeshTools::compressIndices(mesh, *indexBuffer, usage, meshData.indices()); + } + + return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer)); +} + +std::tuple, std::unique_ptr> compile(const Trade::MeshData3D& meshData, const BufferUsage usage) { + Mesh mesh; + mesh.setPrimitive(meshData.primitive()); + + /* Decide about stride and offsets */ + UnsignedInt stride = sizeof(Shaders::Generic3D::Position::Type); + const UnsignedInt normalOffset = sizeof(Shaders::Generic3D::Position::Type); + UnsignedInt textureCoordsOffset = sizeof(Shaders::Generic3D::Position::Type); + if(meshData.hasNormals()) { + stride += sizeof(Shaders::Generic3D::Normal::Type); + textureCoordsOffset += sizeof(Shaders::Generic3D::Normal::Type); + } + if(meshData.hasTextureCoords2D()) + stride += sizeof(Shaders::Generic3D::TextureCoordinates::Type); + + /* Create vertex buffer */ + std::unique_ptr vertexBuffer{new Buffer{Buffer::Target::Array}}; + + /* Interleave positions */ + std::size_t vertexCount; + Containers::Array data; + std::tie(vertexCount, std::ignore, data) = MeshTools::interleave( + meshData.positions(0), + stride - sizeof(Shaders::Generic3D::Position::Type)); + mesh.addVertexBuffer(*vertexBuffer, 0, + Shaders::Generic3D::Position(), + stride - sizeof(Shaders::Generic3D::Position::Type)); + + Debug() << stride << sizeof(Shaders::Generic3D::Position::Type) << vertexCount << normalOffset << textureCoordsOffset; + Debug() << data; + + /* Add also normals, if present */ + if(meshData.hasNormals()) { + MeshTools::interleaveInto(data, + normalOffset, + meshData.normals(0), + stride - normalOffset - sizeof(Shaders::Generic3D::Normal::Type)); + mesh.addVertexBuffer(*vertexBuffer, 0, + normalOffset, + Shaders::Generic3D::Normal(), + stride - normalOffset - sizeof(Shaders::Generic3D::Normal::Type)); + } + + /* Add also texture coordinates, if present */ + if(meshData.hasTextureCoords2D()) { + MeshTools::interleaveInto(data, + textureCoordsOffset, + meshData.textureCoords2D(0), + stride - textureCoordsOffset - sizeof(Shaders::Generic3D::TextureCoordinates::Type)); + mesh.addVertexBuffer(*vertexBuffer, 0, + textureCoordsOffset, + Shaders::Generic3D::TextureCoordinates(), + stride - textureCoordsOffset - sizeof(Shaders::Generic3D::TextureCoordinates::Type)); + } + + /* Fill vertex buffer with interleaved data and finalize mesh + configuration */ + vertexBuffer->setData(data, BufferUsage::StaticDraw); + mesh.setVertexCount(vertexCount); + + /* Fill index buffer */ + std::unique_ptr indexBuffer; + if(meshData.isIndexed()) { + indexBuffer.reset(new Buffer{Buffer::Target::ElementArray}); + MeshTools::compressIndices(mesh, *indexBuffer, usage, meshData.indices()); + } + + return std::make_tuple(std::move(mesh), std::move(vertexBuffer), std::move(indexBuffer)); +} + +}} diff --git a/src/Magnum/MeshTools/Compile.h b/src/Magnum/MeshTools/Compile.h new file mode 100644 index 000000000..3cb41c795 --- /dev/null +++ b/src/Magnum/MeshTools/Compile.h @@ -0,0 +1,81 @@ +#ifndef Magnum_MeshTools_Compile_h +#define Magnum_MeshTools_Compile_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Function @ref Magnum::MeshTools::compile() + */ + +#include +#include + +#include "Magnum/Magnum.h" +#include "Magnum/Trade/Trade.h" +#include "Magnum/MeshTools/visibility.h" + +namespace Magnum { namespace MeshTools { + +/** +@brief Compile 2D mesh data + +Configures mesh for @ref Shaders::Generic2D shader with vertex buffer and +possibly also index buffer, if the mesh is indexed. Positions are bound to +@ref Shaders::Generic2D::Position attribute. If the mesh contains texture +coordinates, they are bound to @ref Shaders::Generic2D::TextureCoordinates +attribute. No data compression or index optimization (except for index buffer +packing) is done. The @p usage parameter is used for both vertex and index +buffer. + +The second returned buffer may be `nullptr` if the mesh is not indexed. + +This is just a convenience function for creating generic meshes, you might want +to use @ref interleave() and @ref compressIndices() functions instead for +greater flexibility. +*/ +MAGNUM_MESHTOOLS_EXPORT std::tuple, std::unique_ptr> compile(const Trade::MeshData2D& meshData, BufferUsage usage); + +/** +@brief Compile 3D mesh data + +Configures mesh for @ref Shaders::Generic3D shader with vertex buffer and +possibly also index buffer, if the mesh is indexed. Positions are bound to +@ref Shaders::Generic3D::Position attribute. If the mesh contains normals, they +are bound to @ref Shaders::Generic3D::Normal attribute, texture coordinates are +bound to @ref Shaders::Generic2D::TextureCoordinates attribute. No data +compression or index optimization (except for index buffer packing) is done. +The @p usage parameter is used for both vertex and index buffer. + +The second returned buffer may be `nullptr` if the mesh is not indexed. + +This is just a convenience function for creating generic meshes, you might want +to use @ref interleave() and @ref compressIndices() functions instead for +greater flexibility. +*/ +MAGNUM_MESHTOOLS_EXPORT std::tuple, std::unique_ptr> compile(const Trade::MeshData3D& meshData, BufferUsage usage); + +}} + +#endif diff --git a/src/Magnum/MeshTools/CompressIndices.h b/src/Magnum/MeshTools/CompressIndices.h index 844962dda..e1e847910 100644 --- a/src/Magnum/MeshTools/CompressIndices.h +++ b/src/Magnum/MeshTools/CompressIndices.h @@ -69,7 +69,7 @@ function writes the output to given buffer and calls @ref Mesh::setIndexCount() and @ref Mesh::setIndexBuffer(), thus you don't need to do anything else for mesh index configuration. -@see @ref MeshTools::interleave() +@see @ref MeshTools::interleave(), @ref MeshTools::compile() */ void MAGNUM_MESHTOOLS_EXPORT compressIndices(Mesh& mesh, Buffer& buffer, BufferUsage usage, const std::vector& indices);