PageRenderTime 60ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llvovolume.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2586 lines | 2053 code | 357 blank | 176 comment | 423 complexity | 72a4750d007eb3fabf818833a5f8f90a MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llvovolume.cpp
  3. * @brief LLVOVolume class implementation
  4. *
  5. * $LicenseInfo:firstyear=2001&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. // A "volume" is a box, cylinder, sphere, or other primitive shape.
  27. #include "llviewerprecompiledheaders.h"
  28. #include "llvovolume.h"
  29. #include <sstream>
  30. #include "llviewercontrol.h"
  31. #include "lldir.h"
  32. #include "llflexibleobject.h"
  33. #include "llfloatertools.h"
  34. #include "llmaterialtable.h"
  35. #include "llprimitive.h"
  36. #include "llvolume.h"
  37. #include "llvolumeoctree.h"
  38. #include "llvolumemgr.h"
  39. #include "llvolumemessage.h"
  40. #include "material_codes.h"
  41. #include "message.h"
  42. #include "llpluginclassmedia.h" // for code in the mediaEvent handler
  43. #include "object_flags.h"
  44. #include "llagentconstants.h"
  45. #include "lldrawable.h"
  46. #include "lldrawpoolavatar.h"
  47. #include "lldrawpoolbump.h"
  48. #include "llface.h"
  49. #include "llspatialpartition.h"
  50. #include "llhudmanager.h"
  51. #include "llflexibleobject.h"
  52. #include "llsky.h"
  53. #include "lltexturefetch.h"
  54. #include "llvector4a.h"
  55. #include "llviewercamera.h"
  56. #include "llviewertexturelist.h"
  57. #include "llviewerobjectlist.h"
  58. #include "llviewerregion.h"
  59. #include "llviewertextureanim.h"
  60. #include "llworld.h"
  61. #include "llselectmgr.h"
  62. #include "pipeline.h"
  63. #include "llsdutil.h"
  64. #include "llmatrix4a.h"
  65. #include "llmediaentry.h"
  66. #include "llmediadataclient.h"
  67. #include "llmeshrepository.h"
  68. #include "llagent.h"
  69. #include "llviewermediafocus.h"
  70. #include "lldatapacker.h"
  71. #include "llviewershadermgr.h"
  72. #include "llvoavatar.h"
  73. #include "llvocache.h"
  74. const S32 MIN_QUIET_FRAMES_COALESCE = 30;
  75. const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
  76. const F32 FORCE_CULL_AREA = 8.f;
  77. const F32 MAX_LOD_DISTANCE = 24.f;
  78. BOOL gAnimateTextures = TRUE;
  79. //extern BOOL gHideSelectedObjects;
  80. F32 LLVOVolume::sLODFactor = 1.f;
  81. F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop
  82. F32 LLVOVolume::sDistanceFactor = 1.0f;
  83. S32 LLVOVolume::sNumLODChanges = 0;
  84. S32 LLVOVolume::mRenderComplexity_last = 0;
  85. S32 LLVOVolume::mRenderComplexity_current = 0;
  86. LLPointer<LLObjectMediaDataClient> LLVOVolume::sObjectMediaClient = NULL;
  87. LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient = NULL;
  88. static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles");
  89. static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes");
  90. static LLFastTimer::DeclareTimer FTM_VOLUME_TEXTURES("Volume Textures");
  91. // Implementation class of LLMediaDataClientObject. See llmediadataclient.h
  92. class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
  93. {
  94. public:
  95. LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew)
  96. {
  97. mObject->addMDCImpl();
  98. }
  99. ~LLMediaDataClientObjectImpl()
  100. {
  101. mObject->removeMDCImpl();
  102. }
  103. virtual U8 getMediaDataCount() const
  104. { return mObject->getNumTEs(); }
  105. virtual LLSD getMediaDataLLSD(U8 index) const
  106. {
  107. LLSD result;
  108. LLTextureEntry *te = mObject->getTE(index);
  109. if (NULL != te)
  110. {
  111. llassert((te->getMediaData() != NULL) == te->hasMedia());
  112. if (te->getMediaData() != NULL)
  113. {
  114. result = te->getMediaData()->asLLSD();
  115. // XXX HACK: workaround bug in asLLSD() where whitelist is not set properly
  116. // See DEV-41949
  117. if (!result.has(LLMediaEntry::WHITELIST_KEY))
  118. {
  119. result[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray();
  120. }
  121. }
  122. }
  123. return result;
  124. }
  125. virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const
  126. {
  127. LLTextureEntry *te = mObject->getTE(index);
  128. if (te)
  129. {
  130. if (te->getMediaData())
  131. {
  132. return (te->getMediaData()->getCurrentURL() == url);
  133. }
  134. }
  135. return url.empty();
  136. }
  137. virtual LLUUID getID() const
  138. { return mObject->getID(); }
  139. virtual void mediaNavigateBounceBack(U8 index)
  140. { mObject->mediaNavigateBounceBack(index); }
  141. virtual bool hasMedia() const
  142. { return mObject->hasMedia(); }
  143. virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string)
  144. { mObject->updateObjectMediaData(data, version_string); }
  145. virtual F64 getMediaInterest() const
  146. {
  147. F64 interest = mObject->getTotalMediaInterest();
  148. if (interest < (F64)0.0)
  149. {
  150. // media interest not valid yet, try pixel area
  151. interest = mObject->getPixelArea();
  152. // HACK: force recalculation of pixel area if interest is the "magic default" of 1024.
  153. if (interest == 1024.f)
  154. {
  155. const_cast<LLVOVolume*>(static_cast<LLVOVolume*>(mObject))->setPixelAreaAndAngle(gAgent);
  156. interest = mObject->getPixelArea();
  157. }
  158. }
  159. return interest;
  160. }
  161. virtual bool isInterestingEnough() const
  162. {
  163. return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest());
  164. }
  165. virtual std::string getCapabilityUrl(const std::string &name) const
  166. { return mObject->getRegion()->getCapability(name); }
  167. virtual bool isDead() const
  168. { return mObject->isDead(); }
  169. virtual U32 getMediaVersion() const
  170. { return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); }
  171. virtual bool isNew() const
  172. { return mNew; }
  173. private:
  174. LLPointer<LLVOVolume> mObject;
  175. bool mNew;
  176. };
  177. LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
  178. : LLViewerObject(id, pcode, regionp),
  179. mVolumeImpl(NULL)
  180. {
  181. mTexAnimMode = 0;
  182. mRelativeXform.setIdentity();
  183. mRelativeXformInvTrans.setIdentity();
  184. mFaceMappingChanged = FALSE;
  185. mLOD = MIN_LOD;
  186. mTextureAnimp = NULL;
  187. mVolumeChanged = FALSE;
  188. mVObjRadius = LLVector3(1,1,0.5f).length();
  189. mNumFaces = 0;
  190. mLODChanged = FALSE;
  191. mSculptChanged = FALSE;
  192. mSpotLightPriority = 0.f;
  193. mMediaImplList.resize(getNumTEs());
  194. mLastFetchedMediaVersion = -1;
  195. mIndexInTex = 0;
  196. mMDCImplCount = 0;
  197. }
  198. LLVOVolume::~LLVOVolume()
  199. {
  200. delete mTextureAnimp;
  201. mTextureAnimp = NULL;
  202. delete mVolumeImpl;
  203. mVolumeImpl = NULL;
  204. if(!mMediaImplList.empty())
  205. {
  206. for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
  207. {
  208. if(mMediaImplList[i].notNull())
  209. {
  210. mMediaImplList[i]->removeObject(this) ;
  211. }
  212. }
  213. }
  214. }
  215. void LLVOVolume::markDead()
  216. {
  217. if (!mDead)
  218. {
  219. if(getMDCImplCount() > 0)
  220. {
  221. LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false);
  222. if (sObjectMediaClient) sObjectMediaClient->removeFromQueue(obj);
  223. if (sObjectMediaNavigateClient) sObjectMediaNavigateClient->removeFromQueue(obj);
  224. }
  225. // Detach all media impls from this object
  226. for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
  227. {
  228. removeMediaImpl(i);
  229. }
  230. if (mSculptTexture.notNull())
  231. {
  232. mSculptTexture->removeVolume(this);
  233. }
  234. }
  235. LLViewerObject::markDead();
  236. }
  237. // static
  238. void LLVOVolume::initClass()
  239. {
  240. // gSavedSettings better be around
  241. if (gSavedSettings.getBOOL("PrimMediaMasterEnabled"))
  242. {
  243. const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay");
  244. const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay");
  245. const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries");
  246. const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize");
  247. const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize");
  248. sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries,
  249. max_sorted_queue_size, max_round_robin_queue_size);
  250. sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay,
  251. max_retries, max_sorted_queue_size, max_round_robin_queue_size);
  252. }
  253. }
  254. // static
  255. void LLVOVolume::cleanupClass()
  256. {
  257. sObjectMediaClient = NULL;
  258. sObjectMediaNavigateClient = NULL;
  259. }
  260. U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
  261. void **user_data,
  262. U32 block_num, EObjectUpdateType update_type,
  263. LLDataPacker *dp)
  264. {
  265. LLColor4U color;
  266. const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA);
  267. // Do base class updates...
  268. U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
  269. LLUUID sculpt_id;
  270. U8 sculpt_type = 0;
  271. if (isSculpted())
  272. {
  273. LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
  274. sculpt_id = sculpt_params->getSculptTexture();
  275. sculpt_type = sculpt_params->getSculptType();
  276. }
  277. if (!dp)
  278. {
  279. if (update_type == OUT_FULL)
  280. {
  281. ////////////////////////////////
  282. //
  283. // Unpack texture animation data
  284. //
  285. //
  286. if (mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureAnim))
  287. {
  288. if (!mTextureAnimp)
  289. {
  290. mTextureAnimp = new LLViewerTextureAnim();
  291. }
  292. else
  293. {
  294. if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH))
  295. {
  296. mTextureAnimp->reset();
  297. }
  298. }
  299. mTexAnimMode = 0;
  300. mTextureAnimp->unpackTAMessage(mesgsys, block_num);
  301. }
  302. else
  303. {
  304. if (mTextureAnimp)
  305. {
  306. delete mTextureAnimp;
  307. mTextureAnimp = NULL;
  308. gPipeline.markTextured(mDrawable);
  309. mFaceMappingChanged = TRUE;
  310. mTexAnimMode = 0;
  311. }
  312. }
  313. // Unpack volume data
  314. LLVolumeParams volume_params;
  315. LLVolumeMessage::unpackVolumeParams(&volume_params, mesgsys, _PREHASH_ObjectData, block_num);
  316. volume_params.setSculptID(sculpt_id, sculpt_type);
  317. if (setVolume(volume_params, 0))
  318. {
  319. markForUpdate(TRUE);
  320. }
  321. }
  322. // Sigh, this needs to be done AFTER the volume is set as well, otherwise bad stuff happens...
  323. ////////////////////////////
  324. //
  325. // Unpack texture entry data
  326. //
  327. S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num);
  328. if (result & teDirtyBits)
  329. {
  330. updateTEData();
  331. }
  332. if (result & TEM_CHANGE_MEDIA)
  333. {
  334. retval |= MEDIA_FLAGS_CHANGED;
  335. }
  336. }
  337. else
  338. {
  339. // CORY TO DO: Figure out how to get the value here
  340. if (update_type != OUT_TERSE_IMPROVED)
  341. {
  342. LLVolumeParams volume_params;
  343. BOOL res = LLVolumeMessage::unpackVolumeParams(&volume_params, *dp);
  344. if (!res)
  345. {
  346. llwarns << "Bogus volume parameters in object " << getID() << llendl;
  347. llwarns << getRegion()->getOriginGlobal() << llendl;
  348. }
  349. volume_params.setSculptID(sculpt_id, sculpt_type);
  350. if (setVolume(volume_params, 0))
  351. {
  352. markForUpdate(TRUE);
  353. }
  354. S32 res2 = unpackTEMessage(*dp);
  355. if (TEM_INVALID == res2)
  356. {
  357. // There's something bogus in the data that we're unpacking.
  358. dp->dumpBufferToLog();
  359. llwarns << "Flushing cache files" << llendl;
  360. if(LLVOCache::hasInstance() && getRegion())
  361. {
  362. LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ;
  363. }
  364. llwarns << "Bogus TE data in " << getID() << llendl;
  365. }
  366. else
  367. {
  368. if (res2 & teDirtyBits)
  369. {
  370. updateTEData();
  371. }
  372. if (res2 & TEM_CHANGE_MEDIA)
  373. {
  374. retval |= MEDIA_FLAGS_CHANGED;
  375. }
  376. }
  377. U32 value = dp->getPassFlags();
  378. if (value & 0x40)
  379. {
  380. if (!mTextureAnimp)
  381. {
  382. mTextureAnimp = new LLViewerTextureAnim();
  383. }
  384. else
  385. {
  386. if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH))
  387. {
  388. mTextureAnimp->reset();
  389. }
  390. }
  391. mTexAnimMode = 0;
  392. mTextureAnimp->unpackTAMessage(*dp);
  393. }
  394. else if (mTextureAnimp)
  395. {
  396. delete mTextureAnimp;
  397. mTextureAnimp = NULL;
  398. gPipeline.markTextured(mDrawable);
  399. mFaceMappingChanged = TRUE;
  400. mTexAnimMode = 0;
  401. }
  402. }
  403. else
  404. {
  405. S32 texture_length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureEntry);
  406. if (texture_length)
  407. {
  408. U8 tdpbuffer[1024];
  409. LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024);
  410. mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num);
  411. S32 result = unpackTEMessage(tdp);
  412. if (result & teDirtyBits)
  413. {
  414. updateTEData();
  415. }
  416. if (result & TEM_CHANGE_MEDIA)
  417. {
  418. retval |= MEDIA_FLAGS_CHANGED;
  419. }
  420. }
  421. }
  422. }
  423. if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED))
  424. {
  425. // If only the media URL changed, and it isn't a media version URL,
  426. // ignore it
  427. if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) &&
  428. mMedia && ! mMedia->mMediaURL.empty() &&
  429. ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) )
  430. {
  431. // If the media changed at all, request new media data
  432. LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " <<
  433. ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL;
  434. requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED);
  435. }
  436. else {
  437. LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " <<
  438. ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL;
  439. }
  440. }
  441. // ...and clean up any media impls
  442. cleanUpMediaImpls();
  443. return retval;
  444. }
  445. void LLVOVolume::animateTextures()
  446. {
  447. F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f;
  448. S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot);
  449. if (result)
  450. {
  451. if (!mTexAnimMode)
  452. {
  453. mFaceMappingChanged = TRUE;
  454. gPipeline.markTextured(mDrawable);
  455. }
  456. mTexAnimMode = result | mTextureAnimp->mMode;
  457. S32 start=0, end=mDrawable->getNumFaces()-1;
  458. if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end)
  459. {
  460. start = end = mTextureAnimp->mFace;
  461. }
  462. for (S32 i = start; i <= end; i++)
  463. {
  464. LLFace* facep = mDrawable->getFace(i);
  465. if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue;
  466. const LLTextureEntry* te = facep->getTextureEntry();
  467. if (!te)
  468. {
  469. continue;
  470. }
  471. if (!(result & LLViewerTextureAnim::ROTATE))
  472. {
  473. te->getRotation(&rot);
  474. }
  475. if (!(result & LLViewerTextureAnim::TRANSLATE))
  476. {
  477. te->getOffset(&off_s,&off_t);
  478. }
  479. if (!(result & LLViewerTextureAnim::SCALE))
  480. {
  481. te->getScale(&scale_s, &scale_t);
  482. }
  483. if (!facep->mTextureMatrix)
  484. {
  485. facep->mTextureMatrix = new LLMatrix4();
  486. }
  487. LLMatrix4& tex_mat = *facep->mTextureMatrix;
  488. tex_mat.setIdentity();
  489. LLVector3 trans ;
  490. if(facep->isAtlasInUse())
  491. {
  492. //
  493. //if use atlas for animated texture
  494. //apply the following transform to the animation matrix.
  495. //
  496. F32 tcoord_xoffset = 0.f ;
  497. F32 tcoord_yoffset = 0.f ;
  498. F32 tcoord_xscale = 1.f ;
  499. F32 tcoord_yscale = 1.f ;
  500. if(facep->isAtlasInUse())
  501. {
  502. const LLVector2* tmp = facep->getTexCoordOffset() ;
  503. tcoord_xoffset = tmp->mV[0] ;
  504. tcoord_yoffset = tmp->mV[1] ;
  505. tmp = facep->getTexCoordScale() ;
  506. tcoord_xscale = tmp->mV[0] ;
  507. tcoord_yscale = tmp->mV[1] ;
  508. }
  509. trans.set(LLVector3(tcoord_xoffset + tcoord_xscale * (off_s+0.5f), tcoord_yoffset + tcoord_yscale * (off_t+0.5f), 0.f));
  510. tex_mat.translate(LLVector3(-(tcoord_xoffset + tcoord_xscale * 0.5f), -(tcoord_yoffset + tcoord_yscale * 0.5f), 0.f));
  511. }
  512. else //non atlas
  513. {
  514. trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f));
  515. tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
  516. }
  517. LLVector3 scale(scale_s, scale_t, 1.f);
  518. LLQuaternion quat;
  519. quat.setQuat(rot, 0, 0, -1.f);
  520. tex_mat.rotate(quat);
  521. LLMatrix4 mat;
  522. mat.initAll(scale, LLQuaternion(), LLVector3());
  523. tex_mat *= mat;
  524. tex_mat.translate(trans);
  525. }
  526. }
  527. else
  528. {
  529. if (mTexAnimMode && mTextureAnimp->mRate == 0)
  530. {
  531. U8 start, count;
  532. if (mTextureAnimp->mFace == -1)
  533. {
  534. start = 0;
  535. count = getNumTEs();
  536. }
  537. else
  538. {
  539. start = (U8) mTextureAnimp->mFace;
  540. count = 1;
  541. }
  542. for (S32 i = start; i < start + count; i++)
  543. {
  544. if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE)
  545. {
  546. setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT);
  547. }
  548. if (mTexAnimMode & LLViewerTextureAnim::SCALE)
  549. {
  550. setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT);
  551. }
  552. if (mTexAnimMode & LLViewerTextureAnim::ROTATE)
  553. {
  554. setTERotation(i, mTextureAnimp->mRot);
  555. }
  556. }
  557. gPipeline.markTextured(mDrawable);
  558. mFaceMappingChanged = TRUE;
  559. mTexAnimMode = 0;
  560. }
  561. }
  562. }
  563. BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
  564. {
  565. LLViewerObject::idleUpdate(agent, world, time);
  566. static LLFastTimer::DeclareTimer ftm("Volume");
  567. LLFastTimer t(ftm);
  568. if (mDead || mDrawable.isNull())
  569. {
  570. return TRUE;
  571. }
  572. ///////////////////////
  573. //
  574. // Do texture animation stuff
  575. //
  576. if (mTextureAnimp && gAnimateTextures)
  577. {
  578. animateTextures();
  579. }
  580. // Dispatch to implementation
  581. if (mVolumeImpl)
  582. {
  583. mVolumeImpl->doIdleUpdate(agent, world, time);
  584. }
  585. const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40;
  586. if (mDrawable->isActive())
  587. {
  588. if (mDrawable->isRoot() &&
  589. mDrawable->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES &&
  590. (!mDrawable->getParent() || !mDrawable->getParent()->isActive()))
  591. {
  592. mDrawable->makeStatic();
  593. }
  594. }
  595. return TRUE;
  596. }
  597. void LLVOVolume::updateTextures()
  598. {
  599. const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds
  600. if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME)
  601. {
  602. updateTextureVirtualSize();
  603. }
  604. }
  605. BOOL LLVOVolume::isVisible() const
  606. {
  607. if(mDrawable.notNull() && mDrawable->isVisible())
  608. {
  609. return TRUE ;
  610. }
  611. if(isAttachment())
  612. {
  613. LLViewerObject* objp = (LLViewerObject*)getParent() ;
  614. while(objp && !objp->isAvatar())
  615. {
  616. objp = (LLViewerObject*)objp->getParent() ;
  617. }
  618. return objp && objp->mDrawable.notNull() && objp->mDrawable->isVisible() ;
  619. }
  620. return FALSE ;
  621. }
  622. void LLVOVolume::updateTextureVirtualSize(bool forced)
  623. {
  624. LLFastTimer ftm(FTM_VOLUME_TEXTURES);
  625. // Update the pixel area of all faces
  626. if(!forced)
  627. {
  628. if(!isVisible())
  629. {
  630. return ;
  631. }
  632. if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE))
  633. {
  634. return;
  635. }
  636. }
  637. static LLCachedControl<bool> dont_load_textures(gSavedSettings,"TextureDisable");
  638. if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible())
  639. {
  640. return;
  641. }
  642. mTextureUpdateTimer.reset();
  643. F32 old_area = mPixelArea;
  644. mPixelArea = 0.f;
  645. const S32 num_faces = mDrawable->getNumFaces();
  646. F32 min_vsize=999999999.f, max_vsize=0.f;
  647. LLViewerCamera* camera = LLViewerCamera::getInstance();
  648. for (S32 i = 0; i < num_faces; i++)
  649. {
  650. LLFace* face = mDrawable->getFace(i);
  651. const LLTextureEntry *te = face->getTextureEntry();
  652. LLViewerTexture *imagep = face->getTexture();
  653. if (!imagep || !te ||
  654. face->mExtents[0].equals3(face->mExtents[1]))
  655. {
  656. continue;
  657. }
  658. F32 vsize;
  659. F32 old_size = face->getVirtualSize();
  660. if (isHUDAttachment())
  661. {
  662. F32 area = (F32) camera->getScreenPixelArea();
  663. vsize = area;
  664. imagep->setBoostLevel(LLViewerTexture::BOOST_HUD);
  665. face->setPixelArea(area); // treat as full screen
  666. face->setVirtualSize(vsize);
  667. }
  668. else
  669. {
  670. vsize = face->getTextureVirtualSize();
  671. }
  672. mPixelArea = llmax(mPixelArea, face->getPixelArea());
  673. if (face->mTextureMatrix != NULL)
  674. {
  675. if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) ||
  676. (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE))
  677. {
  678. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE);
  679. }
  680. }
  681. if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
  682. {
  683. if (vsize < min_vsize) min_vsize = vsize;
  684. if (vsize > max_vsize) max_vsize = vsize;
  685. }
  686. else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
  687. {
  688. LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ;
  689. if(img)
  690. {
  691. F32 pri = img->getDecodePriority();
  692. pri = llmax(pri, 0.0f);
  693. if (pri < min_vsize) min_vsize = pri;
  694. if (pri > max_vsize) max_vsize = pri;
  695. }
  696. }
  697. else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
  698. {
  699. F32 pri = mPixelArea;
  700. if (pri < min_vsize) min_vsize = pri;
  701. if (pri > max_vsize) max_vsize = pri;
  702. }
  703. }
  704. if (isSculpted())
  705. {
  706. LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
  707. LLUUID id = sculpt_params->getSculptTexture();
  708. updateSculptTexture();
  709. if (mSculptTexture.notNull())
  710. {
  711. mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(),
  712. (S32)LLViewerTexture::BOOST_SCULPTED));
  713. mSculptTexture->setForSculpt() ;
  714. if(!mSculptTexture->isCachedRawImageReady())
  715. {
  716. S32 lod = llmin(mLOD, 3);
  717. F32 lodf = ((F32)(lod + 1.0f)/4.f);
  718. F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ;
  719. mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE);
  720. //if the sculpty very close to the view point, load first
  721. {
  722. LLVector3 lookAt = getPositionAgent() - camera->getOrigin();
  723. F32 dist = lookAt.normVec() ;
  724. F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ;
  725. mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ;
  726. }
  727. }
  728. S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture
  729. S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ;
  730. if (texture_discard >= 0 && //texture has some data available
  731. (texture_discard < current_discard || //texture has more data than last rebuild
  732. current_discard < 0)) //no previous rebuild
  733. {
  734. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
  735. mSculptChanged = TRUE;
  736. }
  737. if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED))
  738. {
  739. setDebugText(llformat("T%d C%d V%d\n%dx%d",
  740. texture_discard, current_discard, getVolume()->getSculptLevel(),
  741. mSculptTexture->getHeight(), mSculptTexture->getWidth()));
  742. }
  743. }
  744. }
  745. if (getLightTextureID().notNull())
  746. {
  747. LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
  748. LLUUID id = params->getLightTexture();
  749. mLightTexture = LLViewerTextureManager::getFetchedTexture(id);
  750. if (mLightTexture.notNull())
  751. {
  752. F32 rad = getLightRadius();
  753. mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(),
  754. LLVector3(rad,rad,rad),
  755. *camera));
  756. }
  757. }
  758. if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
  759. {
  760. setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize)));
  761. }
  762. else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
  763. {
  764. setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize)));
  765. }
  766. else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
  767. {
  768. setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize)));
  769. }
  770. if (mPixelArea == 0)
  771. { //flexi phasing issues make this happen
  772. mPixelArea = old_area;
  773. }
  774. }
  775. BOOL LLVOVolume::isActive() const
  776. {
  777. return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive()) ||
  778. (mDrawable.notNull() && mDrawable->isActive());
  779. }
  780. BOOL LLVOVolume::setMaterial(const U8 material)
  781. {
  782. BOOL res = LLViewerObject::setMaterial(material);
  783. return res;
  784. }
  785. void LLVOVolume::setTexture(const S32 face)
  786. {
  787. llassert(face < getNumTEs());
  788. gGL.getTexUnit(0)->bind(getTEImage(face));
  789. }
  790. void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped)
  791. {
  792. if (scale != getScale())
  793. {
  794. // store local radius
  795. LLViewerObject::setScale(scale);
  796. if (mVolumeImpl)
  797. {
  798. mVolumeImpl->onSetScale(scale, damped);
  799. }
  800. updateRadius();
  801. //since drawable transforms do not include scale, changing volume scale
  802. //requires an immediate rebuild of volume verts.
  803. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE);
  804. }
  805. }
  806. LLFace* LLVOVolume::addFace(S32 f)
  807. {
  808. const LLTextureEntry* te = getTE(f);
  809. LLViewerTexture* imagep = getTEImage(f);
  810. return mDrawable->addFace(te, imagep);
  811. }
  812. LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
  813. {
  814. pipeline->allocDrawable(this);
  815. mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME);
  816. S32 max_tes_to_set = getNumTEs();
  817. for (S32 i = 0; i < max_tes_to_set; i++)
  818. {
  819. addFace(i);
  820. }
  821. mNumFaces = max_tes_to_set;
  822. if (isAttachment())
  823. {
  824. mDrawable->makeActive();
  825. }
  826. if (getIsLight())
  827. {
  828. // Add it to the pipeline mLightSet
  829. gPipeline.setLight(mDrawable, TRUE);
  830. }
  831. updateRadius();
  832. bool force_update = true; // avoid non-alpha mDistance update being optimized away
  833. mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update);
  834. return mDrawable;
  835. }
  836. BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bool unique_volume)
  837. {
  838. LLVolumeParams volume_params = params_in;
  839. S32 last_lod = mVolumep.notNull() ? LLVolumeLODGroup::getVolumeDetailFromScale(mVolumep->getDetail()) : -1;
  840. S32 lod = mLOD;
  841. BOOL is404 = FALSE;
  842. if (isSculpted())
  843. {
  844. // if it's a mesh
  845. if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
  846. { //meshes might not have all LODs, get the force detail to best existing LOD
  847. LLUUID mesh_id = volume_params.getSculptID();
  848. lod = gMeshRepo.getActualMeshLOD(volume_params, lod);
  849. if (lod == -1)
  850. {
  851. is404 = TRUE;
  852. lod = 0;
  853. }
  854. }
  855. }
  856. // Check if we need to change implementations
  857. bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE);
  858. if (is_flexible)
  859. {
  860. setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, false);
  861. if (!mVolumeImpl)
  862. {
  863. LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
  864. mVolumeImpl = new LLVolumeImplFlexible(this, data);
  865. }
  866. }
  867. else
  868. {
  869. // Mark the parameter not in use
  870. setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, false);
  871. if (mVolumeImpl)
  872. {
  873. delete mVolumeImpl;
  874. mVolumeImpl = NULL;
  875. if (mDrawable.notNull())
  876. {
  877. // Undo the damage we did to this matrix
  878. mDrawable->updateXform(FALSE);
  879. }
  880. }
  881. }
  882. if (is404)
  883. {
  884. setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", TRUE, LLViewerTexture::BOOST_UI));
  885. //render prim proxy when mesh loading attempts give up
  886. volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE);
  887. }
  888. if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged)
  889. {
  890. mFaceMappingChanged = TRUE;
  891. if (mVolumeImpl)
  892. {
  893. mVolumeImpl->onSetVolume(volume_params, mLOD);
  894. }
  895. updateSculptTexture();
  896. if (isSculpted())
  897. {
  898. updateSculptTexture();
  899. // if it's a mesh
  900. if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
  901. {
  902. if (!getVolume()->isMeshAssetLoaded())
  903. {
  904. //load request not yet issued, request pipeline load this mesh
  905. LLUUID asset_id = volume_params.getSculptID();
  906. S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod);
  907. if (available_lod != lod)
  908. {
  909. LLPrimitive::setVolume(volume_params, available_lod);
  910. }
  911. }
  912. }
  913. else // otherwise is sculptie
  914. {
  915. if (mSculptTexture.notNull())
  916. {
  917. sculpt();
  918. }
  919. }
  920. }
  921. return TRUE;
  922. }
  923. return FALSE;
  924. }
  925. void LLVOVolume::updateSculptTexture()
  926. {
  927. LLPointer<LLViewerFetchedTexture> old_sculpt = mSculptTexture;
  928. if (isSculpted() && !isMesh())
  929. {
  930. LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
  931. LLUUID id = sculpt_params->getSculptTexture();
  932. if (id.notNull())
  933. {
  934. mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
  935. }
  936. }
  937. else
  938. {
  939. mSculptTexture = NULL;
  940. }
  941. if (mSculptTexture != old_sculpt)
  942. {
  943. if (old_sculpt.notNull())
  944. {
  945. old_sculpt->removeVolume(this);
  946. }
  947. if (mSculptTexture.notNull())
  948. {
  949. mSculptTexture->addVolume(this);
  950. }
  951. }
  952. }
  953. void LLVOVolume::notifyMeshLoaded()
  954. {
  955. mSculptChanged = TRUE;
  956. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
  957. }
  958. // sculpt replaces generate() for sculpted surfaces
  959. void LLVOVolume::sculpt()
  960. {
  961. if (mSculptTexture.notNull())
  962. {
  963. U16 sculpt_height = 0;
  964. U16 sculpt_width = 0;
  965. S8 sculpt_components = 0;
  966. const U8* sculpt_data = NULL;
  967. S32 discard_level = mSculptTexture->getDiscardLevel() ;
  968. LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ;
  969. S32 max_discard = mSculptTexture->getMaxDiscardLevel();
  970. if (discard_level > max_discard)
  971. discard_level = max_discard; // clamp to the best we can do
  972. S32 current_discard = getVolume()->getSculptLevel() ;
  973. if(current_discard < -2)
  974. {
  975. llwarns << "WARNING!!: Current discard of sculpty at " << current_discard
  976. << " is less than -2." << llendl;
  977. // corrupted volume... don't update the sculpty
  978. return;
  979. }
  980. else if (current_discard > MAX_DISCARD_LEVEL)
  981. {
  982. llwarns << "WARNING!!: Current discard of sculpty at " << current_discard
  983. << " is more than than allowed max of " << MAX_DISCARD_LEVEL << llendl;
  984. // corrupted volume... don't update the sculpty
  985. return;
  986. }
  987. if (current_discard == discard_level) // no work to do here
  988. return;
  989. if(!raw_image)
  990. {
  991. llassert(discard_level < 0) ;
  992. sculpt_width = 0;
  993. sculpt_height = 0;
  994. sculpt_data = NULL ;
  995. if(LLViewerTextureManager::sTesterp)
  996. {
  997. LLViewerTextureManager::sTesterp->updateGrayTextureBinding();
  998. }
  999. }
  1000. else
  1001. {
  1002. sculpt_height = raw_image->getHeight();
  1003. sculpt_width = raw_image->getWidth();
  1004. sculpt_components = raw_image->getComponents();
  1005. sculpt_data = raw_image->getData();
  1006. if(LLViewerTextureManager::sTesterp)
  1007. {
  1008. mSculptTexture->updateBindStatsForTester() ;
  1009. }
  1010. }
  1011. getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level);
  1012. //notify rebuild any other VOVolumes that reference this sculpty volume
  1013. for (S32 i = 0; i < mSculptTexture->getNumVolumes(); ++i)
  1014. {
  1015. LLVOVolume* volume = (*(mSculptTexture->getVolumeList()))[i];
  1016. if (volume != this && volume->getVolume() == getVolume())
  1017. {
  1018. gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE);
  1019. }
  1020. }
  1021. }
  1022. }
  1023. S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius)
  1024. {
  1025. S32 cur_detail;
  1026. if (LLPipeline::sDynamicLOD)
  1027. {
  1028. // We've got LOD in the profile, and in the twist. Use radius.
  1029. F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance;
  1030. cur_detail = LLVolumeLODGroup::getDetailFromTan(llround(tan_angle, 0.01f));
  1031. }
  1032. else
  1033. {
  1034. cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3);
  1035. }
  1036. return cur_detail;
  1037. }
  1038. BOOL LLVOVolume::calcLOD()
  1039. {
  1040. if (mDrawable.isNull())
  1041. {
  1042. return FALSE;
  1043. }
  1044. S32 cur_detail = 0;
  1045. F32 radius;
  1046. F32 distance;
  1047. if (mDrawable->isState(LLDrawable::RIGGED))
  1048. {
  1049. LLVOAvatar* avatar = getAvatar();
  1050. distance = avatar->mDrawable->mDistanceWRTCamera;
  1051. radius = avatar->getBinRadius();
  1052. }
  1053. else
  1054. {
  1055. distance = mDrawable->mDistanceWRTCamera;
  1056. radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length();
  1057. }
  1058. //hold onto unmodified distance for debugging
  1059. //F32 debug_distance = distance;
  1060. distance *= sDistanceFactor;
  1061. F32 rampDist = LLVOVolume::sLODFactor * 2;
  1062. if (distance < rampDist)
  1063. {
  1064. // Boost LOD when you're REALLY close
  1065. distance *= 1.0f/rampDist;
  1066. distance *= distance;
  1067. distance *= rampDist;
  1068. }
  1069. // DON'T Compensate for field of view changing on FOV zoom.
  1070. distance *= F_PI/3.f;
  1071. cur_detail = computeLODDetail(llround(distance, 0.01f),
  1072. llround(radius, 0.01f));
  1073. if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO))
  1074. {
  1075. //setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail));
  1076. setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex()));
  1077. }
  1078. if (cur_detail != mLOD)
  1079. {
  1080. mAppAngle = llround((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
  1081. mLOD = cur_detail;
  1082. return TRUE;
  1083. }
  1084. else
  1085. {
  1086. return FALSE;
  1087. }
  1088. }
  1089. BOOL LLVOVolume::updateLOD()
  1090. {
  1091. if (mDrawable.isNull())
  1092. {
  1093. return FALSE;
  1094. }
  1095. BOOL lod_changed = calcLOD();
  1096. if (lod_changed)
  1097. {
  1098. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
  1099. mLODChanged = TRUE;
  1100. }
  1101. else
  1102. {
  1103. F32 new_radius = getBinRadius();
  1104. F32 old_radius = mDrawable->getBinRadius();
  1105. if (new_radius < old_radius * 0.9f || new_radius > old_radius*1.1f)
  1106. {
  1107. gPipeline.markPartitionMove(mDrawable);
  1108. }
  1109. }
  1110. lod_changed = lod_changed || LLViewerObject::updateLOD();
  1111. return lod_changed;
  1112. }
  1113. BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp)
  1114. {
  1115. if (!LLViewerObject::setDrawableParent(parentp))
  1116. {
  1117. // no change in drawable parent
  1118. return FALSE;
  1119. }
  1120. if (!mDrawable->isRoot())
  1121. {
  1122. // rebuild vertices in parent relative space
  1123. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
  1124. if (mDrawable->isActive() && !parentp->isActive())
  1125. {
  1126. parentp->makeActive();
  1127. }
  1128. else if (mDrawable->isStatic() && parentp->isActive())
  1129. {
  1130. mDrawable->makeActive();
  1131. }
  1132. }
  1133. return TRUE;
  1134. }
  1135. void LLVOVolume::updateFaceFlags()
  1136. {
  1137. for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
  1138. {
  1139. LLFace *face = mDrawable->getFace(i);
  1140. if (!face)
  1141. {
  1142. return;
  1143. }
  1144. BOOL fullbright = getTE(i)->getFullbright();
  1145. face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT);
  1146. if (fullbright || (mMaterial == LL_MCODE_LIGHT))
  1147. {
  1148. face->setState(LLFace::FULLBRIGHT);
  1149. }
  1150. if (mDrawable->isLight())
  1151. {
  1152. face->setState(LLFace::LIGHT);
  1153. }
  1154. if (isHUDAttachment())
  1155. {
  1156. face->setState(LLFace::HUD_RENDER);
  1157. }
  1158. }
  1159. }
  1160. BOOL LLVOVolume::setParent(LLViewerObject* parent)
  1161. {
  1162. BOOL ret = FALSE ;
  1163. if (parent != getParent())
  1164. {
  1165. ret = LLViewerObject::setParent(parent);
  1166. if (ret && mDrawable)
  1167. {
  1168. gPipeline.markMoved(mDrawable);
  1169. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
  1170. }
  1171. }
  1172. return ret ;
  1173. }
  1174. // NOTE: regenFaces() MUST be followed by genTriangles()!
  1175. void LLVOVolume::regenFaces()
  1176. {
  1177. // remove existing faces
  1178. BOOL count_changed = mNumFaces != getNumTEs();
  1179. if (count_changed)
  1180. {
  1181. deleteFaces();
  1182. // add new faces
  1183. mNumFaces = getNumTEs();
  1184. }
  1185. for (S32 i = 0; i < mNumFaces; i++)
  1186. {
  1187. LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i);
  1188. facep->setTEOffset(i);
  1189. facep->setTexture(getTEImage(i));
  1190. facep->setViewerObject(this);
  1191. // If the face had media on it, this will have broken the link between the LLViewerMediaTexture and the face.
  1192. // Re-establish the link.
  1193. if((int)mMediaImplList.size() > i)
  1194. {
  1195. if(mMediaImplList[i])
  1196. {
  1197. LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[i]->getMediaTextureID()) ;
  1198. if(media_tex)
  1199. {
  1200. media_tex->addMediaToFace(facep) ;
  1201. }
  1202. }
  1203. }
  1204. }
  1205. if (!count_changed)
  1206. {
  1207. updateFaceFlags();
  1208. }
  1209. }
  1210. BOOL LLVOVolume::genBBoxes(BOOL force_global)
  1211. {
  1212. BOOL res = TRUE;
  1213. LLVector4a min,max;
  1214. min.clear();
  1215. max.clear();
  1216. BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED);
  1217. // bool rigged = false;
  1218. LLVolume* volume = mRiggedVolume;
  1219. if (!volume)
  1220. {
  1221. volume = getVolume();
  1222. }
  1223. for (S32 i = 0; i < getVolume()->getNumVolumeFaces(); i++)
  1224. {
  1225. LLFace *face = mDrawable->getFace(i);
  1226. if (!face)
  1227. {
  1228. continue;
  1229. }
  1230. res &= face->genVolumeBBoxes(*volume, i,
  1231. mRelativeXform, mRelativeXformInvTrans,
  1232. (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global);
  1233. if (rebuild)
  1234. {
  1235. if (i == 0)
  1236. {
  1237. min = face->mExtents[0];
  1238. max = face->mExtents[1];
  1239. }
  1240. else
  1241. {
  1242. min.setMin(min, face->mExtents[0]);
  1243. max.setMax(max, face->mExtents[1]);
  1244. }
  1245. }
  1246. }
  1247. if (rebuild)
  1248. {
  1249. mDrawable->setSpatialExtents(min,max);
  1250. min.add(max);
  1251. min.mul(0.5f);
  1252. mDrawable->setPositionGroup(min);
  1253. }
  1254. updateRadius();
  1255. mDrawable->movePartition();
  1256. return res;
  1257. }
  1258. void LLVOVolume::preRebuild()
  1259. {
  1260. if (mVolumeImpl != NULL)
  1261. {
  1262. mVolumeImpl->preRebuild();
  1263. }
  1264. }
  1265. void LLVOVolume::updateRelativeXform()
  1266. {
  1267. if (mVolumeImpl)
  1268. {
  1269. mVolumeImpl->updateRelativeXform();
  1270. return;
  1271. }
  1272. LLDrawable* drawable = mDrawable;
  1273. if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull())
  1274. { //rigged volume (which is in agent space) is used for generating bounding boxes etc
  1275. //inverse of render matrix should go to partition space
  1276. mRelativeXform = getRenderMatrix();
  1277. F32* dst = (F32*) mRelativeXformInvTrans.mMatrix;
  1278. F32* src = (F32*) mRelativeXform.mMatrix;
  1279. dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2];
  1280. dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6];
  1281. dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10];
  1282. mRelativeXform.invert();
  1283. mRelativeXformInvTrans.transpose();
  1284. }
  1285. else if (drawable->isActive())
  1286. {
  1287. // setup relative transforms
  1288. LLQuaternion delta_rot;
  1289. LLVector3 delta_pos, delta_scale;
  1290. //matrix from local space to parent relative/global space
  1291. delta_rot = drawable->isSpatialRoot() ? LLQuaternion() : mDrawable->getRotation();
  1292. delta_pos = drawable->isSpatialRoot() ? LLVector3(0,0,0) : mDrawable->getPosition();
  1293. delta_scale = mDrawable->getScale();
  1294. // Vertex transform (4x4)
  1295. LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot;
  1296. LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot;
  1297. LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot;
  1298. mRelativeXform.initRows(LLVector4(x_axis, 0.f),
  1299. LLVector4(y_axis, 0.f),
  1300. LLVector4(z_axis, 0.f),
  1301. LLVector4(delta_pos, 1.f));
  1302. // compute inverse transpose for normals
  1303. // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
  1304. // mRelativeXformInvTrans.invert();
  1305. // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
  1306. // grumble - invert is NOT a matrix invert, so we do it by hand:
  1307. LLMatrix3 rot_inverse = LLMatrix3(~delta_rot);
  1308. LLMatrix3 scale_inverse;
  1309. scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX],
  1310. LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY],
  1311. LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]);
  1312. mRelativeXformInvTrans = rot_inverse * scale_inverse;
  1313. mRelativeXformInvTrans.transpose();
  1314. }
  1315. else
  1316. {
  1317. LLVector3 pos = getPosition();
  1318. LLVector3 scale = getScale();
  1319. LLQuaternion rot = getRotation();
  1320. if (mParent)
  1321. {
  1322. pos *= mParent->getRotation();
  1323. pos += mParent->getPosition();
  1324. rot *= mParent->getRotation();
  1325. }
  1326. //LLViewerRegion* region = getRegion();
  1327. //pos += region->getOriginAgent();
  1328. LLVector3 x_axis = LLVector3(scale.mV[VX], 0.f, 0.f) * rot;
  1329. LLVector3 y_axis = LLVector3(0.f, scale.mV[VY], 0.f) * rot;
  1330. LLVector3 z_axis = LLVector3(0.f, 0.f, scale.mV[VZ]) * rot;
  1331. mRelativeXform.initRows(LLVector4(x_axis, 0.f),
  1332. LLVector4(y_axis, 0.f),
  1333. LLVector4(z_axis, 0.f),
  1334. LLVector4(pos, 1.f));
  1335. // compute inverse transpose for normals
  1336. LLMatrix3 rot_inverse = LLMatrix3(~rot);
  1337. LLMatrix3 scale_inverse;
  1338. scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX],
  1339. LLVector3(0.0, 1.0, 0.0) / scale.mV[VY],
  1340. LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]);
  1341. mRelativeXformInvTrans = rot_inverse * scale_inverse;
  1342. mRelativeXformInvTrans.transpose();
  1343. }
  1344. }
  1345. static LLFastTimer::DeclareTimer FTM_GEN_FLEX("Generate Flexies");
  1346. static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives");
  1347. static LLFastTimer::DeclareTimer FTM_UPDATE_RIGGED_VOLUME("Update Rigged");
  1348. BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
  1349. {
  1350. LLFastTimer t(FTM_UPDATE_PRIMITIVES);
  1351. if (mDrawable->isState(LLDrawable::REBUILD_RIGGED))
  1352. {
  1353. {
  1354. LLFastTimer t(FTM_UPDATE_RIGGED_VOLUME);
  1355. updateRiggedVolume();
  1356. }
  1357. genBBoxes(FALSE);
  1358. mDrawable->clearState(LLDrawable::REBUILD_RIGGED);
  1359. }
  1360. if (mVolumeImpl != NULL)
  1361. {
  1362. BOOL res;
  1363. {
  1364. LLFastTimer t(FTM_GEN_FLEX);
  1365. res = mVolumeImpl->doUpdateGeometry(drawable);
  1366. }
  1367. updateFaceFlags();
  1368. return res;
  1369. }
  1370. dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));
  1371. BOOL compiled = FALSE;
  1372. updateRelativeXform();
  1373. if (mDrawable.isNull()) // Not sure why this is happening, but it is...
  1374. {
  1375. return TRUE; // No update to complete
  1376. }
  1377. if (mVolumeChanged || mFaceMappingChanged )
  1378. {
  1379. compiled = TRUE;
  1380. if (mVolumeChanged)
  1381. {
  1382. LLFastTimer ftm(FTM_GEN_VOLUME);
  1383. LLVolumeParams volume_params = getVolume()->getParams();
  1384. setVolume(volume_params, 0);
  1385. drawable->setState(LLDrawable::REBUILD_VOLUME);
  1386. }
  1387. {
  1388. LLFastTimer t(FTM_GEN_TRIANGLES);
  1389. regenFaces();
  1390. genBBoxes(FALSE);
  1391. }
  1392. }
  1393. else if ((mLODChanged) || (mSculptChanged))
  1394. {
  1395. LLVolume *old_volumep, *new_volumep;
  1396. F32 old_lod, new_lod;
  1397. S32 old_num_faces, new_num_faces ;
  1398. old_volumep = getVolume();
  1399. old_lod = old_volumep->getDetail();
  1400. old_num_faces = old_volumep->getNumFaces() ;
  1401. old_volumep = NULL ;
  1402. {
  1403. LLFastTimer ftm(FTM_GEN_VOLUME);
  1404. LLVolumeParams volume_params = getVolume()->getParams();
  1405. setVolume(volume_params, 0);
  1406. }
  1407. new_volumep = getVolume();
  1408. new_lod = new_volumep->getDetail();
  1409. new_num_faces = new_volumep->getNumFaces() ;
  1410. new_volumep = NULL ;
  1411. if ((new_lod != old_lod) || mSculptChanged)
  1412. {
  1413. compiled = TRUE;
  1414. sNumLODChanges += new_num_faces ;
  1415. if((S32)getNumTEs() != getVolume()->getNumFaces())
  1416. {
  1417. setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces.
  1418. }
  1419. drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
  1420. {
  1421. LLFastTimer t(FTM_GEN_TRIANGLES);
  1422. if (new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs())
  1423. {
  1424. regenFaces();
  1425. }
  1426. genBBoxes(FALSE);
  1427. if (mSculptChanged)
  1428. { //changes in sculpt maps can thrash an object bounding box without
  1429. //triggering a spatial group bounding box update -- force spatial group
  1430. //to update bounding boxes
  1431. LLSpatialGroup* group = mDrawable->getSpatialGroup();
  1432. if (group)
  1433. {
  1434. group->unbound();
  1435. }
  1436. }
  1437. }
  1438. }
  1439. }
  1440. // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local
  1441. else
  1442. {
  1443. compiled = TRUE;
  1444. // All it did was move or we changed the texture coordinate offset
  1445. LLFastTimer t(FTM_GEN_TRIANGLES);
  1446. genBBoxes(FALSE);
  1447. }
  1448. // Update face flags
  1449. updateFaceFlags();
  1450. if(compiled)
  1451. {
  1452. LLPipeline::sCompiles++;
  1453. }
  1454. mVolumeChanged = FALSE;
  1455. mLODChanged = FALSE;
  1456. mSculptChanged = FALSE;
  1457. mFaceMappingChanged = FALSE;
  1458. return LLViewerObject::updateGeometry(drawable);
  1459. }
  1460. void LLVOVolume::updateFaceSize(S32 idx)
  1461. {
  1462. LLFace* facep = mDrawable->getFace(idx);
  1463. if (idx >= getVolume()->getNumVolumeFaces())
  1464. {
  1465. facep->setSize(0,0, true);
  1466. }
  1467. else
  1468. {
  1469. const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx);
  1470. facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices,
  1471. true); // <--- volume faces should be padded for 16-byte alignment
  1472. }
  1473. }
  1474. BOOL LLVOVolume::isRootEdit() const
  1475. {
  1476. if (mParent && !((LLViewerObject*)mParent)->isAvatar())
  1477. {
  1478. return FALSE;
  1479. }
  1480. return TRUE;
  1481. }
  1482. //virtual
  1483. void LLVOVolume::setNumTEs(const U8 num_tes)
  1484. {
  1485. const U8 old_num_tes = getNumTEs() ;
  1486. if(old_num_tes && old_num_tes < num_tes) //new faces added
  1487. {
  1488. LLViewerObject::setNumTEs(num_tes) ;
  1489. if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists.
  1490. {
  1491. mMediaImplList.resize(num_tes) ;
  1492. const LLTextureEntry* te = getTE(old_num_tes - 1) ;
  1493. for(U8 i = old_num_tes; i < num_tes ; i++)
  1494. {
  1495. setTE(i, *te) ;
  1496. mMediaImplList[i] = mMediaImplList[old_num_tes -1] ;
  1497. }
  1498. mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ;
  1499. }
  1500. }
  1501. else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed
  1502. {
  1503. U8 end = mMediaImplList.size() ;
  1504. for(U8 i = num_tes; i < end ; i++)
  1505. {
  1506. removeMediaImpl(i) ;
  1507. }
  1508. mMediaImplList.resize(num_tes) ;
  1509. LLViewerObject::setNumTEs(num_tes) ;
  1510. }
  1511. else
  1512. {
  1513. LLViewerObject::setNumTEs(num_tes) ;
  1514. }
  1515. return ;
  1516. }
  1517. void LLVOVolume::setTEImage(const U8 te, LLViewerTexture *imagep)
  1518. {
  1519. BOOL changed = (mTEImages[te] != imagep);
  1520. LLViewerObject::setTEImage(te, imagep);
  1521. if (changed)
  1522. {
  1523. gPipeline.markTextured(mDrawable);
  1524. mFaceMappingChanged = TRUE;
  1525. }
  1526. }
  1527. S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid)
  1528. {
  1529. S32 res = LLViewerObject::setTETexture(te, uuid);
  1530. if (res)
  1531. {
  1532. gPipeline.markTextured(mDrawable);
  1533. mFaceMappingChanged = TRUE;
  1534. }
  1535. return res;
  1536. }
  1537. S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color)
  1538. {
  1539. return setTEColor(te, LLColor4(color));
  1540. }
  1541. S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color)
  1542. {
  1543. S32 retval = 0;
  1544. const LLTextureEntry *tep = getTE(te);
  1545. if (!tep)
  1546. {
  1547. llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
  1548. }
  1549. else if (color != tep->getColor())
  1550. {
  1551. if (color.mV[3] != tep->getColor().mV[3])
  1552. {
  1553. gPipeline.markTextured(mDrawable);
  1554. }
  1555. retval = LLPrimitive::setTEColor(te, color);
  1556. if (mDrawable.notNull() && retval)
  1557. {
  1558. // These should only happen on updates which are not the initial update.
  1559. mDrawable->setState(LLDrawable::REBUILD_COLOR);
  1560. dirtyMesh();
  1561. }
  1562. }
  1563. return retval;
  1564. }
  1565. S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap)
  1566. {
  1567. S32 res = LLViewerObject::setTEBumpmap(te, bumpmap);
  1568. if (res)
  1569. {
  1570. gPipeline.markTextured(mDrawable);
  1571. mFaceMappingChanged = TRUE;
  1572. }
  1573. return res;
  1574. }
  1575. S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen)
  1576. {
  1577. S32 res = LLViewerObject::setTETexGen(te, texgen);
  1578. if (res)
  1579. {
  1580. gPipeline.markTextured(mDrawable);
  1581. mFaceMappingChanged = TRUE;
  1582. }
  1583. return res;
  1584. }
  1585. S32 LLVOVolume::setTEMediaTexGen(const U8 te, const U8 media)
  1586. {
  1587. S32 res = LLViewerObject::setTEMediaTexGen(te, media);
  1588. if (res)
  1589. {
  1590. gPipeline.markTextured(mDrawable);
  1591. mFaceMappingChanged = TRUE;
  1592. }
  1593. return res;
  1594. }
  1595. S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny)
  1596. {
  1597. S32 res = LLViewerObject::setTEShiny(te, shiny);
  1598. if (res)
  1599. {
  1600. gPipeline.markTextured(mDrawable);
  1601. mFaceMappingChanged = TRUE;
  1602. }
  1603. return res;
  1604. }
  1605. S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright)
  1606. {
  1607. S32 res = LLViewerObject::setTEFullbright(te, fullbright);
  1608. if (res)
  1609. {
  1610. gPipeline.markTextured(mDrawable);
  1611. mFaceMappingChanged = TRUE;
  1612. }
  1613. return res;
  1614. }
  1615. S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump)
  1616. {
  1617. S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump);
  1618. if (res)
  1619. {
  1620. gPipeline.markTextured(mDrawable);
  1621. mFaceMappingChanged = TRUE;
  1622. }
  1623. return res;
  1624. }
  1625. S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags)
  1626. {
  1627. S32 res = LLViewerObject::setTEMediaFlags(te, media_flags);
  1628. if (res)
  1629. {
  1630. gPipeline.markTextured(mDrawable);
  1631. mFaceMappingChanged = TRUE;
  1632. }
  1633. return res;
  1634. }
  1635. S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow)
  1636. {
  1637. S32 res = LLViewerObject::setTEGlow(te, glow);
  1638. if (res)
  1639. {
  1640. gPipeline.markTextured(mDrawable);
  1641. mFaceMappingChanged = TRUE;
  1642. }
  1643. return res;
  1644. }
  1645. S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t)
  1646. {
  1647. S32 res = LLViewerObject::setTEScale(te, s, t);
  1648. if (res)
  1649. {
  1650. gPipeline.markTextured(mDrawable);
  1651. mFaceMappingChanged = TRUE;
  1652. }
  1653. return res;
  1654. }
  1655. S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s)
  1656. {
  1657. S32 res = LLViewerObject::setTEScaleS(te, s);
  1658. if (res)
  1659. {
  1660. gPipeline.markTextured(mDrawable);
  1661. mFaceMappingChanged = TRUE;
  1662. }
  1663. return res;
  1664. }
  1665. S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t)
  1666. {
  1667. S32 res = LLViewerObject::setTEScaleT(te, t);
  1668. if (res)
  1669. {
  1670. gPipeline.markTextured(mDrawable);
  1671. mFaceMappingChanged = TRUE;
  1672. }
  1673. return res;
  1674. }
  1675. void LLVOVolume::updateTEData()
  1676. {
  1677. /*if (mDrawable.notNull())
  1678. {
  1679. mFaceMappingChanged = TRUE;
  1680. gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE);
  1681. }*/
  1682. }
  1683. bool LLVOVolume::hasMedia() const
  1684. {
  1685. bool result = false;
  1686. const U8 numTEs = getNumTEs();
  1687. for (U8 i = 0; i < numTEs; i++)
  1688. {
  1689. const LLTextureEntry* te = getTE(i);
  1690. if(te->hasMedia())
  1691. {
  1692. result = true;
  1693. break;
  1694. }
  1695. }
  1696. return result;
  1697. }
  1698. LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id)
  1699. {
  1700. LLVolume* volume = getVolume();
  1701. LLVector4a result;
  1702. result.clear();
  1703. LLVector3 ret;
  1704. if (volume && face_id < volume->getNumVolumeFaces())
  1705. {
  1706. const LLVolumeFace& face = volume->getVolumeFace(face_id);
  1707. for (S32 i = 0; i < (S32)face.mNumVertices; ++i)
  1708. {
  1709. result.add(face.mNormals[i]);
  1710. }
  1711. LLVector3 ret(result.getF32ptr());
  1712. ret = volumeDirectionToAgent(ret);
  1713. ret.normVec();
  1714. }
  1715. return ret;
  1716. }
  1717. void LLVOVolume::requestMediaDataUpdate(bool isNew)
  1718. {
  1719. if (sObjectMediaClient)
  1720. sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew));
  1721. }
  1722. bool LLVOVolume::isMediaDataBeingFetched() const
  1723. {
  1724. // I know what I'm doing by const_casting this away: this is just
  1725. // a wrapper class that is only going to do a lookup.
  1726. return (sObjectMediaClient) ? sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false)) : false;
  1727. }
  1728. void LLVOVolume::cleanUpMediaImpls()
  1729. {
  1730. // Iterate through our TEs and remove any Impls that are no longer used
  1731. const U8 numTEs = getNumTEs();
  1732. for (U8 i = 0; i < numTEs; i++)
  1733. {
  1734. const LLTextureEntry* te = getTE(i);
  1735. if( ! te->hasMedia())
  1736. {
  1737. // Delete the media IMPL!
  1738. removeMediaImpl(i) ;
  1739. }
  1740. }
  1741. }
  1742. void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version)
  1743. {
  1744. // media_data_array is an array of media entry maps
  1745. // media_version is the version string in the response.
  1746. U32 fetched_version = LLTextureEntry::getVersionFromMediaVersionString(media_version);
  1747. // Only update it if it is newer!
  1748. if ( (S32)fetched_version > mLastFetchedMediaVersion)
  1749. {
  1750. mLastFetchedMediaVersion = fetched_version;
  1751. //llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl;
  1752. LLSD::array_const_iterator iter = media_data_array.beginArray();
  1753. LLSD::array_const_iterator end = media_data_array.endArray();
  1754. U8 texture_index = 0;
  1755. for (; iter != end; ++iter, ++texture_index)
  1756. {
  1757. syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/);
  1758. }
  1759. }
  1760. }
  1761. void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool merge, bool ignore_agent)
  1762. {
  1763. if(mDead)
  1764. {
  1765. // If the object has been marked dead, don't process media updates.
  1766. return;
  1767. }
  1768. LLTextureEntry *te = getTE(texture_index);
  1769. if(!te)
  1770. {
  1771. return ;
  1772. }
  1773. LL_DEBUGS("MediaOnAPrim") << "BEFORE: texture_index = " << texture_index
  1774. << " hasMedia = " << te->hasMedia() << " : "
  1775. << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl;
  1776. std::string previous_url;
  1777. LLMediaEntry* mep = te->getMediaData();
  1778. if(mep)
  1779. {
  1780. // Save the "current url" from before the update so we can tell if
  1781. // it changes.
  1782. previous_url = mep->getCurrentURL();
  1783. }
  1784. if (merge)
  1785. {
  1786. te->mergeIntoMediaData(media_data);
  1787. }
  1788. else {
  1789. // XXX Question: what if the media data is undefined LLSD, but the
  1790. // update we got above said that we have media flags?? Here we clobber
  1791. // that, assuming the data from the service is more up-to-date.
  1792. te->updateMediaData(media_data);
  1793. }
  1794. mep = te->getMediaData();
  1795. if(mep)
  1796. {
  1797. bool update_from_self = false;
  1798. if (!ignore_agent)
  1799. {
  1800. LLUUID updating_agent = LLTextureEntry::getAgentIDFromMediaVersionString(getMediaURL());
  1801. update_from_self = (updating_agent == gAgent.getID());
  1802. }
  1803. viewer_media_t media_impl = LLViewerMedia::updateMediaImpl(mep, previous_url, update_from_self);
  1804. addMediaImpl(media_impl, texture_index) ;
  1805. }
  1806. else
  1807. {
  1808. removeMediaImpl(texture_index);
  1809. }
  1810. LL_DEBUGS("MediaOnAPrim") << "AFTER: texture_index = " << texture_index
  1811. << " hasMedia = " << te->hasMedia() << " : "
  1812. << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl;
  1813. }
  1814. void LLVOVolume::mediaNavigateBounceBack(U8 texture_index)
  1815. {
  1816. // Find the media entry for this navigate
  1817. const LLMediaEntry* mep = NULL;
  1818. viewer_media_t impl = getMediaImpl(texture_index);
  1819. LLTextureEntry *te = getTE(texture_index);
  1820. if(te)
  1821. {
  1822. mep = te->getMediaData();
  1823. }
  1824. if (mep && impl)
  1825. {
  1826. std::string url = mep->getCurrentURL();
  1827. // Look for a ":", if not there, assume "http://"
  1828. if (!url.empty() && std::string::npos == url.find(':'))
  1829. {
  1830. url = "http://" + url;
  1831. }
  1832. // If the url we're trying to "bounce back" to is either empty or not
  1833. // allowed by the whitelist, try the home url. If *that* doesn't work,
  1834. // set the media as failed and unload it
  1835. if (url.empty() || !mep->checkCandidateUrl(url))
  1836. {
  1837. url = mep->getHomeURL();
  1838. // Look for a ":", if not there, assume "http://"
  1839. if (!url.empty() && std::string::npos == url.find(':'))
  1840. {
  1841. url = "http://" + url;
  1842. }
  1843. }
  1844. if (url.empty() || !mep->checkCandidateUrl(url))
  1845. {
  1846. // The url to navigate back to is not good, and we have nowhere else
  1847. // to go.
  1848. LL_WARNS("MediaOnAPrim") << "FAILED to bounce back URL \"" << url << "\" -- unloading impl" << LL_ENDL;
  1849. impl->setMediaFailed(true);
  1850. }
  1851. else {
  1852. // Okay, navigate now
  1853. LL_INFOS("MediaOnAPrim") << "bouncing back to URL: " << url << LL_ENDL;
  1854. impl->navigateTo(url, "", false, true);
  1855. }
  1856. }
  1857. }
  1858. bool LLVOVolume::hasMediaPermission(const LLMediaEntry* media_entry, MediaPermType perm_type)
  1859. {
  1860. // NOTE: This logic ALMOST duplicates the logic in the server (in particular, in llmediaservice.cpp).
  1861. if (NULL == media_entry ) return false; // XXX should we assert here?
  1862. // The agent has permissions if:
  1863. // - world permissions are on, or
  1864. // - group permissions are on, and agent_id is in the group, or
  1865. // - agent permissions are on, and agent_id is the owner
  1866. // *NOTE: We *used* to check for modify permissions here (i.e. permissions were
  1867. // granted if permModify() was true). However, this doesn't make sense in the
  1868. // viewer: we don't want to show controls or allow interaction if the author
  1869. // has deemed it so. See DEV-42115.
  1870. U8 media_perms = (perm_type == MEDIA_PERM_INTERACT) ? media_entry->getPermsInteract() : media_entry->getPermsControl();
  1871. // World permissions
  1872. if (0 != (media_perms & LLMediaEntry::PERM_ANYONE))
  1873. {
  1874. return true;
  1875. }
  1876. // Group permissions
  1877. else if (0 != (media_perms & LLMediaEntry::PERM_GROUP))
  1878. {
  1879. LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this);
  1880. if (obj_perm && gAgent.isInGroup(obj_perm->getGroup()))
  1881. {
  1882. return true;
  1883. }
  1884. }
  1885. // Owner permissions
  1886. else if (0 != (media_perms & LLMediaEntry::PERM_OWNER) && permYouOwner())
  1887. {
  1888. return true;
  1889. }
  1890. return false;
  1891. }
  1892. void LLVOVolume::mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location)
  1893. {
  1894. bool block_navigation = false;
  1895. // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed
  1896. // to deal with multiple face indices.
  1897. int face_index = getFaceIndexWithMediaImpl(impl, -1);
  1898. // Find the media entry for this navigate
  1899. LLMediaEntry* mep = NULL;
  1900. LLTextureEntry *te = getTE(face_index);
  1901. if(te)
  1902. {
  1903. mep = te->getMediaData();
  1904. }
  1905. if(mep)
  1906. {
  1907. if(!mep->checkCandidateUrl(new_location))
  1908. {
  1909. block_navigation = true;
  1910. }
  1911. if (!block_navigation && !hasMediaPermission(mep, MEDIA_PERM_INTERACT))
  1912. {
  1913. block_navigation = true;
  1914. }
  1915. }
  1916. else
  1917. {
  1918. LL_WARNS("MediaOnAPrim") << "Couldn't find media entry!" << LL_ENDL;
  1919. }
  1920. if(block_navigation)
  1921. {
  1922. LL_INFOS("MediaOnAPrim") << "blocking navigate to URI " << new_location << LL_ENDL;
  1923. // "bounce back" to the current URL from the media entry
  1924. mediaNavigateBounceBack(face_index);
  1925. }
  1926. else if (sObjectMediaNavigateClient)
  1927. {
  1928. LL_DEBUGS("MediaOnAPrim") << "broadcasting navigate with URI " << new_location << LL_ENDL;
  1929. sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this, false), face_index, new_location);
  1930. }
  1931. }
  1932. void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event)
  1933. {
  1934. switch(event)
  1935. {
  1936. case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED:
  1937. {
  1938. switch(impl->getNavState())
  1939. {
  1940. case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED:
  1941. {
  1942. // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back.
  1943. mediaNavigated(impl, plugin, plugin->getLocation());
  1944. }
  1945. break;
  1946. case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED_SPURIOUS:
  1947. // This navigate didn't change the current URL.
  1948. LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL;
  1949. break;
  1950. case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED:
  1951. // This is the first location changed event after the start of a server-directed nav. Don't broadcast it.
  1952. LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL;
  1953. break;
  1954. default:
  1955. // This is a subsequent location-changed due to a redirect. Don't broadcast.
  1956. LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (redirect)" << LL_ENDL;
  1957. break;
  1958. }
  1959. }
  1960. break;
  1961. case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE:
  1962. {
  1963. switch(impl->getNavState())
  1964. {
  1965. case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED:
  1966. {
  1967. // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast or bounced back.
  1968. mediaNavigated(impl, plugin, plugin->getNavigateURI());
  1969. }
  1970. break;
  1971. case LLViewerMediaImpl::MEDIANAVSTATE_COMPLETE_BEFORE_LOCATION_CHANGED_SPURIOUS:
  1972. // This navigate didn't change the current URL.
  1973. LL_DEBUGS("MediaOnAPrim") << " NOT broadcasting navigate (spurious)" << LL_ENDL;
  1974. break;
  1975. case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_COMPLETE_BEFORE_LOCATION_CHANGED:
  1976. // This is the the navigate complete event from a server-directed nav. Don't broadcast it.
  1977. LL_INFOS("MediaOnAPrim") << " NOT broadcasting navigate (server-directed)" << LL_ENDL;
  1978. break;
  1979. default:
  1980. // For all other states, the navigate should have been handled by LOCATION_CHANGED events already.
  1981. break;
  1982. }
  1983. }
  1984. break;
  1985. default:
  1986. break;
  1987. }
  1988. }
  1989. void LLVOVolume::sendMediaDataUpdate()
  1990. {
  1991. if (sObjectMediaClient)
  1992. sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this, false));
  1993. }
  1994. void LLVOVolume::removeMediaImpl(S32 texture_index)
  1995. {
  1996. if(mMediaImplList.size() <= (U32)texture_index || mMediaImplList[texture_index].isNull())
  1997. {
  1998. return ;
  1999. }
  2000. //make the face referencing to mMediaImplList[texture_index] to point back to the old texture.
  2001. if(mDrawable && texture_index < mDrawable->getNumFaces())
  2002. {
  2003. LLFace* facep = mDrawable->getFace(texture_index) ;
  2004. if(facep)
  2005. {
  2006. LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ;
  2007. if(media_tex)
  2008. {
  2009. media_tex->removeMediaFromFace(facep) ;
  2010. }
  2011. }
  2012. }
  2013. //check if some other face(s) of this object reference(s)to this media impl.
  2014. S32 i ;
  2015. S32 end = (S32)mMediaImplList.size() ;
  2016. for(i = 0; i < end ; i++)
  2017. {
  2018. if( i != texture_index && mMediaImplList[i] == mMediaImplList[texture_index])
  2019. {
  2020. break ;
  2021. }
  2022. }
  2023. if(i == end) //this object does not need this media impl.
  2024. {
  2025. mMediaImplList[texture_index]->removeObject(this) ;
  2026. }
  2027. mMediaImplList[texture_index] = NULL ;
  2028. return ;
  2029. }
  2030. void LLVOVolume::addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index)
  2031. {
  2032. if((S32)mMediaImplList.size() < texture_index + 1)
  2033. {
  2034. mMediaImplList.resize(texture_index + 1) ;
  2035. }
  2036. if(mMediaImplList[texture_index].notNull())
  2037. {
  2038. if(mMediaImplList[texture_index] == media_impl)
  2039. {
  2040. return ;
  2041. }
  2042. removeMediaImpl(texture_index) ;
  2043. }
  2044. mMediaImplList[texture_index] = media_impl;
  2045. media_impl->addObject(this) ;
  2046. //add the face to show the media if it is in playing
  2047. if(mDrawable)
  2048. {
  2049. LLFace* facep = mDrawable->getFace(texture_index) ;
  2050. if(facep)
  2051. {
  2052. LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ;
  2053. if(media_tex)
  2054. {
  2055. media_tex->addMediaToFace(facep) ;
  2056. }
  2057. }
  2058. else //the face is not available now, start media on this face later.
  2059. {
  2060. media_impl->setUpdated(TRUE) ;
  2061. }
  2062. }
  2063. return ;
  2064. }
  2065. viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const
  2066. {
  2067. if(mMediaImplList.size() > face_id)
  2068. {
  2069. return mMediaImplList[face_id];
  2070. }
  2071. return NULL;
  2072. }
  2073. F64 LLVOVolume::getTotalMediaInterest() const
  2074. {
  2075. // If this object is currently focused, this object has "high" interest
  2076. if (LLViewerMediaFocus::getInstance()->getFocusedObjectID() == getID())
  2077. return F64_MAX;
  2078. F64 interest = (F64)-1.0; // means not interested;
  2079. // If this object is selected, this object has "high" interest, but since
  2080. // there can be more than one, we still add in calculated impl interest
  2081. // XXX Sadly, 'contains()' doesn't take a const :(
  2082. if (LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this)))
  2083. interest = F64_MAX / 2.0;
  2084. int i = 0;
  2085. const int end = getNumTEs();
  2086. for ( ; i < end; ++i)
  2087. {
  2088. const viewer_media_t &impl = getMediaImpl(i);
  2089. if (!impl.isNull())
  2090. {
  2091. if (interest == (F64)-1.0) interest = (F64)0.0;
  2092. interest += impl->getInterest();
  2093. }
  2094. }
  2095. return interest;
  2096. }
  2097. S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id)
  2098. {
  2099. S32 end = (S32)mMediaImplList.size() ;
  2100. for(S32 face_id = start_face_id + 1; face_id < end; face_id++)
  2101. {
  2102. if(mMediaImplList[face_id] == media_impl)
  2103. {
  2104. return face_id ;
  2105. }
  2106. }
  2107. return -1 ;
  2108. }
  2109. //----------------------------------------------------------------------------
  2110. void LLVOVolume::setLightTextureID(LLUUID id)
  2111. {
  2112. if (id.notNull())
  2113. {
  2114. if (!hasLightTexture())
  2115. {
  2116. setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true);
  2117. }
  2118. LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
  2119. if (param_block && param_block->getLightTexture() != id)
  2120. {
  2121. param_block->setLightTexture(id);
  2122. parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true);
  2123. }
  2124. }
  2125. else
  2126. {
  2127. if (hasLightTexture())
  2128. {
  2129. setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true);
  2130. mLightTexture = NULL;
  2131. }
  2132. }
  2133. }
  2134. void LLVOVolume::setSpotLightParams(LLVector3 params)
  2135. {
  2136. LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
  2137. if (param_block && param_block->getParams() != params)
  2138. {
  2139. param_block->setParams(params);
  2140. parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true);
  2141. }
  2142. }
  2143. void LLVOVolume::setIsLight(BOOL is_light)
  2144. {
  2145. if (is_light != getIsLight())
  2146. {
  2147. if (is_light)
  2148. {
  2149. setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, TRUE, true);
  2150. }
  2151. else
  2152. {
  2153. setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, FALSE, true);
  2154. }
  2155. if (is_light)
  2156. {
  2157. // Add it to the pipeline mLightSet
  2158. gPipeline.setLight(mDrawable, TRUE);
  2159. }
  2160. else
  2161. {
  2162. // Not a light. Remove it from the pipeline's light set.
  2163. gPipeline.setLight(mDrawable, FALSE);
  2164. }
  2165. }
  2166. }
  2167. void LLVOVolume::setLightColor(const LLColor3& color)
  2168. {
  2169. LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
  2170. if (param_block)
  2171. {
  2172. if (param_block->getColor() != color)
  2173. {
  2174. param_block->setColor(LLColor4(color, param_block->getColor().mV[3]));
  2175. parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
  2176. gPipeline.markTextured(mDrawable);
  2177. mFaceMappingChanged = TRUE;
  2178. }
  2179. }
  2180. }
  2181. void LLVOVolume::setLightIntensity(F32 intensity)
  2182. {
  2183. LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
  2184. if (param_block)
  2185. {
  2186. if (param_block->getColor().mV[3] != intensity)
  2187. {
  2188. param_block->setColor(LLColor4(LLColor3(param_block->getColor()), intensity));
  2189. parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
  2190. }
  2191. }
  2192. }
  2193. void LLVOVolume::setLightRadius(F32 radius)
  2194. {
  2195. LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
  2196. if (param_block)
  2197. {
  2198. if (param_block->getRadius() != radius)
  2199. {
  2200. param_block->setRadius(radius);
  2201. parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
  2202. }
  2203. }
  2204. }
  2205. void LLVOVolume::setLightFalloff(F32 falloff)
  2206. {
  2207. LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
  2208. if (param_block)
  2209. {
  2210. if (param_block->getFalloff() != falloff)
  2211. {
  2212. param_block->setFalloff(falloff);
  2213. parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
  2214. }
  2215. }
  2216. }
  2217. void LLVOVolume::setLightCutoff(F32 cutoff)
  2218. {
  2219. LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
  2220. if (param_block)
  2221. {
  2222. if (param_block->getCutoff() != cutoff)
  2223. {
  2224. param_block->setCutoff(cutoff);
  2225. parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
  2226. }
  2227. }
  2228. }
  2229. //---------------------------------