summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llmeshoptimizer/llmeshoptimizer.cpp14
-rw-r--r--indra/llmeshoptimizer/llmeshoptimizer.h5
-rw-r--r--indra/newview/llfloatermodelpreview.cpp19
-rw-r--r--indra/newview/llmodelpreview.cpp203
-rw-r--r--indra/newview/llmodelpreview.h12
-rw-r--r--indra/newview/skins/default/xui/en/floater_model_preview.xml16
6 files changed, 255 insertions, 14 deletions
diff --git a/indra/llmeshoptimizer/llmeshoptimizer.cpp b/indra/llmeshoptimizer/llmeshoptimizer.cpp
index 770cd5aa3c..c46fa8dcf3 100644
--- a/indra/llmeshoptimizer/llmeshoptimizer.cpp
+++ b/indra/llmeshoptimizer/llmeshoptimizer.cpp
@@ -26,18 +26,24 @@
#include "llmeshoptimizer.h"
-#include "linden_common.h"
-
#include "meshoptimizer.h"
-#include "llmath.h"
LLMeshOptimizer::LLMeshOptimizer()
{
-
+ // Todo: Looks like for memory management, we can add allocator and deallocator callbacks
+ // Should be one time
+ // meshopt_setAllocator(allocate, deallocate);
}
LLMeshOptimizer::~LLMeshOptimizer()
{
}
+
+//static
+U32 LLMeshOptimizer::simplifyModel()
+{
+ LL_WARNS() << "NOT IMPLEMENTED" << LL_ENDL;
+ return 0;
+}
diff --git a/indra/llmeshoptimizer/llmeshoptimizer.h b/indra/llmeshoptimizer/llmeshoptimizer.h
index edce4edf05..d53ec2e24c 100644
--- a/indra/llmeshoptimizer/llmeshoptimizer.h
+++ b/indra/llmeshoptimizer/llmeshoptimizer.h
@@ -26,11 +26,16 @@
#ifndef LLMESHOPTIMIZER_H
#define LLMESHOPTIMIZER_H
+#include "linden_common.h"
+
class LLMeshOptimizer
{
public:
LLMeshOptimizer();
~LLMeshOptimizer();
+
+ // returns state
+ static U32 simplifyModel();
private:
};
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index d9edd4dc30..d8f3021fb2 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -722,7 +722,20 @@ void LLFloaterModelPreview::onAutoFillCommit(LLUICtrl* ctrl, void* userdata)
void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
{
- mModelPreview->onLODParamCommit(lod, enforce_tri_limit);
+ LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[lod]);
+ S32 mode = lod_source_combo->getCurrentIndex();
+ switch (mode)
+ {
+ case LLModelPreview::GENERATE:
+ mModelPreview->onLODGenerateParamCommit(lod, enforce_tri_limit);
+ break;
+ case LLModelPreview::MESH_OPTIMIZER:
+ mModelPreview->onLODMeshOptimizerParamCommit(lod, enforce_tri_limit);
+ break;
+ default:
+ LL_ERRS() << "Only supposed to be called to generate models" << LL_ENDL;
+ break;
+ }
//refresh LoDs that reference this one
for (S32 i = lod - 1; i >= 0; --i)
@@ -1721,7 +1734,9 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)
refresh();
LLComboBox* lod_source_combo = getChild<LLComboBox>("lod_source_" + lod_name[lod]);
- if (lod_source_combo->getCurrentIndex() == LLModelPreview::GENERATE)
+ S32 index = lod_source_combo->getCurrentIndex();
+ if (index == LLModelPreview::GENERATE
+ || index == LLModelPreview::MESH_OPTIMIZER)
{ //rebuild LoD to update triangle counts
onLODParamCommit(lod, true);
}
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index a9e80ab5da..a6eef74cdc 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -41,6 +41,7 @@
#include "lliconctrl.h"
#include "llmatrix4a.h"
#include "llmeshrepository.h"
+#include "llmeshoptimizer.h"
#include "llrender.h"
#include "llsdutil_math.h"
#include "llskinningutil.h"
@@ -1339,7 +1340,7 @@ void LLModelPreview::restoreNormals()
updateStatusMessages();
}
-void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_limit)
+void LLModelPreview::genGlodLODs(S32 which_lod, U32 decimation, bool enforce_tri_limit)
{
// Allow LoD from -1 to LLModel::LOD_PHYSICS
if (which_lod < -1 || which_lod > LLModel::NUM_LODS - 1)
@@ -1424,7 +1425,7 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim
mRequestedLoDMode[which_lod] = lod_mode;
}
- if (lod_mode == 0)
+ if (lod_mode == LIMIT_TRIANGLES)
{
lod_mode = GLOD_TRIANGLE_BUDGET;
@@ -2957,7 +2958,7 @@ BOOL LLModelPreview::render()
{
genBuffers(-1, skin_weight);
//genBuffers(3);
- //genLODs();
+ //genGlodLODs();
}
if (!mModel[mPreviewLOD].empty())
@@ -3544,7 +3545,7 @@ bool LLModelPreview::lodQueryCallback()
{
S32 lod = preview->mLodsQuery.back();
preview->mLodsQuery.pop_back();
- preview->genLODs(lod);
+ preview->genGlodLODs(lod);
if (preview->mLookUpLodFiles && (lod == LLModel::LOD_HIGH))
{
@@ -3559,12 +3560,202 @@ bool LLModelPreview::lodQueryCallback()
return true;
}
-void LLModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
+void LLModelPreview::onLODGenerateParamCommit(S32 lod, bool enforce_tri_limit)
{
if (!mLODFrozen)
{
- genLODs(lod, 3, enforce_tri_limit);
+ genGlodLODs(lod, 3, enforce_tri_limit);
refresh();
}
}
+void LLModelPreview::onLODMeshOptimizerParamCommit(S32 lod, bool enforce_tri_limit)
+{
+ if (mLODFrozen)
+ {
+ return;
+ }
+
+ // Allow LoD from -1 to LLModel::LOD_PHYSICS
+ if (lod < -1 || lod > LLModel::NUM_LODS - 1)
+ {
+ std::ostringstream out;
+ out << "Invalid level of detail: " << lod;
+ LL_WARNS() << out.str() << LL_ENDL;
+ LLFloaterModelPreview::addStringToLog(out, false);
+ assert(lod >= -1 && lod < LLModel::NUM_LODS);
+ return;
+ }
+
+ if (mBaseModel.empty())
+ {
+ return;
+ }
+
+
+ U32 triangle_count = 0;
+ U32 instanced_triangle_count = 0;
+
+ //get the triangle count for the whole scene
+ for (LLModelLoader::scene::iterator iter = mBaseScene.begin(), endIter = mBaseScene.end(); iter != endIter; ++iter)
+ {
+ for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance)
+ {
+ LLModel* mdl = instance->mModel;
+ if (mdl)
+ {
+ instanced_triangle_count += mdl->getNumTriangles();
+ }
+ }
+ }
+
+ //get the triangle count for the non-instanced set of models
+ for (U32 i = 0; i < mBaseModel.size(); ++i)
+ {
+ triangle_count += mBaseModel[i]->getNumTriangles();
+ }
+
+ //get ratio of uninstanced triangles to instanced triangles
+ F32 triangle_ratio = (F32)triangle_count / (F32)instanced_triangle_count;
+ U32 base_triangle_count = triangle_count;
+ U32 lod_mode = 0;
+ F32 lod_error_threshold = 0;
+
+
+ // Urgh...
+ // TODO: add interface to mFMP to get error treshold or let mFMP write one into LLModelPreview
+ // We should not be accesing views from other class!
+ LLCtrlSelectionInterface* iface = mFMP->childGetSelectionInterface("lod_mode_" + lod_name[lod]);
+ if (iface)
+ {
+ lod_mode = iface->getFirstSelectedIndex();
+ }
+
+ lod_error_threshold = mFMP->childGetValue("lod_error_threshold_" + lod_name[lod]).asReal();
+
+ if (lod != -1)
+ {
+ mRequestedLoDMode[lod] = lod_mode;
+ }
+
+ S32 limit = -1;
+ if (lod_mode == LIMIT_TRIANGLES)
+ {
+ limit = mFMP->childGetValue("lod_triangle_limit_" + lod_name[lod]).asInteger();
+ //convert from "scene wide" to "non-instanced" triangle limit
+ limit = (S32)((F32)limit*triangle_ratio);
+ }
+
+ // Glod regenerates vertex buffer at this stage
+
+ // Build models
+
+ S32 start = LLModel::LOD_HIGH;
+ S32 end = 0;
+ S32 decimation = 3;
+
+ if (lod != -1)
+ {
+ start = lod;
+ end = lod;
+ }
+
+ mMaxTriangleLimit = base_triangle_count;
+
+ for (S32 lod = start; lod >= end; --lod)
+ {
+ if (lod == -1)
+ {
+ if (lod < start)
+ {
+ triangle_count /= decimation;
+ }
+ }
+ else
+ {
+ if (enforce_tri_limit)
+ {
+ triangle_count = limit;
+ }
+ else
+ {
+ for (S32 j = LLModel::LOD_HIGH; j > lod; --j)
+ {
+ triangle_count /= decimation;
+ }
+ }
+ }
+
+ mModel[lod].clear();
+ mModel[lod].resize(mBaseModel.size());
+ mVertexBuffer[lod].clear();
+
+ mRequestedTriangleCount[lod] = (S32)((F32)triangle_count / triangle_ratio);
+ mRequestedErrorThreshold[lod] = lod_error_threshold;
+
+ for (U32 mdl_idx = 0; mdl_idx < mBaseModel.size(); ++mdl_idx)
+ {
+ LLModel* base = mBaseModel[mdl_idx];
+
+ LLVolumeParams volume_params;
+ volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
+ mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f);
+
+ std::string name = base->mLabel + getLodSuffix(lod);
+
+ mModel[lod][mdl_idx]->mLabel = name;
+ mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID;
+ //mModel[lod][mdl_idx]->setNumVolumeFaces( );
+
+ LLModel* target_model = mModel[lod][mdl_idx];
+
+
+ //
+ LLMeshOptimizer::simplifyModel(/*Some params*/);
+
+ //blind copy skin weights and just take closest skin weight to point on
+ //decimated mesh for now (auto-generating LODs with skin weights is still a bit
+ //of an open problem).
+ target_model->mPosition = base->mPosition;
+ target_model->mSkinWeights = base->mSkinWeights;
+ target_model->mSkinInfo = base->mSkinInfo;
+ //copy material list
+ target_model->mMaterialList = base->mMaterialList;
+
+ if (!validate_model(target_model))
+ {
+ LL_ERRS() << "Invalid model generated when creating LODs" << LL_ENDL;
+ }
+ }
+
+ //rebuild scene based on mBaseScene
+ mScene[lod].clear();
+ mScene[lod] = mBaseScene;
+
+ for (U32 i = 0; i < mBaseModel.size(); ++i)
+ {
+ LLModel* mdl = mBaseModel[i];
+ LLModel* target = mModel[lod][i];
+ if (target)
+ {
+ for (LLModelLoader::scene::iterator iter = mScene[lod].begin(); iter != mScene[lod].end(); ++iter)
+ {
+ for (U32 j = 0; j < iter->second.size(); ++j)
+ {
+ if (iter->second[j].mModel == mdl)
+ {
+ iter->second[j].mModel = target;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ mResourceCost = calcResourceCost();
+
+
+ LLMeshOptimizer::simplifyModel();
+ refresh();
+}
+
diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h
index 3664a27a72..df66d79b7b 100644
--- a/indra/newview/llmodelpreview.h
+++ b/indra/newview/llmodelpreview.h
@@ -125,9 +125,16 @@ public:
{
LOD_FROM_FILE = 0,
GENERATE,
+ MESH_OPTIMIZER,
USE_LOD_ABOVE,
} eLoDMode;
+ typedef enum
+ {
+ LIMIT_TRIANGLES = 0,
+ LIMIT_ERROR_TRESHOLD,
+ } eLoDLimit;
+
public:
// Todo: model preview shouldn't need floater dependency, it
// should just expose data to floater, not control flaoter like it does
@@ -155,7 +162,7 @@ public:
void loadModelCallback(S32 lod);
bool lodsReady() { return !mGenLOD && mLodsQuery.empty(); }
void queryLODs() { mGenLOD = true; };
- void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
+ void genGlodLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
void generateNormals();
void restoreNormals();
U32 calcResourceCost();
@@ -166,7 +173,8 @@ public:
void updateStatusMessages();
void updateLodControls(S32 lod);
void clearGLODGroup();
- void onLODParamCommit(S32 lod, bool enforce_tri_limit);
+ void onLODGenerateParamCommit(S32 lod, bool enforce_tri_limit);
+ void onLODMeshOptimizerParamCommit(S32 lod, bool enforce_tri_limit);
void addEmptyFace(LLModel* pTarget);
const bool getModelPivot(void) const { return mHasPivot; }
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml
index 7f863756eb..96bda42316 100644
--- a/indra/newview/skins/default/xui/en/floater_model_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml
@@ -176,6 +176,10 @@
name="Generate"
label="Generate"
value="Generate" />
+ <item
+ name="MeshOpt"
+ label="MeshOpt"
+ value="MeshOpt" />
</combo_box>
<line_editor
follows="left|top"
@@ -306,6 +310,10 @@
label="Generate"
value="Generate" />
<item
+ name="MeshOpt"
+ label="MeshOpt"
+ value="MeshOpt" />
+ <item
name="Use LoD above"
label="Use LoD above"
value="Use LoD above" />
@@ -439,6 +447,10 @@
label="Generate"
value="Generate" />
<item
+ name="MeshOpt"
+ label="MeshOpt"
+ value="MeshOpt" />
+ <item
name="Use LoD above"
label="Use LoD above"
value="Use LoD above" />
@@ -572,6 +584,10 @@
label="Generate"
value="Generate" />
<item
+ name="MeshOpt"
+ label="MeshOpt"
+ value="MeshOpt" />
+ <item
name="Use LoD above"
label="Use LoD above"
value="Use LoD above" />