diff --git a/code/AssetLib/X/XFileImporter.cpp b/code/AssetLib/X/XFileImporter.cpp index 32865e8a8..1474ad808 100644 --- a/code/AssetLib/X/XFileImporter.cpp +++ b/code/AssetLib/X/XFileImporter.cpp @@ -578,7 +578,7 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vectormMaterials[b]->Get( AI_MATKEY_NAME, name); if( strcmp( name.C_Str(), oldMat.mName.data()) == 0 ) { - oldMat.sceneIndex = a; + oldMat.sceneIndex = b; break; } } diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 048937502..15a8fcc87 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * glTF Extensions Support: * KHR_materials_pbrSpecularGlossiness full + * KHR_materials_specular full * KHR_materials_unlit full * KHR_lights_punctual full * KHR_materials_sheen full @@ -710,6 +711,7 @@ const vec4 defaultBaseColor = { 1, 1, 1, 1 }; const vec3 defaultEmissiveFactor = { 0, 0, 0 }; const vec4 defaultDiffuseFactor = { 1, 1, 1, 1 }; const vec3 defaultSpecularFactor = { 1, 1, 1 }; +const vec3 defaultSpecularColorFactor = { 0, 0, 0 }; const vec3 defaultSheenFactor = { 0, 0, 0 }; const vec3 defaultAttenuationColor = { 1, 1, 1 }; @@ -753,6 +755,16 @@ struct PbrSpecularGlossiness { void SetDefaults(); }; +struct MaterialSpecular { + float specularFactor; + vec3 specularColorFactor; + TextureInfo specularTexture; + TextureInfo specularColorTexture; + + MaterialSpecular() { SetDefaults(); } + void SetDefaults(); +}; + struct MaterialSheen { vec3 sheenColorFactor; float sheenRoughnessFactor; @@ -817,6 +829,9 @@ struct Material : public Object { //extension: KHR_materials_pbrSpecularGlossiness Nullable pbrSpecularGlossiness; + //extension: KHR_materials_specular + Nullable materialSpecular; + //extension: KHR_materials_sheen Nullable materialSheen; @@ -1099,6 +1114,7 @@ public: //! Keeps info about the enabled extensions struct Extensions { bool KHR_materials_pbrSpecularGlossiness; + bool KHR_materials_specular; bool KHR_materials_unlit; bool KHR_lights_punctual; bool KHR_texture_transform; @@ -1113,13 +1129,14 @@ public: bool KHR_texture_basisu; Extensions() : - KHR_materials_pbrSpecularGlossiness(false), - KHR_materials_unlit(false), - KHR_lights_punctual(false), - KHR_texture_transform(false), - KHR_materials_sheen(false), - KHR_materials_clearcoat(false), - KHR_materials_transmission(false), + KHR_materials_pbrSpecularGlossiness(false), + KHR_materials_specular(false), + KHR_materials_unlit(false), + KHR_lights_punctual(false), + KHR_texture_transform(false), + KHR_materials_sheen(false), + KHR_materials_clearcoat(false), + KHR_materials_transmission(false), KHR_materials_volume(false), KHR_materials_ior(false), KHR_materials_emissive_strength(false), diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index b4ea77c79..bd6435766 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -1263,6 +1263,19 @@ inline void Material::Read(Value &material, Asset &r) { this->pbrSpecularGlossiness = Nullable(pbrSG); } } + + if (r.extensionsUsed.KHR_materials_specular) { + if (Value *curMatSpecular = FindObject(*extensions, "KHR_materials_specular")) { + MaterialSpecular specular; + + ReadMember(*curMatSpecular, "specularFactor", specular.specularFactor); + ReadTextureProperty(r, *curMatSpecular, "specularTexture", specular.specularTexture); + ReadMember(*curMatSpecular, "specularColorFactor", specular.specularColorFactor); + ReadTextureProperty(r, *curMatSpecular, "specularColorTexture", specular.specularColorTexture); + + this->materialSpecular = Nullable(specular); + } + } // Extension KHR_texture_transform is handled in ReadTextureProperty @@ -1361,6 +1374,12 @@ inline void PbrSpecularGlossiness::SetDefaults() { glossinessFactor = 1.0f; } +inline void MaterialSpecular::SetDefaults() { + //KHR_materials_specular properties + SetVector(specularColorFactor, defaultSpecularColorFactor); + specularFactor = 0.f; +} + inline void MaterialSheen::SetDefaults() { //KHR_materials_sheen properties SetVector(sheenColorFactor, defaultSheenFactor); @@ -2047,6 +2066,7 @@ inline void Asset::ReadExtensionsUsed(Document &doc) { } CHECK_EXT(KHR_materials_pbrSpecularGlossiness); + CHECK_EXT(KHR_materials_specular); CHECK_EXT(KHR_materials_unlit); CHECK_EXT(KHR_lights_punctual); CHECK_EXT(KHR_texture_transform); diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.h b/code/AssetLib/glTF2/glTF2AssetWriter.h index ec216101c..4e5177b4e 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.h +++ b/code/AssetLib/glTF2/glTF2AssetWriter.h @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * glTF Extensions Support: * KHR_materials_pbrSpecularGlossiness: full + * KHR_materials_specular: full * KHR_materials_unlit: full * KHR_materials_sheen: full * KHR_materials_clearcoat: full diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index 6f6eda502..f6fc7adff 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -418,6 +418,26 @@ namespace glTF2 { exts.AddMember("KHR_materials_unlit", unlit, w.mAl); } + if (m.materialSpecular.isPresent) { + Value materialSpecular(rapidjson::Type::kObjectType); + materialSpecular.SetObject(); + + MaterialSpecular &specular = m.materialSpecular.value; + + if (specular.specularFactor != 0.0f) { + WriteFloat(materialSpecular, specular.specularFactor, "specularFactor", w.mAl); + WriteTex(materialSpecular, specular.specularTexture, "specularTexture", w.mAl); + } + if (specular.specularColorFactor[0] != defaultSpecularColorFactor[0] && specular.specularColorFactor[1] != defaultSpecularColorFactor[1] && specular.specularColorFactor[2] != defaultSpecularColorFactor[2]) { + WriteVec(materialSpecular, specular.specularColorFactor, "specularColorFactor", w.mAl); + WriteTex(materialSpecular, specular.specularColorTexture, "specularColorTexture", w.mAl); + } + + if (!materialSpecular.ObjectEmpty()) { + exts.AddMember("KHR_materials_specular", materialSpecular, w.mAl); + } + } + if (m.materialSheen.isPresent) { Value materialSheen(rapidjson::Type::kObjectType); @@ -550,7 +570,7 @@ namespace glTF2 { inline void Write(Value& obj, Mesh& m, AssetWriter& w) { - /****************** Primitives *******************/ + /****************** Primitives *******************/ Value primitives; primitives.SetArray(); primitives.Reserve(unsigned(m.primitives.size()), w.mAl); @@ -929,6 +949,10 @@ namespace glTF2 { exts.PushBack(StringRef("KHR_materials_unlit"), mAl); } + if (this->mAsset.extensionsUsed.KHR_materials_specular) { + exts.PushBack(StringRef("KHR_materials_specular"), mAl); + } + if (this->mAsset.extensionsUsed.KHR_materials_sheen) { exts.PushBack(StringRef("KHR_materials_sheen"), mAl); } @@ -980,7 +1004,7 @@ namespace glTF2 { if (d.mObjs.empty()) return; Value* container = &mDoc; - const char* context = "Document"; + const char* context = "Document"; if (d.mExtId) { Value* exts = FindObject(mDoc, "extensions"); diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 51c7f8e05..777df50fd 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -640,11 +640,10 @@ aiReturn glTF2Exporter::GetMatColor(const aiMaterial &mat, vec3 &prop, const cha return result; } +// This extension has been deprecated, only export with the specific flag enabled, defaults to false. Uses KHR_material_specular default. bool glTF2Exporter::GetMatSpecGloss(const aiMaterial &mat, glTF2::PbrSpecularGlossiness &pbrSG) { bool result = false; // If has Glossiness, a Specular Color or Specular Texture, use the KHR_materials_pbrSpecularGlossiness extension - // NOTE: This extension is being considered for deprecation (Dec 2020), may be replaced by KHR_material_specular - if (mat.Get(AI_MATKEY_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) == AI_SUCCESS) { result = true; } else { @@ -674,6 +673,25 @@ bool glTF2Exporter::GetMatSpecGloss(const aiMaterial &mat, glTF2::PbrSpecularGlo return result; } +bool glTF2Exporter::GetMatSpecular(const aiMaterial &mat, glTF2::MaterialSpecular &specular) { + // Specular requires either/or, default factors of zero disables specular, so do not export + if (GetMatColor(mat, specular.specularColorFactor, AI_MATKEY_COLOR_SPECULAR) != AI_SUCCESS || mat.Get(AI_MATKEY_SPECULAR_FACTOR, specular.specularFactor) != AI_SUCCESS) { + return false; + } + // The spec states that the default is 1.0 and [1.0, 1.0, 1.0]. We if both are 0, which should disable specular. Otherwise, if one is 0, set to 1.0 + const bool colorFactorIsZero = specular.specularColorFactor[0] == defaultSpecularColorFactor[0] && specular.specularColorFactor[1] == defaultSpecularColorFactor[1] && specular.specularColorFactor[2] == defaultSpecularColorFactor[2]; + if (specular.specularFactor == 0.0f && colorFactorIsZero) { + return false; + } else if (specular.specularFactor == 0.0f) { + specular.specularFactor = 1.0f; + } else if (colorFactorIsZero) { + specular.specularColorFactor[0] = specular.specularColorFactor[1] = specular.specularColorFactor[2] = 1.0f; + } + GetMatTex(mat, specular.specularColorTexture, aiTextureType_SPECULAR); + GetMatTex(mat, specular.specularTexture, aiTextureType_SPECULAR); + return true; +} + bool glTF2Exporter::GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &sheen) { // Return true if got any valid Sheen properties or textures if (GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_SHEEN_COLOR_FACTOR) != aiReturn_SUCCESS) { @@ -818,9 +836,9 @@ void glTF2Exporter::ExportMaterials() { m->alphaMode = alphaMode.C_Str(); } - { + // This extension has been deprecated, only export with the specific flag enabled, defaults to false. Uses KHR_material_specular default. + if (mProperties->GetPropertyBool(AI_CONFIG_USE_GLTF_PBR_SPECULAR_GLOSSINESS)) { // KHR_materials_pbrSpecularGlossiness extension - // NOTE: This extension is being considered for deprecation (Dec 2020) PbrSpecularGlossiness pbrSG; if (GetMatSpecGloss(mat, pbrSG)) { mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true; @@ -837,7 +855,12 @@ void glTF2Exporter::ExportMaterials() { } else { // These extensions are not compatible with KHR_materials_unlit or KHR_materials_pbrSpecularGlossiness if (!m->pbrSpecularGlossiness.isPresent) { - // Sheen + MaterialSpecular specular; + if (GetMatSpecular(mat, specular)) { + mAsset->extensionsUsed.KHR_materials_specular = true; + m->materialSpecular = Nullable(specular); + } + MaterialSheen sheen; if (GetMatSheen(mat, sheen)) { mAsset->extensionsUsed.KHR_materials_sheen = true; diff --git a/code/AssetLib/glTF2/glTF2Exporter.h b/code/AssetLib/glTF2/glTF2Exporter.h index 425180b14..7bf57b567 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.h +++ b/code/AssetLib/glTF2/glTF2Exporter.h @@ -76,6 +76,7 @@ struct OcclusionTextureInfo; struct Node; struct Texture; struct PbrSpecularGlossiness; +struct MaterialSpecular; struct MaterialSheen; struct MaterialClearcoat; struct MaterialTransmission; @@ -117,6 +118,7 @@ protected: aiReturn GetMatColor(const aiMaterial &mat, glTF2::vec4 &prop, const char *propName, int type, int idx) const; aiReturn GetMatColor(const aiMaterial &mat, glTF2::vec3 &prop, const char *propName, int type, int idx) const; bool GetMatSpecGloss(const aiMaterial &mat, glTF2::PbrSpecularGlossiness &pbrSG); + bool GetMatSpecular(const aiMaterial &mat, glTF2::MaterialSpecular &specular); bool GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &sheen); bool GetMatClearcoat(const aiMaterial &mat, glTF2::MaterialClearcoat &clearcoat); bool GetMatTransmission(const aiMaterial &mat, glTF2::MaterialTransmission &transmission); diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 038a52b32..ea4c4970a 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -278,8 +278,19 @@ static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, M aimat->AddProperty(&alphaMode, AI_MATKEY_GLTF_ALPHAMODE); aimat->AddProperty(&mat.alphaCutoff, 1, AI_MATKEY_GLTF_ALPHACUTOFF); + // KHR_materials_specular + if (mat.materialSpecular.isPresent) { + MaterialSpecular &specular = mat.materialSpecular.value; + // Default values of zero disables Specular + if (std::memcmp(specular.specularColorFactor, defaultSpecularColorFactor, sizeof(glTFCommon::vec3)) != 0 || specular.specularFactor != 0.0f) { + SetMaterialColorProperty(r, specular.specularColorFactor, aimat, AI_MATKEY_COLOR_SPECULAR); + aimat->AddProperty(&specular.specularFactor, 1, AI_MATKEY_SPECULAR_FACTOR); + SetMaterialTextureProperty(embeddedTexIdxs, r, specular.specularTexture, aimat, aiTextureType_SPECULAR); + SetMaterialTextureProperty(embeddedTexIdxs, r, specular.specularColorTexture, aimat, aiTextureType_SPECULAR); + } + } // pbrSpecularGlossiness - if (mat.pbrSpecularGlossiness.isPresent) { + else if (mat.pbrSpecularGlossiness.isPresent) { PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value; SetMaterialColorProperty(r, pbrSG.diffuseFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index fad39a216..7cc46db90 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1200,7 +1200,6 @@ IF (ASSIMP_WARNINGS_AS_ERRORS) IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl TARGET_COMPILE_OPTIONS(assimp PRIVATE -Wall -Werror - -Wno-unused-function -Wno-microsoft-enum-value -Wno-switch-enum -Wno-covered-switch-default @@ -1390,7 +1389,7 @@ ENDIF() # Add RT-extension library for glTF importer with Open3DGC-compression. IF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC) - TARGET_LINK_LIBRARIES(assimp ${RT_LIBRARY}) + TARGET_LINK_LIBRARIES(assimp rt) ENDIF () diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index b8dabfff4..0795da65c 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -225,7 +225,7 @@ static void setupExporterArray(std::vector &exporte #endif #ifndef ASSIMP_BUILD_NO_PBRT_EXPORTER - exporters.emplace_back("pbrt", "pbrt-v4 scene description file", "pbrt", &ExportScenePbrt, aiProcess_Triangulate | aiProcess_SortByPType); + exporters.emplace_back("pbrt", "pbrt-v4 scene description file", "pbrt", &ExportScenePbrt, aiProcess_ConvertToLeftHanded | aiProcess_Triangulate | aiProcess_SortByPType); #endif #ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER diff --git a/code/Common/StbCommon.h b/code/Common/StbCommon.h index 573c98ac7..5de2e176d 100644 --- a/code/Common/StbCommon.h +++ b/code/Common/StbCommon.h @@ -48,6 +48,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma GCC diagnostic ignored "-Wunused-function" #endif +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif + #ifndef STB_USE_HUNTER /* Use prefixed names for the symbols from stb_image as it is a very commonly embedded library. Including vanilla stb_image symbols causes duplicate symbol problems if assimp is linked @@ -114,3 +119,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma GCC diagnostic pop #endif +#if defined(__clang__) +#pragma clang diagnostic pop +#endif diff --git a/code/Pbrt/PbrtExporter.cpp b/code/Pbrt/PbrtExporter.cpp index a9f8656a4..67937019f 100644 --- a/code/Pbrt/PbrtExporter.cpp +++ b/code/Pbrt/PbrtExporter.cpp @@ -111,7 +111,22 @@ PbrtExporter::PbrtExporter( mScene(pScene), mIOSystem(pIOSystem), mPath(path), - mFile(file) { + mFile(file), + mRootTransform( + // rotates the (already left-handed) CRS -90 degrees around the x axis in order to + // make +Z 'up' and +Y 'towards viewer', as in default in pbrt + 1.f, 0.f, 0.f, 0.f, // + 0.f, 0.f, -1.f, 0.f, // + 0.f, 1.f, 0.f, 0.f, // + 0.f, 0.f, 0.f, 1.f // + ) { + + mRootTransform = aiMatrix4x4( + -1.f, 0, 0.f, 0.f, // + 0.0f, -1.f, 0.f, 0.f, // + 0.f, 0.f, 1.f, 0.f, // + 0.f, 0.f, 0.f, 1.f // + ) * mRootTransform; // Export embedded textures. if (mScene->mNumTextures > 0) if (!mIOSystem->CreateDirectory("textures")) @@ -260,7 +275,7 @@ aiMatrix4x4 PbrtExporter::GetNodeTransform(const aiString &name) const { node = node->mParent; } } - return m; + return mRootTransform * m; } std::string PbrtExporter::TransformAsString(const aiMatrix4x4 &m) { @@ -309,7 +324,7 @@ void PbrtExporter::WriteCamera(int i) { // Get camera fov float hfov = AI_RAD_TO_DEG(camera->mHorizontalFOV); - float fov = (aspect >= 1.0) ? hfov : (hfov * aspect); + float fov = (aspect >= 1.0) ? hfov : (hfov / aspect); if (fov < 5) { std::cerr << fov << ": suspiciously low field of view specified by camera. Setting to 45 degrees.\n"; fov = 45; @@ -327,7 +342,7 @@ void PbrtExporter::WriteCamera(int i) { if (!cameraActive) mOutput << "# "; - mOutput << "Scale -1 1 1\n"; // right handed -> left handed + mOutput << "Scale 1 1 1\n"; if (!cameraActive) mOutput << "# "; mOutput << "LookAt " @@ -383,8 +398,8 @@ void PbrtExporter::WriteWorldDefinition() { } mOutput << "# Geometry\n\n"; - aiMatrix4x4 worldFromObject; - WriteGeometricObjects(mScene->mRootNode, worldFromObject, meshUses); + + WriteGeometricObjects(mScene->mRootNode, mRootTransform, meshUses); } void PbrtExporter::WriteTextures() { diff --git a/code/Pbrt/PbrtExporter.h b/code/Pbrt/PbrtExporter.h index 4f4e1625d..c7e8180e2 100644 --- a/code/Pbrt/PbrtExporter.h +++ b/code/Pbrt/PbrtExporter.h @@ -100,6 +100,9 @@ private: // A private set to keep track of which textures have been declared std::set mTextureSet; + // Transform to apply to the root node and all root objects such as cameras, lights, etc. + aiMatrix4x4 mRootTransform; + aiMatrix4x4 GetNodeTransform(const aiString& name) const; static std::string TransformAsString(const aiMatrix4x4& m); diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index ad16fa88c..9e843a20d 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -1065,6 +1065,17 @@ enum aiComponent */ #define AI_CONFIG_EXPORT_POINT_CLOUDS "EXPORT_POINT_CLOUDS" +/** @brief Specifies whether to use the deprecated KHR_materials_pbrSpecularGlossiness extension + * + * When this flag is undefined any material with specularity will use the new KHR_materials_specular + * extension. Enabling this flag will revert to the deprecated extension. Note that exporting + * KHR_materials_pbrSpecularGlossiness with extensions other than KHR_materials_unlit is unsupported, + * including the basic pbrMetallicRoughness spec. + * + * Property type: Bool. Default value: false. + */ +#define AI_CONFIG_USE_GLTF_PBR_SPECULAR_GLOSSINESS "USE_GLTF_PBR_SPECULAR_GLOSSINESS" + /** * @brief Specifies the blob name, assimp uses for exporting. * diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 957a94b15..91ac87ee5 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -219,8 +219,14 @@ TEST_F(utglTF2ImportExport, importglTF2AndExport_KHR_materials_pbrSpecularGlossi const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf", aiProcess_ValidateDataStructure); EXPECT_NE(nullptr, scene); - // Export + + // Export with specular glossiness disabled EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb")); + + // Export with specular glossiness enabled + ExportProperties props; + props.SetPropertyBool(AI_CONFIG_USE_GLTF_PBR_SPECULAR_GLOSSINESS, true); + EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb", 0, &props)); // And re-import EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb", true));