diff --git a/src/Magnum/MeshTools/sceneconverter.cpp b/src/Magnum/MeshTools/sceneconverter.cpp index 392b7052c5..2fe3054429 100644 --- a/src/Magnum/MeshTools/sceneconverter.cpp +++ b/src/Magnum/MeshTools/sceneconverter.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,7 @@ #include "Magnum/Trade/LightData.h" #include "Magnum/Trade/MaterialData.h" #include "Magnum/Trade/MeshData.h" -#include "Magnum/Trade/MeshObjectData3D.h" +#include "Magnum/Trade/SceneData.h" #include "Magnum/Trade/SkinData.h" #include "Magnum/Trade/TextureData.h" #include "Magnum/Trade/AbstractSceneConverter.h" @@ -338,30 +339,75 @@ used.)") std::string name; }; + struct SceneFieldInfo { + Trade::SceneField name; + std::string customName; + Trade::SceneFieldType type; + UnsignedInt arraySize; + std::size_t size; + }; + + struct SceneInfo { + UnsignedInt scene; + Trade::SceneObjectType objectType; + UnsignedLong objectCount; + Containers::Array fields; + std::size_t dataSize; + std::string name; + /** @todo object names? */ + }; + /* Parse everything first to avoid errors interleaved with output */ - /* Scene properties. Currently just counting how much is each mesh / - light / material shared. Texture reference count is calculated when - parsing materials. */ + /* Scene properties, together with counting how much is each mesh / + light / material / skin shared. Texture reference count is + calculated when parsing materials. */ + Containers::Array sceneInfos; Containers::Array materialReferenceCount{importer->materialCount()}; Containers::Array lightReferenceCount{importer->lightCount()}; Containers::Array meshReferenceCount{importer->meshCount()}; Containers::Array skinReferenceCount{importer->skin3DCount()}; - for(UnsignedInt i = 0; i != importer->object3DCount(); ++i) { - Containers::Pointer object = importer->object3D(i); - if(!object) continue; - if(object->instanceType() == Trade::ObjectInstanceType3D::Mesh) { - auto& meshObject = static_cast(*object); - if(std::size_t(meshObject.instance()) < meshReferenceCount.size()) - ++meshReferenceCount[meshObject.instance()]; - if(std::size_t(meshObject.material()) < materialReferenceCount.size()) - ++materialReferenceCount[meshObject.material()]; - if(std::size_t(meshObject.skin()) < skinReferenceCount.size()) - ++skinReferenceCount[meshObject.skin()]; - } else if(object->instanceType() == Trade::ObjectInstanceType3D::Light) { - if(std::size_t(object->instance()) < lightReferenceCount.size()) - ++lightReferenceCount[object->instance()]; + for(UnsignedInt i = 0; i != importer->sceneCount(); ++i) { + Containers::Optional scene = importer->scene(i); + if(!scene) continue; + + SceneInfo info{}; + info.scene = i; + info.objectType = scene->objectType(); + info.objectCount = scene->objectCount(); + info.dataSize = scene->data().size(); + info.name = importer->sceneName(i); + for(UnsignedInt j = 0; j != scene->fieldCount(); ++j) { + const Trade::SceneField name = scene->fieldName(j); + + if(name == Trade::SceneField::Mesh) for(const Containers::Pair& meshMaterial: scene->meshesMaterialsAsArray()) { + if(meshMaterial.first() < meshReferenceCount.size()) + ++meshReferenceCount[meshMaterial.first()]; + if(UnsignedInt(meshMaterial.second()) < materialReferenceCount.size()) + ++materialReferenceCount[meshMaterial.second()]; + } + + if(name == Trade::SceneField::Skin) for(const UnsignedInt skin: scene->skinsAsArray()) { + if(skin < skinReferenceCount.size()) + ++skinReferenceCount[skin]; + /** @todo 2D/3D distinction */ + } + + if(name == Trade::SceneField::Light) for(const UnsignedInt light: scene->lightsAsArray()) { + if(light < lightReferenceCount.size()) + ++lightReferenceCount[light]; + } + + arrayAppend(info.fields, InPlaceInit, + name, + Trade::isSceneFieldCustom(name) ? + importer->sceneFieldName(name) : "", + scene->fieldType(j), + scene->fieldArraySize(j), + scene->fieldSize(j)); } + + arrayAppend(sceneInfos, std::move(info)); } /* Animation properties */ @@ -573,6 +619,27 @@ used.)") Containers::Array imageInfos = Trade::Implementation::imageInfo(*importer, error, compactImages); + for(const SceneInfo& info: sceneInfos) { + Debug d; + d << "Scene" << info.scene << Debug::nospace << ":"; + if(!info.name.empty()) d << info.name; + d << Debug::newline; + d << " " << info.objectCount << "objects," << info.objectType + << "(" << Debug::nospace << Utility::formatString("{:.1f}", info.dataSize/1024.0f) << "kB)"; + + for(const SceneFieldInfo& field: info.fields) { + d << Debug::newline << " " << field.name; + if(Trade::isSceneFieldCustom(field.name)) { + d << "(" << Debug::nospace << field.customName + << Debug::nospace << ")"; + } + d << "@" << field.type; + if(field.arraySize) + d << Debug::nospace << Utility::formatString("[{}]", field.arraySize); + d << Debug::nospace << "," << field.size << "entries"; + } + } + for(const AnimationInfo& info: animationInfos) { Debug d; d << "Animation" << info.animation << Debug::nospace << ":"; @@ -606,7 +673,7 @@ used.)") d << "Skin" << info.skin; /* Print reference count only if there actually is a scene, otherwise this information is useless */ - if(importer->object3DCount()) + if(importer->objectCount()) d << Utility::formatString("(referenced by {} objects)", info.references); d << Debug::nospace << ":"; if(!info.name.empty()) d << info.name; @@ -619,7 +686,7 @@ used.)") d << "Light" << info.light; /* Print reference count only if there actually is a scene, otherwise this information is useless */ - if(importer->object3DCount()) + if(importer->objectCount()) d << Utility::formatString("(referenced by {} objects)", info.references); d << Debug::nospace << ":"; if(!info.name.empty()) d << info.name; @@ -638,7 +705,7 @@ used.)") d << "Material" << info.material; /* Print reference count only if there actually is a scene, otherwise this information is useless */ - if(importer->object3DCount()) + if(importer->objectCount()) d << Utility::formatString("(referenced by {} objects)", info.references); d << Debug::nospace << ":"; if(!info.name.empty()) d << info.name; @@ -721,7 +788,7 @@ used.)") d << "Mesh" << info.mesh; /* Print reference count only if there actually is a scene, otherwise this information is useless */ - if(importer->object3DCount()) + if(importer->objectCount()) d << Utility::formatString("(referenced by {} objects)", info.references); d << Debug::nospace << ":"; if(!info.name.empty()) d << info.name;