diff options
author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2022-02-24 00:35:00 +0200 |
---|---|---|
committer | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2022-02-24 14:42:04 +0200 |
commit | 21baea0907027c655c5170975c0ea669430c9c40 (patch) | |
tree | 3299a4e2fe79973f39c7679e4332b571b65cea66 | |
parent | 1af45ee1dfdda1e6408e5f9b3fdeee9a2647bfd0 (diff) |
SL-3787 Fixed mesh uploader LoD generation returning worse results than higher lod
-rw-r--r-- | indra/newview/llmodelpreview.cpp | 61 |
1 files changed, 44 insertions, 17 deletions
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 5d81d2c9b3..9e5a31d71e 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -1759,19 +1759,15 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d { genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, true); } - - LL_INFOS() << "Model " << target_model->getName() - << " lod " << which_lod - << " simplified using per face method." << LL_ENDL; } if (model_meshopt_mode == MESH_OPTIMIZER_AUTO) { - // Switches between 'combine' method and 'per model sloppy' based on combine's result. + // Switches between 'combine' method and 'sloppy' based on combine's result. F32 allowed_ratio_drift = 2.f; - F32 res_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); - - if (res_ratio < 0) + F32 precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); + + if (precise_ratio < 0) { // U16 vertices overflow, shouldn't happen, but just in case for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx) @@ -1779,42 +1775,72 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d genMeshOptimizerPerFace(base, target_model, face_idx, indices_decimator, lod_error_threshold, false); } } - else if (res_ratio * allowed_ratio_drift < indices_decimator) + else if (precise_ratio * allowed_ratio_drift < indices_decimator) { // Try sloppy variant if normal one failed to simplify model enough. - res_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); + // Sloppy variant can fail entirely and has issues with precision, + // so code needs to do multiple attempts with different decimators. + // Todo: this is a bit of a mess, needs to be refined and improved + F32 last_working_decimator = 0.f; + F32 last_working_ratio = F32_MAX; + + F32 sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); + + if (sloppy_ratio > 0) + { + // Would be better to do a copy of target_model here, but if + // we need to use sloppy decimation, model should be cheap + // and fast to generate and it won't affect end result + last_working_decimator = indices_decimator; + last_working_ratio = sloppy_ratio; + } // Sloppy has a tendecy to error into lower side, so a request for 100 // triangles turns into ~70, so check for significant difference from target decimation F32 sloppy_ratio_drift = 1.4f; if (lod_mode == LIMIT_TRIANGLES - && (res_ratio > indices_decimator * sloppy_ratio_drift || res_ratio < 0)) + && (sloppy_ratio > indices_decimator * sloppy_ratio_drift || sloppy_ratio < 0)) { // Apply a correction to compensate. // (indices_decimator / res_ratio) by itself is likely to overshoot to a differend // side due to overal lack of precision, and we don't need an ideal result, which // likely does not exist, just a better one, so a partial correction is enough. - F32 sloppy_decimator = indices_decimator * (indices_decimator / res_ratio + 1) / 2; - res_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); + F32 sloppy_decimator = indices_decimator * (indices_decimator / sloppy_ratio + 1) / 2; + sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, true); } + if (last_working_decimator > 0 && sloppy_ratio < last_working_ratio) + { + // Compensation didn't work, return back to previous decimator + sloppy_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, true); + } + + 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); + } - if (res_ratio < 0) + if (sloppy_ratio < 0 || sloppy_ratio < precise_ratio) { - // Sloppy variant failed to generate triangles. + // Sloppy variant failed to generate triangles or is worse. // Can happen with models that are too simple as is. - // Fallback to normal method or use lower decimator. - genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); + // Fallback to normal method + + precise_ratio = genMeshOptimizerPerModel(base, target_model, indices_decimator, lod_error_threshold, false); LL_INFOS() << "Model " << target_model->getName() << " lod " << which_lod + << " resulting ratio " << precise_ratio << " simplified using per model method." << LL_ENDL; } else { LL_INFOS() << "Model " << target_model->getName() << " lod " << which_lod + << " resulting ratio " << sloppy_ratio << " sloppily simplified using per model method." << LL_ENDL; } } @@ -1822,6 +1848,7 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d { LL_INFOS() << "Model " << target_model->getName() << " lod " << which_lod + << " resulting ratio " << precise_ratio << " simplified using per model method." << LL_ENDL; } } |