Restore GLOD alongside MeshOpt

master
Beq 2022-07-28 15:33:10 +01:00
parent d828e79185
commit 00875f93d0
13 changed files with 751 additions and 5 deletions

View File

@ -235,6 +235,100 @@
</map>
</map>
</map>
<key>glod</key>
<map>
<key>copyright</key>
<string>Copyright 2003 Jonathan Cohen, Nat Duca, David Luebke, Brenden Schubert - Johns Hopkins University and University of Virginia</string>
<key>license</key>
<string>GLOD Open-Source License Version 1.0</string>
<key>license_file</key>
<string>LICENSES/GLOD.txt</string>
<key>name</key>
<string>glod</string>
<key>platforms</key>
<map>
<key>darwin</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>94fc457c46e1fb94b31251bd4747d10f</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>http://3p.firestormviewer.org/glod-1.0pre3.171101143-darwin64-171101143.tar.bz2</string>
</map>
<key>name</key>
<string>darwin</string>
</map>
<key>darwin64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>94fc457c46e1fb94b31251bd4747d10f</string>
<key>url</key>
<string>http://3p.firestormviewer.org/glod-1.0pre3.171101143-darwin64-171101143.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
</map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>3bae1e9a188680a81c1d5b32571538b9</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>http://3p.firestormviewer.org/glod-1.0pre3.180990859-linux-180990859.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
<key>linux64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>acc1181cd31ef32c3724eda84ae4b580</string>
<key>url</key>
<string>http://3p.firestormviewer.org/glod-1.0pre3.180990827-linux64-180990827.tar.bz2</string>
</map>
<key>name</key>
<string>linux64</string>
</map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>e1f8da12a2b7a6c31830b4bb86d31ed6</string>
<key>hash_algorithm</key>
<string>md5</string>
<key>url</key>
<string>http://3p.firestormviewer.org/glod-1.0pre3.vs2017-1906061512-windows-vs2017-1906061512.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
<key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>e906cf08bfbfbd9d4fc78557e021e7d0</string>
<key>url</key>
<string>http://3p.firestormviewer.org/glod-1.0pre3.vs2017-1906061512-windows64-vs2017-1906061512.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>1.0pre3.532346</string>
</map>
<key>gntp-growl</key>
<map>
<key>copyright</key>

View File

@ -40,6 +40,7 @@ set(cmake_SOURCE_FILES
FreeType.cmake
GLEXT.cmake
GLH.cmake
GLOD.cmake
## GStreamer010Plugin.cmake
GoogleMock.cmake
Growl.cmake

View File

@ -57,6 +57,7 @@ if(WINDOWS)
libaprutil-1.dll
libapriconv-1.dll
nghttp2.dll
glod.dll # <FS:Beq> restore GLOD
libhunspell.dll
uriparser.dll
)
@ -198,6 +199,7 @@ elseif(DARWIN)
libaprutil-1.0.dylib
libaprutil-1.dylib
${EXPAT_COPY}
libGLOD.dylib # <FS:Beq> restore GLOD
libhunspell-1.3.0.dylib
libndofdev.dylib
libnghttp2.dylib

15
indra/cmake/GLOD.cmake Normal file
View File

