PageRenderTime 56ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/newview/llspatialpartition.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2720 lines | 2118 code | 432 blank | 170 comment | 317 complexity | 905d06b0391037b1a5379e498573db63 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llspatialpartition.cpp
  3. * @brief LLSpatialGroup class implementation and supporting functions
  4. *
  5. * $LicenseInfo:firstyear=2003&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 "llspatialpartition.h"
  28. #include "llappviewer.h"
  29. #include "lltexturecache.h"
  30. #include "lltexturefetch.h"
  31. #include "llimageworker.h"
  32. #include "llviewerwindow.h"
  33. #include "llviewerobjectlist.h"
  34. #include "llvovolume.h"
  35. #include "llvolume.h"
  36. #include "llvolumeoctree.h"
  37. #include "llviewercamera.h"
  38. #include "llface.h"
  39. #include "llfloatertools.h"
  40. #include "llviewercontrol.h"
  41. #include "llviewerregion.h"
  42. #include "llcamera.h"
  43. #include "pipeline.h"
  44. #include "llmeshrepository.h"
  45. #include "llrender.h"
  46. #include "lloctree.h"
  47. #include "llphysicsshapebuilderutil.h"
  48. #include "llvoavatar.h"
  49. #include "llvolumemgr.h"
  50. #include "lltextureatlas.h"
  51. #include "llglslshader.h"
  52. #include "llviewershadermgr.h"
  53. static LLFastTimer::DeclareTimer FTM_FRUSTUM_CULL("Frustum Culling");
  54. static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound");
  55. const F32 SG_OCCLUSION_FUDGE = 0.25f;
  56. #define SG_DISCARD_TOLERANCE 0.01f
  57. #if LL_OCTREE_PARANOIA_CHECK
  58. #define assert_octree_valid(x) x->validate()
  59. #define assert_states_valid(x) ((LLSpatialGroup*) x->mSpatialPartition->mOctree->getListener(0))->checkStates()
  60. #else
  61. #define assert_octree_valid(x)
  62. #define assert_states_valid(x)
  63. #endif
  64. static U32 sZombieGroups = 0;
  65. U32 LLSpatialGroup::sNodeCount = 0;
  66. #define LL_TRACK_PENDING_OCCLUSION_QUERIES 0
  67. std::set<GLuint> LLSpatialGroup::sPendingQueries;
  68. U32 gOctreeMaxCapacity;
  69. BOOL LLSpatialGroup::sNoDelete = FALSE;
  70. static F32 sLastMaxTexPriority = 1.f;
  71. static F32 sCurMaxTexPriority = 1.f;
  72. class LLOcclusionQueryPool : public LLGLNamePool
  73. {
  74. protected:
  75. virtual GLuint allocateName()
  76. {
  77. GLuint name;
  78. glGenQueriesARB(1, &name);
  79. return name;
  80. }
  81. virtual void releaseName(GLuint name)
  82. {
  83. #if LL_TRACK_PENDING_OCCLUSION_QUERIES
  84. LLSpatialGroup::sPendingQueries.erase(name);
  85. #endif
  86. glDeleteQueriesARB(1, &name);
  87. }
  88. };
  89. static LLOcclusionQueryPool sQueryPool;
  90. //static counter for frame to switch LOD on
  91. void sg_assert(BOOL expr)
  92. {
  93. #if LL_OCTREE_PARANOIA_CHECK
  94. if (!expr)
  95. {
  96. llerrs << "Octree invalid!" << llendl;
  97. }
  98. #endif
  99. }
  100. S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad)
  101. {
  102. return AABBSphereIntersectR2(min, max, origin, rad*rad);
  103. }
  104. S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &r)
  105. {
  106. F32 d = 0.f;
  107. F32 t;
  108. if ((min-origin).magVecSquared() < r &&
  109. (max-origin).magVecSquared() < r)
  110. {
  111. return 2;
  112. }
  113. for (U32 i = 0; i < 3; i++)
  114. {
  115. if (origin.mV[i] < min.mV[i])
  116. {
  117. t = min.mV[i] - origin.mV[i];
  118. d += t*t;
  119. }
  120. else if (origin.mV[i] > max.mV[i])
  121. {
  122. t = origin.mV[i] - max.mV[i];
  123. d += t*t;
  124. }
  125. if (d > r)
  126. {
  127. return 0;
  128. }
  129. }
  130. return 1;
  131. }
  132. S32 AABBSphereIntersect(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &rad)
  133. {
  134. return AABBSphereIntersectR2(min, max, origin, rad*rad);
  135. }
  136. S32 AABBSphereIntersectR2(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &r)
  137. {
  138. F32 d = 0.f;
  139. F32 t;
  140. LLVector4a origina;
  141. origina.load3(origin.mV);
  142. LLVector4a v;
  143. v.setSub(min, origina);
  144. if (v.dot3(v) < r)
  145. {
  146. v.setSub(max, origina);
  147. if (v.dot3(v) < r)
  148. {
  149. return 2;
  150. }
  151. }
  152. for (U32 i = 0; i < 3; i++)
  153. {
  154. if (origin.mV[i] < min[i])
  155. {
  156. t = min[i] - origin.mV[i];
  157. d += t*t;
  158. }
  159. else if (origin.mV[i] > max[i])
  160. {
  161. t = origin.mV[i] - max[i];
  162. d += t*t;
  163. }
  164. if (d > r)
  165. {
  166. return 0;
  167. }
  168. }
  169. return 1;
  170. }
  171. typedef enum
  172. {
  173. b000 = 0x00,
  174. b001 = 0x01,
  175. b010 = 0x02,
  176. b011 = 0x03,
  177. b100 = 0x04,
  178. b101 = 0x05,
  179. b110 = 0x06,
  180. b111 = 0x07,
  181. } eLoveTheBits;
  182. //contact Runitai Linden for a copy of the SL object used to write this table
  183. //basically, you give the table a bitmask of the look-at vector to a node and it
  184. //gives you a triangle fan index array
  185. static U16 sOcclusionIndices[] =
  186. {
  187. //000
  188. b111, b110, b010, b011, b001, b101, b100, b110,
  189. //001
  190. b011, b010, b000, b001, b101, b111, b110, b010,
  191. //010
  192. b101, b100, b110, b111, b011, b001, b000, b100,
  193. //011
  194. b001, b000, b100, b101, b111, b011, b010, b000,
  195. //100
  196. b110, b000, b010, b011, b111, b101, b100, b000,
  197. //101
  198. b010, b100, b000, b001, b011, b111, b110, b100,
  199. //110
  200. b100, b010, b110, b111, b101, b001, b000, b010,
  201. //111
  202. b000, b110, b100, b101, b001, b011, b010, b110,
  203. };
  204. U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center)
  205. {
  206. LLVector4a origin;
  207. origin.load3(camera->getOrigin().mV);
  208. S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7;
  209. return cypher*8;
  210. }
  211. U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center)
  212. {
  213. LLVector4a origin;
  214. origin.load3(camera->getOrigin().mV);
  215. S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7;
  216. return (U8*) (sOcclusionIndices+cypher*8);
  217. }
  218. static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion");
  219. void LLSpatialGroup::buildOcclusion()
  220. {
  221. if (mOcclusionVerts.isNull())
  222. {
  223. mOcclusionVerts = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX,
  224. LLVertexBuffer::sUseStreamDraw ? mBufferUsage : 0); //if GL has a hard time with VBOs, don't use them for occlusion culling.
  225. mOcclusionVerts->allocateBuffer(8, 64, true);
  226. LLStrider<U16> idx;
  227. mOcclusionVerts->getIndexStrider(idx);
  228. for (U32 i = 0; i < 64; i++)
  229. {
  230. *idx++ = sOcclusionIndices[i];
  231. }
  232. }
  233. LLVector4a fudge;
  234. fudge.splat(SG_OCCLUSION_FUDGE);
  235. LLVector4a r;
  236. r.setAdd(mBounds[1], fudge);
  237. LLStrider<LLVector3> pos;
  238. {
  239. LLFastTimer t(FTM_BUILD_OCCLUSION);
  240. mOcclusionVerts->getVertexStrider(pos);
  241. }
  242. {
  243. LLVector4a* v = (LLVector4a*) pos.get();
  244. const LLVector4a& c = mBounds[0];
  245. const LLVector4a& s = r;
  246. static const LLVector4a octant[] =
  247. {
  248. LLVector4a(-1.f, -1.f, -1.f),
  249. LLVector4a(-1.f, -1.f, 1.f),
  250. LLVector4a(-1.f, 1.f, -1.f),
  251. LLVector4a(-1.f, 1.f, 1.f),
  252. LLVector4a(1.f, -1.f, -1.f),
  253. LLVector4a(1.f, -1.f, 1.f),
  254. LLVector4a(1.f, 1.f, -1.f),
  255. LLVector4a(1.f, 1.f, 1.f),
  256. };
  257. //vertex positions are encoded so the 3 bits of their vertex index
  258. //correspond to their axis facing, with bit position 3,2,1 matching
  259. //axis facing x,y,z, bit set meaning positive facing, bit clear
  260. //meaning negative facing
  261. for (S32 i = 0; i < 8; ++i)
  262. {
  263. LLVector4a p;
  264. p.setMul(s, octant[i]);
  265. p.add(c);
  266. v[i] = p;
  267. }
  268. }
  269. {
  270. mOcclusionVerts->flush();
  271. LLVertexBuffer::unbind();
  272. }
  273. clearState(LLSpatialGroup::OCCLUSION_DIRTY);
  274. }
  275. BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group);
  276. //returns:
  277. // 0 if sphere and AABB are not intersecting
  278. // 1 if they are
  279. // 2 if AABB is entirely inside sphere
  280. S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3& pos, const F32 &rad)
  281. {
  282. S32 ret = 2;
  283. LLVector3 min = center - size;
  284. LLVector3 max = center + size;
  285. for (U32 i = 0; i < 3; i++)
  286. {
  287. if (min.mV[i] > pos.mV[i] + rad ||
  288. max.mV[i] < pos.mV[i] - rad)
  289. { //totally outside
  290. return 0;
  291. }
  292. if (min.mV[i] < pos.mV[i] - rad ||
  293. max.mV[i] > pos.mV[i] + rad)
  294. { //intersecting
  295. ret = 1;
  296. }
  297. }
  298. return ret;
  299. }
  300. LLSpatialGroup::~LLSpatialGroup()
  301. {
  302. /*if (sNoDelete)
  303. {
  304. llerrs << "Illegal deletion of LLSpatialGroup!" << llendl;
  305. }*/
  306. if (gDebugGL)
  307. {
  308. gPipeline.checkReferences(this);
  309. }
  310. if (isState(DEAD))
  311. {
  312. sZombieGroups--;
  313. }
  314. sNodeCount--;
  315. if (gGLManager.mHasOcclusionQuery)
  316. {
  317. for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; ++i)
  318. {
  319. if (mOcclusionQuery[i])
  320. {
  321. sQueryPool.release(mOcclusionQuery[i]);
  322. }
  323. }
  324. }
  325. mOcclusionVerts = NULL;
  326. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  327. clearDrawMap();
  328. clearAtlasList() ;
  329. }
  330. BOOL LLSpatialGroup::hasAtlas(LLTextureAtlas* atlasp)
  331. {
  332. S8 type = atlasp->getComponents() - 1 ;
  333. for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter)
  334. {
  335. if(atlasp == *iter)
  336. {
  337. return TRUE ;
  338. }
  339. }
  340. return FALSE ;
  341. }
  342. void LLSpatialGroup::addAtlas(LLTextureAtlas* atlasp, S8 recursive_level)
  343. {
  344. if(!hasAtlas(atlasp))
  345. {
  346. mAtlasList[atlasp->getComponents() - 1].push_back(atlasp) ;
  347. atlasp->addSpatialGroup(this) ;
  348. }
  349. --recursive_level;
  350. if(recursive_level)//levels propagating up.
  351. {
  352. LLSpatialGroup* parent = getParent() ;
  353. if(parent)
  354. {
  355. parent->addAtlas(atlasp, recursive_level) ;
  356. }
  357. }
  358. }
  359. void LLSpatialGroup::removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group, S8 recursive_level)
  360. {
  361. mAtlasList[atlasp->getComponents() - 1].remove(atlasp) ;
  362. if(remove_group)
  363. {
  364. atlasp->removeSpatialGroup(this) ;
  365. }
  366. --recursive_level;
  367. if(recursive_level)//levels propagating up.
  368. {
  369. LLSpatialGroup* parent = getParent() ;
  370. if(parent)
  371. {
  372. parent->removeAtlas(atlasp, recursive_level) ;
  373. }
  374. }
  375. }
  376. void LLSpatialGroup::clearAtlasList()
  377. {
  378. std::list<LLTextureAtlas*>::iterator iter ;
  379. for(S8 i = 0 ; i < 4 ; i++)
  380. {
  381. if(mAtlasList[i].size() > 0)
  382. {
  383. for(iter = mAtlasList[i].begin(); iter != mAtlasList[i].end() ; ++iter)
  384. {
  385. ((LLTextureAtlas*)*iter)->removeSpatialGroup(this) ;
  386. }
  387. mAtlasList[i].clear() ;
  388. }
  389. }
  390. }
  391. LLTextureAtlas* LLSpatialGroup::getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level)
  392. {
  393. S8 type = ncomponents - 1 ;
  394. if(mAtlasList[type].size() > 0)
  395. {
  396. for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter)
  397. {
  398. if(!((LLTextureAtlas*)*iter)->isFull(to_be_reserved))
  399. {
  400. return *iter ;
  401. }
  402. }
  403. }
  404. --recursive_level;
  405. if(recursive_level)
  406. {
  407. LLSpatialGroup* parent = getParent() ;
  408. if(parent)
  409. {
  410. return parent->getAtlas(ncomponents, to_be_reserved, recursive_level) ;
  411. }
  412. }
  413. return NULL ;
  414. }
  415. void LLSpatialGroup::setCurUpdatingSlot(LLTextureAtlasSlot* slotp)
  416. {
  417. mCurUpdatingSlotp = slotp;
  418. //if(!hasAtlas(mCurUpdatingSlotp->getAtlas()))
  419. //{
  420. // addAtlas(mCurUpdatingSlotp->getAtlas()) ;
  421. //}
  422. }
  423. LLTextureAtlasSlot* LLSpatialGroup::getCurUpdatingSlot(LLViewerTexture* imagep, S8 recursive_level)
  424. {
  425. if(gFrameCount && mCurUpdatingTime == gFrameCount && mCurUpdatingTexture == imagep)
  426. {
  427. return mCurUpdatingSlotp ;
  428. }
  429. //--recursive_level ;
  430. //if(recursive_level)
  431. //{
  432. // LLSpatialGroup* parent = getParent() ;
  433. // if(parent)
  434. // {
  435. // return parent->getCurUpdatingSlot(imagep, recursive_level) ;
  436. // }
  437. //}
  438. return NULL ;
  439. }
  440. void LLSpatialGroup::clearDrawMap()
  441. {
  442. mDrawMap.clear();
  443. }
  444. BOOL LLSpatialGroup::isHUDGroup()
  445. {
  446. return mSpatialPartition && mSpatialPartition->isHUDPartition() ;
  447. }
  448. BOOL LLSpatialGroup::isRecentlyVisible() const
  449. {
  450. return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < LLDrawable::getMinVisFrameRange() ;
  451. }
  452. BOOL LLSpatialGroup::isVisible() const
  453. {
  454. return mVisible[LLViewerCamera::sCurCameraID] >= LLDrawable::getCurrentFrame() ? TRUE : FALSE;
  455. }
  456. void LLSpatialGroup::setVisible()
  457. {
  458. mVisible[LLViewerCamera::sCurCameraID] = LLDrawable::getCurrentFrame();
  459. }
  460. void LLSpatialGroup::validate()
  461. {
  462. #if LL_OCTREE_PARANOIA_CHECK
  463. sg_assert(!isState(DIRTY));
  464. sg_assert(!isDead());
  465. LLVector4a myMin;
  466. myMin.setSub(mBounds[0], mBounds[1]);
  467. LLVector4a myMax;
  468. myMax.setAdd(mBounds[0], mBounds[1]);
  469. validateDrawMap();
  470. for (element_iter i = getData().begin(); i != getData().end(); ++i)
  471. {
  472. LLDrawable* drawable = *i;
  473. sg_assert(drawable->getSpatialGroup() == this);
  474. if (drawable->getSpatialBridge())
  475. {
  476. sg_assert(drawable->getSpatialBridge() == mSpatialPartition->asBridge());
  477. }
  478. /*if (drawable->isSpatialBridge())
  479. {
  480. LLSpatialPartition* part = drawable->asPartition();
  481. if (!part)
  482. {
  483. llerrs << "Drawable reports it is a spatial bridge but not a partition." << llendl;
  484. }
  485. LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0);
  486. group->validate();
  487. }*/
  488. }
  489. for (U32 i = 0; i < mOctreeNode->getChildCount(); ++i)
  490. {
  491. LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0);
  492. group->validate();
  493. //ensure all children are enclosed in this node
  494. LLVector4a center = group->mBounds[0];
  495. LLVector4a size = group->mBounds[1];
  496. LLVector4a min;
  497. min.setSub(center, size);
  498. LLVector4a max;
  499. max.setAdd(center, size);
  500. for (U32 j = 0; j < 3; j++)
  501. {
  502. sg_assert(min[j] >= myMin[j]-0.02f);
  503. sg_assert(max[j] <= myMax[j]+0.02f);
  504. }
  505. }
  506. #endif
  507. }
  508. void LLSpatialGroup::checkStates()
  509. {
  510. #if LL_OCTREE_PARANOIA_CHECK
  511. //LLOctreeStateCheck checker;
  512. //checker.traverse(mOctreeNode);
  513. #endif
  514. }
  515. void LLSpatialGroup::validateDrawMap()
  516. {
  517. #if LL_OCTREE_PARANOIA_CHECK
  518. for (draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i)
  519. {
  520. LLSpatialGroup::drawmap_elem_t& draw_vec = i->second;
  521. for (drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j)
  522. {
  523. LLDrawInfo& params = **j;
  524. params.validate();
  525. }
  526. }
  527. #endif
  528. }
  529. BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate)
  530. {
  531. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  532. drawablep->updateSpatialExtents();
  533. OctreeNode* parent = mOctreeNode->getOctParent();
  534. if (mOctreeNode->isInside(drawablep->getPositionGroup()) &&
  535. (mOctreeNode->contains(drawablep) ||
  536. (drawablep->getBinRadius() > mOctreeNode->getSize()[0] &&
  537. parent && parent->getElementCount() >= gOctreeMaxCapacity)))
  538. {
  539. unbound();
  540. setState(OBJECT_DIRTY);
  541. //setState(GEOM_DIRTY);
  542. return TRUE;
  543. }
  544. return FALSE;
  545. }
  546. BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_octree)
  547. {
  548. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  549. if (!from_octree)
  550. {
  551. mOctreeNode->insert(drawablep);
  552. }
  553. else
  554. {
  555. drawablep->setSpatialGroup(this);
  556. setState(OBJECT_DIRTY | GEOM_DIRTY);
  557. setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS);
  558. gPipeline.markRebuild(this, TRUE);
  559. if (drawablep->isSpatialBridge())
  560. {
  561. mBridgeList.push_back((LLSpatialBridge*) drawablep);
  562. }
  563. if (drawablep->getRadius() > 1.f)
  564. {
  565. setState(IMAGE_DIRTY);
  566. }
  567. }
  568. return TRUE;
  569. }
  570. void LLSpatialGroup::rebuildGeom()
  571. {
  572. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  573. if (!isDead())
  574. {
  575. mSpatialPartition->rebuildGeom(this);
  576. }
  577. }
  578. void LLSpatialGroup::rebuildMesh()
  579. {
  580. if (!isDead())
  581. {
  582. mSpatialPartition->rebuildMesh(this);
  583. }
  584. }
  585. static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt");
  586. void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
  587. {
  588. if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY))
  589. {
  590. return;
  591. }
  592. if (group->changeLOD())
  593. {
  594. group->mLastUpdateDistance = group->mDistance;
  595. group->mLastUpdateViewAngle = group->mViewAngle;
  596. }
  597. LLFastTimer ftm(FTM_REBUILD_VBO);
  598. group->clearDrawMap();
  599. //get geometry count
  600. U32 index_count = 0;
  601. U32 vertex_count = 0;
  602. addGeometryCount(group, vertex_count, index_count);
  603. if (vertex_count > 0 && index_count > 0)
  604. { //create vertex buffer containing volume geometry for this node
  605. group->mBuilt = 1.f;
  606. if (group->mVertexBuffer.isNull() || (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs))
  607. {
  608. group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage);
  609. group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true);
  610. stop_glerror();
  611. }
  612. else
  613. {
  614. group->mVertexBuffer->resizeBuffer(vertex_count, index_count);
  615. stop_glerror();
  616. }
  617. getGeometry(group);
  618. }
  619. else
  620. {
  621. group->mVertexBuffer = NULL;
  622. group->mBufferMap.clear();
  623. }
  624. group->mLastUpdateTime = gFrameTimeSeconds;
  625. group->clearState(LLSpatialGroup::GEOM_DIRTY);
  626. }
  627. void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group)
  628. {
  629. }
  630. BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& maxOut)
  631. {
  632. const OctreeNode* node = mOctreeNode;
  633. if (node->getData().empty())
  634. { //don't do anything if there are no objects
  635. if (empty && mOctreeNode->getParent())
  636. { //only root is allowed to be empty
  637. OCT_ERRS << "Empty leaf found in octree." << llendl;
  638. }
  639. return FALSE;
  640. }
  641. LLVector4a& newMin = mObjectExtents[0];
  642. LLVector4a& newMax = mObjectExtents[1];
  643. if (isState(OBJECT_DIRTY))
  644. { //calculate new bounding box
  645. clearState(OBJECT_DIRTY);
  646. //initialize bounding box to first element
  647. OctreeNode::const_element_iter i = node->getData().begin();
  648. LLDrawable* drawablep = *i;
  649. const LLVector4a* minMax = drawablep->getSpatialExtents();
  650. newMin = minMax[0];
  651. newMax = minMax[1];
  652. for (++i; i != node->getData().end(); ++i)
  653. {
  654. drawablep = *i;
  655. minMax = drawablep->getSpatialExtents();
  656. update_min_max(newMin, newMax, minMax[0]);
  657. update_min_max(newMin, newMax, minMax[1]);
  658. //bin up the object
  659. /*for (U32 i = 0; i < 3; i++)
  660. {
  661. if (minMax[0].mV[i] < newMin.mV[i])
  662. {
  663. newMin.mV[i] = minMax[0].mV[i];
  664. }
  665. if (minMax[1].mV[i] > newMax.mV[i])
  666. {
  667. newMax.mV[i] = minMax[1].mV[i];
  668. }
  669. }*/
  670. }
  671. mObjectBounds[0].setAdd(newMin, newMax);
  672. mObjectBounds[0].mul(0.5f);
  673. mObjectBounds[1].setSub(newMax, newMin);
  674. mObjectBounds[1].mul(0.5f);
  675. }
  676. if (empty)
  677. {
  678. minOut = newMin;
  679. maxOut = newMax;
  680. }
  681. else
  682. {
  683. minOut.setMin(minOut, newMin);
  684. maxOut.setMax(maxOut, newMax);
  685. }
  686. return TRUE;
  687. }
  688. void LLSpatialGroup::unbound()
  689. {
  690. if (isState(DIRTY))
  691. {
  692. return;
  693. }
  694. setState(DIRTY);
  695. //all the parent nodes need to rebound this child
  696. if (mOctreeNode)
  697. {
  698. OctreeNode* parent = (OctreeNode*) mOctreeNode->getParent();
  699. while (parent != NULL)
  700. {
  701. LLSpatialGroup* group = (LLSpatialGroup*) parent->getListener(0);
  702. if (group->isState(DIRTY))
  703. {
  704. return;
  705. }
  706. group->setState(DIRTY);
  707. parent = (OctreeNode*) parent->getParent();
  708. }
  709. }
  710. }
  711. LLSpatialGroup* LLSpatialGroup::getParent()
  712. {
  713. if (isDead())
  714. {
  715. return NULL;
  716. }
  717. if(!mOctreeNode)
  718. {
  719. return NULL;
  720. }
  721. OctreeNode* parent = mOctreeNode->getOctParent();
  722. if (parent)
  723. {
  724. return (LLSpatialGroup*) parent->getListener(0);
  725. }
  726. return NULL;
  727. }
  728. BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree)
  729. {
  730. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  731. unbound();
  732. if (mOctreeNode && !from_octree)
  733. {
  734. if (!mOctreeNode->remove(drawablep))
  735. {
  736. OCT_ERRS << "Could not remove drawable from spatial group" << llendl;
  737. }
  738. }
  739. else
  740. {
  741. drawablep->setSpatialGroup(NULL);
  742. setState(GEOM_DIRTY);
  743. gPipeline.markRebuild(this, TRUE);
  744. if (drawablep->isSpatialBridge())
  745. {
  746. for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i)
  747. {
  748. if (*i == drawablep)
  749. {
  750. mBridgeList.erase(i);
  751. break;
  752. }
  753. }
  754. }
  755. if (getElementCount() == 0)
  756. { //delete draw map on last element removal since a rebuild might never happen
  757. clearDrawMap();
  758. }
  759. }
  760. return TRUE;
  761. }
  762. void LLSpatialGroup::shift(const LLVector4a &offset)
  763. {
  764. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  765. LLVector4a t = mOctreeNode->getCenter();
  766. t.add(offset);
  767. mOctreeNode->setCenter(t);
  768. mOctreeNode->updateMinMax();
  769. mBounds[0].add(offset);
  770. mExtents[0].add(offset);
  771. mExtents[1].add(offset);
  772. mObjectBounds[0].add(offset);
  773. mObjectExtents[0].add(offset);
  774. mObjectExtents[1].add(offset);
  775. //if (!mSpatialPartition->mRenderByGroup)
  776. {
  777. setState(GEOM_DIRTY);
  778. gPipeline.markRebuild(this, TRUE);
  779. }
  780. if (mOcclusionVerts.notNull())
  781. {
  782. setState(OCCLUSION_DIRTY);
  783. }
  784. }
  785. class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler
  786. {
  787. public:
  788. U32 mState;
  789. LLSpatialSetState(U32 state) : mState(state) { }
  790. virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); }
  791. };
  792. class LLSpatialSetStateDiff : public LLSpatialSetState
  793. {
  794. public:
  795. LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { }
  796. virtual void traverse(const LLSpatialGroup::OctreeNode* n)
  797. {
  798. LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
  799. if (!group->isState(mState))
  800. {
  801. LLSpatialGroup::OctreeTraveler::traverse(n);
  802. }
  803. }
  804. };
  805. void LLSpatialGroup::setState(U32 state)
  806. {
  807. mState |= state;
  808. llassert(state <= LLSpatialGroup::STATE_MASK);
  809. }
  810. void LLSpatialGroup::setState(U32 state, S32 mode)
  811. {
  812. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  813. llassert(state <= LLSpatialGroup::STATE_MASK);
  814. if (mode > STATE_MODE_SINGLE)
  815. {
  816. if (mode == STATE_MODE_DIFF)
  817. {
  818. LLSpatialSetStateDiff setter(state);
  819. setter.traverse(mOctreeNode);
  820. }
  821. else
  822. {
  823. LLSpatialSetState setter(state);
  824. setter.traverse(mOctreeNode);
  825. }
  826. }
  827. else
  828. {
  829. mState |= state;
  830. }
  831. }
  832. class LLSpatialClearState : public LLSpatialGroup::OctreeTraveler
  833. {
  834. public:
  835. U32 mState;
  836. LLSpatialClearState(U32 state) : mState(state) { }
  837. virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); }
  838. };
  839. class LLSpatialClearStateDiff : public LLSpatialClearState
  840. {
  841. public:
  842. LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { }
  843. virtual void traverse(const LLSpatialGroup::OctreeNode* n)
  844. {
  845. LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
  846. if (group->isState(mState))
  847. {
  848. LLSpatialGroup::OctreeTraveler::traverse(n);
  849. }
  850. }
  851. };
  852. void LLSpatialGroup::clearState(U32 state)
  853. {
  854. llassert(state <= LLSpatialGroup::STATE_MASK);
  855. mState &= ~state;
  856. }
  857. void LLSpatialGroup::clearState(U32 state, S32 mode)
  858. {
  859. llassert(state <= LLSpatialGroup::STATE_MASK);
  860. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  861. if (mode > STATE_MODE_SINGLE)
  862. {
  863. if (mode == STATE_MODE_DIFF)
  864. {
  865. LLSpatialClearStateDiff clearer(state);
  866. clearer.traverse(mOctreeNode);
  867. }
  868. else
  869. {
  870. LLSpatialClearState clearer(state);
  871. clearer.traverse(mOctreeNode);
  872. }
  873. }
  874. else
  875. {
  876. mState &= ~state;
  877. }
  878. }
  879. BOOL LLSpatialGroup::isState(U32 state) const
  880. {
  881. llassert(state <= LLSpatialGroup::STATE_MASK);
  882. return mState & state ? TRUE : FALSE;
  883. }
  884. //=====================================
  885. // Occlusion State Set/Clear
  886. //=====================================
  887. class LLSpatialSetOcclusionState : public LLSpatialGroup::OctreeTraveler
  888. {
  889. public:
  890. U32 mState;
  891. LLSpatialSetOcclusionState(U32 state) : mState(state) { }
  892. virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setOcclusionState(mState); }
  893. };
  894. class LLSpatialSetOcclusionStateDiff : public LLSpatialSetOcclusionState
  895. {
  896. public:
  897. LLSpatialSetOcclusionStateDiff(U32 state) : LLSpatialSetOcclusionState(state) { }
  898. virtual void traverse(const LLSpatialGroup::OctreeNode* n)
  899. {
  900. LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
  901. if (!group->isOcclusionState(mState))
  902. {
  903. LLSpatialGroup::OctreeTraveler::traverse(n);
  904. }
  905. }
  906. };
  907. void LLSpatialGroup::setOcclusionState(U32 state, S32 mode)
  908. {
  909. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  910. if (mode > STATE_MODE_SINGLE)
  911. {
  912. if (mode == STATE_MODE_DIFF)
  913. {
  914. LLSpatialSetOcclusionStateDiff setter(state);
  915. setter.traverse(mOctreeNode);
  916. }
  917. else if (mode == STATE_MODE_BRANCH)
  918. {
  919. LLSpatialSetOcclusionState setter(state);
  920. setter.traverse(mOctreeNode);
  921. }
  922. else
  923. {
  924. for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
  925. {
  926. mOcclusionState[i] |= state;
  927. if ((state & DISCARD_QUERY) && mOcclusionQuery[i])
  928. {
  929. sQueryPool.release(mOcclusionQuery[i]);
  930. mOcclusionQuery[i] = 0;
  931. }
  932. }
  933. }
  934. }
  935. else
  936. {
  937. mOcclusionState[LLViewerCamera::sCurCameraID] |= state;
  938. if ((state & DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
  939. {
  940. sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
  941. mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0;
  942. }
  943. }
  944. }
  945. class LLSpatialClearOcclusionState : public LLSpatialGroup::OctreeTraveler
  946. {
  947. public:
  948. U32 mState;
  949. LLSpatialClearOcclusionState(U32 state) : mState(state) { }
  950. virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearOcclusionState(mState); }
  951. };
  952. class LLSpatialClearOcclusionStateDiff : public LLSpatialClearOcclusionState
  953. {
  954. public:
  955. LLSpatialClearOcclusionStateDiff(U32 state) : LLSpatialClearOcclusionState(state) { }
  956. virtual void traverse(const LLSpatialGroup::OctreeNode* n)
  957. {
  958. LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
  959. if (group->isOcclusionState(mState))
  960. {
  961. LLSpatialGroup::OctreeTraveler::traverse(n);
  962. }
  963. }
  964. };
  965. void LLSpatialGroup::clearOcclusionState(U32 state, S32 mode)
  966. {
  967. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  968. if (mode > STATE_MODE_SINGLE)
  969. {
  970. if (mode == STATE_MODE_DIFF)
  971. {
  972. LLSpatialClearOcclusionStateDiff clearer(state);
  973. clearer.traverse(mOctreeNode);
  974. }
  975. else if (mode == STATE_MODE_BRANCH)
  976. {
  977. LLSpatialClearOcclusionState clearer(state);
  978. clearer.traverse(mOctreeNode);
  979. }
  980. else
  981. {
  982. for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
  983. {
  984. mOcclusionState[i] &= ~state;
  985. }
  986. }
  987. }
  988. else
  989. {
  990. mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state;
  991. }
  992. }
  993. //======================================
  994. // Octree Listener Implementation
  995. //======================================
  996. LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
  997. mState(0),
  998. mBuilt(0.f),
  999. mOctreeNode(node),
  1000. mSpatialPartition(part),
  1001. mVertexBuffer(NULL),
  1002. mBufferUsage(part->mBufferUsage),
  1003. mDistance(0.f),
  1004. mDepth(0.f),
  1005. mLastUpdateDistance(-1.f),
  1006. mLastUpdateTime(gFrameTimeSeconds),
  1007. mAtlasList(4),
  1008. mCurUpdatingTime(0),
  1009. mCurUpdatingSlotp(NULL),
  1010. mCurUpdatingTexture (NULL)
  1011. {
  1012. sNodeCount++;
  1013. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1014. mViewAngle.splat(0.f);
  1015. mLastUpdateViewAngle.splat(-1.f);
  1016. mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[0] = mObjectBounds[1] =
  1017. mObjectExtents[0] = mObjectExtents[1] = mViewAngle;
  1018. sg_assert(mOctreeNode->getListenerCount() == 0);
  1019. mOctreeNode->addListener(this);
  1020. setState(SG_INITIAL_STATE_MASK);
  1021. gPipeline.markRebuild(this, TRUE);
  1022. mBounds[0] = node->getCenter();
  1023. mBounds[1] = node->getSize();
  1024. part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod;
  1025. mLODHash = part->mLODSeed;
  1026. OctreeNode* oct_parent = node->getOctParent();
  1027. LLSpatialGroup* parent = oct_parent ? (LLSpatialGroup*) oct_parent->getListener(0) : NULL;
  1028. for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
  1029. {
  1030. mOcclusionQuery[i] = 0;
  1031. mOcclusionIssued[i] = 0;
  1032. mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0;
  1033. mVisible[i] = 0;
  1034. }
  1035. mOcclusionVerts = NULL;
  1036. mRadius = 1;
  1037. mPixelArea = 1024.f;
  1038. }
  1039. void LLSpatialGroup::updateDistance(LLCamera &camera)
  1040. {
  1041. if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
  1042. {
  1043. llwarns << "Attempted to update distance for camera other than world camera!" << llendl;
  1044. return;
  1045. }
  1046. #if !LL_RELEASE_FOR_DOWNLOAD
  1047. if (isState(LLSpatialGroup::OBJECT_DIRTY))
  1048. {
  1049. llerrs << "Spatial group dirty on distance update." << llendl;
  1050. }
  1051. #endif
  1052. if (!getData().empty())
  1053. {
  1054. mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() :
  1055. (F32) mOctreeNode->getSize().getLength3().getF32();
  1056. mDistance = mSpatialPartition->calcDistance(this, camera);
  1057. mPixelArea = mSpatialPartition->calcPixelArea(this, camera);
  1058. }
  1059. }
  1060. F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera)
  1061. {
  1062. LLVector4a eye;
  1063. LLVector4a origin;
  1064. origin.load3(camera.getOrigin().mV);
  1065. eye.setSub(group->mObjectBounds[0], origin);
  1066. F32 dist = 0.f;
  1067. if (group->mDrawMap.find(LLRenderPass::PASS_ALPHA) != group->mDrawMap.end())
  1068. {
  1069. LLVector4a v = eye;
  1070. dist = eye.getLength3().getF32();
  1071. eye.normalize3fast();
  1072. if (!group->isState(LLSpatialGroup::ALPHA_DIRTY))
  1073. {
  1074. if (!group->mSpatialPartition->isBridge())
  1075. {
  1076. LLVector4a view_angle = eye;
  1077. LLVector4a diff;
  1078. diff.setSub(view_angle, group->mLastUpdateViewAngle);
  1079. if (diff.getLength3().getF32() > 0.64f)
  1080. {
  1081. group->mViewAngle = view_angle;
  1082. group->mLastUpdateViewAngle = view_angle;
  1083. //for occasional alpha sorting within the group
  1084. //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order,
  1085. //not setting this node to dirty would be a very good thing
  1086. group->setState(LLSpatialGroup::ALPHA_DIRTY);
  1087. gPipeline.markRebuild(group, FALSE);
  1088. }
  1089. }
  1090. }
  1091. //calculate depth of node for alpha sorting
  1092. LLVector3 at = camera.getAtAxis();
  1093. LLVector4a ata;
  1094. ata.load3(at.mV);
  1095. LLVector4a t = ata;
  1096. //front of bounding box
  1097. t.mul(0.25f);
  1098. t.mul(group->mObjectBounds[1]);
  1099. v.sub(t);
  1100. group->mDepth = v.dot3(ata).getF32();
  1101. }
  1102. else
  1103. {
  1104. dist = eye.getLength3().getF32();
  1105. }
  1106. if (dist < 16.f)
  1107. {
  1108. dist /= 16.f;
  1109. dist *= dist;
  1110. dist *= 16.f;
  1111. }
  1112. return dist;
  1113. }
  1114. F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
  1115. {
  1116. return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera);
  1117. }
  1118. F32 LLSpatialGroup::getUpdateUrgency() const
  1119. {
  1120. if (!isVisible())
  1121. {
  1122. return 0.f;
  1123. }
  1124. else
  1125. {
  1126. F32 time = gFrameTimeSeconds-mLastUpdateTime+4.f;
  1127. return time + (mObjectBounds[1].dot3(mObjectBounds[1]).getF32()+1.f)/mDistance;
  1128. }
  1129. }
  1130. BOOL LLSpatialGroup::needsUpdate()
  1131. {
  1132. return (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE;
  1133. }
  1134. BOOL LLSpatialGroup::changeLOD()
  1135. {
  1136. if (isState(ALPHA_DIRTY | OBJECT_DIRTY))
  1137. { ///a rebuild is going to happen, update distance and LoD
  1138. return TRUE;
  1139. }
  1140. if (mSpatialPartition->mSlopRatio > 0.f)
  1141. {
  1142. F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius));
  1143. if (fabsf(ratio) >= mSpatialPartition->mSlopRatio)
  1144. {
  1145. return TRUE;
  1146. }
  1147. if (mDistance > mRadius*2.f)
  1148. {
  1149. return FALSE;
  1150. }
  1151. }
  1152. if (needsUpdate())
  1153. {
  1154. return TRUE;
  1155. }
  1156. return FALSE;
  1157. }
  1158. void LLSpatialGroup::handleInsertion(const TreeNode* node, LLDrawable* drawablep)
  1159. {
  1160. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1161. addObject(drawablep, FALSE, TRUE);
  1162. unbound();
  1163. setState(OBJECT_DIRTY);
  1164. }
  1165. void LLSpatialGroup::handleRemoval(const TreeNode* node, LLDrawable* drawable)
  1166. {
  1167. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1168. removeObject(drawable, TRUE);
  1169. setState(OBJECT_DIRTY);
  1170. }
  1171. void LLSpatialGroup::handleDestruction(const TreeNode* node)
  1172. {
  1173. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1174. setState(DEAD);
  1175. for (element_iter i = getData().begin(); i != getData().end(); ++i)
  1176. {
  1177. LLDrawable* drawable = *i;
  1178. if (drawable->getSpatialGroup() == this)
  1179. {
  1180. drawable->setSpatialGroup(NULL);
  1181. }
  1182. }
  1183. clearDrawMap();
  1184. mVertexBuffer = NULL;
  1185. mBufferMap.clear();
  1186. sZombieGroups++;
  1187. mOctreeNode = NULL;
  1188. }
  1189. void LLSpatialGroup::handleStateChange(const TreeNode* node)
  1190. {
  1191. //drop bounding box upon state change
  1192. if (mOctreeNode != node)
  1193. {
  1194. mOctreeNode = (OctreeNode*) node;
  1195. }
  1196. unbound();
  1197. }
  1198. void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child)
  1199. {
  1200. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1201. if (child->getListenerCount() == 0)
  1202. {
  1203. new LLSpatialGroup(child, mSpatialPartition);
  1204. }
  1205. else
  1206. {
  1207. OCT_ERRS << "LLSpatialGroup redundancy detected." << llendl;
  1208. }
  1209. unbound();
  1210. assert_states_valid(this);
  1211. }
  1212. void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNode* child)
  1213. {
  1214. unbound();
  1215. }
  1216. void LLSpatialGroup::destroyGL()
  1217. {
  1218. setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY);
  1219. gPipeline.markRebuild(this, TRUE);
  1220. mLastUpdateTime = gFrameTimeSeconds;
  1221. mVertexBuffer = NULL;
  1222. mBufferMap.clear();
  1223. clearDrawMap();
  1224. for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
  1225. {
  1226. if (mOcclusionQuery[i])
  1227. {
  1228. sQueryPool.release(mOcclusionQuery[i]);
  1229. mOcclusionQuery[i] = 0;
  1230. }
  1231. }
  1232. mOcclusionVerts = NULL;
  1233. for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i)
  1234. {
  1235. LLDrawable* drawable = *i;
  1236. for (S32 j = 0; j < drawable->getNumFaces(); j++)
  1237. {
  1238. LLFace* facep = drawable->getFace(j);
  1239. facep->clearVertexBuffer();
  1240. }
  1241. }
  1242. }
  1243. BOOL LLSpatialGroup::rebound()
  1244. {
  1245. if (!isState(DIRTY))
  1246. { //return TRUE if we're not empty
  1247. return TRUE;
  1248. }
  1249. if (mOctreeNode->getChildCount() == 1 && mOctreeNode->getElementCount() == 0)
  1250. {
  1251. LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0);
  1252. group->rebound();
  1253. //copy single child's bounding box
  1254. mBounds[0] = group->mBounds[0];
  1255. mBounds[1] = group->mBounds[1];
  1256. mExtents[0] = group->mExtents[0];
  1257. mExtents[1] = group->mExtents[1];
  1258. group->setState(SKIP_FRUSTUM_CHECK);
  1259. }
  1260. else if (mOctreeNode->isLeaf())
  1261. { //copy object bounding box if this is a leaf
  1262. boundObjects(TRUE, mExtents[0], mExtents[1]);
  1263. mBounds[0] = mObjectBounds[0];
  1264. mBounds[1] = mObjectBounds[1];
  1265. }
  1266. else
  1267. {
  1268. LLVector4a& newMin = mExtents[0];
  1269. LLVector4a& newMax = mExtents[1];
  1270. LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0);
  1271. group->clearState(SKIP_FRUSTUM_CHECK);
  1272. group->rebound();
  1273. //initialize to first child
  1274. newMin = group->mExtents[0];
  1275. newMax = group->mExtents[1];
  1276. //first, rebound children
  1277. for (U32 i = 1; i < mOctreeNode->getChildCount(); i++)
  1278. {
  1279. group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0);
  1280. group->clearState(SKIP_FRUSTUM_CHECK);
  1281. group->rebound();
  1282. const LLVector4a& max = group->mExtents[1];
  1283. const LLVector4a& min = group->mExtents[0];
  1284. newMax.setMax(newMax, max);
  1285. newMin.setMin(newMin, min);
  1286. }
  1287. boundObjects(FALSE, newMin, newMax);
  1288. mBounds[0].setAdd(newMin, newMax);
  1289. mBounds[0].mul(0.5f);
  1290. mBounds[1].setSub(newMax, newMin);
  1291. mBounds[1].mul(0.5f);
  1292. }
  1293. setState(OCCLUSION_DIRTY);
  1294. clearState(DIRTY);
  1295. return TRUE;
  1296. }
  1297. static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion");
  1298. static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Wait");
  1299. void LLSpatialGroup::checkOcclusion()
  1300. {
  1301. if (LLPipeline::sUseOcclusion > 1)
  1302. {
  1303. LLFastTimer t(FTM_OCCLUSION_READBACK);
  1304. LLSpatialGroup* parent = getParent();
  1305. if (parent && parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
  1306. { //if the parent has been marked as occluded, the child is implicitly occluded
  1307. clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
  1308. }
  1309. else if (isOcclusionState(QUERY_PENDING))
  1310. { //otherwise, if a query is pending, read it back
  1311. GLuint available = 0;
  1312. if (mOcclusionQuery[LLViewerCamera::sCurCameraID])
  1313. {
  1314. glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
  1315. if (mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount)
  1316. { //query was issued last frame, wait until it's available
  1317. S32 max_loop = 1024;
  1318. LLFastTimer t(FTM_OCCLUSION_WAIT);
  1319. while (!available && max_loop-- > 0)
  1320. {
  1321. F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f);
  1322. //do some usefu work while we wait
  1323. LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread
  1324. LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
  1325. LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
  1326. glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
  1327. }
  1328. }
  1329. }
  1330. else
  1331. {
  1332. available = 1;
  1333. }
  1334. if (available)
  1335. { //result is available, read it back, otherwise wait until next frame
  1336. GLuint res = 1;
  1337. if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
  1338. {
  1339. glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res);
  1340. #if LL_TRACK_PENDING_OCCLUSION_QUERIES
  1341. sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
  1342. #endif
  1343. }
  1344. else if (mOcclusionQuery[LLViewerCamera::sCurCameraID])
  1345. { //delete the query to avoid holding onto hundreds of pending queries
  1346. sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
  1347. mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0;
  1348. }
  1349. if (isOcclusionState(DISCARD_QUERY))
  1350. {
  1351. res = 2;
  1352. }
  1353. if (res > 0)
  1354. {
  1355. assert_states_valid(this);
  1356. clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
  1357. assert_states_valid(this);
  1358. }
  1359. else
  1360. {
  1361. assert_states_valid(this);
  1362. setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
  1363. assert_states_valid(this);
  1364. }
  1365. clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
  1366. }
  1367. }
  1368. else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLSpatialGroup::OCCLUDED))
  1369. { //check occlusion has been issued for occluded node that has not had a query issued
  1370. assert_states_valid(this);
  1371. clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
  1372. assert_states_valid(this);
  1373. }
  1374. }
  1375. }
  1376. static LLFastTimer::DeclareTimer FTM_PUSH_OCCLUSION_VERTS("Push Occlusion");
  1377. static LLFastTimer::DeclareTimer FTM_SET_OCCLUSION_STATE("Occlusion State");
  1378. static LLFastTimer::DeclareTimer FTM_OCCLUSION_EARLY_FAIL("Occlusion Early Fail");
  1379. static LLFastTimer::DeclareTimer FTM_OCCLUSION_ALLOCATE("Allocate");
  1380. static LLFastTimer::DeclareTimer FTM_OCCLUSION_BUILD("Build");
  1381. static LLFastTimer::DeclareTimer FTM_OCCLUSION_BEGIN_QUERY("Begin Query");
  1382. static LLFastTimer::DeclareTimer FTM_OCCLUSION_END_QUERY("End Query");
  1383. static LLFastTimer::DeclareTimer FTM_OCCLUSION_SET_BUFFER("Set Buffer");
  1384. static LLFastTimer::DeclareTimer FTM_OCCLUSION_DRAW_WATER("Draw Water");
  1385. static LLFastTimer::DeclareTimer FTM_OCCLUSION_DRAW("Draw");
  1386. void LLSpatialGroup::doOcclusion(LLCamera* camera)
  1387. {
  1388. if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1)
  1389. {
  1390. // Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension
  1391. if (earlyFail(camera, this))
  1392. {
  1393. LLFastTimer t(FTM_OCCLUSION_EARLY_FAIL);
  1394. setOcclusionState(LLSpatialGroup::DISCARD_QUERY);
  1395. assert_states_valid(this);
  1396. clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
  1397. assert_states_valid(this);
  1398. }
  1399. else
  1400. {
  1401. if (!isOcclusionState(QUERY_PENDING) || isOcclusionState(DISCARD_QUERY))
  1402. {
  1403. { //no query pending, or previous query to be discarded
  1404. LLFastTimer t(FTM_RENDER_OCCLUSION);
  1405. if (!mOcclusionQuery[LLViewerCamera::sCurCameraID])
  1406. {
  1407. LLFastTimer t(FTM_OCCLUSION_ALLOCATE);
  1408. mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate();
  1409. }
  1410. if (mOcclusionVerts.isNull() || isState(LLSpatialGroup::OCCLUSION_DIRTY))
  1411. {
  1412. LLFastTimer t(FTM_OCCLUSION_BUILD);
  1413. buildOcclusion();
  1414. }
  1415. // Depth clamp all water to avoid it being culled as a result of being
  1416. // behind the far clip plane, and in the case of edge water to avoid
  1417. // it being culled while still visible.
  1418. bool const use_depth_clamp = gGLManager.mHasDepthClamp &&
  1419. (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER ||
  1420. mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER);
  1421. LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0);
  1422. #if !LL_DARWIN
  1423. U32 mode = gGLManager.mHasOcclusionQuery2 ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED_ARB;
  1424. #else
  1425. U32 mode = GL_SAMPLES_PASSED_ARB;
  1426. #endif
  1427. #if LL_TRACK_PENDING_OCCLUSION_QUERIES
  1428. sPendingQueries.insert(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
  1429. #endif
  1430. {
  1431. LLFastTimer t(FTM_PUSH_OCCLUSION_VERTS);
  1432. //store which frame this query was issued on
  1433. mOcclusionIssued[LLViewerCamera::sCurCameraID] = gFrameCount;
  1434. {
  1435. LLFastTimer t(FTM_OCCLUSION_BEGIN_QUERY);
  1436. glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
  1437. }
  1438. {
  1439. LLFastTimer t(FTM_OCCLUSION_SET_BUFFER);
  1440. mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX);
  1441. }
  1442. if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER)
  1443. {
  1444. LLFastTimer t(FTM_OCCLUSION_DRAW_WATER);
  1445. LLGLSquashToFarClip squash(glh_get_current_projection(), 1);
  1446. if (camera->getOrigin().isExactlyZero())
  1447. { //origin is invalid, draw entire box
  1448. mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0);
  1449. mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);
  1450. }
  1451. else
  1452. {
  1453. mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0]));
  1454. }
  1455. }
  1456. else
  1457. {
  1458. LLFastTimer t(FTM_OCCLUSION_DRAW);
  1459. if (camera->getOrigin().isExactlyZero())
  1460. { //origin is invalid, draw entire box
  1461. mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0);
  1462. mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8);
  1463. }
  1464. else
  1465. {
  1466. mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0]));
  1467. }
  1468. }
  1469. {
  1470. LLFastTimer t(FTM_OCCLUSION_END_QUERY);
  1471. glEndQueryARB(mode);
  1472. }
  1473. }
  1474. }
  1475. {
  1476. LLFastTimer t(FTM_SET_OCCLUSION_STATE);
  1477. setOcclusionState(LLSpatialGroup::QUERY_PENDING);
  1478. clearOcclusionState(LLSpatialGroup::DISCARD_QUERY);
  1479. }
  1480. }
  1481. }
  1482. }
  1483. }
  1484. //==============================================
  1485. LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage)
  1486. : mRenderByGroup(render_by_group)
  1487. {
  1488. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1489. mOcclusionEnabled = TRUE;
  1490. mDrawableType = 0;
  1491. mPartitionType = LLViewerRegion::PARTITION_NONE;
  1492. mLODSeed = 0;
  1493. mLODPeriod = 1;
  1494. mVertexDataMask = data_mask;
  1495. mBufferUsage = buffer_usage;
  1496. mDepthMask = FALSE;
  1497. mSlopRatio = 0.25f;
  1498. mInfiniteFarClip = FALSE;
  1499. LLVector4a center, size;
  1500. center.splat(0.f);
  1501. size.splat(1.f);
  1502. mOctree = new LLSpatialGroup::OctreeRoot(center,size,
  1503. NULL);
  1504. new LLSpatialGroup(mOctree, this);
  1505. }
  1506. LLSpatialPartition::~LLSpatialPartition()
  1507. {
  1508. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1509. delete mOctree;
  1510. mOctree = NULL;
  1511. }
  1512. LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
  1513. {
  1514. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1515. drawablep->updateSpatialExtents();
  1516. //keep drawable from being garbage collected
  1517. LLPointer<LLDrawable> ptr = drawablep;
  1518. assert_octree_valid(mOctree);
  1519. mOctree->insert(drawablep);
  1520. assert_octree_valid(mOctree);
  1521. LLSpatialGroup* group = drawablep->getSpatialGroup();
  1522. if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING))
  1523. {
  1524. group->setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS);
  1525. }
  1526. return group;
  1527. }
  1528. BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp)
  1529. {
  1530. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1531. drawablep->setSpatialGroup(NULL);
  1532. if (!curp->removeObject(drawablep))
  1533. {
  1534. OCT_ERRS << "Failed to remove drawable from octree!" << llendl;
  1535. }
  1536. assert_octree_valid(mOctree);
  1537. return TRUE;
  1538. }
  1539. void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate)
  1540. {
  1541. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1542. // sanity check submitted by open source user bushing Spatula
  1543. // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne)
  1544. if (!drawablep)
  1545. {
  1546. OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << llendl;
  1547. return;
  1548. }
  1549. BOOL was_visible = curp ? curp->isVisible() : FALSE;
  1550. if (curp && curp->mSpatialPartition != this)
  1551. {
  1552. //keep drawable from being garbage collected
  1553. LLPointer<LLDrawable> ptr = drawablep;
  1554. if (curp->mSpatialPartition->remove(drawablep, curp))
  1555. {
  1556. put(drawablep, was_visible);
  1557. return;
  1558. }
  1559. else
  1560. {
  1561. OCT_ERRS << "Drawable lost between spatial partitions on outbound transition." << llendl;
  1562. }
  1563. }
  1564. if (curp && curp->updateInGroup(drawablep, immediate))
  1565. {
  1566. // Already updated, don't need to do anything
  1567. assert_octree_valid(mOctree);
  1568. return;
  1569. }
  1570. //keep drawable from being garbage collected
  1571. LLPointer<LLDrawable> ptr = drawablep;
  1572. if (curp && !remove(drawablep, curp))
  1573. {
  1574. OCT_ERRS << "Move couldn't find existing spatial group!" << llendl;
  1575. }
  1576. put(drawablep, was_visible);
  1577. }
  1578. class LLSpatialShift : public LLSpatialGroup::OctreeTraveler
  1579. {
  1580. public:
  1581. const LLVector4a& mOffset;
  1582. LLSpatialShift(const LLVector4a& offset) : mOffset(offset) { }
  1583. virtual void visit(const LLSpatialGroup::OctreeNode* branch)
  1584. {
  1585. ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset);
  1586. }
  1587. };
  1588. void LLSpatialPartition::shift(const LLVector4a &offset)
  1589. { //shift octree node bounding boxes by offset
  1590. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1591. LLSpatialShift shifter(offset);
  1592. shifter.traverse(mOctree);
  1593. }
  1594. class LLOctreeCull : public LLSpatialGroup::OctreeTraveler
  1595. {
  1596. public:
  1597. LLOctreeCull(LLCamera* camera)
  1598. : mCamera(camera), mRes(0) { }
  1599. virtual bool earlyFail(LLSpatialGroup* group)
  1600. {
  1601. group->checkOcclusion();
  1602. if (group->mOctreeNode->getParent() && //never occlusion cull the root node
  1603. LLPipeline::sUseOcclusion && //ignore occlusion if disabled
  1604. group->isOcclusionState(LLSpatialGroup::OCCLUDED))
  1605. {
  1606. gPipeline.markOccluder(group);
  1607. return true;
  1608. }
  1609. return false;
  1610. }
  1611. virtual void traverse(const LLSpatialGroup::OctreeNode* n)
  1612. {
  1613. LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
  1614. if (earlyFail(group))
  1615. {
  1616. return;
  1617. }
  1618. if (mRes == 2 ||
  1619. (mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)))
  1620. { //fully in, just add everything
  1621. LLSpatialGroup::OctreeTraveler::traverse(n);
  1622. }
  1623. else
  1624. {
  1625. mRes = frustumCheck(group);
  1626. if (mRes)
  1627. { //at least partially in, run on down
  1628. LLSpatialGroup::OctreeTraveler::traverse(n);
  1629. }
  1630. mRes = 0;
  1631. }
  1632. }
  1633. virtual S32 frustumCheck(const LLSpatialGroup* group)
  1634. {
  1635. S32 res = mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]);
  1636. if (res != 0)
  1637. {
  1638. res = llmin(res, AABBSphereIntersect(group->mExtents[0], group->mExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist));
  1639. }
  1640. return res;
  1641. }
  1642. virtual S32 frustumCheckObjects(const LLSpatialGroup* group)
  1643. {
  1644. S32 res = mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]);
  1645. if (res != 0)
  1646. {
  1647. res = llmin(res, AABBSphereIntersect(group->mObjectExtents[0], group->mObjectExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist));
  1648. }
  1649. return res;
  1650. }
  1651. virtual bool checkObjects(const LLSpatialGroup::OctreeNode* branch, const LLSpatialGroup* group)
  1652. {
  1653. if (branch->getElementCount() == 0) //no elements
  1654. {
  1655. return false;
  1656. }
  1657. else if (branch->getChildCount() == 0) //leaf state, already checked tightest bounding box
  1658. {
  1659. return true;
  1660. }
  1661. else if (mRes == 1 && !frustumCheckObjects(group)) //no objects in frustum
  1662. {
  1663. return false;
  1664. }
  1665. return true;
  1666. }
  1667. virtual void preprocess(LLSpatialGroup* group)
  1668. {
  1669. }
  1670. virtual void processGroup(LLSpatialGroup* group)
  1671. {
  1672. if (group->needsUpdate() ||
  1673. group->mVisible[LLViewerCamera::sCurCameraID] < LLDrawable::getCurrentFrame() - 1)
  1674. {
  1675. group->doOcclusion(mCamera);
  1676. }
  1677. gPipeline.markNotCulled(group, *mCamera);
  1678. }
  1679. virtual void visit(const LLSpatialGroup::OctreeNode* branch)
  1680. {
  1681. LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0);
  1682. preprocess(group);
  1683. if (checkObjects(branch, group))
  1684. {
  1685. processGroup(group);
  1686. }
  1687. }
  1688. LLCamera *mCamera;
  1689. S32 mRes;
  1690. };
  1691. class LLOctreeCullNoFarClip : public LLOctreeCull
  1692. {
  1693. public:
  1694. LLOctreeCullNoFarClip(LLCamera* camera)
  1695. : LLOctreeCull(camera) { }
  1696. virtual S32 frustumCheck(const LLSpatialGroup* group)
  1697. {
  1698. return mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]);
  1699. }
  1700. virtual S32 frustumCheckObjects(const LLSpatialGroup* group)
  1701. {
  1702. S32 res = mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]);
  1703. return res;
  1704. }
  1705. };
  1706. class LLOctreeCullShadow : public LLOctreeCull
  1707. {
  1708. public:
  1709. LLOctreeCullShadow(LLCamera* camera)
  1710. : LLOctreeCull(camera) { }
  1711. virtual S32 frustumCheck(const LLSpatialGroup* group)
  1712. {
  1713. return mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1]);
  1714. }
  1715. virtual S32 frustumCheckObjects(const LLSpatialGroup* group)
  1716. {
  1717. return mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]);
  1718. }
  1719. };
  1720. class LLOctreeCullVisExtents: public LLOctreeCullShadow
  1721. {
  1722. public:
  1723. LLOctreeCullVisExtents(LLCamera* camera, LLVector4a& min, LLVector4a& max)
  1724. : LLOctreeCullShadow(camera), mMin(min), mMax(max), mEmpty(TRUE) { }
  1725. virtual bool earlyFail(LLSpatialGroup* group)
  1726. {
  1727. if (group->mOctreeNode->getParent() && //never occlusion cull the root node
  1728. LLPipeline::sUseOcclusion && //ignore occlusion if disabled
  1729. group->isOcclusionState(LLSpatialGroup::OCCLUDED))
  1730. {
  1731. return true;
  1732. }
  1733. return false;
  1734. }
  1735. virtual void traverse(const LLSpatialGroup::OctreeNode* n)
  1736. {
  1737. LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
  1738. if (earlyFail(group))
  1739. {
  1740. return;
  1741. }
  1742. if ((mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) ||
  1743. mRes == 2)
  1744. { //don't need to do frustum check
  1745. LLSpatialGroup::OctreeTraveler::traverse(n);
  1746. }
  1747. else
  1748. {
  1749. mRes = frustumCheck(group);
  1750. if (mRes)
  1751. { //at least partially in, run on down
  1752. LLSpatialGroup::OctreeTraveler::traverse(n);
  1753. }
  1754. mRes = 0;
  1755. }
  1756. }
  1757. virtual void processGroup(LLSpatialGroup* group)
  1758. {
  1759. llassert(!group->isState(LLSpatialGroup::DIRTY) && !group->getData().empty())
  1760. if (mRes < 2)
  1761. {
  1762. if (mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]) > 0)
  1763. {
  1764. mEmpty = FALSE;
  1765. update_min_max(mMin, mMax, group->mObjectExtents[0]);
  1766. update_min_max(mMin, mMax, group->mObjectExtents[1]);
  1767. }
  1768. }
  1769. else
  1770. {
  1771. mEmpty = FALSE;
  1772. update_min_max(mMin, mMax, group->mExtents[0]);
  1773. update_min_max(mMin, mMax, group->mExtents[1]);
  1774. }
  1775. }
  1776. BOOL mEmpty;
  1777. LLVector4a& mMin;
  1778. LLVector4a& mMax;
  1779. };
  1780. class LLOctreeCullDetectVisible: public LLOctreeCullShadow
  1781. {
  1782. public:
  1783. LLOctreeCullDetectVisible(LLCamera* camera)
  1784. : LLOctreeCullShadow(camera), mResult(FALSE) { }
  1785. virtual bool earlyFail(LLSpatialGroup* group)
  1786. {
  1787. if (mResult || //already found a node, don't check any more
  1788. (group->mOctreeNode->getParent() && //never occlusion cull the root node
  1789. LLPipeline::sUseOcclusion && //ignore occlusion if disabled
  1790. group->isOcclusionState(LLSpatialGroup::OCCLUDED)))
  1791. {
  1792. return true;
  1793. }
  1794. return false;
  1795. }
  1796. virtual void processGroup(LLSpatialGroup* group)
  1797. {
  1798. if (group->isVisible())
  1799. {
  1800. mResult = TRUE;
  1801. }
  1802. }
  1803. BOOL mResult;
  1804. };
  1805. class LLOctreeSelect : public LLOctreeCull
  1806. {
  1807. public:
  1808. LLOctreeSelect(LLCamera* camera, std::vector<LLDrawable*>* results)
  1809. : LLOctreeCull(camera), mResults(results) { }
  1810. virtual bool earlyFail(LLSpatialGroup* group) { return false; }
  1811. virtual void preprocess(LLSpatialGroup* group) { }
  1812. virtual void processGroup(LLSpatialGroup* group)
  1813. {
  1814. LLSpatialGroup::OctreeNode* branch = group->mOctreeNode;
  1815. for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
  1816. {
  1817. LLDrawable* drawable = *i;
  1818. if (!drawable->isDead())
  1819. {
  1820. if (drawable->isSpatialBridge())
  1821. {
  1822. drawable->setVisible(*mCamera, mResults, TRUE);
  1823. }
  1824. else
  1825. {
  1826. mResults->push_back(drawable);
  1827. }
  1828. }
  1829. }
  1830. }
  1831. std::vector<LLDrawable*>* mResults;
  1832. };
  1833. void drawBox(const LLVector3& c, const LLVector3& r)
  1834. {
  1835. LLVertexBuffer::unbind();
  1836. gGL.begin(LLRender::TRIANGLE_STRIP);
  1837. //left front
  1838. gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV);
  1839. gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV);
  1840. //right front
  1841. gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV);
  1842. gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV);
  1843. //right back
  1844. gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV);
  1845. gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV);
  1846. //left back
  1847. gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV);
  1848. gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV);
  1849. //left front
  1850. gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV);
  1851. gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV);
  1852. gGL.end();
  1853. //bottom
  1854. gGL.begin(LLRender::TRIANGLE_STRIP);
  1855. gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV);
  1856. gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV);
  1857. gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV);
  1858. gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV);
  1859. gGL.end();
  1860. //top
  1861. gGL.begin(LLRender::TRIANGLE_STRIP);
  1862. gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV);
  1863. gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV);
  1864. gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV);
  1865. gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV);
  1866. gGL.end();
  1867. }
  1868. void drawBox(const LLVector4a& c, const LLVector4a& r)
  1869. {
  1870. drawBox(reinterpret_cast<const LLVector3&>(c), reinterpret_cast<const LLVector3&>(r));
  1871. }
  1872. void drawBoxOutline(const LLVector3& pos, const LLVector3& size)
  1873. {
  1874. LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1));
  1875. LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1));
  1876. LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1));
  1877. LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1));
  1878. gGL.begin(LLRender::LINES);
  1879. //top
  1880. gGL.vertex3fv((pos+v1).mV);
  1881. gGL.vertex3fv((pos+v2).mV);
  1882. gGL.vertex3fv((pos+v2).mV);
  1883. gGL.vertex3fv((pos+v3).mV);
  1884. gGL.vertex3fv((pos+v3).mV);
  1885. gGL.vertex3fv((pos+v4).mV);
  1886. gGL.vertex3fv((pos+v4).mV);
  1887. gGL.vertex3fv((pos+v1).mV);
  1888. //bottom
  1889. gGL.vertex3fv((pos-v1).mV);
  1890. gGL.vertex3fv((pos-v2).mV);
  1891. gGL.vertex3fv((pos-v2).mV);
  1892. gGL.vertex3fv((pos-v3).mV);
  1893. gGL.vertex3fv((pos-v3).mV);
  1894. gGL.vertex3fv((pos-v4).mV);
  1895. gGL.vertex3fv((pos-v4).mV);
  1896. gGL.vertex3fv((pos-v1).mV);
  1897. //right
  1898. gGL.vertex3fv((pos+v1).mV);
  1899. gGL.vertex3fv((pos-v3).mV);
  1900. gGL.vertex3fv((pos+v4).mV);
  1901. gGL.vertex3fv((pos-v2).mV);
  1902. //left
  1903. gGL.vertex3fv((pos+v2).mV);
  1904. gGL.vertex3fv((pos-v4).mV);
  1905. gGL.vertex3fv((pos+v3).mV);
  1906. gGL.vertex3fv((pos-v1).mV);
  1907. gGL.end();
  1908. }
  1909. void drawBoxOutline(const LLVector4a& pos, const LLVector4a& size)
  1910. {
  1911. drawBoxOutline(reinterpret_cast<const LLVector3&>(pos), reinterpret_cast<const LLVector3&>(size));
  1912. }
  1913. class LLOctreeDirty : public LLOctreeTraveler<LLDrawable>
  1914. {
  1915. public:
  1916. virtual void visit(const LLOctreeNode<LLDrawable>* state)
  1917. {
  1918. LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
  1919. group->destroyGL();
  1920. for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
  1921. {
  1922. LLDrawable* drawable = *i;
  1923. if (drawable->getVObj().notNull() && !group->mSpatialPartition->mRenderByGroup)
  1924. {
  1925. gPipeline.markRebuild(drawable, LLDrawable::REBUILD_ALL, TRUE);
  1926. }
  1927. }
  1928. for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
  1929. {
  1930. LLSpatialBridge* bridge = *i;
  1931. traverse(bridge->mOctree);
  1932. }
  1933. }
  1934. };
  1935. void LLSpatialPartition::restoreGL()
  1936. {
  1937. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1938. }
  1939. void LLSpatialPartition::resetVertexBuffers()
  1940. {
  1941. LLOctreeDirty dirty;
  1942. dirty.traverse(mOctree);
  1943. }
  1944. BOOL LLSpatialPartition::isOcclusionEnabled()
  1945. {
  1946. return mOcclusionEnabled || LLPipeline::sUseOcclusion > 2;
  1947. }
  1948. BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax)
  1949. {
  1950. LLVector4a visMina, visMaxa;
  1951. visMina.load3(visMin.mV);
  1952. visMaxa.load3(visMax.mV);
  1953. {
  1954. LLFastTimer ftm(FTM_CULL_REBOUND);
  1955. LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
  1956. group->rebound();
  1957. }
  1958. LLOctreeCullVisExtents vis(&camera, visMina, visMaxa);
  1959. vis.traverse(mOctree);
  1960. visMin.set(visMina.getF32ptr());
  1961. visMax.set(visMaxa.getF32ptr());
  1962. return vis.mEmpty;
  1963. }
  1964. BOOL LLSpatialPartition::visibleObjectsInFrustum(LLCamera& camera)
  1965. {
  1966. LLOctreeCullDetectVisible vis(&camera);
  1967. vis.traverse(mOctree);
  1968. return vis.mResult;
  1969. }
  1970. S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select)
  1971. {
  1972. LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
  1973. #if LL_OCTREE_PARANOIA_CHECK
  1974. ((LLSpatialGroup*)mOctree->getListener(0))->checkStates();
  1975. #endif
  1976. {
  1977. LLFastTimer ftm(FTM_CULL_REBOUND);
  1978. LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
  1979. group->rebound();
  1980. }
  1981. #if LL_OCTREE_PARANOIA_CHECK
  1982. ((LLSpatialGroup*)mOctree->getListener(0))->validate();
  1983. #endif
  1984. if (for_select)
  1985. {
  1986. LLOctreeSelect selecter(&camera, results);
  1987. selecter.traverse(mOctree);
  1988. }
  1989. else if (LLPipeline::sShadowRender)
  1990. {
  1991. LLFastTimer ftm(FTM_FRUSTUM_CULL);
  1992. LLOctreeCullShadow culler(&camera);
  1993. culler.traverse(mOctree);
  1994. }
  1995. else if (mInfiniteFarClip || !LLPipeline::sUseFarClip)
  1996. {
  1997. LLFastTimer ftm(FTM_FRUSTUM_CULL);
  1998. LLOctreeCullNoFarClip culler(&camera);
  1999. culler.traverse(mOctree);
  2000. }
  2001. else
  2002. {
  2003. LLFastTimer ftm(FTM_FRUSTUM_CULL);
  2004. LLOctreeCull culler(&camera);
  2005. culler.traverse(mOctree);
  2006. }
  2007. return 0;
  2008. }
  2009. BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group)
  2010. {
  2011. if (camera->getOrigin().isExactlyZero())
  2012. {
  2013. return FALSE;
  2014. }
  2015. const F32 vel = SG_OCCLUSION_FUDGE*2.f;
  2016. LLVector4a fudge;
  2017. fudge.splat(vel);
  2018. const LLVector4a& c = group->mBounds[0];
  2019. LLVector4a r;
  2020. r.setAdd(group->mBounds[1], fudge);
  2021. /*if (r.magVecSquared() > 1024.0*1024.0)
  2022. {
  2023. return TRUE;
  2024. }*/
  2025. LLVector4a e;
  2026. e.load3(camera->getOrigin().mV);
  2027. LLVector4a min;
  2028. min.setSub(c,r);
  2029. LLVector4a max;
  2030. max.setAdd(c,r);
  2031. S32 lt = e.lessThan(min).getGatheredBits() & 0x7;
  2032. if (lt)
  2033. {
  2034. return FALSE;
  2035. }
  2036. S32 gt = e.greaterThan(max).getGatheredBits() & 0x7;
  2037. if (gt)
  2038. {
  2039. return FALSE;
  2040. }
  2041. return TRUE;
  2042. }
  2043. void pushVerts(LLDrawInfo* params, U32 mask)
  2044. {
  2045. LLRenderPass::applyModelMatrix(*params);
  2046. params->mVertexBuffer->setBuffer(mask);
  2047. params->mVertexBuffer->drawRange(params->mParticle ? LLRender::POINTS : LLRender::TRIANGLES,
  2048. params->mStart, params->mEnd, params->mCount, params->mOffset);
  2049. }
  2050. void pushVerts(LLSpatialGroup* group, U32 mask)
  2051. {
  2052. LLDrawInfo* params = NULL;
  2053. for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
  2054. {
  2055. for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
  2056. {
  2057. params = *j;
  2058. pushVerts(params, mask);
  2059. }
  2060. }
  2061. }
  2062. void pushVerts(LLFace* face, U32 mask)
  2063. {
  2064. llassert(face->verify());
  2065. LLVertexBuffer* buffer = face->getVertexBuffer();
  2066. if (buffer && (face->getGeomCount() >= 3))
  2067. {
  2068. buffer->setBuffer(mask);
  2069. U16 start = face->getGeomStart();
  2070. U16 end = start + face->getGeomCount()-1;
  2071. U32 count = face->getIndicesCount();
  2072. U16 offset = face->getIndicesStart();
  2073. buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset);
  2074. }
  2075. }
  2076. void pushVerts(LLDrawable* drawable, U32 mask)
  2077. {
  2078. for (S32 i = 0; i < drawable->getNumFaces(); ++i)
  2079. {
  2080. pushVerts(drawable->getFace(i), mask);
  2081. }
  2082. }
  2083. void pushVerts(LLVolume* volume)
  2084. {
  2085. LLVertexBuffer::unbind();
  2086. for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
  2087. {
  2088. const LLVolumeFace& face = volume->getVolumeFace(i);
  2089. LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, NULL, face.mNumIndices, face.mIndices);
  2090. }
  2091. }
  2092. void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
  2093. {
  2094. if (buffer)
  2095. {
  2096. buffer->setBuffer(mask);
  2097. buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0);
  2098. }
  2099. }
  2100. void pushBufferVerts(LLSpatialGroup* group, U32 mask)
  2101. {
  2102. if (group->mSpatialPartition->mRenderByGroup)
  2103. {
  2104. if (!group->mDrawMap.empty())
  2105. {
  2106. LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin());
  2107. LLRenderPass::applyModelMatrix(*params);
  2108. pushBufferVerts(group->mVertexBuffer, mask);
  2109. for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i)
  2110. {
  2111. for (LLSpatialGroup::buffer_texture_map_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
  2112. {
  2113. for (LLSpatialGroup::buffer_list_t::iterator k = j->second.begin(); k != j->second.end(); ++k)
  2114. {
  2115. pushBufferVerts(*k, mask);
  2116. }
  2117. }
  2118. }
  2119. }
  2120. }
  2121. else
  2122. {
  2123. drawBox(group->mBounds[0], group->mBounds[1]);
  2124. }
  2125. }
  2126. void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)
  2127. {
  2128. LLDrawInfo* params = NULL;
  2129. LLColor4 colors[] = {
  2130. LLColor4::green,
  2131. LLColor4::green1,
  2132. LLColor4::green2,
  2133. LLColor4::green3,
  2134. LLColor4::green4,
  2135. LLColor4::green5,
  2136. LLColor4::green6
  2137. };
  2138. static const U32 col_count = LL_ARRAY_SIZE(colors);
  2139. U32 col = 0;
  2140. for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
  2141. {
  2142. for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
  2143. {
  2144. params = *j;
  2145. LLRenderPass::applyModelMatrix(*params);
  2146. gGL.diffuseColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f);
  2147. params->mVertexBuffer->setBuffer(mask);
  2148. params->mVertexBuffer->drawRange(params->mParticle ? LLRender::POINTS : LLRender::TRIANGLES,
  2149. params->mStart, params->mEnd, params->mCount, params->mOffset);
  2150. col = (col+1)%col_count;
  2151. }
  2152. }
  2153. }
  2154. void renderOctree(LLSpatialGroup* group)
  2155. {
  2156. //render solid object bounding box, color
  2157. //coded by buffer usage and activity
  2158. gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
  2159. LLVector4 col;
  2160. if (group->mBuilt > 0.f)
  2161. {
  2162. group->mBuilt -= 2.f * gFrameIntervalSeconds;
  2163. if (group->mBufferUsage == GL_STATIC_DRAW_ARB)
  2164. {
  2165. col.setVec(1.0f, 0, 0, group->mBuilt*0.5f);
  2166. }
  2167. else
  2168. {
  2169. col.setVec(0.1f,0.1f,1,0.1f);
  2170. //col.setVec(1.0f, 1.0f, 0, sinf(group->mBuilt*3.14159f)*0.5f);
  2171. }
  2172. if (group->mBufferUsage != GL_STATIC_DRAW_ARB)
  2173. {
  2174. LLGLDepthTest gl_depth(FALSE, FALSE);
  2175. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  2176. gGL.diffuseColor4f(1,0,0,group->mBuilt);
  2177. gGL.flush();
  2178. glLineWidth(5.f);
  2179. drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
  2180. gGL.flush();
  2181. glLineWidth(1.f);
  2182. gGL.flush();
  2183. for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
  2184. {
  2185. LLDrawable* drawable = *i;
  2186. if (!group->mSpatialPartition->isBridge())
  2187. {
  2188. gGL.pushMatrix();
  2189. LLVector3 trans = drawable->getRegion()->getOriginAgent();
  2190. gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]);
  2191. }
  2192. for (S32 j = 0; j < drawable->getNumFaces(); j++)
  2193. {
  2194. LLFace* face = drawable->getFace(j);
  2195. if (face->getVertexBuffer())
  2196. {
  2197. if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f)
  2198. {
  2199. gGL.diffuseColor4f(0, 1, 0, group->mBuilt);
  2200. }
  2201. else if (gFrameTimeSeconds - face->mLastMoveTime < 0.5f)
  2202. {
  2203. gGL.diffuseColor4f(1, 0, 0, group->mBuilt);
  2204. }
  2205. else
  2206. {
  2207. continue;
  2208. }
  2209. face->getVertexBuffer()->setBuffer(LLVertexBuffer::MAP_VERTEX);
  2210. //drawBox((face->mExtents[0] + face->mExtents[1])*0.5f,
  2211. // (face->mExtents[1]-face->mExtents[0])*0.5f);
  2212. face->getVertexBuffer()->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart());
  2213. }
  2214. }
  2215. if (!group->mSpatialPartition->isBridge())
  2216. {
  2217. gGL.popMatrix();
  2218. }
  2219. }
  2220. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  2221. gGL.diffuseColor4f(1,1,1,1);
  2222. }
  2223. }
  2224. else
  2225. {
  2226. if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->getData().empty()
  2227. && group->mSpatialPartition->mRenderByGroup)
  2228. {
  2229. col.setVec(0.8f, 0.4f, 0.1f, 0.1f);
  2230. }
  2231. else
  2232. {
  2233. col.setVec(0.1f, 0.1f, 1.f, 0.1f);
  2234. }
  2235. }
  2236. gGL.diffuseColor4fv(col.mV);
  2237. LLVector4a fudge;
  2238. fudge.splat(0.001f);
  2239. LLVector4a size = group->mObjectBounds[1];
  2240. size.mul(1.01f);
  2241. size.add(fudge);
  2242. //{
  2243. // LLGLDepthTest depth(GL_TRUE, GL_FALSE);
  2244. // drawBox(group->mObjectBounds[0], fudge);
  2245. //}
  2246. gGL.setSceneBlendType(LLRender::BT_ALPHA);
  2247. //if (group->mBuilt <= 0.f)
  2248. {
  2249. //draw opaque outline
  2250. //gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], 1.f);
  2251. //drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
  2252. gGL.diffuseColor4f(0,1,1,1);
  2253. drawBoxOutline(group->mBounds[0],group->mBounds[1]);
  2254. //draw bounding box for draw info
  2255. /*if (group->mSpatialPartition->mRenderByGroup)
  2256. {
  2257. gGL.diffuseColor4f(1.0f, 0.75f, 0.25f, 0.6f);
  2258. for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
  2259. {
  2260. for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
  2261. {
  2262. LLDrawInfo* draw_info = *j;
  2263. LLVector4a center;
  2264. center.setAdd(draw_info->mExtents[1], draw_info->mExtents[0]);
  2265. center.mul(0.5f);
  2266. LLVector4a size;
  2267. size.setSub(draw_info->mExtents[1], draw_info->mExtents[0]);
  2268. size.mul(0.5f);
  2269. drawBoxOutline(center, size);
  2270. }
  2271. }
  2272. }*/
  2273. }
  2274. // LLSpatialGroup::OctreeNode* node = group->mOctreeNode;
  2275. // gGL.diffuseColor4f(0,1,0,1);
  2276. // drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize()));
  2277. }
  2278. void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
  2279. {
  2280. LLGLEnable blend(GL_BLEND);
  2281. gGL.setSceneBlendType(LLRender::BT_ALPHA);
  2282. LLGLEnable cull(GL_CULL_FACE);
  2283. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  2284. BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
  2285. !group->getData().empty();
  2286. if (render_objects)
  2287. {
  2288. LLGLDepthTest depth