From 2f8d6420f346b6ee8c98860030b03d79ff88a9c4 Mon Sep 17 00:00:00 2001 From: Rye Date: Sun, 11 Jan 2026 13:22:32 -0500 Subject: Reduce temporary istringstream allocations during LLDate and GLTF override parsing --- indra/llprimitive/llgltfmaterial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llprimitive/llgltfmaterial.cpp') diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp index 930222e3db..b2cd1dc597 100644 --- a/indra/llprimitive/llgltfmaterial.cpp +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -214,7 +214,7 @@ std::string LLGLTFMaterial::asJSON(bool prettyprint) const // to WriteGltfSceneToStream in the viewer. gltf.WriteGltfSceneToStream(&model_out, str, prettyprint, false); - return str.str(); + return std::move(str).str(); } void LLGLTFMaterial::setFromModel(const tinygltf::Model& model, S32 mat_index) -- cgit v1.3 From 98d7f697ce5d7509a4dabde877de2856e27892dd Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Wed, 28 Jan 2026 03:43:43 +0200 Subject: #2975 PBR support for planar aligment Since checkbox is shared between pbr and normal textures, I'm making it affect both for now. --- indra/llprimitive/llgltfmaterial.cpp | 90 ++++++++++++++++++++++++++++++------ indra/llprimitive/llgltfmaterial.h | 8 ++++ indra/newview/llface.cpp | 85 ++++++++++++++++++++++++++++++++++ indra/newview/llface.h | 2 + indra/newview/llpanelface.cpp | 21 +++++++++ 5 files changed, 192 insertions(+), 14 deletions(-) (limited to 'indra/llprimitive/llgltfmaterial.cpp') diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp index b2cd1dc597..1c47001272 100644 --- a/indra/llprimitive/llgltfmaterial.cpp +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -924,6 +924,25 @@ void LLGLTFMaterial::updateTextureTracking() // for material overrides editor will set it } +// Test cases: +// Case 1. +// Input: scale 1.0,1.0; Offset horizontal 0.0, Offset vertical 0.0 Rotation 0.349066; +// Expected output: scale 1.0,1.0; Offset horizontal 0.201, Offset vertical -0.141 Rotation -0.349066; +// Case 2. +// Input: scale 1.0,1.0; Offset horizontal 0.5, Offset vertical 0.1 Rotation 0; +// Expected output: scale 1.0,1.0; Offset horizontal 0.5, Offset vertical -0.1 Rotation -0; +// Case 3. +// Input: scale 1.0,1.0; Offset horizontal 0.1, Offset vertical 0.2 Rotation 0.349066; +// Expected output: scale 1.0,1.0; Offset horizontal 0.295, Offset vertical -0.345 Rotation -0.349066; +// Case 4. +// Input: scale 1.0,1.0; Offset horizontal 0.5, Offset vertical 0.0 Rotation 0.349066; +// Expected output: scale 1.0,1.0; Offset horizontal 0.701, Offset vertical -0.141 Rotation -0.349066; +// +// Legacy offsets are right to left and top to bottom. +// PBR offsets are right to left and bottom to top. +// +// Legacy rotation is relative to face's center counter clockwise, +// PBR rotation is relative to top-left corner, clockwise void LLGLTFMaterial::convertTextureTransformToPBR( F32 tex_scale_s, F32 tex_scale_t, @@ -935,22 +954,65 @@ void LLGLTFMaterial::convertTextureTransformToPBR( F32& pbr_rotation) { pbr_scale.set(tex_scale_s, tex_scale_t); - pbr_rotation = -(tex_rotation) / 2.f; - const F32 adjusted_offset_s = tex_offset_s; - const F32 adjusted_offset_t = -tex_offset_t; + pbr_rotation = -tex_rotation; + + // Center of the tile + const F32 center_s = 0.5f; + const F32 center_t = 0.5f; + + // Center adjustment for scale F32 center_adjust_s = 0.5f * (1.0f - tex_scale_s); F32 center_adjust_t = 0.5f * (1.0f - tex_scale_t); - if (pbr_rotation != 0.0f) - { - const F32 c = cosf(pbr_rotation); - const F32 s = sinf(pbr_rotation); - const F32 tmp_s = center_adjust_s * c - center_adjust_t * s; - const F32 tmp_t = center_adjust_s * s + center_adjust_t * c; - center_adjust_s = tmp_s; - center_adjust_t = tmp_t; - } + // 2. Offset from center + F32 pos_s = center_adjust_s - center_s; + F32 pos_t = center_adjust_t - center_t; + + // 3. Rotate around center (clockwise, as per GLTF spec) + F32 c = cosf(pbr_rotation); + F32 s = sinf(pbr_rotation); + F32 rot_s = pos_s * c + pos_t * s; + F32 rot_t = -pos_s * s + pos_t * c; + + // 4. Move back to top-left and apply offset + pbr_offset.set(rot_s + center_s + tex_offset_s, rot_t + center_t - tex_offset_t); +} + +// Convert PBR transform values back to legacy TE transform values. +// This is the reverse of convertTextureTransformToPBR. +void LLGLTFMaterial::convertPBRTransformToTexture( + const LLVector2& pbr_scale, + const LLVector2& pbr_offset, + F32 pbr_rotation, + F32& tex_scale_s, + F32& tex_scale_t, + F32& tex_offset_s, + F32& tex_offset_t, + F32& tex_rotation) +{ + tex_scale_s = pbr_scale.mV[0]; + tex_scale_t = pbr_scale.mV[1]; + tex_rotation = -pbr_rotation; + + // Center of the tile + const F32 center_s = 0.5f; + const F32 center_t = 0.5f; + + // Center adjustment for scale + F32 center_adjust_s = 0.5f * (1.0f - tex_scale_s); + F32 center_adjust_t = 0.5f * (1.0f - tex_scale_t); + + // 2. Offset from center + F32 pos_s = center_adjust_s - center_s; + F32 pos_t = center_adjust_t - center_t; + + // 3. Rotate around center (clockwise, as per GLTF spec) + F32 c = cosf(pbr_rotation); + F32 s = sinf(pbr_rotation); + F32 rot_s = pos_s * c + pos_t * s; + F32 rot_t = -pos_s * s + pos_t * c; - pbr_offset.set(adjusted_offset_s + center_adjust_s, - adjusted_offset_t + center_adjust_t); + // 3. Recover legacy offset + tex_offset_s = pbr_offset.mV[0] - rot_s - center_s; + tex_offset_t = -(pbr_offset.mV[1] - rot_t - center_t); } diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index 8d45cb6185..c37062e7d3 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -222,6 +222,14 @@ public: LLVector2& pbr_scale, LLVector2& pbr_offset, F32& pbr_rotation); + + // Convert PBR transform values to legacy TE transform values. + static void convertPBRTransformToTexture(const LLVector2& pbr_scale, + const LLVector2& pbr_offset, + F32 pbr_rotation, + F32& tex_scale_s, F32& tex_scale_t, + F32& tex_offset_s, F32& tex_offset_t, + F32& tex_rotation); protected: static LLVector2 vec2FromJson(const std::map& object, const char* key, const LLVector2& default_value); static F32 floatFromJson(const std::map& object, const char* key, const F32 default_value); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 7c631a7280..2b318dcf5f 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1067,6 +1067,91 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs return true; } +F32 dot_product(const LLVector3& a, const LLVector3& b) +{ + return a.mV[VX] * b.mV[VX] + a.mV[VY] * b.mV[VY] + a.mV[VZ] * b.mV[VZ]; +} + +bool LLFace::calcAlignedPlanarGLTF( + const LLFace* align_to, + LLVector2* res_st_offset, + LLVector2* res_st_scale, + F32* res_st_rot, + S32 gltf_info_index) const +{ + if (!align_to) + { + return false; + } + + const LLTextureEntry* orig_tep = align_to->getTextureEntry(); + const LLTextureEntry* tep = getTextureEntry(); + if (!orig_tep || !tep) + { + return false; + } + + // Only support planar mapping for now + if (orig_tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR || + tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR) + { + return false; + } + + LLGLTFMaterial* orig_mat = orig_tep->getGLTFRenderMaterial(); + LLGLTFMaterial* this_mat = tep->getGLTFRenderMaterial(); + if (!orig_mat || !this_mat) + { + return false; + } + + // Get the original GLTF transform for the specified channel + const auto& orig_tt = orig_mat->mTextureTransform[gltf_info_index]; + + // Convert GLTF transform to legacy TE transform + F32 map_scaleS, map_scaleT, map_offsS, map_offsT, map_rot; + LLGLTFMaterial::convertPBRTransformToTexture( + orig_tt.mScale, + orig_tt.mOffset, + orig_tt.mRotation, + map_scaleS, map_scaleT, map_offsS, map_offsT, map_rot); + + // Calculate aligments + LLVector3 orig_pos, this_pos; + LLQuaternion orig_face_rot, this_face_rot; + F32 orig_proj_scale, this_proj_scale; + align_to->getPlanarProjectedParams(&orig_face_rot, &orig_pos, &orig_proj_scale); + getPlanarProjectedParams(&this_face_rot, &this_pos, &this_proj_scale); + + // The rotation of "this face's" texture: + LLQuaternion orig_st_rot = LLQuaternion(map_rot, LLVector3::z_axis) * orig_face_rot; + LLQuaternion this_st_rot = orig_st_rot * ~this_face_rot; + F32 x_ang, y_ang, z_ang; + this_st_rot.getEulerAngles(&x_ang, &y_ang, &z_ang); + + // Offset and scale of "this face's" texture: + LLVector3 centers_dist = (this_pos - orig_pos) * ~orig_st_rot; + LLVector3 st_scale(map_scaleS, map_scaleT, 1.f); + st_scale *= orig_proj_scale; + centers_dist.scaleVec(st_scale); + LLVector2 orig_st_offset(map_offsS, map_offsT); + + LLVector2 tex_res_st_offset = orig_st_offset + (LLVector2)centers_dist; + tex_res_st_offset.mV[VX] -= (S32)tex_res_st_offset.mV[VX]; + tex_res_st_offset.mV[VY] -= (S32)tex_res_st_offset.mV[VY]; + + st_scale /= this_proj_scale; + + // Convert aligned legacy TE transform back to GLTF transform + LLGLTFMaterial::convertTextureTransformToPBR( + st_scale.mV[0], st_scale.mV[1], + tex_res_st_offset.mV[0], tex_res_st_offset.mV[1], + z_ang, + *res_st_scale, *res_st_offset, *res_st_rot); + + return true; +} + void LLFace::updateRebuildFlags() { if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) diff --git a/indra/newview/llface.h b/indra/newview/llface.h index df31e9ea90..6e9d23c3a2 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -103,6 +103,8 @@ public: LLVector3 getPositionAgent() const; LLVector2 surfaceToTexture(LLVector2 surface_coord, const LLVector4a& position, const LLVector4a& normal); void getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_pos, F32* scale) const; + bool calcAlignedPlanarGLTF(const LLFace* align_to, LLVector2* res_st_offset, + LLVector2* res_st_scale, F32* res_st_rot, S32 gltf_info_index = 0) const; bool calcAlignedPlanarTE(const LLFace* align_to, LLVector2* st_offset, LLVector2* st_scale, F32* st_rot, LLRender::eTexIndex map = LLRender::DIFFUSE_MAP) const; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index bcb51b22ca..128ba42efd 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -852,6 +852,27 @@ struct LLPanelFaceSetAlignedTEFunctor : public LLSelectedTEFunctor LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, uv_scale.mV[VX], te, object->getID()); LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, uv_scale.mV[VY], te, object->getID()); } + + // Also align GLTF material if any + S32 gltf_info_index = 0; // base texture + LLVector2 gltf_offset, gltf_scale; + F32 gltf_rot; + if (facep->calcAlignedPlanarGLTF(mCenterFace, &gltf_offset, &gltf_scale, &gltf_rot, gltf_info_index)) + { + LLGLTFMaterial new_override; + const LLTextureEntry* tep = object->getTE(te); + if (tep && tep->getGLTFMaterialOverride()) + { + new_override = *tep->getGLTFMaterialOverride(); + } + + LLGLTFMaterial::TextureTransform& transform = new_override.mTextureTransform[gltf_info_index]; + transform.mOffset.set(gltf_offset.mV[0], gltf_offset.mV[1]); + transform.mScale.set(gltf_scale.mV[0], gltf_scale.mV[1]); + transform.mRotation = gltf_rot; + + LLGLTFMaterialList::queueModify(object, te, &new_override); + } } if (!set_aligned) { -- cgit v1.3 From e2e62f921d1a60a069f49b09efd941f6f91a0587 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Thu, 12 Mar 2026 22:10:05 +0200 Subject: #2975 Fix scale calculation Needs to account for rotation --- indra/llprimitive/llgltfmaterial.cpp | 62 ++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 7 deletions(-) (limited to 'indra/llprimitive/llgltfmaterial.cpp') diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp index 1c47001272..d1d8d43e78 100644 --- a/indra/llprimitive/llgltfmaterial.cpp +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -937,6 +937,12 @@ void LLGLTFMaterial::updateTextureTracking() // Case 4. // Input: scale 1.0,1.0; Offset horizontal 0.5, Offset vertical 0.0 Rotation 0.349066; // Expected output: scale 1.0,1.0; Offset horizontal 0.701, Offset vertical -0.141 Rotation -0.349066; +// Case 5. +// Input: scale 10.0,15.0; Offset horizontal 0.0, Offset vertical 0.0 Rotation -1.57079637 +// Expected output: scale 15.0,10.0; Offset horizontal 7.5, Offset vertical -4.0 Rotation 1.57079637; +// Case 6. +// Input: scale 10.0,15.0; Offset horizontal 0.0, Offset vertical 0.0 Rotation 0 +// Expected output: scale 10.0,15.0; Offset horizontal 0.5, Offset vertical .0 Rotation 0; // // Legacy offsets are right to left and top to bottom. // PBR offsets are right to left and bottom to top. @@ -953,16 +959,32 @@ void LLGLTFMaterial::convertTextureTransformToPBR( LLVector2& pbr_offset, F32& pbr_rotation) { - pbr_scale.set(tex_scale_s, tex_scale_t); + // Legacy is counter-clockwise, PBR is clockwise pbr_rotation = -tex_rotation; // Center of the tile const F32 center_s = 0.5f; const F32 center_t = 0.5f; + // Calculate the rotated scale + F32 cos_rot = cosf(tex_rotation); + F32 sin_rot = sinf(tex_rotation); + F32 cos_sq = cos_rot * cos_rot; + F32 sin_sq = sin_rot * sin_rot; + + // GLTF scale doesn't match legacy scaling when rotation is applied. + // Legacy applies scale then rotation, which allows for planar aligment + // withoutn deformations, but gltf rotates first, so when scale gets + // aplied image gets deformed by rotation. + // It appears to be imposible to properly match legacy scale, so this + // is an approximation that at least matches at 0, 90, 180, 270 degree + // rotations, and is close enough at angles like 45. + pbr_scale.mV[VX] = tex_scale_s * cos_sq + tex_scale_t * sin_sq; + pbr_scale.mV[VY] = tex_scale_s * sin_sq + tex_scale_t * cos_sq; + // Center adjustment for scale - F32 center_adjust_s = 0.5f * (1.0f - tex_scale_s); - F32 center_adjust_t = 0.5f * (1.0f - tex_scale_t); + F32 center_adjust_s = 0.5f * (1.0f - pbr_scale.mV[VX]); + F32 center_adjust_t = 0.5f * (1.0f - pbr_scale.mV[VY]); // 2. Offset from center F32 pos_s = center_adjust_s - center_s; @@ -990,17 +1012,43 @@ void LLGLTFMaterial::convertPBRTransformToTexture( F32& tex_offset_t, F32& tex_rotation) { - tex_scale_s = pbr_scale.mV[0]; - tex_scale_t = pbr_scale.mV[1]; tex_rotation = -pbr_rotation; + // Reverse the scale transformation + // From: pbr_s = tex_s * cos² + tex_t * sin² + // pbr_t = tex_s * sin² + tex_t * cos² + // Solve for tex_s and tex_t + F32 cos_rot = cosf(tex_rotation); + F32 sin_rot = sinf(tex_rotation); + F32 cos_sq = cos_rot * cos_rot; + F32 sin_sq = sin_rot * sin_rot; + + F32 denom = cos_sq * cos_sq - sin_sq * sin_sq; + + if (fabsf(denom) < 0.0001f) // Near 45 degrees (cos²≈sin²≈0.5) + { + // At 45°: both scales contribute equally + // pbr_s = pbr_t = (tex_s + tex_t) / 2 + // So: tex_s + tex_t = 2 * pbr_avg + // Use the average and assume symmetric scaling + tex_scale_s = tex_scale_t = (pbr_scale.mV[VX] + pbr_scale.mV[VY]) / 2.f; + } + else + { + // Solve the 2x2 system: + // pbr_s * cos² - pbr_t * sin² = tex_s * (cos⁴ - sin⁴) + // pbr_t * cos² - pbr_s * sin² = tex_t * (cos⁴ - sin⁴) + tex_scale_s = (pbr_scale.mV[VX] * cos_sq - pbr_scale.mV[VY] * sin_sq) / denom; + tex_scale_t = (pbr_scale.mV[VY] * cos_sq - pbr_scale.mV[VX] * sin_sq) / denom; + } + // Center of the tile const F32 center_s = 0.5f; const F32 center_t = 0.5f; // Center adjustment for scale - F32 center_adjust_s = 0.5f * (1.0f - tex_scale_s); - F32 center_adjust_t = 0.5f * (1.0f - tex_scale_t); + F32 center_adjust_s = 0.5f * (1.0f - pbr_scale.mV[VX]); + F32 center_adjust_t = 0.5f * (1.0f - pbr_scale.mV[VY]); // 2. Offset from center F32 pos_s = center_adjust_s - center_s; -- cgit v1.3 From f148dbcc8a9566f1f717fdeb00813ad57427bee7 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Fri, 13 Mar 2026 19:03:44 +0200 Subject: Mac build fix for a merge issue. --- indra/llprimitive/llgltfmaterial.cpp | 3 +++ indra/newview/llworldmapmessage.cpp | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/llprimitive/llgltfmaterial.cpp') diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp index d1d8d43e78..764ab222ad 100644 --- a/indra/llprimitive/llgltfmaterial.cpp +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -943,6 +943,9 @@ void LLGLTFMaterial::updateTextureTracking() // Case 6. // Input: scale 10.0,15.0; Offset horizontal 0.0, Offset vertical 0.0 Rotation 0 // Expected output: scale 10.0,15.0; Offset horizontal 0.5, Offset vertical .0 Rotation 0; +// Case 7. +// Input: scale 10.0,15.0; Offset horizontal 0.0, Offset vertical 0.0 Rotation -0.785398163 +// Expected output: scale 12.74,12.74; Offset horizontal 0.5, Offset vertical .0 Rotation 0.785398163; // // Legacy offsets are right to left and top to bottom. // PBR offsets are right to left and bottom to top. diff --git a/indra/newview/llworldmapmessage.cpp b/indra/newview/llworldmapmessage.cpp index a5433133ab..3264f8ae8b 100644 --- a/indra/newview/llworldmapmessage.cpp +++ b/indra/newview/llworldmapmessage.cpp @@ -34,7 +34,6 @@ #include "llfloaterworldmap.h" constexpr U32 LAYER_FLAG = 2; -constexpr S32 MAP_SIM_RETURN_NULL_SIMS = 0x00010000; //--------------------------------------------------------------------------- // World Map Message Handling -- cgit v1.3