Browse Source

sceneconverter: add --object-hierarchy.

Useful for quickly visualizing how the objects are parented to each
other, discovering groupings, overly deep hierarchies and such.
pull/620/head
Vladimír Vondruš 3 years ago
parent
commit
39054f1b64
  1. 2
      doc/changelog.dox
  2. 143
      src/Magnum/SceneTools/Implementation/sceneConverterUtilities.h
  3. 4
      src/Magnum/SceneTools/Test/CMakeLists.txt
  4. 79
      src/Magnum/SceneTools/Test/SceneConverterImplementationTest.cpp
  5. 14
      src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-object-hierarchy-no-parents.txt
  6. 7
      src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-object-hierarchy-only-objects-no-parents.txt
  7. 14
      src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-object-hierarchy-only-objects.txt
  8. 28
      src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-object-hierarchy.txt
  9. 7
      src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-scenes-no-default.txt
  10. 19
      src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-scenes-objects.txt
  11. 7
      src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-scenes.txt
  12. 4
      src/Magnum/SceneTools/sceneconverter.cpp

2
doc/changelog.dox

@ -667,6 +667,8 @@ See also:
`--info-materials`, `--info-meshes`, `--info-skins` and `--info-textures` `--info-materials`, `--info-meshes`, `--info-skins` and `--info-textures`
for printing information just about particular data type, with `--info` for printing information just about particular data type, with `--info`
being a shortcut for all specified together being a shortcut for all specified together
- Added a `--object-hierarchy` option to @ref magnum-sceneconverter "magnum-sceneconverter"
that visualizes scene hierarchy in each scene by indenting object info
- Added a `--prefer` option to @ref magnum-sceneconverter "magnum-sceneconverter", - Added a `--prefer` option to @ref magnum-sceneconverter "magnum-sceneconverter",
allowing to specify what plugins should be preferred for particular import allowing to specify what plugins should be preferred for particular import
and conversion plugin aliases and conversion plugin aliases

143
src/Magnum/SceneTools/Implementation/sceneConverterUtilities.h

@ -33,6 +33,7 @@
#include <Corrade/Utility/Arguments.h> #include <Corrade/Utility/Arguments.h>
#include "Magnum/Math/FunctionsBatch.h" #include "Magnum/Math/FunctionsBatch.h"
#include "Magnum/SceneTools/Hierarchy.h"
#include "Magnum/Trade/AbstractSceneConverter.h" #include "Magnum/Trade/AbstractSceneConverter.h"
#include "Magnum/Trade/AnimationData.h" #include "Magnum/Trade/AnimationData.h"
#include "Magnum/Trade/CameraData.h" #include "Magnum/Trade/CameraData.h"
@ -157,6 +158,8 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility
std::size_t dataSize; std::size_t dataSize;
Trade::DataFlags dataFlags; Trade::DataFlags dataFlags;
Containers::String name; Containers::String name;
/* Populated only if --object-hierarchy is set */
Containers::Array<Containers::Pair<UnsignedInt, UnsignedInt>> childrenDepthFirst;
}; };
struct ObjectInfo { struct ObjectInfo {
@ -198,13 +201,15 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility
Containers::Array<UnsignedInt> meshReferenceCount; Containers::Array<UnsignedInt> meshReferenceCount;
Containers::Array<UnsignedInt> skin2DReferenceCount; Containers::Array<UnsignedInt> skin2DReferenceCount;
Containers::Array<UnsignedInt> skin3DReferenceCount; Containers::Array<UnsignedInt> skin3DReferenceCount;
if((args.isSet("info") || args.isSet("info-scenes")) && importer.sceneCount()) { if((args.isSet("info") || args.isSet("info-scenes") || args.isSet("object-hierarchy")) && importer.sceneCount()) {
materialReferenceCount = Containers::Array<UnsignedInt>{importer.materialCount()}; if(args.isSet("info") || args.isSet("info-scenes")) {
lightReferenceCount = Containers::Array<UnsignedInt>{importer.lightCount()}; materialReferenceCount = Containers::Array<UnsignedInt>{importer.materialCount()};
cameraReferenceCount = Containers::Array<UnsignedInt>{importer.cameraCount()}; lightReferenceCount = Containers::Array<UnsignedInt>{importer.lightCount()};
meshReferenceCount = Containers::Array<UnsignedInt>{importer.meshCount()}; cameraReferenceCount = Containers::Array<UnsignedInt>{importer.cameraCount()};
skin2DReferenceCount = Containers::Array<UnsignedInt>{importer.skin2DCount()}; meshReferenceCount = Containers::Array<UnsignedInt>{importer.meshCount()};
skin3DReferenceCount = Containers::Array<UnsignedInt>{importer.skin3DCount()}; skin2DReferenceCount = Containers::Array<UnsignedInt>{importer.skin2DCount()};
skin3DReferenceCount = Containers::Array<UnsignedInt>{importer.skin3DCount()};
}
for(UnsignedInt i = 0; i != importer.sceneCount(); ++i) { for(UnsignedInt i = 0; i != importer.sceneCount(); ++i) {
Containers::Optional<Trade::SceneData> scene = importer.scene(i); Containers::Optional<Trade::SceneData> scene = importer.scene(i);
@ -221,7 +226,7 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility
info.dataSize = scene->data().size(); info.dataSize = scene->data().size();
info.dataFlags = scene->dataFlags(); info.dataFlags = scene->dataFlags();
info.name = importer.sceneName(i); info.name = importer.sceneName(i);
for(UnsignedInt j = 0; j != scene->fieldCount(); ++j) { if(args.isSet("info") || args.isSet("info-scenes")) for(UnsignedInt j = 0; j != scene->fieldCount(); ++j) {
const Trade::SceneField name = scene->fieldName(j); const Trade::SceneField name = scene->fieldName(j);
if(name == Trade::SceneField::Mesh) for(const Containers::Pair<UnsignedInt, Containers::Pair<UnsignedInt, Int>>& meshMaterial: scene->meshesMaterialsAsArray()) { if(name == Trade::SceneField::Mesh) for(const Containers::Pair<UnsignedInt, Containers::Pair<UnsignedInt, Int>>& meshMaterial: scene->meshesMaterialsAsArray()) {
@ -279,6 +284,9 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility
} }
} }
if(args.isSet("object-hierarchy") && scene->hasField(Trade::SceneField::Parent))
info.childrenDepthFirst = SceneTools::childrenDepthFirst(*scene);
arrayAppend(sceneInfos, std::move(info)); arrayAppend(sceneInfos, std::move(info));
} }
} }
@ -603,6 +611,26 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility
if((args.isSet("info") || args.isSet("info-scenes")) && importer.defaultScene() != -1) if((args.isSet("info") || args.isSet("info-scenes")) && importer.defaultScene() != -1)
Debug{useColor} << Debug::boldColor(Debug::Color::Default) << "Default scene:" << Debug::resetColor << importer.defaultScene(); Debug{useColor} << Debug::boldColor(Debug::Color::Default) << "Default scene:" << Debug::resetColor << importer.defaultScene();
const auto printObjectFieldInfo = [&sceneFieldNames](Debug& d, const ObjectInfo& info) {
for(std::size_t i = 0; i != info.fields.size(); ++i) {
if(i) d << Debug::nospace << ",";
const Containers::Pair<Trade::SceneField, UnsignedInt> nameCount = info.fields[i];
d << Debug::color(Debug::Color::Cyan);
if(Trade::isSceneFieldCustom(nameCount.first())) {
d << "Custom(" << Debug::nospace
<< Trade::sceneFieldCustom(nameCount.first())
<< Debug::nospace << ":" << Debug::nospace
<< Debug::color(Debug::Color::Yellow)
<< sceneFieldNames[sceneFieldCustom(nameCount.first())]
<< Debug::nospace
<< Debug::color(Debug::Color::Cyan) << ")";
} else d << Debug::packed << nameCount.first();
if(nameCount.second() != 1)
d << Debug::nospace << Utility::format("[{}]", nameCount.second());
d << Debug::resetColor;
}
};
std::size_t totalSceneDataSize = 0; std::size_t totalSceneDataSize = 0;
for(const SceneInfo& info: sceneInfos) { for(const SceneInfo& info: sceneInfos) {
Debug d{useColor}; Debug d{useColor};
@ -620,28 +648,62 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility
<< Debug::resetColor; << Debug::resetColor;
d << Debug::nospace << ")"; d << Debug::nospace << ")";
d << Debug::newline << " Fields:"; if(info.fields) {
for(const SceneFieldInfo& field: info.fields) { d << Debug::newline << " Fields:";
d << Debug::newline << " " for(const SceneFieldInfo& field: info.fields) {
<< Debug::boldColor(Debug::Color::Default); d << Debug::newline << " "
if(Trade::isSceneFieldCustom(field.name)) { << Debug::boldColor(Debug::Color::Default);
d << "Custom(" << Debug::nospace if(Trade::isSceneFieldCustom(field.name)) {
<< Trade::sceneFieldCustom(field.name) d << "Custom(" << Debug::nospace
<< Debug::nospace << ":" << Debug::nospace << Trade::sceneFieldCustom(field.name)
<< Debug::color(Debug::Color::Yellow) << Debug::nospace << ":" << Debug::nospace
<< sceneFieldNames[sceneFieldCustom(field.name)] << Debug::color(Debug::Color::Yellow)
<< Debug::nospace << sceneFieldNames[sceneFieldCustom(field.name)]
<< Debug::boldColor(Debug::Color::Default) << ")"; << Debug::nospace
} else d << Debug::packed << field.name; << Debug::boldColor(Debug::Color::Default) << ")";
} else d << Debug::packed << field.name;
d << Debug::color(Debug::Color::Blue) << "@" << Debug::packed << Debug::color(Debug::Color::Cyan) << field.type; d << Debug::color(Debug::Color::Blue) << "@" << Debug::packed << Debug::color(Debug::Color::Cyan) << field.type;
if(field.arraySize) if(field.arraySize)
d << Debug::nospace << Utility::format("[{}]", field.arraySize); d << Debug::nospace << Utility::format("[{}]", field.arraySize);
d << Debug::resetColor; d << Debug::resetColor;
if(field.flags) d << Debug::nospace << "," if(field.flags) d << Debug::nospace << ","
<< Debug::packed << Debug::color(Debug::Color::Green) << Debug::packed << Debug::color(Debug::Color::Green)
<< field.flags << Debug::resetColor; << field.flags << Debug::resetColor;
d << Debug::nospace << "," << field.size << "entries"; d << Debug::nospace << "," << field.size << "entries";
}
}
if(args.isSet("object-hierarchy") && objectInfos) {
d << Debug::newline << " Object hierarchy:";
Containers::Array<std::size_t> childRangeEnds;
arrayAppend(childRangeEnds, info.childrenDepthFirst.size());
for(std::size_t i = 0; i != info.childrenDepthFirst.size(); ++i) {
while(childRangeEnds.back() == i)
arrayRemoveSuffix(childRangeEnds, 1);
const UnsignedInt object = info.childrenDepthFirst[i].first();
const UnsignedInt childCount = info.childrenDepthFirst[i].second();
const ObjectInfo& objectInfo = objectInfos[object];
const Containers::String indent = " "_s*(childRangeEnds.size());
d << Debug::newline << indent << Debug::nospace << Debug::boldColor(Debug::Color::Default) << " Object"
<< object << Debug::nospace << ":" << Debug::resetColor;
if(objectInfo.name) d << Debug::boldColor(Debug::Color::Yellow)
<< objectInfo.name << Debug::resetColor;
if(objectInfo.fields) {
d << Debug::newline << indent << Debug::nospace << " Fields:";
printObjectFieldInfo(d, objectInfo);
}
if(childCount) {
CORRADE_INTERNAL_ASSERT(childRangeEnds.back() > i + 1);
arrayAppend(childRangeEnds, i + childCount + 1);
}
}
} }
totalSceneDataSize += info.dataSize; totalSceneDataSize += info.dataSize;
@ -649,7 +711,9 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility
if(!sceneInfos.isEmpty()) if(!sceneInfos.isEmpty())
Debug{} << "Total scene data size:" << Utility::format("{:.1f}", totalSceneDataSize/1024.0f) << "kB"; Debug{} << "Total scene data size:" << Utility::format("{:.1f}", totalSceneDataSize/1024.0f) << "kB";
for(const ObjectInfo& info: objectInfos) { /* If --object-hierarchy was specified, the object list was printed as part
of the scene already */
if(!args.isSet("object-hierarchy")) for(const ObjectInfo& info: objectInfos) {
/* Objects without a name and not referenced by any scenes are useless, /* Objects without a name and not referenced by any scenes are useless,
ignore */ ignore */
if(!info.name && !info.scenes) continue; if(!info.name && !info.scenes) continue;
@ -670,24 +734,7 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility
<< info.name << Debug::resetColor; << info.name << Debug::resetColor;
if(info.scenes) { if(info.scenes) {
d << Debug::newline << " Fields:"; d << Debug::newline << " Fields:";
printObjectFieldInfo(d, info);
for(std::size_t i = 0; i != info.fields.size(); ++i) {
if(i) d << Debug::nospace << ",";
const Containers::Pair<Trade::SceneField, UnsignedInt> nameCount = info.fields[i];
d << Debug::color(Debug::Color::Cyan);
if(Trade::isSceneFieldCustom(nameCount.first())) {
d << "Custom(" << Debug::nospace
<< Trade::sceneFieldCustom(nameCount.first())
<< Debug::nospace << ":" << Debug::nospace
<< Debug::color(Debug::Color::Yellow)
<< sceneFieldNames[sceneFieldCustom(nameCount.first())]
<< Debug::nospace
<< Debug::color(Debug::Color::Cyan) << ")";
} else d << Debug::packed << nameCount.first();
if(nameCount.second() != 1)
d << Debug::nospace << Utility::format("[{}]", nameCount.second());
d << Debug::resetColor;
}
} }
} }

4
src/Magnum/SceneTools/Test/CMakeLists.txt

@ -67,6 +67,10 @@ corrade_add_test(SceneToolsSceneConverterImple___Test SceneConverterImplementati
SceneConverterImplementationTestFiles/info-meshes-bounds.txt SceneConverterImplementationTestFiles/info-meshes-bounds.txt
SceneConverterImplementationTestFiles/info-meshes.txt SceneConverterImplementationTestFiles/info-meshes.txt
SceneConverterImplementationTestFiles/info-objects.txt SceneConverterImplementationTestFiles/info-objects.txt
SceneConverterImplementationTestFiles/info-object-hierarchy.txt
SceneConverterImplementationTestFiles/info-object-hierarchy-no-parents.txt
SceneConverterImplementationTestFiles/info-object-hierarchy-only-objects.txt
SceneConverterImplementationTestFiles/info-object-hierarchy-only-objects-no-parents.txt
SceneConverterImplementationTestFiles/info-references.txt SceneConverterImplementationTestFiles/info-references.txt
SceneConverterImplementationTestFiles/info-scenes.txt SceneConverterImplementationTestFiles/info-scenes.txt
SceneConverterImplementationTestFiles/info-scenes-no-default.txt SceneConverterImplementationTestFiles/info-scenes-no-default.txt

79
src/Magnum/SceneTools/Test/SceneConverterImplementationTest.cpp

@ -76,15 +76,47 @@ using namespace Math::Literals;
const struct { const struct {
const char* name; const char* name;
const char* arg; Containers::Array<const char*> args;
const char* expected; const char* expected;
Int defaultScene; Int defaultScene;
bool printVisualCheck; bool printVisualCheck;
bool omitParent;
} InfoScenesObjectsData[]{ } InfoScenesObjectsData[]{
{"", "--info", "info-scenes-objects.txt", 1, true}, {"all", {InPlaceInit, {
{"only scenes", "--info-scenes", "info-scenes.txt", 0, false}, "", "--info"
{"only scenes, no default scene", "--info-scenes", "info-scenes-no-default.txt", -1, false}, }}, "info-scenes-objects.txt", 1, true, false},
{"only objects", "--info-objects", "info-objects.txt", 1, false} {"both", {InPlaceInit, {
"", "--info-objects", "--info-scenes"
}}, "info-scenes-objects.txt", 1, false, false},
{"only scenes", {InPlaceInit, {
"", "--info-scenes"
}}, "info-scenes.txt", 0, false, false},
{"only scenes, no default scene", {InPlaceInit, {
"", "--info-scenes"
}}, "info-scenes-no-default.txt", -1, false, false},
{"only objects", {InPlaceInit, {
"", "--info-objects"
}}, "info-objects.txt", 1, false, false},
{"object hierarchy, all", {InPlaceInit, {
"", "--info", "--object-hierarchy"
}}, "info-object-hierarchy.txt", -1, true, false},
{"object hierarchy, both", {InPlaceInit, {
"", "--info-objects", "--info-scenes", "--object-hierarchy"
}}, "info-object-hierarchy.txt", -1, false, false},
{"object hierarchy, no parents", {InPlaceInit, {
"", "--info", "--object-hierarchy"
}}, "info-object-hierarchy-no-parents.txt", -1, false, true},
{"object hierarchy, only scenes", {InPlaceInit, {
/* --object-hierarchy is only used if --info-objects is present
so this is the same as just --info-scenes alone */
"", "--info-scenes", "--object-hierarchy"
}}, "info-scenes-no-default.txt", -1, false, false},
{"object hierarchy, only objects", {InPlaceInit, {
"", "--info-objects", "--object-hierarchy"
}}, "info-object-hierarchy-only-objects.txt", -1, true, false},
{"object hierarchy, only objects, no parents", {InPlaceInit, {
"", "--info-objects", "--object-hierarchy"
}}, "info-object-hierarchy-only-objects-no-parents.txt", -1, false, true},
}; };
const struct { const struct {
@ -133,7 +165,8 @@ SceneConverterImplementationTest::SceneConverterImplementationTest() {
.addBooleanOption("info-meshes") .addBooleanOption("info-meshes")
.addBooleanOption("info-textures") .addBooleanOption("info-textures")
.addBooleanOption("info-images") .addBooleanOption("info-images")
.addBooleanOption("bounds"); .addBooleanOption("bounds")
.addBooleanOption("object-hierarchy");
/* Load the plugin directly from the build tree. Otherwise it's static and /* Load the plugin directly from the build tree. Otherwise it's static and
already loaded. */ already loaded. */
@ -200,7 +233,7 @@ void SceneConverterImplementationTest::infoScenesObjects() {
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
struct Importer: Trade::AbstractImporter { struct Importer: Trade::AbstractImporter {
explicit Importer(Int defaultScene): _defaultScene{defaultScene} {} explicit Importer(Int defaultScene, bool omitParent): _defaultScene{defaultScene}, _omitParent{omitParent} {}
Trade::ImporterFeatures doFeatures() const override { return {}; } Trade::ImporterFeatures doFeatures() const override { return {}; }
bool doIsOpened() const override { return true; } bool doIsOpened() const override { return true; }
@ -236,24 +269,27 @@ void SceneConverterImplementationTest::infoScenesObjects() {
Containers::ArrayView<UnsignedInt> meshMapping; Containers::ArrayView<UnsignedInt> meshMapping;
Containers::ArrayView<UnsignedInt> meshes; Containers::ArrayView<UnsignedInt> meshes;
Containers::ArrayTuple data{ Containers::ArrayTuple data{
{NoInit, 3, parentMapping}, {NoInit, 5, parentMapping},
{ValueInit, 3, parents}, {NoInit, 5, parents},
{NoInit, 4, meshMapping}, {NoInit, 4, meshMapping},
{ValueInit, 4, meshes}, {ValueInit, 4, meshes},
}; };
Utility::copy({1, 3, 2}, parentMapping); Utility::copy({1, 2, 5, 4, 0}, parentMapping);
Utility::copy({2, -1, 1, 2, 5}, parents);
Utility::copy({2, 0, 2, 1}, meshMapping); Utility::copy({2, 0, 2, 1}, meshMapping);
/* No need to fill the data, zero-init is fine */ /* No need to fill the other data, zero-init is fine */
return Trade::SceneData{Trade::SceneMappingType::UnsignedInt, 4, std::move(data), { return Trade::SceneData{Trade::SceneMappingType::UnsignedInt, 6, std::move(data), {
Trade::SceneFieldData{Trade::SceneField::Parent, parentMapping, parents}, Trade::SceneFieldData{_omitParent ? Trade::sceneFieldCustom(0) : Trade::SceneField::Parent, parentMapping, parents},
Trade::SceneFieldData{Trade::SceneField::Mesh, meshMapping, meshes, Trade::SceneFieldFlag::OrderedMapping}, Trade::SceneFieldData{Trade::SceneField::Mesh, meshMapping, meshes, Trade::SceneFieldFlag::OrderedMapping},
}}; }};
} }
/* Two custom fields, one array. Stored as an external memory. */ /* Two custom fields, one array, parent. Stored as an external
memory. */
if(id == 1) { if(id == 1) {
return Trade::SceneData{Trade::SceneMappingType::UnsignedByte, 8, Trade::DataFlag::ExternallyOwned|Trade::DataFlag::Mutable, scene2Data, { return Trade::SceneData{Trade::SceneMappingType::UnsignedByte, 8, Trade::DataFlag::ExternallyOwned|Trade::DataFlag::Mutable, scene2Data, {
Trade::SceneFieldData{Trade::sceneFieldCustom(42), Containers::arrayView(scene2Data->customMapping), Containers::arrayView(scene2Data->custom)}, Trade::SceneFieldData{_omitParent ? Trade::sceneFieldCustom(0) : Trade::SceneField::Parent, Containers::arrayView(scene2Data->parentCustomMapping), Containers::arrayView(scene2Data->parent)},
Trade::SceneFieldData{Trade::sceneFieldCustom(42), Containers::arrayView(scene2Data->parentCustomMapping), Containers::arrayView(scene2Data->custom)},
Trade::SceneFieldData{Trade::sceneFieldCustom(1337), Trade::SceneMappingType::UnsignedByte, scene2Data->customArrayMapping, Trade::SceneFieldType::Short, scene2Data->customArray, 3}, Trade::SceneFieldData{Trade::sceneFieldCustom(1337), Trade::SceneMappingType::UnsignedByte, scene2Data->customArrayMapping, Trade::SceneFieldType::Short, scene2Data->customArray, 3},
}}; }};
} }
@ -262,20 +298,21 @@ void SceneConverterImplementationTest::infoScenesObjects() {
} }
struct { struct {
UnsignedByte customMapping[2]; UnsignedByte parentCustomMapping[2];
Int parent[2];
Double custom[2]; Double custom[2];
UnsignedByte customArrayMapping[3]; UnsignedByte customArrayMapping[3];
Vector3s customArray[3]; Vector3s customArray[3];
} scene2Data[1]{{ } scene2Data[1]{{
/* No need to fill the data, zero-init is fine */ /* No need to fill data other than parents, zero-init is fine */
{7, 3}, {}, {2, 4, 4}, {} {7, 3}, {3, -1}, {}, {2, 4, 4}, {}
}}; }};
Int _defaultScene; Int _defaultScene;
} importer{data.defaultScene}; bool _omitParent;
} importer{data.defaultScene, data.omitParent};
const char* argv[]{"", data.arg}; CORRADE_VERIFY(_infoArgs.tryParse(data.args.size(), data.args));
CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv));
std::chrono::high_resolution_clock::duration time; std::chrono::high_resolution_clock::duration time;

14
src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-object-hierarchy-no-parents.txt

@ -0,0 +1,14 @@
Scene 0: A simple scene
Bound: 6 objects @ UnsignedInt (0.1 kB)
Fields:
Custom(0:) @ Int, 5 entries
Mesh @ UnsignedInt, OrderedMapping, 4 entries
Object hierarchy:
Scene 1:
Bound: 8 objects @ UnsignedByte (0.1 kB, ExternallyOwned|Mutable)
Fields:
Custom(0:) @ Int, 2 entries
Custom(42:) @ Double, 2 entries
Custom(1337:directionVector) @ Short[3], 3 entries
Object hierarchy:
Total scene data size: 0.1 kB

7
src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-object-hierarchy-only-objects-no-parents.txt

@ -0,0 +1,7 @@
Scene 0: A simple scene
Bound: 6 objects @ UnsignedInt (0.1 kB)
Object hierarchy:
Scene 1:
Bound: 8 objects @ UnsignedByte (0.1 kB, ExternallyOwned|Mutable)
Object hierarchy:
Total scene data size: 0.1 kB

14
src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-object-hierarchy-only-objects.txt

@ -0,0 +1,14 @@
Scene 0: A simple scene
Bound: 6 objects @ UnsignedInt (0.1 kB)
Object hierarchy:
Object 2: Two meshes, shared among two scenes
Object 1:
Object 5:
Object 0: Parent-less mesh
Object 4: Two custom arrays
Scene 1:
Bound: 8 objects @ UnsignedByte (0.1 kB, ExternallyOwned|Mutable)
Object hierarchy:
Object 3:
Object 7:
Total scene data size: 0.1 kB

28
src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-object-hierarchy.txt

@ -0,0 +1,28 @@
Scene 0: A simple scene
Bound: 6 objects @ UnsignedInt (0.1 kB)
Fields:
Parent @ Int, 5 entries
Mesh @ UnsignedInt, OrderedMapping, 4 entries
Object hierarchy:
Object 2: Two meshes, shared among two scenes
Fields: Parent, Mesh[2], Custom(1337:directionVector)
Object 1:
Fields: Parent, Mesh
Object 5:
Fields: Parent
Object 0: Parent-less mesh
Fields: Parent, Mesh
Object 4: Two custom arrays
Fields: Parent, Custom(1337:directionVector)[2]
Scene 1:
Bound: 8 objects @ UnsignedByte (0.1 kB, ExternallyOwned|Mutable)
Fields:
Parent @ Int, 2 entries
Custom(42:) @ Double, 2 entries
Custom(1337:directionVector) @ Short[3], 3 entries
Object hierarchy:
Object 3:
Fields: Parent, Custom(42:)
Object 7:
Fields: Parent, Custom(42:)
Total scene data size: 0.1 kB

7
src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-scenes-no-default.txt

@ -1,11 +1,12 @@
Scene 0: A simple scene Scene 0: A simple scene
Bound: 4 objects @ UnsignedInt (0.1 kB) Bound: 6 objects @ UnsignedInt (0.1 kB)
Fields: Fields:
Parent @ Int, 3 entries Parent @ Int, 5 entries
Mesh @ UnsignedInt, OrderedMapping, 4 entries Mesh @ UnsignedInt, OrderedMapping, 4 entries
Scene 1: Scene 1:
Bound: 8 objects @ UnsignedByte (0.0 kB, ExternallyOwned|Mutable) Bound: 8 objects @ UnsignedByte (0.1 kB, ExternallyOwned|Mutable)
Fields: Fields:
Parent @ Int, 2 entries
Custom(42:) @ Double, 2 entries Custom(42:) @ Double, 2 entries
Custom(1337:directionVector) @ Short[3], 3 entries Custom(1337:directionVector) @ Short[3], 3 entries
Total scene data size: 0.1 kB Total scene data size: 0.1 kB

19
src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-scenes-objects.txt

@ -1,26 +1,29 @@
Default scene: 1 Default scene: 1
Scene 0: A simple scene Scene 0: A simple scene
Bound: 4 objects @ UnsignedInt (0.1 kB) Bound: 6 objects @ UnsignedInt (0.1 kB)
Fields: Fields:
Parent @ Int, 3 entries Parent @ Int, 5 entries
Mesh @ UnsignedInt, OrderedMapping, 4 entries Mesh @ UnsignedInt, OrderedMapping, 4 entries
Scene 1: Scene 1:
Bound: 8 objects @ UnsignedByte (0.0 kB, ExternallyOwned|Mutable) Bound: 8 objects @ UnsignedByte (0.1 kB, ExternallyOwned|Mutable)
Fields: Fields:
Parent @ Int, 2 entries
Custom(42:) @ Double, 2 entries Custom(42:) @ Double, 2 entries
Custom(1337:directionVector) @ Short[3], 3 entries Custom(1337:directionVector) @ Short[3], 3 entries
Total scene data size: 0.1 kB Total scene data size: 0.1 kB
Object 0 (referenced by 1 scenes): Parent-less mesh Object 0 (referenced by 1 scenes): Parent-less mesh
Fields: Mesh Fields: Parent, Mesh
Object 1 (referenced by 1 scenes): Object 1 (referenced by 1 scenes):
Fields: Parent, Mesh Fields: Parent, Mesh
Object 2 (referenced by 2 scenes): Two meshes, shared among two scenes Object 2 (referenced by 2 scenes): Two meshes, shared among two scenes
Fields: Parent, Mesh[2], Custom(1337:directionVector) Fields: Parent, Mesh[2], Custom(1337:directionVector)
Object 3 (referenced by 2 scenes): Object 3 (referenced by 1 scenes):
Fields: Parent, Custom(42:) Fields: Parent, Custom(42:)
Object 4 (referenced by 1 scenes): Two custom arrays Object 4 (referenced by 2 scenes): Two custom arrays
Fields: Custom(1337:directionVector)[2] Fields: Parent, Custom(1337:directionVector)[2]
Object 5 (referenced by 1 scenes):
Fields: Parent
Object 6 (referenced by 0 scenes): Only in the second scene, but no fields, thus same as unreferenced Object 6 (referenced by 0 scenes): Only in the second scene, but no fields, thus same as unreferenced
Object 7 (referenced by 1 scenes): Object 7 (referenced by 1 scenes):
Fields: Custom(42:) Fields: Parent, Custom(42:)
Object 8 (referenced by 0 scenes): Not in any scene Object 8 (referenced by 0 scenes): Not in any scene

7
src/Magnum/SceneTools/Test/SceneConverterImplementationTestFiles/info-scenes.txt

@ -1,12 +1,13 @@
Default scene: 0 Default scene: 0
Scene 0: A simple scene Scene 0: A simple scene
Bound: 4 objects @ UnsignedInt (0.1 kB) Bound: 6 objects @ UnsignedInt (0.1 kB)
Fields: Fields:
Parent @ Int, 3 entries Parent @ Int, 5 entries
Mesh @ UnsignedInt, OrderedMapping, 4 entries Mesh @ UnsignedInt, OrderedMapping, 4 entries
Scene 1: Scene 1:
Bound: 8 objects @ UnsignedByte (0.0 kB, ExternallyOwned|Mutable) Bound: 8 objects @ UnsignedByte (0.1 kB, ExternallyOwned|Mutable)
Fields: Fields:
Parent @ Int, 2 entries
Custom(42:) @ Double, 2 entries Custom(42:) @ Double, 2 entries
Custom(1337:directionVector) @ Short[3], 3 entries Custom(1337:directionVector) @ Short[3], 3 entries
Total scene data size: 0.1 kB Total scene data size: 0.1 kB

4
src/Magnum/SceneTools/sceneconverter.cpp

@ -194,7 +194,7 @@ magnum-sceneconverter [-h|--help] [-I|--importer PLUGIN]
[--info-images] [--info-lights] [--info-cameras] [--info-materials] [--info-images] [--info-lights] [--info-cameras] [--info-materials]
[--info-meshes] [--info-objects] [--info-scenes] [--info-skins] [--info-meshes] [--info-objects] [--info-scenes] [--info-skins]
[--info-textures] [--info] [--color on|4bit|off|auto] [--bounds] [--info-textures] [--info] [--color on|4bit|off|auto] [--bounds]
[-v|--verbose] [--profile] [--] input output [--object-hierarchy] [-v|--verbose] [--profile] [--] input output
@endcode @endcode
Arguments: Arguments:
@ -263,6 +263,7 @@ Arguments:
as specifying all other data-related `--info-*` options together as specifying all other data-related `--info-*` options together
- `--color` --- colored output for `--info` (default: `auto`) - `--color` --- colored output for `--info` (default: `auto`)
- `--bounds` --- show bounds of known attributes in `--info` output - `--bounds` --- show bounds of known attributes in `--info` output
- `--object-hierarchy` --- visualize object hierarchy in `--info` output
- `-v`, `--verbose` --- verbose output from importer and converter plugins - `-v`, `--verbose` --- verbose output from importer and converter plugins
- `--profile` --- measure import and conversion time - `--profile` --- measure import and conversion time
@ -451,6 +452,7 @@ int main(int argc, char** argv) {
.addBooleanOption("info").setHelp("info", "print info about everything in the input file and exit, same as specifying all other data-related --info-* options together") .addBooleanOption("info").setHelp("info", "print info about everything in the input file and exit, same as specifying all other data-related --info-* options together")
.addOption("color", "auto").setHelp("color", "colored output for --info", "on|4bit|off|auto") .addOption("color", "auto").setHelp("color", "colored output for --info", "on|4bit|off|auto")
.addBooleanOption("bounds").setHelp("bounds", "show bounds of known attributes in --info output") .addBooleanOption("bounds").setHelp("bounds", "show bounds of known attributes in --info output")
.addBooleanOption("object-hierarchy").setHelp("object-hierarchy", "visualize object hierarchy in --info output")
.addBooleanOption('v', "verbose").setHelp("verbose", "verbose output from importer and converter plugins") .addBooleanOption('v', "verbose").setHelp("verbose", "verbose output from importer and converter plugins")
.addBooleanOption("profile").setHelp("profile", "measure import and conversion time") .addBooleanOption("profile").setHelp("profile", "measure import and conversion time")
.setParseErrorCallback([](const Utility::Arguments& args, Utility::Arguments::ParseError error, const std::string& key) { .setParseErrorCallback([](const Utility::Arguments& args, Utility::Arguments::ParseError error, const std::string& key) {

Loading…
Cancel
Save