diff --git a/code/AssetLib/FBX/FBXExporter.h b/code/AssetLib/FBX/FBXExporter.h index 3f5e8029d..d249b7bee 100644 --- a/code/AssetLib/FBX/FBXExporter.h +++ b/code/AssetLib/FBX/FBXExporter.h @@ -64,10 +64,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct aiScene; struct aiNode; struct aiLight; -//struct aiMaterial; -namespace Assimp -{ +namespace Assimp { class IOSystem; class IOStream; class ExportProperties; diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 0e7251b1e..78e22e931 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -436,11 +436,11 @@ inline void SetSamplerWrap(SamplerWrap& wrap, aiTextureMapMode map) }; } -void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture, aiTextureType tt, unsigned int slot) +void glTF2Exporter::GetTexSampler(const aiMaterial& mat, Ref texture, aiTextureType tt, unsigned int slot) { aiString aId; std::string id; - if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) { + if (aiGetMaterialString(&mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) { id = aId.C_Str(); } @@ -455,49 +455,52 @@ void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture, a SamplerMagFilter filterMag; SamplerMinFilter filterMin; - if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) { + if (aiGetMaterialInteger(&mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) { SetSamplerWrap(texture->sampler->wrapS, mapU); } - if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_V(tt, slot), (int*)&mapV) == AI_SUCCESS) { + if (aiGetMaterialInteger(&mat, AI_MATKEY_MAPPINGMODE_V(tt, slot), (int*)&mapV) == AI_SUCCESS) { SetSamplerWrap(texture->sampler->wrapT, mapV); } - if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(tt, slot), (int*)&filterMag) == AI_SUCCESS) { + if (aiGetMaterialInteger(&mat, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(tt, slot), (int*)&filterMag) == AI_SUCCESS) { texture->sampler->magFilter = filterMag; } - if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(tt, slot), (int*)&filterMin) == AI_SUCCESS) { + if (aiGetMaterialInteger(&mat, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(tt, slot), (int*)&filterMin) == AI_SUCCESS) { texture->sampler->minFilter = filterMin; } aiString name; - if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGNAME(tt, slot), &name) == AI_SUCCESS) { + if (aiGetMaterialString(&mat, AI_MATKEY_GLTF_MAPPINGNAME(tt, slot), &name) == AI_SUCCESS) { texture->sampler->name = name.C_Str(); } } } -void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot) +void glTF2Exporter::GetMatTexProp(const aiMaterial& mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot) { std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName; - mat->Get(textureKey.c_str(), tt, slot, prop); + mat.Get(textureKey.c_str(), tt, slot, prop); } -void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot) +void glTF2Exporter::GetMatTexProp(const aiMaterial& mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot) { std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName; - mat->Get(textureKey.c_str(), tt, slot, prop); + mat.Get(textureKey.c_str(), tt, slot, prop); } -void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTextureType tt, unsigned int slot = 0) +void glTF2Exporter::GetMatTex(const aiMaterial& mat, Ref& texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot = 0) { - if (mat->GetTextureCount(tt) > 0) { + if (mat.GetTextureCount(tt) > 0) { aiString tex; - if (mat->Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) { + // Read texcoord (UV map index) + mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord); + + if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) { std::string path = tex.C_Str(); if (path.size() > 0) { @@ -567,45 +570,45 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe } } -void glTF2Exporter::GetMatTex(const aiMaterial* mat, TextureInfo& prop, aiTextureType tt, unsigned int slot = 0) +void glTF2Exporter::GetMatTex(const aiMaterial& mat, TextureInfo& prop, aiTextureType tt, unsigned int slot = 0) { Ref& texture = prop.texture; - GetMatTex(mat, texture, tt, slot); + GetMatTex(mat, texture, prop.texCoord, tt, slot); - if (texture) { - GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); - } + //if (texture) { + // GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); + //} } -void glTF2Exporter::GetMatTex(const aiMaterial* mat, NormalTextureInfo& prop, aiTextureType tt, unsigned int slot = 0) +void glTF2Exporter::GetMatTex(const aiMaterial& mat, NormalTextureInfo& prop, aiTextureType tt, unsigned int slot = 0) { Ref& texture = prop.texture; - GetMatTex(mat, texture, tt, slot); + GetMatTex(mat, texture, prop.texCoord, tt, slot); if (texture) { - GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); + //GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); GetMatTexProp(mat, prop.scale, "scale", tt, slot); } } -void glTF2Exporter::GetMatTex(const aiMaterial* mat, OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot = 0) +void glTF2Exporter::GetMatTex(const aiMaterial& mat, OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot = 0) { Ref& texture = prop.texture; - GetMatTex(mat, texture, tt, slot); + GetMatTex(mat, texture, prop.texCoord, tt, slot); if (texture) { - GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); + //GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); GetMatTexProp(mat, prop.strength, "strength", tt, slot); } } -aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const char* propName, int type, int idx) +aiReturn glTF2Exporter::GetMatColor(const aiMaterial& mat, vec4& prop, const char* propName, int type, int idx) const { aiColor4D col; - aiReturn result = mat->Get(propName, type, idx, col); + aiReturn result = mat.Get(propName, type, idx, col); if (result == AI_SUCCESS) { prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a; @@ -614,37 +617,116 @@ aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const cha return result; } -aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec3& prop, const char* propName, int type, int idx) +aiReturn glTF2Exporter::GetMatColor(const aiMaterial& mat, vec3& prop, const char* propName, int type, int idx) const { aiColor3D col; - aiReturn result = mat->Get(propName, type, idx, col); + aiReturn result = mat.Get(propName, type, idx, col); if (result == AI_SUCCESS) { - prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; + prop[0] = col.r; + prop[1] = col.g; + prop[2] = col.b; } return result; } +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 { + // Don't have explicit glossiness, convert from pbr roughness or legacy shininess + float shininess; + if (mat.Get(AI_MATKEY_ROUGHNESS_FACTOR, shininess) == AI_SUCCESS) { + pbrSG.glossinessFactor = 1.0f - shininess; // Extension defines this way + } else if (mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) { + pbrSG.glossinessFactor = shininess / 1000; + } + } + + if (GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR) == AI_SUCCESS) { + result = true; + } + // Add any appropriate textures + GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_SPECULAR); + + result = result || pbrSG.specularGlossinessTexture.texture; + + if (result) { + // Likely to always have diffuse + GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE); + GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_COLOR_DIFFUSE); + } + + return result; +} + +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) + return false; + + // Default Sheen color factor {0,0,0} disables Sheen, so do not export + if (sheen.sheenColorFactor == defaultSheenFactor) + return false; + + mat.Get(AI_MATKEY_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor); + + GetMatTex(mat, sheen.sheenColorTexture, AI_MATKEY_SHEEN_COLOR_TEXTURE); + GetMatTex(mat, sheen.sheenRoughnessTexture, AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE); + + return true; +} + +bool glTF2Exporter::GetMatClearcoat(const aiMaterial &mat, glTF2::MaterialClearcoat &clearcoat) { + if (mat.Get(AI_MATKEY_CLEARCOAT_FACTOR, clearcoat.clearcoatFactor) != aiReturn_SUCCESS) { + return false; + } + + // Clearcoat factor of zero disables Clearcoat, so do not export + if (clearcoat.clearcoatFactor == 0.0f) + return false; + + mat.Get(AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR, clearcoat.clearcoatRoughnessFactor); + + GetMatTex(mat, clearcoat.clearcoatTexture, AI_MATKEY_CLEARCOAT_TEXTURE); + GetMatTex(mat, clearcoat.clearcoatRoughnessTexture, AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE); + GetMatTex(mat, clearcoat.clearcoatNormalTexture, AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE); + + return true; +} + +bool glTF2Exporter::GetMatTransmission(const aiMaterial &mat, glTF2::MaterialTransmission &transmission) { + bool result = mat.Get(AI_MATKEY_TRANSMISSION_FACTOR, transmission.transmissionFactor) == aiReturn_SUCCESS; + GetMatTex(mat, transmission.transmissionTexture, AI_MATKEY_TRANSMISSION_TEXTURE); + return result || transmission.transmissionTexture.texture; +} + void glTF2Exporter::ExportMaterials() { aiString aiName; for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { - const aiMaterial* mat = mScene->mMaterials[i]; + ai_assert(mScene->mMaterials[i] != nullptr); + + const aiMaterial & mat = *(mScene->mMaterials[i]); std::string id = "material_" + ai_to_string(i); Ref m = mAsset->materials.Create(id); std::string name; - if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) { + if (mat.Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) { name = aiName.C_Str(); } name = mAsset->FindUniqueID(name, "material"); m->name = name; - GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE); + GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_BASE_COLOR); if (!m->pbrMetallicRoughness.baseColorTexture.texture) { //if there wasn't a baseColorTexture defined in the source, fallback to any diffuse texture @@ -653,26 +735,26 @@ void glTF2Exporter::ExportMaterials() GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); - if (GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR) != AI_SUCCESS) { + if (GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_BASE_COLOR) != AI_SUCCESS) { // if baseColorFactor wasn't defined, then the source is likely not a metallic roughness material. //a fallback to any diffuse color should be used instead GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); } - if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) { + if (mat.Get(AI_MATKEY_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) { //if metallicFactor wasn't defined, then the source is likely not a PBR file, and the metallicFactor should be 0 m->pbrMetallicRoughness.metallicFactor = 0; } // get roughness if source is gltf2 file - if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor) != AI_SUCCESS) { + if (mat.Get(AI_MATKEY_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor) != AI_SUCCESS) { // otherwise, try to derive and convert from specular + shininess values aiColor4D specularColor; ai_real shininess; if ( - mat->Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS && - mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS + mat.Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS && + mat.Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS ) { // convert specular color to luminance float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f; @@ -693,17 +775,17 @@ void glTF2Exporter::ExportMaterials() GetMatTex(mat, m->emissiveTexture, aiTextureType_EMISSIVE); GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE); - mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided); - mat->Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff); + mat.Get(AI_MATKEY_TWOSIDED, m->doubleSided); + mat.Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff); aiString alphaMode; - if (mat->Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) { + if (mat.Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) { m->alphaMode = alphaMode.C_Str(); } else { float opacity; - if (mat->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) { + if (mat.Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) { if (opacity < 1) { m->alphaMode = "BLEND"; m->pbrMetallicRoughness.baseColorFactor[3] *= opacity; @@ -711,85 +793,44 @@ void glTF2Exporter::ExportMaterials() } } - bool hasPbrSpecularGlossiness = false; - mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS, hasPbrSpecularGlossiness); - - if (hasPbrSpecularGlossiness) { - - if (!mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness) { - mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true; - } - + { + // KHR_materials_pbrSpecularGlossiness extension + // NOTE: This extension is being considered for deprecation (Dec 2020) PbrSpecularGlossiness pbrSG; - - GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_COLOR_DIFFUSE); - GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR); - - if (mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) != AI_SUCCESS) { - float shininess; - - if (mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS) { - pbrSG.glossinessFactor = shininess / 1000; - } + if (GetMatSpecGloss(mat, pbrSG)) { + mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true; + m->pbrSpecularGlossiness = Nullable(pbrSG); } - - GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE); - GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_SPECULAR); - - m->pbrSpecularGlossiness = Nullable(pbrSG); } - bool unlit; - if (mat->Get(AI_MATKEY_GLTF_UNLIT, unlit) == AI_SUCCESS && unlit) { + // glTFv2 is either PBR or Unlit + aiShadingMode shadingMode = aiShadingMode_PBR_BRDF; + mat.Get(AI_MATKEY_SHADING_MODEL, shadingMode); + if (shadingMode == aiShadingMode_Unlit) { mAsset->extensionsUsed.KHR_materials_unlit = true; m->unlit = true; - } + } else { + // These extensions are not compatible with KHR_materials_unlit or KHR_materials_pbrSpecularGlossiness + if (!m->pbrSpecularGlossiness.isPresent) { + // Sheen + MaterialSheen sheen; + if (GetMatSheen(mat, sheen)) { + mAsset->extensionsUsed.KHR_materials_sheen = true; + m->materialSheen = Nullable(sheen); + } - bool hasMaterialSheen = false; - mat->Get(AI_MATKEY_GLTF_MATERIAL_SHEEN, hasMaterialSheen); + MaterialClearcoat clearcoat; + if (GetMatClearcoat(mat, clearcoat)) { + mAsset->extensionsUsed.KHR_materials_clearcoat = true; + m->materialClearcoat = Nullable(clearcoat); + } - if (hasMaterialSheen) { - mAsset->extensionsUsed.KHR_materials_sheen = true; - - MaterialSheen sheen; - - GetMatColor(mat, sheen.sheenColorFactor, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR); - mat->Get(AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR, sheen.sheenRoughnessFactor); - GetMatTex(mat, sheen.sheenColorTexture, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE); - GetMatTex(mat, sheen.sheenRoughnessTexture, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE); - - m->materialSheen = Nullable(sheen); - } - - bool hasMaterialClearcoat = false; - mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT, hasMaterialClearcoat); - - if (hasMaterialClearcoat) { - mAsset->extensionsUsed.KHR_materials_clearcoat= true; - - MaterialClearcoat clearcoat; - - mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR, clearcoat.clearcoatFactor); - mat->Get(AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR, clearcoat.clearcoatRoughnessFactor); - GetMatTex(mat, clearcoat.clearcoatTexture, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE); - GetMatTex(mat, clearcoat.clearcoatRoughnessTexture, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE); - GetMatTex(mat, clearcoat.clearcoatNormalTexture, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE); - - m->materialClearcoat = Nullable(clearcoat); - } - - bool hasMaterialTransmission = false; - mat->Get(AI_MATKEY_GLTF_MATERIAL_TRANSMISSION, hasMaterialTransmission); - - if (hasMaterialTransmission) { - mAsset->extensionsUsed.KHR_materials_transmission = true; - - MaterialTransmission transmission; - - mat->Get(AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR, transmission.transmissionFactor); - GetMatTex(mat, transmission.transmissionTexture, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE); - - m->materialTransmission = Nullable(transmission); + MaterialTransmission transmission; + if (GetMatTransmission(mat, transmission)) { + mAsset->extensionsUsed.KHR_materials_transmission = true; + m->materialTransmission = Nullable(transmission); + } + } } } } diff --git a/code/AssetLib/glTF2/glTF2Exporter.h b/code/AssetLib/glTF2/glTF2Exporter.h index 86497516a..f5238297f 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.h +++ b/code/AssetLib/glTF2/glTF2Exporter.h @@ -72,6 +72,10 @@ namespace glTF2 struct OcclusionTextureInfo; struct Node; struct Texture; + struct PbrSpecularGlossiness; + struct MaterialSheen; + struct MaterialClearcoat; + struct MaterialTransmission; // Vec/matrix types, as raw float arrays typedef float (vec2)[2]; @@ -97,15 +101,19 @@ namespace Assimp protected: void WriteBinaryData(IOStream* outfile, std::size_t sceneLength); - void GetTexSampler(const aiMaterial* mat, glTF2::Ref texture, aiTextureType tt, unsigned int slot); - void GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx); - void GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx); - void GetMatTex(const aiMaterial* mat, glTF2::Ref& texture, aiTextureType tt, unsigned int slot); - void GetMatTex(const aiMaterial* mat, glTF2::TextureInfo& prop, aiTextureType tt, unsigned int slot); - void GetMatTex(const aiMaterial* mat, glTF2::NormalTextureInfo& prop, aiTextureType tt, unsigned int slot); - void GetMatTex(const aiMaterial* mat, glTF2::OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot); - aiReturn GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx); - aiReturn GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx); + void GetTexSampler(const aiMaterial& mat, glTF2::Ref texture, aiTextureType tt, unsigned int slot); + void GetMatTexProp(const aiMaterial& mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx); + void GetMatTexProp(const aiMaterial& mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx); + void GetMatTex(const aiMaterial& mat, glTF2::Ref& texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot); + void GetMatTex(const aiMaterial& mat, glTF2::TextureInfo& prop, aiTextureType tt, unsigned int slot); + void GetMatTex(const aiMaterial& mat, glTF2::NormalTextureInfo& prop, aiTextureType tt, unsigned int slot); + void GetMatTex(const aiMaterial& mat, glTF2::OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot); + 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 GetMatSheen(const aiMaterial& mat, glTF2::MaterialSheen& sheen); + bool GetMatClearcoat(const aiMaterial& mat, glTF2::MaterialClearcoat& clearcoat); + bool GetMatTransmission(const aiMaterial& mat, glTF2::MaterialTransmission& transmission); void ExportMetadata(); void ExportMaterials(); void ExportMeshes(); diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index c62989c3b..aadc9fb16 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -165,7 +165,8 @@ inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset } mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); - mat->AddProperty(&prop.texCoord, 1, AI_MATKEY_GLTF_TEXTURE_TEXCOORD(texType, texSlot)); + const int uvIndex = static_cast(prop.texCoord); + mat->AddProperty(&uvIndex, 1, AI_MATKEY_UVWSRC(texType, texSlot)); if (prop.textureTransformSupported) { aiUVTransform transform; @@ -208,6 +209,11 @@ inline void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset if (sampler->minFilter != SamplerMinFilter::UNSET) { mat->AddProperty(&sampler->minFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(texType, texSlot)); } + } else { + // Use glTFv2 default sampler + const aiTextureMapMode default_wrap = aiTextureMapMode_Wrap; + mat->AddProperty(&default_wrap, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot)); + mat->AddProperty(&default_wrap, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot)); } } } @@ -238,16 +244,18 @@ static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, M aimat->AddProperty(&str, AI_MATKEY_NAME); } + // Set Assimp DIFFUSE and BASE COLOR to the pbrMetallicRoughness base color and texture for backwards compatibility + // Technically should not load any pbrMetallicRoughness if extensionsRequired contains KHR_materials_pbrSpecularGlossiness SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); - SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR); + SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_BASE_COLOR); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE); - SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_BASE_COLOR); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); - aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR); - aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR); + aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_METALLIC_FACTOR); + aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_ROUGHNESS_FACTOR); float roughnessAsShininess = 1 - mat.pbrMetallicRoughness.roughnessFactor; roughnessAsShininess *= roughnessAsShininess * 1000; @@ -268,52 +276,58 @@ static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, M if (mat.pbrSpecularGlossiness.isPresent) { PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value; - aimat->AddProperty(&mat.pbrSpecularGlossiness.isPresent, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS); SetMaterialColorProperty(r, pbrSG.diffuseFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_COLOR_SPECULAR); float glossinessAsShininess = pbrSG.glossinessFactor * 1000.0f; aimat->AddProperty(&glossinessAsShininess, 1, AI_MATKEY_SHININESS); - aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR); + aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLOSSINESS_FACTOR); SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.diffuseTexture, aimat, aiTextureType_DIFFUSE); SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR); } + + // glTFv2 is either PBR or Unlit + aiShadingMode shadingMode = aiShadingMode_PBR_BRDF; if (mat.unlit) { - aimat->AddProperty(&mat.unlit, 1, AI_MATKEY_GLTF_UNLIT); + shadingMode = aiShadingMode_Unlit; } - //KHR_materials_sheen + aimat->AddProperty(&shadingMode, 1, AI_MATKEY_SHADING_MODEL); + + + // KHR_materials_sheen if (mat.materialSheen.isPresent) { MaterialSheen &sheen = mat.materialSheen.value; - - aimat->AddProperty(&mat.materialSheen.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_SHEEN); - SetMaterialColorProperty(r, sheen.sheenColorFactor, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR); - aimat->AddProperty(&sheen.sheenRoughnessFactor, 1, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR); - SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenColorTexture, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE); - SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenRoughnessTexture, aimat, AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE); + // Default value {0,0,0} disables Sheen + if (sheen.sheenColorFactor != defaultSheenFactor) { + SetMaterialColorProperty(r, sheen.sheenColorFactor, aimat, AI_MATKEY_SHEEN_COLOR_FACTOR); + aimat->AddProperty(&sheen.sheenRoughnessFactor, 1, AI_MATKEY_SHEEN_ROUGHNESS_FACTOR); + SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenColorTexture, aimat, AI_MATKEY_SHEEN_COLOR_TEXTURE); + SetMaterialTextureProperty(embeddedTexIdxs, r, sheen.sheenRoughnessTexture, aimat, AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE); + } } - //KHR_materials_clearcoat + // KHR_materials_clearcoat if (mat.materialClearcoat.isPresent) { MaterialClearcoat &clearcoat = mat.materialClearcoat.value; - - aimat->AddProperty(&mat.materialClearcoat.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT); - aimat->AddProperty(&clearcoat.clearcoatFactor, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR); - aimat->AddProperty(&clearcoat.clearcoatRoughnessFactor, 1, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR); - SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE); - SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatRoughnessTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE); - SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatNormalTexture, aimat, AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE); + // Default value 0.0 disables clearcoat + if (clearcoat.clearcoatFactor != 0.0f) { + aimat->AddProperty(&clearcoat.clearcoatFactor, 1, AI_MATKEY_CLEARCOAT_FACTOR); + aimat->AddProperty(&clearcoat.clearcoatRoughnessFactor, 1, AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR); + SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatTexture, aimat, AI_MATKEY_CLEARCOAT_TEXTURE); + SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatRoughnessTexture, aimat, AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE); + SetMaterialTextureProperty(embeddedTexIdxs, r, clearcoat.clearcoatNormalTexture, aimat, AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE); + } } - //KHR_materials_transmission + // KHR_materials_transmission if (mat.materialTransmission.isPresent) { MaterialTransmission &transmission = mat.materialTransmission.value; - aimat->AddProperty(&mat.materialTransmission.isPresent, 1, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION); - aimat->AddProperty(&transmission.transmissionFactor, 1, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR); - SetMaterialTextureProperty(embeddedTexIdxs, r, transmission.transmissionTexture, aimat, AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE); + aimat->AddProperty(&transmission.transmissionFactor, 1, AI_MATKEY_TRANSMISSION_FACTOR); + SetMaterialTextureProperty(embeddedTexIdxs, r, transmission.transmissionTexture, aimat, AI_MATKEY_TRANSMISSION_TEXTURE); } return aimat; diff --git a/code/Common/material.cpp b/code/Common/material.cpp index 5230c8b43..6c90e66f0 100644 --- a/code/Common/material.cpp +++ b/code/Common/material.cpp @@ -47,10 +47,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include // ------------------------------------------------------------------------------- -const char* TextureTypeToString(aiTextureType in) -{ - switch (in) - { +const char *TextureTypeToString(aiTextureType in) { + switch (in) { case aiTextureType_NONE: return "n/a"; case aiTextureType_DIFFUSE: @@ -87,6 +85,12 @@ const char* TextureTypeToString(aiTextureType in) return "DiffuseRoughness"; case aiTextureType_AMBIENT_OCCLUSION: return "AmbientOcclusion"; + case aiTextureType_SHEEN: + return "Sheen"; + case aiTextureType_CLEARCOAT: + return "Clearcoat"; + case aiTextureType_TRANSMISSION: + return "Transmission"; case aiTextureType_UNKNOWN: return "Unknown"; default: diff --git a/contrib/poly2tri/poly2tri/sweep/sweep.cc b/contrib/poly2tri/poly2tri/sweep/sweep.cc index 23aeb6b57..8e3d794c0 100644 --- a/contrib/poly2tri/poly2tri/sweep/sweep.cc +++ b/contrib/poly2tri/poly2tri/sweep/sweep.cc @@ -129,7 +129,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl EdgeEvent( tcx, ep, *p1, triangle, *p1 ); } else { // ASSIMP_CHANGE (aramis_acg) - std::runtime_error("EdgeEvent - collinear points not supported"); + throw std::runtime_error("EdgeEvent - collinear points not supported"); } return; } diff --git a/include/assimp/material.h b/include/assimp/material.h index 08c0491c0..2024be07f 100644 --- a/include/assimp/material.h +++ b/include/assimp/material.h @@ -144,7 +144,7 @@ enum aiTextureMapMode { enum aiTextureMapping { /** The mapping coordinates are taken from an UV channel. * - * The #AI_MATKEY_UVWSRC key specifies from which UV channel + * #AI_MATKEY_UVWSRC property specifies from which UV channel * the texture coordinates are to be taken from (remember, * meshes can have more than one UV channel). */ @@ -202,11 +202,15 @@ enum aiTextureType { /** The texture is combined with the result of the diffuse * lighting equation. + * OR + * PBR Specular/Glossiness */ aiTextureType_DIFFUSE = 1, /** The texture is combined with the result of the specular * lighting equation. + * OR + * PBR Specular/Glossiness */ aiTextureType_SPECULAR = 2, @@ -288,6 +292,32 @@ enum aiTextureType { aiTextureType_DIFFUSE_ROUGHNESS = 16, aiTextureType_AMBIENT_OCCLUSION = 17, + /** PBR Material Modifiers + * Some modern renderers have further PBR modifiers that may be overlaid + * on top of the 'base' PBR materials for additional realism. + * These use multiple texture maps, so only the base type is directly defined + */ + + /** Sheen + * Generally used to simulate textiles that are covered in a layer of microfibers + * eg velvet + * https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_sheen + */ + aiTextureType_SHEEN = 19, + + /** Clearcoat + * Simulates a layer of 'polish' or 'laquer' layered on top of a PBR substrate + * https://autodesk.github.io/standard-surface/#closures/coating + * https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat + */ + aiTextureType_CLEARCOAT = 20, + + /** Transmission + * Simulates transmission through the surface + * May include further information such as wall thickness + */ + aiTextureType_TRANSMISSION = 21, + /** Unknown texture * * A texture reference that does not match any of the definitions @@ -309,7 +339,9 @@ ASSIMP_API const char *TextureTypeToString(enum aiTextureType in); // --------------------------------------------------------------------------- /** @brief Defines all shading models supported by the library - * + * + * Property: #AI_MATKEY_SHADING_MODEL + * * The list of shading modes has been taken from Blender. * See Blender documentation for more information. The API does * not distinguish between "specular" and "diffuse" shaders (thus the @@ -318,6 +350,7 @@ ASSIMP_API const char *TextureTypeToString(enum aiTextureType in); * Again, this value is just a hint. Assimp tries to select the shader whose * most common implementation matches the original rendering results of the * 3D modeler which wrote a particular model as closely as possible. + * */ enum aiShadingMode { /** Flat shading. Shading is done on per-face base, @@ -364,13 +397,28 @@ enum aiShadingMode { aiShadingMode_CookTorrance = 0x8, /** No shading at all. Constant light influence of 1.0. + * Also known as "Unlit" */ aiShadingMode_NoShading = 0x9, + aiShadingMode_Unlit = aiShadingMode_NoShading, // Alias /** Fresnel shading */ aiShadingMode_Fresnel = 0xa, + /** Physically-Based Rendering (PBR) shading using + * Bidirectional scattering/reflectance distribution function (BSDF/BRDF) + * There are multiple methods under this banner, and model files may provide + * data for more than one PBR-BRDF method. + * Applications should use the set of provided properties to determine which + * of their preferred PBR rendering methods are likely to be available + * eg: + * - If AI_MATKEY_METALLIC_FACTOR is set, then a Metallic/Roughness is available + * - If AI_MATKEY_GLOSSINESS_FACTOR is set, then a Specular/Glossiness is available + * Note that some PBR methods allow layering of techniques + */ + aiShadingMode_PBR_BRDF = 0xb, + #ifndef SWIG _aiShadingMode_Force32Bit = INT_MAX #endif @@ -922,12 +970,66 @@ extern "C" { // --------------------------------------------------------------------------- // PBR material support +// -------------------- +// Properties defining PBR rendering techniques #define AI_MATKEY_USE_COLOR_MAP "$mat.useColorMap", 0, 0 + +// Metallic/Roughness Workflow +// --------------------------- +// Base RGBA color factor. Will be multiplied by final base color texture values if extant +// Note: Importers may choose to copy this into AI_MATKEY_COLOR_DIFFUSE for compatibility +// with renderers and formats that do not support Metallic/Roughness PBR #define AI_MATKEY_BASE_COLOR "$clr.base", 0, 0 +#define AI_MATKEY_BASE_COLOR_TEXTURE aiTextureType_BASE_COLOR, 0 #define AI_MATKEY_USE_METALLIC_MAP "$mat.useMetallicMap", 0, 0 +// Metallic factor. 0.0 = Full Dielectric, 1.0 = Full Metal #define AI_MATKEY_METALLIC_FACTOR "$mat.metallicFactor", 0, 0 +#define AI_MATKEY_METALLIC_TEXTURE aiTextureType_METALNESS, 0 #define AI_MATKEY_USE_ROUGHNESS_MAP "$mat.useRoughnessMap", 0, 0 +// Roughness factor. 0.0 = Perfectly Smooth, 1.0 = Completely Rough #define AI_MATKEY_ROUGHNESS_FACTOR "$mat.roughnessFactor", 0, 0 +#define AI_MATKEY_ROUGHNESS_TEXTURE aiTextureType_DIFFUSE_ROUGHNESS, 0 + +// Specular/Glossiness Workflow +// --------------------------- +// Diffuse/Albedo Color. Note: Pure Metals have a diffuse of {0,0,0} +// AI_MATKEY_COLOR_DIFFUSE +// Specular Color. +// Note: Metallic/Roughness may also have a Specular Color +// AI_MATKEY_COLOR_SPECULAR +#define AI_MATKEY_SPECULAR_FACTOR "$mat.specularFactor", 0, 0 +// Glossiness factor. 0.0 = Completely Rough, 1.0 = Perfectly Smooth +#define AI_MATKEY_GLOSSINESS_FACTOR "$mat.glossinessFactor", 0, 0 + +// Sheen +// ----- +// Sheen base RGB color. Default {0,0,0} +#define AI_MATKEY_SHEEN_COLOR_FACTOR "$clr.sheen.factor", 0, 0 +// Sheen Roughness Factor. +#define AI_MATKEY_SHEEN_ROUGHNESS_FACTOR "$mat.sheen.roughnessFactor", 0, 0 +#define AI_MATKEY_SHEEN_COLOR_TEXTURE aiTextureType_SHEEN, 0 +#define AI_MATKEY_SHEEN_ROUGHNESS_TEXTURE aiTextureType_SHEEN, 1 + +// Clearcoat +// --------- +// Clearcoat layer intensity. 0.0 = none (disabled) +#define AI_MATKEY_CLEARCOAT_FACTOR "$mat.clearcoat.factor", 0, 0 +#define AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR "$mat.clearcoat.roughnessFactor", 0, 0 +#define AI_MATKEY_CLEARCOAT_TEXTURE aiTextureType_CLEARCOAT, 0 +#define AI_MATKEY_CLEARCOAT_ROUGHNESS_TEXTURE aiTextureType_CLEARCOAT, 1 +#define AI_MATKEY_CLEARCOAT_NORMAL_TEXTURE aiTextureType_CLEARCOAT, 2 + +// Transmission +// ------------ +// https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission +// Base percentage of light transmitted through the surface. 0.0 = Opaque, 1.0 = Fully transparent +#define AI_MATKEY_TRANSMISSION_FACTOR "$mat.transmission.factor", 0, 0 +// Texture defining percentage of light transmitted through the surface. +// Multiplied by AI_MATKEY_TRANSMISSION_FACTOR +#define AI_MATKEY_TRANSMISSION_TEXTURE aiTextureType_TRANSMISSION, 0 + +// Emissive +// -------- #define AI_MATKEY_USE_EMISSIVE_MAP "$mat.useEmissiveMap", 0, 0 #define AI_MATKEY_EMISSIVE_INTENSITY "$mat.emissiveIntensity", 0, 0 #define AI_MATKEY_USE_AO_MAP "$mat.useAOMap", 0, 0 diff --git a/include/assimp/pbrmaterial.h b/include/assimp/pbrmaterial.h index 2e41b8b6d..93e7e3095 100644 --- a/include/assimp/pbrmaterial.h +++ b/include/assimp/pbrmaterial.h @@ -50,32 +50,32 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # pragma GCC system_header #endif -#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0 -#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0 -#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0 -#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1 +//#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0 +//#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0 +//#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0 +//#define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1 #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0 #define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0 #define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0 -#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0 -#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0 -#define AI_MATKEY_GLTF_UNLIT "$mat.gltf.unlit", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_SHEEN "$mat.gltf.materialSheen", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR "$mat.gltf.materialSheen.sheenColorFactor", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR "$mat.gltf.materialSheen.sheenRoughnessFactor", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE aiTextureType_UNKNOWN, 1 -#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 2 -#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT "$mat.gltf.materialClearcoat", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR "$mat.gltf.materialClearcoat.clearcoatFactor", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR "$mat.gltf.materialClearcoat.clearcoatRoughnessFactor", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE aiTextureType_UNKNOWN, 3 -#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 4 -#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE aiTextureType_NORMALS, 1 -#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION "$mat.gltf.materialTransmission", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR "$mat.gltf.materialTransmission.transmissionFactor", 0, 0 -#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE aiTextureType_UNKNOWN, 5 +//#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0 +//#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0 +//#define AI_MATKEY_GLTF_UNLIT "$mat.gltf.unlit", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_SHEEN "$mat.gltf.materialSheen", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_FACTOR "$mat.gltf.materialSheen.sheenColorFactor", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_FACTOR "$mat.gltf.materialSheen.sheenRoughnessFactor", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_SHEEN_COLOR_TEXTURE aiTextureType_UNKNOWN, 1 +//#define AI_MATKEY_GLTF_MATERIAL_SHEEN_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 2 +//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT "$mat.gltf.materialClearcoat", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_FACTOR "$mat.gltf.materialClearcoat.clearcoatFactor", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_FACTOR "$mat.gltf.materialClearcoat.clearcoatRoughnessFactor", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_TEXTURE aiTextureType_UNKNOWN, 3 +//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_ROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 4 +//#define AI_MATKEY_GLTF_MATERIAL_CLEARCOAT_NORMAL_TEXTURE aiTextureType_NORMALS, 1 +//#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION "$mat.gltf.materialTransmission", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_FACTOR "$mat.gltf.materialTransmission.transmissionFactor", 0, 0 +//#define AI_MATKEY_GLTF_MATERIAL_TRANSMISSION_TEXTURE aiTextureType_UNKNOWN, 5 -#define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord" +//#define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord" #define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname" #define _AI_MATKEY_GLTF_MAPPINGID_BASE "$tex.mappingid" #define _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE "$tex.mappingfiltermag" @@ -83,7 +83,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define _AI_MATKEY_GLTF_SCALE_BASE "$tex.scale" #define _AI_MATKEY_GLTF_STRENGTH_BASE "$tex.strength" -#define AI_MATKEY_GLTF_TEXTURE_TEXCOORD(type, N) _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N +//#define AI_MATKEY_GLTF_TEXTURE_TEXCOORD(type, N) _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N #define AI_MATKEY_GLTF_MAPPINGNAME(type, N) _AI_MATKEY_GLTF_MAPPINGNAME_BASE, type, N #define AI_MATKEY_GLTF_MAPPINGID(type, N) _AI_MATKEY_GLTF_MAPPINGID_BASE, type, N #define AI_MATKEY_GLTF_MAPPINGFILTER_MAG(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE, type, N diff --git a/test/models/glTF2/ClearCoat-glTF/ClearCoatLabels.png b/test/models/glTF2/ClearCoat-glTF/ClearCoatLabels.png new file mode 100644 index 000000000..d47f2f5e1 Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/ClearCoatLabels.png differ diff --git a/test/models/glTF2/ClearCoat-glTF/ClearCoatTest.bin b/test/models/glTF2/ClearCoat-glTF/ClearCoatTest.bin new file mode 100644 index 000000000..e7c6a93a4 Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/ClearCoatTest.bin differ diff --git a/test/models/glTF2/ClearCoat-glTF/ClearCoatTest.gltf b/test/models/glTF2/ClearCoat-glTF/ClearCoatTest.gltf new file mode 100644 index 000000000..ae12bfc11 --- /dev/null +++ b/test/models/glTF2/ClearCoat-glTF/ClearCoatTest.gltf @@ -0,0 +1,1669 @@ +{ + "asset" : { + "generator" : "Khronos glTF Blender I/O v1.2.8 with hand-edits for clearcoat", + "version" : "2.0" + }, + "extensionsUsed": [ + "KHR_materials_clearcoat" + ], + "scene" : 0, + "scenes" : [ + { + "name" : "Scene", + "nodes" : [ + 3, + 7, + 11, + 15, + 19, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32 + ] + } + ], + "nodes" : [ + { + "mesh" : 0, + "name" : "BaseLayerSample", + "translation" : [ + -2.0999999046325684, + 0, + 0 + ] + }, + { + "mesh" : 1, + "name" : "ClearCoatSample" + }, + { + "mesh" : 2, + "name" : "CoatOnlySample", + "translation" : [ + 2.0999999046325684, + 0, + 0 + ] + }, + { + "children" : [ + 0, + 1, + 2 + ], + "name" : "R0_SimpleCoatTest", + "translation" : [ + 0, + 5.25, + 0 + ] + }, + { + "mesh" : 3, + "name" : "R1_BaseLayerSample", + "translation" : [ + -2.0999999046325684, + 0, + 0 + ] + }, + { + "mesh" : 4, + "name" : "R1_ClearCoatSample" + }, + { + "mesh" : 5, + "name" : "R1_CoatOnlySample", + "translation" : [ + 2.0999999046325684, + 0, + 0 + ] + }, + { + "children" : [ + 4, + 5, + 6 + ], + "name" : "R1_PartialCoatTest", + "translation" : [ + 0, + 3.1500000953674316, + 0 + ] + }, + { + "mesh" : 6, + "name" : "R2_BaseLayerSample", + "translation" : [ + -2.0999999046325684, + 0, + 0 + ] + }, + { + "mesh" : 7, + "name" : "R2_ClearCoatSample" + }, + { + "mesh" : 8, + "name" : "R2_CoatOnlySample", + "translation" : [ + 2.0999999046325684, + 0, + 0 + ] + }, + { + "children" : [ + 8, + 9, + 10 + ], + "name" : "R2_RoughnessVariations", + "translation" : [ + 0, + 1.0499999523162842, + 0 + ] + }, + { + "mesh" : 9, + "name" : "R3_BaseLayerSample", + "translation" : [ + -2.0999999046325684, + 0, + 0 + ] + }, + { + "mesh" : 10, + "name" : "R3_ClearCoatSample" + }, + { + "mesh" : 11, + "name" : "R3_CoatOnlySample", + "translation" : [ + 2.0999999046325684, + 0, + 0 + ] + }, + { + "children" : [ + 12, + 13, + 14 + ], + "name" : "R3_BaseNormals", + "translation" : [ + 0, + -1.0499999523162842, + 0 + ] + }, + { + "mesh" : 12, + "name" : "R4_BaseLayerSample", + "translation" : [ + -2.0999999046325684, + 0, + 0 + ] + }, + { + "mesh" : 13, + "name" : "R4_ClearCoatSample" + }, + { + "mesh" : 14, + "name" : "R4_CoatOnlySample", + "translation" : [ + 2.0999999046325684, + 0, + 0 + ] + }, + { + "children" : [ + 16, + 17, + 18 + ], + "name" : "R4_CoatNormals", + "translation" : [ + 0, + -5.25, + 0 + ] + }, + { + "mesh" : 15, + "name" : "R5_BaseLayerSample", + "translation" : [ + -2.0999999046325684, + 0, + 0 + ] + }, + { + "mesh" : 16, + "name" : "R5_ClearCoatSample" + }, + { + "mesh" : 17, + "name" : "R5_CoatOnlySample", + "translation" : [ + 2.0999999046325684, + 0, + 0 + ] + }, + { + "children" : [ + 20, + 21, + 22 + ], + "name" : "R5_SharedNormals", + "translation" : [ + 0, + -3.1500000953674316, + 0 + ] + }, + { + "mesh" : 18, + "name" : "X2_Label_CoatingOnly", + "translation" : [ + 2.0712804794311523, + 6.619500160217285, + 0 + ] + }, + { + "mesh" : 19, + "name" : "Y0_Label_SimpleCoating", + "translation" : [ + -5.3578033447265625, + 5.25, + 0 + ] + }, + { + "mesh" : 20, + "name" : "Y1_Label_PartialCoating", + "translation" : [ + -5.3578033447265625, + 3.1673200130462646, + 0 + ] + }, + { + "mesh" : 21, + "name" : "Y2_Label_Roughness", + "translation" : [ + -5.3578033447265625, + 1.1383899450302124, + 0 + ] + }, + { + "mesh" : 22, + "name" : "Y3_Label_BaseNormals", + "translation" : [ + -5.3578033447265625, + -1.099429965019226, + 0 + ] + }, + { + "mesh" : 23, + "name" : "Y4_Label_CoatNormals", + "translation" : [ + -5.3578033447265625, + -5.252500057220459, + 0 + ] + }, + { + "mesh" : 24, + "name" : "Y5_Label_SharedNormals", + "translation" : [ + -5.3578033447265625, + -3.1963000297546387, + 0 + ] + }, + { + "mesh" : 25, + "name" : "X0_Label_BaseLayer", + "translation" : [ + -2.087031602859497, + 6.616230010986328, + 0 + ] + }, + { + "mesh" : 26, + "name" : "X1_Label_Coated", + "translation" : [ + 0, + 6.614150047302246, + 0 + ] + } + ], + "materials" : [ + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "Simple_Base", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.5, + 0.019999999552965164, + 0.009999999776482582, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "Simple_Coated", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.5, + 0.019999999552965164, + 0.009999999776482582, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + }, + "extensions": { + "KHR_materials_clearcoat": { + "clearcoatFactor": 1, + "clearcoatRoughnessFactor": 0.03 + } + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "Simple_Coating", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.029999999329447746 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "Partial_Base", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "Partial_Coated", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + }, + "extensions": { + "KHR_materials_clearcoat": { + "clearcoatFactor": 1, + "clearcoatRoughnessFactor": 0.03, + "clearcoatTexture": { + "index": 0, + "texCoord": 0 + } + } + } + }, + { + "alphaMode" : "BLEND", + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "Partial_Coating", + "pbrMetallicRoughness" : { + "baseColorTexture" : { + "index" : 1, + "texCoord" : 0 + }, + "metallicFactor" : 0, + "roughnessFactor" : 0.029999999329447746 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "RoughVariations_Base", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.6000000238418579 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "RoughVariations_Coated", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.6000000238418579 + }, + "extensions": { + "KHR_materials_clearcoat": { + "clearcoatFactor": 1, + "clearcoatRoughnessFactor": 1, + "clearcoatRoughnessTexture": { + "index": 2, + "texCoord": 0 + } + } + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "RoughVariations_Coating", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "metallicRoughnessTexture" : { + "index" : 2, + "texCoord" : 0 + } + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "BaseNorm_Base", + "normalTexture" : { + "index" : 3, + "texCoord" : 0 + }, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "BaseNorm_Coated", + "normalTexture" : { + "index" : 4, + "texCoord" : 0 + }, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012848637998104095, + 0.021861059591174126, + 0.11068868637084961, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + }, + "extensions": { + "KHR_materials_clearcoat": { + "clearcoatFactor": 1, + "clearcoatRoughnessFactor": 0.03 + } + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "BaseNorm_Coating", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.029999999329447746 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "CoatNorm_Base", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "CoatNorm_Coated", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + }, + "extensions": { + "KHR_materials_clearcoat": { + "clearcoatFactor": 1, + "clearcoatRoughnessFactor": 0.03, + "clearcoatNormalTexture": { + "index": 5, + "texCoord": 0, + "scale": 1 + } + } + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "CoatNorm_Coating", + "normalTexture" : { + "index" : 5, + "texCoord" : 0 + }, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.029999999329447746 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "SharedNorm_Base", + "normalTexture" : { + "index" : 6, + "texCoord" : 0 + }, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "SharedNorm_Coated", + "normalTexture" : { + "index" : 7, + "texCoord" : 0 + }, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.012983020395040512, + 0.022173883393406868, + 0.10946174710988998, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.4399999976158142 + }, + "extensions": { + "KHR_materials_clearcoat": { + "clearcoatFactor": 1, + "clearcoatRoughnessFactor": 0.03, + "clearcoatNormalTexture": { + "index": 7, + "texCoord": 0 + } + } + } + }, + { + "emissiveFactor" : [ + 0, + 0, + 0 + ], + "name" : "SharedNorm_Coating", + "normalTexture" : { + "index" : 8, + "texCoord" : 0 + }, + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.029999999329447746 + } + }, + { + "emissiveFactor" : [ + 1, + 1, + 1 + ], + "emissiveTexture" : { + "index" : 9, + "texCoord" : 0 + }, + "name" : "LabelMaterial", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.8999999761581421 + } + } + ], + "meshes" : [ + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 0 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 1 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 2 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 3 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 4 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 5 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 6 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 7 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 8 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 9 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 10 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 11 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 12 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 13 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 14 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 15 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 16 + } + ] + }, + { + "name" : "ClearCoatSampleMesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 17 + } + ] + }, + { + "name" : "Labels_Mesh", + "primitives" : [ + { + "attributes" : { + "POSITION" : 4, + "NORMAL" : 5, + "TEXCOORD_0" : 6 + }, + "indices" : 7, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.001", + "primitives" : [ + { + "attributes" : { + "POSITION" : 8, + "NORMAL" : 9, + "TEXCOORD_0" : 10 + }, + "indices" : 7, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.002", + "primitives" : [ + { + "attributes" : { + "POSITION" : 11, + "NORMAL" : 12, + "TEXCOORD_0" : 13 + }, + "indices" : 14, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.003", + "primitives" : [ + { + "attributes" : { + "POSITION" : 15, + "NORMAL" : 16, + "TEXCOORD_0" : 17 + }, + "indices" : 14, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.004", + "primitives" : [ + { + "attributes" : { + "POSITION" : 18, + "NORMAL" : 19, + "TEXCOORD_0" : 20 + }, + "indices" : 14, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.005", + "primitives" : [ + { + "attributes" : { + "POSITION" : 21, + "NORMAL" : 22, + "TEXCOORD_0" : 23 + }, + "indices" : 14, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.006", + "primitives" : [ + { + "attributes" : { + "POSITION" : 24, + "NORMAL" : 25, + "TEXCOORD_0" : 26 + }, + "indices" : 14, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.007", + "primitives" : [ + { + "attributes" : { + "POSITION" : 27, + "NORMAL" : 28, + "TEXCOORD_0" : 29 + }, + "indices" : 14, + "material" : 18 + } + ] + }, + { + "name" : "Labels_Mesh.008", + "primitives" : [ + { + "attributes" : { + "POSITION" : 30, + "NORMAL" : 31, + "TEXCOORD_0" : 32 + }, + "indices" : 7, + "material" : 18 + } + ] + } + ], + "textures" : [ + { + "source" : 0 + }, + { + "source" : 1 + }, + { + "source" : 2 + }, + { + "source" : 3 + }, + { + "source" : 3 + }, + { + "source" : 4 + }, + { + "source" : 3 + }, + { + "source" : 3 + }, + { + "source" : 3 + }, + { + "source" : 5 + } + ], + "images" : [ + { + "mimeType" : "image/png", + "name" : "PartialCoating", + "uri" : "PartialCoating.png" + }, + { + "mimeType" : "image/png", + "name" : "PartialCoating_Alpha", + "uri" : "PartialCoating_Alpha.png" + }, + { + "mimeType" : "image/png", + "name" : "RoughnessStripes", + "uri" : "RoughnessStripes.png" + }, + { + "mimeType" : "image/png", + "name" : "RibsNormal", + "uri" : "RibsNormal.png" + }, + { + "mimeType" : "image/jpeg", + "name" : "PlasticWrap_normals", + "uri" : "PlasticWrap_normals.jpg" + }, + { + "mimeType" : "image/png", + "name" : "ClearCoatLabels", + "uri" : "ClearCoatLabels.png" + } + ], + "accessors" : [ + { + "bufferView" : 0, + "componentType" : 5126, + "count" : 1113, + "max" : [ + 1, + 1, + 1.0499999523162842 + ], + "min" : [ + -1, + -1, + -0.06000000983476639 + ], + "type" : "VEC3" + }, + { + "bufferView" : 1, + "componentType" : 5126, + "count" : 1113, + "type" : "VEC3" + }, + { + "bufferView" : 2, + "componentType" : 5126, + "count" : 1113, + "type" : "VEC2" + }, + { + "bufferView" : 3, + "componentType" : 5123, + "count" : 6180, + "type" : "SCALAR" + }, + { + "bufferView" : 4, + "componentType" : 5126, + "count" : 8, + "max" : [ + 1.0280373096466064, + 0.23501670360565186, + 3.8289083903464416e-08 + ], + "min" : [ + -0.968224287033081, + -0.2350165843963623, + -0.010000125505030155 + ], + "type" : "VEC3" + }, + { + "bufferView" : 5, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 6, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 7, + "componentType" : 5123, + "count" : 12, + "type" : "SCALAR" + }, + { + "bufferView" : 8, + "componentType" : 5126, + "count" : 8, + "max" : [ + 2, + 0.23026323318481445, + 3.751463495405005e-08 + ], + "min" : [ + -2, + -0.23026317358016968, + -0.010000579059123993 + ], + "type" : "VEC3" + }, + { + "bufferView" : 9, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 10, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 11, + "componentType" : 5126, + "count" : 8, + "max" : [ + 2, + 0.2302631139755249, + 3.7514624295909016e-08 + ], + "min" : [ + -2, + -0.23026323318481445, + -0.010000428184866905 + ], + "type" : "VEC3" + }, + { + "bufferView" : 12, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 13, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 14, + "componentType" : 5123, + "count" : 12, + "type" : "SCALAR" + }, + { + "bufferView" : 15, + "componentType" : 5126, + "count" : 8, + "max" : [ + 2, + 0.22039484977722168, + 3.590687924770464e-08 + ], + "min" : [ + -2, + -0.22039473056793213, + -0.010000280104577541 + ], + "type" : "VEC3" + }, + { + "bufferView" : 16, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 17, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 18, + "componentType" : 5126, + "count" : 8, + "max" : [ + 2, + 0.21764808893203735, + 3.545937588000925e-08 + ], + "min" : [ + -2, + -0.21764802932739258, + -0.010000137612223625 + ], + "type" : "VEC3" + }, + { + "bufferView" : 19, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 20, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 21, + "componentType" : 5126, + "count" : 8, + "max" : [ + 2, + 0.20775499939918518, + 3.3847587843638394e-08 + ], + "min" : [ + -2, + -0.20775499939918518, + -0.009999996051192284 + ], + "type" : "VEC3" + }, + { + "bufferView" : 22, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 23, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 24, + "componentType" : 5126, + "count" : 8, + "max" : [ + 2, + 0.22341907024383545, + 3.6399587344249085e-08 + ], + "min" : [ + -2, + -0.22341907024383545, + -0.009999859146773815 + ], + "type" : "VEC3" + }, + { + "bufferView" : 25, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 26, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 27, + "componentType" : 5126, + "count" : 8, + "max" : [ + 0.9169960618019104, + 0.22670458257198334, + 3.69348676088066e-08 + ], + "min" : [ + -0.9199233651161194, + -0.22670456767082214, + -0.010000176727771759 + ], + "type" : "VEC3" + }, + { + "bufferView" : 28, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 29, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + }, + { + "bufferView" : 30, + "componentType" : 5126, + "count" : 8, + "max" : [ + 0.8968609571456909, + 0.20853587985038757, + 3.397480696776256e-08 + ], + "min" : [ + -0.9147982001304626, + -0.2085357904434204, + -0.010000113397836685 + ], + "type" : "VEC3" + }, + { + "bufferView" : 31, + "componentType" : 5126, + "count" : 8, + "type" : "VEC3" + }, + { + "bufferView" : 32, + "componentType" : 5126, + "count" : 8, + "type" : "VEC2" + } + ], + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 13356, + "byteOffset" : 0 + }, + { + "buffer" : 0, + "byteLength" : 13356, + "byteOffset" : 13356 + }, + { + "buffer" : 0, + "byteLength" : 8904, + "byteOffset" : 26712 + }, + { + "buffer" : 0, + "byteLength" : 12360, + "byteOffset" : 35616 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 47976 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48072 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 48168 + }, + { + "buffer" : 0, + "byteLength" : 24, + "byteOffset" : 48232 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48256 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48352 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 48448 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48512 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48608 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 48704 + }, + { + "buffer" : 0, + "byteLength" : 24, + "byteOffset" : 48768 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48792 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 48888 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 48984 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49048 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49144 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 49240 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49304 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49400 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 49496 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49560 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49656 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 49752 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49816 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 49912 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 50008 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 50072 + }, + { + "buffer" : 0, + "byteLength" : 96, + "byteOffset" : 50168 + }, + { + "buffer" : 0, + "byteLength" : 64, + "byteOffset" : 50264 + } + ], + "buffers" : [ + { + "byteLength" : 50328, + "uri" : "ClearCoatTest.bin" + } + ] +} diff --git a/test/models/glTF2/ClearCoat-glTF/PartialCoating.png b/test/models/glTF2/ClearCoat-glTF/PartialCoating.png new file mode 100644 index 000000000..d579bbebb Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/PartialCoating.png differ diff --git a/test/models/glTF2/ClearCoat-glTF/PartialCoating_Alpha.png b/test/models/glTF2/ClearCoat-glTF/PartialCoating_Alpha.png new file mode 100644 index 000000000..b1911d9f0 Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/PartialCoating_Alpha.png differ diff --git a/test/models/glTF2/ClearCoat-glTF/PlasticWrap_normals.jpg b/test/models/glTF2/ClearCoat-glTF/PlasticWrap_normals.jpg new file mode 100644 index 000000000..73e6260ef Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/PlasticWrap_normals.jpg differ diff --git a/test/models/glTF2/ClearCoat-glTF/RibsNormal.png b/test/models/glTF2/ClearCoat-glTF/RibsNormal.png new file mode 100644 index 000000000..30c393dd7 Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/RibsNormal.png differ diff --git a/test/models/glTF2/ClearCoat-glTF/RoughnessStripes.png b/test/models/glTF2/ClearCoat-glTF/RoughnessStripes.png new file mode 100644 index 000000000..f3ab3570f Binary files /dev/null and b/test/models/glTF2/ClearCoat-glTF/RoughnessStripes.png differ diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp index 4110edcfc..2c000bb37 100644 --- a/test/unit/utglTF2ImportExport.cpp +++ b/test/unit/utglTF2ImportExport.cpp @@ -57,10 +57,9 @@ using namespace Assimp; class utglTF2ImportExport : public AbstractImportExportBase { public: - virtual bool importerTest() { + virtual bool importerMatTest(const char *file, bool spec_gloss, std::array exp_modes = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap }) { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", - aiProcess_ValidateDataStructure); + const aiScene *scene = importer.ReadFile(file, aiProcess_ValidateDataStructure); EXPECT_NE(scene, nullptr); if (!scene) { return false; @@ -72,13 +71,49 @@ public: } const aiMaterial *material = scene->mMaterials[0]; + // This Material should be a PBR + aiShadingMode shadingMode; + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_SHADING_MODEL, shadingMode)); + EXPECT_EQ(aiShadingMode_PBR_BRDF, shadingMode); + + // Should import the texture as diffuse and as base color aiString path; - aiTextureMapMode modes[2]; + std::array modes; EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, - nullptr, nullptr, modes)); + nullptr, nullptr, modes.data())); EXPECT_STREQ(path.C_Str(), "CesiumLogoFlat.png"); - EXPECT_EQ(modes[0], aiTextureMapMode_Mirror); - EXPECT_EQ(modes[1], aiTextureMapMode_Clamp); + EXPECT_EQ(exp_modes, modes); + + // Also as Base Color + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_BASE_COLOR, 0, &path, nullptr, nullptr, + nullptr, nullptr, modes.data())); + EXPECT_STREQ(path.C_Str(), "CesiumLogoFlat.png"); + EXPECT_EQ(exp_modes, modes); + + // Should have a MetallicFactor (default is 1.0) + ai_real metal_factor = ai_real(0.5); + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_METALLIC_FACTOR, metal_factor)); + EXPECT_EQ(ai_real(0.0), metal_factor); + + // And a roughness factor (default is 1.0) + ai_real roughness_factor = ai_real(0.5); + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_ROUGHNESS_FACTOR, roughness_factor)); + EXPECT_EQ(ai_real(1.0), roughness_factor); + + aiColor3D spec_color = { 0, 0, 0 }; + ai_real glossiness = ai_real(0.5); + if (spec_gloss) { + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_COLOR_SPECULAR, spec_color)); + constexpr ai_real spec_val(0.20000000298023225); // From the file + EXPECT_EQ(spec_val, spec_color.r); + EXPECT_EQ(spec_val, spec_color.g); + EXPECT_EQ(spec_val, spec_color.b); + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_GLOSSINESS_FACTOR, glossiness)); + EXPECT_EQ(ai_real(1.0), glossiness); + } else { + EXPECT_EQ(aiReturn_FAILURE, material->Get(AI_MATKEY_COLOR_SPECULAR, spec_color)); + EXPECT_EQ(aiReturn_FAILURE, material->Get(AI_MATKEY_GLOSSINESS_FACTOR, glossiness)); + } return true; } @@ -105,14 +140,89 @@ public: }; TEST_F(utglTF2ImportExport, importglTF2FromFileTest) { - EXPECT_TRUE(importerTest()); + EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", false, {aiTextureMapMode_Mirror, aiTextureMapMode_Clamp})); } TEST_F(utglTF2ImportExport, importBinaryglTF2FromFileTest) { EXPECT_TRUE(binaryImporterTest()); } +TEST_F(utglTF2ImportExport, importglTF2_KHR_materials_pbrSpecularGlossiness) { + EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf", true)); +} + +void VerifyClearCoatScene(const aiScene *scene) { + ASSERT_NE(nullptr, scene); + + ASSERT_TRUE(scene->HasMaterials()); + + // Find a specific Clearcoat material and check the values + const aiString partial_coated("Partial_Coated"); + bool found_partial_coat = false; + for (size_t i = 0; i < scene->mNumMaterials; ++i) { + const aiMaterial *material = scene->mMaterials[i]; + ASSERT_NE(nullptr, material); + if (material->GetName() == partial_coated) { + found_partial_coat = true; + + ai_real clearcoat_factor(0.0f); + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_CLEARCOAT_FACTOR, clearcoat_factor)); + EXPECT_EQ(ai_real(1.0f), clearcoat_factor); + + ai_real clearcoat_rough_factor(0.0f); + EXPECT_EQ(aiReturn_SUCCESS, material->Get(AI_MATKEY_CLEARCOAT_ROUGHNESS_FACTOR, clearcoat_rough_factor)); + EXPECT_EQ(ai_real(0.03f), clearcoat_rough_factor); + + // Should import the texture as diffuse and as base color + aiString path; + std::array modes; + static const std::array exp_modes = { aiTextureMapMode_Wrap, aiTextureMapMode_Wrap }; + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_CLEARCOAT_TEXTURE, &path, nullptr, nullptr, + nullptr, nullptr, modes.data())); + EXPECT_STREQ(path.C_Str(), "PartialCoating.png"); + EXPECT_EQ(exp_modes, modes); + } + } + EXPECT_TRUE(found_partial_coat); +} + +TEST_F(utglTF2ImportExport, importglTF2_KHR_materials_clearcoat) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/ClearCoat-glTF/ClearCoatTest.gltf", aiProcess_ValidateDataStructure); + VerifyClearCoatScene(scene); +} + #ifndef ASSIMP_BUILD_NO_EXPORT + +TEST_F(utglTF2ImportExport, importglTF2AndExport_KHR_materials_clearcoat) { + { + Assimp::Importer importer; + Assimp::Exporter exporter; + const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/ClearCoat-glTF/ClearCoatTest.gltf", aiProcess_ValidateDataStructure); + ASSERT_NE(nullptr, scene); + // Export + EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/ClearCoat-glTF/ClearCoatTest_out.glb")); + } + + // And re-import + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/ClearCoat-glTF/ClearCoatTest_out.glb", aiProcess_ValidateDataStructure); + VerifyClearCoatScene(scene); +} + +TEST_F(utglTF2ImportExport, importglTF2AndExport_KHR_materials_pbrSpecularGlossiness) { + Assimp::Importer importer; + Assimp::Exporter exporter; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf", + aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); + // Export + EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb")); + + // And re-import + EXPECT_TRUE(importerMatTest(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured_out.glb", true)); +} + TEST_F(utglTF2ImportExport, importglTF2AndExportToOBJ) { Assimp::Importer importer; Assimp::Exporter exporter; @@ -130,6 +240,7 @@ TEST_F(utglTF2ImportExport, importglTF2EmbeddedAndExportToOBJ) { EXPECT_NE(nullptr, scene); EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "obj", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF-Embedded/BoxTextured_out.obj")); } + #endif // ASSIMP_BUILD_NO_EXPORT TEST_F(utglTF2ImportExport, importglTF2PrimitiveModePointsWithoutIndices) { @@ -492,32 +603,58 @@ TEST_F(utglTF2ImportExport, sceneMetadata) { } TEST_F(utglTF2ImportExport, texcoords) { + Assimp::Importer importer; - const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", - aiProcess_ValidateDataStructure); + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", aiProcess_ValidateDataStructure); + ASSERT_NE(scene, nullptr); + ASSERT_TRUE(scene->HasMaterials()); + const aiMaterial *material = scene->mMaterials[0]; + + aiString path; + unsigned int uvIndex = 255; + aiTextureMapMode modes[2]; + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_BASE_COLOR_TEXTURE, &path, nullptr, &uvIndex, nullptr, nullptr, modes)); + EXPECT_STREQ(path.C_Str(), "texture.png"); + EXPECT_EQ(uvIndex, 0); + + uvIndex = 255; + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE, &path, nullptr, &uvIndex, nullptr, nullptr, modes)); + EXPECT_STREQ(path.C_Str(), "texture.png"); + EXPECT_EQ(uvIndex, 1); +} + +#ifndef ASSIMP_BUILD_NO_EXPORT + +TEST_F(utglTF2ImportExport, texcoords_export) { + { + Assimp::Importer importer; + Assimp::Exporter exporter; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", aiProcess_ValidateDataStructure); + ASSERT_NE(scene, nullptr); + ASSERT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "glb2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf_out.glb")); + } + + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTexcoords-glTF/boxTexcoords.gltf", aiProcess_ValidateDataStructure); ASSERT_NE(scene, nullptr); ASSERT_TRUE(scene->HasMaterials()); const aiMaterial *material = scene->mMaterials[0]; aiString path; + unsigned int uvIndex = 255; aiTextureMapMode modes[2]; - EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, - nullptr, nullptr, modes)); + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_BASE_COLOR_TEXTURE, &path, nullptr, &uvIndex, nullptr, nullptr, modes)); EXPECT_STREQ(path.C_Str(), "texture.png"); - - int uvIndex = -1; - EXPECT_EQ(aiGetMaterialInteger(material, AI_MATKEY_GLTF_TEXTURE_TEXCOORD(aiTextureType_DIFFUSE, 0), &uvIndex), aiReturn_SUCCESS); EXPECT_EQ(uvIndex, 0); - // Using manual macro expansion of AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE here. - // The following works with some but not all compilers: - // #define APPLY(X, Y) X(Y) - // ..., APPLY(AI_MATKEY_GLTF_TEXTURE_TEXCOORD, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE), ... - EXPECT_EQ(aiGetMaterialInteger(material, AI_MATKEY_GLTF_TEXTURE_TEXCOORD(aiTextureType_UNKNOWN, 0), &uvIndex), aiReturn_SUCCESS); + uvIndex = 255; + EXPECT_EQ(aiReturn_SUCCESS, material->GetTexture(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE, &path, nullptr, &uvIndex, nullptr, nullptr, modes)); + EXPECT_STREQ(path.C_Str(), "texture.png"); EXPECT_EQ(uvIndex, 1); } +#endif // ASSIMP_BUILD_NO_EXPORT TEST_F(utglTF2ImportExport, recursive_nodes) { Assimp::Importer importer; const aiScene* scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/glTF2/RecursiveNodes/RecursiveNodes.gltf", aiProcess_ValidateDataStructure);