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.cpp194
1 files changed, 116 insertions, 78 deletions
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 6e0722bcf9..be11c53efa 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -78,6 +78,14 @@ LLMeshRepository gMeshRepo;
const U32 MAX_MESH_REQUESTS_PER_SECOND = 100;
+// Maximum mesh version to support. Three least significant digits are reserved for the minor version,
+// with major version changes indicating a format change that is not backwards compatible and should not
+// be parsed by viewers that don't specifically support that version. For example, if the integer "1" is
+// present, the version is 0.001. A viewer that can parse version 0.001 can also parse versions up to 0.999,
+// but not 1.0 (integer 1000).
+// See wiki at https://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format
+const S32 MAX_MESH_VERSION = 999;
+
U32 LLMeshRepository::sBytesReceived = 0;
U32 LLMeshRepository::sHTTPRequestCount = 0;
U32 LLMeshRepository::sHTTPRetryCount = 0;
@@ -843,12 +851,13 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
if (header_size > 0)
{
+ S32 version = mMeshHeader[mesh_id]["version"].asInteger();
S32 offset = header_size + mMeshHeader[mesh_id]["skin"]["offset"].asInteger();
S32 size = mMeshHeader[mesh_id]["skin"]["size"].asInteger();
mHeaderMutex->unlock();
- if (offset >= 0 && size > 0)
+ if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)
{
//check VFS for mesh skin info
LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH);
@@ -915,12 +924,13 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
if (header_size > 0)
{
+ S32 version = mMeshHeader[mesh_id]["version"].asInteger();
S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger();
S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger();
mHeaderMutex->unlock();
- if (offset >= 0 && size > 0)
+ if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)
{
//check VFS for mesh skin info
LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH);
@@ -987,12 +997,13 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
if (header_size > 0)
{
+ S32 version = mMeshHeader[mesh_id]["version"].asInteger();
S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger();
S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger();
mHeaderMutex->unlock();
- if (offset >= 0 && size > 0)
+ if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)
{
//check VFS for mesh physics shape info
LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH);
@@ -1103,10 +1114,12 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
if (header_size > 0)
{
+ S32 version = mMeshHeader[mesh_id]["version"].asInteger();
S32 offset = header_size + mMeshHeader[mesh_id][header_lod[lod]]["offset"].asInteger();
S32 size = mMeshHeader[mesh_id][header_lod[lod]]["size"].asInteger();
mHeaderMutex->unlock();
- if (offset >= 0 && size > 0)
+
+ if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)
{
//check VFS for mesh asset
@@ -1383,6 +1396,8 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
mWholeModelFeeCapability = gAgent.getRegion()->getCapability("NewFileAgentInventory");
mOrigin += gAgent.getAtAxis() * scale.magVec();
+
+ mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut") ;
}
LLMeshUploadThread::~LLMeshUploadThread()
@@ -1573,6 +1588,11 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
for (S32 face_num = 0; face_num < data.mBaseModel->getNumVolumeFaces(); face_num++)
{
+ if(face_num >= instance.mMaterial.size())
+ {
+ break ;
+ }
+
LLImportMaterial& material = instance.mMaterial[face_num];
LLSD face_entry = LLSD::emptyMap();
LLViewerFetchedTexture *texture = material.mDiffuseMap.get();
@@ -1686,7 +1706,7 @@ void LLMeshUploadThread::doWholeModelUpload()
mPendingUploads++;
LLCurlRequest::headers_t headers;
mCurlRequest->post(mWholeModelFeeCapability, headers, model_data,
- new LLWholeModelFeeResponder(this,model_data));
+ new LLWholeModelFeeResponder(this,model_data), mMeshUploadTimeOut);
do
{
@@ -1705,7 +1725,7 @@ void LLMeshUploadThread::doWholeModelUpload()
LLSD body = full_model_data["asset_resources"];
dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num));
mCurlRequest->post(mWholeModelUploadURL, headers, body,
- new LLWholeModelUploadResponder(this, model_data));
+ new LLWholeModelUploadResponder(this, model_data), mMeshUploadTimeOut);
do
{
mCurlRequest->process();
@@ -1799,7 +1819,9 @@ S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod)
{
lod = llclamp(lod, 0, 3);
- if (header.has("404"))
+ S32 version = header["version"];
+
+ if (header.has("404") || version > MAX_MESH_VERSION)
{
return -1;
}
@@ -2135,54 +2157,59 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
LLUUID mesh_id = mMeshParams.getSculptID();
LLSD header = gMeshRepo.mThread->mMeshHeader[mesh_id];
- std::stringstream str;
+ S32 version = header["version"].asInteger();
+
+ if (version <= MAX_MESH_VERSION)
+ {
+ std::stringstream str;
- S32 lod_bytes = 0;
+ S32 lod_bytes = 0;
- for (U32 i = 0; i < LLModel::LOD_PHYSICS; ++i)
- { //figure out how many bytes we'll need to reserve in the file
- std::string lod_name = header_lod[i];
- lod_bytes = llmax(lod_bytes, header[lod_name]["offset"].asInteger()+header[lod_name]["size"].asInteger());
- }
+ for (U32 i = 0; i < LLModel::LOD_PHYSICS; ++i)
+ { //figure out how many bytes we'll need to reserve in the file
+ std::string lod_name = header_lod[i];
+ lod_bytes = llmax(lod_bytes, header[lod_name]["offset"].asInteger()+header[lod_name]["size"].asInteger());
+ }
- //just in case skin info or decomposition is at the end of the file (which it shouldn't be)
- lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger());
- lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger());
+ //just in case skin info or decomposition is at the end of the file (which it shouldn't be)
+ lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger());
+ lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger());
- S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id];
- S32 bytes = lod_bytes + header_bytes;
+ S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id];
+ S32 bytes = lod_bytes + header_bytes;
- //it's possible for the remote asset to have more data than is needed for the local cache
- //only allocate as much space in the VFS as is needed for the local cache
- data_size = llmin(data_size, bytes);
+ //it's possible for the remote asset to have more data than is needed for the local cache
+ //only allocate as much space in the VFS as is needed for the local cache
+ data_size = llmin(data_size, bytes);
- LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH, LLVFile::WRITE);
- if (file.getMaxSize() >= bytes || file.setMaxSize(bytes))
- {
- LLMeshRepository::sCacheBytesWritten += data_size;
+ LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH, LLVFile::WRITE);
+ if (file.getMaxSize() >= bytes || file.setMaxSize(bytes))
+ {
+ LLMeshRepository::sCacheBytesWritten += data_size;
- file.write((const U8*) data, data_size);
+ file.write((const U8*) data, data_size);
- //zero out the rest of the file
- U8 block[4096];
- memset(block, 0, 4096);
+ //zero out the rest of the file
+ U8 block[4096];
+ memset(block, 0, 4096);
- while (bytes-file.tell() > 4096)
- {
- file.write(block, 4096);
- }
+ while (bytes-file.tell() > 4096)
+ {
+ file.write(block, 4096);
+ }
- S32 remaining = bytes-file.tell();
+ S32 remaining = bytes-file.tell();
- if (remaining < 0 || remaining > 4096)
- {
- llerrs << "Bad padding of mesh asset cache entry." << llendl;
- }
+ if (remaining < 0 || remaining > 4096)
+ {
+ llerrs << "Bad padding of mesh asset cache entry." << llendl;
+ }
- if (remaining > 0)
- {
- file.write(block, remaining);
+ if (remaining > 0)
+ {
+ file.write(block, remaining);
+ }
}
}
}
@@ -2874,7 +2901,7 @@ void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data)
LLCurlRequest::headers_t headers;
mPendingUploads++;
- mCurlRequest->post(data.mRSVP, headers, data.mAssetData, new LLMeshUploadResponder(data, this));
+ mCurlRequest->post(data.mRSVP, headers, data.mAssetData, new LLMeshUploadResponder(data, this), mMeshUploadTimeOut);
}
}
@@ -2906,7 +2933,7 @@ void LLMeshUploadThread::doUploadTexture(LLTextureUploadData& data)
LLCurlRequest::headers_t headers;
mPendingUploads++;
- mCurlRequest->post(data.mRSVP, headers, data.mAssetData, new LLTextureUploadResponder(data, this));
+ mCurlRequest->post(data.mRSVP, headers, data.mAssetData, new LLTextureUploadResponder(data, this), mMeshUploadTimeOut);
}
}
@@ -3158,55 +3185,66 @@ void LLMeshRepository::uploadError(LLSD& args)
//static
F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod)
{
- F32 dlowest = llmin(radius/0.03f, 256.f);
- F32 dlow = llmin(radius/0.06f, 256.f);
- F32 dmid = llmin(radius/0.24f, 256.f);
-
- F32 bytes_lowest = header["lowest_lod"]["size"].asReal()/1024.f;
- F32 bytes_low = header["low_lod"]["size"].asReal()/1024.f;
- F32 bytes_mid = header["medium_lod"]["size"].asReal()/1024.f;
- F32 bytes_high = header["high_lod"]["size"].asReal()/1024.f;
+ F32 max_distance = 512.f;
- if (bytes)
- {
- *bytes = 0;
- *bytes += header["lowest_lod"]["size"].asInteger();
- *bytes += header["low_lod"]["size"].asInteger();
- *bytes += header["medium_lod"]["size"].asInteger();
- *bytes += header["high_lod"]["size"].asInteger();
- }
+ F32 dlowest = llmin(radius/0.03f, max_distance);
+ F32 dlow = llmin(radius/0.06f, max_distance);
+ F32 dmid = llmin(radius/0.24f, max_distance);
+
+ F32 METADATA_DISCOUNT = (F32) gSavedSettings.getU32("MeshMetaDataDiscount"); //discount 128 bytes to cover the cost of LLSD tags and compression domain overhead
+ F32 MINIMUM_SIZE = (F32) gSavedSettings.getU32("MeshMinimumByteSize"); //make sure nothing is "free"
+ F32 bytes_per_triangle = (F32) gSavedSettings.getU32("MeshBytesPerTriangle");
- if (bytes_visible)
- {
- lod = LLMeshRepository::getActualMeshLOD(header, lod);
- if (lod >= 0 && lod <= 3)
- {
- *bytes_visible = header[header_lod[lod]]["size"].asInteger();
- }
- }
+ S32 bytes_lowest = header["lowest_lod"]["size"].asInteger();
+ S32 bytes_low = header["low_lod"]["size"].asInteger();
+ S32 bytes_mid = header["medium_lod"]["size"].asInteger();
+ S32 bytes_high = header["high_lod"]["size"].asInteger();
- if (bytes_high == 0.f)
+ if (bytes_high == 0)
{
return 0.f;
}
- if (bytes_mid == 0.f)
+ if (bytes_mid == 0)
{
bytes_mid = bytes_high;
}
- if (bytes_low == 0.f)
+ if (bytes_low == 0)
{
bytes_low = bytes_mid;
}
- if (bytes_lowest == 0.f)
+ if (bytes_lowest == 0)
{
bytes_lowest = bytes_low;
}
- F32 max_area = 65536.f;
+ F32 triangles_lowest = llmax((F32) bytes_lowest-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle;
+ F32 triangles_low = llmax((F32) bytes_low-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle;
+ F32 triangles_mid = llmax((F32) bytes_mid-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle;
+ F32 triangles_high = llmax((F32) bytes_high-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle;
+
+ if (bytes)
+ {
+ *bytes = 0;
+ *bytes += header["lowest_lod"]["size"].asInteger();
+ *bytes += header["low_lod"]["size"].asInteger();
+ *bytes += header["medium_lod"]["size"].asInteger();
+ *bytes += header["high_lod"]["size"].asInteger();
+ }
+
+ if (bytes_visible)
+ {
+ lod = LLMeshRepository::getActualMeshLOD(header, lod);
+ if (lod >= 0 && lod <= 3)
+ {
+ *bytes_visible = header[header_lod[lod]]["size"].asInteger();
+ }
+ }
+
+ F32 max_area = 102932.f; //area of circle that encompasses region
F32 min_area = 1.f;
F32 high_area = llmin(F_PI*dmid*dmid, max_area);
@@ -3229,12 +3267,12 @@ F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32
low_area /= total_area;
lowest_area /= total_area;
- F32 weighted_avg = bytes_high*high_area +
- bytes_mid*mid_area +
- bytes_low*low_area +
- bytes_lowest*lowest_area;
+ F32 weighted_avg = triangles_high*high_area +
+ triangles_mid*mid_area +
+ triangles_low*low_area +
+ triangles_lowest*lowest_area;
- return weighted_avg * gSavedSettings.getF32("MeshStreamingCostScaler");
+ return weighted_avg/gSavedSettings.getU32("MeshTriangleBudget")*15000.f;
}