summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2022-02-24 00:35:00 +0200
committerAndrey Kleshchev <andreykproductengine@lindenlab.com>2022-02-24 14:42:04 +0200
commit21baea0907027c655c5170975c0ea669430c9c40 (patch)
tree3299a4e2fe79973f39c7679e4332b571b65cea66
parent1af45ee1dfdda1e6408e5f9b3fdeee9a2647bfd0 (diff)
SL-3787 Fixed mesh uploader LoD generation returning worse results than higher lod
-rw-r--r--indra/newview/llmodelpreview.cpp61
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;
}
}