PageRenderTime 65ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/newview/llmeshrepository.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2581 lines | 2011 code | 444 blank | 126 comment | 336 complexity | 8ee4dde486a2ada7ec4f722c201b0648 MD5 | raw file
Possible License(s): LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. /**
  2. * @file llmeshrepository.cpp
  3. * @brief Mesh repository implementation.
  4. *
  5. * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "apr_pools.h"
  28. #include "apr_dso.h"
  29. #include "llhttpstatuscodes.h"
  30. #include "llmeshrepository.h"
  31. #include "llagent.h"
  32. #include "llappviewer.h"
  33. #include "llbufferstream.h"
  34. #include "llcallbacklist.h"
  35. #include "llcurl.h"
  36. #include "lldatapacker.h"
  37. #include "llfloatermodelpreview.h"
  38. #include "llfloaterperms.h"
  39. #include "lleconomy.h"
  40. #include "llimagej2c.h"
  41. #include "llhost.h"
  42. #include "llnotificationsutil.h"
  43. #include "llsd.h"
  44. #include "llsdutil_math.h"
  45. #include "llsdserialize.h"
  46. #include "llthread.h"
  47. #include "llvfile.h"
  48. #include "llviewercontrol.h"
  49. #include "llviewerinventory.h"
  50. #include "llviewermenufile.h"
  51. #include "llviewerobjectlist.h"
  52. #include "llviewerregion.h"
  53. #include "llviewertexturelist.h"
  54. #include "llvolume.h"
  55. #include "llvolumemgr.h"
  56. #include "llvovolume.h"
  57. #include "llworld.h"
  58. #include "material_codes.h"
  59. #include "pipeline.h"
  60. #include "llinventorymodel.h"
  61. #include "llfoldertype.h"
  62. #include "llviewerparcelmgr.h"
  63. #include "lluploadfloaterobservers.h"
  64. #include "boost/lexical_cast.hpp"
  65. #ifndef LL_WINDOWS
  66. #include "netdb.h"
  67. #endif
  68. #include <queue>
  69. LLMeshRepository gMeshRepo;
  70. const U32 MAX_MESH_REQUESTS_PER_SECOND = 100;
  71. // Maximum mesh version to support. Three least significant digits are reserved for the minor version,
  72. // with major version changes indicating a format change that is not backwards compatible and should not
  73. // be parsed by viewers that don't specifically support that version. For example, if the integer "1" is
  74. // present, the version is 0.001. A viewer that can parse version 0.001 can also parse versions up to 0.999,
  75. // but not 1.0 (integer 1000).
  76. // See wiki at https://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format
  77. const S32 MAX_MESH_VERSION = 999;
  78. U32 LLMeshRepository::sBytesReceived = 0;
  79. U32 LLMeshRepository::sHTTPRequestCount = 0;
  80. U32 LLMeshRepository::sHTTPRetryCount = 0;
  81. U32 LLMeshRepository::sCacheBytesRead = 0;
  82. U32 LLMeshRepository::sCacheBytesWritten = 0;
  83. U32 LLMeshRepository::sPeakKbps = 0;
  84. const U32 MAX_TEXTURE_UPLOAD_RETRIES = 5;
  85. static S32 dump_num = 0;
  86. std::string make_dump_name(std::string prefix, S32 num)
  87. {
  88. return prefix + boost::lexical_cast<std::string>(num) + std::string(".xml");
  89. }
  90. void dump_llsd_to_file(const LLSD& content, std::string filename);
  91. LLSD llsd_from_file(std::string filename);
  92. std::string header_lod[] =
  93. {
  94. "lowest_lod",
  95. "low_lod",
  96. "medium_lod",
  97. "high_lod"
  98. };
  99. //get the number of bytes resident in memory for given volume
  100. U32 get_volume_memory_size(const LLVolume* volume)
  101. {
  102. U32 indices = 0;
  103. U32 vertices = 0;
  104. for (U32 i = 0; i < volume->getNumVolumeFaces(); ++i)
  105. {
  106. const LLVolumeFace& face = volume->getVolumeFace(i);
  107. indices += face.mNumIndices;
  108. vertices += face.mNumVertices;
  109. }
  110. return indices*2+vertices*11+sizeof(LLVolume)+sizeof(LLVolumeFace)*volume->getNumVolumeFaces();
  111. }
  112. void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res, F32 scale = 1.f)
  113. {
  114. res.mPositions.clear();
  115. res.mNormals.clear();
  116. const F32* v = mesh.mVertexBase;
  117. if (mesh.mIndexType == LLCDMeshData::INT_16)
  118. {
  119. U16* idx = (U16*) mesh.mIndexBase;
  120. for (S32 j = 0; j < mesh.mNumTriangles; ++j)
  121. {
  122. F32* mp0 = (F32*) ((U8*)v+idx[0]*mesh.mVertexStrideBytes);
  123. F32* mp1 = (F32*) ((U8*)v+idx[1]*mesh.mVertexStrideBytes);
  124. F32* mp2 = (F32*) ((U8*)v+idx[2]*mesh.mVertexStrideBytes);
  125. idx = (U16*) (((U8*)idx)+mesh.mIndexStrideBytes);
  126. LLVector3 v0(mp0);
  127. LLVector3 v1(mp1);
  128. LLVector3 v2(mp2);
  129. LLVector3 n = (v1-v0)%(v2-v0);
  130. n.normalize();
  131. res.mPositions.push_back(v0*scale);
  132. res.mPositions.push_back(v1*scale);
  133. res.mPositions.push_back(v2*scale);
  134. res.mNormals.push_back(n);
  135. res.mNormals.push_back(n);
  136. res.mNormals.push_back(n);
  137. }
  138. }
  139. else
  140. {
  141. U32* idx = (U32*) mesh.mIndexBase;
  142. for (S32 j = 0; j < mesh.mNumTriangles; ++j)
  143. {
  144. F32* mp0 = (F32*) ((U8*)v+idx[0]*mesh.mVertexStrideBytes);
  145. F32* mp1 = (F32*) ((U8*)v+idx[1]*mesh.mVertexStrideBytes);
  146. F32* mp2 = (F32*) ((U8*)v+idx[2]*mesh.mVertexStrideBytes);
  147. idx = (U32*) (((U8*)idx)+mesh.mIndexStrideBytes);
  148. LLVector3 v0(mp0);
  149. LLVector3 v1(mp1);
  150. LLVector3 v2(mp2);
  151. LLVector3 n = (v1-v0)%(v2-v0);
  152. n.normalize();
  153. res.mPositions.push_back(v0*scale);
  154. res.mPositions.push_back(v1*scale);
  155. res.mPositions.push_back(v2*scale);
  156. res.mNormals.push_back(n);
  157. res.mNormals.push_back(n);
  158. res.mNormals.push_back(n);
  159. }
  160. }
  161. }
  162. S32 LLMeshRepoThread::sActiveHeaderRequests = 0;
  163. S32 LLMeshRepoThread::sActiveLODRequests = 0;
  164. U32 LLMeshRepoThread::sMaxConcurrentRequests = 1;
  165. class LLMeshHeaderResponder : public LLCurl::Responder
  166. {
  167. public:
  168. LLVolumeParams mMeshParams;
  169. LLMeshHeaderResponder(const LLVolumeParams& mesh_params)
  170. : mMeshParams(mesh_params)
  171. {
  172. }
  173. virtual void completedRaw(U32 status, const std::string& reason,
  174. const LLChannelDescriptors& channels,
  175. const LLIOPipe::buffer_ptr_t& buffer);
  176. };
  177. class LLMeshLODResponder : public LLCurl::Responder
  178. {
  179. public:
  180. LLVolumeParams mMeshParams;
  181. S32 mLOD;
  182. U32 mRequestedBytes;
  183. U32 mOffset;
  184. LLMeshLODResponder(const LLVolumeParams& mesh_params, S32 lod, U32 offset, U32 requested_bytes)
  185. : mMeshParams(mesh_params), mLOD(lod), mOffset(offset), mRequestedBytes(requested_bytes)
  186. {
  187. }
  188. virtual void completedRaw(U32 status, const std::string& reason,
  189. const LLChannelDescriptors& channels,
  190. const LLIOPipe::buffer_ptr_t& buffer);
  191. };
  192. class LLMeshSkinInfoResponder : public LLCurl::Responder
  193. {
  194. public:
  195. LLUUID mMeshID;
  196. U32 mRequestedBytes;
  197. U32 mOffset;
  198. LLMeshSkinInfoResponder(const LLUUID& id, U32 offset, U32 size)
  199. : mMeshID(id), mRequestedBytes(size), mOffset(offset)
  200. {
  201. }
  202. virtual void completedRaw(U32 status, const std::string& reason,
  203. const LLChannelDescriptors& channels,
  204. const LLIOPipe::buffer_ptr_t& buffer);
  205. };
  206. class LLMeshDecompositionResponder : public LLCurl::Responder
  207. {
  208. public:
  209. LLUUID mMeshID;
  210. U32 mRequestedBytes;
  211. U32 mOffset;
  212. LLMeshDecompositionResponder(const LLUUID& id, U32 offset, U32 size)
  213. : mMeshID(id), mRequestedBytes(size), mOffset(offset)
  214. {
  215. }
  216. virtual void completedRaw(U32 status, const std::string& reason,
  217. const LLChannelDescriptors& channels,
  218. const LLIOPipe::buffer_ptr_t& buffer);
  219. };
  220. class LLMeshPhysicsShapeResponder : public LLCurl::Responder
  221. {
  222. public:
  223. LLUUID mMeshID;
  224. U32 mRequestedBytes;
  225. U32 mOffset;
  226. LLMeshPhysicsShapeResponder(const LLUUID& id, U32 offset, U32 size)
  227. : mMeshID(id), mRequestedBytes(size), mOffset(offset)
  228. {
  229. }
  230. virtual void completedRaw(U32 status, const std::string& reason,
  231. const LLChannelDescriptors& channels,
  232. const LLIOPipe::buffer_ptr_t& buffer);
  233. };
  234. void log_upload_error(S32 status, const LLSD& content, std::string stage, std::string model_name)
  235. {
  236. // Add notification popup.
  237. LLSD args;
  238. std::string message = content["error"]["message"];
  239. std::string identifier = content["error"]["identifier"];
  240. args["MESSAGE"] = message;
  241. args["IDENTIFIER"] = identifier;
  242. args["LABEL"] = model_name;
  243. gMeshRepo.uploadError(args);
  244. // Log details.
  245. llwarns << "stage: " << stage << " http status: " << status << llendl;
  246. if (content.has("error"))
  247. {
  248. const LLSD& err = content["error"];
  249. llwarns << "err: " << err << llendl;
  250. llwarns << "mesh upload failed, stage '" << stage
  251. << "' error '" << err["error"].asString()
  252. << "', message '" << err["message"].asString()
  253. << "', id '" << err["identifier"].asString()
  254. << "'" << llendl;
  255. if (err.has("errors"))
  256. {
  257. S32 error_num = 0;
  258. const LLSD& err_list = err["errors"];
  259. for (LLSD::array_const_iterator it = err_list.beginArray();
  260. it != err_list.endArray();
  261. ++it)
  262. {
  263. const LLSD& err_entry = *it;
  264. llwarns << "error[" << error_num << "]:" << llendl;
  265. for (LLSD::map_const_iterator map_it = err_entry.beginMap();
  266. map_it != err_entry.endMap();
  267. ++map_it)
  268. {
  269. llwarns << "\t" << map_it->first << ": "
  270. << map_it->second << llendl;
  271. }
  272. error_num++;
  273. }
  274. }
  275. }
  276. else
  277. {
  278. llwarns << "bad mesh, no error information available" << llendl;
  279. }
  280. }
  281. class LLWholeModelFeeResponder: public LLCurl::Responder
  282. {
  283. LLMeshUploadThread* mThread;
  284. LLSD mModelData;
  285. LLHandle<LLWholeModelFeeObserver> mObserverHandle;
  286. public:
  287. LLWholeModelFeeResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelFeeObserver> observer_handle):
  288. mThread(thread),
  289. mModelData(model_data),
  290. mObserverHandle(observer_handle)
  291. {
  292. }
  293. virtual void completed(U32 status,
  294. const std::string& reason,
  295. const LLSD& content)
  296. {
  297. LLSD cc = content;
  298. if (gSavedSettings.getS32("MeshUploadFakeErrors")&1)
  299. {
  300. cc = llsd_from_file("fake_upload_error.xml");
  301. }
  302. mThread->mPendingUploads--;
  303. dump_llsd_to_file(cc,make_dump_name("whole_model_fee_response_",dump_num));
  304. LLWholeModelFeeObserver* observer = mObserverHandle.get();
  305. if (isGoodStatus(status) &&
  306. cc["state"].asString() == "upload")
  307. {
  308. mThread->mWholeModelUploadURL = cc["uploader"].asString();
  309. if (observer)
  310. {
  311. cc["data"]["upload_price"] = cc["upload_price"];
  312. observer->onModelPhysicsFeeReceived(cc["data"], mThread->mWholeModelUploadURL);
  313. }
  314. }
  315. else
  316. {
  317. llwarns << "fee request failed" << llendl;
  318. log_upload_error(status,cc,"fee",mModelData["name"]);
  319. mThread->mWholeModelUploadURL = "";
  320. if (observer)
  321. {
  322. observer->setModelPhysicsFeeErrorStatus(status, reason);
  323. }
  324. }
  325. }
  326. };
  327. class LLWholeModelUploadResponder: public LLCurl::Responder
  328. {
  329. LLMeshUploadThread* mThread;
  330. LLSD mModelData;
  331. LLHandle<LLWholeModelUploadObserver> mObserverHandle;
  332. public:
  333. LLWholeModelUploadResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelUploadObserver> observer_handle):
  334. mThread(thread),
  335. mModelData(model_data),
  336. mObserverHandle(observer_handle)
  337. {
  338. }
  339. virtual void completed(U32 status,
  340. const std::string& reason,
  341. const LLSD& content)
  342. {
  343. LLSD cc = content;
  344. if (gSavedSettings.getS32("MeshUploadFakeErrors")&2)
  345. {
  346. cc = llsd_from_file("fake_upload_error.xml");
  347. }
  348. mThread->mPendingUploads--;
  349. dump_llsd_to_file(cc,make_dump_name("whole_model_upload_response_",dump_num));
  350. LLWholeModelUploadObserver* observer = mObserverHandle.get();
  351. // requested "mesh" asset type isn't actually the type
  352. // of the resultant object, fix it up here.
  353. if (isGoodStatus(status) &&
  354. cc["state"].asString() == "complete")
  355. {
  356. mModelData["asset_type"] = "object";
  357. gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mModelData,cc));
  358. if (observer)
  359. {
  360. doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadSuccess, observer));
  361. }
  362. }
  363. else
  364. {
  365. llwarns << "upload failed" << llendl;
  366. std::string model_name = mModelData["name"].asString();
  367. log_upload_error(status,cc,"upload",model_name);
  368. if (observer)
  369. {
  370. doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadFailure, observer));
  371. }
  372. }
  373. }
  374. };
  375. LLMeshRepoThread::LLMeshRepoThread()
  376. : LLThread("mesh repo")
  377. {
  378. mWaiting = false;
  379. mMutex = new LLMutex(NULL);
  380. mHeaderMutex = new LLMutex(NULL);
  381. mSignal = new LLCondition(NULL);
  382. }
  383. LLMeshRepoThread::~LLMeshRepoThread()
  384. {
  385. delete mMutex;
  386. mMutex = NULL;
  387. delete mHeaderMutex;
  388. mHeaderMutex = NULL;
  389. delete mSignal;
  390. mSignal = NULL;
  391. }
  392. void LLMeshRepoThread::run()
  393. {
  394. mCurlRequest = new LLCurlRequest();
  395. LLCDResult res = LLConvexDecomposition::initThread();
  396. if (res != LLCD_OK)
  397. {
  398. llwarns << "convex decomposition unable to be loaded" << llendl;
  399. }
  400. while (!LLApp::isQuitting())
  401. {
  402. mWaiting = true;
  403. mSignal->wait();
  404. mWaiting = false;
  405. if (!LLApp::isQuitting())
  406. {
  407. static U32 count = 0;
  408. static F32 last_hundred = gFrameTimeSeconds;
  409. if (gFrameTimeSeconds - last_hundred > 1.f)
  410. { //a second has gone by, clear count
  411. last_hundred = gFrameTimeSeconds;
  412. count = 0;
  413. }
  414. // NOTE: throttling intentionally favors LOD requests over header requests
  415. while (!mLODReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveLODRequests < sMaxConcurrentRequests)
  416. {
  417. {
  418. mMutex->lock();
  419. LODRequest req = mLODReqQ.front();
  420. mLODReqQ.pop();
  421. mMutex->unlock();
  422. if (!fetchMeshLOD(req.mMeshParams, req.mLOD, count))//failed, resubmit
  423. {
  424. mMutex->lock();
  425. mLODReqQ.push(req) ;
  426. mMutex->unlock();
  427. }
  428. }
  429. }
  430. while (!mHeaderReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveHeaderRequests < sMaxConcurrentRequests)
  431. {
  432. {
  433. mMutex->lock();
  434. HeaderRequest req = mHeaderReqQ.front();
  435. mHeaderReqQ.pop();
  436. mMutex->unlock();
  437. if (!fetchMeshHeader(req.mMeshParams, count))//failed, resubmit
  438. {
  439. mMutex->lock();
  440. mHeaderReqQ.push(req) ;
  441. mMutex->unlock();
  442. }
  443. }
  444. }
  445. { //mSkinRequests is protected by mSignal
  446. std::set<LLUUID> incomplete;
  447. for (std::set<LLUUID>::iterator iter = mSkinRequests.begin(); iter != mSkinRequests.end(); ++iter)
  448. {
  449. LLUUID mesh_id = *iter;
  450. if (!fetchMeshSkinInfo(mesh_id))
  451. {
  452. incomplete.insert(mesh_id);
  453. }
  454. }
  455. mSkinRequests = incomplete;
  456. }
  457. { //mDecompositionRequests is protected by mSignal
  458. std::set<LLUUID> incomplete;
  459. for (std::set<LLUUID>::iterator iter = mDecompositionRequests.begin(); iter != mDecompositionRequests.end(); ++iter)
  460. {
  461. LLUUID mesh_id = *iter;
  462. if (!fetchMeshDecomposition(mesh_id))
  463. {
  464. incomplete.insert(mesh_id);
  465. }
  466. }
  467. mDecompositionRequests = incomplete;
  468. }
  469. { //mPhysicsShapeRequests is protected by mSignal
  470. std::set<LLUUID> incomplete;
  471. for (std::set<LLUUID>::iterator iter = mPhysicsShapeRequests.begin(); iter != mPhysicsShapeRequests.end(); ++iter)
  472. {
  473. LLUUID mesh_id = *iter;
  474. if (!fetchMeshPhysicsShape(mesh_id))
  475. {
  476. incomplete.insert(mesh_id);
  477. }
  478. }
  479. mPhysicsShapeRequests = incomplete;
  480. }
  481. mCurlRequest->process();
  482. }
  483. }
  484. if (mSignal->isLocked())
  485. { //make sure to let go of the mutex associated with the given signal before shutting down
  486. mSignal->unlock();
  487. }
  488. res = LLConvexDecomposition::quitThread();
  489. if (res != LLCD_OK)
  490. {
  491. llwarns << "convex decomposition unable to be quit" << llendl;
  492. }
  493. delete mCurlRequest;
  494. mCurlRequest = NULL;
  495. }
  496. void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id)
  497. { //protected by mSignal, no locking needed here
  498. mSkinRequests.insert(mesh_id);
  499. }
  500. void LLMeshRepoThread::loadMeshDecomposition(const LLUUID& mesh_id)
  501. { //protected by mSignal, no locking needed here
  502. mDecompositionRequests.insert(mesh_id);
  503. }
  504. void LLMeshRepoThread::loadMeshPhysicsShape(const LLUUID& mesh_id)
  505. { //protected by mSignal, no locking needed here
  506. mPhysicsShapeRequests.insert(mesh_id);
  507. }
  508. void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
  509. { //protected by mSignal, no locking needed here
  510. mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID());
  511. if (iter != mMeshHeader.end())
  512. { //if we have the header, request LOD byte range
  513. LODRequest req(mesh_params, lod);
  514. {
  515. LLMutexLock lock(mMutex);
  516. mLODReqQ.push(req);
  517. }
  518. }
  519. else
  520. {
  521. HeaderRequest req(mesh_params);
  522. pending_lod_map::iterator pending = mPendingLOD.find(mesh_params);
  523. if (pending != mPendingLOD.end())
  524. { //append this lod request to existing header request
  525. pending->second.push_back(lod);
  526. llassert(pending->second.size() <= LLModel::NUM_LODS)
  527. }
  528. else
  529. { //if no header request is pending, fetch header
  530. LLMutexLock lock(mMutex);
  531. mHeaderReqQ.push(req);
  532. mPendingLOD[mesh_params].push_back(lod);
  533. }
  534. }
  535. }
  536. //static
  537. std::string LLMeshRepoThread::constructUrl(LLUUID mesh_id)
  538. {
  539. std::string http_url;
  540. if (gAgent.getRegion())
  541. {
  542. http_url = gMeshRepo.mGetMeshCapability;
  543. }
  544. if (!http_url.empty())
  545. {
  546. http_url += "/?mesh_id=";
  547. http_url += mesh_id.asString().c_str();
  548. }
  549. else
  550. {
  551. llwarns << "Current region does not have GetMesh capability! Cannot load " << mesh_id << ".mesh" << llendl;
  552. }
  553. return http_url;
  554. }
  555. bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)
  556. { //protected by mMutex
  557. mHeaderMutex->lock();
  558. if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
  559. { //we have no header info for this mesh, do nothing
  560. mHeaderMutex->unlock();
  561. return false;
  562. }
  563. bool ret = true ;
  564. U32 header_size = mMeshHeaderSize[mesh_id];
  565. if (header_size > 0)
  566. {
  567. S32 version = mMeshHeader[mesh_id]["version"].asInteger();
  568. S32 offset = header_size + mMeshHeader[mesh_id]["skin"]["offset"].asInteger();
  569. S32 size = mMeshHeader[mesh_id]["skin"]["size"].asInteger();
  570. mHeaderMutex->unlock();
  571. if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)
  572. {
  573. //check VFS for mesh skin info
  574. LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH);
  575. if (file.getSize() >= offset+size)
  576. {
  577. LLMeshRepository::sCacheBytesRead += size;
  578. file.seek(offset);
  579. U8* buffer = new U8[size];
  580. file.read(buffer, size);
  581. //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
  582. bool zero = true;
  583. for (S32 i = 0; i < llmin(size, 1024) && zero; ++i)
  584. {
  585. zero = buffer[i] > 0 ? false : true;
  586. }
  587. if (!zero)
  588. { //attempt to parse
  589. if (skinInfoReceived(mesh_id, buffer, size))
  590. {
  591. delete[] buffer;
  592. return true;
  593. }
  594. }
  595. delete[] buffer;
  596. }
  597. //reading from VFS failed for whatever reason, fetch from sim
  598. std::vector<std::string> headers;
  599. headers.push_back("Accept: application/octet-stream");
  600. std::string http_url = constructUrl(mesh_id);
  601. if (!http_url.empty())
  602. {
  603. ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
  604. new LLMeshSkinInfoResponder(mesh_id, offset, size));
  605. if(ret)
  606. {
  607. ++sActiveLODRequests;
  608. LLMeshRepository::sHTTPRequestCount++;
  609. }
  610. }
  611. }
  612. }
  613. else
  614. {
  615. mHeaderMutex->unlock();
  616. }
  617. //early out was not hit, effectively fetched
  618. return ret;
  619. }
  620. bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
  621. { //protected by mMutex
  622. mHeaderMutex->lock();
  623. if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
  624. { //we have no header info for this mesh, do nothing
  625. mHeaderMutex->unlock();
  626. return false;
  627. }
  628. U32 header_size = mMeshHeaderSize[mesh_id];
  629. bool ret = true ;
  630. if (header_size > 0)
  631. {
  632. S32 version = mMeshHeader[mesh_id]["version"].asInteger();
  633. S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger();
  634. S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger();
  635. mHeaderMutex->unlock();
  636. if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)
  637. {
  638. //check VFS for mesh skin info
  639. LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH);
  640. if (file.getSize() >= offset+size)
  641. {
  642. LLMeshRepository::sCacheBytesRead += size;
  643. file.seek(offset);
  644. U8* buffer = new U8[size];
  645. file.read(buffer, size);
  646. //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
  647. bool zero = true;
  648. for (S32 i = 0; i < llmin(size, 1024) && zero; ++i)
  649. {
  650. zero = buffer[i] > 0 ? false : true;
  651. }
  652. if (!zero)
  653. { //attempt to parse
  654. if (decompositionReceived(mesh_id, buffer, size))
  655. {
  656. delete[] buffer;
  657. return true;
  658. }
  659. }
  660. delete[] buffer;
  661. }
  662. //reading from VFS failed for whatever reason, fetch from sim
  663. std::vector<std::string> headers;
  664. headers.push_back("Accept: application/octet-stream");
  665. std::string http_url = constructUrl(mesh_id);
  666. if (!http_url.empty())
  667. {
  668. ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
  669. new LLMeshDecompositionResponder(mesh_id, offset, size));
  670. if(ret)
  671. {
  672. ++sActiveLODRequests;
  673. LLMeshRepository::sHTTPRequestCount++;
  674. }
  675. }
  676. }
  677. }
  678. else
  679. {
  680. mHeaderMutex->unlock();
  681. }
  682. //early out was not hit, effectively fetched
  683. return ret;
  684. }
  685. bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
  686. { //protected by mMutex
  687. mHeaderMutex->lock();
  688. if (mMeshHeader.find(mesh_id) == mMeshHeader.end())
  689. { //we have no header info for this mesh, do nothing
  690. mHeaderMutex->unlock();
  691. return false;
  692. }
  693. U32 header_size = mMeshHeaderSize[mesh_id];
  694. bool ret = true ;
  695. if (header_size > 0)
  696. {
  697. S32 version = mMeshHeader[mesh_id]["version"].asInteger();
  698. S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger();
  699. S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger();
  700. mHeaderMutex->unlock();
  701. if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)
  702. {
  703. //check VFS for mesh physics shape info
  704. LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH);
  705. if (file.getSize() >= offset+size)
  706. {
  707. LLMeshRepository::sCacheBytesRead += size;
  708. file.seek(offset);
  709. U8* buffer = new U8[size];
  710. file.read(buffer, size);
  711. //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
  712. bool zero = true;
  713. for (S32 i = 0; i < llmin(size, 1024) && zero; ++i)
  714. {
  715. zero = buffer[i] > 0 ? false : true;
  716. }
  717. if (!zero)
  718. { //attempt to parse
  719. if (physicsShapeReceived(mesh_id, buffer, size))
  720. {
  721. delete[] buffer;
  722. return true;
  723. }
  724. }
  725. delete[] buffer;
  726. }
  727. //reading from VFS failed for whatever reason, fetch from sim
  728. std::vector<std::string> headers;
  729. headers.push_back("Accept: application/octet-stream");
  730. std::string http_url = constructUrl(mesh_id);
  731. if (!http_url.empty())
  732. {
  733. ret = mCurlRequest->getByteRange(http_url, headers, offset, size,
  734. new LLMeshPhysicsShapeResponder(mesh_id, offset, size));
  735. if(ret)
  736. {
  737. ++sActiveLODRequests;
  738. LLMeshRepository::sHTTPRequestCount++;
  739. }
  740. }
  741. }
  742. else
  743. { //no physics shape whatsoever, report back NULL
  744. physicsShapeReceived(mesh_id, NULL, 0);
  745. }
  746. }
  747. else
  748. {
  749. mHeaderMutex->unlock();
  750. }
  751. //early out was not hit, effectively fetched
  752. return ret;
  753. }
  754. //return false if failed to get header
  755. bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count)
  756. {
  757. {
  758. //look for mesh in asset in vfs
  759. LLVFile file(gVFS, mesh_params.getSculptID(), LLAssetType::AT_MESH);
  760. S32 size = file.getSize();
  761. if (size > 0)
  762. { //NOTE -- if the header size is ever more than 4KB, this will break
  763. U8 buffer[4096];
  764. S32 bytes = llmin(size, 4096);
  765. LLMeshRepository::sCacheBytesRead += bytes;
  766. file.read(buffer, bytes);
  767. if (headerReceived(mesh_params, buffer, bytes))
  768. { //did not do an HTTP request, return false
  769. return true;
  770. }
  771. }
  772. }
  773. //either cache entry doesn't exist or is corrupt, request header from simulator
  774. bool retval = true ;
  775. std::vector<std::string> headers;
  776. headers.push_back("Accept: application/octet-stream");
  777. std::string http_url = constructUrl(mesh_params.getSculptID());
  778. if (!http_url.empty())
  779. {
  780. //grab first 4KB if we're going to bother with a fetch. Cache will prevent future fetches if a full mesh fits
  781. //within the first 4KB
  782. //NOTE -- this will break of headers ever exceed 4KB
  783. retval = mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params));
  784. if(retval)
  785. {
  786. ++sActiveHeaderRequests;
  787. LLMeshRepository::sHTTPRequestCount++;
  788. }
  789. count++;
  790. }
  791. return retval;
  792. }
  793. //return false if failed to get mesh lod.
  794. bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count)
  795. { //protected by mMutex
  796. mHeaderMutex->lock();
  797. bool retval = true;
  798. LLUUID mesh_id = mesh_params.getSculptID();
  799. U32 header_size = mMeshHeaderSize[mesh_id];
  800. if (header_size > 0)
  801. {
  802. S32 version = mMeshHeader[mesh_id]["version"].asInteger();
  803. S32 offset = header_size + mMeshHeader[mesh_id][header_lod[lod]]["offset"].asInteger();
  804. S32 size = mMeshHeader[mesh_id][header_lod[lod]]["size"].asInteger();
  805. mHeaderMutex->unlock();
  806. if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0)
  807. {
  808. //check VFS for mesh asset
  809. LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH);
  810. if (file.getSize() >= offset+size)
  811. {
  812. LLMeshRepository::sCacheBytesRead += size;
  813. file.seek(offset);
  814. U8* buffer = new U8[size];
  815. file.read(buffer, size);
  816. //make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
  817. bool zero = true;
  818. for (S32 i = 0; i < llmin(size, 1024) && zero; ++i)
  819. {
  820. zero = buffer[i] > 0 ? false : true;
  821. }
  822. if (!zero)
  823. { //attempt to parse
  824. if (lodReceived(mesh_params, lod, buffer, size))
  825. {
  826. delete[] buffer;
  827. return true;
  828. }
  829. }
  830. delete[] buffer;
  831. }
  832. //reading from VFS failed for whatever reason, fetch from sim
  833. std::vector<std::string> headers;
  834. headers.push_back("Accept: application/octet-stream");
  835. std::string http_url = constructUrl(mesh_id);
  836. if (!http_url.empty())
  837. {
  838. retval = mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,
  839. new LLMeshLODResponder(mesh_params, lod, offset, size));
  840. if(retval)
  841. {
  842. ++sActiveLODRequests;
  843. LLMeshRepository::sHTTPRequestCount++;
  844. }
  845. count++;
  846. }
  847. else
  848. {
  849. mUnavailableQ.push(LODRequest(mesh_params, lod));
  850. }
  851. }
  852. else
  853. {
  854. mUnavailableQ.push(LODRequest(mesh_params, lod));
  855. }
  856. }
  857. else
  858. {
  859. mHeaderMutex->unlock();
  860. }
  861. return retval;
  862. }
  863. bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size)
  864. {
  865. LLSD header;
  866. U32 header_size = 0;
  867. if (data_size > 0)
  868. {
  869. std::string res_str((char*) data, data_size);
  870. std::string deprecated_header("<? LLSD/Binary ?>");
  871. if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
  872. {
  873. res_str = res_str.substr(deprecated_header.size()+1, data_size);
  874. header_size = deprecated_header.size()+1;
  875. }
  876. data_size = res_str.size();
  877. std::istringstream stream(res_str);
  878. if (!LLSDSerialize::fromBinary(header, stream, data_size))
  879. {
  880. llwarns << "Mesh header parse error. Not a valid mesh asset!" << llendl;
  881. return false;
  882. }
  883. header_size += stream.tellg();
  884. }
  885. else
  886. {
  887. llinfos
  888. << "Marking header as non-existent, will not retry." << llendl;
  889. header["404"] = 1;
  890. }
  891. {
  892. LLUUID mesh_id = mesh_params.getSculptID();
  893. mHeaderMutex->lock();
  894. mMeshHeaderSize[mesh_id] = header_size;
  895. mMeshHeader[mesh_id] = header;
  896. mHeaderMutex->unlock();
  897. //check for pending requests
  898. pending_lod_map::iterator iter = mPendingLOD.find(mesh_params);
  899. if (iter != mPendingLOD.end())
  900. {
  901. LLMutexLock lock(mMutex);
  902. for (U32 i = 0; i < iter->second.size(); ++i)
  903. {
  904. LODRequest req(mesh_params, iter->second[i]);
  905. mLODReqQ.push(req);
  906. }
  907. }
  908. mPendingLOD.erase(iter);
  909. }
  910. return true;
  911. }
  912. bool LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size)
  913. {
  914. LLVolume* volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod));
  915. std::string mesh_string((char*) data, data_size);
  916. std::istringstream stream(mesh_string);
  917. if (volume->unpackVolumeFaces(stream, data_size))
  918. {
  919. LoadedMesh mesh(volume, mesh_params, lod);
  920. if (volume->getNumFaces() > 0)
  921. {
  922. LLMutexLock lock(mMutex);
  923. mLoadedQ.push(mesh);
  924. return true;
  925. }
  926. }
  927. return false;
  928. }
  929. bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size)
  930. {
  931. LLSD skin;
  932. if (data_size > 0)
  933. {
  934. std::string res_str((char*) data, data_size);
  935. std::istringstream stream(res_str);
  936. if (!unzip_llsd(skin, stream, data_size))
  937. {
  938. llwarns << "Mesh skin info parse error. Not a valid mesh asset!" << llendl;
  939. return false;
  940. }
  941. }
  942. {
  943. LLMeshSkinInfo info(skin);
  944. info.mMeshID = mesh_id;
  945. //llinfos<<"info pelvis offset"<<info.mPelvisOffset<<llendl;
  946. mSkinInfoQ.push(info);
  947. }
  948. return true;
  949. }
  950. bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size)
  951. {
  952. LLSD decomp;
  953. if (data_size > 0)
  954. {
  955. std::string res_str((char*) data, data_size);
  956. std::istringstream stream(res_str);
  957. if (!unzip_llsd(decomp, stream, data_size))
  958. {
  959. llwarns << "Mesh decomposition parse error. Not a valid mesh asset!" << llendl;
  960. return false;
  961. }
  962. }
  963. {
  964. LLModel::Decomposition* d = new LLModel::Decomposition(decomp);
  965. d->mMeshID = mesh_id;
  966. mDecompositionQ.push(d);
  967. }
  968. return true;
  969. }
  970. bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size)
  971. {
  972. LLSD physics_shape;
  973. LLModel::Decomposition* d = new LLModel::Decomposition();
  974. d->mMeshID = mesh_id;
  975. if (data == NULL)
  976. { //no data, no physics shape exists
  977. d->mPhysicsShapeMesh.clear();
  978. }
  979. else
  980. {
  981. LLVolumeParams volume_params;
  982. volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
  983. volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH);
  984. LLPointer<LLVolume> volume = new LLVolume(volume_params,0);
  985. std::string mesh_string((char*) data, data_size);
  986. std::istringstream stream(mesh_string);
  987. if (volume->unpackVolumeFaces(stream, data_size))
  988. {
  989. //load volume faces into decomposition buffer
  990. S32 vertex_count = 0;
  991. S32 index_count = 0;
  992. for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
  993. {
  994. const LLVolumeFace& face = volume->getVolumeFace(i);
  995. vertex_count += face.mNumVertices;
  996. index_count += face.mNumIndices;
  997. }
  998. d->mPhysicsShapeMesh.clear();
  999. std::vector<LLVector3>& pos = d->mPhysicsShapeMesh.mPositions;
  1000. std::vector<LLVector3>& norm = d->mPhysicsShapeMesh.mNormals;
  1001. for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
  1002. {
  1003. const LLVolumeFace& face = volume->getVolumeFace(i);
  1004. for (S32 i = 0; i < face.mNumIndices; ++i)
  1005. {
  1006. U16 idx = face.mIndices[i];
  1007. pos.push_back(LLVector3(face.mPositions[idx].getF32ptr()));
  1008. norm.push_back(LLVector3(face.mNormals[idx].getF32ptr()));
  1009. }
  1010. }
  1011. }
  1012. }
  1013. mDecompositionQ.push(d);
  1014. return true;
  1015. }
  1016. LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures,
  1017. bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload,
  1018. LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer)
  1019. : LLThread("mesh upload"),
  1020. mDiscarded(FALSE),
  1021. mDoUpload(do_upload),
  1022. mWholeModelUploadURL(upload_url),
  1023. mFeeObserverHandle(fee_observer),
  1024. mUploadObserverHandle(upload_observer)
  1025. {
  1026. mInstanceList = data;
  1027. mUploadTextures = upload_textures;
  1028. mUploadSkin = upload_skin;
  1029. mUploadJoints = upload_joints;
  1030. mMutex = new LLMutex(NULL);
  1031. mCurlRequest = NULL;
  1032. mPendingUploads = 0;
  1033. mFinished = false;
  1034. mOrigin = gAgent.getPositionAgent();
  1035. mHost = gAgent.getRegionHost();
  1036. mWholeModelFeeCapability = gAgent.getRegion()->getCapability("NewFileAgentInventory");
  1037. mOrigin += gAgent.getAtAxis() * scale.magVec();
  1038. mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut") ;
  1039. }
  1040. LLMeshUploadThread::~LLMeshUploadThread()
  1041. {
  1042. }
  1043. LLMeshUploadThread::DecompRequest::DecompRequest(LLModel* mdl, LLModel* base_model, LLMeshUploadThread* thread)
  1044. {
  1045. mStage = "single_hull";
  1046. mModel = mdl;
  1047. mDecompID = &mdl->mDecompID;
  1048. mBaseModel = base_model;
  1049. mThread = thread;
  1050. //copy out positions and indices
  1051. assignData(mdl) ;
  1052. mThread->mFinalDecomp = this;
  1053. mThread->mPhysicsComplete = false;
  1054. }
  1055. void LLMeshUploadThread::DecompRequest::completed()
  1056. {
  1057. if (mThread->mFinalDecomp == this)
  1058. {
  1059. mThread->mPhysicsComplete = true;
  1060. }
  1061. llassert(mHull.size() == 1);
  1062. mThread->mHullMap[mBaseModel] = mHull[0];
  1063. }
  1064. //called in the main thread.
  1065. void LLMeshUploadThread::preStart()
  1066. {
  1067. //build map of LLModel refs to instances for callbacks
  1068. for (instance_list::iterator iter = mInstanceList.begin(); iter != mInstanceList.end(); ++iter)
  1069. {
  1070. mInstance[iter->mModel].push_back(*iter);
  1071. }
  1072. }
  1073. void LLMeshUploadThread::discard()
  1074. {
  1075. LLMutexLock lock(mMutex) ;
  1076. mDiscarded = TRUE ;
  1077. }
  1078. BOOL LLMeshUploadThread::isDiscarded()
  1079. {
  1080. LLMutexLock lock(mMutex) ;
  1081. return mDiscarded ;
  1082. }
  1083. void LLMeshUploadThread::run()
  1084. {
  1085. if (mDoUpload)
  1086. {
  1087. doWholeModelUpload();
  1088. }
  1089. else
  1090. {
  1091. requestWholeModelFee();
  1092. }
  1093. }
  1094. void dump_llsd_to_file(const LLSD& content, std::string filename)
  1095. {
  1096. if (gSavedSettings.getBOOL("MeshUploadLogXML"))
  1097. {
  1098. std::ofstream of(filename.c_str());
  1099. LLSDSerialize::toPrettyXML(content,of);
  1100. }
  1101. }
  1102. LLSD llsd_from_file(std::string filename)
  1103. {
  1104. std::ifstream ifs(filename.c_str());
  1105. LLSD result;
  1106. LLSDSerialize::fromXML(result,ifs);
  1107. return result;
  1108. }
  1109. void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
  1110. {
  1111. LLSD result;
  1112. LLSD res;
  1113. result["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
  1114. result["texture_folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE);
  1115. result["asset_type"] = "mesh";
  1116. result["inventory_type"] = "object";
  1117. result["description"] = "(No Description)";
  1118. result["next_owner_mask"] = LLSD::Integer(LLFloaterPerms::getNextOwnerPerms());
  1119. result["group_mask"] = LLSD::Integer(LLFloaterPerms::getGroupPerms());
  1120. result["everyone_mask"] = LLSD::Integer(LLFloaterPerms::getEveryonePerms());
  1121. res["mesh_list"] = LLSD::emptyArray();
  1122. res["texture_list"] = LLSD::emptyArray();
  1123. res["instance_list"] = LLSD::emptyArray();
  1124. S32 mesh_num = 0;
  1125. S32 texture_num = 0;
  1126. std::set<LLViewerTexture* > textures;
  1127. std::map<LLViewerTexture*,S32> texture_index;
  1128. std::map<LLModel*,S32> mesh_index;
  1129. std::string model_name;
  1130. std::string model_metric;
  1131. S32 instance_num = 0;
  1132. for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
  1133. {
  1134. LLMeshUploadData data;
  1135. data.mBaseModel = iter->first;
  1136. LLModelInstance& first_instance = *(iter->second.begin());
  1137. for (S32 i = 0; i < 5; i++)
  1138. {
  1139. data.mModel[i] = first_instance.mLOD[i];
  1140. }
  1141. if (mesh_index.find(data.mBaseModel) == mesh_index.end())
  1142. {
  1143. // Have not seen this model before - create a new mesh_list entry for it.
  1144. if (model_name.empty())
  1145. {
  1146. model_name = data.mBaseModel->getName();
  1147. }
  1148. if (model_metric.empty())
  1149. {
  1150. model_metric = data.mBaseModel->getMetric();
  1151. }
  1152. std::stringstream ostr;
  1153. LLModel::Decomposition& decomp =
  1154. data.mModel[LLModel::LOD_PHYSICS].notNull() ?
  1155. data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
  1156. data.mBaseModel->mPhysics;
  1157. decomp.mBaseHull = mHullMap[data.mBaseModel];
  1158. LLSD mesh_header = LLModel::writeModel(
  1159. ostr,
  1160. data.mModel[LLModel::LOD_PHYSICS],
  1161. data.mModel[LLModel::LOD_HIGH],
  1162. data.mModel[LLModel::LOD_MEDIUM],
  1163. data.mModel[LLModel::LOD_LOW],
  1164. data.mModel[LLModel::LOD_IMPOSTOR],
  1165. decomp,
  1166. mUploadSkin,
  1167. mUploadJoints);
  1168. data.mAssetData = ostr.str();
  1169. std::string str = ostr.str();
  1170. res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end());
  1171. mesh_index[data.mBaseModel] = mesh_num;
  1172. mesh_num++;
  1173. }
  1174. // For all instances that use this model
  1175. for (instance_list::iterator instance_iter = iter->second.begin();
  1176. instance_iter != iter->second.end();
  1177. ++instance_iter)
  1178. {
  1179. LLModelInstance& instance = *instance_iter;
  1180. LLSD instance_entry;
  1181. for (S32 i = 0; i < 5; i++)
  1182. {
  1183. data.mModel[i] = instance.mLOD[i];
  1184. }
  1185. LLVector3 pos, scale;
  1186. LLQuaternion rot;
  1187. LLMatrix4 transformation = instance.mTransform;
  1188. decomposeMeshMatrix(transformation,pos,rot,scale);
  1189. instance_entry["position"] = ll_sd_from_vector3(pos);
  1190. instance_entry["rotation"] = ll_sd_from_quaternion(rot);
  1191. instance_entry["scale"] = ll_sd_from_vector3(scale);
  1192. instance_entry["material"] = LL_MCODE_WOOD;
  1193. instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
  1194. instance_entry["mesh"] = mesh_index[data.mBaseModel];
  1195. instance_entry["face_list"] = LLSD::emptyArray();
  1196. S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ;
  1197. for (S32 face_num = 0; face_num < end; face_num++)
  1198. {
  1199. LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
  1200. LLSD face_entry = LLSD::emptyMap();
  1201. LLViewerFetchedTexture *texture = material.mDiffuseMap.get();
  1202. if ((texture != NULL) &&
  1203. (textures.find(texture) == textures.end()))
  1204. {
  1205. textures.insert(texture);
  1206. }
  1207. std::stringstream texture_str;
  1208. if (texture != NULL && include_textures && mUploadTextures)
  1209. {
  1210. if(texture->hasSavedRawImage())
  1211. {
  1212. LLPointer<LLImageJ2C> upload_file =
  1213. LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
  1214. texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
  1215. }
  1216. }
  1217. if (texture != NULL &&
  1218. mUploadTextures &&
  1219. texture_index.find(texture) == texture_index.end())
  1220. {
  1221. texture_index[texture] = texture_num;
  1222. std::string str = texture_str.str();
  1223. res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
  1224. texture_num++;
  1225. }
  1226. // Subset of TextureEntry fields.
  1227. if (texture != NULL && mUploadTextures)
  1228. {
  1229. face_entry["image"] = texture_index[texture];
  1230. face_entry["scales"] = 1.0;
  1231. face_entry["scalet"] = 1.0;
  1232. face_entry["offsets"] = 0.0;
  1233. face_entry["offsett"] = 0.0;
  1234. face_entry["imagerot"] = 0.0;
  1235. }
  1236. face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor);
  1237. face_entry["fullbright"] = material.mFullbright;
  1238. instance_entry["face_list"][face_num] = face_entry;
  1239. }
  1240. res["instance_list"][instance_num] = instance_entry;
  1241. instance_num++;
  1242. }
  1243. }
  1244. if (model_name.empty()) model_name = "mesh model";
  1245. result["name"] = model_name;
  1246. if (model_metric.empty()) model_metric = "MUT_Unspecified";
  1247. res["metric"] = model_metric;
  1248. result["asset_resources"] = res;
  1249. dump_llsd_to_file(result,make_dump_name("whole_model_",dump_num));
  1250. dest = result;
  1251. }
  1252. void LLMeshUploadThread::generateHulls()
  1253. {
  1254. bool has_valid_requests = false ;
  1255. for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
  1256. {
  1257. LLMeshUploadData data;
  1258. data.mBaseModel = iter->first;
  1259. LLModelInstance& instance = *(iter->second.begin());
  1260. for (S32 i = 0; i < 5; i++)
  1261. {
  1262. data.mModel[i] = instance.mLOD[i];
  1263. }
  1264. //queue up models for hull generation
  1265. LLModel* physics = NULL;
  1266. if (data.mModel[LLModel::LOD_PHYSICS].notNull())
  1267. {
  1268. physics = data.mModel[LLModel::LOD_PHYSICS];
  1269. }
  1270. else if (data.mModel[LLModel::LOD_LOW].notNull())
  1271. {
  1272. physics = data.mModel[LLModel::LOD_LOW];
  1273. }
  1274. else if (data.mModel[LLModel::LOD_MEDIUM].notNull())
  1275. {
  1276. physics = data.mModel[LLModel::LOD_MEDIUM];
  1277. }
  1278. else
  1279. {
  1280. physics = data.mModel[LLModel::LOD_HIGH];
  1281. }
  1282. llassert(physics != NULL);
  1283. DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this);
  1284. if(request->isValid())
  1285. {
  1286. gMeshRepo.mDecompThread->submitRequest(request);
  1287. has_valid_requests = true ;
  1288. }
  1289. }
  1290. if(has_valid_requests)
  1291. {
  1292. while (!mPhysicsComplete)
  1293. {
  1294. apr_sleep(100);
  1295. }
  1296. }
  1297. }
  1298. void LLMeshUploadThread::doWholeModelUpload()
  1299. {
  1300. mCurlRequest = new LLCurlRequest();
  1301. if (mWholeModelUploadURL.empty())
  1302. {
  1303. llinfos << "unable to upload, fee request failed" << llendl;
  1304. }
  1305. else
  1306. {
  1307. generateHulls();
  1308. LLSD full_model_data;
  1309. wholeModelToLLSD(full_model_data, true);
  1310. LLSD body = full_model_data["asset_resources"];
  1311. dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num));
  1312. LLCurlRequest::headers_t headers;
  1313. {
  1314. LLCurl::ResponderPtr responder = new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle) ;
  1315. while(!mCurlRequest->post(mWholeModelUploadURL, headers, body, responder, mMeshUploadTimeOut))
  1316. {
  1317. //sleep for 10ms to prevent eating a whole core
  1318. apr_sleep(10000);
  1319. }
  1320. }
  1321. do
  1322. {
  1323. mCurlRequest->process();
  1324. //sleep for 10ms to prevent eating a whole core
  1325. apr_sleep(10000);
  1326. } while (mCurlRequest->getQueued() > 0);
  1327. }
  1328. delete mCurlRequest;
  1329. mCurlRequest = NULL;
  1330. // Currently a no-op.
  1331. mFinished = true;
  1332. }
  1333. void LLMeshUploadThread::requestWholeModelFee()
  1334. {
  1335. dump_num++;
  1336. mCurlRequest = new LLCurlRequest();
  1337. generateHulls();
  1338. LLSD model_data;
  1339. wholeModelToLLSD(model_data,false);
  1340. dump_llsd_to_file(model_data,make_dump_name("whole_model_fee_request_",dump_num));
  1341. mPendingUploads++;
  1342. LLCurlRequest::headers_t headers;
  1343. {
  1344. LLCurl::ResponderPtr responder = new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle) ;
  1345. while(!mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, responder, mMeshUploadTimeOut))
  1346. {
  1347. //sleep for 10ms to prevent eating a whole core
  1348. apr_sleep(10000);
  1349. }
  1350. }
  1351. do
  1352. {
  1353. mCurlRequest->process();
  1354. //sleep for 10ms to prevent eating a whole core
  1355. apr_sleep(10000);
  1356. } while (mCurlRequest->getQueued() > 0);
  1357. delete mCurlRequest;
  1358. mCurlRequest = NULL;
  1359. // Currently a no-op.
  1360. mFinished = true;
  1361. }
  1362. void LLMeshRepoThread::notifyLoadedMeshes()
  1363. {
  1364. while (!mLoadedQ.empty())
  1365. {
  1366. mMutex->lock();
  1367. LoadedMesh mesh = mLoadedQ.front();
  1368. mLoadedQ.pop();
  1369. mMutex->unlock();
  1370. if (mesh.mVolume && mesh.mVolume->getNumVolumeFaces() > 0)
  1371. {
  1372. gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume);
  1373. }
  1374. else
  1375. {
  1376. gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams,
  1377. LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail()));
  1378. }
  1379. }
  1380. while (!mUnavailableQ.empty())
  1381. {
  1382. mMutex->lock();
  1383. LODRequest req = mUnavailableQ.front();
  1384. mUnavailableQ.pop();
  1385. mMutex->unlock();
  1386. gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD);
  1387. }
  1388. while (!mSkinInfoQ.empty())
  1389. {
  1390. gMeshRepo.notifySkinInfoReceived(mSkinInfoQ.front());
  1391. mSkinInfoQ.pop();
  1392. }
  1393. while (!mDecompositionQ.empty())
  1394. {
  1395. gMeshRepo.notifyDecompositionReceived(mDecompositionQ.front());
  1396. mDecompositionQ.pop();
  1397. }
  1398. }
  1399. S32 LLMeshRepoThread::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
  1400. { //only ever called from main thread
  1401. LLMutexLock lock(mHeaderMutex);
  1402. mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID());
  1403. if (iter != mMeshHeader.end())
  1404. {
  1405. LLSD& header = iter->second;
  1406. return LLMeshRepository::getActualMeshLOD(header, lod);
  1407. }
  1408. return lod;
  1409. }
  1410. //static
  1411. S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod)
  1412. {
  1413. lod = llclamp(lod, 0, 3);
  1414. S32 version = header["version"];
  1415. if (header.has("404") || version > MAX_MESH_VERSION)
  1416. {
  1417. return -1;
  1418. }
  1419. if (header[header_lod[lod]]["size"].asInteger() > 0)
  1420. {
  1421. return lod;
  1422. }
  1423. //search down to find the next available lower lod
  1424. for (S32 i = lod-1; i >= 0; --i)
  1425. {
  1426. if (header[header_lod[i]]["size"].asInteger() > 0)
  1427. {
  1428. return i;
  1429. }
  1430. }
  1431. //search up to find then ext available higher lod
  1432. for (S32 i = lod+1; i < 4; ++i)
  1433. {
  1434. if (header[header_lod[i]]["size"].asInteger() > 0)
  1435. {
  1436. return i;
  1437. }
  1438. }
  1439. //header exists and no good lod found, treat as 404
  1440. header["404"] = 1;
  1441. return -1;
  1442. }
  1443. void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header)
  1444. {
  1445. mThread->mMeshHeader[data.mUUID] = header;
  1446. // we cache the mesh for default parameters
  1447. LLVolumeParams volume_params;
  1448. volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
  1449. volume_params.setSculptID(data.mUUID, LL_SCULPT_TYPE_MESH);
  1450. for (U32 i = 0; i < 4; i++)
  1451. {
  1452. if (data.mModel[i].notNull())
  1453. {
  1454. LLPointer<LLVolume> volume = new LLVolume(volume_params, LLVolumeLODGroup::getVolumeScaleFromDetail(i));
  1455. volume->copyVolumeFaces(data.mModel[i]);
  1456. volume->setMeshAssetLoaded(TRUE);
  1457. }
  1458. }
  1459. }
  1460. void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,
  1461. const LLChannelDescriptors& channels,
  1462. const LLIOPipe::buffer_ptr_t& buffer)
  1463. {
  1464. LLMeshRepoThread::sActiveLODRequests--;
  1465. S32 data_size = buffer->countAfter(channels.in(), NULL);
  1466. if (status < 200 || status > 400)
  1467. {
  1468. llwarns << status << ": " << reason << llendl;
  1469. }
  1470. if (data_size < mRequestedBytes)
  1471. {
  1472. if (status == 499 || status == 503)
  1473. { //timeout or service unavailable, try again
  1474. LLMeshRepository::sHTTPRetryCount++;
  1475. gMeshRepo.mThread->loadMeshLOD(mMeshParams, mLOD);
  1476. }
  1477. else
  1478. {
  1479. llwarns << "Unhandled status " << status << llendl;
  1480. }
  1481. return;
  1482. }
  1483. LLMeshRepository::sBytesReceived += mRequestedBytes;
  1484. U8* data = NULL;
  1485. if (data_size > 0)
  1486. {
  1487. data = new U8[data_size];
  1488. buffer->readAfter(channels.in(), NULL, data, data_size);
  1489. }
  1490. if (gMeshRepo.mThread->lodReceived(mMeshParams, mLOD, data, data_size))
  1491. {
  1492. //good fetch from sim, write to VFS for caching
  1493. LLVFile file(gVFS, mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLVFile::WRITE);
  1494. S32 offset = mOffset;
  1495. S32 size = mRequestedBytes;
  1496. if (file.getSize() >= offset+size)
  1497. {
  1498. file.seek(offset);
  1499. file.write(data, size);
  1500. LLMeshRepository::sCacheBytesWritten += size;
  1501. }
  1502. }
  1503. delete [] data;
  1504. }
  1505. void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason,
  1506. const LLChannelDescriptors& channels,
  1507. const LLIOPipe::buffer_ptr_t& buffer)
  1508. {
  1509. S32 data_size = buffer->countAfter(channels.in(), NULL);
  1510. if (status < 200 || status > 400)
  1511. {
  1512. llwarns << status << ": " << reason << llendl;
  1513. }
  1514. if (data_size < mRequestedBytes)
  1515. {
  1516. if (status == 499 || status == 503)
  1517. { //timeout or service unavailable, try again
  1518. LLMeshRepository::sHTTPRetryCount++;
  1519. gMeshRepo.mThread->loadMeshSkinInfo(mMeshID);
  1520. }
  1521. else
  1522. {
  1523. llwarns << "Unhandled status " << status << llendl;
  1524. }
  1525. return;
  1526. }
  1527. LLMeshRepository::sBytesReceived += mRequestedBytes;
  1528. U8* data = NULL;
  1529. if (data_size > 0)
  1530. {
  1531. data = new U8[data_size];
  1532. buffer->readAfter(channels.in(), NULL, data, data_size);
  1533. }
  1534. if (gMeshRepo.mThread->skinInfoReceived(mMeshID, data, data_size))
  1535. {
  1536. //good fetch from sim, write to VFS for caching
  1537. LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE);
  1538. S32 offset = mOffset;
  1539. S32 size = mRequestedBytes;
  1540. if (file.getSize() >= offset+size)
  1541. {
  1542. LLMeshRepository::sCacheBytesWritten += size;
  1543. file.seek(offset);
  1544. file.write(data, size);
  1545. }
  1546. }
  1547. delete [] data;
  1548. }
  1549. void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& reason,
  1550. const LLChannelDescriptors& channels,
  1551. const LLIOPipe::buffer_ptr_t& buffer)
  1552. {
  1553. S32 data_size = buffer->countAfter(channels.in(), NULL);
  1554. if (status < 200 || status > 400)
  1555. {
  1556. llwarns << status << ": " << reason << llendl;
  1557. }
  1558. if (data_size < mRequestedBytes)
  1559. {
  1560. if (status == 499 || status == 503)
  1561. { //timeout or service unavailable, try again
  1562. LLMeshRepository::sHTTPRetryCount++;
  1563. gMeshRepo.mThread->loadMeshDecomposition(mMeshID);
  1564. }
  1565. else
  1566. {
  1567. llwarns << "Unhandled status " << status << llendl;
  1568. }
  1569. return;
  1570. }
  1571. LLMeshRepository::sBytesReceived += mRequestedBytes;
  1572. U8* data = NULL;
  1573. if (data_size > 0)
  1574. {
  1575. data = new U8[data_size];
  1576. buffer->readAfter(channels.in(), NULL, data, data_size);
  1577. }
  1578. if (gMeshRepo.mThread->decompositionReceived(mMeshID, data, data_size))
  1579. {
  1580. //good fetch from sim, write to VFS for caching
  1581. LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE);
  1582. S32 offset = mOffset;
  1583. S32 size = mRequestedBytes;
  1584. if (file.getSize() >= offset+size)
  1585. {
  1586. LLMeshRepository::sCacheBytesWritten += size;
  1587. file.seek(offset);
  1588. file.write(data, size);
  1589. }
  1590. }
  1591. delete [] data;
  1592. }
  1593. void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& reason,
  1594. const LLChannelDescriptors& channels,
  1595. const LLIOPipe::buffer_ptr_t& buffer)
  1596. {
  1597. S32 data_size = buffer->countAfter(channels.in(), NULL);
  1598. if (status < 200 || status > 400)
  1599. {
  1600. llwarns << status << ": " << reason << llendl;
  1601. }
  1602. if (data_size < mRequestedBytes)
  1603. {
  1604. if (status == 499 || status == 503)
  1605. { //timeout or service unavailable, try again
  1606. LLMeshRepository::sHTTPRetryCount++;
  1607. gMeshRepo.mThread->loadMeshPhysicsShape(mMeshID);
  1608. }
  1609. else
  1610. {
  1611. llwarns << "Unhandled status " << status << llendl;
  1612. }
  1613. return;
  1614. }
  1615. LLMeshRepository::sBytesReceived += mRequestedBytes;
  1616. U8* data = NULL;
  1617. if (data_size > 0)
  1618. {
  1619. data = new U8[data_size];
  1620. buffer->readAfter(channels.in(), NULL, data, data_size);
  1621. }
  1622. if (gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size))
  1623. {
  1624. //good fetch from sim, write to VFS for caching
  1625. LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE);
  1626. S32 offset = mOffset;
  1627. S32 size = mRequestedBytes;
  1628. if (file.getSize() >= offset+size)
  1629. {
  1630. LLMeshRepository::sCacheBytesWritten += size;
  1631. file.seek(offset);
  1632. file.write(data, size);
  1633. }
  1634. }
  1635. delete [] data;
  1636. }
  1637. void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,
  1638. const LLChannelDescriptors& channels,
  1639. const LLIOPipe::buffer_ptr_t& buffer)
  1640. {
  1641. LLMeshRepoThread::sActiveHeaderRequests--;
  1642. if (status < 200 || status > 400)
  1643. {
  1644. //llwarns
  1645. // << "Header responder failed with status: "
  1646. // << status << ": " << reason << llendl;
  1647. // 503 (service unavailable) or 499 (timeout)
  1648. // can be due to server load and can be retried
  1649. // TODO*: Add maximum retry logic, exponential backoff
  1650. // and (somewhat more optional than the others) retries
  1651. // again after some set period of time
  1652. if (status == 503 || status == 499)
  1653. { //retry
  1654. LLMeshRepo

Large files files are truncated, but you can click here to view the full file