diff --git a/src/Magnum/MeshTools/Compile.cpp b/src/Magnum/MeshTools/Compile.cpp index 3ef943f76..7905e6730 100644 --- a/src/Magnum/MeshTools/Compile.cpp +++ b/src/Magnum/MeshTools/Compile.cpp @@ -52,7 +52,11 @@ namespace Magnum { namespace MeshTools { -GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer&& indices, GL::Buffer&& vertices) { +namespace { + +GL::Mesh compileInternal(const Trade::MeshData& meshData, GL::Buffer&& indices, GL::Buffer&& vertices, const CompileFlags flags) { + /* Only this one flag is allowed at this point */ + CORRADE_INTERNAL_ASSERT(!(flags & ~CompileFlag::NoWarnOnCustomAttributes)); CORRADE_ASSERT((!meshData.isIndexed() || indices.id()) && vertices.id(), "MeshTools::compile(): invalid external buffer(s)", GL::Mesh{}); @@ -70,7 +74,8 @@ GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer&& indices, GL::Buff single 32-bit value :( */ const VertexFormat format = meshData.attributeFormat(i); if(isVertexFormatImplementationSpecific(format)) { - Warning{} << "MeshTools::compile(): ignoring attribute" << meshData.attributeName(i) << "with an implementation-specific format" << reinterpret_cast(vertexFormatUnwrap(format)); + if(!(flags & CompileFlag::NoWarnOnCustomAttributes)) + Warning{} << "MeshTools::compile(): ignoring attribute" << meshData.attributeName(i) << "with an implementation-specific format" << reinterpret_cast(vertexFormatUnwrap(format)); continue; } @@ -101,7 +106,8 @@ GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer&& indices, GL::Buff } if(!attribute) { - Warning{} << "MeshTools::compile(): ignoring unknown attribute" << meshData.attributeName(i); + if(!(flags & CompileFlag::NoWarnOnCustomAttributes)) + Warning{} << "MeshTools::compile(): ignoring unknown attribute" << meshData.attributeName(i); continue; } @@ -122,7 +128,7 @@ GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer&& indices, GL::Buff return mesh; } -GL::Mesh compile(const Trade::MeshData& meshData) { +GL::Mesh compileInternal(const Trade::MeshData& meshData, const CompileFlags flags) { GL::Buffer indices{NoCreate}; if(meshData.isIndexed()) { indices = GL::Buffer{GL::Buffer::TargetHint::ElementArray}; @@ -132,19 +138,29 @@ GL::Mesh compile(const Trade::MeshData& meshData) { GL::Buffer vertices{GL::Buffer::TargetHint::Array}; vertices.setData(meshData.vertexData()); - return compile(meshData, std::move(indices), std::move(vertices)); + return compileInternal(meshData, std::move(indices), std::move(vertices), flags); +} + +} + +GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer&& indices, GL::Buffer&& vertices) { + return compileInternal(meshData, std::move(indices), std::move(vertices), {}); } GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer& indices, GL::Buffer& vertices) { - return compile(meshData, GL::Buffer::wrap(indices.id(), GL::Buffer::TargetHint::ElementArray), GL::Buffer::wrap(vertices.id(), GL::Buffer::TargetHint::Array)); + return compileInternal(meshData, GL::Buffer::wrap(indices.id(), GL::Buffer::TargetHint::ElementArray), GL::Buffer::wrap(vertices.id(), GL::Buffer::TargetHint::Array), CompileFlag::NoWarnOnCustomAttributes); } GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer& indices, GL::Buffer&& vertices) { - return compile(meshData, GL::Buffer::wrap(indices.id(), GL::Buffer::TargetHint::ElementArray), std::move(vertices)); + return compileInternal(meshData, GL::Buffer::wrap(indices.id(), GL::Buffer::TargetHint::ElementArray), std::move(vertices), CompileFlag::NoWarnOnCustomAttributes); } GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer&& indices, GL::Buffer& vertices) { - return compile(meshData, std::move(indices), GL::Buffer::wrap(vertices.id(), GL::Buffer::TargetHint::Array)); + return compileInternal(meshData, std::move(indices), GL::Buffer::wrap(vertices.id(), GL::Buffer::TargetHint::Array), CompileFlag::NoWarnOnCustomAttributes); +} + +GL::Mesh compile(const Trade::MeshData& meshData) { + return compileInternal(meshData, {}); } GL::Mesh compile(const Trade::MeshData& meshData, CompileFlags flags) { @@ -194,8 +210,8 @@ GL::Mesh compile(const Trade::MeshData& meshData, CompileFlags flags) { } flags &= ~(CompileFlag::GenerateFlatNormals|CompileFlag::GenerateSmoothNormals); - CORRADE_INTERNAL_ASSERT(!flags); - return compile(meshData); + CORRADE_INTERNAL_ASSERT(!(flags & ~CompileFlag::NoWarnOnCustomAttributes)); + return compileInternal(meshData, flags); } #ifdef MAGNUM_BUILD_DEPRECATED diff --git a/src/Magnum/MeshTools/Compile.h b/src/Magnum/MeshTools/Compile.h index 335349586..8392c7927 100644 --- a/src/Magnum/MeshTools/Compile.h +++ b/src/Magnum/MeshTools/Compile.h @@ -72,7 +72,18 @@ enum class CompileFlag: UnsignedByte { * is not a triangle mesh or doesn't have 3D positions, this flag does * nothing. If the mesh already has its own normals, these get replaced. */ - GenerateSmoothNormals = 1 << 1 + GenerateSmoothNormals = 1 << 1, + + /** + * By default, @ref compile() warns when it encounters custom attributes + * and attributes with implementation-specific format, as those get ignored + * by it. If you're binding those manually with + * @ref compile(const Trade::MeshData&, GL::Buffer&, GL::Buffer&) or + * handling them in some other way on the application side already, use + * this flag to suppress the warning messages. + * @m_since_latest + */ + NoWarnOnCustomAttributes = 1 << 2 }; /** @@ -105,7 +116,8 @@ possibly also an index buffer, if the mesh is indexed. their type. - Custom attributes and known attributes of implementation-specific types are ignored with a warning. See the @ref compile(const Trade::MeshData&, GL::Buffer&, GL::Buffer&) - for an example showing how to bind them manually. + for an example showing how to bind them manually, and + @ref CompileFlag::NoWarnOnCustomAttributes to suppress the warning. If normal generation is not requested, @ref Trade::MeshData::indexData() and @ref Trade::MeshData::vertexData() are uploaded as-is without any further @@ -158,6 +170,11 @@ by the mesh or not: If @p meshData is not indexed, the @p indices parameter is ignored --- in that case you can pass a @ref NoCreate "NoCreate"-d instance to avoid allocating an unnecessary OpenGL buffer object. + +Compared to @ref compile(const Trade::MeshData&, CompileFlags), this function +implicitly enables the @ref CompileFlag::NoWarnOnCustomAttributes flag, +assuming that custom attributes and attributes with implementation-specific +formats are explicitly handled on the application side. */ MAGNUM_MESHTOOLS_EXPORT GL::Mesh compile(const Trade::MeshData& meshData, GL::Buffer& indices, GL::Buffer& vertices); diff --git a/src/Magnum/MeshTools/Test/CompileGLTest.cpp b/src/Magnum/MeshTools/Test/CompileGLTest.cpp index 7debc5f29..b68344f70 100644 --- a/src/Magnum/MeshTools/Test/CompileGLTest.cpp +++ b/src/Magnum/MeshTools/Test/CompileGLTest.cpp @@ -93,7 +93,7 @@ struct CompileGLTest: GL::OpenGLTester { void packedAttributes(); - void unknownAttribute(); + void customAttribute(); void implementationSpecificAttributeFormat(); void generateNormalsNoPosition(); void generateNormals2DPosition(); @@ -170,6 +170,14 @@ constexpr struct { {"move both", true, true, true} }; +constexpr struct { + const char* name; + CompileFlags flags; +} CustomAttributeWarningData[] { + {"", {}}, + {"no warning", CompileFlag::NoWarnOnCustomAttributes} +}; + using namespace Math::Literals; constexpr Color4ub ImageData[] { @@ -203,11 +211,13 @@ CompileGLTest::CompileGLTest() { CORRADE_IGNORE_DEPRECATED_POP #endif - addTests({&CompileGLTest::packedAttributes, + addTests({&CompileGLTest::packedAttributes}); + + addInstancedTests({&CompileGLTest::customAttribute, + &CompileGLTest::implementationSpecificAttributeFormat}, + Containers::arraySize(CustomAttributeWarningData)); - &CompileGLTest::unknownAttribute, - &CompileGLTest::implementationSpecificAttributeFormat, - &CompileGLTest::generateNormalsNoPosition, + addTests({&CompileGLTest::generateNormalsNoPosition, &CompileGLTest::generateNormals2DPosition, &CompileGLTest::generateNormalsNoFloats}); @@ -714,27 +724,39 @@ void CompileGLTest::packedAttributes() { (DebugTools::CompareImageToFile{_manager, 1.0f, 0.0948f})); } -void CompileGLTest::unknownAttribute() { +void CompileGLTest::customAttribute() { + auto&& instanceData = CustomAttributeWarningData[testCaseInstanceId()]; + setTestCaseDescription(instanceData.name); + Trade::MeshData data{MeshPrimitive::Triangles, nullptr, {Trade::MeshAttributeData{Trade::meshAttributeCustom(115), VertexFormat::Short, nullptr}}}; std::ostringstream out; Warning redirectError{&out}; - MeshTools::compile(data); - CORRADE_COMPARE(out.str(), + if(instanceData.flags) + MeshTools::compile(data, instanceData.flags); + else + MeshTools::compile(data); + CORRADE_COMPARE(out.str(), instanceData.flags ? "" : "MeshTools::compile(): ignoring unknown attribute Trade::MeshAttribute::Custom(115)\n"); } void CompileGLTest::implementationSpecificAttributeFormat() { + auto&& instanceData = CustomAttributeWarningData[testCaseInstanceId()]; + setTestCaseDescription(instanceData.name); + Trade::MeshData data{MeshPrimitive::Triangles, nullptr, {Trade::MeshAttributeData{Trade::MeshAttribute::Position, vertexFormatWrap(0xdead), nullptr}}}; std::ostringstream out; Warning redirectError{&out}; - MeshTools::compile(data); - CORRADE_COMPARE(out.str(), + if(instanceData.flags) + MeshTools::compile(data, instanceData.flags); + else + MeshTools::compile(data); + CORRADE_COMPARE(out.str(), instanceData.flags ? "" : "MeshTools::compile(): ignoring attribute Trade::MeshAttribute::Position with an implementation-specific format 0xdead\n"); }