From f7be3048de830c5b3567c23a04c3746079bfcb67 Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Tue, 1 Dec 2020 12:05:42 +0000 Subject: [PATCH 1/9] New 3ds Max PBR Materials in FBX --- code/AssetLib/FBX/FBXConverter.cpp | 15 +- code/AssetLib/FBX/FBXProperties.cpp | 12 +- test/models/FBX/maxPbrMaterial_metalRough.fbx | 618 ++++++++++++++++++ test/models/FBX/maxPbrMaterial_specGloss.fbx | 618 ++++++++++++++++++ test/unit/utFBXImporterExporter.cpp | 106 +++ 5 files changed, 1367 insertions(+), 2 deletions(-) create mode 100644 test/models/FBX/maxPbrMaterial_metalRough.fbx create mode 100644 test/models/FBX/maxPbrMaterial_specGloss.fbx diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index efecf450f..e6b1a75c0 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -2011,12 +2011,25 @@ void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const TextureMap &_ TrySetTextureProperties(out_mat, _textures, "Maya|TEX_roughness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh); TrySetTextureProperties(out_mat, _textures, "Maya|TEX_ao_map", aiTextureType_AMBIENT_OCCLUSION, mesh); - // 3DSMax PBR + // 3DSMax Physical material TrySetTextureProperties(out_mat, _textures, "3dsMax|Parameters|base_color_map", aiTextureType_BASE_COLOR, mesh); TrySetTextureProperties(out_mat, _textures, "3dsMax|Parameters|bump_map", aiTextureType_NORMAL_CAMERA, mesh); TrySetTextureProperties(out_mat, _textures, "3dsMax|Parameters|emission_map", aiTextureType_EMISSION_COLOR, mesh); TrySetTextureProperties(out_mat, _textures, "3dsMax|Parameters|metalness_map", aiTextureType_METALNESS, mesh); TrySetTextureProperties(out_mat, _textures, "3dsMax|Parameters|roughness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh); + + // 3DSMax PBR materials + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|base_color_map", aiTextureType_BASE_COLOR, mesh); + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|norm_map", aiTextureType_NORMAL_CAMERA, mesh); + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|emit_color_map", aiTextureType_EMISSION_COLOR, mesh); + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|ao_map", aiTextureType_AMBIENT_OCCLUSION, mesh); + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|opacity_map", aiTextureType_OPACITY, mesh); + // Metalness/Roughness mode + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|metalness_map", aiTextureType_METALNESS, mesh); + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|roughness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh); + // Specular/Gloss mode + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|specular_map", aiTextureType_SPECULAR, mesh); + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|glossiness_map", aiTextureType_SHININESS, mesh); } void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const LayeredTextureMap &layeredTextures, const MeshGeometry *const mesh) { diff --git a/code/AssetLib/FBX/FBXProperties.cpp b/code/AssetLib/FBX/FBXProperties.cpp index a3a95228e..ccccd3012 100644 --- a/code/AssetLib/FBX/FBXProperties.cpp +++ b/code/AssetLib/FBX/FBXProperties.cpp @@ -90,7 +90,7 @@ Property* ReadTypedProperty(const Element& element) ai_assert(tok.size() >= 5); return new TypedProperty(ParseTokenAsInt(*tok[4]) != 0); } - else if (!strcmp(cs, "int") || !strcmp(cs, "Int") || !strcmp(cs, "enum") || !strcmp(cs, "Enum")) { + else if (!strcmp(cs, "int") || !strcmp(cs, "Int") || !strcmp(cs, "enum") || !strcmp(cs, "Enum") || !strcmp(cs, "Integer")) { ai_assert(tok.size() >= 5); return new TypedProperty(ParseTokenAsInt(*tok[4])); } @@ -121,6 +121,16 @@ Property* ReadTypedProperty(const Element& element) ai_assert(tok.size() >= 5); return new TypedProperty(ParseTokenAsFloat(*tok[4])); } + else if (!strcmp(cs, "ColorAndAlpha")) + { + ai_assert(tok.size() >= 8); + return new TypedProperty(aiColor4D( + ParseTokenAsFloat(*tok[4]), + ParseTokenAsFloat(*tok[5]), + ParseTokenAsFloat(*tok[6]), + ParseTokenAsFloat(*tok[7])) + ); + } return nullptr; } diff --git a/test/models/FBX/maxPbrMaterial_metalRough.fbx b/test/models/FBX/maxPbrMaterial_metalRough.fbx new file mode 100644 index 000000000..a66275269 --- /dev/null +++ b/test/models/FBX/maxPbrMaterial_metalRough.fbx @@ -0,0 +1,618 @@ +; FBX 7.7.0 project file +; ---------------------------------------------------- + +FBXHeaderExtension: { + FBXHeaderVersion: 1004 + FBXVersion: 7700 + CreationTimeStamp: { + Version: 1000 + Year: 2020 + Month: 12 + Day: 1 + Hour: 9 + Minute: 35 + Second: 57 + Millisecond: 532 + } + Creator: "FBX SDK/FBX Plugins version 2020.0.1" + OtherFlags: { + TCDefinition: 127 + } + SceneInfo: "SceneInfo::GlobalInfo", "UserData" { + Type: "UserData" + Version: 100 + MetaData: { + Version: 100 + Title: "" + Subject: "" + Author: "" + Keywords: "" + Revision: "" + Comment: "" + } + Properties70: { + P: "DocumentUrl", "KString", "Url", "", "G:\Temp\Max2021PbrMaterials\MaxPbrMaterial.fbx" + P: "SrcDocumentUrl", "KString", "Url", "", "G:\Temp\Max2021PbrMaterials\MaxPbrMaterial.fbx" + P: "Original", "Compound", "", "" + P: "Original|ApplicationVendor", "KString", "", "", "Autodesk" + P: "Original|ApplicationName", "KString", "", "", "3ds Max" + P: "Original|ApplicationVersion", "KString", "", "", "2021" + P: "Original|DateTime_GMT", "DateTime", "", "", "01/12/2020 09:35:57.532" + P: "Original|FileName", "KString", "", "", "G:\Temp\Max2021PbrMaterials\MaxPbrMaterial.fbx" + P: "LastSaved", "Compound", "", "" + P: "LastSaved|ApplicationVendor", "KString", "", "", "Autodesk" + P: "LastSaved|ApplicationName", "KString", "", "", "3ds Max" + P: "LastSaved|ApplicationVersion", "KString", "", "", "2021" + P: "LastSaved|DateTime_GMT", "DateTime", "", "", "01/12/2020 09:35:57.532" + P: "Original|ApplicationActiveProject", "KString", "", "", "C:\3ds Max 2021" + P: "Original|ApplicationNativeFile", "KString", "", "", "C;\3ds Max 2021\MaxPbrMaterial.max" + } + } +} +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", "",2 + P: "OriginalUpAxisSign", "int", "Integer", "",1 + P: "UnitScaleFactor", "double", "Number", "",100 + P: "OriginalUnitScaleFactor", "double", "Number", "",100.00000066 + P: "AmbientColor", "ColorRGB", "Color", "",0,0,0 + P: "DefaultCamera", "KString", "", "", "Producer Perspective" + P: "TimeMode", "enum", "", "",6 + P: "TimeProtocol", "enum", "", "",2 + P: "SnapOnFrameMode", "enum", "", "",0 + P: "TimeSpanStart", "KTime", "Time", "",0 + P: "TimeSpanStop", "KTime", "Time", "",153953860000 + P: "CustomFrameRate", "double", "Number", "",-1 + P: "TimeMarker", "Compound", "", "" + P: "CurrentTimeMarker", "int", "Integer", "",-1 + } +} + +; Documents Description +;------------------------------------------------------------------ + +Documents: { + Count: 1 + Document: 2188301813872, "", "Scene" { + Properties70: { + P: "SourceObject", "object", "", "" + P: "ActiveAnimStackName", "KString", "", "", "" + } + RootNode: 0 + } +} + +; Document References +;------------------------------------------------------------------ + +References: { +} + +; Object definitions +;------------------------------------------------------------------ + +Definitions: { + Version: 100 + Count: 18 + ObjectType: "GlobalSettings" { + Count: 1 + } + 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: "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: "FbxSurfaceMaterial" { + Properties70: { + P: "ShadingModel", "KString", "", "", "Unknown" + P: "MultiLayer", "bool", "", "",0 + } + } + } + ObjectType: "Texture" { + Count: 7 + 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: "Video" { + Count: 7 + 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: 2188426094640, "Geometry::", "Mesh" { + Properties70: { + P: "Color", "ColorRGB", "Color", "",0.341176470588235,0.882352941176471,0.776470588235294 + } + Vertices: *24 { + a: -8.91135215759277,-10.98219871521,0,8.91135215759277,-10.98219871521,0,-8.91135215759277,10.98219871521,0,8.91135215759277,10.98219871521,0,-8.91135215759277,-10.98219871521,16.787576675415,8.91135215759277,-10.98219871521,16.787576675415,-8.91135215759277,10.98219871521,16.787576675415,8.91135215759277,10.98219871521,16.787576675415 + } + PolygonVertexIndex: *24 { + a: 0,2,3,-2,4,5,7,-7,0,1,5,-5,1,3,7,-6,3,2,6,-8,2,0,4,-7 + } + Edges: *12 { + a: 0,1,2,3,4,5,6,7,9,11,13,17 + } + 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,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,0,1,0,0,1,0,0,1,0,0,1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0 + } + NormalsW: *24 { + a: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + } + } + LayerElementUV: 0 { + Version: 101 + Name: "UVChannel_1" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "IndexToDirect" + UV: *48 { + a: 1,0,0,0,1,1,0,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1 + } + UVIndex: *24 { + a: 0,2,3,1,4,5,7,6,8,9,11,10,12,13,15,14,16,17,19,18,20,21,23,22 + } + } + 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: 2187845653184, "Model::Box001", "Mesh" { + Version: 232 + Properties70: { + P: "PreRotation", "Vector3D", "Vector", "",-90,-0,0 + P: "RotationActive", "bool", "", "",1 + P: "InheritType", "enum", "", "",1 + P: "ScalingMax", "Vector3D", "Vector", "",0,0,0 + P: "DefaultAttributeIndex", "int", "Integer", "",0 + P: "Lcl Translation", "Lcl Translation", "", "A",0.570660591125488,0,-0.671265125274658 + P: "MaxHandle", "int", "Integer", "UH",2 + } + Shading: T + Culling: "CullingOff" + } + Material: 2188102329504, "Material::PBR Material", "" { + Version: 102 + ShadingModel: "unknown" + MultiLayer: 0 + Properties70: { + P: "ShadingModel", "KString", "", "", "unknown" + P: "AmbientColor", "ColorRGB", "Color", "",0,1,1 + P: "DiffuseColor", "ColorRGB", "Color", "",0,1,1 + P: "SpecularColor", "ColorRGB", "Color", "",0.75,1,1 + P: "SpecularFactor", "double", "Number", "",2.25 + P: "ShininessExponent", "double", "Number", "",32 + P: "TransparencyFactor", "double", "Number", "",0 + P: "EmissiveColor", "ColorRGB", "Color", "",3.14159274101257,3.14159250259399,0 + P: "EmissiveFactor", "double", "Number", "",1 + P: "3dsMax", "Compound", "", "" + P: "3dsMax|ClassIDa", "int", "Integer", "",-804315648 + P: "3dsMax|ClassIDb", "int", "Integer", "",-1099438848 + P: "3dsMax|SuperClassID", "int", "Integer", "",3072 + P: "3dsMax|settings", "Compound", "", "" + P: "3dsMax|settings|ao_affects_diffuse", "Bool", "", "A",1 + P: "3dsMax|settings|ao_affects_reflection", "Bool", "", "A",1 + P: "3dsMax|settings|normal_flip_red", "Bool", "", "A",0 + P: "3dsMax|settings|normal_flip_green", "Bool", "", "A",0 + P: "3dsMax|main", "Compound", "", "" + P: "3dsMax|main|basecolor", "ColorAndAlpha", "", "A",0,1,1,1 + P: "3dsMax|main|base_color_map", "Reference", "", "A" + P: "3dsMax|main|metalness", "Float", "", "A",0.25 + P: "3dsMax|main|metalness_map", "Reference", "", "A" + P: "3dsMax|main|roughness", "Float", "", "A",0.5 + P: "3dsMax|main|roughness_map", "Reference", "", "A" + P: "3dsMax|main|useGlossiness", "Integer", "", "A",2 + P: "3dsMax|main|ao_map", "Reference", "", "A" + P: "3dsMax|main|bump_map_amt", "Float", "", "A",0.75 + P: "3dsMax|main|norm_map", "Reference", "", "A" + P: "3dsMax|main|emit_color", "ColorAndAlpha", "", "A",1,1,0,1 + P: "3dsMax|main|emit_color_map", "Reference", "", "A" + P: "3dsMax|main|opacity_map", "Reference", "", "A" + } + } + Video: 2188262711712, "Video::Albedo", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\albedo.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\albedo.png" + } + UseMipMap: 0 + Filename: "Textures\albedo.png" + RelativeFilename: "Textures\albedo.png" + } + Video: 2188262695872, "Video::Metalness", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\metalness.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\metalness.png" + } + UseMipMap: 0 + Filename: "Textures\metalness.png" + RelativeFilename: "Textures\metalness.png" + } + Video: 2188262686752, "Video::Roughness", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\roughness.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\roughness.png" + } + UseMipMap: 0 + Filename: "Textures\roughness.png" + RelativeFilename: "Textures\roughness.png" + } + Video: 2188262700672, "Video::Occlusion", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\occlusion.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\occlusion.png" + } + UseMipMap: 0 + Filename: "Textures\occlusion.png" + RelativeFilename: "Textures\occlusion.png" + } + Video: 2188262708832, "Video::Normal", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\normal.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\normal.png" + } + UseMipMap: 0 + Filename: "Textures\normal.png" + RelativeFilename: "Textures\normal.png" + } + Video: 2188262712672, "Video::Emission", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\emission.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\emission.png" + } + UseMipMap: 0 + Filename: "Textures\emission.png" + RelativeFilename: "Textures\emission.png" + } + Video: 2188262696352, "Video::Opacity", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\opacity.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\opacity.png" + } + UseMipMap: 0 + Filename: "Textures\opacity.png" + RelativeFilename: "Textures\opacity.png" + } + Texture: 2188262656992, "Texture::Albedo", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Albedo" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Albedo" + FileName: "Textures\albedo.png" + RelativeFilename: "Textures\albedo.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2188262678592, "Texture::Metalness", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Metalness" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Metalness" + FileName: "Textures\metalness.png" + RelativeFilename: "Textures\metalness.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2188262682432, "Texture::Roughness", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Roughness" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Roughness" + FileName: "Textures\roughness.png" + RelativeFilename: "Textures\roughness.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2188262656032, "Texture::Occlusion", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Occlusion" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Occlusion" + FileName: "Textures\occlusion.png" + RelativeFilename: "Textures\occlusion.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2188262659392, "Texture::Normal", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Normal" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Normal" + FileName: "Textures\normal.png" + RelativeFilename: "Textures\normal.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2188262700192, "Texture::Emission", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Emission" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Emission" + FileName: "Textures\emission.png" + RelativeFilename: "Textures\emission.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2188262684832, "Texture::Opacity", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Opacity" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Opacity" + FileName: "Textures\opacity.png" + RelativeFilename: "Textures\opacity.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } +} + +; Object connections +;------------------------------------------------------------------ + +Connections: { + + ;Model::Box001, Model::RootNode + C: "OO",2187845653184,0 + + ;Geometry::, Model::Box001 + C: "OO",2188426094640,2187845653184 + + ;Material::PBR Material, Model::Box001 + C: "OO",2188102329504,2187845653184 + + ;Texture::Albedo, Material::PBR Material + C: "OP",2188262656992,2188102329504, "3dsMax|main|base_color_map" + + ;Texture::Metalness, Material::PBR Material + C: "OP",2188262678592,2188102329504, "3dsMax|main|metalness_map" + + ;Texture::Roughness, Material::PBR Material + C: "OP",2188262682432,2188102329504, "3dsMax|main|roughness_map" + + ;Texture::Occlusion, Material::PBR Material + C: "OP",2188262656032,2188102329504, "3dsMax|main|ao_map" + + ;Texture::Normal, Material::PBR Material + C: "OP",2188262659392,2188102329504, "3dsMax|main|norm_map" + + ;Texture::Emission, Material::PBR Material + C: "OP",2188262700192,2188102329504, "3dsMax|main|emit_color_map" + + ;Texture::Opacity, Material::PBR Material + C: "OP",2188262684832,2188102329504, "3dsMax|main|opacity_map" + + ;Video::Albedo, Texture::Albedo + C: "OO",2188262711712,2188262656992 + + ;Video::Metalness, Texture::Metalness + C: "OO",2188262695872,2188262678592 + + ;Video::Roughness, Texture::Roughness + C: "OO",2188262686752,2188262682432 + + ;Video::Occlusion, Texture::Occlusion + C: "OO",2188262700672,2188262656032 + + ;Video::Normal, Texture::Normal + C: "OO",2188262708832,2188262659392 + + ;Video::Emission, Texture::Emission + C: "OO",2188262712672,2188262700192 + + ;Video::Opacity, Texture::Opacity + C: "OO",2188262696352,2188262684832 +} diff --git a/test/models/FBX/maxPbrMaterial_specGloss.fbx b/test/models/FBX/maxPbrMaterial_specGloss.fbx new file mode 100644 index 000000000..83a4432c9 --- /dev/null +++ b/test/models/FBX/maxPbrMaterial_specGloss.fbx @@ -0,0 +1,618 @@ +; FBX 7.7.0 project file +; ---------------------------------------------------- + +FBXHeaderExtension: { + FBXHeaderVersion: 1004 + FBXVersion: 7700 + CreationTimeStamp: { + Version: 1000 + Year: 2020 + Month: 12 + Day: 1 + Hour: 11 + Minute: 50 + Second: 44 + Millisecond: 89 + } + Creator: "FBX SDK/FBX Plugins version 2020.0.1" + OtherFlags: { + TCDefinition: 127 + } + SceneInfo: "SceneInfo::GlobalInfo", "UserData" { + Type: "UserData" + Version: 100 + MetaData: { + Version: 100 + Title: "" + Subject: "" + Author: "" + Keywords: "" + Revision: "" + Comment: "" + } + Properties70: { + P: "DocumentUrl", "KString", "Url", "", "C:\3ds Max 2021\maxPbrMaterial_specGloss.fbx" + P: "SrcDocumentUrl", "KString", "Url", "", "C:\3ds Max 2021\maxPbrMaterial_specGloss.fbx" + P: "Original", "Compound", "", "" + P: "Original|ApplicationVendor", "KString", "", "", "Autodesk" + P: "Original|ApplicationName", "KString", "", "", "3ds Max" + P: "Original|ApplicationVersion", "KString", "", "", "2021" + P: "Original|DateTime_GMT", "DateTime", "", "", "01/12/2020 11:50:44.088" + P: "Original|FileName", "KString", "", "", "C:\3ds Max 2021\maxPbrMaterial_specGloss.fbx" + P: "LastSaved", "Compound", "", "" + P: "LastSaved|ApplicationVendor", "KString", "", "", "Autodesk" + P: "LastSaved|ApplicationName", "KString", "", "", "3ds Max" + P: "LastSaved|ApplicationVersion", "KString", "", "", "2021" + P: "LastSaved|DateTime_GMT", "DateTime", "", "", "01/12/2020 11:50:44.088" + P: "Original|ApplicationActiveProject", "KString", "", "", "C:\3ds Max 2021" + P: "Original|ApplicationNativeFile", "KString", "", "", "C:\3ds Max 2021\MaxPbrMaterial2.max" + } + } +} +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", "",2 + P: "OriginalUpAxisSign", "int", "Integer", "",1 + P: "UnitScaleFactor", "double", "Number", "",100 + P: "OriginalUnitScaleFactor", "double", "Number", "",100.00000066 + P: "AmbientColor", "ColorRGB", "Color", "",0,0,0 + P: "DefaultCamera", "KString", "", "", "Producer Perspective" + P: "TimeMode", "enum", "", "",6 + P: "TimeProtocol", "enum", "", "",2 + P: "SnapOnFrameMode", "enum", "", "",0 + P: "TimeSpanStart", "KTime", "Time", "",0 + P: "TimeSpanStop", "KTime", "Time", "",153953860000 + P: "CustomFrameRate", "double", "Number", "",-1 + P: "TimeMarker", "Compound", "", "" + P: "CurrentTimeMarker", "int", "Integer", "",-1 + } +} + +; Documents Description +;------------------------------------------------------------------ + +Documents: { + Count: 1 + Document: 2188636931248, "", "Scene" { + Properties70: { + P: "SourceObject", "object", "", "" + P: "ActiveAnimStackName", "KString", "", "", "" + } + RootNode: 0 + } +} + +; Document References +;------------------------------------------------------------------ + +References: { +} + +; Object definitions +;------------------------------------------------------------------ + +Definitions: { + Version: 100 + Count: 18 + ObjectType: "GlobalSettings" { + Count: 1 + } + 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: "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: "FbxSurfaceMaterial" { + Properties70: { + P: "ShadingModel", "KString", "", "", "Unknown" + P: "MultiLayer", "bool", "", "",0 + } + } + } + ObjectType: "Texture" { + Count: 7 + 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: "Video" { + Count: 7 + 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: 2188631051296, "Geometry::", "Mesh" { + Properties70: { + P: "Color", "ColorRGB", "Color", "",0.341176470588235,0.882352941176471,0.776470588235294 + } + Vertices: *24 { + a: -8.91135215759277,-10.98219871521,0,8.91135215759277,-10.98219871521,0,-8.91135215759277,10.98219871521,0,8.91135215759277,10.98219871521,0,-8.91135215759277,-10.98219871521,16.787576675415,8.91135215759277,-10.98219871521,16.787576675415,-8.91135215759277,10.98219871521,16.787576675415,8.91135215759277,10.98219871521,16.787576675415 + } + PolygonVertexIndex: *24 { + a: 0,2,3,-2,4,5,7,-7,0,1,5,-5,1,3,7,-6,3,2,6,-8,2,0,4,-7 + } + Edges: *12 { + a: 0,1,2,3,4,5,6,7,9,11,13,17 + } + 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,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,0,1,0,0,1,0,0,1,0,0,1,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0 + } + NormalsW: *24 { + a: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + } + } + LayerElementUV: 0 { + Version: 101 + Name: "UVChannel_1" + MappingInformationType: "ByPolygonVertex" + ReferenceInformationType: "IndexToDirect" + UV: *48 { + a: 1,0,0,0,1,1,0,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,1,1 + } + UVIndex: *24 { + a: 0,2,3,1,4,5,7,6,8,9,11,10,12,13,15,14,16,17,19,18,20,21,23,22 + } + } + 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: 2188763600256, "Model::Box001", "Mesh" { + Version: 232 + Properties70: { + P: "PreRotation", "Vector3D", "Vector", "",-90,-0,0 + P: "RotationActive", "bool", "", "",1 + P: "InheritType", "enum", "", "",1 + P: "ScalingMax", "Vector3D", "Vector", "",0,0,0 + P: "DefaultAttributeIndex", "int", "Integer", "",0 + P: "Lcl Translation", "Lcl Translation", "", "A",0.570660591125488,0,-0.671265125274658 + P: "MaxHandle", "int", "Integer", "UH",2 + } + Shading: T + Culling: "CullingOff" + } + Material: 2188661245104, "Material::02 - Default", "" { + Version: 102 + ShadingModel: "unknown" + MultiLayer: 0 + Properties70: { + P: "ShadingModel", "KString", "", "", "unknown" + P: "AmbientColor", "ColorRGB", "Color", "",0,1,1 + P: "DiffuseColor", "ColorRGB", "Color", "",0,1,1 + P: "SpecularColor", "ColorRGB", "Color", "",1,1,1 + P: "SpecularFactor", "double", "Number", "",2 + P: "ShininessExponent", "double", "Number", "",1024 + P: "TransparencyFactor", "double", "Number", "",0 + P: "EmissiveColor", "ColorRGB", "Color", "",3.14159274101257,0,3.14159321784973 + P: "EmissiveFactor", "double", "Number", "",1 + P: "3dsMax", "Compound", "", "" + P: "3dsMax|ClassIDa", "int", "Integer", "",-804315648 + P: "3dsMax|ClassIDb", "int", "Integer", "",31173939 + P: "3dsMax|SuperClassID", "int", "Integer", "",3072 + P: "3dsMax|settings", "Compound", "", "" + P: "3dsMax|settings|ao_affects_diffuse", "Bool", "", "A",1 + P: "3dsMax|settings|ao_affects_reflection", "Bool", "", "A",1 + P: "3dsMax|settings|normal_flip_red", "Bool", "", "A",0 + P: "3dsMax|settings|normal_flip_green", "Bool", "", "A",0 + P: "3dsMax|main", "Compound", "", "" + P: "3dsMax|main|basecolor", "ColorAndAlpha", "", "A",0,1,1,1 + P: "3dsMax|main|base_color_map", "Reference", "", "A" + P: "3dsMax|main|Specular", "ColorAndAlpha", "", "A",1,1,0,1 + P: "3dsMax|main|specular_map", "Reference", "", "A" + P: "3dsMax|main|glossiness", "Float", "", "A",0.33 + P: "3dsMax|main|glossiness_map", "Reference", "", "A" + P: "3dsMax|main|useGlossiness", "Integer", "", "A",1 + P: "3dsMax|main|ao_map", "Reference", "", "A" + P: "3dsMax|main|bump_map_amt", "Float", "", "A",0.66 + P: "3dsMax|main|norm_map", "Reference", "", "A" + P: "3dsMax|main|emit_color", "ColorAndAlpha", "", "A",1,0,1,1 + P: "3dsMax|main|emit_color_map", "Reference", "", "A" + P: "3dsMax|main|opacity_map", "Reference", "", "A" + } + } + Video: 2188262470272, "Video::Albedo", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\albedo.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\albedo.png" + } + UseMipMap: 0 + Filename: "Textures\albedo.png" + RelativeFilename: "Textures\albedo.png" + } + Video: 2188262470752, "Video::Specular", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\specular.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\specular.png" + } + UseMipMap: 0 + Filename: "Textures\specular.png" + RelativeFilename: "Textures\specular.png" + } + Video: 2188262476032, "Video::Glossiness", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\glossiness.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\glossiness.png" + } + UseMipMap: 0 + Filename: "Textures\glossiness.png" + RelativeFilename: "Textures\glossiness.png" + } + Video: 2188262483232, "Video::Occlusion", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\occlusion.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\occlusion.png" + } + UseMipMap: 0 + Filename: "Textures\occlusion.png" + RelativeFilename: "Textures\occlusion.png" + } + Video: 2188262486112, "Video::Normal", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\normal.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\normal.png" + } + UseMipMap: 0 + Filename: "Textures\normal.png" + RelativeFilename: "Textures\normal.png" + } + Video: 2188262486592, "Video::Emission", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\emission.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\emission.png" + } + UseMipMap: 0 + Filename: "Textures\emission.png" + RelativeFilename: "Textures\emission.png" + } + Video: 2188262687712, "Video::Opacity", "Clip" { + Type: "Clip" + Properties70: { + P: "Path", "KString", "XRefUrl", "", "Textures\opacity.png" + P: "RelPath", "KString", "XRefUrl", "", "Textures\opacity.png" + } + UseMipMap: 0 + Filename: "Textures\opacity.png" + RelativeFilename: "Textures\opacity.png" + } + Texture: 2188262484672, "Texture::Albedo", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Albedo" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Albedo" + FileName: "Textures\albedo.png" + RelativeFilename: "Textures\albedo.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2188262499552, "Texture::Specular", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Specular" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Specular" + FileName: "Textures\specular.png" + RelativeFilename: "Textures\specular.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2188262475552, "Texture::Glossiness", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Glossiness" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Glossiness" + FileName: "Textures\glossiness.png" + RelativeFilename: "Textures\glossiness.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2188262480352, "Texture::Occlusion", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Occlusion" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Occlusion" + FileName: "Textures\occlusion.png" + RelativeFilename: "Textures\occlusion.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2188262482752, "Texture::Normal", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Normal" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Normal" + FileName: "Textures\normal.png" + RelativeFilename: "Textures\normal.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2188262481312, "Texture::Emission", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Emission" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Emission" + FileName: "Textures\emission.png" + RelativeFilename: "Textures\emission.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } + Texture: 2188262469792, "Texture::Opacity", "" { + Type: "TextureVideoClip" + Version: 202 + TextureName: "Texture::Opacity" + Properties70: { + P: "UVSet", "KString", "", "", "UVChannel_1" + P: "UseMaterial", "bool", "", "",1 + } + Media: "Video::Opacity" + FileName: "Textures\opacity.png" + RelativeFilename: "Textures\opacity.png" + ModelUVTranslation: 0,0 + ModelUVScaling: 1,1 + Texture_Alpha_Source: "None" + Cropping: 0,0,0,0 + } +} + +; Object connections +;------------------------------------------------------------------ + +Connections: { + + ;Model::Box001, Model::RootNode + C: "OO",2188763600256,0 + + ;Geometry::, Model::Box001 + C: "OO",2188631051296,2188763600256 + + ;Material::02 - Default, Model::Box001 + C: "OO",2188661245104,2188763600256 + + ;Texture::Albedo, Material::02 - Default + C: "OP",2188262484672,2188661245104, "3dsMax|main|base_color_map" + + ;Texture::Specular, Material::02 - Default + C: "OP",2188262499552,2188661245104, "3dsMax|main|specular_map" + + ;Texture::Glossiness, Material::02 - Default + C: "OP",2188262475552,2188661245104, "3dsMax|main|glossiness_map" + + ;Texture::Occlusion, Material::02 - Default + C: "OP",2188262480352,2188661245104, "3dsMax|main|ao_map" + + ;Texture::Normal, Material::02 - Default + C: "OP",2188262482752,2188661245104, "3dsMax|main|norm_map" + + ;Texture::Emission, Material::02 - Default + C: "OP",2188262481312,2188661245104, "3dsMax|main|emit_color_map" + + ;Texture::Opacity, Material::02 - Default + C: "OP",2188262469792,2188661245104, "3dsMax|main|opacity_map" + + ;Video::Albedo, Texture::Albedo + C: "OO",2188262470272,2188262484672 + + ;Video::Specular, Texture::Specular + C: "OO",2188262470752,2188262499552 + + ;Video::Glossiness, Texture::Glossiness + C: "OO",2188262476032,2188262475552 + + ;Video::Occlusion, Texture::Occlusion + C: "OO",2188262483232,2188262480352 + + ;Video::Normal, Texture::Normal + C: "OO",2188262486112,2188262482752 + + ;Video::Emission, Texture::Emission + C: "OO",2188262486592,2188262481312 + + ;Video::Opacity, Texture::Opacity + C: "OO",2188262687712,2188262469792 +} diff --git a/test/unit/utFBXImporterExporter.cpp b/test/unit/utFBXImporterExporter.cpp index 2f1ea79e8..88fda49cd 100644 --- a/test/unit/utFBXImporterExporter.cpp +++ b/test/unit/utFBXImporterExporter.cpp @@ -317,3 +317,109 @@ TEST_F(utFBXImporterExporter, importCubesWithOutOfRangeFloat) { ASSERT_NE(nullptr, scene); ASSERT_TRUE(scene->mRootNode); } + +TEST_F(utFBXImporterExporter, importMaxPbrMaterialsMetalRoughness) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/maxPbrMaterial_metalRough.fbx", aiProcess_ValidateDataStructure); + ASSERT_NE(nullptr, scene); + ASSERT_TRUE(scene->mRootNode); + + ASSERT_EQ(scene->mNumMaterials, 1); + const aiMaterial* mat = scene->mMaterials[0]; + aiString texture; + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_BASE_COLOR, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\albedo.png")); + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_METALNESS, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\metalness.png")); + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_EMISSION_COLOR, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\emission.png")); + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_NORMAL_CAMERA, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\normal.png")); + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE_ROUGHNESS, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\roughness.png")); + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_AMBIENT_OCCLUSION, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\occlusion.png")); + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_OPACITY, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\opacity.png")); + + // The material contains values for standard properties (e.g. SpecularColor), where 3ds Max has presumably + // used formulas to map the Pbr values into the standard material model. However, the pbr values themselves + // are available in the material as untyped "raw" properties. We check that these are correctly parsed: + + aiColor4D baseColor; + ASSERT_EQ(mat->Get("$raw.3dsMax|main|basecolor", aiTextureType_NONE, 0, baseColor), aiReturn_SUCCESS); + EXPECT_EQ(baseColor, aiColor4D(0, 1, 1, 1)); + + float metalness; + ASSERT_EQ(mat->Get("$raw.3dsMax|main|metalness", aiTextureType_NONE, 0, metalness), aiReturn_SUCCESS); + EXPECT_EQ(metalness, 0.25f); + + float roughness; + ASSERT_EQ(mat->Get("$raw.3dsMax|main|roughness", aiTextureType_NONE, 0, roughness), aiReturn_SUCCESS); + EXPECT_EQ(roughness, 0.5f); + + int useGlossiness; + ASSERT_EQ(mat->Get("$raw.3dsMax|main|useGlossiness", aiTextureType_NONE, 0, useGlossiness), aiReturn_SUCCESS); + EXPECT_EQ(useGlossiness, 2); // AFAICT 1 = Roughness map is glossiness, 2 = Roughness map is roughness. + + float bumpMapAmt; // Presumably amount. + ASSERT_EQ(mat->Get("$raw.3dsMax|main|bump_map_amt", aiTextureType_NONE, 0, bumpMapAmt), aiReturn_SUCCESS); + EXPECT_EQ(bumpMapAmt, 0.75f); + + aiColor4D emitColor; + ASSERT_EQ(mat->Get("$raw.3dsMax|main|emit_color", aiTextureType_NONE, 0, emitColor), aiReturn_SUCCESS); + EXPECT_EQ(emitColor, aiColor4D(1, 1, 0, 1)); +} + +TEST_F(utFBXImporterExporter, importMaxPbrMaterialsSpecularGloss) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/maxPbrMaterial_specGloss.fbx", aiProcess_ValidateDataStructure); + ASSERT_NE(nullptr, scene); + ASSERT_TRUE(scene->mRootNode); + + ASSERT_EQ(scene->mNumMaterials, 1); + const aiMaterial* mat = scene->mMaterials[0]; + aiString texture; + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_BASE_COLOR, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\albedo.png")); + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_SPECULAR, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\specular.png")); + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_EMISSION_COLOR, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\emission.png")); + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_NORMAL_CAMERA, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\normal.png")); + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_SHININESS, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\glossiness.png")); + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_AMBIENT_OCCLUSION, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\occlusion.png")); + ASSERT_EQ(mat->Get(AI_MATKEY_TEXTURE(aiTextureType_OPACITY, 0), texture), AI_SUCCESS); + EXPECT_EQ(texture, aiString("Textures\\opacity.png")); + + // The material contains values for standard properties (e.g. SpecularColor), where 3ds Max has presumably + // used formulas to map the Pbr values into the standard material model. However, the pbr values themselves + // are available in the material as untyped "raw" properties. We check that these are correctly parsed: + + aiColor4D baseColor; + ASSERT_EQ(mat->Get("$raw.3dsMax|main|basecolor", aiTextureType_NONE, 0, baseColor), aiReturn_SUCCESS); + EXPECT_EQ(baseColor, aiColor4D(0, 1, 1, 1)); + + aiColor4D specular; + ASSERT_EQ(mat->Get("$raw.3dsMax|main|Specular", aiTextureType_NONE, 0, specular), aiReturn_SUCCESS); + EXPECT_EQ(specular, aiColor4D(1, 1, 0, 1)); + + float glossiness; + ASSERT_EQ(mat->Get("$raw.3dsMax|main|glossiness", aiTextureType_NONE, 0, glossiness), aiReturn_SUCCESS); + EXPECT_EQ(glossiness, 0.33f); + + int useGlossiness; + ASSERT_EQ(mat->Get("$raw.3dsMax|main|useGlossiness", aiTextureType_NONE, 0, useGlossiness), aiReturn_SUCCESS); + EXPECT_EQ(useGlossiness, 1); // AFAICT 1 = Glossiness map is glossiness, 2 = Glossiness map is roughness. + + float bumpMapAmt; // Presumably amount. + ASSERT_EQ(mat->Get("$raw.3dsMax|main|bump_map_amt", aiTextureType_NONE, 0, bumpMapAmt), aiReturn_SUCCESS); + EXPECT_EQ(bumpMapAmt, 0.66f); + + aiColor4D emitColor; + ASSERT_EQ(mat->Get("$raw.3dsMax|main|emit_color", aiTextureType_NONE, 0, emitColor), aiReturn_SUCCESS); + EXPECT_EQ(emitColor, aiColor4D(1, 0, 1, 1)); +} From 19af3f0d31088caf0157c804c81fe289e1a1bf1c Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Wed, 2 Dec 2020 16:59:29 +0000 Subject: [PATCH 2/9] Swap the meaning using the out_mat property. --- code/AssetLib/FBX/FBXConverter.cpp | 23 +++++++++++++++++++---- test/unit/utFBXImporterExporter.cpp | 4 ++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index e6b1a75c0..7070042f8 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -2024,12 +2024,27 @@ void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const TextureMap &_ TrySetTextureProperties(out_mat, _textures, "3dsMax|main|emit_color_map", aiTextureType_EMISSION_COLOR, mesh); TrySetTextureProperties(out_mat, _textures, "3dsMax|main|ao_map", aiTextureType_AMBIENT_OCCLUSION, mesh); TrySetTextureProperties(out_mat, _textures, "3dsMax|main|opacity_map", aiTextureType_OPACITY, mesh); - // Metalness/Roughness mode + // Metalness/Roughness material type TrySetTextureProperties(out_mat, _textures, "3dsMax|main|metalness_map", aiTextureType_METALNESS, mesh); - TrySetTextureProperties(out_mat, _textures, "3dsMax|main|roughness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh); - // Specular/Gloss mode + // Specular/Gloss material type TrySetTextureProperties(out_mat, _textures, "3dsMax|main|specular_map", aiTextureType_SPECULAR, mesh); - TrySetTextureProperties(out_mat, _textures, "3dsMax|main|glossiness_map", aiTextureType_SHININESS, mesh); + + // Glossiness vs roughness in 3ds Max Pbr Materials + int useGlossiness; + if (out_mat->Get("$raw.3dsMax|main|useGlossiness", aiTextureType_NONE, 0, useGlossiness) == aiReturn_SUCCESS) + { + // These textures swap meaning if ((useGlossiness == 1) != (material type is Specular/Gloss)) + if (useGlossiness == 1) + { + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|roughness_map", aiTextureType_SHININESS, mesh); + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|glossiness_map", aiTextureType_SHININESS, mesh); + } + else // useGlossiness == 2 + { + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|roughness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh); + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|glossiness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh); + } + } } void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const LayeredTextureMap &layeredTextures, const MeshGeometry *const mesh) { diff --git a/test/unit/utFBXImporterExporter.cpp b/test/unit/utFBXImporterExporter.cpp index 88fda49cd..332bfc1ec 100644 --- a/test/unit/utFBXImporterExporter.cpp +++ b/test/unit/utFBXImporterExporter.cpp @@ -360,7 +360,7 @@ TEST_F(utFBXImporterExporter, importMaxPbrMaterialsMetalRoughness) { int useGlossiness; ASSERT_EQ(mat->Get("$raw.3dsMax|main|useGlossiness", aiTextureType_NONE, 0, useGlossiness), aiReturn_SUCCESS); - EXPECT_EQ(useGlossiness, 2); // AFAICT 1 = Roughness map is glossiness, 2 = Roughness map is roughness. + EXPECT_EQ(useGlossiness, 2); // 1 = Roughness map is glossiness, 2 = Roughness map is roughness. float bumpMapAmt; // Presumably amount. ASSERT_EQ(mat->Get("$raw.3dsMax|main|bump_map_amt", aiTextureType_NONE, 0, bumpMapAmt), aiReturn_SUCCESS); @@ -413,7 +413,7 @@ TEST_F(utFBXImporterExporter, importMaxPbrMaterialsSpecularGloss) { int useGlossiness; ASSERT_EQ(mat->Get("$raw.3dsMax|main|useGlossiness", aiTextureType_NONE, 0, useGlossiness), aiReturn_SUCCESS); - EXPECT_EQ(useGlossiness, 1); // AFAICT 1 = Glossiness map is glossiness, 2 = Glossiness map is roughness. + EXPECT_EQ(useGlossiness, 1); // 1 = Glossiness map is glossiness, 2 = Glossiness map is roughness. float bumpMapAmt; // Presumably amount. ASSERT_EQ(mat->Get("$raw.3dsMax|main|bump_map_amt", aiTextureType_NONE, 0, bumpMapAmt), aiReturn_SUCCESS); From 471d2acc92651df88a51ea00ea8b8566608f676e Mon Sep 17 00:00:00 2001 From: Malcolm Tyrrell Date: Thu, 3 Dec 2020 11:17:45 +0000 Subject: [PATCH 3/9] Improvements & style --- code/AssetLib/FBX/FBXConverter.cpp | 12 +++++------ code/AssetLib/FBX/FBXProperties.cpp | 33 ++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index 7070042f8..ba7089f29 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -2031,19 +2031,19 @@ void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const TextureMap &_ // Glossiness vs roughness in 3ds Max Pbr Materials int useGlossiness; - if (out_mat->Get("$raw.3dsMax|main|useGlossiness", aiTextureType_NONE, 0, useGlossiness) == aiReturn_SUCCESS) - { + if (out_mat->Get("$raw.3dsMax|main|useGlossiness", aiTextureType_NONE, 0, useGlossiness) == aiReturn_SUCCESS) { // These textures swap meaning if ((useGlossiness == 1) != (material type is Specular/Gloss)) - if (useGlossiness == 1) - { + if (useGlossiness == 1) { TrySetTextureProperties(out_mat, _textures, "3dsMax|main|roughness_map", aiTextureType_SHININESS, mesh); TrySetTextureProperties(out_mat, _textures, "3dsMax|main|glossiness_map", aiTextureType_SHININESS, mesh); } - else // useGlossiness == 2 - { + else if (useGlossiness == 2) { TrySetTextureProperties(out_mat, _textures, "3dsMax|main|roughness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh); TrySetTextureProperties(out_mat, _textures, "3dsMax|main|glossiness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh); } + else { + FBXImporter::LogWarn("A 3dsMax Pbr Material must have a useGlossiness value to correctly interpret roughness and glossiness textures."); + } } } diff --git a/code/AssetLib/FBX/FBXProperties.cpp b/code/AssetLib/FBX/FBXProperties.cpp index ccccd3012..84098cf10 100644 --- a/code/AssetLib/FBX/FBXProperties.cpp +++ b/code/AssetLib/FBX/FBXProperties.cpp @@ -69,6 +69,20 @@ Property::~Property() namespace { +void checkTokenCount(const TokenList& tok, unsigned int expectedCount) +{ + ai_assert(expectedCount >= 2); + if (tok.size() < expectedCount) { + const std::string& s = ParseTokenAsString(*tok[1]); + if (tok[1]->IsBinary()) { + throw DeadlyImportError("Not enough tokens for property of type ", s, " at offset ", tok[1]->Offset()); + } + else { + throw DeadlyImportError("Not enough tokens for property of type ", s, " at line ", tok[1]->Line()); + } + } +} + // ------------------------------------------------------------------------------------------------ // read a typed property out of a FBX element. The return value is nullptr if the property cannot be read. Property* ReadTypedProperty(const Element& element) @@ -83,23 +97,23 @@ Property* ReadTypedProperty(const Element& element) const std::string& s = ParseTokenAsString(*tok[1]); const char* const cs = s.c_str(); if (!strcmp(cs,"KString")) { - ai_assert(tok.size() >= 5); + checkTokenCount(tok, 5); return new TypedProperty(ParseTokenAsString(*tok[4])); } else if (!strcmp(cs,"bool") || !strcmp(cs,"Bool")) { - ai_assert(tok.size() >= 5); + checkTokenCount(tok, 5); return new TypedProperty(ParseTokenAsInt(*tok[4]) != 0); } else if (!strcmp(cs, "int") || !strcmp(cs, "Int") || !strcmp(cs, "enum") || !strcmp(cs, "Enum") || !strcmp(cs, "Integer")) { - ai_assert(tok.size() >= 5); + checkTokenCount(tok, 5); return new TypedProperty(ParseTokenAsInt(*tok[4])); } else if (!strcmp(cs, "ULongLong")) { - ai_assert(tok.size() >= 5); + checkTokenCount(tok, 5); return new TypedProperty(ParseTokenAsID(*tok[4])); } else if (!strcmp(cs, "KTime")) { - ai_assert(tok.size() >= 5); + checkTokenCount(tok, 5); return new TypedProperty(ParseTokenAsInt64(*tok[4])); } else if (!strcmp(cs,"Vector3D") || @@ -110,7 +124,7 @@ Property* ReadTypedProperty(const Element& element) !strcmp(cs,"Lcl Rotation") || !strcmp(cs,"Lcl Scaling") ) { - ai_assert(tok.size() >= 7); + checkTokenCount(tok, 7); return new TypedProperty(aiVector3D( ParseTokenAsFloat(*tok[4]), ParseTokenAsFloat(*tok[5]), @@ -118,12 +132,11 @@ Property* ReadTypedProperty(const Element& element) ); } else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) { - ai_assert(tok.size() >= 5); + checkTokenCount(tok, 5); return new TypedProperty(ParseTokenAsFloat(*tok[4])); } - else if (!strcmp(cs, "ColorAndAlpha")) - { - ai_assert(tok.size() >= 8); + else if (!strcmp(cs, "ColorAndAlpha")) { + checkTokenCount(tok, 8); return new TypedProperty(aiColor4D( ParseTokenAsFloat(*tok[4]), ParseTokenAsFloat(*tok[5]), From 8701a86c9d474bc07c2eceec72074bda98a3b128 Mon Sep 17 00:00:00 2001 From: Jean-Louis Boudrand Date: Thu, 10 Dec 2020 23:47:54 +0100 Subject: [PATCH 4/9] Fixed a crash of the Gltf 2 exporter in the case of an animation without a translation, rotation or scale animation key. --- code/AssetLib/glTF2/glTF2Exporter.cpp | 36 +++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 637808877..5852dfc01 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -1258,9 +1258,6 @@ inline Ref GetSamplerInputRef(Asset& asset, std::string& animId, Ref& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) { const unsigned int numKeyframes = nodeChannel->mNumPositionKeys; - if (numKeyframes == 0) { - return; - } std::vector times(numKeyframes); std::vector values(numKeyframes * 3); @@ -1281,9 +1278,6 @@ inline void ExtractTranslationSampler(Asset& asset, std::string& animId, Ref& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) { const unsigned int numKeyframes = nodeChannel->mNumScalingKeys; - if (numKeyframes == 0) { - return; - } std::vector times(numKeyframes); std::vector values(numKeyframes * 3); @@ -1304,9 +1298,6 @@ inline void ExtractScaleSampler(Asset& asset, std::string& animId, Ref& inline void ExtractRotationSampler(Asset& asset, std::string& animId, Ref& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond, Animation::Sampler& sampler) { const unsigned int numKeyframes = nodeChannel->mNumRotationKeys; - if (numKeyframes == 0) { - return; - } std::vector times(numKeyframes); std::vector values(numKeyframes * 4); @@ -1359,17 +1350,26 @@ void glTF2Exporter::ExportAnimations() Ref animNode = mAsset->nodes.Get(nodeChannel->mNodeName.C_Str()); - Animation::Sampler translationSampler; - ExtractTranslationSampler(*mAsset, name, bufferRef, nodeChannel, ticksPerSecond, translationSampler); - AddSampler(animRef, animNode, translationSampler, AnimationPath_TRANSLATION); + if (nodeChannel->mNumPositionKeys > 0) + { + Animation::Sampler translationSampler; + ExtractTranslationSampler(*mAsset, name, bufferRef, nodeChannel, ticksPerSecond, translationSampler); + AddSampler(animRef, animNode, translationSampler, AnimationPath_TRANSLATION); + } - Animation::Sampler rotationSampler; - ExtractRotationSampler(*mAsset, name, bufferRef, nodeChannel, ticksPerSecond, rotationSampler); - AddSampler(animRef, animNode, rotationSampler, AnimationPath_ROTATION); + if (nodeChannel->mNumRotationKeys > 0) + { + Animation::Sampler rotationSampler; + ExtractRotationSampler(*mAsset, name, bufferRef, nodeChannel, ticksPerSecond, rotationSampler); + AddSampler(animRef, animNode, rotationSampler, AnimationPath_ROTATION); + } - Animation::Sampler scaleSampler; - ExtractScaleSampler(*mAsset, name, bufferRef, nodeChannel, ticksPerSecond, scaleSampler); - AddSampler(animRef, animNode, scaleSampler, AnimationPath_SCALE); + if (nodeChannel->mNumScalingKeys > 0) + { + Animation::Sampler scaleSampler; + ExtractScaleSampler(*mAsset, name, bufferRef, nodeChannel, ticksPerSecond, scaleSampler); + AddSampler(animRef, animNode, scaleSampler, AnimationPath_SCALE); + } } // Assimp documentation staes this is not used (not implemented) From e2af015a57a276e4bca23f03cc26e947a582e9d0 Mon Sep 17 00:00:00 2001 From: Biswapriyo Nath Date: Fri, 11 Dec 2020 21:43:09 +0530 Subject: [PATCH 5/9] Common: Fix GCC error invalid conversion in MINGW. --- code/CMakeLists.txt | 2 +- code/Common/ZipArchiveIOSystem.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index bb83a5f97..7a017cfa4 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1015,7 +1015,7 @@ ENDIF() # RT-extensions is used in "contrib/Open3DGC/o3dgcTimer.h" for collecting statistics. Pointed file # has implementation for different platforms: WIN32, __MACH__ and other ("else" block). FIND_PACKAGE(RT QUIET) -IF (NOT ASSIMP_HUNTER_ENABLED AND (RT_FOUND OR MSVC)) +IF (NOT ASSIMP_HUNTER_ENABLED AND (RT_FOUND OR WIN32)) SET( ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC 1 ) ADD_DEFINITIONS( -DASSIMP_IMPORTER_GLTF_USE_OPEN3DGC=1 ) ELSE () diff --git a/code/Common/ZipArchiveIOSystem.cpp b/code/Common/ZipArchiveIOSystem.cpp index f55f9ff53..6cd50739e 100644 --- a/code/Common/ZipArchiveIOSystem.cpp +++ b/code/Common/ZipArchiveIOSystem.cpp @@ -146,7 +146,7 @@ int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) { zlib_filefunc_def IOSystem2Unzip::get(IOSystem *pIOHandler) { zlib_filefunc_def mapping; -#ifdef ASSIMP_USE_HUNTER +#if defined (ASSIMP_USE_HUNTER) || defined (__MINGW32__) // GH#3144 mapping.zopen_file = (open_file_func)open; mapping.zread_file = (read_file_func)read; mapping.zwrite_file = (write_file_func)write; @@ -335,7 +335,7 @@ ZipArchiveIOSystem::Implement::Implement(IOSystem *pIOHandler, const char *pFile if (pFilename[0] == 0 || nullptr == pMode) { return; } - + zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler); m_ZipFileHandle = unzOpen2(pFilename, &mapping); } From c65f2cb3fbd7dd66474ea8821fba0080f144f33d Mon Sep 17 00:00:00 2001 From: Biswapriyo Nath Date: Sat, 12 Dec 2020 11:15:04 +0530 Subject: [PATCH 6/9] Remove extra semicolon while GCC being pedantic. --- code/AssetLib/Collada/ColladaHelper.cpp | 4 ++-- contrib/Open3DGC/o3dgcVector.inl | 4 ++-- .../SimpleTexturedOpenGL/src/model_loading.cpp | 2 +- tools/assimp_view/MeshRenderer.cpp | 2 +- tools/assimp_view/MessageProc.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/AssetLib/Collada/ColladaHelper.cpp b/code/AssetLib/Collada/ColladaHelper.cpp index 0a779e04e..1a4bed3b1 100644 --- a/code/AssetLib/Collada/ColladaHelper.cpp +++ b/code/AssetLib/Collada/ColladaHelper.cpp @@ -53,7 +53,7 @@ const MetaKeyPairVector MakeColladaAssimpMetaKeys() { result.emplace_back("authoring_tool", AI_METADATA_SOURCE_GENERATOR); result.emplace_back("copyright", AI_METADATA_SOURCE_COPYRIGHT); return result; -}; +} const MetaKeyPairVector &GetColladaAssimpMetaKeys() { static const MetaKeyPairVector result = MakeColladaAssimpMetaKeys(); @@ -66,7 +66,7 @@ const MetaKeyPairVector MakeColladaAssimpMetaKeysCamelCase() { ToCamelCase(val.first); } return result; -}; +} const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase() { static const MetaKeyPairVector result = MakeColladaAssimpMetaKeysCamelCase(); diff --git a/contrib/Open3DGC/o3dgcVector.inl b/contrib/Open3DGC/o3dgcVector.inl index 5549b00ce..de8dfd5f1 100644 --- a/contrib/Open3DGC/o3dgcVector.inl +++ b/contrib/Open3DGC/o3dgcVector.inl @@ -175,7 +175,7 @@ namespace o3dgc m_data[2] = rhs.m_data[2]; } template - inline Vec3::~Vec3(void){}; + inline Vec3::~Vec3(void){} template inline Vec3::Vec3() {} @@ -308,7 +308,7 @@ namespace o3dgc m_data[1] = rhs.m_data[1]; } template - inline Vec2::~Vec2(void){}; + inline Vec2::~Vec2(void){} template inline Vec2::Vec2() {} diff --git a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp index a36c792d4..aa2344118 100644 --- a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp +++ b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp @@ -763,7 +763,7 @@ void cleanup() if (g_hWnd) KillGLWindow(); -}; +} LRESULT CALLBACK WndProc(HWND hWnd, // Handles for this Window UINT uMsg, // Message for this Window diff --git a/tools/assimp_view/MeshRenderer.cpp b/tools/assimp_view/MeshRenderer.cpp index d93bb4aea..972b3db24 100644 --- a/tools/assimp_view/MeshRenderer.cpp +++ b/tools/assimp_view/MeshRenderer.cpp @@ -161,4 +161,4 @@ int CMeshRenderer::DrawSorted(unsigned int iIndex,const aiMatrix4x4& mWorld) { return 1; } -}; +} diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 80589e647..cebb78e22 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -2143,7 +2143,7 @@ INT_PTR CALLBACK AboutMessageProc(HWND hwndDlg,UINT uMsg, } return FALSE; } -}; +} using namespace AssimpView; From d18fce3f0695173c25f855c823d0e23701257f73 Mon Sep 17 00:00:00 2001 From: Jean-Louis Boudrand Date: Sun, 13 Dec 2020 17:02:50 +0100 Subject: [PATCH 7/9] Fix https://github.com/assimp/assimp/issues/3054 Corrected the animation of each bone of an animation were exported in different animations (+tabs fixes) --- code/AssetLib/glTF2/glTF2Exporter.cpp | 28 +++++++++++++-------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 5852dfc01..6ebb54568 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -1338,38 +1338,36 @@ void glTF2Exporter::ExportAnimations() if (anim->mName.length > 0) { nameAnim = anim->mName.C_Str(); } + Ref animRef = mAsset->animations.Create(nameAnim); for (unsigned int channelIndex = 0; channelIndex < anim->mNumChannels; ++channelIndex) { const aiNodeAnim* nodeChannel = anim->mChannels[channelIndex]; - // It appears that assimp stores this type of animation as multiple animations. - // where each aiNodeAnim in mChannels animates a specific node. std::string name = nameAnim + "_" + to_string(channelIndex); name = mAsset->FindUniqueID(name, "animation"); - Ref animRef = mAsset->animations.Create(name); Ref animNode = mAsset->nodes.Get(nodeChannel->mNodeName.C_Str()); if (nodeChannel->mNumPositionKeys > 0) { - Animation::Sampler translationSampler; - ExtractTranslationSampler(*mAsset, name, bufferRef, nodeChannel, ticksPerSecond, translationSampler); - AddSampler(animRef, animNode, translationSampler, AnimationPath_TRANSLATION); - } + Animation::Sampler translationSampler; + ExtractTranslationSampler(*mAsset, name, bufferRef, nodeChannel, ticksPerSecond, translationSampler); + AddSampler(animRef, animNode, translationSampler, AnimationPath_TRANSLATION); + } if (nodeChannel->mNumRotationKeys > 0) { - Animation::Sampler rotationSampler; - ExtractRotationSampler(*mAsset, name, bufferRef, nodeChannel, ticksPerSecond, rotationSampler); - AddSampler(animRef, animNode, rotationSampler, AnimationPath_ROTATION); - } + Animation::Sampler rotationSampler; + ExtractRotationSampler(*mAsset, name, bufferRef, nodeChannel, ticksPerSecond, rotationSampler); + AddSampler(animRef, animNode, rotationSampler, AnimationPath_ROTATION); + } if (nodeChannel->mNumScalingKeys > 0) { - Animation::Sampler scaleSampler; - ExtractScaleSampler(*mAsset, name, bufferRef, nodeChannel, ticksPerSecond, scaleSampler); - AddSampler(animRef, animNode, scaleSampler, AnimationPath_SCALE); - } + Animation::Sampler scaleSampler; + ExtractScaleSampler(*mAsset, name, bufferRef, nodeChannel, ticksPerSecond, scaleSampler); + AddSampler(animRef, animNode, scaleSampler, AnimationPath_SCALE); + } } // Assimp documentation staes this is not used (not implemented) From b8bf1eac041f0bbb406019a28f310509dad51b86 Mon Sep 17 00:00:00 2001 From: Inho Lee Date: Mon, 7 Dec 2020 09:51:19 +0100 Subject: [PATCH 8/9] FBXConverter : Fix timescales of FBX animations FBX animations were recorded by framenumber, not by time. This patch will change it as a base of milliseconds. --- code/AssetLib/FBX/FBXConverter.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index 1a484a38a..c27e48076 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -79,7 +79,7 @@ using namespace Util; #define MAGIC_NODE_TAG "_$AssimpFbx$" -#define CONVERT_FBX_TIME(time) static_cast(time) / 46186158000LL +#define CONVERT_FBX_TIME(time) (static_cast(time) * 1000.0 / 46186158000LL) FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBones) : defaultMaterialIndex(), @@ -2560,7 +2560,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) { meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights; meshMorphAnim->mKeys[j].mValues = new unsigned int[numValuesAndWeights]; meshMorphAnim->mKeys[j].mWeights = new double[numValuesAndWeights]; - meshMorphAnim->mKeys[j].mTime = CONVERT_FBX_TIME(animIt.first) * anim_fps; + meshMorphAnim->mKeys[j].mTime = CONVERT_FBX_TIME(animIt.first); for (unsigned int k = 0; k < numValuesAndWeights; k++) { meshMorphAnim->mKeys[j].mValues[k] = keyData->values.at(k); meshMorphAnim->mKeys[j].mWeights[k] = keyData->weights.at(k); @@ -2578,8 +2578,8 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) { return; } - double start_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(start_time) * anim_fps) : min_time; - double stop_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(stop_time) * anim_fps) : max_time; + double start_time_fps = has_local_startstop ? CONVERT_FBX_TIME(start_time) : min_time; + double stop_time_fps = has_local_startstop ? CONVERT_FBX_TIME(stop_time) : max_time; // adjust relative timing for animation for (unsigned int c = 0; c < anim->mNumChannels; c++) { @@ -3099,7 +3099,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, InterpolateKeys(outTranslations, keytimes, keyframeLists[TransformationComp_Translation], defTranslate, maxTime, minTime); } else { for (size_t i = 0; i < keyCount; ++i) { - outTranslations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps; + outTranslations[i].mTime = CONVERT_FBX_TIME(keytimes[i]); outTranslations[i].mValue = defTranslate; } } @@ -3108,7 +3108,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder); } else { for (size_t i = 0; i < keyCount; ++i) { - outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps; + outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]); outRotations[i].mValue = defQuat; } } @@ -3117,7 +3117,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name, InterpolateKeys(outScales, keytimes, keyframeLists[TransformationComp_Scaling], defScale, maxTime, minTime); } else { for (size_t i = 0; i < keyCount; ++i) { - outScales[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps; + outScales[i].mTime = CONVERT_FBX_TIME(keytimes[i]); outScales[i].mValue = defScale; } } @@ -3306,7 +3306,7 @@ void FBXConverter::InterpolateKeys(aiVectorKey *valOut, const KeyTimeList &keys, } // magic value to convert fbx times to seconds - valOut->mTime = CONVERT_FBX_TIME(time) * anim_fps; + valOut->mTime = CONVERT_FBX_TIME(time); min_time = std::min(min_time, valOut->mTime); max_time = std::max(max_time, valOut->mTime); From 4e5b25cd81990003e2035d39e58e1df5629b403f Mon Sep 17 00:00:00 2001 From: Inho Lee Date: Wed, 16 Dec 2020 17:55:05 +0100 Subject: [PATCH 9/9] Keep AnimMesh data during the SortByPTypeProcess A Postprocessing step, SortByPTypeProcess, can rebuild Mesh data, but it does not handle AnimMesh. This patch helps to rebuild appropriate AnimMeshes for the Mesh. --- code/PostProcessing/SortByPTypeProcess.cpp | 64 ++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/code/PostProcessing/SortByPTypeProcess.cpp b/code/PostProcessing/SortByPTypeProcess.cpp index c4f9c7e4d..332d9d7ef 100644 --- a/code/PostProcessing/SortByPTypeProcess.cpp +++ b/code/PostProcessing/SortByPTypeProcess.cpp @@ -243,6 +243,45 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { } } + if (mesh->mNumAnimMeshes > 0 && mesh->mAnimMeshes) { + out->mNumAnimMeshes = mesh->mNumAnimMeshes; + out->mAnimMeshes = new aiAnimMesh *[out->mNumAnimMeshes]; + } + + for (unsigned int j = 0; j < mesh->mNumAnimMeshes; ++j) { + aiAnimMesh *animMesh = mesh->mAnimMeshes[j]; + aiAnimMesh *outAnimMesh = out->mAnimMeshes[j] = new aiAnimMesh; + outAnimMesh->mNumVertices = out->mNumVertices; + if (animMesh->mVertices) + outAnimMesh->mVertices = new aiVector3D[out->mNumVertices]; + else + outAnimMesh->mVertices = nullptr; + if (animMesh->mNormals) + outAnimMesh->mNormals = new aiVector3D[out->mNumVertices]; + else + outAnimMesh->mNormals = nullptr; + if (animMesh->mTangents) + outAnimMesh->mTangents = new aiVector3D[out->mNumVertices]; + else + outAnimMesh->mTangents = nullptr; + if (animMesh->mBitangents) + outAnimMesh->mBitangents = new aiVector3D[out->mNumVertices]; + else + outAnimMesh->mBitangents = nullptr; + for (int jj = 0; jj < AI_MAX_NUMBER_OF_COLOR_SETS; ++jj) { + if (animMesh->mColors[jj]) + outAnimMesh->mColors[jj] = new aiColor4D[out->mNumVertices]; + else + outAnimMesh->mColors[jj] = nullptr; + } + for (int jj = 0; jj < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++jj) { + if (animMesh->mTextureCoords[jj]) + outAnimMesh->mTextureCoords[jj] = new aiVector3D[out->mNumVertices]; + else + outAnimMesh->mTextureCoords[jj] = nullptr; + } + } + typedef std::vector TempBoneInfo; std::vector tempBones(mesh->mNumBones); @@ -252,6 +291,7 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { } unsigned int outIdx = 0; + unsigned int amIdx = 0; // AnimMesh index for (unsigned int m = 0; m < mesh->mNumFaces; ++m) { aiFace &in = mesh->mFaces[m]; if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real + 1)) { @@ -293,6 +333,30 @@ void SortByPTypeProcess::Execute(aiScene *pScene) { *cols[pp]++ = mesh->mColors[pp][idx]; } + unsigned int pp = 0; + for (; pp < mesh->mNumAnimMeshes; ++pp) { + aiAnimMesh *animMesh = mesh->mAnimMeshes[pp]; + aiAnimMesh *outAnimMesh = out->mAnimMeshes[pp]; + if (animMesh->mVertices) + outAnimMesh->mVertices[amIdx] = animMesh->mVertices[idx]; + if (animMesh->mNormals) + outAnimMesh->mNormals[amIdx] = animMesh->mNormals[idx]; + if (animMesh->mTangents) + outAnimMesh->mTangents[amIdx] = animMesh->mTangents[idx]; + if (animMesh->mBitangents) + outAnimMesh->mBitangents[amIdx] = animMesh->mBitangents[idx]; + for (int jj = 0; jj < AI_MAX_NUMBER_OF_COLOR_SETS; ++jj) { + if (animMesh->mColors[jj]) + outAnimMesh->mColors[jj][amIdx] = animMesh->mColors[jj][idx]; + } + for (int jj = 0; jj < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++jj) { + if (animMesh->mTextureCoords[jj]) + outAnimMesh->mTextureCoords[jj][amIdx] = animMesh->mTextureCoords[jj][idx]; + } + } + if (pp == mesh->mNumAnimMeshes) + amIdx++; + in.mIndices[q] = outIdx++; }