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.h563
1 files changed, 563 insertions, 0 deletions
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
new file mode 100644
index 0000000000..f237c3a60e
--- /dev/null
+++ b/indra/newview/llmeshrepository.h
@@ -0,0 +1,563 @@
+/**
+ * @file llmeshrepository.h
+ * @brief Client-side repository of mesh assets.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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 "llassettype.h"
+#include "llmodel.h"
+#include "lluuid.h"
+#include "llviewertexture.h"
+#include "llvolume.h"
+
+#define LLCONVEXDECOMPINTER_STATIC 1
+
+#include "llconvexdecomposition.h"
+
+class LLVOVolume;
+class LLMeshResponder;
+class LLCurlRequest;
+class LLMutex;
+class LLCondition;
+class LLVFS;
+class LLMeshRepository;
+
+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 LLImportMaterial
+{
+public:
+ LLPointer<LLViewerFetchedTexture> mDiffuseMap;
+ std::string mDiffuseMapFilename;
+ std::string mDiffuseMapLabel;
+ LLColor4 mDiffuseColor;
+ bool mFullbright;
+
+ bool operator<(const LLImportMaterial &params) const;
+
+ LLImportMaterial()
+ : mFullbright(false)
+ {
+ mDiffuseColor.set(1,1,1,1);
+ }
+
+ LLImportMaterial(LLSD& data);
+
+ LLSD asLLSD();
+};
+
+class LLModelInstance
+{
+public:
+ LLPointer<LLModel> mModel;
+ LLPointer<LLModel> mLOD[5];
+
+ std::string mLabel;
+
+ LLUUID mMeshID;
+ S32 mLocalMeshID;
+
+ LLMatrix4 mTransform;
+ std::vector<LLImportMaterial> mMaterial;
+
+ LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::vector<LLImportMaterial>& materials)
+ : mModel(model), mLabel(label), mTransform(transform), mMaterial(materials)
+ {
+ mLocalMeshID = -1;
+ }
+
+ LLModelInstance(LLSD& data);
+
+ LLSD asLLSD();
+};
+
+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);
+ 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 LLMeshRepoThread : public LLThread
+{
+public:
+
+ static S32 sActiveHeaderRequests;
+ static S32 sActiveLODRequests;
+ static U32 sMaxConcurrentRequests;
+
+ LLCurlRequest* mCurlRequest;
+ LLMutex* mMutex;
+ LLMutex* mHeaderMutex;
+ LLCondition* mSignal;
+
+ bool mWaiting;
+
+ //map of known mesh headers
+ typedef std::map<LLUUID, LLSD> mesh_header_map;
+ mesh_header_map mMeshHeader;
+
+ std::map<LLUUID, U32> mMeshHeaderSize;
+ std::map<LLUUID, U32> mMeshResourceCost;
+
+ class HeaderRequest
+ {
+ public:
+ const LLVolumeParams mMeshParams;
+
+ HeaderRequest(const LLVolumeParams& mesh_params)
+ : mMeshParams(mesh_params)
+ {
+ }
+
+ bool operator<(const HeaderRequest& rhs) const
+ {
+ return mMeshParams < rhs.mMeshParams;
+ }
+ };
+
+ class LODRequest
+ {
+ public:
+ LLVolumeParams mMeshParams;
+ S32 mLOD;
+ F32 mScore;
+
+ LODRequest(const LLVolumeParams& mesh_params, S32 lod)
+ : 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 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::set<LLUUID> mSkinRequests;
+
+ //queue of completed skin info requests
+ std::queue<LLMeshSkinInfo> mSkinInfoQ;
+
+ //set of requested decompositions
+ std::set<LLUUID> mDecompositionRequests;
+
+ //set of requested physics shapes
+ std::set<LLUUID> mPhysicsShapeRequests;
+
+ //queue of completed Decomposition info requests
+ std::queue<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::queue<LODRequest> mUnavailableQ;
+
+ //queue of successfully loaded meshes
+ std::queue<LoadedMesh> mLoadedQ;
+
+ //map of pending header requests and currently desired LODs
+ typedef std::map<LLVolumeParams, std::vector<S32> > pending_lod_map;
+ pending_lod_map mPendingLOD;
+
+ static std::string constructUrl(LLUUID mesh_id);
+
+ LLMeshRepoThread();
+ ~LLMeshRepoThread();
+
+ virtual void run();
+
+ void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
+ bool fetchMeshHeader(const LLVolumeParams& mesh_params);
+ bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
+ bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);
+ bool 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);
+ bool physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
+ LLSD& getMeshHeader(const LLUUID& mesh_id);
+
+ void notifyLoadedMeshes();
+ S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
+ U32 getResourceCost(const LLUUID& mesh_params);
+
+ 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);
+
+ //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);
+
+
+};
+
+class LLMeshUploadThread : public LLThread
+{
+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;
+ 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;
+ LLCurlRequest* mCurlRequest;
+ S32 mPendingConfirmations;
+ S32 mPendingUploads;
+ S32 mPendingCost;
+ LLVector3 mOrigin;
+ bool mFinished;
+ bool mUploadTextures;
+ bool mUploadSkin;
+ bool mUploadJoints;
+ BOOL mDiscarded ;
+
+ LLHost mHost;
+ std::string mWholeModelFeeCapability;
+ std::string mWholeModelUploadURL;
+
+ std::queue<LLMeshUploadData> mUploadQ;
+ std::queue<LLMeshUploadData> mConfirmedQ;
+ std::queue<LLModelInstance> mInstanceQ;
+
+ std::queue<LLTextureUploadData> mTextureQ;
+ std::queue<LLTextureUploadData> mConfirmedTextureQ;
+
+ std::map<LLViewerFetchedTexture*, LLTextureUploadData> mTextureMap;
+
+ LLMeshUploadThread(instance_list& data, LLVector3& scale, bool upload_textures,
+ bool upload_skin, bool upload_joints);
+ ~LLMeshUploadThread();
+
+ void uploadTexture(LLTextureUploadData& data);
+ void doUploadTexture(LLTextureUploadData& data);
+ void priceResult(LLTextureUploadData& data, const LLSD& content);
+ void onTextureUploaded(LLTextureUploadData& data);
+
+ void uploadModel(LLMeshUploadData& data);
+ void doUploadModel(LLMeshUploadData& data);
+ void onModelUploaded(LLMeshUploadData& data);
+ void createObjects(LLMeshUploadData& data);
+ LLSD createObject(LLModelInstance& instance);
+ void priceResult(LLMeshUploadData& data, const LLSD& content);
+
+ bool finished() { return mFinished; }
+ virtual void run();
+ void preStart();
+ void discard() ;
+ BOOL isDiscarded();
+
+ void doWholeModelUpload();
+
+ void wholeModelToLLSD(LLSD& dest, bool include_textures);
+
+ void decomposeMeshMatrix(LLMatrix4& transformation,
+ LLVector3& result_pos,
+ LLQuaternion& result_rot,
+ LLVector3& result_scale);
+};
+
+class LLMeshRepository
+{
+public:
+
+ //metrics
+ static U32 sBytesReceived;
+ static U32 sHTTPRequestCount;
+ static U32 sHTTPRetryCount;
+ static U32 sCacheBytesRead;
+ static U32 sCacheBytesWritten;
+ static U32 sPeakKbps;
+
+ static F32 getStreamingCost(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1);
+
+ LLMeshRepository();
+
+ void init();
+ void shutdown();
+ S32 update() ;
+
+ //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 notifyDecompositionReceived(LLModel::Decomposition* info);
+
+ S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
+ static S32 getActualMeshLOD(LLSD& header, S32 lod);
+ U32 calcResourceCost(LLSD& header);
+ U32 getResourceCost(const LLUUID& mesh_params);
+ const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj);
+ LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
+ void fetchPhysicsShape(const LLUUID& mesh_id);
+ bool hasPhysicsShape(const LLUUID& mesh_id);
+
+ void buildHull(const LLVolumeParams& params, S32 detail);
+ void buildPhysicsMesh(LLModel::Decomposition& decomp);
+
+ bool meshUploadEnabled();
+ bool meshRezEnabled();
+
+
+ LLSD& getMeshHeader(const LLUUID& mesh_id);
+
+ void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
+ bool upload_skin, bool upload_joints);
+
+ S32 getMeshSize(const LLUUID& mesh_id, S32 lod);
+
+ typedef std::map<LLVolumeParams, std::set<LLUUID> > mesh_load_map;
+ mesh_load_map mLoadingMeshes[4];
+
+ typedef std::map<LLUUID, 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 std::map<LLUUID, std::set<LLUUID> > 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;
+
+ void cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header);
+
+ LLMeshRepoThread* mThread;
+ std::vector<LLMeshUploadThread*> mUploads;
+ std::vector<LLMeshUploadThread*> mUploadWaitList;
+
+ LLPhysicsDecomp* mDecompThread;
+
+ 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);
+
+ std::string mGetMeshCapability;
+
+};
+
+extern LLMeshRepository gMeshRepo;
+
+#endif
+