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.
3011 lines
142 KiB
3011 lines
142 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
2020 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/Utility/DebugStl.h> |
|
|
|
#include "Magnum/Math/Color.h" |
|
#include "Magnum/Math/Half.h" |
|
#include "Magnum/Trade/MeshData.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 constructIndex2DNotIndexed(); |
|
void constructIndex2DWrongSize(); |
|
void constructIndex2DNonContiguous(); |
|
void constructIndexNullptr(); |
|
|
|
void constructAttribute(); |
|
void constructAttributeDefault(); |
|
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 constructArrayAttributeNullptr(); |
|
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(); |
|
}; |
|
|
|
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} |
|
}; |
|
|
|
MeshDataTest::MeshDataTest() { |
|
addTests({&MeshDataTest::customAttributeName, |
|
&MeshDataTest::customAttributeNameTooLarge, |
|
&MeshDataTest::customAttributeNameNotCustom, |
|
&MeshDataTest::debugAttributeName, |
|
|
|
&MeshDataTest::constructIndex, |
|
&MeshDataTest::constructIndexTypeErased, |
|
&MeshDataTest::constructIndexTypeErasedWrongSize, |
|
&MeshDataTest::constructIndex2D, |
|
&MeshDataTest::constructIndex2DNotIndexed, |
|
&MeshDataTest::constructIndex2DWrongSize, |
|
&MeshDataTest::constructIndex2DNonContiguous, |
|
&MeshDataTest::constructIndexNullptr, |
|
|
|
&MeshDataTest::constructAttribute, |
|
&MeshDataTest::constructAttributeDefault, |
|
&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::constructArrayAttributeNullptr, |
|
&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}); |
|
} |
|
|
|
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::constructIndex2DNotIndexed() { |
|
MeshIndexData indices{Containers::StridedArrayView2D<const char>{}}; |
|
CORRADE_COMPARE(indices.type(), MeshIndexType{}); |
|
CORRADE_COMPARE(indices.data().data(), nullptr); |
|
} |
|
|
|
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::constructAttributeDefault() { |
|
MeshAttributeData data; |
|
CORRADE_COMPARE(data.name(), MeshAttribute{}); |
|
CORRADE_COMPARE(data.format(), VertexFormat{}); |
|
|
|
constexpr MeshAttributeData cdata; |
|
CORRADE_COMPARE(cdata.name(), MeshAttribute{}); |
|
CORRADE_COMPARE(cdata.format(), VertexFormat{}); |
|
} |
|
|
|
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)}; |
|
MeshAttributeData{meshAttributeCustom(1), VertexFormat::Float, Containers::arrayCast<const Vector3>(positionData), 4}; |
|
/* 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 enough to fit VertexFormat::Float[4], got 12\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, Containers::StridedArrayView2D<char>{vertexData, {3, 4*sizeof(Vector2)}}, 4}; |
|
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, |
|
Containers::StridedArrayView2D<char>{vertexData, |
|
{3, 4*sizeof(Vector2)}}, 3}; |
|
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, |
|
Containers::StridedArrayView2D<char>{vertexData, |
|
{3, sizeof(Vector2)*4}}.every({1, 2}), 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, attribute, 4}; |
|
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::constructArrayAttributeNullptr() { |
|
MeshAttributeData positions{meshAttributeCustom(35), VertexFormat::Vector2, nullptr, 4}; |
|
CORRADE_VERIFY(!positions.isOffsetOnly()); |
|
CORRADE_COMPARE(positions.arraySize(), 4); |
|
CORRADE_COMPARE(positions.name(), meshAttributeCustom(35)); |
|
CORRADE_COMPARE(positions.format(), VertexFormat::Vector2); |
|
CORRADE_VERIFY(!positions.data().data()); |
|
} |
|
|
|
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, positions, 0}; |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector2, 0, 3, 6*sizeof(Vector2), 0}; |
|
MeshAttributeData{meshAttributeCustom(35), vertexFormatWrap(0xdead), positions, 0}; |
|
MeshAttributeData{meshAttributeCustom(35), positions2D}; |
|
MeshAttributeData{meshAttributeCustom(35), VertexFormat::Vector2, positions2Dchar, 3}; |
|
MeshAttributeData{meshAttributeCustom(35), VertexFormat::Vector2, 0, 3, 6*sizeof(Vector2), 3}; |
|
|
|
/* This is not */ |
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector2b, Containers::arrayView(positionData), 3}; |
|
MeshAttributeData{meshAttributeCustom(35), vertexFormatWrap(0xdead), Containers::arrayView(positionData), 3}; |
|
MeshAttributeData{MeshAttribute::Position, positions2D}; |
|
MeshAttributeData{MeshAttribute::Position, VertexFormat::Vector2, positions2Dchar, 3}; |
|
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.indices().size(), (Containers::StridedArrayView2D<std::size_t>::Size{0, 4})); |
|
CORRADE_COMPARE(data.mutableIndices().size(), (Containers::StridedArrayView2D<std::size_t>::Size{0, 4})); |
|
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.importerState(), &importerState); |
|
|
|
/* Access to indexData() and typeless access to (mutable)indices() is |
|
allowed, to allow creation of MeshData instances referencing other |
|
MeshData without having to branch on isIndexed(). */ |
|
CORRADE_VERIFY(!data.isIndexed()); |
|
CORRADE_COMPARE(data.indexData(), nullptr); |
|
CORRADE_COMPARE(data.indices().data(), nullptr); |
|
CORRADE_COMPARE(data.indices().size(), (Containers::StridedArrayView2D<std::size_t>::Size{0, 0})); |
|
CORRADE_COMPARE(data.mutableIndices().data(), nullptr); |
|
CORRADE_COMPARE(data.mutableIndices().size(), (Containers::StridedArrayView2D<std::size_t>::Size{0, 0})); |
|
|
|
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<UnsignedInt>(); |
|
data.mutableIndices<UnsignedShort>(); |
|
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::mutableIndices(): 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); |
|
} |
|
|
|
}}}} |
|
|
|
CORRADE_TEST_MAIN(Magnum::Trade::Test::MeshDataTest)
|
|
|