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.
4967 lines
224 KiB
4967 lines
224 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
2020, 2021 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/Containers/ArrayTuple.h> |
|
#include <Corrade/Containers/Optional.h> |
|
#include <Corrade/Containers/Pair.h> |
|
#include <Corrade/Containers/Triple.h> |
|
#include <Corrade/TestSuite/Tester.h> |
|
#include <Corrade/TestSuite/Compare/Container.h> |
|
#include <Corrade/Utility/DebugStl.h> |
|
#include <Corrade/Utility/FormatStl.h> |
|
|
|
#include "Magnum/Magnum.h" |
|
#include "Magnum/Math/Half.h" |
|
#include "Magnum/Math/DualComplex.h" |
|
#include "Magnum/Math/DualQuaternion.h" |
|
#include "Magnum/Math/Range.h" |
|
#include "Magnum/Trade/SceneData.h" |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
#include <vector> |
|
#include <Corrade/Containers/GrowableArray.h> |
|
#endif |
|
|
|
namespace Magnum { namespace Trade { namespace Test { namespace { |
|
|
|
struct SceneDataTest: TestSuite::Tester { |
|
explicit SceneDataTest(); |
|
|
|
void objectTypeSizeAlignment(); |
|
void objectTypeSizeAlignmentInvalid(); |
|
void debugObjectType(); |
|
|
|
void customFieldName(); |
|
void customFieldNameTooLarge(); |
|
void customFieldNameNotCustom(); |
|
void debugFieldName(); |
|
|
|
void fieldTypeSizeAlignment(); |
|
void fieldTypeSizeAlignmentInvalid(); |
|
void debugFieldType(); |
|
|
|
void constructField(); |
|
void constructFieldDefault(); |
|
void constructFieldCustom(); |
|
void constructField2D(); |
|
void constructFieldTypeErased(); |
|
void constructFieldNonOwningArray(); |
|
void constructFieldOffsetOnly(); |
|
void constructFieldArray(); |
|
void constructFieldArray2D(); |
|
void constructFieldArrayTypeErased(); |
|
void constructFieldArrayOffsetOnly(); |
|
|
|
void constructFieldWrongType(); |
|
void constructFieldInconsistentViewSize(); |
|
void constructFieldTooLargeObjectStride(); |
|
void constructFieldTooLargeFieldStride(); |
|
void constructFieldWrongDataAccess(); |
|
void constructField2DWrongSize(); |
|
void constructField2DNonContiguous(); |
|
void constructFieldArrayNonContiguous(); |
|
void constructFieldArrayNotAllowed(); |
|
void constructFieldArray2DWrongSize(); |
|
void constructFieldArray2DNonContiguous(); |
|
|
|
void construct(); |
|
void constructZeroFields(); |
|
void constructZeroObjects(); |
|
void constructNotOwned(); |
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
void constructDeprecated(); |
|
void constructDeprecatedBoth2DAnd3D(); |
|
#endif |
|
|
|
void constructDuplicateField(); |
|
void constructDuplicateCustomField(); |
|
void constructInconsistentObjectType(); |
|
void constructObjectDataNotContained(); |
|
void constructFieldDataNotContained(); |
|
void constructObjectTypeTooSmall(); |
|
void constructNotOwnedFlagOwned(); |
|
void constructMismatchedTRSViews(); |
|
template<class T> void constructMismatchedTRSDimensionality(); |
|
void constructMismatchedMeshMaterialView(); |
|
void constructAmbiguousSkinDimensions(); |
|
|
|
void constructCopy(); |
|
void constructMove(); |
|
|
|
template<class T> void objectsAsArrayByIndex(); |
|
template<class T> void objectsAsArrayByName(); |
|
void objectsAsArrayLongType(); |
|
void objectsIntoArrayByIndex(); |
|
void objectsIntoArrayByName(); |
|
void objectsIntoArrayInvalidSizeOrOffset(); |
|
template<class T> void parentsAsArray(); |
|
#ifndef CORRADE_TARGET_32BIT |
|
void parentsAsArrayLongType(); |
|
#endif |
|
void parentsIntoArray(); |
|
void parentsIntoArrayInvalidSizeOrOffset(); |
|
template<class T> void transformations2DAsArray(); |
|
template<class T, class U, class V> void transformations2DAsArrayTRS(); |
|
void transformations2DAsArrayBut3DType(); |
|
void transformations2DIntoArray(); |
|
void transformations2DIntoArrayTRS(); |
|
void transformations2DIntoArrayInvalidSizeOrOffset(); |
|
void transformations2DIntoArrayInvalidSizeOrOffsetTRS(); |
|
template<class T> void transformations3DAsArray(); |
|
template<class T, class U, class V> void transformations3DAsArrayTRS(); |
|
void transformations3DAsArrayBut2DType(); |
|
void transformations3DIntoArray(); |
|
void transformations3DIntoArrayTRS(); |
|
void transformations3DIntoArrayInvalidSizeOrOffset(); |
|
void transformations3DIntoArrayInvalidSizeOrOffsetTRS(); |
|
template<class T, class U> void meshesMaterialsAsArray(); |
|
void meshesMaterialsIntoArray(); |
|
void meshesMaterialsIntoArrayInvalidSizeOrOffset(); |
|
template<class T> void lightsAsArray(); |
|
void lightsIntoArray(); |
|
void lightsIntoArrayInvalidSizeOrOffset(); |
|
template<class T> void camerasAsArray(); |
|
void camerasIntoArray(); |
|
void camerasIntoArrayInvalidSizeOrOffset(); |
|
template<class T> void skinsAsArray(); |
|
void skinsIntoArray(); |
|
void skinsIntoArrayInvalidSizeOrOffset(); |
|
template<class T> void importerStateAsArray(); |
|
void importerStateIntoArray(); |
|
void importerStateIntoArrayInvalidSizeOrOffset(); |
|
|
|
void mutableAccessNotAllowed(); |
|
|
|
void objectsNotFound(); |
|
void objectsWrongType(); |
|
|
|
void fieldNotFound(); |
|
void fieldWrongType(); |
|
void fieldWrongPointerType(); |
|
void fieldWrongArrayAccess(); |
|
|
|
/* Different object types checked just for the parentFor(), other APIs |
|
use the same helper */ |
|
template<class T> void parentFor(); |
|
void childrenFor(); |
|
void transformation2DFor(); |
|
void transformation2DForTRS(); |
|
void transformation2DForBut3DType(); |
|
void transformation3DFor(); |
|
void transformation3DForTRS(); |
|
void transformation3DForBut2DType(); |
|
void meshesMaterialsFor(); |
|
void lightsFor(); |
|
void camerasFor(); |
|
void skinsFor(); |
|
void importerStateFor(); |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
void childrenDeprecated(); |
|
#endif |
|
|
|
void fieldForFieldMissing(); |
|
void fieldForInvalidObject(); |
|
|
|
void releaseFieldData(); |
|
void releaseData(); |
|
}; |
|
|
|
const struct { |
|
const char* name; |
|
DataFlags dataFlags; |
|
} NotOwnedData[]{ |
|
{"", {}}, |
|
{"mutable", DataFlag::Mutable} |
|
}; |
|
|
|
const struct { |
|
const char* name; |
|
std::size_t offset; |
|
std::size_t size; |
|
std::size_t expectedSize; |
|
} IntoArrayOffsetData[]{ |
|
{"whole", 0, 3, 3}, |
|
{"one element in the middle", 1, 1, 1}, |
|
{"suffix to a larger array", 2, 10, 1}, |
|
{"offset at the end", 3, 10, 0} |
|
}; |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
const struct { |
|
const char* name; |
|
bool is2D; |
|
bool is3D; |
|
} ChildrenDeprecatedData[]{ |
|
{"2D", true, false}, |
|
{"3D", false, true}, |
|
{"neither", false, false} |
|
}; |
|
#endif |
|
|
|
SceneDataTest::SceneDataTest() { |
|
addTests({&SceneDataTest::objectTypeSizeAlignment, |
|
&SceneDataTest::objectTypeSizeAlignmentInvalid, |
|
&SceneDataTest::debugObjectType, |
|
|
|
&SceneDataTest::customFieldName, |
|
&SceneDataTest::customFieldNameTooLarge, |
|
&SceneDataTest::customFieldNameNotCustom, |
|
&SceneDataTest::debugFieldName, |
|
|
|
&SceneDataTest::fieldTypeSizeAlignment, |
|
&SceneDataTest::fieldTypeSizeAlignmentInvalid, |
|
&SceneDataTest::debugFieldType, |
|
|
|
&SceneDataTest::constructField, |
|
&SceneDataTest::constructFieldDefault, |
|
&SceneDataTest::constructFieldCustom, |
|
&SceneDataTest::constructField2D, |
|
&SceneDataTest::constructFieldTypeErased, |
|
&SceneDataTest::constructFieldNonOwningArray, |
|
&SceneDataTest::constructFieldOffsetOnly, |
|
&SceneDataTest::constructFieldArray, |
|
&SceneDataTest::constructFieldArray2D, |
|
&SceneDataTest::constructFieldArrayTypeErased, |
|
&SceneDataTest::constructFieldArrayOffsetOnly, |
|
|
|
&SceneDataTest::constructFieldWrongType, |
|
&SceneDataTest::constructFieldInconsistentViewSize, |
|
&SceneDataTest::constructFieldTooLargeObjectStride, |
|
&SceneDataTest::constructFieldTooLargeFieldStride, |
|
&SceneDataTest::constructFieldWrongDataAccess, |
|
&SceneDataTest::constructField2DWrongSize, |
|
&SceneDataTest::constructField2DNonContiguous, |
|
&SceneDataTest::constructFieldArrayNonContiguous, |
|
&SceneDataTest::constructFieldArrayNotAllowed, |
|
&SceneDataTest::constructFieldArray2DWrongSize, |
|
&SceneDataTest::constructFieldArray2DNonContiguous, |
|
|
|
&SceneDataTest::construct, |
|
&SceneDataTest::constructZeroFields, |
|
&SceneDataTest::constructZeroObjects}); |
|
|
|
addInstancedTests({&SceneDataTest::constructNotOwned}, |
|
Containers::arraySize(NotOwnedData)); |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
addInstancedTests({&SceneDataTest::constructDeprecated}, |
|
Containers::arraySize(ChildrenDeprecatedData)); |
|
|
|
addTests({&SceneDataTest::constructDeprecatedBoth2DAnd3D}); |
|
#endif |
|
|
|
addTests({&SceneDataTest::constructDuplicateField, |
|
&SceneDataTest::constructDuplicateCustomField, |
|
&SceneDataTest::constructInconsistentObjectType, |
|
&SceneDataTest::constructObjectDataNotContained, |
|
&SceneDataTest::constructFieldDataNotContained, |
|
&SceneDataTest::constructObjectTypeTooSmall, |
|
&SceneDataTest::constructNotOwnedFlagOwned, |
|
&SceneDataTest::constructMismatchedTRSViews, |
|
&SceneDataTest::constructMismatchedTRSDimensionality<Float>, |
|
&SceneDataTest::constructMismatchedTRSDimensionality<Double>, |
|
&SceneDataTest::constructMismatchedMeshMaterialView, |
|
&SceneDataTest::constructAmbiguousSkinDimensions, |
|
|
|
&SceneDataTest::constructCopy, |
|
&SceneDataTest::constructMove, |
|
|
|
&SceneDataTest::objectsAsArrayByIndex<UnsignedByte>, |
|
&SceneDataTest::objectsAsArrayByIndex<UnsignedShort>, |
|
&SceneDataTest::objectsAsArrayByIndex<UnsignedInt>, |
|
&SceneDataTest::objectsAsArrayByIndex<UnsignedLong>, |
|
&SceneDataTest::objectsAsArrayByName<UnsignedByte>, |
|
&SceneDataTest::objectsAsArrayByName<UnsignedShort>, |
|
&SceneDataTest::objectsAsArrayByName<UnsignedInt>, |
|
&SceneDataTest::objectsAsArrayByName<UnsignedLong>, |
|
&SceneDataTest::objectsAsArrayLongType}); |
|
|
|
addInstancedTests({&SceneDataTest::objectsIntoArrayByIndex, |
|
&SceneDataTest::objectsIntoArrayByName}, |
|
Containers::arraySize(IntoArrayOffsetData)); |
|
|
|
addTests({&SceneDataTest::objectsIntoArrayInvalidSizeOrOffset, |
|
&SceneDataTest::parentsAsArray<Byte>, |
|
&SceneDataTest::parentsAsArray<Short>, |
|
&SceneDataTest::parentsAsArray<Int>, |
|
&SceneDataTest::parentsAsArray<Long>, |
|
#ifndef CORRADE_TARGET_32BIT |
|
&SceneDataTest::parentsAsArrayLongType, |
|
#endif |
|
}); |
|
|
|
addInstancedTests({&SceneDataTest::parentsIntoArray}, |
|
Containers::arraySize(IntoArrayOffsetData)); |
|
|
|
addTests({&SceneDataTest::parentsIntoArrayInvalidSizeOrOffset, |
|
&SceneDataTest::transformations2DAsArray<Matrix3>, |
|
&SceneDataTest::transformations2DAsArray<Matrix3d>, |
|
&SceneDataTest::transformations2DAsArray<DualComplex>, |
|
&SceneDataTest::transformations2DAsArray<DualComplexd>, |
|
&SceneDataTest::transformations2DAsArrayTRS<Float, Float, Double>, |
|
&SceneDataTest::transformations2DAsArrayTRS<Double, Double, Float>, |
|
&SceneDataTest::transformations2DAsArrayBut3DType}); |
|
|
|
addInstancedTests({&SceneDataTest::transformations2DIntoArray, |
|
&SceneDataTest::transformations2DIntoArrayTRS}, |
|
Containers::arraySize(IntoArrayOffsetData)); |
|
|
|
addTests({&SceneDataTest::transformations2DIntoArrayInvalidSizeOrOffset, |
|
&SceneDataTest::transformations2DIntoArrayInvalidSizeOrOffsetTRS, |
|
&SceneDataTest::transformations3DAsArray<Matrix4>, |
|
&SceneDataTest::transformations3DAsArray<Matrix4d>, |
|
&SceneDataTest::transformations3DAsArray<DualQuaternion>, |
|
&SceneDataTest::transformations3DAsArray<DualQuaterniond>, |
|
&SceneDataTest::transformations3DAsArrayTRS<Float, Double, Double>, |
|
&SceneDataTest::transformations3DAsArrayTRS<Double, Float, Float>, |
|
&SceneDataTest::transformations3DAsArrayBut2DType}); |
|
|
|
addInstancedTests({&SceneDataTest::transformations3DIntoArray, |
|
&SceneDataTest::transformations3DIntoArrayTRS}, |
|
Containers::arraySize(IntoArrayOffsetData)); |
|
|
|
addTests({&SceneDataTest::transformations3DIntoArrayInvalidSizeOrOffset, |
|
&SceneDataTest::transformations3DIntoArrayInvalidSizeOrOffsetTRS, |
|
&SceneDataTest::meshesMaterialsAsArray<UnsignedByte, Int>, |
|
&SceneDataTest::meshesMaterialsAsArray<UnsignedShort, Byte>, |
|
&SceneDataTest::meshesMaterialsAsArray<UnsignedInt, Short>}); |
|
|
|
addInstancedTests({&SceneDataTest::meshesMaterialsIntoArray}, |
|
Containers::arraySize(IntoArrayOffsetData)); |
|
|
|
addTests({&SceneDataTest::meshesMaterialsIntoArrayInvalidSizeOrOffset, |
|
&SceneDataTest::lightsAsArray<UnsignedByte>, |
|
&SceneDataTest::lightsAsArray<UnsignedShort>, |
|
&SceneDataTest::lightsAsArray<UnsignedInt>}); |
|
|
|
addInstancedTests({&SceneDataTest::lightsIntoArray}, |
|
Containers::arraySize(IntoArrayOffsetData)); |
|
|
|
addTests({&SceneDataTest::lightsIntoArrayInvalidSizeOrOffset, |
|
&SceneDataTest::camerasAsArray<UnsignedByte>, |
|
&SceneDataTest::camerasAsArray<UnsignedShort>, |
|
&SceneDataTest::camerasAsArray<UnsignedInt>}); |
|
|
|
addInstancedTests({&SceneDataTest::camerasIntoArray}, |
|
Containers::arraySize(IntoArrayOffsetData)); |
|
|
|
addTests({&SceneDataTest::camerasIntoArrayInvalidSizeOrOffset, |
|
&SceneDataTest::skinsAsArray<UnsignedByte>, |
|
&SceneDataTest::skinsAsArray<UnsignedShort>, |
|
&SceneDataTest::skinsAsArray<UnsignedInt>}); |
|
|
|
addInstancedTests({&SceneDataTest::skinsIntoArray}, |
|
Containers::arraySize(IntoArrayOffsetData)); |
|
|
|
addTests({&SceneDataTest::skinsIntoArrayInvalidSizeOrOffset, |
|
&SceneDataTest::importerStateAsArray<const void*>, |
|
&SceneDataTest::importerStateAsArray<void*>}); |
|
|
|
addInstancedTests({&SceneDataTest::importerStateIntoArray}, |
|
Containers::arraySize(IntoArrayOffsetData)); |
|
|
|
addTests({&SceneDataTest::importerStateIntoArrayInvalidSizeOrOffset, |
|
|
|
&SceneDataTest::mutableAccessNotAllowed, |
|
|
|
&SceneDataTest::objectsNotFound, |
|
&SceneDataTest::objectsWrongType, |
|
|
|
&SceneDataTest::fieldNotFound, |
|
&SceneDataTest::fieldWrongType, |
|
&SceneDataTest::fieldWrongPointerType, |
|
&SceneDataTest::fieldWrongArrayAccess, |
|
|
|
&SceneDataTest::parentFor<UnsignedByte>, |
|
&SceneDataTest::parentFor<UnsignedShort>, |
|
&SceneDataTest::parentFor<UnsignedInt>, |
|
&SceneDataTest::parentFor<UnsignedLong>, |
|
&SceneDataTest::childrenFor, |
|
&SceneDataTest::transformation2DFor, |
|
&SceneDataTest::transformation2DForTRS, |
|
&SceneDataTest::transformation2DForBut3DType, |
|
&SceneDataTest::transformation3DFor, |
|
&SceneDataTest::transformation3DForTRS, |
|
&SceneDataTest::transformation3DForBut2DType, |
|
&SceneDataTest::meshesMaterialsFor, |
|
&SceneDataTest::lightsFor, |
|
&SceneDataTest::camerasFor, |
|
&SceneDataTest::skinsFor, |
|
&SceneDataTest::importerStateFor}); |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
addInstancedTests({&SceneDataTest::childrenDeprecated}, |
|
Containers::arraySize(ChildrenDeprecatedData)); |
|
#endif |
|
|
|
addTests({&SceneDataTest::fieldForFieldMissing, |
|
&SceneDataTest::fieldForInvalidObject, |
|
|
|
&SceneDataTest::releaseFieldData, |
|
&SceneDataTest::releaseData}); |
|
} |
|
|
|
using namespace Math::Literals; |
|
|
|
void SceneDataTest::objectTypeSizeAlignment() { |
|
CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedByte), 1); |
|
CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedByte), 1); |
|
CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedShort), 2); |
|
CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedShort), 2); |
|
CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedInt), 4); |
|
CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedInt), 4); |
|
CORRADE_COMPARE(sceneObjectTypeSize(SceneObjectType::UnsignedLong), 8); |
|
CORRADE_COMPARE(sceneObjectTypeAlignment(SceneObjectType::UnsignedLong), 8); |
|
} |
|
|
|
void SceneDataTest::objectTypeSizeAlignmentInvalid() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
|
|
sceneObjectTypeSize(SceneObjectType{}); |
|
sceneObjectTypeAlignment(SceneObjectType{}); |
|
sceneObjectTypeSize(SceneObjectType(0x73)); |
|
sceneObjectTypeAlignment(SceneObjectType(0x73)); |
|
|
|
CORRADE_COMPARE(out.str(), |
|
"Trade::sceneObjectTypeSize(): invalid type Trade::SceneObjectType(0x0)\n" |
|
"Trade::sceneObjectTypeAlignment(): invalid type Trade::SceneObjectType(0x0)\n" |
|
"Trade::sceneObjectTypeSize(): invalid type Trade::SceneObjectType(0x73)\n" |
|
"Trade::sceneObjectTypeAlignment(): invalid type Trade::SceneObjectType(0x73)\n"); |
|
} |
|
|
|
void SceneDataTest::debugObjectType() { |
|
std::ostringstream out; |
|
Debug{&out} << SceneObjectType::UnsignedLong << SceneObjectType(0x73); |
|
CORRADE_COMPARE(out.str(), "Trade::SceneObjectType::UnsignedLong Trade::SceneObjectType(0x73)\n"); |
|
} |
|
|
|
void SceneDataTest::customFieldName() { |
|
CORRADE_VERIFY(!isSceneFieldCustom(SceneField::Rotation)); |
|
CORRADE_VERIFY(!isSceneFieldCustom(SceneField(0x0fffffffu))); |
|
CORRADE_VERIFY(isSceneFieldCustom(SceneField::Custom)); |
|
CORRADE_VERIFY(isSceneFieldCustom(SceneField(0x80000000u))); |
|
|
|
CORRADE_COMPARE(UnsignedInt(sceneFieldCustom(0)), 0x80000000u); |
|
CORRADE_COMPARE(UnsignedInt(sceneFieldCustom(0xabcd)), 0x8000abcdu); |
|
CORRADE_COMPARE(UnsignedInt(sceneFieldCustom(0x7fffffff)), 0xffffffffu); |
|
|
|
CORRADE_COMPARE(sceneFieldCustom(SceneField::Custom), 0); |
|
CORRADE_COMPARE(sceneFieldCustom(SceneField(0x8000abcdu)), 0xabcd); |
|
CORRADE_COMPARE(sceneFieldCustom(SceneField(0xffffffffu)), 0x7fffffffu); |
|
|
|
constexpr bool is = isSceneFieldCustom(SceneField(0x8000abcdu)); |
|
CORRADE_VERIFY(is); |
|
constexpr SceneField a = sceneFieldCustom(0xabcd); |
|
CORRADE_COMPARE(UnsignedInt(a), 0x8000abcdu); |
|
constexpr UnsignedInt b = sceneFieldCustom(a); |
|
CORRADE_COMPARE(b, 0xabcd); |
|
} |
|
|
|
void SceneDataTest::customFieldNameTooLarge() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
sceneFieldCustom(1u << 31); |
|
CORRADE_COMPARE(out.str(), "Trade::sceneFieldCustom(): index 2147483648 too large\n"); |
|
} |
|
|
|
void SceneDataTest::customFieldNameNotCustom() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
sceneFieldCustom(SceneField::Transformation); |
|
CORRADE_COMPARE(out.str(), "Trade::sceneFieldCustom(): Trade::SceneField::Transformation is not custom\n"); |
|
} |
|
|
|
void SceneDataTest::debugFieldName() { |
|
std::ostringstream out; |
|
Debug{&out} << SceneField::Transformation << sceneFieldCustom(73) << SceneField(0xdeadda7); |
|
CORRADE_COMPARE(out.str(), "Trade::SceneField::Transformation Trade::SceneField::Custom(73) Trade::SceneField(0xdeadda7)\n"); |
|
} |
|
|
|
void SceneDataTest::fieldTypeSizeAlignment() { |
|
/* Test at least one of every size */ |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Byte), sizeof(Byte)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Degh), sizeof(Degh)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Vector3ub), sizeof(Vector3ub)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Range1Dh), sizeof(Range1Dh)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Vector3s), sizeof(Vector3s)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Long), sizeof(Long)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix3x2h), sizeof(Matrix3x2h)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix4x2h), sizeof(Matrix4x2h)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix3x3h), sizeof(Matrix3x3h)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Range3Di), sizeof(Range3Di)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::DualQuaternion), sizeof(DualQuaternion)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix3x3), sizeof(Matrix3x3)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix3x2d), sizeof(Matrix3x2d)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::DualQuaterniond), sizeof(DualQuaterniond)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix3x3d), sizeof(Matrix3x3d)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix3x4d), sizeof(Matrix3x4d)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Matrix4x4d), sizeof(Matrix4x4d)); |
|
CORRADE_COMPARE(sceneFieldTypeSize(SceneFieldType::Pointer), sizeof(const void*)); |
|
|
|
/* Test at least one of every alignment */ |
|
CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::Vector3ub), alignof(UnsignedByte)); |
|
CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::Matrix3x3h), alignof(Half)); |
|
CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::Range3Di), alignof(UnsignedInt)); |
|
CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::DualComplexd), alignof(Double)); |
|
CORRADE_COMPARE(sceneFieldTypeAlignment(SceneFieldType::Pointer), alignof(const void*)); |
|
} |
|
|
|
void SceneDataTest::fieldTypeSizeAlignmentInvalid() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
|
|
sceneFieldTypeSize(SceneFieldType{}); |
|
sceneFieldTypeAlignment(SceneFieldType{}); |
|
sceneFieldTypeSize(SceneFieldType(0xdead)); |
|
sceneFieldTypeAlignment(SceneFieldType(0xdead)); |
|
|
|
CORRADE_COMPARE(out.str(), |
|
"Trade::sceneFieldTypeSize(): invalid type Trade::SceneFieldType(0x0)\n" |
|
"Trade::sceneFieldTypeAlignment(): invalid type Trade::SceneFieldType(0x0)\n" |
|
"Trade::sceneFieldTypeSize(): invalid type Trade::SceneFieldType(0xdead)\n" |
|
"Trade::sceneFieldTypeAlignment(): invalid type Trade::SceneFieldType(0xdead)\n"); |
|
} |
|
|
|
void SceneDataTest::debugFieldType() { |
|
std::ostringstream out; |
|
Debug{&out} << SceneFieldType::Matrix3x4h << SceneFieldType(0xdead); |
|
CORRADE_COMPARE(out.str(), "Trade::SceneFieldType::Matrix3x4h Trade::SceneFieldType(0xdead)\n"); |
|
} |
|
|
|
constexpr Complexd Rotations2D[3] { |
|
Complexd{Constantsd::sqrtHalf(), Constantsd::sqrtHalf()}, /* 45° */ |
|
Complexd{1.0, 0.0}, /* 0° */ |
|
Complexd{0.0, 1.0}, /* 90° */ |
|
}; |
|
const UnsignedShort RotationObjects2D[3] { |
|
17, |
|
35, |
|
98 |
|
}; |
|
|
|
void SceneDataTest::constructField() { |
|
const UnsignedShort rotationObjectData[3]{}; |
|
const Complexd rotationFieldData[3]; |
|
|
|
SceneFieldData rotations{SceneField::Rotation, Containers::arrayView(rotationObjectData), Containers::arrayView(rotationFieldData)}; |
|
CORRADE_VERIFY(!rotations.isOffsetOnly()); |
|
CORRADE_COMPARE(rotations.name(), SceneField::Rotation); |
|
CORRADE_COMPARE(rotations.size(), 3); |
|
CORRADE_COMPARE(rotations.objectType(), SceneObjectType::UnsignedShort); |
|
CORRADE_COMPARE(rotations.objectData().size(), 3); |
|
CORRADE_COMPARE(rotations.objectData().stride(), sizeof(UnsignedShort)); |
|
CORRADE_VERIFY(rotations.objectData().data() == rotationObjectData); |
|
CORRADE_COMPARE(rotations.fieldType(), SceneFieldType::Complexd); |
|
CORRADE_COMPARE(rotations.fieldArraySize(), 0); |
|
CORRADE_COMPARE(rotations.fieldData().size(), 3); |
|
CORRADE_COMPARE(rotations.fieldData().stride(), sizeof(Complexd)); |
|
CORRADE_VERIFY(rotations.fieldData().data() == rotationFieldData); |
|
|
|
/* This is allowed too for simplicity, the parameter has to be large enough |
|
tho */ |
|
char someArray[3*sizeof(Complexd)]; |
|
CORRADE_COMPARE(rotations.fieldData(someArray).size(), 3); |
|
CORRADE_COMPARE(rotations.fieldData(someArray).stride(), sizeof(Complexd)); |
|
CORRADE_VERIFY(rotations.fieldData(someArray).data() == rotationFieldData); |
|
CORRADE_COMPARE(rotations.objectData(someArray).size(), 3); |
|
CORRADE_COMPARE(rotations.objectData(someArray).stride(), sizeof(UnsignedShort)); |
|
CORRADE_VERIFY(rotations.objectData(someArray).data() == rotationObjectData); |
|
|
|
#ifndef CORRADE_MSVC2015_COMPATIBILITY /* Won't bother anymore */ |
|
constexpr SceneFieldData crotations{SceneField::Rotation, Containers::arrayView(RotationObjects2D), Containers::arrayView(Rotations2D)}; |
|
constexpr bool isOffsetOnly = crotations.isOffsetOnly(); |
|
constexpr SceneField name = crotations.name(); |
|
constexpr SceneObjectType objectType = crotations.objectType(); |
|
constexpr Containers::StridedArrayView1D<const void> objectData = crotations.objectData(); |
|
constexpr SceneFieldType fieldType = crotations.fieldType(); |
|
constexpr UnsignedShort fieldArraySize = crotations.fieldArraySize(); |
|
constexpr Containers::StridedArrayView1D<const void> fieldData = crotations.fieldData(); |
|
CORRADE_VERIFY(!isOffsetOnly); |
|
CORRADE_COMPARE(name, SceneField::Rotation); |
|
CORRADE_COMPARE(objectType, SceneObjectType::UnsignedShort); |
|
CORRADE_COMPARE(objectData.size(), 3); |
|
CORRADE_COMPARE(objectData.stride(), sizeof(UnsignedShort)); |
|
CORRADE_COMPARE(objectData.data(), RotationObjects2D); |
|
CORRADE_COMPARE(fieldType, SceneFieldType::Complexd); |
|
CORRADE_COMPARE(fieldArraySize, 0); |
|
CORRADE_COMPARE(fieldData.size(), 3); |
|
CORRADE_COMPARE(fieldData.stride(), sizeof(Complexd)); |
|
CORRADE_COMPARE(fieldData.data(), Rotations2D); |
|
#endif |
|
} |
|
|
|
void SceneDataTest::constructFieldDefault() { |
|
SceneFieldData data; |
|
CORRADE_COMPARE(data.name(), SceneField{}); |
|
CORRADE_COMPARE(data.fieldType(), SceneFieldType{}); |
|
CORRADE_COMPARE(data.objectType(), SceneObjectType{}); |
|
|
|
constexpr SceneFieldData cdata; |
|
CORRADE_COMPARE(cdata.name(), SceneField{}); |
|
CORRADE_COMPARE(cdata.fieldType(), SceneFieldType{}); |
|
CORRADE_COMPARE(cdata.objectType(), SceneObjectType{}); |
|
} |
|
|
|
void SceneDataTest::constructFieldCustom() { |
|
/* Verifying it doesn't hit any assertion about disallowed type for given |
|
attribute */ |
|
|
|
const UnsignedByte rangeObjectData[3]{}; |
|
const Range2Dh rangeFieldData[3]; |
|
SceneFieldData ranges{sceneFieldCustom(13), Containers::arrayView(rangeObjectData), Containers::arrayView(rangeFieldData)}; |
|
CORRADE_COMPARE(ranges.name(), sceneFieldCustom(13)); |
|
CORRADE_COMPARE(ranges.objectType(), SceneObjectType::UnsignedByte); |
|
CORRADE_VERIFY(ranges.objectData().data() == rangeObjectData); |
|
CORRADE_COMPARE(ranges.fieldType(), SceneFieldType::Range2Dh); |
|
CORRADE_VERIFY(ranges.fieldData().data() == rangeFieldData); |
|
} |
|
|
|
void SceneDataTest::constructField2D() { |
|
char rotationObjectData[6*sizeof(UnsignedShort)]; |
|
char rotationFieldData[6*sizeof(Complexd)]; |
|
auto rotationObjectView = Containers::StridedArrayView2D<char>{rotationObjectData, {6, sizeof(UnsignedShort)}}.every(2); |
|
auto rotationFieldView = Containers::StridedArrayView2D<char>{rotationFieldData, {6, sizeof(Complexd)}}.every(2); |
|
|
|
SceneFieldData rotations{SceneField::Rotation, rotationObjectView, SceneFieldType::Complexd, rotationFieldView}; |
|
CORRADE_VERIFY(!rotations.isOffsetOnly()); |
|
CORRADE_COMPARE(rotations.name(), SceneField::Rotation); |
|
CORRADE_COMPARE(rotations.size(), 3); |
|
CORRADE_COMPARE(rotations.objectType(), SceneObjectType::UnsignedShort); |
|
CORRADE_COMPARE(rotations.objectData().size(), 3); |
|
CORRADE_COMPARE(rotations.objectData().stride(), 2*sizeof(UnsignedShort)); |
|
CORRADE_COMPARE(rotations.objectData().data(), rotationObjectView.data()); |
|
CORRADE_COMPARE(rotations.fieldType(), SceneFieldType::Complexd); |
|
CORRADE_COMPARE(rotations.fieldArraySize(), 0); |
|
CORRADE_COMPARE(rotations.fieldData().size(), 3); |
|
CORRADE_COMPARE(rotations.fieldData().stride(), 2*sizeof(Complexd)); |
|
CORRADE_COMPARE(rotations.fieldData().data(), rotationFieldView.data()); |
|
} |
|
|
|
void SceneDataTest::constructFieldTypeErased() { |
|
const UnsignedLong scalingObjectData[3]{}; |
|
const Vector3 scalingFieldData[3]; |
|
SceneFieldData scalings{SceneField::Scaling, SceneObjectType::UnsignedLong, Containers::arrayCast<const char>(Containers::stridedArrayView(scalingObjectData)), SceneFieldType::Vector3, Containers::arrayCast<const char>(Containers::stridedArrayView(scalingFieldData))}; |
|
CORRADE_VERIFY(!scalings.isOffsetOnly()); |
|
CORRADE_COMPARE(scalings.name(), SceneField::Scaling); |
|
CORRADE_COMPARE(scalings.size(), 3); |
|
CORRADE_COMPARE(scalings.objectType(), SceneObjectType::UnsignedLong); |
|
CORRADE_COMPARE(scalings.objectData().size(), 3); |
|
CORRADE_COMPARE(scalings.objectData().stride(), sizeof(UnsignedLong)); |
|
CORRADE_COMPARE(scalings.objectData().data(), scalingObjectData); |
|
CORRADE_COMPARE(scalings.fieldType(), SceneFieldType::Vector3); |
|
CORRADE_COMPARE(scalings.fieldArraySize(), 0); |
|
CORRADE_COMPARE(scalings.fieldData().size(), 3); |
|
CORRADE_COMPARE(scalings.fieldData().stride(), sizeof(Vector3)); |
|
CORRADE_COMPARE(scalings.fieldData().data(), scalingFieldData); |
|
} |
|
|
|
void SceneDataTest::constructFieldNonOwningArray() { |
|
const SceneFieldData data[3]; |
|
Containers::Array<SceneFieldData> array = sceneFieldDataNonOwningArray(data); |
|
CORRADE_COMPARE(array.size(), 3); |
|
CORRADE_COMPARE(static_cast<const void*>(array.data()), data); |
|
} |
|
|
|
void SceneDataTest::constructFieldOffsetOnly() { |
|
struct Data { |
|
Byte parent; |
|
UnsignedShort object; |
|
Vector2 translation; |
|
} data[] { |
|
{0, 2, {2.0f, 3.0f}}, |
|
{0, 15, {67.0f, -1.1f}} |
|
}; |
|
|
|
SceneFieldData a{SceneField::Translation, 2, SceneObjectType::UnsignedShort, offsetof(Data, object), sizeof(Data), SceneFieldType::Vector2, offsetof(Data, translation), sizeof(Data)}; |
|
CORRADE_VERIFY(a.isOffsetOnly()); |
|
CORRADE_COMPARE(a.name(), SceneField::Translation); |
|
CORRADE_COMPARE(a.size(), 2); |
|
CORRADE_COMPARE(a.objectType(), SceneObjectType::UnsignedShort); |
|
CORRADE_COMPARE(a.objectData(data).size(), 2); |
|
CORRADE_COMPARE(a.objectData(data).stride(), sizeof(Data)); |
|
CORRADE_COMPARE_AS(Containers::arrayCast<const UnsignedShort>(a.objectData(data)), |
|
Containers::arrayView<UnsignedShort>({2, 15}), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE(a.fieldType(), SceneFieldType::Vector2); |
|
CORRADE_COMPARE(a.fieldArraySize(), 0); |
|
CORRADE_COMPARE(a.fieldData(data).size(), 2); |
|
CORRADE_COMPARE(a.fieldData(data).stride(), sizeof(Data)); |
|
CORRADE_COMPARE_AS(Containers::arrayCast<const Vector2>(a.fieldData(data)), |
|
Containers::arrayView<Vector2>({{2.0f, 3.0f}, {67.0f, -1.1f}}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
constexpr UnsignedByte ArrayOffsetObjectData[3]{}; |
|
constexpr Int ArrayOffsetFieldData[3*4]{}; |
|
|
|
void SceneDataTest::constructFieldArray() { |
|
UnsignedByte offsetObjectData[3]; |
|
Int offsetFieldData[3*4]; |
|
SceneFieldData data{sceneFieldCustom(34), Containers::arrayView(offsetObjectData), Containers::StridedArrayView2D<Int>{offsetFieldData, {3, 4}}}; |
|
CORRADE_VERIFY(!data.isOffsetOnly()); |
|
CORRADE_COMPARE(data.name(), sceneFieldCustom(34)); |
|
CORRADE_COMPARE(data.size(), 3); |
|
CORRADE_COMPARE(data.objectType(), SceneObjectType::UnsignedByte); |
|
CORRADE_COMPARE(data.objectData().size(), 3); |
|
CORRADE_COMPARE(data.objectData().stride(), sizeof(UnsignedByte)); |
|
CORRADE_VERIFY(data.objectData().data() == offsetObjectData); |
|
CORRADE_COMPARE(data.fieldType(), SceneFieldType::Int); |
|
CORRADE_COMPARE(data.fieldArraySize(), 4); |
|
CORRADE_COMPARE(data.fieldData().size(), 3); |
|
CORRADE_COMPARE(data.fieldData().stride(), 4*sizeof(Int)); |
|
CORRADE_VERIFY(data.fieldData().data() == offsetFieldData); |
|
|
|
constexpr SceneFieldData cdata{sceneFieldCustom(34), Containers::arrayView(ArrayOffsetObjectData), Containers::StridedArrayView2D<const Int>{ArrayOffsetFieldData, {3, 4}}}; |
|
CORRADE_VERIFY(!cdata.isOffsetOnly()); |
|
CORRADE_COMPARE(cdata.name(), sceneFieldCustom(34)); |
|
CORRADE_COMPARE(cdata.size(), 3); |
|
CORRADE_COMPARE(cdata.objectType(), SceneObjectType::UnsignedByte); |
|
CORRADE_COMPARE(cdata.objectData().size(), 3); |
|
CORRADE_COMPARE(cdata.objectData().stride(), sizeof(UnsignedByte)); |
|
CORRADE_VERIFY(cdata.objectData().data() == ArrayOffsetObjectData); |
|
CORRADE_COMPARE(cdata.fieldType(), SceneFieldType::Int); |
|
CORRADE_COMPARE(cdata.fieldArraySize(), 4); |
|
CORRADE_COMPARE(cdata.fieldData().size(), 3); |
|
CORRADE_COMPARE(cdata.fieldData().stride(), 4*sizeof(Int)); |
|
CORRADE_VERIFY(cdata.fieldData().data() == ArrayOffsetFieldData); |
|
} |
|
|
|
void SceneDataTest::constructFieldArray2D() { |
|
char offsetObjectData[3*sizeof(UnsignedByte)]; |
|
char offsetFieldData[3*4*sizeof(Int)]; |
|
SceneFieldData data{sceneFieldCustom(34), Containers::StridedArrayView2D<char>{offsetObjectData, {3, sizeof(UnsignedByte)}}, SceneFieldType::Int, Containers::StridedArrayView2D<char>{offsetFieldData, {3, 4*sizeof(Int)}}, 4}; |
|
CORRADE_VERIFY(!data.isOffsetOnly()); |
|
CORRADE_COMPARE(data.name(), sceneFieldCustom(34)); |
|
CORRADE_COMPARE(data.size(), 3); |
|
CORRADE_COMPARE(data.objectType(), SceneObjectType::UnsignedByte); |
|
CORRADE_COMPARE(data.objectData().size(), 3); |
|
CORRADE_COMPARE(data.objectData().stride(), sizeof(UnsignedByte)); |
|
CORRADE_VERIFY(data.objectData().data() == offsetObjectData); |
|
CORRADE_COMPARE(data.fieldType(), SceneFieldType::Int); |
|
CORRADE_COMPARE(data.fieldArraySize(), 4); |
|
CORRADE_COMPARE(data.fieldData().size(), 3); |
|
CORRADE_COMPARE(data.fieldData().stride(), 4*sizeof(Int)); |
|
CORRADE_VERIFY(data.fieldData().data() == offsetFieldData); |
|
} |
|
|
|
void SceneDataTest::constructFieldArrayTypeErased() { |
|
Int offsetData[3*4]; |
|
Containers::StridedArrayView1D<Int> offset{offsetData, 3, 4*sizeof(Int)}; |
|
UnsignedByte offsetObjectData[3]; |
|
SceneFieldData data{sceneFieldCustom(34), SceneObjectType::UnsignedByte, Containers::arrayCast<const char>(Containers::stridedArrayView(offsetObjectData)), SceneFieldType::Int, Containers::arrayCast<const char>(offset), 4}; |
|
CORRADE_VERIFY(!data.isOffsetOnly()); |
|
CORRADE_COMPARE(data.name(), sceneFieldCustom(34)); |
|
CORRADE_COMPARE(data.size(), 3); |
|
CORRADE_COMPARE(data.fieldType(), SceneFieldType::Int); |
|
CORRADE_COMPARE(data.objectType(), SceneObjectType::UnsignedByte); |
|
CORRADE_COMPARE(data.objectData().size(), 3); |
|
CORRADE_COMPARE(data.objectData().stride(), sizeof(UnsignedByte)); |
|
CORRADE_VERIFY(data.objectData().data() == offsetObjectData); |
|
CORRADE_COMPARE(data.fieldArraySize(), 4); |
|
CORRADE_COMPARE(data.fieldData().size(), 3); |
|
CORRADE_COMPARE(data.fieldData().stride(), 4*sizeof(Int)); |
|
CORRADE_VERIFY(data.fieldData().data() == offsetData); |
|
} |
|
|
|
void SceneDataTest::constructFieldArrayOffsetOnly() { |
|
struct Data { |
|
Byte parent; |
|
UnsignedByte object; |
|
Int offset[4]; |
|
}; |
|
|
|
SceneFieldData data{sceneFieldCustom(34), 3, SceneObjectType::UnsignedByte, offsetof(Data, object), sizeof(Data), SceneFieldType::Int, offsetof(Data, offset), sizeof(Data), 4}; |
|
CORRADE_VERIFY(data.isOffsetOnly()); |
|
CORRADE_COMPARE(data.name(), sceneFieldCustom(34)); |
|
CORRADE_COMPARE(data.size(), 3); |
|
CORRADE_COMPARE(data.objectType(), SceneObjectType::UnsignedByte); |
|
CORRADE_COMPARE(data.fieldType(), SceneFieldType::Int); |
|
CORRADE_COMPARE(data.fieldArraySize(), 4); |
|
|
|
Data actual[3]; |
|
CORRADE_COMPARE(data.fieldData(actual).size(), 3); |
|
CORRADE_COMPARE(data.fieldData(actual).stride(), sizeof(Data)); |
|
CORRADE_VERIFY(data.fieldData(actual).data() == &actual[0].offset); |
|
CORRADE_COMPARE(data.objectData(actual).size(), 3); |
|
CORRADE_COMPARE(data.objectData(actual).stride(), sizeof(Data)); |
|
CORRADE_VERIFY(data.objectData(actual).data() == &actual[0].object); |
|
|
|
constexpr SceneFieldData cdata{sceneFieldCustom(34), 3, SceneObjectType::UnsignedByte, offsetof(Data, object), sizeof(Data), SceneFieldType::Int, offsetof(Data, offset), sizeof(Data), 4}; |
|
CORRADE_VERIFY(cdata.isOffsetOnly()); |
|
CORRADE_COMPARE(cdata.name(), sceneFieldCustom(34)); |
|
CORRADE_COMPARE(cdata.size(), 3); |
|
CORRADE_COMPARE(cdata.objectType(), SceneObjectType::UnsignedByte); |
|
CORRADE_COMPARE(cdata.fieldType(), SceneFieldType::Int); |
|
CORRADE_COMPARE(cdata.fieldArraySize(), 4); |
|
} |
|
|
|
void SceneDataTest::constructFieldInconsistentViewSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const UnsignedShort rotationObjectData[3]{}; |
|
const Complexd rotationFieldData[2]; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneFieldData{SceneField::Rotation, Containers::arrayView(rotationObjectData), Containers::arrayView(rotationFieldData)}; |
|
CORRADE_COMPARE(out.str(), "Trade::SceneFieldData: expected object and field view to have the same size but got 3 and 2\n"); |
|
} |
|
|
|
void SceneDataTest::constructFieldWrongType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const UnsignedShort rotationObjectData[3]{}; |
|
const Quaternion rotationFieldData[3]; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneFieldData{SceneField::Transformation, Containers::arrayView(rotationObjectData), Containers::arrayView(rotationFieldData)}; |
|
SceneFieldData{SceneField::Transformation, 3, SceneObjectType::UnsignedShort, 0, sizeof(UnsignedShort), SceneFieldType::Quaternion, 0, sizeof(Quaternion)}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneFieldData: Trade::SceneFieldType::Quaternion is not a valid type for Trade::SceneField::Transformation\n" |
|
"Trade::SceneFieldData: Trade::SceneFieldType::Quaternion is not a valid type for Trade::SceneField::Transformation\n"); |
|
} |
|
|
|
void SceneDataTest::constructFieldTooLargeObjectStride() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
UnsignedInt enough[2]; |
|
char toomuch[2*(32768 + sizeof(UnsignedInt))]; |
|
|
|
/* These should be fine */ |
|
SceneFieldData{SceneField::Mesh, SceneObjectType::UnsignedInt, Containers::StridedArrayView1D<UnsignedInt>{Containers::arrayCast<UnsignedInt>(toomuch), 2, 32767}, SceneFieldType::UnsignedInt, enough}; |
|
SceneFieldData{SceneField::Mesh, SceneObjectType::UnsignedInt, Containers::StridedArrayView1D<UnsignedInt>{Containers::arrayCast<UnsignedInt>(toomuch), 2, 32768}.flipped<0>(), SceneFieldType::UnsignedInt, enough}; |
|
SceneFieldData{SceneField::Mesh, 2, SceneObjectType::UnsignedInt, 0, 32767, SceneFieldType::UnsignedInt, 0, 4}; |
|
SceneFieldData{SceneField::Mesh, 2, SceneObjectType::UnsignedInt, 65536, -32768, SceneFieldType::UnsignedInt, 0, 4}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneFieldData{SceneField::Mesh, SceneObjectType::UnsignedInt, Containers::StridedArrayView1D<UnsignedInt>{Containers::arrayCast<UnsignedInt>(toomuch), 2, 32768}, SceneFieldType::UnsignedInt, enough}; |
|
SceneFieldData{SceneField::Mesh, SceneObjectType::UnsignedInt, Containers::StridedArrayView1D<UnsignedInt>{Containers::arrayCast<UnsignedInt>(toomuch), 2, 32769}.flipped<0>(), SceneFieldType::UnsignedInt, enough}; |
|
SceneFieldData{SceneField::Mesh, 2, SceneObjectType::UnsignedInt, 0, 32768, SceneFieldType::UnsignedInt, 0, 4}; |
|
SceneFieldData{SceneField::Mesh, 2, SceneObjectType::UnsignedInt, 65538, -32769, SceneFieldType::UnsignedInt, 0, 4}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneFieldData: expected object view stride to fit into 16 bits, but got 32768\n" |
|
"Trade::SceneFieldData: expected object view stride to fit into 16 bits, but got -32769\n" |
|
"Trade::SceneFieldData: expected object view stride to fit into 16 bits, but got 32768\n" |
|
"Trade::SceneFieldData: expected object view stride to fit into 16 bits, but got -32769\n"); |
|
} |
|
|
|
void SceneDataTest::constructFieldTooLargeFieldStride() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
UnsignedInt enough[2]; |
|
char toomuch[2*(32768 + sizeof(UnsignedInt))]; |
|
|
|
/* These should be fine */ |
|
SceneFieldData{SceneField::Mesh, SceneObjectType::UnsignedInt, enough, SceneFieldType::UnsignedInt, Containers::StridedArrayView1D<UnsignedInt>{Containers::arrayCast<UnsignedInt>(toomuch), 2, 32767}}; |
|
SceneFieldData{SceneField::Mesh, SceneObjectType::UnsignedInt, enough, SceneFieldType::UnsignedInt, Containers::StridedArrayView1D<UnsignedInt>{Containers::arrayCast<UnsignedInt>(toomuch), 2, 32768}.flipped<0>()}; |
|
SceneFieldData{SceneField::Mesh, 2, SceneObjectType::UnsignedInt, 0, 4, SceneFieldType::UnsignedInt, 0, 32767}; |
|
SceneFieldData{SceneField::Mesh, 2, SceneObjectType::UnsignedInt, 0, 4, SceneFieldType::UnsignedInt, 65536, -32768}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneFieldData{SceneField::Mesh, SceneObjectType::UnsignedInt, enough, SceneFieldType::UnsignedInt, Containers::StridedArrayView1D<UnsignedInt>{Containers::arrayCast<UnsignedInt>(toomuch), 2, 32768}}; |
|
SceneFieldData{SceneField::Mesh, SceneObjectType::UnsignedInt, enough, SceneFieldType::UnsignedInt, Containers::StridedArrayView1D<UnsignedInt>{Containers::arrayCast<UnsignedInt>(toomuch), 2, 32769}.flipped<0>()}; |
|
SceneFieldData{SceneField::Mesh, 2, SceneObjectType::UnsignedInt, 0, 4, SceneFieldType::UnsignedInt, 0, 32768}; |
|
SceneFieldData{SceneField::Mesh, 2, SceneObjectType::UnsignedInt, 0, 4, SceneFieldType::UnsignedInt, 65538, -32769}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneFieldData: expected field view stride to fit into 16 bits, but got 32768\n" |
|
"Trade::SceneFieldData: expected field view stride to fit into 16 bits, but got -32769\n" |
|
"Trade::SceneFieldData: expected field view stride to fit into 16 bits, but got 32768\n" |
|
"Trade::SceneFieldData: expected field view stride to fit into 16 bits, but got -32769\n"); |
|
} |
|
|
|
void SceneDataTest::constructFieldWrongDataAccess() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const UnsignedShort rotationObjectData[3]{}; |
|
const Quaternion rotationFieldData[3]; |
|
SceneFieldData a{SceneField::Rotation, Containers::arrayView(rotationObjectData), Containers::arrayView(rotationFieldData)}; |
|
SceneFieldData b{SceneField::Rotation, 3, SceneObjectType::UnsignedShort, 0, sizeof(UnsignedShort), SceneFieldType::Quaternion, 0, sizeof(Quaternion)}; |
|
CORRADE_VERIFY(!a.isOffsetOnly()); |
|
CORRADE_VERIFY(b.isOffsetOnly()); |
|
|
|
a.objectData(rotationObjectData); /* This is fine, no asserts */ |
|
a.fieldData(rotationFieldData); |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
b.objectData(); |
|
b.fieldData(); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneFieldData::objectData(): the field is offset-only, supply a data array\n" |
|
"Trade::SceneFieldData::fieldData(): the field is offset-only, supply a data array\n"); |
|
} |
|
|
|
void SceneDataTest::constructField2DWrongSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
char rotationFieldData[5*sizeof(Complex)]; |
|
char rotationObjectData[5*sizeof(UnsignedInt)]; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneFieldData{SceneField::Rotation, |
|
Containers::StridedArrayView2D<char>{rotationObjectData, {4, 5}}.every(2), |
|
SceneFieldType::Complex, |
|
Containers::StridedArrayView2D<char>{rotationFieldData, {4, sizeof(Complex)}}.every(2)}; |
|
SceneFieldData{SceneField::Translation, |
|
Containers::StridedArrayView2D<char>{rotationObjectData, {4, sizeof(UnsignedInt)}}.every(2), |
|
SceneFieldType::Vector3, |
|
Containers::StridedArrayView2D<char>{rotationFieldData, {4, sizeof(Complex)}}.every(2)}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneFieldData: expected second object view dimension size 1, 2, 4 or 8 but got 5\n" |
|
"Trade::SceneFieldData: second field view dimension size 8 doesn't match Trade::SceneFieldType::Vector3\n"); |
|
} |
|
|
|
void SceneDataTest::constructField2DNonContiguous() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
char rotationObjectData[8*sizeof(UnsignedInt)]; |
|
char rotationFieldData[8*sizeof(Complex)]; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneFieldData{SceneField::Rotation, |
|
Containers::StridedArrayView2D<char>{rotationObjectData, {4, 2*sizeof(UnsignedInt)}}.every({1, 2}), |
|
SceneFieldType::Complex, |
|
Containers::StridedArrayView2D<char>{rotationFieldData, {4, sizeof(Complex)}}}; |
|
SceneFieldData{SceneField::Rotation, |
|
Containers::StridedArrayView2D<char>{rotationObjectData, {4, sizeof(UnsignedInt)}}, |
|
SceneFieldType::Complex, |
|
Containers::StridedArrayView2D<char>{rotationFieldData, {4, 2*sizeof(Complex)}}.every({1, 2})}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneFieldData: second object view dimension is not contiguous\n" |
|
"Trade::SceneFieldData: second field view dimension is not contiguous\n"); |
|
} |
|
|
|
void SceneDataTest::constructFieldArrayNonContiguous() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
UnsignedByte offsetObjectData[3]; |
|
Int offsetFieldData[3*4]; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneFieldData data{sceneFieldCustom(34), Containers::arrayView(offsetObjectData), Containers::StridedArrayView2D<Int>{offsetFieldData, {3, 4}}.every({1, 2})}; |
|
CORRADE_COMPARE(out.str(), "Trade::SceneFieldData: second field view dimension is not contiguous\n"); |
|
} |
|
|
|
void SceneDataTest::constructFieldArrayNotAllowed() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
UnsignedShort rotationObjectData[3]{}; |
|
Quaternion rotationFieldData[3]; |
|
Containers::ArrayView<UnsignedShort> rotationObjects = rotationObjectData; |
|
Containers::ArrayView<Quaternion> rotationFields = rotationFieldData; |
|
Containers::StridedArrayView2D<Quaternion> rotationFields2D{rotationFieldData, {3, 3}, {0, sizeof(Quaternion)}}; |
|
auto rotationFields2DChar = Containers::arrayCast<2, const char>(rotationFields2D); |
|
auto rotationObjectsChar = Containers::arrayCast<2, const char>(rotationObjects); |
|
|
|
/* This is all fine */ |
|
SceneFieldData{SceneField::Rotation, |
|
SceneObjectType::UnsignedShort, rotationObjects, |
|
SceneFieldType::Quaternion, rotationFields, 0}; |
|
SceneFieldData{SceneField::Rotation, 3, |
|
SceneObjectType::UnsignedShort, 0, sizeof(UnsignedShort), |
|
SceneFieldType::Quaternion, 0, sizeof(Quaternion), 0}; |
|
SceneFieldData{sceneFieldCustom(37), |
|
rotationObjects, |
|
rotationFields2D}; |
|
SceneFieldData{sceneFieldCustom(37), |
|
rotationObjectsChar, |
|
SceneFieldType::Quaternion, rotationFields2DChar, 3}; |
|
SceneFieldData{sceneFieldCustom(37), 3, |
|
SceneObjectType::UnsignedShort, 0, sizeof(UnsignedShort), |
|
SceneFieldType::Quaternion, 0, sizeof(Quaternion), 3}; |
|
|
|
/* This is not */ |
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneFieldData{SceneField::Rotation, |
|
SceneObjectType::UnsignedShort, rotationObjects, |
|
SceneFieldType::Quaternion, rotationFields, 3}; |
|
SceneFieldData{SceneField::Rotation, 3, |
|
SceneObjectType::UnsignedShort, 0, sizeof(UnsignedShort), |
|
SceneFieldType::Quaternion, 0, sizeof(Quaternion), 3}; |
|
SceneFieldData{SceneField::Rotation, |
|
rotationObjects, |
|
rotationFields2D}; |
|
SceneFieldData{SceneField::Rotation, |
|
rotationObjectsChar, |
|
SceneFieldType::Quaternion, rotationFields2DChar, 3}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneFieldData: Trade::SceneField::Rotation can't be an array field\n" |
|
"Trade::SceneFieldData: Trade::SceneField::Rotation can't be an array field\n" |
|
"Trade::SceneFieldData: Trade::SceneField::Rotation can't be an array field\n" |
|
"Trade::SceneFieldData: Trade::SceneField::Rotation can't be an array field\n"); |
|
} |
|
|
|
void SceneDataTest::constructFieldArray2DWrongSize() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
char rotationObjectData[4*sizeof(UnsignedInt)]; |
|
char rotationFieldData[4*sizeof(Complex)]; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneFieldData{sceneFieldCustom(37), |
|
Containers::StridedArrayView2D<char>{rotationObjectData, {4, sizeof(UnsignedInt)}}.every(2), |
|
SceneFieldType::Int, |
|
Containers::StridedArrayView2D<char>{rotationFieldData, {4, sizeof(Complex)}}.every(2), 3}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneFieldData: second field view dimension size 8 doesn't match Trade::SceneFieldType::Int and field array size 3\n"); |
|
} |
|
|
|
void SceneDataTest::constructFieldArray2DNonContiguous() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
char offsetObjectData[18*sizeof(UnsignedInt)]; |
|
char offsetFieldData[18*sizeof(Int)]; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneFieldData{sceneFieldCustom(37), |
|
Containers::StridedArrayView2D<char>{offsetObjectData, {3, 2*sizeof(UnsignedInt)}}.every({1, 2}), |
|
SceneFieldType::Int, |
|
Containers::StridedArrayView2D<char>{offsetFieldData, {3, 3*sizeof(Int)}}, 3}; |
|
SceneFieldData{sceneFieldCustom(37), |
|
Containers::StridedArrayView2D<char>{offsetObjectData, {3, sizeof(UnsignedInt)}}, |
|
SceneFieldType::Int, |
|
Containers::StridedArrayView2D<char>{offsetFieldData, {3, 6*sizeof(Int)}}.every({1, 2}), 3}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneFieldData: second object view dimension is not contiguous\n" |
|
"Trade::SceneFieldData: second field view dimension is not contiguous\n"); |
|
} |
|
|
|
void SceneDataTest::construct() { |
|
struct TransformParent { |
|
UnsignedShort object; |
|
Matrix4 transformation; |
|
Int parent; |
|
}; |
|
|
|
Containers::StridedArrayView1D<TransformParent> transformsParentFieldObjectData; |
|
Containers::StridedArrayView1D<UnsignedByte> meshFieldData; |
|
Containers::StridedArrayView1D<Vector2> radiusFieldData; |
|
Containers::StridedArrayView1D<UnsignedShort> materialMeshRadiusObjectData; |
|
Containers::ArrayTuple data{ |
|
{NoInit, 5, transformsParentFieldObjectData}, |
|
{NoInit, 2, meshFieldData}, |
|
{NoInit, 2, radiusFieldData}, |
|
{NoInit, 2, materialMeshRadiusObjectData}, |
|
}; |
|
transformsParentFieldObjectData[0].object = 4; |
|
transformsParentFieldObjectData[0].transformation = Matrix4::translation(Vector3::xAxis(5.0f)); |
|
transformsParentFieldObjectData[0].parent = -1; |
|
|
|
transformsParentFieldObjectData[1].object = 2; |
|
transformsParentFieldObjectData[1].transformation = Matrix4::translation(Vector3::yAxis(5.0f)); |
|
transformsParentFieldObjectData[1].parent = 0; |
|
|
|
transformsParentFieldObjectData[2].object = 3; |
|
transformsParentFieldObjectData[2].transformation = Matrix4::translation(Vector3::zAxis(5.0f)); |
|
transformsParentFieldObjectData[2].parent = 2; |
|
|
|
transformsParentFieldObjectData[3].object = 0; |
|
transformsParentFieldObjectData[3].transformation = Matrix4::translation(Vector3::yScale(5.0f)); |
|
transformsParentFieldObjectData[3].parent = 1; |
|
|
|
transformsParentFieldObjectData[4].object = 1; |
|
transformsParentFieldObjectData[4].transformation = Matrix4::translation(Vector3::zScale(5.0f)); |
|
transformsParentFieldObjectData[4].parent = -1; |
|
|
|
meshFieldData[0] = 5; |
|
radiusFieldData[0] = {37.5f, 1.5f}; |
|
materialMeshRadiusObjectData[0] = 2; |
|
|
|
meshFieldData[1] = 7; |
|
radiusFieldData[1] = {22.5f, 0.5f}; |
|
materialMeshRadiusObjectData[1] = 6; |
|
|
|
int importerState; |
|
SceneFieldData transformations{SceneField::Transformation, |
|
transformsParentFieldObjectData.slice(&TransformParent::object), |
|
transformsParentFieldObjectData.slice(&TransformParent::transformation)}; |
|
/* Offset-only */ |
|
SceneFieldData parents{SceneField::Parent, 5, |
|
SceneObjectType::UnsignedShort, offsetof(TransformParent, object), sizeof(TransformParent), |
|
SceneFieldType::Int, offsetof(TransformParent, parent), sizeof(TransformParent)}; |
|
SceneFieldData meshes{SceneField::Mesh, |
|
materialMeshRadiusObjectData, |
|
meshFieldData}; |
|
/* Custom & array */ |
|
SceneFieldData radiuses{sceneFieldCustom(37), |
|
materialMeshRadiusObjectData, |
|
Containers::arrayCast<2, Float>(radiusFieldData)}; |
|
SceneData scene{SceneObjectType::UnsignedShort, 8, std::move(data), { |
|
transformations, parents, meshes, radiuses |
|
}, &importerState}; |
|
|
|
/* Basics */ |
|
CORRADE_COMPARE(scene.dataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_VERIFY(!scene.fieldData().empty()); |
|
CORRADE_COMPARE(static_cast<const void*>(scene.data()), transformsParentFieldObjectData.data()); |
|
CORRADE_COMPARE(static_cast<void*>(scene.mutableData()), transformsParentFieldObjectData.data()); |
|
CORRADE_COMPARE(scene.objectCount(), 8); |
|
CORRADE_COMPARE(scene.objectType(), SceneObjectType::UnsignedShort); |
|
CORRADE_COMPARE(scene.fieldCount(), 4); |
|
CORRADE_COMPARE(scene.importerState(), &importerState); |
|
|
|
/* is2D() / is3D() exhaustively tested in transformations*DAsArray[TRS]() |
|
and constructZeroFields() */ |
|
|
|
/* Field property access by ID */ |
|
CORRADE_COMPARE(scene.fieldName(0), SceneField::Transformation); |
|
CORRADE_COMPARE(scene.fieldName(1), SceneField::Parent); |
|
CORRADE_COMPARE(scene.fieldName(2), SceneField::Mesh); |
|
CORRADE_COMPARE(scene.fieldName(3), sceneFieldCustom(37)); |
|
CORRADE_COMPARE(scene.fieldType(0), SceneFieldType::Matrix4x4); |
|
CORRADE_COMPARE(scene.fieldType(1), SceneFieldType::Int); |
|
CORRADE_COMPARE(scene.fieldType(2), SceneFieldType::UnsignedByte); |
|
CORRADE_COMPARE(scene.fieldType(3), SceneFieldType::Float); |
|
CORRADE_COMPARE(scene.fieldSize(0), 5); |
|
CORRADE_COMPARE(scene.fieldSize(1), 5); |
|
CORRADE_COMPARE(scene.fieldSize(2), 2); |
|
CORRADE_COMPARE(scene.fieldSize(3), 2); |
|
CORRADE_COMPARE(scene.fieldArraySize(0), 0); |
|
CORRADE_COMPARE(scene.fieldArraySize(1), 0); |
|
CORRADE_COMPARE(scene.fieldArraySize(2), 0); |
|
CORRADE_COMPARE(scene.fieldArraySize(3), 2); |
|
|
|
/* Raw field data access by ID */ |
|
CORRADE_COMPARE(scene.fieldData(2).name(), SceneField::Mesh); |
|
CORRADE_COMPARE(scene.fieldData(2).size(), 2); |
|
CORRADE_COMPARE(scene.fieldData(2).objectType(), SceneObjectType::UnsignedShort); |
|
CORRADE_COMPARE(Containers::arrayCast<const UnsignedShort>(scene.fieldData(2).objectData())[1], 6); |
|
CORRADE_COMPARE(Containers::arrayCast<const UnsignedByte>(scene.fieldData(2).fieldData())[1], 7); |
|
CORRADE_VERIFY(!scene.fieldData(2).isOffsetOnly()); |
|
CORRADE_COMPARE(scene.fieldData(2).fieldType(), SceneFieldType::UnsignedByte); |
|
CORRADE_COMPARE(scene.fieldData(2).fieldArraySize(), 0); |
|
/* Offset-only */ |
|
CORRADE_COMPARE(scene.fieldData(1).name(), SceneField::Parent); |
|
CORRADE_COMPARE(scene.fieldData(1).size(), 5); |
|
CORRADE_COMPARE(scene.fieldData(1).objectType(), SceneObjectType::UnsignedShort); |
|
CORRADE_VERIFY(!scene.fieldData(1).isOffsetOnly()); |
|
CORRADE_COMPARE(scene.fieldData(1).fieldType(), SceneFieldType::Int); |
|
CORRADE_COMPARE(scene.fieldData(1).fieldArraySize(), 0); |
|
CORRADE_COMPARE(Containers::arrayCast<const UnsignedShort>(scene.fieldData(1).objectData())[4], 1); |
|
CORRADE_COMPARE(Containers::arrayCast<const Int>(scene.fieldData(1).fieldData())[4], -1); |
|
/* Array */ |
|
CORRADE_COMPARE(scene.fieldData(3).name(), sceneFieldCustom(37)); |
|
CORRADE_COMPARE(scene.fieldData(3).size(), 2); |
|
CORRADE_COMPARE(scene.fieldData(3).objectType(), SceneObjectType::UnsignedShort); |
|
CORRADE_VERIFY(!scene.fieldData(3).isOffsetOnly()); |
|
CORRADE_COMPARE(scene.fieldData(3).fieldType(), SceneFieldType::Float); |
|
CORRADE_COMPARE(scene.fieldData(3).fieldArraySize(), 2); |
|
CORRADE_COMPARE(Containers::arrayCast<const UnsignedShort>(scene.fieldData(3).objectData())[0], 2); |
|
CORRADE_COMPARE(Containers::arrayCast<const Vector2>(scene.fieldData(3).fieldData())[0], (Vector2{37.5f, 1.5f})); |
|
|
|
/* Typeless object access by ID with a cast later */ |
|
CORRADE_COMPARE(scene.objects(0).size()[0], 5); |
|
CORRADE_COMPARE(scene.objects(1).size()[0], 5); |
|
CORRADE_COMPARE(scene.objects(2).size()[0], 2); |
|
CORRADE_COMPARE(scene.objects(3).size()[0], 2); |
|
CORRADE_COMPARE(scene.mutableObjects(0).size()[0], 5); |
|
CORRADE_COMPARE(scene.mutableObjects(1).size()[0], 5); |
|
CORRADE_COMPARE(scene.mutableObjects(2).size()[0], 2); |
|
CORRADE_COMPARE(scene.mutableObjects(3).size()[0], 2); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(scene.objects(0))[2]), 3); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(scene.objects(1))[4]), 1); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(scene.objects(2))[1]), 6); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(scene.objects(3))[0]), 2); |
|
CORRADE_COMPARE((Containers::arrayCast<1, UnsignedShort>(scene.mutableObjects(0))[2]), 3); |
|
CORRADE_COMPARE((Containers::arrayCast<1, UnsignedShort>(scene.mutableObjects(1))[4]), 1); |
|
CORRADE_COMPARE((Containers::arrayCast<1, UnsignedShort>(scene.mutableObjects(2))[1]), 6); |
|
CORRADE_COMPARE((Containers::arrayCast<1, UnsignedShort>(scene.mutableObjects(3))[0]), 2); |
|
|
|
/* Typeless field access by ID with a cast later */ |
|
CORRADE_COMPARE(scene.field(0).size()[0], 5); |
|
CORRADE_COMPARE(scene.field(1).size()[0], 5); |
|
CORRADE_COMPARE(scene.field(2).size()[0], 2); |
|
CORRADE_COMPARE(scene.field(3).size()[0], 2); |
|
CORRADE_COMPARE(scene.mutableField(0).size()[0], 5); |
|
CORRADE_COMPARE(scene.mutableField(1).size()[0], 5); |
|
CORRADE_COMPARE(scene.mutableField(2).size()[0], 2); |
|
CORRADE_COMPARE(scene.mutableField(3).size()[0], 2); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Matrix4>(scene.field(0))[2]), Matrix4::translation(Vector3::zAxis(5.0f))); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Int>(scene.field(1))[4]), -1); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedByte>(scene.field(2))[1]), 7); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Vector2>(scene.field(3))[0]), (Vector2{37.5f, 1.5f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Matrix4>(scene.mutableField(0))[2]), Matrix4::translation(Vector3::zAxis(5.0f))); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Int>(scene.mutableField(1))[4]), -1); |
|
CORRADE_COMPARE((Containers::arrayCast<1, UnsignedByte>(scene.mutableField(2))[1]), 7); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Vector2>(scene.mutableField(3))[0]), (Vector2{37.5f, 1.5f})); |
|
|
|
/* Typed object access by ID */ |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(0).size(), 5); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(1).size(), 5); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(2).size(), 2); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(3).size(), 2); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(0).size(), 5); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(1).size(), 5); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(2).size(), 2); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(3).size(), 2); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(0)[2], 3); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(1)[4], 1); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(2)[1], 6); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(3)[0], 2); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(0)[2], 3); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(1)[4], 1); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(2)[1], 6); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(3)[0], 2); |
|
|
|
/* Typed field access by ID */ |
|
CORRADE_COMPARE(scene.field<Matrix4>(0).size(), 5); |
|
CORRADE_COMPARE(scene.field<Int>(1).size(), 5); |
|
CORRADE_COMPARE(scene.field<UnsignedByte>(2).size(), 2); |
|
CORRADE_COMPARE(scene.field<Float[]>(3).size()[0], 2); |
|
CORRADE_COMPARE(scene.field<Float[]>(3).size()[1], 2); |
|
CORRADE_COMPARE(scene.mutableField<Matrix4>(0).size(), 5); |
|
CORRADE_COMPARE(scene.mutableField<Int>(1).size(), 5); |
|
CORRADE_COMPARE(scene.mutableField<UnsignedByte>(2).size(), 2); |
|
CORRADE_COMPARE(scene.mutableField<Float[]>(3).size()[0], 2); |
|
CORRADE_COMPARE(scene.mutableField<Float[]>(3).size()[1], 2); |
|
CORRADE_COMPARE(scene.field<Matrix4>(0)[2], Matrix4::translation(Vector3::zAxis(5.0f))); |
|
CORRADE_COMPARE(scene.field<Int>(1)[4], -1); |
|
CORRADE_COMPARE(scene.field<UnsignedByte>(2)[1], 7); |
|
CORRADE_COMPARE(scene.field<Float[]>(3)[0][0], 37.5f); |
|
CORRADE_COMPARE(scene.field<Float[]>(3)[0][1], 1.5f); |
|
CORRADE_COMPARE(scene.mutableField<Matrix4>(0)[2], Matrix4::translation(Vector3::zAxis(5.0f))); |
|
CORRADE_COMPARE(scene.mutableField<Int>(1)[4], -1); |
|
CORRADE_COMPARE(scene.mutableField<UnsignedByte>(2)[1], 7); |
|
CORRADE_COMPARE(scene.mutableField<Float[]>(3)[0][0], 37.5f); |
|
CORRADE_COMPARE(scene.mutableField<Float[]>(3)[0][1], 1.5f); |
|
|
|
/* Field property access by name */ |
|
CORRADE_COMPARE(scene.fieldId(SceneField::Transformation), 0); |
|
CORRADE_COMPARE(scene.fieldId(SceneField::Parent), 1); |
|
CORRADE_COMPARE(scene.fieldId(SceneField::Mesh), 2); |
|
CORRADE_COMPARE(scene.fieldId(sceneFieldCustom(37)), 3); |
|
CORRADE_VERIFY(scene.hasField(SceneField::Transformation)); |
|
CORRADE_VERIFY(scene.hasField(SceneField::Parent)); |
|
CORRADE_VERIFY(scene.hasField(SceneField::Mesh)); |
|
CORRADE_VERIFY(scene.hasField(sceneFieldCustom(37))); |
|
CORRADE_VERIFY(!scene.hasField(SceneField::Skin)); |
|
CORRADE_COMPARE(scene.fieldType(SceneField::Transformation), SceneFieldType::Matrix4x4); |
|
CORRADE_COMPARE(scene.fieldType(SceneField::Parent), SceneFieldType::Int); |
|
CORRADE_COMPARE(scene.fieldType(SceneField::Mesh), SceneFieldType::UnsignedByte); |
|
CORRADE_COMPARE(scene.fieldType(sceneFieldCustom(37)), SceneFieldType::Float); |
|
CORRADE_COMPARE(scene.fieldSize(SceneField::Transformation), 5); |
|
CORRADE_COMPARE(scene.fieldSize(SceneField::Parent), 5); |
|
CORRADE_COMPARE(scene.fieldSize(SceneField::Mesh), 2); |
|
CORRADE_COMPARE(scene.fieldSize(sceneFieldCustom(37)), 2); |
|
CORRADE_COMPARE(scene.fieldArraySize(SceneField::Transformation), 0); |
|
CORRADE_COMPARE(scene.fieldArraySize(SceneField::Parent), 0); |
|
CORRADE_COMPARE(scene.fieldArraySize(SceneField::Mesh), 0); |
|
CORRADE_COMPARE(scene.fieldArraySize(sceneFieldCustom(37)), 2); |
|
|
|
/* Typeless object access by name with a cast later */ |
|
CORRADE_COMPARE(scene.objects(SceneField::Transformation).size()[0], 5); |
|
CORRADE_COMPARE(scene.objects(SceneField::Parent).size()[0], 5); |
|
CORRADE_COMPARE(scene.objects(2).size()[0], 2); |
|
CORRADE_COMPARE(scene.objects(3).size()[0], 2); |
|
CORRADE_COMPARE(scene.mutableObjects(SceneField::Transformation).size()[0], 5); |
|
CORRADE_COMPARE(scene.mutableObjects(SceneField::Parent).size()[0], 5); |
|
CORRADE_COMPARE(scene.mutableObjects(2).size()[0], 2); |
|
CORRADE_COMPARE(scene.mutableObjects(3).size()[0], 2); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(scene.objects(SceneField::Transformation))[2]), 3); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(scene.objects(SceneField::Parent))[4]), 1); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(scene.objects(2))[1]), 6); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedShort>(scene.objects(3))[0]), 2); |
|
CORRADE_COMPARE((Containers::arrayCast<1, UnsignedShort>(scene.mutableObjects(SceneField::Transformation))[2]), 3); |
|
CORRADE_COMPARE((Containers::arrayCast<1, UnsignedShort>(scene.mutableObjects(SceneField::Parent))[4]), 1); |
|
CORRADE_COMPARE((Containers::arrayCast<1, UnsignedShort>(scene.mutableObjects(2))[1]), 6); |
|
CORRADE_COMPARE((Containers::arrayCast<1, UnsignedShort>(scene.mutableObjects(3))[0]), 2); |
|
|
|
/* Typeless field access by name with a cast later */ |
|
CORRADE_COMPARE(scene.field(SceneField::Transformation).size()[0], 5); |
|
CORRADE_COMPARE(scene.field(SceneField::Parent).size()[0], 5); |
|
CORRADE_COMPARE(scene.field(SceneField::Mesh).size()[0], 2); |
|
CORRADE_COMPARE(scene.field(sceneFieldCustom(37)).size()[0], 2); |
|
CORRADE_COMPARE(scene.mutableField(SceneField::Transformation).size()[0], 5); |
|
CORRADE_COMPARE(scene.mutableField(SceneField::Parent).size()[0], 5); |
|
CORRADE_COMPARE(scene.mutableField(SceneField::Mesh).size()[0], 2); |
|
CORRADE_COMPARE(scene.mutableField(sceneFieldCustom(37)).size()[0], 2); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Matrix4>(scene.field(SceneField::Transformation))[2]), Matrix4::translation(Vector3::zAxis(5.0f))); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Int>(scene.field(SceneField::Parent))[4]), -1); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const UnsignedByte>(scene.field(SceneField::Mesh))[1]), 7); |
|
CORRADE_COMPARE((Containers::arrayCast<1, const Vector2>(scene.field(sceneFieldCustom(37)))[0]), (Vector2{37.5f, 1.5f})); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Matrix4>(scene.mutableField(SceneField::Transformation))[2]), Matrix4::translation(Vector3::zAxis(5.0f))); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Int>(scene.mutableField(SceneField::Parent))[4]), -1); |
|
CORRADE_COMPARE((Containers::arrayCast<1, UnsignedByte>(scene.mutableField(SceneField::Mesh))[1]), 7); |
|
CORRADE_COMPARE((Containers::arrayCast<1, Vector2>(scene.mutableField(sceneFieldCustom(37)))[0]), (Vector2{37.5f, 1.5f})); |
|
|
|
/* Typed object access by name */ |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(SceneField::Transformation).size(), 5); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(SceneField::Parent).size(), 5); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(SceneField::Mesh).size(), 2); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(sceneFieldCustom(37)).size(), 2); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(SceneField::Transformation).size(), 5); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(SceneField::Parent).size(), 5); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(SceneField::Mesh).size(), 2); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(sceneFieldCustom(37)).size(), 2); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(SceneField::Transformation)[2], 3); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(SceneField::Parent)[4], 1); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(SceneField::Mesh)[1], 6); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(sceneFieldCustom(37))[0], 2); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(SceneField::Transformation)[2], 3); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(SceneField::Parent)[4], 1); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(SceneField::Mesh)[1], 6); |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(sceneFieldCustom(37))[0], 2); |
|
|
|
/* Typed field access by name */ |
|
CORRADE_COMPARE(scene.field<Matrix4>(SceneField::Transformation).size(), 5); |
|
CORRADE_COMPARE(scene.field<Int>(SceneField::Parent).size(), 5); |
|
CORRADE_COMPARE(scene.field<UnsignedByte>(SceneField::Mesh).size(), 2); |
|
CORRADE_COMPARE(scene.field<Float[]>(sceneFieldCustom(37)).size()[0], 2); |
|
CORRADE_COMPARE(scene.field<Float[]>(sceneFieldCustom(37)).size()[1], 2); |
|
CORRADE_COMPARE(scene.mutableField<Matrix4>(SceneField::Transformation).size(), 5); |
|
CORRADE_COMPARE(scene.mutableField<Int>(SceneField::Parent).size(), 5); |
|
CORRADE_COMPARE(scene.mutableField<UnsignedByte>(SceneField::Mesh).size(), 2); |
|
CORRADE_COMPARE(scene.mutableField<Float[]>(sceneFieldCustom(37)).size()[0], 2); |
|
CORRADE_COMPARE(scene.mutableField<Float[]>(sceneFieldCustom(37)).size()[1], 2); |
|
CORRADE_COMPARE(scene.field<Matrix4>(SceneField::Transformation)[2], Matrix4::translation(Vector3::zAxis(5.0f))); |
|
CORRADE_COMPARE(scene.field<Int>(SceneField::Parent)[4], -1); |
|
CORRADE_COMPARE(scene.field<UnsignedByte>(SceneField::Mesh)[1], 7); |
|
CORRADE_COMPARE(scene.field<Float[]>(sceneFieldCustom(37))[0][0], 37.5f); |
|
CORRADE_COMPARE(scene.field<Float[]>(sceneFieldCustom(37))[0][1], 1.5f); |
|
CORRADE_COMPARE(scene.mutableField<Matrix4>(SceneField::Transformation)[2], Matrix4::translation(Vector3::zAxis(5.0f))); |
|
CORRADE_COMPARE(scene.mutableField<Int>(SceneField::Parent)[4], -1); |
|
CORRADE_COMPARE(scene.mutableField<UnsignedByte>(SceneField::Mesh)[1], 7); |
|
CORRADE_COMPARE(scene.mutableField<Float[]>(sceneFieldCustom(37))[0][0], 37.5f); |
|
CORRADE_COMPARE(scene.mutableField<Float[]>(sceneFieldCustom(37))[0][1], 1.5f); |
|
} |
|
|
|
void SceneDataTest::constructZeroFields() { |
|
int importerState; |
|
SceneData scene{SceneObjectType::UnsignedShort, 37563, nullptr, {}, &importerState}; |
|
CORRADE_COMPARE(scene.dataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_VERIFY(scene.fieldData().empty()); |
|
CORRADE_COMPARE(static_cast<const void*>(scene.data()), nullptr); |
|
CORRADE_COMPARE(static_cast<void*>(scene.mutableData()), nullptr); |
|
CORRADE_COMPARE(scene.importerState(), &importerState); |
|
CORRADE_COMPARE(scene.objectCount(), 37563); |
|
CORRADE_COMPARE(scene.objectType(), SceneObjectType::UnsignedShort); |
|
CORRADE_COMPARE(scene.fieldCount(), 0); |
|
CORRADE_VERIFY(!scene.is2D()); |
|
CORRADE_VERIFY(!scene.is3D()); |
|
} |
|
|
|
void SceneDataTest::constructZeroObjects() { |
|
int importerState; |
|
SceneFieldData meshes{SceneField::Mesh, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::UnsignedShort, nullptr}; |
|
SceneFieldData materials{SceneField::MeshMaterial, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}; |
|
SceneData scene{SceneObjectType::UnsignedInt, 0, nullptr, {meshes, materials}, &importerState}; |
|
CORRADE_COMPARE(scene.dataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_VERIFY(!scene.fieldData().empty()); |
|
CORRADE_COMPARE(static_cast<const void*>(scene.data()), nullptr); |
|
CORRADE_COMPARE(static_cast<void*>(scene.mutableData()), nullptr); |
|
CORRADE_COMPARE(scene.importerState(), &importerState); |
|
CORRADE_COMPARE(scene.objectCount(), 0); |
|
CORRADE_COMPARE(scene.objectType(), SceneObjectType::UnsignedInt); |
|
CORRADE_COMPARE(scene.fieldCount(), 2); |
|
|
|
/* Field property access by name */ |
|
CORRADE_COMPARE(scene.fieldType(SceneField::Mesh), SceneFieldType::UnsignedShort); |
|
CORRADE_COMPARE(scene.fieldType(SceneField::MeshMaterial), SceneFieldType::Int); |
|
CORRADE_COMPARE(scene.fieldSize(SceneField::Mesh), 0); |
|
CORRADE_COMPARE(scene.fieldSize(SceneField::MeshMaterial), 0); |
|
CORRADE_COMPARE(scene.objects(SceneField::Mesh).data(), nullptr); |
|
CORRADE_COMPARE(scene.objects(SceneField::MeshMaterial).data(), nullptr); |
|
} |
|
|
|
void SceneDataTest::constructNotOwned() { |
|
auto&& instanceData = NotOwnedData[testCaseInstanceId()]; |
|
setTestCaseDescription(instanceData.name); |
|
|
|
struct Data { |
|
UnsignedShort object; |
|
UnsignedByte mesh; |
|
} data[]{ |
|
{0, 2}, |
|
{1, 1}, |
|
{2, 0} |
|
}; |
|
|
|
int importerState; |
|
SceneFieldData mesh{SceneField::Mesh, |
|
Containers::stridedArrayView(data).slice(&Data::object), |
|
Containers::stridedArrayView(data).slice(&Data::mesh)}; |
|
SceneData scene{SceneObjectType::UnsignedShort, 7, instanceData.dataFlags, Containers::arrayView(data), {mesh}, &importerState}; |
|
|
|
CORRADE_COMPARE(scene.dataFlags(), instanceData.dataFlags); |
|
CORRADE_COMPARE(static_cast<const void*>(scene.data()), +data); |
|
if(instanceData.dataFlags & DataFlag::Mutable) |
|
CORRADE_COMPARE(static_cast<void*>(scene.mutableData()), static_cast<void*>(data)); |
|
CORRADE_COMPARE(scene.objectCount(), 7); |
|
CORRADE_COMPARE(scene.objectType(), SceneObjectType::UnsignedShort); |
|
CORRADE_COMPARE(scene.fieldCount(), 1); |
|
CORRADE_COMPARE(scene.importerState(), &importerState); |
|
|
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(0).size(), 3); |
|
CORRADE_COMPARE(scene.objects<UnsignedShort>(0)[2], 2); |
|
if(instanceData.dataFlags & DataFlag::Mutable) |
|
CORRADE_COMPARE(scene.mutableObjects<UnsignedShort>(0)[2], 2); |
|
|
|
CORRADE_COMPARE(scene.field<UnsignedByte>(0).size(), 3); |
|
CORRADE_COMPARE(scene.field<UnsignedByte>(0)[2], 0); |
|
if(instanceData.dataFlags & DataFlag::Mutable) |
|
CORRADE_COMPARE(scene.mutableField<UnsignedByte>(0)[2], 0); |
|
} |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
void SceneDataTest::constructDeprecated() { |
|
auto&& data = ChildrenDeprecatedData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
int a; |
|
CORRADE_IGNORE_DEPRECATED_PUSH |
|
SceneData scene{ |
|
data.is2D ? std::vector<UnsignedInt>{5, 17, 36, 22} : std::vector<UnsignedInt>{}, |
|
data.is3D ? std::vector<UnsignedInt>{5, 17, 36, 22} : std::vector<UnsignedInt>{}, |
|
&a}; |
|
CORRADE_IGNORE_DEPRECATED_POP |
|
CORRADE_COMPARE(scene.objectType(), SceneObjectType::UnsignedInt); |
|
if(data.is2D || data.is3D) |
|
CORRADE_COMPARE(scene.objectCount(), 37); |
|
else |
|
CORRADE_COMPARE(scene.objectCount(), 0); |
|
CORRADE_COMPARE(scene.dataFlags(), DataFlag::Mutable|DataFlag::Owned); |
|
CORRADE_COMPARE(scene.importerState(), &a); |
|
CORRADE_COMPARE(scene.fieldCount(), 1); |
|
CORRADE_COMPARE(scene.fieldName(0), SceneField::Parent); |
|
CORRADE_COMPARE(scene.fieldType(0), SceneFieldType::Int); |
|
if(data.is2D || data.is3D) { |
|
CORRADE_COMPARE_AS(scene.objects<UnsignedInt>(0), |
|
Containers::arrayView<UnsignedInt>({5, 17, 36, 22}), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.field<Int>(0), |
|
Containers::arrayView<Int>({-1, -1, -1, -1}), |
|
TestSuite::Compare::Container); |
|
} else CORRADE_COMPARE(scene.fieldSize(SceneField::Parent), 0); |
|
/* There's no transformation field that would disambiguate this, the state |
|
is set directly */ |
|
CORRADE_COMPARE(scene.is2D(), data.is2D); |
|
CORRADE_COMPARE(scene.is3D(), data.is3D); |
|
|
|
/* The deleters have to be trivial, otherwise this instance wouldn't be |
|
usable from an AbstractImporter */ |
|
CORRADE_VERIFY(!scene.releaseFieldData().deleter()); |
|
CORRADE_VERIFY(!scene.releaseData().deleter()); |
|
} |
|
|
|
void SceneDataTest::constructDeprecatedBoth2DAnd3D() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
CORRADE_IGNORE_DEPRECATED_PUSH |
|
SceneData scene{{5, 17}, {36, 22}}; |
|
CORRADE_IGNORE_DEPRECATED_POP |
|
CORRADE_COMPARE(out.str(), "Trade::SceneData: it's no longer possible to have a scene with both 2D and 3D objects\n"); |
|
} |
|
#endif |
|
|
|
void SceneDataTest::constructDuplicateField() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
/* Builtin fields are checked using a bitfield, as they have monotonic |
|
numbering */ |
|
SceneFieldData meshes{SceneField::Mesh, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::UnsignedShort, nullptr}; |
|
SceneFieldData materials{SceneField::MeshMaterial, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}; |
|
SceneFieldData meshesAgain{SceneField::Mesh, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::UnsignedInt, nullptr}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneData scene{SceneObjectType::UnsignedInt, 0, nullptr, {meshes, materials, meshesAgain}}; |
|
CORRADE_COMPARE(out.str(), "Trade::SceneData: duplicate field Trade::SceneField::Mesh\n"); |
|
} |
|
|
|
void SceneDataTest::constructDuplicateCustomField() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
/* These are checked in an O(n^2) way, separately from builtin fields. |
|
Can't use a bitfield since the field index can be anything. */ |
|
SceneFieldData customA{sceneFieldCustom(37), SceneObjectType::UnsignedInt, nullptr, SceneFieldType::UnsignedShort, nullptr}; |
|
SceneFieldData customB{sceneFieldCustom(1038576154), SceneObjectType::UnsignedInt, nullptr, SceneFieldType::UnsignedInt, nullptr}; |
|
SceneFieldData customAAgain{sceneFieldCustom(37), SceneObjectType::UnsignedInt, nullptr, SceneFieldType::UnsignedInt, nullptr}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneData scene{SceneObjectType::UnsignedInt, 0, nullptr, {customA, customB, customAAgain}}; |
|
CORRADE_COMPARE(out.str(), "Trade::SceneData: duplicate field Trade::SceneField::Custom(37)\n"); |
|
} |
|
|
|
void SceneDataTest::constructInconsistentObjectType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
SceneFieldData meshes{SceneField::Mesh, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::UnsignedShort, nullptr}; |
|
SceneFieldData materials{SceneField::MeshMaterial, SceneObjectType::UnsignedShort, nullptr, SceneFieldType::Int, nullptr}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneData scene{SceneObjectType::UnsignedInt, 0, nullptr, {meshes, materials}}; |
|
CORRADE_COMPARE(out.str(), "Trade::SceneData: inconsistent object type, got Trade::SceneObjectType::UnsignedShort for field 1 but expected Trade::SceneObjectType::UnsignedInt\n"); |
|
} |
|
|
|
void SceneDataTest::constructObjectDataNotContained() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::Array<char> data{reinterpret_cast<char*>(0xbadda9), 10, [](char*, std::size_t){}}; |
|
Containers::ArrayView<UnsignedShort> dataIn{reinterpret_cast<UnsignedShort*>(0xbadda9), 5}; |
|
Containers::ArrayView<UnsignedShort> dataSlightlyOut{reinterpret_cast<UnsignedShort*>(0xbaddaa), 5}; |
|
Containers::ArrayView<UnsignedShort> dataOut{reinterpret_cast<UnsignedShort*>(0xdead), 5}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
/* First a "slightly off" view that exceeds the original by one byte */ |
|
SceneData{SceneObjectType::UnsignedShort, 5, {}, data, { |
|
SceneFieldData{SceneField::Mesh, dataSlightlyOut, dataIn} |
|
}}; |
|
/* Second a view that's in a completely different location */ |
|
SceneData{SceneObjectType::UnsignedShort, 5, {}, data, { |
|
SceneFieldData{SceneField::Light, dataIn, dataIn}, |
|
SceneFieldData{SceneField::Mesh, dataOut, dataIn} |
|
}}; |
|
/* Verify the owning constructor does the checks as well */ |
|
SceneData{SceneObjectType::UnsignedShort, 5, std::move(data), { |
|
SceneFieldData{SceneField::Light, dataIn, dataIn}, |
|
SceneFieldData{SceneField::Mesh, dataOut, dataIn} |
|
}}; |
|
/* And if we have no data at all, it doesn't try to dereference them but |
|
still checks properly */ |
|
SceneData{SceneObjectType::UnsignedShort, 5, nullptr, { |
|
SceneFieldData{SceneField::Mesh, dataOut, dataIn} |
|
}}; |
|
/* Finally, offset-only fields with a different message */ |
|
SceneData{SceneObjectType::UnsignedByte, 6, Containers::Array<char>{24}, { |
|
SceneFieldData{SceneField::Mesh, 6, SceneObjectType::UnsignedByte, 4, 4, SceneFieldType::UnsignedByte, 0, 4} |
|
}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData: object data [0xbaddaa:0xbaddb4] of field 0 are not contained in passed data array [0xbadda9:0xbaddb3]\n" |
|
"Trade::SceneData: object data [0xdead:0xdeb7] of field 1 are not contained in passed data array [0xbadda9:0xbaddb3]\n" |
|
"Trade::SceneData: object data [0xdead:0xdeb7] of field 1 are not contained in passed data array [0xbadda9:0xbaddb3]\n" |
|
"Trade::SceneData: object data [0xdead:0xdeb7] of field 0 are not contained in passed data array [0x0:0x0]\n" |
|
|
|
"Trade::SceneData: offset-only object data of field 0 span 25 bytes but passed data array has only 24\n"); |
|
} |
|
|
|
void SceneDataTest::constructFieldDataNotContained() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
/* Mostly the same as constructObjectDataNotContained() with object and |
|
field views swapped, and added checks for array fields */ |
|
|
|
Containers::Array<char> data{reinterpret_cast<char*>(0xbadda9), 10, [](char*, std::size_t){}}; |
|
Containers::ArrayView<UnsignedShort> dataIn{reinterpret_cast<UnsignedShort*>(0xbadda9), 5}; |
|
Containers::ArrayView<UnsignedShort> dataSlightlyOut{reinterpret_cast<UnsignedShort*>(0xbaddaa), 5}; |
|
Containers::ArrayView<UnsignedShort> dataOut{reinterpret_cast<UnsignedShort*>(0xdead), 5}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
/* First a "slightly off" view that exceeds the original by one byte */ |
|
SceneData{SceneObjectType::UnsignedShort, 5, {}, data, { |
|
SceneFieldData{SceneField::Mesh, dataIn, dataSlightlyOut} |
|
}}; |
|
/* Second a view that's in a completely different location */ |
|
SceneData{SceneObjectType::UnsignedShort, 5, {}, data, { |
|
SceneFieldData{SceneField::Light, dataIn, dataIn}, |
|
SceneFieldData{SceneField::Mesh, dataIn, dataOut} |
|
}}; |
|
/* Verify array size is taken into account as well. If not, the data would |
|
span only 7 bytes out of 10 (instead of 12), which is fine. */ |
|
SceneData{SceneObjectType::UnsignedShort, 5, {}, data, { |
|
SceneFieldData{sceneFieldCustom(37), dataIn.prefix(2), Containers::StridedArrayView2D<UnsignedByte>{Containers::ArrayView<UnsignedByte>{reinterpret_cast<UnsignedByte*>(0xbadda9), 12}, {2, 6}}} |
|
}}; |
|
/* Verify the owning constructor does the checks as well */ |
|
SceneData{SceneObjectType::UnsignedShort, 5, std::move(data), { |
|
SceneFieldData{SceneField::Light, dataIn, dataIn}, |
|
SceneFieldData{SceneField::Mesh, dataIn, dataOut} |
|
}}; |
|
/* Not checking for nullptr data, since that got checked for object view |
|
already and there's no way to trigger it for fields */ |
|
/* Finally, offset-only fields with a different message */ |
|
SceneData{SceneObjectType::UnsignedShort, 6, Containers::Array<char>{24}, { |
|
SceneFieldData{SceneField::Mesh, 6, SceneObjectType::UnsignedShort, 0, 4, SceneFieldType::UnsignedByte, 4, 4} |
|
}}; |
|
/* This again spans 21 bytes if array size isn't taken into account, and 25 |
|
if it is */ |
|
SceneData{SceneObjectType::UnsignedShort, 5, Containers::Array<char>{24}, { |
|
SceneFieldData{sceneFieldCustom(37), 5, SceneObjectType::UnsignedShort, 0, 5, SceneFieldType::UnsignedByte, 0, 5, 5} |
|
}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData: field data [0xbaddaa:0xbaddb4] of field 0 are not contained in passed data array [0xbadda9:0xbaddb3]\n" |
|
"Trade::SceneData: field data [0xdead:0xdeb7] of field 1 are not contained in passed data array [0xbadda9:0xbaddb3]\n" |
|
"Trade::SceneData: field data [0xbadda9:0xbaddb5] of field 0 are not contained in passed data array [0xbadda9:0xbaddb3]\n" |
|
"Trade::SceneData: field data [0xdead:0xdeb7] of field 1 are not contained in passed data array [0xbadda9:0xbaddb3]\n" |
|
|
|
"Trade::SceneData: offset-only field data of field 0 span 25 bytes but passed data array has only 24\n" |
|
"Trade::SceneData: offset-only field data of field 0 span 25 bytes but passed data array has only 24\n"); |
|
} |
|
|
|
void SceneDataTest::constructObjectTypeTooSmall() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
/* This is fine */ |
|
SceneData{SceneObjectType::UnsignedByte, 0xff, nullptr, {}}; |
|
SceneData{SceneObjectType::UnsignedShort, 0xffff, nullptr, {}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0xffffffffu, nullptr, {}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneData{SceneObjectType::UnsignedByte, 0x100, nullptr, {}}; |
|
SceneData{SceneObjectType::UnsignedShort, 0x10000, nullptr, {}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0x100000000ull, nullptr, {}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData: Trade::SceneObjectType::UnsignedByte is too small for 256 objects\n" |
|
"Trade::SceneData: Trade::SceneObjectType::UnsignedShort is too small for 65536 objects\n" |
|
"Trade::SceneData: Trade::SceneObjectType::UnsignedInt is too small for 4294967296 objects\n"); |
|
} |
|
|
|
void SceneDataTest::constructNotOwnedFlagOwned() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const char data[32]{}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneData{SceneObjectType::UnsignedByte, 5, DataFlag::Owned, Containers::arrayView(data), {}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData: can't construct with non-owned data but Trade::DataFlag::Owned\n"); |
|
} |
|
|
|
void SceneDataTest::constructMismatchedTRSViews() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::ArrayView<const char> data{reinterpret_cast<char*>(0xcafe0000), |
|
/* Three entries, each having a 2D TRS and 3 object IDs */ |
|
3*(24 + 12)}; |
|
Containers::ArrayView<const UnsignedInt> translationObjectData{ |
|
reinterpret_cast<const UnsignedInt*>(data.data()), 3}; |
|
Containers::ArrayView<const Vector2> translationFieldData{ |
|
reinterpret_cast<const Vector2*>(data.data() + 0x0c), 3}; |
|
Containers::ArrayView<const UnsignedInt> rotationObjectData{ |
|
reinterpret_cast<const UnsignedInt*>(data.data() + 0x24), 3}; |
|
Containers::ArrayView<const Complex> rotationFieldData{ |
|
reinterpret_cast<const Complex*>(data.data() + 0x30), 3}; |
|
Containers::ArrayView<const UnsignedInt> scalingObjectData{ |
|
reinterpret_cast<const UnsignedInt*>(data.data() + 0x48), 3}; |
|
Containers::ArrayView<const Vector2> scalingFieldData{ |
|
reinterpret_cast<const Vector2*>(data.data() + 0x54), 3}; |
|
|
|
SceneFieldData translations{SceneField::Translation, translationObjectData, translationFieldData}; |
|
SceneFieldData rotationsDifferent{SceneField::Rotation, rotationObjectData, rotationFieldData}; |
|
SceneFieldData scalingsDifferent{SceneField::Scaling, scalingObjectData, scalingFieldData}; |
|
SceneFieldData rotationsSameButLess{SceneField::Rotation, translationObjectData.except(1), rotationFieldData.except(1)}; |
|
SceneFieldData scalingsSameButLess{SceneField::Scaling, translationObjectData.except(2), scalingFieldData.except(2)}; |
|
|
|
/* Test that all pairs get checked */ |
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneData{SceneObjectType::UnsignedInt, 3, {}, data, {translations, rotationsDifferent}}; |
|
SceneData{SceneObjectType::UnsignedInt, 3, {}, data, {translations, scalingsDifferent}}; |
|
SceneData{SceneObjectType::UnsignedInt, 3, {}, data, {rotationsDifferent, scalingsDifferent}}; |
|
SceneData{SceneObjectType::UnsignedInt, 3, {}, data, {translations, rotationsSameButLess}}; |
|
SceneData{SceneObjectType::UnsignedInt, 3, {}, data, {translations, scalingsSameButLess}}; |
|
SceneData{SceneObjectType::UnsignedInt, 3, {}, data, {rotationsSameButLess, scalingsSameButLess}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData: Trade::SceneField::Rotation object data [0xcafe0024:0xcafe0030] is different from Trade::SceneField::Translation object data [0xcafe0000:0xcafe000c]\n" |
|
"Trade::SceneData: Trade::SceneField::Scaling object data [0xcafe0048:0xcafe0054] is different from Trade::SceneField::Translation object data [0xcafe0000:0xcafe000c]\n" |
|
"Trade::SceneData: Trade::SceneField::Scaling object data [0xcafe0048:0xcafe0054] is different from Trade::SceneField::Rotation object data [0xcafe0024:0xcafe0030]\n" |
|
"Trade::SceneData: Trade::SceneField::Rotation object data [0xcafe0000:0xcafe0008] is different from Trade::SceneField::Translation object data [0xcafe0000:0xcafe000c]\n" |
|
"Trade::SceneData: Trade::SceneField::Scaling object data [0xcafe0000:0xcafe0004] is different from Trade::SceneField::Translation object data [0xcafe0000:0xcafe000c]\n" |
|
"Trade::SceneData: Trade::SceneField::Scaling object data [0xcafe0000:0xcafe0004] is different from Trade::SceneField::Rotation object data [0xcafe0000:0xcafe0008]\n"); |
|
} |
|
|
|
template<class> struct NameTraits; |
|
#define _c(format) template<> struct NameTraits<format> { \ |
|
static const char* name() { return #format; } \ |
|
}; |
|
_c(UnsignedByte) |
|
_c(Byte) |
|
_c(UnsignedShort) |
|
_c(Short) |
|
_c(UnsignedInt) |
|
_c(Int) |
|
_c(UnsignedLong) |
|
_c(Long) |
|
_c(Float) |
|
_c(Double) |
|
_c(Vector2) |
|
_c(Vector2d) |
|
_c(Vector3) |
|
_c(Vector3d) |
|
_c(Matrix3) |
|
_c(Matrix3d) |
|
_c(Matrix4) |
|
_c(Matrix4d) |
|
_c(Complex) |
|
_c(Complexd) |
|
_c(Quaternion) |
|
_c(Quaterniond) |
|
_c(DualComplex) |
|
_c(DualComplexd) |
|
_c(DualQuaternion) |
|
_c(DualQuaterniond) |
|
template<class T> struct NameTraits<const T*> { |
|
static const char* name() { return "Pointer"; } |
|
}; |
|
template<class T> struct NameTraits<T*> { |
|
static const char* name() { return "MutablePointer"; } |
|
}; |
|
#undef _c |
|
|
|
template<class T> void SceneDataTest::constructMismatchedTRSDimensionality() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
SceneFieldData transformationMatrices2D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Matrix3<T>>::type(), nullptr}; |
|
SceneFieldData transformations2D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::DualComplex<T>>::type(), nullptr}; |
|
SceneFieldData transformationMatrices3D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Matrix4<T>>::type(), nullptr}; |
|
SceneFieldData transformations3D{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::DualQuaternion<T>>::type(), nullptr}; |
|
SceneFieldData translations2D{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Vector2<T>>::type(), nullptr}; |
|
SceneFieldData translations3D{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Vector3<T>>::type(), nullptr}; |
|
SceneFieldData rotations2D{SceneField::Rotation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Complex<T>>::type(), nullptr}; |
|
SceneFieldData rotations3D{SceneField::Rotation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Quaternion<T>>::type(), nullptr}; |
|
SceneFieldData scalings2D{SceneField::Scaling, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Vector2<T>>::type(), nullptr}; |
|
SceneFieldData scalings3D{SceneField::Scaling, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Vector3<T>>::type(), nullptr}; |
|
|
|
/* Test that all pairs get checked */ |
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices2D, translations3D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices2D, rotations3D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices2D, scalings3D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations2D, translations3D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations2D, rotations3D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations2D, scalings3D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {translations2D, rotations3D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {translations2D, scalings3D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {rotations2D, scalings3D}}; |
|
|
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices3D, translations2D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices3D, rotations2D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformationMatrices3D, scalings2D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations3D, translations2D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations3D, rotations2D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {transformations3D, scalings2D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {translations3D, rotations2D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {translations3D, scalings2D}}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, {rotations3D, scalings2D}}; |
|
CORRADE_COMPARE(out.str(), Utility::formatString( |
|
"Trade::SceneData: expected a 2D translation field but got Trade::SceneFieldType::{0}\n" |
|
"Trade::SceneData: expected a 2D rotation field but got Trade::SceneFieldType::{1}\n" |
|
"Trade::SceneData: expected a 2D scaling field but got Trade::SceneFieldType::{0}\n" |
|
"Trade::SceneData: expected a 2D translation field but got Trade::SceneFieldType::{0}\n" |
|
"Trade::SceneData: expected a 2D rotation field but got Trade::SceneFieldType::{1}\n" |
|
"Trade::SceneData: expected a 2D scaling field but got Trade::SceneFieldType::{0}\n" |
|
"Trade::SceneData: expected a 2D rotation field but got Trade::SceneFieldType::{1}\n" |
|
"Trade::SceneData: expected a 2D scaling field but got Trade::SceneFieldType::{0}\n" |
|
"Trade::SceneData: expected a 2D scaling field but got Trade::SceneFieldType::{0}\n" |
|
|
|
"Trade::SceneData: expected a 3D translation field but got Trade::SceneFieldType::{2}\n" |
|
"Trade::SceneData: expected a 3D rotation field but got Trade::SceneFieldType::{3}\n" |
|
"Trade::SceneData: expected a 3D scaling field but got Trade::SceneFieldType::{2}\n" |
|
"Trade::SceneData: expected a 3D translation field but got Trade::SceneFieldType::{2}\n" |
|
"Trade::SceneData: expected a 3D rotation field but got Trade::SceneFieldType::{3}\n" |
|
"Trade::SceneData: expected a 3D scaling field but got Trade::SceneFieldType::{2}\n" |
|
"Trade::SceneData: expected a 3D rotation field but got Trade::SceneFieldType::{3}\n" |
|
"Trade::SceneData: expected a 3D scaling field but got Trade::SceneFieldType::{2}\n" |
|
"Trade::SceneData: expected a 3D scaling field but got Trade::SceneFieldType::{2}\n", |
|
NameTraits<Math::Vector3<T>>::name(), |
|
NameTraits<Math::Quaternion<T>>::name(), |
|
NameTraits<Math::Vector2<T>>::name(), |
|
NameTraits<Math::Complex<T>>::name())); |
|
} |
|
|
|
void SceneDataTest::constructMismatchedMeshMaterialView() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
Containers::ArrayView<const char> data{reinterpret_cast<char*>(0xcafe0000), |
|
/* Three entries, each having mesh/material ID and 2 object IDs */ |
|
3*(8 + 8)}; |
|
Containers::ArrayView<const UnsignedInt> meshObjectData{ |
|
reinterpret_cast<const UnsignedInt*>(data.data()), 3}; |
|
Containers::ArrayView<const UnsignedInt> meshFieldData{ |
|
reinterpret_cast<const UnsignedInt*>(data.data() + 0x0c), 3}; |
|
Containers::ArrayView<const UnsignedInt> meshMaterialObjectData{ |
|
reinterpret_cast<const UnsignedInt*>(data.data() + 0x18), 3}; |
|
Containers::ArrayView<const Int> meshMaterialFieldData{ |
|
reinterpret_cast<const Int*>(data.data() + 0x24), 3}; |
|
|
|
SceneFieldData meshes{SceneField::Mesh, meshObjectData, meshFieldData}; |
|
SceneFieldData meshMaterialsDifferent{SceneField::MeshMaterial, meshMaterialObjectData, meshMaterialFieldData}; |
|
SceneFieldData meshMaterialsSameButLess{SceneField::MeshMaterial, meshObjectData.except(1), meshMaterialFieldData.except(1)}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneData{SceneObjectType::UnsignedInt, 3, {}, data, {meshes, meshMaterialsDifferent}}; |
|
SceneData{SceneObjectType::UnsignedInt, 3, {}, data, {meshes, meshMaterialsSameButLess}}; |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData: Trade::SceneField::MeshMaterial object data [0xcafe0018:0xcafe0024] is different from Trade::SceneField::Mesh object data [0xcafe0000:0xcafe000c]\n" |
|
"Trade::SceneData: Trade::SceneField::MeshMaterial object data [0xcafe0000:0xcafe0008] is different from Trade::SceneField::Mesh object data [0xcafe0000:0xcafe000c]\n"); |
|
} |
|
|
|
void SceneDataTest::constructAmbiguousSkinDimensions() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
SceneData{SceneObjectType::UnsignedInt, 0, nullptr, { |
|
SceneFieldData{SceneField::Skin, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::UnsignedInt, nullptr} |
|
}}; |
|
CORRADE_COMPARE(out.str(), "Trade::SceneData: a skin field requires some transformation field to be present in order to disambiguate between 2D and 3D\n"); |
|
} |
|
|
|
void SceneDataTest::constructCopy() { |
|
CORRADE_VERIFY(!std::is_copy_constructible<SceneData>{}); |
|
CORRADE_VERIFY(!std::is_copy_assignable<SceneData>{}); |
|
} |
|
|
|
void SceneDataTest::constructMove() { |
|
struct Mesh { |
|
UnsignedShort object; |
|
UnsignedInt mesh; |
|
}; |
|
|
|
Containers::Array<char> data{NoInit, 3*sizeof(Mesh)}; |
|
auto meshData = Containers::arrayCast<Mesh>(data); |
|
meshData[0] = {0, 2}; |
|
meshData[1] = {73, 1}; |
|
meshData[2] = {122, 2}; |
|
|
|
int importerState; |
|
SceneFieldData meshes{SceneField::Mesh, stridedArrayView(meshData).slice(&Mesh::object), stridedArrayView(meshData).slice(&Mesh::mesh)}; |
|
SceneData a{SceneObjectType::UnsignedShort, 15, std::move(data), {meshes}, &importerState}; |
|
|
|
SceneData b{std::move(a)}; |
|
CORRADE_COMPARE(b.dataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(b.objectCount(), 15); |
|
CORRADE_COMPARE(b.objectType(), SceneObjectType::UnsignedShort); |
|
CORRADE_COMPARE(b.fieldCount(), 1); |
|
CORRADE_COMPARE(b.importerState(), &importerState); |
|
CORRADE_COMPARE(static_cast<const void*>(b.data()), meshData.data()); |
|
CORRADE_COMPARE(b.fieldName(0), SceneField::Mesh); |
|
CORRADE_COMPARE(b.fieldType(0), SceneFieldType::UnsignedInt); |
|
CORRADE_COMPARE(b.fieldSize(0), 3); |
|
CORRADE_COMPARE(b.fieldArraySize(0), 0); |
|
CORRADE_COMPARE(b.objects<UnsignedShort>(0)[2], 122); |
|
CORRADE_COMPARE(b.field<UnsignedInt>(0)[2], 2); |
|
|
|
SceneData c{SceneObjectType::UnsignedByte, 76, nullptr, {}}; |
|
c = std::move(b); |
|
CORRADE_COMPARE(c.dataFlags(), DataFlag::Owned|DataFlag::Mutable); |
|
CORRADE_COMPARE(c.objectCount(), 15); |
|
CORRADE_COMPARE(c.objectType(), SceneObjectType::UnsignedShort); |
|
CORRADE_COMPARE(c.fieldCount(), 1); |
|
CORRADE_COMPARE(c.importerState(), &importerState); |
|
CORRADE_COMPARE(static_cast<const void*>(c.data()), meshData.data()); |
|
CORRADE_COMPARE(c.fieldName(0), SceneField::Mesh); |
|
CORRADE_COMPARE(c.fieldType(0), SceneFieldType::UnsignedInt); |
|
CORRADE_COMPARE(c.fieldSize(0), 3); |
|
CORRADE_COMPARE(c.fieldArraySize(0), 0); |
|
CORRADE_COMPARE(c.objects<UnsignedShort>(0)[2], 122); |
|
CORRADE_COMPARE(c.field<UnsignedInt>(0)[2], 2); |
|
|
|
CORRADE_VERIFY(std::is_nothrow_move_constructible<SceneData>::value); |
|
CORRADE_VERIFY(std::is_nothrow_move_assignable<SceneData>::value); |
|
} |
|
|
|
template<class T> void SceneDataTest::objectsAsArrayByIndex() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
struct Field { |
|
T object; |
|
UnsignedByte mesh; |
|
} fields[]{ |
|
{T(15), 0}, |
|
{T(37), 1}, |
|
{T(44), 15} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{Implementation::sceneObjectTypeFor<T>(), 50, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, Implementation::sceneObjectTypeFor<T>(), nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Mesh, view.slice(&Field::object), view.slice(&Field::mesh)} |
|
}}; |
|
|
|
CORRADE_COMPARE_AS(scene.objectsAsArray(1), |
|
Containers::arrayView<UnsignedInt>({15, 37, 44}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T> void SceneDataTest::objectsAsArrayByName() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
struct Field { |
|
T object; |
|
UnsignedByte mesh; |
|
} fields[]{ |
|
{T(15), 0}, |
|
{T(37), 1}, |
|
{T(44), 15} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{Implementation::sceneObjectTypeFor<T>(), 50, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, Implementation::sceneObjectTypeFor<T>(), nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Mesh, view.slice(&Field::object), view.slice(&Field::mesh)} |
|
}}; |
|
|
|
CORRADE_COMPARE_AS(scene.objectsAsArray(SceneField::Mesh), |
|
Containers::arrayView<UnsignedInt>({15, 37, 44}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void SceneDataTest::objectsAsArrayLongType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedLong object; |
|
UnsignedByte mesh; |
|
} fields[3]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedLong, 0x100000000ull, {}, fields, { |
|
SceneFieldData{SceneField::Mesh, view.slice(&Field::object), view.slice(&Field::mesh)} |
|
}}; |
|
|
|
/* AsArray calls into IntoArray, which then has the assert, so this tests |
|
both */ |
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.objectsAsArray(0); |
|
scene.objectsAsArray(SceneField::Mesh); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::objectsInto(): indices for up to 4294967296 objects can't fit into a 32-bit type, access them directly via objects() instead\n" |
|
"Trade::SceneData::objectsInto(): indices for up to 4294967296 objects can't fit into a 32-bit type, access them directly via objects() instead\n"); |
|
} |
|
|
|
void SceneDataTest::objectsIntoArrayByIndex() { |
|
auto&& data = IntoArrayOffsetData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Both AsArray() and Into() share a common helper. The AsArray() test |
|
above verified handling of various data types and this checks the |
|
offset/size parameters of the Into() variant. */ |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt mesh; |
|
} fields[] { |
|
{15, 0}, |
|
{37, 1}, |
|
{44, 15} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 50, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Mesh, |
|
view.slice(&Field::object), |
|
view.slice(&Field::mesh)}, |
|
}}; |
|
|
|
/* The offset-less overload should give back all data */ |
|
{ |
|
UnsignedInt out[3]; |
|
scene.objectsInto(1, out); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(out), |
|
view.slice(&Field::object), |
|
TestSuite::Compare::Container); |
|
|
|
/* The offset variant only a subset */ |
|
} { |
|
Containers::Array<UnsignedInt> out{data.size}; |
|
CORRADE_COMPARE(scene.objectsInto(1, data.offset, out), data.expectedSize); |
|
CORRADE_COMPARE_AS(out.prefix(data.expectedSize), |
|
view.slice(&Field::object) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void SceneDataTest::objectsIntoArrayByName() { |
|
auto&& data = IntoArrayOffsetData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Both AsArray() and Into() share a common helper. The AsArray() test |
|
above verified handling of various data types and this checks the |
|
offset/size parameters of the Into() variant. */ |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt mesh; |
|
} fields[] { |
|
{15, 0}, |
|
{37, 1}, |
|
{44, 15} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 50, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Mesh, |
|
view.slice(&Field::object), |
|
view.slice(&Field::mesh)}, |
|
}}; |
|
|
|
/* The offset-less overload should give back all data */ |
|
{ |
|
UnsignedInt out[3]; |
|
scene.objectsInto(SceneField::Mesh, out); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(out), |
|
view.slice(&Field::object), |
|
TestSuite::Compare::Container); |
|
|
|
/* The offset variant only a subset */ |
|
} { |
|
Containers::Array<UnsignedInt> out{data.size}; |
|
CORRADE_COMPARE(scene.objectsInto(SceneField::Mesh, data.offset, out), data.expectedSize); |
|
CORRADE_COMPARE_AS(out.prefix(data.expectedSize), |
|
view.slice(&Field::object) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void SceneDataTest::objectsIntoArrayInvalidSizeOrOffset() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedByte mesh; |
|
} fields[3]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
SceneFieldData{SceneField::Mesh, view.slice(&Field::object), view.slice(&Field::mesh)} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
UnsignedInt destination[2]; |
|
scene.objectsInto(0, destination); |
|
scene.objectsInto(SceneField::Mesh, destination); |
|
scene.objectsInto(0, 4, destination); |
|
scene.objectsInto(SceneField::Mesh, 4, destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::objectsInto(): expected a view with 3 elements but got 2\n" |
|
"Trade::SceneData::objectsInto(): expected a view with 3 elements but got 2\n" |
|
"Trade::SceneData::objectsInto(): offset 4 out of bounds for a field of size 3\n" |
|
"Trade::SceneData::objectsInto(): offset 4 out of bounds for a field of size 3\n"); |
|
} |
|
|
|
template<class T> void SceneDataTest::parentsAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
struct Field { |
|
UnsignedByte object; |
|
T parent; |
|
} fields[]{ |
|
{0, T(15)}, |
|
{1, T(-1)}, |
|
{15, T(44)} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedByte, 50, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Mesh, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::UnsignedInt, nullptr}, |
|
SceneFieldData{SceneField::Parent, view.slice(&Field::object), view.slice(&Field::parent)} |
|
}}; |
|
|
|
CORRADE_COMPARE_AS(scene.parentsAsArray(), |
|
Containers::arrayView({15, -1, 44}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
#ifndef CORRADE_TARGET_32BIT |
|
void SceneDataTest::parentsAsArrayLongType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedLong object; |
|
Long parent; |
|
}; |
|
|
|
Containers::Array<char> data{nullptr, 0x100000000ull*sizeof(Field), [](char*, std::size_t) {}}; |
|
Containers::StridedArrayView1D<Field> view = Containers::arrayCast<Field>(data); |
|
|
|
SceneData scene{SceneObjectType::UnsignedLong, 0x100000000ull, std::move(data), { |
|
SceneFieldData{SceneField::Parent, view.slice(&Field::object), view.slice(&Field::parent)} |
|
}}; |
|
|
|
/* AsArray calls into IntoArray, which then has the assert, so this tests |
|
both */ |
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.parentsAsArray(); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::parentsInto(): parent indices for up to 4294967296 objects can't fit into a 32-bit type, access them directly via field() instead\n"); |
|
} |
|
#endif |
|
|
|
void SceneDataTest::parentsIntoArray() { |
|
auto&& data = IntoArrayOffsetData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Both AsArray() and Into() share a common helper. The AsArray() test |
|
above verified handling of various data types and this checks the |
|
offset/size parameters of the Into() variant. */ |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
Int parent; |
|
} fields[] { |
|
{1, 15}, |
|
{0, -1}, |
|
{4, 44} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Mesh, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::UnsignedInt, nullptr}, |
|
SceneFieldData{SceneField::Parent, |
|
view.slice(&Field::object), |
|
view.slice(&Field::parent)}, |
|
}}; |
|
|
|
/* The offset-less overload should give back all data */ |
|
{ |
|
Int out[3]; |
|
scene.parentsInto(out); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(out), |
|
view.slice(&Field::parent), |
|
TestSuite::Compare::Container); |
|
|
|
/* The offset variant only a subset */ |
|
} { |
|
Containers::Array<Int> out{data.size}; |
|
CORRADE_COMPARE(scene.parentsInto(data.offset, out), data.expectedSize); |
|
CORRADE_COMPARE_AS(out.prefix(data.expectedSize), |
|
view.slice(&Field::parent) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void SceneDataTest::parentsIntoArrayInvalidSizeOrOffset() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
Int parent; |
|
} fields[3]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
SceneFieldData{SceneField::Parent, view.slice(&Field::object), view.slice(&Field::parent)} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Int destination[2]; |
|
scene.parentsInto(destination); |
|
scene.parentsInto(4, destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::parentsInto(): expected a view with 3 elements but got 2\n" |
|
"Trade::SceneData::parentsInto(): offset 4 out of bounds for a field of size 3\n"); |
|
} |
|
|
|
template<class T> void SceneDataTest::transformations2DAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
typedef typename T::Type U; |
|
|
|
struct Transformation { |
|
UnsignedInt object; |
|
T transformation; |
|
}; |
|
|
|
struct Component { |
|
UnsignedInt object; |
|
Vector2 translation; |
|
Vector2 scaling; |
|
}; |
|
|
|
Containers::StridedArrayView1D<Transformation> transformations; |
|
Containers::StridedArrayView1D<Component> components; |
|
Containers::Array<char> data = Containers::ArrayTuple{ |
|
{NoInit, 4, transformations}, |
|
{NoInit, 2, components} |
|
}; |
|
transformations[0] = {1, T::translation({U(3.0), U(2.0)})}; |
|
transformations[1] = {0, T::rotation(Math::Deg<U>(35.0))}; |
|
transformations[2] = {4, T::translation({U(1.5), U(2.5)})* |
|
T::rotation(Math::Deg<U>(-15.0))}; |
|
transformations[3] = {5, T::rotation(Math::Deg<U>(-15.0))* |
|
T::translation({U(1.5), U(2.5)})}; |
|
/* Object number 4 additionally has a scaling component (which isn't |
|
representable with dual complex numbers). It currently doesn't get added |
|
to the transformations returned from transformations2DInto() but that |
|
may change in the future for dual complex numbers). The translation |
|
component is then *assumed* to be equivalent to what's stored in the |
|
Transformation field and so applied neither. Here it's different, and |
|
that shouldn't affect anything. */ |
|
components[0] = {4, {-1.5f, -2.5f}, {2.0f, 5.0f}}; |
|
/* This is deliberately an error -- specifying a TRS for an object that |
|
doesn't have a Transformation field. Since there's no fast way to check |
|
for those and error/warn on those, they get just ignored. */ |
|
components[1] = {2, {3.5f, -1.0f}, {1.0f, 1.5f}}; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 6, std::move(data), { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Transformation, |
|
transformations.slice(&Transformation::object), |
|
transformations.slice(&Transformation::transformation)}, |
|
SceneFieldData{SceneField::Translation, |
|
components.slice(&Component::object), |
|
components.slice(&Component::translation)}, |
|
SceneFieldData{SceneField::Scaling, |
|
components.slice(&Component::object), |
|
components.slice(&Component::scaling)}, |
|
}}; |
|
|
|
CORRADE_VERIFY(scene.is2D()); |
|
CORRADE_VERIFY(!scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView({ |
|
Matrix3::translation({3.0f, 2.0f}), |
|
Matrix3::rotation(35.0_degf), |
|
Matrix3::translation({1.5f, 2.5f})*Matrix3::rotation(-15.0_degf), |
|
Matrix3::rotation(-15.0_degf)*Matrix3::translation({1.5f, 2.5f}) |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T, class U, class V> void SceneDataTest::transformations2DAsArrayTRS() { |
|
setTestCaseTemplateName({NameTraits<T>::name(), NameTraits<U>::name(), NameTraits<V>::name()}); |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
Math::Vector2<T> translation; |
|
Math::Complex<U> rotation; |
|
Math::Vector2<V> scaling; |
|
} fields[]{ |
|
{1, {T(3.0), T(2.0)}, |
|
{}, |
|
{V(1.0), V(1.0)}}, |
|
{0, {}, |
|
Math::Complex<U>::rotation(Math::Deg<U>{U(35.0)}), |
|
{V(1.0), V(1.0)}}, |
|
{2, {}, /* Identity transformation here */ |
|
{}, |
|
{V(1.0), V(1.0)}}, |
|
{4, {}, |
|
{}, |
|
{V(2.0), V(1.0)}}, |
|
{7, {T(1.5), T(2.5)}, |
|
Math::Complex<U>::rotation(Math::Deg<U>{U(-15.0)}), |
|
{V(-0.5), V(4.0)}}, |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneFieldData translation{SceneField::Translation, |
|
view.slice(&Field::object), |
|
view.slice(&Field::translation)}; |
|
SceneFieldData rotation{SceneField::Rotation, |
|
view.slice(&Field::object), |
|
view.slice(&Field::rotation)}; |
|
SceneFieldData scaling{SceneField::Scaling, |
|
view.slice(&Field::object), |
|
view.slice(&Field::scaling)}; |
|
|
|
/* Just one of translation / rotation / scaling */ |
|
{ |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
translation |
|
}}; |
|
CORRADE_VERIFY(scene.is2D()); |
|
CORRADE_VERIFY(!scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ |
|
Matrix3::translation({3.0f, 2.0f}), |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3::translation({1.5f, 2.5f}) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings2DAsArray(), (Containers::arrayView<Containers::Triple<Vector2, Complex, Vector2>>({ |
|
{{3.0f, 2.0f}, {}, Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{1.5f, 2.5f}, {}, Vector2{1.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} { |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
rotation |
|
}}; |
|
CORRADE_VERIFY(scene.is2D()); |
|
CORRADE_VERIFY(!scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3::rotation(35.0_degf), |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3::rotation(-15.0_degf) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings2DAsArray(), (Containers::arrayView<Containers::Triple<Vector2, Complex, Vector2>>({ |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, Complex::rotation(35.0_degf), Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, Complex::rotation(-15.0_degf), Vector2{1.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} { |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
scaling |
|
}}; |
|
CORRADE_VERIFY(scene.is2D()); |
|
CORRADE_VERIFY(!scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3::scaling({2.0f, 1.0f}), |
|
Matrix3::scaling({-0.5f, 4.0f}) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings2DAsArray(), (Containers::arrayView<Containers::Triple<Vector2, Complex, Vector2>>({ |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, {}, {2.0f, 1.0f}}, |
|
{{}, {}, {-0.5f, 4.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} |
|
|
|
/* Pairs */ |
|
{ |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
translation, |
|
rotation |
|
}}; |
|
CORRADE_VERIFY(scene.is2D()); |
|
CORRADE_VERIFY(!scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ |
|
Matrix3::translation({3.0f, 2.0f}), |
|
Matrix3::rotation(35.0_degf), |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3::translation({1.5f, 2.5f})*Matrix3::rotation({-15.0_degf}) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings2DAsArray(), (Containers::arrayView<Containers::Triple<Vector2, Complex, Vector2>>({ |
|
{{3.0f, 2.0f}, {}, Vector2{1.0f}}, |
|
{{}, Complex::rotation(35.0_degf), Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{1.5f, 2.5f}, Complex::rotation(-15.0_degf), Vector2{1.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} { |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
translation, |
|
scaling |
|
}}; |
|
CORRADE_VERIFY(scene.is2D()); |
|
CORRADE_VERIFY(!scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ |
|
Matrix3::translation({3.0f, 2.0f}), |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3::scaling({2.0f, 1.0f}), |
|
Matrix3::translation({1.5f, 2.5f})*Matrix3::scaling({-0.5f, 4.0f}) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings2DAsArray(), (Containers::arrayView<Containers::Triple<Vector2, Complex, Vector2>>({ |
|
{{3.0f, 2.0f}, {}, Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, {}, {2.0f, 1.0f}}, |
|
{{1.5f, 2.5f}, {}, {-0.5f, 4.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} { |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
rotation, |
|
scaling |
|
}}; |
|
CORRADE_VERIFY(scene.is2D()); |
|
CORRADE_VERIFY(!scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3::rotation(35.0_degf), |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3::scaling({2.0f, 1.0f}), |
|
Matrix3::rotation({-15.0_degf})*Matrix3::scaling({-0.5f, 4.0f}) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings2DAsArray(), (Containers::arrayView<Containers::Triple<Vector2, Complex, Vector2>>({ |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, Complex::rotation(35.0_degf), Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, {}, {2.0f, 1.0f}}, |
|
{{}, Complex::rotation(-15.0_degf), {-0.5f, 4.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} |
|
|
|
/* All */ |
|
{ |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
translation, |
|
rotation, |
|
scaling |
|
}}; |
|
CORRADE_VERIFY(scene.is2D()); |
|
CORRADE_VERIFY(!scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ |
|
Matrix3::translation({3.0f, 2.0f}), |
|
Matrix3::rotation(35.0_degf), |
|
Matrix3{Math::IdentityInit}, |
|
Matrix3::scaling({2.0f, 1.0f}), |
|
Matrix3::translation({1.5f, 2.5f})*Matrix3::rotation({-15.0_degf})*Matrix3::scaling({-0.5f, 4.0f}) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings2DAsArray(), (Containers::arrayView<Containers::Triple<Vector2, Complex, Vector2>>({ |
|
{{3.0f, 2.0f}, {}, Vector2{1.0f}}, |
|
{{}, Complex::rotation(35.0_degf), Vector2{1.0f}}, |
|
{{}, {}, Vector2{1.0f}}, |
|
{{}, {}, {2.0f, 1.0f}}, |
|
{{1.5f, 2.5f}, Complex::rotation(-15.0_degf), {-0.5f, 4.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void SceneDataTest::transformations2DAsArrayBut3DType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
/* Because TRSAsArray() allocates an Array<Triple> and then calls |
|
TRSInto(), which skips views that are nullptr, we wouldn't get the |
|
assertion for translations, as those are at offset 0, which would be |
|
interpreted as an empty view if there were no elements. Thus using |
|
rotations instead. */ |
|
SceneData scene{SceneObjectType::UnsignedInt, 0, nullptr, { |
|
SceneFieldData{SceneField::Rotation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Quaternion, nullptr} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.transformations2DAsArray(); |
|
scene.translationsRotationsScalings2DAsArray(); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::transformations2DInto(): scene has a 3D transformation type\n" |
|
"Trade::SceneData::translationsRotationsScalings2DInto(): scene has a 3D transformation type\n"); |
|
} |
|
|
|
void SceneDataTest::transformations2DIntoArray() { |
|
auto&& data = IntoArrayOffsetData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Both AsArray() and Into() share a common helper. The AsArray() test |
|
above verified handling of various data types and this checks the |
|
offset/size parameters of the Into() variant. */ |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
Matrix3 transformation; |
|
} fields[] { |
|
{1, Matrix3::translation({3.0f, 2.0f})*Matrix3::scaling({1.5f, 2.0f})}, |
|
{0, Matrix3::rotation(35.0_degf)}, |
|
{4, Matrix3::translation({3.0f, 2.0f})*Matrix3::rotation(35.0_degf)} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Transformation, |
|
view.slice(&Field::object), |
|
view.slice(&Field::transformation)}, |
|
}}; |
|
|
|
/* The offset-less overload should give back all data */ |
|
{ |
|
Matrix3 out[3]; |
|
scene.transformations2DInto(out); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(out), |
|
view.slice(&Field::transformation), |
|
TestSuite::Compare::Container); |
|
|
|
/* The offset variant only a subset */ |
|
} { |
|
Containers::Array<Matrix3> out{data.size}; |
|
CORRADE_COMPARE(scene.transformations2DInto(data.offset, out), data.expectedSize); |
|
CORRADE_COMPARE_AS(out.prefix(data.expectedSize), |
|
view.slice(&Field::transformation) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void SceneDataTest::transformations2DIntoArrayTRS() { |
|
auto&& data = IntoArrayOffsetData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Both AsArray() and Into() share a common helper. The AsArray() test |
|
above verified handling of various data types and this checks the |
|
offset/size parameters of the Into() variant. */ |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
Vector2 translation; |
|
Complex rotation; |
|
Vector2 scaling; |
|
} fields[] { |
|
{1, {3.0f, 2.0f}, {}, {1.5f, 2.0f}}, |
|
{0, {}, Complex::rotation(35.0_degf), {1.0f, 1.0f}}, |
|
{4, {3.0f, 2.0f}, Complex::rotation(35.0_degf), {1.0f, 1.0f}} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Translation, |
|
view.slice(&Field::object), |
|
view.slice(&Field::translation)}, |
|
SceneFieldData{SceneField::Rotation, |
|
view.slice(&Field::object), |
|
view.slice(&Field::rotation)}, |
|
SceneFieldData{SceneField::Scaling, |
|
view.slice(&Field::object), |
|
view.slice(&Field::scaling)}, |
|
}}; |
|
|
|
Matrix3 expected[]{ |
|
Matrix3::translation({3.0f, 2.0f})*Matrix3::scaling({1.5f, 2.0f}), |
|
Matrix3::rotation(35.0_degf), |
|
Matrix3::translation({3.0f, 2.0f})*Matrix3::rotation(35.0_degf) |
|
}; |
|
|
|
/* The offset-less overload should give back all data */ |
|
{ |
|
Matrix3 out[3]; |
|
scene.transformations2DInto(out); |
|
CORRADE_COMPARE_AS(Containers::arrayView(out), |
|
Containers::arrayView(expected), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with TRS components */ |
|
} { |
|
Vector2 translationsOut[3]; |
|
Complex rotationsOut[3]; |
|
Vector2 scalingsOut[3]; |
|
scene.translationsRotationsScalings2DInto(translationsOut, rotationsOut, scalingsOut); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(translationsOut), |
|
view.slice(&Field::translation), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(rotationsOut), |
|
view.slice(&Field::rotation), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(scalingsOut), |
|
view.slice(&Field::scaling), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just translations */ |
|
} { |
|
Vector2 translationsOut[3]; |
|
scene.translationsRotationsScalings2DInto(translationsOut, nullptr, nullptr); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(translationsOut), |
|
view.slice(&Field::translation), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just rotations */ |
|
} { |
|
Complex rotationsOut[3]; |
|
scene.translationsRotationsScalings2DInto(nullptr, rotationsOut, nullptr); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(rotationsOut), |
|
view.slice(&Field::rotation), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just scalings */ |
|
} { |
|
Vector2 scalingsOut[3]; |
|
scene.translationsRotationsScalings2DInto(nullptr, nullptr, scalingsOut); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(scalingsOut), |
|
view.slice(&Field::scaling), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with neither is stupid, but should work too */ |
|
} { |
|
scene.translationsRotationsScalings2DInto(nullptr, nullptr, nullptr); |
|
|
|
/* The offset variant only a subset */ |
|
} { |
|
Containers::Array<Matrix3> out{data.size}; |
|
CORRADE_COMPARE(scene.transformations2DInto(data.offset, out), data.expectedSize); |
|
CORRADE_COMPARE_AS(out.prefix(data.expectedSize), |
|
Containers::arrayView(expected).slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with TRS components */ |
|
} { |
|
Containers::Array<Vector2> translationsOut{data.size}; |
|
Containers::Array<Complex> rotationsOut{data.size}; |
|
Containers::Array<Vector2> scalingsOut{data.size}; |
|
CORRADE_COMPARE(scene.translationsRotationsScalings2DInto(data.offset, translationsOut, rotationsOut, scalingsOut), data.expectedSize); |
|
CORRADE_COMPARE_AS(translationsOut.prefix(data.expectedSize), |
|
view.slice(&Field::translation) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(rotationsOut.prefix(data.expectedSize), |
|
view.slice(&Field::rotation) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scalingsOut.prefix(data.expectedSize), |
|
view.slice(&Field::scaling) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just translations */ |
|
} { |
|
Containers::Array<Vector2> translationsOut{data.size}; |
|
CORRADE_COMPARE(scene.translationsRotationsScalings2DInto(data.offset, translationsOut, nullptr, nullptr), data.expectedSize); |
|
CORRADE_COMPARE_AS(translationsOut.prefix(data.expectedSize), |
|
view.slice(&Field::translation) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just rotations */ |
|
} { |
|
Containers::Array<Complex> rotationsOut{data.size}; |
|
CORRADE_COMPARE(scene.translationsRotationsScalings2DInto(data.offset, nullptr, rotationsOut, nullptr), data.expectedSize); |
|
CORRADE_COMPARE_AS(rotationsOut.prefix(data.expectedSize), |
|
view.slice(&Field::rotation) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just scalings */ |
|
} { |
|
Containers::Array<Vector2> scalingsOut{data.size}; |
|
CORRADE_COMPARE(scene.translationsRotationsScalings2DInto(data.offset, nullptr, nullptr, scalingsOut), data.expectedSize); |
|
CORRADE_COMPARE_AS(scalingsOut.prefix(data.expectedSize), |
|
view.slice(&Field::scaling) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with neither is stupid, but should work too */ |
|
} { |
|
CORRADE_COMPARE(scene.translationsRotationsScalings2DInto(data.offset, nullptr, nullptr, nullptr), 0); |
|
} |
|
} |
|
|
|
void SceneDataTest::transformations2DIntoArrayInvalidSizeOrOffset() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
Matrix3 transformation; |
|
} fields[3]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
SceneFieldData{SceneField::Transformation, view.slice(&Field::object), view.slice(&Field::transformation)} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Matrix3 destination[2]; |
|
scene.transformations2DInto(destination); |
|
scene.transformations2DInto(4, destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::transformations2DInto(): expected a view with 3 elements but got 2\n" |
|
"Trade::SceneData::transformations2DInto(): offset 4 out of bounds for a field of size 3\n"); |
|
} |
|
|
|
void SceneDataTest::transformations2DIntoArrayInvalidSizeOrOffsetTRS() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
Vector2 translation; |
|
} fields[3]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
SceneFieldData{SceneField::Translation, view.slice(&Field::object), view.slice(&Field::translation)} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Vector2 translationDestinationCorrect[3]; |
|
Vector2 translationDestination[2]; |
|
Complex rotationDestinationCorrect[3]; |
|
Complex rotationDestination[2]; |
|
Vector2 scalingDestinationCorrect[3]; |
|
Vector2 scalingDestination[2]; |
|
scene.translationsRotationsScalings2DInto(translationDestination, rotationDestinationCorrect, scalingDestinationCorrect); |
|
scene.translationsRotationsScalings2DInto(translationDestinationCorrect, rotationDestination, scalingDestinationCorrect); |
|
scene.translationsRotationsScalings2DInto(translationDestinationCorrect, rotationDestinationCorrect, scalingDestination); |
|
scene.translationsRotationsScalings2DInto(4, translationDestination, rotationDestination, scalingDestination); |
|
scene.translationsRotationsScalings2DInto(0, translationDestinationCorrect, rotationDestination, nullptr); |
|
scene.translationsRotationsScalings2DInto(0, translationDestinationCorrect, nullptr, scalingDestination); |
|
scene.translationsRotationsScalings2DInto(0, nullptr, rotationDestinationCorrect, scalingDestination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::translationsRotationsScalings2DInto(): expected translation destination view either empty or with 3 elements but got 2\n" |
|
"Trade::SceneData::translationsRotationsScalings2DInto(): expected rotation destination view either empty or with 3 elements but got 2\n" |
|
"Trade::SceneData::translationsRotationsScalings2DInto(): expected scaling destination view either empty or with 3 elements but got 2\n" |
|
"Trade::SceneData::translationsRotationsScalings2DInto(): offset 4 out of bounds for a field of size 3\n" |
|
"Trade::SceneData::translationsRotationsScalings2DInto(): translation and rotation destination views have different size, 3 vs 2\n" |
|
"Trade::SceneData::translationsRotationsScalings2DInto(): translation and scaling destination views have different size, 3 vs 2\n" |
|
"Trade::SceneData::translationsRotationsScalings2DInto(): rotation and scaling destination views have different size, 3 vs 2\n"); |
|
} |
|
|
|
template<class T> void SceneDataTest::transformations3DAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
typedef typename T::Type U; |
|
|
|
struct Transformation { |
|
UnsignedInt object; |
|
T transformation; |
|
}; |
|
|
|
struct Component { |
|
UnsignedInt object; |
|
Vector3 translation; |
|
Vector3 scaling; |
|
}; |
|
|
|
Containers::StridedArrayView1D<Transformation> transformations; |
|
Containers::StridedArrayView1D<Component> components; |
|
Containers::Array<char> data = Containers::ArrayTuple{ |
|
{NoInit, 4, transformations}, |
|
{NoInit, 2, components} |
|
}; |
|
transformations[0] = {1, T::translation({U(3.0), U(2.0), U(-0.5)})}; |
|
transformations[1] = {0, T::rotation(Math::Deg<U>(35.0), |
|
Math::Vector3<U>::yAxis())}; |
|
transformations[2] = {4, T::translation({U(1.5), U(2.5), U(0.75)})* |
|
T::rotation(Math::Deg<U>(-15.0), |
|
Math::Vector3<U>::xAxis())}; |
|
transformations[3] = {5, T::rotation(Math::Deg<U>(-15.0), |
|
Math::Vector3<U>::xAxis())* |
|
T::translation({U(1.5), U(2.5), U(0.75)})}; |
|
/* Object number 4 additionally has a scaling component (which isn't |
|
representable with dual quaternions). It currently doesn't get added |
|
to the transformations returned from transformations2DInto() but that |
|
may change in the future for dual quaternions). The translation |
|
component is then *assumed* to be equivalent to what's stored in the |
|
Transformation field and so applied neither. Here it's different, and |
|
that shouldn't affect anything. */ |
|
components[0] = {4, {-1.5f, -2.5f, 5.5f}, {2.0f, 5.0f, 3.0f}}; |
|
/* This is deliberately an error -- specifying a TRS for an object that |
|
doesn't have a Transformation field. Since there's no fast way to check |
|
for those and error/warn on those, they get just ignored. */ |
|
components[1] = {2, {3.5f, -1.0f, 2.2f}, {1.0f, 1.5f, 1.0f}}; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 6, std::move(data), { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Transformation, |
|
transformations.slice(&Transformation::object), |
|
transformations.slice(&Transformation::transformation)}, |
|
SceneFieldData{SceneField::Translation, |
|
components.slice(&Component::object), |
|
components.slice(&Component::translation)}, |
|
SceneFieldData{SceneField::Scaling, |
|
components.slice(&Component::object), |
|
components.slice(&Component::scaling)}, |
|
}}; |
|
|
|
CORRADE_VERIFY(!scene.is2D()); |
|
CORRADE_VERIFY(scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView({ |
|
Matrix4::translation({3.0f, 2.0f, -0.5f}), |
|
Matrix4::rotationY(35.0_degf), |
|
Matrix4::translation({1.5f, 2.5f, 0.75f})*Matrix4::rotationX(-15.0_degf), |
|
Matrix4::rotationX(-15.0_degf)*Matrix4::translation({1.5f, 2.5f, 0.75f}) |
|
}), TestSuite::Compare::Container); |
|
} |
|
|
|
template<class T, class U, class V> void SceneDataTest::transformations3DAsArrayTRS() { |
|
setTestCaseTemplateName({NameTraits<T>::name(), NameTraits<U>::name(), NameTraits<V>::name()}); |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
Math::Vector3<T> translation; |
|
Math::Quaternion<U> rotation; |
|
Math::Vector3<V> scaling; |
|
} fields[]{ |
|
{1, {T(3.0), T(2.0), T(1.0)}, |
|
{}, |
|
{V(1.0), V(1.0), V(1.0)}}, |
|
{0, {}, |
|
Math::Quaternion<U>::rotation(Math::Deg<U>{U(35.0)}, Math::Vector3<U>::yAxis()), |
|
{V(1.0), V(1.0), V(1.0)}}, |
|
{2, {}, /* Identity transformation here */ |
|
{}, |
|
{V(1.0), V(1.0), V(1.0)}}, |
|
{4, {}, |
|
{}, |
|
{V(2.0), V(1.0), V(0.0)}}, |
|
{7, {T(1.5), T(2.5), T(3.5)}, |
|
Math::Quaternion<U>::rotation(Math::Deg<U>{U(-15.0)}, Math::Vector3<U>::xAxis()), |
|
{V(-0.5), V(4.0), V(-16.0)}}, |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneFieldData translation{SceneField::Translation, |
|
view.slice(&Field::object), |
|
view.slice(&Field::translation)}; |
|
SceneFieldData rotation{SceneField::Rotation, |
|
view.slice(&Field::object), |
|
view.slice(&Field::rotation)}; |
|
SceneFieldData scaling{SceneField::Scaling, |
|
view.slice(&Field::object), |
|
view.slice(&Field::scaling)}; |
|
|
|
/* Just one of translation / rotation / scaling */ |
|
{ |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
translation |
|
}}; |
|
CORRADE_VERIFY(!scene.is2D()); |
|
CORRADE_VERIFY(scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ |
|
Matrix4::translation({3.0f, 2.0, 1.0f}), |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4::translation({1.5f, 2.5f, 3.5f}) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings3DAsArray(), (Containers::arrayView<Containers::Triple<Vector3, Quaternion, Vector3>>({ |
|
{{3.0f, 2.0, 1.0f}, {}, Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{1.5f, 2.5f, 3.5f}, {}, Vector3{1.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} { |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
rotation |
|
}}; |
|
CORRADE_VERIFY(!scene.is2D()); |
|
CORRADE_VERIFY(scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4::rotationY(35.0_degf), |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4::rotationX(-15.0_degf) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings3DAsArray(), (Containers::arrayView<Containers::Triple<Vector3, Quaternion, Vector3>>({ |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, Quaternion::rotation(35.0_degf, Vector3::yAxis()), Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, Quaternion::rotation(-15.0_degf, Vector3::xAxis()), Vector3{1.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} { |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
scaling |
|
}}; |
|
CORRADE_VERIFY(!scene.is2D()); |
|
CORRADE_VERIFY(scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4::scaling({2.0f, 1.0f, 0.0f}), |
|
Matrix4::scaling({-0.5f, 4.0f, -16.0f}) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings3DAsArray(), (Containers::arrayView<Containers::Triple<Vector3, Quaternion, Vector3>>({ |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, {}, {2.0f, 1.0f, 0.0f}}, |
|
{{}, {}, {-0.5f, 4.0f, -16.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} |
|
|
|
/* Pairs */ |
|
{ |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
translation, |
|
rotation |
|
}}; |
|
CORRADE_VERIFY(!scene.is2D()); |
|
CORRADE_VERIFY(scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ |
|
Matrix4::translation({3.0f, 2.0, 1.0f}), |
|
Matrix4::rotationY(35.0_degf), |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4::translation({1.5f, 2.5f, 3.5f})*Matrix4::rotationX(-15.0_degf) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings3DAsArray(), (Containers::arrayView<Containers::Triple<Vector3, Quaternion, Vector3>>({ |
|
{{3.0f, 2.0, 1.0f}, {}, Vector3{1.0f}}, |
|
{{}, Quaternion::rotation(35.0_degf, Vector3::yAxis()), Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{1.5f, 2.5f, 3.5f}, Quaternion::rotation(-15.0_degf, Vector3::xAxis()), Vector3{1.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} { |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
translation, |
|
scaling |
|
}}; |
|
CORRADE_VERIFY(!scene.is2D()); |
|
CORRADE_VERIFY(scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ |
|
Matrix4::translation({3.0f, 2.0, 1.0f}), |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4::scaling({2.0f, 1.0f, 0.0f}), |
|
Matrix4::translation({1.5f, 2.5f, 3.5f})*Matrix4::scaling({-0.5f, 4.0f, -16.0f}) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings3DAsArray(), (Containers::arrayView<Containers::Triple<Vector3, Quaternion, Vector3>>({ |
|
{{3.0f, 2.0, 1.0f}, {}, Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, {}, {2.0f, 1.0f, 0.0f}}, |
|
{{1.5f, 2.5f, 3.5f}, {}, {-0.5f, 4.0f, -16.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} { |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
rotation, |
|
scaling |
|
}}; |
|
CORRADE_VERIFY(!scene.is2D()); |
|
CORRADE_VERIFY(scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4::rotationY(35.0_degf), |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4::scaling({2.0f, 1.0f, 0.0f}), |
|
Matrix4::rotationX({-15.0_degf})*Matrix4::scaling({-0.5f, 4.0f, -16.0f}) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings3DAsArray(), (Containers::arrayView<Containers::Triple<Vector3, Quaternion, Vector3>>({ |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, Quaternion::rotation(35.0_degf, Vector3::yAxis()), Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, {}, {2.0f, 1.0f, 0.0f}}, |
|
{{}, Quaternion::rotation(-15.0_degf, Vector3::xAxis()), {-0.5f, 4.0f, -16.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} |
|
|
|
/* All */ |
|
{ |
|
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { |
|
translation, |
|
rotation, |
|
scaling |
|
}}; |
|
CORRADE_VERIFY(!scene.is2D()); |
|
CORRADE_VERIFY(scene.is3D()); |
|
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ |
|
Matrix4::translation({3.0f, 2.0, 1.0f}), |
|
Matrix4::rotationY(35.0_degf), |
|
Matrix4{Math::IdentityInit}, |
|
Matrix4::scaling({2.0f, 1.0f, 0.0f}), |
|
Matrix4::translation({1.5f, 2.5f, 3.5f})*Matrix4::rotationX({-15.0_degf})*Matrix4::scaling({-0.5f, 4.0f, -16.0f}) |
|
}), TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.translationsRotationsScalings3DAsArray(), (Containers::arrayView<Containers::Triple<Vector3, Quaternion, Vector3>>({ |
|
{{3.0f, 2.0, 1.0f}, {}, Vector3{1.0f}}, |
|
{{}, Quaternion::rotation(35.0_degf, Vector3::yAxis()), Vector3{1.0f}}, |
|
{{}, {}, Vector3{1.0f}}, |
|
{{}, {}, {2.0f, 1.0f, 0.0f}}, |
|
{{1.5f, 2.5f, 3.5f}, Quaternion::rotation(-15.0_degf, Vector3::xAxis()), {-0.5f, 4.0f, -16.0f}}, |
|
})), TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void SceneDataTest::transformations3DAsArrayBut2DType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
/* Because TRSAsArray() allocates an Array<Triple> and then calls |
|
TRSInto(), which skips views that are nullptr, we wouldn't get the |
|
assertion for translations, as those are at offset 0, which would be |
|
interpreted as an empty view if there were no elements. Thus using |
|
rotations instead. */ |
|
SceneData scene{SceneObjectType::UnsignedInt, 0, nullptr, { |
|
SceneFieldData{SceneField::Rotation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Complex, nullptr} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.transformations3DAsArray(); |
|
scene.translationsRotationsScalings3DAsArray(); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::transformations3DInto(): scene has a 2D transformation type\n" |
|
"Trade::SceneData::translationsRotationsScalings3DInto(): scene has a 2D transformation type\n"); |
|
} |
|
|
|
void SceneDataTest::transformations3DIntoArray() { |
|
auto&& data = IntoArrayOffsetData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Both AsArray() and Into() share a common helper. The AsArray() test |
|
above verified handling of various data types and this checks the |
|
offset/size parameters of the Into() variant. */ |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
Matrix4 transformation; |
|
} fields[] { |
|
{1, Matrix4::translation({3.0f, 2.0f, 1.0f})*Matrix4::scaling({1.5f, 2.0f, 4.5f})}, |
|
{0, Matrix4::rotationX(35.0_degf)}, |
|
{4, Matrix4::translation({3.0f, 2.0f, 1.0f})*Matrix4::rotationX(35.0_degf)} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Transformation, |
|
view.slice(&Field::object), |
|
view.slice(&Field::transformation)}, |
|
}}; |
|
|
|
/* The offset-less overload should give back all data */ |
|
{ |
|
Matrix4 out[3]; |
|
scene.transformations3DInto(out); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(out), |
|
view.slice(&Field::transformation), |
|
TestSuite::Compare::Container); |
|
|
|
/* The offset variant only a subset */ |
|
} { |
|
Containers::Array<Matrix4> out{data.size}; |
|
CORRADE_COMPARE(scene.transformations3DInto(data.offset, out), data.expectedSize); |
|
CORRADE_COMPARE_AS(out.prefix(data.expectedSize), |
|
view.slice(&Field::transformation) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void SceneDataTest::transformations3DIntoArrayTRS() { |
|
auto&& data = IntoArrayOffsetData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Both AsArray() and Into() share a common helper. The AsArray() test |
|
above verified handling of various data types and this checks the |
|
offset/size parameters of the Into() variant. */ |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
Vector3 translation; |
|
Quaternion rotation; |
|
Vector3 scaling; |
|
} fields[] { |
|
{1, {3.0f, 2.0f, 1.0f}, {}, {1.5f, 2.0f, 4.5f}}, |
|
{0, {}, Quaternion::rotation(35.0_degf, Vector3::xAxis()), {1.0f, 1.0f, 1.0f}}, |
|
{4, {3.0f, 2.0f, 1.0f}, Quaternion::rotation(35.0_degf, Vector3::xAxis()), {1.0f, 1.0f, 1.0f}} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Translation, |
|
view.slice(&Field::object), |
|
view.slice(&Field::translation)}, |
|
SceneFieldData{SceneField::Rotation, |
|
view.slice(&Field::object), |
|
view.slice(&Field::rotation)}, |
|
SceneFieldData{SceneField::Scaling, |
|
view.slice(&Field::object), |
|
view.slice(&Field::scaling)}, |
|
}}; |
|
|
|
Matrix4 expected[]{ |
|
Matrix4::translation({3.0f, 2.0f, 1.0f})*Matrix4::scaling({1.5f, 2.0f, 4.5f}), |
|
Matrix4::rotationX(35.0_degf), |
|
Matrix4::translation({3.0f, 2.0f, 1.0f})*Matrix4::rotationX(35.0_degf) |
|
}; |
|
|
|
/* The offset-less overload should give back all data */ |
|
{ |
|
Matrix4 out[3]; |
|
scene.transformations3DInto(out); |
|
CORRADE_COMPARE_AS(Containers::arrayView(out), |
|
Containers::arrayView(expected), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with TRS components */ |
|
} { |
|
Vector3 translationsOut[3]; |
|
Quaternion rotationsOut[3]; |
|
Vector3 scalingsOut[3]; |
|
scene.translationsRotationsScalings3DInto(translationsOut, rotationsOut, scalingsOut); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(translationsOut), |
|
view.slice(&Field::translation), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(rotationsOut), |
|
view.slice(&Field::rotation), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(scalingsOut), |
|
view.slice(&Field::scaling), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just translations */ |
|
} { |
|
Vector3 translationsOut[3]; |
|
scene.translationsRotationsScalings3DInto(translationsOut, nullptr, nullptr); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(translationsOut), |
|
view.slice(&Field::translation), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just rotations */ |
|
} { |
|
Quaternion rotationsOut[3]; |
|
scene.translationsRotationsScalings3DInto(nullptr, rotationsOut, nullptr); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(rotationsOut), |
|
view.slice(&Field::rotation), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just scalings */ |
|
} { |
|
Vector3 scalingsOut[3]; |
|
scene.translationsRotationsScalings3DInto(nullptr, nullptr, scalingsOut); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(scalingsOut), |
|
view.slice(&Field::scaling), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with neither is stupid, but should work too */ |
|
} { |
|
scene.translationsRotationsScalings3DInto(nullptr, nullptr, nullptr); |
|
|
|
/* The offset variant only a subset */ |
|
} { |
|
Containers::Array<Matrix4> out{data.size}; |
|
CORRADE_COMPARE(scene.transformations3DInto(data.offset, out), data.expectedSize); |
|
CORRADE_COMPARE_AS(out.prefix(data.expectedSize), |
|
Containers::arrayView(expected).slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with TRS components */ |
|
} { |
|
Containers::Array<Vector3> translationsOut{data.size}; |
|
Containers::Array<Quaternion> rotationsOut{data.size}; |
|
Containers::Array<Vector3> scalingsOut{data.size}; |
|
CORRADE_COMPARE(scene.translationsRotationsScalings3DInto(data.offset, translationsOut, rotationsOut, scalingsOut), data.expectedSize); |
|
CORRADE_COMPARE_AS(translationsOut.prefix(data.expectedSize), |
|
view.slice(&Field::translation) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(rotationsOut.prefix(data.expectedSize), |
|
view.slice(&Field::rotation) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scalingsOut.prefix(data.expectedSize), |
|
view.slice(&Field::scaling) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just translations */ |
|
} { |
|
Containers::Array<Vector3> translationsOut{data.size}; |
|
CORRADE_COMPARE(scene.translationsRotationsScalings3DInto(data.offset, translationsOut, nullptr, nullptr), data.expectedSize); |
|
CORRADE_COMPARE_AS(translationsOut.prefix(data.expectedSize), |
|
view.slice(&Field::translation) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just rotations */ |
|
} { |
|
Containers::Array<Quaternion> rotationsOut{data.size}; |
|
CORRADE_COMPARE(scene.translationsRotationsScalings3DInto(data.offset, nullptr, rotationsOut, nullptr), data.expectedSize); |
|
CORRADE_COMPARE_AS(rotationsOut.prefix(data.expectedSize), |
|
view.slice(&Field::rotation) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just scalings */ |
|
} { |
|
Containers::Array<Vector3> scalingsOut{data.size}; |
|
CORRADE_COMPARE(scene.translationsRotationsScalings3DInto(data.offset, nullptr, nullptr, scalingsOut), data.expectedSize); |
|
CORRADE_COMPARE_AS(scalingsOut.prefix(data.expectedSize), |
|
view.slice(&Field::scaling) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with neither is stupid, but should work too */ |
|
} { |
|
CORRADE_COMPARE(scene.translationsRotationsScalings3DInto(data.offset, nullptr, nullptr, nullptr), 0); |
|
} |
|
} |
|
|
|
void SceneDataTest::transformations3DIntoArrayInvalidSizeOrOffset() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
Matrix4 transformation; |
|
} fields[3]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
SceneFieldData{SceneField::Transformation, view.slice(&Field::object), view.slice(&Field::transformation)} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Matrix4 destination[2]; |
|
scene.transformations3DInto(destination); |
|
scene.transformations3DInto(4, destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::transformations3DInto(): expected a view with 3 elements but got 2\n" |
|
"Trade::SceneData::transformations3DInto(): offset 4 out of bounds for a field of size 3\n"); |
|
} |
|
|
|
void SceneDataTest::transformations3DIntoArrayInvalidSizeOrOffsetTRS() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
Vector2 translation; |
|
} fields[3]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
SceneFieldData{SceneField::Translation, view.slice(&Field::object), view.slice(&Field::translation)} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
Vector3 translationDestinationCorrect[3]; |
|
Vector3 translationDestination[2]; |
|
Quaternion rotationDestinationCorrect[3]; |
|
Quaternion rotationDestination[2]; |
|
Vector3 scalingDestinationCorrect[3]; |
|
Vector3 scalingDestination[2]; |
|
scene.translationsRotationsScalings3DInto(translationDestination, rotationDestinationCorrect, scalingDestinationCorrect); |
|
scene.translationsRotationsScalings3DInto(translationDestinationCorrect, rotationDestination, scalingDestinationCorrect); |
|
scene.translationsRotationsScalings3DInto(translationDestinationCorrect, rotationDestinationCorrect, scalingDestination); |
|
scene.translationsRotationsScalings3DInto(4, translationDestination, rotationDestination, scalingDestination); |
|
scene.translationsRotationsScalings3DInto(0, translationDestinationCorrect, rotationDestination, nullptr); |
|
scene.translationsRotationsScalings3DInto(0, translationDestinationCorrect, nullptr, scalingDestination); |
|
scene.translationsRotationsScalings3DInto(0, nullptr, rotationDestinationCorrect, scalingDestination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::translationsRotationsScalings3DInto(): expected translation destination view either empty or with 3 elements but got 2\n" |
|
"Trade::SceneData::translationsRotationsScalings3DInto(): expected rotation destination view either empty or with 3 elements but got 2\n" |
|
"Trade::SceneData::translationsRotationsScalings3DInto(): expected scaling destination view either empty or with 3 elements but got 2\n" |
|
"Trade::SceneData::translationsRotationsScalings3DInto(): offset 4 out of bounds for a field of size 3\n" |
|
"Trade::SceneData::translationsRotationsScalings3DInto(): translation and rotation destination views have different size, 3 vs 2\n" |
|
"Trade::SceneData::translationsRotationsScalings3DInto(): translation and scaling destination views have different size, 3 vs 2\n" |
|
"Trade::SceneData::translationsRotationsScalings3DInto(): rotation and scaling destination views have different size, 3 vs 2\n"); |
|
} |
|
|
|
template<class T, class U> void SceneDataTest::meshesMaterialsAsArray() { |
|
setTestCaseTemplateName({NameTraits<T>::name(), NameTraits<U>::name()}); |
|
|
|
struct Field { |
|
UnsignedByte object; |
|
T mesh; |
|
U meshMaterial; |
|
} fields[]{ |
|
{0, T(15), U(3)}, |
|
{1, T(37), U(-1)}, |
|
{15, T(44), U(25)} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneFieldData meshes{SceneField::Mesh, |
|
view.slice(&Field::object), |
|
view.slice(&Field::mesh)}; |
|
SceneFieldData meshMaterials{SceneField::MeshMaterial, |
|
view.slice(&Field::object), |
|
view.slice(&Field::meshMaterial)}; |
|
|
|
/* Both meshes and materials */ |
|
{ |
|
SceneData scene{SceneObjectType::UnsignedByte, 50, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Int, nullptr}, |
|
meshes, |
|
meshMaterials |
|
}}; |
|
|
|
CORRADE_COMPARE_AS(scene.meshesMaterialsAsArray(), |
|
(Containers::arrayView<Containers::Pair<UnsignedInt, Int>>({ |
|
{15, 3}, |
|
{37, -1}, |
|
{44, 25} |
|
})), TestSuite::Compare::Container); |
|
|
|
/* Only meshes */ |
|
} { |
|
SceneData scene{SceneObjectType::UnsignedByte, 50, {}, fields, { |
|
meshes |
|
}}; |
|
|
|
CORRADE_COMPARE_AS(scene.meshesMaterialsAsArray(), |
|
(Containers::arrayView<Containers::Pair<UnsignedInt, Int>>({ |
|
{15, -1}, |
|
{37, -1}, |
|
{44, -1} |
|
})), TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void SceneDataTest::meshesMaterialsIntoArray() { |
|
auto&& data = IntoArrayOffsetData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Both AsArray() and Into() share a common helper. The AsArray() test |
|
above verified handling of various data types and this checks the |
|
offset/size parameters of the Into() variant. */ |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt mesh; |
|
Int meshMaterial; |
|
} fields[]{ |
|
{1, 15, 3}, |
|
{0, 37, -1}, |
|
{4, 44, 22} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Mesh, |
|
view.slice(&Field::object), |
|
view.slice(&Field::mesh)}, |
|
SceneFieldData{SceneField::MeshMaterial, |
|
view.slice(&Field::object), |
|
view.slice(&Field::meshMaterial)}, |
|
}}; |
|
|
|
/* The offset-less overload should give back all data */ |
|
{ |
|
UnsignedInt meshesOut[3]; |
|
Int meshMaterialsOut[3]; |
|
scene.meshesMaterialsInto(meshesOut, meshMaterialsOut); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(meshesOut), |
|
view.slice(&Field::mesh), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(meshMaterialsOut), |
|
view.slice(&Field::meshMaterial), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just meshes */ |
|
} { |
|
UnsignedInt meshesOut[3]; |
|
scene.meshesMaterialsInto(meshesOut, nullptr); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(meshesOut), |
|
view.slice(&Field::mesh), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just materials */ |
|
} { |
|
Int meshMaterialsOut[3]; |
|
scene.meshesMaterialsInto(nullptr, meshMaterialsOut); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(meshMaterialsOut), |
|
view.slice(&Field::meshMaterial), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with neither is stupid, but should work too */ |
|
} { |
|
scene.meshesMaterialsInto(nullptr, nullptr); |
|
|
|
/* The offset variant should give back only a subset */ |
|
} { |
|
Containers::Array<UnsignedInt> meshesOut{data.size}; |
|
Containers::Array<Int> meshMaterialsOut{data.size}; |
|
CORRADE_COMPARE(scene.meshesMaterialsInto(data.offset, meshesOut, meshMaterialsOut), data.expectedSize); |
|
CORRADE_COMPARE_AS(meshesOut.prefix(data.expectedSize), |
|
view.slice(&Field::mesh) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(meshMaterialsOut.prefix(data.expectedSize), |
|
view.slice(&Field::meshMaterial) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just meshes */ |
|
} { |
|
Containers::Array<UnsignedInt> meshesOut{data.size}; |
|
CORRADE_COMPARE(scene.meshesMaterialsInto(data.offset, meshesOut, nullptr), data.expectedSize); |
|
CORRADE_COMPARE_AS(meshesOut.prefix(data.expectedSize), |
|
view.slice(&Field::mesh) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with just materials */ |
|
} { |
|
Containers::Array<Int> meshMaterialsOut{data.size}; |
|
CORRADE_COMPARE(scene.meshesMaterialsInto(data.offset, nullptr, meshMaterialsOut), data.expectedSize); |
|
CORRADE_COMPARE_AS(meshMaterialsOut.prefix(data.expectedSize), |
|
view.slice(&Field::meshMaterial) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
|
|
/* Variant with neither is stupid, but should work too */ |
|
} { |
|
CORRADE_COMPARE(scene.meshesMaterialsInto(data.offset, nullptr, nullptr), 0); |
|
} |
|
} |
|
|
|
void SceneDataTest::meshesMaterialsIntoArrayInvalidSizeOrOffset() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt mesh; |
|
} fields[3]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
SceneFieldData{SceneField::Mesh, view.slice(&Field::object), view.slice(&Field::mesh)} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
UnsignedInt meshDestinationCorrect[3]; |
|
UnsignedInt meshDestination[2]; |
|
Int meshMaterialDestinationCorrect[3]; |
|
Int meshMaterialDestination[2]; |
|
scene.meshesMaterialsInto(meshDestination, meshMaterialDestinationCorrect); |
|
scene.meshesMaterialsInto(meshDestinationCorrect, meshMaterialDestination); |
|
scene.meshesMaterialsInto(4, meshDestination, meshMaterialDestination); |
|
scene.meshesMaterialsInto(0, meshDestinationCorrect, meshMaterialDestination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::meshesMaterialsInto(): expected mesh destination view either empty or with 3 elements but got 2\n" |
|
"Trade::SceneData::meshesMaterialsInto(): expected mesh material destination view either empty or with 3 elements but got 2\n" |
|
"Trade::SceneData::meshesMaterialsInto(): offset 4 out of bounds for a field of size 3\n" |
|
"Trade::SceneData::meshesMaterialsInto(): mesh and mesh material destination views have different size, 3 vs 2\n"); |
|
} |
|
|
|
template<class T> void SceneDataTest::lightsAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
struct Field { |
|
UnsignedByte object; |
|
T light; |
|
} fields[]{ |
|
{0, T(15)}, |
|
{1, T(37)}, |
|
{15, T(44)} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedByte, 50, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Light, view.slice(&Field::object), view.slice(&Field::light)} |
|
}}; |
|
|
|
CORRADE_COMPARE_AS(scene.lightsAsArray(), |
|
Containers::arrayView<UnsignedInt>({15, 37, 44}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void SceneDataTest::lightsIntoArray() { |
|
auto&& data = IntoArrayOffsetData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Both AsArray() and Into() share a common helper. The AsArray() test |
|
above verified handling of various data types and this checks the |
|
offset/size parameters of the Into() variant. */ |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt light; |
|
} fields[] { |
|
{1, 15}, |
|
{0, 37}, |
|
{4, 44} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Light, |
|
view.slice(&Field::object), |
|
view.slice(&Field::light)}, |
|
}}; |
|
|
|
/* The offset-less overload should give back all data */ |
|
{ |
|
UnsignedInt out[3]; |
|
scene.lightsInto(out); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(out), |
|
view.slice(&Field::light), |
|
TestSuite::Compare::Container); |
|
|
|
/* The offset variant only a subset */ |
|
} { |
|
Containers::Array<UnsignedInt> out{data.size}; |
|
CORRADE_COMPARE(scene.lightsInto(data.offset, out), data.expectedSize); |
|
CORRADE_COMPARE_AS(out.prefix(data.expectedSize), |
|
view.slice(&Field::light) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void SceneDataTest::lightsIntoArrayInvalidSizeOrOffset() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt light; |
|
} fields[3]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
SceneFieldData{SceneField::Light, view.slice(&Field::object), view.slice(&Field::light)} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
UnsignedInt destination[2]; |
|
scene.lightsInto(destination); |
|
scene.lightsInto(4, destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::lightsInto(): expected a view with 3 elements but got 2\n" |
|
"Trade::SceneData::lightsInto(): offset 4 out of bounds for a field of size 3\n"); |
|
} |
|
|
|
template<class T> void SceneDataTest::camerasAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
struct Field { |
|
UnsignedByte object; |
|
T camera; |
|
} fields[]{ |
|
{0, T(15)}, |
|
{1, T(37)}, |
|
{15, T(44)} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedByte, 50, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Camera, view.slice(&Field::object), view.slice(&Field::camera)} |
|
}}; |
|
|
|
CORRADE_COMPARE_AS(scene.camerasAsArray(), |
|
Containers::arrayView<UnsignedInt>({15, 37, 44}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void SceneDataTest::camerasIntoArray() { |
|
auto&& data = IntoArrayOffsetData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Both AsArray() and Into() share a common helper. The AsArray() test |
|
above verified handling of various data types and this checks the |
|
offset/size parameters of the Into() variant. */ |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt camera; |
|
} fields[]{ |
|
{1, 15}, |
|
{0, 37}, |
|
{4, 44} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Camera, |
|
view.slice(&Field::object), |
|
view.slice(&Field::camera)}, |
|
}}; |
|
|
|
/* The offset-less overload should give back all data */ |
|
{ |
|
UnsignedInt out[3]; |
|
scene.camerasInto(out); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(out), |
|
view.slice(&Field::camera), |
|
TestSuite::Compare::Container); |
|
|
|
/* The offset variant only a subset */ |
|
} { |
|
Containers::Array<UnsignedInt> out{data.size}; |
|
CORRADE_COMPARE(scene.camerasInto(data.offset, out), data.expectedSize); |
|
CORRADE_COMPARE_AS(out.prefix(data.expectedSize), |
|
view.slice(&Field::camera) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void SceneDataTest::camerasIntoArrayInvalidSizeOrOffset() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt camera; |
|
} fields[3]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
SceneFieldData{SceneField::Camera, view.slice(&Field::object), view.slice(&Field::camera)} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
UnsignedInt destination[2]; |
|
scene.camerasInto(destination); |
|
scene.camerasInto(4, destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::camerasInto(): expected a view with 3 elements but got 2\n" |
|
"Trade::SceneData::camerasInto(): offset 4 out of bounds for a field of size 3\n"); |
|
} |
|
|
|
template<class T> void SceneDataTest::skinsAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
struct Field { |
|
UnsignedByte object; |
|
T skin; |
|
} fields[]{ |
|
{0, T(15)}, |
|
{1, T(37)}, |
|
{15, T(44)} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedByte, 50, {}, fields, { |
|
/* To verify it isn't just picking the first ever field; also to |
|
satisfy the requirement of having a transformation field to |
|
disambiguate the dimensionality */ |
|
SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Vector3, nullptr}, |
|
SceneFieldData{SceneField::Skin, view.slice(&Field::object), view.slice(&Field::skin)} |
|
}}; |
|
|
|
CORRADE_COMPARE_AS(scene.skinsAsArray(), |
|
Containers::arrayView<UnsignedInt>({15, 37, 44}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void SceneDataTest::skinsIntoArray() { |
|
auto&& data = IntoArrayOffsetData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Both AsArray() and Into() share a common helper. The AsArray() test |
|
above verified handling of various data types and this checks the |
|
offset/size parameters of the Into() variant. */ |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt skin; |
|
} fields[] { |
|
{1, 15}, |
|
{0, 37}, |
|
{4, 44} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
/* To verify it isn't just picking the first ever field; also to |
|
satisfy the requirement of having a transformation field to |
|
disambiguate the dimensionality */ |
|
SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Vector3, nullptr}, |
|
SceneFieldData{SceneField::Skin, |
|
view.slice(&Field::object), |
|
view.slice(&Field::skin)}, |
|
}}; |
|
|
|
/* The offset-less overload should give back all data */ |
|
{ |
|
UnsignedInt out[3]; |
|
scene.skinsInto(out); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(out), |
|
view.slice(&Field::skin), |
|
TestSuite::Compare::Container); |
|
|
|
/* The offset variant only a subset */ |
|
} { |
|
Containers::Array<UnsignedInt> out{data.size}; |
|
CORRADE_COMPARE(scene.skinsInto(data.offset, out), data.expectedSize); |
|
CORRADE_COMPARE_AS(out.prefix(data.expectedSize), |
|
view.slice(&Field::skin) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void SceneDataTest::skinsIntoArrayInvalidSizeOrOffset() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt skin; |
|
} fields[3]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
/* To satisfy the requirement of having a transformation field to |
|
disambiguate the dimensionality */ |
|
SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Vector3, nullptr}, |
|
SceneFieldData{SceneField::Skin, view.slice(&Field::object), view.slice(&Field::skin)} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
UnsignedInt destination[2]; |
|
scene.skinsInto(destination); |
|
scene.skinsInto(4, destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::skinsInto(): expected a view with 3 elements but got 2\n" |
|
"Trade::SceneData::skinsInto(): offset 4 out of bounds for a field of size 3\n"); |
|
} |
|
|
|
template<class T> void SceneDataTest::importerStateAsArray() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
int a, b; |
|
|
|
struct Field { |
|
UnsignedByte object; |
|
T importerState; |
|
} fields[]{ |
|
{0, &a}, |
|
{1, nullptr}, |
|
{15, &b} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedByte, 50, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::ImporterState, view.slice(&Field::object), view.slice(&Field::importerState)} |
|
}}; |
|
|
|
CORRADE_COMPARE_AS(scene.importerStateAsArray(), |
|
Containers::arrayView<const void*>({&a, nullptr, &b}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void SceneDataTest::importerStateIntoArray() { |
|
auto&& data = IntoArrayOffsetData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
/* Both AsArray() and Into() share a common helper. The AsArray() test |
|
above verified handling of various data types and this checks the |
|
offset/size parameters of the Into() variant. */ |
|
|
|
int a, b; |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
const void* importerState; |
|
} fields[]{ |
|
{1, &a}, |
|
{0, nullptr}, |
|
{4, &b} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
/* To verify it isn't just picking the first ever field */ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::ImporterState, |
|
view.slice(&Field::object), |
|
view.slice(&Field::importerState)}, |
|
}}; |
|
|
|
/* The offset-less overload should give back all data */ |
|
{ |
|
const void* out[3]; |
|
scene.importerStateInto(out); |
|
CORRADE_COMPARE_AS(Containers::stridedArrayView(out), |
|
view.slice(&Field::importerState), |
|
TestSuite::Compare::Container); |
|
|
|
/* The offset variant only a subset */ |
|
} { |
|
Containers::Array<const void*> out{data.size}; |
|
CORRADE_COMPARE(scene.importerStateInto(data.offset, out), data.expectedSize); |
|
CORRADE_COMPARE_AS(out.prefix(data.expectedSize), |
|
view.slice(&Field::importerState) |
|
.slice(data.offset, data.offset + data.expectedSize), |
|
TestSuite::Compare::Container); |
|
} |
|
} |
|
|
|
void SceneDataTest::importerStateIntoArrayInvalidSizeOrOffset() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
const void* importerState; |
|
} fields[3]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
SceneFieldData{SceneField::ImporterState, view.slice(&Field::object), view.slice(&Field::importerState)} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
const void* destination[2]; |
|
scene.importerStateInto(destination); |
|
scene.importerStateInto(4, destination); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::importerStateInto(): expected a view with 3 elements but got 2\n" |
|
"Trade::SceneData::importerStateInto(): offset 4 out of bounds for a field of size 3\n"); |
|
} |
|
|
|
void SceneDataTest::mutableAccessNotAllowed() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
const struct Field { |
|
UnsignedInt object; |
|
UnsignedShort foobar; |
|
UnsignedShort mesh; |
|
} fields[2]{}; |
|
|
|
Containers::StridedArrayView1D<const Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, {}, fields, { |
|
SceneFieldData{sceneFieldCustom(35), |
|
view.slice(&Field::object), |
|
view.slice(&Field::foobar)}, |
|
SceneFieldData{SceneField::Mesh, |
|
view.slice(&Field::object), |
|
view.slice(&Field::mesh)}, |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.mutableData(); |
|
scene.mutableObjects(0); |
|
scene.mutableObjects<UnsignedInt>(0); |
|
scene.mutableObjects(SceneField::Mesh); |
|
scene.mutableObjects<UnsignedInt>(SceneField::Mesh); |
|
scene.mutableField(0); |
|
scene.mutableField<UnsignedInt>(0); |
|
scene.mutableField<UnsignedInt[]>(1); |
|
scene.mutableField(SceneField::Mesh); |
|
scene.mutableField<UnsignedInt>(SceneField::Mesh); |
|
scene.mutableField<UnsignedInt[]>(sceneFieldCustom(35)); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::mutableData(): data not mutable\n" |
|
"Trade::SceneData::mutableObjects(): data not mutable\n" |
|
"Trade::SceneData::mutableObjects(): data not mutable\n" |
|
"Trade::SceneData::mutableObjects(): data not mutable\n" |
|
"Trade::SceneData::mutableObjects(): data not mutable\n" |
|
"Trade::SceneData::mutableField(): data not mutable\n" |
|
"Trade::SceneData::mutableField(): data not mutable\n" |
|
"Trade::SceneData::mutableField(): data not mutable\n" |
|
"Trade::SceneData::mutableField(): data not mutable\n" |
|
"Trade::SceneData::mutableField(): data not mutable\n" |
|
"Trade::SceneData::mutableField(): data not mutable\n"); |
|
} |
|
|
|
void SceneDataTest::objectsNotFound() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedShort foobar; |
|
UnsignedShort mesh; |
|
} fields[2]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, DataFlag::Mutable, fields, { |
|
SceneFieldData{sceneFieldCustom(35), view.slice(&Field::object), view.slice(&Field::foobar)}, |
|
SceneFieldData{SceneField::Mesh, view.slice(&Field::object), view.slice(&Field::mesh)}, |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.objects(2); |
|
scene.objects<UnsignedInt>(2); |
|
scene.mutableObjects(2); |
|
scene.mutableObjects<UnsignedInt>(2); |
|
scene.objects(sceneFieldCustom(666)); |
|
scene.objects<UnsignedInt>(sceneFieldCustom(666)); |
|
scene.mutableObjects(sceneFieldCustom(666)); |
|
scene.mutableObjects<UnsignedInt>(sceneFieldCustom(666)); |
|
|
|
scene.objectsAsArray(2); |
|
scene.objectsAsArray(sceneFieldCustom(666)); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::objects(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::objects(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::mutableObjects(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::mutableObjects(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::objects(): field Trade::SceneField::Custom(666) not found\n" |
|
"Trade::SceneData::objects(): field Trade::SceneField::Custom(666) not found\n" |
|
"Trade::SceneData::mutableObjects(): field Trade::SceneField::Custom(666) not found\n" |
|
"Trade::SceneData::mutableObjects(): field Trade::SceneField::Custom(666) not found\n" |
|
|
|
"Trade::SceneData::objectsInto(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::objectsInto(): field Trade::SceneField::Custom(666) not found\n"); |
|
} |
|
|
|
void SceneDataTest::objectsWrongType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedShort object; |
|
UnsignedShort foobar; |
|
UnsignedInt mesh; |
|
} fields[2]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedShort, 5, DataFlag::Mutable, fields, { |
|
SceneFieldData{sceneFieldCustom(35), view.slice(&Field::object), view.slice(&Field::foobar)}, |
|
SceneFieldData{SceneField::Mesh, view.slice(&Field::object), view.slice(&Field::mesh)}, |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.objects<UnsignedByte>(1); |
|
scene.mutableObjects<UnsignedByte>(1); |
|
scene.objects<UnsignedByte>(SceneField::Mesh); |
|
scene.mutableObjects<UnsignedByte>(SceneField::Mesh); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::objects(): objects are Trade::SceneObjectType::UnsignedShort but requested Trade::SceneObjectType::UnsignedByte\n" |
|
"Trade::SceneData::mutableObjects(): objects are Trade::SceneObjectType::UnsignedShort but requested Trade::SceneObjectType::UnsignedByte\n" |
|
"Trade::SceneData::objects(): objects are Trade::SceneObjectType::UnsignedShort but requested Trade::SceneObjectType::UnsignedByte\n" |
|
"Trade::SceneData::mutableObjects(): objects are Trade::SceneObjectType::UnsignedShort but requested Trade::SceneObjectType::UnsignedByte\n"); |
|
} |
|
|
|
void SceneDataTest::fieldNotFound() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt foo, bar; |
|
} fields[2]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, DataFlag::Mutable, fields, { |
|
SceneFieldData{sceneFieldCustom(34), view.slice(&Field::object), view.slice(&Field::foo)}, |
|
SceneFieldData{sceneFieldCustom(35), view.slice(&Field::object), view.slice(&Field::bar)}, |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.fieldData(2); |
|
scene.fieldName(2); |
|
scene.fieldType(2); |
|
scene.fieldSize(2); |
|
scene.fieldArraySize(2); |
|
scene.field(2); |
|
scene.field<UnsignedInt>(2); |
|
scene.field<UnsignedInt[]>(2); |
|
scene.mutableField(2); |
|
scene.mutableField<UnsignedInt>(2); |
|
scene.mutableField<UnsignedInt[]>(2); |
|
|
|
scene.fieldId(sceneFieldCustom(666)); |
|
scene.fieldType(sceneFieldCustom(666)); |
|
scene.fieldSize(sceneFieldCustom(666)); |
|
scene.fieldArraySize(sceneFieldCustom(666)); |
|
scene.field(sceneFieldCustom(666)); |
|
scene.field<UnsignedInt>(sceneFieldCustom(666)); |
|
scene.field<UnsignedInt[]>(sceneFieldCustom(666)); |
|
scene.mutableField(sceneFieldCustom(666)); |
|
scene.mutableField<UnsignedInt>(sceneFieldCustom(666)); |
|
scene.mutableField<UnsignedInt[]>(sceneFieldCustom(666)); |
|
|
|
scene.parentsAsArray(); |
|
scene.parentsInto(nullptr); |
|
scene.parentsInto(0, nullptr); |
|
scene.transformations2DAsArray(); |
|
scene.transformations2DInto(nullptr); |
|
scene.transformations2DInto(0, nullptr); |
|
scene.translationsRotationsScalings2DAsArray(); |
|
scene.translationsRotationsScalings2DInto(nullptr, nullptr, nullptr); |
|
scene.translationsRotationsScalings2DInto(0, nullptr, nullptr, nullptr); |
|
scene.transformations3DAsArray(); |
|
scene.transformations3DInto(nullptr); |
|
scene.transformations3DInto(0, nullptr); |
|
scene.translationsRotationsScalings3DAsArray(); |
|
scene.translationsRotationsScalings3DInto(nullptr, nullptr, nullptr); |
|
scene.translationsRotationsScalings3DInto(0, nullptr, nullptr, nullptr); |
|
scene.meshesMaterialsAsArray(); |
|
scene.meshesMaterialsInto(nullptr, nullptr); |
|
scene.meshesMaterialsInto(0, nullptr, nullptr); |
|
scene.lightsAsArray(); |
|
scene.lightsInto(nullptr); |
|
scene.lightsInto(0, nullptr); |
|
scene.camerasAsArray(); |
|
scene.camerasInto(nullptr); |
|
scene.camerasInto(0, nullptr); |
|
scene.skinsAsArray(); |
|
scene.skinsInto(nullptr); |
|
scene.skinsInto(0, nullptr); |
|
scene.importerStateAsArray(); |
|
scene.importerStateInto(nullptr); |
|
scene.importerStateInto(0, nullptr); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::fieldData(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::fieldName(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::fieldType(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::fieldSize(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::fieldArraySize(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::field(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::field(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::field(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::mutableField(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::mutableField(): index 2 out of range for 2 fields\n" |
|
"Trade::SceneData::mutableField(): index 2 out of range for 2 fields\n" |
|
|
|
"Trade::SceneData::fieldId(): field Trade::SceneField::Custom(666) not found\n" |
|
"Trade::SceneData::fieldType(): field Trade::SceneField::Custom(666) not found\n" |
|
"Trade::SceneData::fieldSize(): field Trade::SceneField::Custom(666) not found\n" |
|
"Trade::SceneData::fieldArraySize(): field Trade::SceneField::Custom(666) not found\n" |
|
"Trade::SceneData::field(): field Trade::SceneField::Custom(666) not found\n" |
|
"Trade::SceneData::field(): field Trade::SceneField::Custom(666) not found\n" |
|
"Trade::SceneData::field(): field Trade::SceneField::Custom(666) not found\n" |
|
"Trade::SceneData::mutableField(): field Trade::SceneField::Custom(666) not found\n" |
|
"Trade::SceneData::mutableField(): field Trade::SceneField::Custom(666) not found\n" |
|
"Trade::SceneData::mutableField(): field Trade::SceneField::Custom(666) not found\n" |
|
|
|
/* AsArray() and Into() each share a common helper but have different |
|
top-level code paths. They however have the same assertion messages |
|
to save binary size a bit. */ |
|
"Trade::SceneData::parentsInto(): field not found\n" |
|
"Trade::SceneData::parentsInto(): field not found\n" |
|
"Trade::SceneData::parentsInto(): field not found\n" |
|
"Trade::SceneData::transformations2DInto(): no transformation-related field found\n" |
|
"Trade::SceneData::transformations2DInto(): no transformation-related field found\n" |
|
"Trade::SceneData::transformations2DInto(): no transformation-related field found\n" |
|
"Trade::SceneData::translationsRotationsScalings2DInto(): no transformation-related field found\n" |
|
"Trade::SceneData::translationsRotationsScalings2DInto(): no transformation-related field found\n" |
|
"Trade::SceneData::translationsRotationsScalings2DInto(): no transformation-related field found\n" |
|
"Trade::SceneData::transformations3DInto(): no transformation-related field found\n" |
|
"Trade::SceneData::transformations3DInto(): no transformation-related field found\n" |
|
"Trade::SceneData::transformations3DInto(): no transformation-related field found\n" |
|
"Trade::SceneData::translationsRotationsScalings3DInto(): no transformation-related field found\n" |
|
"Trade::SceneData::translationsRotationsScalings3DInto(): no transformation-related field found\n" |
|
"Trade::SceneData::translationsRotationsScalings3DInto(): no transformation-related field found\n" |
|
"Trade::SceneData::meshesMaterialsInto(): field Trade::SceneField::Mesh not found\n" |
|
"Trade::SceneData::meshesMaterialsInto(): field Trade::SceneField::Mesh not found\n" |
|
"Trade::SceneData::meshesMaterialsInto(): field Trade::SceneField::Mesh not found\n" |
|
"Trade::SceneData::lightsInto(): field not found\n" |
|
"Trade::SceneData::lightsInto(): field not found\n" |
|
"Trade::SceneData::lightsInto(): field not found\n" |
|
"Trade::SceneData::camerasInto(): field not found\n" |
|
"Trade::SceneData::camerasInto(): field not found\n" |
|
"Trade::SceneData::camerasInto(): field not found\n" |
|
"Trade::SceneData::skinsInto(): field not found\n" |
|
"Trade::SceneData::skinsInto(): field not found\n" |
|
"Trade::SceneData::skinsInto(): field not found\n" |
|
"Trade::SceneData::importerStateInto(): field not found\n" |
|
"Trade::SceneData::importerStateInto(): field not found\n" |
|
"Trade::SceneData::importerStateInto(): field not found\n"); |
|
} |
|
|
|
void SceneDataTest::fieldWrongType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedShort foobar; |
|
UnsignedShort mesh; |
|
} fields[2]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, DataFlag::Mutable, fields, { |
|
SceneFieldData{sceneFieldCustom(35), view.slice(&Field::object), view.slice(&Field::foobar)}, |
|
SceneFieldData{SceneField::Mesh, view.slice(&Field::object), view.slice(&Field::mesh)}, |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.field<UnsignedByte>(1); |
|
scene.field<UnsignedByte[]>(1); |
|
scene.mutableField<UnsignedByte>(1); |
|
scene.mutableField<UnsignedByte[]>(1); |
|
scene.field<UnsignedByte>(SceneField::Mesh); |
|
scene.field<UnsignedByte[]>(SceneField::Mesh); |
|
scene.mutableField<UnsignedByte>(SceneField::Mesh); |
|
scene.mutableField<UnsignedByte[]>(SceneField::Mesh); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::field(): Trade::SceneField::Mesh is Trade::SceneFieldType::UnsignedShort but requested a type equivalent to Trade::SceneFieldType::UnsignedByte\n" |
|
"Trade::SceneData::field(): Trade::SceneField::Mesh is Trade::SceneFieldType::UnsignedShort but requested a type equivalent to Trade::SceneFieldType::UnsignedByte\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Mesh is Trade::SceneFieldType::UnsignedShort but requested a type equivalent to Trade::SceneFieldType::UnsignedByte\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Mesh is Trade::SceneFieldType::UnsignedShort but requested a type equivalent to Trade::SceneFieldType::UnsignedByte\n" |
|
"Trade::SceneData::field(): Trade::SceneField::Mesh is Trade::SceneFieldType::UnsignedShort but requested a type equivalent to Trade::SceneFieldType::UnsignedByte\n" |
|
"Trade::SceneData::field(): Trade::SceneField::Mesh is Trade::SceneFieldType::UnsignedShort but requested a type equivalent to Trade::SceneFieldType::UnsignedByte\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Mesh is Trade::SceneFieldType::UnsignedShort but requested a type equivalent to Trade::SceneFieldType::UnsignedByte\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Mesh is Trade::SceneFieldType::UnsignedShort but requested a type equivalent to Trade::SceneFieldType::UnsignedByte\n"); |
|
} |
|
|
|
void SceneDataTest::fieldWrongPointerType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Thing { |
|
UnsignedInt object; |
|
Int* foobar; |
|
const Int* importerState; |
|
} things[2]; |
|
Containers::StridedArrayView1D<Thing> view = things; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, DataFlag::Mutable, things, { |
|
SceneFieldData{sceneFieldCustom(35), view.slice(&Thing::object), Containers::arrayCast<2, Int*>(view.slice(&Thing::foobar))}, |
|
SceneFieldData{SceneField::ImporterState, view.slice(&Thing::object), view.slice(&Thing::importerState)}, |
|
}}; |
|
|
|
/* These are fine (type is not checked) */ |
|
scene.field<Float*[]>(0); |
|
scene.field<const Float*>(1); |
|
scene.mutableField<Float*[]>(0); |
|
scene.mutableField<const Float*>(1); |
|
scene.field<Float*[]>(sceneFieldCustom(35)); |
|
scene.field<const Float*>(SceneField::ImporterState); |
|
scene.mutableField<Float*[]>(sceneFieldCustom(35)); |
|
scene.mutableField<const Float*>(SceneField::ImporterState); |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.field<Int>(0); |
|
scene.field<const Int*>(0); |
|
scene.field<const Int*[]>(0); |
|
scene.field<Int*>(1); |
|
scene.field<Int*[]>(1); |
|
scene.mutableField<Int>(0); |
|
scene.mutableField<const Int*>(0); |
|
scene.mutableField<const Int*[]>(0); |
|
scene.mutableField<Int*>(1); |
|
scene.mutableField<Int*[]>(1); |
|
scene.field<Int>(sceneFieldCustom(35)); |
|
scene.field<const Int*>(sceneFieldCustom(35)); |
|
scene.field<const Int*[]>(sceneFieldCustom(35)); |
|
scene.field<Int*>(SceneField::ImporterState); |
|
scene.field<Int*>(SceneField::ImporterState); |
|
scene.mutableField<Int>(sceneFieldCustom(35)); |
|
scene.mutableField<const Int*>(sceneFieldCustom(35)); |
|
scene.mutableField<const Int*[]>(sceneFieldCustom(35)); |
|
scene.mutableField<Int*>(SceneField::ImporterState); |
|
scene.mutableField<Int*[]>(SceneField::ImporterState); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::field(): Trade::SceneField::Custom(35) is Trade::SceneFieldType::MutablePointer but requested a type equivalent to Trade::SceneFieldType::Int\n" |
|
"Trade::SceneData::field(): Trade::SceneField::Custom(35) is Trade::SceneFieldType::MutablePointer but requested a type equivalent to Trade::SceneFieldType::Pointer\n" |
|
"Trade::SceneData::field(): Trade::SceneField::Custom(35) is Trade::SceneFieldType::MutablePointer but requested a type equivalent to Trade::SceneFieldType::Pointer\n" |
|
"Trade::SceneData::field(): Trade::SceneField::ImporterState is Trade::SceneFieldType::Pointer but requested a type equivalent to Trade::SceneFieldType::MutablePointer\n" |
|
"Trade::SceneData::field(): Trade::SceneField::ImporterState is Trade::SceneFieldType::Pointer but requested a type equivalent to Trade::SceneFieldType::MutablePointer\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Custom(35) is Trade::SceneFieldType::MutablePointer but requested a type equivalent to Trade::SceneFieldType::Int\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Custom(35) is Trade::SceneFieldType::MutablePointer but requested a type equivalent to Trade::SceneFieldType::Pointer\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Custom(35) is Trade::SceneFieldType::MutablePointer but requested a type equivalent to Trade::SceneFieldType::Pointer\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::ImporterState is Trade::SceneFieldType::Pointer but requested a type equivalent to Trade::SceneFieldType::MutablePointer\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::ImporterState is Trade::SceneFieldType::Pointer but requested a type equivalent to Trade::SceneFieldType::MutablePointer\n" |
|
"Trade::SceneData::field(): Trade::SceneField::Custom(35) is Trade::SceneFieldType::MutablePointer but requested a type equivalent to Trade::SceneFieldType::Int\n" |
|
"Trade::SceneData::field(): Trade::SceneField::Custom(35) is Trade::SceneFieldType::MutablePointer but requested a type equivalent to Trade::SceneFieldType::Pointer\n" |
|
"Trade::SceneData::field(): Trade::SceneField::Custom(35) is Trade::SceneFieldType::MutablePointer but requested a type equivalent to Trade::SceneFieldType::Pointer\n" |
|
"Trade::SceneData::field(): Trade::SceneField::ImporterState is Trade::SceneFieldType::Pointer but requested a type equivalent to Trade::SceneFieldType::MutablePointer\n" |
|
"Trade::SceneData::field(): Trade::SceneField::ImporterState is Trade::SceneFieldType::Pointer but requested a type equivalent to Trade::SceneFieldType::MutablePointer\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Custom(35) is Trade::SceneFieldType::MutablePointer but requested a type equivalent to Trade::SceneFieldType::Int\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Custom(35) is Trade::SceneFieldType::MutablePointer but requested a type equivalent to Trade::SceneFieldType::Pointer\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Custom(35) is Trade::SceneFieldType::MutablePointer but requested a type equivalent to Trade::SceneFieldType::Pointer\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::ImporterState is Trade::SceneFieldType::Pointer but requested a type equivalent to Trade::SceneFieldType::MutablePointer\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::ImporterState is Trade::SceneFieldType::Pointer but requested a type equivalent to Trade::SceneFieldType::MutablePointer\n"); |
|
} |
|
|
|
void SceneDataTest::fieldWrongArrayAccess() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt mesh; |
|
UnsignedInt foobar; |
|
} fields[2]{}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 5, DataFlag::Mutable, fields, { |
|
SceneFieldData{SceneField::Mesh, view.slice(&Field::object), view.slice(&Field::mesh)}, |
|
SceneFieldData{sceneFieldCustom(35), view.slice(&Field::object), Containers::arrayCast<2, UnsignedInt>(view.slice(&Field::foobar))}, |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.field<UnsignedInt[]>(0); |
|
scene.field<UnsignedInt>(1); |
|
scene.mutableField<UnsignedInt[]>(0); |
|
scene.mutableField<UnsignedInt>(1); |
|
scene.field<UnsignedInt[]>(SceneField::Mesh); |
|
scene.field<UnsignedInt>(sceneFieldCustom(35)); |
|
scene.mutableField<UnsignedInt[]>(SceneField::Mesh); |
|
scene.mutableField<UnsignedInt>(sceneFieldCustom(35)); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::field(): Trade::SceneField::Mesh is not an array field, can't use T[] to access it\n" |
|
"Trade::SceneData::field(): Trade::SceneField::Custom(35) is an array field, use T[] to access it\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Mesh is not an array field, can't use T[] to access it\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Custom(35) is an array field, use T[] to access it\n" |
|
"Trade::SceneData::field(): Trade::SceneField::Mesh is not an array field, can't use T[] to access it\n" |
|
"Trade::SceneData::field(): Trade::SceneField::Custom(35) is an array field, use T[] to access it\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Mesh is not an array field, can't use T[] to access it\n" |
|
"Trade::SceneData::mutableField(): Trade::SceneField::Custom(35) is an array field, use T[] to access it\n"); |
|
} |
|
|
|
template<class T> void SceneDataTest::parentFor() { |
|
setTestCaseTemplateName(NameTraits<T>::name()); |
|
|
|
struct Field { |
|
T object; |
|
Int parent; |
|
} fields[]{ |
|
{3, -1}, |
|
{4, 0}, |
|
{2, 1}, |
|
{4, 2} /* duplicate, ignored */ |
|
}; |
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{Implementation::sceneObjectTypeFor<T>(), 7, {}, fields, { |
|
SceneFieldData{SceneField::Parent, view.slice(&Field::object), view.slice(&Field::parent)} |
|
}}; |
|
|
|
CORRADE_COMPARE(scene.parentFor(2), 4); |
|
CORRADE_COMPARE(scene.parentFor(3), -1); |
|
|
|
/* Duplicate entries -- only the first one gets used, it doesn't traverse |
|
further */ |
|
CORRADE_COMPARE(scene.parentFor(4), 3); |
|
|
|
/* Object that's not in the array at all */ |
|
CORRADE_COMPARE(scene.parentFor(1), Containers::NullOpt); |
|
} |
|
|
|
void SceneDataTest::childrenFor() { |
|
struct Field { |
|
UnsignedInt object; |
|
Int parent; |
|
} fields[]{ |
|
{4, -1}, |
|
{3, 0}, |
|
{2, 1}, |
|
{1, 0}, |
|
{5, 0}, |
|
{0, -1}, |
|
}; |
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 7, {}, fields, { |
|
SceneFieldData{SceneField::Parent, view.slice(&Field::object), view.slice(&Field::parent)} |
|
}}; |
|
|
|
/* Just one child */ |
|
CORRADE_COMPARE_AS(scene.childrenFor(3), |
|
Containers::arrayView<UnsignedInt>({2}), |
|
TestSuite::Compare::Container); |
|
|
|
/* More */ |
|
CORRADE_COMPARE_AS(scene.childrenFor(-1), |
|
Containers::arrayView<UnsignedInt>({4, 0}), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.childrenFor(4), |
|
Containers::arrayView<UnsignedInt>({3, 1, 5}), |
|
TestSuite::Compare::Container); |
|
|
|
/* Object that is present in the parent array but has no children */ |
|
CORRADE_COMPARE_AS(scene.childrenFor(5), |
|
Containers::arrayView<UnsignedInt>({}), |
|
TestSuite::Compare::Container); |
|
|
|
/* Object that is not in the parent array at all */ |
|
CORRADE_COMPARE_AS(scene.childrenFor(6), |
|
Containers::arrayView<UnsignedInt>({}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void SceneDataTest::transformation2DFor() { |
|
const struct Field { |
|
UnsignedInt object; |
|
Matrix3 transformation; |
|
} fields[] { |
|
{1, Matrix3::translation({3.0f, 2.0f})*Matrix3::scaling({1.5f, 2.0f})}, |
|
{0, Matrix3::rotation(35.0_degf)}, |
|
{4, Matrix3::translation({3.0f, 2.0f})*Matrix3::rotation(35.0_degf)}, |
|
{1, Matrix3::translation({1.0f, 2.0f})} /* duplicate, ignored */ |
|
}; |
|
Containers::StridedArrayView1D<const Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 7, {}, fields, { |
|
SceneFieldData{SceneField::Transformation, view.slice(&Field::object), view.slice(&Field::transformation)} |
|
}}; |
|
|
|
CORRADE_COMPARE(scene.transformation2DFor(4), |
|
Matrix3::translation({3.0f, 2.0f})*Matrix3::rotation(35.0_degf)); |
|
CORRADE_COMPARE(scene.transformation2DFor(0), |
|
Matrix3::Matrix3::Matrix3::Matrix3::rotation(35.0_degf)); |
|
|
|
/* Duplicate entries -- only the first one gets used, it doesn't traverse |
|
further */ |
|
CORRADE_COMPARE(scene.transformation2DFor(1), |
|
Matrix3::translation({3.0f, 2.0f})*Matrix3::scaling({1.5f, 2.0f})); |
|
|
|
/* Object that's not in the array at all */ |
|
CORRADE_COMPARE(scene.transformation2DFor(2), |
|
Containers::NullOpt); |
|
} |
|
|
|
void SceneDataTest::transformation2DForTRS() { |
|
const struct Field { |
|
UnsignedInt object; |
|
Vector2 translation; |
|
Complex rotation; |
|
Vector2 scaling; |
|
} fields[] { |
|
{1, {3.0f, 2.0f}, {}, {1.5f, 2.0f}}, |
|
{0, {}, Complex::rotation(35.0_degf), {1.0f, 1.0f}}, |
|
{4, {3.0f, 2.0f}, Complex::rotation(35.0_degf), {1.0f, 1.0f}}, |
|
{1, {1.0f, 2.0f}, {}, {1.0f, 1.0f}} /* duplicate, ignored */ |
|
}; |
|
Containers::StridedArrayView1D<const Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 7, {}, fields, { |
|
SceneFieldData{SceneField::Translation, view.slice(&Field::object), view.slice(&Field::translation)}, |
|
SceneFieldData{SceneField::Rotation, view.slice(&Field::object), view.slice(&Field::rotation)}, |
|
SceneFieldData{SceneField::Scaling, view.slice(&Field::object), view.slice(&Field::scaling)} |
|
}}; |
|
|
|
CORRADE_COMPARE(scene.transformation2DFor(4), |
|
Matrix3::translation({3.0f, 2.0f})*Matrix3::rotation(35.0_degf)); |
|
CORRADE_COMPARE(scene.translationRotationScaling2DFor(4), |
|
Containers::triple(Vector2{3.0f, 2.0f}, Complex::rotation(35.0_degf), Vector2{1.0f})); |
|
CORRADE_COMPARE(scene.transformation2DFor(0), |
|
Matrix3::rotation(35.0_degf)); |
|
CORRADE_COMPARE(scene.translationRotationScaling2DFor(0), |
|
Containers::triple(Vector2{}, Complex::rotation(35.0_degf), Vector2{1.0f})); |
|
|
|
/* Duplicate entries -- only the first one gets used, it doesn't traverse |
|
further */ |
|
CORRADE_COMPARE(scene.transformation2DFor(1), |
|
Matrix3::translation({3.0f, 2.0f})*Matrix3::scaling({1.5f, 2.0f})); |
|
CORRADE_COMPARE(scene.translationRotationScaling2DFor(1), |
|
Containers::triple(Vector2{3.0f, 2.0f}, Complex{}, Vector2{1.5f, 2.0f})); |
|
|
|
/* Object that's not in the array at all */ |
|
CORRADE_COMPARE(scene.transformation2DFor(2), |
|
Containers::NullOpt); |
|
CORRADE_COMPARE(scene.translationRotationScaling2DFor(2), |
|
Containers::NullOpt); |
|
} |
|
|
|
void SceneDataTest::transformation2DForBut3DType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 1, nullptr, { |
|
SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Vector3, nullptr} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.transformation2DFor(0); |
|
scene.translationRotationScaling2DFor(0); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::transformation2DFor(): scene has a 3D transformation type\n" |
|
"Trade::SceneData::translationRotationScaling2DFor(): scene has a 3D transformation type\n"); |
|
} |
|
|
|
void SceneDataTest::transformation3DFor() { |
|
const struct Field { |
|
UnsignedInt object; |
|
Matrix4 transformation; |
|
} fields[] { |
|
{1, Matrix4::translation({3.0f, 2.0f, 1.0f})*Matrix4::scaling({1.5f, 2.0f, 4.5f})}, |
|
{0, Matrix4::rotationX(35.0_degf)}, |
|
{4, Matrix4::translation({3.0f, 2.0f, 1.0f})*Matrix4::rotationX(35.0_degf)}, |
|
{1, Matrix4::translation({1.0f, 2.0f, 3.0f})} /* duplicate, ignored */ |
|
}; |
|
Containers::StridedArrayView1D<const Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 7, {}, fields, { |
|
SceneFieldData{SceneField::Transformation, view.slice(&Field::object), view.slice(&Field::transformation)} |
|
}}; |
|
|
|
CORRADE_COMPARE(scene.transformation3DFor(4), |
|
Matrix4::translation({3.0f, 2.0f, 1.0f})*Matrix4::rotationX(35.0_degf)); |
|
CORRADE_COMPARE(scene.transformation3DFor(0), |
|
Matrix4::rotationX(35.0_degf)); |
|
|
|
/* Duplicate entries -- only the first one gets used, it doesn't traverse |
|
further */ |
|
CORRADE_COMPARE(scene.transformation3DFor(1), |
|
Matrix4::translation({3.0f, 2.0f, 1.0f})*Matrix4::scaling({1.5f, 2.0f, 4.5f})); |
|
|
|
/* Object that's not in the array at all */ |
|
CORRADE_COMPARE(scene.transformation3DFor(2), |
|
Containers::NullOpt); |
|
} |
|
|
|
void SceneDataTest::transformation3DForTRS() { |
|
const struct Field { |
|
UnsignedInt object; |
|
Vector3 translation; |
|
Quaternion rotation; |
|
Vector3 scaling; |
|
} fields[] { |
|
{1, {3.0f, 2.0f, 1.0f}, {}, {1.5f, 2.0f, 4.5f}}, |
|
{0, {}, Quaternion::rotation(35.0_degf, Vector3::xAxis()), {1.0f, 1.0f, 1.0f}}, |
|
{4, {3.0f, 2.0f, 1.0f}, Quaternion::rotation(35.0_degf, Vector3::xAxis()), {1.0f, 1.0f, 1.0f}}, |
|
{1, {1.0f, 2.0f, 3.0f}, Quaternion{}, Vector3{1.0f}} /* duplicate, ignored */ |
|
}; |
|
Containers::StridedArrayView1D<const Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 7, {}, fields, { |
|
SceneFieldData{SceneField::Translation, view.slice(&Field::object), view.slice(&Field::translation)}, |
|
SceneFieldData{SceneField::Rotation, view.slice(&Field::object), view.slice(&Field::rotation)}, |
|
SceneFieldData{SceneField::Scaling, view.slice(&Field::object), view.slice(&Field::scaling)} |
|
}}; |
|
|
|
CORRADE_COMPARE(scene.transformation3DFor(4), |
|
Matrix4::translation({3.0f, 2.0f, 1.0f})*Matrix4::rotationX(35.0_degf)); |
|
CORRADE_COMPARE(scene.translationRotationScaling3DFor(4), |
|
Containers::triple(Vector3{3.0f, 2.0f, 1.0f}, Quaternion::rotation(35.0_degf, Vector3::xAxis()), Vector3{1.0f})); |
|
CORRADE_COMPARE(scene.transformation3DFor(0), |
|
Matrix4::rotationX(35.0_degf)); |
|
CORRADE_COMPARE(scene.translationRotationScaling3DFor(0), |
|
Containers::triple(Vector3{}, Quaternion::rotation(35.0_degf, Vector3::xAxis()), Vector3{1.0f})); |
|
|
|
/* Duplicate entries -- only the first one gets used, it doesn't traverse |
|
further */ |
|
CORRADE_COMPARE(scene.transformation3DFor(1), |
|
Matrix4::translation({3.0f, 2.0f, 1.0f})*Matrix4::scaling({1.5f, 2.0f, 4.5f})); |
|
CORRADE_COMPARE(scene.translationRotationScaling3DFor(1), |
|
Containers::triple(Vector3{3.0f, 2.0f, 1.0f}, Quaternion{}, Vector3{1.5f, 2.0f, 4.5f})); |
|
|
|
/* Object that's not in the array at all */ |
|
CORRADE_COMPARE(scene.transformation3DFor(2), |
|
Containers::NullOpt); |
|
CORRADE_COMPARE(scene.translationRotationScaling3DFor(2), |
|
Containers::NullOpt); |
|
} |
|
|
|
void SceneDataTest::transformation3DForBut2DType() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 1, nullptr, { |
|
SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Vector2, nullptr} |
|
}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.transformation3DFor(0); |
|
scene.translationRotationScaling3DFor(0); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::transformation3DFor(): scene has a 2D transformation type\n" |
|
"Trade::SceneData::translationRotationScaling3DFor(): scene has a 2D transformation type\n"); |
|
} |
|
|
|
void SceneDataTest::meshesMaterialsFor() { |
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt mesh; |
|
Int meshMaterial; |
|
} fields[]{ |
|
{4, 1, -1}, |
|
{1, 3, 0}, |
|
{2, 4, 1}, |
|
{2, 5, -1}, |
|
{2, 1, 0}, |
|
}; |
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 7, {}, fields, { |
|
SceneFieldData{SceneField::Mesh, view.slice(&Field::object), view.slice(&Field::mesh)}, |
|
SceneFieldData{SceneField::MeshMaterial, view.slice(&Field::object), view.slice(&Field::meshMaterial)} |
|
}}; |
|
|
|
/* Just one */ |
|
CORRADE_COMPARE_AS(scene.meshesMaterialsFor(1), |
|
(Containers::arrayView<Containers::Pair<UnsignedInt, Int>>({{3, 0}})), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.meshesMaterialsFor(4), |
|
(Containers::arrayView<Containers::Pair<UnsignedInt, Int>>({{1, -1}})), |
|
TestSuite::Compare::Container); |
|
|
|
/* More */ |
|
CORRADE_COMPARE_AS(scene.meshesMaterialsFor(2), |
|
(Containers::arrayView<Containers::Pair<UnsignedInt, Int>>({ |
|
{4, 1}, {5, -1}, {1, 0} |
|
})), TestSuite::Compare::Container); |
|
|
|
/* Object that is not in the array at all */ |
|
CORRADE_COMPARE_AS(scene.meshesMaterialsFor(6), |
|
(Containers::arrayView<Containers::Pair<UnsignedInt, Int>>({})), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void SceneDataTest::lightsFor() { |
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt light; |
|
} fields[]{ |
|
{4, 1}, |
|
{1, 3}, |
|
{2, 4}, |
|
{2, 5} |
|
}; |
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 7, {}, fields, { |
|
SceneFieldData{SceneField::Light, view.slice(&Field::object), view.slice(&Field::light)} |
|
}}; |
|
|
|
/* Just one */ |
|
CORRADE_COMPARE_AS(scene.lightsFor(1), |
|
(Containers::arrayView<UnsignedInt>({3})), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.lightsFor(4), |
|
(Containers::arrayView<UnsignedInt>({1})), |
|
TestSuite::Compare::Container); |
|
|
|
/* More */ |
|
CORRADE_COMPARE_AS(scene.lightsFor(2), |
|
(Containers::arrayView<UnsignedInt>({ |
|
4, 5 |
|
})), TestSuite::Compare::Container); |
|
|
|
/* Object that is not in the array at all */ |
|
CORRADE_COMPARE_AS(scene.lightsFor(6), |
|
(Containers::arrayView<UnsignedInt>({})), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void SceneDataTest::camerasFor() { |
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt camera; |
|
} fields[]{ |
|
{4, 1}, |
|
{1, 3}, |
|
{2, 4}, |
|
{2, 5} |
|
}; |
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 7, {}, fields, { |
|
SceneFieldData{SceneField::Camera, view.slice(&Field::object), view.slice(&Field::camera)} |
|
}}; |
|
|
|
/* Just one */ |
|
CORRADE_COMPARE_AS(scene.camerasFor(1), |
|
(Containers::arrayView<UnsignedInt>({3})), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.camerasFor(4), |
|
(Containers::arrayView<UnsignedInt>({1})), |
|
TestSuite::Compare::Container); |
|
|
|
/* More */ |
|
CORRADE_COMPARE_AS(scene.camerasFor(2), |
|
(Containers::arrayView<UnsignedInt>({ |
|
4, 5 |
|
})), TestSuite::Compare::Container); |
|
|
|
/* Object that is not in the array at all */ |
|
CORRADE_COMPARE_AS(scene.camerasFor(6), |
|
(Containers::arrayView<UnsignedInt>({})), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void SceneDataTest::skinsFor() { |
|
struct Field { |
|
UnsignedInt object; |
|
UnsignedInt skin; |
|
} fields[]{ |
|
{4, 1}, |
|
{1, 3}, |
|
{2, 4}, |
|
{2, 5} |
|
}; |
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 7, {}, fields, { |
|
/* To satisfy the requirement of having a transformation field to |
|
disambiguate the dimensionality */ |
|
SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Vector3, nullptr}, |
|
SceneFieldData{SceneField::Skin, view.slice(&Field::object), view.slice(&Field::skin)} |
|
}}; |
|
|
|
/* Just one */ |
|
CORRADE_COMPARE_AS(scene.skinsFor(1), |
|
(Containers::arrayView<UnsignedInt>({3})), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.skinsFor(4), |
|
(Containers::arrayView<UnsignedInt>({1})), |
|
TestSuite::Compare::Container); |
|
|
|
/* More */ |
|
CORRADE_COMPARE_AS(scene.skinsFor(2), |
|
(Containers::arrayView<UnsignedInt>({ |
|
4, 5 |
|
})), TestSuite::Compare::Container); |
|
|
|
/* Object that is not in the array at all */ |
|
CORRADE_COMPARE_AS(scene.skinsFor(6), |
|
(Containers::arrayView<UnsignedInt>({})), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void SceneDataTest::importerStateFor() { |
|
int a, b, c; |
|
|
|
struct Field { |
|
UnsignedInt object; |
|
const void* importerState; |
|
} fields[]{ |
|
{3, &a}, |
|
{4, &b}, |
|
{2, nullptr}, |
|
{4, &c} |
|
}; |
|
|
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 7, {}, fields, { |
|
SceneFieldData{SceneField::ImporterState, view.slice(&Field::object), view.slice(&Field::importerState)} |
|
}}; |
|
|
|
CORRADE_COMPARE(scene.importerStateFor(2), nullptr); |
|
CORRADE_COMPARE(scene.importerStateFor(3), &a); |
|
|
|
/* Duplicate entries -- only the first one gets used, it doesn't traverse |
|
further */ |
|
CORRADE_COMPARE(scene.importerStateFor(4), &b); |
|
|
|
/* Object that's not in the array at all */ |
|
CORRADE_COMPARE(scene.importerStateFor(1), Containers::NullOpt); |
|
} |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
void SceneDataTest::childrenDeprecated() { |
|
auto&& data = ChildrenDeprecatedData[testCaseInstanceId()]; |
|
setTestCaseDescription(data.name); |
|
|
|
struct Field { |
|
UnsignedByte object; |
|
Short parent; |
|
} fields[]{ |
|
{5, -1}, |
|
{2, 0}, |
|
{3, 0}, |
|
{0, -1}, |
|
{1, 2}, |
|
{4, -1} |
|
}; |
|
Containers::StridedArrayView1D<Field> view = fields; |
|
|
|
Containers::Array<SceneFieldData> fieldData; |
|
arrayAppend(fieldData, SceneFieldData{SceneField::Parent, view.slice(&Field::object), view.slice(&Field::parent)}); |
|
if(data.is2D) |
|
arrayAppend(fieldData, SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Vector2, nullptr}); |
|
if(data.is3D) |
|
arrayAppend(fieldData, SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Vector3, nullptr}); |
|
|
|
SceneData scene{SceneObjectType::UnsignedByte, 25, {}, fields, std::move(fieldData)}; |
|
CORRADE_IGNORE_DEPRECATED_PUSH |
|
CORRADE_COMPARE_AS(scene.children2D(), |
|
(data.is2D ? std::vector<UnsignedInt>{5, 0, 4} : std::vector<UnsignedInt>{}), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.children3D(), |
|
(data.is3D ? std::vector<UnsignedInt>{5, 0, 4} : std::vector<UnsignedInt>{}), |
|
TestSuite::Compare::Container); |
|
CORRADE_IGNORE_DEPRECATED_POP |
|
} |
|
#endif |
|
|
|
void SceneDataTest::fieldForFieldMissing() { |
|
SceneData scene{SceneObjectType::UnsignedInt, 7, nullptr, {}}; |
|
|
|
CORRADE_COMPARE(scene.parentFor(6), Containers::NullOpt); |
|
CORRADE_COMPARE_AS(scene.childrenFor(6), |
|
Containers::arrayView<UnsignedInt>({}), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE(scene.transformation2DFor(6), Containers::NullOpt); |
|
CORRADE_COMPARE(scene.translationRotationScaling2DFor(6), Containers::NullOpt); |
|
CORRADE_COMPARE(scene.transformation3DFor(6), Containers::NullOpt); |
|
CORRADE_COMPARE(scene.translationRotationScaling3DFor(6), Containers::NullOpt); |
|
CORRADE_COMPARE_AS(scene.meshesMaterialsFor(6), |
|
(Containers::arrayView<Containers::Pair<UnsignedInt, Int>>({})), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.lightsFor(6), |
|
Containers::arrayView<UnsignedInt>({}), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.camerasFor(6), |
|
Containers::arrayView<UnsignedInt>({}), |
|
TestSuite::Compare::Container); |
|
CORRADE_COMPARE_AS(scene.skinsFor(6), |
|
Containers::arrayView<UnsignedInt>({}), |
|
TestSuite::Compare::Container); |
|
} |
|
|
|
void SceneDataTest::fieldForInvalidObject() { |
|
#ifdef CORRADE_NO_ASSERT |
|
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); |
|
#endif |
|
|
|
SceneData scene{SceneObjectType::UnsignedInt, 7, nullptr, {}}; |
|
|
|
std::ostringstream out; |
|
Error redirectError{&out}; |
|
scene.parentFor(7); |
|
scene.childrenFor(-2); |
|
scene.childrenFor(7); |
|
scene.transformation2DFor(7); |
|
scene.translationRotationScaling2DFor(7); |
|
scene.transformation3DFor(7); |
|
scene.translationRotationScaling3DFor(7); |
|
scene.meshesMaterialsFor(7); |
|
scene.lightsFor(7); |
|
scene.camerasFor(7); |
|
scene.skinsFor(7); |
|
CORRADE_COMPARE(out.str(), |
|
"Trade::SceneData::parentFor(): object 7 out of bounds for 7 objects\n" |
|
"Trade::SceneData::childrenFor(): object -2 out of bounds for 7 objects\n" |
|
"Trade::SceneData::childrenFor(): object 7 out of bounds for 7 objects\n" |
|
"Trade::SceneData::transformation2DFor(): object 7 out of bounds for 7 objects\n" |
|
"Trade::SceneData::translationRotationScaling2DFor(): object 7 out of bounds for 7 objects\n" |
|
"Trade::SceneData::transformation3DFor(): object 7 out of bounds for 7 objects\n" |
|
"Trade::SceneData::translationRotationScaling3DFor(): object 7 out of bounds for 7 objects\n" |
|
"Trade::SceneData::meshesMaterialsFor(): object 7 out of bounds for 7 objects\n" |
|
"Trade::SceneData::lightsFor(): object 7 out of bounds for 7 objects\n" |
|
"Trade::SceneData::camerasFor(): object 7 out of bounds for 7 objects\n" |
|
"Trade::SceneData::skinsFor(): object 7 out of bounds for 7 objects\n"); |
|
} |
|
|
|
void SceneDataTest::releaseFieldData() { |
|
struct Field { |
|
UnsignedByte object; |
|
UnsignedInt mesh; |
|
}; |
|
|
|
Containers::Array<char> data{NoInit, 3*sizeof(Field)}; |
|
Containers::StridedArrayView1D<Field> view = Containers::arrayCast<Field>(data); |
|
|
|
auto fields = Containers::array({ |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Mesh, view.slice(&Field::object), view.slice(&Field::mesh)} |
|
}); |
|
SceneFieldData* originalFields = fields; |
|
|
|
SceneData scene{SceneObjectType::UnsignedByte, 50, std::move(data), std::move(fields)}; |
|
|
|
Containers::Array<SceneFieldData> released = scene.releaseFieldData(); |
|
CORRADE_COMPARE(released.data(), originalFields); |
|
CORRADE_COMPARE(released.size(), 2); |
|
|
|
/* Fields are all gone */ |
|
CORRADE_COMPARE(static_cast<const void*>(scene.fieldData()), nullptr); |
|
CORRADE_COMPARE(scene.fieldCount(), 0); |
|
|
|
/* Data stays untouched, object count and type as well, as it con't result |
|
in any dangling data access */ |
|
CORRADE_COMPARE(scene.data(), view.data()); |
|
CORRADE_COMPARE(scene.objectCount(), 50); |
|
CORRADE_COMPARE(scene.objectType(), SceneObjectType::UnsignedByte); |
|
} |
|
|
|
void SceneDataTest::releaseData() { |
|
struct Field { |
|
UnsignedByte object; |
|
UnsignedByte mesh; |
|
}; |
|
|
|
Containers::Array<char> data{NoInit, 3*sizeof(Field)}; |
|
Containers::StridedArrayView1D<Field> view = Containers::arrayCast<Field>(data); |
|
|
|
SceneData scene{SceneObjectType::UnsignedByte, 50, std::move(data), { |
|
SceneFieldData{SceneField::Parent, SceneObjectType::UnsignedByte, nullptr, SceneFieldType::Int, nullptr}, |
|
SceneFieldData{SceneField::Mesh, view.slice(&Field::object), view.slice(&Field::mesh)} |
|
}}; |
|
|
|
Containers::Array<char> released = scene.releaseData(); |
|
CORRADE_COMPARE(released.data(), view.data()); |
|
CORRADE_COMPARE(released.size(), 3*sizeof(Field)); |
|
|
|
/* Both fields and data are all gone */ |
|
CORRADE_COMPARE(static_cast<const void*>(scene.fieldData()), nullptr); |
|
CORRADE_COMPARE(scene.fieldCount(), 0); |
|
CORRADE_COMPARE(static_cast<const void*>(scene.data()), nullptr); |
|
|
|
/* Object count and type stays untouched, as it con't result in any |
|
dangling data access */ |
|
CORRADE_COMPARE(scene.objectCount(), 50); |
|
CORRADE_COMPARE(scene.objectType(), SceneObjectType::UnsignedByte); |
|
} |
|
|
|
}}}} |
|
|
|
CORRADE_TEST_MAIN(Magnum::Trade::Test::SceneDataTest)
|
|
|