From caec8fe38a460101b1611afec7a6b0a4c93d0b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Mon, 28 Jun 2021 14:34:57 +0800 Subject: [PATCH] Release 1.0.0-alpha.21; Better UV channel get (#44) --- Core/Source/bee/Convert/FbxMeshVertexLayout.h | 7 +- .../bee/Convert/SceneConverter.Material.cpp | 29 ++--- .../bee/Convert/SceneConverter.Mesh.cpp | 13 +- .../bee/Convert/SceneConverter.Texture.cpp | 113 +++++++++--------- Core/Source/bee/Convert/SceneConverter.h | 36 +++++- 5 files changed, 117 insertions(+), 81 deletions(-) diff --git a/Core/Source/bee/Convert/FbxMeshVertexLayout.h b/Core/Source/bee/Convert/FbxMeshVertexLayout.h index bc5a1b5..d2f5d04 100644 --- a/Core/Source/bee/Convert/FbxMeshVertexLayout.h +++ b/Core/Source/bee/Convert/FbxMeshVertexLayout.h @@ -1,10 +1,11 @@ #pragma once -#include -#include #include #include +#include +#include +#include #include namespace bee { @@ -57,5 +58,7 @@ struct FbxMeshVertexLayout { }; std::vector shapes; + + std::unordered_map uv_channel_index_map; }; } // namespace bee \ No newline at end of file diff --git a/Core/Source/bee/Convert/SceneConverter.Material.cpp b/Core/Source/bee/Convert/SceneConverter.Material.cpp index e5d9a54..e1a13ab 100644 --- a/Core/Source/bee/Convert/SceneConverter.Material.cpp +++ b/Core/Source/bee/Convert/SceneConverter.Material.cpp @@ -345,8 +345,8 @@ std::optional SceneConverter::_convertLambertMaterial( std::array transparentColor = {1.0f, 1.0f, 1.0f}; { const auto fbxTransparencyFactor = fbx_material_.TransparencyFactor.Get(); - if (const auto glTFOpacityTextureIndex = - _convertTextureProperty(fbx_material_.TransparentColor)) { + if (const auto glTFOpacityTextureIndex = _convertTextureProperty( + fbx_material_.TransparentColor, material_usage_.texture_context)) { forbidTextureProperty(u8"Transparent color"); } else { const auto fbxTransparentColor = fbx_material_.TransparentColor.Get(); @@ -370,8 +370,8 @@ std::optional SceneConverter::_convertLambertMaterial( glTFPbrMetallicRoughness.baseColorFactor[i] = static_cast(diffuseFactor); } - if (const auto glTFDiffuseTexture = - _convertTextureProperty(fbx_material_.Diffuse)) { + if (const auto glTFDiffuseTexture = _convertTextureProperty( + fbx_material_.Diffuse, material_usage_.texture_context)) { glTFPbrMetallicRoughness.baseColorTexture = *glTFDiffuseTexture; } else { const auto fbxDiffuseColor = fbx_material_.Diffuse.Get(); @@ -384,22 +384,22 @@ std::optional SceneConverter::_convertLambertMaterial( } // Normal map - if (const auto glTFNormalMap = - _convertTexturePropertyAsNormalTexture(fbx_material_.NormalMap)) { + if (const auto glTFNormalMap = _convertTexturePropertyAsNormalTexture( + fbx_material_.NormalMap, material_usage_.texture_context)) { glTFMaterial.normalTexture = *glTFNormalMap; } // Bump map - if (const auto glTFBumpMap = - _convertTexturePropertyAsNormalTexture(fbx_material_.Bump)) { + if (const auto glTFBumpMap = _convertTexturePropertyAsNormalTexture( + fbx_material_.Bump, material_usage_.texture_context)) { glTFMaterial.normalTexture = *glTFBumpMap; } // Emissive { const auto emissiveFactor = fbx_material_.EmissiveFactor.Get(); - if (const auto glTFEmissiveTexture = - _convertTextureProperty(fbx_material_.Emissive)) { + if (const auto glTFEmissiveTexture = _convertTextureProperty( + fbx_material_.Emissive, material_usage_.texture_context)) { glTFMaterial.emissiveTexture = *glTFEmissiveTexture; for (int i = 0; i < 3; ++i) { glTFMaterial.emissiveFactor[i] = static_cast(emissiveFactor); @@ -487,15 +487,15 @@ SceneConverter::_convertStanardMaterialProperties( // Normal map if (standardProperties.normal_map) { if (const auto glTFNormalMap = _convertFileTextureAsNormalTexture( - *standardProperties.normal_map)) { + *standardProperties.normal_map, material_usage_.texture_context)) { glTFMaterial.normalTexture = *glTFNormalMap; } } // Bump map if (standardProperties.bump) { - if (const auto glTFBumpMap = - _convertFileTextureAsNormalTexture(*standardProperties.bump)) { + if (const auto glTFBumpMap = _convertFileTextureAsNormalTexture( + *standardProperties.bump, material_usage_.texture_context)) { glTFMaterial.normalTexture = *glTFBumpMap; } } @@ -567,7 +567,8 @@ std::optional SceneConverter::_convertUnknownMaterial( const auto fbxFileTexture = fbx_property_.GetSrcObject(); if (fbxFileTexture) { - const auto glTFTexture = _convertFileTextureShared(*fbxFileTexture); + const auto glTFTexture = _convertFileTextureShared( + *fbxFileTexture, material_usage_.texture_context); if (glTFTexture) { return *glTFTexture; } else { diff --git a/Core/Source/bee/Convert/SceneConverter.Mesh.cpp b/Core/Source/bee/Convert/SceneConverter.Mesh.cpp index 5f6972b..0f46806 100644 --- a/Core/Source/bee/Convert/SceneConverter.Mesh.cpp +++ b/Core/Source/bee/Convert/SceneConverter.Mesh.cpp @@ -161,8 +161,11 @@ fx::gltf::Primitive SceneConverter::_convertMeshAsPrimitive( std::span fbx_shapes_, std::span skin_influence_channels_, MaterialUsage &material_usage_) { - auto vertexLayout = + const auto vertexLayout = _getFbxMeshVertexLayout(fbx_mesh_, fbx_shapes_, skin_influence_channels_); + material_usage_.texture_context.channel_index_map = + vertexLayout.uv_channel_index_map; + const auto vertexSize = vertexLayout.size; using UniqueVertexIndex = std::uint32_t; @@ -357,9 +360,13 @@ FbxMeshVertexLayout SceneConverter::_getFbxMeshVertexLayout( vertexLaytout.uvs.resize(nUVElements); for (decltype(nUVElements) iUVElement = 0; iUVElement < nUVElements; ++iUVElement) { + const auto &elementUV = *fbx_mesh_.GetElementUV(iUVElement); + const std::string_view name = elementUV.GetName(); + if (!name.empty()) { + vertexLaytout.uv_channel_index_map.emplace(name, iUVElement); + } vertexLaytout.uvs[iUVElement] = { - vertexLaytout.size, - makeFbxLayerElementAccessor(*fbx_mesh_.GetElementUV(iUVElement))}; + vertexLaytout.size, makeFbxLayerElementAccessor(elementUV)}; vertexLaytout.size += sizeof(NeutralUVComponent) * 2; } } diff --git a/Core/Source/bee/Convert/SceneConverter.Texture.cpp b/Core/Source/bee/Convert/SceneConverter.Texture.cpp index 77327e0..d92557b 100644 --- a/Core/Source/bee/Convert/SceneConverter.Texture.cpp +++ b/Core/Source/bee/Convert/SceneConverter.Texture.cpp @@ -21,13 +21,6 @@ glm_fbx_vec3 fbx_to_glm(const fbxsdk::FbxDouble3 &v_) { return {v_[0], v_[1], v_[2]}; } -std::regex adsk_3ds_max_uv_set_name_regex{R"(UVChannel_(\d+))", - std::regex_constants::ECMAScript}; - -// https://community.esri.com/t5/arcgis-cityengine-questions/city-engine-does-not-quot-read-quot-multiple-uvset-from-collada/td-p/433179 -std::regex maya_uv_set_name_regex{R"(map(\d+))", - std::regex_constants::ECMAScript}; - glm_fbx_mat4 compute_fbx_texture_transform(glm_fbx_vec3 pivot_center_, glm_fbx_vec3 offset_, glm_fbx_quat rotation_, @@ -65,11 +58,13 @@ glm_fbx_mat4 compute_fbx_texture_transform(glm_fbx_vec3 pivot_center_, namespace bee { std::optional -SceneConverter::_convertTextureProperty(fbxsdk::FbxProperty &fbx_property_) { +SceneConverter::_convertTextureProperty( + fbxsdk::FbxProperty &fbx_property_, + const TextureContext &texture_context_) { const auto fbxFileTexture = fbx_property_.GetSrcObject(); if (fbxFileTexture) { - return _convertFileTextureShared(*fbxFileTexture); + return _convertFileTextureShared(*fbxFileTexture, texture_context_); } else { const auto fbxTexture = fbx_property_.GetSrcObject(); if (fbxTexture) { @@ -82,56 +77,35 @@ SceneConverter::_convertTextureProperty(fbxsdk::FbxProperty &fbx_property_) { std::optional SceneConverter::_convertFileTextureShared( - fbxsdk::FbxFileTexture &fbx_file_texture_) { - auto fbxTextureId = fbx_file_texture_.GetUniqueID(); - if (auto r = _textureMap.find(fbxTextureId); r != _textureMap.end()) { - return r->second; - } else { - auto glTFTextureIndex = _convertFileTexture(fbx_file_texture_); - if (!glTFTextureIndex) { - _textureMap.emplace(fbxTextureId, std::nullopt); - return std::nullopt; + fbxsdk::FbxFileTexture &fbx_file_texture_, + const TextureContext &texture_context_) { + auto materialTexture = [&]() -> std::optional { + auto fbxTextureId = fbx_file_texture_.GetUniqueID(); + if (auto r = _textureMap.find(fbxTextureId); r != _textureMap.end()) { + return r->second; } else { - fx::gltf::Material::Texture materialTexture; - materialTexture.index = *glTFTextureIndex; - - const auto fbxUVSet = fbx_file_texture_.UVSet.Get(); - if (fbxUVSet.IsEmpty() || fbxUVSet == "default") { - materialTexture.texCoord = 0; + auto glTFTextureIndex = _convertFileTexture(fbx_file_texture_); + if (!glTFTextureIndex) { + _textureMap.emplace(fbxTextureId, std::nullopt); + return std::nullopt; } else { - bool matched = false; - - for (const auto ®ex : - {adsk_3ds_max_uv_set_name_regex, maya_uv_set_name_regex}) { - if (std::cmatch matches; std::regex_match( - static_cast(fbxUVSet), matches, regex)) { - const auto set = std::stoi(matches[1]); - // Counting from 1.. - materialTexture.texCoord = static_cast(set - 1); - _log(Logger::Level::verbose, - fmt::format("Recognized texture {}'s uv set {} as {}-th.", - fbx_file_texture_.GetName(), - static_cast(fbxUVSet), - materialTexture.texCoord)); - matched = true; - break; - } - } + fx::gltf::Material::Texture materialTexture; + materialTexture.index = *glTFTextureIndex; - if (!matched) { - _log(Logger::Level::error, - fmt::format("Texture {} specified an unrecognized uv set {}", - fbx_file_texture_.GetName(), - static_cast(fbxUVSet))); - } - } + _convertTextureUVTransform(fbx_file_texture_, materialTexture); - _convertTextureUVTransform(fbx_file_texture_, materialTexture); - - _textureMap.emplace(fbxTextureId, materialTexture); - return materialTexture; + _textureMap.emplace(fbxTextureId, materialTexture); + return materialTexture; + } } + }(); + + if (materialTexture) { + const auto uvIndex = _findUVIndex(fbx_file_texture_, texture_context_); + materialTexture->texCoord = static_cast(uvIndex); } + + return materialTexture; } std::optional SceneConverter::_convertFileTexture( @@ -156,8 +130,10 @@ std::optional SceneConverter::_convertFileTexture( std::optional SceneConverter::_convertTexturePropertyAsNormalTexture( - fbxsdk::FbxProperty &fbx_property_) { - const auto materialTexture = _convertTextureProperty(fbx_property_); + fbxsdk::FbxProperty &fbx_property_, + const TextureContext &texture_context_) { + const auto materialTexture = + _convertTextureProperty(fbx_property_, texture_context_); if (!materialTexture) { return std::nullopt; } @@ -168,8 +144,10 @@ SceneConverter::_convertTexturePropertyAsNormalTexture( std::optional SceneConverter::_convertFileTextureAsNormalTexture( - fbxsdk::FbxFileTexture &fbx_file_texture_) { - const auto materialTexture = _convertFileTextureShared(fbx_file_texture_); + fbxsdk::FbxFileTexture &fbx_file_texture_, + const TextureContext &texture_context_) { + const auto materialTexture = + _convertFileTextureShared(fbx_file_texture_, texture_context_); if (!materialTexture) { return std::nullopt; } @@ -178,6 +156,27 @@ SceneConverter::_convertFileTextureAsNormalTexture( return normalTexture; } +std::uint32_t +SceneConverter::_findUVIndex(const fbxsdk::FbxTexture &fbx_texture_, + const TextureContext &texture_context_) { + const auto fbxUVSet = fbx_texture_.UVSet.Get(); + if (fbxUVSet.IsEmpty() || fbxUVSet == "default") { + return 0; + } + + if (const auto rIndex = texture_context_.channel_index_map.find( + std::string{fbxUVSet.operator const char *()}); + rIndex != texture_context_.channel_index_map.end()) { + return rIndex->second; + } + + _log(Logger::Level::warning, + fmt::format("Texture {} specified an unrecognized uv set {}", + fbx_texture_.GetName(), + static_cast(fbxUVSet))); + return 0; +} + void SceneConverter::_convertTextureUVTransform( const fbxsdk::FbxTexture &fbx_texture_, fx::gltf::Material::Texture &glTF_texture_info_) { diff --git a/Core/Source/bee/Convert/SceneConverter.h b/Core/Source/bee/Convert/SceneConverter.h index 6db079b..f01301b 100644 --- a/Core/Source/bee/Convert/SceneConverter.h +++ b/Core/Source/bee/Convert/SceneConverter.h @@ -177,11 +177,29 @@ class SceneConverter { std::vector values; }; + struct TextureContext { + std::unordered_map channel_index_map; + + bool compatible_with(const TextureContext &that_) const { + const auto &lhs = this->channel_index_map; + const auto &rhs = that_.channel_index_map; + for (const auto &[k, v] : lhs) { + if (const auto r = rhs.find(k); r != rhs.end() && r->second != v) { + return false; + } + } + return true; + } + }; + struct MaterialUsage { bool hasTransparentVertex = false; + TextureContext texture_context; + bool operator==(const MaterialUsage &that_) const { - return this->hasTransparentVertex == that_.hasTransparentVertex; + return this->hasTransparentVertex == that_.hasTransparentVertex && + this->texture_context.compatible_with(that_.texture_context); } }; @@ -357,19 +375,27 @@ class SceneConverter { const MaterialUsage &material_usage_); std::optional - _convertTextureProperty(fbxsdk::FbxProperty &fbx_property_); + _convertTextureProperty(fbxsdk::FbxProperty &fbx_property_, + const TextureContext &texture_context_); std::optional - _convertFileTextureShared(fbxsdk::FbxFileTexture &fbx_file_texture_); + _convertFileTextureShared(fbxsdk::FbxFileTexture &fbx_file_texture_, + const TextureContext &texture_context_); std::optional _convertFileTexture(const fbxsdk::FbxFileTexture &fbx_texture_); std::optional - _convertTexturePropertyAsNormalTexture(fbxsdk::FbxProperty &fbx_property_); + _convertTexturePropertyAsNormalTexture( + fbxsdk::FbxProperty &fbx_property_, + const TextureContext &texture_context_); std::optional - _convertFileTextureAsNormalTexture(fbxsdk::FbxFileTexture &fbx_file_texture_); + _convertFileTextureAsNormalTexture(fbxsdk::FbxFileTexture &fbx_file_texture_, + const TextureContext &texture_context_); + + std::uint32_t _findUVIndex(const fbxsdk::FbxTexture &fbx_texture_, + const TextureContext &texture_context_); void _convertTextureUVTransform(const fbxsdk::FbxTexture &fbx_texture_,