diff --git a/doc/changelog.dox b/doc/changelog.dox index 137ca7736..f4afb5015 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -49,6 +49,7 @@ See also: @ref Vector2s, @ref Vector3s, @ref Vector4s, @ref Color3h, @ref Color4h, @ref Color3us, @ref Color4us convenience typedefs for half-float, 8- and 16-bit integer vector and color types +- New @ref VertexFormat enum for vertex formats and related utilities @subsubsection changelog-latest-new-audio Audio library diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index 37fc5c828..a1253ba6c 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -39,6 +39,7 @@ set(Magnum_GracefulAssert_SRCS ImageView.cpp Mesh.cpp PixelFormat.cpp + VertexFormat.cpp Animation/Player.cpp Animation/Interpolation.cpp) @@ -60,6 +61,7 @@ set(Magnum_HEADERS Tags.h Timeline.h Types.h + VertexFormat.h visibility.h) set(Magnum_PRIVATE_HEADERS @@ -68,7 +70,8 @@ set(Magnum_PRIVATE_HEADERS Implementation/meshIndexTypeMapping.hpp Implementation/meshPrimitiveMapping.hpp Implementation/compressedPixelFormatMapping.hpp - Implementation/pixelFormatMapping.hpp) + Implementation/pixelFormatMapping.hpp + Implementation/vertexFormatMapping.hpp) # Functionality specific to static Windows builds if(CORRADE_TARGET_WINDOWS AND NOT CORRADE_TARGET_WINDOWS_RT AND MAGNUM_BUILD_STATIC) diff --git a/src/Magnum/Implementation/vertexFormatMapping.hpp b/src/Magnum/Implementation/vertexFormatMapping.hpp new file mode 100644 index 000000000..405eaa1be --- /dev/null +++ b/src/Magnum/Implementation/vertexFormatMapping.hpp @@ -0,0 +1,38 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + 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. +*/ + +/* Each entry is just the name, for debug output and configuration to string */ +#ifdef _c +_c(Float) +_c(UnsignedByte) +_c(Byte) +_c(UnsignedShort) +_c(Short) +_c(UnsignedInt) +_c(Int) +_c(Vector2) +_c(Vector3) +_c(Vector4) +#endif diff --git a/src/Magnum/Magnum.h b/src/Magnum/Magnum.h index f169d1884..5def75eae 100644 --- a/src/Magnum/Magnum.h +++ b/src/Magnum/Magnum.h @@ -862,6 +862,7 @@ typedef BasicMutableCompressedImageView<3> MutableCompressedImageView3D; enum class MeshPrimitive: UnsignedInt; enum class MeshIndexType: UnsignedInt; +enum class VertexFormat: UnsignedInt; enum class PixelFormat: UnsignedInt; enum class CompressedPixelFormat: UnsignedInt; diff --git a/src/Magnum/PixelFormat.h b/src/Magnum/PixelFormat.h index 58c4d756b..bfcb74685 100644 --- a/src/Magnum/PixelFormat.h +++ b/src/Magnum/PixelFormat.h @@ -61,7 +61,8 @@ For D3D, corresponds to @m_class{m-doc-external} [DXGI_FORMAT](https://docs.micr and import is provided by the @ref Trade::DdsImporter "DdsImporter" plugin; for Metal, corresponds to @m_class{m-doc-external} [MTLPixelFormat](https://developer.apple.com/documentation/metal/mtlpixelformat?language=objc). See documentation of each value for more information about the mapping. -@see @ref pixelSize(), @ref CompressedPixelFormat, @ref Image, @ref ImageView +@see @ref pixelSize(), @ref CompressedPixelFormat, @ref Image, @ref ImageView, + @ref VertexFormat */ enum class PixelFormat: UnsignedInt { /* Zero reserved for an invalid format (but not being a named value) */ diff --git a/src/Magnum/Test/CMakeLists.txt b/src/Magnum/Test/CMakeLists.txt index c205c80f0..e46b1abf4 100644 --- a/src/Magnum/Test/CMakeLists.txt +++ b/src/Magnum/Test/CMakeLists.txt @@ -34,8 +34,8 @@ corrade_add_test(PixelStorageTest PixelStorageTest.cpp LIBRARIES Magnum) corrade_add_test(ResourceManagerTest ResourceManagerTest.cpp LIBRARIES Magnum) target_compile_definitions(ResourceManagerTest PRIVATE "CORRADE_GRACEFUL_ASSERT") corrade_add_test(SamplerTest SamplerTest.cpp LIBRARIES MagnumTestLib) - corrade_add_test(TagsTest TagsTest.cpp LIBRARIES Magnum) +corrade_add_test(VertexFormatTest VertexFormatTest.cpp LIBRARIES MagnumTestLib) set_target_properties( ArrayTest @@ -47,4 +47,5 @@ set_target_properties( ResourceManagerTest SamplerTest TagsTest + VertexFormatTest PROPERTIES FOLDER "Magnum/Test") diff --git a/src/Magnum/Test/MeshTest.cpp b/src/Magnum/Test/MeshTest.cpp index c121a9c72..b1e63acf1 100644 --- a/src/Magnum/Test/MeshTest.cpp +++ b/src/Magnum/Test/MeshTest.cpp @@ -29,6 +29,7 @@ #include #include "Magnum/Mesh.h" +#include "Magnum/Math/Vector4.h" namespace Magnum { namespace Test { namespace { @@ -43,6 +44,7 @@ struct MeshTest: TestSuite::Tester { void debugPrimitive(); void debugIndexType(); + void configurationPrimitive(); void configurationIndexType(); }; @@ -56,6 +58,7 @@ MeshTest::MeshTest() { &MeshTest::debugPrimitive, &MeshTest::debugIndexType, + &MeshTest::configurationPrimitive, &MeshTest::configurationIndexType}); } diff --git a/src/Magnum/Test/VertexFormatTest.cpp b/src/Magnum/Test/VertexFormatTest.cpp new file mode 100644 index 000000000..a95fef885 --- /dev/null +++ b/src/Magnum/Test/VertexFormatTest.cpp @@ -0,0 +1,139 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + 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 + +#include "Magnum/VertexFormat.h" +#include "Magnum/Math/Vector4.h" + +namespace Magnum { namespace Test { namespace { + +struct VertexFormatTest: TestSuite::Tester { + explicit VertexFormatTest(); + + void mapping(); + + void size(); + void sizeInvalid(); + + void debug(); + void configuration(); +}; + +VertexFormatTest::VertexFormatTest() { + addTests({&VertexFormatTest::mapping, + + &VertexFormatTest::size, + &VertexFormatTest::sizeInvalid, + + &VertexFormatTest::debug, + &VertexFormatTest::configuration}); +} + +void VertexFormatTest::mapping() { + /* This goes through the first 16 bits, which should be enough. Going + through 32 bits takes 8 seconds, too much. */ + UnsignedInt firstUnhandled = 0xffff; + UnsignedInt nextHandled = 1; /* 0 is an invalid type */ + for(UnsignedInt i = 1; i <= 0xffff; ++i) { + const auto type = VertexFormat(i); + /* Each case verifies: + - that the entries are ordered by number by comparing a function to + expected result (so insertion here is done in proper place) + - that there was no gap (unhandled value inside the range) */ + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic error "-Wswitch" + #endif + switch(type) { + #define _c(type) \ + case VertexFormat::type: \ + CORRADE_COMPARE(Utility::ConfigurationValue::toString(VertexFormat::type, {}), #type); \ + CORRADE_COMPARE(nextHandled, i); \ + CORRADE_COMPARE(firstUnhandled, 0xffff); \ + ++nextHandled; \ + continue; + #include "Magnum/Implementation/vertexFormatMapping.hpp" + #undef _c + } + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif + + /* Not handled by any value, remember -- we might either be at the end + of the enum range (which is okay) or some value might be unhandled + here */ + firstUnhandled = i; + } + + CORRADE_COMPARE(firstUnhandled, 0xffff); +} + +void VertexFormatTest::size() { + CORRADE_COMPARE(Magnum::vertexFormatSize(VertexFormat::Vector2), sizeof(Vector2)); + CORRADE_COMPARE(Magnum::vertexFormatSize(VertexFormat::Vector3), sizeof(Vector3)); + CORRADE_COMPARE(Magnum::vertexFormatSize(VertexFormat::Vector4), sizeof(Vector4)); +} + +void VertexFormatTest::sizeInvalid() { + std::ostringstream out; + Error redirectError{&out}; + + Magnum::vertexFormatSize(VertexFormat{}); + Magnum::vertexFormatSize(VertexFormat(0xdead)); + + CORRADE_COMPARE(out.str(), + "vertexFormatSize(): invalid format VertexFormat(0x0)\n" + "vertexFormatSize(): invalid format VertexFormat(0xdead)\n"); +} + +void VertexFormatTest::debug() { + std::ostringstream o; + Debug(&o) << VertexFormat::Vector4 << VertexFormat(0xdead); + CORRADE_COMPARE(o.str(), "VertexFormat::Vector4 VertexFormat(0xdead)\n"); +} + +void VertexFormatTest::configuration() { + Utility::Configuration c; + + c.setValue("format", VertexFormat::Vector3); + CORRADE_COMPARE(c.value("format"), "Vector3"); + CORRADE_COMPARE(c.value("format"), VertexFormat::Vector3); + + c.setValue("zero", VertexFormat{}); + CORRADE_COMPARE(c.value("zero"), ""); + CORRADE_COMPARE(c.value("zero"), VertexFormat{}); + + c.setValue("invalid", VertexFormat(0xdead)); + CORRADE_COMPARE(c.value("invalid"), ""); + CORRADE_COMPARE(c.value("invalid"), VertexFormat{}); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::Test::VertexFormatTest) diff --git a/src/Magnum/VertexFormat.cpp b/src/Magnum/VertexFormat.cpp new file mode 100644 index 000000000..344c35c2a --- /dev/null +++ b/src/Magnum/VertexFormat.cpp @@ -0,0 +1,93 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + 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 "VertexFormat.h" + +#include +#include +#include +#include + +namespace Magnum { + +UnsignedInt vertexFormatSize(const VertexFormat format) { + switch(format) { + case VertexFormat::UnsignedByte: + case VertexFormat::Byte: + return 1; + case VertexFormat::UnsignedShort: + case VertexFormat::Short: + return 2; + case VertexFormat::Float: + case VertexFormat::UnsignedInt: + case VertexFormat::Int: + return 4; + case VertexFormat::Vector2: return 8; + case VertexFormat::Vector3: return 12; + case VertexFormat::Vector4: return 16; + } + + CORRADE_ASSERT(false, "vertexFormatSize(): invalid format" << format, {}); +} + +namespace { + +constexpr const char* VertexFormatNames[] { + #define _c(format) #format, + #include "Magnum/Implementation/vertexFormatMapping.hpp" + #undef _c +}; + +} + +Debug& operator<<(Debug& debug, const VertexFormat value) { + debug << "VertexFormat" << Debug::nospace; + + if(UnsignedInt(value) - 1 < Containers::arraySize(VertexFormatNames)) { + return debug << "::" << Debug::nospace << VertexFormatNames[UnsignedInt(value) - 1]; + } + + return debug << "(" << Debug::nospace << reinterpret_cast(UnsignedInt(value)) << Debug::nospace << ")"; +} + +} + +namespace Corrade { namespace Utility { + +std::string ConfigurationValue::toString(Magnum::VertexFormat value, ConfigurationValueFlags) { + if(Magnum::UnsignedInt(value) - 1 < Containers::arraySize(Magnum::VertexFormatNames)) + return Magnum::VertexFormatNames[Magnum::UnsignedInt(value) - 1]; + + return {}; +} + +Magnum::VertexFormat ConfigurationValue::fromString(const std::string& stringValue, ConfigurationValueFlags) { + for(std::size_t i = 0; i != Containers::arraySize(Magnum::VertexFormatNames); ++i) + if(stringValue == Magnum::VertexFormatNames[i]) return Magnum::VertexFormat(i + 1); + + return {}; +} + +}} diff --git a/src/Magnum/VertexFormat.h b/src/Magnum/VertexFormat.h new file mode 100644 index 000000000..1ecdcb771 --- /dev/null +++ b/src/Magnum/VertexFormat.h @@ -0,0 +1,114 @@ +#ifndef Magnum_VertexFormat_h +#define Magnum_VertexFormat_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 + 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 Enum @ref Magnum::VertexFormat, function @ref Magnum::vertexFormatSize() + */ + +#include + +#include "Magnum/Magnum.h" +#include "Magnum/visibility.h" + +namespace Magnum { + +/** +@brief Vertex format +@m_since_latest + +Like @ref PixelFormat, but for mesh attributes --- including double-precision +types and matrices. +*/ +enum class VertexFormat: UnsignedInt { + /* Zero reserved for an invalid type (but not being a named value) */ + + Float = 1, /**< @ref Float */ + UnsignedByte, /**< @ref UnsignedByte */ + Byte, /**< @ref Byte */ + UnsignedShort, /**< @ref UnsignedShort */ + Short, /**< @ref Short */ + UnsignedInt, /**< @ref UnsignedInt */ + Int, /**< @ref Int */ + + /** + * @ref Vector2. Usually used for 2D positions and 2D texture coordinates. + */ + Vector2, + + /** + * @ref Vector3 or @ref Color3. Usually used for 3D positions, normals and + * three-component colors. + */ + Vector3, + + /** + * @ref Vector4 or @ref Color4. Usually used for four-component colors. + */ + Vector4 +}; + +/** +@brief Size of given vertex format +@m_since_latest +*/ +MAGNUM_EXPORT UnsignedInt vertexFormatSize(VertexFormat format); + +/** +@debugoperatorenum{VertexFormat} +@m_since_latest +*/ +MAGNUM_EXPORT Debug& operator<<(Debug& debug, VertexFormat value); + +} + +namespace Corrade { namespace Utility { + +/** +@configurationvalue{Magnum::VertexFormat} +@m_since_latest +*/ +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::VertexFormat value, ConfigurationValueFlags); + + /** + * @brief Read enum value as string + * + * If the value is invalid, returns a zero (invalid) type. + */ + static Magnum::VertexFormat fromString(const std::string& stringValue, ConfigurationValueFlags); +}; + +}} + +#endif