DRTVWR-542 WIP
parent
97c954dd84
commit
7b7b8a8da8
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -176,6 +176,10 @@
|
|||
name="Generate"
|
||||
label="Generate"
|
||||
value="Generate" />
|
||||
<item
|
||||
name="MeshOpt"
|
||||
label="MeshOpt"
|
||||
value="MeshOpt" />
|
||||
</combo_box>
|
||||
<line_editor
|
||||
follows="left|top"
|
||||
|
|
@ -305,6 +309,10 @@
|
|||
name="Generate"
|
||||
label="Generate"
|
||||
value="Generate" />
|
||||
<item
|
||||
name="MeshOpt"
|
||||
label="MeshOpt"
|
||||
value="MeshOpt" />
|
||||
<item
|
||||
name="Use LoD above"
|
||||
label="Use LoD above"
|
||||
|
|
@ -438,6 +446,10 @@
|
|||
name="Generate"
|
||||
label="Generate"
|
||||
value="Generate" />
|
||||
<item
|
||||
name="MeshOpt"
|
||||
label="MeshOpt"
|
||||
value="MeshOpt" />
|
||||
<item
|
||||
name="Use LoD above"
|
||||
label="Use LoD above"
|
||||
|
|
@ -571,6 +583,10 @@
|
|||
name="Generate"
|
||||
label="Generate"
|
||||
value="Generate" />
|
||||
<item
|
||||
name="MeshOpt"
|
||||
label="MeshOpt"
|
||||
value="MeshOpt" />
|
||||
<item
|
||||
name="Use LoD above"
|
||||
label="Use LoD above"
|
||||
|
|
|
|||
Loading…
Reference in New Issue