Browse Source

Trade: introduce SceneData::is2D() and is3D().

This moves the transformation type consistency checks directly into the
constructor and makes the discovered dimension count available through a
getter. As a result, a lot of duplicate assertions (and
corresponding tests) could be removed while tightening the behavior --
before it was possible to have a 2D transformation matrix complemented
with a 3D rotation quaternion and all asserts would pass, yet the user
would be required to call transformations2DAsArray() *but*
translationsRotationsScalings3DAsArray().

Since scenes can exist without any transformation field, there's both
is2D() and is3D() and they both return false in that case.
pull/525/head
Vladimír Vondruš 5 years ago
parent
commit
c9ac4d6f82
  1. 270
      src/Magnum/Trade/SceneData.cpp
  2. 82
      src/Magnum/Trade/SceneData.h
  3. 440
      src/Magnum/Trade/Test/SceneDataTest.cpp

270
src/Magnum/Trade/SceneData.cpp

@ -363,7 +363,7 @@ Containers::Array<SceneFieldData> sceneFieldDataNonOwningArray(const Containers:
return Containers::Array<SceneFieldData>{const_cast<SceneFieldData*>(view.data()), view.size(), reinterpret_cast<void(*)(SceneFieldData*, std::size_t)>(Implementation::nonOwnedArrayDeleter)}; return Containers::Array<SceneFieldData>{const_cast<SceneFieldData*>(view.data()), view.size(), reinterpret_cast<void(*)(SceneFieldData*, std::size_t)>(Implementation::nonOwnedArrayDeleter)};
} }
SceneData::SceneData(const SceneObjectType objectType, const UnsignedLong objectCount, Containers::Array<char>&& data, Containers::Array<SceneFieldData>&& fields, const void* const importerState) noexcept: _dataFlags{DataFlag::Owned|DataFlag::Mutable}, _objectType{objectType}, _objectCount{objectCount}, _importerState{importerState}, _fields{std::move(fields)}, _data{std::move(data)} { SceneData::SceneData(const SceneObjectType objectType, const UnsignedLong objectCount, Containers::Array<char>&& data, Containers::Array<SceneFieldData>&& fields, const void* const importerState) noexcept: _dataFlags{DataFlag::Owned|DataFlag::Mutable}, _objectType{objectType}, _dimensions{}, _objectCount{objectCount}, _importerState{importerState}, _fields{std::move(fields)}, _data{std::move(data)} {
/* Check that object type is large enough */ /* Check that object type is large enough */
CORRADE_ASSERT( CORRADE_ASSERT(
(objectType == SceneObjectType::UnsignedByte && objectCount <= 0xffull) || (objectType == SceneObjectType::UnsignedByte && objectCount <= 0xffull) ||
@ -376,14 +376,19 @@ SceneData::SceneData(const SceneObjectType objectType, const UnsignedLong object
/* Check various assumptions about field data */ /* Check various assumptions about field data */
Math::BoolVector<12> fieldsPresent; /** @todo some constant for this */ Math::BoolVector<12> fieldsPresent; /** @todo some constant for this */
const UnsignedInt objectTypeSize = sceneObjectTypeSize(_objectType); const UnsignedInt objectTypeSize = sceneObjectTypeSize(_objectType);
#endif
UnsignedInt transformationField = ~UnsignedInt{};
UnsignedInt translationField = ~UnsignedInt{}; UnsignedInt translationField = ~UnsignedInt{};
UnsignedInt rotationField = ~UnsignedInt{}; UnsignedInt rotationField = ~UnsignedInt{};
UnsignedInt scalingField = ~UnsignedInt{}; UnsignedInt scalingField = ~UnsignedInt{};
#ifndef CORRADE_NO_ASSERT
UnsignedInt meshField = ~UnsignedInt{}; UnsignedInt meshField = ~UnsignedInt{};
UnsignedInt meshMaterialField = ~UnsignedInt{}; UnsignedInt meshMaterialField = ~UnsignedInt{};
#endif
for(std::size_t i = 0; i != _fields.size(); ++i) { for(std::size_t i = 0; i != _fields.size(); ++i) {
const SceneFieldData& field = _fields[i]; const SceneFieldData& field = _fields[i];
#ifndef CORRADE_NO_ASSERT
/* The object type has to be the same among all fields. Technically it /* The object type has to be the same among all fields. Technically it
wouldn't need to be, but if there's 60k objects then using a 8bit wouldn't need to be, but if there's 60k objects then using a 8bit
type for certain fields would mean only the first 256 objects can be type for certain fields would mean only the first 256 objects can be
@ -441,22 +446,30 @@ SceneData::SceneData(const SceneObjectType objectType, const UnsignedLong object
"Trade::SceneData: field data [" << Debug::nospace << fieldBegin << Debug::nospace << ":" << Debug::nospace << fieldEnd << Debug::nospace << "] of field" << i << "are not contained in passed data array [" << Debug::nospace << static_cast<const void*>(_data.begin()) << Debug::nospace << ":" << Debug::nospace << static_cast<const void*>(_data.end()) << Debug::nospace << "]", ); "Trade::SceneData: field data [" << Debug::nospace << fieldBegin << Debug::nospace << ":" << Debug::nospace << fieldEnd << Debug::nospace << "] of field" << i << "are not contained in passed data array [" << Debug::nospace << static_cast<const void*>(_data.begin()) << Debug::nospace << ":" << Debug::nospace << static_cast<const void*>(_data.end()) << Debug::nospace << "]", );
} }
} }
#endif
/* Remember TRS and mesh/material fields to check their object mapping /* Remember TRS and mesh/material fields to figure out whether the
consistency outside of the loop below */ scene is 2D or 3D and check their object mapping consistency outside
if(_fields[i]._name == SceneField::Translation) { of the loop below */
if(_fields[i]._name == SceneField::Transformation) {
transformationField = i;
} else if(_fields[i]._name == SceneField::Translation) {
translationField = i; translationField = i;
} else if(_fields[i]._name == SceneField::Rotation) { } else if(_fields[i]._name == SceneField::Rotation) {
rotationField = i; rotationField = i;
} else if(_fields[i]._name == SceneField::Scaling) { } else if(_fields[i]._name == SceneField::Scaling) {
scalingField = i; scalingField = i;
} else if(_fields[i]._name == SceneField::Mesh) { }
#ifndef CORRADE_NO_ASSERT
else if(_fields[i]._name == SceneField::Mesh) {
meshField = i; meshField = i;
} else if(_fields[i]._name == SceneField::MeshMaterial) { } else if(_fields[i]._name == SceneField::MeshMaterial) {
meshMaterialField = i; meshMaterialField = i;
} }
#endif
} }
#ifndef CORRADE_NO_ASSERT
/* Check that certain fields share the same object mapping. Printing as if /* Check that certain fields share the same object mapping. Printing as if
all would be pointers (and not offset-only), it's not worth the extra all would be pointers (and not offset-only), it's not worth the extra
effort just for an assert message. Also, compared to above, where effort just for an assert message. Also, compared to above, where
@ -486,6 +499,67 @@ SceneData::SceneData(const SceneObjectType objectType, const UnsignedLong object
if(meshField != ~UnsignedInt{} && meshMaterialField != ~UnsignedInt{}) if(meshField != ~UnsignedInt{} && meshMaterialField != ~UnsignedInt{})
checkFieldObjectDataMatch(_fields[meshField], _fields[meshMaterialField]); checkFieldObjectDataMatch(_fields[meshField], _fields[meshMaterialField]);
#endif #endif
/* Decide about dimensionality based on transformation type, if present */
if(transformationField != ~UnsignedInt{}) {
const SceneFieldType fieldType = _fields[transformationField]._fieldType;
if(fieldType == SceneFieldType::Matrix3x3 ||
fieldType == SceneFieldType::Matrix3x3d ||
fieldType == SceneFieldType::DualComplex ||
fieldType == SceneFieldType::DualComplexd)
_dimensions = 2;
else if(fieldType == SceneFieldType::Matrix4x4 ||
fieldType == SceneFieldType::Matrix4x4d ||
fieldType == SceneFieldType::DualQuaternion ||
fieldType == SceneFieldType::DualQuaterniond)
_dimensions = 3;
else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
/* Use TRS fields to decide about dimensionality, if the transformation
field is not present. If it is, verify that they match it. */
if(translationField != ~UnsignedInt{}) {
const SceneFieldType fieldType = _fields[translationField]._fieldType;
if(fieldType == SceneFieldType::Vector2 ||
fieldType == SceneFieldType::Vector2d) {
CORRADE_ASSERT(!_dimensions || _dimensions == 2,
"Trade::SceneData: expected a 3D translation field but got" << fieldType, );
_dimensions = 2;
} else if(fieldType == SceneFieldType::Vector3 ||
fieldType == SceneFieldType::Vector3d) {
CORRADE_ASSERT(!_dimensions || _dimensions == 3,
"Trade::SceneData: expected a 2D translation field but got" << fieldType, );
_dimensions = 3;
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
if(rotationField != ~UnsignedInt{}) {
const SceneFieldType fieldType = _fields[rotationField]._fieldType;
if(fieldType == SceneFieldType::Complex ||
fieldType == SceneFieldType::Complexd) {
CORRADE_ASSERT(!_dimensions || _dimensions == 2,
"Trade::SceneData: expected a 3D rotation field but got" << fieldType, );
_dimensions = 2;
} else if(fieldType == SceneFieldType::Quaternion ||
fieldType == SceneFieldType::Quaterniond) {
CORRADE_ASSERT(!_dimensions || _dimensions == 3,
"Trade::SceneData: expected a 2D rotation field but got" << fieldType, );
_dimensions = 3;
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
if(scalingField != ~UnsignedInt{}) {
const SceneFieldType fieldType = _fields[scalingField]._fieldType;
if(fieldType == SceneFieldType::Vector2 ||
fieldType == SceneFieldType::Vector2d) {
CORRADE_ASSERT(!_dimensions || _dimensions == 2,
"Trade::SceneData: expected a 3D scaling field but got" << fieldType, );
_dimensions = 2;
} else if(fieldType == SceneFieldType::Vector3 ||
fieldType == SceneFieldType::Vector3d) {
CORRADE_ASSERT(!_dimensions || _dimensions == 3,
"Trade::SceneData: expected a 2D scaling field but got" << fieldType, );
_dimensions = 3;
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
} }
SceneData::SceneData(const SceneObjectType objectType, const UnsignedLong objectCount, Containers::Array<char>&& data, const std::initializer_list<SceneFieldData> fields, const void* const importerState): SceneData{objectType, objectCount, std::move(data), Implementation::initializerListToArrayWithDefaultDeleter(fields), importerState} {} SceneData::SceneData(const SceneObjectType objectType, const UnsignedLong objectCount, Containers::Array<char>&& data, const std::initializer_list<SceneFieldData> fields, const void* const importerState): SceneData{objectType, objectCount, std::move(data), Implementation::initializerListToArrayWithDefaultDeleter(fields), importerState} {}
@ -903,6 +977,10 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
/* *FieldId, offset and destination.size() is assumed to be in bounds (or /* *FieldId, offset and destination.size() is assumed to be in bounds (or
an invalid field ID), checked by the callers */ an invalid field ID), checked by the callers */
/* If is2D() returned false as well, all *FieldId would be invalid, which
the caller is assumed to check. */
CORRADE_ASSERT(!is3D(), "Trade::SceneData::transformations2DInto(): scene has a 3D transformation type", );
/** @todo apply scalings as well if dual complex? */ /** @todo apply scalings as well if dual complex? */
/* Prefer the transformation field, if present */ /* Prefer the transformation field, if present */
@ -919,11 +997,6 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
convertTransformation<DualComplex>(fieldData, destination); convertTransformation<DualComplex>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::DualComplexd) { } else if(field._fieldType == SceneFieldType::DualComplexd) {
convertTransformation<DualComplexd>(fieldData, destination); convertTransformation<DualComplexd>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Matrix4x4 ||
field._fieldType == SceneFieldType::Matrix4x4d ||
field._fieldType == SceneFieldType::DualQuaternion ||
field._fieldType == SceneFieldType::DualQuaterniond) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::transformations2DInto(): field has a 3D transformation type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
/* If not, combine from TRS components */ /* If not, combine from TRS components */
@ -941,9 +1014,6 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
applyScaling<Vector2>(fieldData, destination); applyScaling<Vector2>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Vector2d) { } else if(field._fieldType == SceneFieldType::Vector2d) {
applyScaling<Vector2d>(fieldData, destination); applyScaling<Vector2d>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Vector3 ||
field._fieldType == SceneFieldType::Vector3d) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::transformations2DInto(): field has a 3D scaling type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
@ -956,9 +1026,6 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
applyRotation<Complex>(fieldData, destination); applyRotation<Complex>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Complexd) { } else if(field._fieldType == SceneFieldType::Complexd) {
applyRotation<Complexd>(fieldData, destination); applyRotation<Complexd>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Quaternion ||
field._fieldType == SceneFieldType::Quaterniond) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::transformations2DInto(): field has a 3D rotation type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
@ -971,9 +1038,6 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
applyTranslation<Vector2>(fieldData, destination); applyTranslation<Vector2>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Vector2d) { } else if(field._fieldType == SceneFieldType::Vector2d) {
applyTranslation<Vector2d>(fieldData, destination); applyTranslation<Vector2d>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Vector3 ||
field._fieldType == SceneFieldType::Vector3d) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::transformations2DInto(): field has a 3D translation type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
@ -1022,6 +1086,10 @@ void SceneData::translationsRotationsScalings2DIntoInternal(const UnsignedInt tr
/* *FieldId, offset and *Destination.size() is assumed to be in bounds (or /* *FieldId, offset and *Destination.size() is assumed to be in bounds (or
an invalid field ID), checked by the callers */ an invalid field ID), checked by the callers */
/* If is2D() returned false as well, all *FieldId would be invalid, which
the caller is assumed to check. */
CORRADE_ASSERT(!is3D(), "Trade::SceneData::translationsRotationsScalings2DInto(): scene has a 3D transformation type", );
/* Retrieve translation, if desired. If no field is present, output a zero /* Retrieve translation, if desired. If no field is present, output a zero
vector for all objects. */ vector for all objects. */
if(translationDestination) { if(translationDestination) {
@ -1036,9 +1104,6 @@ void SceneData::translationsRotationsScalings2DIntoInternal(const UnsignedInt tr
Utility::copy(Containers::arrayCast<const Vector2>(fieldData), translationDestination); Utility::copy(Containers::arrayCast<const Vector2>(fieldData), translationDestination);
} else if(field._fieldType == SceneFieldType::Vector2d) { } else if(field._fieldType == SceneFieldType::Vector2d) {
Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 2), Containers::arrayCast<2, Float>(translationDestination)); Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 2), Containers::arrayCast<2, Float>(translationDestination));
} else if(field._fieldType == SceneFieldType::Vector3 ||
field._fieldType == SceneFieldType::Vector3d) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::translationsRotationsScalings2DInto(): field has a 3D translation type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
} }
@ -1057,9 +1122,6 @@ void SceneData::translationsRotationsScalings2DIntoInternal(const UnsignedInt tr
Utility::copy(Containers::arrayCast<const Complex>(fieldData), rotationDestination); Utility::copy(Containers::arrayCast<const Complex>(fieldData), rotationDestination);
} else if(field._fieldType == SceneFieldType::Complexd) { } else if(field._fieldType == SceneFieldType::Complexd) {
Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 2), Containers::arrayCast<2, Float>(rotationDestination)); Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 2), Containers::arrayCast<2, Float>(rotationDestination));
} else if(field._fieldType == SceneFieldType::Quaternion ||
field._fieldType == SceneFieldType::Quaterniond) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::translationsRotationsScalings2DInto(): field has a 3D rotation type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
} }
@ -1078,9 +1140,6 @@ void SceneData::translationsRotationsScalings2DIntoInternal(const UnsignedInt tr
Utility::copy(Containers::arrayCast<const Vector2>(fieldData), scalingDestination); Utility::copy(Containers::arrayCast<const Vector2>(fieldData), scalingDestination);
} else if(field._fieldType == SceneFieldType::Vector2d) { } else if(field._fieldType == SceneFieldType::Vector2d) {
Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 2), Containers::arrayCast<2, Float>(scalingDestination)); Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 2), Containers::arrayCast<2, Float>(scalingDestination));
} else if(field._fieldType == SceneFieldType::Vector3 ||
field._fieldType == SceneFieldType::Vector3d) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::translationsRotationsScalings2DInto(): field has a 3D scaling type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
} }
@ -1144,6 +1203,10 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
/* *FieldId, offset and destination.size() is assumed to be in bounds (or /* *FieldId, offset and destination.size() is assumed to be in bounds (or
an invalid field ID), checked by the callers */ an invalid field ID), checked by the callers */
/* If is3D() returned false as well, all *FieldId would be invalid, which
the caller is assumed to check. */
CORRADE_ASSERT(!is2D(), "Trade::SceneData::transformations3DInto(): scene has a 2D transformation type", );
/** @todo apply scalings as well if dual quat? */ /** @todo apply scalings as well if dual quat? */
/* Prefer the transformation field, if present */ /* Prefer the transformation field, if present */
@ -1160,11 +1223,6 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
convertTransformation<DualQuaternion>(fieldData, destination); convertTransformation<DualQuaternion>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::DualQuaterniond) { } else if(field._fieldType == SceneFieldType::DualQuaterniond) {
convertTransformation<DualQuaterniond>(fieldData, destination); convertTransformation<DualQuaterniond>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Matrix3x3 ||
field._fieldType == SceneFieldType::Matrix3x3d ||
field._fieldType == SceneFieldType::DualComplex ||
field._fieldType == SceneFieldType::DualComplexd) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::transformations3DInto(): field has a 2D transformation type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
/* If not, combine from TRS components */ /* If not, combine from TRS components */
@ -1182,9 +1240,6 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
applyScaling<Vector3>(fieldData, destination); applyScaling<Vector3>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Vector3d) { } else if(field._fieldType == SceneFieldType::Vector3d) {
applyScaling<Vector3d>(fieldData, destination); applyScaling<Vector3d>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Vector2 ||
field._fieldType == SceneFieldType::Vector2d) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::transformations3DInto(): field has a 2D scaling type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
@ -1197,9 +1252,6 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
applyRotation<Quaternion>(fieldData, destination); applyRotation<Quaternion>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Quaterniond) { } else if(field._fieldType == SceneFieldType::Quaterniond) {
applyRotation<Quaterniond>(fieldData, destination); applyRotation<Quaterniond>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Complex ||
field._fieldType == SceneFieldType::Complexd) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::transformations3DInto(): field has a 2D rotation type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
@ -1212,9 +1264,6 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
applyTranslation<Vector3>(fieldData, destination); applyTranslation<Vector3>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Vector3d) { } else if(field._fieldType == SceneFieldType::Vector3d) {
applyTranslation<Vector3d>(fieldData, destination); applyTranslation<Vector3d>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Vector2 ||
field._fieldType == SceneFieldType::Vector2d) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::transformations3DInto(): field has a 2D translation type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
@ -1263,6 +1312,10 @@ void SceneData::translationsRotationsScalings3DIntoInternal(const UnsignedInt tr
/* *FieldId, offset and *Destination.size() is assumed to be in bounds (or /* *FieldId, offset and *Destination.size() is assumed to be in bounds (or
an invalid field ID), checked by the callers */ an invalid field ID), checked by the callers */
/* If is3D() returned false as well, all *FieldId would be invalid, which
the caller is assumed to check. */
CORRADE_ASSERT(!is2D(), "Trade::SceneData::translationsRotationsScalings3DInto(): scene has a 2D transformation type", );
/* Retrieve translation, if desired. If no field is present, output a zero /* Retrieve translation, if desired. If no field is present, output a zero
vector for all objects. */ vector for all objects. */
if(translationDestination) { if(translationDestination) {
@ -1277,9 +1330,6 @@ void SceneData::translationsRotationsScalings3DIntoInternal(const UnsignedInt tr
Utility::copy(Containers::arrayCast<const Vector3>(fieldData), translationDestination); Utility::copy(Containers::arrayCast<const Vector3>(fieldData), translationDestination);
} else if(field._fieldType == SceneFieldType::Vector3d) { } else if(field._fieldType == SceneFieldType::Vector3d) {
Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 3), Containers::arrayCast<2, Float>(translationDestination)); Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 3), Containers::arrayCast<2, Float>(translationDestination));
} else if(field._fieldType == SceneFieldType::Vector2 ||
field._fieldType == SceneFieldType::Vector2d) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::translationsRotationsScalings3DInto(): field has a 2D translation type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
} }
@ -1298,9 +1348,6 @@ void SceneData::translationsRotationsScalings3DIntoInternal(const UnsignedInt tr
Utility::copy(Containers::arrayCast<const Quaternion>(fieldData), rotationDestination); Utility::copy(Containers::arrayCast<const Quaternion>(fieldData), rotationDestination);
} else if(field._fieldType == SceneFieldType::Quaterniond) { } else if(field._fieldType == SceneFieldType::Quaterniond) {
Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 4), Containers::arrayCast<2, Float>(rotationDestination)); Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 4), Containers::arrayCast<2, Float>(rotationDestination));
} else if(field._fieldType == SceneFieldType::Complex ||
field._fieldType == SceneFieldType::Complexd) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::translationsRotationsScalings3DInto(): field has a 2D rotation type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
} }
@ -1319,9 +1366,6 @@ void SceneData::translationsRotationsScalings3DIntoInternal(const UnsignedInt tr
Utility::copy(Containers::arrayCast<const Vector3>(fieldData), scalingDestination); Utility::copy(Containers::arrayCast<const Vector3>(fieldData), scalingDestination);
} else if(field._fieldType == SceneFieldType::Vector3d) { } else if(field._fieldType == SceneFieldType::Vector3d) {
Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 3), Containers::arrayCast<2, Float>(scalingDestination)); Math::castInto(Containers::arrayCast<2, const Double>(fieldData, 3), Containers::arrayCast<2, Float>(scalingDestination));
} else if(field._fieldType == SceneFieldType::Vector2 ||
field._fieldType == SceneFieldType::Vector2d) {
CORRADE_ASSERT_UNREACHABLE("Trade::SceneData::translationsRotationsScalings3DInto(): field has a 2D scaling type" << field._fieldType, );
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */ } else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
} }
} }
@ -1698,39 +1742,9 @@ Containers::Optional<Matrix3> SceneData::transformation2DFor(const UnsignedInt o
UnsignedInt transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, fieldWithObjectMapping; UnsignedInt transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, fieldWithObjectMapping;
if(findTransformFields(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, &fieldWithObjectMapping) == ~std::size_t{}) return {}; if(findTransformFields(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, &fieldWithObjectMapping) == ~std::size_t{}) return {};
#ifndef CORRADE_NO_ASSERT /* If is2D() returned false as well, all *FieldId would be invalid, which
if(transformationFieldId != ~UnsignedInt{}) { is handled above. */
const SceneFieldType type = _fields[transformationFieldId]._fieldType; CORRADE_ASSERT(!is3D(), "Trade::SceneData::transformation2DFor(): scene has a 3D transformation type", {});
CORRADE_ASSERT(
type == SceneFieldType::Matrix3x3 ||
type == SceneFieldType::Matrix3x3d ||
type == SceneFieldType::DualComplex ||
type == SceneFieldType::DualComplexd,
"Trade::SceneData::transformation2DFor(): field has a 3D transformation type" << type, {});
} else {
if(translationFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[translationFieldId]._fieldType;
CORRADE_ASSERT(
type == SceneFieldType::Vector2 ||
type == SceneFieldType::Vector2d,
"Trade::SceneData::transformation2DFor(): field has a 3D translation type" << type, {});
}
if(rotationFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[rotationFieldId]._fieldType;
CORRADE_ASSERT(
type == SceneFieldType::Complex ||
type == SceneFieldType::Complexd,
"Trade::SceneData::transformation2DFor(): field has a 3D rotation type" << type, {});
}
if(scalingFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[scalingFieldId]._fieldType;
CORRADE_ASSERT(
type == SceneFieldType::Vector2 ||
type == SceneFieldType::Vector2d,
"Trade::SceneData::transformation2DFor(): field has a 3D scaling type" << type, {});
}
}
#endif
const std::size_t offset = fieldFor(_fields[fieldWithObjectMapping], 0, object); const std::size_t offset = fieldFor(_fields[fieldWithObjectMapping], 0, object);
if(offset == _fields[fieldWithObjectMapping]._size) return {}; if(offset == _fields[fieldWithObjectMapping]._size) return {};
@ -1747,29 +1761,9 @@ Containers::Optional<Containers::Triple<Vector2, Complex, Vector2>> SceneData::t
UnsignedInt translationFieldId, rotationFieldId, scalingFieldId, fieldWithObjectMapping; UnsignedInt translationFieldId, rotationFieldId, scalingFieldId, fieldWithObjectMapping;
if(findTranslationRotationScalingFields(translationFieldId, rotationFieldId, scalingFieldId, &fieldWithObjectMapping) == ~std::size_t{}) return {}; if(findTranslationRotationScalingFields(translationFieldId, rotationFieldId, scalingFieldId, &fieldWithObjectMapping) == ~std::size_t{}) return {};
#ifndef CORRADE_NO_ASSERT /* If is2D() returned false as well, all *FieldId would be invalid, which
if(translationFieldId != ~UnsignedInt{}) { is handled above. */
const SceneFieldType type = _fields[translationFieldId]._fieldType; CORRADE_ASSERT(!is3D(), "Trade::SceneData::translationRotationScaling2DFor(): scene has a 3D transformation type", {});
CORRADE_ASSERT(
type == SceneFieldType::Vector2 ||
type == SceneFieldType::Vector2d,
"Trade::SceneData::translationRotationScaling2DFor(): field has a 3D translation type" << type, {});
}
if(rotationFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[rotationFieldId]._fieldType;
CORRADE_ASSERT(
type == SceneFieldType::Complex ||
type == SceneFieldType::Complexd,
"Trade::SceneData::translationRotationScaling2DFor(): field has a 3D rotation type" << type, {});
}
if(scalingFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[scalingFieldId]._fieldType;
CORRADE_ASSERT(
type == SceneFieldType::Vector2 ||
type == SceneFieldType::Vector2d,
"Trade::SceneData::translationRotationScaling2DFor(): field has a 3D scaling type" << type, {});
}
#endif
const std::size_t offset = fieldFor(_fields[fieldWithObjectMapping], 0, object); const std::size_t offset = fieldFor(_fields[fieldWithObjectMapping], 0, object);
if(offset == _fields[fieldWithObjectMapping]._size) return {}; if(offset == _fields[fieldWithObjectMapping]._size) return {};
@ -1788,39 +1782,9 @@ Containers::Optional<Matrix4> SceneData::transformation3DFor(const UnsignedInt o
UnsignedInt transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, fieldWithObjectMapping; UnsignedInt transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, fieldWithObjectMapping;
if(findTransformFields(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, &fieldWithObjectMapping) == ~std::size_t{}) return {}; if(findTransformFields(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, &fieldWithObjectMapping) == ~std::size_t{}) return {};
#ifndef CORRADE_NO_ASSERT /* If is3D() returned false as well, all *FieldId would be invalid, which
if(transformationFieldId != ~UnsignedInt{}) { is handled above. */
const SceneFieldType type = _fields[transformationFieldId]._fieldType; CORRADE_ASSERT(!is2D(), "Trade::SceneData::transformation3DFor(): scene has a 2D transformation type", {});
CORRADE_ASSERT(
type == SceneFieldType::Matrix4x4 ||
type == SceneFieldType::Matrix4x4d ||
type == SceneFieldType::DualQuaternion ||
type == SceneFieldType::DualQuaterniond,
"Trade::SceneData::transformation3DFor(): field has a 2D transformation type" << type, {});
} else {
if(translationFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[translationFieldId]._fieldType;
CORRADE_ASSERT(
type == SceneFieldType::Vector3 ||
type == SceneFieldType::Vector3d,
"Trade::SceneData::transformation3DFor(): field has a 2D translation type" << type, {});
}
if(rotationFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[rotationFieldId]._fieldType;
CORRADE_ASSERT(
type == SceneFieldType::Quaternion ||
type == SceneFieldType::Quaterniond,
"Trade::SceneData::transformation3DFor(): field has a 2D rotation type" << type, {});
}
if(scalingFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[scalingFieldId]._fieldType;
CORRADE_ASSERT(
type == SceneFieldType::Vector3 ||
type == SceneFieldType::Vector3d,
"Trade::SceneData::transformation3DFor(): field has a 2D scaling type" << type, {});
}
}
#endif
const std::size_t offset = fieldFor(_fields[fieldWithObjectMapping], 0, object); const std::size_t offset = fieldFor(_fields[fieldWithObjectMapping], 0, object);
if(offset == _fields[fieldWithObjectMapping]._size) return {}; if(offset == _fields[fieldWithObjectMapping]._size) return {};
@ -1837,29 +1801,9 @@ Containers::Optional<Containers::Triple<Vector3, Quaternion, Vector3>> SceneData
UnsignedInt translationFieldId, rotationFieldId, scalingFieldId, fieldWithObjectMapping; UnsignedInt translationFieldId, rotationFieldId, scalingFieldId, fieldWithObjectMapping;
if(findTranslationRotationScalingFields(translationFieldId, rotationFieldId, scalingFieldId, &fieldWithObjectMapping) == ~std::size_t{}) return {}; if(findTranslationRotationScalingFields(translationFieldId, rotationFieldId, scalingFieldId, &fieldWithObjectMapping) == ~std::size_t{}) return {};
#ifndef CORRADE_NO_ASSERT /* If is3D() returned false as well, all *FieldId would be invalid, which
if(translationFieldId != ~UnsignedInt{}) { is handled above. */
const SceneFieldType type = _fields[translationFieldId]._fieldType; CORRADE_ASSERT(!is2D(), "Trade::SceneData::translationRotationScaling3DFor(): scene has a 2D transformation type", {});
CORRADE_ASSERT(
type == SceneFieldType::Vector3 ||
type == SceneFieldType::Vector3d,
"Trade::SceneData::translationRotationScaling3DFor(): field has a 2D translation type" << type, {});
}
if(rotationFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[rotationFieldId]._fieldType;
CORRADE_ASSERT(
type == SceneFieldType::Quaternion ||
type == SceneFieldType::Quaterniond,
"Trade::SceneData::translationRotationScaling3DFor(): field has a 2D rotation type" << type, {});
}
if(scalingFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[scalingFieldId]._fieldType;
CORRADE_ASSERT(
type == SceneFieldType::Vector3 ||
type == SceneFieldType::Vector3d,
"Trade::SceneData::translationRotationScaling3DFor(): field has a 2D scaling type" << type, {});
}
#endif
const std::size_t offset = fieldFor(_fields[fieldWithObjectMapping], 0, object); const std::size_t offset = fieldFor(_fields[fieldWithObjectMapping], 0, object);
if(offset == _fields[fieldWithObjectMapping]._size) return {}; if(offset == _fields[fieldWithObjectMapping]._size) return {};

82
src/Magnum/Trade/SceneData.h

@ -121,15 +121,18 @@ enum class SceneField: UnsignedInt {
* *
* The transformation can be also represented by separate * The transformation can be also represented by separate
* @ref SceneField::Translation, @ref SceneField::Rotation and * @ref SceneField::Translation, @ref SceneField::Rotation and
* @ref SceneField::Scaling fields. If both @ref SceneField::Transformation * @ref SceneField::Scaling fields. All present transformation-related
* and TRS fields are specified, it's expected that all objects that have * fields are expected to have the same dimensionality --- either all 2D or
* TRS fields have a combined transformation field as well, and * all 3D. If both @ref SceneField::Transformation and TRS fields are
* specified, it's expected that all objects that have TRS fields have a
* combined transformation field as well, and
* @ref SceneData::transformations2DAsArray() / * @ref SceneData::transformations2DAsArray() /
* @ref SceneData::transformations3DAsArray() then takes into account only * @ref SceneData::transformations3DAsArray() then takes into account only
* the combined transformation field. TRS fields can however be specified * the combined transformation field. TRS fields can however be specified
* only for a subset of transformed objects, useful for example when only * only for a subset of transformed objects, useful for example when only
* certain objects have these properties animated. * certain objects have these properties animated.
* @see @ref SceneData::transformations2DAsArray(), * @see @ref SceneData::is2D(), @ref SceneData::is3D(),
* @ref SceneData::transformations2DAsArray(),
* @ref SceneData::transformations3DAsArray(), * @ref SceneData::transformations3DAsArray(),
* @ref SceneData::transformation2DFor(), * @ref SceneData::transformation2DFor(),
* @ref SceneData::transformation3DFor() * @ref SceneData::transformation3DFor()
@ -146,11 +149,13 @@ enum class SceneField: UnsignedInt {
* *
* The translation field usually is (but doesn't have to be) complemented * The translation field usually is (but doesn't have to be) complemented
* by a @ref SceneField::Rotation and @ref SceneField::Scaling, which, if * by a @ref SceneField::Rotation and @ref SceneField::Scaling, which, if
* present, are expected to all share the same object mapping view. The TRS * present, are expected to all share the same object mapping view and have
* the same dimensionality, either all 2D or all 3D. The TRS
* components can either completely replace @ref SceneField::Transformation * components can either completely replace @ref SceneField::Transformation
* or be provided just for a subset of it --- see its documentation for * or be provided just for a subset of it --- see its documentation for
* details. * details.
* @see @ref SceneData::transformations2DAsArray(), * @see @ref SceneData::is2D(), @ref SceneData::is3D(),
* @ref SceneData::transformations2DAsArray(),
* @ref SceneData::transformations3DAsArray(), * @ref SceneData::transformations3DAsArray(),
* @ref SceneData::transformation2DFor(), * @ref SceneData::transformation2DFor(),
* @ref SceneData::transformation3DFor(), * @ref SceneData::transformation3DFor(),
@ -171,11 +176,13 @@ enum class SceneField: UnsignedInt {
* *
* The rotation field usually is (but doesn't have to be) complemented by a * The rotation field usually is (but doesn't have to be) complemented by a
* @ref SceneField::Translation and @ref SceneField::Scaling, which, if * @ref SceneField::Translation and @ref SceneField::Scaling, which, if
* present, are expected to all share the same object mapping view. The TRS * present, are expected to all share the same object mapping view and have
* the same dimensionality, either all 2D or all 3D. The TRS
* components can either completely replace @ref SceneField::Transformation * components can either completely replace @ref SceneField::Transformation
* or be provided just for a subset of it --- see its documentation for * or be provided just for a subset of it --- see its documentation for
* details. * details.
* @see @ref SceneData::transformations2DAsArray(), * @see @ref SceneData::is2D(), @ref SceneData::is3D(),
* @ref SceneData::transformations2DAsArray(),
* @ref SceneData::transformations3DAsArray(), * @ref SceneData::transformations3DAsArray(),
* @ref SceneData::transformation2DFor(), * @ref SceneData::transformation2DFor(),
* @ref SceneData::transformation3DFor(), * @ref SceneData::transformation3DFor(),
@ -196,11 +203,13 @@ enum class SceneField: UnsignedInt {
* *
* The scaling field usually is (but doesn't have to be) complemented by a * The scaling field usually is (but doesn't have to be) complemented by a
* @ref SceneField::Translation and @ref SceneField::Rotation, which, if * @ref SceneField::Translation and @ref SceneField::Rotation, which, if
* present, are expected to all share the same object mapping view. The TRS * present, are expected to all share the same object mapping view and have
* the same dimensionality, either all 2D or all 3D. The TRS
* components can either completely replace @ref SceneField::Transformation * components can either completely replace @ref SceneField::Transformation
* or be provided just for a subset of it --- see its documentation for * or be provided just for a subset of it --- see its documentation for
* details. * details.
* @see @ref SceneData::transformations2DAsArray(), * @see @ref SceneData::is2D(), @ref SceneData::is3D(),
* @ref SceneData::transformations2DAsArray(),
* @ref SceneData::transformations3DAsArray(), * @ref SceneData::transformations3DAsArray(),
* @ref SceneData::transformation2DFor(), * @ref SceneData::transformation2DFor(),
* @ref SceneData::transformation3DFor(), * @ref SceneData::transformation3DFor(),
@ -993,9 +1002,47 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/ */
UnsignedShort fieldArraySize(UnsignedInt id) const; UnsignedShort fieldArraySize(UnsignedInt id) const;
/**
* @brief Whether the scene is two-dimensional
* @m_since_latest
*
* Returns @cpp true @ce if the present
* @ref SceneField::Transformation,
* @relativeref{SceneField,Translation},
* @relativeref{SceneField,Rotation} and
* @relativeref{SceneField,Scaling} fields have a 2D type,
* @cpp false @ce otherwise.
*
* If there's no transformation-related field, the scene is treated as
* neither 2D nor 3D and both @ref is2D() and @ref is3D() return
* @cpp false @ce. On the other hand, a scene can't be both 2D and 3D.
* @see @ref hasField()
*/
bool is2D() const { return _dimensions == 2; }
/**
* @brief Whether the scene is three-dimensional
* @m_since_latest
*
* Returns @cpp true @ce if the present
* @ref SceneField::Transformation,
* @relativeref{SceneField,Translation},
* @relativeref{SceneField,Rotation} and
* @relativeref{SceneField,Scaling} fields have a 3D type,
* @cpp false @ce otherwise.
*
* If there's no transformation-related field, the scene is treated as
* neither 2D nor 3D and both @ref is2D() and @ref is3D() return
* @cpp false @ce. On the other hand, a scene can't be both 2D and 3D.
* @see @ref hasField()
*/
bool is3D() const { return _dimensions == 3; }
/** /**
* @brief Whether the scene has given field * @brief Whether the scene has given field
* @m_since_latest * @m_since_latest
*
* @see @ref is2D(), @ref is3D()
*/ */
bool hasField(SceneField name) const; bool hasField(SceneField name) const;
@ -1430,7 +1477,7 @@ class MAGNUM_TRADE_EXPORT SceneData {
* expected to exist and they are expected to have a type corresponding * expected to exist and they are expected to have a type corresponding
* to 2D, otherwise you're supposed to use * to 2D, otherwise you're supposed to use
* @ref transformations3DAsArray(). * @ref transformations3DAsArray().
* @see @ref transformations2DInto(), @ref hasField(), * @see @ref is2D(), @ref transformations2DInto(), @ref hasField(),
* @ref fieldType(SceneField) const, @ref transformation2DFor() * @ref fieldType(SceneField) const, @ref transformation2DFor()
*/ */
Containers::Array<Matrix3> transformations2DAsArray() const; Containers::Array<Matrix3> transformations2DAsArray() const;
@ -1476,8 +1523,8 @@ class MAGNUM_TRADE_EXPORT SceneData {
* field isn't present, the second value is an identity rotation. If * field isn't present, the second value is an identity rotation. If
* the @relativeref{SceneField,Scaling} field isn't present, the third * the @relativeref{SceneField,Scaling} field isn't present, the third
* value is an identity scaling (@cpp 1.0f @ce in both dimensions). * value is an identity scaling (@cpp 1.0f @ce in both dimensions).
* @see @ref translationsRotationsScalings2DInto(), @ref hasField(), * @see @ref is2D(), @ref translationsRotationsScalings2DInto(),
* @ref fieldType(SceneField) const, * @ref hasField(), @ref fieldType(SceneField) const,
* @ref translationRotationScaling2DFor() * @ref translationRotationScaling2DFor()
*/ */
Containers::Array<Containers::Triple<Vector2, Complex, Vector2>> translationsRotationsScalings2DAsArray() const; Containers::Array<Containers::Triple<Vector2, Complex, Vector2>> translationsRotationsScalings2DAsArray() const;
@ -1522,7 +1569,7 @@ class MAGNUM_TRADE_EXPORT SceneData {
* expected to exist and they are expected to have a type corresponding * expected to exist and they are expected to have a type corresponding
* to 3D, otherwise you're supposed to use * to 3D, otherwise you're supposed to use
* @ref transformations2DAsArray(). * @ref transformations2DAsArray().
* @see @ref transformations3DInto(), @ref hasField(), * @see @ref is3D(), @ref transformations3DInto(), @ref hasField(),
* @ref fieldType(SceneField) const, @ref transformation3DFor() * @ref fieldType(SceneField) const, @ref transformation3DFor()
*/ */
Containers::Array<Matrix4> transformations3DAsArray() const; Containers::Array<Matrix4> transformations3DAsArray() const;
@ -1568,8 +1615,8 @@ class MAGNUM_TRADE_EXPORT SceneData {
* field isn't present, the second value is an identity rotation. If * field isn't present, the second value is an identity rotation. If
* the @relativeref{SceneField,Scaling} field isn't present, the third * the @relativeref{SceneField,Scaling} field isn't present, the third
* value is an identity scaling (@cpp 1.0f @ce in all dimensions). * value is an identity scaling (@cpp 1.0f @ce in all dimensions).
* @see @ref translationsRotationsScalings3DInto(), @ref hasField(), * @see @ref is3D(), @ref translationsRotationsScalings3DInto(),
* @ref fieldType(SceneField) const, * @ref hasField(), @ref fieldType(SceneField) const,
* @ref translationRotationScaling3DFor() * @ref translationRotationScaling3DFor()
*/ */
Containers::Array<Containers::Triple<Vector3, Quaternion, Vector3>> translationsRotationsScalings3DAsArray() const; Containers::Array<Containers::Triple<Vector3, Quaternion, Vector3>> translationsRotationsScalings3DAsArray() const;
@ -2114,7 +2161,8 @@ class MAGNUM_TRADE_EXPORT SceneData {
DataFlags _dataFlags; DataFlags _dataFlags;
SceneObjectType _objectType; SceneObjectType _objectType;
/* 2/6 bytes free */ UnsignedByte _dimensions;
/* 1/5 bytes free */
UnsignedLong _objectCount; UnsignedLong _objectCount;
const void* _importerState; const void* _importerState;
Containers::Array<SceneFieldData> _fields; Containers::Array<SceneFieldData> _fields;

440
src/Magnum/Trade/Test/SceneDataTest.cpp

@ -96,6 +96,7 @@ struct SceneDataTest: TestSuite::Tester {
void constructObjectTypeTooSmall(); void constructObjectTypeTooSmall();
void constructNotOwnedFlagOwned(); void constructNotOwnedFlagOwned();
void constructMismatchedTRSViews(); void constructMismatchedTRSViews();
template<class T> void constructMismatchedTRSDimensionality();
void constructMismatchedMeshMaterialView(); void constructMismatchedMeshMaterialView();
void constructCopy(); void constructCopy();
@ -115,16 +116,14 @@ struct SceneDataTest: TestSuite::Tester {
void parentsIntoArrayInvalidSizeOrOffset(); void parentsIntoArrayInvalidSizeOrOffset();
template<class T> void transformations2DAsArray(); template<class T> void transformations2DAsArray();
template<class T, class U, class V> void transformations2DAsArrayTRS(); template<class T, class U, class V> void transformations2DAsArrayTRS();
template<class T> void transformations2DAsArrayBut3DType(); void transformations2DAsArrayBut3DType();
template<class T> void transformations2DAsArrayBut3DTypeTRS();
void transformations2DIntoArray(); void transformations2DIntoArray();
void transformations2DIntoArrayTRS(); void transformations2DIntoArrayTRS();
void transformations2DIntoArrayInvalidSizeOrOffset(); void transformations2DIntoArrayInvalidSizeOrOffset();
void transformations2DIntoArrayInvalidSizeOrOffsetTRS(); void transformations2DIntoArrayInvalidSizeOrOffsetTRS();
template<class T> void transformations3DAsArray(); template<class T> void transformations3DAsArray();
template<class T, class U, class V> void transformations3DAsArrayTRS(); template<class T, class U, class V> void transformations3DAsArrayTRS();
template<class T> void transformations3DAsArrayBut2DType(); void transformations3DAsArrayBut2DType();
template<class T> void transformations3DAsArrayBut2DTypeTRS();
void transformations3DIntoArray(); void transformations3DIntoArray();
void transformations3DIntoArrayTRS(); void transformations3DIntoArrayTRS();
void transformations3DIntoArrayInvalidSizeOrOffset(); void transformations3DIntoArrayInvalidSizeOrOffset();
@ -161,12 +160,10 @@ struct SceneDataTest: TestSuite::Tester {
void childrenFor(); void childrenFor();
void transformation2DFor(); void transformation2DFor();
void transformation2DForTRS(); void transformation2DForTRS();
template<class T> void transformation2DForBut3DType(); void transformation2DForBut3DType();
template<class T> void transformation2DForBut3DTypeTRS();
void transformation3DFor(); void transformation3DFor();
void transformation3DForTRS(); void transformation3DForTRS();
template<class T> void transformation3DForBut2DType(); void transformation3DForBut2DType();
template<class T> void transformation3DForBut2DTypeTRS();
void meshesMaterialsFor(); void meshesMaterialsFor();
void lightsFor(); void lightsFor();
void camerasFor(); void camerasFor();
@ -253,6 +250,8 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::constructObjectTypeTooSmall, &SceneDataTest::constructObjectTypeTooSmall,
&SceneDataTest::constructNotOwnedFlagOwned, &SceneDataTest::constructNotOwnedFlagOwned,
&SceneDataTest::constructMismatchedTRSViews, &SceneDataTest::constructMismatchedTRSViews,
&SceneDataTest::constructMismatchedTRSDimensionality<Float>,
&SceneDataTest::constructMismatchedTRSDimensionality<Double>,
&SceneDataTest::constructMismatchedMeshMaterialView, &SceneDataTest::constructMismatchedMeshMaterialView,
&SceneDataTest::constructCopy, &SceneDataTest::constructCopy,
@ -292,12 +291,7 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::transformations2DAsArray<DualComplexd>, &SceneDataTest::transformations2DAsArray<DualComplexd>,
&SceneDataTest::transformations2DAsArrayTRS<Float, Float, Double>, &SceneDataTest::transformations2DAsArrayTRS<Float, Float, Double>,
&SceneDataTest::transformations2DAsArrayTRS<Double, Double, Float>, &SceneDataTest::transformations2DAsArrayTRS<Double, Double, Float>,
&SceneDataTest::transformations2DAsArrayBut3DType<Matrix4x4>, &SceneDataTest::transformations2DAsArrayBut3DType});
&SceneDataTest::transformations2DAsArrayBut3DType<Matrix4x4d>,
&SceneDataTest::transformations2DAsArrayBut3DType<DualQuaternion>,
&SceneDataTest::transformations2DAsArrayBut3DType<DualQuaterniond>,
&SceneDataTest::transformations2DAsArrayBut3DTypeTRS<Float>,
&SceneDataTest::transformations2DAsArrayBut3DTypeTRS<Double>});
addInstancedTests({&SceneDataTest::transformations2DIntoArray, addInstancedTests({&SceneDataTest::transformations2DIntoArray,
&SceneDataTest::transformations2DIntoArrayTRS}, &SceneDataTest::transformations2DIntoArrayTRS},
@ -311,12 +305,7 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::transformations3DAsArray<DualQuaterniond>, &SceneDataTest::transformations3DAsArray<DualQuaterniond>,
&SceneDataTest::transformations3DAsArrayTRS<Float, Double, Double>, &SceneDataTest::transformations3DAsArrayTRS<Float, Double, Double>,
&SceneDataTest::transformations3DAsArrayTRS<Double, Float, Float>, &SceneDataTest::transformations3DAsArrayTRS<Double, Float, Float>,
&SceneDataTest::transformations3DAsArrayBut2DType<Matrix3x3>, &SceneDataTest::transformations3DAsArrayBut2DType});
&SceneDataTest::transformations3DAsArrayBut2DType<Matrix3x3d>,
&SceneDataTest::transformations3DAsArrayBut2DType<DualComplex>,
&SceneDataTest::transformations3DAsArrayBut2DType<DualComplexd>,
&SceneDataTest::transformations3DAsArrayBut2DTypeTRS<Float>,
&SceneDataTest::transformations3DAsArrayBut2DTypeTRS<Double>});
addInstancedTests({&SceneDataTest::transformations3DIntoArray, addInstancedTests({&SceneDataTest::transformations3DIntoArray,
&SceneDataTest::transformations3DIntoArrayTRS}, &SceneDataTest::transformations3DIntoArrayTRS},
@ -381,20 +370,10 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::childrenFor, &SceneDataTest::childrenFor,
&SceneDataTest::transformation2DFor, &SceneDataTest::transformation2DFor,
&SceneDataTest::transformation2DForTRS, &SceneDataTest::transformation2DForTRS,
&SceneDataTest::transformation2DForBut3DType<Matrix4x4>, &SceneDataTest::transformation2DForBut3DType,
&SceneDataTest::transformation2DForBut3DType<Matrix4x4d>,
&SceneDataTest::transformation2DForBut3DType<DualQuaternion>,
&SceneDataTest::transformation2DForBut3DType<DualQuaterniond>,
&SceneDataTest::transformation2DForBut3DTypeTRS<Float>,
&SceneDataTest::transformation2DForBut3DTypeTRS<Double>,
&SceneDataTest::transformation3DFor, &SceneDataTest::transformation3DFor,
&SceneDataTest::transformation3DForTRS, &SceneDataTest::transformation3DForTRS,
&SceneDataTest::transformation3DForBut2DType<Matrix3x3>, &SceneDataTest::transformation3DForBut2DType,
&SceneDataTest::transformation3DForBut2DType<Matrix3x3d>,
&SceneDataTest::transformation3DForBut2DType<DualComplex>,
&SceneDataTest::transformation3DForBut2DType<DualComplex>,
&SceneDataTest::transformation3DForBut2DTypeTRS<Float>,
&SceneDataTest::transformation3DForBut2DTypeTRS<Double>,
&SceneDataTest::meshesMaterialsFor, &SceneDataTest::meshesMaterialsFor,
&SceneDataTest::lightsFor, &SceneDataTest::lightsFor,
&SceneDataTest::camerasFor, &SceneDataTest::camerasFor,
@ -1136,6 +1115,9 @@ void SceneDataTest::construct() {
CORRADE_COMPARE(scene.fieldCount(), 4); CORRADE_COMPARE(scene.fieldCount(), 4);
CORRADE_COMPARE(scene.importerState(), &importerState); CORRADE_COMPARE(scene.importerState(), &importerState);
/* is2D() / is3D() exhaustively tested in transformations*DAsArray[TRS]()
and constructZeroFields() */
/* Field property access by ID */ /* Field property access by ID */
CORRADE_COMPARE(scene.fieldName(0), SceneField::Transformation); CORRADE_COMPARE(scene.fieldName(0), SceneField::Transformation);
CORRADE_COMPARE(scene.fieldName(1), SceneField::Parent); CORRADE_COMPARE(scene.fieldName(1), SceneField::Parent);
@ -1369,6 +1351,8 @@ void SceneDataTest::constructZeroFields() {
CORRADE_COMPARE(scene.objectCount(), 37563); CORRADE_COMPARE(scene.objectCount(), 37563);
CORRADE_COMPARE(scene.objectType(), SceneObjectType::UnsignedShort); CORRADE_COMPARE(scene.objectType(), SceneObjectType::UnsignedShort);
CORRADE_COMPARE(scene.fieldCount(), 0); CORRADE_COMPARE(scene.fieldCount(), 0);
CORRADE_VERIFY(!scene.is2D());
CORRADE_VERIFY(!scene.is3D());
} }
void SceneDataTest::constructZeroObjects() { void SceneDataTest::constructZeroObjects() {
@ -1660,6 +1644,110 @@ void SceneDataTest::constructMismatchedTRSViews() {
"Trade::SceneData: Trade::SceneField::Scaling object data [0xcafe0000:0xcafe0004] is different from Trade::SceneField::Rotation object data [0xcafe0000:0xcafe0008]\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() { void SceneDataTest::constructMismatchedMeshMaterialView() {
#ifdef CORRADE_NO_ASSERT #ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
@ -1744,48 +1832,6 @@ void SceneDataTest::constructMove() {
CORRADE_VERIFY(std::is_nothrow_move_assignable<SceneData>::value); CORRADE_VERIFY(std::is_nothrow_move_assignable<SceneData>::value);
} }
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(Matrix3x3)
_c(Matrix3d)
_c(Matrix3x3d)
_c(Matrix4)
_c(Matrix4x4)
_c(Matrix4d)
_c(Matrix4x4d)
_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::objectsAsArrayByIndex() { template<class T> void SceneDataTest::objectsAsArrayByIndex() {
setTestCaseTemplateName(NameTraits<T>::name()); setTestCaseTemplateName(NameTraits<T>::name());
@ -2165,6 +2211,8 @@ template<class T> void SceneDataTest::transformations2DAsArray() {
components.slice(&Component::scaling)}, components.slice(&Component::scaling)},
}}; }};
CORRADE_VERIFY(scene.is2D());
CORRADE_VERIFY(!scene.is3D());
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView({ CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView({
Matrix3::translation({3.0f, 2.0f}), Matrix3::translation({3.0f, 2.0f}),
Matrix3::rotation(35.0_degf), Matrix3::rotation(35.0_degf),
@ -2216,6 +2264,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, {
translation translation
}}; }};
CORRADE_VERIFY(scene.is2D());
CORRADE_VERIFY(!scene.is3D());
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({
Matrix3::translation({3.0f, 2.0f}), Matrix3::translation({3.0f, 2.0f}),
Matrix3{Math::IdentityInit}, Matrix3{Math::IdentityInit},
@ -2234,6 +2284,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, {
rotation rotation
}}; }};
CORRADE_VERIFY(scene.is2D());
CORRADE_VERIFY(!scene.is3D());
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({
Matrix3{Math::IdentityInit}, Matrix3{Math::IdentityInit},
Matrix3::rotation(35.0_degf), Matrix3::rotation(35.0_degf),
@ -2252,6 +2304,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, {
scaling scaling
}}; }};
CORRADE_VERIFY(scene.is2D());
CORRADE_VERIFY(!scene.is3D());
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({
Matrix3{Math::IdentityInit}, Matrix3{Math::IdentityInit},
Matrix3{Math::IdentityInit}, Matrix3{Math::IdentityInit},
@ -2274,6 +2328,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
translation, translation,
rotation rotation
}}; }};
CORRADE_VERIFY(scene.is2D());
CORRADE_VERIFY(!scene.is3D());
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({
Matrix3::translation({3.0f, 2.0f}), Matrix3::translation({3.0f, 2.0f}),
Matrix3::rotation(35.0_degf), Matrix3::rotation(35.0_degf),
@ -2293,6 +2349,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
translation, translation,
scaling scaling
}}; }};
CORRADE_VERIFY(scene.is2D());
CORRADE_VERIFY(!scene.is3D());
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({
Matrix3::translation({3.0f, 2.0f}), Matrix3::translation({3.0f, 2.0f}),
Matrix3{Math::IdentityInit}, Matrix3{Math::IdentityInit},
@ -2312,6 +2370,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
rotation, rotation,
scaling scaling
}}; }};
CORRADE_VERIFY(scene.is2D());
CORRADE_VERIFY(!scene.is3D());
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({
Matrix3{Math::IdentityInit}, Matrix3{Math::IdentityInit},
Matrix3::rotation(35.0_degf), Matrix3::rotation(35.0_degf),
@ -2335,6 +2395,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
rotation, rotation,
scaling scaling
}}; }};
CORRADE_VERIFY(scene.is2D());
CORRADE_VERIFY(!scene.is3D());
CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({ CORRADE_COMPARE_AS(scene.transformations2DAsArray(), Containers::arrayView<Matrix3>({
Matrix3::translation({3.0f, 2.0f}), Matrix3::translation({3.0f, 2.0f}),
Matrix3::rotation(35.0_degf), Matrix3::rotation(35.0_degf),
@ -2352,27 +2414,7 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
} }
} }
template<class T> void SceneDataTest::transformations2DAsArrayBut3DType() { void SceneDataTest::transformations2DAsArrayBut3DType() {
setTestCaseTemplateName(NameTraits<T>::name());
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
SceneData scene{SceneObjectType::UnsignedInt, 0, nullptr, {
SceneFieldData{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<T>::type(), nullptr}
}};
std::ostringstream out;
Error redirectError{&out};
scene.transformations2DAsArray();
CORRADE_COMPARE(out.str(), Utility::formatString(
"Trade::SceneData::transformations2DInto(): field has a 3D transformation type Trade::SceneFieldType::{}\n", NameTraits<T>::name()));
}
template<class T> void SceneDataTest::transformations2DAsArrayBut3DTypeTRS() {
setTestCaseTemplateName(NameTraits<T>::name());
#ifdef CORRADE_NO_ASSERT #ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif #endif
@ -2380,40 +2422,19 @@ template<class T> void SceneDataTest::transformations2DAsArrayBut3DTypeTRS() {
/* Because TRSAsArray() allocates an Array<Triple> and then calls /* Because TRSAsArray() allocates an Array<Triple> and then calls
TRSInto(), which skips views that are nullptr, we wouldn't get the TRSInto(), which skips views that are nullptr, we wouldn't get the
assertion for translations, as those are at offset 0, which would be assertion for translations, as those are at offset 0, which would be
interpreted as an empty view if there were no elements. So we have to interpreted as an empty view if there were no elements. Thus using
supply at least one element to make all assertions trigger. */ rotations instead. */
struct Field { SceneData scene{SceneObjectType::UnsignedInt, 0, nullptr, {
UnsignedInt object; SceneFieldData{SceneField::Rotation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Quaternion, nullptr}
Math::Vector3<T> translation;
Math::Quaternion<T> rotation;
Math::Vector3<T> scaling;
} data[1];
Containers::StridedArrayView1D<Field> view = data;
SceneData translation{SceneObjectType::UnsignedInt, 1, {}, data, {
SceneFieldData{SceneField::Translation, view.slice(&Field::object), view.slice(&Field::translation)}
}};
SceneData rotation{SceneObjectType::UnsignedInt, 1, {}, data, {
SceneFieldData{SceneField::Rotation, view.slice(&Field::object), view.slice(&Field::rotation)}
}};
SceneData scaling{SceneObjectType::UnsignedInt, 1, {}, data, {
SceneFieldData{SceneField::Scaling, view.slice(&Field::object), view.slice(&Field::scaling)}
}}; }};
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
translation.transformations2DAsArray(); scene.transformations2DAsArray();
translation.translationsRotationsScalings2DAsArray(); scene.translationsRotationsScalings2DAsArray();
rotation.transformations2DAsArray(); CORRADE_COMPARE(out.str(),
rotation.translationsRotationsScalings2DAsArray(); "Trade::SceneData::transformations2DInto(): scene has a 3D transformation type\n"
scaling.transformations2DAsArray(); "Trade::SceneData::translationsRotationsScalings2DInto(): scene has a 3D transformation type\n");
scaling.translationsRotationsScalings2DAsArray();
CORRADE_COMPARE(out.str(), Utility::formatString(
"Trade::SceneData::transformations2DInto(): field has a 3D translation type Trade::SceneFieldType::{0}\n"
"Trade::SceneData::translationsRotationsScalings2DInto(): field has a 3D translation type Trade::SceneFieldType::{0}\n"
"Trade::SceneData::transformations2DInto(): field has a 3D rotation type Trade::SceneFieldType::{1}\n"
"Trade::SceneData::translationsRotationsScalings2DInto(): field has a 3D rotation type Trade::SceneFieldType::{1}\n"
"Trade::SceneData::transformations2DInto(): field has a 3D scaling type Trade::SceneFieldType::{0}\n"
"Trade::SceneData::translationsRotationsScalings2DInto(): field has a 3D scaling type Trade::SceneFieldType::{0}\n", NameTraits<Math::Vector3<T>>::name(), NameTraits<Math::Quaternion<T>>::name()));
} }
void SceneDataTest::transformations2DIntoArray() { void SceneDataTest::transformations2DIntoArray() {
@ -2740,6 +2761,8 @@ template<class T> void SceneDataTest::transformations3DAsArray() {
components.slice(&Component::scaling)}, components.slice(&Component::scaling)},
}}; }};
CORRADE_VERIFY(!scene.is2D());
CORRADE_VERIFY(scene.is3D());
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView({ CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView({
Matrix4::translation({3.0f, 2.0f, -0.5f}), Matrix4::translation({3.0f, 2.0f, -0.5f}),
Matrix4::rotationY(35.0_degf), Matrix4::rotationY(35.0_degf),
@ -2791,6 +2814,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, {
translation translation
}}; }};
CORRADE_VERIFY(!scene.is2D());
CORRADE_VERIFY(scene.is3D());
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({
Matrix4::translation({3.0f, 2.0, 1.0f}), Matrix4::translation({3.0f, 2.0, 1.0f}),
Matrix4{Math::IdentityInit}, Matrix4{Math::IdentityInit},
@ -2809,6 +2834,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, {
rotation rotation
}}; }};
CORRADE_VERIFY(!scene.is2D());
CORRADE_VERIFY(scene.is3D());
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({
Matrix4{Math::IdentityInit}, Matrix4{Math::IdentityInit},
Matrix4::rotationY(35.0_degf), Matrix4::rotationY(35.0_degf),
@ -2827,6 +2854,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, { SceneData scene{SceneObjectType::UnsignedInt, 8, {}, fields, {
scaling scaling
}}; }};
CORRADE_VERIFY(!scene.is2D());
CORRADE_VERIFY(scene.is3D());
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({
Matrix4{Math::IdentityInit}, Matrix4{Math::IdentityInit},
Matrix4{Math::IdentityInit}, Matrix4{Math::IdentityInit},
@ -2849,6 +2878,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
translation, translation,
rotation rotation
}}; }};
CORRADE_VERIFY(!scene.is2D());
CORRADE_VERIFY(scene.is3D());
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({
Matrix4::translation({3.0f, 2.0, 1.0f}), Matrix4::translation({3.0f, 2.0, 1.0f}),
Matrix4::rotationY(35.0_degf), Matrix4::rotationY(35.0_degf),
@ -2868,6 +2899,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
translation, translation,
scaling scaling
}}; }};
CORRADE_VERIFY(!scene.is2D());
CORRADE_VERIFY(scene.is3D());
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({
Matrix4::translation({3.0f, 2.0, 1.0f}), Matrix4::translation({3.0f, 2.0, 1.0f}),
Matrix4{Math::IdentityInit}, Matrix4{Math::IdentityInit},
@ -2887,6 +2920,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
rotation, rotation,
scaling scaling
}}; }};
CORRADE_VERIFY(!scene.is2D());
CORRADE_VERIFY(scene.is3D());
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({
Matrix4{Math::IdentityInit}, Matrix4{Math::IdentityInit},
Matrix4::rotationY(35.0_degf), Matrix4::rotationY(35.0_degf),
@ -2910,6 +2945,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
rotation, rotation,
scaling scaling
}}; }};
CORRADE_VERIFY(!scene.is2D());
CORRADE_VERIFY(scene.is3D());
CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({ CORRADE_COMPARE_AS(scene.transformations3DAsArray(), Containers::arrayView<Matrix4>({
Matrix4::translation({3.0f, 2.0, 1.0f}), Matrix4::translation({3.0f, 2.0, 1.0f}),
Matrix4::rotationY(35.0_degf), Matrix4::rotationY(35.0_degf),
@ -2927,27 +2964,7 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
} }
} }
template<class T> void SceneDataTest::transformations3DAsArrayBut2DType() { void SceneDataTest::transformations3DAsArrayBut2DType() {
setTestCaseTemplateName(NameTraits<T>::name());
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
SceneData scene{SceneObjectType::UnsignedInt, 0, nullptr, {
SceneFieldData{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<T>::type(), nullptr}
}};
std::ostringstream out;
Error redirectError{&out};
scene.transformations3DAsArray();
CORRADE_COMPARE(out.str(), Utility::formatString(
"Trade::SceneData::transformations3DInto(): field has a 2D transformation type Trade::SceneFieldType::{}\n", NameTraits<T>::name()));
}
template<class T> void SceneDataTest::transformations3DAsArrayBut2DTypeTRS() {
setTestCaseTemplateName(NameTraits<T>::name());
#ifdef CORRADE_NO_ASSERT #ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif #endif
@ -2955,40 +2972,19 @@ template<class T> void SceneDataTest::transformations3DAsArrayBut2DTypeTRS() {
/* Because TRSAsArray() allocates an Array<Triple> and then calls /* Because TRSAsArray() allocates an Array<Triple> and then calls
TRSInto(), which skips views that are nullptr, we wouldn't get the TRSInto(), which skips views that are nullptr, we wouldn't get the
assertion for translations, as those are at offset 0, which would be assertion for translations, as those are at offset 0, which would be
interpreted as an empty view if there were no elements. So we have to interpreted as an empty view if there were no elements. Thus using
supply at least one element to make all assertions trigger. */ rotations instead. */
struct Field { SceneData scene{SceneObjectType::UnsignedInt, 0, nullptr, {
UnsignedInt object; SceneFieldData{SceneField::Rotation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Complex, nullptr}
Math::Vector2<T> translation;
Math::Complex<T> rotation;
Math::Vector2<T> scaling;
} data[1];
Containers::StridedArrayView1D<Field> view = data;
SceneData translation{SceneObjectType::UnsignedInt, 1, {}, data, {
SceneFieldData{SceneField::Translation, view.slice(&Field::object), view.slice(&Field::translation)}
}};
SceneData rotation{SceneObjectType::UnsignedInt, 1, {}, data, {
SceneFieldData{SceneField::Rotation, view.slice(&Field::object), view.slice(&Field::rotation)}
}};
SceneData scaling{SceneObjectType::UnsignedInt, 1, {}, data, {
SceneFieldData{SceneField::Scaling, view.slice(&Field::object), view.slice(&Field::scaling)}
}}; }};
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
translation.transformations3DAsArray(); scene.transformations3DAsArray();
translation.translationsRotationsScalings3DAsArray(); scene.translationsRotationsScalings3DAsArray();
rotation.transformations3DAsArray(); CORRADE_COMPARE(out.str(),
rotation.translationsRotationsScalings3DAsArray(); "Trade::SceneData::transformations3DInto(): scene has a 2D transformation type\n"
scaling.transformations3DAsArray(); "Trade::SceneData::translationsRotationsScalings3DInto(): scene has a 2D transformation type\n");
scaling.translationsRotationsScalings3DAsArray();
CORRADE_COMPARE(out.str(), Utility::formatString(
"Trade::SceneData::transformations3DInto(): field has a 2D translation type Trade::SceneFieldType::{0}\n"
"Trade::SceneData::translationsRotationsScalings3DInto(): field has a 2D translation type Trade::SceneFieldType::{0}\n"
"Trade::SceneData::transformations3DInto(): field has a 2D rotation type Trade::SceneFieldType::{1}\n"
"Trade::SceneData::translationsRotationsScalings3DInto(): field has a 2D rotation type Trade::SceneFieldType::{1}\n"
"Trade::SceneData::transformations3DInto(): field has a 2D scaling type Trade::SceneFieldType::{0}\n"
"Trade::SceneData::translationsRotationsScalings3DInto(): field has a 2D scaling type Trade::SceneFieldType::{0}\n", NameTraits<Math::Vector2<T>>::name(), NameTraits<Math::Complex<T>>::name()));
} }
void SceneDataTest::transformations3DIntoArray() { void SceneDataTest::transformations3DIntoArray() {
@ -4387,56 +4383,22 @@ void SceneDataTest::transformation2DForTRS() {
Containers::NullOpt); Containers::NullOpt);
} }
template<class T> void SceneDataTest::transformation2DForBut3DType() { void SceneDataTest::transformation2DForBut3DType() {
setTestCaseTemplateName(NameTraits<T>::name());
#ifdef CORRADE_NO_ASSERT #ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif #endif
SceneData scene{SceneObjectType::UnsignedInt, 1, nullptr, { SceneData scene{SceneObjectType::UnsignedInt, 1, nullptr, {
SceneFieldData{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<T>::type(), nullptr} SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Vector3, nullptr}
}}; }};
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
scene.transformation2DFor(0); scene.transformation2DFor(0);
CORRADE_COMPARE(out.str(), Utility::formatString( scene.translationRotationScaling2DFor(0);
"Trade::SceneData::transformation2DFor(): field has a 3D transformation type Trade::SceneFieldType::{}\n", NameTraits<T>::name())); CORRADE_COMPARE(out.str(),
} "Trade::SceneData::transformation2DFor(): scene has a 3D transformation type\n"
"Trade::SceneData::translationRotationScaling2DFor(): scene has a 3D transformation type\n");
template<class T> void SceneDataTest::transformation2DForBut3DTypeTRS() {
setTestCaseTemplateName(NameTraits<T>::name());
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
SceneData translation{SceneObjectType::UnsignedInt, 1, nullptr, {
SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Vector3<T>>::type(), nullptr}
}};
SceneData rotation{SceneObjectType::UnsignedInt, 1, nullptr, {
SceneFieldData{SceneField::Rotation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Quaternion<T>>::type(), nullptr}
}};
SceneData scaling{SceneObjectType::UnsignedInt, 1, nullptr, {
SceneFieldData{SceneField::Scaling, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Vector3<T>>::type(), nullptr}
}};
std::ostringstream out;
Error redirectError{&out};
translation.transformation2DFor(0);
translation.translationRotationScaling2DFor(0);
rotation.transformation2DFor(0);
rotation.translationRotationScaling2DFor(0);
scaling.transformation2DFor(0);
scaling.translationRotationScaling2DFor(0);
CORRADE_COMPARE(out.str(), Utility::formatString(
"Trade::SceneData::transformation2DFor(): field has a 3D translation type Trade::SceneFieldType::{0}\n"
"Trade::SceneData::translationRotationScaling2DFor(): field has a 3D translation type Trade::SceneFieldType::{0}\n"
"Trade::SceneData::transformation2DFor(): field has a 3D rotation type Trade::SceneFieldType::{1}\n"
"Trade::SceneData::translationRotationScaling2DFor(): field has a 3D rotation type Trade::SceneFieldType::{1}\n"
"Trade::SceneData::transformation2DFor(): field has a 3D scaling type Trade::SceneFieldType::{0}\n"
"Trade::SceneData::translationRotationScaling2DFor(): field has a 3D scaling type Trade::SceneFieldType::{0}\n", NameTraits<Math::Vector3<T>>::name(), NameTraits<Math::Quaternion<T>>::name()));
} }
void SceneDataTest::transformation3DFor() { void SceneDataTest::transformation3DFor() {
@ -4513,56 +4475,22 @@ void SceneDataTest::transformation3DForTRS() {
Containers::NullOpt); Containers::NullOpt);
} }
template<class T> void SceneDataTest::transformation3DForBut2DType() { void SceneDataTest::transformation3DForBut2DType() {
setTestCaseTemplateName(NameTraits<T>::name());
#ifdef CORRADE_NO_ASSERT #ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif #endif
SceneData scene{SceneObjectType::UnsignedInt, 1, nullptr, { SceneData scene{SceneObjectType::UnsignedInt, 1, nullptr, {
SceneFieldData{SceneField::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<T>::type(), nullptr} SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Vector2, nullptr}
}}; }};
std::ostringstream out; std::ostringstream out;
Error redirectError{&out}; Error redirectError{&out};
scene.transformation3DFor(0); scene.transformation3DFor(0);
CORRADE_COMPARE(out.str(), Utility::formatString( scene.translationRotationScaling3DFor(0);
"Trade::SceneData::transformation3DFor(): field has a 2D transformation type Trade::SceneFieldType::{}\n", NameTraits<T>::name())); CORRADE_COMPARE(out.str(),
} "Trade::SceneData::transformation3DFor(): scene has a 2D transformation type\n"
"Trade::SceneData::translationRotationScaling3DFor(): scene has a 2D transformation type\n");
template<class T> void SceneDataTest::transformation3DForBut2DTypeTRS() {
setTestCaseTemplateName(NameTraits<T>::name());
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
SceneData translation{SceneObjectType::UnsignedInt, 1, nullptr, {
SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Vector2<T>>::type(), nullptr}
}};
SceneData rotation{SceneObjectType::UnsignedInt, 1, nullptr, {
SceneFieldData{SceneField::Rotation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Complex<T>>::type(), nullptr}
}};
SceneData scaling{SceneObjectType::UnsignedInt, 1, nullptr, {
SceneFieldData{SceneField::Scaling, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<Math::Vector2<T>>::type(), nullptr}
}};
std::ostringstream out;
Error redirectError{&out};
translation.transformation3DFor(0);
translation.translationRotationScaling3DFor(0);
rotation.transformation3DFor(0);
rotation.translationRotationScaling3DFor(0);
scaling.transformation3DFor(0);
scaling.translationRotationScaling3DFor(0);
CORRADE_COMPARE(out.str(), Utility::formatString(
"Trade::SceneData::transformation3DFor(): field has a 2D translation type Trade::SceneFieldType::{0}\n"
"Trade::SceneData::translationRotationScaling3DFor(): field has a 2D translation type Trade::SceneFieldType::{0}\n"
"Trade::SceneData::transformation3DFor(): field has a 2D rotation type Trade::SceneFieldType::{1}\n"
"Trade::SceneData::translationRotationScaling3DFor(): field has a 2D rotation type Trade::SceneFieldType::{1}\n"
"Trade::SceneData::transformation3DFor(): field has a 2D scaling type Trade::SceneFieldType::{0}\n"
"Trade::SceneData::translationRotationScaling3DFor(): field has a 2D scaling type Trade::SceneFieldType::{0}\n", NameTraits<Math::Vector2<T>>::name(), NameTraits<Math::Complex<T>>::name()));
} }
void SceneDataTest::meshesMaterialsFor() { void SceneDataTest::meshesMaterialsFor() {

Loading…
Cancel
Save