summaryrefslogtreecommitdiff
path: root/indra/newview/llmeshrepository.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llmeshrepository.cpp')
-rw-r--r--indra/newview/llmeshrepository.cpp899
1 files changed, 460 insertions, 439 deletions
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index a8c6f69425..413f02b723 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -256,6 +256,7 @@
// mDecompositionRequests mMutex rw.repo.mMutex, ro.repo.none [5]
// mPhysicsShapeRequests mMutex rw.repo.mMutex, ro.repo.none [5]
// mDecompositionQ mMutex rw.repo.mLoadedMutex, rw.main.mLoadedMutex [5] (was: [0])
+// mPhysicsQ mMutex rw.repo.mLoadedMutex, rw.main.mLoadedMutex [5] (was: [0])
// mHeaderReqQ mMutex ro.repo.none [5], rw.repo.mMutex, rw.any.mMutex
// mLODReqQ mMutex ro.repo.none [5], rw.repo.mMutex, rw.any.mMutex
// mUnavailableQ mMutex rw.repo.none [0], ro.main.none [5], rw.main.mLoadedMutex
@@ -544,6 +545,66 @@ bool RequestStats::isDelayed() const
return mTimer.getStarted() && !mTimer.hasExpired();
}
+F32 calculate_score(LLVOVolume* object)
+{
+ if (!object)
+ {
+ return -1.f;
+ }
+ LLDrawable* drawable = object->mDrawable;
+ if (!drawable)
+ {
+ return -1;
+ }
+ if (drawable->isState(LLDrawable::RIGGED) || object->isAttachment())
+ {
+ LLVOAvatar* avatar = object->getAvatar();
+ LLDrawable* av_drawable = avatar ? avatar->mDrawable : nullptr;
+ if (avatar && av_drawable)
+ {
+ // See LLVOVolume::calcLOD()
+ F32 radius;
+ if (avatar->isControlAvatar())
+ {
+ const LLVector3* box = avatar->getLastAnimExtents();
+ LLVector3 diag = box[1] - box[0];
+ radius = diag.magVec() * 0.5f;
+ }
+ else
+ {
+ // Volume in a rigged mesh attached to a regular avatar.
+ const LLVector3* box = avatar->getLastAnimExtents();
+ LLVector3 diag = box[1] - box[0];
+ radius = diag.magVec();
+
+ if (!avatar->isSelf() && !avatar->hasFirstFullAttachmentData())
+ {
+ // slightly deprioritize avatars that are still receiving data
+ radius *= 0.9f;
+ }
+ }
+ return radius / llmax(av_drawable->mDistanceWRTCamera, 1.f);
+ }
+ }
+ return drawable->getRadius() / llmax(drawable->mDistanceWRTCamera, 1.f);
+}
+
+void PendingRequestBase::updateScore()
+{
+ mScore = 0;
+ if (mTrackedData)
+ {
+ for (LLVOVolume* volume : mTrackedData->mVolumes)
+ {
+ F32 cur_score = calculate_score(volume);
+ if (cur_score > 0)
+ {
+ mScore = llmax(mScore, cur_score);
+ }
+ }
+ }
+}
+
LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMaterial& material)
{
LLPointer< LLViewerFetchedTexture > * ppTex = static_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData);
@@ -756,8 +817,12 @@ public:
};
-void log_upload_error(LLCore::HttpStatus status, const LLSD& content,
- const char * const stage, const std::string & model_name)
+void log_upload_error(
+ LLCore::HttpStatus status,
+ const LLSD& content,
+ const char * const stage,
+ const std::string & model_name,
+ const std::vector<std::string> & texture_filenames)
{
// Add notification popup.
LLSD args;
@@ -815,6 +880,20 @@ void log_upload_error(LLCore::HttpStatus status, const LLSD& content,
error_num++;
}
}
+
+ if (err.has("TextureIndex"))
+ {
+ S32 texture_index = err["TextureIndex"].asInteger();
+ if (texture_index < texture_filenames.size())
+ {
+ args["MESSAGE"] = message + "\n" + texture_filenames[texture_index];
+ }
+ else
+ {
+ llassert(false); // figure out why or how texture wasn't in the list
+ args["MESSAGE"] = message + llformat("\nTexture index: %d", texture_index);
+ }
+ }
}
else
{
@@ -904,6 +983,12 @@ LLMeshRepoThread::~LLMeshRepoThread()
mDecompositionQ.pop_front();
}
+ while (!mPhysicsQ.empty())
+ {
+ delete mPhysicsQ.front();
+ mPhysicsQ.pop_front();
+ }
+
delete mHttpRequest;
mHttpRequest = nullptr;
delete mMutex;
@@ -1210,6 +1295,12 @@ void LLMeshRepoThread::run()
LL_WARNS(LOG_MESH) << "Convex decomposition unable to be quit." << LL_ENDL;
}
}
+void LLMeshRepoThread::cleanup()
+{
+ mShuttingDown = true;
+ mSignal->broadcast();
+ mMeshThreadPool->close();
+}
// Mutex: LLMeshRepoThread::mMutex must be held on entry
void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id)
@@ -1493,6 +1584,11 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
[mesh_id, buffer, size]
()
{
+ if (gMeshRepo.mThread->isShuttingDown())
+ {
+ delete[] buffer;
+ return;
+ }
if (!gMeshRepo.mThread->skinInfoReceived(mesh_id, buffer, size))
{
// either header is faulty or something else overwrote the cache
@@ -1798,42 +1894,36 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
//static
void LLMeshRepoThread::incActiveLODRequests()
{
- LLMutexLock lock(gMeshRepo.mThread->mMutex);
++LLMeshRepoThread::sActiveLODRequests;
}
//static
void LLMeshRepoThread::decActiveLODRequests()
{
- LLMutexLock lock(gMeshRepo.mThread->mMutex);
--LLMeshRepoThread::sActiveLODRequests;
}
//static
void LLMeshRepoThread::incActiveHeaderRequests()
{
- LLMutexLock lock(gMeshRepo.mThread->mMutex);
++LLMeshRepoThread::sActiveHeaderRequests;
}
//static
void LLMeshRepoThread::decActiveHeaderRequests()
{
- LLMutexLock lock(gMeshRepo.mThread->mMutex);
--LLMeshRepoThread::sActiveHeaderRequests;
}
//static
void LLMeshRepoThread::incActiveSkinRequests()
{
- LLMutexLock lock(gMeshRepo.mThread->mMutex);
++LLMeshRepoThread::sActiveSkinRequests;
}
//static
void LLMeshRepoThread::decActiveSkinRequests()
{
- LLMutexLock lock(gMeshRepo.mThread->mMutex);
--LLMeshRepoThread::sActiveSkinRequests;
}
@@ -1993,6 +2083,11 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
[params, mesh_id, lod, buffer, size]
()
{
+ if (gMeshRepo.mThread->isShuttingDown())
+ {
+ delete[] buffer;
+ return;
+ }
if (gMeshRepo.mThread->lodReceived(params, lod, buffer, size) == MESH_OK)
{
LL_DEBUGS(LOG_MESH) << "Mesh/Cache: Mesh body for ID " << mesh_id << " - was retrieved from the cache." << LL_ENDL;
@@ -2210,7 +2305,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
if (gMeshRepo.mLoadingSkins.find(mesh_id) == gMeshRepo.mLoadingSkins.end())
{
- gMeshRepo.mLoadingSkins[mesh_id] = {}; // add an empty vector to indicate to main thread that we are loading skin info
+ gMeshRepo.mLoadingSkins[mesh_id]; // add an empty vector to indicate to main thread that we are loading skin info
}
}
@@ -2222,6 +2317,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes
}
if (request_skin)
{
+ LLMutexLock lock(mMutex);
mSkinRequests.push_back(UUIDBasedRequest(mesh_id));
}
}
@@ -2292,7 +2388,13 @@ EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_p
LLPointer<LLVolume> volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod));
if (volume->unpackVolumeFaces(data, data_size))
{
- if (volume->getNumFaces() > 0)
+ // Use LLVolume::getNumVolumeFaces() here and not LLVolume::getNumFaces(),
+ // because setMeshAssetLoaded() has not yet been called for this volume
+ // (it is set later in LLMeshRepository::notifyMeshLoaded()), and
+ // getNumFaces() would return the number of faces in the LLProfile
+ // instead. HB
+ S32 num_faces = volume->getNumVolumeFaces();
+ if (num_faces > 0)
{
// if we have a valid SkinInfo, cache per-joint bounding boxes for this LOD
LLPointer<LLMeshSkinInfo> skin_info = nullptr;
@@ -2306,7 +2408,7 @@ EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_p
}
if (skin_info.notNull() && isAgentAvatarValid())
{
- for (S32 i = 0; i < volume->getNumFaces(); ++i)
+ for (S32 i = 0; i < num_faces; ++i)
{
// NOTE: no need to lock gAgentAvatarp as the state being checked is not changed after initialization
LLVolumeFace& face = volume->getVolumeFace(i);
@@ -2325,6 +2427,11 @@ EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_p
// might be good idea to turn mesh into pointer to avoid making a copy
mesh.mVolume = NULL;
}
+ {
+ // make sure skin info is not removed from list while we are decreasing reference count
+ LLMutexLock lock(mSkinMapMutex);
+ skin_info = nullptr;
+ }
return MESH_OK;
}
}
@@ -2361,7 +2468,7 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat
LLPointer<LLMeshSkinInfo> info = nullptr;
info = new LLMeshSkinInfo(mesh_id, skin);
- if (isAgentAvatarValid())
+ if (isAgentAvatarValid() && gAgentAvatarp->mInitFlags != 0)
{ // joint numbers are consistent inside LLVOAvatar and animations, but inconsistent inside meshes,
// generate a map of mesh joint numbers to LLVOAvatar joint numbers
LLSkinningUtil::initJointNums(info, gAgentAvatarp);
@@ -2465,14 +2572,15 @@ EMeshProcessingResult LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_
{
LLMutexLock lock(mLoadedMutex);
- mDecompositionQ.push_back(d);
+ mPhysicsQ.push_back(d);
}
return MESH_OK;
}
-LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures,
+LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list_t& data, const LLMeshUploadThread::lod_sources_map_t& sources_list,
+ LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints, bool lock_scale_if_joint_position,
- const std::string & upload_url, bool do_upload,
+ const std::string & upload_url, LLUUID destination_folder_id, bool do_upload,
LLHandle<LLWholeModelFeeObserver> fee_observer,
LLHandle<LLWholeModelUploadObserver> upload_observer)
: LLThread("mesh upload"),
@@ -2480,10 +2588,12 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
mDiscarded(false),
mDoUpload(do_upload),
mWholeModelUploadURL(upload_url),
+ mDestinationFolderId(destination_folder_id),
mFeeObserverHandle(fee_observer),
mUploadObserverHandle(upload_observer)
{
mInstanceList = data;
+ mLodSources = sources_list;
mUploadTextures = upload_textures;
mUploadSkin = upload_skin;
mUploadJoints = upload_joints;
@@ -2549,7 +2659,7 @@ void LLMeshUploadThread::DecompRequest::completed()
void LLMeshUploadThread::preStart()
{
//build map of LLModel refs to instances for callbacks
- for (instance_list::iterator iter = mInstanceList.begin(); iter != mInstanceList.end(); ++iter)
+ for (instance_list_t::iterator iter = mInstanceList.begin(); iter != mInstanceList.end(); ++iter)
{
mInstance[iter->mModel].push_back(*iter);
}
@@ -2583,6 +2693,8 @@ void dump_llsd_to_file(const LLSD& content, std::string filename)
{
if (gSavedSettings.getBOOL("MeshUploadLogXML"))
{
+ filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
+ filename);
llofstream of(filename.c_str());
LLSDSerialize::toPrettyXML(content,of);
}
@@ -2596,346 +2708,302 @@ LLSD llsd_from_file(std::string filename)
return result;
}
-void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
+void LLMeshUploadThread::packModelIntance(
+ LLModel* model,
+ LLMeshUploadThread::instance_list_t& instance_list,
+ std::string& model_name,
+ LLSD& res,
+ S32& mesh_num,
+ S32& texture_num,
+ S32& instance_num,
+ std::unordered_set<LLViewerTexture* >& textures,
+ std::unordered_map<LLViewerTexture*, S32> texture_index,
+ std::unordered_map<LLModel*, S32>& mesh_index,
+ std::vector<std::string>& texture_list_dest,
+ bool include_textures
+ )
{
- LLSD result;
-
- LLSD res;
- result["folder_id"] = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_OBJECT);
- result["texture_folder_id"] = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_TEXTURE);
- result["asset_type"] = "mesh";
- result["inventory_type"] = "object";
- result["description"] = "(No Description)";
- result["next_owner_mask"] = LLSD::Integer(LLFloaterPerms::getNextOwnerPerms("Uploads"));
- result["group_mask"] = LLSD::Integer(LLFloaterPerms::getGroupPerms("Uploads"));
- result["everyone_mask"] = LLSD::Integer(LLFloaterPerms::getEveryonePerms("Uploads"));
-
- res["mesh_list"] = LLSD::emptyArray();
- res["texture_list"] = LLSD::emptyArray();
- res["instance_list"] = LLSD::emptyArray();
- S32 mesh_num = 0;
- S32 texture_num = 0;
-
- std::unordered_set<LLViewerTexture* > textures;
- std::unordered_map<LLViewerTexture*,S32> texture_index;
+ LLMeshUploadData data;
+ data.mBaseModel = model;
- std::unordered_map<LLModel*,S32> mesh_index;
- std::string model_name;
-
- S32 instance_num = 0;
-
- for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
+ LLModelInstance& first_instance = *(instance_list.begin());
+ for (S32 i = 0; i < 5; i++)
{
- LLMeshUploadData data;
- data.mBaseModel = iter->first;
+ data.mModel[i] = first_instance.mLOD[i];
+ }
- if (data.mBaseModel->mSubmodelID)
+ if (mesh_index.find(data.mBaseModel) == mesh_index.end())
+ {
+ // Have not seen this model before - create a new mesh_list entry for it.
+ if (model_name.empty())
{
- // These are handled below to insure correct parenting order on creation
- // due to map walking being based on model address (aka random)
- continue;
+ model_name = data.mBaseModel->getName();
}
- LLModelInstance& first_instance = *(iter->second.begin());
- for (S32 i = 0; i < 5; i++)
- {
- data.mModel[i] = first_instance.mLOD[i];
- }
+ std::stringstream ostr;
- if (mesh_index.find(data.mBaseModel) == mesh_index.end())
- {
- // Have not seen this model before - create a new mesh_list entry for it.
- if (model_name.empty())
- {
- model_name = data.mBaseModel->getName();
- }
+ LLModel::Decomposition& decomp =
+ data.mModel[LLModel::LOD_PHYSICS].notNull() ?
+ data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
+ data.mBaseModel->mPhysics;
- std::stringstream ostr;
+ decomp.mBaseHull = mHullMap[data.mBaseModel];
- LLModel::Decomposition& decomp =
- data.mModel[LLModel::LOD_PHYSICS].notNull() ?
- data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
- data.mBaseModel->mPhysics;
+ LLSD mesh_header = LLModel::writeModel(
+ ostr,
+ data.mModel[LLModel::LOD_PHYSICS],
+ data.mModel[LLModel::LOD_HIGH],
+ data.mModel[LLModel::LOD_MEDIUM],
+ data.mModel[LLModel::LOD_LOW],
+ data.mModel[LLModel::LOD_IMPOSTOR],
+ decomp,
+ mUploadSkin,
+ mUploadJoints,
+ mLockScaleIfJointPosition,
+ LLModel::WRITE_BINARY,
+ false,
+ data.mBaseModel->mSubmodelID);
- decomp.mBaseHull = mHullMap[data.mBaseModel];
+ data.mAssetData = ostr.str();
+ std::string str = ostr.str();
- LLSD mesh_header = LLModel::writeModel(
- ostr,
- data.mModel[LLModel::LOD_PHYSICS],
- data.mModel[LLModel::LOD_HIGH],
- data.mModel[LLModel::LOD_MEDIUM],
- data.mModel[LLModel::LOD_LOW],
- data.mModel[LLModel::LOD_IMPOSTOR],
- decomp,
- mUploadSkin,
- mUploadJoints,
- mLockScaleIfJointPosition,
- false,
- false,
- data.mBaseModel->mSubmodelID);
+ res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(), str.end());
+ mesh_index[data.mBaseModel] = mesh_num;
+ mesh_num++;
+ }
- data.mAssetData = ostr.str();
- std::string str = ostr.str();
+ // For all instances that use this model
+ for (instance_list_t::iterator instance_iter = instance_list.begin();
+ instance_iter != instance_list.end();
+ ++instance_iter)
+ {
+ LLModelInstance& instance = *instance_iter;
- res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end());
- mesh_index[data.mBaseModel] = mesh_num;
- mesh_num++;
- }
+ LLSD instance_entry;
- // For all instances that use this model
- for (instance_list::iterator instance_iter = iter->second.begin();
- instance_iter != iter->second.end();
- ++instance_iter)
+ for (S32 i = 0; i < 5; i++)
{
+ data.mModel[i] = instance.mLOD[i];
+ }
- LLModelInstance& instance = *instance_iter;
-
- LLSD instance_entry;
+ LLVector3 pos, scale;
+ LLQuaternion rot;
+ LLMatrix4 transformation = instance.mTransform;
+ decomposeMeshMatrix(transformation, pos, rot, scale);
+ instance_entry["position"] = ll_sd_from_vector3(pos);
+ instance_entry["rotation"] = ll_sd_from_quaternion(rot);
+ instance_entry["scale"] = ll_sd_from_vector3(scale);
- for (S32 i = 0; i < 5; i++)
- {
- data.mModel[i] = instance.mLOD[i];
- }
+ instance_entry["material"] = LL_MCODE_WOOD;
+ if (model->mSubmodelID)
+ {
+ // Should it really be different?
+ instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_NONE);
+ }
+ else
+ {
+ instance_entry["physics_shape_type"] = data.mModel[LLModel::LOD_PHYSICS].notNull() ? (U8)(LLViewerObject::PHYSICS_SHAPE_PRIM) : (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
+ }
+ instance_entry["mesh"] = mesh_index[data.mBaseModel];
+ instance_entry["mesh_name"] = instance.mLabel;
- LLVector3 pos, scale;
- LLQuaternion rot;
- LLMatrix4 transformation = instance.mTransform;
- decomposeMeshMatrix(transformation,pos,rot,scale);
- instance_entry["position"] = ll_sd_from_vector3(pos);
- instance_entry["rotation"] = ll_sd_from_quaternion(rot);
- instance_entry["scale"] = ll_sd_from_vector3(scale);
+ instance_entry["face_list"] = LLSD::emptyArray();
- instance_entry["material"] = LL_MCODE_WOOD;
- instance_entry["physics_shape_type"] = data.mModel[LLModel::LOD_PHYSICS].notNull() ? (U8)(LLViewerObject::PHYSICS_SHAPE_PRIM) : (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
- instance_entry["mesh"] = mesh_index[data.mBaseModel];
- instance_entry["mesh_name"] = instance.mLabel;
+ // We want to be able to allow more than 8 materials...
+ //
+ S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), instance.mModel->getNumVolumeFaces());
- instance_entry["face_list"] = LLSD::emptyArray();
+ for (S32 face_num = 0; face_num < end; face_num++)
+ {
+ // multiple faces can reuse the same material
+ LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
+ LLSD face_entry = LLSD::emptyMap();
- // We want to be able to allow more than 8 materials...
- //
- S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), instance.mModel->getNumVolumeFaces()) ;
+ LLViewerFetchedTexture* texture = NULL;
- for (S32 face_num = 0; face_num < end; face_num++)
+ if (material.mDiffuseMapFilename.size())
{
- // multiple faces can reuse the same material
- LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
- LLSD face_entry = LLSD::emptyMap();
+ texture = FindViewerTexture(material);
+ }
- LLViewerFetchedTexture *texture = NULL;
+ if ((texture != NULL) &&
+ (textures.find(texture) == textures.end()))
+ {
+ textures.insert(texture);
+ }
- if (material.mDiffuseMapFilename.size())
+ std::stringstream texture_str;
+ if (texture != NULL && include_textures && mUploadTextures)
+ {
+ if (texture->hasSavedRawImage())
{
- texture = FindViewerTexture(material);
- }
+ LLImageDataLock lock(texture->getSavedRawImage());
- if ((texture != NULL) &&
- (textures.find(texture) == textures.end()))
- {
- textures.insert(texture);
- }
+ LLPointer<LLImageJ2C> upload_file =
+ LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
- std::stringstream texture_str;
- if (texture != NULL && include_textures && mUploadTextures)
- {
- if (texture->hasSavedRawImage())
+ if (!upload_file.isNull() && upload_file->getDataSize() && !upload_file->isBufferInvalid())
{
- LLImageDataLock lock(texture->getSavedRawImage());
-
- LLPointer<LLImageJ2C> upload_file =
- LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
-
- if (!upload_file.isNull() && upload_file->getDataSize())
- {
- texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
- }
+ texture_str.write((const char*)upload_file->getData(), upload_file->getDataSize());
}
}
+ }
- if (texture != NULL &&
- mUploadTextures &&
- texture_index.find(texture) == texture_index.end())
- {
- texture_index[texture] = texture_num;
- std::string str = texture_str.str();
- res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
- texture_num++;
- }
-
- // Subset of TextureEntry fields.
- if (texture != NULL && mUploadTextures)
- {
- face_entry["image"] = texture_index[texture];
- face_entry["scales"] = 1.0;
- face_entry["scalet"] = 1.0;
- face_entry["offsets"] = 0.0;
- face_entry["offsett"] = 0.0;
- face_entry["imagerot"] = 0.0;
- }
- face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor);
- face_entry["fullbright"] = material.mFullbright;
- instance_entry["face_list"][face_num] = face_entry;
+ if (texture != NULL &&
+ mUploadTextures &&
+ texture_index.find(texture) == texture_index.end())
+ {
+ texture_index[texture] = texture_num;
+ std::string str = texture_str.str();
+ res["texture_list"][texture_num] = LLSD::Binary(str.begin(), str.end());
+ // store indexes for error handling;
+ texture_list_dest.push_back(material.mDiffuseMapFilename);
+ texture_num++;
}
- res["instance_list"][instance_num] = instance_entry;
- instance_num++;
+ // Subset of TextureEntry fields.
+ if (texture != NULL && mUploadTextures)
+ {
+ face_entry["image"] = texture_index[texture];
+ face_entry["scales"] = 1.0;
+ face_entry["scalet"] = 1.0;
+ face_entry["offsets"] = 0.0;
+ face_entry["offsett"] = 0.0;
+ face_entry["imagerot"] = 0.0;
+ }
+ face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor);
+ face_entry["fullbright"] = material.mFullbright;
+ instance_entry["face_list"][face_num] = face_entry;
}
+
+ res["instance_list"][instance_num] = instance_entry;
+ instance_num++;
}
+}
+
+void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, std::vector<std::string>& texture_list_dest, bool include_textures)
+{
+ LLSD result;
- for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
+ LLSD res;
+ if (mDestinationFolderId.isNull())
{
- LLMeshUploadData data;
- data.mBaseModel = iter->first;
+ result["folder_id"] = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_OBJECT);
+ result["texture_folder_id"] = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_TEXTURE);
+ }
+ else
+ {
+ result["folder_id"] = mDestinationFolderId;
+ result["texture_folder_id"] = mDestinationFolderId;
+ }
+ result["asset_type"] = "mesh";
+ result["inventory_type"] = "object";
+ result["description"] = "(No Description)";
+ result["next_owner_mask"] = LLSD::Integer(LLFloaterPerms::getNextOwnerPerms("Uploads"));
+ result["group_mask"] = LLSD::Integer(LLFloaterPerms::getGroupPerms("Uploads"));
+ result["everyone_mask"] = LLSD::Integer(LLFloaterPerms::getEveryonePerms("Uploads"));
+
+ res["mesh_list"] = LLSD::emptyArray();
+ res["texture_list"] = LLSD::emptyArray();
+ res["instance_list"] = LLSD::emptyArray();
+ LLSD& lod_sources = res["source_format"];
+ lod_sources["high"] = 0;
+ for (auto &source : mLodSources)
+ {
+ lod_sources[source.first] = source.second;
+ }
+ S32 mesh_num = 0;
+ S32 texture_num = 0;
+ S32 instance_num = 0;
+
+ std::unordered_set<LLViewerTexture* > textures;
+ std::unordered_map<LLViewerTexture*,S32> texture_index;
+
+ std::unordered_map<LLModel*,S32> mesh_index;
+ std::string model_name;
- if (!data.mBaseModel->mSubmodelID)
+ // If server gets a m1, m2, m3, m4 list, m1 becomes the root
+ // and the rest go as m4, m3, m2
+ // to counter that mInstance is sorted as m4, m3, m2, m1
+ // and we grab m1 from the end and send it first
+ LLModel* root_model = nullptr;
+ for (instance_map_t::reverse_iterator iter = mInstance.rbegin(); iter != mInstance.rend(); ++iter)
+ {
+ if (iter->first->mSubmodelID)
{
- // These were handled above already...
- //
+ // Submodel can't be root
continue;
}
-
- LLModelInstance& first_instance = *(iter->second.begin());
- for (S32 i = 0; i < 5; i++)
+ root_model = iter->first;
+ packModelIntance(
+ iter->first,
+ iter->second,
+ model_name,
+ res,
+ mesh_num,
+ texture_num,
+ instance_num,
+ textures,
+ texture_index,
+ mesh_index,
+ texture_list_dest,
+ include_textures);
+ break;
+ }
+
+ // Handle models, ignore submodels for now.
+ // Probably should pre-sort by mSubmodelID instead of running twice.
+ // Note: mInstance should be sorted by model name for the sake of
+ // deterministic order.
+ for (auto& iter : mInstance)
+ {
+ if (iter.first->mSubmodelID)
{
- data.mModel[i] = first_instance.mLOD[i];
+ // These are handled below to insure correct parenting order on creation
+ // due to map walking being based on model address (aka random)
+ continue;
}
-
- if (mesh_index.find(data.mBaseModel) == mesh_index.end())
+ if (root_model == iter.first)
{
- // Have not seen this model before - create a new mesh_list entry for it.
- if (model_name.empty())
- {
- model_name = data.mBaseModel->getName();
- }
-
- std::stringstream ostr;
-
- LLModel::Decomposition& decomp =
- data.mModel[LLModel::LOD_PHYSICS].notNull() ?
- data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
- data.mBaseModel->mPhysics;
-
- decomp.mBaseHull = mHullMap[data.mBaseModel];
-
- LLSD mesh_header = LLModel::writeModel(
- ostr,
- data.mModel[LLModel::LOD_PHYSICS],
- data.mModel[LLModel::LOD_HIGH],
- data.mModel[LLModel::LOD_MEDIUM],
- data.mModel[LLModel::LOD_LOW],
- data.mModel[LLModel::LOD_IMPOSTOR],
- decomp,
- mUploadSkin,
- mUploadJoints,
- mLockScaleIfJointPosition,
- false,
- false,
- data.mBaseModel->mSubmodelID);
-
- data.mAssetData = ostr.str();
- std::string str = ostr.str();
-
- res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end());
- mesh_index[data.mBaseModel] = mesh_num;
- mesh_num++;
+ // Reached root, root was already packed and is last non-submodel
+ break;
}
+ packModelIntance(
+ iter.first,
+ iter.second,
+ model_name,
+ res,
+ mesh_num,
+ texture_num,
+ instance_num,
+ textures,
+ texture_index,
+ mesh_index,
+ texture_list_dest,
+ include_textures);
+ }
- // For all instances that use this model
- for (instance_list::iterator instance_iter = iter->second.begin();
- instance_iter != iter->second.end();
- ++instance_iter)
+ // Now handle the submodels.
+ for (auto& iter : mInstance)
+ {
+ if (!iter.first->mSubmodelID)
{
-
- LLModelInstance& instance = *instance_iter;
-
- LLSD instance_entry;
-
- for (S32 i = 0; i < 5; i++)
- {
- data.mModel[i] = instance.mLOD[i];
- }
-
- LLVector3 pos, scale;
- LLQuaternion rot;
- LLMatrix4 transformation = instance.mTransform;
- decomposeMeshMatrix(transformation,pos,rot,scale);
- instance_entry["position"] = ll_sd_from_vector3(pos);
- instance_entry["rotation"] = ll_sd_from_quaternion(rot);
- instance_entry["scale"] = ll_sd_from_vector3(scale);
-
- instance_entry["material"] = LL_MCODE_WOOD;
- instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_NONE);
- instance_entry["mesh"] = mesh_index[data.mBaseModel];
-
- instance_entry["face_list"] = LLSD::emptyArray();
-
- // We want to be able to allow more than 8 materials...
- //
- S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ;
-
- for (S32 face_num = 0; face_num < end; face_num++)
- {
- LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
- LLSD face_entry = LLSD::emptyMap();
-
- LLViewerFetchedTexture *texture = NULL;
-
- if (material.mDiffuseMapFilename.size())
- {
- texture = FindViewerTexture(material);
- }
-
- if ((texture != NULL) &&
- (textures.find(texture) == textures.end()))
- {
- textures.insert(texture);
- }
-
- std::stringstream texture_str;
- if (texture != NULL && include_textures && mUploadTextures)
- {
- if (texture->hasSavedRawImage())
- {
- LLImageDataLock lock(texture->getSavedRawImage());
-
- LLPointer<LLImageJ2C> upload_file =
- LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
-
- if (!upload_file.isNull() && upload_file->getDataSize())
- {
- texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
- }
- }
- }
-
- if (texture != NULL &&
- mUploadTextures &&
- texture_index.find(texture) == texture_index.end())
- {
- texture_index[texture] = texture_num;
- std::string str = texture_str.str();
- res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
- texture_num++;
- }
-
- // Subset of TextureEntry fields.
- if (texture != NULL && mUploadTextures)
- {
- face_entry["image"] = texture_index[texture];
- face_entry["scales"] = 1.0;
- face_entry["scalet"] = 1.0;
- face_entry["offsets"] = 0.0;
- face_entry["offsett"] = 0.0;
- face_entry["imagerot"] = 0.0;
- }
- face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor);
- face_entry["fullbright"] = material.mFullbright;
- instance_entry["face_list"][face_num] = face_entry;
- }
-
- res["instance_list"][instance_num] = instance_entry;
- instance_num++;
+ // These were handled above already...
+ continue;
}
+ packModelIntance(
+ iter.first,
+ iter.second,
+ model_name,
+ res,
+ mesh_num,
+ texture_num,
+ instance_num,
+ textures,
+ texture_index,
+ mesh_index,
+ texture_list_dest,
+ include_textures);
}
if (model_name.empty()) model_name = "mesh model";
@@ -2951,7 +3019,7 @@ void LLMeshUploadThread::generateHulls()
{
bool has_valid_requests = false ;
- for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
+ for (instance_map_t::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
{
LLMeshUploadData data;
data.mBaseModel = iter->first;
@@ -3023,7 +3091,8 @@ void LLMeshUploadThread::doWholeModelUpload()
LL_DEBUGS(LOG_MESH) << "Hull generation completed." << LL_ENDL;
mModelData = LLSD::emptyMap();
- wholeModelToLLSD(mModelData, true);
+ mTextureFiles.clear();
+ wholeModelToLLSD(mModelData, mTextureFiles, true);
LLSD body = mModelData["asset_resources"];
dump_llsd_to_file(body, make_dump_name("whole_model_body_", dump_num));
@@ -3076,7 +3145,8 @@ void LLMeshUploadThread::requestWholeModelFee()
generateHulls();
mModelData = LLSD::emptyMap();
- wholeModelToLLSD(mModelData, false);
+ mTextureFiles.clear();
+ wholeModelToLLSD(mModelData, mTextureFiles, false);
dump_llsd_to_file(mModelData, make_dump_name("whole_model_fee_request_", dump_num));
LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,
mHttpPolicyClass,
@@ -3142,7 +3212,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
body["error"] = LLSD::emptyMap();
body["error"]["message"] = reason;
body["error"]["identifier"] = "NetworkError"; // from asset-upload/upload_util.py
- log_upload_error(status, body, "upload", mModelData["name"].asString());
+ log_upload_error(status, body, "upload", mModelData["name"].asString(), mTextureFiles);
if (observer)
{
@@ -3177,7 +3247,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
else
{
LL_WARNS(LOG_MESH) << "Upload failed. Not in expected 'complete' state." << LL_ENDL;
- log_upload_error(status, body, "upload", mModelData["name"].asString());
+ log_upload_error(status, body, "upload", mModelData["name"].asString(), mTextureFiles);
if (observer)
{
@@ -3202,7 +3272,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
body["error"] = LLSD::emptyMap();
body["error"]["message"] = reason;
body["error"]["identifier"] = "NetworkError"; // from asset-upload/upload_util.py
- log_upload_error(status, body, "fee", mModelData["name"].asString());
+ log_upload_error(status, body, "fee", mModelData["name"].asString(), mTextureFiles);
if (observer)
{
@@ -3235,7 +3305,7 @@ void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResp
else
{
LL_WARNS(LOG_MESH) << "Fee request failed. Not in expected 'upload' state." << LL_ENDL;
- log_upload_error(status, body, "fee", mModelData["name"].asString());
+ log_upload_error(status, body, "fee", mModelData["name"].asString(), mTextureFiles);
if (observer)
{
@@ -3313,13 +3383,14 @@ void LLMeshRepoThread::notifyLoadedMeshes()
}
}
- if (!mSkinInfoQ.empty() || !mSkinUnavailableQ.empty() || ! mDecompositionQ.empty())
+ if (!mSkinInfoQ.empty() || !mSkinUnavailableQ.empty() || !mDecompositionQ.empty() || !mPhysicsQ.empty())
{
if (mLoadedMutex->trylock())
{
std::deque<LLPointer<LLMeshSkinInfo>> skin_info_q;
std::deque<UUIDBasedRequest> skin_info_unavail_q;
std::list<LLModel::Decomposition*> decomp_q;
+ std::list<LLModel::Decomposition*> physics_q;
if (! mSkinInfoQ.empty())
{
@@ -3336,6 +3407,11 @@ void LLMeshRepoThread::notifyLoadedMeshes()
decomp_q.swap(mDecompositionQ);
}
+ if (!mPhysicsQ.empty())
+ {
+ physics_q.swap(mPhysicsQ);
+ }
+
mLoadedMutex->unlock();
// Process the elements free of the lock
@@ -3352,9 +3428,15 @@ void LLMeshRepoThread::notifyLoadedMeshes()
while (! decomp_q.empty())
{
- gMeshRepo.notifyDecompositionReceived(decomp_q.front());
+ gMeshRepo.notifyDecompositionReceived(decomp_q.front(), false);
decomp_q.pop_front();
}
+
+ while (!physics_q.empty())
+ {
+ gMeshRepo.notifyDecompositionReceived(physics_q.front(), true);
+ physics_q.pop_front();
+ }
}
}
@@ -3792,6 +3874,11 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body
[shrd_handler, data, data_size]
()
{
+ if (gMeshRepo.mThread->isShuttingDown())
+ {
+ delete[] data;
+ return;
+ }
LLMeshLODHandler* handler = (LLMeshLODHandler * )shrd_handler.get();
handler->processLod(data, data_size);
delete[] data;
@@ -3905,6 +3992,11 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /*
[shrd_handler, data, data_size]
()
{
+ if (gMeshRepo.mThread->isShuttingDown())
+ {
+ delete[] data;
+ return;
+ }
LLMeshSkinInfoHandler* handler = (LLMeshSkinInfoHandler*)shrd_handler.get();
handler->processSkin(data, data_size);
delete[] data;
@@ -4127,8 +4219,7 @@ void LLMeshRepository::shutdown()
mUploads[i]->discard() ; //discard the uploading requests.
}
- mThread->mSignal->broadcast();
- mThread->mMeshThreadPool->close();
+ mThread->cleanup();
while (!mThread->isStopped())
{
@@ -4193,13 +4284,13 @@ void LLMeshRepository::unregisterMesh(LLVOVolume* vobj)
{
for (auto& param : lod)
{
- vector_replace_with_last(param.second, vobj);
+ vector_replace_with_last(param.second.mVolumes, vobj);
}
}
for (auto& skin_pair : mLoadingSkins)
{
- vector_replace_with_last(skin_pair.second, vobj);
+ vector_replace_with_last(skin_pair.second.mVolumes, vobj);
}
}
@@ -4222,16 +4313,17 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
mesh_load_map::iterator iter = mLoadingMeshes[new_lod].find(mesh_id);
if (iter != mLoadingMeshes[new_lod].end())
{ //request pending for this mesh, append volume id to list
- auto it = std::find(iter->second.begin(), iter->second.end(), vobj);
- if (it == iter->second.end()) {
- iter->second.push_back(vobj);
+ auto it = std::find(iter->second.mVolumes.begin(), iter->second.mVolumes.end(), vobj);
+ if (it == iter->second.mVolumes.end()) {
+ iter->second.addVolume(vobj);
}
}
else
{
//first request for this mesh
- mLoadingMeshes[new_lod][mesh_id].push_back(vobj);
- mPendingRequests.emplace_back(new PendingRequestLOD(mesh_params, new_lod));
+ std::shared_ptr<PendingRequestBase> request(new PendingRequestLOD(mesh_params, new_lod));
+ mPendingRequests.emplace_back(request);
+ mLoadingMeshes[new_lod][mesh_id].initData(vobj, request);
LLMeshRepository::sLODPending++;
}
}
@@ -4290,50 +4382,6 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
return new_lod;
}
-F32 calculate_score(LLVOVolume* object)
-{
- if (!object)
- {
- return -1.f;
- }
- LLDrawable* drawable = object->mDrawable;
- if (!drawable)
- {
- return -1;
- }
- if (drawable->isState(LLDrawable::RIGGED) || object->isAttachment())
- {
- LLVOAvatar* avatar = object->getAvatar();
- LLDrawable* av_drawable = avatar ? avatar->mDrawable : nullptr;
- if (avatar && av_drawable)
- {
- // See LLVOVolume::calcLOD()
- F32 radius;
- if (avatar->isControlAvatar())
- {
- const LLVector3* box = avatar->getLastAnimExtents();
- LLVector3 diag = box[1] - box[0];
- radius = diag.magVec() * 0.5f;
- }
- else
- {
- // Volume in a rigged mesh attached to a regular avatar.
- const LLVector3* box = avatar->getLastAnimExtents();
- LLVector3 diag = box[1] - box[0];
- radius = diag.magVec();
-
- if (!avatar->isSelf() && !avatar->hasFirstFullAttachmentData())
- {
- // slightly deprioritize avatars that are still receiving data
- radius *= 0.9f;
- }
- }
- return radius / llmax(av_drawable->mDistanceWRTCamera, 1.f);
- }
- }
- return drawable->getRadius() / llmax(drawable->mDistanceWRTCamera, 1.f);
-}
-
void LLMeshRepository::notifyLoadedMeshes()
{ //called from main thread
LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; //LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH);
@@ -4470,13 +4518,20 @@ void LLMeshRepository::notifyLoadedMeshes()
{
LLMutexTrylock lock1(mMeshMutex);
LLMutexTrylock lock2(mThread->mMutex);
+ LLMutexTrylock lock3(mThread->mHeaderMutex);
+ LLMutexTrylock lock4(mThread->mPendingMutex);
static U32 hold_offs(0);
- if (! lock1.isLocked() || ! lock2.isLocked())
+ if (! lock1.isLocked() || ! lock2.isLocked() || ! lock3.isLocked() || ! lock4.isLocked())
{
// If we can't get the locks, skip and pick this up later.
+ // Eventually thread queue will be free enough
++hold_offs;
sMaxLockHoldoffs = llmax(sMaxLockHoldoffs, hold_offs);
+ if (hold_offs > 4)
+ {
+ LL_WARNS_ONCE() << "High mesh thread holdoff" << LL_ENDL;
+ }
return;
}
hold_offs = 0;
@@ -4523,61 +4578,25 @@ void LLMeshRepository::notifyLoadedMeshes()
if (mPendingRequests.size() > push_count)
{
+ LL_PROFILE_ZONE_NAMED("Mesh score update");
// More requests than the high-water limit allows so
// sort and forward the most important.
- //calculate "score" for pending requests
-
- //create score map
- std::map<LLUUID, F32> score_map;
-
- for (U32 i = 0; i < LLVolumeLODGroup::NUM_LODS; ++i)
+ // update "score" for pending requests
+ for (std::shared_ptr<PendingRequestBase>& req_p : mPendingRequests)
{
- for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter)
- {
- F32 max_score = 0.f;
- for (auto obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)
- {
- F32 cur_score = calculate_score(*obj_iter);
- if (cur_score >= 0.f)
- {
- max_score = llmax(max_score, cur_score);
- }
- }
-
- score_map[iter->first] = max_score;
- }
- }
- for (mesh_load_map::iterator iter = mLoadingSkins.begin(); iter != mLoadingSkins.end(); ++iter)
- {
- F32 max_score = 0.f;
- for (auto obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)
- {
- F32 cur_score = calculate_score(*obj_iter);
- if (cur_score >= 0.f)
- {
- max_score = llmax(max_score, cur_score);
- }
- }
-
- score_map[iter->first] = max_score;
- }
-
- //set "score" for pending requests
- for (std::unique_ptr<PendingRequestBase>& req_p : mPendingRequests)
- {
- req_p->setScore(score_map[req_p->getId()]);
+ req_p->checkScore();
}
//sort by "score"
std::partial_sort(mPendingRequests.begin(), mPendingRequests.begin() + push_count,
mPendingRequests.end(), PendingRequestBase::CompareScoreGreater());
}
- LLMutexTrylock lock3(mThread->mHeaderMutex);
- LLMutexTrylock lock4(mThread->mPendingMutex);
while (!mPendingRequests.empty() && push_count > 0)
{
- std::unique_ptr<PendingRequestBase>& req_p = mPendingRequests.front();
+ std::shared_ptr<PendingRequestBase>& req_p = mPendingRequests.front();
+ // todo: check hasTrackedData here and erase request if none
+ // since this is supposed to mean that request was removed
switch (req_p->getRequestType())
{
case MESH_REQUEST_LOD:
@@ -4632,7 +4651,7 @@ void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo* info)
skin_load_map::iterator iter = mLoadingSkins.find(info->mMeshID);
if (iter != mLoadingSkins.end())
{
- for (LLVOVolume* vobj : iter->second)
+ for (LLVOVolume* vobj : iter->second.mVolumes)
{
if (vobj)
{
@@ -4648,7 +4667,7 @@ void LLMeshRepository::notifySkinInfoUnavailable(const LLUUID& mesh_id)
skin_load_map::iterator iter = mLoadingSkins.find(mesh_id);
if (iter != mLoadingSkins.end())
{
- for (LLVOVolume* vobj : iter->second)
+ for (LLVOVolume* vobj : iter->second.mVolumes)
{
if (vobj)
{
@@ -4659,13 +4678,13 @@ void LLMeshRepository::notifySkinInfoUnavailable(const LLUUID& mesh_id)
}
}
-void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decomp)
+void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decomp, bool physics_mesh)
{
- decomposition_map::iterator iter = mDecompositionMap.find(decomp->mMeshID);
+ LLUUID decomp_id = decomp->mMeshID; // Copy to avoid invalidation in below deletion
+ decomposition_map::iterator iter = mDecompositionMap.find(decomp_id);
if (iter == mDecompositionMap.end())
{ //just insert decomp into map
- mDecompositionMap[decomp->mMeshID] = decomp;
- mLoadingDecompositions.erase(decomp->mMeshID);
+ mDecompositionMap[decomp_id] = decomp;
sCacheBytesDecomps += decomp->sizeBytes();
}
else
@@ -4673,10 +4692,17 @@ void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decom
sCacheBytesDecomps -= iter->second->sizeBytes();
iter->second->merge(decomp);
sCacheBytesDecomps += iter->second->sizeBytes();
-
- mLoadingDecompositions.erase(decomp->mMeshID);
delete decomp;
}
+
+ if (physics_mesh)
+ {
+ mLoadingPhysicsShapes.erase(decomp_id);
+ }
+ else
+ {
+ mLoadingDecompositions.erase(decomp_id);
+ }
}
void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume, S32 lod)
@@ -4712,7 +4738,7 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
}
//notify waiting LLVOVolume instances that their requested mesh is available
- for (LLVOVolume* vobj : obj_iter->second)
+ for (LLVOVolume* vobj : obj_iter->second.mVolumes)
{
if (vobj)
{
@@ -4742,7 +4768,7 @@ void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params,
LLPrimitive::getVolumeManager()->unrefVolume(sys_volume);
}
- for (LLVOVolume* vobj : obj_iter->second)
+ for (LLVOVolume* vobj : obj_iter->second.mVolumes)
{
if (vobj)
{
@@ -4785,16 +4811,17 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOV
skin_load_map::iterator iter = mLoadingSkins.find(mesh_id);
if (iter != mLoadingSkins.end())
{ //request pending for this mesh, append volume id to list
- auto it = std::find(iter->second.begin(), iter->second.end(), requesting_obj);
- if (it == iter->second.end()) {
- iter->second.push_back(requesting_obj);
+ auto it = std::find(iter->second.mVolumes.begin(), iter->second.mVolumes.end(), requesting_obj);
+ if (it == iter->second.mVolumes.end()) {
+ iter->second.addVolume(requesting_obj);
}
}
else
{
//first request for this mesh
- mLoadingSkins[mesh_id].push_back(requesting_obj);
- mPendingRequests.emplace_back(new PendingRequestUUID(mesh_id, MESH_REQUEST_SKIN));
+ std::shared_ptr<PendingRequestBase> request(new PendingRequestUUID(mesh_id, MESH_REQUEST_SKIN));
+ mLoadingSkins[mesh_id].initData(requesting_obj, request);
+ mPendingRequests.emplace_back(request);
}
}
}
@@ -4822,7 +4849,6 @@ void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id)
std::unordered_set<LLUUID>::iterator iter = mLoadingPhysicsShapes.find(mesh_id);
if (iter == mLoadingPhysicsShapes.end())
{ //no request pending for this skin info
- // *FIXME: Nothing ever deletes entries, can't be right
mLoadingPhysicsShapes.insert(mesh_id);
mPendingPhysicsShapeRequests.push(mesh_id);
}
@@ -4971,14 +4997,15 @@ bool LLMeshRepoThread::hasHeader(const LLUUID& mesh_id) const
return iter != mMeshHeader.end();
}
-void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
+void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, const std::map<std::string, std::string> &lod_sources,
+ LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints, bool lock_scale_if_joint_position,
- std::string upload_url, bool do_upload,
+ std::string upload_url, const LLUUID& destination_folder_id, bool do_upload,
LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer)
{
- LLMeshUploadThread* thread = new LLMeshUploadThread(data, scale, upload_textures,
+ LLMeshUploadThread* thread = new LLMeshUploadThread(data, lod_sources, scale, upload_textures,
upload_skin, upload_joints, lock_scale_if_joint_position,
- upload_url, do_upload, fee_observer, upload_observer);
+ upload_url, destination_folder_id, do_upload, fee_observer, upload_observer);
mUploadWaitList.push_back(thread);
}
@@ -5968,13 +5995,7 @@ bool LLMeshRepository::meshUploadEnabled()
bool LLMeshRepository::meshRezEnabled()
{
static LLCachedControl<bool> mesh_enabled(gSavedSettings, "MeshEnabled");
- LLViewerRegion *region = gAgent.getRegion();
- if(mesh_enabled &&
- region)
- {
- return region->meshRezEnabled();
- }
- return false;
+ return mesh_enabled;
}
// Threading: main thread only