Skip to content

Commit 5fe152c

Browse files
authored
Fix #4195: Preserve transforms when switching PBR materials (#4725)
Fixes texture transforms being reset when switching from Blinn-Phong to PBR materials and between PBR. Previously, custom scale, offset, and rotation settings would be lost, making it tedious to switch between PBR materials.
1 parent a54a96a commit 5fe152c

File tree

5 files changed

+339
-13
lines changed

5 files changed

+339
-13
lines changed

indra/llprimitive/llgltfmaterial.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,3 +923,34 @@ void LLGLTFMaterial::updateTextureTracking()
923923
// setTEGLTFMaterialOverride is responsible for tracking
924924
// for material overrides editor will set it
925925
}
926+
927+
void LLGLTFMaterial::convertTextureTransformToPBR(
928+
F32 tex_scale_s,
929+
F32 tex_scale_t,
930+
F32 tex_offset_s,
931+
F32 tex_offset_t,
932+
F32 tex_rotation,
933+
LLVector2& pbr_scale,
934+
LLVector2& pbr_offset,
935+
F32& pbr_rotation)
936+
{
937+
pbr_scale.set(tex_scale_s, tex_scale_t);
938+
pbr_rotation = -(tex_rotation) / 2.f;
939+
const F32 adjusted_offset_s = tex_offset_s;
940+
const F32 adjusted_offset_t = -tex_offset_t;
941+
F32 center_adjust_s = 0.5f * (1.0f - tex_scale_s);
942+
F32 center_adjust_t = 0.5f * (1.0f - tex_scale_t);
943+
944+
if (pbr_rotation != 0.0f)
945+
{
946+
const F32 c = cosf(pbr_rotation);
947+
const F32 s = sinf(pbr_rotation);
948+
const F32 tmp_s = center_adjust_s * c - center_adjust_t * s;
949+
const F32 tmp_t = center_adjust_s * s + center_adjust_t * c;
950+
center_adjust_s = tmp_s;
951+
center_adjust_t = tmp_t;
952+
}
953+
954+
pbr_offset.set(adjusted_offset_s + center_adjust_s,
955+
adjusted_offset_t + center_adjust_t);
956+
}

indra/llprimitive/llgltfmaterial.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,14 @@ class LLGLTFMaterial : public LLRefCount
214214
bool hasLocalTextures() { return !mTrackingIdToLocalTexture.empty(); }
215215
virtual bool replaceLocalTexture(const LLUUID& tracking_id, const LLUUID &old_id, const LLUUID& new_id);
216216
virtual void updateTextureTracking();
217+
218+
// Convert legacy TE transform values to PBR transform values.
219+
static void convertTextureTransformToPBR(F32 tex_scale_s, F32 tex_scale_t,
220+
F32 tex_offset_s, F32 tex_offset_t,
221+
F32 tex_rotation,
222+
LLVector2& pbr_scale,
223+
LLVector2& pbr_offset,
224+
F32& pbr_rotation);
217225
protected:
218226
static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value);
219227
static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value);

indra/newview/llgltfmateriallist.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -380,17 +380,6 @@ void LLGLTFMaterialList::queueApply(const LLViewerObject* obj, S32 side, const L
380380
LLGLTFMaterial* material = new LLGLTFMaterial(*material_override);
381381
sApplyQueue.push_back({ obj->getID(), side, asset_id, material });
382382
}
383-
384-
if (sUpdates.size() >= MAX_TASK_UPDATES)
385-
{
386-
LLCoros::instance().launch("modifyMaterialCoro",
387-
std::bind(&LLGLTFMaterialList::modifyMaterialCoro,
388-
gAgent.getRegionCapability("ModifyMaterialParams"),
389-
sUpdates,
390-
std::shared_ptr<CallbackHolder>(nullptr)));
391-
392-
sUpdates = LLSD::emptyArray();
393-
}
394383
}
395384

396385
void LLGLTFMaterialList::queueUpdate(const LLSD& data)

