From 7864d237ecad062347c8a3aa292a06afe8d33492 Mon Sep 17 00:00:00 2001 From: bqqbarbhg Date: Fri, 22 Sep 2023 15:58:13 +0300 Subject: [PATCH 1/2] UfbxImporter: Add support for searching images --- .../ExternalTextures/tex-red-external.png | Bin 0 -> 69 bytes .../UfbxImporter/Test/UfbxImporterTest.cpp | 127 ++++- .../external-absolute-texture-missing.fbx | Bin 0 -> 18188 bytes .../Test/external-absolute-texture.fbx | Bin 0 -> 18188 bytes .../Test/image-absolute-path-mid-root.fbx | 455 ++++++++++++++++++ .../Test/image-absolute-path-multi-slash.fbx | 455 ++++++++++++++++++ .../UfbxImporter/Test/image-parent-path.fbx | 455 ++++++++++++++++++ .../UfbxImporter/UfbxImporter.conf | 10 + .../UfbxImporter/UfbxImporter.cpp | 57 ++- 9 files changed, 1555 insertions(+), 4 deletions(-) create mode 100644 src/MagnumPlugins/UfbxImporter/Test/ExternalTextures/tex-red-external.png create mode 100644 src/MagnumPlugins/UfbxImporter/Test/external-absolute-texture-missing.fbx create mode 100644 src/MagnumPlugins/UfbxImporter/Test/external-absolute-texture.fbx create mode 100644 src/MagnumPlugins/UfbxImporter/Test/image-absolute-path-mid-root.fbx create mode 100644 src/MagnumPlugins/UfbxImporter/Test/image-absolute-path-multi-slash.fbx create mode 100644 src/MagnumPlugins/UfbxImporter/Test/image-parent-path.fbx diff --git a/src/MagnumPlugins/UfbxImporter/Test/ExternalTextures/tex-red-external.png b/src/MagnumPlugins/UfbxImporter/Test/ExternalTextures/tex-red-external.png new file mode 100644 index 0000000000000000000000000000000000000000..a7045ed3777ba0813dc84d3b3965c3f1f2cd48db GIT binary patch literal 69 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1SBVv2j2ryJf1F&Asp9}f1E$Sz`)GN$RKgI RcLPwI!PC{xWt~$(69BjF4?+L{ literal 0 HcmV?d00001 diff --git a/src/MagnumPlugins/UfbxImporter/Test/UfbxImporterTest.cpp b/src/MagnumPlugins/UfbxImporter/Test/UfbxImporterTest.cpp index 4782844f3..ff3076f60 100644 --- a/src/MagnumPlugins/UfbxImporter/Test/UfbxImporterTest.cpp +++ b/src/MagnumPlugins/UfbxImporter/Test/UfbxImporterTest.cpp @@ -135,6 +135,13 @@ struct UfbxImporterTest: TestSuite::Tester { void imageDeduplication(); void imageNonExistentName(); void imageAbsolutePath(); + void imageSearch(); + void imageSearchSubdir(); + void imageSearchSubdirTooDeep(); + void imageSearchMissing(); + void imageSearchMidRoot(); + void imageSearchMultiSlash(); + void imageSearchParentPath(); void imageNot2D(); void imageBrokenExternal(); void imageBrokenEmbedded(); @@ -315,6 +322,13 @@ UfbxImporterTest::UfbxImporterTest() { &UfbxImporterTest::imageDeduplication, &UfbxImporterTest::imageNonExistentName, &UfbxImporterTest::imageAbsolutePath, + &UfbxImporterTest::imageSearch, + &UfbxImporterTest::imageSearchSubdir, + &UfbxImporterTest::imageSearchSubdirTooDeep, + &UfbxImporterTest::imageSearchMissing, + &UfbxImporterTest::imageSearchMidRoot, + &UfbxImporterTest::imageSearchMultiSlash, + &UfbxImporterTest::imageSearchParentPath, &UfbxImporterTest::imageNot2D, &UfbxImporterTest::imageBrokenExternal, &UfbxImporterTest::imageBrokenEmbedded, @@ -2330,11 +2344,122 @@ void UfbxImporterTest::imageAbsolutePath() { std::ostringstream out; Error redirectError{&out}; - CORRADE_VERIFY(!importer->image2D(0)); CORRADE_COMPARE_AS(out.str(), "Trade::AbstractImporter::openFile(): cannot open file /absolute/path/to/tex-red.png", TestSuite::Compare::StringContains); } +void UfbxImporterTest::imageSearch() { + if(_manager.loadState("PngImporter") == PluginManager::LoadState::NotFound) + CORRADE_SKIP("PngImporter plugin not found, cannot test"); + + Containers::Pointer importer = _manager.instantiate("UfbxImporter"); + importer->configuration().setValue("imageSearchDepth", -1); + CORRADE_VERIFY(importer->openFile(Utility::Path::join(UFBXIMPORTER_TEST_DIR, "image-absolute-path.fbx"))); + + CORRADE_COMPARE(importer->image2DCount(), 1); + + Containers::Optional image = importer->image2D(0); + CORRADE_VERIFY(image); + CORRADE_COMPARE(image->size(), (Vector2i{1, 1})); + CORRADE_COMPARE(image->pixels()[0][0], 0xff0000_rgb); +} + +void UfbxImporterTest::imageSearchSubdir() { + if(_manager.loadState("PngImporter") == PluginManager::LoadState::NotFound) + CORRADE_SKIP("PngImporter plugin not found, cannot test"); + + Containers::Pointer importer = _manager.instantiate("UfbxImporter"); + importer->configuration().setValue("imageSearchDepth", -1); + CORRADE_VERIFY(importer->openFile(Utility::Path::join(UFBXIMPORTER_TEST_DIR, "external-absolute-texture.fbx"))); + + CORRADE_COMPARE(importer->image2DCount(), 1); + + Containers::Optional image = importer->image2D(0); + CORRADE_VERIFY(image); + CORRADE_COMPARE(image->size(), (Vector2i{1, 1})); + CORRADE_COMPARE(image->pixels()[0][0], 0xff0000_rgb); +} + +void UfbxImporterTest::imageSearchSubdirTooDeep() { + if(_manager.loadState("PngImporter") == PluginManager::LoadState::NotFound) + CORRADE_SKIP("PngImporter plugin not found, cannot test"); + + Containers::Pointer importer = _manager.instantiate("UfbxImporter"); + importer->configuration().setValue("imageSearchDepth", 1); + CORRADE_VERIFY(importer->openFile(Utility::Path::join(UFBXIMPORTER_TEST_DIR, "external-absolute-texture.fbx"))); + + CORRADE_COMPARE(importer->image2DCount(), 1); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!importer->image2D(0)); + CORRADE_COMPARE_AS(out.str(), "Trade::UfbxImporter::image2D(): could not resolve image: W:/ExternalTextures/tex-red-external.png", TestSuite::Compare::StringContains); +} + +void UfbxImporterTest::imageSearchMissing() { + if(_manager.loadState("PngImporter") == PluginManager::LoadState::NotFound) + CORRADE_SKIP("PngImporter plugin not found, cannot test"); + + Containers::Pointer importer = _manager.instantiate("UfbxImporter"); + importer->configuration().setValue("imageSearchDepth", -1); + CORRADE_VERIFY(importer->openFile(Utility::Path::join(UFBXIMPORTER_TEST_DIR, "external-absolute-texture-missing.fbx"))); + + CORRADE_COMPARE(importer->image2DCount(), 1); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!importer->image2D(0)); + CORRADE_COMPARE_AS(out.str(), "Trade::UfbxImporter::image2D(): could not resolve image: W:/ExternalTextures/tex-missing-file.png", TestSuite::Compare::StringContains); +} + +void UfbxImporterTest::imageSearchMidRoot() { + if(_manager.loadState("PngImporter") == PluginManager::LoadState::NotFound) + CORRADE_SKIP("PngImporter plugin not found, cannot test"); + + Containers::Pointer importer = _manager.instantiate("UfbxImporter"); + importer->configuration().setValue("imageSearchDepth", -1); + CORRADE_VERIFY(importer->openFile(Utility::Path::join(UFBXIMPORTER_TEST_DIR, "image-absolute-path-mid-root.fbx"))); + + CORRADE_COMPARE(importer->image2DCount(), 1); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!importer->image2D(0)); + CORRADE_COMPARE_AS(out.str(), "Trade::UfbxImporter::image2D(): could not resolve image: /absolute/C:/to/tex-missing.png", TestSuite::Compare::StringContains); +} + +void UfbxImporterTest::imageSearchMultiSlash() { + if(_manager.loadState("PngImporter") == PluginManager::LoadState::NotFound) + CORRADE_SKIP("PngImporter plugin not found, cannot test"); + + Containers::Pointer importer = _manager.instantiate("UfbxImporter"); + importer->configuration().setValue("imageSearchDepth", -1); + CORRADE_VERIFY(importer->openFile(Utility::Path::join(UFBXIMPORTER_TEST_DIR, "image-absolute-path-multi-slash.fbx"))); + + CORRADE_COMPARE(importer->image2DCount(), 1); + + Containers::Optional image = importer->image2D(0); + CORRADE_VERIFY(image); + CORRADE_COMPARE(image->size(), (Vector2i{1, 1})); + CORRADE_COMPARE(image->pixels()[0][0], 0xff0000_rgb); +} + +void UfbxImporterTest::imageSearchParentPath() { + if(_manager.loadState("PngImporter") == PluginManager::LoadState::NotFound) + CORRADE_SKIP("PngImporter plugin not found, cannot test"); + + Containers::Pointer importer = _manager.instantiate("UfbxImporter"); + importer->configuration().setValue("imageSearchDepth", -1); + CORRADE_VERIFY(importer->openFile(Utility::Path::join(UFBXIMPORTER_TEST_DIR, "image-parent-path.fbx"))); + + CORRADE_COMPARE(importer->image2DCount(), 1); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!importer->image2D(0)); + CORRADE_COMPARE_AS(out.str(), "Trade::UfbxImporter::image2D(): could not resolve image: path/../UfbxImporter.cpp", TestSuite::Compare::StringContains); +} + void UfbxImporterTest::imageNot2D() { if(_manager.loadState("DdsImporter") == PluginManager::LoadState::NotFound) CORRADE_SKIP("DdsImporter plugin not found, cannot test"); diff --git a/src/MagnumPlugins/UfbxImporter/Test/external-absolute-texture-missing.fbx b/src/MagnumPlugins/UfbxImporter/Test/external-absolute-texture-missing.fbx new file mode 100644 index 0000000000000000000000000000000000000000..244cea712d9e4e5f876247a886c5b22be3bcd396 GIT binary patch literal 18188 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 i*QrYWUoih)mLh;r{}H>}tyZ literal 0 HcmV?d00001 diff --git a/src/MagnumPlugins/UfbxImporter/Test/external-absolute-texture.fbx b/src/MagnumPlugins/UfbxImporter/Test/external-absolute-texture.fbx new file mode 100644 index 0000000000000000000000000000000000000000..c6080005f6386c6a135c2adc1b3668136be69b57 GIT binary patch literal 18188 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 literal 0 HcmV?d00001 diff --git a/src/MagnumPlugins/UfbxImporter/Test/image-absolute-path-mid-root.fbx b/src/MagnumPlugins/UfbxImporter/Test/image-absolute-path-mid-root.fbx new file mode 100644 index 000000000..07e6ec00b --- /dev/null +++ b/src/MagnumPlugins/UfbxImporter/Test/image-absolute-path-mid-root.fbx @@ -0,0 +1,455 @@ +; FBX 7.7.0 project file +; ---------------------------------------------------- + +FBXHeaderExtension: { + FBXHeaderVersion: 1004 + FBXVersion: 7700 + CreationTimeStamp: { + Version: 1000 + Year: 2022 + Month: 12 + Day: 4 + Hour: 17 + Minute: 32 + Second: 4 + Millisecond: 104 + } + Creator: "FBX SDK/FBX Plugins version 2020.3" + OtherFlags: { + TCDefinition: 127 + } + SceneInfo: "SceneInfo::GlobalInfo", "UserData" { + Type: "UserData" + Version: 100 + MetaData: { + Version: 100 + Title: "" + Subject: "" + Author: "" + Keywords: "" + Revision: "" + Comment: "" + } + Properties70: { + P: "Original", "Compound", "", "" + P: "Original|ApplicationVendor", "KString", "", "", "Autodesk" + P: "Original|ApplicationName", "KString", "", "", "Maya" + P: "Original|ApplicationVersion", "KString", "", "", "2023" + P: "Original|DateTime_GMT", "DateTime", "", "", "04/12/2022 15:32:04.102" + P: "LastSaved", "Compound", "", "" + P: "LastSaved|ApplicationVendor", "KString", "", "", "Autodesk" + P: "LastSaved|ApplicationName", "KString", "", "", "Maya" + P: "LastSaved|ApplicationVersion", "KString", "", "", "2023" + P: "LastSaved|DateTime_GMT", "DateTime", "", "", "04/12/2022 15:32:04.102" + } + } +} +GlobalSettings: { + Version: 1000 + Properties70: { + P: "UpAxis", "int", "Integer", "",1 + P: "UpAxisSign", "int", "Integer", "",1 + P: "FrontAxis", "int", "Integer", "",2 + P: "FrontAxisSign", "int", "Integer", "",1 + P: "CoordAxis", "int", "Integer", "",0 + P: "CoordAxisSign", "int", "Integer", "",1 + P: "OriginalUpAxis", "int", "Integer", "",1 + P: "OriginalUpAxisSign", "int", "Integer", "",1 + P: "UnitScaleFactor", "double", "Number", "",1 + P: "OriginalUnitScaleFactor", "double", "Number", "",1 + P: "AmbientColor", "ColorRGB", "Color", "",0,0,0 + P: "DefaultCamera", "KString", "", "", "Producer Perspective" + P: "TimeMode", "enum", "", "",11 + P: "TimeProtocol", "enum", "", "",2 + P: "SnapOnFrameMode", "enum", "", "",0 + P: "TimeSpanStart", "KTime", "Time", "",0 + P: "TimeSpanStop", "KTime", "Time", "",192442325000 + P: "CustomFrameRate", "double", "Number", "",-1 + P: "TimeMarker", "Compound", "", "" + P: "CurrentTimeMarker", "int", "Integer", "",-1 + } +} + +; Documents Description +;------------------------------------------------------------------ + +Documents: { + Count: 1 + Document: 2547745423312, "", "Scene" { + Properties70: { + P: "SourceObject", "object", "", "" + P: "ActiveAnimStackName", "KString", "", "", "Take 001" + } + RootNode: 0 + } +} + +; Document References +;------------------------------------------------------------------ + +References: { +} + +; Object definitions +;------------------------------------------------------------------ + +Definitions: { + Version: 100 + Count: 8 + ObjectType: "GlobalSettings" { + Count: 1 + } + ObjectType: "AnimationStack" { + Count: 1 + PropertyTemplate: "FbxAnimStack" { + Properties70: { + P: "Description", "KString", "", "", "" + P: "LocalStart", "KTime", "Time", "",0 + P: "LocalStop", "KTime", "Time", "",0 + P: "ReferenceStart", "KTime", "Time", "",0 + P: "ReferenceStop", "KTime", "Time", "",0 + } + } + } + ObjectType: "AnimationLayer" { + Count: 1 + PropertyTemplate: "FbxAnimLayer" { + Properties70: { + P: "Weight", "Number", "", "A",100 + P: "Mute", "bool", "", "",0 + P: "Solo", "bool", "", "",0 + P: "Lock", "bool", "", "",0 + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "BlendMode", "enum", "", "",0 + P: "RotationAccumulationMode", "enum", "", "",0 + P: "ScaleAccumulationMode", "enum", "", "",0 + P: "BlendModeBypass", "ULongLong", "", "",0 + } + } + } + ObjectType: "Geometry" { + Count: 1 + PropertyTemplate: "FbxMesh" { + Properties70: { + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "BBoxMin", "Vector3D", "Vector", "",0,0,0 + P: "BBoxMax", "Vector3D", "Vector", "",0,0,0 + P: "Primary Visibility", "bool", "", "",1 + P: "Casts Shadows", "bool", "", "",1 + P: "Receive Shadows", "bool", "", "",1 + } + } + } + ObjectType: "Material" { + Count: 1 + PropertyTemplate: "FbxSurfaceLambert" { + Properties70: { + P: "ShadingModel", "KString", "", "", "Lambert" + P: "MultiLayer", "bool", "", "",0 + P: "EmissiveColor", "Color", "", "A",0,0,0 + P: "EmissiveFactor", "Number", "", "A",1 + P: "AmbientColor", "Color", "", "A",0.2,0.2,0.2 + P: "AmbientFactor", "Number", "", "A",1 + P: "DiffuseColor", "Color", "", "A",0.8,0.8,0.8 + P: "DiffuseFactor", "Number", "", "A",1 + P: "Bump", "Vector3D", "Vector", "",0,0,0 + P: "NormalMap", "Vector3D", "Vector", "",0,0,0 + P: "BumpFactor", "double", "Number", "",1 + P: "TransparentColor", "Color", "", "A",0,0,0 + P: "TransparencyFactor", "Number", "", "A",0 + P: "DisplacementColor", "ColorRGB", "Color", "",0,0,0 + P: "DisplacementFactor", "double", "Number", "",1 + P: "VectorDisplacementColor", "ColorRGB", "Color", "",0,0,0 + P: "VectorDisplacementFactor", "double", "Number", "",1 + } + } + } + ObjectType: "Texture" { + Count: 1 + PropertyTemplate: "FbxFileTexture" { + Properties70: { + P: "TextureTypeUse", "enum", "", "",0 + P: "Texture alpha", "Number", "", "A",1 + P: "CurrentMappingType", "enum", "", "",0 + P: "WrapModeU", "enum", "", "",0 + P: "WrapModeV", "enum", "", "",0 + P: "UVSwap", "bool", "", "",0 + P: "PremultiplyAlpha", "bool", "", "",1 + P: "Translation", "Vector", "", "A",0,0,0 + P: "Rotation", "Vector", "", "A",0,0,0 + P: "Scaling", "Vector", "", "A",1,1,1 + P: "TextureRotationPivot", "Vector3D", "Vector", "",0,0,0 + P: "TextureScalingPivot", "Vector3D", "Vector", "",0,0,0 + P: "CurrentTextureBlendMode", "enum", "", "",1 + P: "UVSet", "KString", "", "", "default" + P: "UseMaterial", "bool", "", "",0 + P: "UseMipMap", "bool", "", "",0 + } + } + } + ObjectType: "Model" { + Count: 1 + PropertyTemplate: "FbxNode" { + Properties70: { + P: "QuaternionInterpolate", "enum", "", "",0 + P: "RotationOffset", "Vector3D", "Vector", "",0,0,0 + P: "RotationPivot", "Vector3D", "Vector", "",0,0,0 + P: "ScalingOffset", "Vector3D", "Vector", "",0,0,0 + P: "ScalingPivot", "Vector3D", "Vector", "",0,0,0 + P: "TranslationActive", "bool", "", "",0 + P: "TranslationMin", "Vector3D", "Vector", "",0,0,0 + P: "TranslationMax", "Vector3D", "Vector", "",0,0,0 + P: "TranslationMinX", "bool", "", "",0 + P: "TranslationMinY", "bool", "", "",0 + P: "TranslationMinZ", "bool", "", "",0 + P: "TranslationMaxX", "bool", "", "",0 + P: "TranslationMaxY", "bool", "", "",0 + P: "TranslationMaxZ", "bool", "", "",0 + P: "RotationOrder", "enum", "", "",0 + P: "RotationSpaceForLimitOnly", "bool", "", "",0 + P: "RotationStiffnessX", "double", "Number", "",0 + P: "RotationStiffnessY", "double", "Number", "",0 + P: "RotationStiffnessZ", "double", "Number", "",0 + P: "AxisLen", "double", "Number", "",10 + P: "PreRotation", "Vector3D", "Vector", "",0,0,0 + P: "PostRotation", "Vector3D", "Vector", "",0,0,0 + P: "RotationActive", "bool", "", "",0 + P: "RotationMin", "Vector3D", "Vector", "",0,0,0 + P: "RotationMax", "Vector3D", "Vector", "",0,0,0 + P: "RotationMinX", "bool", "", "",0 + P: "RotationMinY", "bool", "", "",0 + P: "RotationMinZ", "bool", "", "",0 + P: "RotationMaxX", "bool", "", "",0 + P: "RotationMaxY", "bool", "", "",0 + P: "RotationMaxZ", "bool", "", "",0 + P: "InheritType", "enum", "", "",0 + P: "ScalingActive", "bool", "", "",0 + P: "ScalingMin", "Vector3D", "Vector", "",0,0,0 + P: "ScalingMax", "Vector3D", "Vector", "",1,1,1 + P: "ScalingMinX", "bool", "", "",0 + P: "ScalingMinY", "bool", "", "",0 + P: "ScalingMinZ", "bool", "", "",0 + P: "ScalingMaxX", "bool", "", "",0 + P: "ScalingMaxY", "bool", "", "",0 + P: "ScalingMaxZ", "bool", "", "",0 + P: "GeometricTranslation", "Vector3D", "Vector", "",0,0,0 + P: "GeometricRotation", "Vector3D", "Vector", "",0,0,0 + P: "GeometricScaling", "Vector3D", "Vector", "",1,1,1 + P: "MinDampRangeX", "double", "Number", "",0 + P: "MinDampRangeY", "double", "Number", "",0 + P: "MinDampRangeZ", "double", "Number", "",0 + P: "MaxDampRangeX", "double", "Number", "",0 + P: "MaxDampRangeY", "double", "Number", "",0 + P: "MaxDampRangeZ", "double", "Number", "",0 + P: "MinDampStrengthX", "double", "Number", "",0 + P: "MinDampStrengthY", "double", "Number", "",0 + P: "MinDampStrengthZ", "double", "Number", "",0 + P: "MaxDampStrengthX", "double", "Number", "",0 + P: "MaxDampStrengthY", "double", "Number", "",0 + P: "MaxDampStrengthZ", "double", "Number", "",0 + P: "PreferedAngleX", "double", "Number", "",0 + P: "PreferedAngleY", "double", "Number", "",0 + P: "PreferedAngleZ", "double", "Number", "",0 + P: "LookAtProperty", "object", "", "" + P: "UpVectorProperty", "object", "", "" + P: "Show", "bool", "", "",1 + P: "NegativePercentShapeSupport", "bool", "", "",1 + P: "DefaultAttributeIndex", "int", "Integer", "",-1 + P: "Freeze", "bool", "", "",0 + P: "LODBox", "bool", "", "",0 + P: "Lcl Translation", "Lcl Translation", "", "A",0,0,0 + P: "Lcl Rotation", "Lcl Rotation", "", "A",0,0,0 + P: "Lcl Scaling", "Lcl Scaling", "", "A",1,1,1 + P: "Visibility", "Visibility", "", "A",1 + P: "Visibility Inheritance", "Visibility Inheritance", "", "",1 + } + } + } + ObjectType: "Video" { + Count: 1 + PropertyTemplate: "FbxVideo" { + Properties70: { + P: "Path", "KString", "XRefUrl", "", "" + P: "RelPath", "KString", "XRefUrl", "", "" + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "ClipIn", "KTime", "Time", "",0 + P: "ClipOut", "KTime", "Time", "",0 + P: "Offset", "KTime", "Time", "",0 + P: "PlaySpeed", "double", "Number", "",0 + P: "FreeRunning", "bool", "", "",0 + P: "Loop", "bool", "", "",0 + P: "Mute", "bool", "", "",0 + P: "AccessMode", "enum", "", "",0 + P: "ImageSequence", "bool", "", "",0 + P: "ImageSequenceOffset", "int", "Integer", "",0 + P: "FrameRate", "double", "Number", "",0 + P: "LastFrame", "int", "Integer", "",0 + P: "Width", "int", "Integer", "",0 + P: "Height", "int", "Integer", "",0 + P: "StartFrame", "int", "Integer", "",0 + P: "StopFrame", "int", "Integer", "",0 + P: "InterlaceMode", "enum", "", "",0 + } + } + } +} + +; Object properties +;------------------------------------------------------------------ + +Objects: { + Geometry: 2547755072720, "Geometry::", "Mesh" { + Vertices: *24 { + a: -0.5,-0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,-0.5,-0.5,-0.5,0.5,-0.5,-0.5 + } + PolygonVertexIndex: *24 { + a: 0,1,3,-3,2,3,5,-5,4,5,7,-7,6,7,1,-1,1,7,5,-4,6,0,2,-5 + } + Edges: *12 { + a: 0,2,6,10,3,1,7,5,11,9,15,13 + } + GeometryVersion: 124 + LayerElementNormal: 0 { + Version: 102 + Name: "" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "Direct" + Normals: *72 { + a: 0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0 + } + NormalsW: *24 { + a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + } + } + LayerElementUV: 0 { + Version: 101 + Name: "map1" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "IndexToDirect" + UV: *28 { + a: 0.375,0,0.625,0,0.375,0.25,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.625,1,0.875,0,0.875,0.25,0.125,0,0.125,0.25 + } + UVIndex: *24 { + a: 0,1,3,2,2,3,5,4,4,5,7,6,6,7,9,8,1,10,11,3,12,0,2,13 + } + } + LayerElementMaterial: 0 { + Version: 101 + Name: "" + MappingInformationType: "AllSame" + ReferenceInformationType: "IndexToDirect" + Materials: *1 { + a: 0 + } + } + Layer: 0 { + Version: 100 + LayerElement: { + Type: "LayerElementNormal" + TypedIndex: 0 + } + LayerElement: { + Type: "LayerElementMaterial" + TypedIndex: 0 + } + LayerElement: { + Type: "LayerElementUV" + TypedIndex: 0 + } + } + } + Model: 2547465394448, "Model::pCube1", "Mesh" { + Version: 232 + Properties70: { + P: "RotationActive", "bool", "", "",1 + P: "InheritType", "enum", "", "",1 + P: "ScalingMax", "Vector3D", "Vector", "",0,0,0 + P: "DefaultAttributeIndex", "int", "Integer", "",0 + P: "currentUVSet", "KString", "", "U", "map1" + } + Shading: T + Culling: "CullingOff" + } + Material: 2547463729088, "Material::lambert1", "" { + Version: 102 + ShadingModel: "lambert" + MultiLayer: 0 + Properties70: { + P: "AmbientColor", "Color", "", "A",0,0,0 + P: "DiffuseColor", "Color", "", "A",1,1,1 + P: "DiffuseFactor", "Number", "", "A",0.800000011920929 + P: "TransparencyFactor", "Number", "", "A",1 + P: "Emissive", "Vector3D", "Vector", "",0,0,0 + P: "Ambient", "Vector3D", "Vector", "",0,0,0 + P: "Diffuse", "Vector3D", "Vector", "",0.800000011920929,0.800000011920929,0.800000011920929 + P: "Opacity", "double", "Number", "",1 + } + } + Video: 2547456447424, "Video::file1", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "/absolute/C:/to/tex-missing.png" + } + UseMipMap: 0 + Filename: "/absolute/C:/to/tex-missing.png" + } + Texture: 2547440851232, "Texture::file1", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::file1" + Properties70: { + P: "CurrentTextureBlendMode", "enum", "", "",0 + P: "UVSet", "KString", "", "", "map1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::file1" + FileName: "/absolute/C:/to/tex-missing.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + AnimationStack: 2547987022224, "AnimStack::Take 001", "" { + Properties70: { + P: "LocalStop", "KTime", "Time", "",38488465000 + P: "ReferenceStop", "KTime", "Time", "",38488465000 + } + } + AnimationLayer: 2547420079184, "AnimLayer::BaseLayer", "" { + } +} + +; Object connections +;------------------------------------------------------------------ + +Connections: { + + ;Model::pCube1, Model::RootNode + C: "OO",2547465394448,0 + + ;AnimLayer::BaseLayer, AnimStack::Take 001 + C: "OO",2547420079184,2547987022224 + + ;Texture::file1, Material::lambert1 + C: "OP",2547440851232,2547463729088, "DiffuseColor" + + ;Video::file1, Texture::file1 + C: "OO",2547456447424,2547440851232 + + ;Geometry::, Model::pCube1 + C: "OO",2547755072720,2547465394448 + + ;Material::lambert1, Model::pCube1 + C: "OO",2547463729088,2547465394448 +} +;Takes section +;---------------------------------------------------- + +Takes: { + Current: "Take 001" + Take: "Take 001" { + FileName: "Take_001.tak" + LocalTime: 0,38488465000 + ReferenceTime: 0,38488465000 + } +} diff --git a/src/MagnumPlugins/UfbxImporter/Test/image-absolute-path-multi-slash.fbx b/src/MagnumPlugins/UfbxImporter/Test/image-absolute-path-multi-slash.fbx new file mode 100644 index 000000000..04b074c1d --- /dev/null +++ b/src/MagnumPlugins/UfbxImporter/Test/image-absolute-path-multi-slash.fbx @@ -0,0 +1,455 @@ +; FBX 7.7.0 project file +; ---------------------------------------------------- + +FBXHeaderExtension: { + FBXHeaderVersion: 1004 + FBXVersion: 7700 + CreationTimeStamp: { + Version: 1000 + Year: 2022 + Month: 12 + Day: 4 + Hour: 17 + Minute: 32 + Second: 4 + Millisecond: 104 + } + Creator: "FBX SDK/FBX Plugins version 2020.3" + OtherFlags: { + TCDefinition: 127 + } + SceneInfo: "SceneInfo::GlobalInfo", "UserData" { + Type: "UserData" + Version: 100 + MetaData: { + Version: 100 + Title: "" + Subject: "" + Author: "" + Keywords: "" + Revision: "" + Comment: "" + } + Properties70: { + P: "Original", "Compound", "", "" + P: "Original|ApplicationVendor", "KString", "", "", "Autodesk" + P: "Original|ApplicationName", "KString", "", "", "Maya" + P: "Original|ApplicationVersion", "KString", "", "", "2023" + P: "Original|DateTime_GMT", "DateTime", "", "", "04/12/2022 15:32:04.102" + P: "LastSaved", "Compound", "", "" + P: "LastSaved|ApplicationVendor", "KString", "", "", "Autodesk" + P: "LastSaved|ApplicationName", "KString", "", "", "Maya" + P: "LastSaved|ApplicationVersion", "KString", "", "", "2023" + P: "LastSaved|DateTime_GMT", "DateTime", "", "", "04/12/2022 15:32:04.102" + } + } +} +GlobalSettings: { + Version: 1000 + Properties70: { + P: "UpAxis", "int", "Integer", "",1 + P: "UpAxisSign", "int", "Integer", "",1 + P: "FrontAxis", "int", "Integer", "",2 + P: "FrontAxisSign", "int", "Integer", "",1 + P: "CoordAxis", "int", "Integer", "",0 + P: "CoordAxisSign", "int", "Integer", "",1 + P: "OriginalUpAxis", "int", "Integer", "",1 + P: "OriginalUpAxisSign", "int", "Integer", "",1 + P: "UnitScaleFactor", "double", "Number", "",1 + P: "OriginalUnitScaleFactor", "double", "Number", "",1 + P: "AmbientColor", "ColorRGB", "Color", "",0,0,0 + P: "DefaultCamera", "KString", "", "", "Producer Perspective" + P: "TimeMode", "enum", "", "",11 + P: "TimeProtocol", "enum", "", "",2 + P: "SnapOnFrameMode", "enum", "", "",0 + P: "TimeSpanStart", "KTime", "Time", "",0 + P: "TimeSpanStop", "KTime", "Time", "",192442325000 + P: "CustomFrameRate", "double", "Number", "",-1 + P: "TimeMarker", "Compound", "", "" + P: "CurrentTimeMarker", "int", "Integer", "",-1 + } +} + +; Documents Description +;------------------------------------------------------------------ + +Documents: { + Count: 1 + Document: 2547745423312, "", "Scene" { + Properties70: { + P: "SourceObject", "object", "", "" + P: "ActiveAnimStackName", "KString", "", "", "Take 001" + } + RootNode: 0 + } +} + +; Document References +;------------------------------------------------------------------ + +References: { +} + +; Object definitions +;------------------------------------------------------------------ + +Definitions: { + Version: 100 + Count: 8 + ObjectType: "GlobalSettings" { + Count: 1 + } + ObjectType: "AnimationStack" { + Count: 1 + PropertyTemplate: "FbxAnimStack" { + Properties70: { + P: "Description", "KString", "", "", "" + P: "LocalStart", "KTime", "Time", "",0 + P: "LocalStop", "KTime", "Time", "",0 + P: "ReferenceStart", "KTime", "Time", "",0 + P: "ReferenceStop", "KTime", "Time", "",0 + } + } + } + ObjectType: "AnimationLayer" { + Count: 1 + PropertyTemplate: "FbxAnimLayer" { + Properties70: { + P: "Weight", "Number", "", "A",100 + P: "Mute", "bool", "", "",0 + P: "Solo", "bool", "", "",0 + P: "Lock", "bool", "", "",0 + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "BlendMode", "enum", "", "",0 + P: "RotationAccumulationMode", "enum", "", "",0 + P: "ScaleAccumulationMode", "enum", "", "",0 + P: "BlendModeBypass", "ULongLong", "", "",0 + } + } + } + ObjectType: "Geometry" { + Count: 1 + PropertyTemplate: "FbxMesh" { + Properties70: { + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "BBoxMin", "Vector3D", "Vector", "",0,0,0 + P: "BBoxMax", "Vector3D", "Vector", "",0,0,0 + P: "Primary Visibility", "bool", "", "",1 + P: "Casts Shadows", "bool", "", "",1 + P: "Receive Shadows", "bool", "", "",1 + } + } + } + ObjectType: "Material" { + Count: 1 + PropertyTemplate: "FbxSurfaceLambert" { + Properties70: { + P: "ShadingModel", "KString", "", "", "Lambert" + P: "MultiLayer", "bool", "", "",0 + P: "EmissiveColor", "Color", "", "A",0,0,0 + P: "EmissiveFactor", "Number", "", "A",1 + P: "AmbientColor", "Color", "", "A",0.2,0.2,0.2 + P: "AmbientFactor", "Number", "", "A",1 + P: "DiffuseColor", "Color", "", "A",0.8,0.8,0.8 + P: "DiffuseFactor", "Number", "", "A",1 + P: "Bump", "Vector3D", "Vector", "",0,0,0 + P: "NormalMap", "Vector3D", "Vector", "",0,0,0 + P: "BumpFactor", "double", "Number", "",1 + P: "TransparentColor", "Color", "", "A",0,0,0 + P: "TransparencyFactor", "Number", "", "A",0 + P: "DisplacementColor", "ColorRGB", "Color", "",0,0,0 + P: "DisplacementFactor", "double", "Number", "",1 + P: "VectorDisplacementColor", "ColorRGB", "Color", "",0,0,0 + P: "VectorDisplacementFactor", "double", "Number", "",1 + } + } + } + ObjectType: "Texture" { + Count: 1 + PropertyTemplate: "FbxFileTexture" { + Properties70: { + P: "TextureTypeUse", "enum", "", "",0 + P: "Texture alpha", "Number", "", "A",1 + P: "CurrentMappingType", "enum", "", "",0 + P: "WrapModeU", "enum", "", "",0 + P: "WrapModeV", "enum", "", "",0 + P: "UVSwap", "bool", "", "",0 + P: "PremultiplyAlpha", "bool", "", "",1 + P: "Translation", "Vector", "", "A",0,0,0 + P: "Rotation", "Vector", "", "A",0,0,0 + P: "Scaling", "Vector", "", "A",1,1,1 + P: "TextureRotationPivot", "Vector3D", "Vector", "",0,0,0 + P: "TextureScalingPivot", "Vector3D", "Vector", "",0,0,0 + P: "CurrentTextureBlendMode", "enum", "", "",1 + P: "UVSet", "KString", "", "", "default" + P: "UseMaterial", "bool", "", "",0 + P: "UseMipMap", "bool", "", "",0 + } + } + } + ObjectType: "Model" { + Count: 1 + PropertyTemplate: "FbxNode" { + Properties70: { + P: "QuaternionInterpolate", "enum", "", "",0 + P: "RotationOffset", "Vector3D", "Vector", "",0,0,0 + P: "RotationPivot", "Vector3D", "Vector", "",0,0,0 + P: "ScalingOffset", "Vector3D", "Vector", "",0,0,0 + P: "ScalingPivot", "Vector3D", "Vector", "",0,0,0 + P: "TranslationActive", "bool", "", "",0 + P: "TranslationMin", "Vector3D", "Vector", "",0,0,0 + P: "TranslationMax", "Vector3D", "Vector", "",0,0,0 + P: "TranslationMinX", "bool", "", "",0 + P: "TranslationMinY", "bool", "", "",0 + P: "TranslationMinZ", "bool", "", "",0 + P: "TranslationMaxX", "bool", "", "",0 + P: "TranslationMaxY", "bool", "", "",0 + P: "TranslationMaxZ", "bool", "", "",0 + P: "RotationOrder", "enum", "", "",0 + P: "RotationSpaceForLimitOnly", "bool", "", "",0 + P: "RotationStiffnessX", "double", "Number", "",0 + P: "RotationStiffnessY", "double", "Number", "",0 + P: "RotationStiffnessZ", "double", "Number", "",0 + P: "AxisLen", "double", "Number", "",10 + P: "PreRotation", "Vector3D", "Vector", "",0,0,0 + P: "PostRotation", "Vector3D", "Vector", "",0,0,0 + P: "RotationActive", "bool", "", "",0 + P: "RotationMin", "Vector3D", "Vector", "",0,0,0 + P: "RotationMax", "Vector3D", "Vector", "",0,0,0 + P: "RotationMinX", "bool", "", "",0 + P: "RotationMinY", "bool", "", "",0 + P: "RotationMinZ", "bool", "", "",0 + P: "RotationMaxX", "bool", "", "",0 + P: "RotationMaxY", "bool", "", "",0 + P: "RotationMaxZ", "bool", "", "",0 + P: "InheritType", "enum", "", "",0 + P: "ScalingActive", "bool", "", "",0 + P: "ScalingMin", "Vector3D", "Vector", "",0,0,0 + P: "ScalingMax", "Vector3D", "Vector", "",1,1,1 + P: "ScalingMinX", "bool", "", "",0 + P: "ScalingMinY", "bool", "", "",0 + P: "ScalingMinZ", "bool", "", "",0 + P: "ScalingMaxX", "bool", "", "",0 + P: "ScalingMaxY", "bool", "", "",0 + P: "ScalingMaxZ", "bool", "", "",0 + P: "GeometricTranslation", "Vector3D", "Vector", "",0,0,0 + P: "GeometricRotation", "Vector3D", "Vector", "",0,0,0 + P: "GeometricScaling", "Vector3D", "Vector", "",1,1,1 + P: "MinDampRangeX", "double", "Number", "",0 + P: "MinDampRangeY", "double", "Number", "",0 + P: "MinDampRangeZ", "double", "Number", "",0 + P: "MaxDampRangeX", "double", "Number", "",0 + P: "MaxDampRangeY", "double", "Number", "",0 + P: "MaxDampRangeZ", "double", "Number", "",0 + P: "MinDampStrengthX", "double", "Number", "",0 + P: "MinDampStrengthY", "double", "Number", "",0 + P: "MinDampStrengthZ", "double", "Number", "",0 + P: "MaxDampStrengthX", "double", "Number", "",0 + P: "MaxDampStrengthY", "double", "Number", "",0 + P: "MaxDampStrengthZ", "double", "Number", "",0 + P: "PreferedAngleX", "double", "Number", "",0 + P: "PreferedAngleY", "double", "Number", "",0 + P: "PreferedAngleZ", "double", "Number", "",0 + P: "LookAtProperty", "object", "", "" + P: "UpVectorProperty", "object", "", "" + P: "Show", "bool", "", "",1 + P: "NegativePercentShapeSupport", "bool", "", "",1 + P: "DefaultAttributeIndex", "int", "Integer", "",-1 + P: "Freeze", "bool", "", "",0 + P: "LODBox", "bool", "", "",0 + P: "Lcl Translation", "Lcl Translation", "", "A",0,0,0 + P: "Lcl Rotation", "Lcl Rotation", "", "A",0,0,0 + P: "Lcl Scaling", "Lcl Scaling", "", "A",1,1,1 + P: "Visibility", "Visibility", "", "A",1 + P: "Visibility Inheritance", "Visibility Inheritance", "", "",1 + } + } + } + ObjectType: "Video" { + Count: 1 + PropertyTemplate: "FbxVideo" { + Properties70: { + P: "Path", "KString", "XRefUrl", "", "" + P: "RelPath", "KString", "XRefUrl", "", "" + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "ClipIn", "KTime", "Time", "",0 + P: "ClipOut", "KTime", "Time", "",0 + P: "Offset", "KTime", "Time", "",0 + P: "PlaySpeed", "double", "Number", "",0 + P: "FreeRunning", "bool", "", "",0 + P: "Loop", "bool", "", "",0 + P: "Mute", "bool", "", "",0 + P: "AccessMode", "enum", "", "",0 + P: "ImageSequence", "bool", "", "",0 + P: "ImageSequenceOffset", "int", "Integer", "",0 + P: "FrameRate", "double", "Number", "",0 + P: "LastFrame", "int", "Integer", "",0 + P: "Width", "int", "Integer", "",0 + P: "Height", "int", "Integer", "",0 + P: "StartFrame", "int", "Integer", "",0 + P: "StopFrame", "int", "Integer", "",0 + P: "InterlaceMode", "enum", "", "",0 + } + } + } +} + +; Object properties +;------------------------------------------------------------------ + +Objects: { + Geometry: 2547755072720, "Geometry::", "Mesh" { + Vertices: *24 { + a: -0.5,-0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,-0.5,-0.5,-0.5,0.5,-0.5,-0.5 + } + PolygonVertexIndex: *24 { + a: 0,1,3,-3,2,3,5,-5,4,5,7,-7,6,7,1,-1,1,7,5,-4,6,0,2,-5 + } + Edges: *12 { + a: 0,2,6,10,3,1,7,5,11,9,15,13 + } + GeometryVersion: 124 + LayerElementNormal: 0 { + Version: 102 + Name: "" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "Direct" + Normals: *72 { + a: 0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0 + } + NormalsW: *24 { + a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + } + } + LayerElementUV: 0 { + Version: 101 + Name: "map1" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "IndexToDirect" + UV: *28 { + a: 0.375,0,0.625,0,0.375,0.25,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.625,1,0.875,0,0.875,0.25,0.125,0,0.125,0.25 + } + UVIndex: *24 { + a: 0,1,3,2,2,3,5,4,4,5,7,6,6,7,9,8,1,10,11,3,12,0,2,13 + } + } + LayerElementMaterial: 0 { + Version: 101 + Name: "" + MappingInformationType: "AllSame" + ReferenceInformationType: "IndexToDirect" + Materials: *1 { + a: 0 + } + } + Layer: 0 { + Version: 100 + LayerElement: { + Type: "LayerElementNormal" + TypedIndex: 0 + } + LayerElement: { + Type: "LayerElementMaterial" + TypedIndex: 0 + } + LayerElement: { + Type: "LayerElementUV" + TypedIndex: 0 + } + } + } + Model: 2547465394448, "Model::pCube1", "Mesh" { + Version: 232 + Properties70: { + P: "RotationActive", "bool", "", "",1 + P: "InheritType", "enum", "", "",1 + P: "ScalingMax", "Vector3D", "Vector", "",0,0,0 + P: "DefaultAttributeIndex", "int", "Integer", "",0 + P: "currentUVSet", "KString", "", "U", "map1" + } + Shading: T + Culling: "CullingOff" + } + Material: 2547463729088, "Material::lambert1", "" { + Version: 102 + ShadingModel: "lambert" + MultiLayer: 0 + Properties70: { + P: "AmbientColor", "Color", "", "A",0,0,0 + P: "DiffuseColor", "Color", "", "A",1,1,1 + P: "DiffuseFactor", "Number", "", "A",0.800000011920929 + P: "TransparencyFactor", "Number", "", "A",1 + P: "Emissive", "Vector3D", "Vector", "",0,0,0 + P: "Ambient", "Vector3D", "Vector", "",0,0,0 + P: "Diffuse", "Vector3D", "Vector", "",0.800000011920929,0.800000011920929,0.800000011920929 + P: "Opacity", "double", "Number", "",1 + } + } + Video: 2547456447424, "Video::file1", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "W:/ExternalTextures///tex-red-external.png" + } + UseMipMap: 0 + Filename: "/absolute/C:/to/tex-missing.png" + } + Texture: 2547440851232, "Texture::file1", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::file1" + Properties70: { + P: "CurrentTextureBlendMode", "enum", "", "",0 + P: "UVSet", "KString", "", "", "map1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::file1" + FileName: "W:/ExternalTextures///tex-red-external.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + AnimationStack: 2547987022224, "AnimStack::Take 001", "" { + Properties70: { + P: "LocalStop", "KTime", "Time", "",38488465000 + P: "ReferenceStop", "KTime", "Time", "",38488465000 + } + } + AnimationLayer: 2547420079184, "AnimLayer::BaseLayer", "" { + } +} + +; Object connections +;------------------------------------------------------------------ + +Connections: { + + ;Model::pCube1, Model::RootNode + C: "OO",2547465394448,0 + + ;AnimLayer::BaseLayer, AnimStack::Take 001 + C: "OO",2547420079184,2547987022224 + + ;Texture::file1, Material::lambert1 + C: "OP",2547440851232,2547463729088, "DiffuseColor" + + ;Video::file1, Texture::file1 + C: "OO",2547456447424,2547440851232 + + ;Geometry::, Model::pCube1 + C: "OO",2547755072720,2547465394448 + + ;Material::lambert1, Model::pCube1 + C: "OO",2547463729088,2547465394448 +} +;Takes section +;---------------------------------------------------- + +Takes: { + Current: "Take 001" + Take: "Take 001" { + FileName: "Take_001.tak" + LocalTime: 0,38488465000 + ReferenceTime: 0,38488465000 + } +} diff --git a/src/MagnumPlugins/UfbxImporter/Test/image-parent-path.fbx b/src/MagnumPlugins/UfbxImporter/Test/image-parent-path.fbx new file mode 100644 index 000000000..4df758b5f --- /dev/null +++ b/src/MagnumPlugins/UfbxImporter/Test/image-parent-path.fbx @@ -0,0 +1,455 @@ +; FBX 7.7.0 project file +; ---------------------------------------------------- + +FBXHeaderExtension: { + FBXHeaderVersion: 1004 + FBXVersion: 7700 + CreationTimeStamp: { + Version: 1000 + Year: 2022 + Month: 12 + Day: 4 + Hour: 17 + Minute: 32 + Second: 4 + Millisecond: 104 + } + Creator: "FBX SDK/FBX Plugins version 2020.3" + OtherFlags: { + TCDefinition: 127 + } + SceneInfo: "SceneInfo::GlobalInfo", "UserData" { + Type: "UserData" + Version: 100 + MetaData: { + Version: 100 + Title: "" + Subject: "" + Author: "" + Keywords: "" + Revision: "" + Comment: "" + } + Properties70: { + P: "Original", "Compound", "", "" + P: "Original|ApplicationVendor", "KString", "", "", "Autodesk" + P: "Original|ApplicationName", "KString", "", "", "Maya" + P: "Original|ApplicationVersion", "KString", "", "", "2023" + P: "Original|DateTime_GMT", "DateTime", "", "", "04/12/2022 15:32:04.102" + P: "LastSaved", "Compound", "", "" + P: "LastSaved|ApplicationVendor", "KString", "", "", "Autodesk" + P: "LastSaved|ApplicationName", "KString", "", "", "Maya" + P: "LastSaved|ApplicationVersion", "KString", "", "", "2023" + P: "LastSaved|DateTime_GMT", "DateTime", "", "", "04/12/2022 15:32:04.102" + } + } +} +GlobalSettings: { + Version: 1000 + Properties70: { + P: "UpAxis", "int", "Integer", "",1 + P: "UpAxisSign", "int", "Integer", "",1 + P: "FrontAxis", "int", "Integer", "",2 + P: "FrontAxisSign", "int", "Integer", "",1 + P: "CoordAxis", "int", "Integer", "",0 + P: "CoordAxisSign", "int", "Integer", "",1 + P: "OriginalUpAxis", "int", "Integer", "",1 + P: "OriginalUpAxisSign", "int", "Integer", "",1 + P: "UnitScaleFactor", "double", "Number", "",1 + P: "OriginalUnitScaleFactor", "double", "Number", "",1 + P: "AmbientColor", "ColorRGB", "Color", "",0,0,0 + P: "DefaultCamera", "KString", "", "", "Producer Perspective" + P: "TimeMode", "enum", "", "",11 + P: "TimeProtocol", "enum", "", "",2 + P: "SnapOnFrameMode", "enum", "", "",0 + P: "TimeSpanStart", "KTime", "Time", "",0 + P: "TimeSpanStop", "KTime", "Time", "",192442325000 + P: "CustomFrameRate", "double", "Number", "",-1 + P: "TimeMarker", "Compound", "", "" + P: "CurrentTimeMarker", "int", "Integer", "",-1 + } +} + +; Documents Description +;------------------------------------------------------------------ + +Documents: { + Count: 1 + Document: 2547745423312, "", "Scene" { + Properties70: { + P: "SourceObject", "object", "", "" + P: "ActiveAnimStackName", "KString", "", "", "Take 001" + } + RootNode: 0 + } +} + +; Document References +;------------------------------------------------------------------ + +References: { +} + +; Object definitions +;------------------------------------------------------------------ + +Definitions: { + Version: 100 + Count: 8 + ObjectType: "GlobalSettings" { + Count: 1 + } + ObjectType: "AnimationStack" { + Count: 1 + PropertyTemplate: "FbxAnimStack" { + Properties70: { + P: "Description", "KString", "", "", "" + P: "LocalStart", "KTime", "Time", "",0 + P: "LocalStop", "KTime", "Time", "",0 + P: "ReferenceStart", "KTime", "Time", "",0 + P: "ReferenceStop", "KTime", "Time", "",0 + } + } + } + ObjectType: "AnimationLayer" { + Count: 1 + PropertyTemplate: "FbxAnimLayer" { + Properties70: { + P: "Weight", "Number", "", "A",100 + P: "Mute", "bool", "", "",0 + P: "Solo", "bool", "", "",0 + P: "Lock", "bool", "", "",0 + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "BlendMode", "enum", "", "",0 + P: "RotationAccumulationMode", "enum", "", "",0 + P: "ScaleAccumulationMode", "enum", "", "",0 + P: "BlendModeBypass", "ULongLong", "", "",0 + } + } + } + ObjectType: "Geometry" { + Count: 1 + PropertyTemplate: "FbxMesh" { + Properties70: { + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "BBoxMin", "Vector3D", "Vector", "",0,0,0 + P: "BBoxMax", "Vector3D", "Vector", "",0,0,0 + P: "Primary Visibility", "bool", "", "",1 + P: "Casts Shadows", "bool", "", "",1 + P: "Receive Shadows", "bool", "", "",1 + } + } + } + ObjectType: "Material" { + Count: 1 + PropertyTemplate: "FbxSurfaceLambert" { + Properties70: { + P: "ShadingModel", "KString", "", "", "Lambert" + P: "MultiLayer", "bool", "", "",0 + P: "EmissiveColor", "Color", "", "A",0,0,0 + P: "EmissiveFactor", "Number", "", "A",1 + P: "AmbientColor", "Color", "", "A",0.2,0.2,0.2 + P: "AmbientFactor", "Number", "", "A",1 + P: "DiffuseColor", "Color", "", "A",0.8,0.8,0.8 + P: "DiffuseFactor", "Number", "", "A",1 + P: "Bump", "Vector3D", "Vector", "",0,0,0 + P: "NormalMap", "Vector3D", "Vector", "",0,0,0 + P: "BumpFactor", "double", "Number", "",1 + P: "TransparentColor", "Color", "", "A",0,0,0 + P: "TransparencyFactor", "Number", "", "A",0 + P: "DisplacementColor", "ColorRGB", "Color", "",0,0,0 + P: "DisplacementFactor", "double", "Number", "",1 + P: "VectorDisplacementColor", "ColorRGB", "Color", "",0,0,0 + P: "VectorDisplacementFactor", "double", "Number", "",1 + } + } + } + ObjectType: "Texture" { + Count: 1 + PropertyTemplate: "FbxFileTexture" { + Properties70: { + P: "TextureTypeUse", "enum", "", "",0 + P: "Texture alpha", "Number", "", "A",1 + P: "CurrentMappingType", "enum", "", "",0 + P: "WrapModeU", "enum", "", "",0 + P: "WrapModeV", "enum", "", "",0 + P: "UVSwap", "bool", "", "",0 + P: "PremultiplyAlpha", "bool", "", "",1 + P: "Translation", "Vector", "", "A",0,0,0 + P: "Rotation", "Vector", "", "A",0,0,0 + P: "Scaling", "Vector", "", "A",1,1,1 + P: "TextureRotationPivot", "Vector3D", "Vector", "",0,0,0 + P: "TextureScalingPivot", "Vector3D", "Vector", "",0,0,0 + P: "CurrentTextureBlendMode", "enum", "", "",1 + P: "UVSet", "KString", "", "", "default" + P: "UseMaterial", "bool", "", "",0 + P: "UseMipMap", "bool", "", "",0 + } + } + } + ObjectType: "Model" { + Count: 1 + PropertyTemplate: "FbxNode" { + Properties70: { + P: "QuaternionInterpolate", "enum", "", "",0 + P: "RotationOffset", "Vector3D", "Vector", "",0,0,0 + P: "RotationPivot", "Vector3D", "Vector", "",0,0,0 + P: "ScalingOffset", "Vector3D", "Vector", "",0,0,0 + P: "ScalingPivot", "Vector3D", "Vector", "",0,0,0 + P: "TranslationActive", "bool", "", "",0 + P: "TranslationMin", "Vector3D", "Vector", "",0,0,0 + P: "TranslationMax", "Vector3D", "Vector", "",0,0,0 + P: "TranslationMinX", "bool", "", "",0 + P: "TranslationMinY", "bool", "", "",0 + P: "TranslationMinZ", "bool", "", "",0 + P: "TranslationMaxX", "bool", "", "",0 + P: "TranslationMaxY", "bool", "", "",0 + P: "TranslationMaxZ", "bool", "", "",0 + P: "RotationOrder", "enum", "", "",0 + P: "RotationSpaceForLimitOnly", "bool", "", "",0 + P: "RotationStiffnessX", "double", "Number", "",0 + P: "RotationStiffnessY", "double", "Number", "",0 + P: "RotationStiffnessZ", "double", "Number", "",0 + P: "AxisLen", "double", "Number", "",10 + P: "PreRotation", "Vector3D", "Vector", "",0,0,0 + P: "PostRotation", "Vector3D", "Vector", "",0,0,0 + P: "RotationActive", "bool", "", "",0 + P: "RotationMin", "Vector3D", "Vector", "",0,0,0 + P: "RotationMax", "Vector3D", "Vector", "",0,0,0 + P: "RotationMinX", "bool", "", "",0 + P: "RotationMinY", "bool", "", "",0 + P: "RotationMinZ", "bool", "", "",0 + P: "RotationMaxX", "bool", "", "",0 + P: "RotationMaxY", "bool", "", "",0 + P: "RotationMaxZ", "bool", "", "",0 + P: "InheritType", "enum", "", "",0 + P: "ScalingActive", "bool", "", "",0 + P: "ScalingMin", "Vector3D", "Vector", "",0,0,0 + P: "ScalingMax", "Vector3D", "Vector", "",1,1,1 + P: "ScalingMinX", "bool", "", "",0 + P: "ScalingMinY", "bool", "", "",0 + P: "ScalingMinZ", "bool", "", "",0 + P: "ScalingMaxX", "bool", "", "",0 + P: "ScalingMaxY", "bool", "", "",0 + P: "ScalingMaxZ", "bool", "", "",0 + P: "GeometricTranslation", "Vector3D", "Vector", "",0,0,0 + P: "GeometricRotation", "Vector3D", "Vector", "",0,0,0 + P: "GeometricScaling", "Vector3D", "Vector", "",1,1,1 + P: "MinDampRangeX", "double", "Number", "",0 + P: "MinDampRangeY", "double", "Number", "",0 + P: "MinDampRangeZ", "double", "Number", "",0 + P: "MaxDampRangeX", "double", "Number", "",0 + P: "MaxDampRangeY", "double", "Number", "",0 + P: "MaxDampRangeZ", "double", "Number", "",0 + P: "MinDampStrengthX", "double", "Number", "",0 + P: "MinDampStrengthY", "double", "Number", "",0 + P: "MinDampStrengthZ", "double", "Number", "",0 + P: "MaxDampStrengthX", "double", "Number", "",0 + P: "MaxDampStrengthY", "double", "Number", "",0 + P: "MaxDampStrengthZ", "double", "Number", "",0 + P: "PreferedAngleX", "double", "Number", "",0 + P: "PreferedAngleY", "double", "Number", "",0 + P: "PreferedAngleZ", "double", "Number", "",0 + P: "LookAtProperty", "object", "", "" + P: "UpVectorProperty", "object", "", "" + P: "Show", "bool", "", "",1 + P: "NegativePercentShapeSupport", "bool", "", "",1 + P: "DefaultAttributeIndex", "int", "Integer", "",-1 + P: "Freeze", "bool", "", "",0 + P: "LODBox", "bool", "", "",0 + P: "Lcl Translation", "Lcl Translation", "", "A",0,0,0 + P: "Lcl Rotation", "Lcl Rotation", "", "A",0,0,0 + P: "Lcl Scaling", "Lcl Scaling", "", "A",1,1,1 + P: "Visibility", "Visibility", "", "A",1 + P: "Visibility Inheritance", "Visibility Inheritance", "", "",1 + } + } + } + ObjectType: "Video" { + Count: 1 + PropertyTemplate: "FbxVideo" { + Properties70: { + P: "Path", "KString", "XRefUrl", "", "" + P: "RelPath", "KString", "XRefUrl", "", "" + P: "Color", "ColorRGB", "Color", "",0.8,0.8,0.8 + P: "ClipIn", "KTime", "Time", "",0 + P: "ClipOut", "KTime", "Time", "",0 + P: "Offset", "KTime", "Time", "",0 + P: "PlaySpeed", "double", "Number", "",0 + P: "FreeRunning", "bool", "", "",0 + P: "Loop", "bool", "", "",0 + P: "Mute", "bool", "", "",0 + P: "AccessMode", "enum", "", "",0 + P: "ImageSequence", "bool", "", "",0 + P: "ImageSequenceOffset", "int", "Integer", "",0 + P: "FrameRate", "double", "Number", "",0 + P: "LastFrame", "int", "Integer", "",0 + P: "Width", "int", "Integer", "",0 + P: "Height", "int", "Integer", "",0 + P: "StartFrame", "int", "Integer", "",0 + P: "StopFrame", "int", "Integer", "",0 + P: "InterlaceMode", "enum", "", "",0 + } + } + } +} + +; Object properties +;------------------------------------------------------------------ + +Objects: { + Geometry: 2547755072720, "Geometry::", "Mesh" { + Vertices: *24 { + a: -0.5,-0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,0.5,0.5,0.5,-0.5,0.5,-0.5,0.5,0.5,-0.5,-0.5,-0.5,-0.5,0.5,-0.5,-0.5 + } + PolygonVertexIndex: *24 { + a: 0,1,3,-3,2,3,5,-5,4,5,7,-7,6,7,1,-1,1,7,5,-4,6,0,2,-5 + } + Edges: *12 { + a: 0,2,6,10,3,1,7,5,11,9,15,13 + } + GeometryVersion: 124 + LayerElementNormal: 0 { + Version: 102 + Name: "" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "Direct" + Normals: *72 { + a: 0,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0 + } + NormalsW: *24 { + a: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 + } + } + LayerElementUV: 0 { + Version: 101 + Name: "map1" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "IndexToDirect" + UV: *28 { + a: 0.375,0,0.625,0,0.375,0.25,0.625,0.25,0.375,0.5,0.625,0.5,0.375,0.75,0.625,0.75,0.375,1,0.625,1,0.875,0,0.875,0.25,0.125,0,0.125,0.25 + } + UVIndex: *24 { + a: 0,1,3,2,2,3,5,4,4,5,7,6,6,7,9,8,1,10,11,3,12,0,2,13 + } + } + LayerElementMaterial: 0 { + Version: 101 + Name: "" + MappingInformationType: "AllSame" + ReferenceInformationType: "IndexToDirect" + Materials: *1 { + a: 0 + } + } + Layer: 0 { + Version: 100 + LayerElement: { + Type: "LayerElementNormal" + TypedIndex: 0 + } + LayerElement: { + Type: "LayerElementMaterial" + TypedIndex: 0 + } + LayerElement: { + Type: "LayerElementUV" + TypedIndex: 0 + } + } + } + Model: 2547465394448, "Model::pCube1", "Mesh" { + Version: 232 + Properties70: { + P: "RotationActive", "bool", "", "",1 + P: "InheritType", "enum", "", "",1 + P: "ScalingMax", "Vector3D", "Vector", "",0,0,0 + P: "DefaultAttributeIndex", "int", "Integer", "",0 + P: "currentUVSet", "KString", "", "U", "map1" + } + Shading: T + Culling: "CullingOff" + } + Material: 2547463729088, "Material::lambert1", "" { + Version: 102 + ShadingModel: "lambert" + MultiLayer: 0 + Properties70: { + P: "AmbientColor", "Color", "", "A",0,0,0 + P: "DiffuseColor", "Color", "", "A",1,1,1 + P: "DiffuseFactor", "Number", "", "A",0.800000011920929 + P: "TransparencyFactor", "Number", "", "A",1 + P: "Emissive", "Vector3D", "Vector", "",0,0,0 + P: "Ambient", "Vector3D", "Vector", "",0,0,0 + P: "Diffuse", "Vector3D", "Vector", "",0.800000011920929,0.800000011920929,0.800000011920929 + P: "Opacity", "double", "Number", "",1 + } + } + Video: 2547456447424, "Video::file1", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "path/../UfbxImporter.cpp" + } + UseMipMap: 0 + Filename: "path/../UfbxImporter.cpp" + } + Texture: 2547440851232, "Texture::file1", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::file1" + Properties70: { + P: "CurrentTextureBlendMode", "enum", "", "",0 + P: "UVSet", "KString", "", "", "map1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::file1" + FileName: "path/../UfbxImporter.cpp" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + AnimationStack: 2547987022224, "AnimStack::Take 001", "" { + Properties70: { + P: "LocalStop", "KTime", "Time", "",38488465000 + P: "ReferenceStop", "KTime", "Time", "",38488465000 + } + } + AnimationLayer: 2547420079184, "AnimLayer::BaseLayer", "" { + } +} + +; Object connections +;------------------------------------------------------------------ + +Connections: { + + ;Model::pCube1, Model::RootNode + C: "OO",2547465394448,0 + + ;AnimLayer::BaseLayer, AnimStack::Take 001 + C: "OO",2547420079184,2547987022224 + + ;Texture::file1, Material::lambert1 + C: "OP",2547440851232,2547463729088, "DiffuseColor" + + ;Video::file1, Texture::file1 + C: "OO",2547456447424,2547440851232 + + ;Geometry::, Model::pCube1 + C: "OO",2547755072720,2547465394448 + + ;Material::lambert1, Model::pCube1 + C: "OO",2547463729088,2547465394448 +} +;Takes section +;---------------------------------------------------- + +Takes: { + Current: "Take 001" + Take: "Take 001" { + FileName: "Take_001.tak" + LocalTime: 0,38488465000 + ReferenceTime: 0,38488465000 + } +} diff --git a/src/MagnumPlugins/UfbxImporter/UfbxImporter.conf b/src/MagnumPlugins/UfbxImporter/UfbxImporter.conf index 0fa5531d1..a1f08f51a 100644 --- a/src/MagnumPlugins/UfbxImporter/UfbxImporter.conf +++ b/src/MagnumPlugins/UfbxImporter/UfbxImporter.conf @@ -30,6 +30,16 @@ ignoreEmbedded=false # information such as object relationships and names. ignoreAllContent=false +# Search for images if the relative path is not found. +# For example for an absolute path "C:/path/to/image.png" the importer will +# check if a file exists in the following order, relative to the .fbx file: +# (depth=1) ./image.png +# (depth=2) ./to/image.png +# (depth=3) ./path/to/image.png +# The default value of imageSearchDepth=0 will never search for images, +# use -1 of unbounded amount of subdirectories to search. +imageSearchDepth=0 + # Maximum amount of temporary memory in bytes to use, negative for unlimited. # Loading is aborted if memory usage exceeds this limit. maxTemporaryMemory=-1 diff --git a/src/MagnumPlugins/UfbxImporter/UfbxImporter.cpp b/src/MagnumPlugins/UfbxImporter/UfbxImporter.cpp index 8c89e02cf..31ce3f744 100644 --- a/src/MagnumPlugins/UfbxImporter/UfbxImporter.cpp +++ b/src/MagnumPlugins/UfbxImporter/UfbxImporter.cpp @@ -1468,9 +1468,60 @@ AbstractImporter* UfbxImporter::setupOrReuseImporterForImage(UnsignedInt id, con return nullptr; } - ufbx_string filename = file.filename.length > 0 ? file.filename : file.absolute_filename; - if(!importer.openFile(filename)) - return nullptr; + const ufbx_string filename = file.filename.length > 0 ? file.filename : file.absolute_filename; + const UnsignedInt imageSearchDepth = unboundedIfNegative(configuration().value("imageSearchDepth")); + if(imageSearchDepth > 0) { + bool found = false; + Containers::String path = Utility::Path::fromNativeSeparators(filename); + if (!path.isEmpty() && Utility::Path::exists(path)) { + found = true; + } else { + const Containers::String root = Utility::Path::fromNativeSeparators(_state->scene->metadata.relative_root); + /* Resolve path manually from either relative or absolute filename, + do not use filename here as it already includes the relative + path of the FBX file. */ + path = Utility::Path::fromNativeSeparators(file.relative_filename.length > 0 ? file.relative_filename : file.absolute_filename); + + /* Try to find files with increasing amount of directories, + for /root/sub/dir/file.png we would try in order: + file.png, dir/file.png, sub/dir/file.png */ + size_t relativeBegin = path.size(); + for(UnsignedInt depth = 0; depth < imageSearchDepth && relativeBegin > 0; depth++) { + /* Trim all consecutive parent separators */ + while(relativeBegin > 0 && path[relativeBegin - 1] == '/') + relativeBegin -= 1; + + const Containers::StringView parent = path.prefix(relativeBegin).findLastOr('/', path.begin()); + relativeBegin = size_t(parent.end() - path.begin()); + + const Containers::StringView relativeSuffix = path.exceptPrefix(relativeBegin); + + /* Do not allow searching from parent or absolute directories. + Note that Windows-style C:/ paths are considered absolute on + all platforms as many FBX files contain Windows absolute + paths, even in the RelativeFilename field */ + if(relativeSuffix.hasPrefix("../"_s) || relativeSuffix.hasPrefix("/"_s) + || (relativeSuffix.size() >= 3 && relativeSuffix[1] == ':' && relativeSuffix[2] == '/')) + break; + + const Containers::String relativePath = Utility::Path::join(root, path.exceptPrefix(relativeBegin)); + if (Utility::Path::exists(relativePath)) { + found = true; + path = relativePath; + break; + } + } + } + if (!found) { + Error{} << errorPrefix << "could not resolve image:" << path; + return nullptr; + } + if(!importer.openFile(path)) + return nullptr; + } else { + if(!importer.openFile(filename)) + return nullptr; + } } if(importer.image2DCount() != 1) { From 6522e39aef300a712e467a0fadc8314dd5863a11 Mon Sep 17 00:00:00 2001 From: bqqbarbhg Date: Fri, 22 Sep 2023 16:44:28 +0300 Subject: [PATCH 2/2] UfbxImporter: Add fromWindowsSeparators() We need to convert Windows paths from the file even on non-Windows --- .../UfbxImporter/UfbxImporter.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/MagnumPlugins/UfbxImporter/UfbxImporter.cpp b/src/MagnumPlugins/UfbxImporter/UfbxImporter.cpp index 31ce3f744..f8b56d8ef 100644 --- a/src/MagnumPlugins/UfbxImporter/UfbxImporter.cpp +++ b/src/MagnumPlugins/UfbxImporter/UfbxImporter.cpp @@ -1437,6 +1437,18 @@ Containers::Optional UfbxImporter::doTexture(UnsignedInt id) { fileTexture.fileTextureIndex}; } +namespace { + +Containers::String fromWindowsSeparators(Containers::String path) +{ + /* Windows implementation of Utility::Path::fromNativeSeparators() */ + if(!path.isSmall() && path.deleter()) path = Containers::String{path}; + for(char& c: path) if(c == '\\') c = '/'; + return path; +} + +} + AbstractImporter* UfbxImporter::setupOrReuseImporterForImage(UnsignedInt id, const char* errorPrefix) { const ufbx_texture_file& file = _state->scene->texture_files[id]; @@ -1472,15 +1484,15 @@ AbstractImporter* UfbxImporter::setupOrReuseImporterForImage(UnsignedInt id, con const UnsignedInt imageSearchDepth = unboundedIfNegative(configuration().value("imageSearchDepth")); if(imageSearchDepth > 0) { bool found = false; - Containers::String path = Utility::Path::fromNativeSeparators(filename); + Containers::String path = fromWindowsSeparators(filename); if (!path.isEmpty() && Utility::Path::exists(path)) { found = true; } else { - const Containers::String root = Utility::Path::fromNativeSeparators(_state->scene->metadata.relative_root); + const Containers::String root = fromWindowsSeparators(_state->scene->metadata.relative_root); /* Resolve path manually from either relative or absolute filename, do not use filename here as it already includes the relative path of the FBX file. */ - path = Utility::Path::fromNativeSeparators(file.relative_filename.length > 0 ? file.relative_filename : file.absolute_filename); + path = fromWindowsSeparators(file.relative_filename.length > 0 ? file.relative_filename : file.absolute_filename); /* Try to find files with increasing amount of directories, for /root/sub/dir/file.png we would try in order: