Skip to content

Commit

Permalink
Generate a more unique texture name for glb embedded textures (#606)
Browse files Browse the repository at this point in the history
Signed-off-by: Ian Chen <[email protected]>
Co-authored-by: Addisu Z. Taddese <[email protected]>
  • Loading branch information
iche033 and azeey authored May 8, 2024
1 parent 500ce44 commit 27f7017
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 28 deletions.
72 changes: 46 additions & 26 deletions graphics/src/AssimpLoader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
*
*/

#include <cstddef>
#include <queue>
#include <string>
#include <unordered_set>

#include "gz/common/graphics/Types.hh"
Expand Down Expand Up @@ -69,10 +71,12 @@ class AssimpLoader::Implementation
/// \param[in] _scene the assimp scene
/// \param[in] _matIdx index of the material in the scene
/// \param[in] _path path where the mesh is located
/// \param[in] _fileBaseName Base name of the mesh file.
/// \return pointer to the converted common::Material
public: MaterialPtr CreateMaterial(const aiScene* _scene,
public: MaterialPtr CreateMaterial(const aiScene *_scene,
unsigned _matIdx,
const std::string& _path) const;
const std::string &_path,
const std::string &_fileBaseName) const;

/// \brief Load a texture embedded in a mesh (i.e. for GLB format)
/// into a gz::common::Image
Expand All @@ -82,13 +86,15 @@ class AssimpLoader::Implementation

/// \brief Utility function to generate a texture name for both embedded
/// and external textures
/// \param[in] _prefix Prefix to add to the texture name
/// \param[in] _scene the assimp scene
/// \param[in] _mat the assimp material
/// \param[in] _type the type of texture (i.e. Diffuse, Metal)
/// \return the generated texture name
public: std::string GenerateTextureName(const aiScene* _scene,
aiMaterial* _mat,
const std::string& _type) const;
public: std::string GenerateTextureName(const std::string &_prefix,
const aiScene* _scene,
aiMaterial *_mat,
const std::string &_type) const;

/// \brief Function to parse texture information and load it if embedded
/// \param[in] _scene the assimp scene
Expand Down Expand Up @@ -320,7 +326,8 @@ void AssimpLoader::Implementation::RecursiveSkeletonCreate(const aiNode* _node,

//////////////////////////////////////////////////
MaterialPtr AssimpLoader::Implementation::CreateMaterial(
const aiScene* _scene, unsigned _matIdx, const std::string& _path) const
const aiScene *_scene, unsigned _matIdx, const std::string &_path,
const std::string &_fileBaseName) const
{
MaterialPtr mat = std::make_shared<Material>();
aiColor4D color;
Expand Down Expand Up @@ -386,8 +393,8 @@ MaterialPtr AssimpLoader::Implementation::CreateMaterial(
if (ret == AI_SUCCESS)
{
// Check if the texture is embedded or not
auto [texName, texData] = this->LoadTexture(_scene,
texturePath, this->GenerateTextureName(_scene, assimpMat, "Diffuse"));
auto [texName, texData] = this->LoadTexture(_scene, texturePath,
this->GenerateTextureName(_fileBaseName, _scene, assimpMat, "Diffuse"));
if (texData != nullptr)
mat->SetTextureImage(texName, texData);
else
Expand Down Expand Up @@ -421,18 +428,19 @@ MaterialPtr AssimpLoader::Implementation::CreateMaterial(
if (ret == AI_SUCCESS)
{
auto [texName, texData] = this->LoadTexture(_scene, texturePath,
this->GenerateTextureName(_scene, assimpMat, "MetallicRoughness"));
this->GenerateTextureName(_fileBaseName, _scene, assimpMat,
"MetallicRoughness"));
// Load it into a common::Image then split it
auto texImg = texData != nullptr ? texData :
std::make_shared<common::Image>(joinPaths(_path, texName));
auto [metalTexture, roughTexture] =
this->SplitMetallicRoughnessMap(*texImg);
pbr.SetMetalnessMap(
this->GenerateTextureName(_scene, assimpMat, "Metalness"),
metalTexture);
this->GenerateTextureName(_fileBaseName, _scene, assimpMat,
"Metalness"), metalTexture);
pbr.SetRoughnessMap(
this->GenerateTextureName(_scene, assimpMat, "Roughness"),
roughTexture);
this->GenerateTextureName(_fileBaseName, _scene, assimpMat,
"Roughness"), roughTexture);
}
else
{
Expand All @@ -441,15 +449,17 @@ MaterialPtr AssimpLoader::Implementation::CreateMaterial(
if (ret == AI_SUCCESS)
{
auto [texName, texData] = this->LoadTexture(_scene, texturePath,
this->GenerateTextureName(_scene, assimpMat, "Metalness"));
this->GenerateTextureName(_fileBaseName, _scene, assimpMat,
"Metalness"));
pbr.SetMetalnessMap(texName, texData);
}
ret = assimpMat->GetTexture(
aiTextureType_DIFFUSE_ROUGHNESS, 0, &texturePath);
if (ret == AI_SUCCESS)
{
auto [texName, texData] = this->LoadTexture(_scene, texturePath,
this->GenerateTextureName(_scene, assimpMat, "Roughness"));
this->GenerateTextureName(_fileBaseName, _scene, assimpMat,
"Roughness"));
pbr.SetRoughnessMap(texName, texData);
}
// Load lightmap only if it is not a glb/glTF mesh that contains a
Expand All @@ -464,7 +474,8 @@ MaterialPtr AssimpLoader::Implementation::CreateMaterial(
if (ret == AI_SUCCESS)
{
auto [texName, texData] = this->LoadTexture(_scene, texturePath,
this->GenerateTextureName(_scene, assimpMat, "Lightmap"));
this->GenerateTextureName(_fileBaseName, _scene, assimpMat,
"Lightmap"));
pbr.SetLightMap(texName, uvIdx, texData);
}
}
Expand All @@ -473,15 +484,16 @@ MaterialPtr AssimpLoader::Implementation::CreateMaterial(
if (ret == AI_SUCCESS)
{
auto [texName, texData] = this->LoadTexture(_scene, texturePath,
this->GenerateTextureName(_scene, assimpMat, "Normal"));
this->GenerateTextureName(_fileBaseName, _scene, assimpMat, "Normal"));
// TODO(luca) different normal map spaces
pbr.SetNormalMap(texName, NormalMapSpace::TANGENT, texData);
}
ret = assimpMat->GetTexture(aiTextureType_EMISSIVE, 0, &texturePath);
if (ret == AI_SUCCESS)
{
auto [texName, texData] = this->LoadTexture(_scene, texturePath,
this->GenerateTextureName(_scene, assimpMat, "Emissive"));
this->GenerateTextureName(_fileBaseName, _scene, assimpMat,
"Emissive"));
pbr.SetEmissiveMap(texName, texData);
}
#ifndef GZ_ASSIMP_PRE_5_2_0
Expand Down Expand Up @@ -600,15 +612,16 @@ ImagePtr AssimpLoader::Implementation::LoadEmbeddedTexture(

//////////////////////////////////////////////////
std::string AssimpLoader::Implementation::GenerateTextureName(
const aiScene* _scene, aiMaterial* _mat, const std::string& _type) const
const std::string &_prefix, const aiScene *_scene, aiMaterial *_mat,
const std::string &_type) const
{
#ifdef GZ_ASSIMP_PRE_5_2_0
auto rootName = _scene->mRootNode->mName;
#else
auto rootName = _scene->mName;
#endif
return ToString(rootName) + "_" + ToString(_mat->GetName()) +
"_" + _type;
return _prefix + "_" + ToString(rootName) + "_" +
ToString(_mat->GetName()) + "_" + _type;
}

