summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Lihatskiy <alihatskiy@productengine.com>2025-07-14 15:23:52 +0300
committerAndrey Lihatskiy <118752495+marchcat@users.noreply.github.com>2025-07-14 13:22:41 +0000
commit63134f79434481a450a146eae76f90a9f86091a4 (patch)
treed7c04396c625f7bcd919faf9b3d6c7d6a2074a9d
parent07d0fbe94e89d0509b64232858e384a439810bb8 (diff)
#4204 Cache processed materials
-rw-r--r--indra/newview/gltf/llgltfloader.cpp190
-rw-r--r--indra/newview/gltf/llgltfloader.h4
2 files changed, 109 insertions, 85 deletions
diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp
index a181c97ac0..f2361f58ba 100644
--- a/indra/newview/gltf/llgltfloader.cpp
+++ b/indra/newview/gltf/llgltfloader.cpp
@@ -126,6 +126,9 @@ LLGLTFLoader::~LLGLTFLoader() {}
bool LLGLTFLoader::OpenFile(const std::string &filename)
{
+ // Clear the material cache for new file
+ mMaterialCache.clear();
+
tinygltf::TinyGLTF loader;
std::string filename_lc(filename);
LLStringUtil::toLower(filename_lc);
@@ -562,6 +565,106 @@ bool LLGLTFLoader::addJointToModelSkin(LLMeshSkinInfo& skin_info, S32 gltf_skin_
return true;
}
+LLImportMaterial LLGLTFLoader::processMaterial(S32 material_index)
+{
+ // Check cache first
+ auto cached = mMaterialCache.find(material_index);
+ if (cached != mMaterialCache.end())
+ {
+ return cached->second;
+ }
+
+ LLImportMaterial impMat;
+ impMat.mDiffuseColor = LLColor4::white; // Default color
+
+ // Process material if available
+ if (material_index >= 0 && material_index < mGLTFAsset.mMaterials.size())
+ {
+ LL::GLTF::Material* material = &mGLTFAsset.mMaterials[material_index];
+
+ // Set diffuse color from base color factor
+ impMat.mDiffuseColor = LLColor4(
+ material->mPbrMetallicRoughness.mBaseColorFactor[0],
+ material->mPbrMetallicRoughness.mBaseColorFactor[1],
+ material->mPbrMetallicRoughness.mBaseColorFactor[2],
+ material->mPbrMetallicRoughness.mBaseColorFactor[3]
+ );
+
+ // Process base color texture if it exists
+ if (material->mPbrMetallicRoughness.mBaseColorTexture.mIndex >= 0)
+ {
+ S32 texIndex = material->mPbrMetallicRoughness.mBaseColorTexture.mIndex;
+ if (texIndex < mGLTFAsset.mTextures.size())
+ {
+ S32 sourceIndex = mGLTFAsset.mTextures[texIndex].mSource;
+ if (sourceIndex >= 0 && sourceIndex < mGLTFAsset.mImages.size())
+ {
+ LL::GLTF::Image& image = mGLTFAsset.mImages[sourceIndex];
+
+ // Use URI as texture file name
+ if (!image.mUri.empty())
+ {
+ // URI might be a remote URL or a local path
+ std::string filename = image.mUri;
+
+ // Extract just the filename from the URI
+ size_t pos = filename.find_last_of("/\\");
+ if (pos != std::string::npos)
+ {
+ filename = filename.substr(pos + 1);
+ }
+
+ // Store the texture filename
+ impMat.mDiffuseMapFilename = filename;
+ impMat.mDiffuseMapLabel = material->mName.empty() ? filename : material->mName;
+
+ LL_INFOS("GLTF_IMPORT") << "Found texture: " << impMat.mDiffuseMapFilename
+ << " for material: " << material->mName << LL_ENDL;
+
+ LLSD args;
+ args["Message"] = "TextureFound";
+ args["TEXTURE_NAME"] = impMat.mDiffuseMapFilename;
+ args["MATERIAL_NAME"] = material->mName;
+ mWarningsArray.append(args);
+
+ // If the image has a texture loaded already, use it
+ if (image.mTexture.notNull())
+ {
+ impMat.setDiffuseMap(image.mTexture->getID());
+ LL_INFOS("GLTF_IMPORT") << "Using existing texture ID: " << image.mTexture->getID().asString() << LL_ENDL;
+ }
+ else
+ {
+ // Texture will be loaded later through the callback system
+ LL_INFOS("GLTF_IMPORT") << "Texture needs loading: " << impMat.mDiffuseMapFilename << LL_ENDL;
+ }
+ }
+ else if (image.mTexture.notNull())
+ {
+ // No URI but we have a texture, use it directly
+ impMat.setDiffuseMap(image.mTexture->getID());
+ LL_INFOS("GLTF_IMPORT") << "Using existing texture ID without URI: " << image.mTexture->getID().asString() << LL_ENDL;
+ }
+ else if (image.mBufferView >= 0)
+ {
+ // For embedded textures (no URI but has buffer data)
+ std::string temp_filename = extractTextureToTempFile(texIndex, "base_color");
+ if (!temp_filename.empty())
+ {
+ impMat.mDiffuseMapFilename = temp_filename;
+ impMat.mDiffuseMapLabel = material->mName.empty() ? temp_filename : material->mName;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Cache the processed material
+ mMaterialCache[material_index] = impMat;
+ return impMat;
+}
+
bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const std::string& base_name, const LL::GLTF::Mesh& mesh, const LL::GLTF::Node& nodeno, material_map& mats)
{
// Set the requested label for the floater display and uploading
@@ -623,91 +726,8 @@ bool LLGLTFLoader::populateModelFromMesh(LLModel* pModel, const std::string& bas
LLVolumeFace face;
std::vector<GLTFVertex> vertices;
- LLImportMaterial impMat;
- impMat.mDiffuseColor = LLColor4::white; // Default color
-
- // Process material if available
- if (prim.mMaterial >= 0 && prim.mMaterial < mGLTFAsset.mMaterials.size())
- {
- LL::GLTF::Material* material = &mGLTFAsset.mMaterials[prim.mMaterial];
-
- // Set diffuse color from base color factor
- impMat.mDiffuseColor = LLColor4(
- material->mPbrMetallicRoughness.mBaseColorFactor[0],
- material->mPbrMetallicRoughness.mBaseColorFactor[1],
- material->mPbrMetallicRoughness.mBaseColorFactor[2],
- material->mPbrMetallicRoughness.mBaseColorFactor[3]
- );
-
- // Process base color texture if it exists
- if (material->mPbrMetallicRoughness.mBaseColorTexture.mIndex >= 0)
- {
- S32 texIndex = material->mPbrMetallicRoughness.mBaseColorTexture.mIndex;
- if (texIndex < mGLTFAsset.mTextures.size())
- {
- S32 sourceIndex = mGLTFAsset.mTextures[texIndex].mSource;
- if (sourceIndex >= 0 && sourceIndex < mGLTFAsset.mImages.size())
- {
- LL::GLTF::Image& image = mGLTFAsset.mImages[sourceIndex];
-
- // Use URI as texture file name
- if (!image.mUri.empty())
- {
- // URI might be a remote URL or a local path
- std::string filename = image.mUri;
-
- // Extract just the filename from the URI
- size_t pos = filename.find_last_of("/\\");
- if (pos != std::string::npos)
- {
- filename = filename.substr(pos + 1);
- }
-
- // Store the texture filename
- impMat.mDiffuseMapFilename = filename;
- impMat.mDiffuseMapLabel = material->mName.empty() ? filename : material->mName;
-
- LL_INFOS("GLTF_IMPORT") << "Found texture: " << impMat.mDiffuseMapFilename
- << " for material: " << material->mName << LL_ENDL;
-
- LLSD args;
- args["Message"] = "TextureFound";
- args["TEXTURE_NAME"] = impMat.mDiffuseMapFilename;
- args["MATERIAL_NAME"] = material->mName;
- mWarningsArray.append(args);
-
- // If the image has a texture loaded already, use it
- if (image.mTexture.notNull())
- {
- impMat.setDiffuseMap(image.mTexture->getID());
- LL_INFOS("GLTF_IMPORT") << "Using existing texture ID: " << image.mTexture->getID().asString() << LL_ENDL;
- }
- else
- {
- // Texture will be loaded later through the callback system
- LL_INFOS("GLTF_IMPORT") << "Texture needs loading: " << impMat.mDiffuseMapFilename << LL_ENDL;
- }
- }
- else if (image.mTexture.notNull())
- {
- // No URI but we have a texture, use it directly
- impMat.setDiffuseMap(image.mTexture->getID());
- LL_INFOS("GLTF_IMPORT") << "Using existing texture ID without URI: " << image.mTexture->getID().asString() << LL_ENDL;
- }
- else if (image.mBufferView >= 0)
- {
- // For embedded textures (no URI but has buffer data)
- std::string temp_filename = extractTextureToTempFile(texIndex, "base_color");
- if (!temp_filename.empty())
- {
- impMat.mDiffuseMapFilename = temp_filename;
- impMat.mDiffuseMapLabel = material->mName.empty() ? temp_filename : material->mName;
- }
- }
- }
- }
- }
- }
+ // Use cached material processing
+ LLImportMaterial impMat = processMaterial(prim.mMaterial);
if (prim.getIndexCount() % 3 != 0)
{
diff --git a/indra/newview/gltf/llgltfloader.h b/indra/newview/gltf/llgltfloader.h
index 3a9531bf7b..b4c6e0c66c 100644
--- a/indra/newview/gltf/llgltfloader.h
+++ b/indra/newview/gltf/llgltfloader.h
@@ -131,11 +131,15 @@ protected:
// per skin joint count, needs to be tracked for the sake of limits check.
std::vector<S32> mValidJointsCount;
+ // Material cache to avoid duplicate processing
+ std::map<S32, LLImportMaterial> mMaterialCache;
+
private:
bool parseMeshes();
void computeCombinedNodeTransform(const LL::GLTF::Asset& asset, S32 node_index, glm::mat4& combined_transform) const;
void processNodeHierarchy(S32 node_idx, std::map<std::string, S32>& mesh_name_counts, U32 submodel_limit, const LLVolumeParams& volume_params);
bool addJointToModelSkin(LLMeshSkinInfo& skin_info, S32 gltf_skin_idx, size_t gltf_joint_idx);
+ LLImportMaterial processMaterial(S32 material_index);
bool populateModelFromMesh(LLModel* pModel, const std::string& base_name, const LL::GLTF::Mesh &mesh, const LL::GLTF::Node &node, material_map& mats);
void populateJointsFromSkin(S32 skin_idx);
void populateJointGroups();