Browse Source

Trade: correctly copy skins alongside duplicated multi-mesh objects.

This is implemented in a generic way internally, to allow copying of
arbitrary fields, not just skins for meshes, in the upcoming SceneTools
utility.
pull/525/head
Vladimír Vondruš 4 years ago
parent
commit
b6200d0d93
  1. 2
      src/Magnum/Trade/AbstractImporter.cpp
  2. 110
      src/Magnum/Trade/Implementation/sceneTools.h
  3. 30
      src/Magnum/Trade/Test/AbstractImporterTest.cpp
  4. 89
      src/Magnum/Trade/Test/SceneToolsTest.cpp

2
src/Magnum/Trade/AbstractImporter.cpp

@ -531,7 +531,7 @@ void AbstractImporter::populateCachedScenes() {
compatibility code path anyway, so just skip the processing
altogether in that case. */
if(_cachedScenes->scenes[i]->hasField(SceneField::Parent))
_cachedScenes->scenes[i] = Implementation::sceneConvertToSingleFunctionObjects(*_cachedScenes->scenes[i], Containers::arrayView({SceneField::Mesh, SceneField::Camera, SceneField::Light}), newObjectOffset);
_cachedScenes->scenes[i] = Implementation::sceneConvertToSingleFunctionObjects(*_cachedScenes->scenes[i], Containers::arrayView({SceneField::Mesh, SceneField::Camera, SceneField::Light}), Containers::arrayView({SceneField::Skin}), newObjectOffset);
/* Return the 2D/3D object count based on which scenes are 2D and
which not. The objectCount() provided by the importer is ignored

110
src/Magnum/Trade/Implementation/sceneTools.h

@ -191,20 +191,28 @@ inline SceneData sceneCombine(const SceneMappingType mappingType, const Unsigned
return SceneData{mappingType, mappingBound, std::move(outData), std::move(outFields)};
}
inline Containers::Optional<std::size_t> findField(Containers::ArrayView<const SceneField> fields, SceneField field) {
for(std::size_t i = 0; i != fields.size(); ++i)
if(fields[i] == field) return i;
return {};
}
/* Creates a SceneData copy where each object has at most one of the fields
listed in the passed array. This is done by enlarging the parents array
and moving extraneous features to new objects that are marked as a child of
the original. No transformations or other fields are added for the new
objects. Fields that are connected together (such as meshes and materials)
are assumed to share the same object mapping with only one of them passed in
the fieldsToConvert array, which will result for all fields from the same
set being reassociated to the new object.
listed in the passed `fieldsToConvert` array. This is done by enlarging the
parents array and moving extraneous features to new objects that are marked
as a child of the original. Fields that are connected together (such as
meshes and materials) are assumed to share the same object mapping with only
one of them passed in the fieldsToConvert array, which will result for all
fields from the same set being reassociated to the new object.
Fields listed in `fieldsToCopy` are copied from the original object. This
is useful for e.g. skins, to preserve them for the separated meshes.
Requies a SceneField::Parent to be present -- otherwise it wouldn't be
possible to know where to attach the new objects. */
/** @todo when published, (again) add an initializer_list overload and turn all
internal asserts into (tested!) message asserts */
inline SceneData sceneConvertToSingleFunctionObjects(const SceneData& scene, Containers::ArrayView<const SceneField> fieldsToConvert, const UnsignedInt newObjectOffset) {
inline SceneData sceneConvertToSingleFunctionObjects(const SceneData& scene, Containers::ArrayView<const SceneField> fieldsToConvert, Containers::ArrayView<const SceneField> fieldsToCopy, const UnsignedInt newObjectOffset) {
/** @todo assert for really high object counts (where this cast would fail) */
Containers::Array<UnsignedInt> objectAttachmentCount{ValueInit, std::size_t(scene.mappingBound())};
for(const SceneField field: fieldsToConvert) {
@ -224,6 +232,28 @@ inline SceneData sceneConvertToSingleFunctionObjects(const SceneData& scene, Con
}
}
/* entriesToAddToFieldsToCopy[i] specifies how many fields to add for the
fieldsToCopy[i] field */
Containers::Array<UnsignedInt> fieldsToCopyAdditionCount{ValueInit, fieldsToCopy.size()};
for(std::size_t i = 0; i != fieldsToCopy.size(); ++i) {
const SceneField field = fieldsToCopy[i];
CORRADE_INTERNAL_ASSERT(field != SceneField::Parent);
CORRADE_INTERNAL_ASSERT(!findField(fieldsToConvert, field));
/* Skip fields that are not present */
const Containers::Optional<UnsignedInt> fieldId = scene.findFieldId(field);
if(!fieldId) continue;
/** @todo use a statically-allocated array & Into() in a loop instead
once this is more than a private backwards-compatibility utility
where PERF WHATEVER WHO CARES */
for(const UnsignedInt object: scene.mappingAsArray(*fieldId)) {
CORRADE_INTERNAL_ASSERT(object < objectAttachmentCount.size());
if(objectAttachmentCount[object])
fieldsToCopyAdditionCount[i] += objectAttachmentCount[object] - 1;
}
}
UnsignedInt objectsToAdd = 0;
for(const UnsignedInt count: objectAttachmentCount)
if(count > 1) objectsToAdd += count - 1;
@ -239,9 +269,26 @@ inline SceneData sceneConvertToSingleFunctionObjects(const SceneData& scene, Con
for(std::size_t i = 0; i != scene.fieldCount(); ++i) {
const SceneFieldData& field = scene.fieldData(i);
/* If this field is among the fields we want to copy, enlarge it for
the new entries */
if(Containers::Optional<std::size_t> fieldToCopy = findField(fieldsToCopy, field.name())) {
/** @todo wow this placeholder construction is HIDEOUS */
fields[i] = SceneFieldData{field.name(),
field.mappingType(),
Containers::ArrayView<const UnsignedInt>{nullptr, std::size_t(field.size() + fieldsToCopyAdditionCount[*fieldToCopy])},
field.fieldType(),
Containers::StridedArrayView1D<const void>{
{nullptr, ~std::size_t{}},
std::size_t(field.size() + fieldsToCopyAdditionCount[*fieldToCopy]),
std::ptrdiff_t((field.fieldArraySize() ? field.fieldArraySize() : 1)*sceneFieldTypeSize(field.fieldType()))
},
field.fieldArraySize(),
field.flags() & ~SceneFieldFlag::ImplicitMapping
};
/* If this is a parent, enlarge it for the newly added objects, and if
it was implicit make it ordered */
if(field.name() == SceneField::Parent) {
} else if(field.name() == SceneField::Parent) {
/** @todo some nicer constructor for placeholders once this is in
public interest */
fields[i] = SceneFieldData{SceneField::Parent, Containers::ArrayView<const UnsignedInt>{nullptr, std::size_t(field.size() + objectsToAdd)}, Containers::ArrayView<const Int>{nullptr, std::size_t(field.size() + objectsToAdd)},
@ -269,6 +316,19 @@ inline SceneData sceneConvertToSingleFunctionObjects(const SceneData& scene, Con
const Containers::StridedArrayView1D<Int> outParents = out.mutableField<Int>(parentFieldId);
CORRADE_INTERNAL_ASSERT_OUTPUT(scene.parentsInto(0, outParentMapping, outParents) == scene.fieldSize(parentFieldId));
/* Copy existing field-to-copy data to a prefix of the output */
for(std::size_t i = 0; i != fieldsToCopy.size(); ++i) {
const SceneField field = fieldsToCopy[i];
const Containers::Optional<UnsignedInt> fieldId = scene.findFieldId(field);
if(!fieldId) continue;
const Containers::StridedArrayView1D<UnsignedInt> outMapping = out.mutableMapping<UnsignedInt>(*fieldId);
const Containers::StridedArrayView2D<char> outField = out.mutableField(*fieldId);
CORRADE_INTERNAL_ASSERT_OUTPUT(scene.mappingInto(*fieldId, 0, outMapping) == scene.fieldSize(*fieldId));
Utility::copy(scene.field(*fieldId), outField.prefix(scene.fieldSize(*fieldId)));
}
/* List new objects at the end of the extended parent field */
const Containers::StridedArrayView1D<UnsignedInt> newParentMapping = outParentMapping.suffix(scene.fieldSize(parentFieldId));
const Containers::StridedArrayView1D<Int> newParents = outParents.suffix(scene.fieldSize(parentFieldId));
@ -282,6 +342,9 @@ inline SceneData sceneConvertToSingleFunctionObjects(const SceneData& scene, Con
constexpr UnsignedInt zero[1]{};
Utility::copy(Containers::stridedArrayView(zero).broadcasted<0>(scene.mappingBound()), objectAttachmentCount);
/* Clear the fieldsToCopyAdditionCount array to reuse it below */
Utility::copy(Containers::stridedArrayView(zero).broadcasted<0>(fieldsToCopy.size()), fieldsToCopyAdditionCount);
/* For objects with multiple fields move the extra fields to newly added
children */
{
@ -298,6 +361,35 @@ inline SceneData sceneConvertToSingleFunctionObjects(const SceneData& scene, Con
attached, then attach the field to a new object and make
that new object a child of the previous one. */
if(fieldObject < objectAttachmentCount.size() && objectAttachmentCount[fieldObject]) {
/* Go through all fields to copy and copy each entry that
was assigned to the original object */
for(std::size_t i = 0; i != fieldsToCopy.size(); ++i) {
const Containers::Optional<UnsignedInt> fieldToCopyId = scene.findFieldId(fieldsToCopy[i]);
if(!fieldToCopyId) continue;
/* View to copy the data from */
const Containers::StridedArrayView2D<const char> fieldToCopyDataSrc = scene.field(*fieldToCopyId);
/* Views to put the mapping to and copy the data to */
const std::size_t newFieldToCopyOffset = scene.fieldSize(*fieldToCopyId);
const Containers::StridedArrayView1D<UnsignedInt> newFieldToCopyMapping = out.mutableMapping<UnsignedInt>(*fieldToCopyId).suffix(newFieldToCopyOffset);
const Containers::StridedArrayView2D<char> newFieldToCopy = out.mutableField(*fieldToCopyId).suffix(newFieldToCopyOffset);
/* As long as there are entries attached to the
original objects, copy them */
std::size_t offset = 0;
while(Containers::Optional<std::size_t> found = scene.findFieldObjectOffset(*fieldToCopyId, fieldObject, offset)) {
/* Assgn a new field entry to the new object */
newFieldToCopyMapping[fieldsToCopyAdditionCount[i]] = newParentMapping[newParentIndex];
/* Copy the data from the old entry to it */
Utility::copy(fieldToCopyDataSrc[*found], newFieldToCopy[fieldsToCopyAdditionCount[i]]);
++fieldsToCopyAdditionCount[i];
offset = *found + 1;
}
}
/* Use the old object as a parent of the new object */
newParents[newParentIndex] = fieldObject;
/* Assign the field to the new object */

30
src/Magnum/Trade/Test/AbstractImporterTest.cpp

@ -2710,13 +2710,19 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects2D() {
UnsignedInt object;
UnsignedInt camera;
};
struct Skin {
UnsignedInt object;
UnsignedInt skin;
};
Containers::StridedArrayView1D<Parent> parents;
Containers::StridedArrayView1D<Mesh> meshes;
Containers::StridedArrayView1D<Camera> cameras;
Containers::StridedArrayView1D<Skin> skins;
Containers::Array<char> dataData = Containers::ArrayTuple{
{NoInit, 5, parents},
{NoInit, 7, meshes},
{NoInit, 2, cameras},
{NoInit, 2, skins},
};
Utility::copy({{15, -1}, {21, -1}, {22, 21}, {23, 22}, {1, -1}}, parents);
Utility::copy({
@ -2729,6 +2735,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects2D() {
{21, 5, -1}
}, meshes);
Utility::copy({{22, 1}, {1, 5}}, cameras);
Utility::copy({{15, 9}, {21, 10}}, skins);
/* Second scene that also has a duplicate, to verify the newly added object
IDs don't conflict with each other. A potential downside is that
@ -2752,6 +2759,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects2D() {
SceneFieldData{SceneField::Mesh, meshes.slice(&Mesh::object), meshes.slice(&Mesh::mesh)},
SceneFieldData{SceneField::MeshMaterial, meshes.slice(&Mesh::object), meshes.slice(&Mesh::meshMaterial)},
SceneFieldData{SceneField::Camera, cameras.slice(&Camera::object), cameras.slice(&Camera::camera)},
SceneFieldData{SceneField::Skin, skins.slice(&Skin::object), skins.slice(&Skin::skin)},
/* Just to disambiguate this as a 2D scene */
SceneFieldData{SceneField::Transformation, SceneMappingType::UnsignedInt, nullptr, SceneFieldType::Matrix3x3, nullptr},
}};
@ -2844,6 +2852,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects2D() {
TestSuite::Compare::Container);
MeshObjectData2D& mo = static_cast<MeshObjectData2D&>(*o);
CORRADE_COMPARE(mo.material(), 2);
CORRADE_COMPARE(mo.skin(), -1);
} {
Containers::Pointer<ObjectData2D> o = importer.object2D(15);
CORRADE_VERIFY(o);
@ -2854,6 +2863,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects2D() {
TestSuite::Compare::Container);
MeshObjectData2D& mo = static_cast<MeshObjectData2D&>(*o);
CORRADE_COMPARE(mo.material(), 4);
CORRADE_COMPARE(mo.skin(), 9);
} {
Containers::Pointer<ObjectData2D> o = importer.object2D(21);
CORRADE_VERIFY(o);
@ -2864,6 +2874,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects2D() {
TestSuite::Compare::Container);
MeshObjectData2D& mo = static_cast<MeshObjectData2D&>(*o);
CORRADE_COMPARE(mo.material(), -1);
CORRADE_COMPARE(mo.skin(), 10);
} {
Containers::Pointer<ObjectData2D> o = importer.object2D(22);
CORRADE_VERIFY(o);
@ -2882,6 +2893,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects2D() {
TestSuite::Compare::Container);
MeshObjectData2D& mo = static_cast<MeshObjectData2D&>(*o);
CORRADE_COMPARE(mo.material(), 0);
CORRADE_COMPARE(mo.skin(), -1);
} {
Containers::Pointer<ObjectData2D> o = importer.object2D(63);
CORRADE_VERIFY(o);
@ -2892,6 +2904,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects2D() {
TestSuite::Compare::Container);
MeshObjectData2D& mo = static_cast<MeshObjectData2D&>(*o);
CORRADE_COMPARE(mo.material(), 3);
CORRADE_COMPARE(mo.skin(), -1);
} {
Containers::Pointer<ObjectData2D> o = importer.object2D(64);
CORRADE_VERIFY(o);
@ -2902,6 +2915,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects2D() {
TestSuite::Compare::Container);
MeshObjectData2D& mo = static_cast<MeshObjectData2D&>(*o);
CORRADE_COMPARE(mo.material(), 2);
CORRADE_COMPARE(mo.skin(), -1);
} {
Containers::Pointer<ObjectData2D> o = importer.object2D(65);
CORRADE_VERIFY(o);
@ -2912,6 +2926,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects2D() {
TestSuite::Compare::Container);
MeshObjectData2D& mo = static_cast<MeshObjectData2D&>(*o);
CORRADE_COMPARE(mo.material(), 1);
CORRADE_COMPARE(mo.skin(), 9);
} {
Containers::Pointer<ObjectData2D> o = importer.object2D(66);
CORRADE_VERIFY(o);
@ -2977,13 +2992,19 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects3D() {
UnsignedInt object;
UnsignedInt camera;
};
struct Skin {
UnsignedInt object;
UnsignedInt skin;
};
Containers::StridedArrayView1D<Parent> parents;
Containers::StridedArrayView1D<Mesh> meshes;
Containers::StridedArrayView1D<Camera> cameras;
Containers::StridedArrayView1D<Skin> skins;
Containers::Array<char> dataData = Containers::ArrayTuple{
{NoInit, 5, parents},
{NoInit, 7, meshes},
{NoInit, 2, cameras},
{NoInit, 2, skins},
};
Utility::copy({{15, -1}, {21, -1}, {22, 21}, {23, 22}, {1, -1}}, parents);
Utility::copy({
@ -2996,6 +3017,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects3D() {
{21, 5, -1}
}, meshes);
Utility::copy({{22, 1}, {1, 5}}, cameras);
Utility::copy({{15, 9}, {21, 10}}, skins);
/* Second scene that also has a duplicate, to verify the newly added object
IDs don't conflict with each other. A potential downside is that
@ -3019,6 +3041,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects3D() {
SceneFieldData{SceneField::Mesh, meshes.slice(&Mesh::object), meshes.slice(&Mesh::mesh)},
SceneFieldData{SceneField::MeshMaterial, meshes.slice(&Mesh::object), meshes.slice(&Mesh::meshMaterial)},
SceneFieldData{SceneField::Camera, cameras.slice(&Camera::object), cameras.slice(&Camera::camera)},
SceneFieldData{SceneField::Skin, skins.slice(&Skin::object), skins.slice(&Skin::skin)},
/* Just to disambiguate this as a 3D scene */
SceneFieldData{SceneField::Transformation, SceneMappingType::UnsignedInt, nullptr, SceneFieldType::Matrix4x4, nullptr},
}};
@ -3111,6 +3134,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects3D() {
TestSuite::Compare::Container);
MeshObjectData3D& mo = static_cast<MeshObjectData3D&>(*o);
CORRADE_COMPARE(mo.material(), 2);
CORRADE_COMPARE(mo.skin(), -1);
} {
Containers::Pointer<ObjectData3D> o = importer.object3D(15);
CORRADE_VERIFY(o);
@ -3121,6 +3145,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects3D() {
TestSuite::Compare::Container);
MeshObjectData3D& mo = static_cast<MeshObjectData3D&>(*o);
CORRADE_COMPARE(mo.material(), 4);
CORRADE_COMPARE(mo.skin(), 9);
} {
Containers::Pointer<ObjectData3D> o = importer.object3D(21);
CORRADE_VERIFY(o);
@ -3131,6 +3156,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects3D() {
TestSuite::Compare::Container);
MeshObjectData3D& mo = static_cast<MeshObjectData3D&>(*o);
CORRADE_COMPARE(mo.material(), -1);
CORRADE_COMPARE(mo.skin(), 10);
} {
Containers::Pointer<ObjectData3D> o = importer.object3D(22);
CORRADE_VERIFY(o);
@ -3149,6 +3175,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects3D() {
TestSuite::Compare::Container);
MeshObjectData3D& mo = static_cast<MeshObjectData3D&>(*o);
CORRADE_COMPARE(mo.material(), 0);
CORRADE_COMPARE(mo.skin(), -1);
} {
Containers::Pointer<ObjectData3D> o = importer.object3D(63);
CORRADE_VERIFY(o);
@ -3159,6 +3186,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects3D() {
TestSuite::Compare::Container);
MeshObjectData3D& mo = static_cast<MeshObjectData3D&>(*o);
CORRADE_COMPARE(mo.material(), 3);
CORRADE_COMPARE(mo.skin(), -1);
} {
Containers::Pointer<ObjectData3D> o = importer.object3D(64);
CORRADE_VERIFY(o);
@ -3169,6 +3197,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects3D() {
TestSuite::Compare::Container);
MeshObjectData3D& mo = static_cast<MeshObjectData3D&>(*o);
CORRADE_COMPARE(mo.material(), 2);
CORRADE_COMPARE(mo.skin(), -1);
} {
Containers::Pointer<ObjectData3D> o = importer.object3D(65);
CORRADE_VERIFY(o);
@ -3179,6 +3208,7 @@ void AbstractImporterTest::sceneDeprecatedFallbackMultiFunctionObjects3D() {
TestSuite::Compare::Container);
MeshObjectData3D& mo = static_cast<MeshObjectData3D&>(*o);
CORRADE_COMPARE(mo.material(), 1);
CORRADE_COMPARE(mo.skin(), 9);
} {
Containers::Pointer<ObjectData3D> o = importer.object3D(66);
CORRADE_VERIFY(o);

89
src/Magnum/Trade/Test/SceneToolsTest.cpp

@ -43,6 +43,7 @@ struct SceneToolsTest: TestSuite::Tester {
void combineObjectSharedFieldPlaceholder();
void convertToSingleFunctionObjects();
void convertToSingleFunctionObjectsFieldsToCopy();
};
struct {
@ -83,6 +84,8 @@ SceneToolsTest::SceneToolsTest() {
addInstancedTests({&SceneToolsTest::convertToSingleFunctionObjects},
Containers::arraySize(ConvertToSingleFunctionObjectsData));
addTests({&SceneToolsTest::convertToSingleFunctionObjectsFieldsToCopy});
}
using namespace Math::Literals;
@ -419,7 +422,7 @@ void SceneToolsTest::convertToSingleFunctionObjects() {
sceneFieldCustom(15),
/* Include also a field that's not present -- it should get skipped */
SceneField::ImporterState
}), 63);
}), {}, 63);
/* There should be three more objects, or the original count preserved if
it's large enough */
@ -571,7 +574,91 @@ void SceneToolsTest::convertToSingleFunctionObjects() {
Containers::arrayView(foo3FieldData),
TestSuite::Compare::Container);
CORRADE_COMPARE(scene.fieldFlags(sceneFieldCustom(17)), SceneFieldFlags{});
}
void SceneToolsTest::convertToSingleFunctionObjectsFieldsToCopy() {
const UnsignedShort parentMappingData[]{2, 15, 21, 22};
const Byte parentFieldData[]{-1, -1, -1, 21};
const UnsignedShort meshMappingData[]{15, 21, 21, 21, 22, 15};
const UnsignedInt meshFieldData[]{6, 1, 2, 4, 7, 3};
const UnsignedShort skinMappingData[]{22, 21};
const UnsignedInt skinFieldData[]{5, 13};
const UnsignedLong fooMappingData[]{15, 23, 15, 21};
const Int fooFieldData[]{0, 1, 2, 3, 4, 5, 6, 7};
SceneData original = Implementation::sceneCombine(SceneMappingType::UnsignedShort, 50, Containers::arrayView({
SceneFieldData{SceneField::Parent, Containers::arrayView(parentMappingData), Containers::arrayView(parentFieldData)},
SceneFieldData{SceneField::Mesh, Containers::arrayView(meshMappingData), Containers::arrayView(meshFieldData)},
SceneFieldData{SceneField::Skin, Containers::arrayView(skinMappingData), Containers::arrayView(skinFieldData)},
/* Array field */
SceneFieldData{sceneFieldCustom(15), Containers::arrayView(fooMappingData), Containers::StridedArrayView2D<const Int>{fooFieldData, {4, 2}}},
/* Just to disambiguate between 2D and 3D */
SceneFieldData{SceneField::Transformation, SceneMappingType::UnsignedShort, nullptr, SceneFieldType::Matrix4x4, nullptr}
}));
SceneData scene = Implementation::sceneConvertToSingleFunctionObjects(original,
Containers::arrayView({
/* Include also a field that's not present -- it should get skipped */
SceneField::ImporterState,
/* Three additional mesh assignments that go to new objects */
SceneField::Mesh
}),
Containers::arrayView({
/* One assignment is to an object that has just one mesh, it should
not be copied anywhere, the other should be duplicated two
times */
SceneField::Skin,
/* Array field with multiple assignments per object -- all should
be copied */
sceneFieldCustom(15),
/* Include also a field that's not present -- it should get skipped */
SceneField::Camera
}), 60);
CORRADE_COMPARE_AS(scene.parentsAsArray(), (Containers::arrayView<Containers::Pair<UnsignedInt, Int>>({
{2, -1},
{15, -1},
{21, -1},
{22, 21},
{60, 21}, /* duplicated mesh assignment to object 21 */
{61, 21}, /* duplicated mesh assignment to object 21 */
{62, 15} /* duplicated mesh assignment to object 15 */
})), TestSuite::Compare::Container);
CORRADE_COMPARE_AS(scene.meshesMaterialsAsArray(), (Containers::arrayView<Containers::Pair<UnsignedInt, Containers::Pair<UnsignedInt, Int>>>({
{15, {6, -1}},
{21, {1, -1}},
{60, {2, -1}}, /* duplicated mesh assignment to object 21 */
{61, {4, -1}}, /* duplicated mesh assignment to object 21 */
{22, {7, -1}},
{62, {3, -1}} /* duplicated mesh assignment to object 15 */
})), TestSuite::Compare::Container);
CORRADE_COMPARE_AS(scene.skinsAsArray(), (Containers::arrayView<Containers::Pair<UnsignedInt, UnsignedInt>>({
{22, 5},
{21, 13},
{60, 13}, /* duplicated from object 21 */
{61, 13}, /* duplicated from object 21 */
})), TestSuite::Compare::Container);
CORRADE_COMPARE_AS(scene.mapping<UnsignedInt>(sceneFieldCustom(15)), Containers::arrayView<UnsignedInt>({
15, 23, 15, 21,
60, 61, /* duplicated from object 21 (two duplicates of one object) */
62, 62, /* duplicated from object 15 (two entries for one object) */
}), TestSuite::Compare::Container);
CORRADE_COMPARE_AS((scene.field<Int[]>(sceneFieldCustom(15)).transposed<0, 1>()[0]), Containers::arrayView<Int>({
0, 2, 4, 6,
6, 6, /* duplicated from object 21 (two duplicates of one object) */
0, 4, /* duplicated from object 15 (two entries for one object) */
}), TestSuite::Compare::Container);
CORRADE_COMPARE_AS((scene.field<Int[]>(sceneFieldCustom(15)).transposed<0, 1>()[1]), Containers::arrayView<Int>({
1, 3, 5, 7,
7, 7, /* duplicated from object 21 (two duplicates of one object) */
1, 5, /* duplicated from object 15 (two entries for one object) */
}), TestSuite::Compare::Container);
}
}}}}

Loading…
Cancel
Save