mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3261 lines
152 KiB
3261 lines
152 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019 |
|
Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
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 <sstream> |
|
#include <Corrade/TestSuite/Tester.h> |
|
#include <Corrade/TestSuite/Compare/Container.h> |
|
#include <Corrade/TestSuite/Compare/StringToFile.h> |
|
#include <Corrade/Utility/Algorithms.h> |
|
#include <Corrade/Utility/DebugStl.h> |
|
#include <Corrade/Utility/Directory.h> |
|
#include <Corrade/Utility/FormatStl.h> |
|
|
|
#include "Magnum/Math/Color.h" |
|
#include "Magnum/Math/Half.h" |
|
#include "Magnum/Trade/MeshData.h" |
|
|
|
#include "configure.h" |
|
|
|
namespace Magnum { namespace Trade { namespace Test { namespace { |
|
|
|
struct MeshDataTest: TestSuite::Tester { |
|
explicit MeshDataTest(); |
|
|
|
void customAttributeName(); |
|
void customAttributeNameTooLarge(); |
|
void customAttributeNameNotCustom(); |
|
void debugAttributeName(); |
|
|
|
void constructIndex(); |
|
void constructIndexTypeErased(); |
|
void constructIndexTypeErasedWrongSize(); |
|
void constructIndex2D(); |
|
void constructIndex2DWrongSize(); |
|
void constructIndex2DNonContiguous(); |
|
void constructIndexNullptr(); |
|
|
|
void constructAttribute(); |
|
void constructAttributeCustom(); |
|
void constructAttribute2D(); |
|
void constructAttribute2DWrongSize(); |
|
void constructAttribute2DNonContiguous(); |
|
void constructAttributeTypeErased(); |
|
void constructAttributeNullptr(); |
|
void constructAttributePadding(); |
|
void constructAttributeNonOwningArray(); |
|
void constructAttributeOffsetOnly(); |
|
void constructAttributeImplementationSpecificFormat(); |
|
void constructAttributeWrongFormat(); |
|
void constructAttributeWrongStride(); |
|
void constructAttributeWrongDataAccess(); |
|
|
|
void constructArrayAttribute(); |
|
void constructArrayAttributeNonContiguous(); |
|
void constructArrayAttribute2D(); |
|
void constructArrayAttribute2DWrongSize(); |
|
void constructArrayAttribute2DNonContiguous(); |
|
void constructArrayAttributeTypeErased(); |
|
void constructArrayAttributeOffsetOnly(); |
|
void constructArrayAttributeNotAllowed(); |
|
|
|
void construct(); |
|
|
|
void constructZeroIndices(); |
|
void constructZeroAttributes(); |
|
void constructZeroVertices(); |
|
void constructIndexless(); |
|
void constructIndexlessZeroVertices(); |
|
void constructAttributeless(); |
|
void constructIndexlessAttributeless(); |
|
void constructIndexlessAttributelessZeroVertices(); |
|
|
|
void constructNotOwned(); |
|
void constructIndicesNotOwned(); |
|
void constructVerticesNotOwned(); |
|
void constructIndexlessNotOwned(); |
|
void constructAttributelessNotOwned(); |
|
|
|
void constructIndexDataButNotIndexed(); |
|
void constructAttributelessImplicitVertexCount(); |
|
void constructIndicesNotContained(); |
|
void constructAttributeNotContained(); |
|
void constructInconsitentVertexCount(); |
|
void constructNotOwnedIndexFlagOwned(); |
|
void constructNotOwnedVertexFlagOwned(); |
|
void constructIndicesNotOwnedFlagOwned(); |
|
void constructVerticesNotOwnedFlagOwned(); |
|
void constructIndexlessNotOwnedFlagOwned(); |
|
void constructAttributelessNotOwnedFlagOwned(); |
|
void constructInvalidAttributeData(); |
|
|
|
void constructCopy(); |
|
void constructMove(); |
|
|
|
template<class T> void indicesAsArray(); |
|
void indicesIntoArrayInvalidSize(); |
|
template<class T> void positions2DAsArray(); |
|
template<class T> void positions2DAsArrayPackedUnsigned(); |
|
template<class T> void positions2DAsArrayPackedSigned(); |
|
template<class T> void positions2DAsArrayPackedUnsignedNormalized(); |
|
template<class T> void positions2DAsArrayPackedSignedNormalized(); |
|
void positions2DIntoArrayInvalidSize(); |
|
template<class T> void positions3DAsArray(); |
|
template<class T> void positions3DAsArrayPackedUnsigned(); |
|
template<class T> void positions3DAsArrayPackedSigned(); |
|
template<class T> void positions3DAsArrayPackedUnsignedNormalized(); |
|
template<class T> void positions3DAsArrayPackedSignedNormalized(); |
|
void positions3DIntoArrayInvalidSize(); |
|
template<class T> void tangentsAsArray(); |
|
template<class T> void tangentsAsArrayPackedSignedNormalized(); |
|
void tangentsIntoArrayInvalidSize(); |
|
template<class T> void bitangentSignsAsArray(); |
|
template<class T> void bitangentSignsAsArrayPackedSignedNormalized(); |
|
void bitangentSignsAsArrayNotFourComponent(); |
|
void bitangentSignsIntoArrayInvalidSize(); |
|
template<class T> void bitangentsAsArray(); |
|
template<class T> void bitangentsAsArrayPackedSignedNormalized(); |
|
void bitangentsIntoArrayInvalidSize(); |
|
template<class T> void normalsAsArray(); |
|
template<class T> void normalsAsArrayPackedSignedNormalized(); |
|
void normalsIntoArrayInvalidSize(); |
|
template<class T> void textureCoordinates2DAsArray(); |
|
template<class T> void textureCoordinates2DAsArrayPackedUnsigned(); |
|
template<class T> void textureCoordinates2DAsArrayPackedSigned(); |
|
template<class T> void textureCoordinates2DAsArrayPackedUnsignedNormalized(); |
|
template<class T> void textureCoordinates2DAsArrayPackedSignedNormalized(); |
|
void textureCoordinates2DIntoArrayInvalidSize(); |
|
template<class T> void colorsAsArray(); |
|
template<class T> void colorsAsArrayPackedUnsignedNormalized(); |
|
void colorsIntoArrayInvalidSize(); |
|
template<class T> void objectIdsAsArray(); |
|
void objectIdsIntoArrayInvalidSize(); |
|
|
|
void implementationSpecificVertexFormat(); |
|
void implementationSpecificVertexFormatWrongAccess(); |
|
void implementationSpecificVertexFormatNotContained(); |
|
|
|
void arrayAttribute(); |
|
void arrayAttributeWrongAccess(); |
|
|
|
void mutableAccessNotAllowed(); |
|
|
|
void indicesNotIndexed(); |
|
void indicesWrongType(); |
|
|
|
void attributeNotFound(); |
|
void attributeWrongType(); |
|
|
|
void releaseIndexData(); |
|
void releaseAttributeData(); |
|
void releaseVertexData(); |
|
|
|
void serialize(); |
|
void serializeEmpty(); |
|
void serializeIntoTooSmall(); |
|
|
|
void deserialize(); |
|
void deserializeInvalid(); |
|
}; |
|
|
|
const struct { |
|
const char* name; |
|
UnsignedInt vertexCount, expectedVertexCount; |
|
} ConstructData[] { |
|
{"implicit vertex count", MeshData::ImplicitVertexCount, 3}, |
|
{"explicit vertex count", 3, 3}, |
|
{"explicit large vertex count", 17, 17}, |
|
{"explicit zero vertex count", 0, 0} |
|
}; |
|
|
|
const struct { |
|
const char* name; |
|
DataFlags indexDataFlags, vertexDataFlags; |
|
} NotOwnedData[] { |
|
{"", {}, {}}, |
|
{"indices mutable", DataFlag::Mutable, {}}, |
|
{"vertices mutable", {}, DataFlag::Mutable}, |
|
{"both mutable", DataFlag::Mutable, DataFlag::Mutable} |
|
}; |
|
|
|
const struct { |
|
const char* name; |
|
DataFlags dataFlags; |
|
} SingleNotOwnedData[] { |
|
{"", {}}, |
|
{"mutable", DataFlag::Mutable} |
|
}; |
|
|
|
const struct { |
|
const char* name; |
|
const char* filePrefix; |
|
bool indexed; |
|
} SerializeData[] { |
|
{"", "mesh", true}, |
|
{"non-indexed", "mesh-nonindexed", false} |
|
}; |
|
|
|
const struct { |
|
const char* name; |
|
std::size_t size; |
|
std::size_t offset; |
|
Containers::Array<char> replace; |
|
const char* message; |
|
} DeserializeInvalidData[] { |
|
/* This checks we correctly propagate chunk header errors, the rest is |
|
verified in DataTest */ |
|
{"too short to contain a chunk header", |
|
sizeof(void*) == 4 ? 19 : 23, 0, nullptr, |
|
sizeof(void*) == 4 ? |
|
"dataChunkHeaderDeserialize(): expected at least 20 bytes for a header but got 19" : |
|
"dataChunkHeaderDeserialize(): expected at least 24 bytes for a header but got 23"}, |
|
|
|
{"chunk too short to contain a meshdata header", |
|
0, 16, /* not cutting the file, only adapting header */ |
|
#ifndef CORRADE_TARGET_BIG_ENDIAN |
|
sizeof(void*) == 4 ? Containers::array<char>({0x2f, 0, 0, 0}) : |
|
Containers::array<char>({0x3f, 0, 0, 0, 0, 0, 0, 0}), |
|
#else |
|
sizeof(void*) == 4 ? Containers::array<char>({0, 0, 0, 0x2f}) : |
|
Containers::array<char>({0, 0, 0, 0, 0, 0, 0, 0x3f}), |
|
#endif |
|
sizeof(void*) == 4 ? |
|
"MeshData::deserialize(): expected at least a 48-byte chunk for a header but got 47" : |
|
"MeshData::deserialize(): expected at least a 64-byte chunk for a header but got 63"}, |
|
{"chunk too short to contain all data", |
|
0, 16, /* not cutting the file, only adapting header */ |
|
#ifndef CORRADE_TARGET_BIG_ENDIAN |
|
sizeof(void*) == 4 ? Containers::array<char>({'\xd3', 0, 0, 0}) : |
|
Containers::array<char>({'\xf3', 0, 0, 0, 0, 0, 0, 0}), |
|
#else |
|
sizeof(void*) == 4 ? Containers::array<char>({0, 0, 0, '\xd3'}) : |
|
Containers::array<char>({0, 0, 0, 0, 0, 0, 0, '\xf3'}), |
|
#endif |
|
sizeof(void*) == 4 ? |
|
"MeshData::deserialize(): expected a 212-byte chunk but got 211" : |
|
"MeshData::deserialize(): expected a 244-byte chunk but got 243"}, |
|
{"invalid type", |
|
0, 12, Containers::array({'M', 'e', 'h', 'h'}), |
|
"MeshData::deserialize(): expected data chunk type Trade::DataChunkType('M', 'e', 's', 'h') but got Trade::DataChunkType('M', 'e', 'h', 'h')"}, |
|
{"invalid type version", |
|
0, 10, |
|
#ifndef CORRADE_TARGET_BIG_ENDIAN |
|
Containers::array<char>({1, 0}), |
|
#else |
|
Containers::array<char>({0, 1}), |
|
#endif |
|
"MeshData::deserialize(): invalid chunk type version, expected 0 but got 1"}, |
|
{"index array out of bounds", |
|
0, sizeof(void*) == 4 ? 36 : 40, |
|
#ifndef CORRADE_TARGET_BIG_ENDIAN |
|
sizeof(void*) == 4 ? Containers::array<char>({5, 0, 0, 0}) : |
|
Containers::array<char>({5, 0, 0, 0, 0, 0, 0, 0}), |
|
#else |
|
sizeof(void*) == 4 ? Containers::array<char>({0, 0, 0, 5}) : |
|
Containers::array<char>({0, 0, 0, 0, 0, 0, 0, 5}), |
|
#endif |
|
"MeshData::deserialize(): indices [5:13] out of range for 12 bytes of index data"}, |
|
{"attribute out of bounds", |
|
0, sizeof(void*) == 4 ? 48 + 20 + 16 : 64 + 24 + 16, |
|
#ifndef CORRADE_TARGET_BIG_ENDIAN |
|
sizeof(void*) == 4 ? Containers::array<char>({23, 0, 0, 0}) : |
|
Containers::array<char>({23, 0, 0, 0, 0, 0, 0, 0}), |
|
#else |
|
sizeof(void*) == 4 ? Containers::array<char>({0, 0, 0, 23}) : |
|
Containers::array<char>({0, 0, 0, 0, 0, 0, 0, 23}), |
|
#endif |
|
"MeshData::deserialize(): attribute 1 [23:73] out of range for 72 bytes of vertex data"} |
|
}; |
|
|
|
MeshDataTest::MeshDataTest() { |
|
addTests({&MeshDataTest::customAttributeName, |
|
&MeshDataTest::customAttributeNameTooLarge, |
|
&MeshDataTest::customAttributeNameNotCustom, |
|
&MeshDataTest::debugAttributeName, |
|
|
|
&MeshDataTest::constructIndex, |
|
&MeshDataTest::constructIndexTypeErased, |
|
&MeshDataTest::constructIndexTypeErasedWrongSize, |
|
&MeshDataTest::constructIndex2D, |
|
&MeshDataTest::constructIndex2DWrongSize, |
|
&MeshDataTest::constructIndex2DNonContiguous, |
|
&MeshDataTest::constructIndexNullptr, |
|
|
|
&MeshDataTest::constructAttribute, |
|
&MeshDataTest::constructAttributeCustom, |
|
&MeshDataTest::constructAttribute2D, |
|
&MeshDataTest::constructAttribute2DWrongSize, |
|
&MeshDataTest::constructAttribute2DNonContiguous, |
|
&MeshDataTest::constructAttributeTypeErased, |
|
&MeshDataTest::constructAttributeNullptr, |
|
&MeshDataTest::constructAttributePadding, |
|
&MeshDataTest::constructAttributeNonOwningArray, |
|
&MeshDataTest::constructAttributeOffsetOnly, |
|
&MeshDataTest::constructAttributeImplementationSpecificFormat, |
|
&MeshDataTest::constructAttributeWrongFormat, |
|
&MeshDataTest::constructAttributeWrongStride, |
|
&MeshDataTest::constructAttributeWrongDataAccess, |
|
|
|
&MeshDataTest::constructArrayAttribute, |
|
&MeshDataTest::constructArrayAttributeNonContiguous, |
|
&MeshDataTest::constructArrayAttribute2D, |
|
&MeshDataTest::constructArrayAttribute2DWrongSize, |
|
&MeshDataTest::constructArrayAttribute2DNonContiguous, |
|
&MeshDataTest::constructArrayAttributeTypeErased, |
|
&MeshDataTest::constructArrayAttributeOffsetOnly, |
|
&MeshDataTest::constructArrayAttributeNotAllowed}); |
|
|
|
addInstancedTests({&MeshDataTest::construct}, |
|
Containers::arraySize(ConstructData)); |
|
|
|
addTests({&MeshDataTest::constructZeroIndices, |
|
&MeshDataTest::constructZeroAttributes, |
|
&MeshDataTest::constructZeroVertices, |
|
&MeshDataTest::constructIndexless, |
|
&MeshDataTest::constructIndexlessZeroVertices, |
|
&MeshDataTest::constructAttributeless, |
|
&MeshDataTest::constructIndexlessAttributeless, |
|
&MeshDataTest::constructIndexlessAttributelessZeroVertices}); |
|
|
|
addInstancedTests({&MeshDataTest::constructNotOwned}, |
|
Containers::arraySize(NotOwnedData)); |
|
addInstancedTests({&MeshDataTest::constructIndicesNotOwned, |
|
&MeshDataTest::constructVerticesNotOwned, |
|
&MeshDataTest::constructIndexlessNotOwned, |
|
&MeshDataTest::constructAttributelessNotOwned}, |
|
Containers::arraySize(SingleNotOwnedData)); |
|
|
|
addTests({&MeshDataTest::constructIndexDataButNotIndexed, |
|
&MeshDataTest::constructAttributelessImplicitVertexCount, |
|
&MeshDataTest::constructIndicesNotContained, |
|
&MeshDataTest::constructAttributeNotContained, |
|
&MeshDataTest::constructInconsitentVertexCount, |
|
&MeshDataTest::constructNotOwnedIndexFlagOwned, |
|
&MeshDataTest::constructNotOwnedVertexFlagOwned, |
|
&MeshDataTest::constructIndicesNotOwnedFlagOwned, |
|
&MeshDataTest::constructVerticesNotOwnedFlagOwned, |
|
&MeshDataTest::constructIndexlessNotOwnedFlagOwned, |
|
&MeshDataTest::constructAttributelessNotOwnedFlagOwned, |
|
&MeshDataTest::constructInvalidAttributeData, |
|
|
|
&MeshDataTest::constructCopy, |
|
&MeshDataTest::constructMove, |
|
|
|
&MeshDataTest::indicesAsArray<UnsignedByte>, |
|
&MeshDataTest::indicesAsArray<UnsignedShort>, |
|
&MeshDataTest::indicesAsArray<UnsignedInt>, |
|
&MeshDataTest::indicesIntoArrayInvalidSize, |
|
&MeshDataTest::positions2DAsArray<Vector2>, |
|
&MeshDataTest::positions2DAsArray<Vector2h>, |
|
&MeshDataTest::positions2DAsArray<Vector3>, |
|
&MeshDataTest::positions2DAsArray<Vector3h>, |
|
&MeshDataTest::positions2DAsArrayPackedUnsigned<Vector2ub>, |
|
&MeshDataTest::positions2DAsArrayPackedUnsigned<Vector2us>, |
|
&MeshDataTest::positions2DAsArrayPackedUnsigned<Vector3ub>, |
|
&MeshDataTest::positions2DAsArrayPackedUnsigned<Vector3us>, |
|
&MeshDataTest::positions2DAsArrayPackedSigned<Vector2b>, |
|
&MeshDataTest::positions2DAsArrayPackedSigned<Vector2s>, |
|
&MeshDataTest::positions2DAsArrayPackedSigned<Vector3b>, |
|
&MeshDataTest::positions2DAsArrayPackedSigned<Vector3s>, |
|
&MeshDataTest::positions2DAsArrayPackedUnsignedNormalized<Vector2ub>, |
|
&MeshDataTest::positions2DAsArrayPackedUnsignedNormalized<Vector2us>, |
|
&MeshDataTest::positions2DAsArrayPackedUnsignedNormalized<Vector3ub>, |
|
&MeshDataTest::positions2DAsArrayPackedUnsignedNormalized<Vector3us>, |
|
&MeshDataTest::positions2DAsArrayPackedSignedNormalized<Vector2b>, |
|
&MeshDataTest::positions2DAsArrayPackedSignedNormalized<Vector2s>, |
|
&MeshDataTest::positions2DAsArrayPackedSignedNormalized<Vector3b>, |
|
&MeshDataTest::positions2DAsArrayPackedSignedNormalized<Vector3s>, |
|
&MeshDataTest::positions2DIntoArrayInvalidSize, |
|
&MeshDataTest::positions3DAsArray<Vector2>, |
|
&MeshDataTest::positions3DAsArray<Vector2h>, |
|
&MeshDataTest::positions3DAsArray<Vector3>, |
|
&MeshDataTest::positions3DAsArray<Vector3h>, |
|
&MeshDataTest::positions3DAsArrayPackedUnsigned<Vector2ub>, |
|
&MeshDataTest::positions3DAsArrayPackedUnsigned<Vector2us>, |
|
&MeshDataTest::positions3DAsArrayPackedUnsigned<Vector3ub>, |
|
&MeshDataTest::positions3DAsArrayPackedUnsigned<Vector3us>, |
|
&MeshDataTest::positions3DAsArrayPackedSigned<Vector2b>, |
|
&MeshDataTest::positions3DAsArrayPackedSigned<Vector2s>, |
|
&MeshDataTest::positions3DAsArrayPackedSigned<Vector3b>, |
|
&MeshDataTest::positions3DAsArrayPackedSigned<Vector3s>, |
|
&MeshDataTest::positions3DAsArrayPackedUnsignedNormalized<Vector2ub>, |
|
&MeshDataTest::positions3DAsArrayPackedUnsignedNormalized<Vector2us>, |
|
&MeshDataTest::positions3DAsArrayPackedUnsignedNormalized<Vector3ub>, |
|
&MeshDataTest::positions3DAsArrayPackedUnsignedNormalized<Vector3us>, |
|
&MeshDataTest::positions3DAsArrayPackedSignedNormalized<Vector2b>, |
|
&MeshDataTest::positions3DAsArrayPackedSignedNormalized<Vector2s>, |
|
&MeshDataTest::positions3DAsArrayPackedSignedNormalized<Vector3b>, |
|
&MeshDataTest::positions3DAsArrayPackedSignedNormalized<Vector3s>, |
|
&MeshDataTest::positions3DIntoArrayInvalidSize, |
|
&MeshDataTest::tangentsAsArray<Vector3>, |
|
&MeshDataTest::tangentsAsArray<Vector3h>, |
|
&MeshDataTest::tangentsAsArray<Vector4>, |
|
&MeshDataTest::tangentsAsArray<Vector4h>, |
|
&MeshDataTest::tangentsAsArrayPackedSignedNormalized<Vector3b>, |
|
&MeshDataTest::tangentsAsArrayPackedSignedNormalized<Vector3s>, |
|
&MeshDataTest::tangentsAsArrayPackedSignedNormalized<Vector4b>, |
|
&MeshDataTest::tangentsAsArrayPackedSignedNormalized<Vector4s>, |
|
&MeshDataTest::tangentsIntoArrayInvalidSize, |
|
&MeshDataTest::bitangentSignsAsArray<Float>, |
|
&MeshDataTest::bitangentSignsAsArray<Half>, |
|
&MeshDataTest::bitangentSignsAsArrayPackedSignedNormalized<Byte>, |
|
&MeshDataTest::bitangentSignsAsArrayPackedSignedNormalized<Short>, |
|
&MeshDataTest::bitangentSignsAsArrayNotFourComponent, |
|
&MeshDataTest::bitangentSignsIntoArrayInvalidSize, |
|
&MeshDataTest::bitangentsAsArray<Vector3>, |
|
&MeshDataTest::bitangentsAsArray<Vector3h>, |
|
&MeshDataTest::bitangentsAsArrayPackedSignedNormalized<Vector3b>, |
|
&MeshDataTest::bitangentsAsArrayPackedSignedNormalized<Vector3s>, |
|
&MeshDataTest::bitangentsIntoArrayInvalidSize, |
|
&MeshDataTest::normalsAsArray<Vector3>, |
|
&MeshDataTest::normalsAsArray<Vector3h>, |
|
&MeshDataTest::normalsAsArrayPackedSignedNormalized<Vector3b>, |
|
&MeshDataTest::normalsAsArrayPackedSignedNormalized<Vector3s>, |
|
&MeshDataTest::normalsIntoArrayInvalidSize, |
|
&MeshDataTest::textureCoordinates2DAsArray<Vector2>, |
|
&MeshDataTest::textureCoordinates2DAsArray<Vector2h>, |
|
&MeshDataTest::textureCoordinates2DAsArrayPackedUnsigned<Vector2ub>, |
|
&MeshDataTest::textureCoordinates2DAsArrayPackedUnsigned<Vector2us>, |
|
&MeshDataTest::textureCoordinates2DAsArrayPackedSigned<Vector2b>, |
|
&MeshDataTest::textureCoordinates2DAsArrayPackedSigned<Vector2s>, |
|
&MeshDataTest::textureCoordinates2DAsArrayPackedUnsignedNormalized<Vector2ub>, |
|
&MeshDataTest::textureCoordinates2DAsArrayPackedUnsignedNormalized<Vector2us>, |
|
&MeshDataTest::textureCoordinates2DAsArrayPackedSignedNormalized<Vector2b>, |
|
&MeshDataTest::textureCoordinates2DAsArrayPackedSignedNormalized<Vector2s>, |
|
&MeshDataTest::textureCoordinates2DIntoArrayInvalidSize, |
|
&MeshDataTest::colorsAsArray<Color3>, |
|
&MeshDataTest::colorsAsArray<Color3h>, |
|
&MeshDataTest::colorsAsArray<Color4>, |
|
&MeshDataTest::colorsAsArray<Color4h>, |
|
&MeshDataTest::colorsAsArrayPackedUnsignedNormalized<Color3ub>, |
|
&MeshDataTest::colorsAsArrayPackedUnsignedNormalized<Color3us>, |
|
&MeshDataTest::colorsAsArrayPackedUnsignedNormalized<Color4ub>, |
|
&MeshDataTest::colorsAsArrayPackedUnsignedNormalized<Color4us>, |
|
&MeshDataTest::colorsIntoArrayInvalidSize, |
|
&MeshDataTest::objectIdsAsArray<UnsignedByte>, |
|
&MeshDataTest::objectIdsAsArray<UnsignedShort>, |
|
&MeshDataTest::objectIdsAsArray<UnsignedInt>, |
|
&MeshDataTest::objectIdsIntoArrayInvalidSize, |
|
|
|
&MeshDataTest::implementationSpecificVertexFormat, |
|
&MeshDataTest::implementationSpecificVertexFormatWrongAccess, |
|
&MeshDataTest::implementationSpecificVertexFormatNotContained, |
|
|
|
&MeshDataTest::arrayAttribute, |
|
&MeshDataTest::arrayAttributeWrongAccess, |
|
|
|
&MeshDataTest::mutableAccessNotAllowed, |
|
|
|
&MeshDataTest::indicesNotIndexed, |
|
&MeshDataTest::indicesWrongType, |
|
|
|
&MeshDataTest::attributeNotFound, |
|
&MeshDataTest::attributeWrongType, |
|
|
|
&MeshDataTest::releaseIndexData, |
|
&MeshDataTest::releaseAttributeData, |
|
&MeshDataTest::releaseVertexData}); |
|
|
|
addInstancedTests({&MeshDataTest::serialize}, |
|
Containers::arraySize(SerializeData)); |
|
|
|
addTests({&MeshDataTest::serializeEmpty, |
|
&MeshDataTest::serializeIntoTooSmall}); |
|
|
|
addInstancedTests({&MeshDataTest::deserialize}, |
|
Containers::arraySize(SerializeData)); |
|
|
|
addInstancedTests({&MeshDataTest::deserializeInvalid}, |
|
Containers::arraySize(DeserializeInvalidData)); |
|
} |
|
|
|
void MeshDataTest::customAttributeName() { |
|
CORRADE_VERIFY(!isMeshAttributeCustom(MeshAttribute::Position)); |
|
CORRADE_VERIFY(!isMeshAttributeCustom(MeshAttribute(32767))); |
|
CORRADE_VERIFY(isMeshAttributeCustom(MeshAttribute::Custom)); |
|
CORRADE_VERIFY(isMeshAttributeCustom(MeshAttribute(65535))); |
|
|
|
CORRADE_COMPARE(UnsignedShort(meshAttributeCustom(0)), 32768); |
|
CORRADE_COMPARE(UnsignedShort(meshAttributeCustom(8290)), 41058); |
|
CORRADE_COMPARE(UnsignedShort(meshAttributeCustom(32767)), 65535); |
|
|
|
CORRADE_COMPARE(meshAttributeCustom(MeshAttribute::Custom), 0); |
|
CORRADE_COMPARE(meshAttributeCustom(MeshAttribute(41058)), 8290); |
|
CORRADE_COMPARE(meshAttributeCustom(MeshAttribute(65535)), 32767); |
|
|
|
constexpr bool is = isMeshAttributeCustom(MeshAttribute(41058)); |
|
CORRADE_VERIFY(is); |
|
constexpr MeshAttribute a = meshAttributeCustom(8290); |
|
CORRADE_COMPARE(UnsignedShort(a), 41058); |
|
constexpr UnsignedShort b = meshAttributeCustom(a); |
|
CORRADE_COMPARE(b, 8290); |
|
} |
|
|
|
void MeshDataTest::customAttributeNameTooLarge() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
meshAttributeCustom(32768); |
|
CORRADE_COMPARE(out.str(), "Trade::meshAttributeCustom(): index 32768 too large\n"); |
|
} |
|
|
|
void MeshDataTest::customAttributeNameNotCustom() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
meshAttributeCustom(MeshAttribute::TextureCoordinates); |
|
CORRADE_COMPARE(out.str(), "Trade::meshAttributeCustom(): Trade::MeshAttribute::TextureCoordinates is not custom\n"); |
|
} |
|
|
|
void MeshDataTest::debugAttributeName() { |
|
std::ostringstream out; |
|
Debug{&out} << MeshAttribute::Position << meshAttributeCustom(73) << MeshAttribute(0x73); |
|
CORRADE_COMPARE(out.str(), "Trade::MeshAttribute::Position Trade::MeshAttribute::Custom(73) Trade::MeshAttribute(0x73)\n"); |
|
} |
|
|
|
using namespace Math::Literals; |
|
|
|
constexpr UnsignedByte IndexBytes[]{25, 132, 3}; |
|
constexpr UnsignedShort IndexShorts[]{2575, 13224, 3}; |
|
constexpr UnsignedInt IndexInts[]{2110122, 132257, 3}; |
|
|
|
void MeshDataTest::constructIndex() { |
|
{ |
|
const UnsignedByte indexData[]{25, 132, 3}; |
|
MeshIndexData indices{indexData}; |
|
CORRADE_COMPARE(indices.type(), MeshIndexType::UnsignedByte); |
|
CORRADE_COMPARE(indices.data().data(), indexData); |
|
|
|
constexpr MeshIndexData cindices{IndexBytes}; |
|
constexpr MeshIndexType type = cindices.type(); |
|
constexpr Containers::ArrayView<const void> data = cindices.data(); |
|
CORRADE_COMPARE(type, MeshIndexType::UnsignedByte); |
|
CORRADE_COMPARE(data.data(), IndexBytes); |
|
} { |
|
const UnsignedShort indexData[]{2575, 13224, 3}; |
|
MeshIndexData indices{indexData}; |
|
CORRADE_COMPARE(indices.type(), MeshIndexType::UnsignedShort); |
|
CORRADE_COMPARE(indices.data().data(), indexData); |
|
|
|
constexpr MeshIndexData cindices{IndexShorts}; |
|
constexpr MeshIndexType type = cindices.type(); |
|
constexpr Containers::ArrayView<const void> data = cindices.data(); |
|
CORRADE_COMPARE(type, MeshIndexType::UnsignedShort); |
|
CORRADE_COMPARE(data.data(), IndexShorts); |
|
} { |
|
const UnsignedInt indexData[]{2110122, 132257, 3}; |
|
MeshIndexData indices{indexData}; |
|
CORRADE_COMPARE(indices.type(), MeshIndexType::UnsignedInt); |
|
CORRADE_COMPARE(indices.data().data(), indexData); |
|
|
|
constexpr MeshIndexData cindices{IndexInts}; |
|
constexpr MeshIndexType type = cindices.type(); |
|
constexpr Containers::ArrayView<const void> data = cindices.data(); |
|
CORRADE_COMPARE(type, MeshIndexType::UnsignedInt); |
|
CORRADE_COMPARE(data.data(), IndexInts); |
|
} |
|
} |
|
|
|
void MeshDataTest::constructIndexTypeErased() { |
|
const char indexData[3*2]{}; |
|
MeshIndexData indices{MeshIndexType::UnsignedShort, indexData}; |
|
CORRADE_COMPARE(indices.type(), MeshIndexType::UnsignedShort); |
|
CORRADE_VERIFY(indices.data().data() == indexData); |
|
} |
|
|
|
void MeshDataTest::constructIndexTypeErasedWrongSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const char indexData[3*2]{}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshIndexData{MeshIndexType::UnsignedInt, indexData}; |
|
CORRADE_COMPARE(out.str(), "Trade::MeshIndexData: view size 6 does not correspond to MeshIndexType::UnsignedInt\n"); |
|
} |
|
|
|
void MeshDataTest::constructIndex2D() { |
|
{ |
|
const UnsignedByte indexData[]{25, 132, 3}; |
|
MeshIndexData indices{Containers::arrayCast<2, const char>(Containers::stridedArrayView(indexData))}; |
|
CORRADE_COMPARE(indices.type(), MeshIndexType::UnsignedByte); |
|
CORRADE_COMPARE(indices.data().data(), indexData); |
|
} { |
|
const UnsignedShort indexData[]{2575, 13224, 3}; |
|
MeshIndexData indices{Containers::arrayCast<2, const char>(Containers::stridedArrayView(indexData))}; |
|
CORRADE_COMPARE(indices.type(), MeshIndexType::UnsignedShort); |
|
CORRADE_COMPARE(indices.data().data(), indexData); |
|
} { |
|
const UnsignedInt indexData[]{2110122, 132257, 3}; |
|
MeshIndexData indices{Containers::arrayCast<2, const char>(Containers::stridedArrayView(indexData))}; |
|
CORRADE_COMPARE(indices.type(), MeshIndexType::UnsignedInt); |
|
CORRADE_COMPARE(indices.data().data(), indexData); |
|
} |
|
} |
|
|
|
void MeshDataTest::constructIndex2DWrongSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const char data[3*3]{}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshIndexData{Containers::StridedArrayView2D<const char>{data, {3, 3}}}; |
|
CORRADE_COMPARE(out.str(), "Trade::MeshIndexData: expected index type size 1, 2 or 4 but got 3\n"); |
|
} |
|
|
|
void MeshDataTest::constructIndex2DNonContiguous() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const char data[3*4]{}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshIndexData{Containers::StridedArrayView2D<const char>{data, {3, 2}, {4, 2}}}; |
|
CORRADE_COMPARE(out.str(), "Trade::MeshIndexData: view is not contiguous\n"); |
|
} |
|
|
|
void MeshDataTest::constructIndexNullptr() { |
|
/* Just verify it's not ambiguous */ |
|
MeshIndexData data{nullptr}; |
|
CORRADE_VERIFY(!data.data()); |
|
} |
|
|
|
constexpr Vector2 Positions[] { |
|
{1.2f, 0.2f}, |
|
{2.2f, 1.1f}, |
|
{-0.2f, 7.2f} |
|
}; |
|
|
|
void MeshDataTest::constructAttribute() { |
|
const Vector2 positionData[3]; |
|
MeshAttributeData positions{MeshAttribute::Position, Containers::arrayView(positionData)}; |
|
CORRADE_VERIFY(!positions.isOffsetOnly()); |
|
CORRADE_COMPARE(positions.arraySize(), 0); |
|
CORRADE_COMPARE(positions.name(), MeshAttribute::Position); |
|
CORRADE_COMPARE(positions.format(), VertexFormat::Vector2); |
|
CORRADE_COMPARE(positions.offset(positionData), 0); |
|
CORRADE_COMPARE(positions.stride(), sizeof(Vector2)); |
|
CORRADE_VERIFY(positions.data().data() == positionData); |
|
/* This is allowed too for simplicity, it just ignores the parameter */ |
|
CORRADE_VERIFY(positions.data(positionData).data() == positionData); |
|
|
|
constexpr MeshAttributeData cpositions{MeshAttribute::Position, Containers::arrayView(Positions)}; |
|
constexpr bool isOffsetOnly = cpositions.isOffsetOnly(); |
|
constexpr UnsignedShort arraySize = cpositions.arraySize(); |
|
constexpr MeshAttribute name = cpositions.name(); |
|
constexpr VertexFormat format = cpositions.format(); |
|
constexpr Short stride = cpositions.stride(); |
|
constexpr Containers::StridedArrayView1D<const void> data = cpositions.data(); |
|
CORRADE_VERIFY(!isOffsetOnly); |
|
CORRADE_COMPARE(arraySize, 0); |
|
CORRADE_COMPARE(name, MeshAttribute::Position); |
|
CORRADE_COMPARE(format, VertexFormat::Vector2); |
|
CORRADE_COMPARE(stride, sizeof(Vector2)); |
|
CORRADE_COMPARE(data.data(), Positions); |
|
} |
|
|
|
void MeshDataTest::constructAttributeCustom() { |
|
const Short idData[3]{}; |
|
MeshAttributeData ids{meshAttributeCustom(13), Containers::arrayView(idData)}; |
|
CORRADE_COMPARE(ids.name(), meshAttributeCustom(13)); |
|
CORRADE_COMPARE(ids.format(), VertexFormat::Short); |
|
CORRADE_VERIFY(ids.data().data() == idData); |
|
} |
|
|
|
void MeshDataTest::constructAttribute2D() { |
|
char positionData[4*sizeof(Vector2)]{}; |
|
auto positionView = Containers::StridedArrayView2D<char>{positionData, |
|
{4, sizeof(Vector2)}}.every(2); |
|
|
|
MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector2, positionView}; |
|
CORRADE_VERIFY(!positions.isOffsetOnly()); |
|
CORRADE_COMPARE(positions.arraySize(), 0); |
|
CORRADE_COMPARE(positions.name(), MeshAttribute::Position); |
|
CORRADE_COMPARE(positions.format(), VertexFormat::Vector2); |
|
CORRADE_COMPARE(positions.data().data(), positionView.data()); |
|
} |
|
|
|
void MeshDataTest::constructAttribute2DWrongSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
char positionData[4*sizeof(Vector2)]{}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector3, |
|
Containers::StridedArrayView2D<char>{positionData, |
|
{4, sizeof(Vector2)}}.every(2)}; |
|
CORRADE_COMPARE(out.str(), "Trade::MeshAttributeData: second view dimension size 8 doesn't match VertexFormat::Vector3\n"); |
|
} |
|
|
|
void MeshDataTest::constructAttribute2DNonContiguous() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
char positionData[4*sizeof(Vector2)]{}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector2, |
|
Containers::StridedArrayView2D<char>{positionData, |
|
{2, sizeof(Vector2)*2}}.every({1, 2})}; |
|
CORRADE_COMPARE(out.str(), "Trade::MeshAttributeData: second view dimension is not contiguous\n"); |
|
} |
|
|
|
void MeshDataTest::constructAttributeTypeErased() { |
|
const Vector3 positionData[3]{}; |
|
MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector3, Containers::arrayCast<const char>(Containers::stridedArrayView(positionData))}; |
|
CORRADE_VERIFY(!positions.isOffsetOnly()); |
|
CORRADE_COMPARE(positions.arraySize(), 0); |
|
CORRADE_COMPARE(positions.name(), MeshAttribute::Position); |
|
CORRADE_COMPARE(positions.format(), VertexFormat::Vector3); |
|
CORRADE_VERIFY(positions.data().data() == positionData); |
|
} |
|
|
|
void MeshDataTest::constructAttributeNullptr() { |
|
MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector2, nullptr}; |
|
CORRADE_VERIFY(!positions.isOffsetOnly()); |
|
CORRADE_COMPARE(positions.arraySize(), 0); |
|
CORRADE_COMPARE(positions.name(), MeshAttribute::Position); |
|
CORRADE_COMPARE(positions.format(), VertexFormat::Vector2); |
|
CORRADE_VERIFY(!positions.data().data()); |
|
} |
|
|
|
void MeshDataTest::constructAttributePadding() { |
|
MeshAttributeData padding{-35}; |
|
CORRADE_VERIFY(!padding.isOffsetOnly()); |
|
CORRADE_COMPARE(padding.arraySize(), 0); |
|
CORRADE_COMPARE(padding.name(), MeshAttribute{}); |
|
CORRADE_COMPARE(padding.format(), VertexFormat{}); |
|
CORRADE_COMPARE(padding.data().size(), 0); |
|
CORRADE_COMPARE(padding.data().stride(), -35); |
|
CORRADE_VERIFY(!padding.data()); |
|
} |
|
|
|
void MeshDataTest::constructAttributeNonOwningArray() { |
|
const MeshAttributeData data[3]; |
|
Containers::Array<MeshAttributeData> array = meshAttributeDataNonOwningArray(data); |
|
CORRADE_COMPARE(array.size(), 3); |
|
CORRADE_COMPARE(static_cast<const void*>(array.data()), data); |
|
} |
|
|
|
void MeshDataTest::constructAttributeOffsetOnly() { |
|
struct { |
|
Vector2 position; |
|
Vector2 textureCoordinates; |
|
} vertexData[] { |
|
{{}, {1.0f, 0.3f}}, |
|
{{}, {0.5f, 0.7f}}, |
|
}; |
|
|
|
MeshAttributeData a{MeshAttribute::TextureCoordinates, VertexFormat::Vector2, sizeof(Vector2), 2, 2*sizeof(Vector2)}; |
|
CORRADE_VERIFY(a.isOffsetOnly()); |
|
CORRADE_COMPARE(a.arraySize(), 0); |
|
CORRADE_COMPARE(a.name(), MeshAttribute::TextureCoordinates); |
|
CORRADE_COMPARE(a.format(), VertexFormat::Vector2); |
|
CORRADE_COMPARE(a.offset(vertexData), sizeof(Vector2)); |
|
CORRADE_COMPARE(a.stride(), 2*sizeof(Vector2)); |
|
CORRADE_COMPARE_AS(Containers::arrayCast<const Vector2>(a.data(vertexData)), |
|
Containers::arrayView<Vector2>({{1.0f, 0.3f}, {0.5f, 0.7f}}), |
|
TestSuite::Compare::Container); |
|
|
|
constexpr MeshAttributeData ca{MeshAttribute::TextureCoordinates, VertexFormat::Vector2, sizeof(Vector2), 2, 2*sizeof(Vector2)}; |
|
CORRADE_VERIFY(ca.isOffsetOnly()); |
|
CORRADE_COMPARE(ca.arraySize(), 0); |
|
CORRADE_COMPARE(ca.name(), MeshAttribute::TextureCoordinates); |
|
CORRADE_COMPARE(ca.format(), VertexFormat::Vector2); |
|
CORRADE_COMPARE(ca.offset(vertexData), sizeof(Vector2)); |
|
CORRADE_COMPARE(ca.stride(), 2*sizeof(Vector2)); |
|
CORRADE_COMPARE_AS(Containers::arrayCast<const Vector2>(a.data(vertexData)), |
|
Containers::arrayView<Vector2>({{1.0f, 0.3f}, {0.5f, 0.7f}}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void MeshDataTest::constructAttributeImplementationSpecificFormat() { |
|
Vector2 positions[]{{1.0f, 0.3f}, {0.5f, 0.7f}}; |
|
|
|
/* This should not fire any asserts */ |
|
MeshAttributeData a{MeshAttribute::TextureCoordinates, vertexFormatWrap(0x3a), positions}; |
|
CORRADE_COMPARE(a.name(), MeshAttribute::TextureCoordinates); |
|
CORRADE_COMPARE(a.format(), vertexFormatWrap(0x3a)); |
|
CORRADE_COMPARE_AS(Containers::arrayCast<const Vector2>(a.data()), |
|
Containers::arrayView<Vector2>({{1.0f, 0.3f}, {0.5f, 0.7f}}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void MeshDataTest::constructAttributeWrongFormat() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Vector2 positionData[3]; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshAttributeData{MeshAttribute::Color, Containers::arrayView(positionData)}; |
|
MeshAttributeData{MeshAttribute::Color, VertexFormat::Vector2, 0, 3, sizeof(Vector2)}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshAttributeData: VertexFormat::Vector2 is not a valid format for Trade::MeshAttribute::Color\n" |
|
"Trade::MeshAttributeData: VertexFormat::Vector2 is not a valid format for Trade::MeshAttribute::Color\n"); |
|
} |
|
|
|
void MeshDataTest::constructAttributeWrongStride() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
char positionData[3*sizeof(Vector3)]{}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector3, Containers::arrayCast<const char>(positionData)}; |
|
/* We need this one to be constexpr, which means there can't be a warning |
|
about stride not matching the size */ |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector3, 0, 3*sizeof(Vector3), 1}; |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector3, Containers::StridedArrayView1D<const void>{positionData, 0, -16}}; |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector3, Containers::StridedArrayView1D<const void>{positionData, 0, 65000}}; |
|
MeshAttributeData{65000}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshAttributeData: expected stride to be positive and enough to fit VertexFormat::Vector3, got 1\n" |
|
"Trade::MeshAttributeData: expected stride to be positive and at most 32k, got -16\n" |
|
"Trade::MeshAttributeData: expected stride to be positive and at most 32k, got 65000\n" |
|
"Trade::MeshAttributeData: at most 32k padding supported, got 65000\n" |
|
); |
|
} |
|
|
|
void MeshDataTest::constructAttributeWrongDataAccess() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Vector2 positionData[3]; |
|
MeshAttributeData a{MeshAttribute::Position, Containers::arrayView(positionData)}; |
|
MeshAttributeData b{MeshAttribute::Position, VertexFormat::Vector2, 0, 3, sizeof(Vector2)}; |
|
CORRADE_VERIFY(!a.isOffsetOnly()); |
|
CORRADE_VERIFY(b.isOffsetOnly()); |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
b.data(); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshAttributeData::data(): the attribute is a relative offset, supply a data array\n"); |
|
} |
|
|
|
constexpr Vector2 ArrayVertexData[3*4] |
|
/* MSVC 2015 needs an explicit initializer. GCC 4.8 *doesn't*. */ |
|
#ifdef CORRADE_MSVC2015_COMPATIBILITY |
|
{} |
|
#endif |
|
; |
|
|
|
void MeshDataTest::constructArrayAttribute() { |
|
Vector2 vertexData[3*4]; |
|
Containers::StridedArrayView2D<Vector2> attribute{vertexData, {3, 4}}; |
|
MeshAttributeData data{meshAttributeCustom(35), attribute}; |
|
CORRADE_VERIFY(!data.isOffsetOnly()); |
|
CORRADE_COMPARE(data.name(), meshAttributeCustom(35)); |
|
CORRADE_COMPARE(data.format(), VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.arraySize(), 4); |
|
CORRADE_VERIFY(data.data().data() == vertexData); |
|
CORRADE_COMPARE(data.data().size(), 3); |
|
CORRADE_COMPARE(data.data().stride(), sizeof(Vector2)*4); |
|
|
|
constexpr Containers::StridedArrayView2D<const Vector2> cattribute{ArrayVertexData, {3, 4}}; |
|
constexpr MeshAttributeData cdata{meshAttributeCustom(35), cattribute}; |
|
CORRADE_VERIFY(!cdata.isOffsetOnly()); |
|
CORRADE_COMPARE(cdata.name(), meshAttributeCustom(35)); |
|
CORRADE_COMPARE(cdata.format(), VertexFormat::Vector2); |
|
CORRADE_COMPARE(cdata.arraySize(), 4); |
|
CORRADE_VERIFY(cdata.data().data() == ArrayVertexData); |
|
CORRADE_COMPARE(cdata.data().size(), 3); |
|
CORRADE_COMPARE(cdata.data().stride(), sizeof(Vector2)*4); |
|
} |
|
|
|
void MeshDataTest::constructArrayAttributeNonContiguous() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Vector2 vertexData[4*3]{}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshAttributeData{meshAttributeCustom(35), |
|
Containers::StridedArrayView2D<Vector2>{vertexData, |
|
{4, 3}}.every({1, 2})}; |
|
CORRADE_COMPARE(out.str(), "Trade::MeshAttributeData: second view dimension is not contiguous\n"); |
|
} |
|
|
|
void MeshDataTest::constructArrayAttribute2D() { |
|
char vertexData[3*4*sizeof(Vector2)]; |
|
MeshAttributeData data{meshAttributeCustom(35), VertexFormat::Vector2, 4, Containers::StridedArrayView2D<char>{vertexData, {3, 4*sizeof(Vector2)}}}; |
|
CORRADE_VERIFY(!data.isOffsetOnly()); |
|
CORRADE_COMPARE(data.name(), meshAttributeCustom(35)); |
|
CORRADE_COMPARE(data.format(), VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.arraySize(), 4); |
|
CORRADE_VERIFY(data.data().data() == vertexData); |
|
CORRADE_COMPARE(data.data().size(), 3); |
|
CORRADE_COMPARE(data.data().stride(), sizeof(Vector2)*4); |
|
} |
|
|
|
void MeshDataTest::constructArrayAttribute2DWrongSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
char vertexData[3*4*sizeof(Vector2)]{}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshAttributeData{meshAttributeCustom(35), VertexFormat::Vector2, 3, |
|
Containers::StridedArrayView2D<char>{vertexData, |
|
{3, 4*sizeof(Vector2)}}}; |
|
CORRADE_COMPARE(out.str(), "Trade::MeshAttributeData: second view dimension size 32 doesn't match VertexFormat::Vector2 and array size 3\n"); |
|
} |
|
|
|
void MeshDataTest::constructArrayAttribute2DNonContiguous() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
char vertexData[4*3*sizeof(Vector2)]{}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshAttributeData{meshAttributeCustom(35), VertexFormat::Vector2, 2, |
|
Containers::StridedArrayView2D<char>{vertexData, |
|
{3, sizeof(Vector2)*4}}.every({1, 2})}; |
|
CORRADE_COMPARE(out.str(), "Trade::MeshAttributeData: second view dimension is not contiguous\n"); |
|
} |
|
|
|
void MeshDataTest::constructArrayAttributeTypeErased() { |
|
Vector2 vertexData[3*4]; |
|
Containers::StridedArrayView1D<Vector2> attribute{vertexData, 3, 4*sizeof(Vector2)}; |
|
MeshAttributeData data{meshAttributeCustom(35), VertexFormat::Vector2, 4, attribute}; |
|
CORRADE_VERIFY(!data.isOffsetOnly()); |
|
CORRADE_COMPARE(data.name(), meshAttributeCustom(35)); |
|
CORRADE_COMPARE(data.format(), VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.arraySize(), 4); |
|
CORRADE_VERIFY(data.data().data() == vertexData); |
|
CORRADE_COMPARE(data.data().size(), 3); |
|
CORRADE_COMPARE(data.data().stride(), sizeof(Vector2)*4); |
|
} |
|
|
|
void MeshDataTest::constructArrayAttributeOffsetOnly() { |
|
MeshAttributeData data{meshAttributeCustom(35), VertexFormat::Vector2, sizeof(Vector2), 3, sizeof(Vector2), 4}; |
|
CORRADE_VERIFY(data.isOffsetOnly()); |
|
CORRADE_COMPARE(data.name(), meshAttributeCustom(35)); |
|
CORRADE_COMPARE(data.format(), VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.arraySize(), 4); |
|
|
|
Vector2 vertexData[1 + 3*4]; |
|
CORRADE_VERIFY(data.data(vertexData).data() == vertexData + 1); |
|
CORRADE_COMPARE(data.data(vertexData).size(), 3); |
|
CORRADE_COMPARE(data.data(vertexData).stride(), sizeof(Vector2)); |
|
|
|
constexpr MeshAttributeData cdata{meshAttributeCustom(35), VertexFormat::Vector2, sizeof(Vector2), 3, sizeof(Vector2), 4}; |
|
CORRADE_VERIFY(cdata.isOffsetOnly()); |
|
CORRADE_COMPARE(cdata.name(), meshAttributeCustom(35)); |
|
CORRADE_COMPARE(cdata.format(), VertexFormat::Vector2); |
|
CORRADE_COMPARE(cdata.arraySize(), 4); |
|
} |
|
|
|
void MeshDataTest::constructArrayAttributeNotAllowed() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Vector2 positionData[3*3]; |
|
Containers::ArrayView<Vector2> positions{positionData}; |
|
Containers::StridedArrayView2D<Vector2> positions2D{positionData, {3, 3}}; |
|
auto positions2Dchar = Containers::arrayCast<2, const char>(positions2D); |
|
|
|
/* This is all fine */ |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector2, 0, positions}; |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector2, 0, 3, 6*sizeof(Vector2), 0}; |
|
MeshAttributeData{meshAttributeCustom(35), vertexFormatWrap(0xdead), 0, positions}; |
|
MeshAttributeData{meshAttributeCustom(35), positions2D}; |
|
MeshAttributeData{meshAttributeCustom(35), VertexFormat::Vector2, 3, positions2Dchar}; |
|
MeshAttributeData{meshAttributeCustom(35), VertexFormat::Vector2, 0, 3, 6*sizeof(Vector2), 3}; |
|
|
|
/* This is not */ |
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector2, 3, Containers::arrayView(positionData)}; |
|
MeshAttributeData{meshAttributeCustom(35), vertexFormatWrap(0xdead), 3, Containers::arrayView(positionData)}; |
|
MeshAttributeData{MeshAttribute::Position, positions2D}; |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector2, 3, positions2Dchar}; |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector2, 0, 3, 6*sizeof(Vector2), 3}; |
|
MeshAttributeData{meshAttributeCustom(35), vertexFormatWrap(0xdead), 0, 3, 6*sizeof(Vector2), 3}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshAttributeData: Trade::MeshAttribute::Position can't be an array attribute\n" |
|
"Trade::MeshAttributeData: array attributes can't have an implementation-specific format\n" |
|
"Trade::MeshAttributeData: Trade::MeshAttribute::Position can't be an array attribute\n" |
|
"Trade::MeshAttributeData: Trade::MeshAttribute::Position can't be an array attribute\n" |
|
"Trade::MeshAttributeData: Trade::MeshAttribute::Position can't be an array attribute\n" |
|
"Trade::MeshAttributeData: array attributes can't have an implementation-specific format\n"); |
|
} |
|
|
|
void MeshDataTest::construct() { |
|
auto&& instanceData = ConstructData[testCaseInstanceId()]; |
|
setTestCaseDescription(instanceData.name); |
|
|
|
struct Vertex { |
|
Vector3 position; |
|
Vector3 normal; |
|
Vector2 textureCoordinate; |
|
Short id; |
|
}; |
|
|
|
Containers::Array<char> indexData{8*sizeof(UnsignedShort)}; |
|
auto indexView = Containers::arrayCast<UnsignedShort>(indexData).slice(1, 7); |
|
indexView[0] = 0; |
|
indexView[1] = 1; |
|
indexView[2] = 2; |
|
indexView[3] = 0; |
|
indexView[4] = 2; |
|
indexView[5] = 1; |
|
|
|
/* Enough vertex data to fit also the case with large explicit vertex count |
|
(but fill just the first 3, as those are only tested) */ |
|
Containers::Array<char> vertexData{17*sizeof(Vertex)}; |
|
auto vertexView = Containers::arrayCast<Vertex>(vertexData).prefix(3); |
|
vertexView[0].position = {0.1f, 0.2f, 0.3f}; |
|
vertexView[1].position = {0.4f, 0.5f, 0.6f}; |
|
vertexView[2].position = {0.7f, 0.8f, 0.9f}; |
|
vertexView[0].normal = Vector3::xAxis(); |
|
vertexView[1].normal = Vector3::yAxis(); |
|
vertexView[2].normal = Vector3::zAxis(); |
|
vertexView[0].textureCoordinate = {0.000f, 0.125f}; |
|
vertexView[1].textureCoordinate = {0.250f, 0.375f}; |
|
vertexView[2].textureCoordinate = {0.500f, 0.625f}; |
|
vertexView[0].id = 15; |
|
vertexView[1].id = -374; |
|
vertexView[2].id = 22; |
|
|
|
if(instanceData.vertexCount < 3) |
|
vertexView = vertexView.prefix(instanceData.vertexCount); |
|
|
|
int importerState; |
|
MeshIndexData indices{indexView}; |
|
MeshAttributeData positions{MeshAttribute::Position, |
|
Containers::StridedArrayView1D<Vector3>{vertexData, &vertexView[0].position, vertexView.size(), sizeof(Vertex)}}; |
|
/* Using a relative offset */ |
|
MeshAttributeData normals{MeshAttribute::Normal, |
|
VertexFormat::Vector3, offsetof(Vertex, normal), |
|
UnsignedInt(vertexView.size()), sizeof(Vertex)}; |
|
MeshAttributeData textureCoordinates{MeshAttribute::TextureCoordinates, |
|
Containers::StridedArrayView1D<Vector2>{vertexData, &vertexView[0].textureCoordinate, vertexView.size(), sizeof(Vertex)}}; |
|
MeshAttributeData ids{meshAttributeCustom(13), |
|
Containers::StridedArrayView1D<Short>{vertexData, &vertexView[0].id, vertexView.size(), sizeof(Vertex)}}; |
|
MeshData data{MeshPrimitive::Triangles, |
|
std::move(indexData), indices, |
|
/* Texture coordinates deliberately twice (though aliased) */ |
|
std::move(vertexData), {positions, textureCoordinates, normals, textureCoordinates, ids}, instanceData.vertexCount, &importerState}; |
|
|
|
/* Basics */ |
|
CORRADE_COMPARE(data.indexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.vertexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.primitive(), MeshPrimitive::Triangles); |
|
CORRADE_VERIFY(!data.attributeData().empty()); |
|
CORRADE_COMPARE(static_cast<const void*>(data.indexData() + 2), indexView.data()); |
|
CORRADE_COMPARE(static_cast<const void*>(data.vertexData()), vertexView.data()); |
|
CORRADE_COMPARE(static_cast<void*>(data.mutableIndexData() + 2), indexView.data()); |
|
CORRADE_COMPARE(static_cast<void*>(data.mutableVertexData()), vertexView.data()); |
|
CORRADE_COMPARE(data.importerState(), &importerState); |
|
|
|
/* Index access */ |
|
CORRADE_VERIFY(data.isIndexed()); |
|
CORRADE_COMPARE(data.indexCount(), 6); |
|
CORRADE_COMPARE(data.indexType(), MeshIndexType::UnsignedShort); |
|
CORRADE_COMPARE(data.indexOffset(), 2); |
|
|
|
/* Typeless index access with a cast later */ |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(data.indices())[1]), 1); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(data.indices())[3]), 0); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(data.indices())[4]), 2); |
|
|
|
/* Typed index access */ |
|
CORRADE_COMPARE(data.indices<UnsignedShort>()[0], 0); |
|
CORRADE_COMPARE(data.indices<UnsignedShort>()[2], 2); |
|
CORRADE_COMPARE(data.indices<UnsignedShort>()[5], 1); |
|
|
|
/* Attribute access by ID */ |
|
CORRADE_COMPARE(data.vertexCount(), instanceData.expectedVertexCount); |
|
CORRADE_COMPARE(data.attributeCount(), 5); |
|
CORRADE_COMPARE(data.attributeName(0), MeshAttribute::Position); |
|
CORRADE_COMPARE(data.attributeName(1), MeshAttribute::TextureCoordinates); |
|
CORRADE_COMPARE(data.attributeName(2), MeshAttribute::Normal); |
|
CORRADE_COMPARE(data.attributeName(3), MeshAttribute::TextureCoordinates); |
|
CORRADE_COMPARE(data.attributeName(4), meshAttributeCustom(13)); |
|
CORRADE_COMPARE(data.attributeFormat(0), VertexFormat::Vector3); |
|
CORRADE_COMPARE(data.attributeFormat(1), VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.attributeFormat(2), VertexFormat::Vector3); |
|
CORRADE_COMPARE(data.attributeFormat(3), VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.attributeFormat(4), VertexFormat::Short); |
|
CORRADE_COMPARE(data.attributeOffset(0), 0); |
|
CORRADE_COMPARE(data.attributeOffset(1), 2*sizeof(Vector3)); |
|
CORRADE_COMPARE(data.attributeOffset(2), sizeof(Vector3)); |
|
CORRADE_COMPARE(data.attributeOffset(3), 2*sizeof(Vector3)); |
|
CORRADE_COMPARE(data.attributeOffset(4), 2*sizeof(Vector3) + sizeof(Vector2)); |
|
CORRADE_COMPARE(data.attributeStride(0), sizeof(Vertex)); |
|
CORRADE_COMPARE(data.attributeStride(1), sizeof(Vertex)); |
|
CORRADE_COMPARE(data.attributeStride(2), sizeof(Vertex)); |
|
CORRADE_COMPARE(data.attributeStride(3), sizeof(Vertex)); |
|
CORRADE_COMPARE(data.attributeArraySize(0), 0); |
|
CORRADE_COMPARE(data.attributeArraySize(1), 0); |
|
CORRADE_COMPARE(data.attributeArraySize(2), 0); |
|
CORRADE_COMPARE(data.attributeArraySize(3), 0); |
|
CORRADE_COMPARE(data.attributeArraySize(4), 0); |
|
|
|
/* Typeless access by ID with a cast later */ |
|
CORRADE_COMPARE(data.attribute(0).size()[0], instanceData.expectedVertexCount); |
|
CORRADE_COMPARE(data.mutableAttribute(0).size()[0], instanceData.expectedVertexCount); |
|
if(instanceData.vertexCount) { |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Vector3>( |
|
data.attribute(0))[1]), (Vector3{0.4f, 0.5f, 0.6f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Vector2>( |
|
data.attribute(1))[0]), (Vector2{0.000f, 0.125f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Vector3>( |
|
data.attribute(2))[2]), Vector3::zAxis()); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Vector2>( |
|
data.attribute(3))[1]), (Vector2{0.250f, 0.375f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Short>( |
|
data.attribute(4))[0]), 15); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Vector3>( |
|
data.mutableAttribute(0))[1]), (Vector3{0.4f, 0.5f, 0.6f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Vector2>( |
|
data.mutableAttribute(1))[0]), (Vector2{0.000f, 0.125f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Vector3>( |
|
data.mutableAttribute(2))[2]), Vector3::zAxis()); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Vector2>( |
|
data.mutableAttribute(3))[1]), (Vector2{0.250f, 0.375f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Short>( |
|
data.mutableAttribute(4))[0]), 15); |
|
} |
|
|
|
/* Typed access by ID */ |
|
CORRADE_COMPARE(data.attribute<Vector3>(0).size(), instanceData.expectedVertexCount); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector3>(0).size(), instanceData.expectedVertexCount); |
|
if(instanceData.vertexCount) { |
|
CORRADE_COMPARE(data.attribute<Vector3>(0)[1], (Vector3{0.4f, 0.5f, 0.6f})); |
|
CORRADE_COMPARE(data.attribute<Vector2>(1)[0], (Vector2{0.000f, 0.125f})); |
|
CORRADE_COMPARE(data.attribute<Vector3>(2)[2], Vector3::zAxis()); |
|
CORRADE_COMPARE(data.attribute<Vector2>(3)[1], (Vector2{0.250f, 0.375f})); |
|
CORRADE_COMPARE(data.attribute<Short>(4)[1], -374); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector3>(0)[1], (Vector3{0.4f, 0.5f, 0.6f})); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector2>(1)[0], (Vector2{0.000f, 0.125f})); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector3>(2)[2], Vector3::zAxis()); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector2>(3)[1], (Vector2{0.250f, 0.375f})); |
|
CORRADE_COMPARE(data.mutableAttribute<Short>(4)[1], -374); |
|
} |
|
|
|
/* Raw attribute data access by ID */ |
|
CORRADE_COMPARE(data.attributeData(3).name(), MeshAttribute::TextureCoordinates); |
|
CORRADE_COMPARE(data.attributeData(3).format(), VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.attributeData(3).data().size(), instanceData.expectedVertexCount); |
|
if(instanceData.vertexCount) |
|
CORRADE_COMPARE(Containers::arrayCast<const Vector2>(data.attributeData(3).data())[1], (Vector2{0.250f, 0.375f})); |
|
|
|
/* Attribute access by name */ |
|
CORRADE_VERIFY(data.hasAttribute(MeshAttribute::Position)); |
|
CORRADE_VERIFY(data.hasAttribute(MeshAttribute::Normal)); |
|
CORRADE_VERIFY(data.hasAttribute(MeshAttribute::TextureCoordinates)); |
|
CORRADE_VERIFY(data.hasAttribute(meshAttributeCustom(13))); |
|
CORRADE_VERIFY(!data.hasAttribute(MeshAttribute::Color)); |
|
CORRADE_VERIFY(!data.hasAttribute(meshAttributeCustom(23))); |
|
CORRADE_COMPARE(data.attributeCount(MeshAttribute::Position), 1); |
|
CORRADE_COMPARE(data.attributeCount(MeshAttribute::Normal), 1); |
|
CORRADE_COMPARE(data.attributeCount(MeshAttribute::TextureCoordinates), 2); |
|
CORRADE_COMPARE(data.attributeCount(meshAttributeCustom(13)), 1); |
|
CORRADE_COMPARE(data.attributeCount(MeshAttribute::Color), 0); |
|
CORRADE_COMPARE(data.attributeCount(meshAttributeCustom(23)), 0); |
|
CORRADE_COMPARE(data.attributeId(MeshAttribute::Position), 0); |
|
CORRADE_COMPARE(data.attributeId(MeshAttribute::Normal), 2); |
|
CORRADE_COMPARE(data.attributeId(MeshAttribute::TextureCoordinates), 1); |
|
CORRADE_COMPARE(data.attributeId(MeshAttribute::TextureCoordinates, 1), 3); |
|
CORRADE_COMPARE(data.attributeId(meshAttributeCustom(13)), 4); |
|
CORRADE_COMPARE(data.attributeFormat(MeshAttribute::Position), |
|
VertexFormat::Vector3); |
|
CORRADE_COMPARE(data.attributeFormat(MeshAttribute::Normal), |
|
VertexFormat::Vector3); |
|
CORRADE_COMPARE(data.attributeFormat(MeshAttribute::TextureCoordinates, 0), |
|
VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.attributeFormat(MeshAttribute::TextureCoordinates, 1), |
|
VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.attributeFormat(meshAttributeCustom(13)), |
|
VertexFormat::Short); |
|
CORRADE_COMPARE(data.attributeOffset(MeshAttribute::Position), 0); |
|
CORRADE_COMPARE(data.attributeOffset(MeshAttribute::Normal), sizeof(Vector3)); |
|
CORRADE_COMPARE(data.attributeOffset(MeshAttribute::TextureCoordinates, 0), 2*sizeof(Vector3)); |
|
CORRADE_COMPARE(data.attributeOffset(MeshAttribute::TextureCoordinates, 1), 2*sizeof(Vector3)); CORRADE_COMPARE(data.attributeOffset(meshAttributeCustom(13)), 2*sizeof(Vector3) + sizeof(Vector2)); |
|
CORRADE_COMPARE(data.attributeStride(MeshAttribute::Position), sizeof(Vertex)); |
|
CORRADE_COMPARE(data.attributeStride(MeshAttribute::Normal), sizeof(Vertex)); |
|
CORRADE_COMPARE(data.attributeStride(MeshAttribute::TextureCoordinates, 0), sizeof(Vertex)); |
|
CORRADE_COMPARE(data.attributeStride(MeshAttribute::TextureCoordinates, 1), sizeof(Vertex)); |
|
CORRADE_COMPARE(data.attributeStride(meshAttributeCustom(13)), sizeof(Vertex)); |
|
CORRADE_COMPARE(data.attributeArraySize(MeshAttribute::Position), 0); |
|
CORRADE_COMPARE(data.attributeArraySize(MeshAttribute::Normal), 0); |
|
CORRADE_COMPARE(data.attributeArraySize(MeshAttribute::TextureCoordinates, 0), 0); |
|
CORRADE_COMPARE(data.attributeArraySize(MeshAttribute::TextureCoordinates, 1), 0); |
|
CORRADE_COMPARE(data.attributeArraySize(meshAttributeCustom(13)), 0); |
|
|
|
/* Typeless access by name with a cast later */ |
|
CORRADE_COMPARE(data.attribute(MeshAttribute::Position).size()[0], instanceData.expectedVertexCount); |
|
CORRADE_COMPARE(data.mutableAttribute(MeshAttribute::Position).size()[0], instanceData.expectedVertexCount); |
|
if(instanceData.vertexCount) { |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Vector3>( |
|
data.attribute(MeshAttribute::Position))[1]), (Vector3{0.4f, 0.5f, 0.6f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Vector3>( |
|
data.attribute(MeshAttribute::Normal))[2]), Vector3::zAxis()); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Vector2>( |
|
data.attribute(MeshAttribute::TextureCoordinates, 0))[0]), (Vector2{0.000f, 0.125f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Vector2>( |
|
data.attribute(MeshAttribute::TextureCoordinates, 1))[1]), (Vector2{0.250f, 0.375f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Short>( |
|
data.attribute(meshAttributeCustom(13)))[1]), -374); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Vector3>( |
|
data.mutableAttribute(MeshAttribute::Position))[1]), (Vector3{0.4f, 0.5f, 0.6f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Vector3>( |
|
data.mutableAttribute(MeshAttribute::Normal))[2]), Vector3::zAxis()); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Vector2>( |
|
data.mutableAttribute(MeshAttribute::TextureCoordinates, 0))[0]), (Vector2{0.000f, 0.125f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Vector2>( |
|
data.mutableAttribute(MeshAttribute::TextureCoordinates, 1))[1]), (Vector2{0.250f, 0.375f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Short>( |
|
data.mutableAttribute(meshAttributeCustom(13)))[1]), -374); |
|
} |
|
|
|
/* Typed access by name */ |
|
CORRADE_COMPARE(data.attribute(MeshAttribute::Position).size()[0], instanceData.expectedVertexCount); |
|
CORRADE_COMPARE(data.mutableAttribute(MeshAttribute::Position).size()[0], instanceData.expectedVertexCount); |
|
if(instanceData.vertexCount) { |
|
CORRADE_COMPARE(data.attribute<Vector3>(MeshAttribute::Position)[1], (Vector3{0.4f, 0.5f, 0.6f})); |
|
CORRADE_COMPARE(data.attribute<Vector3>(MeshAttribute::Normal)[2], Vector3::zAxis()); |
|
CORRADE_COMPARE(data.attribute<Vector2>(MeshAttribute::TextureCoordinates, 0)[0], (Vector2{0.000f, 0.125f})); |
|
CORRADE_COMPARE(data.attribute<Vector2>(MeshAttribute::TextureCoordinates, 1)[1], (Vector2{0.250f, 0.375f})); |
|
CORRADE_COMPARE(data.attribute<Short>(meshAttributeCustom(13))[2], 22); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector3>(MeshAttribute::Position)[1], (Vector3{0.4f, 0.5f, 0.6f})); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector3>(MeshAttribute::Normal)[2], Vector3::zAxis()); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector2>(MeshAttribute::TextureCoordinates, 0)[0], (Vector2{0.000f, 0.125f})); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector2>(MeshAttribute::TextureCoordinates, 1)[1], (Vector2{0.250f, 0.375f})); |
|
CORRADE_COMPARE(data.attribute<Short>(meshAttributeCustom(13))[2], 22); |
|
} |
|
} |
|
|
|
void MeshDataTest::constructZeroIndices() { |
|
/* This is a valid use case because this could be an empty slice of a |
|
well-defined indexed mesh. Explicitly use a non-null zero-sized array |
|
to check the importer is checking size and not pointer. */ |
|
Containers::Array<char> vertexData{3*sizeof(Vector3)}; |
|
auto vertices = Containers::arrayCast<Vector3>(vertexData); |
|
char i; |
|
Containers::Array<char> indexData{&i, 0, [](char*, std::size_t){}}; |
|
auto indices = Containers::arrayCast<UnsignedInt>(indexData); |
|
MeshAttributeData positions{MeshAttribute::Position, vertices}; |
|
MeshData data{MeshPrimitive::Triangles, |
|
std::move(indexData), MeshIndexData{indices}, |
|
std::move(vertexData), {positions}}; |
|
|
|
CORRADE_COMPARE(data.indexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_VERIFY(data.isIndexed()); |
|
CORRADE_COMPARE(data.indexType(), MeshIndexType::UnsignedInt); |
|
CORRADE_COMPARE(data.indexCount(), 0); |
|
CORRADE_COMPARE(data.vertexCount(), 3); |
|
} |
|
|
|
void MeshDataTest::constructZeroAttributes() { |
|
/* This is a valid use case because e.g. the index/vertex data can be |
|
shared by multiple meshes and this particular one is just a plain |
|
index array */ |
|
Containers::Array<char> indexData{3*sizeof(UnsignedInt)}; |
|
Containers::Array<char> vertexData{3}; |
|
auto indexView = Containers::arrayCast<UnsignedInt>(indexData); |
|
MeshData data{MeshPrimitive::Triangles, |
|
std::move(indexData), MeshIndexData{indexView}, |
|
std::move(vertexData), {}, 15}; |
|
|
|
CORRADE_COMPARE(data.indexCount(), 3); |
|
CORRADE_COMPARE(data.vertexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.attributeCount(), 0); |
|
CORRADE_VERIFY(!data.attributeData()); |
|
CORRADE_COMPARE(data.vertexData().size(), 3); |
|
CORRADE_COMPARE(data.vertexCount(), 15); |
|
} |
|
|
|
void MeshDataTest::constructZeroVertices() { |
|
/* This is a valid use case because this could be an empty slice of a |
|
well-defined indexed mesh */ |
|
Containers::Array<char> indexData{3*sizeof(UnsignedInt)}; |
|
auto indexView = Containers::arrayCast<UnsignedInt>(indexData); |
|
MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector3, nullptr}; |
|
MeshData data{MeshPrimitive::Triangles, |
|
std::move(indexData), MeshIndexData{indexView}, |
|
nullptr, {positions}}; |
|
|
|
CORRADE_COMPARE(data.indexCount(), 3); |
|
CORRADE_COMPARE(data.vertexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.attributeCount(), 1); |
|
CORRADE_COMPARE(data.attributeName(0), MeshAttribute::Position); |
|
CORRADE_COMPARE(data.attributeFormat(0), VertexFormat::Vector3); |
|
CORRADE_COMPARE(data.attribute<Vector3>(0).size(), 0); |
|
CORRADE_VERIFY(!data.vertexData()); |
|
CORRADE_COMPARE(data.vertexCount(), 0); |
|
} |
|
|
|
void MeshDataTest::constructIndexless() { |
|
Containers::Array<char> vertexData{3*sizeof(Vector2)}; |
|
auto vertexView = Containers::arrayCast<Vector2>(vertexData); |
|
vertexView[0] = {0.1f, 0.2f}; |
|
vertexView[1] = {0.4f, 0.5f}; |
|
vertexView[2] = {0.7f, 0.8f}; |
|
|
|
int importerState; |
|
MeshAttributeData positions{MeshAttribute::Position, vertexView}; |
|
MeshData data{MeshPrimitive::LineLoop, std::move(vertexData), {positions}, MeshData::ImplicitVertexCount, &importerState}; |
|
CORRADE_COMPARE(data.indexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
/* These are empty so it doesn't matter, but this is a nice non-restrictive |
|
default */ |
|
CORRADE_COMPARE(data.vertexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.primitive(), MeshPrimitive::LineLoop); |
|
CORRADE_COMPARE(data.indexData(), nullptr); |
|
CORRADE_COMPARE(data.importerState(), &importerState); |
|
|
|
CORRADE_VERIFY(!data.isIndexed()); |
|
CORRADE_COMPARE(data.vertexCount(), 3); |
|
CORRADE_COMPARE(data.attributeCount(), 1); |
|
CORRADE_COMPARE(data.attributeFormat(MeshAttribute::Position), VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.attribute<Vector2>(MeshAttribute::Position)[1], (Vector2{0.4f, 0.5f})); |
|
} |
|
|
|
void MeshDataTest::constructIndexlessZeroVertices() { |
|
MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector2, nullptr}; |
|
MeshData data{MeshPrimitive::LineLoop, nullptr, {positions}}; |
|
CORRADE_COMPARE(data.primitive(), MeshPrimitive::LineLoop); |
|
CORRADE_COMPARE(data.indexData(), nullptr); |
|
CORRADE_COMPARE(data.vertexData(), nullptr); |
|
|
|
CORRADE_VERIFY(!data.isIndexed()); |
|
CORRADE_COMPARE(data.vertexCount(), 0); |
|
CORRADE_COMPARE(data.attributeCount(), 1); |
|
CORRADE_COMPARE(data.attributeFormat(MeshAttribute::Position), VertexFormat::Vector2); |
|
} |
|
|
|
void MeshDataTest::constructAttributeless() { |
|
Containers::Array<char> indexData{6*sizeof(UnsignedInt)}; |
|
auto indexView = Containers::arrayCast<UnsignedInt>(indexData); |
|
indexView[0] = 0; |
|
indexView[1] = 1; |
|
indexView[2] = 2; |
|
indexView[3] = 0; |
|
indexView[4] = 2; |
|
indexView[5] = 1; |
|
|
|
int importerState; |
|
MeshIndexData indices{indexView}; |
|
MeshData data{MeshPrimitive::TriangleStrip, std::move(indexData), indices, 3, &importerState}; |
|
/* These are empty so it doesn't matter, but this is a nice non-restrictive |
|
default */ |
|
CORRADE_COMPARE(data.indexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.vertexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.primitive(), MeshPrimitive::TriangleStrip); |
|
CORRADE_VERIFY(!data.attributeData()); |
|
CORRADE_COMPARE(data.vertexData(), nullptr); |
|
CORRADE_COMPARE(data.importerState(), &importerState); |
|
|
|
CORRADE_VERIFY(data.isIndexed()); |
|
CORRADE_COMPARE(data.indexCount(), 6); |
|
CORRADE_COMPARE(data.indexType(), MeshIndexType::UnsignedInt); |
|
CORRADE_COMPARE(data.indices<UnsignedInt>()[0], 0); |
|
CORRADE_COMPARE(data.indices<UnsignedInt>()[2], 2); |
|
CORRADE_COMPARE(data.indices<UnsignedInt>()[5], 1); |
|
|
|
CORRADE_COMPARE(data.vertexCount(), 3); |
|
CORRADE_COMPARE(data.attributeCount(), 0); |
|
} |
|
|
|
void MeshDataTest::constructNotOwned() { |
|
auto&& instanceData = NotOwnedData[testCaseInstanceId()]; |
|
setTestCaseDescription(instanceData.name); |
|
|
|
UnsignedShort indexData[]{0, 1, 0}; |
|
Vector2 vertexData[]{{0.1f, 0.2f}, {0.4f, 0.5f}}; |
|
|
|
int importerState; |
|
MeshIndexData indices{indexData}; |
|
MeshAttributeData positions{MeshAttribute::Position, Containers::arrayView(vertexData)}; |
|
MeshData data{MeshPrimitive::Triangles, instanceData.indexDataFlags, Containers::arrayView(indexData), indices, instanceData.vertexDataFlags, Containers::arrayView(vertexData), {positions}, MeshData::ImplicitVertexCount, &importerState}; |
|
|
|
CORRADE_COMPARE(data.indexDataFlags(), instanceData.indexDataFlags); |
|
CORRADE_COMPARE(data.vertexDataFlags(), instanceData.vertexDataFlags); |
|
CORRADE_COMPARE(data.primitive(), MeshPrimitive::Triangles); |
|
CORRADE_COMPARE(static_cast<const void*>(data.indexData()), +indexData); |
|
CORRADE_COMPARE(static_cast<const void*>(data.vertexData()), +vertexData); |
|
if(instanceData.indexDataFlags & DataFlag::Mutable) |
|
CORRADE_COMPARE(static_cast<const void*>(data.mutableIndexData()), +indexData); |
|
if(instanceData.vertexDataFlags & DataFlag::Mutable) |
|
CORRADE_COMPARE(static_cast<const void*>(data.mutableVertexData()), +vertexData); |
|
CORRADE_COMPARE(data.importerState(), &importerState); |
|
|
|
CORRADE_VERIFY(data.isIndexed()); |
|
CORRADE_COMPARE(data.indexCount(), 3); |
|
CORRADE_COMPARE(data.indexType(), MeshIndexType::UnsignedShort); |
|
CORRADE_COMPARE(data.indices<UnsignedShort>()[1], 1); |
|
CORRADE_COMPARE(data.indices<UnsignedShort>()[2], 0); |
|
if(instanceData.indexDataFlags & DataFlag::Mutable) { |
|
CORRADE_COMPARE(data.mutableIndices<UnsignedShort>()[1], 1); |
|
CORRADE_COMPARE(data.mutableIndices<UnsignedShort>()[2], 0); |
|
} |
|
|
|
CORRADE_COMPARE(data.vertexCount(), 2); |
|
CORRADE_COMPARE(data.attributeCount(), 1); |
|
CORRADE_COMPARE(data.attributeName(0), MeshAttribute::Position); |
|
CORRADE_COMPARE(data.attributeFormat(0), VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.attributeOffset(0), 0); |
|
CORRADE_COMPARE(data.attributeStride(0), sizeof(Vector2)); |
|
CORRADE_COMPARE(data.attribute<Vector2>(0)[0], (Vector2{0.1f, 0.2f})); |
|
CORRADE_COMPARE(data.attribute<Vector2>(0)[1], (Vector2{0.4f, 0.5f})); |
|
if(instanceData.vertexDataFlags & DataFlag::Mutable) { |
|
CORRADE_COMPARE(data.mutableAttribute<Vector2>(0)[0], (Vector2{0.1f, 0.2f})); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector2>(0)[1], (Vector2{0.4f, 0.5f})); |
|
} |
|
} |
|
|
|
void MeshDataTest::constructIndicesNotOwned() { |
|
auto&& instanceData = SingleNotOwnedData[testCaseInstanceId()]; |
|
setTestCaseDescription(instanceData.name); |
|
|
|
UnsignedShort indexData[]{0, 1, 0}; |
|
Containers::Array<char> vertexData{2*sizeof(Vector2)}; |
|
auto vertexView = Containers::arrayCast<Vector2>(vertexData); |
|
vertexView[0] = {0.1f, 0.2f}; |
|
vertexView[1] = {0.4f, 0.5f}; |
|
|
|
int importerState; |
|
MeshIndexData indices{indexData}; |
|
MeshAttributeData positions{MeshAttribute::Position, vertexView}; |
|
MeshData data{MeshPrimitive::Triangles, instanceData.dataFlags, Containers::arrayView(indexData), indices, std::move(vertexData), {positions}, MeshData::ImplicitVertexCount, &importerState}; |
|
|
|
CORRADE_COMPARE(data.indexDataFlags(), instanceData.dataFlags); |
|
CORRADE_COMPARE(data.vertexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.primitive(), MeshPrimitive::Triangles); |
|
CORRADE_COMPARE(static_cast<const void*>(data.indexData()), +indexData); |
|
CORRADE_COMPARE(static_cast<const void*>(data.vertexData()), vertexView.data()); |
|
if(instanceData.dataFlags & DataFlag::Mutable) |
|
CORRADE_COMPARE(static_cast<const void*>(data.mutableIndexData()), +indexData); |
|
CORRADE_COMPARE(static_cast<const void*>(data.mutableVertexData()), vertexView.data()); |
|
CORRADE_COMPARE(data.importerState(), &importerState); |
|
|
|
CORRADE_VERIFY(data.isIndexed()); |
|
CORRADE_COMPARE(data.indexCount(), 3); |
|
CORRADE_COMPARE(data.indexType(), MeshIndexType::UnsignedShort); |
|
CORRADE_COMPARE(data.indices<UnsignedShort>()[1], 1); |
|
CORRADE_COMPARE(data.indices<UnsignedShort>()[2], 0); |
|
if(instanceData.dataFlags & DataFlag::Mutable) { |
|
CORRADE_COMPARE(data.mutableIndices<UnsignedShort>()[1], 1); |
|
CORRADE_COMPARE(data.mutableIndices<UnsignedShort>()[2], 0); |
|
} |
|
|
|
CORRADE_COMPARE(data.vertexCount(), 2); |
|
CORRADE_COMPARE(data.attributeCount(), 1); |
|
CORRADE_COMPARE(data.attributeName(0), MeshAttribute::Position); |
|
CORRADE_COMPARE(data.attributeFormat(0), VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.attributeOffset(0), 0); |
|
CORRADE_COMPARE(data.attributeStride(0), sizeof(Vector2)); |
|
CORRADE_COMPARE(data.attribute<Vector2>(0)[0], (Vector2{0.1f, 0.2f})); |
|
CORRADE_COMPARE(data.attribute<Vector2>(0)[1], (Vector2{0.4f, 0.5f})); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector2>(0)[0], (Vector2{0.1f, 0.2f})); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector2>(0)[1], (Vector2{0.4f, 0.5f})); |
|
} |
|
|
|
void MeshDataTest::constructVerticesNotOwned() { |
|
auto&& instanceData = SingleNotOwnedData[testCaseInstanceId()]; |
|
setTestCaseDescription(instanceData.name); |
|
|
|
Containers::Array<char> indexData{3*sizeof(UnsignedShort)}; |
|
auto indexView = Containers::arrayCast<UnsignedShort>(indexData); |
|
indexView[0] = 0; |
|
indexView[1] = 1; |
|
indexView[2] = 0; |
|
Vector2 vertexData[]{{0.1f, 0.2f}, {0.4f, 0.5f}}; |
|
|
|
int importerState; |
|
MeshIndexData indices{indexView}; |
|
MeshAttributeData positions{MeshAttribute::Position, Containers::arrayView(vertexData)}; |
|
MeshData data{MeshPrimitive::Triangles, std::move(indexData), indices, instanceData.dataFlags, Containers::arrayView(vertexData), {positions}, MeshData::ImplicitVertexCount, &importerState}; |
|
|
|
CORRADE_COMPARE(data.indexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.vertexDataFlags(), instanceData.dataFlags); |
|
CORRADE_COMPARE(data.primitive(), MeshPrimitive::Triangles); |
|
CORRADE_COMPARE(static_cast<const void*>(data.indexData()), indexView.data()); |
|
CORRADE_COMPARE(static_cast<const void*>(data.vertexData()), +vertexData); |
|
CORRADE_COMPARE(static_cast<const void*>(data.mutableIndexData()), indexView.data()); |
|
if(instanceData.dataFlags & DataFlag::Mutable) |
|
CORRADE_COMPARE(static_cast<const void*>(data.mutableVertexData()), +vertexData); |
|
CORRADE_COMPARE(data.importerState(), &importerState); |
|
|
|
CORRADE_VERIFY(data.isIndexed()); |
|
CORRADE_COMPARE(data.indexCount(), 3); |
|
CORRADE_COMPARE(data.indexType(), MeshIndexType::UnsignedShort); |
|
CORRADE_COMPARE(data.indices<UnsignedShort>()[1], 1); |
|
CORRADE_COMPARE(data.indices<UnsignedShort>()[2], 0); |
|
CORRADE_COMPARE(data.mutableIndices<UnsignedShort>()[1], 1); |
|
CORRADE_COMPARE(data.mutableIndices<UnsignedShort>()[2], 0); |
|
|
|
CORRADE_COMPARE(data.vertexCount(), 2); |
|
CORRADE_COMPARE(data.attributeCount(), 1); |
|
CORRADE_COMPARE(data.attributeName(0), MeshAttribute::Position); |
|
CORRADE_COMPARE(data.attributeFormat(0), VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.attributeOffset(0), 0); |
|
CORRADE_COMPARE(data.attributeStride(0), sizeof(Vector2)); |
|
CORRADE_COMPARE(data.attribute<Vector2>(0)[0], (Vector2{0.1f, 0.2f})); |
|
CORRADE_COMPARE(data.attribute<Vector2>(0)[1], (Vector2{0.4f, 0.5f})); |
|
if(instanceData.dataFlags & DataFlag::Mutable) { |
|
CORRADE_COMPARE(data.mutableAttribute<Vector2>(0)[0], (Vector2{0.1f, 0.2f})); |
|
CORRADE_COMPARE(data.mutableAttribute<Vector2>(0)[1], (Vector2{0.4f, 0.5f})); |
|
} |
|
} |
|
|
|
void MeshDataTest::constructIndexlessNotOwned() { |
|
auto&& instanceData = SingleNotOwnedData[testCaseInstanceId()]; |
|
setTestCaseDescription(instanceData.name); |
|
|
|
Vector2 vertexData[]{{0.1f, 0.2f}, {0.4f, 0.5f}}; |
|
|
|
int importerState; |
|
MeshAttributeData positions{MeshAttribute::Position, Containers::arrayView(vertexData)}; |
|
MeshData data{MeshPrimitive::LineLoop, instanceData.dataFlags, vertexData, {positions}, MeshData::ImplicitVertexCount, &importerState}; |
|
|
|
CORRADE_COMPARE(data.indexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.vertexDataFlags(), instanceData.dataFlags); |
|
CORRADE_COMPARE(data.primitive(), MeshPrimitive::LineLoop); |
|
CORRADE_COMPARE(data.indexData(), nullptr); |
|
if(instanceData.dataFlags & DataFlag::Mutable) |
|
CORRADE_COMPARE(data.mutableIndexData(), nullptr); |
|
CORRADE_COMPARE(data.importerState(), &importerState); |
|
|
|
CORRADE_VERIFY(!data.isIndexed()); |
|
CORRADE_COMPARE(data.vertexCount(), 2); |
|
CORRADE_COMPARE(data.attributeCount(), 1); |
|
CORRADE_COMPARE(data.attributeFormat(MeshAttribute::Position), VertexFormat::Vector2); |
|
CORRADE_COMPARE(data.attribute<Vector2>(MeshAttribute::Position)[1], (Vector2{0.4f, 0.5f})); |
|
if(instanceData.dataFlags & DataFlag::Mutable) |
|
CORRADE_COMPARE(data.mutableAttribute<Vector2>(MeshAttribute::Position)[1], (Vector2{0.4f, 0.5f})); |
|
} |
|
|
|
void MeshDataTest::constructAttributelessNotOwned() { |
|
auto&& instanceData = SingleNotOwnedData[testCaseInstanceId()]; |
|
setTestCaseDescription(instanceData.name); |
|
|
|
UnsignedShort indexData[]{0, 1, 0}; |
|
|
|
int importerState; |
|
MeshIndexData indices{indexData}; |
|
MeshData data{MeshPrimitive::TriangleStrip, instanceData.dataFlags, indexData, indices, 5, &importerState}; |
|
CORRADE_COMPARE(data.indexDataFlags(), instanceData.dataFlags); |
|
CORRADE_COMPARE(data.vertexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.primitive(), MeshPrimitive::TriangleStrip); |
|
CORRADE_VERIFY(!data.attributeData()); |
|
CORRADE_COMPARE(data.vertexData(), nullptr); |
|
if(instanceData.dataFlags & DataFlag::Mutable) |
|
CORRADE_COMPARE(data.mutableVertexData(), nullptr); |
|
CORRADE_COMPARE(data.importerState(), &importerState); |
|
|
|
CORRADE_VERIFY(data.isIndexed()); |
|
CORRADE_COMPARE(data.indexCount(), 3); |
|
CORRADE_COMPARE(data.indexType(), MeshIndexType::UnsignedShort); |
|
CORRADE_COMPARE(data.indices<UnsignedShort>()[0], 0); |
|
CORRADE_COMPARE(data.indices<UnsignedShort>()[1], 1); |
|
CORRADE_COMPARE(data.indices<UnsignedShort>()[2], 0); |
|
if(instanceData.dataFlags & DataFlag::Mutable) { |
|
CORRADE_COMPARE(data.mutableIndices<UnsignedShort>()[0], 0); |
|
CORRADE_COMPARE(data.mutableIndices<UnsignedShort>()[1], 1); |
|
CORRADE_COMPARE(data.mutableIndices<UnsignedShort>()[2], 0); |
|
} |
|
|
|
CORRADE_COMPARE(data.vertexCount(), 5); |
|
CORRADE_COMPARE(data.attributeCount(), 0); |
|
} |
|
|
|
void MeshDataTest::constructIndexlessAttributeless() { |
|
int importerState; |
|
MeshData data{MeshPrimitive::TriangleStrip, 37, &importerState}; |
|
/* These are both empty so it doesn't matter, but this is a nice |
|
non-restrictive default */ |
|
CORRADE_COMPARE(data.indexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.vertexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(data.primitive(), MeshPrimitive::TriangleStrip); |
|
CORRADE_VERIFY(!data.attributeData()); |
|
CORRADE_COMPARE(data.indexData(), nullptr); |
|
CORRADE_COMPARE(data.vertexData(), nullptr); |
|
CORRADE_COMPARE(data.importerState(), &importerState); |
|
|
|
CORRADE_VERIFY(!data.isIndexed()); |
|
CORRADE_COMPARE(data.vertexCount(), 37); |
|
CORRADE_COMPARE(data.attributeCount(), 0); |
|
} |
|
|
|
void MeshDataTest::constructIndexlessAttributelessZeroVertices() { |
|
int importerState; |
|
MeshData data{MeshPrimitive::TriangleStrip, 0, &importerState}; |
|
CORRADE_COMPARE(data.primitive(), MeshPrimitive::TriangleStrip); |
|
CORRADE_VERIFY(!data.attributeData()); |
|
CORRADE_COMPARE(data.indexData(), nullptr); |
|
CORRADE_COMPARE(data.vertexData(), nullptr); |
|
CORRADE_COMPARE(data.importerState(), &importerState); |
|
|
|
CORRADE_VERIFY(!data.isIndexed()); |
|
CORRADE_COMPARE(data.vertexCount(), 0); |
|
CORRADE_COMPARE(data.attributeCount(), 0); |
|
} |
|
|
|
void MeshDataTest::constructIndexDataButNotIndexed() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> indexData{6}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector2, nullptr}; |
|
MeshData{MeshPrimitive::Points, std::move(indexData), MeshIndexData{}, nullptr, {positions}}; |
|
CORRADE_COMPARE(out.str(), "Trade::MeshData: indexData passed for a non-indexed mesh\n"); |
|
} |
|
|
|
void MeshDataTest::constructAttributelessImplicitVertexCount() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshData{MeshPrimitive::Points, nullptr, {}}; |
|
CORRADE_COMPARE(out.str(), "Trade::MeshData: vertex count can't be implicit if there are no attributes\n"); |
|
} |
|
|
|
void MeshDataTest::constructIndicesNotContained() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> indexData{reinterpret_cast<char*>(0xbadda9), 6, [](char*, std::size_t){}}; |
|
Containers::ArrayView<UnsignedShort> indexData2{reinterpret_cast<UnsignedShort*>(0xdead), 3}; |
|
MeshIndexData indices{indexData2}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshData{MeshPrimitive::Triangles, std::move(indexData), indices, 1}; |
|
MeshData{MeshPrimitive::Triangles, nullptr, indices, 1}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData: indices [0xdead:0xdeb3] are not contained in passed indexData array [0xbadda9:0xbaddaf]\n" |
|
"Trade::MeshData: indices [0xdead:0xdeb3] are not contained in passed indexData array [0x0:0x0]\n"); |
|
} |
|
|
|
void MeshDataTest::constructAttributeNotContained() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{reinterpret_cast<char*>(0xbadda9), 24, [](char*, std::size_t){}}; |
|
Containers::ArrayView<Vector2> vertexData2{reinterpret_cast<Vector2*>(0xdead), 3}; |
|
MeshAttributeData positions{MeshAttribute::Position, Containers::arrayCast<Vector2>(vertexData)}; |
|
MeshAttributeData positions2{MeshAttribute::Position, Containers::arrayView(vertexData2)}; |
|
MeshAttributeData positions3{MeshAttribute::Position, VertexFormat::Vector2, 1, 3, 8}; |
|
/* See implementationSpecificVertexFormatNotContained() below for |
|
implementation-specific formats */ |
|
|
|
/* Here the original positions array is shrunk from 3 items to 2 and the |
|
vertex data too, which should work without asserting -- comparing just |
|
the original view would not pass, which is wrong */ |
|
MeshData{MeshPrimitive::Triangles, {}, vertexData.prefix(16), {positions}, 2}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
/* Here the original positions array is extended from 3 items to 4, which |
|
makes it not fit anymore, and thus an assert should hit -- comparing |
|
just the original view would pass, which is wrong */ |
|
MeshData{MeshPrimitive::Triangles, {}, vertexData, {positions}, 4}; |
|
MeshData{MeshPrimitive::Triangles, std::move(vertexData), {positions, positions2}}; |
|
MeshData{MeshPrimitive::Triangles, nullptr, {positions}}; |
|
MeshData{MeshPrimitive::Triangles, Containers::Array<char>{24}, {positions3}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData: attribute 0 [0xbadda9:0xbaddc9] is not contained in passed vertexData array [0xbadda9:0xbaddc1]\n" |
|
"Trade::MeshData: attribute 1 [0xdead:0xdec5] is not contained in passed vertexData array [0xbadda9:0xbaddc1]\n" |
|
"Trade::MeshData: attribute 0 [0xbadda9:0xbaddc1] is not contained in passed vertexData array [0x0:0x0]\n" |
|
"Trade::MeshData: offset attribute 0 spans 25 bytes but passed vertexData array has only 24\n"); |
|
} |
|
|
|
void MeshDataTest::constructInconsitentVertexCount() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{136}; |
|
MeshAttributeData positions{MeshAttribute::Position, Containers::arrayCast<Vector2>(vertexData).prefix(3)}; |
|
MeshAttributeData positions2{MeshAttribute::Position, Containers::arrayCast<Vector2>(vertexData).prefix(2)}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
/* The explicit vertex count should be ignored for the assertion message, |
|
we only check that all passed attribute arrays have the same vertex |
|
count. However, the actual "containment" of the attribute views is |
|
checked with the explicit vertex count -- see the |
|
constructAttributeNotContained() test above. */ |
|
MeshData{MeshPrimitive::Triangles, std::move(vertexData), {positions, positions2}, 17}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData: attribute 1 has 2 vertices but 3 expected\n"); |
|
} |
|
|
|
void MeshDataTest::constructNotOwnedIndexFlagOwned() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const UnsignedShort indexData[]{0, 1, 0}; |
|
const Vector2 vertexData[]{{0.1f, 0.2f}, {0.4f, 0.5f}}; |
|
|
|
MeshIndexData indices{indexData}; |
|
MeshAttributeData positions{MeshAttribute::Position, Containers::arrayView(vertexData)}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshData data{MeshPrimitive::Triangles, DataFlag::Owned, indexData, indices, {}, vertexData, {positions}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData: can't construct with non-owned index data but Trade::DataFlag::Owned\n"); |
|
} |
|
|
|
void MeshDataTest::constructNotOwnedVertexFlagOwned() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const UnsignedShort indexData[]{0, 1, 0}; |
|
const Vector2 vertexData[]{{0.1f, 0.2f}, {0.4f, 0.5f}}; |
|
|
|
MeshIndexData indices{indexData}; |
|
MeshAttributeData positions{MeshAttribute::Position, Containers::arrayView(vertexData)}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshData data{MeshPrimitive::Triangles, {}, indexData, indices, DataFlag::Owned, vertexData, {positions}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData: can't construct with non-owned vertex data but Trade::DataFlag::Owned\n"); |
|
} |
|
|
|
void MeshDataTest::constructIndicesNotOwnedFlagOwned() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
UnsignedShort indexData[]{0, 1, 0}; |
|
Containers::Array<char> vertexData{2*sizeof(Vector2)}; |
|
auto vertexView = Containers::arrayCast<Vector2>(vertexData); |
|
vertexView[0] = {0.1f, 0.2f}; |
|
vertexView[1] = {0.4f, 0.5f}; |
|
|
|
MeshIndexData indices{indexData}; |
|
MeshAttributeData positions{MeshAttribute::Position, vertexView}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshData data{MeshPrimitive::Triangles, DataFlag::Owned, indexData, indices, std::move(vertexData), {positions}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData: can't construct with non-owned index data but Trade::DataFlag::Owned\n"); |
|
} |
|
|
|
void MeshDataTest::constructVerticesNotOwnedFlagOwned() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> indexData{3*sizeof(UnsignedShort)}; |
|
auto indexView = Containers::arrayCast<UnsignedShort>(indexData); |
|
indexView[0] = 0; |
|
indexView[1] = 1; |
|
indexView[2] = 0; |
|
Vector2 vertexData[]{{0.1f, 0.2f}, {0.4f, 0.5f}}; |
|
|
|
MeshIndexData indices{indexView}; |
|
MeshAttributeData positions{MeshAttribute::Position, Containers::arrayView(vertexData)}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshData data{MeshPrimitive::Triangles, std::move(indexData), indices, DataFlag::Owned, vertexData, {positions}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData: can't construct with non-owned vertex data but Trade::DataFlag::Owned\n"); |
|
} |
|
|
|
void MeshDataTest::constructIndexlessNotOwnedFlagOwned() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const Vector2 vertexData[]{{0.1f, 0.2f}, {0.4f, 0.5f}}; |
|
MeshAttributeData positions{MeshAttribute::Position, Containers::arrayView(vertexData)}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshData data{MeshPrimitive::Triangles, DataFlag::Owned, vertexData, {positions}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData: can't construct with non-owned vertex data but Trade::DataFlag::Owned\n"); |
|
} |
|
|
|
void MeshDataTest::constructAttributelessNotOwnedFlagOwned() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const UnsignedShort indexData[]{0, 1, 0}; |
|
MeshIndexData indices{indexData}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshData data{MeshPrimitive::Triangles, DataFlag::Owned, indexData, indices, 2}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData: can't construct with non-owned index data but Trade::DataFlag::Owned\n"); |
|
} |
|
|
|
void MeshDataTest::constructInvalidAttributeData() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
MeshAttributeData a; |
|
MeshAttributeData b{3}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshData{MeshPrimitive::Triangles, nullptr, {a}}; |
|
MeshData{MeshPrimitive::Triangles, nullptr, {b}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData: attribute 0 doesn't specify anything\n" |
|
"Trade::MeshData: attribute 0 doesn't specify anything\n"); |
|
} |
|
|
|
void MeshDataTest::constructCopy() { |
|
CORRADE_VERIFY(!(std::is_constructible<MeshData, const MeshData&>{})); |
|
CORRADE_VERIFY(!(std::is_assignable<MeshData, const MeshData&>{})); |
|
} |
|
|
|
void MeshDataTest::constructMove() { |
|
Containers::Array<char> indexData{3*sizeof(UnsignedShort)}; |
|
auto indexView = Containers::arrayCast<UnsignedShort>(indexData); |
|
indexView[0] = 0; |
|
indexView[1] = 1; |
|
indexView[2] = 0; |
|
|
|
Containers::Array<char> vertexData{2*sizeof(Vector2)}; |
|
auto vertexView = Containers::arrayCast<Vector2>(vertexData); |
|
vertexView[0] = {0.1f, 0.2f}; |
|
vertexView[1] = {0.4f, 0.5f}; |
|
|
|
int importerState; |
|
MeshIndexData indices{indexView}; |
|
MeshAttributeData positions{MeshAttribute::Position, vertexView}; |
|
MeshData a{MeshPrimitive::Triangles, std::move(indexData), indices, std::move(vertexData), {positions}, MeshData::ImplicitVertexCount, &importerState}; |
|
|
|
MeshData b{std::move(a)}; |
|
|
|
CORRADE_COMPARE(b.indexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(b.vertexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(b.primitive(), MeshPrimitive::Triangles); |
|
CORRADE_COMPARE(static_cast<const void*>(b.indexData()), indexView.data()); |
|
CORRADE_COMPARE(static_cast<const void*>(b.vertexData()), vertexView.data()); |
|
CORRADE_COMPARE(b.importerState(), &importerState); |
|
|
|
CORRADE_VERIFY(b.isIndexed()); |
|
CORRADE_COMPARE(b.indexCount(), 3); |
|
CORRADE_COMPARE(b.indexType(), MeshIndexType::UnsignedShort); |
|
CORRADE_COMPARE(b.indices<UnsignedShort>()[1], 1); |
|
CORRADE_COMPARE(b.indices<UnsignedShort>()[2], 0); |
|
|
|
CORRADE_COMPARE(b.vertexCount(), 2); |
|
CORRADE_COMPARE(b.attributeCount(), 1); |
|
CORRADE_COMPARE(b.attributeName(0), MeshAttribute::Position); |
|
CORRADE_COMPARE(b.attributeFormat(0), VertexFormat::Vector2); |
|
CORRADE_COMPARE(b.attributeOffset(0), 0); |
|
CORRADE_COMPARE(b.attributeStride(0), sizeof(Vector2)); |
|
CORRADE_COMPARE(b.attribute<Vector2>(0)[0], (Vector2{0.1f, 0.2f})); |
|
CORRADE_COMPARE(b.attribute<Vector2>(0)[1], (Vector2{0.4f, 0.5f})); |
|
|
|
MeshData c{MeshPrimitive::LineLoop, 37}; |
|
c = std::move(b); |
|
|
|
CORRADE_COMPARE(c.indexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(c.vertexDataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(c.primitive(), MeshPrimitive::Triangles); |
|
CORRADE_COMPARE(static_cast<const void*>(c.indexData()), indexView.data()); |
|
CORRADE_COMPARE(static_cast<const void*>(c.vertexData()), vertexView.data()); |
|
CORRADE_COMPARE(c.importerState(), &importerState); |
|
|
|
CORRADE_VERIFY(c.isIndexed()); |
|
CORRADE_COMPARE(c.indexCount(), 3); |
|
CORRADE_COMPARE(c.indexType(), MeshIndexType::UnsignedShort); |
|
CORRADE_COMPARE(c.indices<UnsignedShort>()[1], 1); |
|
CORRADE_COMPARE(c.indices<UnsignedShort>()[2], 0); |
|
|
|
CORRADE_COMPARE(c.vertexCount(), 2); |
|
CORRADE_COMPARE(c.attributeCount(), 1); |
|
CORRADE_COMPARE(c.attributeName(0), MeshAttribute::Position); |
|
CORRADE_COMPARE(c.attributeFormat(0), VertexFormat::Vector2); |
|
CORRADE_COMPARE(c.attributeOffset(0), 0); |
|
CORRADE_COMPARE(c.attributeStride(0), sizeof(Vector2)); |
|
CORRADE_COMPARE(c.attribute<Vector2>(0)[0], (Vector2{0.1f, 0.2f})); |
|
CORRADE_COMPARE(c.attribute<Vector2>(0)[1], (Vector2{0.4f, 0.5f})); |
|
|
|
CORRADE_VERIFY(std::is_nothrow_move_constructible<MeshData>::value); |
|
CORRADE_VERIFY(std::is_nothrow_move_assignable<MeshData>::value); |
|
} |
|
|
|
template<class> struct NameTraits; |
|
#define _c(format) template<> struct NameTraits<format> { \ |
|
static const char* name() { return #format; } \ |
|
}; |
|
_c(Vector2) |
|
_c(Vector2h) |
|
_c(Vector2ub) |
|
_c(Vector2b) |
|
_c(Vector2us) |
|
_c(Vector2s) |
|
_c(Vector3) |
|
_c(Vector3h) |
|
_c(Vector3ub) |
|
_c(Vector3b) |
|
_c(Vector3us) |
|
_c(Vector3s) |
|
_c(Vector4) |
|
_c(Vector4h) |
|
_c(Vector4b) |
|
_c(Vector4s) |
|
_c(Color3) |
|
_c(Color3h) |
|
_c(Color3ub) |
|
_c(Color3us) |
|
_c(Color4) |
|
_c(Color4h) |
|
_c(Color4ub) |
|
_c(Color4us) |
|
#undef _c |
|
|
|
template<class T> void MeshDataTest::indicesAsArray() { |
|
setTestCaseTemplateName(Math::TypeTraits<T>::name()); |
|
|
|
Containers::Array<char> indexData{3*sizeof(T)}; |
|
auto indexView = Containers::arrayCast<T>(indexData); |
|
indexView[0] = 75; |
|
indexView[1] = 131; |
|
indexView[2] = 240; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(indexData), MeshIndexData{indexView}, 241}; |
|
CORRADE_COMPARE_AS(data.indicesAsArray(), |
|
Containers::arrayView<UnsignedInt>({75, 131, 240}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void MeshDataTest::indicesIntoArrayInvalidSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> indexData{3*sizeof(UnsignedInt)}; |
|
MeshData data{MeshPrimitive::Points, std::move(indexData), MeshIndexData{Containers::arrayCast<UnsignedInt>(indexData)}, 1}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
UnsignedInt destination[2]; |
|
data.indicesInto(destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::indicesInto(): expected a view with 3 elements but got 2\n"); |
|
} |
|
|
|
template<class T> void MeshDataTest::positions2DAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
typedef typename T::Type U; |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto positionsView = Containers::arrayCast<T>(vertexData); |
|
positionsView[0] = T::pad(Math::Vector2<U>{U(2.0f), U(1.0f)}); |
|
positionsView[1] = T::pad(Math::Vector2<U>{U(0.0f), U(-1.0f)}); |
|
positionsView[2] = T::pad(Math::Vector2<U>{U(-2.0f), U(3.0f)}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Position, positionsView}}}; |
|
CORRADE_COMPARE_AS(data.positions2DAsArray(), |
|
Containers::arrayView<Vector2>({{2.0f, 1.0f}, {0.0f, -1.0f}, {-2.0f, 3.0f}}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::positions2DAsArrayPackedUnsigned() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto positionsView = Containers::arrayCast<T>(vertexData); |
|
positionsView[0] = T::pad(Math::Vector2<typename T::Type>{2, 1}); |
|
positionsView[1] = T::pad(Math::Vector2<typename T::Type>{0, 15}); |
|
positionsView[2] = T::pad(Math::Vector2<typename T::Type>{22, 3}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Position, positionsView}}}; |
|
CORRADE_COMPARE_AS(data.positions2DAsArray(), |
|
Containers::arrayView<Vector2>({{2.0f, 1.0f}, {0.0f, 15.0f}, {22.0f, 3.0f}}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::positions2DAsArrayPackedSigned() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto positionsView = Containers::arrayCast<T>(vertexData); |
|
positionsView[0] = T::pad(Math::Vector2<typename T::Type>{2, 1}); |
|
positionsView[1] = T::pad(Math::Vector2<typename T::Type>{0, -15}); |
|
positionsView[2] = T::pad(Math::Vector2<typename T::Type>{-22, 3}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Position, positionsView}}}; |
|
CORRADE_COMPARE_AS(data.positions2DAsArray(), |
|
Containers::arrayView<Vector2>({{2.0f, 1.0f}, {0.0f, -15.0f}, {-22.0f, 3.0f}}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::positions2DAsArrayPackedUnsignedNormalized() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{2*sizeof(T)}; |
|
auto positionsView = Containers::arrayCast<T>(vertexData); |
|
positionsView[0] = T::pad(Math::Vector2<typename T::Type>{Math::pack<typename T::Type>(1.0f), 0}); |
|
positionsView[1] = T::pad(Math::Vector2<typename T::Type>{0, Math::pack<typename T::Type>(1.0f)}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Position, |
|
/* Assuming the normalized enum is always after the non-normalized */ |
|
VertexFormat(UnsignedInt(Implementation::vertexFormatFor<T>()) + 1), |
|
positionsView}}}; |
|
CORRADE_COMPARE_AS(data.positions2DAsArray(), |
|
Containers::arrayView<Vector2>({{1.0f, 0.0f}, {0.0f, 1.0f}}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::positions2DAsArrayPackedSignedNormalized() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{2*sizeof(T)}; |
|
auto positionsView = Containers::arrayCast<T>(vertexData); |
|
positionsView[0] = T::pad(Math::Vector2<typename T::Type>{Math::pack<typename T::Type>(1.0f), 0}); |
|
positionsView[1] = T::pad(Math::Vector2<typename T::Type>{0, Math::pack<typename T::Type>(-1.0f)}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Position, |
|
/* Assuming the normalized enum is always after the non-normalized */ |
|
VertexFormat(UnsignedInt(Implementation::vertexFormatFor<T>()) + 1), |
|
positionsView}}}; |
|
CORRADE_COMPARE_AS(data.positions2DAsArray(), |
|
Containers::arrayView<Vector2>({{1.0f, 0.0f}, {0.0f, -1.0f}}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void MeshDataTest::positions2DIntoArrayInvalidSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{3*sizeof(Vector2)}; |
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Position, Containers::arrayCast<Vector2>(vertexData)}}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Vector2 destination[2]; |
|
data.positions2DInto(destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::positions2DInto(): expected a view with 3 elements but got 2\n"); |
|
} |
|
|
|
template<class T> void MeshDataTest::positions3DAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
typedef typename T::Type U; |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto positionsView = Containers::arrayCast<T>(vertexData); |
|
/* Needs to be sufficiently representable to have the test work also for |
|
half floats */ |
|
positionsView[0] = T::pad(Math::Vector3<U>{U(2.0f), U(1.0f), U(0.75f)}); |
|
positionsView[1] = T::pad(Math::Vector3<U>{U(0.0f), U(-1.0f), U(1.25f)}); |
|
positionsView[2] = T::pad(Math::Vector3<U>{U(-2.0f), U(3.0f), U(2.5f)}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Position, positionsView}}}; |
|
CORRADE_COMPARE_AS(data.positions3DAsArray(), Containers::arrayView<Vector3>({ |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{2.0f, 1.0f, 0.75f})), |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{0.0f, -1.0f, 1.25f})), |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{-2.0f, 3.0f, 2.5f})) |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::positions3DAsArrayPackedUnsigned() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto positionsView = Containers::arrayCast<T>(vertexData); |
|
positionsView[0] = T::pad(Math::Vector3<typename T::Type>{2, 1, 135}); |
|
positionsView[1] = T::pad(Math::Vector3<typename T::Type>{0, 15, 2}); |
|
positionsView[2] = T::pad(Math::Vector3<typename T::Type>{22, 3, 192}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Position, positionsView}}}; |
|
CORRADE_COMPARE_AS(data.positions3DAsArray(), Containers::arrayView<Vector3>({ |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{2.0f, 1.0f, 135.0f})), |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{0.0f, 15.0f, 2.0f})), |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{22.0f, 3.0f, 192.0f})) |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::positions3DAsArrayPackedSigned() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto positionsView = Containers::arrayCast<T>(vertexData); |
|
positionsView[0] = T::pad(Math::Vector3<typename T::Type>{2, 1, -117}); |
|
positionsView[1] = T::pad(Math::Vector3<typename T::Type>{0, -15, 2}); |
|
positionsView[2] = T::pad(Math::Vector3<typename T::Type>{-22, 3, 86}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Position, positionsView}}}; |
|
CORRADE_COMPARE_AS(data.positions3DAsArray(), Containers::arrayView<Vector3>({ |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{2.0f, 1.0f, -117.0f})), |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{0.0f, -15.0f, 2.0f})), |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{-22.0f, 3.0f, 86.0f})) |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::positions3DAsArrayPackedUnsignedNormalized() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{2*sizeof(T)}; |
|
auto positionsView = Containers::arrayCast<T>(vertexData); |
|
positionsView[0] = T::pad(Math::Vector3<typename T::Type>{Math::pack<typename T::Type>(1.0f), 0, Math::pack<typename T::Type>(1.0f)}); |
|
positionsView[1] = T::pad(Math::Vector3<typename T::Type>{0, Math::pack<typename T::Type>(1.0f), 0}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Position, |
|
/* Assuming the normalized enum is always after the non-normalized */ |
|
VertexFormat(UnsignedInt(Implementation::vertexFormatFor<T>()) + 1), |
|
positionsView}}}; |
|
CORRADE_COMPARE_AS(data.positions3DAsArray(), Containers::arrayView<Vector3>({ |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{1.0f, 0.0f, 1.0f})), |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{0.0f, 1.0f, 0.0f})) |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::positions3DAsArrayPackedSignedNormalized() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{2*sizeof(T)}; |
|
auto positionsView = Containers::arrayCast<T>(vertexData); |
|
positionsView[0] = T::pad(Math::Vector3<typename T::Type>{Math::pack<typename T::Type>(1.0f), 0, Math::pack<typename T::Type>(1.0f)}); |
|
positionsView[1] = T::pad(Math::Vector3<typename T::Type>{0, Math::pack<typename T::Type>(-1.0f), 0}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Position, |
|
/* Assuming the normalized enum is always after the non-normalized */ |
|
VertexFormat(UnsignedInt(Implementation::vertexFormatFor<T>()) + 1), |
|
positionsView}}}; |
|
CORRADE_COMPARE_AS(data.positions3DAsArray(), Containers::arrayView<Vector3>({ |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{1.0f, 0.0f, 1.0f})), |
|
Vector3::pad(Math::Vector<T::Size, Float>::pad(Vector3{0.0f, -1.0f, 0.0f})) |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
void MeshDataTest::positions3DIntoArrayInvalidSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{3*sizeof(Vector3)}; |
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Position, Containers::arrayCast<Vector3>(vertexData)}}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Vector3 destination[2]; |
|
data.positions3DInto(destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::positions3DInto(): expected a view with 3 elements but got 2\n"); |
|
} |
|
|
|
template<class T> void MeshDataTest::tangentsAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
typedef typename T::Type U; |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto tangentView = Containers::arrayCast<T>(vertexData); |
|
/* Needs to be sufficiently representable to have the test work also for |
|
half floats */ |
|
tangentView[0] = T::pad(Math::Vector3<U>{U(2.0f), U(1.0f), U(0.75f)}); |
|
tangentView[1] = T::pad(Math::Vector3<U>{U(0.0f), U(-1.0f), U(1.25f)}); |
|
tangentView[2] = T::pad(Math::Vector3<U>{U(-2.0f), U(3.0f), U(2.5f)}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Tangent, tangentView}}}; |
|
CORRADE_COMPARE_AS(data.tangentsAsArray(), Containers::arrayView<Vector3>({ |
|
{2.0f, 1.0f, 0.75f}, {0.0f, -1.0f, 1.25f}, {-2.0f, 3.0f, 2.5f}, |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::tangentsAsArrayPackedSignedNormalized() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
typedef typename T::Type U; |
|
|
|
Containers::Array<char> vertexData{2*sizeof(T)}; |
|
auto tangentsView = Containers::arrayCast<T>(vertexData); |
|
tangentsView[0] = T::pad(Math::Vector3<U>{Math::pack<U>(1.0f), 0, Math::pack<U>(1.0f)}); |
|
tangentsView[1] = T::pad(Math::Vector3<U>{0, Math::pack<U>(-1.0f), 0}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Tangent, |
|
/* Assuming the normalized enum is always after the non-normalized */ |
|
VertexFormat(UnsignedInt(Implementation::vertexFormatFor<T>()) + 1), |
|
tangentsView}}}; |
|
CORRADE_COMPARE_AS(data.tangentsAsArray(), Containers::arrayView<Vector3>({ |
|
{1.0f, 0.0f, 1.0f}, {0.0f, -1.0f, 0.0f} |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
void MeshDataTest::tangentsIntoArrayInvalidSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{3*sizeof(Vector3)}; |
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Tangent, Containers::arrayCast<Vector3>(vertexData)}}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Vector3 destination[2]; |
|
data.tangentsInto(destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::tangentsInto(): expected a view with 3 elements but got 2\n"); |
|
} |
|
|
|
template<class T> void MeshDataTest::bitangentSignsAsArray() { |
|
setTestCaseTemplateName(Math::TypeTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{3*sizeof(Math::Vector4<T>)}; |
|
auto tangentView = Containers::arrayCast<Math::Vector4<T>>(vertexData); |
|
/* Needs to be sufficiently representable to have the test work also for |
|
half floats */ |
|
tangentView[0] = {T(2.0f), T(1.0f), T(0.75f), T(-1.0f)}; |
|
tangentView[1] = {T(0.0f), T(-1.0f), T(1.25f), T(1.0f)}; |
|
tangentView[2] = {T(-2.0f), T(3.0f), T(2.5f), T(-1.0f)}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Tangent, tangentView}}}; |
|
CORRADE_COMPARE_AS(data.bitangentSignsAsArray(), Containers::arrayView<Float>({ |
|
-1.0f, 1.0f, -1.0f |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::bitangentSignsAsArrayPackedSignedNormalized() { |
|
setTestCaseTemplateName(Math::TypeTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{2*sizeof(Math::Vector4<T>)}; |
|
auto bitangentsView = Containers::arrayCast<Math::Vector4<T>>(vertexData); |
|
bitangentsView[0] = {Math::pack<T>(1.0f), 0, Math::pack<T>(1.0f), Math::pack<T>(-1.0f)}; |
|
bitangentsView[1] = {0, Math::pack<T>(-1.0f), 0, Math::pack<T>(1.0f)}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Tangent, |
|
/* Assuming the normalized enum is always after the non-normalized */ |
|
VertexFormat(UnsignedInt(Implementation::vertexFormatFor<Math::Vector4<T>>()) + 1), |
|
bitangentsView}}}; |
|
CORRADE_COMPARE_AS(data.bitangentSignsAsArray(), Containers::arrayView<Float>({ |
|
-1.0f, 1.0f |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
void MeshDataTest::bitangentSignsAsArrayNotFourComponent() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{3*sizeof(Vector3s)}; |
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Tangent, VertexFormat::Vector3sNormalized, Containers::arrayCast<Vector3s>(vertexData)}}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Float destination[3]; |
|
data.bitangentSignsInto(destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::bitangentSignsInto(): expected four-component tangents, but got VertexFormat::Vector3sNormalized\n"); |
|
} |
|
|
|
void MeshDataTest::bitangentSignsIntoArrayInvalidSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{3*sizeof(Vector4)}; |
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Tangent, Containers::arrayCast<Vector4>(vertexData)}}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Float destination[2]; |
|
data.bitangentSignsInto(destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::bitangentSignsInto(): expected a view with 3 elements but got 2\n"); |
|
} |
|
|
|
template<class T> void MeshDataTest::bitangentsAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
typedef typename T::Type U; |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto bitangentsView = Containers::arrayCast<T>(vertexData); |
|
/* Needs to be sufficiently representable to have the test work also for |
|
half floats */ |
|
bitangentsView[0] = {U(2.0f), U(1.0f), U(0.75f)}; |
|
bitangentsView[1] = {U(0.0f), U(-1.0f), U(1.25f)}; |
|
bitangentsView[2] = {U(-2.0f), U(3.0f), U(2.5f)}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Bitangent, bitangentsView}}}; |
|
CORRADE_COMPARE_AS(data.bitangentsAsArray(), Containers::arrayView<Vector3>({ |
|
{2.0f, 1.0f, 0.75f}, {0.0f, -1.0f, 1.25f}, {-2.0f, 3.0f, 2.5f}, |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::bitangentsAsArrayPackedSignedNormalized() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{2*sizeof(T)}; |
|
auto bitangentsView = Containers::arrayCast<T>(vertexData); |
|
bitangentsView[0] = {Math::pack<typename T::Type>(1.0f), 0, Math::pack<typename T::Type>(1.0f)}; |
|
bitangentsView[1] = {0, Math::pack<typename T::Type>(-1.0f), 0}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Bitangent, |
|
/* Assuming the normalized enum is always after the non-normalized */ |
|
VertexFormat(UnsignedInt(Implementation::vertexFormatFor<T>()) + 1), |
|
bitangentsView}}}; |
|
CORRADE_COMPARE_AS(data.bitangentsAsArray(), Containers::arrayView<Vector3>({ |
|
{1.0f, 0.0f, 1.0f}, {0.0f, -1.0f, 0.0f} |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
void MeshDataTest::bitangentsIntoArrayInvalidSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{3*sizeof(Vector3)}; |
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Bitangent, Containers::arrayCast<Vector3>(vertexData)}}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Vector3 destination[2]; |
|
data.bitangentsInto(destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::bitangentsInto(): expected a view with 3 elements but got 2\n"); |
|
} |
|
|
|
template<class T> void MeshDataTest::normalsAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
typedef typename T::Type U; |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto normalsView = Containers::arrayCast<T>(vertexData); |
|
/* Needs to be sufficiently representable to have the test work also for |
|
half floats */ |
|
normalsView[0] = {U(2.0f), U(1.0f), U(0.75f)}; |
|
normalsView[1] = {U(0.0f), U(-1.0f), U(1.25f)}; |
|
normalsView[2] = {U(-2.0f), U(3.0f), U(2.5f)}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Normal, normalsView}}}; |
|
CORRADE_COMPARE_AS(data.normalsAsArray(), Containers::arrayView<Vector3>({ |
|
{2.0f, 1.0f, 0.75f}, {0.0f, -1.0f, 1.25f}, {-2.0f, 3.0f, 2.5f}, |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::normalsAsArrayPackedSignedNormalized() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{2*sizeof(T)}; |
|
auto normalsView = Containers::arrayCast<T>(vertexData); |
|
normalsView[0] = {Math::pack<typename T::Type>(1.0f), 0, Math::pack<typename T::Type>(1.0f)}; |
|
normalsView[1] = {0, Math::pack<typename T::Type>(-1.0f), 0}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Normal, |
|
/* Assuming the normalized enum is always after the non-normalized */ |
|
VertexFormat(UnsignedInt(Implementation::vertexFormatFor<T>()) + 1), |
|
normalsView}}}; |
|
CORRADE_COMPARE_AS(data.normalsAsArray(), Containers::arrayView<Vector3>({ |
|
{1.0f, 0.0f, 1.0f}, {0.0f, -1.0f, 0.0f} |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
void MeshDataTest::normalsIntoArrayInvalidSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{3*sizeof(Vector3)}; |
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Normal, Containers::arrayCast<Vector3>(vertexData)}}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Vector3 destination[2]; |
|
data.normalsInto(destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::normalsInto(): expected a view with 3 elements but got 2\n"); |
|
} |
|
|
|
template<class T> void MeshDataTest::textureCoordinates2DAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
typedef typename T::Type U; |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto textureCoordinatesView = Containers::arrayCast<T>(vertexData); |
|
textureCoordinatesView[0] = {U(2.0f), U(1.0f)}; |
|
textureCoordinatesView[1] = {U(0.0f), U(-1.0f)}; |
|
textureCoordinatesView[2] = {U(-2.0f), U(3.0f)}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::TextureCoordinates, textureCoordinatesView}}}; |
|
CORRADE_COMPARE_AS(data.textureCoordinates2DAsArray(), Containers::arrayView<Vector2>({ |
|
{2.0f, 1.0f}, {0.0f, -1.0f}, {-2.0f, 3.0f}, |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::textureCoordinates2DAsArrayPackedUnsigned() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto textureCoordinatesView = Containers::arrayCast<T>(vertexData); |
|
textureCoordinatesView[0] = {2, 1}; |
|
textureCoordinatesView[1] = {0, 15}; |
|
textureCoordinatesView[2] = {22, 3}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::TextureCoordinates, textureCoordinatesView}}}; |
|
CORRADE_COMPARE_AS(data.textureCoordinates2DAsArray(), |
|
Containers::arrayView<Vector2>({{2.0f, 1.0f}, {0.0f, 15.0f}, {22.0f, 3.0f}}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::textureCoordinates2DAsArrayPackedSigned() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto textureCoordinatesView = Containers::arrayCast<T>(vertexData); |
|
textureCoordinatesView[0] = {2, 1}; |
|
textureCoordinatesView[1] = {0, -15}; |
|
textureCoordinatesView[2] = {-22, 3}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::TextureCoordinates, textureCoordinatesView}}}; |
|
CORRADE_COMPARE_AS(data.textureCoordinates2DAsArray(), |
|
Containers::arrayView<Vector2>({{2.0f, 1.0f}, {0.0f, -15.0f}, {-22.0f, 3.0f}}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::textureCoordinates2DAsArrayPackedUnsignedNormalized() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{2*sizeof(T)}; |
|
auto textureCoordinatesView = Containers::arrayCast<T>(vertexData); |
|
textureCoordinatesView[0] = {Math::pack<typename T::Type>(1.0f), 0}; |
|
textureCoordinatesView[1] = {0, Math::pack<typename T::Type>(1.0f)}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::TextureCoordinates, |
|
/* Assuming the normalized enum is always after the non-normalized */ |
|
VertexFormat(UnsignedInt(Implementation::vertexFormatFor<T>()) + 1), |
|
textureCoordinatesView}}}; |
|
CORRADE_COMPARE_AS(data.textureCoordinates2DAsArray(), |
|
Containers::arrayView<Vector2>({{1.0f, 0.0f}, {0.0f, 1.0f}}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::textureCoordinates2DAsArrayPackedSignedNormalized() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{2*sizeof(T)}; |
|
auto textureCoordinatesView = Containers::arrayCast<T>(vertexData); |
|
textureCoordinatesView[0] = {Math::pack<typename T::Type>(1.0f), 0}; |
|
textureCoordinatesView[1] = {0, Math::pack<typename T::Type>(-1.0f)}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::TextureCoordinates, |
|
/* Assuming the normalized enum is always after the non-normalized */ |
|
VertexFormat(UnsignedInt(Implementation::vertexFormatFor<T>()) + 1), |
|
textureCoordinatesView}}}; |
|
CORRADE_COMPARE_AS(data.textureCoordinates2DAsArray(), |
|
Containers::arrayView<Vector2>({{1.0f, 0.0f}, {0.0f, -1.0f}}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void MeshDataTest::textureCoordinates2DIntoArrayInvalidSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{3*sizeof(Vector2)}; |
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::TextureCoordinates, Containers::arrayCast<Vector2>(vertexData)}}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Vector2 destination[2]; |
|
data.textureCoordinates2DInto(destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::textureCoordinates2DInto(): expected a view with 3 elements but got 2\n"); |
|
} |
|
|
|
template<class T> void MeshDataTest::colorsAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
typedef typename T::Type U; |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto colorsView = Containers::arrayCast<T>(vertexData); |
|
/* Can't use e.g. 0xff3366_rgbf because that's not representable in |
|
half-floats */ |
|
colorsView[0] = {U(2.0f), U(1.0f), U(0.75f)}; |
|
colorsView[1] = {U(0.0f), U(-1.0f), U(1.25f)}; |
|
colorsView[2] = {U(-2.0f), U(3.0f), U(2.5f)}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Color, colorsView}}}; |
|
CORRADE_COMPARE_AS(data.colorsAsArray(), Containers::arrayView<Color4>({ |
|
{2.0f, 1.0f, 0.75f}, {0.0f, -1.0f, 1.25f}, {-2.0f, 3.0f, 2.5f}, |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void MeshDataTest::colorsAsArrayPackedUnsignedNormalized() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{2*sizeof(T)}; |
|
auto colorsView = Containers::arrayCast<T>(vertexData); |
|
colorsView[0] = T::pad(Math::Color4<typename T::Type>{Math::pack<typename T::Type>(1.0f), 0, Math::pack<typename T::Type>(1.0f), 0}); |
|
colorsView[1] = T::pad(Math::Color4<typename T::Type>{0, Math::pack<typename T::Type>(1.0f), 0, Math::pack<typename T::Type>(1.0f)}); |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Color, colorsView}}}; |
|
CORRADE_COMPARE_AS(data.colorsAsArray(), Containers::arrayView<Color4>({ |
|
Color4::pad(Math::Vector<T::Size, Float>::pad(Vector4{1.0f, 0.0f, 1.0f, 0.0f}), 1.0f), |
|
Color4::pad(Math::Vector<T::Size, Float>::pad(Vector4{0.0f, 1.0f, 0.0f, 1.0f}), 1.0f) |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
void MeshDataTest::colorsIntoArrayInvalidSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{3*sizeof(Color4)}; |
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::Color, Containers::arrayCast<Color4>(vertexData)}}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Color4 destination[2]; |
|
data.colorsInto(destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::colorsInto(): expected a view with 3 elements but got 2\n"); |
|
} |
|
|
|
template<class T> void MeshDataTest::objectIdsAsArray() { |
|
setTestCaseTemplateName(Math::TypeTraits<T>::name()); |
|
|
|
Containers::Array<char> vertexData{3*sizeof(T)}; |
|
auto objectIdsView = Containers::arrayCast<T>(vertexData); |
|
/* Can't use e.g. 0xff3366_rgbf because that's not representable in |
|
half-floats */ |
|
objectIdsView[0] = {157}; |
|
objectIdsView[1] = {24}; |
|
objectIdsView[2] = {1}; |
|
|
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::ObjectId, objectIdsView}}}; |
|
CORRADE_COMPARE_AS(data.objectIdsAsArray(), Containers::arrayView<UnsignedInt>({ |
|
157, 24, 1 |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
void MeshDataTest::objectIdsIntoArrayInvalidSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{3*sizeof(UnsignedInt)}; |
|
MeshData data{MeshPrimitive::Points, std::move(vertexData), {MeshAttributeData{MeshAttribute::ObjectId, Containers::arrayCast<UnsignedInt>(vertexData)}}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
UnsignedInt destination[2]; |
|
data.objectIdsInto(destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::objectIdsInto(): expected a view with 3 elements but got 2\n"); |
|
} |
|
|
|
/* MSVC 2015 doesn't like anonymous bitfields in inline structs, so putting the |
|
declaration outside */ |
|
struct VertexWithImplementationSpecificData { |
|
Long:64; |
|
long double thing; |
|
}; |
|
|
|
void MeshDataTest::implementationSpecificVertexFormat() { |
|
VertexWithImplementationSpecificData vertexData[] { |
|
{456.0l}, |
|
{456.0l} |
|
}; |
|
|
|
/* Constructing should work w/o asserts */ |
|
Containers::StridedArrayView1D<long double> attribute{vertexData, |
|
&vertexData[0].thing, 2, sizeof(VertexWithImplementationSpecificData)}; |
|
MeshData data{MeshPrimitive::TriangleFan, DataFlag::Mutable, vertexData, { |
|
MeshAttributeData{MeshAttribute::Position, |
|
vertexFormatWrap(0xdead1), attribute}, |
|
MeshAttributeData{MeshAttribute::Normal, |
|
vertexFormatWrap(0xdead2), attribute}, |
|
MeshAttributeData{MeshAttribute::TextureCoordinates, |
|
vertexFormatWrap(0xdead3), attribute}, |
|
MeshAttributeData{MeshAttribute::Color, |
|
vertexFormatWrap(0xdead4), attribute}}}; |
|
|
|
/* Getting typeless attribute should work also */ |
|
UnsignedInt format = 0xdead1; |
|
for(MeshAttribute name: {MeshAttribute::Position, |
|
MeshAttribute::Normal, |
|
MeshAttribute::TextureCoordinates, |
|
MeshAttribute::Color}) { |
|
CORRADE_ITERATION(name); |
|
CORRADE_COMPARE(data.attributeFormat(name), vertexFormatWrap(format++)); |
|
|
|
/* The actual type size is unknown, so this will use the full stride */ |
|
CORRADE_COMPARE(data.attribute(name).size()[1], sizeof(VertexWithImplementationSpecificData)); |
|
|
|
CORRADE_COMPARE_AS((Containers::arrayCast<1, const long double>( |
|
data.attribute(name).prefix({2, sizeof(long double)}))), |
|
attribute, TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS((Containers::arrayCast<1, const long double>( |
|
data.mutableAttribute(name).prefix({2, sizeof(long double)}))), |
|
attribute, TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void MeshDataTest::implementationSpecificVertexFormatWrongAccess() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
VertexWithImplementationSpecificData vertexData[] { |
|
{456.0l}, |
|
{456.0l} |
|
}; |
|
|
|
Containers::StridedArrayView1D<long double> attribute{vertexData, |
|
&vertexData[0].thing, 2, sizeof(VertexWithImplementationSpecificData)}; |
|
MeshData data{MeshPrimitive::TriangleFan, DataFlag::Mutable, vertexData, { |
|
MeshAttributeData{MeshAttribute::Position, |
|
vertexFormatWrap(0xdead1), attribute}, |
|
MeshAttributeData{MeshAttribute::Tangent, |
|
vertexFormatWrap(0xdead2), attribute}, |
|
MeshAttributeData{MeshAttribute::Bitangent, |
|
vertexFormatWrap(0xdead2), attribute}, |
|
MeshAttributeData{MeshAttribute::Normal, |
|
vertexFormatWrap(0xdead2), attribute}, |
|
MeshAttributeData{MeshAttribute::TextureCoordinates, |
|
vertexFormatWrap(0xdead3), attribute}, |
|
MeshAttributeData{MeshAttribute::Color, |
|
vertexFormatWrap(0xdead4), attribute}, |
|
MeshAttributeData{MeshAttribute::ObjectId, |
|
vertexFormatWrap(0xdead4), attribute}}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
data.attribute<Float>(MeshAttribute::Position); |
|
data.attribute<Float>(MeshAttribute::Normal); |
|
data.attribute<Float>(MeshAttribute::TextureCoordinates); |
|
data.attribute<Float>(MeshAttribute::Color); |
|
data.mutableAttribute<Float>(MeshAttribute::Position); |
|
data.mutableAttribute<Float>(MeshAttribute::Normal); |
|
data.mutableAttribute<Float>(MeshAttribute::TextureCoordinates); |
|
data.mutableAttribute<Float>(MeshAttribute::Color); |
|
data.positions2DAsArray(); |
|
data.positions3DAsArray(); |
|
data.tangentsAsArray(); |
|
data.bitangentSignsAsArray(); |
|
data.bitangentsAsArray(); |
|
data.normalsAsArray(); |
|
data.textureCoordinates2DAsArray(); |
|
data.colorsAsArray(); |
|
data.objectIdsAsArray(); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::attribute(): can't cast data from an implementation-specific vertex format 0xdead1\n" |
|
"Trade::MeshData::attribute(): can't cast data from an implementation-specific vertex format 0xdead2\n" |
|
"Trade::MeshData::attribute(): can't cast data from an implementation-specific vertex format 0xdead3\n" |
|
"Trade::MeshData::attribute(): can't cast data from an implementation-specific vertex format 0xdead4\n" |
|
"Trade::MeshData::mutableAttribute(): can't cast data from an implementation-specific vertex format 0xdead1\n" |
|
"Trade::MeshData::mutableAttribute(): can't cast data from an implementation-specific vertex format 0xdead2\n" |
|
"Trade::MeshData::mutableAttribute(): can't cast data from an implementation-specific vertex format 0xdead3\n" |
|
"Trade::MeshData::mutableAttribute(): can't cast data from an implementation-specific vertex format 0xdead4\n" |
|
"Trade::MeshData::positions2DInto(): can't extract data out of an implementation-specific vertex format 0xdead1\n" |
|
"Trade::MeshData::positions3DInto(): can't extract data out of an implementation-specific vertex format 0xdead1\n" |
|
"Trade::MeshData::tangentsInto(): can't extract data out of an implementation-specific vertex format 0xdead2\n" |
|
"Trade::MeshData::bitangentSignsInto(): can't extract data out of an implementation-specific vertex format 0xdead2\n" |
|
"Trade::MeshData::bitangentsInto(): can't extract data out of an implementation-specific vertex format 0xdead2\n" |
|
"Trade::MeshData::normalsInto(): can't extract data out of an implementation-specific vertex format 0xdead2\n" |
|
"Trade::MeshData::textureCoordinatesInto(): can't extract data out of an implementation-specific vertex format 0xdead3\n" |
|
"Trade::MeshData::colorsInto(): can't extract data out of an implementation-specific vertex format 0xdead4\n" |
|
"Trade::MeshData::objectIdsInto(): can't extract data out of an implementation-specific vertex format 0xdead4\n"); |
|
} |
|
|
|
void MeshDataTest::implementationSpecificVertexFormatNotContained() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> vertexData{reinterpret_cast<char*>(0xbadda9), 3, [](char*, std::size_t){}}; |
|
Containers::ArrayView<char> vertexData2{reinterpret_cast<char*>(0xdead), 3}; |
|
MeshAttributeData positions{MeshAttribute::Position, vertexFormatWrap(0x3a), vertexData}; |
|
MeshAttributeData positions2{MeshAttribute::Position, vertexFormatWrap(0x3a), vertexData2}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshData{MeshPrimitive::Triangles, std::move(vertexData), {positions, positions2}}; |
|
CORRADE_COMPARE(out.str(), |
|
/* Assumes size of the type is 0, so the diagnostic is different from |
|
constructAttributeNotContained() */ |
|
"Trade::MeshData: attribute 1 [0xdead:0xdeaf] is not contained in passed vertexData array [0xbadda9:0xbaddac]\n"); |
|
} |
|
|
|
void MeshDataTest::arrayAttribute() { |
|
Vector2 vertexData[3*4]{ |
|
{1.0f, 2.0f}, {3.0f, 4.0f}, {5.0f, 6.0f}, {7.0f, 8.0f}, |
|
{1.1f, 2.2f}, {3.3f, 4.4f}, {5.5f, 6.6f}, {7.7f, 8.8f}, |
|
{0.1f, 0.2f}, {0.3f, 0.4f}, {0.5f, 0.6f}, {0.7f, 0.8f}, |
|
}; |
|
Containers::StridedArrayView2D<Vector2> positions2D{vertexData, {3, 4}}; |
|
|
|
MeshData data{MeshPrimitive::TriangleFan, DataFlag::Mutable, vertexData, { |
|
MeshAttributeData{meshAttributeCustom(35), positions2D} |
|
}}; |
|
|
|
CORRADE_COMPARE(data.vertexCount(), 3); |
|
CORRADE_COMPARE(data.attributeArraySize(meshAttributeCustom(35)), 4); |
|
|
|
/* Raw access is "as usual" */ |
|
auto attribute = Containers::arrayCast<2, const Vector2>(data.attribute(0)); |
|
auto attributeByName = Containers::arrayCast<2, const Vector2>(data.attribute(meshAttributeCustom(35))); |
|
auto mutableAttribute = Containers::arrayCast<2, Vector2>(data.mutableAttribute(0)); |
|
auto mutableAttributeByName = Containers::arrayCast<2, Vector2>(data.mutableAttribute(meshAttributeCustom(35))); |
|
CORRADE_COMPARE(attribute.size()[0], 3); |
|
CORRADE_COMPARE(attributeByName.size()[0], 3); |
|
CORRADE_COMPARE(mutableAttribute.size()[0], 3); |
|
CORRADE_COMPARE(mutableAttributeByName.size()[0], 3); |
|
for(std::size_t i = 0; i != 3; ++i) { |
|
CORRADE_ITERATION(i); |
|
CORRADE_COMPARE_AS(attribute[i], positions2D[i], |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(attributeByName[i], positions2D[i], |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(mutableAttribute[i], positions2D[i], |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(mutableAttributeByName[i], positions2D[i], |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
/* Typed access */ |
|
attribute = data.attribute<Vector2[]>(0); |
|
attributeByName = data.attribute<Vector2[]>(meshAttributeCustom(35)); |
|
mutableAttribute = data.mutableAttribute<Vector2[]>(0); |
|
mutableAttributeByName = data.mutableAttribute<Vector2[]>(meshAttributeCustom(35)); |
|
CORRADE_COMPARE(attribute.size()[0], 3); |
|
CORRADE_COMPARE(attributeByName.size()[0], 3); |
|
CORRADE_COMPARE(mutableAttribute.size()[0], 3); |
|
CORRADE_COMPARE(mutableAttributeByName.size()[0], 3); |
|
for(std::size_t i = 0; i != 3; ++i) { |
|
CORRADE_ITERATION(i); |
|
CORRADE_COMPARE_AS(attribute[i], positions2D[i], |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(attributeByName[i], positions2D[i], |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(mutableAttribute[i], positions2D[i], |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(mutableAttributeByName[i], positions2D[i], |
|
TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void MeshDataTest::arrayAttributeWrongAccess() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Vector2 vertexData[3*4]{ |
|
{1.0f, 2.0f}, {3.0f, 4.0f}, {5.0f, 6.0f}, {7.0f, 8.0f}, |
|
{1.1f, 2.2f}, {3.3f, 4.4f}, {5.5f, 6.6f}, {7.7f, 8.8f}, |
|
{0.1f, 0.2f}, {0.3f, 0.4f}, {0.5f, 0.6f}, {0.7f, 0.8f}, |
|
}; |
|
Containers::StridedArrayView1D<Vector2> positions{vertexData, 3, 4*sizeof(Vector2)}; |
|
Containers::StridedArrayView2D<Vector2> positions2D{vertexData, {3, 4}}; |
|
|
|
MeshData data{MeshPrimitive::TriangleFan, DataFlag::Mutable, vertexData, { |
|
MeshAttributeData{MeshAttribute::Position, positions}, |
|
MeshAttributeData{meshAttributeCustom(35), positions2D} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
data.attribute<Vector2[]>(0); |
|
data.attribute<Vector2>(1); |
|
data.mutableAttribute<Vector2[]>(0); |
|
data.mutableAttribute<Vector2>(1); |
|
data.attribute<Vector2[]>(MeshAttribute::Position); |
|
data.attribute<Vector2>(meshAttributeCustom(35)); |
|
data.mutableAttribute<Vector2[]>(MeshAttribute::Position); |
|
data.mutableAttribute<Vector2>(meshAttributeCustom(35)); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::attribute(): use T[] to access an array attribute\n" |
|
"Trade::MeshData::attribute(): use T[] to access an array attribute\n" |
|
"Trade::MeshData::mutableAttribute(): use T[] to access an array attribute\n" |
|
"Trade::MeshData::mutableAttribute(): use T[] to access an array attribute\n" |
|
"Trade::MeshData::attribute(): use T[] to access an array attribute\n" |
|
"Trade::MeshData::attribute(): use T[] to access an array attribute\n" |
|
"Trade::MeshData::mutableAttribute(): use T[] to access an array attribute\n" |
|
"Trade::MeshData::mutableAttribute(): use T[] to access an array attribute\n"); |
|
} |
|
|
|
void MeshDataTest::mutableAccessNotAllowed() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const UnsignedShort indexData[]{0, 1, 0}; |
|
const Vector2 vertexData[]{{0.1f, 0.2f}, {0.4f, 0.5f}}; |
|
|
|
MeshIndexData indices{indexData}; |
|
MeshAttributeData positions{MeshAttribute::Position, Containers::arrayView(vertexData)}; |
|
MeshData data{MeshPrimitive::Triangles, {}, indexData, indices, {}, vertexData, {positions}}; |
|
CORRADE_COMPARE(data.indexDataFlags(), DataFlags{}); |
|
CORRADE_COMPARE(data.vertexDataFlags(), DataFlags{}); |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
data.mutableIndexData(); |
|
data.mutableVertexData(); |
|
data.mutableIndices(); |
|
data.mutableIndices<UnsignedShort>(); |
|
data.mutableAttribute(0); |
|
data.mutableAttribute<Vector2>(0); |
|
data.mutableAttribute(MeshAttribute::Position); |
|
data.mutableAttribute<Vector2>(MeshAttribute::Position); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::mutableIndexData(): index data not mutable\n" |
|
"Trade::MeshData::mutableVertexData(): vertex data not mutable\n" |
|
"Trade::MeshData::mutableIndices(): index data not mutable\n" |
|
"Trade::MeshData::mutableIndices(): index data not mutable\n" |
|
"Trade::MeshData::mutableAttribute(): vertex data not mutable\n" |
|
"Trade::MeshData::mutableAttribute(): vertex data not mutable\n" |
|
"Trade::MeshData::mutableAttribute(): vertex data not mutable\n" |
|
"Trade::MeshData::mutableAttribute(): vertex data not mutable\n"); |
|
} |
|
|
|
void MeshDataTest::indicesNotIndexed() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
MeshData data{MeshPrimitive::Triangles, 37}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
data.indexCount(); |
|
data.indexType(); |
|
data.indexOffset(); |
|
data.indices(); |
|
data.indices<UnsignedInt>(); |
|
data.indicesAsArray(); |
|
UnsignedInt a[1]; |
|
data.indicesInto(a); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::indexCount(): the mesh is not indexed\n" |
|
"Trade::MeshData::indexType(): the mesh is not indexed\n" |
|
"Trade::MeshData::indexOffset(): the mesh is not indexed\n" |
|
"Trade::MeshData::indices(): the mesh is not indexed\n" |
|
"Trade::MeshData::indices(): the mesh is not indexed\n" |
|
"Trade::MeshData::indicesAsArray(): the mesh is not indexed\n" |
|
"Trade::MeshData::indicesInto(): the mesh is not indexed\n"); |
|
} |
|
|
|
void MeshDataTest::indicesWrongType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> indexData{sizeof(UnsignedShort)}; |
|
auto indexView = Containers::arrayCast<UnsignedShort>(indexData); |
|
indexView[0] = 57616; |
|
MeshData data{MeshPrimitive::Points, std::move(indexData), MeshIndexData{indexView}, 57617}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
data.indices<UnsignedByte>(); |
|
CORRADE_COMPARE(out.str(), "Trade::MeshData::indices(): improper type requested for MeshIndexType::UnsignedShort\n"); |
|
} |
|
|
|
void MeshDataTest::attributeNotFound() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
MeshAttributeData colors1{MeshAttribute::Color, VertexFormat::Vector3, nullptr}; |
|
MeshAttributeData colors2{MeshAttribute::Color, VertexFormat::Vector4, nullptr}; |
|
MeshData data{MeshPrimitive::Points, nullptr, {colors1, colors2}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
data.attributeName(2); |
|
data.attributeFormat(2); |
|
data.attributeOffset(2); |
|
data.attributeStride(2); |
|
data.attributeArraySize(2); |
|
data.attribute(2); |
|
data.attribute<Vector2>(2); |
|
data.attributeId(MeshAttribute::Position); |
|
data.attributeId(MeshAttribute::Color, 2); |
|
data.attributeFormat(MeshAttribute::Position); |
|
data.attributeFormat(MeshAttribute::Color, 2); |
|
data.attributeOffset(MeshAttribute::Position); |
|
data.attributeOffset(MeshAttribute::Color, 2); |
|
data.attributeStride(MeshAttribute::Position); |
|
data.attributeStride(MeshAttribute::Color, 2); |
|
data.attributeArraySize(MeshAttribute::Position); |
|
data.attributeArraySize(MeshAttribute::Color, 2); |
|
data.attribute(MeshAttribute::Position); |
|
data.attribute(MeshAttribute::Color, 2); |
|
data.attribute<Vector2>(MeshAttribute::Position); |
|
data.attribute<Vector2>(MeshAttribute::Color, 2); |
|
data.positions2DAsArray(); |
|
data.positions3DAsArray(); |
|
data.tangentsAsArray(); |
|
data.bitangentSignsAsArray(); |
|
data.bitangentsAsArray(); |
|
data.normalsAsArray(); |
|
data.textureCoordinates2DAsArray(); |
|
data.colorsAsArray(2); |
|
data.objectIdsAsArray(); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::attributeName(): index 2 out of range for 2 attributes\n" |
|
"Trade::MeshData::attributeFormat(): index 2 out of range for 2 attributes\n" |
|
"Trade::MeshData::attributeOffset(): index 2 out of range for 2 attributes\n" |
|
"Trade::MeshData::attributeStride(): index 2 out of range for 2 attributes\n" |
|
"Trade::MeshData::attributeArraySize(): index 2 out of range for 2 attributes\n" |
|
"Trade::MeshData::attribute(): index 2 out of range for 2 attributes\n" |
|
"Trade::MeshData::attribute(): index 2 out of range for 2 attributes\n" |
|
"Trade::MeshData::attributeId(): index 0 out of range for 0 Trade::MeshAttribute::Position attributes\n" |
|
"Trade::MeshData::attributeId(): index 2 out of range for 2 Trade::MeshAttribute::Color attributes\n" |
|
"Trade::MeshData::attributeFormat(): index 0 out of range for 0 Trade::MeshAttribute::Position attributes\n" |
|
"Trade::MeshData::attributeFormat(): index 2 out of range for 2 Trade::MeshAttribute::Color attributes\n" |
|
"Trade::MeshData::attributeOffset(): index 0 out of range for 0 Trade::MeshAttribute::Position attributes\n" |
|
"Trade::MeshData::attributeOffset(): index 2 out of range for 2 Trade::MeshAttribute::Color attributes\n" |
|
"Trade::MeshData::attributeStride(): index 0 out of range for 0 Trade::MeshAttribute::Position attributes\n" |
|
"Trade::MeshData::attributeStride(): index 2 out of range for 2 Trade::MeshAttribute::Color attributes\n" |
|
"Trade::MeshData::attributeArraySize(): index 0 out of range for 0 Trade::MeshAttribute::Position attributes\n" |
|
"Trade::MeshData::attributeArraySize(): index 2 out of range for 2 Trade::MeshAttribute::Color attributes\n" |
|
"Trade::MeshData::attribute(): index 0 out of range for 0 Trade::MeshAttribute::Position attributes\n" |
|
"Trade::MeshData::attribute(): index 2 out of range for 2 Trade::MeshAttribute::Color attributes\n" |
|
"Trade::MeshData::attribute(): index 0 out of range for 0 Trade::MeshAttribute::Position attributes\n" |
|
"Trade::MeshData::attribute(): index 2 out of range for 2 Trade::MeshAttribute::Color attributes\n" |
|
"Trade::MeshData::positions2DInto(): index 0 out of range for 0 position attributes\n" |
|
"Trade::MeshData::positions3DInto(): index 0 out of range for 0 position attributes\n" |
|
"Trade::MeshData::tangentsInto(): index 0 out of range for 0 tangent attributes\n" |
|
"Trade::MeshData::bitangentSignsInto(): index 0 out of range for 0 tangent attributes\n" |
|
"Trade::MeshData::bitangentsInto(): index 0 out of range for 0 bitangent attributes\n" |
|
"Trade::MeshData::normalsInto(): index 0 out of range for 0 normal attributes\n" |
|
"Trade::MeshData::textureCoordinates2DInto(): index 0 out of range for 0 texture coordinate attributes\n" |
|
"Trade::MeshData::colorsInto(): index 2 out of range for 2 color attributes\n" |
|
"Trade::MeshData::objectIdsInto(): index 0 out of range for 0 object ID attributes\n"); |
|
} |
|
|
|
void MeshDataTest::attributeWrongType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
MeshAttributeData positions{MeshAttribute::Position, VertexFormat::Vector3, nullptr}; |
|
MeshData data{MeshPrimitive::Points, nullptr, {positions}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
data.attribute<Vector4>(MeshAttribute::Position); |
|
CORRADE_COMPARE(out.str(), "Trade::MeshData::attribute(): improper type requested for Trade::MeshAttribute::Position of format VertexFormat::Vector3\n"); |
|
} |
|
|
|
void MeshDataTest::releaseIndexData() { |
|
Containers::Array<char> indexData{23}; |
|
auto indexView = Containers::arrayCast<UnsignedShort>(indexData.slice(6, 12)); |
|
|
|
MeshData data{MeshPrimitive::TriangleStrip, std::move(indexData), MeshIndexData{indexView}, 10}; |
|
CORRADE_VERIFY(data.isIndexed()); |
|
CORRADE_COMPARE(data.indexCount(), 3); |
|
CORRADE_COMPARE(data.indexOffset(), 6); |
|
|
|
Containers::Array<char> released = data.releaseIndexData(); |
|
CORRADE_COMPARE(static_cast<void*>(released.data() + 6), indexView.data()); |
|
/* This is not null as we still need the value for calculating offsets */ |
|
CORRADE_COMPARE(static_cast<const void*>(data.indexData()), released.data()); |
|
CORRADE_COMPARE(data.indexData().size(), 0); |
|
CORRADE_VERIFY(data.isIndexed()); |
|
CORRADE_COMPARE(data.indexCount(), 0); |
|
CORRADE_COMPARE(data.indexType(), MeshIndexType::UnsignedShort); |
|
CORRADE_COMPARE(data.indexOffset(), 6); |
|
} |
|
|
|
void MeshDataTest::releaseAttributeData() { |
|
Containers::Array<char> vertexData{16}; |
|
auto vertexView = Containers::arrayCast<Vector2>(vertexData); |
|
|
|
MeshAttributeData positions{MeshAttribute::Position, vertexView}; |
|
MeshData data{MeshPrimitive::LineLoop, std::move(vertexData), {positions, positions}}; |
|
CORRADE_COMPARE(data.attributeCount(), 2); |
|
|
|
Containers::Array<MeshAttributeData> released = data.releaseAttributeData(); |
|
CORRADE_COMPARE(released.size(), 2); |
|
CORRADE_COMPARE(static_cast<const void*>(released[0].data().data()), vertexView.data()); |
|
CORRADE_COMPARE(released[0].data().size(), 2); |
|
/* Unlike the other two, this is null as we don't need the value for |
|
calculating anything */ |
|
CORRADE_COMPARE(static_cast<const void*>(data.attributeData()), nullptr); |
|
CORRADE_COMPARE(data.attributeCount(), 0); |
|
CORRADE_COMPARE(static_cast<const void*>(data.vertexData()), vertexView); |
|
CORRADE_COMPARE(data.vertexCount(), 2); |
|
} |
|
|
|
void MeshDataTest::releaseVertexData() { |
|
Containers::Array<char> vertexData{80}; |
|
auto vertexView = Containers::arrayCast<Vector2>(vertexData.slice(48, 72)); |
|
|
|
MeshAttributeData positions{MeshAttribute::Position, vertexView}; |
|
MeshData data{MeshPrimitive::LineLoop, std::move(vertexData), {positions, positions}}; |
|
CORRADE_COMPARE(data.attributeCount(), 2); |
|
CORRADE_COMPARE(data.vertexCount(), 3); |
|
CORRADE_COMPARE(data.attributeOffset(0), 48); |
|
|
|
Containers::Array<char> released = data.releaseVertexData(); |
|
CORRADE_VERIFY(data.attributeData()); |
|
CORRADE_COMPARE(data.attributeCount(), 2); |
|
CORRADE_COMPARE(static_cast<const void*>(static_cast<const char*>(data.attribute(0).data())), vertexView.data()); |
|
CORRADE_COMPARE(static_cast<const void*>(static_cast<const char*>(data.mutableAttribute(0).data())), vertexView.data()); |
|
/* Returned views should be patched to have zero size (but not the direct |
|
access, there it stays as it's an internal API really) */ |
|
CORRADE_COMPARE(data.attribute(0).size()[0], 0); |
|
CORRADE_COMPARE(data.mutableAttribute(0).size()[0], 0); |
|
CORRADE_COMPARE(data.attributeData()[0].data().size(), 3); |
|
CORRADE_COMPARE(static_cast<void*>(released.data() + 48), vertexView.data()); |
|
/* This is not null as we still need the value for calculating offsets */ |
|
CORRADE_COMPARE(static_cast<const void*>(data.vertexData()), released.data()); |
|
CORRADE_COMPARE(data.vertexCount(), 0); |
|
CORRADE_COMPARE(data.attributeOffset(0), 48); |
|
} |
|
|
|
constexpr char BlobFileSuffix[] { |
|
'-', |
|
#ifndef CORRADE_TARGET_BIG_ENDIAN |
|
'l', |
|
#else |
|
'b', |
|
#endif |
|
'e', sizeof(void*) == 4 ? '3' : '6', sizeof(void*) == 4 ? '2' : '4', |
|
'.', 'b', 'l', 'o', 'b', '\0' |
|
}; |
|
|
|
void MeshDataTest::serialize() { |
|
auto&& data = SerializeData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Clang on iOS and Android doesn't like constexpr here */ |
|
constexpr struct Vertex { |
|
Vector2 position; |
|
Vector2ub textureCoordinates; |
|
UnsignedShort props[2]; |
|
/* I'd use UnsignedShort:16 here but (at least on Android) the bytes |
|
get random values, breaking the test. On iOS and Android that would |
|
also make the compiler complain about constexpr, and finally MSVC |
|
2015 chokes on the : if this is an inline struct. */ |
|
UnsignedShort _padding; |
|
Double weight; |
|
} vertexData[] { |
|
{{1.0f, 0.5f}, {23, 15}, {3247, 1256}, 0, 1.1}, |
|
{{2.0f, 1.5f}, {232, 144}, {6243, 1241}, 0, 1.2}, |
|
{{3.0f, 2.5f}, {17, 242}, {15, 2323}, 0, 1.3} |
|
}; |
|
|
|
constexpr UnsignedShort indexData[] { |
|
2555, 3241, 1, 0, 1, 0 |
|
}; |
|
|
|
Containers::ArrayView<const void> indexView; |
|
MeshIndexData indices; |
|
if(data.indexed) { |
|
indexView = indexData; |
|
indices = MeshIndexData{Containers::arrayView(indexData).suffix(2)}; |
|
} |
|
|
|
MeshData meshData{MeshPrimitive::TriangleFan, |
|
{}, indexView, indices, |
|
{}, vertexData, { |
|
/* Test all attribute type sizes (2, 4, 8) for endian swapping in |
|
the MagnumImporter / MagnumSceneConverter plugins */ |
|
MeshAttributeData{MeshAttribute::Position, |
|
Containers::StridedArrayView1D<const Vector2>{vertexData, &vertexData[0].position, 3, sizeof(Vertex)}}, |
|
MeshAttributeData{MeshAttribute::TextureCoordinates, |
|
Containers::StridedArrayView1D<const Vector2ub>{vertexData, &vertexData[0].textureCoordinates, 3, sizeof(Vertex)}}, |
|
/* Test array attribs */ |
|
MeshAttributeData{meshAttributeCustom(23), |
|
VertexFormat::UnsignedShort, 2, |
|
Containers::StridedArrayView1D<const UnsignedShort>{vertexData, &vertexData[0].props[0], 3, sizeof(Vertex)}}, |
|
/* Test offset-only attribs as well */ |
|
MeshAttributeData{meshAttributeCustom(14), VertexFormat::Double, |
|
16, 3, sizeof(Vertex)} |
|
}}; |
|
|
|
Containers::Array<char> blob = meshData.serialize(); |
|
CORRADE_COMPARE_AS((std::string{blob.data(), blob.size()}), |
|
Utility::Directory::join(TRADE_TEST_DIR, std::string{data.filePrefix} + BlobFileSuffix), |
|
TestSuite::Compare::StringToFile); |
|
} |
|
|
|
void MeshDataTest::serializeEmpty() { |
|
MeshData meshData{MeshPrimitive::Edges, 1256}; |
|
|
|
Containers::Array<char> blob = meshData.serialize(); |
|
CORRADE_COMPARE_AS((std::string{blob.data(), blob.size()}), |
|
Utility::Directory::join(TRADE_TEST_DIR, std::string{"mesh-empty"} + BlobFileSuffix), |
|
TestSuite::Compare::StringToFile); |
|
} |
|
|
|
void MeshDataTest::serializeIntoTooSmall() { |
|
constexpr UnsignedInt indexData[]{0, 1, 0}; |
|
|
|
MeshData meshData{MeshPrimitive::Faces, |
|
{}, indexData, MeshIndexData{indexData}, 2}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
char blob[sizeof(void*) == 4 ? 59 : 75]; |
|
meshData.serializeInto(blob); |
|
if(sizeof(void*) == 4) CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::serializeInto(): data too small, expected at least 60 bytes but got 59\n"); |
|
else CORRADE_COMPARE(out.str(), |
|
"Trade::MeshData::serializeInto(): data too small, expected at least 76 bytes but got 75\n"); |
|
} |
|
|
|
void MeshDataTest::deserialize() { |
|
auto&& data = SerializeData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
Containers::Array<char> blob = Utility::Directory::read(Utility::Directory::join(TRADE_TEST_DIR, std::string{data.filePrefix} + BlobFileSuffix)); |
|
|
|
Containers::Optional<MeshData> meshData = MeshData::deserialize(blob); |
|
CORRADE_VERIFY(meshData); |
|
CORRADE_COMPARE(meshData->attributeCount(), 4); |
|
CORRADE_COMPARE(meshData->vertexCount(), 3); |
|
CORRADE_COMPARE(meshData->indexDataFlags(), DataFlag::Mutable); |
|
CORRADE_COMPARE(meshData->vertexDataFlags(), DataFlag::Mutable); |
|
|
|
CORRADE_COMPARE(meshData->attributeName(0), MeshAttribute::Position); |
|
CORRADE_COMPARE(meshData->attributeFormat(0), VertexFormat::Vector2); |
|
CORRADE_COMPARE(meshData->attributeOffset(0), 0); |
|
CORRADE_COMPARE(meshData->attributeStride(0), 24); |
|
CORRADE_COMPARE(meshData->attributeArraySize(0), 0); |
|
CORRADE_COMPARE_AS(meshData->attribute<Vector2>(0), |
|
Containers::arrayView<Vector2>({ |
|
{1.0f, 0.5f}, {2.0f, 1.5f}, {3.0f, 2.5f} |
|
}), TestSuite::Compare::Container); |
|
|
|
CORRADE_COMPARE(meshData->attributeName(1), MeshAttribute::TextureCoordinates); |
|
CORRADE_COMPARE(meshData->attributeFormat(1), VertexFormat::Vector2ub); |
|
CORRADE_COMPARE(meshData->attributeOffset(1), 8); |
|
CORRADE_COMPARE(meshData->attributeStride(1), 24); |
|
CORRADE_COMPARE(meshData->attributeArraySize(1), 0); |
|
CORRADE_COMPARE_AS(meshData->attribute<Vector2ub>(1), |
|
Containers::arrayView<Vector2ub>({ |
|
{23, 15}, {232, 144}, {17, 242} |
|
}), TestSuite::Compare::Container); |
|
|
|
CORRADE_COMPARE(meshData->attributeName(2), meshAttributeCustom(23)); |
|
CORRADE_COMPARE(meshData->attributeFormat(2), VertexFormat::UnsignedShort); |
|
CORRADE_COMPARE(meshData->attributeOffset(2), 10); |
|
CORRADE_COMPARE(meshData->attributeStride(2), 24); |
|
CORRADE_COMPARE(meshData->attributeArraySize(2), 2); |
|
CORRADE_COMPARE_AS((meshData->attribute<UnsignedShort[]>(2).transposed<0, 1>()[0]), |
|
Containers::arrayView<UnsignedShort>({3247, 6243, 15}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS((meshData->attribute<UnsignedShort[]>(2).transposed<0, 1>()[1]), |
|
Containers::arrayView<UnsignedShort>({1256, 1241, 2323}), TestSuite::Compare::Container); |
|
|
|
CORRADE_COMPARE(meshData->attributeName(3), meshAttributeCustom(14)); |
|
CORRADE_COMPARE(meshData->attributeFormat(3), VertexFormat::Double); |
|
CORRADE_COMPARE(meshData->attributeOffset(3), 16); |
|
CORRADE_COMPARE(meshData->attributeStride(3), 24); |
|
CORRADE_COMPARE(meshData->attributeArraySize(3), 0); |
|
CORRADE_COMPARE_AS(meshData->attribute<Double>(3), |
|
Containers::arrayView<Double>({ |
|
1.1, 1.2, 1.3 |
|
}), TestSuite::Compare::Container); |
|
|
|
if(data.indexed) { |
|
CORRADE_VERIFY(meshData->isIndexed()); |
|
CORRADE_COMPARE(meshData->indexCount(), 4); |
|
CORRADE_COMPARE(meshData->indexType(), MeshIndexType::UnsignedShort); |
|
CORRADE_COMPARE(meshData->indexOffset(), 4); |
|
CORRADE_COMPARE_AS(meshData->indices<UnsignedShort>(), |
|
Containers::arrayView<UnsignedShort>({1, 0, 1, 0}), |
|
TestSuite::Compare::Container); |
|
} else CORRADE_VERIFY(!meshData->isIndexed()); |
|
|
|
/* Constant data should not have mutable flags set. Test just basics |
|
otherwise, as all this should be mostly handled by the same code. */ |
|
meshData = MeshData::deserialize(Containers::arrayView<const char>(blob)); |
|
CORRADE_VERIFY(meshData); |
|
CORRADE_COMPARE(meshData->attributeCount(), 4); |
|
CORRADE_COMPARE(meshData->vertexCount(), 3); |
|
CORRADE_COMPARE(meshData->indexDataFlags(), DataFlags{}); |
|
CORRADE_COMPARE(meshData->vertexDataFlags(), DataFlags{}); |
|
if(data.indexed) { |
|
CORRADE_VERIFY(meshData->isIndexed()); |
|
CORRADE_COMPARE(meshData->indexCount(), 4); |
|
} |
|
} |
|
|
|
void MeshDataTest::deserializeInvalid() { |
|
auto&& data = DeserializeInvalidData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
Containers::Array<char> blob = Utility::Directory::read(Utility::Directory::join(TRADE_TEST_DIR, std::string{"mesh"} + BlobFileSuffix)); |
|
CORRADE_VERIFY(blob); |
|
|
|
Containers::ArrayView<char> view = blob; |
|
if(data.size) view = view.prefix(data.size); |
|
if(data.replace) Utility::copy(data.replace, view.slice(data.offset, data.offset + data.replace.size())); |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
CORRADE_VERIFY(!MeshData::deserialize(view)); |
|
CORRADE_COMPARE(out.str(), |
|
Utility::formatString("Trade::{}\n", data.message)); |
|
} |
|
|
|
}}}} |
|
|
|
CORRADE_TEST_MAIN(Magnum::Trade::Test::MeshDataTest)
|
|
|