Skip to content

Commit

Permalink
Release 1.0.0-alpha.21; Better UV channel get (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
shrinktofit authored Jun 28, 2021
1 parent 44ef92f commit caec8fe
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 81 deletions.
7 changes: 5 additions & 2 deletions Core/Source/bee/Convert/FbxMeshVertexLayout.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@

#pragma once

#include <cstdint>
#include <optional>
#include <bee/Convert/NeutralType.h>
#include <bee/Convert/fbxsdk/LayerelementAccessor.h>
#include <cstdint>
#include <optional>
#include <unordered_map>
#include <vector>

namespace bee {
Expand Down Expand Up @@ -57,5 +58,7 @@ struct FbxMeshVertexLayout {
};

std::vector<ShapeLayout> shapes;

std::unordered_map<std::string, std::uint32_t> uv_channel_index_map;
};
} // namespace bee
29 changes: 15 additions & 14 deletions Core/Source/bee/Convert/SceneConverter.Material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,8 @@ std::optional<GLTFBuilder::XXIndex> SceneConverter::_convertLambertMaterial(
std::array<float, 3> 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();
Expand All @@ -370,8 +370,8 @@ std::optional<GLTFBuilder::XXIndex> SceneConverter::_convertLambertMaterial(
glTFPbrMetallicRoughness.baseColorFactor[i] =
static_cast<float>(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();
Expand All @@ -384,22 +384,22 @@ std::optional<GLTFBuilder::XXIndex> 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<float>(emissiveFactor);
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -567,7 +567,8 @@ std::optional<GLTFBuilder::XXIndex> SceneConverter::_convertUnknownMaterial(
const auto fbxFileTexture =
fbx_property_.GetSrcObject<fbxsdk::FbxFileTexture>();
if (fbxFileTexture) {
const auto glTFTexture = _convertFileTextureShared(*fbxFileTexture);
const auto glTFTexture = _convertFileTextureShared(
*fbxFileTexture, material_usage_.texture_context);
if (glTFTexture) {
return *glTFTexture;
} else {
Expand Down
13 changes: 10 additions & 3 deletions Core/Source/bee/Convert/SceneConverter.Mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,11 @@ fx::gltf::Primitive SceneConverter::_convertMeshAsPrimitive(
std::span<fbxsdk::FbxShape *> fbx_shapes_,
std::span<MeshSkinData::InfluenceChannel> 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;
Expand Down Expand Up @@ -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;
}
}
Expand Down
113 changes: 56 additions & 57 deletions Core/Source/bee/Convert/SceneConverter.Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_,
Expand Down Expand Up @@ -65,11 +58,13 @@ glm_fbx_mat4 compute_fbx_texture_transform(glm_fbx_vec3 pivot_center_,

namespace bee {
std::optional<fx::gltf::Material::Texture>
SceneConverter::_convertTextureProperty(fbxsdk::FbxProperty &fbx_property_) {
SceneConverter::_convertTextureProperty(
fbxsdk::FbxProperty &fbx_property_,
const TextureContext &texture_context_) {
const auto fbxFileTexture =
fbx_property_.GetSrcObject<fbxsdk::FbxFileTexture>();
if (fbxFileTexture) {
return _convertFileTextureShared(*fbxFileTexture);
return _convertFileTextureShared(*fbxFileTexture, texture_context_);
} else {
const auto fbxTexture = fbx_property_.GetSrcObject<fbxsdk::FbxTexture>();
if (fbxTexture) {
Expand All @@ -82,56 +77,35 @@ SceneConverter::_convertTextureProperty(fbxsdk::FbxProperty &fbx_property_) {

std::optional<fx::gltf::Material::Texture>
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<fx::gltf::Material::Texture> {
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 &regex :
{adsk_3ds_max_uv_set_name_regex, maya_uv_set_name_regex}) {
if (std::cmatch matches; std::regex_match(
static_cast<const char *>(fbxUVSet), matches, regex)) {
const auto set = std::stoi(matches[1]);
// Counting from 1..
materialTexture.texCoord = static_cast<std::int32_t>(set - 1);
_log(Logger::Level::verbose,
fmt::format("Recognized texture {}'s uv set {} as {}-th.",
fbx_file_texture_.GetName(),
static_cast<const char *>(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<const char *>(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<std::int32_t>(uvIndex);
}

return materialTexture;
}

std::optional<GLTFBuilder::XXIndex> SceneConverter::_convertFileTexture(
Expand All @@ -156,8 +130,10 @@ std::optional<GLTFBuilder::XXIndex> SceneConverter::_convertFileTexture(

std::optional<fx::gltf::Material::NormalTexture>
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;
}
Expand All @@ -168,8 +144,10 @@ SceneConverter::_convertTexturePropertyAsNormalTexture(

std::optional<fx::gltf::Material::NormalTexture>
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;
}
Expand All @@ -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<const char *>(fbxUVSet)));
return 0;
}

void SceneConverter::_convertTextureUVTransform(
const fbxsdk::FbxTexture &fbx_texture_,
fx::gltf::Material::Texture &glTF_texture_info_) {
Expand Down
36 changes: 31 additions & 5 deletions Core/Source/bee/Convert/SceneConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,29 @@ class SceneConverter {
std::vector<double> values;
};

struct TextureContext {
std::unordered_map<std::string, std::uint32_t> 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);
}
};

Expand Down Expand Up @@ -357,19 +375,27 @@ class SceneConverter {
const MaterialUsage &material_usage_);

std::optional<fx::gltf::Material::Texture>
_convertTextureProperty(fbxsdk::FbxProperty &fbx_property_);
_convertTextureProperty(fbxsdk::FbxProperty &fbx_property_,
const TextureContext &texture_context_);

std::optional<fx::gltf::Material::Texture>
_convertFileTextureShared(fbxsdk::FbxFileTexture &fbx_file_texture_);
_convertFileTextureShared(fbxsdk::FbxFileTexture &fbx_file_texture_,
const TextureContext &texture_context_);

std::optional<GLTFBuilder::XXIndex>
_convertFileTexture(const fbxsdk::FbxFileTexture &fbx_texture_);

std::optional<fx::gltf::Material::NormalTexture>
_convertTexturePropertyAsNormalTexture(fbxsdk::FbxProperty &fbx_property_);
_convertTexturePropertyAsNormalTexture(
fbxsdk::FbxProperty &fbx_property_,
const TextureContext &texture_context_);

std::optional<fx::gltf::Material::NormalTexture>
_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_,
Expand Down

0 comments on commit caec8fe

Please sign in to comment.