@ -0,0 +1,15 @@
# -*- cmake -*-
#if (USESYSTEMLIBS)
# set(GLOD_FIND_REQUIRED true)
# include(FindGLOD)
#else (USESYSTEMLIBS)
include(Prebuilt)
use_prebuilt_binary(glod)
set(GLOD_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
if(LINUX)
set(GLOD_LIBRARIES GLOD vds)
else()
set(GLOD_LIBRARIES GLOD)
endif()
#endif (USESYSTEMLIBS)

View File

@ -17,6 +17,7 @@ include(GLIB)
include(DragDrop)
include(EXPAT)
include(FMODSTUDIO)
include(GLOD) # <FS:Beq/> restore GLOD
include(Hunspell)
include(JPEGEncoderBasic)
include(JsonCpp)
@ -83,6 +84,7 @@ endif(FMODSTUDIO)
include_directories(
${DBUSGLIB_INCLUDE_DIRS}
${JSONCPP_INCLUDE_DIR}
${GLOD_INCLUDE_DIR} # <FS:Beq/> restore GLOD
${LLAUDIO_INCLUDE_DIRS}
${LLCHARACTER_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
@ -2272,6 +2274,11 @@ if (WINDOWS)
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libapr-1.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libaprutil-1.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libapriconv-1.dll
# <FS:Beq> Restore GLOD build dependencies
${SHARED_LIB_STAGING_DIR}/Release/glod.dll
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/glod.dll
${SHARED_LIB_STAGING_DIR}/Debug/glod.dll
# </FS:Beq>
${SHARED_LIB_STAGING_DIR}/Release/libcollada14dom22.dll
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/libcollada14dom22.dll
${SHARED_LIB_STAGING_DIR}/Debug/libcollada14dom22-d.dll
@ -2521,6 +2528,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${OPENGL_LIBRARIES}
${FMODWRAPPER_LIBRARY} # must come after LLAudio
${OPENAL_LIBRARIES}
${GLOD_LIBRARIES} # <FS:Beq/> restore GLOD dependencies
${OPENGL_LIBRARIES}
${JSONCPP_LIBRARIES}
${SDL_LIBRARY}

View File

@ -44,7 +44,7 @@
#ifdef TRACY_ENABLE
// USAGE_TRACKING - displays overlapping stats that may imply double counting.
// ATTACHMENT_TRACKING - displays detailed tracking info for Avatar and Attachment. very heavy overhead.
#define USAGE_TRACKING
// #define USAGE_TRACKING
#define ATTACHMENT_TRACKING
#else
#undef USAGE_TRACKING

View File

@ -796,3 +796,69 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
=============
GLOD license
=============
The GLOD Open-Source License Version 1.0 June 16, 2004
Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns
Hopkins University and David Luebke, Brenden Schubert, University of
Virginia. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, is permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer and
request.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer and
request in the documentation and/or other materials provided with
the distribution.
3. The name "GLOD" must not be used to endorse or promote products
derived from this software without prior written permission.
4. Redistributions of any modified version of this source, whether in
source or binary form , must include a form of the following
acknowledgment: "This product is derived from the GLOD library,
which is available from http://www.cs.jhu.edu/~graphics/GLOD."
5. Redistributions of any modified version of this source in binary
form must provide, free of charge, access to the modified version
of the code.
6. This license shall be governed by and construed and enforced in
accordance with the laws of the State of Maryland, without
reference to its conflicts of law provisions. The exclusive
jurisdiction and venue for all legal actions relating to this
license shall be in courts of competent subject matter jurisdiction
located in the State of Maryland.
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, GLOD IS PROVIDED
UNDER THIS LICENSE ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
THAT GLOD IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR
PURPOSE OR NON-INFRINGING. ALL WARRANTIES ARE DISCLAIMED AND THE
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE CODE IS WITH
YOU. SHOULD ANY CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
COPYRIGHT HOLDER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY
CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY CODE IS
AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
THE COPYRIGHT HOLDER OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES FOR LOSS OF
PROFITS, REVENUE, OR FOR LOSS OF INFORMATION OR ANY OTHER LOSS.
YOU EXPRESSLY AGREE TO FOREVER INDEMNIFY, DEFEND AND HOLD HARMLESS THE
COPYRIGHT HOLDERS AND CONTRIBUTORS OF GLOD AGAINST ALL CLAIMS,
DEMANDS, SUITS OR OTHER ACTIONS ARISING DIRECTLY OR INDIRECTLY FROM
YOUR ACCEPTANCE AND USE OF GLOD.
Although NOT REQUIRED, we would appreciate it if active users of GLOD
put a link on their web site to the GLOD web site when possible.

View File

@ -828,6 +828,9 @@ void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit)
case LLModelPreview::MESH_OPTIMIZER_COMBINE:
mModelPreview->onLODMeshOptimizerParamCommit(lod, enforce_tri_limit, mode);
break;
case LLModelPreview::GENERATE:
mModelPreview->onLODGLODParamCommit(lod, enforce_tri_limit);
break;
default:
LL_ERRS() << "Only supposed to be called to generate models" << LL_ENDL;
break;
@ -1957,6 +1960,7 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod)
S32 index = lod_source_combo->getCurrentIndex();
if (index == LLModelPreview::MESH_OPTIMIZER_AUTO
|| index == LLModelPreview::GENERATE // <FS:Beq/> Improved LOD generation
|| index == LLModelPreview::MESH_OPTIMIZER_SLOPPY
|| index == LLModelPreview::MESH_OPTIMIZER_COMBINE)
{ //rebuild LoD to update triangle counts

View File

@ -92,6 +92,7 @@ bool LLModelPreview::sIgnoreLoadedCallback = false;
// </FS:Beq>
const F32 SKIN_WEIGHT_CAMERA_DISTANCE = 16.f;
#include "glod/glod.h" // <FS:Beq/> More flexible LOD generation
// <FS:Beq> mesh loader suffix configuration
//static
const std::array<std::string,5> LLModelPreview::sSuffixVarNames
@ -103,6 +104,25 @@ const std::array<std::string,5> LLModelPreview::sSuffixVarNames
"FSMeshPhysicsSuffix"
};
// </FS:Beq>
// <FS:Beq> More flexible LOD generation
BOOL stop_gloderror()
{
GLuint error = glodGetError();
if (error != GLOD_NO_ERROR)
{
std::ostringstream out;
out << "GLOD error detected, cannot generate LOD (try another method?): " << std::hex << error;
LL_WARNS("MeshUpload") << out.str() << LL_ENDL;
LLFloaterModelPreview::addStringToLog(out, true);
return TRUE;
}
return FALSE;
}
// </FS:Beq>
LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& material)
{
LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(material.getDiffuseMap(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_PREVIEW);
@ -222,6 +242,12 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
mLoadState = LLModelLoader::STARTING;
mGroup = 0;
mLODFrozen = false;
// <FS:Beq> Improved LOD generation
mBuildShareTolerance = 0.f;
mBuildQueueMode = GLOD_QUEUE_GREEDY;
mBuildBorderMode = GLOD_BORDER_UNLOCK;
mBuildOperator = GLOD_OPERATOR_EDGE_COLLAPSE;
// </FS:Beq>
mUVGuideTexture = LLViewerTextureManager::getFetchedTextureFromFile(gSavedSettings.getString("FSMeshPreviewUVGuideFile"), FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW); // <FS:Beq> - Add UV guide overlay to pmesh preview
for (U32 i = 0; i < LLModel::NUM_LODS; ++i)
@ -234,7 +260,7 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
mViewOption["show_textures"] = false;
mFMP = fmp;
glodInit(); // <FS:Beq/> Improved LOD generation
mHasPivot = false;
mModelPivot = LLVector3(0.0f, 0.0f, 0.0f);
@ -918,7 +944,12 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable
}
mLODFile[lod] = filename;
// <FS:Beq> Improved LOD generation
if (lod == LLModel::LOD_HIGH)
{
clearGLODGroup();
}
// </FS:Beq>
std::map<std::string, std::string> joint_alias_map;
getJointAliases(joint_alias_map);
@ -1061,12 +1092,31 @@ void LLModelPreview::clearIncompatible(S32 lod)
mBaseModel = mModel[lod];
mBaseScene = mScene[lod];
mVertexBuffer[5].clear();
clearGLODGroup(); // <FS:Beq/> Improved LOD generation
}
}
}
}
}
// <FS:Beq> Improved LOD generation
void LLModelPreview::clearGLODGroup()
{
if (mGroup)
{
for (std::map<LLPointer<LLModel>, U32>::iterator iter = mObject.begin(); iter != mObject.end(); ++iter)
{
glodDeleteObject(iter->second);
stop_gloderror();
}
mObject.clear();
glodDeleteGroup(mGroup);
stop_gloderror();
mGroup = 0;
}
}
// </FS:Beq>
void LLModelPreview::loadModelCallback(S32 loaded_lod)
{
assert_main_thread();
@ -1220,6 +1270,7 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod)
}
mBaseModel = mModel[loaded_lod];
clearGLODGroup(); // <FS:Beq/> Improved LOD generation
mBaseScene = mScene[loaded_lod];
mVertexBuffer[5].clear();
@ -1450,6 +1501,453 @@ void LLModelPreview::restoreNormals()
updateStatusMessages();
}
// <FS:Beq> Improved LOD generation
// Restore the GLOD entry point.
// There would appear to be quite a lot of commonality which would be well suited to refactoring but
// LL are still playing with Mesh Optimiser code.
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)
{
std::ostringstream out;
out << "Invalid level of detail: " << which_lod;
LL_WARNS() << out.str() << LL_ENDL;
LLFloaterModelPreview::addStringToLog(out, false);
assert(which_lod >= -1 && which_lod < LLModel::NUM_LODS);
return;
}
if (mBaseModel.empty())
{
return;
}
LLVertexBuffer::unbind();
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
if (shader)
{
shader->unbind();
}
stop_gloderror();
static U32 cur_name = 1;
S32 limit = -1;
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 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
U32 lod_mode = 0;
F32 lod_error_threshold = 0;
// The LoD should be in range from Lowest to High
if (which_lod > -1 && which_lod < NUM_LOD)
{
LLCtrlSelectionInterface* iface = mFMP->childGetSelectionInterface("lod_mode_" + lod_name[which_lod]);
if (iface)
{
lod_mode = iface->getFirstSelectedIndex();
}
lod_error_threshold = mFMP->childGetValue("lod_error_threshold_" + lod_name[which_lod]).asReal();
}
if (which_lod != -1)
{
mRequestedLoDMode[which_lod] = lod_mode;
}
if (lod_mode == 0)
{
lod_mode = GLOD_TRIANGLE_BUDGET;
// The LoD should be in range from Lowest to High
if (which_lod > -1 && which_lod < NUM_LOD)
{
limit = mFMP->childGetValue("lod_triangle_limit_" + lod_name[which_lod]).asInteger();
//convert from "scene wide" to "non-instanced" triangle limit
limit = (S32)((F32)limit*triangle_ratio);
}
}
else
{
lod_mode = GLOD_ERROR_THRESHOLD;
}
bool object_dirty = false;
if (mGroup == 0)
{
object_dirty = true;
mGroup = cur_name++;
glodNewGroup(mGroup);
}
if (object_dirty)
{
for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter)
{ //build GLOD objects for each model in base model list
LLModel* mdl = *iter;
if (mObject[mdl] != 0)
{
glodDeleteObject(mObject[mdl]);
}
mObject[mdl] = cur_name++;
glodNewObject(mObject[mdl], mGroup, GLOD_DISCRETE);
stop_gloderror();
if (iter == mBaseModel.begin() && !mdl->mSkinWeights.empty())
{ //regenerate vertex buffer for skinned models to prevent animation feedback during LOD generation
mVertexBuffer[5].clear();
}
if (mVertexBuffer[5].empty())
{
genBuffers(5, false);
}
U32 tri_count = 0;
for (U32 i = 0; i < mVertexBuffer[5][mdl].size(); ++i)
{
LLVertexBuffer* buff = mVertexBuffer[5][mdl][i];
buff->setBuffer(type_mask & buff->getTypeMask());
U32 num_indices = mVertexBuffer[5][mdl][i]->getNumIndices();
if (num_indices > 2)
{
// <FS:ND> Fix glod so it works when just using the opengl core profile
//glodInsertElements(mObject[mdl], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, (U8*)mVertexBuffer[5][mdl][i]->getIndicesPointer(), 0, 0.f);
LLStrider<LLVector3> vertex_strider;
LLStrider<LLVector3> normal_strider;
LLStrider<LLVector2> tc_strider;
LLStrider< U16 > index_strider;
buff->getIndexStrider( index_strider );
glodVBO vbo = {};
if( buff->hasDataType( LLVertexBuffer::TYPE_VERTEX ) )
{
buff->getVertexStrider( vertex_strider );
vbo.mV.p = vertex_strider.get();
vbo.mV.size = 3;
vbo.mV.stride = LLVertexBuffer::sTypeSize[ LLVertexBuffer::TYPE_VERTEX ];
vbo.mV.type = GL_FLOAT;
}
if( buff->hasDataType( LLVertexBuffer::TYPE_NORMAL ) )
{
buff->getNormalStrider( normal_strider );
vbo.mN.p = normal_strider.get();
vbo.mN.stride = LLVertexBuffer::sTypeSize[ LLVertexBuffer::TYPE_NORMAL ];
vbo.mN.type = GL_FLOAT;
}
if( buff->hasDataType( LLVertexBuffer::TYPE_TEXCOORD0 ) )
{
buff->getTexCoord0Strider( tc_strider );
vbo.mT.p = tc_strider.get();
vbo.mT.size = 2;
vbo.mT.stride = LLVertexBuffer::sTypeSize[ LLVertexBuffer::TYPE_TEXCOORD0 ];
vbo.mT.type = GL_FLOAT;
}
glodInsertElements( mObject[ mdl ], i, GL_TRIANGLES, num_indices, GL_UNSIGNED_SHORT, (U8*)index_strider.get(), 0, 0.f, &vbo );
// </FS:ND>
}
tri_count += num_indices / 3;
stop_gloderror();
}
glodBuildObject(mObject[mdl]);
stop_gloderror();
}
}
S32 start = LLModel::LOD_HIGH;
S32 end = 0;
if (which_lod != -1)
{
start = end = which_lod;
}
mMaxTriangleLimit = base_triangle_count;
for (S32 lod = start; lod >= end; --lod)
{
if (which_lod == -1)
{
if (lod < start)
{
triangle_count /= decimation;
}
}
else
{
if (enforce_tri_limit)
{
triangle_count = limit;
}
else
{
for (S32 j = LLModel::LOD_HIGH; j>which_lod; --j)
{
triangle_count /= decimation;
}
}
}
mModel[lod].clear();
mModel[lod].resize(mBaseModel.size());
mVertexBuffer[lod].clear();
U32 actual_tris = 0;
U32 actual_verts = 0;
U32 submeshes = 0;
mRequestedTriangleCount[lod] = (S32)((F32)triangle_count / triangle_ratio);
mRequestedErrorThreshold[lod] = lod_error_threshold;
glodGroupParameteri(mGroup, GLOD_ADAPT_MODE, lod_mode);
stop_gloderror();
glodGroupParameteri(mGroup, GLOD_ERROR_MODE, GLOD_OBJECT_SPACE_ERROR);
stop_gloderror();
glodGroupParameterf(mGroup, GLOD_OBJECT_SPACE_ERROR_THRESHOLD, lod_error_threshold);
stop_gloderror();
if (lod_mode != GLOD_TRIANGLE_BUDGET)
{
glodGroupParameteri(mGroup, GLOD_MAX_TRIANGLES, 0);
}
else
{
//SH-632: always add 1 to desired amount to avoid decimating below desired amount
glodGroupParameteri(mGroup, GLOD_MAX_TRIANGLES, triangle_count + 1);
}
stop_gloderror();
glodAdaptGroup(mGroup);
stop_gloderror();
for (U32 mdl_idx = 0; mdl_idx < mBaseModel.size(); ++mdl_idx)
{
LLModel* base = mBaseModel[mdl_idx];
GLint patch_count = 0;
glodGetObjectParameteriv(mObject[base], GLOD_NUM_PATCHES, &patch_count);
stop_gloderror();
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;
GLint* sizes = new GLint[patch_count * 2];
glodGetObjectParameteriv(mObject[base], GLOD_PATCH_SIZES, sizes);
stop_gloderror();
GLint* names = new GLint[patch_count];
glodGetObjectParameteriv(mObject[base], GLOD_PATCH_NAMES, names);
stop_gloderror();
mModel[lod][mdl_idx]->setNumVolumeFaces(patch_count);
LLModel* target_model = mModel[lod][mdl_idx];
for (GLint i = 0; i < patch_count; ++i)
{
type_mask = mVertexBuffer[5][base][i]->getTypeMask();
LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(type_mask, 0);
if (sizes[i * 2 + 1] > 0 && sizes[i * 2] > 0)
{
if (!buff->allocateBuffer(sizes[i * 2 + 1], sizes[i * 2], true))
{
// Todo: find a way to stop preview in this case instead of crashing
LL_ERRS() << "Failed buffer allocation during preview LOD generation."
<< " Vertices: " << sizes[i * 2 + 1]
<< " Indices: " << sizes[i * 2] << LL_ENDL;
}
buff->setBuffer(type_mask);
// <FS:ND> Fix glod so it works when just using the opengl core profile
//glodFillElements(mObject[base], names[i], GL_UNSIGNED_SHORT, (U8*)buff->getIndicesPointer());
LLStrider<LLVector3> vertex_strider;
LLStrider<LLVector3> normal_strider;
LLStrider<LLVector2> tc_strider;
LLStrider< U16 > index_strider;
buff->getIndexStrider( index_strider );
glodVBO vbo = {};
if( buff->hasDataType( LLVertexBuffer::TYPE_VERTEX ) )
{
buff->getVertexStrider( vertex_strider );
vbo.mV.p = vertex_strider.get();
vbo.mV.size = 3;
vbo.mV.stride = LLVertexBuffer::sTypeSize[ LLVertexBuffer::TYPE_VERTEX ];
vbo.mV.type = GL_FLOAT;
}
if( buff->hasDataType( LLVertexBuffer::TYPE_NORMAL ) )
{
buff->getNormalStrider( normal_strider );
vbo.mN.p = normal_strider.get();
vbo.mN.stride = LLVertexBuffer::sTypeSize[ LLVertexBuffer::TYPE_NORMAL ];
vbo.mN.type = GL_FLOAT;
}
if( buff->hasDataType( LLVertexBuffer::TYPE_TEXCOORD0 ) )
{
buff->getTexCoord0Strider( tc_strider );
vbo.mT.p = tc_strider.get();
vbo.mT.size = 2;
vbo.mT.stride = LLVertexBuffer::sTypeSize[ LLVertexBuffer::TYPE_TEXCOORD0 ];
vbo.mT.type = GL_FLOAT;
}
glodFillElements( mObject[ base ], names[ i ], GL_UNSIGNED_SHORT, (U8*)index_strider.get(), &vbo );
// </FS:ND>
stop_gloderror();
}
else
{
// This face was eliminated or we failed to allocate buffer,
// attempt to create a dummy triangle (one vertex, 3 indices, all 0)
buff->allocateBuffer(1, 3, true);
memset((U8*)buff->getMappedData(), 0, buff->getSize());
// <FS:ND> Fix when running with opengl core profile
//memset((U8*)buff->getIndicesPointer(), 0, buff->getIndicesSize());
LLStrider< U16 > index_strider;
buff->getIndexStrider( index_strider );
memset( (U8*)index_strider.get(), 0, buff->getIndicesSize() );
// </FS:ND>
}
buff->validateRange(0, buff->getNumVerts() - 1, buff->getNumIndices(), 0);
LLStrider<LLVector3> pos;
LLStrider<LLVector3> norm;
LLStrider<LLVector2> tc;
LLStrider<U16> index;
buff->getVertexStrider(pos);
if (type_mask & LLVertexBuffer::MAP_NORMAL)
{
buff->getNormalStrider(norm);
}
if (type_mask & LLVertexBuffer::MAP_TEXCOORD0)
{
buff->getTexCoord0Strider(tc);
}
buff->getIndexStrider(index);
target_model->setVolumeFaceData(names[i], pos, norm, tc, index, buff->getNumVerts(), buff->getNumIndices());
actual_tris += buff->getNumIndices() / 3;
actual_verts += buff->getNumVerts();
++submeshes;
if (!validate_face(target_model->getVolumeFace(names[i])))
{
std::ostringstream out;
out << "Invalid face generated during LOD generation.";
LLFloaterModelPreview::addStringToLog(out,true);
LL_ERRS() << out.str() << LL_ENDL;
}
}
//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;
}
delete[] sizes;
delete[] names;
}
//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;
}
}
}
}
}
}
LLVertexBuffer::unbind();
if (shader)
{
shader->bind();
}
refresh(); // <FS:ND/> refresh once to make sure render gets called with the updated vbos
}
// </FS:Beq>
// Runs per object, but likely it is a better way to run per model+submodels
// returns a ratio of base model indices to resulting indices
// returns -1 in case of failure
@ -4368,8 +4866,13 @@ bool LLModelPreview::lodQueryCallback()
{
S32 lod = preview->mLodsQuery.back();
preview->mLodsQuery.pop_back();
// <FS:Beq> Improved LOD generation
#ifdef USE_GLOD_AS_DEFAULT
preview->genLODsUsingGLOD(lod);
#else
preview->genMeshOptimizerLODs(lod, MESH_OPTIMIZER_AUTO, 3, false);
#endif
// </FS:Beq>
if (preview->mLookUpLodFiles && (lod == LLModel::LOD_HIGH))
{
preview->lookupLODModelFiles(LLModel::LOD_HIGH);
@ -4383,9 +4886,21 @@ bool LLModelPreview::lodQueryCallback()
return true;
}
// <FS:Beq> Improved LOD generation
void LLModelPreview::onLODGLODParamCommit(S32 lod, bool enforce_tri_limit)
{
if (mFMP && !mLODFrozen)
{
genGlodLODs(lod, 3, enforce_tri_limit);
mFMP->refresh();
refresh();
mDirty = true;
}
}
void LLModelPreview::onLODMeshOptimizerParamCommit(S32 requested_lod, bool enforce_tri_limit, S32 mode)
{
if (!mLODFrozen)
if (mFMP && !mLODFrozen) // <FS:Beq> minor sidestep of potential crash
{
genMeshOptimizerLODs(requested_lod, mode, 3, enforce_tri_limit);
mFMP->refresh(); // <FS:Beq/> BUG-231970 Fix b0rken upload floater refresh

View File

@ -128,6 +128,7 @@ public:
MESH_OPTIMIZER_AUTO, // automatically selects method based on model or face
MESH_OPTIMIZER_COMBINE, // combines faces into a single model, simplifies, then splits back into faces
MESH_OPTIMIZER_SLOPPY, // uses sloppy method, works per face
GENERATE, // Use GLOD <FS:Beq/> Improved LOD generation
USE_LOD_ABOVE,
} eLoDMode;
@ -165,6 +166,7 @@ public:
void loadModelCallback(S32 lod);
bool lodsReady() { return !mGenLOD && mLodsQuery.empty(); }
void queryLODs() { mGenLOD = true; };
void genGlodLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
void genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 decimation = 3, bool enforce_tri_limit = false);
void generateNormals();
void restoreNormals();
@ -175,6 +177,8 @@ public:
void clearIncompatible(S32 lod);
void updateStatusMessages();
void updateLodControls(S32 lod);
void clearGLODGroup();
void onLODGLODParamCommit(S32 lod, bool enforce_tri_limit);
void onLODMeshOptimizerParamCommit(S32 lod, bool enforce_tri_limit, S32 mode);
void addEmptyFace(LLModel* pTarget);
@ -272,6 +276,16 @@ protected:
S32 mRequestedTriangleCount[LLModel::NUM_LODS];
F32 mRequestedErrorThreshold[LLModel::NUM_LODS];
F32 mRequestedCreaseAngle[LLModel::NUM_LODS];
// <FS:Beq> Improved LOD generation
F32 mBuildShareTolerance;
U32 mBuildQueueMode;
U32 mBuildOperator;
U32 mBuildBorderMode;
U32 mRequestedBuildOperator[LLModel::NUM_LODS];
U32 mRequestedQueueMode[LLModel::NUM_LODS];
U32 mRequestedBorderMode[LLModel::NUM_LODS];
F32 mRequestedShareTolerance[LLModel::NUM_LODS];
// </FS:Beq>
LLModelLoader* mModelLoader;

View File

@ -248,6 +248,7 @@ expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
FMOD Sound System, Copyright (C) Firelight Technologies Pty, Ltd., 1994-2020
FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg.
GL Copyright (C) 1999-2004 Brian Paul.
GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia.
Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
HACD Copyright (C) 2011, Khaled Mamou (kmamou@gmail.com)
jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)

