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)};
}
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 */
CORRADE_ASSERT(
(objectType == SceneObjectType::UnsignedByte && objectCount <= 0xffull) ||
@ -376,14 +376,19 @@ SceneData::SceneData(const SceneObjectType objectType, const UnsignedLong object
/* Check various assumptions about field data */
Math::BoolVector<12> fieldsPresent; /** @todo some constant for this */
const UnsignedInt objectTypeSize = sceneObjectTypeSize(_objectType);
#endif
UnsignedInt transformationField = ~UnsignedInt{};
UnsignedInt translationField = ~UnsignedInt{};
UnsignedInt rotationField = ~UnsignedInt{};
UnsignedInt scalingField = ~UnsignedInt{};
#ifndef CORRADE_NO_ASSERT
UnsignedInt meshField = ~UnsignedInt{};
UnsignedInt meshMaterialField = ~UnsignedInt{};
#endif
for(std::size_t i = 0; i != _fields.size(); ++i) {
const SceneFieldData& field = _fields[i];
#ifndef CORRADE_NO_ASSERT
/* 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
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 << "]", );
}
}
#endif
/* Remember TRS and mesh/material fields to check their object mapping
consistency outside of the loop below */
if(_fields[i]._name == SceneField::Translation) {
/* Remember TRS and mesh/material fields to figure out whether the
scene is 2D or 3D and check their object mapping consistency outside
of the loop below */
if(_fields[i]._name == SceneField::Transformation) {
transformationField = i;
} else if(_fields[i]._name == SceneField::Translation) {
translationField = i;
} else if(_fields[i]._name == SceneField::Rotation) {
rotationField = i;
} else if(_fields[i]._name == SceneField::Scaling) {
scalingField = i;
} else if(_fields[i]._name == SceneField::Mesh) {
}
#ifndef CORRADE_NO_ASSERT
else if(_fields[i]._name == SceneField::Mesh) {
meshField = i;
} else if(_fields[i]._name == SceneField::MeshMaterial) {
meshMaterialField = i;
}
#endif
}
#ifndef CORRADE_NO_ASSERT
/* 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
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{})
checkFieldObjectDataMatch(_fields[meshField], _fields[meshMaterialField]);
#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} {}
@ -903,6 +977,10 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
/* *FieldId, offset and destination.size() is assumed to be in bounds (or
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? */
/* Prefer the transformation field, if present */
@ -919,11 +997,6 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
convertTransformation<DualComplex>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::DualComplexd) {
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 */
/* If not, combine from TRS components */
@ -941,9 +1014,6 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
applyScaling<Vector2>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Vector2d) {
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 */
}
@ -956,9 +1026,6 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
applyRotation<Complex>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Complexd) {
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 */
}
@ -971,9 +1038,6 @@ void SceneData::transformations2DIntoInternal(const UnsignedInt transformationFi
applyTranslation<Vector2>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Vector2d) {
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 */
}
@ -1022,6 +1086,10 @@ void SceneData::translationsRotationsScalings2DIntoInternal(const UnsignedInt tr
/* *FieldId, offset and *Destination.size() is assumed to be in bounds (or
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
vector for all objects. */
if(translationDestination) {
@ -1036,9 +1104,6 @@ void SceneData::translationsRotationsScalings2DIntoInternal(const UnsignedInt tr
Utility::copy(Containers::arrayCast<const Vector2>(fieldData), translationDestination);
} else if(field._fieldType == SceneFieldType::Vector2d) {
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 */
}
}
@ -1057,9 +1122,6 @@ void SceneData::translationsRotationsScalings2DIntoInternal(const UnsignedInt tr
Utility::copy(Containers::arrayCast<const Complex>(fieldData), rotationDestination);
} else if(field._fieldType == SceneFieldType::Complexd) {
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 */
}
}
@ -1078,9 +1140,6 @@ void SceneData::translationsRotationsScalings2DIntoInternal(const UnsignedInt tr
Utility::copy(Containers::arrayCast<const Vector2>(fieldData), scalingDestination);
} else if(field._fieldType == SceneFieldType::Vector2d) {
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 */
}
}
@ -1144,6 +1203,10 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
/* *FieldId, offset and destination.size() is assumed to be in bounds (or
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? */
/* Prefer the transformation field, if present */
@ -1160,11 +1223,6 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
convertTransformation<DualQuaternion>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::DualQuaterniond) {
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 */
/* If not, combine from TRS components */
@ -1182,9 +1240,6 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
applyScaling<Vector3>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Vector3d) {
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 */
}
@ -1197,9 +1252,6 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
applyRotation<Quaternion>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Quaterniond) {
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 */
}
@ -1212,9 +1264,6 @@ void SceneData::transformations3DIntoInternal(const UnsignedInt transformationFi
applyTranslation<Vector3>(fieldData, destination);
} else if(field._fieldType == SceneFieldType::Vector3d) {
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 */
}
@ -1263,6 +1312,10 @@ void SceneData::translationsRotationsScalings3DIntoInternal(const UnsignedInt tr
/* *FieldId, offset and *Destination.size() is assumed to be in bounds (or
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
vector for all objects. */
if(translationDestination) {
@ -1277,9 +1330,6 @@ void SceneData::translationsRotationsScalings3DIntoInternal(const UnsignedInt tr
Utility::copy(Containers::arrayCast<const Vector3>(fieldData), translationDestination);
} else if(field._fieldType == SceneFieldType::Vector3d) {
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 */
}
}
@ -1298,9 +1348,6 @@ void SceneData::translationsRotationsScalings3DIntoInternal(const UnsignedInt tr
Utility::copy(Containers::arrayCast<const Quaternion>(fieldData), rotationDestination);
} else if(field._fieldType == SceneFieldType::Quaterniond) {
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 */
}
}
@ -1319,9 +1366,6 @@ void SceneData::translationsRotationsScalings3DIntoInternal(const UnsignedInt tr
Utility::copy(Containers::arrayCast<const Vector3>(fieldData), scalingDestination);
} else if(field._fieldType == SceneFieldType::Vector3d) {
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 */
}
}
@ -1698,39 +1742,9 @@ Containers::Optional<Matrix3> SceneData::transformation2DFor(const UnsignedInt o
UnsignedInt transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, fieldWithObjectMapping;
if(findTransformFields(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, &fieldWithObjectMapping) == ~std::size_t{}) return {};
#ifndef CORRADE_NO_ASSERT
if(transformationFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[transformationFieldId]._fieldType;
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
/* If is2D() returned false as well, all *FieldId would be invalid, which
is handled above. */
CORRADE_ASSERT(!is3D(), "Trade::SceneData::transformation2DFor(): scene has a 3D transformation type", {});
const std::size_t offset = fieldFor(_fields[fieldWithObjectMapping], 0, object);
if(offset == _fields[fieldWithObjectMapping]._size) return {};
@ -1747,29 +1761,9 @@ Containers::Optional<Containers::Triple<Vector2, Complex, Vector2>> SceneData::t
UnsignedInt translationFieldId, rotationFieldId, scalingFieldId, fieldWithObjectMapping;
if(findTranslationRotationScalingFields(translationFieldId, rotationFieldId, scalingFieldId, &fieldWithObjectMapping) == ~std::size_t{}) return {};
#ifndef CORRADE_NO_ASSERT
if(translationFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[translationFieldId]._fieldType;
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
/* If is2D() returned false as well, all *FieldId would be invalid, which
is handled above. */
CORRADE_ASSERT(!is3D(), "Trade::SceneData::translationRotationScaling2DFor(): scene has a 3D transformation type", {});
const std::size_t offset = fieldFor(_fields[fieldWithObjectMapping], 0, object);
if(offset == _fields[fieldWithObjectMapping]._size) return {};
@ -1788,39 +1782,9 @@ Containers::Optional<Matrix4> SceneData::transformation3DFor(const UnsignedInt o
UnsignedInt transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, fieldWithObjectMapping;
if(findTransformFields(transformationFieldId, translationFieldId, rotationFieldId, scalingFieldId, &fieldWithObjectMapping) == ~std::size_t{}) return {};
#ifndef CORRADE_NO_ASSERT
if(transformationFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[transformationFieldId]._fieldType;
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
/* If is3D() returned false as well, all *FieldId would be invalid, which
is handled above. */
CORRADE_ASSERT(!is2D(), "Trade::SceneData::transformation3DFor(): scene has a 2D transformation type", {});
const std::size_t offset = fieldFor(_fields[fieldWithObjectMapping], 0, object);
if(offset == _fields[fieldWithObjectMapping]._size) return {};
@ -1837,29 +1801,9 @@ Containers::Optional<Containers::Triple<Vector3, Quaternion, Vector3>> SceneData
UnsignedInt translationFieldId, rotationFieldId, scalingFieldId, fieldWithObjectMapping;
if(findTranslationRotationScalingFields(translationFieldId, rotationFieldId, scalingFieldId, &fieldWithObjectMapping) == ~std::size_t{}) return {};
#ifndef CORRADE_NO_ASSERT
if(translationFieldId != ~UnsignedInt{}) {
const SceneFieldType type = _fields[translationFieldId]._fieldType;
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
/* If is3D() returned false as well, all *FieldId would be invalid, which
is handled above. */
CORRADE_ASSERT(!is2D(), "Trade::SceneData::translationRotationScaling3DFor(): scene has a 2D transformation type", {});
const std::size_t offset = fieldFor(_fields[fieldWithObjectMapping], 0, object);
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
* @ref SceneField::Translation, @ref SceneField::Rotation and
* @ref SceneField::Scaling fields. 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 SceneField::Scaling fields. All present transformation-related
* fields are expected to have the same dimensionality --- either all 2D or
* 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::transformations3DAsArray() then takes into account only
* the combined transformation field. TRS fields can however be specified
* only for a subset of transformed objects, useful for example when only
* 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::transformation2DFor(),
* @ref SceneData::transformation3DFor()
@ -146,11 +149,13 @@ enum class SceneField: UnsignedInt {
*
* The translation field usually is (but doesn't have to be) complemented
* 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
* or be provided just for a subset of it --- see its documentation for
* details.
* @see @ref SceneData::transformations2DAsArray(),
* @see @ref SceneData::is2D(), @ref SceneData::is3D(),
* @ref SceneData::transformations2DAsArray(),
* @ref SceneData::transformations3DAsArray(),
* @ref SceneData::transformation2DFor(),
* @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
* @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
* or be provided just for a subset of it --- see its documentation for
* details.
* @see @ref SceneData::transformations2DAsArray(),
* @see @ref SceneData::is2D(), @ref SceneData::is3D(),
* @ref SceneData::transformations2DAsArray(),
* @ref SceneData::transformations3DAsArray(),
* @ref SceneData::transformation2DFor(),
* @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
* @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
* or be provided just for a subset of it --- see its documentation for
* details.
* @see @ref SceneData::transformations2DAsArray(),
* @see @ref SceneData::is2D(), @ref SceneData::is3D(),
* @ref SceneData::transformations2DAsArray(),
* @ref SceneData::transformations3DAsArray(),
* @ref SceneData::transformation2DFor(),
* @ref SceneData::transformation3DFor(),
@ -993,9 +1002,47 @@ class MAGNUM_TRADE_EXPORT SceneData {
*/
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
* @m_since_latest
*
* @see @ref is2D(), @ref is3D()
*/
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
* to 2D, otherwise you're supposed to use
* @ref transformations3DAsArray().
* @see @ref transformations2DInto(), @ref hasField(),
* @see @ref is2D(), @ref transformations2DInto(), @ref hasField(),
* @ref fieldType(SceneField) const, @ref transformation2DFor()
*/
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
* the @relativeref{SceneField,Scaling} field isn't present, the third
* value is an identity scaling (@cpp 1.0f @ce in both dimensions).
* @see @ref translationsRotationsScalings2DInto(), @ref hasField(),
* @ref fieldType(SceneField) const,
* @see @ref is2D(), @ref translationsRotationsScalings2DInto(),
* @ref hasField(), @ref fieldType(SceneField) const,
* @ref translationRotationScaling2DFor()
*/
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
* to 3D, otherwise you're supposed to use
* @ref transformations2DAsArray().
* @see @ref transformations3DInto(), @ref hasField(),
* @see @ref is3D(), @ref transformations3DInto(), @ref hasField(),
* @ref fieldType(SceneField) const, @ref transformation3DFor()
*/
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
* the @relativeref{SceneField,Scaling} field isn't present, the third
* value is an identity scaling (@cpp 1.0f @ce in all dimensions).
* @see @ref translationsRotationsScalings3DInto(), @ref hasField(),
* @ref fieldType(SceneField) const,
* @see @ref is3D(), @ref translationsRotationsScalings3DInto(),
* @ref hasField(), @ref fieldType(SceneField) const,
* @ref translationRotationScaling3DFor()
*/
Containers::Array<Containers::Triple<Vector3, Quaternion, Vector3>> translationsRotationsScalings3DAsArray() const;
@ -2114,7 +2161,8 @@ class MAGNUM_TRADE_EXPORT SceneData {
DataFlags _dataFlags;
SceneObjectType _objectType;
/* 2/6 bytes free */
UnsignedByte _dimensions;
/* 1/5 bytes free */
UnsignedLong _objectCount;
const void* _importerState;
Containers::Array<SceneFieldData> _fields;

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

@ -96,6 +96,7 @@ struct SceneDataTest: TestSuite::Tester {
void constructObjectTypeTooSmall();
void constructNotOwnedFlagOwned();
void constructMismatchedTRSViews();
template<class T> void constructMismatchedTRSDimensionality();
void constructMismatchedMeshMaterialView();
void constructCopy();
@ -115,16 +116,14 @@ struct SceneDataTest: TestSuite::Tester {
void parentsIntoArrayInvalidSizeOrOffset();
template<class T> void transformations2DAsArray();
template<class T, class U, class V> void transformations2DAsArrayTRS();
template<class T> void transformations2DAsArrayBut3DType();
template<class T> void transformations2DAsArrayBut3DTypeTRS();
void transformations2DAsArrayBut3DType();
void transformations2DIntoArray();
void transformations2DIntoArrayTRS();
void transformations2DIntoArrayInvalidSizeOrOffset();
void transformations2DIntoArrayInvalidSizeOrOffsetTRS();
template<class T> void transformations3DAsArray();
template<class T, class U, class V> void transformations3DAsArrayTRS();
template<class T> void transformations3DAsArrayBut2DType();
template<class T> void transformations3DAsArrayBut2DTypeTRS();
void transformations3DAsArrayBut2DType();
void transformations3DIntoArray();
void transformations3DIntoArrayTRS();
void transformations3DIntoArrayInvalidSizeOrOffset();
@ -161,12 +160,10 @@ struct SceneDataTest: TestSuite::Tester {
void childrenFor();
void transformation2DFor();
void transformation2DForTRS();
template<class T> void transformation2DForBut3DType();
template<class T> void transformation2DForBut3DTypeTRS();
void transformation2DForBut3DType();
void transformation3DFor();
void transformation3DForTRS();
template<class T> void transformation3DForBut2DType();
template<class T> void transformation3DForBut2DTypeTRS();
void transformation3DForBut2DType();
void meshesMaterialsFor();
void lightsFor();
void camerasFor();
@ -253,6 +250,8 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::constructObjectTypeTooSmall,
&SceneDataTest::constructNotOwnedFlagOwned,
&SceneDataTest::constructMismatchedTRSViews,
&SceneDataTest::constructMismatchedTRSDimensionality<Float>,
&SceneDataTest::constructMismatchedTRSDimensionality<Double>,
&SceneDataTest::constructMismatchedMeshMaterialView,
&SceneDataTest::constructCopy,
@ -292,12 +291,7 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::transformations2DAsArray<DualComplexd>,
&SceneDataTest::transformations2DAsArrayTRS<Float, Float, Double>,
&SceneDataTest::transformations2DAsArrayTRS<Double, Double, Float>,
&SceneDataTest::transformations2DAsArrayBut3DType<Matrix4x4>,
&SceneDataTest::transformations2DAsArrayBut3DType<Matrix4x4d>,
&SceneDataTest::transformations2DAsArrayBut3DType<DualQuaternion>,
&SceneDataTest::transformations2DAsArrayBut3DType<DualQuaterniond>,
&SceneDataTest::transformations2DAsArrayBut3DTypeTRS<Float>,
&SceneDataTest::transformations2DAsArrayBut3DTypeTRS<Double>});
&SceneDataTest::transformations2DAsArrayBut3DType});
addInstancedTests({&SceneDataTest::transformations2DIntoArray,
&SceneDataTest::transformations2DIntoArrayTRS},
@ -311,12 +305,7 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::transformations3DAsArray<DualQuaterniond>,
&SceneDataTest::transformations3DAsArrayTRS<Float, Double, Double>,
&SceneDataTest::transformations3DAsArrayTRS<Double, Float, Float>,
&SceneDataTest::transformations3DAsArrayBut2DType<Matrix3x3>,
&SceneDataTest::transformations3DAsArrayBut2DType<Matrix3x3d>,
&SceneDataTest::transformations3DAsArrayBut2DType<DualComplex>,
&SceneDataTest::transformations3DAsArrayBut2DType<DualComplexd>,
&SceneDataTest::transformations3DAsArrayBut2DTypeTRS<Float>,
&SceneDataTest::transformations3DAsArrayBut2DTypeTRS<Double>});
&SceneDataTest::transformations3DAsArrayBut2DType});
addInstancedTests({&SceneDataTest::transformations3DIntoArray,
&SceneDataTest::transformations3DIntoArrayTRS},
@ -381,20 +370,10 @@ SceneDataTest::SceneDataTest() {
&SceneDataTest::childrenFor,
&SceneDataTest::transformation2DFor,
&SceneDataTest::transformation2DForTRS,
&SceneDataTest::transformation2DForBut3DType<Matrix4x4>,
&SceneDataTest::transformation2DForBut3DType<Matrix4x4d>,
&SceneDataTest::transformation2DForBut3DType<DualQuaternion>,
&SceneDataTest::transformation2DForBut3DType<DualQuaterniond>,
&SceneDataTest::transformation2DForBut3DTypeTRS<Float>,
&SceneDataTest::transformation2DForBut3DTypeTRS<Double>,
&SceneDataTest::transformation2DForBut3DType,
&SceneDataTest::transformation3DFor,
&SceneDataTest::transformation3DForTRS,
&SceneDataTest::transformation3DForBut2DType<Matrix3x3>,
&SceneDataTest::transformation3DForBut2DType<Matrix3x3d>,
&SceneDataTest::transformation3DForBut2DType<DualComplex>,
&SceneDataTest::transformation3DForBut2DType<DualComplex>,
&SceneDataTest::transformation3DForBut2DTypeTRS<Float>,
&SceneDataTest::transformation3DForBut2DTypeTRS<Double>,
&SceneDataTest::transformation3DForBut2DType,
&SceneDataTest::meshesMaterialsFor,
&SceneDataTest::lightsFor,
&SceneDataTest::camerasFor,
@ -1136,6 +1115,9 @@ void SceneDataTest::construct() {
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);
@ -1369,6 +1351,8 @@ void SceneDataTest::constructZeroFields() {
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() {
@ -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");
}
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");
@ -1744,48 +1832,6 @@ void SceneDataTest::constructMove() {
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() {
setTestCaseTemplateName(NameTraits<T>::name());
@ -2165,6 +2211,8 @@ template<class T> void SceneDataTest::transformations2DAsArray() {
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),
@ -2216,6 +2264,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
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},
@ -2234,6 +2284,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
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),
@ -2252,6 +2304,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
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},
@ -2274,6 +2328,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
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),
@ -2293,6 +2349,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
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},
@ -2312,6 +2370,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
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),
@ -2335,6 +2395,8 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
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),
@ -2352,27 +2414,7 @@ template<class T, class U, class V> void SceneDataTest::transformations2DAsArray
}
}
template<class T> 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());
void SceneDataTest::transformations2DAsArrayBut3DType() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
@ -2380,40 +2422,19 @@ template<class T> void SceneDataTest::transformations2DAsArrayBut3DTypeTRS() {
/* 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. So we have to
supply at least one element to make all assertions trigger. */
struct Field {
UnsignedInt object;
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)}
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};
translation.transformations2DAsArray();
translation.translationsRotationsScalings2DAsArray();
rotation.transformations2DAsArray();
rotation.translationsRotationsScalings2DAsArray();
scaling.transformations2DAsArray();
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()));
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() {
@ -2740,6 +2761,8 @@ template<class T> void SceneDataTest::transformations3DAsArray() {
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),
@ -2791,6 +2814,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
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},
@ -2809,6 +2834,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
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),
@ -2827,6 +2854,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
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},
@ -2849,6 +2878,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
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),
@ -2868,6 +2899,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
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},
@ -2887,6 +2920,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
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),
@ -2910,6 +2945,8 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
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),
@ -2927,27 +2964,7 @@ template<class T, class U, class V> void SceneDataTest::transformations3DAsArray
}
}
template<class T> 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());
void SceneDataTest::transformations3DAsArrayBut2DType() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
@ -2955,40 +2972,19 @@ template<class T> void SceneDataTest::transformations3DAsArrayBut2DTypeTRS() {
/* 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. So we have to
supply at least one element to make all assertions trigger. */
struct Field {
UnsignedInt object;
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)}
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};
translation.transformations3DAsArray();
translation.translationsRotationsScalings3DAsArray();
rotation.transformations3DAsArray();
rotation.translationsRotationsScalings3DAsArray();
scaling.transformations3DAsArray();
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()));
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() {
@ -4387,56 +4383,22 @@ void SceneDataTest::transformation2DForTRS() {
Containers::NullOpt);
}
template<class T> void SceneDataTest::transformation2DForBut3DType() {
setTestCaseTemplateName(NameTraits<T>::name());
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::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<T>::type(), nullptr}
SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Vector3, nullptr}
}};
std::ostringstream out;
Error redirectError{&out};
scene.transformation2DFor(0);
CORRADE_COMPARE(out.str(), Utility::formatString(
"Trade::SceneData::transformation2DFor(): field has a 3D transformation type Trade::SceneFieldType::{}\n", NameTraits<T>::name()));
}
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()));
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() {
@ -4513,56 +4475,22 @@ void SceneDataTest::transformation3DForTRS() {
Containers::NullOpt);
}
template<class T> void SceneDataTest::transformation3DForBut2DType() {
setTestCaseTemplateName(NameTraits<T>::name());
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::Transformation, SceneObjectType::UnsignedInt, nullptr, Implementation::SceneFieldTypeFor<T>::type(), nullptr}
SceneFieldData{SceneField::Translation, SceneObjectType::UnsignedInt, nullptr, SceneFieldType::Vector2, nullptr}
}};
std::ostringstream out;
Error redirectError{&out};
scene.transformation3DFor(0);
CORRADE_COMPARE(out.str(), Utility::formatString(
"Trade::SceneData::transformation3DFor(): field has a 2D transformation type Trade::SceneFieldType::{}\n", NameTraits<T>::name()));
}
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()));
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() {

Loading…
Cancel
Save