//////////////////////////////////////////////////
Expand Down Expand Up @@ -695,12 +708,18 @@ Mesh *AssimpLoader::Load(const std::string &_filename)
}
auto& rootNode = scene->mRootNode;
auto rootName = ToString(rootNode->mName);

// compute assimp root node transform
std::string extension = _filename.substr(_filename.rfind(".") + 1,
_filename.size());
auto fileBaseName = common::basename(_filename);
std::string extension;
std::size_t extIdx = _filename.rfind(".");
if (extIdx != std::string::npos)
{
extension = _filename.substr(extIdx + 1, _filename.size());
fileBaseName = fileBaseName.substr(0, fileBaseName.rfind(extension) - 1);
}
std::transform(extension.begin(), extension.end(),
extension.begin(), ::tolower);

// compute assimp root node transform
bool useIdentityRotation = (extension != "glb" && extension != "glTF");
auto transform = this->dataPtr->UpdatedRootNodeTransform(scene,
useIdentityRotation);
Expand All @@ -709,7 +728,8 @@ Mesh *AssimpLoader::Load(const std::string &_filename)
// Add the materials first
for (unsigned _matIdx = 0; _matIdx < scene->mNumMaterials; ++_matIdx)
{
auto mat = this->dataPtr->CreateMaterial(scene, _matIdx, path);
auto mat = this->dataPtr->CreateMaterial(scene, _matIdx, path,
fileBaseName);
mesh->AddMaterial(mat);
}
// Create the skeleton
Expand Down
4 changes: 2 additions & 2 deletions graphics/src/AssimpLoader_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -721,9 +721,9 @@ TEST_F(AssimpLoader, LoadGlTF2BoxWithJPEGTexture)
// Assimp 5.2.0 and above uses the scene name for its texture names,
// older version use the root node instead.
#ifdef GZ_ASSIMP_PRE_5_2_0
EXPECT_EQ("Cube_Material_Diffuse", mat->TextureImage());
EXPECT_EQ("box_texture_jpg_Cube_Material_Diffuse", mat->TextureImage());
#else
EXPECT_EQ("Scene_Material_Diffuse", mat->TextureImage());
EXPECT_EQ("box_texture_jpg_Scene_Material_Diffuse", mat->TextureImage());
#endif
EXPECT_NE(nullptr, mat->TextureData());
delete mesh;
Expand Down

0 comments on commit 27f7017

Please sign in to comment.