indra/newview/llselectmgr.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,9 +1996,96 @@ bool LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id)
19961996
asset_id = BLANK_MATERIAL_ASSET_ID;
19971997
}
19981998
}
1999+
2000+
// If this face already has the target material ID, do nothing.
2001+
// This prevents re-sending the same ID on OK, which can cause the server
2002+
// to drop overrides when queueApply is invoked with the OLD id.
2003+
if (objectp->getRenderMaterialID(te) == asset_id)
2004+
{
2005+
return true;
2006+
}
2007+
2008+
// Preserve existing texture transforms when switching to PBR material
2009+
LLTextureEntry* tep = objectp->getTE(te);
2010+
bool should_preserve_transforms = false;
2011+
LLGLTFMaterial* preserved_override = nullptr;
2012+
2013+
if (tep && asset_id.notNull())
2014+
{
2015+
// Only preserve transforms from existing GLTF material override
2016+
// Do not fall back to texture entry transforms when switching between PBR materials
2017+
LLGLTFMaterial* existing_override = tep->getGLTFMaterialOverride();
2018+
if (existing_override)
2019+
{
2020+
// Check if existing override has non-default transforms
2021+
const LLGLTFMaterial::TextureTransform& existing_transform = existing_override->mTextureTransform[0];
2022+
const LLGLTFMaterial::TextureTransform& default_transform = LLGLTFMaterial::TextureTransform();
2023+
2024+
if (existing_transform.mScale != default_transform.mScale ||
2025+
existing_transform.mOffset != default_transform.mOffset ||
2026+
existing_transform.mRotation != default_transform.mRotation)
2027+
{
2028+
// Preserve non-default transforms from current PBR material
2029+
preserved_override = new LLGLTFMaterial();
2030+
for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
2031+
{
2032+
preserved_override->mTextureTransform[i].mScale = existing_transform.mScale;
2033+
preserved_override->mTextureTransform[i].mOffset = existing_transform.mOffset;
2034+
preserved_override->mTextureTransform[i].mRotation = existing_transform.mRotation;
2035+
}
2036+
should_preserve_transforms = true;
2037+
}
2038+
// If existing override has default transforms, don't preserve anything
2039+
}
2040+
else
2041+
{
2042+
// No existing PBR material override - check texture entry transforms
2043+
// This handles the case of switching from Blinn-Phong to PBR material
2044+
F32 existing_scale_s, existing_scale_t, existing_offset_s, existing_offset_t, existing_rotation;
2045+
tep->getScale(&existing_scale_s, &existing_scale_t);
2046+
tep->getOffset(&existing_offset_s, &existing_offset_t);
2047+
existing_rotation = tep->getRotation();
2048+
2049+
const LLGLTFMaterial::TextureTransform& default_transform = LLGLTFMaterial::TextureTransform();
2050+
if (existing_scale_s != default_transform.mScale.mV[0] || existing_scale_t != default_transform.mScale.mV[1] ||
2051+
existing_offset_s != default_transform.mOffset.mV[0] || existing_offset_t != default_transform.mOffset.mV[1] ||
2052+
existing_rotation != default_transform.mRotation)
2053+
{
2054+
// Preserve non-default transforms from texture entry
2055+
preserved_override = new LLGLTFMaterial();
2056+
for (U32 i = 0; i < LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT; ++i)
2057+
{
2058+
LLVector2 pbr_scale, pbr_offset;
2059+
F32 pbr_rotation;
2060+
LLGLTFMaterial::convertTextureTransformToPBR(
2061+
existing_scale_s, existing_scale_t,
2062+
existing_offset_s, existing_offset_t,
2063+
existing_rotation,
2064+
pbr_scale, pbr_offset, pbr_rotation);
2065+
preserved_override->mTextureTransform[i].mScale = pbr_scale;
2066+
preserved_override->mTextureTransform[i].mOffset = pbr_offset;
2067+
preserved_override->mTextureTransform[i].mRotation = pbr_rotation;
2068+
}
2069+
should_preserve_transforms = true;
2070+
}
2071+
}
2072+
}
2073+
19992074
objectp->clearTEWaterExclusion(te);
20002075
// Blank out most override data on the object and send to server
20012076
objectp->setRenderMaterialID(te, asset_id);
2077+
if (should_preserve_transforms && preserved_override)
2078+
{
2079+
// Apply material with preserved transforms
2080+
LLGLTFMaterialList::queueApply(objectp, te, asset_id, preserved_override);
2081+
// Update local state
2082+
objectp->setRenderMaterialID(te, asset_id, false, true);
2083+
tep->setGLTFMaterialOverride(preserved_override);
2084+
}
2085+
else
2086+
{
2087+
objectp->setRenderMaterialID(te, asset_id);
2088+
}
20022089

20032090
return true;
20042091
}

0 commit comments

Comments
 (0)