View File

@ -203,6 +203,10 @@
name="MeshOptSloppy"
label="Generate Sloppy"
value="MeshOptSloppy" />
<item
name="Generate"
label="Generate"
value="Generate" />
</combo_box>
<line_editor
follows="left|top"
@ -340,6 +344,10 @@
name="MeshOptSloppy"
label="Generate Sloppy"
value="MeshOptSloppy" />
<item
name="Generate"
label="Generate"
value="Generate" />
<item
name="Use LoD above"
label="Use LoD above"
@ -481,6 +489,10 @@
name="MeshOptSloppy"
label="Generate Sloppy"
value="MeshOptSloppy" />
<item
name="Generate"
label="Generate"
value="Generate" />
<item
name="Use LoD above"
label="Use LoD above"
@ -622,6 +634,10 @@
name="MeshOptSloppy"
label="Generate Sloppy"
value="MeshOptSloppy" />
<item
name="Generate"
label="Generate"
value="Generate" />
<item
name="Use LoD above"
label="Use LoD above"

View File

@ -600,6 +600,14 @@ class WindowsManifest(ViewerManifest):
# Get shared libs from the shared libs staging directory
with self.prefix(src=os.path.join(self.args['build'], os.pardir,
'sharedlibs', self.args['configuration'])):
# Mesh 3rd party libs needed for auto LOD and collada reading
try:
self.path("glod.dll")
except RuntimeError as err:
print (err.message)
print ("Skipping GLOD library (assumming linked statically)")
# Get fmodstudio dll if needed
if self.args['fmodstudio'] == 'ON':
if(self.args['configuration'].lower() == 'debug'):
@ -1442,6 +1450,7 @@ class DarwinManifest(ViewerManifest):
"libapr-1.0.dylib",
"libaprutil-1.0.dylib",
"libexpat.1.dylib",
"libGLOD.dylib",
# libnghttp2.dylib is a symlink to
# libnghttp2.major.dylib, which is a symlink
# to libnghttp2.version.dylib. Get all of them.
@ -2135,6 +2144,7 @@ class Linux_i686_Manifest(LinuxManifest):
self.path("libaprutil-1.so.0.4.1")
self.path("libdb*.so")
self.path("libexpat.so.*")
self.path("libGLOD.so")
self.path("libuuid.so*")
self.path("libSDL-1.2.so.*")
self.path("libdirectfb-1.*.so.*")