summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2025-07-22 01:54:33 +0300
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2025-07-22 19:16:26 +0300
commitd84897967e836cd2dadf8f609eb98946f500d5b1 (patch)
treef5371065be3e40be6fa1457d670e85b9ff52d88f
parent8df303ed8506a0c4fe8965130e1ac9df75d156b1 (diff)
#4318 Warn or log when texture gets scaled down
for material and model upload
-rw-r--r--indra/llprimitive/llmodelloader.cpp4
-rw-r--r--indra/llprimitive/llmodelloader.h4
-rw-r--r--indra/newview/gltf/llgltfloader.cpp1
-rw-r--r--indra/newview/llfloatermodelpreview.cpp8
-rw-r--r--indra/newview/llmaterialeditor.cpp36
-rw-r--r--indra/newview/llmodelpreview.cpp38
-rw-r--r--indra/newview/llmodelpreview.h5
-rw-r--r--indra/newview/skins/default/xui/en/floater_model_preview.xml1
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml14
9 files changed, 94 insertions, 17 deletions
diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp
index db4c4259f3..630c109d8f 100644
--- a/indra/llprimitive/llmodelloader.cpp
+++ b/indra/llprimitive/llmodelloader.cpp
@@ -123,7 +123,6 @@ LLModelLoader::LLModelLoader(
, mLod(lod)
, mTrySLM(false)
, mFirstTransform(true)
-, mNumOfFetchingTextures(0)
, mLoadCallback(load_cb)
, mJointLookupFunc(joint_lookup_func)
, mTextureLoadFunc(texture_load_func)
@@ -134,6 +133,7 @@ LLModelLoader::LLModelLoader(
, mNoNormalize(false)
, mNoOptimize(false)
, mCacheOnlyHitIfRigged(false)
+, mTexturesNeedScaling(false)
, mMaxJointsPerMesh(maxJointsPerMesh)
, mGeneratedModelLimit(modelLimit)
, mDebugMode(debugMode)
@@ -669,7 +669,7 @@ void LLModelLoader::loadTextures()
if(!material.mDiffuseMapFilename.empty())
{
- mNumOfFetchingTextures += mTextureLoadFunc(material, mOpaqueData);
+ mTextureLoadFunc(material, mOpaqueData);
}
}
}
diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h
index 06a17f006e..335d809386 100644
--- a/indra/llprimitive/llmodelloader.h
+++ b/indra/llprimitive/llmodelloader.h
@@ -109,6 +109,7 @@ public:
bool mTrySLM;
bool mCacheOnlyHitIfRigged; // ignore cached SLM if it does not contain rig info (and we want rig info)
+ bool mTexturesNeedScaling;
model_list mModelList;
// The scene is pretty much what ends up getting loaded for upload. Basically assign things to this guy if you want something uploaded.
@@ -170,9 +171,6 @@ public:
void stretch_extents(const LLModel* model, const LLMatrix4& mat);
- S32 mNumOfFetchingTextures ; // updated in the main thread
- bool areTexturesReady() { return !mNumOfFetchingTextures; } // called in the main thread.
-
bool verifyCount( int expected, int result );
//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
diff --git a/indra/newview/gltf/llgltfloader.cpp b/indra/newview/gltf/llgltfloader.cpp
index 3019a12446..9f6caf4198 100644
--- a/indra/newview/gltf/llgltfloader.cpp
+++ b/indra/newview/gltf/llgltfloader.cpp
@@ -611,6 +611,7 @@ LLGLTFLoader::LLGLTFImportMaterial LLGLTFLoader::processMaterial(S32 material_in
LL::GLTF::Image& image = mGLTFAsset.mImages[sourceIndex];
if (image.mTexture.notNull())
{
+ mTexturesNeedScaling |= image.mHeight > LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT || image.mWidth > LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT;
impMat.setDiffuseMap(image.mTexture->getID());
LL_INFOS("GLTF_IMPORT") << "Using existing texture ID: " << image.mTexture->getID().asString() << LL_ENDL;
}
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index bd33ab2dbe..5aef7f20b4 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -1340,26 +1340,26 @@ void LLFloaterModelPreview::addStringToLog(const std::string& message, const LLS
{
std::string str;
switch (lod)
-{
+ {
case LLModel::LOD_IMPOSTOR: str = "LOD0 "; break;
case LLModel::LOD_LOW: str = "LOD1 "; break;
case LLModel::LOD_MEDIUM: str = "LOD2 "; break;
case LLModel::LOD_PHYSICS: str = "PHYS "; break;
case LLModel::LOD_HIGH: str = "LOD3 "; break;
default: break;
-}
+ }
LLStringUtil::format_map_t args_msg;
LLSD::map_const_iterator iter = args.beginMap();
LLSD::map_const_iterator end = args.endMap();
for (; iter != end; ++iter)
-{
+ {
args_msg[iter->first] = iter->second.asString();
}
str += sInstance->getString(message, args_msg);
sInstance->addStringToLogTab(str, flash);
}
- }
+}
// static
void LLFloaterModelPreview::addStringToLog(const std::string& str, bool flash)
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index 5b3ac53d51..3cab060357 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -2479,6 +2479,42 @@ void LLMaterialEditor::loadMaterial(const tinygltf::Model &model_in, const std::
pack_textures(base_color_img, normal_img, mr_img, emissive_img, occlusion_img,
mBaseColorJ2C, mNormalJ2C, mMetallicRoughnessJ2C, mEmissiveJ2C);
+ if (open_floater)
+ {
+ bool textures_scaled = false;
+ if (mBaseColorFetched && mBaseColorJ2C
+ && (mBaseColorFetched->getWidth() != mBaseColorJ2C->getWidth()
+ || mBaseColorFetched->getHeight() != mBaseColorJ2C->getHeight()))
+ {
+ textures_scaled = true;
+ }
+ else if (mNormalFetched && mNormalJ2C
+ && (mNormalFetched->getWidth() != mNormalJ2C->getWidth()
+ || mNormalFetched->getHeight() != mNormalJ2C->getHeight()))
+ {
+ textures_scaled = true;
+ }
+ else if (mMetallicRoughnessFetched && mMetallicRoughnessJ2C
+ && (mMetallicRoughnessFetched->getWidth() != mMetallicRoughnessJ2C->getWidth()
+ || mMetallicRoughnessFetched->getHeight() != mMetallicRoughnessJ2C->getHeight()))
+ {
+ textures_scaled = true;
+ }
+ else if (mEmissiveFetched && mEmissiveJ2C
+ && (mEmissiveFetched->getWidth() != mEmissiveJ2C->getWidth()
+ || mEmissiveFetched->getHeight() != mEmissiveJ2C->getHeight()))
+ {
+ textures_scaled = true;
+ }
+
+ if (textures_scaled)
+ {
+ LLSD args;
+ args["MAX_SIZE"] = LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT;
+ LLNotificationsUtil::add("MaterialImagesWereScaled", args);
+ }
+ }
+
LLUUID base_color_id;
if (mBaseColorFetched.notNull())
{
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index ac697383e2..e819f4dec0 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -169,6 +169,8 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
, mLastJointUpdate(false)
, mFirstSkinUpdate(true)
, mHasDegenerate(false)
+ , mNumOfFetchingTextures(0)
+ , mTexturesNeedScaling(false)
, mImporterDebug(LLCachedControl<bool>(gSavedSettings, "ImporterDebugVerboseLogging", false))
{
mNeedsUpdate = true;
@@ -559,10 +561,7 @@ void LLModelPreview::rebuildUploadData()
texture->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, true, false, new LLHandle<LLModelPreview>(getHandle()), &mCallbackTextureList, false);
texture->forceToSaveRawImage(0, F32_MAX);
texture->updateFetch();
- if (mModelLoader)
- {
- mModelLoader->mNumOfFetchingTextures++;
- }
+ mNumOfFetchingTextures++;
}
}
}
@@ -997,7 +996,9 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)
setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload());
setLegacyRigFlags(mModelLoader->getLegacyRigFlags());
+ mTexturesNeedScaling |= mModelLoader->mTexturesNeedScaling;
mModelLoader->loadTextures();
+ warnTextureScaling();
if (loaded_lod == -1)
{ //populate all LoDs from model loader scene
@@ -2510,7 +2511,7 @@ void LLModelPreview::updateStatusMessages()
LLMutexLock lock(this);
if (mModelLoader)
{
- if (!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean())
+ if (!areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean())
{
// Some textures are still loading, prevent upload until they are done
mModelNoErrors = false;
@@ -3216,6 +3217,7 @@ U32 LLModelPreview::loadTextures(LLImportMaterial& material, LLHandle<LLModelPre
tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, true, false, new LLHandle<LLModelPreview>(handle), &preview->mCallbackTextureList, false);
tex->forceToSaveRawImage(0, F32_MAX);
material.setDiffuseMap(tex->getID()); // record tex ID
+ preview->mNumOfFetchingTextures++;
return 1;
}
@@ -4060,6 +4062,18 @@ void LLModelPreview::setPreviewLOD(S32 lod)
updateStatusMessages();
}
+void LLModelPreview::warnTextureScaling()
+{
+ if (areTexturesReady() && mTexturesNeedScaling)
+ {
+ std::ostringstream out;
+ out << "One or more textures in this model were scaled to be within the allowed limits.";
+ LL_INFOS() << out.str() << LL_ENDL;
+ LLSD args;
+ LLFloaterModelPreview::addStringToLog("ModelTextureScaling", args, true, -1);
+ }
+}
+
//static
void LLModelPreview::textureLoadedCallback(
bool success,
@@ -4080,11 +4094,19 @@ void LLModelPreview::textureLoadedCallback(
LLModelPreview* preview = static_cast<LLModelPreview*>(handle->get());
preview->refresh();
- if (final && preview->mModelLoader)
+ if (final)
{
- if (preview->mModelLoader->mNumOfFetchingTextures > 0)
+ if (src_vi
+ && (src_vi->getOriginalWidth() > LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT
+ || src_vi->getOriginalHeight() > LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT))
+ {
+ preview->mTexturesNeedScaling = true;
+ }
+
+ if (preview->mNumOfFetchingTextures > 0)
{
- preview->mModelLoader->mNumOfFetchingTextures--;
+ preview->mNumOfFetchingTextures--;
+ preview->warnTextureScaling();
}
}
}
diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h
index 0873263587..7b3b699b33 100644
--- a/indra/newview/llmodelpreview.h
+++ b/indra/newview/llmodelpreview.h
@@ -204,6 +204,7 @@ public:
std::vector<S32> mLodsQuery;
std::vector<S32> mLodsWithParsingError;
bool mHasDegenerate;
+ bool areTexturesReady() { return !mNumOfFetchingTextures; }
protected:
@@ -213,6 +214,7 @@ protected:
static LLJoint* lookupJointByName(const std::string&, void* opaque);
static U32 loadTextures(LLImportMaterial& material, LLHandle<LLModelPreview> handle);
+ void warnTextureScaling();
void lookupLODModelFiles(S32 lod);
private:
@@ -242,6 +244,9 @@ private:
/// Not read unless mWarnOfUnmatchedPhyicsMeshes is true.
LLPointer<LLModel> mDefaultPhysicsShapeP;
+ S32 mNumOfFetchingTextures;
+ bool mTexturesNeedScaling;
+
typedef enum
{
MESH_OPTIMIZER_FULL,
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index a86b9c7da2..f11d687840 100644
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -39,6 +39,7 @@
<string name="decomposing">Analyzing...</string>
<string name="simplifying">Simplifying...</string>
<string name="tbd">TBD</string>
+ <string name="ModelTextureScaling">One or more textures in this model were scaled to be within the allowed limits.</string>
<!-- Warnings and info from model loader-->
<string name="TooManyJoint">Skinning disabled due to too many joints: [JOINTS], maximum: [MAX]</string>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 82e77119ab..a7e892f6f2 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -7136,6 +7136,20 @@ You don&apos;t have permission to view this notecard.
</notification>
<notification
+ icon="alertmodal.tga"
+ name="MaterialImagesWereScaled"
+ type="alertmodal">
+One or more textures in this material were scaled to be within the allowed limits.
+Textures must have power of two dimensions and must not exceed [MAX_SIZE]x[MAX_SIZE] pixels.
+ <unique/>
+ <tag>confirm</tag>
+ <usetemplate
+ ignoretext="Warn if textures will be scaled during upload."
+ name="okignore"
+ yestext="OK"/>
+ </notification>
+
+ <notification
icon="notifytip.tga"
name="RezItemNoPermissions"
type="notifytip">