From 3e80fa3dbc943de9b784fedc202ba38cf238f46d Mon Sep 17 00:00:00 2001 From: David Parks Date: Mon, 2 Nov 2009 19:55:37 +0000 Subject: Sync up with render-pipeline-7 ignore-dead-branch --- indra/newview/pipeline.cpp | 241 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 214 insertions(+), 27 deletions(-) (limited to 'indra/newview/pipeline.cpp') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index b50e71bf48..7cf5cf75ad 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -342,6 +342,8 @@ LLPipeline::LLPipeline() : mGlowPool(NULL), mBumpPool(NULL), mWLSkyPool(NULL), + mMeshMutex(NULL), + mMeshThreadCount(0), mLightMask(0), mLightMovingMask(0), mLightingDetail(0) @@ -399,6 +401,7 @@ void LLPipeline::init() stop_glerror(); + mMeshMutex = new LLMutex(NULL); for (U32 i = 0; i < 2; ++i) { mSpotLightFade[i] = 1.f; @@ -473,6 +476,9 @@ void LLPipeline::cleanup() //delete mWLSkyPool; mWLSkyPool = NULL; + delete mMeshMutex; + mMeshMutex = NULL; + releaseGLBuffers(); mBloomImagep = NULL; @@ -1783,6 +1789,8 @@ void LLPipeline::rebuildPriorityGroups() assertInitialized(); + notifyLoadedMeshes(); + // Iterate through all drawables on the priority build queue, for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin(); iter != mGroupQ1.end(); ++iter) @@ -1793,6 +1801,7 @@ void LLPipeline::rebuildPriorityGroups() } mGroupQ1.clear(); + } void LLPipeline::rebuildGroups() @@ -3419,27 +3428,14 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); - renderHighlights(); - mHighlightFaces.clear(); - - renderDebug(); - - LLVertexBuffer::unbind(); - - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - // Render debugging beacons. - gObjectList.renderObjectBeacons(); - LLHUDObject::renderAll(); - gObjectList.resetObjectBeacons(); - } - if (occlude) { occlude = FALSE; gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); doOcclusion(camera); + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); } } @@ -5836,6 +5832,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + + if (LLRenderTarget::sUseFBO) + { //copy depth buffer from mScreen to framebuffer + LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), + 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); + } } @@ -6912,6 +6914,24 @@ void LLPipeline::renderDeferredLighting() mRenderTypeMask = render_mask; } + { + //render highlights, etc. + renderHighlights(); + mHighlightFaces.clear(); + + renderDebug(); + + LLVertexBuffer::unbind(); + + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + // Render debugging beacons. + gObjectList.renderObjectBeacons(); + LLHUDObject::renderAll(); + gObjectList.resetObjectBeacons(); + } + } + mScreen.flush(); } @@ -7241,18 +7261,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLGLDisable cull(GL_CULL_FACE); updateCull(camera, ref_result, 1); stateSort(camera, ref_result); - gGL.setColorMask(true, true); - mWaterRef.clear(); - gGL.setColorMask(true, false); - - } - else - { - gGL.setColorMask(true, true); - mWaterRef.clear(); - gGL.setColorMask(true, false); - } - + } + + gGL.setColorMask(true, true); + mWaterRef.clear(); + gGL.setColorMask(true, false); + ref_mask = mRenderTypeMask; mRenderTypeMask = mask; } @@ -7907,6 +7921,7 @@ void LLPipeline::generateHighlight(LLCamera& camera) mHighlight.flush(); gGL.setColorMask(true, false); + gViewerWindow->setup3DViewport(); } } @@ -8886,3 +8901,175 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() } +void LLPipeline::loadMesh(LLVOVolume* volume, LLUUID mesh_id) +{ + + { + LLMutexLock lock(mMeshMutex); + //add volume to list of loading meshes + mesh_load_map::iterator iter = mLoadingMeshes.find(mesh_id); + if (iter != mLoadingMeshes.end()) + { //request pending for this mesh, append volume id to list + iter->second.insert(volume->getID()); + return; + } + + //first request for this mesh + mLoadingMeshes[mesh_id].insert(volume->getID()); + } + + if (gAssetStorage->hasLocalAsset(mesh_id, LLAssetType::AT_MESH)) + { //already have asset, load desired LOD in background + mPendingMeshes.push_back(new LLMeshThread(mesh_id, volume->getVolume())); + } + else + { //fetch asset and load when done + gAssetStorage->getAssetData(mesh_id, LLAssetType::AT_MESH, + getMeshAssetCallback, volume->getVolume(), TRUE); + } + +} + +//static +void LLPipeline::getMeshAssetCallback(LLVFS *vfs, + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status) +{ + gPipeline.mPendingMeshes.push_back(new LLMeshThread(asset_uuid, (LLVolume*) user_data)); +} + + +LLPipeline::LLMeshThread::LLMeshThread(LLUUID mesh_id, LLVolume* target) +: LLThread("mesh_loading_thread") +{ + mMeshID = mesh_id; + mVolume = NULL; + mDetail = target->getDetail(); + mTargetVolume = target; +} + +LLPipeline::LLMeshThread::~LLMeshThread() +{ + +} + +void LLPipeline::LLMeshThread::run() +{ + if (!gAssetStorage || LLApp::instance()->isQuitting()) + { + return; + } + + char* buffer = NULL; + S32 size = 0; + + LLVFS* vfs = gAssetStorage->mVFS; + + { + LLVFile file(vfs, mMeshID, LLAssetType::AT_MESH, LLVFile::READ); + file.waitForLock(VFSLOCK_READ); + size = file.getSize(); + + if (size == 0) + { + gPipeline.meshLoaded(this); + return; + } + + buffer = new char[size]; + file.read((U8*)&buffer[0], size); + } + + { + std::string buffer_string(buffer, size); + std::istringstream buffer_stream(buffer_string); + + { + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + mVolume = new LLVolume(volume_params, mDetail); + mVolume->createVolumeFacesFromStream(buffer_stream); + } + } + delete[] buffer; + + gPipeline.meshLoaded(this); +} + +void LLPipeline::meshLoaded(LLPipeline::LLMeshThread* mesh_thread) +{ + LLMutexLock lock(mMeshMutex); + mLoadedMeshes.push_back(mesh_thread); +} + +void LLPipeline::notifyLoadedMeshes() +{ //called from main thread + + U32 max_thread_count = llmax(gSavedSettings.getU32("MeshThreadCount"), (U32) 1); + while (mMeshThreadCount < max_thread_count && !mPendingMeshes.empty()) + { + LLMeshThread* mesh_thread = mPendingMeshes.front(); + mesh_thread->start(); + ++mMeshThreadCount; + mPendingMeshes.pop_front(); + } + + LLMutexLock lock(mMeshMutex); + std::list stopping_threads; + + for (std::list::iterator iter = mLoadedMeshes.begin(); iter != mLoadedMeshes.end(); ++iter) + { //for each mesh done loading + LLMeshThread* mesh = *iter; + + if (!mesh->isStopped()) + { //don't process a LLMeshThread until it's stopped + stopping_threads.push_back(mesh); + continue; + } + + //get list of objects waiting to be notified this mesh is loaded + mesh_load_map::iterator obj_iter = mLoadingMeshes.find(mesh->mMeshID); + + if (mesh->mVolume && obj_iter != mLoadingMeshes.end()) + { + //make sure target volume is still valid + BOOL valid = FALSE; + + for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + { + LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); + + if (vobj) + { + if (vobj->getVolume() == mesh->mTargetVolume) + { + valid = TRUE; + } + } + } + + + if (valid) + { + mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); + for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + { + LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); + if (vobj) + { + vobj->notifyMeshLoaded(); + } + } + } + + mLoadingMeshes.erase(mesh->mMeshID); + } + + delete mesh; + --mMeshThreadCount; + } + + mLoadedMeshes = stopping_threads; +} + -- cgit v1.2.3 From 88292104d9a2332e6169f2add8f0b590bb22dbff Mon Sep 17 00:00:00 2001 From: David Parks Date: Wed, 4 Nov 2009 14:19:05 +0000 Subject: Fix for crash when loading some meshes. Added button to auto-fill LODs. --- indra/newview/pipeline.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview/pipeline.cpp') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 7cf5cf75ad..4fc94c08bc 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8988,6 +8988,7 @@ void LLPipeline::LLMeshThread::run() { LLVolumeParams volume_params; volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + volume_params.setSculptID(mMeshID, LL_SCULPT_TYPE_MESH); mVolume = new LLVolume(volume_params, mDetail); mVolume->createVolumeFacesFromStream(buffer_stream); } -- cgit v1.2.3 From 1c495c56c1011f4514d96b75cbcfb5a8256de78f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 5 Nov 2009 17:12:18 -0600 Subject: Fix for crash on teleport to mesh enabled region. Fix for flashing meshes on LOD switch. --- indra/newview/pipeline.cpp | 47 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) (limited to 'indra/newview/pipeline.cpp') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 1a1d29ac32..4ac95fa939 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8902,33 +8902,68 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() } -void LLPipeline::loadMesh(LLVOVolume* volume, LLUUID mesh_id) +void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) { - { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes mesh_load_map::iterator iter = mLoadingMeshes.find(mesh_id); if (iter != mLoadingMeshes.end()) { //request pending for this mesh, append volume id to list - iter->second.insert(volume->getID()); + iter->second.insert(vobj->getID()); return; } //first request for this mesh - mLoadingMeshes[mesh_id].insert(volume->getID()); + mLoadingMeshes[mesh_id].insert(vobj->getID()); } if (gAssetStorage->hasLocalAsset(mesh_id, LLAssetType::AT_MESH)) { //already have asset, load desired LOD in background - mPendingMeshes.push_back(new LLMeshThread(mesh_id, volume->getVolume())); + mPendingMeshes.push_back(new LLMeshThread(mesh_id, vobj->getVolume())); } else { //fetch asset and load when done gAssetStorage->getAssetData(mesh_id, LLAssetType::AT_MESH, - getMeshAssetCallback, volume->getVolume(), TRUE); + getMeshAssetCallback, vobj->getVolume(), TRUE); } + //do a quick search to see if we can't display something while we wait for this mesh to load + LLVolume* volume = vobj->getVolume(); + + if (volume) + { + LLVolumeParams params = volume->getParams(); + + LLVolumeLODGroup* group = LLPrimitive::getVolumeManager()->getGroup(params); + + if (group) + { + //first see what the next lowest LOD available might be + for (S32 i = detail-1; i >= 0; --i) + { + LLVolume* lod = group->refLOD(i); + if (lod && lod->getNumVolumeFaces() > 0) + { + volume->copyVolumeFaces(lod); + group->derefLOD(lod); + return; + } + } + + //no lower LOD is a available, is a higher lod available? + for (S32 i = detail+1; i < 4; ++i) + { + LLVolume* lod = group->refLOD(i); + if (lod && lod->getNumVolumeFaces() > 0) + { + volume->copyVolumeFaces(lod); + group->derefLOD(lod); + return; + } + } + } + } } //static -- cgit v1.2.3 From 10069e0e13e3214ba9320fdce915440b2e12f938 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 5 Nov 2009 19:58:10 -0600 Subject: Fix for prims all being 0 lod. Fix for dangling prim references. --- indra/newview/pipeline.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/newview/pipeline.cpp') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4ac95fa939..3554ceb7f0 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8949,6 +8949,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); return; } + group->derefLOD(lod); } //no lower LOD is a available, is a higher lod available? @@ -8961,6 +8962,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); return; } + group->derefLOD(lod); } } } -- cgit v1.2.3 From 4e420a36c67e611cd7d85652b43d9cd65315e563 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sat, 7 Nov 2009 08:22:39 -0600 Subject: Fix for missing LOD spam. --- indra/newview/pipeline.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/newview/pipeline.cpp') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3554ceb7f0..f13bb73acf 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8949,6 +8949,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); return; } + group->derefLOD(lod); } @@ -8962,6 +8963,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); return; } + group->derefLOD(lod); } } -- cgit v1.2.3 From 81bfdcbfae4f203e60f00794966383b01475995b Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 18 Nov 2009 18:10:48 -0600 Subject: Tetrahedron displays in place of unloaded mesh. Still has some LOD issues. --- indra/newview/pipeline.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'indra/newview/pipeline.cpp') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c262e94ff4..3410ad6559 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8976,6 +8976,9 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); } } + + //nothing found, so make a tetrahedron + volume->makeTetrahedron(); } } @@ -9102,7 +9105,11 @@ void LLPipeline::notifyLoadedMeshes() if (valid) { - mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); + if (mesh->mVolume->getNumVolumeFaces() > 0) + { + mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); + } + for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) { LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); -- cgit v1.2.3 From 62233f22469cdc66042fc7bbbbd367dbb7212fde Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 24 Nov 2009 07:38:04 -0600 Subject: Fix for copying of tetrahedrons in place of mesh LODs. Fix for bad tetrahedron bounding box. Bad fix for simultaneous loading of multiple LODs. --- indra/newview/pipeline.cpp | 50 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'indra/newview/pipeline.cpp') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3410ad6559..0ee619244b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8913,23 +8913,29 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) { + + if (detail < 0 || detail > 4) + { + return; + } + { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes - mesh_load_map::iterator iter = mLoadingMeshes.find(mesh_id); - if (iter != mLoadingMeshes.end()) + mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_id); + if (iter != mLoadingMeshes[detail].end()) { //request pending for this mesh, append volume id to list iter->second.insert(vobj->getID()); return; } //first request for this mesh - mLoadingMeshes[mesh_id].insert(vobj->getID()); + mLoadingMeshes[detail][mesh_id].insert(vobj->getID()); } if (gAssetStorage->hasLocalAsset(mesh_id, LLAssetType::AT_MESH)) { //already have asset, load desired LOD in background - mPendingMeshes.push_back(new LLMeshThread(mesh_id, vobj->getVolume())); + mPendingMeshes.push_back(new LLMeshThread(mesh_id, vobj->getVolume(), detail)); } else { //fetch asset and load when done @@ -8952,7 +8958,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) for (S32 i = detail-1; i >= 0; --i) { LLVolume* lod = group->refLOD(i); - if (lod && lod->getNumVolumeFaces() > 0) + if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0) { volume->copyVolumeFaces(lod); group->derefLOD(lod); @@ -8966,7 +8972,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) for (S32 i = detail+1; i < 4; ++i) { LLVolume* lod = group->refLOD(i); - if (lod && lod->getNumVolumeFaces() > 0) + if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0) { volume->copyVolumeFaces(lod); group->derefLOD(lod); @@ -8976,6 +8982,10 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); } } + else + { + llerrs << "WTF?" << llendl; + } //nothing found, so make a tetrahedron volume->makeTetrahedron(); @@ -8992,12 +9002,22 @@ void LLPipeline::getMeshAssetCallback(LLVFS *vfs, } -LLPipeline::LLMeshThread::LLMeshThread(LLUUID mesh_id, LLVolume* target) +LLPipeline::LLMeshThread::LLMeshThread(LLUUID mesh_id, LLVolume* target, S32 detail) : LLThread("mesh_loading_thread") { mMeshID = mesh_id; mVolume = NULL; mDetail = target->getDetail(); + + if (detail == -1) + { + mDetailIndex = LLVolumeLODGroup::getVolumeDetailFromScale(target->getDetail()); + } + else + { + mDetailIndex = detail; + } + mTargetVolume = target; } @@ -9073,6 +9093,10 @@ void LLPipeline::notifyLoadedMeshes() for (std::list::iterator iter = mLoadedMeshes.begin(); iter != mLoadedMeshes.end(); ++iter) { //for each mesh done loading + + + + LLMeshThread* mesh = *iter; if (!mesh->isStopped()) @@ -9081,10 +9105,12 @@ void LLPipeline::notifyLoadedMeshes() continue; } + S32 detail = mesh->mDetailIndex; + //get list of objects waiting to be notified this mesh is loaded - mesh_load_map::iterator obj_iter = mLoadingMeshes.find(mesh->mMeshID); + mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh->mMeshID); - if (mesh->mVolume && obj_iter != mLoadingMeshes.end()) + if (mesh->mVolume && obj_iter != mLoadingMeshes[detail].end()) { //make sure target volume is still valid BOOL valid = FALSE; @@ -9109,6 +9135,10 @@ void LLPipeline::notifyLoadedMeshes() { mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); } + else + { + llwarns << "Mesh loading returned empty volume." << llendl; + } for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) { @@ -9120,7 +9150,7 @@ void LLPipeline::notifyLoadedMeshes() } } - mLoadingMeshes.erase(mesh->mMeshID); + mLoadingMeshes[detail].erase(mesh->mMeshID); } delete mesh; -- cgit v1.2.3 From 6d66910c6e2fbb25bf8b5c7b90e795f350342104 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 25 Nov 2009 11:35:41 -0600 Subject: Fix for spam on invalid mesh asset. Fix for index buffer overflow spam and crash in llvertexbuffer. --- indra/newview/pipeline.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'indra/newview/pipeline.cpp') diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 0ee619244b..af3a35615c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1807,8 +1807,6 @@ void LLPipeline::rebuildPriorityGroups() assertInitialized(); - notifyLoadedMeshes(); - // Iterate through all drawables on the priority build queue, for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin(); iter != mGroupQ1.end(); ++iter) @@ -1888,6 +1886,8 @@ void LLPipeline::updateGeom(F32 max_dtime) // for now, only LLVOVolume does this to throttle LOD changes LLVOVolume::preUpdateGeom(); + notifyLoadedMeshes(); + // Iterate through all drawables on the priority build queue, for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); iter != mBuildQ1.end();) @@ -8913,7 +8913,6 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) { - if (detail < 0 || detail > 4) { return; @@ -9093,10 +9092,6 @@ void LLPipeline::notifyLoadedMeshes() for (std::list::iterator iter = mLoadedMeshes.begin(); iter != mLoadedMeshes.end(); ++iter) { //for each mesh done loading - - - - LLMeshThread* mesh = *iter; if (!mesh->isStopped()) @@ -9131,14 +9126,13 @@ void LLPipeline::notifyLoadedMeshes() if (valid) { - if (mesh->mVolume->getNumVolumeFaces() > 0) - { - mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); - } - else + if (mesh->mVolume->getNumVolumeFaces() <= 0) { llwarns << "Mesh loading returned empty volume." << llendl; + mesh->mVolume->makeTetrahedron(); } + + mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) { -- cgit v1.2.3