summaryrefslogtreecommitdiff
path: root/indra/llprimitive
diff options
context:
space:
mode:
authorErik Kundiman <erik@megapahit.org>2026-03-07 14:55:05 +0800
committerErik Kundiman <erik@megapahit.org>2026-03-07 14:55:05 +0800
commiteac10375e294cd24c21c09497e838e70dcf4d74a (patch)
tree4b53b1ebc1582e3323c80953236dca6b3a92ab65 /indra/llprimitive
parent8142dd11b4cae8d4768a2d985a24340163a42a5c (diff)
parent3529bc5f9d29a71355f3a3666540abff57dc1a4c (diff)
Merge tag 'Second_Life_Release#3529bc5f-2026.02' into 2026.02
Diffstat (limited to 'indra/llprimitive')
-rw-r--r--indra/llprimitive/llgltfmaterial.cpp92
-rw-r--r--indra/llprimitive/llgltfmaterial.h8
-rw-r--r--indra/llprimitive/llmaterialid.h30
-rw-r--r--indra/llprimitive/llprimitive.h9
4 files changed, 109 insertions, 30 deletions
diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp
index 930222e3db..1c47001272 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)
@@ -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 6bb021254b..64b585aacf 100644
--- a/indra/llprimitive/llgltfmaterial.h
+++ b/indra/llprimitive/llgltfmaterial.h
@@ -223,6 +223,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<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value);
static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value);
diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h
index bd6256d961..41dd5a8710 100644
--- a/indra/llprimitive/llmaterialid.h
+++ b/indra/llprimitive/llmaterialid.h
@@ -67,15 +67,11 @@ public:
static const LLMaterialID null;
- // Returns a 64 bits digest of the material Id, by XORing its two 64 bits
- // long words. HB
- inline U64 getDigest64() const
- {
- U64* tmp = (U64*)mID;
- return tmp[0] ^ tmp[1];
- }
-
private:
+ // definitions follow class
+ friend std::hash<LLMaterialID>;
+ friend size_t hash_value(const LLMaterialID&) noexcept;
+
void parseFromBinary(const LLSD::Binary& pMaterialID);
void copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID);
int compareToOtherMaterialID(const LLMaterialID& pOtherMaterialID) const;
@@ -90,15 +86,27 @@ namespace std
{
inline size_t operator()(const LLMaterialID& id) const noexcept
{
- return (size_t)id.getDigest64();
+ size_t h = 0;
+ // Golden ratio hash with avalanche mixing
+ // Process 8 bytes at a time by manually constructing 64-bit values
+ // Shift by 31: mixes upper half into lower half for better bit distribution
+ // Shift by 47: ensures highest bits influence final hash output
+ for (int i = 0; i < MATERIAL_ID_SIZE; i += 8) {
+ size_t chunk = (size_t)id.mID[i] | ((size_t)id.mID[i + 1] << 8) |
+ ((size_t)id.mID[i+2] << 16) | ((size_t)id.mID[i+3] << 24) |
+ ((size_t)id.mID[i+4] << 32) | ((size_t)id.mID[i+5] << 40) |
+ ((size_t)id.mID[i + 6] << 48) | ((size_t)id.mID[i + 7] << 56);
+ h ^= (chunk * 0x9e3779b97f4a7c15ULL) ^ (h >> 31) ^ (h >> 47);
+ }
+ return h;
}
};
}
-// For use with boost containers.
+// For use with boost::container_hash
inline size_t hash_value(const LLMaterialID& id) noexcept
{
- return (size_t)id.getDigest64();
+ return std::hash<LLMaterialID>{}(id);
}
#endif // LL_LLMATERIALID_H
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 31bc76344c..c3e3e19ee9 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -109,11 +109,12 @@ public:
PARAMS_EXTENDED_MESH = 0x70,
PARAMS_RENDER_MATERIAL = 0x80,
PARAMS_REFLECTION_PROBE = 0x90,
+ PARAMS_MAX = PARAMS_REFLECTION_PROBE,
};
public:
U16 mType;
- virtual ~LLNetworkData() {};
+ virtual ~LLNetworkData() = default;
virtual bool pack(LLDataPacker &dp) const = 0;
virtual bool unpack(LLDataPacker &dp) = 0;
virtual bool operator==(const LLNetworkData& data) const = 0;
@@ -319,7 +320,7 @@ public:
bool fromLLSD(LLSD& sd);
void setSculptTexture(const LLUUID& texture_id, U8 sculpt_type);
- LLUUID getSculptTexture() const { return mSculptTexture; }
+ const LLUUID& getSculptTexture() const { return mSculptTexture; }
U8 getSculptType() const { return mSculptType; }
};
@@ -340,10 +341,10 @@ public:
bool fromLLSD(LLSD& sd);
void setLightTexture(const LLUUID& id) { mLightTexture = id; }
- LLUUID getLightTexture() const { return mLightTexture; }
+ const LLUUID& getLightTexture() const { return mLightTexture; }
bool isLightSpotlight() const { return mLightTexture.notNull(); }
void setParams(const LLVector3& params) { mParams = params; }
- LLVector3 getParams() const { return mParams; }
+ const LLVector3& getParams() const { return mParams; }
};