diff options
| author | Erik Kundiman <erik@megapahit.org> | 2026-09-23 13:20:38 +0800 |
|---|---|---|
| committer | Erik Kundiman <erik@megapahit.org> | 2026-09-23 13:20:38 +0800 |
| commit | 8d89fd3a93f78ee81d69f3b57c4d514d483567be (patch) | |
| tree | c5b33bcc4429e91d61029ea8381d959ef44ced69 /indra/llmath | |
| parent | 8557e9659ca5b71aabcbb21758be03a959c2098d (diff) | |
| parent | 62025f0e343e065a39667886357564be79202d42 (diff) | |
Merge tag 'Second_Life_Release#62025f0e-26.4' into 26.4
Diffstat (limited to 'indra/llmath')
| -rw-r--r-- | indra/llmath/llvolume.cpp | 161 | ||||
| -rw-r--r-- | indra/llmath/llvolume.h | 11 |
2 files changed, 7 insertions, 165 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index a029fea992..e2407860b3 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1972,8 +1972,6 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const bool ge mNumHullIndices = 0; // set defaults - mSculptValidationCache.fill(LLSculptValidationState::Unvalidated); - if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) { mPathp = new LLDynamicPath(); @@ -2001,13 +1999,6 @@ void LLVolume::resizePath(S32 length) setDirty(); } -void LLVolume::setDirty() -{ - mPathp->setDirty(); - mProfilep->setDirty(); - mSculptValidationCache.fill(LLSculptValidationState::Unvalidated); -} - void LLVolume::regen() { generate(); @@ -3289,100 +3280,10 @@ S32 sculpt_sides(F32 detail) } } -static bool validate_sculpt_geometry(const LLVolume* volume, bool validate_area) -{ - if (!volume || volume->getNumVolumeFaces() == 0) - { - return true; - } - - // Validate each face in the sculpt - for (S32 face_idx = 0; face_idx < volume->getNumVolumeFaces(); ++face_idx) - { - const LLVolumeFace& face = volume->getVolumeFace(face_idx); - - // Skip validation for degenerate faces - if (face.mNumVertices < 3 || face.mNumIndices < 3) - { - continue; - } - - // Calculate 'bounding' surface - LLVector4a extent_size; - extent_size.setSub(face.mExtents[1], face.mExtents[0]); - - F32 width = extent_size[0]; - F32 height = extent_size[1]; - F32 depth = extent_size[2]; - - F32 bounding_surface = width * height + width * depth + height * depth; - bounding_surface *= 2; - - if (!llfinite(bounding_surface) || bounding_surface <= FLT_EPSILON) - { - return false; - } - - // Calculate total surface area of all triangles - F32 total_triangle_area = 0.0f; - S32 num_triangles = face.mNumIndices / 3; - - for (S32 i = 0; i < num_triangles; ++i) - { - S32 idx_base = i * 3; - U16 idx0 = face.mIndices[idx_base]; - U16 idx1 = face.mIndices[idx_base + 1]; - U16 idx2 = face.mIndices[idx_base + 2]; - - // Validate indices - if (idx0 >= face.mNumVertices || idx1 >= face.mNumVertices || idx2 >= face.mNumVertices) - { - continue; - } - - const LLVector4a& v0 = face.mPositions[idx0]; - const LLVector4a& v1 = face.mPositions[idx1]; - const LLVector4a& v2 = face.mPositions[idx2]; - - // Calculate triangle area - LLVector4a edge1, edge2, cross; - edge1.setSub(v1, v0); - edge2.setSub(v2, v0); - cross.setCross3(edge1, edge2); - - F32 triangle_area = cross.getLength3().getF32() * 0.5f; - total_triangle_area += triangle_area; - } - - if (!llfinite(total_triangle_area)) - { - return false; - } - - // The idea here is that the total area of a sculpt is normally comparable - // to the area of a bounding box. But a random overlapping collection of - // triangles has a significantly larger area than a sculpt normally has. - F32 area_ratio = total_triangle_area / bounding_surface; - constexpr F32 MAX_AREA_TO_AREA_RATIO = 16.0f; - if (validate_area && area_ratio > MAX_AREA_TO_AREA_RATIO) - { - LL_DEBUGS("LLVOLUME") << "Sculpt rejected: excessive triangle area." - << " Face index: " << face_idx - << " Total triangle area: " << total_triangle_area << " sq m" - << " Bounding surface area: " << bounding_surface << " sq m" - << " Ratio: " << area_ratio - << " Triangle count: " << num_triangles - << " Bounds: [" << width << " x " << height << " x " << depth << "]" << LL_ENDL; - return false; - } - } - - return true; -} // determine the number of vertices in both s and t direction for this sculpt -static void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32& s, S32& t) +void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32& s, S32& t) { // this code has the following properties: // 1) the aspect ratio of the mesh is as close as possible to the ratio of the map @@ -3417,7 +3318,7 @@ static void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 deta } // sculpt replaces generate() for sculpted surfaces -void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder, bool validate_area) +void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder) { U8 sculpt_type = mParams.getSculptType(); @@ -3492,62 +3393,10 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, mSculptLevel = sculpt_level; - LLSculptValidationState cached_state = LLSculptValidationState::Valid; - if (!data_is_empty && (sculpt_level >= 0) && sculpt_level < SCULPT_CACHE_SIZE) - { - // validation might be expensive, so we do it only once per lod. - cached_state = mSculptValidationCache[sculpt_level]; - } - - switch (cached_state) - { - case LLSculptValidationState::Valid: - { - // Delete any existing faces, then regenerate - mVolumeFaces.clear(); - createVolumeFaces(); - break; - } - case LLSculptValidationState::Invalid: - { - // Invalid geometry - // Regenerate mesh with an empty placeholder - mVolumeFaces.clear(); - sculptGenerateEmptyPlaceholder(); - createVolumeFaces(); - break; - } - case LLSculptValidationState::Unvalidated: - { - // First time at this LOD - mVolumeFaces.clear(); - createVolumeFaces(); - - bool valid_geometry = true; - - // Todo: can this be backed into createVolumeFaces? - // Or calculated without having to call createVolumeFaces first? - // Todo 2: should the same be done for meshes? - valid_geometry = validate_sculpt_geometry(this, validate_area); - mSculptValidationCache[sculpt_level] = valid_geometry ? LLSculptValidationState::Valid : LLSculptValidationState::Invalid; - - if (!valid_geometry) - { - LL_WARNS("LLVOLUME") << "Sculpt failed geometry validation - either invalid image or malicious. " - << "Replacing with placeholder. Image: " << mParams.getSculptID() << LL_ENDL; - - // Clear the malicious faces - mVolumeFaces.clear(); - - // Regenerate mesh with empty placeholder - sculptGenerateEmptyPlaceholder(); + // Delete any existing faces so that they get regenerated + mVolumeFaces.clear(); - // Recreate faces with placeholder geometry - createVolumeFaces(); - } - break; - } - } //switch (cached_state) + createVolumeFaces(); } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 40e6f8e220..3496928f7b 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -60,8 +60,6 @@ class LLVolumeOctree; #include "llalignedarray.h" #include "llrigginginfo.h" -#include <array> - //============================================================================ constexpr S32 MIN_DETAIL_FACES = 6; @@ -1042,7 +1040,7 @@ public: const LLVector4a& getMeshPt(const U32 i) const { return mMesh[i]; } - void setDirty(); + void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); } void regen(); void genTangents(S32 face); @@ -1095,7 +1093,7 @@ public: U32 mFaceMask; // bit array of which faces exist in this volume LLVector3 mLODScaleBias; // vector for biasing LOD based on scale - void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder, bool validate_area); + void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder); void copyVolumeFaces(const LLVolume* volume); void copyFacesTo(std::vector<LLVolumeFace> &faces) const; void copyFacesFrom(const std::vector<LLVolumeFace> &faces); @@ -1133,11 +1131,6 @@ public: bool mIsMeshAssetLoaded; bool mIsMeshAssetUnavaliable; - // Cache for sculpt geometry validation results - static constexpr S32 SCULPT_CACHE_SIZE = 6; // 0 to 5 inclusive - enum class LLSculptValidationState : S8 { Unvalidated, Valid, Invalid }; - std::array<LLSculptValidationState, SCULPT_CACHE_SIZE> mSculptValidationCache; - const LLVolumeParams mParams; LLPath *mPathp; LLProfile *mProfilep; |
