diff --git a/doc/changelog.dox b/doc/changelog.dox index 13826a031..1c112c59f 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -495,10 +495,10 @@ See also: - Added a `--bounds` option to @ref magnum-sceneconverter "magnum-sceneconverter", showing data ranges of known attributes - @ref magnum-sceneconverter "magnum-sceneconverter" now has separate - `--info-animations`, `--info-images`, `--info-lights`, `--info-materials`, - `--info-meshes`, `--info-skins` and `--info-textures` for printing - information just about particular data type, with `--info` being a shortcut - for all specified together + `--info-animations`, `--info-images`, `--info-lights`, `--info-cameras`, + `--info-materials`, `--info-meshes`, `--info-skins` and `--info-textures` + for printing information just about particular data type, with `--info` + being a shortcut for all specified together @subsubsection changelog-latest-changes-shaders Shaders library diff --git a/src/Magnum/SceneTools/Implementation/sceneConverterUtilities.h b/src/Magnum/SceneTools/Implementation/sceneConverterUtilities.h index 6c41538d2..2de8de8f9 100644 --- a/src/Magnum/SceneTools/Implementation/sceneConverterUtilities.h +++ b/src/Magnum/SceneTools/Implementation/sceneConverterUtilities.h @@ -33,6 +33,7 @@ #include "Magnum/Math/FunctionsBatch.h" #include "Magnum/Trade/AnimationData.h" +#include "Magnum/Trade/CameraData.h" #include "Magnum/Trade/LightData.h" #include "Magnum/Trade/MaterialData.h" #include "Magnum/Trade/MeshData.h" @@ -87,6 +88,12 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility Containers::String name; }; + struct CameraInfo { + UnsignedInt camera; + Trade::CameraData data{{}, {}, {}, {}}; + Containers::String name; + }; + struct MaterialInfo { UnsignedInt material; Trade::MaterialData data{{}, {}}; @@ -176,12 +183,14 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility std::unordered_map sceneFieldNames; Containers::Array materialReferenceCount; Containers::Array lightReferenceCount; + Containers::Array cameraReferenceCount; Containers::Array meshReferenceCount; Containers::Array skin2DReferenceCount; Containers::Array skin3DReferenceCount; if((args.isSet("info") || args.isSet("info-scenes")) && importer.sceneCount()) { materialReferenceCount = Containers::Array{importer.materialCount()}; lightReferenceCount = Containers::Array{importer.lightCount()}; + cameraReferenceCount = Containers::Array{importer.cameraCount()}; meshReferenceCount = Containers::Array{importer.meshCount()}; skin2DReferenceCount = Containers::Array{importer.skin2DCount()}; skin3DReferenceCount = Containers::Array{importer.skin3DCount()}; @@ -222,6 +231,11 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility ++lightReferenceCount[light.second()]; } + if(name == Trade::SceneField::Camera) for(const Containers::Pair& camera: scene->camerasAsArray()) { + if(camera.second() < cameraReferenceCount.size()) + ++cameraReferenceCount[camera.second()]; + } + arrayAppend(info.fields, InPlaceInit, name, scene->fieldFlags(j), @@ -339,6 +353,26 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility arrayAppend(lightInfos, std::move(info)); } + /* Camera properties */ + Containers::Array cameraInfos; + if(args.isSet("info") || args.isSet("info-cameras")) for(UnsignedInt i = 0; i != importer.cameraCount(); ++i) { + Containers::Optional camera; + { + Trade::Implementation::Duration d{importTime}; + if(!(camera = importer.camera(i))) { + error = true; + continue; + } + } + + CameraInfo info{}; + info.camera = i; + info.name = importer.cameraName(i); + info.data = *std::move(camera); + + arrayAppend(cameraInfos, std::move(info)); + } + /* Material properties, together with how much is each texture shared (which gets used only if both --info-materials and --info-textures is passed and the file has at least one material). */ @@ -722,6 +756,41 @@ bool printInfo(const Debug::Flags useColor, const bool useColor24, const Utility << info.data.range(); } + for(const CameraInfo& info: cameraInfos) { + Debug d{useColor}; + d << Debug::boldColor(Debug::Color::Default) << "Camera" << info.camera << Debug::resetColor; + + /* Print reference count only if there actually are scenes and they + were parsed, otherwise this information is useless */ + if(cameraReferenceCount) { + const UnsignedInt count = cameraReferenceCount[info.camera]; + if(!count) d << Debug::color(Debug::Color::Red); + d << "(referenced by" << count << "objects)"; + if(!count) d << Debug::resetColor; + } + + d << Debug::boldColor(Debug::Color::Default) << Debug::nospace << ":" + << Debug::resetColor; + if(info.name) d << Debug::boldColor(Debug::Color::Yellow) + << info.name << Debug::resetColor; + + d << Debug::newline << " Type:" << Debug::packed + << Debug::color(Debug::Color::Cyan) + << info.data.type() << Debug::resetColor << Debug::newline; + /* Print orthographic cameras with size, perspective with FoV */ + if(info.data.type() == Trade::CameraType::Orthographic2D || + info.data.type() == Trade::CameraType::Orthographic3D) { + d << " Size:" << Debug::packed << info.data.size(); + } else if(info.data.type() == Trade::CameraType::Perspective3D) { + d << " FoV:" << Debug::packed << Deg(info.data.fov()) + << Debug::nospace << "°"; + } + /* Near/far is implicitly 0 for 2D */ + if(info.data.type() != Trade::CameraType::Orthographic2D) + d << Debug::nospace << "," << info.data.near() << "-" << info.data.far(); + d << Debug::newline << " Aspect ratio:" << info.data.aspectRatio(); + } + for(const MaterialInfo& info: materialInfos) { Debug d{useColor}; d << Debug::boldColor(Debug::Color::Default) << "Material" << info.material << Debug::resetColor; diff --git a/src/Magnum/SceneTools/Test/CMakeLists.txt b/src/Magnum/SceneTools/Test/CMakeLists.txt index e021cff00..0ea8253b3 100644 --- a/src/Magnum/SceneTools/Test/CMakeLists.txt +++ b/src/Magnum/SceneTools/Test/CMakeLists.txt @@ -45,6 +45,7 @@ corrade_add_test(SceneToolsSceneConverterTest SceneConverterTest.cpp LIBRARIES MagnumSceneTools FILES SceneConverterTestFiles/info-animations.txt + SceneConverterTestFiles/info-cameras.txt SceneConverterTestFiles/info-images.txt SceneConverterTestFiles/info-lights.txt SceneConverterTestFiles/info-materials.txt diff --git a/src/Magnum/SceneTools/Test/SceneConverterTest.cpp b/src/Magnum/SceneTools/Test/SceneConverterTest.cpp index f6bc6c649..abf4589e0 100644 --- a/src/Magnum/SceneTools/Test/SceneConverterTest.cpp +++ b/src/Magnum/SceneTools/Test/SceneConverterTest.cpp @@ -49,6 +49,7 @@ struct SceneConverterTest: TestSuite::Tester { void infoImplementationAnimations(); void infoImplementationSkins(); void infoImplementationLights(); + void infoImplementationCameras(); void infoImplementationMaterials(); void infoImplementationMeshes(); void infoImplementationMeshesBounds(); @@ -92,6 +93,7 @@ SceneConverterTest::SceneConverterTest() { addInstancedTests({&SceneConverterTest::infoImplementationAnimations, &SceneConverterTest::infoImplementationSkins, &SceneConverterTest::infoImplementationLights, + &SceneConverterTest::infoImplementationCameras, &SceneConverterTest::infoImplementationMaterials, &SceneConverterTest::infoImplementationMeshes}, Containers::arraySize(InfoImplementationOneOrAllData)); @@ -112,6 +114,7 @@ SceneConverterTest::SceneConverterTest() { .addBooleanOption("info-animations") .addBooleanOption("info-skins") .addBooleanOption("info-lights") + .addBooleanOption("info-cameras") .addBooleanOption("info-materials") .addBooleanOption("info-meshes") .addBooleanOption("info-textures") @@ -434,6 +437,65 @@ void SceneConverterTest::infoImplementationLights() { TestSuite::Compare::StringToFile); } +void SceneConverterTest::infoImplementationCameras() { + auto&& data = InfoImplementationOneOrAllData[testCaseInstanceId()]; + setTestCaseDescription(data.name); + + struct Importer: Trade::AbstractImporter { + Trade::ImporterFeatures doFeatures() const override { return {}; } + bool doIsOpened() const override { return true; } + void doClose() override {} + + UnsignedInt doCameraCount() const override { return 3; } + Containers::String doCameraName(UnsignedInt id) override { + return id == 0 ? "Orthographic 2D" : ""; + } + Containers::Optional doCamera(UnsignedInt id) override { + /* First 2D ortho camera, where near/far will get omited */ + if(id == 0) return Trade::CameraData{ + Trade::CameraType::Orthographic2D, + {5.0f, 6.0f}, + 0.0f, 0.0f + }; + + /* 3D ortho camera */ + if(id == 1) return Trade::CameraData{ + Trade::CameraType::Orthographic3D, + {2.0f, 3.0f}, + -1.0f, 0.5f + }; + + /* Third a perspective camera, specified with size, but printed + with FoV */ + if(id == 2) return Trade::CameraData{ + Trade::CameraType::Perspective3D, + 35.0_degf, 4.0f/3.0f, 0.01f, 100.0f + }; + + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + } importer; + + const char* argv[]{"", data.oneOrAll ? "--info-cameras" : "--info"}; + CORRADE_VERIFY(_infoArgs.tryParse(Containers::arraySize(argv), argv)); + + std::chrono::high_resolution_clock::duration time; + + /* Print to visually verify coloring */ + if(data.printVisualCheck) { + Debug{} << "======================== visual color verification start ======================="; + Implementation::printInfo(Debug::isTty() ? Debug::Flags{} : Debug::Flag::DisableColors, Debug::isTty(), _infoArgs, importer, time); + Debug{} << "======================== visual color verification end ========================="; + } + + std::ostringstream out; + Debug redirectOutput{&out}; + CORRADE_VERIFY(Implementation::printInfo(Debug::Flag::DisableColors, false, _infoArgs, importer, time) == false); + CORRADE_COMPARE_AS(out.str(), + Utility::Path::join(SCENETOOLS_TEST_DIR, "SceneConverterTestFiles/info-cameras.txt"), + TestSuite::Compare::StringToFile); +} + void SceneConverterTest::infoImplementationMaterials() { auto&& data = InfoImplementationOneOrAllData[testCaseInstanceId()]; setTestCaseDescription(data.name); @@ -783,6 +845,9 @@ void SceneConverterTest::infoImplementationReferenceCount() { Trade::SceneFieldData{Trade::SceneField::Light, Containers::arrayView(sceneData3D->mapping), Containers::arrayView(sceneData3D->lights)}, + Trade::SceneFieldData{Trade::SceneField::Camera, + Containers::arrayView(sceneData3D->mapping), + Containers::arrayView(sceneData3D->cameras)}, Trade::SceneFieldData{Trade::SceneField::Skin, Containers::arrayView(sceneData3D->mapping), Containers::arrayView(sceneData3D->skins)}, @@ -866,6 +931,29 @@ void SceneConverterTest::infoImplementationReferenceCount() { CORRADE_INTERNAL_ASSERT_UNREACHABLE(); } + UnsignedInt doCameraCount() const override { return 3; } + Containers::String doCameraName(UnsignedInt id) override { + return id == 0 ? "Not referenced" : ""; + } + Containers::Optional doCamera(UnsignedInt id) override { + if(id == 0) return Trade::CameraData{ + Trade::CameraType::Orthographic3D, + {2.0f, 3.0f}, + -1.0f, 0.5f + }; + if(id == 1) return Trade::CameraData{ + Trade::CameraType::Orthographic3D, + {2.0f, 2.0f}, + 0.0f, 1.0f + }; + if(id == 2) return Trade::CameraData{ + Trade::CameraType::Orthographic2D, + {2.0f, 2.0f}, + 0.0f, 0.0f + }; + CORRADE_INTERNAL_ASSERT_UNREACHABLE(); + } + UnsignedInt doMaterialCount() const override { return 3; } Containers::String doMaterialName(UnsignedInt id) override { return id == 2 ? "Not referenced" : ""; @@ -985,12 +1073,14 @@ void SceneConverterTest::infoImplementationReferenceCount() { UnsignedInt meshes[4]; Int materials[4]; UnsignedInt lights[4]; + UnsignedInt cameras[4]; UnsignedInt skins[4]; } sceneData3D[1]{{ {0, 1, 1, 25}, {2, 0, 2, 67}, {0, 1, 23, 0}, {0, 17, 0, 2}, + {166, 1, 2, 1}, {1, 1, 22, 2} }}; @@ -1066,6 +1156,12 @@ void SceneConverterTest::infoImplementationError() { return {}; } + UnsignedInt doCameraCount() const override { return 2; } + Containers::Optional doCamera(UnsignedInt id) override { + Error{} << "Camera" << id << "error!"; + return {}; + } + UnsignedInt doMaterialCount() const override { return 2; } Containers::Optional doMaterial(UnsignedInt id) override { Error{} << "Material" << id << "error!"; @@ -1114,6 +1210,8 @@ void SceneConverterTest::infoImplementationError() { "3D skin 1 error!\n" "Light 0 error!\n" "Light 1 error!\n" + "Camera 0 error!\n" + "Camera 1 error!\n" "Material 0 error!\n" "Material 1 error!\n" "Mesh 0 error!\n" diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-cameras.txt b/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-cameras.txt new file mode 100644 index 000000000..9977ea326 --- /dev/null +++ b/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-cameras.txt @@ -0,0 +1,12 @@ +Camera 0: Orthographic 2D + Type: Orthographic2D + Size: {5, 6} + Aspect ratio: 0.833333 +Camera 1: + Type: Orthographic3D + Size: {2, 3}, -1 - 0.5 + Aspect ratio: 0.666667 +Camera 2: + Type: Perspective3D + FoV: 35°, 0.01 - 100 + Aspect ratio: 1.33333 diff --git a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-references.txt b/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-references.txt index 1cda5540b..927de37b7 100644 --- a/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-references.txt +++ b/src/Magnum/SceneTools/Test/SceneConverterTestFiles/info-references.txt @@ -5,6 +5,7 @@ Scene 0: Mesh @ UnsignedInt, 4 entries MeshMaterial @ Int, 4 entries Light @ UnsignedInt, 4 entries + Camera @ UnsignedInt, 4 entries Skin @ UnsignedInt, 4 entries Scene 1: Bound: 4 objects @ UnsignedInt (0.0 kB, {}) @@ -14,9 +15,9 @@ Scene 1: Skin @ UnsignedInt, 3 entries Total scene data size: 0.1 kB Object 0 (referenced by 1 scenes): - Fields: Mesh, MeshMaterial, Light, Skin + Fields: Mesh, MeshMaterial, Light, Camera, Skin Object 1 (referenced by 2 scenes): - Fields: Mesh[2], MeshMaterial[2], Light[2], Skin[2], Mesh, Skin + Fields: Mesh[2], MeshMaterial[2], Light[2], Camera[2], Skin[2], Mesh, Skin Object 2 (referenced by 0 scenes): Not referenced Object 3 (referenced by 1 scenes): Fields: Mesh, Skin @@ -41,6 +42,18 @@ Light 1 (referenced by 0 objects): Not referenced Light 2 (referenced by 1 objects): Type: Directional Color: {0.203922, 0.341176, 1} +Camera 0 (referenced by 0 objects): Not referenced + Type: Orthographic3D + Size: {2, 3}, -1 - 0.5 + Aspect ratio: 0.666667 +Camera 1 (referenced by 2 objects): + Type: Orthographic3D + Size: {2, 2}, 0 - 1 + Aspect ratio: 1 +Camera 2 (referenced by 1 objects): + Type: Orthographic2D + Size: {2, 2} + Aspect ratio: 1 Material 0 (referenced by 2 objects): Type: {} Base layer: diff --git a/src/Magnum/SceneTools/sceneconverter.cpp b/src/Magnum/SceneTools/sceneconverter.cpp index 4dff2f194..b7c015fc0 100644 --- a/src/Magnum/SceneTools/sceneconverter.cpp +++ b/src/Magnum/SceneTools/sceneconverter.cpp @@ -122,8 +122,8 @@ magnum-sceneconverter [-h|--help] [-I|--importer PLUGIN] [-i|--importer-options key=val,key2=val2,…] [-c|--converter-options key=val,key2=val2,…]... [--mesh MESH] [--level LEVEL] [--concatenate-meshes] [--info-animations] [--info-images] - [--info-lights] [--info-materials] [--info-meshes] [--info-objects] - [--info-scenes] [--info-skins] [--info-textures] [--info] + [--info-lights] [--info-cameras] [--info-materials] [--info-meshes] + [--info-objects] [--info-scenes] [--info-skins] [--info-textures] [--info] [--color on|4bit|off|auto] [--bounds] [-v|--verbose] [--profile] [--] input output @endcode @@ -161,6 +161,7 @@ Arguments: exit - `--info-images` --- print into about images in the input file and exit - `--info-lights` --- print into about lights in the input file and exit +- `--info-cameras` --- print into about cameras in the input file and exit - `--info-materials` --- print into about materials in the input file and exit - `--info-meshes` --- print into about meshes in the input file and exit @@ -218,6 +219,7 @@ bool isInfoRequested(const Utility::Arguments& args) { return args.isSet("info-animations") || args.isSet("info-images") || args.isSet("info-lights") || + args.isSet("info-cameras") || args.isSet("info-materials") || args.isSet("info-meshes") || args.isSet("info-objects") || @@ -250,6 +252,7 @@ int main(int argc, char** argv) { .addBooleanOption("info-animations").setHelp("info-animations", "print info about animations in the input file and exit") .addBooleanOption("info-images").setHelp("info-images", "print info about images in the input file and exit") .addBooleanOption("info-lights").setHelp("info-lights", "print info about images in the input file and exit") + .addBooleanOption("info-cameras").setHelp("info-cameras", "print info about cameras in the input file and exit") .addBooleanOption("info-materials").setHelp("info-materials", "print info about materials in the input file and exit") .addBooleanOption("info-meshes").setHelp("info-meshes", "print info about meshes in the input file and exit") .addBooleanOption("info-objects").setHelp("info-objects", "print info about objects in the input file and exit")