summaryrefslogtreecommitdiff
path: root/indra/newview/llmeshrepository.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llmeshrepository.h')
-rw-r--r--indra/newview/llmeshrepository.h1492
1 files changed, 746 insertions, 746 deletions
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index cd719f66a6..d62c6eb894 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -1,746 +1,746 @@
-/**
- * @file llmeshrepository.h
- * @brief Client-side repository of mesh assets.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010-2013, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_MESH_REPOSITORY_H
-#define LL_MESH_REPOSITORY_H
-
-#include <unordered_map>
-#include "llassettype.h"
-#include "llmodel.h"
-#include "lluuid.h"
-#include "llviewertexture.h"
-#include "llvolume.h"
-#include "lldeadmantimer.h"
-#include "httpcommon.h"
-#include "httprequest.h"
-#include "httpoptions.h"
-#include "httpheaders.h"
-#include "httphandler.h"
-#include "llthread.h"
-
-#define LLCONVEXDECOMPINTER_STATIC 1
-
-#include "llconvexdecomposition.h"
-#include "lluploadfloaterobservers.h"
-
-class LLVOVolume;
-class LLMutex;
-class LLCondition;
-class LLMeshRepository;
-
-typedef enum e_mesh_processing_result_enum
-{
- MESH_OK = 0,
- MESH_NO_DATA = 1,
- MESH_OUT_OF_MEMORY,
- MESH_HTTP_REQUEST_FAILED,
- MESH_PARSE_FAILURE,
- MESH_INVALID,
- MESH_UNKNOWN
-} EMeshProcessingResult;
-
-class LLMeshUploadData
-{
-public:
- LLPointer<LLModel> mBaseModel;
- LLPointer<LLModel> mModel[5];
- LLUUID mUUID;
- U32 mRetries;
- std::string mRSVP;
- std::string mAssetData;
- LLSD mPostData;
-
- LLMeshUploadData()
- {
- mRetries = 0;
- }
-};
-
-class LLTextureUploadData
-{
-public:
- LLViewerFetchedTexture* mTexture;
- LLUUID mUUID;
- std::string mRSVP;
- std::string mLabel;
- U32 mRetries;
- std::string mAssetData;
- LLSD mPostData;
-
- LLTextureUploadData()
- {
- mRetries = 0;
- }
-
- LLTextureUploadData(LLViewerFetchedTexture* texture, std::string& label)
- : mTexture(texture), mLabel(label)
- {
- mRetries = 0;
- }
-};
-
-class LLPhysicsDecomp : public LLThread
-{
-public:
-
- typedef std::map<std::string, LLSD> decomp_params;
-
- class Request : public LLRefCount
- {
- public:
- //input params
- S32* mDecompID;
- std::string mStage;
- std::vector<LLVector3> mPositions;
- std::vector<U16> mIndices;
- decomp_params mParams;
-
- //output state
- std::string mStatusMessage;
- std::vector<LLModel::PhysicsMesh> mHullMesh;
- LLModel::convex_hull_decomposition mHull;
-
- //status message callback, called from decomposition thread
- virtual S32 statusCallback(const char* status, S32 p1, S32 p2) = 0;
-
- //completed callback, called from the main thread
- virtual void completed() = 0;
-
- virtual void setStatusMessage(const std::string& msg);
-
- bool isValid() const {return mPositions.size() > 2 && mIndices.size() > 2 ;}
-
- protected:
- //internal use
- LLVector3 mBBox[2] ;
- F32 mTriangleAreaThreshold ;
-
- void assignData(LLModel* mdl) ;
- void updateTriangleAreaThreshold() ;
- bool isValidTriangle(U16 idx1, U16 idx2, U16 idx3) ;
- };
-
- LLCondition* mSignal;
- LLMutex* mMutex;
-
- bool mInited;
- bool mQuitting;
- bool mDone;
-
- LLPhysicsDecomp();
- ~LLPhysicsDecomp();
-
- void shutdown();
-
- void submitRequest(Request* request);
- static S32 llcdCallback(const char*, S32, S32);
- void cancel();
-
- void setMeshData(LLCDMeshData& mesh, bool vertex_based);
- void doDecomposition();
- void doDecompositionSingleHull();
-
- virtual void run();
-
- void completeCurrent();
- void notifyCompleted();
-
- std::map<std::string, S32> mStageID;
-
- typedef std::queue<LLPointer<Request> > request_queue;
- request_queue mRequestQ;
-
- LLPointer<Request> mCurRequest;
-
- std::queue<LLPointer<Request> > mCompletedQ;
-
-};
-
-class RequestStats
-{
-public:
- RequestStats() : mRetries(0) {};
-
- void updateTime();
- bool canRetry() const;
- bool isDelayed() const;
- U32 getRetries() { return mRetries; }
-
-private:
- U32 mRetries;
- LLFrameTimer mTimer;
-};
-
-class LLMeshHeader
-{
-public:
-
- LLMeshHeader() {}
-
- explicit LLMeshHeader(const LLSD& header)
- {
- fromLLSD(header);
- }
-
- void fromLLSD(const LLSD& header)
- {
- const char* lod[] =
- {
- "lowest_lod",
- "low_lod",
- "medium_lod",
- "high_lod"
- };
-
- mVersion = header["version"].asInteger();
-
- for (U32 i = 0; i < 4; ++i)
- {
- mLodOffset[i] = header[lod[i]]["offset"].asInteger();
- mLodSize[i] = header[lod[i]]["size"].asInteger();
- }
-
- mSkinOffset = header["skin"]["offset"].asInteger();
- mSkinSize = header["skin"]["size"].asInteger();
-
- mPhysicsConvexOffset = header["physics_convex"]["offset"].asInteger();
- mPhysicsConvexSize = header["physics_convex"]["size"].asInteger();
-
- mPhysicsMeshOffset = header["physics_mesh"]["offset"].asInteger();
- mPhysicsMeshSize = header["physics_mesh"]["size"].asInteger();
-
- m404 = header.has("404");
- }
-
- S32 mVersion = -1;
- S32 mSkinOffset = -1;
- S32 mSkinSize = -1;
-
- S32 mPhysicsConvexOffset = -1;
- S32 mPhysicsConvexSize = -1;
-
- S32 mPhysicsMeshOffset = -1;
- S32 mPhysicsMeshSize = -1;
-
- S32 mLodOffset[4] = { -1 };
- S32 mLodSize[4] = { -1 };
-
- bool m404 = false;
-};
-
-class LLMeshRepoThread : public LLThread
-{
-public:
-
- volatile static S32 sActiveHeaderRequests;
- volatile static S32 sActiveLODRequests;
- static U32 sMaxConcurrentRequests;
- static S32 sRequestLowWater;
- static S32 sRequestHighWater;
- static S32 sRequestWaterLevel; // Stats-use only, may read outside of thread
-
- LLMutex* mMutex;
- LLMutex* mHeaderMutex;
- LLCondition* mSignal;
-
- //map of known mesh headers
- typedef boost::unordered_map<LLUUID, std::pair<U32, LLMeshHeader>> mesh_header_map; // pair is header_size and data
- mesh_header_map mMeshHeader;
-
- class HeaderRequest : public RequestStats
- {
- public:
- const LLVolumeParams mMeshParams;
-
- HeaderRequest(const LLVolumeParams& mesh_params)
- : RequestStats(), mMeshParams(mesh_params)
- {
- }
-
- bool operator<(const HeaderRequest& rhs) const
- {
- return mMeshParams < rhs.mMeshParams;
- }
- };
-
- class LODRequest : public RequestStats
- {
- public:
- LLVolumeParams mMeshParams;
- S32 mLOD;
- F32 mScore;
-
- LODRequest(const LLVolumeParams& mesh_params, S32 lod)
- : RequestStats(), mMeshParams(mesh_params), mLOD(lod), mScore(0.f)
- {
- }
- };
-
- struct CompareScoreGreater
- {
- bool operator()(const LODRequest& lhs, const LODRequest& rhs)
- {
- return lhs.mScore > rhs.mScore; // greatest = first
- }
- };
-
- class UUIDBasedRequest : public RequestStats
- {
- public:
- LLUUID mId;
-
- UUIDBasedRequest(const LLUUID& id)
- : RequestStats(), mId(id)
- {
- }
-
- bool operator<(const UUIDBasedRequest& rhs) const
- {
- return mId < rhs.mId;
- }
- };
-
- class LoadedMesh
- {
- public:
- LLPointer<LLVolume> mVolume;
- LLVolumeParams mMeshParams;
- S32 mLOD;
-
- LoadedMesh(LLVolume* volume, const LLVolumeParams& mesh_params, S32 lod)
- : mVolume(volume), mMeshParams(mesh_params), mLOD(lod)
- {
- }
-
- };
-
- //set of requested skin info
- std::deque<UUIDBasedRequest> mSkinRequests;
-
- // list of completed skin info requests
- std::deque<LLMeshSkinInfo*> mSkinInfoQ;
-
- // list of skin info requests that have failed or are unavailaibe
- std::deque<UUIDBasedRequest> mSkinUnavailableQ;
-
- //set of requested decompositions
- std::set<UUIDBasedRequest> mDecompositionRequests;
-
- //set of requested physics shapes
- std::set<UUIDBasedRequest> mPhysicsShapeRequests;
-
- // list of completed Decomposition info requests
- std::list<LLModel::Decomposition*> mDecompositionQ;
-
- //queue of requested headers
- std::queue<HeaderRequest> mHeaderReqQ;
-
- //queue of requested LODs
- std::queue<LODRequest> mLODReqQ;
-
- //queue of unavailable LODs (either asset doesn't exist or asset doesn't have desired LOD)
- std::deque<LODRequest> mUnavailableQ;
-
- //queue of successfully loaded meshes
- std::deque<LoadedMesh> mLoadedQ;
-
- //map of pending header requests and currently desired LODs
- typedef boost::unordered_map<LLUUID, std::vector<S32> > pending_lod_map;
- pending_lod_map mPendingLOD;
-
- // llcorehttp library interface objects.
- LLCore::HttpStatus mHttpStatus;
- LLCore::HttpRequest * mHttpRequest;
- LLCore::HttpOptions::ptr_t mHttpOptions;
- LLCore::HttpOptions::ptr_t mHttpLargeOptions;
- LLCore::HttpHeaders::ptr_t mHttpHeaders;
- LLCore::HttpRequest::policy_t mHttpPolicyClass;
- LLCore::HttpRequest::policy_t mHttpLargePolicyClass;
-
- typedef std::set<LLCore::HttpHandler::ptr_t> http_request_set;
- http_request_set mHttpRequestSet; // Outstanding HTTP requests
-
- std::string mGetMeshCapability;
-
- LLMeshRepoThread();
- ~LLMeshRepoThread();
-
- virtual void run();
-
- void lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
- void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
-
- bool fetchMeshHeader(const LLVolumeParams& mesh_params, bool can_retry = true);
- bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, bool can_retry = true);
- EMeshProcessingResult headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);
- EMeshProcessingResult lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size);
- bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
- bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
- EMeshProcessingResult physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
- bool hasPhysicsShapeInHeader(const LLUUID& mesh_id);
- bool hasSkinInfoInHeader(const LLUUID& mesh_id);
- bool hasHeader(const LLUUID& mesh_id);
-
- void notifyLoadedMeshes();
- S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
-
- void loadMeshSkinInfo(const LLUUID& mesh_id);
- void loadMeshDecomposition(const LLUUID& mesh_id);
- void loadMeshPhysicsShape(const LLUUID& mesh_id);
-
- //send request for skin info, returns true if header info exists
- // (should hold onto mesh_id and try again later if header info does not exist)
- bool fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry = true);
-
- //send request for decomposition, returns true if header info exists
- // (should hold onto mesh_id and try again later if header info does not exist)
- bool fetchMeshDecomposition(const LLUUID& mesh_id);
-
- //send request for PhysicsShape, returns true if header info exists
- // (should hold onto mesh_id and try again later if header info does not exist)
- bool fetchMeshPhysicsShape(const LLUUID& mesh_id);
-
- static void incActiveLODRequests();
- static void decActiveLODRequests();
- static void incActiveHeaderRequests();
- static void decActiveHeaderRequests();
-
- // Set the caps strings and preferred version for constructing
- // mesh fetch URLs.
- //
- // Mutex: must be holding mMutex when called
- void setGetMeshCap(const std::string & get_mesh);
-
- // Mutex: acquires mMutex
- void constructUrl(LLUUID mesh_id, std::string * url);
-
-private:
- // Issue a GET request to a URL with 'Range' header using
- // the correct policy class and other attributes. If an invalid
- // handle is returned, the request failed and caller must retry
- // or dispose of handler.
- //
- // Threads: Repo thread only
- LLCore::HttpHandle getByteRange(const std::string & url,
- size_t offset, size_t len,
- const LLCore::HttpHandler::ptr_t &handler);
-};
-
-
-// Class whose instances represent a single upload-type request for
-// meshes: one fee query or one actual upload attempt. Yes, it creates
-// a unique thread for that single request. As it is 1:1, it can also
-// trivially serve as the HttpHandler object for request completion
-// notifications.
-
-class LLMeshUploadThread : public LLThread, public LLCore::HttpHandler
-{
-private:
- S32 mMeshUploadTimeOut ; //maximum time in seconds to execute an uploading request.
-
-public:
- class DecompRequest : public LLPhysicsDecomp::Request
- {
- public:
- LLPointer<LLModel> mModel;
- LLPointer<LLModel> mBaseModel;
-
- LLMeshUploadThread* mThread;
-
- DecompRequest(LLModel* mdl, LLModel* base_model, LLMeshUploadThread* thread);
-
- S32 statusCallback(const char* status, S32 p1, S32 p2) { return 1; }
- void completed();
- };
-
- LLPointer<DecompRequest> mFinalDecomp;
- volatile bool mPhysicsComplete;
-
- typedef std::map<LLPointer<LLModel>, std::vector<LLVector3> > hull_map;
- hull_map mHullMap;
-
- typedef std::vector<LLModelInstance> instance_list;
- instance_list mInstanceList;
-
- typedef std::map<LLPointer<LLModel>, instance_list> instance_map;
- instance_map mInstance;
-
- LLMutex* mMutex;
- S32 mPendingUploads;
- LLVector3 mOrigin;
- bool mFinished;
- bool mUploadTextures;
- bool mUploadSkin;
- bool mUploadJoints;
- bool mLockScaleIfJointPosition;
- volatile bool mDiscarded;
-
- LLHost mHost;
- std::string mWholeModelFeeCapability;
- std::string mWholeModelUploadURL;
-
- LLMeshUploadThread(instance_list& data, 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 = true,
- LLHandle<LLWholeModelFeeObserver> fee_observer = (LLHandle<LLWholeModelFeeObserver>()),
- LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
- ~LLMeshUploadThread();
-
- bool finished() const { return mFinished; }
- virtual void run();
- void preStart();
- void discard() ;
- bool isDiscarded() const;
-
- void generateHulls();
-
- void doWholeModelUpload();
- void requestWholeModelFee();
-
- void wholeModelToLLSD(LLSD& dest, bool include_textures);
-
- void decomposeMeshMatrix(LLMatrix4& transformation,
- LLVector3& result_pos,
- LLQuaternion& result_rot,
- LLVector3& result_scale);
-
- void setFeeObserverHandle(LLHandle<LLWholeModelFeeObserver> observer_handle) { mFeeObserverHandle = observer_handle; }
- void setUploadObserverHandle(LLHandle<LLWholeModelUploadObserver> observer_handle) { mUploadObserverHandle = observer_handle; }
-
- // Inherited from LLCore::HttpHandler
- virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
-
- LLViewerFetchedTexture* FindViewerTexture(const LLImportMaterial& material);
-
-private:
- LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle;
- LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle;
-
- bool mDoUpload; // if false only model data will be requested, otherwise the model will be uploaded
- LLSD mModelData;
-
- // llcorehttp library interface objects.
- LLCore::HttpStatus mHttpStatus;
- LLCore::HttpRequest * mHttpRequest;
- LLCore::HttpOptions::ptr_t mHttpOptions;
- LLCore::HttpHeaders::ptr_t mHttpHeaders;
- LLCore::HttpRequest::policy_t mHttpPolicyClass;
-};
-
-// Params related to streaming cost, render cost, and scene complexity tracking.
-class LLMeshCostData
-{
-public:
- LLMeshCostData();
-
- bool init(const LLMeshHeader& header);
-
- // Size for given LOD
- S32 getSizeByLOD(S32 lod);
-
- // Sum of all LOD sizes.
- S32 getSizeTotal();
-
- // Estimated triangle counts for the given LOD.
- F32 getEstTrisByLOD(S32 lod);
-
- // Estimated triangle counts for the largest LOD. Typically this
- // is also the "high" LOD, but not necessarily.
- F32 getEstTrisMax();
-
- // Triangle count as computed by original streaming cost
- // formula. Triangles in each LOD are weighted based on how
- // frequently they will be seen.
- // This was called "unscaled_value" in the original getStreamingCost() functions.
- F32 getRadiusWeightedTris(F32 radius);
-
- // Triangle count used by triangle-based cost formula. Based on
- // triangles in highest LOD plus potentially partial charges for
- // lower LODs depending on complexity.
- F32 getEstTrisForStreamingCost();
-
- // Streaming cost. This should match the server-side calculation
- // for the corresponding volume.
- F32 getRadiusBasedStreamingCost(F32 radius);
-
- // New streaming cost formula, currently only used for animated objects.
- F32 getTriangleBasedStreamingCost();
-
-private:
- // From the "size" field of the mesh header. LOD 0=lowest, 3=highest.
- std::array<S32,4> mSizeByLOD;
-
- // Estimated triangle counts derived from the LOD sizes. LOD 0=lowest, 3=highest.
- std::array<F32,4> mEstTrisByLOD;
-};
-
-class LLMeshRepository
-{
-public:
-
- //metrics
- static U32 sBytesReceived;
- static U32 sMeshRequestCount; // Total request count, http or cached, all component types
- static U32 sHTTPRequestCount; // Http GETs issued (not large)
- static U32 sHTTPLargeRequestCount; // Http GETs issued for large requests
- static U32 sHTTPRetryCount; // Total request retries whether successful or failed
- static U32 sHTTPErrorCount; // Requests ending in error
- static U32 sLODPending;
- static U32 sLODProcessing;
- static U32 sCacheBytesRead;
- static U32 sCacheBytesWritten;
- static U32 sCacheBytesHeaders;
- static U32 sCacheBytesSkins;
- static U32 sCacheBytesDecomps;
- static U32 sCacheReads;
- static U32 sCacheWrites;
- static U32 sMaxLockHoldoffs; // Maximum sequential locking failures
-
- static LLDeadmanTimer sQuiescentTimer; // Time-to-complete-mesh-downloads after significant events
-
- // Estimated triangle count of the largest LOD
- F32 getEstTrianglesMax(LLUUID mesh_id);
- F32 getEstTrianglesStreamingCost(LLUUID mesh_id);
- F32 getStreamingCostLegacy(LLUUID mesh_id, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
- static F32 getStreamingCostLegacy(LLMeshHeader& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
- bool getCostData(LLUUID mesh_id, LLMeshCostData& data);
- bool getCostData(LLMeshHeader& header, LLMeshCostData& data);
-
- LLMeshRepository();
-
- void init();
- void shutdown();
- S32 update();
-
- void unregisterMesh(LLVOVolume* volume);
- //mesh management functions
- S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0, S32 last_lod = -1);
-
- void notifyLoadedMeshes();
- void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume);
- void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod);
- void notifySkinInfoReceived(LLMeshSkinInfo* info);
- void notifySkinInfoUnavailable(const LLUUID& info);
- void notifyDecompositionReceived(LLModel::Decomposition* info);
-
- S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
- static S32 getActualMeshLOD(LLMeshHeader& header, S32 lod);
- const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj = nullptr);
- LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
- void fetchPhysicsShape(const LLUUID& mesh_id);
- bool hasPhysicsShape(const LLUUID& mesh_id);
- bool hasSkinInfo(const LLUUID& mesh_id);
- bool hasHeader(const LLUUID& mesh_id);
-
- void buildHull(const LLVolumeParams& params, S32 detail);
- void buildPhysicsMesh(LLModel::Decomposition& decomp);
-
- bool meshUploadEnabled();
- bool meshRezEnabled();
-
- void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
- bool upload_skin, bool upload_joints, bool lock_scale_if_joint_position,
- std::string upload_url, bool do_upload = true,
- LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()),
- LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
-
- S32 getMeshSize(const LLUUID& mesh_id, S32 lod);
-
- // Quiescent timer management, main thread only.
- static void metricsStart();
- static void metricsStop();
- static void metricsProgress(unsigned int count);
- static void metricsUpdate();
-
- typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > mesh_load_map;
- mesh_load_map mLoadingMeshes[4];
-
- typedef std::unordered_map<LLUUID, LLPointer<LLMeshSkinInfo>> skin_map;
- skin_map mSkinMap;
-
- typedef std::map<LLUUID, LLModel::Decomposition*> decomposition_map;
- decomposition_map mDecompositionMap;
-
- LLMutex* mMeshMutex;
-
- std::vector<LLMeshRepoThread::LODRequest> mPendingRequests;
-
- //list of mesh ids awaiting skin info
- typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > skin_load_map;
- skin_load_map mLoadingSkins;
-
- //list of mesh ids that need to send skin info fetch requests
- std::queue<LLUUID> mPendingSkinRequests;
-
- //list of mesh ids awaiting decompositions
- std::set<LLUUID> mLoadingDecompositions;
-
- //list of mesh ids that need to send decomposition fetch requests
- std::queue<LLUUID> mPendingDecompositionRequests;
-
- //list of mesh ids awaiting physics shapes
- std::set<LLUUID> mLoadingPhysicsShapes;
-
- //list of mesh ids that need to send physics shape fetch requests
- std::queue<LLUUID> mPendingPhysicsShapeRequests;
-
- U32 mMeshThreadCount;
-
- LLMeshRepoThread* mThread;
- std::vector<LLMeshUploadThread*> mUploads;
- std::vector<LLMeshUploadThread*> mUploadWaitList;
-
- LLPhysicsDecomp* mDecompThread;
-
- LLFrameTimer mSkinInfoCullTimer;
-
- class inventory_data
- {
- public:
- LLSD mPostData;
- LLSD mResponse;
-
- inventory_data(const LLSD& data, const LLSD& content)
- : mPostData(data), mResponse(content)
- {
- }
- };
-
- std::queue<inventory_data> mInventoryQ;
-
- std::queue<LLSD> mUploadErrorQ;
-
- void uploadError(LLSD& args);
- void updateInventory(inventory_data data);
-};
-
-extern LLMeshRepository gMeshRepo;
-
-const F32 ANIMATED_OBJECT_BASE_COST = 15.0f;
-const F32 ANIMATED_OBJECT_COST_PER_KTRI = 1.5f;
-
-#endif
-
+/**
+ * @file llmeshrepository.h
+ * @brief Client-side repository of mesh assets.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010-2013, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_MESH_REPOSITORY_H
+#define LL_MESH_REPOSITORY_H
+
+#include <unordered_map>
+#include "llassettype.h"
+#include "llmodel.h"
+#include "lluuid.h"
+#include "llviewertexture.h"
+#include "llvolume.h"
+#include "lldeadmantimer.h"
+#include "httpcommon.h"
+#include "httprequest.h"
+#include "httpoptions.h"
+#include "httpheaders.h"
+#include "httphandler.h"
+#include "llthread.h"
+
+#define LLCONVEXDECOMPINTER_STATIC 1
+
+#include "llconvexdecomposition.h"
+#include "lluploadfloaterobservers.h"
+
+class LLVOVolume;
+class LLMutex;
+class LLCondition;
+class LLMeshRepository;
+
+typedef enum e_mesh_processing_result_enum
+{
+ MESH_OK = 0,
+ MESH_NO_DATA = 1,
+ MESH_OUT_OF_MEMORY,
+ MESH_HTTP_REQUEST_FAILED,
+ MESH_PARSE_FAILURE,
+ MESH_INVALID,
+ MESH_UNKNOWN
+} EMeshProcessingResult;
+
+class LLMeshUploadData
+{
+public:
+ LLPointer<LLModel> mBaseModel;
+ LLPointer<LLModel> mModel[5];
+ LLUUID mUUID;
+ U32 mRetries;
+ std::string mRSVP;
+ std::string mAssetData;
+ LLSD mPostData;
+
+ LLMeshUploadData()
+ {
+ mRetries = 0;
+ }
+};
+
+class LLTextureUploadData
+{
+public:
+ LLViewerFetchedTexture* mTexture;
+ LLUUID mUUID;
+ std::string mRSVP;
+ std::string mLabel;
+ U32 mRetries;
+ std::string mAssetData;
+ LLSD mPostData;
+
+ LLTextureUploadData()
+ {
+ mRetries = 0;
+ }
+
+ LLTextureUploadData(LLViewerFetchedTexture* texture, std::string& label)
+ : mTexture(texture), mLabel(label)
+ {
+ mRetries = 0;
+ }
+};
+
+class LLPhysicsDecomp : public LLThread
+{
+public:
+
+ typedef std::map<std::string, LLSD> decomp_params;
+
+ class Request : public LLRefCount
+ {
+ public:
+ //input params
+ S32* mDecompID;
+ std::string mStage;
+ std::vector<LLVector3> mPositions;
+ std::vector<U16> mIndices;
+ decomp_params mParams;
+
+ //output state
+ std::string mStatusMessage;
+ std::vector<LLModel::PhysicsMesh> mHullMesh;
+ LLModel::convex_hull_decomposition mHull;
+
+ //status message callback, called from decomposition thread
+ virtual S32 statusCallback(const char* status, S32 p1, S32 p2) = 0;
+
+ //completed callback, called from the main thread
+ virtual void completed() = 0;
+
+ virtual void setStatusMessage(const std::string& msg);
+
+ bool isValid() const {return mPositions.size() > 2 && mIndices.size() > 2 ;}
+
+ protected:
+ //internal use
+ LLVector3 mBBox[2] ;
+ F32 mTriangleAreaThreshold ;
+
+ void assignData(LLModel* mdl) ;
+ void updateTriangleAreaThreshold() ;
+ bool isValidTriangle(U16 idx1, U16 idx2, U16 idx3) ;
+ };
+
+ LLCondition* mSignal;
+ LLMutex* mMutex;
+
+ bool mInited;
+ bool mQuitting;
+ bool mDone;
+
+ LLPhysicsDecomp();
+ ~LLPhysicsDecomp();
+
+ void shutdown();
+
+ void submitRequest(Request* request);
+ static S32 llcdCallback(const char*, S32, S32);
+ void cancel();
+
+ void setMeshData(LLCDMeshData& mesh, bool vertex_based);
+ void doDecomposition();
+ void doDecompositionSingleHull();
+
+ virtual void run();
+
+ void completeCurrent();
+ void notifyCompleted();
+
+ std::map<std::string, S32> mStageID;
+
+ typedef std::queue<LLPointer<Request> > request_queue;
+ request_queue mRequestQ;
+
+ LLPointer<Request> mCurRequest;
+
+ std::queue<LLPointer<Request> > mCompletedQ;
+
+};
+
+class RequestStats
+{
+public:
+ RequestStats() : mRetries(0) {};
+
+ void updateTime();
+ bool canRetry() const;
+ bool isDelayed() const;
+ U32 getRetries() { return mRetries; }
+
+private:
+ U32 mRetries;
+ LLFrameTimer mTimer;
+};
+
+class LLMeshHeader
+{
+public:
+
+ LLMeshHeader() {}
+
+ explicit LLMeshHeader(const LLSD& header)
+ {
+ fromLLSD(header);
+ }
+
+ void fromLLSD(const LLSD& header)
+ {
+ const char* lod[] =
+ {
+ "lowest_lod",
+ "low_lod",
+ "medium_lod",
+ "high_lod"
+ };
+
+ mVersion = header["version"].asInteger();
+
+ for (U32 i = 0; i < 4; ++i)
+ {
+ mLodOffset[i] = header[lod[i]]["offset"].asInteger();
+ mLodSize[i] = header[lod[i]]["size"].asInteger();
+ }
+
+ mSkinOffset = header["skin"]["offset"].asInteger();
+ mSkinSize = header["skin"]["size"].asInteger();
+
+ mPhysicsConvexOffset = header["physics_convex"]["offset"].asInteger();
+ mPhysicsConvexSize = header["physics_convex"]["size"].asInteger();
+
+ mPhysicsMeshOffset = header["physics_mesh"]["offset"].asInteger();
+ mPhysicsMeshSize = header["physics_mesh"]["size"].asInteger();
+
+ m404 = header.has("404");
+ }
+
+ S32 mVersion = -1;
+ S32 mSkinOffset = -1;
+ S32 mSkinSize = -1;
+
+ S32 mPhysicsConvexOffset = -1;
+ S32 mPhysicsConvexSize = -1;
+
+ S32 mPhysicsMeshOffset = -1;
+ S32 mPhysicsMeshSize = -1;
+
+ S32 mLodOffset[4] = { -1 };
+ S32 mLodSize[4] = { -1 };
+
+ bool m404 = false;
+};
+
+class LLMeshRepoThread : public LLThread
+{
+public:
+
+ volatile static S32 sActiveHeaderRequests;
+ volatile static S32 sActiveLODRequests;
+ static U32 sMaxConcurrentRequests;
+ static S32 sRequestLowWater;
+ static S32 sRequestHighWater;
+ static S32 sRequestWaterLevel; // Stats-use only, may read outside of thread
+
+ LLMutex* mMutex;
+ LLMutex* mHeaderMutex;
+ LLCondition* mSignal;
+
+ //map of known mesh headers
+ typedef boost::unordered_map<LLUUID, std::pair<U32, LLMeshHeader>> mesh_header_map; // pair is header_size and data
+ mesh_header_map mMeshHeader;
+
+ class HeaderRequest : public RequestStats
+ {
+ public:
+ const LLVolumeParams mMeshParams;
+
+ HeaderRequest(const LLVolumeParams& mesh_params)
+ : RequestStats(), mMeshParams(mesh_params)
+ {
+ }
+
+ bool operator<(const HeaderRequest& rhs) const
+ {
+ return mMeshParams < rhs.mMeshParams;
+ }
+ };
+
+ class LODRequest : public RequestStats
+ {
+ public:
+ LLVolumeParams mMeshParams;
+ S32 mLOD;
+ F32 mScore;
+
+ LODRequest(const LLVolumeParams& mesh_params, S32 lod)
+ : RequestStats(), mMeshParams(mesh_params), mLOD(lod), mScore(0.f)
+ {
+ }
+ };
+
+ struct CompareScoreGreater
+ {
+ bool operator()(const LODRequest& lhs, const LODRequest& rhs)
+ {
+ return lhs.mScore > rhs.mScore; // greatest = first
+ }
+ };
+
+ class UUIDBasedRequest : public RequestStats
+ {
+ public:
+ LLUUID mId;
+
+ UUIDBasedRequest(const LLUUID& id)
+ : RequestStats(), mId(id)
+ {
+ }
+
+ bool operator<(const UUIDBasedRequest& rhs) const
+ {
+ return mId < rhs.mId;
+ }
+ };
+
+ class LoadedMesh
+ {
+ public:
+ LLPointer<LLVolume> mVolume;
+ LLVolumeParams mMeshParams;
+ S32 mLOD;
+
+ LoadedMesh(LLVolume* volume, const LLVolumeParams& mesh_params, S32 lod)
+ : mVolume(volume), mMeshParams(mesh_params), mLOD(lod)
+ {
+ }
+
+ };
+
+ //set of requested skin info
+ std::deque<UUIDBasedRequest> mSkinRequests;
+
+ // list of completed skin info requests
+ std::deque<LLMeshSkinInfo*> mSkinInfoQ;
+
+ // list of skin info requests that have failed or are unavailaibe
+ std::deque<UUIDBasedRequest> mSkinUnavailableQ;
+
+ //set of requested decompositions
+ std::set<UUIDBasedRequest> mDecompositionRequests;
+
+ //set of requested physics shapes
+ std::set<UUIDBasedRequest> mPhysicsShapeRequests;
+
+ // list of completed Decomposition info requests
+ std::list<LLModel::Decomposition*> mDecompositionQ;
+
+ //queue of requested headers
+ std::queue<HeaderRequest> mHeaderReqQ;
+
+ //queue of requested LODs
+ std::queue<LODRequest> mLODReqQ;
+
+ //queue of unavailable LODs (either asset doesn't exist or asset doesn't have desired LOD)
+ std::deque<LODRequest> mUnavailableQ;
+
+ //queue of successfully loaded meshes
+ std::deque<LoadedMesh> mLoadedQ;
+
+ //map of pending header requests and currently desired LODs
+ typedef boost::unordered_map<LLUUID, std::vector<S32> > pending_lod_map;
+ pending_lod_map mPendingLOD;
+
+ // llcorehttp library interface objects.
+ LLCore::HttpStatus mHttpStatus;
+ LLCore::HttpRequest * mHttpRequest;
+ LLCore::HttpOptions::ptr_t mHttpOptions;
+ LLCore::HttpOptions::ptr_t mHttpLargeOptions;
+ LLCore::HttpHeaders::ptr_t mHttpHeaders;
+ LLCore::HttpRequest::policy_t mHttpPolicyClass;
+ LLCore::HttpRequest::policy_t mHttpLargePolicyClass;
+
+ typedef std::set<LLCore::HttpHandler::ptr_t> http_request_set;
+ http_request_set mHttpRequestSet; // Outstanding HTTP requests
+
+ std::string mGetMeshCapability;
+
+ LLMeshRepoThread();
+ ~LLMeshRepoThread();
+
+ virtual void run();
+
+ void lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
+ void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
+
+ bool fetchMeshHeader(const LLVolumeParams& mesh_params, bool can_retry = true);
+ bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, bool can_retry = true);
+ EMeshProcessingResult headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);
+ EMeshProcessingResult lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size);
+ bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
+ bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
+ EMeshProcessingResult physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
+ bool hasPhysicsShapeInHeader(const LLUUID& mesh_id);
+ bool hasSkinInfoInHeader(const LLUUID& mesh_id);
+ bool hasHeader(const LLUUID& mesh_id);
+
+ void notifyLoadedMeshes();
+ S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
+
+ void loadMeshSkinInfo(const LLUUID& mesh_id);
+ void loadMeshDecomposition(const LLUUID& mesh_id);
+ void loadMeshPhysicsShape(const LLUUID& mesh_id);
+
+ //send request for skin info, returns true if header info exists
+ // (should hold onto mesh_id and try again later if header info does not exist)
+ bool fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry = true);
+
+ //send request for decomposition, returns true if header info exists
+ // (should hold onto mesh_id and try again later if header info does not exist)
+ bool fetchMeshDecomposition(const LLUUID& mesh_id);
+
+ //send request for PhysicsShape, returns true if header info exists
+ // (should hold onto mesh_id and try again later if header info does not exist)
+ bool fetchMeshPhysicsShape(const LLUUID& mesh_id);
+
+ static void incActiveLODRequests();
+ static void decActiveLODRequests();
+ static void incActiveHeaderRequests();
+ static void decActiveHeaderRequests();
+
+ // Set the caps strings and preferred version for constructing
+ // mesh fetch URLs.
+ //
+ // Mutex: must be holding mMutex when called
+ void setGetMeshCap(const std::string & get_mesh);
+
+ // Mutex: acquires mMutex
+ void constructUrl(LLUUID mesh_id, std::string * url);
+
+private:
+ // Issue a GET request to a URL with 'Range' header using
+ // the correct policy class and other attributes. If an invalid
+ // handle is returned, the request failed and caller must retry
+ // or dispose of handler.
+ //
+ // Threads: Repo thread only
+ LLCore::HttpHandle getByteRange(const std::string & url,
+ size_t offset, size_t len,
+ const LLCore::HttpHandler::ptr_t &handler);
+};
+
+
+// Class whose instances represent a single upload-type request for
+// meshes: one fee query or one actual upload attempt. Yes, it creates
+// a unique thread for that single request. As it is 1:1, it can also
+// trivially serve as the HttpHandler object for request completion
+// notifications.
+
+class LLMeshUploadThread : public LLThread, public LLCore::HttpHandler
+{
+private:
+ S32 mMeshUploadTimeOut ; //maximum time in seconds to execute an uploading request.
+
+public:
+ class DecompRequest : public LLPhysicsDecomp::Request
+ {
+ public:
+ LLPointer<LLModel> mModel;
+ LLPointer<LLModel> mBaseModel;
+
+ LLMeshUploadThread* mThread;
+
+ DecompRequest(LLModel* mdl, LLModel* base_model, LLMeshUploadThread* thread);
+
+ S32 statusCallback(const char* status, S32 p1, S32 p2) { return 1; }
+ void completed();
+ };
+
+ LLPointer<DecompRequest> mFinalDecomp;
+ volatile bool mPhysicsComplete;
+
+ typedef std::map<LLPointer<LLModel>, std::vector<LLVector3> > hull_map;
+ hull_map mHullMap;
+
+ typedef std::vector<LLModelInstance> instance_list;
+ instance_list mInstanceList;
+
+ typedef std::map<LLPointer<LLModel>, instance_list> instance_map;
+ instance_map mInstance;
+
+ LLMutex* mMutex;
+ S32 mPendingUploads;
+ LLVector3 mOrigin;
+ bool mFinished;
+ bool mUploadTextures;
+ bool mUploadSkin;
+ bool mUploadJoints;
+ bool mLockScaleIfJointPosition;
+ volatile bool mDiscarded;
+
+ LLHost mHost;
+ std::string mWholeModelFeeCapability;
+ std::string mWholeModelUploadURL;
+
+ LLMeshUploadThread(instance_list& data, 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 = true,
+ LLHandle<LLWholeModelFeeObserver> fee_observer = (LLHandle<LLWholeModelFeeObserver>()),
+ LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
+ ~LLMeshUploadThread();
+
+ bool finished() const { return mFinished; }
+ virtual void run();
+ void preStart();
+ void discard() ;
+ bool isDiscarded() const;
+
+ void generateHulls();
+
+ void doWholeModelUpload();
+ void requestWholeModelFee();
+
+ void wholeModelToLLSD(LLSD& dest, bool include_textures);
+
+ void decomposeMeshMatrix(LLMatrix4& transformation,
+ LLVector3& result_pos,
+ LLQuaternion& result_rot,
+ LLVector3& result_scale);
+
+ void setFeeObserverHandle(LLHandle<LLWholeModelFeeObserver> observer_handle) { mFeeObserverHandle = observer_handle; }
+ void setUploadObserverHandle(LLHandle<LLWholeModelUploadObserver> observer_handle) { mUploadObserverHandle = observer_handle; }
+
+ // Inherited from LLCore::HttpHandler
+ virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
+
+ LLViewerFetchedTexture* FindViewerTexture(const LLImportMaterial& material);
+
+private:
+ LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle;
+ LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle;
+
+ bool mDoUpload; // if false only model data will be requested, otherwise the model will be uploaded
+ LLSD mModelData;
+
+ // llcorehttp library interface objects.
+ LLCore::HttpStatus mHttpStatus;
+ LLCore::HttpRequest * mHttpRequest;
+ LLCore::HttpOptions::ptr_t mHttpOptions;
+ LLCore::HttpHeaders::ptr_t mHttpHeaders;
+ LLCore::HttpRequest::policy_t mHttpPolicyClass;
+};
+
+// Params related to streaming cost, render cost, and scene complexity tracking.
+class LLMeshCostData
+{
+public:
+ LLMeshCostData();
+
+ bool init(const LLMeshHeader& header);
+
+ // Size for given LOD
+ S32 getSizeByLOD(S32 lod);
+
+ // Sum of all LOD sizes.
+ S32 getSizeTotal();
+
+ // Estimated triangle counts for the given LOD.
+ F32 getEstTrisByLOD(S32 lod);
+
+ // Estimated triangle counts for the largest LOD. Typically this
+ // is also the "high" LOD, but not necessarily.
+ F32 getEstTrisMax();
+
+ // Triangle count as computed by original streaming cost
+ // formula. Triangles in each LOD are weighted based on how
+ // frequently they will be seen.
+ // This was called "unscaled_value" in the original getStreamingCost() functions.
+ F32 getRadiusWeightedTris(F32 radius);
+
+ // Triangle count used by triangle-based cost formula. Based on
+ // triangles in highest LOD plus potentially partial charges for
+ // lower LODs depending on complexity.
+ F32 getEstTrisForStreamingCost();
+
+ // Streaming cost. This should match the server-side calculation
+ // for the corresponding volume.
+ F32 getRadiusBasedStreamingCost(F32 radius);
+
+ // New streaming cost formula, currently only used for animated objects.
+ F32 getTriangleBasedStreamingCost();
+
+private:
+ // From the "size" field of the mesh header. LOD 0=lowest, 3=highest.
+ std::array<S32,4> mSizeByLOD;
+
+ // Estimated triangle counts derived from the LOD sizes. LOD 0=lowest, 3=highest.
+ std::array<F32,4> mEstTrisByLOD;
+};
+
+class LLMeshRepository
+{
+public:
+
+ //metrics
+ static U32 sBytesReceived;
+ static U32 sMeshRequestCount; // Total request count, http or cached, all component types
+ static U32 sHTTPRequestCount; // Http GETs issued (not large)
+ static U32 sHTTPLargeRequestCount; // Http GETs issued for large requests
+ static U32 sHTTPRetryCount; // Total request retries whether successful or failed
+ static U32 sHTTPErrorCount; // Requests ending in error
+ static U32 sLODPending;
+ static U32 sLODProcessing;
+ static U32 sCacheBytesRead;
+ static U32 sCacheBytesWritten;
+ static U32 sCacheBytesHeaders;
+ static U32 sCacheBytesSkins;
+ static U32 sCacheBytesDecomps;
+ static U32 sCacheReads;
+ static U32 sCacheWrites;
+ static U32 sMaxLockHoldoffs; // Maximum sequential locking failures
+
+ static LLDeadmanTimer sQuiescentTimer; // Time-to-complete-mesh-downloads after significant events
+
+ // Estimated triangle count of the largest LOD
+ F32 getEstTrianglesMax(LLUUID mesh_id);
+ F32 getEstTrianglesStreamingCost(LLUUID mesh_id);
+ F32 getStreamingCostLegacy(LLUUID mesh_id, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
+ static F32 getStreamingCostLegacy(LLMeshHeader& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL);
+ bool getCostData(LLUUID mesh_id, LLMeshCostData& data);
+ bool getCostData(LLMeshHeader& header, LLMeshCostData& data);
+
+ LLMeshRepository();
+
+ void init();
+ void shutdown();
+ S32 update();
+
+ void unregisterMesh(LLVOVolume* volume);
+ //mesh management functions
+ S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0, S32 last_lod = -1);
+
+ void notifyLoadedMeshes();
+ void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume);
+ void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod);
+ void notifySkinInfoReceived(LLMeshSkinInfo* info);
+ void notifySkinInfoUnavailable(const LLUUID& info);
+ void notifyDecompositionReceived(LLModel::Decomposition* info);
+
+ S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
+ static S32 getActualMeshLOD(LLMeshHeader& header, S32 lod);
+ const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj = nullptr);
+ LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
+ void fetchPhysicsShape(const LLUUID& mesh_id);
+ bool hasPhysicsShape(const LLUUID& mesh_id);
+ bool hasSkinInfo(const LLUUID& mesh_id);
+ bool hasHeader(const LLUUID& mesh_id);
+
+ void buildHull(const LLVolumeParams& params, S32 detail);
+ void buildPhysicsMesh(LLModel::Decomposition& decomp);
+
+ bool meshUploadEnabled();
+ bool meshRezEnabled();
+
+ void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
+ bool upload_skin, bool upload_joints, bool lock_scale_if_joint_position,
+ std::string upload_url, bool do_upload = true,
+ LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()),
+ LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
+
+ S32 getMeshSize(const LLUUID& mesh_id, S32 lod);
+
+ // Quiescent timer management, main thread only.
+ static void metricsStart();
+ static void metricsStop();
+ static void metricsProgress(unsigned int count);
+ static void metricsUpdate();
+
+ typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > mesh_load_map;
+ mesh_load_map mLoadingMeshes[4];
+
+ typedef std::unordered_map<LLUUID, LLPointer<LLMeshSkinInfo>> skin_map;
+ skin_map mSkinMap;
+
+ typedef std::map<LLUUID, LLModel::Decomposition*> decomposition_map;
+ decomposition_map mDecompositionMap;
+
+ LLMutex* mMeshMutex;
+
+ std::vector<LLMeshRepoThread::LODRequest> mPendingRequests;
+
+ //list of mesh ids awaiting skin info
+ typedef boost::unordered_map<LLUUID, std::vector<LLVOVolume*> > skin_load_map;
+ skin_load_map mLoadingSkins;
+
+ //list of mesh ids that need to send skin info fetch requests
+ std::queue<LLUUID> mPendingSkinRequests;
+
+ //list of mesh ids awaiting decompositions
+ std::set<LLUUID> mLoadingDecompositions;
+
+ //list of mesh ids that need to send decomposition fetch requests
+ std::queue<LLUUID> mPendingDecompositionRequests;
+
+ //list of mesh ids awaiting physics shapes
+ std::set<LLUUID> mLoadingPhysicsShapes;
+
+ //list of mesh ids that need to send physics shape fetch requests
+ std::queue<LLUUID> mPendingPhysicsShapeRequests;
+
+ U32 mMeshThreadCount;
+
+ LLMeshRepoThread* mThread;
+ std::vector<LLMeshUploadThread*> mUploads;
+ std::vector<LLMeshUploadThread*> mUploadWaitList;
+
+ LLPhysicsDecomp* mDecompThread;
+
+ LLFrameTimer mSkinInfoCullTimer;
+
+ class inventory_data
+ {
+ public:
+ LLSD mPostData;
+ LLSD mResponse;
+
+ inventory_data(const LLSD& data, const LLSD& content)
+ : mPostData(data), mResponse(content)
+ {
+ }
+ };
+
+ std::queue<inventory_data> mInventoryQ;
+
+ std::queue<LLSD> mUploadErrorQ;
+
+ void uploadError(LLSD& args);
+ void updateInventory(inventory_data data);
+};
+
+extern LLMeshRepository gMeshRepo;
+
+const F32 ANIMATED_OBJECT_BASE_COST = 15.0f;
+const F32 ANIMATED_OBJECT_COST_PER_KTRI = 1.5f;
+
+#endif
+