From c141ecdcc2f074145b0a25087396be73a2e5ce7a Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Fri, 25 Feb 2022 13:36:35 +0200
Subject: [PATCH] SL-3787 Fixed sloppy mode returning invalid model

In automatic mode for simple models gradualy increase sloppy decimator until something valid is found.
---
 indra/newview/llmodelpreview.cpp | 41 ++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index 9e5a31d71e9..6bbe27d101a 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -1757,7 +1757,11 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
                 // Run meshoptimizer for each face
                 for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)
                 {
-                    genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, true);
+                    if (genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, true) < 0)
+                    {
+                        // Sloppy failed and returned an invalid model
+                        genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false);
+                    }
                 }
             }
 
@@ -1818,9 +1822,38 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
 
                     if (sloppy_ratio < 0)
                     {
-                        // sloppy method didn't work, final attempt with lower decimation
-                        F32 sloppy_decimator = indices_decimator / decimation;
-                        sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true);
+                        // Sloppy method didn't work, try with smaller decimation values
+                        S32 size_vertices = 0;
+
+                        for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx)
+                        {
+                            const LLVolumeFace &face = base->getVolumeFace(face_idx);
+                            size_vertices += face.mNumVertices;
+                        }
+
+                        // Complex models aren't supposed to get here, they are supposed
+                        // to work on a first try of sloppy due to having more viggle room.
+                        // If they didn't, something is likely wrong, no point locking the
+                        // thread in a long calculation that will fail.
+                        const U32 too_many_vertices = 27000;
+                        if (size_vertices > too_many_vertices)
+                        {
+                            LL_WARNS() << "Sloppy optimization method failed for a complex model " << target_model->getName() << LL_ENDL;
+                        }
+                        else
+                        {
+                            // Find a decimator that does work
+                            F32 sloppy_decimation_step = sqrt((F32)decimation); // example: 27->15->9->5->3
+                            F32 sloppy_decimator = indices_decimator / sloppy_decimation_step;
+
+                            while (sloppy_ratio < 0
+                                && sloppy_decimator > precise_ratio
+                                && sloppy_decimator > 1)// precise_ratio isn't supposed to be below 1, but check just in case
+                            {
+                                sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true);
+                                sloppy_decimator = sloppy_decimator / sloppy_decimation_step;
+                            }
+                        }
                     }
 
                     if (sloppy_ratio < 0 || sloppy_ratio < precise_ratio)
-- 
GitLab