summaryrefslogtreecommitdiff
path: root/indra/newview/llmeshrepository.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llmeshrepository.cpp')
-rwxr-xr-x[-rw-r--r--]indra/newview/llmeshrepository.cpp1437
1 files changed, 552 insertions, 885 deletions
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 6e0722bcf9..f461c7e46f 100644..100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -34,9 +34,9 @@
#include "llagent.h"
#include "llappviewer.h"
#include "llbufferstream.h"
+#include "llcallbacklist.h"
#include "llcurl.h"
#include "lldatapacker.h"
-#include "llfasttimer.h"
#include "llfloatermodelpreview.h"
#include "llfloaterperms.h"
#include "lleconomy.h"
@@ -49,6 +49,7 @@
#include "llthread.h"
#include "llvfile.h"
#include "llviewercontrol.h"
+#include "llviewerinventory.h"
#include "llviewermenufile.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
@@ -62,6 +63,7 @@
#include "llinventorymodel.h"
#include "llfoldertype.h"
#include "llviewerparcelmgr.h"
+#include "lluploadfloaterobservers.h"
#include "boost/lexical_cast.hpp"
@@ -71,16 +73,24 @@
#include <queue>
-LLFastTimer::DeclareTimer FTM_MESH_UPDATE("Mesh Update");
-LLFastTimer::DeclareTimer FTM_LOAD_MESH("Load Mesh");
-
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;
+U32 LLMeshRepository::sLODProcessing = 0;
+U32 LLMeshRepository::sLODPending = 0;
+
U32 LLMeshRepository::sCacheBytesRead = 0;
U32 LLMeshRepository::sCacheBytesWritten = 0;
U32 LLMeshRepository::sPeakKbps = 0;
@@ -190,196 +200,6 @@ S32 LLMeshRepoThread::sActiveHeaderRequests = 0;
S32 LLMeshRepoThread::sActiveLODRequests = 0;
U32 LLMeshRepoThread::sMaxConcurrentRequests = 1;
-
-class LLTextureCostResponder : public LLCurl::Responder
-{
-public:
- LLTextureUploadData mData;
- LLMeshUploadThread* mThread;
-
- LLTextureCostResponder(LLTextureUploadData data, LLMeshUploadThread* thread)
- : mData(data), mThread(thread)
- {
-
- }
-
- virtual void completed(U32 status, const std::string& reason, const LLSD& content)
- {
- mThread->mPendingConfirmations--;
- if (isGoodStatus(status))
- {
- mThread->priceResult(mData, content);
- }
- else
- {
- llwarns << status << ": " << reason << llendl;
-
- if (mData.mRetries < MAX_TEXTURE_UPLOAD_RETRIES)
- {
- llwarns << "Retrying. (" << ++mData.mRetries << ")" << llendl;
-
- if (status == 499 || status == 500)
- {
- mThread->uploadTexture(mData);
- }
- else
- {
- llerrs << "Unhandled status " << status << llendl;
- }
- }
- else
- {
- llwarns << "Giving up after " << mData.mRetries << " retries." << llendl;
- }
- }
- }
-};
-
-class LLTextureUploadResponder : public LLCurl::Responder
-{
-public:
- LLTextureUploadData mData;
- LLMeshUploadThread* mThread;
-
- LLTextureUploadResponder(LLTextureUploadData data, LLMeshUploadThread* thread)
- : mData(data), mThread(thread)
- {
- }
-
- virtual void completed(U32 status, const std::string& reason, const LLSD& content)
- {
- mThread->mPendingUploads--;
- if (isGoodStatus(status))
- {
- mData.mUUID = content["new_asset"].asUUID();
- gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mData.mPostData, content));
- mThread->onTextureUploaded(mData);
- }
- else
- {
- llwarns << status << ": " << reason << llendl;
- llwarns << "Retrying. (" << ++mData.mRetries << ")" << llendl;
-
- if (status == 404)
- {
- mThread->uploadTexture(mData);
- }
- else if (status == 499)
- {
- mThread->mConfirmedTextureQ.push(mData);
- }
- else
- {
- llerrs << "Unhandled status " << status << llendl;
- }
- }
- }
-};
-
-class LLMeshCostResponder : public LLCurl::Responder
-{
-public:
- LLMeshUploadData mData;
- LLMeshUploadThread* mThread;
-
- LLMeshCostResponder(LLMeshUploadData data, LLMeshUploadThread* thread)
- : mData(data), mThread(thread)
- {
-
- }
-
- virtual void completed(U32 status, const std::string& reason, const LLSD& content)
- {
- mThread->mPendingConfirmations--;
-
- if (isGoodStatus(status))
- {
- mThread->priceResult(mData, content);
- }
- else
- {
- llwarns << status << ": " << reason << llendl;
-
- if (status == HTTP_INTERNAL_ERROR)
- {
- llwarns << "Retrying. (" << ++mData.mRetries << ")" << llendl;
- mThread->uploadModel(mData);
- }
- else if (status == HTTP_BAD_REQUEST)
- {
- llwarns << "Status 400 received from server, giving up." << llendl;
- }
- else if (status == HTTP_NOT_FOUND)
- {
- llwarns <<"Status 404 received, server is disconnected, giving up." << llendl ;
- }
- else
- {
- llerrs << "Unhandled status " << status << llendl;
- }
- }
- }
-};
-
-class LLMeshUploadResponder : public LLCurl::Responder
-{
-public:
- LLMeshUploadData mData;
- LLMeshUploadThread* mThread;
-
- LLMeshUploadResponder(LLMeshUploadData data, LLMeshUploadThread* thread)
- : mData(data), mThread(thread)
- {
- }
-
- virtual void completed(U32 status, const std::string& reason, const LLSD& content)
- {
- mThread->mPendingUploads--;
- if (isGoodStatus(status))
- {
- mData.mUUID = content["new_asset"].asUUID();
- if (mData.mUUID.isNull())
- {
- LLSD args;
- std::string message = content["error"]["message"];
- std::string identifier = content["error"]["identifier"];
- std::string invalidity_identifier = content["error"]["invalidity_identifier"];
-
- args["MESSAGE"] = message;
- args["IDENTIFIER"] = identifier;
- args["INVALIDITY_IDENTIFIER"] = invalidity_identifier;
- args["LABEL"] = mData.mBaseModel->mLabel;
-
- gMeshRepo.uploadError(args);
- }
- else
- {
- gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mData.mPostData, content));
- mThread->onModelUploaded(mData);
- }
- }
- else
- {
- llwarns << status << ": " << reason << llendl;
- llwarns << "Retrying. (" << ++mData.mRetries << ")" << llendl;
-
- if (status == 404)
- {
- mThread->uploadModel(mData);
- }
- else if (status == 499)
- {
- mThread->mConfirmedQ.push(mData);
- }
- else if (status != 500)
- { //drop internal server errors on the floor, otherwise grab
- llerrs << "Unhandled status " << status << llendl;
- }
- }
- }
-};
-
-
class LLMeshHeaderResponder : public LLCurl::Responder
{
public:
@@ -388,6 +208,12 @@ public:
LLMeshHeaderResponder(const LLVolumeParams& mesh_params)
: mMeshParams(mesh_params)
{
+ LLMeshRepoThread::sActiveHeaderRequests++;
+ }
+
+ ~LLMeshHeaderResponder()
+ {
+ LLMeshRepoThread::sActiveHeaderRequests--;
}
virtual void completedRaw(U32 status, const std::string& reason,
@@ -407,6 +233,12 @@ public:
LLMeshLODResponder(const LLVolumeParams& mesh_params, S32 lod, U32 offset, U32 requested_bytes)
: mMeshParams(mesh_params), mLOD(lod), mOffset(offset), mRequestedBytes(requested_bytes)
{
+ LLMeshRepoThread::sActiveLODRequests++;
+ }
+
+ ~LLMeshLODResponder()
+ {
+ LLMeshRepoThread::sActiveLODRequests--;
}
virtual void completedRaw(U32 status, const std::string& reason,
@@ -518,38 +350,16 @@ void log_upload_error(S32 status, const LLSD& content, std::string stage, std::s
}
}
-class LLModelObjectUploadResponder: public LLCurl::Responder
-{
- LLSD mObjectAsset;
- LLMeshUploadThread* mThread;
-
-public:
- LLModelObjectUploadResponder(LLMeshUploadThread* thread, const LLSD& object_asset):
- mThread(thread),
- mObjectAsset(object_asset)
- {
- }
-
- virtual void completedRaw(U32 status, const std::string& reason,
- const LLChannelDescriptors& channels,
- const LLIOPipe::buffer_ptr_t& buffer)
- {
- assert_main_thread();
-
- llinfos << "completed" << llendl;
- mThread->mPendingUploads--;
- mThread->mFinished = true;
- }
-};
-
class LLWholeModelFeeResponder: public LLCurl::Responder
{
LLMeshUploadThread* mThread;
LLSD mModelData;
+ LLHandle<LLWholeModelFeeObserver> mObserverHandle;
public:
- LLWholeModelFeeResponder(LLMeshUploadThread* thread, LLSD& model_data):
+ LLWholeModelFeeResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelFeeObserver> observer_handle):
mThread(thread),
- mModelData(model_data)
+ mModelData(model_data),
+ mObserverHandle(observer_handle)
{
}
virtual void completed(U32 status,
@@ -562,20 +372,32 @@ public:
cc = llsd_from_file("fake_upload_error.xml");
}
- llinfos << "completed" << llendl;
mThread->mPendingUploads--;
dump_llsd_to_file(cc,make_dump_name("whole_model_fee_response_",dump_num));
+
+ LLWholeModelFeeObserver* observer = mObserverHandle.get();
+
if (isGoodStatus(status) &&
cc["state"].asString() == "upload")
{
- llinfos << "fee request succeeded" << llendl;
- mThread->mWholeModelUploadURL = cc["uploader"].asString();
+ mThread->mWholeModelUploadURL = cc["uploader"].asString();
+
+ if (observer)
+ {
+ cc["data"]["upload_price"] = cc["upload_price"];
+ observer->onModelPhysicsFeeReceived(cc["data"], mThread->mWholeModelUploadURL);
+ }
}
else
{
llwarns << "fee request failed" << llendl;
log_upload_error(status,cc,"fee",mModelData["name"]);
mThread->mWholeModelUploadURL = "";
+
+ if (observer)
+ {
+ observer->setModelPhysicsFeeErrorStatus(status, reason);
+ }
}
}
@@ -585,11 +407,13 @@ class LLWholeModelUploadResponder: public LLCurl::Responder
{
LLMeshUploadThread* mThread;
LLSD mModelData;
+ LLHandle<LLWholeModelUploadObserver> mObserverHandle;
public:
- LLWholeModelUploadResponder(LLMeshUploadThread* thread, LLSD& model_data):
+ LLWholeModelUploadResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelUploadObserver> observer_handle):
mThread(thread),
- mModelData(model_data)
+ mModelData(model_data),
+ mObserverHandle(observer_handle)
{
}
virtual void completed(U32 status,
@@ -602,30 +426,40 @@ public:
cc = llsd_from_file("fake_upload_error.xml");
}
- //assert_main_thread();
mThread->mPendingUploads--;
dump_llsd_to_file(cc,make_dump_name("whole_model_upload_response_",dump_num));
- llinfos << "LLWholeModelUploadResponder content: " << cc << llendl;
+
+ LLWholeModelUploadObserver* observer = mObserverHandle.get();
+
// requested "mesh" asset type isn't actually the type
// of the resultant object, fix it up here.
if (isGoodStatus(status) &&
cc["state"].asString() == "complete")
{
- llinfos << "upload succeeded" << llendl;
mModelData["asset_type"] = "object";
gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mModelData,cc));
+
+ if (observer)
+ {
+ doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadSuccess, observer));
+ }
}
else
{
llwarns << "upload failed" << llendl;
std::string model_name = mModelData["name"].asString();
log_upload_error(status,cc,"upload",model_name);
+
+ if (observer)
+ {
+ doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadFailure, observer));
+ }
}
}
};
LLMeshRepoThread::LLMeshRepoThread()
-: LLThread("mesh repo", NULL)
+: LLThread("mesh repo")
{
mWaiting = false;
mMutex = new LLMutex(NULL);
@@ -674,28 +508,35 @@ void LLMeshRepoThread::run()
while (!mLODReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveLODRequests < sMaxConcurrentRequests)
{
+ if (mMutex)
{
mMutex->lock();
LODRequest req = mLODReqQ.front();
mLODReqQ.pop();
+ LLMeshRepository::sLODProcessing--;
mMutex->unlock();
- if (fetchMeshLOD(req.mMeshParams, req.mLOD))
+ if (!fetchMeshLOD(req.mMeshParams, req.mLOD, count))//failed, resubmit
{
- count++;
+ mMutex->lock();
+ mLODReqQ.push(req) ;
+ mMutex->unlock();
}
}
}
while (!mHeaderReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveHeaderRequests < sMaxConcurrentRequests)
{
+ if (mMutex)
{
mMutex->lock();
HeaderRequest req = mHeaderReqQ.front();
mHeaderReqQ.pop();
mMutex->unlock();
- if (fetchMeshHeader(req.mMeshParams))
+ if (!fetchMeshHeader(req.mMeshParams, count))//failed, resubmit
{
- count++;
+ mMutex->lock();
+ mHeaderReqQ.push(req) ;
+ mMutex->unlock();
}
}
}
@@ -784,6 +625,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
{
LLMutexLock lock(mMutex);
mLODReqQ.push(req);
+ LLMeshRepository::sLODProcessing++;
}
}
else
@@ -831,6 +673,12 @@ std::string LLMeshRepoThread::constructUrl(LLUUID mesh_id)
bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
{ //protected by mMutex
+
+ if (!mHeaderMutex)
+ {
+ return false;
+ }
+
mHeaderMutex->lock();
if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
@@ -839,27 +687,29 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
return false;
}
+ bool ret = true ;
U32 header_size = mMeshHeaderSize[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);
if (file.getSize() >= offset+size)
- {
+ {
LLMeshRepository::sCacheBytesRead += size;
file.seek(offset);
U8* buffer = new U8[size];
file.read(buffer, size);
- //make sure buffer isn't all 0's (reserved block but not written)
+ //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
bool zero = true;
for (S32 i = 0; i < llmin(size, 1024) && zero; ++i)
{
@@ -869,7 +719,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
if (!zero)
{ //attempt to parse
if (skinInfoReceived(mesh_id, buffer, size))
- {
+ {
delete[] buffer;
return true;
}
@@ -884,11 +734,13 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
std::string http_url = constructUrl(mesh_id);
if (!http_url.empty())
- {
- ++sActiveLODRequests;
- LLMeshRepository::sHTTPRequestCount++;
- mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
- new LLMeshSkinInfoResponder(mesh_id, offset, size));
+ {
+ ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
+ new LLMeshSkinInfoResponder(mesh_id, offset, size));
+ if(ret)
+ {
+ LLMeshRepository::sHTTPRequestCount++;
+ }
}
}
}
@@ -898,11 +750,16 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
}
//early out was not hit, effectively fetched
- return true;
+ return ret;
}
bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
{ //protected by mMutex
+ if (!mHeaderMutex)
+ {
+ return false;
+ }
+
mHeaderMutex->lock();
if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
@@ -912,26 +769,29 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
}
U32 header_size = mMeshHeaderSize[mesh_id];
-
+ bool ret = true ;
+
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);
if (file.getSize() >= offset+size)
{
LLMeshRepository::sCacheBytesRead += size;
+
file.seek(offset);
U8* buffer = new U8[size];
file.read(buffer, size);
- //make sure buffer isn't all 0's (reserved block but not written)
+ //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
bool zero = true;
for (S32 i = 0; i < llmin(size, 1024) && zero; ++i)
{
@@ -956,11 +816,13 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
std::string http_url = constructUrl(mesh_id);
if (!http_url.empty())
- {
- ++sActiveLODRequests;
- LLMeshRepository::sHTTPRequestCount++;
- mCurlRequest->getByteRange(http_url, headers, offset, size,
- new LLMeshDecompositionResponder(mesh_id, offset, size));
+ {
+ ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
+ new LLMeshDecompositionResponder(mesh_id, offset, size));
+ if(ret)
+ {
+ LLMeshRepository::sHTTPRequestCount++;
+ }
}
}
}
@@ -970,11 +832,16 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
}
//early out was not hit, effectively fetched
- return true;
+ return ret;
}
bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
{ //protected by mMutex
+ if (!mHeaderMutex)
+ {
+ return false;
+ }
+
mHeaderMutex->lock();
if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
@@ -984,15 +851,17 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
}
U32 header_size = mMeshHeaderSize[mesh_id];
+ bool ret = true ;
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);
@@ -1003,7 +872,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
U8* buffer = new U8[size];
file.read(buffer, size);
- //make sure buffer isn't all 0's (reserved block but not written)
+ //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
bool zero = true;
for (S32 i = 0; i < llmin(size, 1024) && zero; ++i)
{
@@ -1028,11 +897,14 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
std::string http_url = constructUrl(mesh_id);
if (!http_url.empty())
- {
- ++sActiveLODRequests;
- LLMeshRepository::sHTTPRequestCount++;
- mCurlRequest->getByteRange(http_url, headers, offset, size,
- new LLMeshPhysicsShapeResponder(mesh_id, offset, size));
+ {
+ ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
+ new LLMeshPhysicsShapeResponder(mesh_id, offset, size));
+
+ if(ret)
+ {
+ LLMeshRepository::sHTTPRequestCount++;
+ }
}
}
else
@@ -1046,13 +918,12 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
}
//early out was not hit, effectively fetched
- return true;
+ return ret;
}
-bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
+//return false if failed to get header
+bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count)
{
- bool retval = false;
-
{
//look for mesh in asset in vfs
LLVFile file(gVFS, mesh_params.getSculptID(), LLAssetType::AT_MESH);
@@ -1060,42 +931,51 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)
S32 size = file.getSize();
if (size > 0)
- {
- U8 buffer[1024];
- S32 bytes = llmin(size, 1024);
+ { //NOTE -- if the header size is ever more than 4KB, this will break
+ U8 buffer[4096];
+ S32 bytes = llmin(size, 4096);
LLMeshRepository::sCacheBytesRead += bytes;
file.read(buffer, bytes);
if (headerReceived(mesh_params, buffer, bytes))
{ //did not do an HTTP request, return false
- return false;
+ return true;
}
}
}
- //either cache entry doesn't exist or is corrupt, request header from simulator
-
+ //either cache entry doesn't exist or is corrupt, request header from simulator
+ bool retval = true ;
std::vector<std::string> headers;
headers.push_back("Accept: application/octet-stream");
std::string http_url = constructUrl(mesh_params.getSculptID());
if (!http_url.empty())
{
- ++sActiveHeaderRequests;
- retval = true;
//grab first 4KB if we're going to bother with a fetch. Cache will prevent future fetches if a full mesh fits
//within the first 4KB
- LLMeshRepository::sHTTPRequestCount++;
- mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params));
+ //NOTE -- this will break of headers ever exceed 4KB
+ retval = mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params));
+ if(retval)
+ {
+ LLMeshRepository::sHTTPRequestCount++;
+ }
+ count++;
}
return retval;
}
-bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
+//return false if failed to get mesh lod.
+bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count)
{ //protected by mMutex
+ if (!mHeaderMutex)
+ {
+ return false;
+ }
+
mHeaderMutex->lock();
- bool retval = false;
+ bool retval = true;
LLUUID mesh_id = mesh_params.getSculptID();
@@ -1103,10 +983,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
@@ -1118,7 +1000,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
U8* buffer = new U8[size];
file.read(buffer, size);
- //make sure buffer isn't all 0's (reserved block but not written)
+ //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
bool zero = true;
for (S32 i = 0; i < llmin(size, 1024) && zero; ++i)
{
@@ -1130,7 +1012,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
if (lodReceived(mesh_params, lod, buffer, size))
{
delete[] buffer;
- return false;
+ return true;
}
}
@@ -1143,12 +1025,15 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
std::string http_url = constructUrl(mesh_id);
if (!http_url.empty())
- {
- ++sActiveLODRequests;
- retval = true;
- LLMeshRepository::sHTTPRequestCount++;
- mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
+ {
+ retval = mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
new LLMeshLODResponder(mesh_params, lod, offset, size));
+
+ if(retval)
+ {
+ LLMeshRepository::sHTTPRequestCount++;
+ }
+ count++;
}
else
{
@@ -1204,15 +1089,13 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
}
{
- U32 cost = gMeshRepo.calcResourceCost(header);
-
LLUUID mesh_id = mesh_params.getSculptID();
- mHeaderMutex->lock();
- mMeshHeaderSize[mesh_id] = header_size;
- mMeshHeader[mesh_id] = header;
- mMeshResourceCost[mesh_id] = cost;
- mHeaderMutex->unlock();
+ {
+ LLMutexLock lock(mHeaderMutex);
+ mMeshHeaderSize[mesh_id] = header_size;
+ mMeshHeader[mesh_id] = header;
+ }
//check for pending requests
pending_lod_map::iterator iter = mPendingLOD.find(mesh_params);
@@ -1223,6 +1106,7 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
{
LODRequest req(mesh_params, iter->second[i]);
mLODReqQ.push(req);
+ LLMeshRepository::sLODProcessing++;
}
}
mPendingLOD.erase(iter);
@@ -1233,17 +1117,19 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat
bool LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size)
{
- LLVolume* volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod));
+ LLPointer<LLVolume> volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod));
std::string mesh_string((char*) data, data_size);
std::istringstream stream(mesh_string);
if (volume->unpackVolumeFaces(stream, data_size))
{
- LoadedMesh mesh(volume, mesh_params, lod);
if (volume->getNumFaces() > 0)
{
- LLMutexLock lock(mMutex);
- mLoadedQ.push(mesh);
+ LoadedMesh mesh(volume, mesh_params, lod);
+ {
+ LLMutexLock lock(mMutex);
+ mLoadedQ.push(mesh);
+ }
return true;
}
}
@@ -1363,9 +1249,14 @@ bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32
}
LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures,
- bool upload_skin, bool upload_joints)
+ bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload,
+ LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer)
: LLThread("mesh upload"),
- mDiscarded(FALSE)
+ mDiscarded(FALSE),
+ mDoUpload(do_upload),
+ mWholeModelUploadURL(upload_url),
+ mFeeObserverHandle(fee_observer),
+ mUploadObserverHandle(upload_observer)
{
mInstanceList = data;
mUploadTextures = upload_textures;
@@ -1373,9 +1264,7 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
mUploadJoints = upload_joints;
mMutex = new LLMutex(NULL);
mCurlRequest = NULL;
- mPendingConfirmations = 0;
mPendingUploads = 0;
- mPendingCost = 0;
mFinished = false;
mOrigin = gAgent.getPositionAgent();
mHost = gAgent.getRegionHost();
@@ -1383,6 +1272,8 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
mWholeModelFeeCapability = gAgent.getRegion()->getCapability("NewFileAgentInventory");
mOrigin += gAgent.getAtAxis() * scale.magVec();
+
+ mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut") ;
}
LLMeshUploadThread::~LLMeshUploadThread()
@@ -1441,7 +1332,14 @@ BOOL LLMeshUploadThread::isDiscarded()
void LLMeshUploadThread::run()
{
- doWholeModelUpload();
+ if (mDoUpload)
+ {
+ doWholeModelUpload();
+ }
+ else
+ {
+ requestWholeModelFee();
+ }
}
void dump_llsd_to_file(const LLSD& content, std::string filename)
@@ -1467,10 +1365,13 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
LLSD res;
result["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
+ result["texture_folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE);
result["asset_type"] = "mesh";
result["inventory_type"] = "object";
- result["name"] = "mesh model";
- result["description"] = "your description here";
+ result["description"] = "(No Description)";
+ result["next_owner_mask"] = LLSD::Integer(LLFloaterPerms::getNextOwnerPerms());
+ result["group_mask"] = LLSD::Integer(LLFloaterPerms::getGroupPerms());
+ result["everyone_mask"] = LLSD::Integer(LLFloaterPerms::getEveryonePerms());
res["mesh_list"] = LLSD::emptyArray();
res["texture_list"] = LLSD::emptyArray();
@@ -1482,6 +1383,8 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
std::map<LLViewerTexture*,S32> texture_index;
std::map<LLModel*,S32> mesh_index;
+ std::string model_name;
+ std::string model_metric;
S32 instance_num = 0;
@@ -1498,10 +1401,14 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
if (mesh_index.find(data.mBaseModel) == mesh_index.end())
{
// Have not seen this model before - create a new mesh_list entry for it.
- std::string model_name = data.mBaseModel->getName();
- if (!model_name.empty())
+ if (model_name.empty())
{
- result["name"] = model_name;
+ model_name = data.mBaseModel->getName();
+ }
+
+ if (model_metric.empty())
+ {
+ model_metric = data.mBaseModel->getMetric();
}
std::stringstream ostr;
@@ -1556,24 +1463,15 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
instance_entry["scale"] = ll_sd_from_vector3(scale);
instance_entry["material"] = LL_MCODE_WOOD;
- LLPermissions perm;
- perm.setOwnerAndGroup(gAgent.getID(), gAgent.getID(), LLUUID::null, false);
- perm.setCreator(gAgent.getID());
-
- perm.initMasks(PERM_ITEM_UNRESTRICTED | PERM_MOVE, //base
- PERM_ITEM_UNRESTRICTED | PERM_MOVE, //owner
- LLFloaterPerms::getEveryonePerms(),
- LLFloaterPerms::getGroupPerms(),
- LLFloaterPerms::getNextOwnerPerms());
- instance_entry["permissions"] = ll_create_sd_from_permissions(perm);
instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
instance_entry["mesh"] = mesh_index[data.mBaseModel];
instance_entry["face_list"] = LLSD::emptyArray();
- for (S32 face_num = 0; face_num < data.mBaseModel->getNumVolumeFaces(); face_num++)
+ S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ;
+ for (S32 face_num = 0; face_num < end; face_num++)
{
- LLImportMaterial& material = instance.mMaterial[face_num];
+ LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
LLSD face_entry = LLSD::emptyMap();
LLViewerFetchedTexture *texture = material.mDiffuseMap.get();
@@ -1624,19 +1522,20 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
}
}
+ if (model_name.empty()) model_name = "mesh model";
+ result["name"] = model_name;
+ if (model_metric.empty()) model_metric = "MUT_Unspecified";
+ res["metric"] = model_metric;
result["asset_resources"] = res;
dump_llsd_to_file(result,make_dump_name("whole_model_",dump_num));
dest = result;
}
-void LLMeshUploadThread::doWholeModelUpload()
+void LLMeshUploadThread::generateHulls()
{
- dump_num++;
-
- mCurlRequest = new LLCurlRequest();
+ bool has_valid_requests = false ;
- // Queue up models for hull generation (viewer-side)
for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
{
LLMeshUploadData data;
@@ -1656,6 +1555,10 @@ void LLMeshUploadThread::doWholeModelUpload()
{
physics = data.mModel[LLModel::LOD_PHYSICS];
}
+ else if (data.mModel[LLModel::LOD_LOW].notNull())
+ {
+ physics = data.mModel[LLModel::LOD_LOW];
+ }
else if (data.mModel[LLModel::LOD_MEDIUM].notNull())
{
physics = data.mModel[LLModel::LOD_MEDIUM];
@@ -1666,33 +1569,27 @@ void LLMeshUploadThread::doWholeModelUpload()
}
llassert(physics != NULL);
-
+
DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this);
if(request->isValid())
{
gMeshRepo.mDecompThread->submitRequest(request);
- }
- }
-
- while (!mPhysicsComplete)
- {
- apr_sleep(100);
+ has_valid_requests = true ;
+ }
}
-
- LLSD model_data;
- wholeModelToLLSD(model_data,false);
- dump_llsd_to_file(model_data,make_dump_name("whole_model_fee_request_",dump_num));
-
- mPendingUploads++;
- LLCurlRequest::headers_t headers;
- mCurlRequest->post(mWholeModelFeeCapability, headers, model_data,
- new LLWholeModelFeeResponder(this,model_data));
-
- do
+
+ if(has_valid_requests)
{
- mCurlRequest->process();
- } while (mCurlRequest->getQueued() > 0);
+ while (!mPhysicsComplete)
+ {
+ apr_sleep(100);
+ }
+ }
+}
+void LLMeshUploadThread::doWholeModelUpload()
+{
+ mCurlRequest = new LLCurlRequest();
if (mWholeModelUploadURL.empty())
{
@@ -1700,15 +1597,29 @@ void LLMeshUploadThread::doWholeModelUpload()
}
else
{
+ generateHulls();
+
LLSD full_model_data;
wholeModelToLLSD(full_model_data, true);
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));
+ LLCurlRequest::headers_t headers;
+
+ {
+ LLCurl::ResponderPtr responder = new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle) ;
+
+ while(!mCurlRequest->post(mWholeModelUploadURL, headers, body, responder, mMeshUploadTimeOut))
+ {
+ //sleep for 10ms to prevent eating a whole core
+ apr_sleep(10000);
+ }
+ }
+
do
{
mCurlRequest->process();
+ //sleep for 10ms to prevent eating a whole core
+ apr_sleep(10000);
} while (mCurlRequest->getQueued() > 0);
}
@@ -1719,25 +1630,51 @@ void LLMeshUploadThread::doWholeModelUpload()
mFinished = true;
}
-void LLMeshUploadThread::uploadModel(LLMeshUploadData& data)
-{ //called from arbitrary thread
+void LLMeshUploadThread::requestWholeModelFee()
+{
+ dump_num++;
+
+ mCurlRequest = new LLCurlRequest();
+
+ generateHulls();
+
+ LLSD model_data;
+ wholeModelToLLSD(model_data,false);
+ dump_llsd_to_file(model_data,make_dump_name("whole_model_fee_request_",dump_num));
+
+ mPendingUploads++;
+ LLCurlRequest::headers_t headers;
+
{
- LLMutexLock lock(mMutex);
- mUploadQ.push(data);
+ LLCurl::ResponderPtr responder = new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle) ;
+ while(!mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, responder, mMeshUploadTimeOut))
+ {
+ //sleep for 10ms to prevent eating a whole core
+ apr_sleep(10000);
+ }
}
-}
-void LLMeshUploadThread::uploadTexture(LLTextureUploadData& data)
-{ //called from mesh upload thread
- mTextureQ.push(data);
-}
+ do
+ {
+ mCurlRequest->process();
+ //sleep for 10ms to prevent eating a whole core
+ apr_sleep(10000);
+ } while (mCurlRequest->getQueued() > 0);
+ delete mCurlRequest;
+ mCurlRequest = NULL;
-static LLFastTimer::DeclareTimer FTM_NOTIFY_MESH_LOADED("Notify Loaded");
-static LLFastTimer::DeclareTimer FTM_NOTIFY_MESH_UNAVAILABLE("Notify Unavailable");
+ // Currently a no-op.
+ mFinished = true;
+}
void LLMeshRepoThread::notifyLoadedMeshes()
{
+ if (!mMutex)
+ {
+ return;
+ }
+
while (!mLoadedQ.empty())
{
mMutex->lock();
@@ -1799,7 +1736,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;
}
@@ -1832,19 +1771,6 @@ S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod)
return -1;
}
-U32 LLMeshRepoThread::getResourceCost(const LLUUID& mesh_id)
-{
- LLMutexLock lock(mHeaderMutex);
-
- std::map<LLUUID, U32>::iterator iter = mMeshResourceCost.find(mesh_id);
- if (iter != mMeshResourceCost.end())
- {
- return iter->second;
- }
-
- return 0;
-}
-
void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header)
{
mThread->mMeshHeader[data.mUUID] = header;
@@ -1860,6 +1786,7 @@ void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header)
{
LLPointer<LLVolume> volume = new LLVolume(volume_params, LLVolumeLODGroup::getVolumeScaleFromDetail(i));
volume->copyVolumeFaces(data.mModel[i]);
+ volume->setMeshAssetLoaded(TRUE);
}
}
@@ -1870,7 +1797,6 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,
const LLIOPipe::buffer_ptr_t& buffer)
{
- LLMeshRepoThread::sActiveLODRequests--;
S32 data_size = buffer->countAfter(channels.in(), NULL);
if (status < 200 || status > 400)
@@ -2087,7 +2013,6 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer)
{
- LLMeshRepoThread::sActiveHeaderRequests--;
if (status < 200 || status > 400)
{
//llwarns
@@ -2135,54 +2060,54 @@ 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();
- S32 lod_bytes = 0;
+ if (version <= MAX_MESH_VERSION)
+ {
+ std::stringstream str;
- 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());
- }
+ 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());
+ }
- //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);
-
- while (bytes-file.tell() > 4096)
- {
- file.write(block, 4096);
- }
+ //zero out the rest of the file
+ U8 block[4096];
+ memset(block, 0, 4096);
- S32 remaining = bytes-file.tell();
+ while (bytes-file.tell() > 4096)
+ {
+ file.write(block, 4096);
+ }
- if (remaining < 0 || remaining > 4096)
- {
- llerrs << "Bad padding of mesh asset cache entry." << llendl;
- }
+ S32 remaining = bytes-file.tell();
- if (remaining > 0)
- {
- file.write(block, remaining);
+ if (remaining > 0)
+ {
+ file.write(block, remaining);
+ }
}
}
}
@@ -2292,8 +2217,6 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
return detail;
}
- LLFastTimer t(FTM_LOAD_MESH);
-
{
LLMutexLock lock(mMeshMutex);
//add volume to list of loading meshes
@@ -2307,6 +2230,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
//first request for this mesh
mLoadingMeshes[detail][mesh_params].insert(vobj->getID());
mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail));
+ LLMeshRepository::sLODPending++;
}
}
@@ -2315,11 +2239,6 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
if (volume)
{
- if (volume->getNumVolumeFaces() == 0 && !volume->isTetrahedron())
- {
- volume->makeTetrahedron();
- }
-
LLVolumeParams params = volume->getParams();
LLVolumeLODGroup* group = LLPrimitive::getVolumeManager()->getGroup(params);
@@ -2330,7 +2249,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
if (last_lod >= 0)
{
LLVolume* lod = group->refLOD(last_lod);
- if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0)
+ if (lod && lod->isMeshAssetLoaded() && lod->getNumVolumeFaces() > 0)
{
group->derefLOD(lod);
return last_lod;
@@ -2342,7 +2261,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
for (S32 i = detail-1; i >= 0; --i)
{
LLVolume* lod = group->refLOD(i);
- if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0)
+ if (lod && lod->isMeshAssetLoaded() && lod->getNumVolumeFaces() > 0)
{
group->derefLOD(lod);
return i;
@@ -2355,7 +2274,7 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
for (S32 i = detail+1; i < 4; ++i)
{
LLVolume* lod = group->refLOD(i);
- if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0)
+ if (lod && lod->isMeshAssetLoaded() && lod->getNumVolumeFaces() > 0)
{
group->derefLOD(lod);
return i;
@@ -2369,11 +2288,6 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para
return detail;
}
-static LLFastTimer::DeclareTimer FTM_START_MESH_THREAD("Start Thread");
-static LLFastTimer::DeclareTimer FTM_LOAD_MESH_LOD("Load LOD");
-static LLFastTimer::DeclareTimer FTM_MESH_LOCK1("Lock 1");
-static LLFastTimer::DeclareTimer FTM_MESH_LOCK2("Lock 2");
-
void LLMeshRepository::notifyLoadedMeshes()
{ //called from main thread
@@ -2406,6 +2320,38 @@ void LLMeshRepository::notifyLoadedMeshes()
LLAssetType::EType asset_type = LLAssetType::lookup(data.mPostData["asset_type"].asString());
LLInventoryType::EType inventory_type = LLInventoryType::lookup(data.mPostData["inventory_type"].asString());
+ // Handle addition of texture, if any.
+ if ( data.mResponse.has("new_texture_folder_id") )
+ {
+ const LLUUID& folder_id = data.mResponse["new_texture_folder_id"].asUUID();
+
+ if ( folder_id.notNull() )
+ {
+ LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE);
+
+ std::string name;
+ // Check if the server built a different name for the texture folder
+ if ( data.mResponse.has("new_texture_folder_name") )
+ {
+ name = data.mResponse["new_texture_folder_name"].asString();
+ }
+ else
+ {
+ name = data.mPostData["name"].asString();
+ }
+
+ // Add the category to the internal representation
+ LLPointer<LLViewerInventoryCategory> cat =
+ new LLViewerInventoryCategory(folder_id, parent_id,
+ LLFolderType::FT_NONE, name, gAgent.getID());
+ cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN);
+
+ LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);
+ gInventory.accountForUpdate(update);
+ gInventory.updateCategory(cat);
+ }
+ }
+
on_new_single_inventory_upload_complete(
asset_type,
inventory_type,
@@ -2414,7 +2360,8 @@ void LLMeshRepository::notifyLoadedMeshes()
data.mPostData["name"],
data.mPostData["description"],
data.mResponse,
- 0);
+ data.mResponse["upload_price"]);
+ //}
mInventoryQ.pop();
}
@@ -2439,102 +2386,92 @@ void LLMeshRepository::notifyLoadedMeshes()
}
}
- LLFastTimer t(FTM_MESH_UPDATE);
-
{
- LLFastTimer t(FTM_MESH_LOCK1);
- mMeshMutex->lock();
- }
-
- {
- LLFastTimer t(FTM_MESH_LOCK2);
- mThread->mMutex->lock();
- }
-
- //popup queued error messages from background threads
- while (!mUploadErrorQ.empty())
- {
- LLNotificationsUtil::add("MeshUploadError", mUploadErrorQ.front());
- mUploadErrorQ.pop();
- }
+ LLMutexLock lock1(mMeshMutex);
+ LLMutexLock lock2(mThread->mMutex);
+
+ //popup queued error messages from background threads
+ while (!mUploadErrorQ.empty())
+ {
+ LLNotificationsUtil::add("MeshUploadError", mUploadErrorQ.front());
+ mUploadErrorQ.pop();
+ }
- S32 push_count = LLMeshRepoThread::sMaxConcurrentRequests-(LLMeshRepoThread::sActiveHeaderRequests+LLMeshRepoThread::sActiveLODRequests);
+ S32 push_count = LLMeshRepoThread::sMaxConcurrentRequests-(LLMeshRepoThread::sActiveHeaderRequests+LLMeshRepoThread::sActiveLODRequests);
- if (push_count > 0)
- {
- //calculate "score" for pending requests
+ if (push_count > 0)
+ {
+ //calculate "score" for pending requests
- //create score map
- std::map<LLUUID, F32> score_map;
+ //create score map
+ std::map<LLUUID, F32> score_map;
- for (U32 i = 0; i < 4; ++i)
- {
- for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter)
+ for (U32 i = 0; i < 4; ++i)
{
- F32 max_score = 0.f;
- for (std::set<LLUUID>::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)
+ for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter)
{
- LLViewerObject* object = gObjectList.findObject(*obj_iter);
-
- if (object)
+ F32 max_score = 0.f;
+ for (std::set<LLUUID>::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter)
{
- LLDrawable* drawable = object->mDrawable;
- if (drawable)
+ LLViewerObject* object = gObjectList.findObject(*obj_iter);
+
+ if (object)
{
- F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f);
- max_score = llmax(max_score, cur_score);
+ LLDrawable* drawable = object->mDrawable;
+ if (drawable)
+ {
+ F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f);
+ max_score = llmax(max_score, cur_score);
+ }
}
}
- }
- score_map[iter->first.getSculptID()] = max_score;
+ score_map[iter->first.getSculptID()] = max_score;
+ }
+ }
+
+ //set "score" for pending requests
+ for (std::vector<LLMeshRepoThread::LODRequest>::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter)
+ {
+ iter->mScore = score_map[iter->mMeshParams.getSculptID()];
+ }
+
+ //sort by "score"
+ std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater());
+
+ while (!mPendingRequests.empty() && push_count > 0)
+ {
+ LLMeshRepoThread::LODRequest& request = mPendingRequests.front();
+ mThread->loadMeshLOD(request.mMeshParams, request.mLOD);
+ mPendingRequests.erase(mPendingRequests.begin());
+ LLMeshRepository::sLODPending--;
+ push_count--;
}
}
- //set "score" for pending requests
- for (std::vector<LLMeshRepoThread::LODRequest>::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter)
+ //send skin info requests
+ while (!mPendingSkinRequests.empty())
{
- iter->mScore = score_map[iter->mMeshParams.getSculptID()];
+ mThread->loadMeshSkinInfo(mPendingSkinRequests.front());
+ mPendingSkinRequests.pop();
}
-
- //sort by "score"
- std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater());
-
- while (!mPendingRequests.empty() && push_count > 0)
+
+ //send decomposition requests
+ while (!mPendingDecompositionRequests.empty())
{
- LLFastTimer t(FTM_LOAD_MESH_LOD);
- LLMeshRepoThread::LODRequest& request = mPendingRequests.front();
- mThread->loadMeshLOD(request.mMeshParams, request.mLOD);
- mPendingRequests.erase(mPendingRequests.begin());
- push_count--;
+ mThread->loadMeshDecomposition(mPendingDecompositionRequests.front());
+ mPendingDecompositionRequests.pop();
}
- }
-
- //send skin info requests
- while (!mPendingSkinRequests.empty())
- {
- mThread->loadMeshSkinInfo(mPendingSkinRequests.front());
- mPendingSkinRequests.pop();
- }
- //send decomposition requests
- while (!mPendingDecompositionRequests.empty())
- {
- mThread->loadMeshDecomposition(mPendingDecompositionRequests.front());
- mPendingDecompositionRequests.pop();
- }
+ //send physics shapes decomposition requests
+ while (!mPendingPhysicsShapeRequests.empty())
+ {
+ mThread->loadMeshPhysicsShape(mPendingPhysicsShapeRequests.front());
+ mPendingPhysicsShapeRequests.pop();
+ }
- //send physics shapes decomposition requests
- while (!mPendingPhysicsShapeRequests.empty())
- {
- mThread->loadMeshPhysicsShape(mPendingPhysicsShapeRequests.front());
- mPendingPhysicsShapeRequests.pop();
+ mThread->notifyLoadedMeshes();
}
-
- mThread->notifyLoadedMeshes();
-
- mThread->mMutex->unlock();
- mMeshMutex->unlock();
mThread->mSignal->signal();
}
@@ -2588,7 +2525,6 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
if (volume->getNumVolumeFaces() <= 0)
{
llwarns << "Mesh loading returned empty volume." << llendl;
- volume->makeTetrahedron();
}
{ //update system volume
@@ -2596,6 +2532,7 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
if (sys_volume)
{
sys_volume->copyVolumeFaces(volume);
+ sys_volume->setMeshAssetLoaded(TRUE);
LLPrimitive::getVolumeManager()->unrefVolume(sys_volume);
}
else
@@ -2652,26 +2589,7 @@ S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo
return mThread->getActualMeshLOD(mesh_params, lod);
}
-U32 LLMeshRepository::calcResourceCost(LLSD& header)
-{
- U32 bytes = 0;
-
- for (U32 i = 0; i < 4; i++)
- {
- bytes += header[header_lod[i]]["size"].asInteger();
- }
-
- bytes += header["skin"]["size"].asInteger();
-
- return bytes/4096 + 1;
-}
-
-U32 LLMeshRepository::getResourceCost(const LLUUID& mesh_id)
-{
- return mThread->getResourceCost(mesh_id);
-}
-
-const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj)
+const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj)
{
if (mesh_id.notNull())
{
@@ -2809,9 +2727,11 @@ LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id)
void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
- bool upload_skin, bool upload_joints)
+ bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload,
+ LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer)
{
- LLMeshUploadThread* thread = new LLMeshUploadThread(data, scale, upload_textures, upload_skin, upload_joints);
+ LLMeshUploadThread* thread = new LLMeshUploadThread(data, scale, upload_textures, upload_skin, upload_joints, upload_url,
+ do_upload, fee_observer, upload_observer);
mUploadWaitList.push_back(thread);
}
@@ -2839,101 +2759,6 @@ S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)
}
-
-void LLMeshUploadThread::doUploadModel(LLMeshUploadData& data)
-{
- if(isDiscarded())
- {
- return ;
- }
-
- if (!data.mRSVP.empty())
- {
- 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];
-
- 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);
-
- data.mAssetData = ostr.str();
-
- LLCurlRequest::headers_t headers;
- mPendingUploads++;
-
- mCurlRequest->post(data.mRSVP, headers, data.mAssetData, new LLMeshUploadResponder(data, this));
- }
-}
-
-void LLMeshUploadThread::doUploadTexture(LLTextureUploadData& data)
-{
- if(isDiscarded())
- {
- return ;
- }
-
- if (!data.mRSVP.empty())
- {
- std::stringstream ostr;
-
- if (!data.mTexture->isRawImageValid())
- {
- data.mTexture->reloadRawImage(data.mTexture->getDiscardLevel());
- }
-
- if(data.mTexture->hasSavedRawImage())
- {
- LLPointer<LLImageJ2C> upload_file = LLViewerTextureList::convertToUploadFile(data.mTexture->getSavedRawImage());
-
- ostr.write((const char*) upload_file->getData(), upload_file->getDataSize());
- }
-
- data.mAssetData = ostr.str();
-
- LLCurlRequest::headers_t headers;
- mPendingUploads++;
-
- mCurlRequest->post(data.mRSVP, headers, data.mAssetData, new LLTextureUploadResponder(data, this));
- }
-}
-
-
-void LLMeshUploadThread::onModelUploaded(LLMeshUploadData& data)
-{
- createObjects(data);
-}
-
-void LLMeshUploadThread::onTextureUploaded(LLTextureUploadData& data)
-{
- mTextureMap[data.mTexture] = data;
-}
-
-
-void LLMeshUploadThread::createObjects(LLMeshUploadData& data)
-{
- instance_list& instances = mInstance[data.mBaseModel];
-
- for (instance_list::iterator iter = instances.begin(); iter != instances.end(); ++iter)
- { //create prims that reference given mesh
- LLModelInstance& instance = *iter;
- instance.mMeshID = data.mUUID;
- mInstanceQ.push(instance);
- }
-}
-
void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation,
LLVector3& result_pos,
LLQuaternion& result_rot,
@@ -2974,147 +2799,6 @@ void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation,
result_rot = quat_rotation;
}
-
-LLSD LLMeshUploadThread::createObject(LLModelInstance& instance)
-{
- LLMatrix4 transformation = instance.mTransform;
-
- llassert(instance.mMeshID.notNull());
-
- // check for reflection
- BOOL reflected = (transformation.determinant() < 0);
-
- // compute position
- LLVector3 position = LLVector3(0, 0, 0) * transformation;
-
- // compute scale
- LLVector3 x_transformed = LLVector3(1, 0, 0) * transformation - position;
- LLVector3 y_transformed = LLVector3(0, 1, 0) * transformation - position;
- LLVector3 z_transformed = LLVector3(0, 0, 1) * transformation - position;
- F32 x_length = x_transformed.normalize();
- F32 y_length = y_transformed.normalize();
- F32 z_length = z_transformed.normalize();
- LLVector3 scale = LLVector3(x_length, y_length, z_length);
-
- // adjust for "reflected" geometry
- LLVector3 x_transformed_reflected = x_transformed;
- if (reflected)
- {
- x_transformed_reflected *= -1.0;
- }
-
- // compute rotation
- LLMatrix3 rotation_matrix;
- rotation_matrix.setRows(x_transformed_reflected, y_transformed, z_transformed);
- LLQuaternion quat_rotation = rotation_matrix.quaternion();
- quat_rotation.normalize(); // the rotation_matrix might not have been orthoginal. make it so here.
- LLVector3 euler_rotation;
- quat_rotation.getEulerAngles(&euler_rotation.mV[VX], &euler_rotation.mV[VY], &euler_rotation.mV[VZ]);
-
- //
- // build parameter block to construct this prim
- //
-
- LLSD object_params;
-
- // create prim
-
- // set volume params
- U8 sculpt_type = LL_SCULPT_TYPE_MESH;
- if (reflected)
- {
- sculpt_type |= LL_SCULPT_FLAG_MIRROR;
- }
- LLVolumeParams volume_params;
- volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
- volume_params.setBeginAndEndS( 0.f, 1.f );
- volume_params.setBeginAndEndT( 0.f, 1.f );
- volume_params.setRatio ( 1, 1 );
- volume_params.setShear ( 0, 0 );
- volume_params.setSculptID(instance.mMeshID, sculpt_type);
- object_params["shape"] = volume_params.asLLSD();
-
- object_params["material"] = LL_MCODE_WOOD;
-
- object_params["group-id"] = gAgent.getGroupID();
- object_params["pos"] = ll_sd_from_vector3(position + mOrigin);
- object_params["rotation"] = ll_sd_from_quaternion(quat_rotation);
- object_params["scale"] = ll_sd_from_vector3(scale);
- object_params["name"] = instance.mLabel;
-
- // load material from dae file
- object_params["facelist"] = LLSD::emptyArray();
- for (S32 i = 0; i < instance.mMaterial.size(); i++)
- {
- LLTextureEntry te;
- LLImportMaterial& mat = instance.mMaterial[i];
-
- te.setColor(mat.mDiffuseColor);
-
- LLUUID diffuse_id = mTextureMap[mat.mDiffuseMap].mUUID;
-
- if (diffuse_id.notNull())
- {
- te.setID(diffuse_id);
- }
- else
- {
- te.setID(LLUUID("5748decc-f629-461c-9a36-a35a221fe21f")); // blank texture
- }
-
- te.setFullbright(mat.mFullbright);
-
- object_params["facelist"][i] = te.asLLSD();
- }
-
- // set extra parameters
- LLSculptParams sculpt_params;
- sculpt_params.setSculptTexture(instance.mMeshID);
- sculpt_params.setSculptType(sculpt_type);
- U8 buffer[MAX_OBJECT_PARAMS_SIZE+1];
- LLDataPackerBinaryBuffer dp(buffer, MAX_OBJECT_PARAMS_SIZE);
- sculpt_params.pack(dp);
- std::vector<U8> v(dp.getCurrentSize());
- memcpy(&v[0], buffer, dp.getCurrentSize());
- LLSD extra_parameter;
- extra_parameter["extra_parameter"] = sculpt_params.mType;
- extra_parameter["param_data"] = v;
- object_params["extra_parameters"].append(extra_parameter);
-
- LLPermissions perm;
- perm.setOwnerAndGroup(gAgent.getID(), gAgent.getID(), LLUUID::null, false);
- perm.setCreator(gAgent.getID());
-
- perm.initMasks(PERM_ITEM_UNRESTRICTED | PERM_MOVE, //base
- PERM_ITEM_UNRESTRICTED | PERM_MOVE, //owner
- LLFloaterPerms::getEveryonePerms(),
- LLFloaterPerms::getGroupPerms(),
- LLFloaterPerms::getNextOwnerPerms());
-
- object_params["permissions"] = ll_create_sd_from_permissions(perm);
-
- object_params["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
-
- return object_params;
-}
-
-void LLMeshUploadThread::priceResult(LLMeshUploadData& data, const LLSD& content)
-{
- mPendingCost += content["upload_price"].asInteger();
- data.mRSVP = content["rsvp"].asString();
-
- mConfirmedQ.push(data);
-}
-
-void LLMeshUploadThread::priceResult(LLTextureUploadData& data, const LLSD& content)
-{
- mPendingCost += content["upload_price"].asInteger();
- data.mRSVP = content["rsvp"].asString();
-
- mConfirmedTextureQ.push(data);
-}
-
-
bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const
{
if (mDiffuseMap != rhs.mDiffuseMap)
@@ -3137,6 +2821,11 @@ bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const
return mDiffuseColor < rhs.mDiffuseColor;
}
+ if (mBinding != rhs.mBinding)
+ {
+ return mBinding < rhs.mBinding;
+ }
+
return mFullbright < rhs.mFullbright;
}
@@ -3156,57 +2845,68 @@ void LLMeshRepository::uploadError(LLSD& args)
}
//static
-F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod)
+F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value)
{
- 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 +2929,17 @@ 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;
+
+ if (unscaled_value)
+ {
+ *unscaled_value = weighted_avg;
+ }
- return weighted_avg * gSavedSettings.getF32("MeshStreamingCostScaler");
+ return weighted_avg/gSavedSettings.getU32("MeshTriangleBudget")*15000.f;
}
@@ -3291,24 +2996,27 @@ S32 LLPhysicsDecomp::llcdCallback(const char* status, S32 p1, S32 p2)
return 1;
}
-void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh)
+void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh, bool vertex_based)
{
mesh.mVertexBase = mCurRequest->mPositions[0].mV;
mesh.mVertexStrideBytes = 12;
mesh.mNumVertices = mCurRequest->mPositions.size();
- mesh.mIndexType = LLCDMeshData::INT_16;
- mesh.mIndexBase = &(mCurRequest->mIndices[0]);
- mesh.mIndexStrideBytes = 6;
+ if(!vertex_based)
+ {
+ mesh.mIndexType = LLCDMeshData::INT_16;
+ mesh.mIndexBase = &(mCurRequest->mIndices[0]);
+ mesh.mIndexStrideBytes = 6;
- mesh.mNumTriangles = mCurRequest->mIndices.size()/3;
+ mesh.mNumTriangles = mCurRequest->mIndices.size()/3;
+ }
- if (mesh.mNumTriangles > 0 && mesh.mNumVertices > 2)
+ if ((vertex_based || mesh.mNumTriangles > 0) && mesh.mNumVertices > 2)
{
LLCDResult ret = LLCD_OK;
if (LLConvexDecomposition::getInstance() != NULL)
{
- ret = LLConvexDecomposition::getInstance()->setMeshData(&mesh);
+ ret = LLConvexDecomposition::getInstance()->setMeshData(&mesh, vertex_based);
}
if (ret)
@@ -3332,7 +3040,7 @@ void LLPhysicsDecomp::doDecomposition()
//load data intoLLCD
if (stage == 0)
{
- setMeshData(mesh);
+ setMeshData(mesh, false);
}
//build parameter map
@@ -3411,13 +3119,14 @@ void LLPhysicsDecomp::doDecomposition()
num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(stage);
}
- mMutex->lock();
- mCurRequest->mHull.clear();
- mCurRequest->mHull.resize(num_hulls);
+ {
+ LLMutexLock lock(mMutex);
+ mCurRequest->mHull.clear();
+ mCurRequest->mHull.resize(num_hulls);
- mCurRequest->mHullMesh.clear();
- mCurRequest->mHullMesh.resize(num_hulls);
- mMutex->unlock();
+ mCurRequest->mHullMesh.clear();
+ mCurRequest->mHullMesh.resize(num_hulls);
+ }
for (S32 i = 0; i < num_hulls; ++i)
{
@@ -3441,14 +3150,14 @@ void LLPhysicsDecomp::doDecomposition()
get_vertex_buffer_from_mesh(mesh, mCurRequest->mHullMesh[i]);
- mMutex->lock();
- mCurRequest->mHull[i] = p;
- mMutex->unlock();
+ {
+ LLMutexLock lock(mMutex);
+ mCurRequest->mHull[i] = p;
+ }
}
{
LLMutexLock lock(mMutex);
-
mCurRequest->setStatusMessage("FAIL");
completeCurrent();
}
@@ -3506,22 +3215,6 @@ void make_box(LLPhysicsDecomp::Request * request)
void LLPhysicsDecomp::doDecompositionSingleHull()
{
- LLCDMeshData mesh;
-
- setMeshData(mesh);
-
-
- //set all parameters to default
- std::map<std::string, const LLCDParam*> param_map;
-
- static const LLCDParam* params = NULL;
- static S32 param_count = 0;
-
- if (!params)
- {
- param_count = LLConvexDecomposition::getInstance()->getParameters(&params);
- }
-
LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance();
if (decomp == NULL)
@@ -3529,75 +3222,46 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
//stub. do nothing.
return;
}
-
- for (S32 i = 0; i < param_count; ++i)
- {
- decomp->setParam(params[i].mName, params[i].mDefault.mIntOrEnumValue);
- }
-
- const S32 STAGE_DECOMPOSE = mStageID["Decompose"];
- const S32 STAGE_SIMPLIFY = mStageID["Simplify"];
- const S32 DECOMP_PREVIEW = 0;
- const S32 SIMPLIFY_RETAIN = 0;
- decomp->setParam("Decompose Quality", DECOMP_PREVIEW);
- decomp->setParam("Simplify Method", SIMPLIFY_RETAIN);
- decomp->setParam("Retain%", 0.f);
+ LLCDMeshData mesh;
- LLCDResult ret = LLCD_OK;
- ret = decomp->executeStage(STAGE_DECOMPOSE);
-
- if (ret)
+ setMeshData(mesh, true);
+
+ LLCDResult ret = decomp->buildSingleHull() ;
+ if(ret)
{
llwarns << "Could not execute decomposition stage when attempting to create single hull." << llendl;
make_box(mCurRequest);
}
else
{
- ret = decomp->executeStage(STAGE_SIMPLIFY);
-
- if (ret)
{
- llwarns << "Could not execute simiplification stage when attempting to create single hull." << llendl;
- make_box(mCurRequest);
- }
- else
- {
- S32 num_hulls =0;
- if (LLConvexDecomposition::getInstance() != NULL)
- {
- num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(STAGE_SIMPLIFY);
- }
-
- mMutex->lock();
+ LLMutexLock lock(mMutex);
mCurRequest->mHull.clear();
- mCurRequest->mHull.resize(num_hulls);
+ mCurRequest->mHull.resize(1);
mCurRequest->mHullMesh.clear();
- mMutex->unlock();
+ }
- for (S32 i = 0; i < num_hulls; ++i)
- {
- std::vector<LLVector3> p;
- LLCDHull hull;
- // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code
- LLConvexDecomposition::getInstance()->getHullFromStage(STAGE_SIMPLIFY, i, &hull);
+ std::vector<LLVector3> p;
+ LLCDHull hull;
+
+ // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code
+ decomp->getSingleHull(&hull);
- const F32* v = hull.mVertexBase;
+ const F32* v = hull.mVertexBase;
- for (S32 j = 0; j < hull.mNumVertices; ++j)
- {
- LLVector3 vert(v[0], v[1], v[2]);
- p.push_back(vert);
- v = (F32*) (((U8*) v) + hull.mVertexStrideBytes);
- }
-
- mMutex->lock();
- mCurRequest->mHull[i] = p;
- mMutex->unlock();
- }
+ for (S32 j = 0; j < hull.mNumVertices; ++j)
+ {
+ LLVector3 vert(v[0], v[1], v[2]);
+ p.push_back(vert);
+ v = (F32*) (((U8*) v) + hull.mVertexStrideBytes);
}
- }
-
+
+ {
+ LLMutexLock lock(mMutex);
+ mCurRequest->mHull[0] = p;
+ }
+ }
{
completeCurrent();
@@ -3760,7 +3424,8 @@ LLModelInstance::LLModelInstance(LLSD& data)
for (U32 i = 0; i < data["material"].size(); ++i)
{
- mMaterial.push_back(LLImportMaterial(data["material"][i]));
+ LLImportMaterial mat(data["material"][i]);
+ mMaterial[mat.mBinding] = mat;
}
}
@@ -3773,9 +3438,10 @@ LLSD LLModelInstance::asLLSD()
ret["label"] = mLabel;
ret["transform"] = mTransform.getValue();
- for (U32 i = 0; i < mMaterial.size(); ++i)
+ U32 i = 0;
+ for (std::map<std::string, LLImportMaterial>::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter)
{
- ret["material"][i] = mMaterial[i].asLLSD();
+ ret["material"][i++] = iter->second.asLLSD();
}
return ret;
@@ -3787,6 +3453,7 @@ LLImportMaterial::LLImportMaterial(LLSD& data)
mDiffuseMapLabel = data["diffuse"]["label"].asString();
mDiffuseColor.setValue(data["diffuse"]["color"]);
mFullbright = data["fullbright"].asBoolean();
+ mBinding = data["binding"].asString();
}
@@ -3798,7 +3465,8 @@ LLSD LLImportMaterial::asLLSD()
ret["diffuse"]["label"] = mDiffuseMapLabel;
ret["diffuse"]["color"] = mDiffuseColor.getValue();
ret["fullbright"] = mFullbright;
-
+ ret["binding"] = mBinding;
+
return ret;
}
@@ -3849,8 +3517,7 @@ void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)
bool LLMeshRepository::meshUploadEnabled()
{
LLViewerRegion *region = gAgent.getRegion();
- if(gSavedSettings.getBOOL("MeshEnabled") &&
- LLViewerParcelMgr::getInstance()->allowAgentBuild() &&
+ if(gSavedSettings.getBOOL("MeshEnabled") &&
region)
{
return region->meshUploadEnabled();