From b3fa6e538aa341a273b95c435d0bfbb2580242f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 19 Apr 2018 21:57:13 +0200 Subject: [PATCH] Split the OpenGL layer out, pt 11: generic MeshPrimitive and MeshIndexType. Similarly to pixel formats, there is now generic Magnum::MeshPrimitive and Magnum::MeshIndexType, which is convertible to GL::MeshPrimitive and GL::MeshIndexType using GL::meshPrimitive() and GL::meshIndexType(). In addition, the following is done: * The original GL::Mesh::IndexType is now GL::MeshIndexType, original name is now just a typedef. * GL::Mesh::indexSize() is deprecated in favor of Magnum::meshIndexTypeSize() and GL::Mesh::indexTypeSize(). * New GL::Mesh::indexType() and GL::MeshView::mesh() getters (not sure why they were omitted) * GL::Mesh::indexType(), GL::Mesh::indexTypeSize(), GL::MeshView::setIndexRange() now expect that the mesh is indexed (useful property in my opinion, also avoids getting random results). * The extra MeshPrimitive::LinesAdjacency etc. are still present for backwards compatibility, but marked as deprecated. Use GL::MeshPrimitive values instead. --- doc/changelog.dox | 39 +++- src/Magnum/CMakeLists.txt | 3 +- src/Magnum/GL/CMakeLists.txt | 2 +- src/Magnum/GL/GL.h | 1 + src/Magnum/GL/Mesh.cpp | 238 +++++++++----------- src/Magnum/GL/Mesh.h | 186 ++++++++------- src/Magnum/GL/MeshView.cpp | 3 +- src/Magnum/GL/MeshView.h | 12 +- src/Magnum/GL/Test/CMakeLists.txt | 2 +- src/Magnum/GL/Test/MeshGLTest.cpp | 71 ++++-- src/Magnum/GL/Test/MeshTest.cpp | 106 ++++++--- src/Magnum/Magnum.h | 5 +- src/Magnum/Mesh.cpp | 165 ++++++++++++++ src/Magnum/Mesh.h | 206 ++++++++++++++++- src/Magnum/Test/CMakeLists.txt | 2 + src/Magnum/Test/MeshTest.cpp | 98 ++++++++ src/MagnumPlugins/ObjImporter/Test/Test.cpp | 2 +- 17 files changed, 867 insertions(+), 274 deletions(-) create mode 100644 src/Magnum/Mesh.cpp create mode 100644 src/Magnum/Test/MeshTest.cpp diff --git a/doc/changelog.dox b/doc/changelog.dox index 32f00832f..0beee5aa9 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -55,6 +55,9 @@ See also: @ref isCompressedPixelFormatImplementationSpecific() utilities now used by @ref Image / @ref CompressedImage and @ref ImageView / @ref CompressedImageView instead of the GL-specific formats +- New @ref MeshPrimitive and @ref MeshIndexType enums containing generic + API-independent mesh primitive types and index types, together with + @ref meshIndexTypeSize() utilities @subsubsection changelog-latest-new-math Math library @@ -68,7 +71,13 @@ See also: @ref GL::hasCompressedPixelFormat(), @ref compressedPixelFormat() utilities for converting generic @ref PixelFormat / @ref CompressedPixelFormat to GL-specific @ref GL::PixelFormat, @ref GL::PixelType and - @ref GL::CompressedPixelFormat values + @ref GL::CompressedPixelFormat values. The @ref BufferImage and + @ref CompressedBufferImage classes now have overloads accepting both types. +- New @ref GL::meshPrimitive() and @ref GL::meshIndexType() utilities for + converting generic @ref MeshPrimitive and @ref MeshIndexType to GL-specific + @ref GL::MeshPrimitive and @ref GL::MeshIndexType values. The @ref Mesh + class now has overloads accepting both types. +- New @ref Mesh::indexType() and @ref MeshView::mesh() getters - Initial support for OpenGL ES 3.2 and OpenGL 4.6 - New OpenGL extension support: - @extension{ARB,texture_filter_anisotropic} @@ -106,6 +115,12 @@ See also: a compatibility code path is implemented, the @ref GL library expects that all parameters are at their defaults. +@subsubsection changelog-latest-changes-gl GL library + +- The @ref GL::Mesh::indexTypeSize() and @ref GL::MeshView::setIndexRange() + now expect that the mesh is indexed (instead of silently not doing + anything) + @subsection changelog-latest-buildsystem Build system - All plugin interfaces now implement @@ -166,6 +181,14 @@ See also: - `setData()` functions in the @ref Image and @ref CompressedImage classes are deprecated because they don't offer anything extra over simple move-assignment of a new instance. +- The @ref MeshPrimitive enum now contains generic API-independent values. + The additional GL-specific types are present there, but marked as + deprecated. Use the GL-specific @ref GL::MeshPrimitive enum instead. +- THe `GL::Mesh::IndexType` enum and the `Mesh::indexSize(MeshIndexType)` + function is deprecated, use @ref Magnum::MeshIndexType / + @ref GL::MeshIndexType and @ref meshIndexTypeSize() instead +- The `GL::Mesh::indexSize()` function is deprecated, use + @ref GL::Mesh::indexTypeSize() instead - Class @cpp Primitives::Capsule2D @ce and @cpp Primitives::Capsule3D @ce is deprecated, use @ref Primitives::capsule2DWireframe(), @ref Primitives::capsule3DSolid() and @ref Primitives::capsule3DWireframe() @@ -249,6 +272,20 @@ See also: @ref Magnum::CompressedPixelFormat may break. In all other cases, @ref CompressedImage::format() "CompressedImage*::format()" returns @ref Magnum::CompressedPixelFormat. +- `MeshPrimitive` has been moved verbatim to @ref GL::MeshPrimitive and + there's a new @ref Magnum::MeshPrimitive enum for generic primitive types. + It contains (deprecated) additional @ref GL::MeshPrimitive values for + covering most of backwards compatibility, but code that relies on these + two types being the same (or have values that match GL enums) may break. + In particular, @ref GL::Mesh::primitive() now returns + @ref GL::MeshPrimitive instead of @ref Magnum::MeshPrimitive, code + depending on the return type being implicitly convertible to + @ref Magnum::MeshPrimitive may break. IN all other cases, + @ref Trade::MeshData2D::primitive() "Trade::MeshData*D::primitive()" etc. + returns @ref Magnum::MeshPrimitive. +- Configuration value reader/writers are now for only + @ref Magnum::MeshPrimitive and @ref Magnum::MeshIndexType, not for + @ref GL::MeshPrimitive or @ref GL::MeshIndexType - The @ref Image::pixelSize(), @ref ImageView::pixelSize(), @ref Trade::ImageData::pixelSize() and @ref BufferImage::pixelSize() functions now return @ref UnsignedInt instead of @cpp std::size_t @ce. diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 30e551b41..c32687f43 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -28,6 +28,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake # Files shared between main library and unit test library set(Magnum_SRCS + Mesh.cpp PixelStorage.cpp Resource.cpp Timeline.cpp) @@ -44,6 +45,7 @@ set(Magnum_HEADERS Image.h ImageView.h Magnum.h + Mesh.h PixelFormat.h PixelStorage.h Resource.h @@ -68,7 +70,6 @@ if(WITH_GL AND BUILD_DEPRECATED) DefaultFramebuffer.h Extensions.h Framebuffer.h - Mesh.h MeshView.h OpenGL.h Renderbuffer.h diff --git a/src/Magnum/GL/CMakeLists.txt b/src/Magnum/GL/CMakeLists.txt index b57d246cc..60654396a 100644 --- a/src/Magnum/GL/CMakeLists.txt +++ b/src/Magnum/GL/CMakeLists.txt @@ -34,7 +34,6 @@ set(MagnumGL_SRCS Context.cpp DefaultFramebuffer.cpp Framebuffer.cpp - Mesh.cpp MeshView.cpp OpenGL.cpp Renderbuffer.cpp @@ -57,6 +56,7 @@ set(MagnumGL_SRCS Implementation/maxTextureSize.cpp) set(MagnumGL_GracefulAssert_SRCS + Mesh.cpp PixelFormat.cpp) set(MagnumGL_HEADERS diff --git a/src/Magnum/GL/GL.h b/src/Magnum/GL/GL.h index def15e6f9..3b3deffce 100644 --- a/src/Magnum/GL/GL.h +++ b/src/Magnum/GL/GL.h @@ -91,6 +91,7 @@ enum class ImageAccess: GLenum; #endif enum class MeshPrimitive: GLenum; +enum class MeshIndexType: GLenum; class Mesh; class MeshView; diff --git a/src/Magnum/GL/Mesh.cpp b/src/Magnum/GL/Mesh.cpp index 4552d717b..8b0e41e42 100644 --- a/src/Magnum/GL/Mesh.cpp +++ b/src/Magnum/GL/Mesh.cpp @@ -27,6 +27,7 @@ #include +#include "Magnum/Mesh.h" #include "Magnum/GL/AbstractShaderProgram.h" #include "Magnum/GL/Buffer.h" #include "Magnum/GL/Context.h" @@ -43,6 +44,92 @@ namespace Magnum { namespace GL { +namespace { + +constexpr MeshPrimitive PrimitiveMapping[]{ + MeshPrimitive::Points, + MeshPrimitive::Lines, + MeshPrimitive::LineLoop, + MeshPrimitive::LineStrip, + MeshPrimitive::Triangles, + MeshPrimitive::TriangleStrip, + MeshPrimitive::TriangleFan +}; + +constexpr MeshIndexType IndexTypeMapping[]{ + MeshIndexType::UnsignedByte, + MeshIndexType::UnsignedShort, + MeshIndexType::UnsignedInt +}; + +} + +MeshPrimitive meshPrimitive(const Magnum::MeshPrimitive primitive) { + #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + CORRADE_IGNORE_DEPRECATED_PUSH + if(primitive == Magnum::MeshPrimitive::LinesAdjacency || + primitive == Magnum::MeshPrimitive::LineStripAdjacency || + primitive == Magnum::MeshPrimitive::TrianglesAdjacency || + primitive == Magnum::MeshPrimitive::TriangleStripAdjacency || + primitive == Magnum::MeshPrimitive::Patches) + return MeshPrimitive(UnsignedInt(primitive)); + CORRADE_IGNORE_DEPRECATED_POP + #endif + + CORRADE_ASSERT(UnsignedInt(primitive) < Containers::arraySize(PrimitiveMapping), + "GL::meshPrimitive(): invalid primitive" << primitive, {}); + return PrimitiveMapping[UnsignedInt(primitive)]; +} + +MeshIndexType meshIndexType(const Magnum::MeshIndexType type) { + CORRADE_ASSERT(UnsignedInt(type) < Containers::arraySize(IndexTypeMapping), + "GL::meshIndexType(): invalid type" << type, {}); + return IndexTypeMapping[UnsignedInt(type)]; +} + +#ifndef DOXYGEN_GENERATING_OUTPUT +Debug& operator<<(Debug& debug, MeshPrimitive value) { + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case MeshPrimitive::value: return debug << "GL::MeshPrimitive::" #value; + _c(Points) + _c(Lines) + _c(LineLoop) + _c(LineStrip) + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + _c(LineStripAdjacency) + _c(LinesAdjacency) + #endif + _c(Triangles) + _c(TriangleStrip) + _c(TriangleFan) + #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + _c(TrianglesAdjacency) + _c(TriangleStripAdjacency) + _c(Patches) + #endif + #undef _c + /* LCOV_EXCL_STOP */ + } + + return debug << "GL::MeshPrimitive(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; +} + +Debug& operator<<(Debug& debug, MeshIndexType value) { + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case MeshIndexType::value: return debug << "GL::MeshIndexType::" #value; + _c(UnsignedByte) + _c(UnsignedShort) + _c(UnsignedInt) + #undef _c + /* LCOV_EXCL_STOP */ + } + + return debug << "GL::MeshIndexType(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; +} +#endif + struct Mesh::AttributeLayout { explicit AttributeLayout(const Buffer& buffer, GLuint location, GLint size, GLenum type, DynamicAttribute::Kind kind, GLintptr offset, GLsizei stride, GLuint divisor) noexcept: buffer{Buffer::wrap(buffer.id())}, location{location}, size{size}, type{type}, kind{kind}, offset{offset}, stride{stride}, divisor{divisor} {} @@ -110,15 +197,11 @@ Int Mesh::maxElementsVertices() { } #endif -std::size_t Mesh::indexSize(IndexType type) { - switch(type) { - case IndexType::UnsignedByte: return 1; - case IndexType::UnsignedShort: return 2; - case IndexType::UnsignedInt: return 4; - } - - CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ +#ifdef MAGNUM_BUILD_DEPRECATED +std::size_t Mesh::indexSize(Magnum::MeshIndexType type) { + return meshIndexTypeSize(type); } +#endif Mesh::Mesh(const MeshPrimitive primitive): _primitive{primitive}, _flags{ObjectFlag::DeleteOnDestruction}, _count{0}, _baseVertex{0}, _instanceCount{1}, #ifndef MAGNUM_TARGET_GLES @@ -127,7 +210,7 @@ Mesh::Mesh(const MeshPrimitive primitive): _primitive{primitive}, _flags{ObjectF #ifndef MAGNUM_TARGET_GLES2 _indexStart(0), _indexEnd(0), #endif - _indexOffset(0), _indexType(IndexType::UnsignedInt), _indexBuffer(nullptr) + _indexOffset(0), _indexType(MeshIndexType::UnsignedInt), _indexBuffer(nullptr) { (this->*Context::current().state().mesh->createImplementation)(); } @@ -139,7 +222,7 @@ Mesh::Mesh(NoCreateT) noexcept: _id{0}, _primitive{MeshPrimitive::Triangles}, _f #ifndef MAGNUM_TARGET_GLES2 _indexStart(0), _indexEnd(0), #endif - _indexOffset(0), _indexType(IndexType::UnsignedInt), _indexBuffer(nullptr) {} + _indexOffset(0), _indexType(MeshIndexType::UnsignedInt), _indexBuffer(nullptr) {} Mesh::~Mesh() { /* Moved out or not deleting on destruction, nothing to do */ @@ -222,6 +305,23 @@ Mesh& Mesh::setLabelInternal(const Containers::ArrayView label) { } #endif +MeshIndexType Mesh::indexType() const { + CORRADE_ASSERT(_indexBuffer, "Mesh::indexType(): mesh is not indexed", {}); + return _indexType; +} + +UnsignedInt Mesh::indexTypeSize() const { + CORRADE_ASSERT(_indexBuffer, "Mesh::indexTypeSize(): mesh is not indexed", {}); + + switch(_indexType) { + case MeshIndexType::UnsignedByte: return 1; + case MeshIndexType::UnsignedShort: return 2; + case MeshIndexType::UnsignedInt: return 4; + } + + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ +} + Mesh& Mesh::addVertexBufferInstanced(Buffer& buffer, const UnsignedInt divisor, const GLintptr offset, const GLsizei stride, const DynamicAttribute& attribute) { AttributeLayout l{buffer, attribute.location(), @@ -235,7 +335,7 @@ Mesh& Mesh::addVertexBufferInstanced(Buffer& buffer, const UnsignedInt divisor, return *this; } -Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end) { +Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, MeshIndexType type, UnsignedInt start, UnsignedInt end) { #ifdef MAGNUM_TARGET_WEBGL CORRADE_ASSERT(buffer.targetHint() == Buffer::TargetHint::ElementArray, "GL::Mesh::setIndexBuffer(): the buffer has unexpected target hint, expected" << Buffer::TargetHint::ElementArray << "but got" << buffer.targetHint(), *this); @@ -629,120 +729,4 @@ void Mesh::drawElementsInstancedImplementationNV(const GLsizei count, const GLin #endif #endif -#ifndef DOXYGEN_GENERATING_OUTPUT -Debug& operator<<(Debug& debug, MeshPrimitive value) { - switch(value) { - /* LCOV_EXCL_START */ - #define _c(value) case MeshPrimitive::value: return debug << "GL::MeshPrimitive::" #value; - _c(Points) - _c(LineStrip) - _c(LineLoop) - _c(Lines) - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - _c(LineStripAdjacency) - _c(LinesAdjacency) - #endif - _c(TriangleStrip) - _c(TriangleFan) - _c(Triangles) - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - _c(TriangleStripAdjacency) - _c(TrianglesAdjacency) - _c(Patches) - #endif - #undef _c - /* LCOV_EXCL_STOP */ - } - - return debug << "GL::MeshPrimitive(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; -} - -Debug& operator<<(Debug& debug, Mesh::IndexType value) { - switch(value) { - /* LCOV_EXCL_START */ - #define _c(value) case Mesh::IndexType::value: return debug << "GL::Mesh::IndexType::" #value; - _c(UnsignedByte) - _c(UnsignedShort) - _c(UnsignedInt) - #undef _c - /* LCOV_EXCL_STOP */ - } - - return debug << "GL::Mesh::IndexType(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; -} -#endif - -}} - -namespace Corrade { namespace Utility { - -std::string ConfigurationValue::toString(Magnum::GL::MeshPrimitive value, ConfigurationValueFlags) { - switch(value) { - #define _c(value) case Magnum::GL::MeshPrimitive::value: return #value; - _c(Points) - _c(LineStrip) - _c(LineLoop) - _c(Lines) - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - _c(LineStripAdjacency) - _c(LinesAdjacency) - #endif - _c(TriangleStrip) - _c(TriangleFan) - _c(Triangles) - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - _c(TriangleStripAdjacency) - _c(TrianglesAdjacency) - _c(Patches) - #endif - #undef _c - } - - return {}; -} - -Magnum::GL::MeshPrimitive ConfigurationValue::fromString(const std::string& stringValue, ConfigurationValueFlags) { - #define _c(value) if(stringValue == #value) return Magnum::GL::MeshPrimitive::value; - _c(LineStrip) - _c(LineLoop) - _c(Lines) - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - _c(LineStripAdjacency) - _c(LinesAdjacency) - #endif - _c(TriangleStrip) - _c(TriangleFan) - _c(Triangles) - #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - _c(TriangleStripAdjacency) - _c(TrianglesAdjacency) - _c(Patches) - #endif - #undef _c - - return Magnum::GL::MeshPrimitive::Points; -} - -std::string ConfigurationValue::toString(Magnum::GL::Mesh::IndexType value, ConfigurationValueFlags) { - switch(value) { - #define _c(value) case Magnum::GL::Mesh::IndexType::value: return #value; - _c(UnsignedByte) - _c(UnsignedShort) - _c(UnsignedInt) - #undef _c - } - - return {}; -} - -Magnum::GL::Mesh::IndexType ConfigurationValue::fromString(const std::string& stringValue, ConfigurationValueFlags) { - #define _c(value) if(stringValue == #value) return Magnum::GL::Mesh::IndexType::value; - _c(UnsignedByte) - _c(UnsignedShort) - _c(UnsignedInt) - #undef _c - - return Magnum::GL::Mesh::IndexType::UnsignedInt; -} - }} diff --git a/src/Magnum/GL/Mesh.h b/src/Magnum/GL/Mesh.h index 18dec0ab3..8891d847f 100644 --- a/src/Magnum/GL/Mesh.h +++ b/src/Magnum/GL/Mesh.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class @ref Magnum::GL::Mesh + * @brief Class @ref Magnum::GL::Mesh, enum @ref Magnum::GL::MeshPrimitive, @ref Magnum::GL::MeshIndexType, function @ref Magnum::GL::meshPrimitive(), @ref Magnum::GL::meshIndexType() */ #include @@ -41,11 +41,12 @@ namespace Magnum { namespace GL { /** - * @brief Mesh primitive type - * - * @see @ref Mesh::primitive(), @ref Mesh::setPrimitive() - * @m_enum_values_as_keywords - */ +@brief Mesh primitive type + +@see @ref Magnum::MeshPrimitive, @ref meshPrimitive(), @ref Mesh::primitive(), + @ref Mesh::setPrimitive() +@m_enum_values_as_keywords +*/ enum class MeshPrimitive: GLenum { /** Single points. */ Points = GL_POINTS, @@ -135,6 +136,41 @@ enum class MeshPrimitive: GLenum { #endif }; +/** +@brief Convert generic mesh primitive to OpenGL mesh primitive + +@see @ref meshIndexType() +*/ +MAGNUM_GL_EXPORT MeshPrimitive meshPrimitive(Magnum::MeshPrimitive); + +/** +@brief Index type + +@see @ref Magnum::MeshIndexType, @ref meshIndexType(), + @ref meshIndexTypeSize(), @ref Mesh::setIndexBuffer() +@m_enum_values_as_keywords +*/ +enum class MeshIndexType: GLenum { + UnsignedByte = GL_UNSIGNED_BYTE, /**< Unsigned byte */ + UnsignedShort = GL_UNSIGNED_SHORT, /**< Unsigned short */ + + /** + * Unsigned int + * @requires_gles30 Extension @extension{OES,element_index_uint} + * in OpenGL ES 2.0. + * @requires_webgl20 Extension @webgl_extension{OES,element_index_uint} + * in WebGL 1.0. + */ + UnsignedInt = GL_UNSIGNED_INT +}; + +/** +@brief Convert generic mesh index type to OpenGL mesh index type + +@see @ref meshPrimitive(), @ref meshIndexTypeSize() +*/ +MAGNUM_GL_EXPORT MeshIndexType meshIndexType(Magnum::MeshIndexType); + namespace Implementation { struct MeshState; } /** @@ -240,25 +276,13 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { friend Implementation::MeshState; public: - /** - * @brief Index type - * - * @see @ref setIndexBuffer(), @ref indexSize() - * @m_enum_values_as_keywords + #ifdef MAGNUM_BUILD_DEPRECATED + /** @brief @copybrief MeshIndexType + * @deprecated Use @ref Magnum::MeshIndexType or @ref GL::MeshIndexType + * instead. */ - enum class IndexType: GLenum { - UnsignedByte = GL_UNSIGNED_BYTE, /**< Unsigned byte */ - UnsignedShort = GL_UNSIGNED_SHORT, /**< Unsigned short */ - - /** - * Unsigned int - * @requires_gles30 Extension @extension{OES,element_index_uint} - * in OpenGL ES 2.0. - * @requires_webgl20 Extension @webgl_extension{OES,element_index_uint} - * in WebGL 1.0. - */ - UnsignedInt = GL_UNSIGNED_INT - }; + typedef CORRADE_DEPRECATED("use MeshIndexType instead") Magnum::MeshIndexType IndexType; + #endif #ifndef MAGNUM_TARGET_GLES2 /** @@ -308,12 +332,12 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { static Int maxElementsVertices(); #endif - /** - * @brief Size of given index type - * - * @see @ref indexSize() const + #ifdef MAGNUM_BUILD_DEPRECATED + /** @brief @copybrief meshIndexTypeSize() + * @deprecated Use @ref meshIndexTypeSize() instead. */ - static std::size_t indexSize(IndexType type); + static CORRADE_DEPRECATED("use meshIndexTypeSize() instead") std::size_t indexSize(Magnum::MeshIndexType type); + #endif /** * @brief Wrap existing OpenGL vertex array object @@ -357,6 +381,9 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { */ explicit Mesh(MeshPrimitive primitive = MeshPrimitive::Triangles); + /** @overload */ + explicit Mesh(Magnum::MeshPrimitive primitive): Mesh{meshPrimitive(primitive)} {} + /** * @brief Construct without creating the underlying OpenGL object * @@ -466,11 +493,28 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { bool isIndexed() const { return _indexBuffer; } /** - * @brief Index size + * @brief Index type + * + * Expects that the mesh is indexed. + * @see @ref isIndexed() + */ + MeshIndexType indexType() const; + + /** + * @brief Index type size * - * @see @ref indexSize(IndexType) + * Expects that the mesh is indexed. + * @see @ref isIndexed(), @ref meshIndexTypeSize(Magnum::MeshIndexType) */ - std::size_t indexSize() const { return indexSize(_indexType); } + UnsignedInt indexTypeSize() const; + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Index size + * @deprecated Use @ref indexTypeSize() instead. + */ + CORRADE_DEPRECATED("use indexTypeSize() instead") std::size_t indexSize() const { return indexTypeSize(); } + #endif /** @brief Primitive type */ MeshPrimitive primitive() const { return _primitive; } @@ -486,6 +530,11 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { return *this; } + /** @overload */ + Mesh& setPrimitive(Magnum::MeshPrimitive primitive) { + return setPrimitive(meshPrimitive(primitive)); + } + /** @brief Vertex/index count */ Int count() const { return _count; } @@ -710,9 +759,9 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { * The smaller range is specified with @p start and @p end the less * memory operations are needed (and possibly some optimizations), * improving draw performance. Specifying @cpp 0 @ce for both - * parameters behaves the same as @ref setIndexBuffer(Buffer&, GLintptr, IndexType). + * parameters behaves the same as @ref setIndexBuffer(Buffer&, GLintptr, MeshIndexType). * On OpenGL ES 2.0 this function behaves always as - * @ref setIndexBuffer(Buffer&, GLintptr, IndexType), as this + * @ref setIndexBuffer(Buffer&, GLintptr, MeshIndexType), as this * functionality is not available there. * * If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL @@ -726,7 +775,12 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { * @ref maxElementsVertices(), @ref setCount(), @ref isIndexed(), * @fn_gl{BindVertexArray}, @fn_gl{BindBuffer} */ - Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, UnsignedInt start, UnsignedInt end); + Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, MeshIndexType type, UnsignedInt start, UnsignedInt end); + + /** @overload */ + Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, Magnum::MeshIndexType type, UnsignedInt start, UnsignedInt end) { + return setIndexBuffer(buffer, offset, meshIndexType(type), start, end); + } /** * @brief Set index buffer @@ -735,14 +789,19 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { * @param type Index data type * @return Reference to self (for method chaining) * - * Alternative to @ref setIndexBuffer(Buffer&, GLintptr, IndexType, UnsignedInt, UnsignedInt) + * Alternative to @ref setIndexBuffer(Buffer&, GLintptr, MeshIndexType, UnsignedInt, UnsignedInt) * with unspecified index limits, see its documentation for more * information. Prefer to set index limits for better performance. */ - Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type) { + Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, MeshIndexType type) { return setIndexBuffer(buffer, offset, type, 0, 0); } + /** @overload */ + Mesh& setIndexBuffer(Buffer& buffer, GLintptr offset, Magnum::MeshIndexType type) { + return setIndexBuffer(buffer, offset, meshIndexType(type)); + } + /** * @brief Draw the mesh * @param shader Shader to use for drawing @@ -979,7 +1038,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { UnsignedInt _indexStart, _indexEnd; #endif GLintptr _indexOffset; - IndexType _indexType; + MeshIndexType _indexType; Buffer* _indexBuffer; std::vector _attributes; @@ -988,8 +1047,8 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject { /** @debugoperatorenum{MeshPrimitive} */ MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, MeshPrimitive value); -/** @debugoperatorclassenum{Mesh,Mesh::IndexType} */ -MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, Mesh::IndexType value); +/** @debugoperatorenum{MeshIndexType} */ +MAGNUM_GL_EXPORT Debug& operator<<(Debug& debug, MeshIndexType value); inline GLuint Mesh::release() { const GLuint id = _id; @@ -1002,11 +1061,6 @@ inline GLuint Mesh::release() { #ifdef MAGNUM_BUILD_DEPRECATED /* Note: needs to be prefixed with Magnum:: otherwise Doxygen can't find it */ -/** @brief @copybrief GL::MeshPrimitive - * @deprecated Use @ref GL::MeshPrimitive instead. - */ -typedef CORRADE_DEPRECATED("use GL::MeshPrimitive instead") Magnum::GL::MeshPrimitive MeshPrimitive; - /** @brief @copybrief GL::Mesh * @deprecated Use @ref GL::Mesh instead. */ @@ -1015,46 +1069,4 @@ typedef CORRADE_DEPRECATED("use GL::Mesh instead") Magnum::GL::Mesh Mesh; } -namespace Corrade { namespace Utility { - -/** @configurationvalue{Magnum::MeshPrimitive} */ -template<> struct MAGNUM_GL_EXPORT ConfigurationValue { - ConfigurationValue() = delete; - - /** - * @brief Writes enum value as string - * - * If the value is invalid, returns empty string. - */ - static std::string toString(Magnum::GL::MeshPrimitive value, ConfigurationValueFlags); - - /** - * @brief Reads enum value as string - * - * If the value is invalid, returns @ref Magnum::MeshPrimitive::Points "MeshPrimitive::Points". - */ - static Magnum::GL::MeshPrimitive fromString(const std::string& stringValue, ConfigurationValueFlags); -}; - -/** @configurationvalue{Magnum::Mesh::IndexType} */ -template<> struct MAGNUM_GL_EXPORT ConfigurationValue { - ConfigurationValue() = delete; - - /** - * @brief Write enum value as string - * - * If the value is invalid, returns empty string. - */ - static std::string toString(Magnum::GL::Mesh::IndexType value, ConfigurationValueFlags); - - /** - * @brief Read enum value as string - * - * If the value is invalid, returns @ref Magnum::Mesh::IndexType::UnsignedInt "Mesh::IndexType::UnsignedInt". - */ - static Magnum::GL::Mesh::IndexType fromString(const std::string& stringValue, ConfigurationValueFlags); -}; - -}} - #endif diff --git a/src/Magnum/GL/MeshView.cpp b/src/Magnum/GL/MeshView.cpp index b10a9a3fd..057d1f34a 100644 --- a/src/Magnum/GL/MeshView.cpp +++ b/src/Magnum/GL/MeshView.cpp @@ -140,7 +140,8 @@ void MeshView::multiDrawImplementationFallback(std::initializer_list void primitive(); + #ifndef MAGNUM_TARGET_WEBGL void label(); #endif @@ -112,8 +114,8 @@ struct MeshGLTest: OpenGLTester { void addVertexBufferMultiple(); void addVertexBufferMultipleGaps(); - void setIndexBuffer(); - void setIndexBufferRange(); + template void setIndexBuffer(); + template void setIndexBufferRange(); void setIndexBufferUnsignedInt(); void unbindVAOWhenSettingIndexBufferData(); @@ -152,6 +154,9 @@ MeshGLTest::MeshGLTest() { &MeshGLTest::constructMove, &MeshGLTest::wrap, + &MeshGLTest::primitive, + &MeshGLTest::primitive, + #ifndef MAGNUM_TARGET_WEBGL &MeshGLTest::label #endif @@ -214,8 +219,10 @@ MeshGLTest::MeshGLTest() { addTests({&MeshGLTest::addVertexBufferMultiple, &MeshGLTest::addVertexBufferMultipleGaps, - &MeshGLTest::setIndexBuffer, - &MeshGLTest::setIndexBufferRange, + &MeshGLTest::setIndexBuffer, + &MeshGLTest::setIndexBuffer, + &MeshGLTest::setIndexBufferRange, + &MeshGLTest::setIndexBufferRange, &MeshGLTest::setIndexBufferUnsignedInt, &MeshGLTest::unbindVAOWhenSettingIndexBufferData, @@ -347,6 +354,21 @@ void MeshGLTest::wrap() { #endif } +template void MeshGLTest::primitive() { + setTestCaseName(std::is_same::value ? + "setPrimitive" : + "setPrimitive"); + + { + Mesh mesh{T::LineLoop}; + CORRADE_COMPARE(mesh.primitive(), MeshPrimitive::LineLoop); + } { + Mesh mesh; + mesh.setPrimitive(T::TriangleFan); + CORRADE_COMPARE(mesh.primitive(), MeshPrimitive::TriangleFan); + } +} + #ifndef MAGNUM_TARGET_WEBGL void MeshGLTest::label() { /* No-Op version is tested in AbstractObjectGLTest */ @@ -542,15 +564,18 @@ Checker::Checker(AbstractShaderProgram&& shader, RenderbufferFormat format, Mesh .setCount(2); /* Skip first vertex so we test also offsets */ - MeshView(mesh) - .setCount(1) + MeshView view{mesh}; + view.setCount(1) .setBaseVertex(mesh.baseVertex()) .setInstanceCount(mesh.instanceCount()) #ifndef MAGNUM_TARGET_GLES .setBaseInstance(mesh.baseInstance()) #endif - .setIndexRange(1) - .draw(shader); + ; + + if(view.mesh().isIndexed()) view.setIndexRange(1); + + view.draw(shader); } template T Checker::get(PixelFormat format, PixelType type) { @@ -1635,20 +1660,26 @@ namespace { constexpr Color4ub indexedResult(64 + 15 + 97, 17 + 164 + 28, 56 + 17, 255); } -void MeshGLTest::setIndexBuffer() { +template void MeshGLTest::setIndexBuffer() { + setTestCaseName(std::is_same::value ? + "setIndexBuffer" : + "setIndexBuffer"); + Buffer vertices; vertices.setData(indexedVertexData, BufferUsage::StaticDraw); - constexpr UnsignedShort indexData[] = { 2, 1, 0 }; + constexpr UnsignedByte indexData[] = { 2, 1, 0 }; Buffer indices{Buffer::TargetHint::ElementArray}; indices.setData(indexData, BufferUsage::StaticDraw); Mesh mesh; mesh.addVertexBuffer(vertices, 1*4, MultipleShader::Position(), MultipleShader::Normal(), MultipleShader::TextureCoordinates()) - .setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); + .setIndexBuffer(indices, 2, T::UnsignedByte); MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(mesh.indexType(), MeshIndexType::UnsignedByte); + CORRADE_COMPARE(mesh.indexTypeSize(), 1); const auto value = Checker(MultipleShader{}, #ifndef MAGNUM_TARGET_GLES2 @@ -1662,7 +1693,11 @@ void MeshGLTest::setIndexBuffer() { CORRADE_COMPARE(value, indexedResult); } -void MeshGLTest::setIndexBufferRange() { +template void MeshGLTest::setIndexBufferRange() { + setTestCaseName(std::is_same::value ? + "setIndexBufferRange" : + "setIndexBufferRange"); + Buffer vertices; vertices.setData(indexedVertexData, BufferUsage::StaticDraw); @@ -1673,9 +1708,11 @@ void MeshGLTest::setIndexBufferRange() { Mesh mesh; mesh.addVertexBuffer(vertices, 1*4, MultipleShader::Position(), MultipleShader::Normal(), MultipleShader::TextureCoordinates()) - .setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort, 0, 1); + .setIndexBuffer(indices, 2, T::UnsignedShort, 0, 1); MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(mesh.indexType(), GL::MeshIndexType::UnsignedShort); + CORRADE_COMPARE(mesh.indexTypeSize(), 2); const auto value = Checker(MultipleShader{}, #ifndef MAGNUM_TARGET_GLES2 @@ -1708,6 +1745,8 @@ void MeshGLTest::setIndexBufferUnsignedInt() { .setIndexBuffer(indices, 4, Mesh::IndexType::UnsignedInt); MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(mesh.indexType(), GL::MeshIndexType::UnsignedInt); + CORRADE_COMPARE(mesh.indexTypeSize(), 4); const auto value = Checker(MultipleShader{}, #ifndef MAGNUM_TARGET_GLES2 @@ -2326,6 +2365,6 @@ void MeshGLTest::multiDrawBaseVertex() { } #endif -}} +}}} -CORRADE_TEST_MAIN(Magnum::Test::MeshGLTest) +CORRADE_TEST_MAIN(Magnum::GL::Test::MeshGLTest) diff --git a/src/Magnum/GL/Test/MeshTest.cpp b/src/Magnum/GL/Test/MeshTest.cpp index 6a6be6af1..ef3a88647 100644 --- a/src/Magnum/GL/Test/MeshTest.cpp +++ b/src/Magnum/GL/Test/MeshTest.cpp @@ -28,31 +28,48 @@ #include #include "Magnum/Mesh.h" +#include "Magnum/GL/Mesh.h" -namespace Magnum { namespace Test { +namespace Magnum { namespace GL { namespace Test { struct MeshTest: TestSuite::Tester { explicit MeshTest(); void constructNoCreate(); - void indexSize(); + #ifdef MAGNUM_BUILD_DEPRECATED + void indexSizeDeprecated(); + #endif + + void mapPrimitive(); + #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + void mapPrimitiveDeprecated(); + #endif + void mapPrimitiveInvalid(); + void mapIndexType(); + void mapIndexTypeInvalid(); void debugPrimitive(); void debugIndexType(); - void configurationPrimitive(); - void configurationIndexType(); }; MeshTest::MeshTest() { addTests({&MeshTest::constructNoCreate, - &MeshTest::indexSize, + #ifdef MAGNUM_BUILD_DEPRECATED + &MeshTest::indexSizeDeprecated, + #endif + + &MeshTest::mapPrimitive, + #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + &MeshTest::mapPrimitiveDeprecated, + #endif + &MeshTest::mapPrimitiveInvalid, + &MeshTest::mapIndexType, + &MeshTest::mapIndexTypeInvalid, &MeshTest::debugPrimitive, - &MeshTest::debugIndexType, - &MeshTest::configurationPrimitive, - &MeshTest::configurationIndexType}); + &MeshTest::debugIndexType}); } void MeshTest::constructNoCreate() { @@ -64,40 +81,71 @@ void MeshTest::constructNoCreate() { CORRADE_VERIFY(true); } -void MeshTest::indexSize() { +#ifdef MAGNUM_BUILD_DEPRECATED +void MeshTest::indexSizeDeprecated() { + CORRADE_IGNORE_DEPRECATED_PUSH CORRADE_COMPARE(Mesh::indexSize(Mesh::IndexType::UnsignedByte), 1); CORRADE_COMPARE(Mesh::indexSize(Mesh::IndexType::UnsignedShort), 2); CORRADE_COMPARE(Mesh::indexSize(Mesh::IndexType::UnsignedInt), 4); + CORRADE_IGNORE_DEPRECATED_POP +} +#endif + +void MeshTest::mapPrimitive() { + CORRADE_COMPARE(meshPrimitive(Magnum::MeshPrimitive::Points), MeshPrimitive::Points); + CORRADE_COMPARE(meshPrimitive(Magnum::MeshPrimitive::Lines), MeshPrimitive::Lines); + CORRADE_COMPARE(meshPrimitive(Magnum::MeshPrimitive::LineLoop), MeshPrimitive::LineLoop); + CORRADE_COMPARE(meshPrimitive(Magnum::MeshPrimitive::LineStrip), MeshPrimitive::LineStrip); + CORRADE_COMPARE(meshPrimitive(Magnum::MeshPrimitive::Triangles), MeshPrimitive::Triangles); + CORRADE_COMPARE(meshPrimitive(Magnum::MeshPrimitive::TriangleStrip), MeshPrimitive::TriangleStrip); + CORRADE_COMPARE(meshPrimitive(Magnum::MeshPrimitive::TriangleFan), MeshPrimitive::TriangleFan); } -void MeshTest::debugPrimitive() { - std::ostringstream o; - Debug(&o) << MeshPrimitive::TriangleFan << MeshPrimitive(0xdead); - CORRADE_COMPARE(o.str(), "GL::MeshPrimitive::TriangleFan GL::MeshPrimitive(0xdead)\n"); +#if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) +void MeshTest::mapPrimitiveDeprecated() { + CORRADE_IGNORE_DEPRECATED_PUSH + CORRADE_COMPARE(meshPrimitive(Magnum::MeshPrimitive::TriangleStripAdjacency), + MeshPrimitive::TriangleStripAdjacency); + CORRADE_IGNORE_DEPRECATED_POP } +#endif -void MeshTest::debugIndexType() { - std::ostringstream o; - Debug(&o) << Mesh::IndexType::UnsignedShort << Mesh::IndexType(0xdead); - CORRADE_COMPARE(o.str(), "GL::Mesh::IndexType::UnsignedShort GL::Mesh::IndexType(0xdead)\n"); +void MeshTest::mapPrimitiveInvalid() { + std::ostringstream out; + Error redirectError{&out}; + + meshPrimitive(Magnum::MeshPrimitive(0x123)); + CORRADE_COMPARE(out.str(), + "GL::meshPrimitive(): invalid primitive MeshPrimitive(0x123)\n"); } -void MeshTest::configurationPrimitive() { - Utility::Configuration c; +void MeshTest::mapIndexType() { + CORRADE_COMPARE(meshIndexType(Magnum::MeshIndexType::UnsignedByte), MeshIndexType::UnsignedByte); + CORRADE_COMPARE(meshIndexType(Magnum::MeshIndexType::UnsignedShort), MeshIndexType::UnsignedShort); + CORRADE_COMPARE(meshIndexType(Magnum::MeshIndexType::UnsignedInt), MeshIndexType::UnsignedInt); +} + +void MeshTest::mapIndexTypeInvalid() { + std::ostringstream out; + Error redirectError{&out}; - c.setValue("primitive", MeshPrimitive::LineStrip); - CORRADE_COMPARE(c.value("primitive"), "LineStrip"); - CORRADE_COMPARE(c.value("primitive"), MeshPrimitive::LineStrip); + meshIndexType(Magnum::MeshIndexType(0x123)); + CORRADE_COMPARE(out.str(), + "GL::meshIndexType(): invalid type MeshIndexType(0x123)\n"); } -void MeshTest::configurationIndexType() { - Utility::Configuration c; +void MeshTest::debugPrimitive() { + std::ostringstream o; + Debug(&o) << MeshPrimitive::TriangleFan << MeshPrimitive(0xdead); + CORRADE_COMPARE(o.str(), "GL::MeshPrimitive::TriangleFan GL::MeshPrimitive(0xdead)\n"); +} - c.setValue("type", Mesh::IndexType::UnsignedByte); - CORRADE_COMPARE(c.value("type"), "UnsignedByte"); - CORRADE_COMPARE(c.value("type"), Mesh::IndexType::UnsignedByte); +void MeshTest::debugIndexType() { + std::ostringstream o; + Debug(&o) << MeshIndexType::UnsignedShort << MeshIndexType(0xdead); + CORRADE_COMPARE(o.str(), "GL::MeshIndexType::UnsignedShort GL::MeshIndexType(0xdead)\n"); } -}} +}}} -CORRADE_TEST_MAIN(Magnum::Test::MeshTest) +CORRADE_TEST_MAIN(Magnum::GL::Test::MeshTest) diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index 1bd37b7dd..5aeffbf58 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -698,6 +698,9 @@ typedef CompressedImageView<1> CompressedImageView1D; typedef CompressedImageView<2> CompressedImageView2D; typedef CompressedImageView<3> CompressedImageView3D; +enum class MeshPrimitive: UnsignedInt; +enum class MeshIndexType: UnsignedInt; + enum class PixelFormat: UnsignedInt; enum class CompressedPixelFormat: UnsignedInt; @@ -760,8 +763,6 @@ typedef CORRADE_DEPRECATED("use GL::ImageAccess instead") GL::ImageAccess ImageA typedef CORRADE_DEPRECATED("use GL::ImageFormat instead") GL::ImageFormat ImageFormat; #endif -typedef CORRADE_DEPRECATED("use GL::MeshPrimitive instead") GL::MeshPrimitive MeshPrimitive; - typedef CORRADE_DEPRECATED("use GL::Mesh instead") GL::Mesh Mesh; typedef CORRADE_DEPRECATED("use GL::MeshView instead") GL::MeshView MeshView; diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp new file mode 100644 index 000000000..a07b7b308 --- /dev/null +++ b/src/Magnum/Mesh.cpp @@ -0,0 +1,165 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + 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 "Mesh.h" + +#include +#include + +namespace Magnum { + +UnsignedInt meshIndexTypeSize(MeshIndexType type) { + switch(type) { + case MeshIndexType::UnsignedByte: return 1; + case MeshIndexType::UnsignedShort: return 2; + case MeshIndexType::UnsignedInt: return 4; + } + + CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ +} + +#ifndef DOXYGEN_GENERATING_OUTPUT +Debug& operator<<(Debug& debug, MeshPrimitive value) { + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case MeshPrimitive::value: return debug << "MeshPrimitive::" #value; + _c(Points) + _c(Lines) + _c(LineLoop) + _c(LineStrip) + _c(Triangles) + _c(TriangleStrip) + _c(TriangleFan) + #undef _c + + /* Here mainly to suppress compiler warnings about unhandled cases and + also to check that there are no accidentally conflicting values. */ + #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + CORRADE_IGNORE_DEPRECATED_PUSH + #define _c(value) case MeshPrimitive::value: return debug << "GL::MeshPrimitive::" #value; + _c(LinesAdjacency) + _c(LineStripAdjacency) + _c(TrianglesAdjacency) + _c(TriangleStripAdjacency) + _c(Patches) + #undef _c + CORRADE_IGNORE_DEPRECATED_POP + #endif + /* LCOV_EXCL_STOP */ + } + + return debug << "MeshPrimitive(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; +} + +Debug& operator<<(Debug& debug, MeshIndexType value) { + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case MeshIndexType::value: return debug << "MeshIndexType::" #value; + _c(UnsignedByte) + _c(UnsignedShort) + _c(UnsignedInt) + #undef _c + /* LCOV_EXCL_STOP */ + } + + return debug << "MeshIndexType(" << Debug::nospace << reinterpret_cast(GLenum(value)) << Debug::nospace << ")"; +} +#endif + +} + +namespace Corrade { namespace Utility { + +std::string ConfigurationValue::toString(Magnum::MeshPrimitive value, ConfigurationValueFlags) { + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case Magnum::MeshPrimitive::value: return #value; + _c(Points) + _c(Lines) + _c(LineLoop) + _c(LineStrip) + _c(Triangles) + _c(TriangleStrip) + _c(TriangleFan) + #undef _c + + #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + CORRADE_IGNORE_DEPRECATED_PUSH + case Magnum::MeshPrimitive::LinesAdjacency: + case Magnum::MeshPrimitive::LineStripAdjacency: + case Magnum::MeshPrimitive::TrianglesAdjacency: + case Magnum::MeshPrimitive::TriangleStripAdjacency: + case Magnum::MeshPrimitive::Patches: + return {}; + CORRADE_IGNORE_DEPRECATED_POP + #endif + /* LCOV_EXCL_STOP */ + } + + return {}; +} + +Magnum::MeshPrimitive ConfigurationValue::fromString(const std::string& stringValue, ConfigurationValueFlags) { + /* LCOV_EXCL_START */ + #define _c(value) if(stringValue == #value) return Magnum::MeshPrimitive::value; + _c(LineStrip) + _c(LineLoop) + _c(Lines) + _c(Triangles) + _c(TriangleStrip) + _c(TriangleFan) + #undef _c + /* LCOV_EXCL_STOP */ + + return Magnum::MeshPrimitive::Points; +} + +std::string ConfigurationValue::toString(Magnum::MeshIndexType value, ConfigurationValueFlags) { + switch(value) { + /* LCOV_EXCL_START */ + #define _c(value) case Magnum::MeshIndexType::value: return #value; + _c(UnsignedByte) + _c(UnsignedShort) + _c(UnsignedInt) + #undef _c + /* LCOV_EXCL_STOP */ + } + + return {}; +} + +Magnum::MeshIndexType ConfigurationValue::fromString(const std::string& stringValue, ConfigurationValueFlags) { + /* LCOV_EXCL_START */ + #define _c(value) if(stringValue == #value) return Magnum::MeshIndexType::value; + _c(UnsignedByte) + _c(UnsignedShort) + _c(UnsignedInt) + #undef _c + /* LCOV_EXCL_STOP */ + + return Magnum::MeshIndexType::UnsignedInt; +} + +}} diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index d109acc23..350abdffb 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -26,16 +26,212 @@ */ /** @file - * @deprecated Use @ref Magnum/GL/Mesh.h instead. + * @brief Enum @ref Magnum::MeshPrimitive, @ref Magnum::MeshIndexType, function @ref Magnum::meshIndexTypeSize() */ -#include "Magnum/configure.h" +#include + +#include "Magnum/Magnum.h" +#include "Magnum/visibility.h" #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) #include "Magnum/GL/Mesh.h" -CORRADE_DEPRECATED_FILE("use Magnum/GL/Mesh.h instead") -#else -#error use Magnum/GL/Mesh.h instead #endif +namespace Magnum { + +/** +@brief Mesh primitive type + +In case of OpenGL, corresponds to @ref GL::MeshPrimitive and is convertible to +it using @ref GL::meshPrimitive(). See documentation of each value for more +information about the mapping. +*/ +enum class MeshPrimitive: UnsignedInt { + /** + * Single points. + * + * Corresponds to @ref GL::MeshPrimitive::Points. + */ + Points, + + /** + * Each pair of vertices defines a single line, lines aren't + * connected together. + * + * Corresponds to @ref GL::MeshPrimitive::Lines. + */ + Lines, + + /** + * Line strip, last and first vertex are connected together. + * + * Corresponds to @ref GL::MeshPrimitive::LineLoop. + */ + LineLoop, + + /** + * First two vertices define first line segment, each following + * vertex defines another segment. + * + * Corresponds to @ref GL::MeshPrimitive::LineStrip. + */ + LineStrip, + + /** + * Each three vertices define one triangle. + * + * Corresponds to @ref GL::MeshPrimitive::Triangles. + */ + Triangles, + + /** + * First three vertices define first triangle, each following + * vertex defines another triangle. + * + * Corresponds to @ref GL::MeshPrimitive::TriangleStrip. + */ + TriangleStrip, + + /** + * First vertex is center, each following vertex is connected to + * previous and center vertex. + * + * Corresponds to @ref GL::MeshPrimitive::TriangleFan. + */ + TriangleFan, + + #if defined(MAGNUM_BUILD_DEPRECATED) && defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) + /** + * Lines with adjacency information. + * @requires_gl32 Extension @extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_gles32 Extension @extension{ANDROID,extension_pack_es31a} / + * @extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + */ + LinesAdjacency CORRADE_DEPRECATED_ENUM("use GL::MeshPrimitive::Patches instead") = UnsignedInt(GL::MeshPrimitive::LinesAdjacency), + + /** + * Line strip with adjacency information. + * @requires_gl32 Extension @extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_gles32 Extension @extension{ANDROID,extension_pack_es31a} / + * @extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + */ + LineStripAdjacency CORRADE_DEPRECATED_ENUM("use GL::MeshPrimitive::Patches instead") = UnsignedInt(GL::MeshPrimitive::LineStripAdjacency), + + /** + * Triangles with adjacency information. + * @requires_gl32 Extension @extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_gles32 Extension @extension{ANDROID,extension_pack_es31a} / + * @extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + */ + TrianglesAdjacency CORRADE_DEPRECATED_ENUM("use GL::MeshPrimitive::Patches instead") = UnsignedInt(GL::MeshPrimitive::TrianglesAdjacency), + + /** + * Triangle strip with adjacency information. + * @requires_gl32 Extension @extension{ARB,geometry_shader4} + * @requires_gles30 Not defined in OpenGL ES 2.0. + * @requires_gles32 Extension @extension{ANDROID,extension_pack_es31a} / + * @extension{EXT,geometry_shader} + * @requires_gles Geometry shaders are not available in WebGL. + */ + TriangleStripAdjacency CORRADE_DEPRECATED_ENUM("use GL::MeshPrimitive::Patches instead") = UnsignedInt(GL::MeshPrimitive::TriangleStripAdjacency), + + /** + * Patches. + * @deprecated Use @ref GL::MeshPrimitive::Patches instead + */ + Patches CORRADE_DEPRECATED_ENUM("use GL::MeshPrimitive::Patches instead") = UnsignedInt(GL::MeshPrimitive::Patches) + #endif +}; + +/** @debugoperatorenum{MeshPrimitive} */ +MAGNUM_EXPORT Debug& operator<<(Debug& debug, MeshPrimitive value); + +/** +@brief Mesh primitive type + +In case of OpenGL, corresponds to @ref GL::MeshIndexType and is convertible to +it using @ref GL::meshIndexType(). See documentation of each value for more +information about the mapping. +@see @ref meshIndexTypeSize() +*/ +enum class MeshIndexType: UnsignedInt { + /** + * Unsigned byte + * + * Corresponds to @ref GL::MeshIndexType::UnsignedByte. + */ + UnsignedByte, + + /** + * Unsigned short + * + * Corresponds to @ref GL::MeshIndexType::UnsignedShort. + */ + UnsignedShort, + + /** + * Unsigned int + * + * Corresponds to @ref GL::MeshIndexType::UnsignedInt. + */ + UnsignedInt +}; + +/** @brief Size of given mesh index type */ +MAGNUM_EXPORT UnsignedInt meshIndexTypeSize(MeshIndexType type); + +/** @debugoperatorenum{MeshIndexType} */ +MAGNUM_EXPORT Debug& operator<<(Debug& debug, MeshIndexType value); + +} + +namespace Corrade { namespace Utility { + +/** @configurationvalue{Magnum::MeshPrimitive} */ +template<> struct MAGNUM_EXPORT ConfigurationValue { + ConfigurationValue() = delete; + + /** + * @brief Writes enum value as string + * + * If the value is invalid, returns empty string. + */ + static std::string toString(Magnum::MeshPrimitive value, ConfigurationValueFlags); + + /** + * @brief Reads enum value as string + * + * If the value is invalid, returns @ref Magnum::MeshPrimitive::Points "MeshPrimitive::Points". + */ + static Magnum::MeshPrimitive fromString(const std::string& stringValue, ConfigurationValueFlags); +}; + +/** @configurationvalue{Magnum::MeshIndexType} */ +template<> struct MAGNUM_EXPORT ConfigurationValue { + ConfigurationValue() = delete; + + /** + * @brief Write enum value as string + * + * If the value is invalid, returns empty string. + */ + static std::string toString(Magnum::MeshIndexType value, ConfigurationValueFlags); + + /** + * @brief Read enum value as string + * + * If the value is invalid, returns @ref Magnum::MeshIndexType::UnsignedInt "MeshIndexType::UnsignedInt". + */ + static Magnum::MeshIndexType fromString(const std::string& stringValue, ConfigurationValueFlags); +}; + +}} + #endif diff --git a/src/Magnum/Test/CMakeLists.txt b/src/Magnum/Test/CMakeLists.txt index 588435c99..8ad4909c5 100644 --- a/src/Magnum/Test/CMakeLists.txt +++ b/src/Magnum/Test/CMakeLists.txt @@ -26,6 +26,7 @@ corrade_add_test(ArrayTest ArrayTest.cpp LIBRARIES Magnum) corrade_add_test(ImageTest ImageTest.cpp LIBRARIES MagnumTestLib) corrade_add_test(ImageViewTest ImageViewTest.cpp LIBRARIES MagnumTestLib) +corrade_add_test(MeshTest MeshTest.cpp LIBRARIES Magnum) corrade_add_test(PixelFormatTest PixelFormatTest.cpp LIBRARIES MagnumTestLib) target_compile_definitions(PixelFormatTest PRIVATE "CORRADE_GRACEFUL_ASSERT") corrade_add_test(PixelStorageTest PixelStorageTest.cpp LIBRARIES Magnum) @@ -45,6 +46,7 @@ set_target_properties( ArrayTest ImageTest ImageViewTest + MeshTest PixelFormatTest PixelStorageTest ResourceManagerTest diff --git a/src/Magnum/Test/MeshTest.cpp b/src/Magnum/Test/MeshTest.cpp new file mode 100644 index 000000000..d87e7bfa6 --- /dev/null +++ b/src/Magnum/Test/MeshTest.cpp @@ -0,0 +1,98 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 + 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 +#include +#include + +#include "Magnum/Mesh.h" + +namespace Magnum { namespace Test { + +struct MeshTest: TestSuite::Tester { + explicit MeshTest(); + + void indexTypeSize(); + + void debugPrimitive(); + void debugIndexType(); + void configurationPrimitive(); + void configurationIndexType(); +}; + +MeshTest::MeshTest() { + addTests({&MeshTest::indexTypeSize, + + &MeshTest::debugPrimitive, + &MeshTest::debugIndexType, + &MeshTest::configurationPrimitive, + &MeshTest::configurationIndexType}); +} + +void MeshTest::indexTypeSize() { + CORRADE_COMPARE(meshIndexTypeSize(MeshIndexType::UnsignedByte), 1); + CORRADE_COMPARE(meshIndexTypeSize(MeshIndexType::UnsignedShort), 2); + CORRADE_COMPARE(meshIndexTypeSize(MeshIndexType::UnsignedInt), 4); +} + +void MeshTest::debugPrimitive() { + std::ostringstream o; + Debug(&o) << MeshPrimitive::TriangleFan << MeshPrimitive(0xdead); + CORRADE_COMPARE(o.str(), "MeshPrimitive::TriangleFan MeshPrimitive(0xdead)\n"); +} + +void MeshTest::debugIndexType() { + std::ostringstream o; + Debug(&o) << MeshIndexType::UnsignedShort << MeshIndexType(0xdead); + CORRADE_COMPARE(o.str(), "MeshIndexType::UnsignedShort MeshIndexType(0xdead)\n"); +} + +void MeshTest::configurationPrimitive() { + Utility::Configuration c; + + c.setValue("primitive", MeshPrimitive::LineStrip); + CORRADE_COMPARE(c.value("primitive"), "LineStrip"); + CORRADE_COMPARE(c.value("primitive"), MeshPrimitive::LineStrip); + + c.setValue("invalid", MeshPrimitive(0xdead)); + CORRADE_COMPARE(c.value("invalid"), ""); + CORRADE_COMPARE(c.value("invalid"), MeshPrimitive::Points); +} + +void MeshTest::configurationIndexType() { + Utility::Configuration c; + + c.setValue("type", MeshIndexType::UnsignedShort); + CORRADE_COMPARE(c.value("type"), "UnsignedShort"); + CORRADE_COMPARE(c.value("type"), MeshIndexType::UnsignedShort); + + c.setValue("invalid", MeshIndexType(0xdead)); + CORRADE_COMPARE(c.value("invalid"), ""); + CORRADE_COMPARE(c.value("invalid"), MeshIndexType::UnsignedInt); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::MeshTest) diff --git a/src/MagnumPlugins/ObjImporter/Test/Test.cpp b/src/MagnumPlugins/ObjImporter/Test/Test.cpp index e65eaa961..7e38d7f94 100644 --- a/src/MagnumPlugins/ObjImporter/Test/Test.cpp +++ b/src/MagnumPlugins/ObjImporter/Test/Test.cpp @@ -214,7 +214,7 @@ void ObjImporterTest::mixedPrimitives() { std::ostringstream out; Error redirectError{&out}; CORRADE_VERIFY(!importer->mesh3D(0)); - CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): mixed primitive GL::MeshPrimitive::Points and GL::MeshPrimitive::Lines\n"); + CORRADE_COMPARE(out.str(), "Trade::ObjImporter::mesh3D(): mixed primitive MeshPrimitive::Points and MeshPrimitive::Lines\n"); } void ObjImporterTest::positionsOnly() {