diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index e8fd7967b..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(), @@ -2014,12 +2014,40 @@ 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 material type + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|metalness_map", aiTextureType_METALNESS, mesh); + // Specular/Gloss material type + TrySetTextureProperties(out_mat, _textures, "3dsMax|main|specular_map", aiTextureType_SPECULAR, 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 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."); + } + } } void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const LayeredTextureMap &layeredTextures, const MeshGeometry *const mesh) { @@ -2532,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); @@ -2550,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++) { @@ -3071,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; } } @@ -3080,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; } } @@ -3089,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; } } @@ -3278,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); diff --git a/code/AssetLib/FBX/FBXProperties.cpp b/code/AssetLib/FBX/FBXProperties.cpp index a3a95228e..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")) { - ai_assert(tok.size() >= 5); + else if (!strcmp(cs, "int") || !strcmp(cs, "Int") || !strcmp(cs, "enum") || !strcmp(cs, "Enum") || !strcmp(cs, "Integer")) { + 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,9 +132,18 @@ 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")) { + checkTokenCount(tok, 8); + return new TypedProperty(aiColor4D( + ParseTokenAsFloat(*tok[4]), + ParseTokenAsFloat(*tok[5]), + ParseTokenAsFloat(*tok[6]), + ParseTokenAsFloat(*tok[7])) + ); + } return nullptr; } 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++; } 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..332bfc1ec 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); // 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); // 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)); +}