diff --git a/doc/generated/shaders.cpp b/doc/generated/shaders.cpp index 8a30f4281..f4cbc9bcd 100644 --- a/doc/generated/shaders.cpp +++ b/doc/generated/shaders.cpp @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -211,7 +212,7 @@ Containers::StringView ShaderVisualizer::line() { .setViewportSize(Vector2{ImageSize}) .setWidth(5.0f) .setSmoothness(1.0f) - .draw(MeshTools::compileLines(mesh)); + .draw(MeshTools::compileLines(MeshTools::generateLines(mesh))); return "line.png"; } diff --git a/doc/snippets/MagnumShaders-gl.cpp b/doc/snippets/MagnumShaders-gl.cpp index 6a928ef5f..aaec29ba1 100644 --- a/doc/snippets/MagnumShaders-gl.cpp +++ b/doc/snippets/MagnumShaders-gl.cpp @@ -52,6 +52,7 @@ #include "Magnum/Math/FunctionsBatch.h" #include "Magnum/MeshTools/Compile.h" #include "Magnum/MeshTools/Duplicate.h" +#include "Magnum/MeshTools/GenerateLines.h" #include "Magnum/Shaders/DistanceFieldVectorGL.h" #include "Magnum/Shaders/FlatGL.h" #include "Magnum/Shaders/MeshVisualizerGL.h" @@ -703,7 +704,7 @@ vert.addSource(Utility::format( { /* [LineGL-usage] */ Trade::MeshData circle = Primitives::circle2DWireframe(16); -GL::Mesh mesh = MeshTools::compileLines(circle); +GL::Mesh mesh = MeshTools::compileLines(MeshTools::generateLines(circle)); /* [LineGL-usage] */ } diff --git a/src/Magnum/MeshTools/CMakeLists.txt b/src/Magnum/MeshTools/CMakeLists.txt index 863d08bd3..108df9fa8 100644 --- a/src/Magnum/MeshTools/CMakeLists.txt +++ b/src/Magnum/MeshTools/CMakeLists.txt @@ -41,6 +41,7 @@ set(MagnumMeshTools_GracefulAssert_SRCS FilterAttributes.cpp FlipNormals.cpp GenerateIndices.cpp + GenerateLines.cpp GenerateNormals.cpp Interleave.cpp Reference.cpp @@ -56,6 +57,7 @@ set(MagnumMeshTools_HEADERS FilterAttributes.h FlipNormals.h GenerateIndices.h + GenerateLines.h GenerateNormals.h Interleave.h InterleaveFlags.h diff --git a/src/Magnum/MeshTools/CompileLines.cpp b/src/Magnum/MeshTools/CompileLines.cpp index e65b2798b..ce8e1c913 100644 --- a/src/Magnum/MeshTools/CompileLines.cpp +++ b/src/Magnum/MeshTools/CompileLines.cpp @@ -25,10 +25,12 @@ #include "CompileLines.h" +#include + #include "Magnum/GL/Buffer.h" #include "Magnum/GL/Mesh.h" #include "Magnum/MeshTools/Compile.h" -#include "Magnum/MeshTools/Implementation/GenerateLines.h" +#include "Magnum/MeshTools/GenerateLines.h" /* This header is included only privately and doesn't introduce any linker dependency (taking just the PreviousPosition, NextPosition and Annotation @@ -38,13 +40,16 @@ namespace Magnum { namespace MeshTools { -GL::Mesh compileLines(const Trade::MeshData& lineMesh) { - Trade::MeshData mesh = Implementation::generateLines(lineMesh); - - #ifdef CORRADE_GRACEFUL_ASSERT - /* If it asserted inside, bail */ - if(!mesh.attributeCount()) return GL::Mesh{}; - #endif +GL::Mesh compileLines(const Trade::MeshData& mesh) { + /* The assertion checks might be a bit excessive but the custom attributes + *may* conflict with some other user-defined ones so better rule that out + as much as possible */ + CORRADE_ASSERT( + mesh.primitive() == MeshPrimitive::Triangles && + mesh.hasAttribute(Implementation::LineMeshAttributePreviousPosition) && + mesh.hasAttribute(Implementation::LineMeshAttributeNextPosition) && + mesh.hasAttribute(Implementation::LineMeshAttributeAnnotation), + "MeshTools::compileLines(): the mesh wasn't produced with generateLines()", GL::Mesh{}); /* Upload the buffers, bind the line-specific attributes manually */ GL::Buffer indices{GL::Buffer::TargetHint::ElementArray, mesh.indexData()}; @@ -56,28 +61,28 @@ GL::Mesh compileLines(const Trade::MeshData& lineMesh) { static_assert(Shaders::GenericGL3D::TextureCoordinates::Location == UnsignedInt(Shaders::LineGL3D::Annotation::Location), ""); static_assert(Shaders::GenericGL3D::Tangent::Location == UnsignedInt(Shaders::LineGL3D::PreviousPosition::Location), ""); static_assert(Shaders::GenericGL3D::Normal::Location == UnsignedInt(Shaders::LineGL3D::NextPosition::Location), ""); - if(const Containers::Optional id = lineMesh.findAttributeId(Trade::MeshAttribute::TextureCoordinates)) - Warning{} << "MeshTools::compileLines():" << lineMesh.attributeName(*id) << "conflicts with line annotation attribute, ignoring"; - if(const Containers::Optional id = lineMesh.findAttributeId(Trade::MeshAttribute::Tangent)) - Warning{} << "MeshTools::compileLines():" << lineMesh.attributeName(*id) << "conflicts with line previous position attribute, ignoring"; - if(const Containers::Optional id = lineMesh.findAttributeId(Trade::MeshAttribute::Normal)) - Warning{} << "MeshTools::compileLines():" << lineMesh.attributeName(*id) << "conflicts with line next position attribute, ignoring"; + if(const Containers::Optional id = mesh.findAttributeId(Trade::MeshAttribute::TextureCoordinates)) + Warning{} << "MeshTools::compileLines():" << mesh.attributeName(*id) << "conflicts with line annotation attribute, ignoring"; + if(const Containers::Optional id = mesh.findAttributeId(Trade::MeshAttribute::Tangent)) + Warning{} << "MeshTools::compileLines():" << mesh.attributeName(*id) << "conflicts with line previous position attribute, ignoring"; + if(const Containers::Optional id = mesh.findAttributeId(Trade::MeshAttribute::Normal)) + Warning{} << "MeshTools::compileLines():" << mesh.attributeName(*id) << "conflicts with line next position attribute, ignoring"; /* PreviousPosition / NextPosition are bound to the same location in both 2D and 3D, using the 3D variant so it can be trimmed to just two components in 2D (which wouldn't be possible the other way around) */ out.addVertexBuffer(vertices, - mesh.attributeOffset(Implementation::MeshAttributePreviousPosition), - mesh.attributeStride(Implementation::MeshAttributePreviousPosition), - GL::DynamicAttribute{Shaders::LineGL3D::PreviousPosition{}, mesh.attributeFormat(Implementation::MeshAttributePreviousPosition)}); + mesh.attributeOffset(Implementation::LineMeshAttributePreviousPosition), + mesh.attributeStride(Implementation::LineMeshAttributePreviousPosition), + GL::DynamicAttribute{Shaders::LineGL3D::PreviousPosition{}, mesh.attributeFormat(Implementation::LineMeshAttributePreviousPosition)}); out.addVertexBuffer(vertices, - mesh.attributeOffset(Implementation::MeshAttributeNextPosition), - mesh.attributeStride(Implementation::MeshAttributeNextPosition), - GL::DynamicAttribute{Shaders::LineGL3D::NextPosition{}, mesh.attributeFormat(Implementation::MeshAttributeNextPosition)}); + mesh.attributeOffset(Implementation::LineMeshAttributeNextPosition), + mesh.attributeStride(Implementation::LineMeshAttributeNextPosition), + GL::DynamicAttribute{Shaders::LineGL3D::NextPosition{}, mesh.attributeFormat(Implementation::LineMeshAttributeNextPosition)}); out.addVertexBuffer(std::move(vertices), - mesh.attributeOffset(Implementation::MeshAttributeAnnotation), - mesh.attributeStride(Implementation::MeshAttributeAnnotation), - GL::DynamicAttribute{Shaders::LineGL3D::Annotation{}, mesh.attributeFormat(Implementation::MeshAttributeAnnotation)}); + mesh.attributeOffset(Implementation::LineMeshAttributeAnnotation), + mesh.attributeStride(Implementation::LineMeshAttributeAnnotation), + GL::DynamicAttribute{Shaders::LineGL3D::Annotation{}, mesh.attributeFormat(Implementation::LineMeshAttributeAnnotation)}); return out; } diff --git a/src/Magnum/MeshTools/CompileLines.h b/src/Magnum/MeshTools/CompileLines.h index f5e2633f4..d2165bb1b 100644 --- a/src/Magnum/MeshTools/CompileLines.h +++ b/src/Magnum/MeshTools/CompileLines.h @@ -45,31 +45,10 @@ namespace Magnum { namespace MeshTools { @brief Compile a line mesh for use with @ref Shaders::LineGL @m_since_latest -Returns a @ref MeshPrimitive::Triangles mesh with -@ref MeshIndexType::UnsignedInt indices, all input attributes preserved in -their original format, and additionally with -@ref Shaders::LineGL::PreviousPosition and @ref Shaders::LineGL::NextPosition -attributes added in the same format as the input -@ref Trade::MeshAttribute::Position, and the @ref Shaders::LineGL::Annotation -attribute as @ref VertexFormat::UnsignedInt, according to the -@ref Shaders-LineGL-mesh-representation documentation of the shader. +Expects that the @p mesh is returned from @ref generateLines(), see its +documentation for more information. -Each line segment in the input vertices is converted to a quad, with first two -vertices inheriting vertex data from the first point of the segment and second -two vertices inheriting data from the second point of the segment. If the input -mesh is indexed, it's deindexed first. Neighbor information from a -@ref MeshPrimitive::LineStrip or @ref MeshPrimitive::LineLoop mesh is used to -form a single contiguous strip or a loop, @ref MeshPrimitive::Lines is treated -as loose segments. - -For compatibility with shaders other than @ref Shaders::LineGL, the output mesh -can be also interpreted as indexed @ref MeshPrimitive::Lines --- out of every -six indices forming a quad, two will form a line segment between the two -original points, and the remaining four collapse into two degenerate line -segments. - -Expects that the mesh contains at least a @ref Trade::MeshAttribute::Position -and is a line @relativeref{Magnum,MeshPrimitive}. +@experimental @note This function is available only if Magnum is compiled with @ref MAGNUM_TARGET_GL enabled (done by default). See @ref building-features @@ -82,7 +61,7 @@ and is a line @relativeref{Magnum,MeshPrimitive}. is not available in WebGL 1.0, thus neither this function is defined in WebGL 1.0 builds. */ -MAGNUM_MESHTOOLS_EXPORT GL::Mesh compileLines(const Trade::MeshData& lineMesh); +MAGNUM_MESHTOOLS_EXPORT GL::Mesh compileLines(const Trade::MeshData& mesh); }} #else diff --git a/src/Magnum/MeshTools/Implementation/GenerateLines.h b/src/Magnum/MeshTools/GenerateLines.cpp similarity index 89% rename from src/Magnum/MeshTools/Implementation/GenerateLines.h rename to src/Magnum/MeshTools/GenerateLines.cpp index 95ad388ed..a42665a7c 100644 --- a/src/Magnum/MeshTools/Implementation/GenerateLines.h +++ b/src/Magnum/MeshTools/GenerateLines.cpp @@ -1,5 +1,3 @@ -#ifndef Magnum_MeshTools_Implementation_GenerateLines_h -#define Magnum_MeshTools_Implementation_GenerateLines_h /* This file is part of Magnum. @@ -25,6 +23,8 @@ DEALINGS IN THE SOFTWARE. */ +#include "GenerateLines.h" + #include #include #include @@ -32,30 +32,19 @@ #include "Magnum/MeshTools/Duplicate.h" #include "Magnum/MeshTools/GenerateIndices.h" -#include "Magnum/Trade/MeshData.h" /* This header is included only privately and doesn't introduce any linker dependency (taking just the LineVertexAnnotations enum), thus it's completely safe to not link to the Shaders library */ #include "Magnum/Shaders/Line.h" -namespace Magnum { namespace MeshTools { namespace Implementation { namespace { - -/* This code is used internally by compileLines() and returns a MeshData - instance in order to be testable. The intention is to eventually make this - API public and the custom attributes builtin in order to make it possible to - (for example) produce glTF files that are already directly renderable as - wide line meshes. */ - -constexpr Trade::MeshAttribute MeshAttributePreviousPosition = Trade::meshAttributeCustom(32765); -constexpr Trade::MeshAttribute MeshAttributeNextPosition = Trade::meshAttributeCustom(32766); -constexpr Trade::MeshAttribute MeshAttributeAnnotation = Trade::meshAttributeCustom(32767); +namespace Magnum { namespace MeshTools { Trade::MeshData generateLines(const Trade::MeshData& lineMesh) { CORRADE_ASSERT(lineMesh.primitive() == MeshPrimitive::Lines || lineMesh.primitive() == MeshPrimitive::LineStrip || lineMesh.primitive() == MeshPrimitive::LineLoop, - "Trade::MeshTools::compileLines(): expected a line primitive, got" << lineMesh.primitive(), (Trade::MeshData{MeshPrimitive::Triangles, 0})); + "Trade::MeshTools::generateLines(): expected a line primitive, got" << lineMesh.primitive(), (Trade::MeshData{MeshPrimitive::Triangles, 0})); /** @todo this will assert if the count in MeshData is wrong, check here already */ @@ -97,19 +86,19 @@ Trade::MeshData generateLines(const Trade::MeshData& lineMesh) { /* Position is required, everything else is optional */ const Containers::Optional positionAttributeId = lineMesh.findAttributeId(Trade::MeshAttribute::Position); CORRADE_ASSERT(positionAttributeId, - "Trade::MeshTools::compileLines(): the mesh has no positions", (Trade::MeshData{MeshPrimitive::Triangles, 0})); + "Trade::MeshTools::generateLines(): the mesh has no positions", (Trade::MeshData{MeshPrimitive::Triangles, 0})); /* Duplicate the input mesh to have each input line segment turned into four vertices for a quad. Allocate space for the additional attributes as well. */ Trade::MeshData mesh = duplicate(Trade::MeshData{MeshPrimitive::Triangles, {}, pointDuplicationIndices, Trade::MeshIndexData{pointDuplicationIndices}, {}, lineMesh.vertexData(), Trade::meshAttributeDataNonOwningArray(lineMesh.attributeData()), lineMesh.vertexCount()}, { - Trade::MeshAttributeData{MeshAttributePreviousPosition, + Trade::MeshAttributeData{Implementation::LineMeshAttributePreviousPosition, lineMesh.attributeFormat(*positionAttributeId), nullptr}, - Trade::MeshAttributeData{MeshAttributeNextPosition, + Trade::MeshAttributeData{Implementation::LineMeshAttributeNextPosition, lineMesh.attributeFormat(*positionAttributeId), nullptr}, /** @todo use a 8-bit type and make the attribute non-interleaved to save space? */ - Trade::MeshAttributeData{MeshAttributeAnnotation, + Trade::MeshAttributeData{Implementation::LineMeshAttributeAnnotation, VertexFormat::UnsignedInt, nullptr}, }); @@ -123,12 +112,12 @@ Trade::MeshData generateLines(const Trade::MeshData& lineMesh) { {positions.size()[0]/2, 2, positions.size()[1]}, {positions.stride()[0]*2, positions.stride()[0], positions.stride()[1]}}; - const Containers::StridedArrayView2D previousPositions = mesh.mutableAttribute(MeshAttributePreviousPosition); + const Containers::StridedArrayView2D previousPositions = mesh.mutableAttribute(Implementation::LineMeshAttributePreviousPosition); const Containers::StridedArrayView3D previousPositions3{mesh.mutableVertexData(), static_cast(previousPositions.data()), {previousPositions.size()[0]/2, 2, previousPositions.size()[1]}, {previousPositions.stride()[0]*2, previousPositions.stride()[0], previousPositions.stride()[1]}}; - const Containers::StridedArrayView2D nextPositions = mesh.mutableAttribute(MeshAttributeNextPosition); + const Containers::StridedArrayView2D nextPositions = mesh.mutableAttribute(Implementation::LineMeshAttributeNextPosition); const Containers::StridedArrayView3D nextPositions3{mesh.mutableVertexData(), static_cast(nextPositions.data()), {nextPositions.size()[0]/2, 2, nextPositions.size()[1]}, {nextPositions.stride()[0]*2, nextPositions.stride()[0], nextPositions.stride()[1]}}; @@ -180,7 +169,7 @@ Trade::MeshData generateLines(const Trade::MeshData& lineMesh) { } /* Fill in point annotation */ - const Containers::StridedArrayView1D annotations = Containers::arrayCast(mesh.mutableAttribute(MeshAttributeAnnotation)); + const Containers::StridedArrayView1D annotations = Containers::arrayCast(mesh.mutableAttribute(Implementation::LineMeshAttributeAnnotation)); for(UnsignedInt i = 0; i != quadCount; ++i) { annotations[i*4 + 0] = Shaders::LineVertexAnnotation::Up|Shaders::LineVertexAnnotation::Begin; annotations[i*4 + 1] = Shaders::LineVertexAnnotation::Begin; @@ -282,6 +271,4 @@ Trade::MeshData generateLines(const Trade::MeshData& lineMesh) { mesh.releaseVertexData(), mesh.releaseAttributeData()}; } -}}}} - -#endif +}} diff --git a/src/Magnum/MeshTools/GenerateLines.h b/src/Magnum/MeshTools/GenerateLines.h new file mode 100644 index 000000000..b5d8be5e2 --- /dev/null +++ b/src/Magnum/MeshTools/GenerateLines.h @@ -0,0 +1,89 @@ +#ifndef Magnum_MeshTools_GenerateLines_h +#define Magnum_MeshTools_GenerateLines_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, + 2020, 2021, 2022 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::generateLines() + * @m_since_latest + */ + +#include "Magnum/MeshTools/visibility.h" +#include "Magnum/Trade/MeshData.h" /* needs meshAttributeCustom() for now */ + +namespace Magnum { namespace MeshTools { + +namespace Implementation { + +/** @todo make these builtin, and once they are, deprecate compileLines() in + favor of compile() handling these extra attributes as well */ +constexpr Trade::MeshAttribute LineMeshAttributePreviousPosition = Trade::meshAttributeCustom(32765); +constexpr Trade::MeshAttribute LineMeshAttributeNextPosition = Trade::meshAttributeCustom(32766); +constexpr Trade::MeshAttribute LineMeshAttributeAnnotation = Trade::meshAttributeCustom(32767); + +} + +/** +@brief Generate a line mesh for use with @ref Shaders::LineGL +@m_since_latest + +Creates a @ref MeshPrimitive::Triangles mesh with +@ref MeshIndexType::UnsignedInt indices, all input attributes preserved in +their original format, and additionally with custom attributes corresponding to +@ref Shaders::LineGL::PreviousPosition and @ref Shaders::LineGL::NextPosition +added in the same format as the input @ref Trade::MeshAttribute::Position, and +a custom attribute corresponding to the @ref Shaders::LineGL::Annotation +attribute as @ref VertexFormat::UnsignedInt. See +@ref Shaders-LineGL-mesh-representation "documentation of the shader" for +details about the internal representation. + +Each line segment in the input vertices is converted to a quad, with first two +vertices inheriting vertex data from the first point of the segment and second +two vertices inheriting data from the second point of the segment. If the input +mesh is indexed, it's deindexed first. Neighbor information from a +@ref MeshPrimitive::LineStrip or @ref MeshPrimitive::LineLoop mesh is used to +form a single contiguous strip or a loop, @ref MeshPrimitive::Lines is treated +as loose segments. + +For compatibility with shaders other than @ref Shaders::LineGL, the output mesh +can be also interpreted as indexed @ref MeshPrimitive::Lines --- out of every +six indices forming a quad, two will form a line segment between the two +original points, and the remaining four collapse into two degenerate line +segments. + +Expects that the mesh contains at least a @ref Trade::MeshAttribute::Position +and is a line @relativeref{Magnum,MeshPrimitive}. + +The returned @ref Trade::MeshData instance is meant to be passed to +@ref compileLines() for use with the shader. It can however be also processed +with other @ref MeshTools first, such as @ref compressIndices(const Trade::MeshData&, MeshIndexType) or @ref concatenate(). + +@experimental +*/ +MAGNUM_MESHTOOLS_EXPORT Trade::MeshData generateLines(const Trade::MeshData& lineMesh); + +}} + +#endif diff --git a/src/Magnum/MeshTools/Test/CMakeLists.txt b/src/Magnum/MeshTools/Test/CMakeLists.txt index ae43f35da..2cc712d04 100644 --- a/src/Magnum/MeshTools/Test/CMakeLists.txt +++ b/src/Magnum/MeshTools/Test/CMakeLists.txt @@ -35,6 +35,9 @@ corrade_add_test(MeshToolsDuplicateTest DuplicateTest.cpp LIBRARIES MagnumMeshTo corrade_add_test(MeshToolsFilterAttributesTest FilterAttributesTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsFlipNormalsTest FlipNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsGenerateIndicesTest GenerateIndicesTest.cpp LIBRARIES MagnumMeshToolsTestLib) +corrade_add_test(MeshToolsGenerateLinesTest GenerateLinesTest.cpp + # Needs to link to Shaders for debug output for LineVertexAnnotations + LIBRARIES MagnumMeshToolsTestLib MagnumShaders) corrade_add_test(MeshToolsGenerateNormalsTest GenerateNormalsTest.cpp LIBRARIES MagnumMeshToolsTestLib MagnumPrimitives) corrade_add_test(MeshToolsInterleaveTest InterleaveTest.cpp LIBRARIES MagnumMeshToolsTestLib) corrade_add_test(MeshToolsReferenceTest ReferenceTest.cpp LIBRARIES MagnumMeshToolsTestLib MagnumPrimitives) @@ -43,12 +46,6 @@ corrade_add_test(MeshToolsSubdivideTest SubdivideTest.cpp LIBRARIES Magnum Magnu corrade_add_test(MeshToolsTipsifyTest TipsifyTest.cpp LIBRARIES MagnumMeshTools) corrade_add_test(MeshToolsTransformTest TransformTest.cpp LIBRARIES MagnumMeshToolsTestLib) -if(NOT MAGNUM_TARGET_GLES2) - corrade_add_test(MeshToolsCompileLinesTest CompileLinesTest.cpp - # Needs to link to Shaders for debug output for LineVertexAnnotations - LIBRARIES MagnumMeshToolsTestLib MagnumShaders) -endif() - # Graceful assert for testing set_property(TARGET MeshToolsConcatenateTest diff --git a/src/Magnum/MeshTools/Test/CompileLinesGLTest.cpp b/src/Magnum/MeshTools/Test/CompileLinesGLTest.cpp index 871ef2fcc..6951e4ee9 100644 --- a/src/Magnum/MeshTools/Test/CompileLinesGLTest.cpp +++ b/src/Magnum/MeshTools/Test/CompileLinesGLTest.cpp @@ -45,6 +45,7 @@ #include "Magnum/Math/Matrix4.h" #include "Magnum/MeshTools/Compile.h" #include "Magnum/MeshTools/CompileLines.h" +#include "Magnum/MeshTools/GenerateLines.h" #include "Magnum/Shaders/FlatGL.h" #include "Magnum/Shaders/Line.h" #include "Magnum/Shaders/LineGL.h" @@ -68,7 +69,7 @@ struct CompileLinesGLTest: GL::OpenGLTester { void emptyMesh(); - void notLines(); + void notGeneratedLineMesh(); void noAttributes(); void noPositionAttribute(); @@ -128,9 +129,7 @@ CompileLinesGLTest::CompileLinesGLTest() { addTests({&CompileLinesGLTest::emptyMesh, - &CompileLinesGLTest::notLines, - &CompileLinesGLTest::noAttributes, - &CompileLinesGLTest::noPositionAttribute}); + &CompileLinesGLTest::notGeneratedLineMesh}); /* Load the plugins directly from the build tree. Otherwise they're either static and already loaded or not present in the build tree */ @@ -174,7 +173,7 @@ void CompileLinesGLTest::twoDimensions() { if(data.colors) arrayAppend(attributes, InPlaceInit, Trade::MeshAttribute::Color, vertices.slice(&Vertex::color)); - GL::Mesh mesh = compileLines(Trade::MeshData{MeshPrimitive::LineLoop, {}, vertexData, std::move(attributes)}); + GL::Mesh mesh = compileLines(generateLines(Trade::MeshData{MeshPrimitive::LineLoop, {}, vertexData, std::move(attributes)})); Shaders::LineGL2D shader{Shaders::LineGL2D::Configuration{} .setFlags(data.colors ? Shaders::LineGL2D::Flag::VertexColor : Shaders::LineGL2D::Flags{}) @@ -206,9 +205,9 @@ void CompileLinesGLTest::threeDimensions() { {-1.0f, +1.0f, -0.5f}, }; - GL::Mesh mesh = compileLines(Trade::MeshData{MeshPrimitive::LineLoop, {}, positions, { + GL::Mesh mesh = compileLines(generateLines(Trade::MeshData{MeshPrimitive::LineLoop, {}, positions, { Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::stridedArrayView(positions)} - }}); + }})); Shaders::LineGL3D{} .setViewportSize({32, 32}) @@ -268,7 +267,7 @@ void CompileLinesGLTest::linePrimitiveCompatibility() { /* Render the line mesh with the primitive set back to lines. The index buffer layout should be compatible with it, and produce the same result. */ - shader.draw(compileLines(lineMeshData).setPrimitive(MeshPrimitive::Lines)); + shader.draw(compileLines(generateLines(lineMeshData)).setPrimitive(MeshPrimitive::Lines)); MAGNUM_VERIFY_NO_GL_ERROR(); CORRADE_COMPARE_WITH( _framebuffer.read({{}, {32, 32}}, {PixelFormat::RGBA8Unorm}), @@ -298,10 +297,10 @@ void CompileLinesGLTest::conflictingAttributes() { }; auto vertices = Containers::stridedArrayView(vertexData); - Trade::MeshData lineMesh{MeshPrimitive::LineLoop, {}, vertexData, { + Trade::MeshData lineMesh = generateLines(Trade::MeshData{MeshPrimitive::LineLoop, {}, vertexData, { Trade::MeshAttributeData{Trade::MeshAttribute::Position, vertices.slice(&Vertex::position)}, Trade::MeshAttributeData{data.attribute, data.format, vertices.slice(&Vertex::extra)}, - }}; + }}); std::ostringstream out; GL::Mesh mesh{NoCreate}; @@ -325,48 +324,31 @@ void CompileLinesGLTest::conflictingAttributes() { } void CompileLinesGLTest::emptyMesh() { - GL::Mesh mesh = compileLines(Trade::MeshData{MeshPrimitive::LineLoop, {}, nullptr, { + GL::Mesh mesh = compileLines(generateLines(Trade::MeshData{MeshPrimitive::LineLoop, {}, nullptr, { Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector2, nullptr} - }}); + }})); CORRADE_COMPARE(mesh.primitive(), GL::MeshPrimitive::Triangles); CORRADE_VERIFY(mesh.isIndexed()); CORRADE_COMPARE(mesh.count(), 0); } -void CompileLinesGLTest::notLines() { +void CompileLinesGLTest::notGeneratedLineMesh() { CORRADE_SKIP_IF_NO_ASSERT(); Vector3 positions[3]{}; std::ostringstream out; Error redirectError{&out}; - compileLines(Trade::MeshData{MeshPrimitive::TriangleFan, {}, positions, { + compileLines(Trade::MeshData{MeshPrimitive::Lines, {}, positions, { Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::stridedArrayView(positions)} }}); - CORRADE_COMPARE(out.str(), "Trade::MeshTools::compileLines(): expected a line primitive, got MeshPrimitive::TriangleFan\n"); -} - -void CompileLinesGLTest::noAttributes() { - CORRADE_SKIP_IF_NO_ASSERT(); - - std::ostringstream out; - Error redirectError{&out}; - compileLines(Trade::MeshData{MeshPrimitive::Lines, 12}); - CORRADE_COMPARE(out.str(), "Trade::MeshTools::compileLines(): the mesh has no positions\n"); -} - -void CompileLinesGLTest::noPositionAttribute() { - CORRADE_SKIP_IF_NO_ASSERT(); - - Vector3 colors[2]{}; - - std::ostringstream out; - Error redirectError{&out}; - compileLines(Trade::MeshData{MeshPrimitive::Lines, {}, colors, { - Trade::MeshAttributeData{Trade::MeshAttribute::Color, Containers::stridedArrayView(colors)} + compileLines(Trade::MeshData{MeshPrimitive::Triangles, {}, positions, { + Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::stridedArrayView(positions)} }}); - CORRADE_COMPARE(out.str(), "Trade::MeshTools::compileLines(): the mesh has no positions\n"); + CORRADE_COMPARE(out.str(), + "MeshTools::compileLines(): the mesh wasn't produced with generateLines()\n" + "MeshTools::compileLines(): the mesh wasn't produced with generateLines()\n"); } }}}} diff --git a/src/Magnum/MeshTools/Test/CompileLinesTest.cpp b/src/Magnum/MeshTools/Test/GenerateLinesTest.cpp similarity index 77% rename from src/Magnum/MeshTools/Test/CompileLinesTest.cpp rename to src/Magnum/MeshTools/Test/GenerateLinesTest.cpp index a4bf5472a..1238ea681 100644 --- a/src/Magnum/MeshTools/Test/CompileLinesTest.cpp +++ b/src/Magnum/MeshTools/Test/GenerateLinesTest.cpp @@ -26,14 +26,17 @@ #include #include #include +#include +#include "Magnum/Math/Color.h" #include "Magnum/Math/PackingBatch.h" -#include "Magnum/MeshTools/Implementation/GenerateLines.h" +#include "Magnum/MeshTools/GenerateLines.h" +#include "Magnum/Shaders/Line.h" namespace Magnum { namespace MeshTools { namespace Test { namespace { -struct CompileLinesTest: TestSuite::Tester { - explicit CompileLinesTest(); +struct GenerateLinesTest: TestSuite::Tester { + explicit GenerateLinesTest(); template void oneLoop(); @@ -41,9 +44,10 @@ struct CompileLinesTest: TestSuite::Tester { void zeroVertices(); void twoVerticesStrip(); void twoVerticesLoop(); - /* Non-line primitives and absence of position attribute tested in - CompileLinesGLTest, to verify it's not accessed earlier than the - assertion */ + + void notLines(); + void noAttributes(); + void noPositionAttribute(); }; using namespace Math::Literals; @@ -103,20 +107,24 @@ const struct { /** @todo closed (indexed) strip, once arbitrary index buffer looping is supported */ }; -CompileLinesTest::CompileLinesTest() { - addInstancedTests({ - &CompileLinesTest::oneLoop, - &CompileLinesTest::oneLoop, - &CompileLinesTest::oneLoop}, +GenerateLinesTest::GenerateLinesTest() { + addInstancedTests({ + &GenerateLinesTest::oneLoop, + &GenerateLinesTest::oneLoop, + &GenerateLinesTest::oneLoop}, Containers::arraySize(OneLoopData)); - addTests({&CompileLinesTest::extraAttributes, - &CompileLinesTest::zeroVertices, - &CompileLinesTest::twoVerticesStrip, - &CompileLinesTest::twoVerticesLoop}); + addTests({&GenerateLinesTest::extraAttributes, + &GenerateLinesTest::zeroVertices, + &GenerateLinesTest::twoVerticesStrip, + &GenerateLinesTest::twoVerticesLoop, + + &GenerateLinesTest::notLines, + &GenerateLinesTest::noAttributes, + &GenerateLinesTest::noPositionAttribute}); } -template void CompileLinesTest::oneLoop() { +template void GenerateLinesTest::oneLoop() { auto&& data = OneLoopData[testCaseInstanceId()]; setTestCaseTemplateName(Math::TypeTraits::name()); setTestCaseDescription(data.name); @@ -130,7 +138,7 @@ template void CompileLinesTest::oneLoop() { Trade::MeshAttributeData{Trade::MeshAttribute::Position, stridedArrayView(data.positions)} }}; - Trade::MeshData mesh = Implementation::generateLines(lineMesh); + Trade::MeshData mesh = generateLines(lineMesh); CORRADE_COMPARE(mesh.primitive(), MeshPrimitive::Triangles); CORRADE_COMPARE(mesh.attributeCount(), 4); @@ -179,14 +187,14 @@ template void CompileLinesTest::oneLoop() { {-1.0f, -1.0f}, {-1.0f, -1.0f} }), TestSuite::Compare::Container); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributePreviousPosition)); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributeNextPosition)); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributeAnnotation)); - CORRADE_COMPARE(mesh.attributeFormat(Implementation::MeshAttributePreviousPosition), VertexFormat::Vector2); - CORRADE_COMPARE(mesh.attributeFormat(Implementation::MeshAttributeNextPosition), VertexFormat::Vector2); - CORRADE_COMPARE(mesh.attributeFormat(Implementation::MeshAttributeAnnotation), VertexFormat::UnsignedInt); + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributePreviousPosition)); + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributeNextPosition)); + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributeAnnotation)); + CORRADE_COMPARE(mesh.attributeFormat(Implementation::LineMeshAttributePreviousPosition), VertexFormat::Vector2); + CORRADE_COMPARE(mesh.attributeFormat(Implementation::LineMeshAttributeNextPosition), VertexFormat::Vector2); + CORRADE_COMPARE(mesh.attributeFormat(Implementation::LineMeshAttributeAnnotation), VertexFormat::UnsignedInt); if(data.expectedJoins && data.expectedJoinsFirstLast) { - CORRADE_COMPARE_AS(mesh.attribute(Implementation::MeshAttributePreviousPosition), Containers::arrayView({ + CORRADE_COMPARE_AS(mesh.attribute(Implementation::LineMeshAttributePreviousPosition), Containers::arrayView({ positions[12], positions[12], positions[0], positions[0], positions[0], positions[0], @@ -196,7 +204,7 @@ template void CompileLinesTest::oneLoop() { positions[8], positions[8], positions[12], positions[12], }), TestSuite::Compare::Container); - CORRADE_COMPARE_AS(mesh.attribute(Implementation::MeshAttributeNextPosition), Containers::arrayView({ + CORRADE_COMPARE_AS(mesh.attribute(Implementation::LineMeshAttributeNextPosition), Containers::arrayView({ positions[2], positions[2], positions[6], positions[6], positions[6], positions[6], @@ -206,7 +214,7 @@ template void CompileLinesTest::oneLoop() { positions[14], positions[14], positions[2], positions[2], }), TestSuite::Compare::Container); - CORRADE_COMPARE_AS((Containers::arrayCast<1, const Shaders::LineVertexAnnotations>(mesh.attribute(Implementation::MeshAttributeAnnotation))), Containers::arrayView({ + CORRADE_COMPARE_AS((Containers::arrayCast<1, const Shaders::LineVertexAnnotations>(mesh.attribute(Implementation::LineMeshAttributeAnnotation))), Containers::arrayView({ Shaders::LineVertexAnnotation::Up| Shaders::LineVertexAnnotation::Begin| Shaders::LineVertexAnnotation::Join, @@ -241,7 +249,7 @@ template void CompileLinesTest::oneLoop() { Shaders::LineVertexAnnotation::Join, }), TestSuite::Compare::Container); } else if(data.expectedJoins) { - CORRADE_COMPARE_AS(mesh.attribute(Implementation::MeshAttributePreviousPosition), Containers::arrayView({ + CORRADE_COMPARE_AS(mesh.attribute(Implementation::LineMeshAttributePreviousPosition), Containers::arrayView({ {}, {}, positions[0], positions[0], positions[0], positions[0], @@ -251,7 +259,7 @@ template void CompileLinesTest::oneLoop() { positions[8], positions[8], positions[12], positions[12], }), TestSuite::Compare::Container); - CORRADE_COMPARE_AS(mesh.attribute(Implementation::MeshAttributeNextPosition), Containers::arrayView({ + CORRADE_COMPARE_AS(mesh.attribute(Implementation::LineMeshAttributeNextPosition), Containers::arrayView({ positions[2], positions[2], positions[6], positions[6], positions[6], positions[6], @@ -261,7 +269,7 @@ template void CompileLinesTest::oneLoop() { positions[14], positions[14], {}, {} }), TestSuite::Compare::Container); - CORRADE_COMPARE_AS((Containers::arrayCast<1, const Shaders::LineVertexAnnotations>(mesh.attribute(Implementation::MeshAttributeAnnotation))), Containers::arrayView({ + CORRADE_COMPARE_AS((Containers::arrayCast<1, const Shaders::LineVertexAnnotations>(mesh.attribute(Implementation::LineMeshAttributeAnnotation))), Containers::arrayView({ Shaders::LineVertexAnnotation::Up| Shaders::LineVertexAnnotation::Begin, Shaders::LineVertexAnnotation::Begin, @@ -293,7 +301,7 @@ template void CompileLinesTest::oneLoop() { {}, }), TestSuite::Compare::Container); } else { - CORRADE_COMPARE_AS(mesh.attribute(Implementation::MeshAttributePreviousPosition), Containers::arrayView({ + CORRADE_COMPARE_AS(mesh.attribute(Implementation::LineMeshAttributePreviousPosition), Containers::arrayView({ {}, {}, positions[0], positions[0], {}, {}, @@ -303,7 +311,7 @@ template void CompileLinesTest::oneLoop() { {}, {}, positions[12], positions[12], }), TestSuite::Compare::Container); - CORRADE_COMPARE_AS(mesh.attribute(Implementation::MeshAttributeNextPosition), Containers::arrayView({ + CORRADE_COMPARE_AS(mesh.attribute(Implementation::LineMeshAttributeNextPosition), Containers::arrayView({ positions[2], positions[2], {}, {}, positions[6], positions[6], @@ -313,7 +321,7 @@ template void CompileLinesTest::oneLoop() { positions[14], positions[14], {}, {}, }), TestSuite::Compare::Container); - CORRADE_COMPARE_AS((Containers::arrayCast<1, const Shaders::LineVertexAnnotations>(mesh.attribute(Implementation::MeshAttributeAnnotation))), Containers::arrayView({ + CORRADE_COMPARE_AS((Containers::arrayCast<1, const Shaders::LineVertexAnnotations>(mesh.attribute(Implementation::LineMeshAttributeAnnotation))), Containers::arrayView({ Shaders::LineVertexAnnotation::Up| Shaders::LineVertexAnnotation::Begin, Shaders::LineVertexAnnotation::Begin, @@ -338,7 +346,7 @@ template void CompileLinesTest::oneLoop() { } } -void CompileLinesTest::extraAttributes() { +void GenerateLinesTest::extraAttributes() { const struct Vertex { Color3ub color; Vector3b position; @@ -360,7 +368,7 @@ void CompileLinesTest::extraAttributes() { Trade::MeshAttributeData{Trade::MeshAttribute::ObjectId, vertices.slice(&Vertex::objectId)}, }}; - Trade::MeshData mesh = Implementation::generateLines(lineMesh); + Trade::MeshData mesh = generateLines(lineMesh); CORRADE_COMPARE(mesh.primitive(), MeshPrimitive::Triangles); CORRADE_COMPARE(mesh.attributeCount(), 6); @@ -417,14 +425,14 @@ void CompileLinesTest::extraAttributes() { 156, 156, }), TestSuite::Compare::Container); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributePreviousPosition)); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributeNextPosition)); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributeAnnotation)); - CORRADE_COMPARE(mesh.attributeFormat(Implementation::MeshAttributePreviousPosition), VertexFormat::Vector3b); - CORRADE_COMPARE(mesh.attributeFormat(Implementation::MeshAttributeNextPosition), VertexFormat::Vector3b); - CORRADE_COMPARE(mesh.attributeFormat(Implementation::MeshAttributeAnnotation), VertexFormat::UnsignedInt); + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributePreviousPosition)); + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributeNextPosition)); + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributeAnnotation)); + CORRADE_COMPARE(mesh.attributeFormat(Implementation::LineMeshAttributePreviousPosition), VertexFormat::Vector3b); + CORRADE_COMPARE(mesh.attributeFormat(Implementation::LineMeshAttributeNextPosition), VertexFormat::Vector3b); + CORRADE_COMPARE(mesh.attributeFormat(Implementation::LineMeshAttributeAnnotation), VertexFormat::UnsignedInt); - CORRADE_COMPARE_AS(mesh.attribute(Implementation::MeshAttributePreviousPosition), Containers::arrayView({ + CORRADE_COMPARE_AS(mesh.attribute(Implementation::LineMeshAttributePreviousPosition), Containers::arrayView({ positions[12], positions[12], positions[0], positions[0], positions[0], positions[0], @@ -434,7 +442,7 @@ void CompileLinesTest::extraAttributes() { positions[8], positions[8], positions[12], positions[12], }), TestSuite::Compare::Container); - CORRADE_COMPARE_AS(mesh.attribute(Implementation::MeshAttributeNextPosition), Containers::arrayView({ + CORRADE_COMPARE_AS(mesh.attribute(Implementation::LineMeshAttributeNextPosition), Containers::arrayView({ positions[2], positions[2], positions[6], positions[6], positions[6], positions[6], @@ -444,7 +452,7 @@ void CompileLinesTest::extraAttributes() { positions[14], positions[14], positions[2], positions[2], }), TestSuite::Compare::Container); - CORRADE_COMPARE_AS((Containers::arrayCast<1, const Shaders::LineVertexAnnotations>(mesh.attribute(Implementation::MeshAttributeAnnotation))), Containers::arrayView({ + CORRADE_COMPARE_AS((Containers::arrayCast<1, const Shaders::LineVertexAnnotations>(mesh.attribute(Implementation::LineMeshAttributeAnnotation))), Containers::arrayView({ Shaders::LineVertexAnnotation::Up| Shaders::LineVertexAnnotation::Begin| Shaders::LineVertexAnnotation::Join, @@ -480,23 +488,23 @@ void CompileLinesTest::extraAttributes() { }), TestSuite::Compare::Container); } -void CompileLinesTest::zeroVertices() { +void GenerateLinesTest::zeroVertices() { Trade::MeshData lineMesh{MeshPrimitive::LineLoop, nullptr, { Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector3usNormalized, nullptr} }}; - Trade::MeshData mesh = Implementation::generateLines(lineMesh); + Trade::MeshData mesh = generateLines(lineMesh); CORRADE_COMPARE(mesh.primitive(), MeshPrimitive::Triangles); CORRADE_COMPARE(mesh.attributeCount(), 4); CORRADE_COMPARE(mesh.vertexCount(), 0); CORRADE_VERIFY(mesh.hasAttribute(Trade::MeshAttribute::Position)); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributePreviousPosition)); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributePreviousPosition)); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributeAnnotation)); + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributePreviousPosition)); + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributePreviousPosition)); + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributeAnnotation)); } -void CompileLinesTest::twoVerticesStrip() { +void GenerateLinesTest::twoVerticesStrip() { Vector2 positionData[]{ {-1.0f, 0.0f}, {+1.0f, 0.0f} @@ -506,7 +514,7 @@ void CompileLinesTest::twoVerticesStrip() { Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::stridedArrayView(positionData)} }}; - Trade::MeshData mesh = Implementation::generateLines(lineMesh); + Trade::MeshData mesh = generateLines(lineMesh); CORRADE_COMPARE(mesh.primitive(), MeshPrimitive::Triangles); CORRADE_COMPARE(mesh.attributeCount(), 4); @@ -524,23 +532,23 @@ void CompileLinesTest::twoVerticesStrip() { {+1.0f, 0.0f}, {+1.0f, 0.0f}, }), TestSuite::Compare::Container); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributePreviousPosition)); - CORRADE_COMPARE(mesh.attributeFormat(Implementation::MeshAttributePreviousPosition), VertexFormat::Vector2); - CORRADE_COMPARE_AS(mesh.attribute(Implementation::MeshAttributePreviousPosition), Containers::arrayView({ + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributePreviousPosition)); + CORRADE_COMPARE(mesh.attributeFormat(Implementation::LineMeshAttributePreviousPosition), VertexFormat::Vector2); + CORRADE_COMPARE_AS(mesh.attribute(Implementation::LineMeshAttributePreviousPosition), Containers::arrayView({ {}, {}, positions[0], positions[0], }), TestSuite::Compare::Container); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributePreviousPosition)); - CORRADE_COMPARE(mesh.attributeFormat(Implementation::MeshAttributeNextPosition), VertexFormat::Vector2); - CORRADE_COMPARE_AS(mesh.attribute(Implementation::MeshAttributeNextPosition), Containers::arrayView({ + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributePreviousPosition)); + CORRADE_COMPARE(mesh.attributeFormat(Implementation::LineMeshAttributeNextPosition), VertexFormat::Vector2); + CORRADE_COMPARE_AS(mesh.attribute(Implementation::LineMeshAttributeNextPosition), Containers::arrayView({ positions[2], positions[2], {}, {}, }), TestSuite::Compare::Container); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributeAnnotation)); - CORRADE_COMPARE(mesh.attributeFormat(Implementation::MeshAttributeAnnotation), VertexFormat::UnsignedInt); - CORRADE_COMPARE_AS((Containers::arrayCast<1, const Shaders::LineVertexAnnotations>(mesh.attribute(Implementation::MeshAttributeAnnotation))), Containers::arrayView({ + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributeAnnotation)); + CORRADE_COMPARE(mesh.attributeFormat(Implementation::LineMeshAttributeAnnotation), VertexFormat::UnsignedInt); + CORRADE_COMPARE_AS((Containers::arrayCast<1, const Shaders::LineVertexAnnotations>(mesh.attribute(Implementation::LineMeshAttributeAnnotation))), Containers::arrayView({ Shaders::LineVertexAnnotation::Up| Shaders::LineVertexAnnotation::Begin, Shaders::LineVertexAnnotation::Begin, @@ -549,7 +557,7 @@ void CompileLinesTest::twoVerticesStrip() { }), TestSuite::Compare::Container); } -void CompileLinesTest::twoVerticesLoop() { +void GenerateLinesTest::twoVerticesLoop() { Vector2 positionData[]{ {-1.0f, 0.0f}, {+1.0f, 0.0f} @@ -559,7 +567,7 @@ void CompileLinesTest::twoVerticesLoop() { Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::stridedArrayView(positionData)} }}; - Trade::MeshData mesh = Implementation::generateLines(lineMesh); + Trade::MeshData mesh = generateLines(lineMesh); CORRADE_COMPARE(mesh.primitive(), MeshPrimitive::Triangles); CORRADE_COMPARE(mesh.attributeCount(), 4); @@ -582,27 +590,27 @@ void CompileLinesTest::twoVerticesLoop() { {-1.0f, 0.0f}, {-1.0f, 0.0f}, }), TestSuite::Compare::Container); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributePreviousPosition)); - CORRADE_COMPARE(mesh.attributeFormat(Implementation::MeshAttributePreviousPosition), VertexFormat::Vector2); - CORRADE_COMPARE_AS(mesh.attribute(Implementation::MeshAttributePreviousPosition), Containers::arrayView({ + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributePreviousPosition)); + CORRADE_COMPARE(mesh.attributeFormat(Implementation::LineMeshAttributePreviousPosition), VertexFormat::Vector2); + CORRADE_COMPARE_AS(mesh.attribute(Implementation::LineMeshAttributePreviousPosition), Containers::arrayView({ positions[4], positions[4], positions[0], positions[0], positions[0], positions[0], positions[4], positions[4], }), TestSuite::Compare::Container); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributePreviousPosition)); - CORRADE_COMPARE(mesh.attributeFormat(Implementation::MeshAttributeNextPosition), VertexFormat::Vector2); - CORRADE_COMPARE_AS(mesh.attribute(Implementation::MeshAttributeNextPosition), Containers::arrayView({ + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributePreviousPosition)); + CORRADE_COMPARE(mesh.attributeFormat(Implementation::LineMeshAttributeNextPosition), VertexFormat::Vector2); + CORRADE_COMPARE_AS(mesh.attribute(Implementation::LineMeshAttributeNextPosition), Containers::arrayView({ positions[2], positions[2], positions[6], positions[6], positions[6], positions[6], positions[2], positions[2], }), TestSuite::Compare::Container); - CORRADE_VERIFY(mesh.hasAttribute(Implementation::MeshAttributeAnnotation)); - CORRADE_COMPARE(mesh.attributeFormat(Implementation::MeshAttributeAnnotation), VertexFormat::UnsignedInt); - CORRADE_COMPARE_AS((Containers::arrayCast<1, const Shaders::LineVertexAnnotations>(mesh.attribute(Implementation::MeshAttributeAnnotation))), Containers::arrayView({ + CORRADE_VERIFY(mesh.hasAttribute(Implementation::LineMeshAttributeAnnotation)); + CORRADE_COMPARE(mesh.attributeFormat(Implementation::LineMeshAttributeAnnotation), VertexFormat::UnsignedInt); + CORRADE_COMPARE_AS((Containers::arrayCast<1, const Shaders::LineVertexAnnotations>(mesh.attribute(Implementation::LineMeshAttributeAnnotation))), Containers::arrayView({ Shaders::LineVertexAnnotation::Up| Shaders::LineVertexAnnotation::Begin| Shaders::LineVertexAnnotation::Join, @@ -622,6 +630,41 @@ void CompileLinesTest::twoVerticesLoop() { }), TestSuite::Compare::Container); } +void GenerateLinesTest::notLines() { + CORRADE_SKIP_IF_NO_ASSERT(); + + Vector3 positions[3]{}; + + std::ostringstream out; + Error redirectError{&out}; + generateLines(Trade::MeshData{MeshPrimitive::TriangleFan, {}, positions, { + Trade::MeshAttributeData{Trade::MeshAttribute::Position, Containers::stridedArrayView(positions)} + }}); + CORRADE_COMPARE(out.str(), "Trade::MeshTools::generateLines(): expected a line primitive, got MeshPrimitive::TriangleFan\n"); +} + +void GenerateLinesTest::noAttributes() { + CORRADE_SKIP_IF_NO_ASSERT(); + + std::ostringstream out; + Error redirectError{&out}; + generateLines(Trade::MeshData{MeshPrimitive::Lines, 12}); + CORRADE_COMPARE(out.str(), "Trade::MeshTools::generateLines(): the mesh has no positions\n"); +} + +void GenerateLinesTest::noPositionAttribute() { + CORRADE_SKIP_IF_NO_ASSERT(); + + Vector3 colors[2]{}; + + std::ostringstream out; + Error redirectError{&out}; + generateLines(Trade::MeshData{MeshPrimitive::Lines, {}, colors, { + Trade::MeshAttributeData{Trade::MeshAttribute::Color, Containers::stridedArrayView(colors)} + }}); + CORRADE_COMPARE(out.str(), "Trade::MeshTools::generateLines(): the mesh has no positions\n"); +} + }}}} -CORRADE_TEST_MAIN(Magnum::MeshTools::Test::CompileLinesTest) +CORRADE_TEST_MAIN(Magnum::MeshTools::Test::GenerateLinesTest) diff --git a/src/Magnum/Shaders/LineGL.h b/src/Magnum/Shaders/LineGL.h index 622738e39..befa857fa 100644 --- a/src/Magnum/Shaders/LineGL.h +++ b/src/Magnum/Shaders/LineGL.h @@ -88,8 +88,9 @@ describing point wíth their surroundings, and @ref Annotation with point-specific annotation such as whether given point is a line cap or a join with neighboring segment. The data layout is described in detail in @ref Shaders-LineGL-mesh-representation below, however in practice it's easiest -to compile an existing line @ref Trade::MeshData to the desired form using -@ref MeshTools::compileLines(): +to convert an existing line @ref Trade::MeshData to a form accepted by this +shader with @ref MeshTools::generateLines() and then compile it to a +@ref GL::Mesh with @ref MeshTools::compileLines(): @snippet MagnumShaders-gl.cpp LineGL-usage