diff options
-rw-r--r-- | indra/llmeshoptimizer/llmeshoptimizer.cpp | 14 | ||||
-rw-r--r-- | indra/llmeshoptimizer/llmeshoptimizer.h | 5 | ||||
-rw-r--r-- | indra/newview/llfloatermodelpreview.cpp | 19 | ||||
-rw-r--r-- | indra/newview/llmodelpreview.cpp | 203 | ||||
-rw-r--r-- | indra/newview/llmodelpreview.h | 12 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_model_preview.xml | 16 |
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" /> |