aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llspatialpartition.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:34 -0500
committerJacek Antonelli2008-08-15 23:45:34 -0500
commitcd17687f01420952712a500107e0f93e7ab8d5f8 (patch)
treece48c2b706f2c1176290e39fb555fbdf6648ce01 /linden/indra/newview/llspatialpartition.cpp
parentSecond Life viewer sources 1.19.0.5 (diff)
downloadmeta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.zip
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.gz
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.bz2
meta-impy-cd17687f01420952712a500107e0f93e7ab8d5f8.tar.xz
Second Life viewer sources 1.19.1.0
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/llspatialpartition.cpp2125
1 files changed, 1021 insertions, 1104 deletions
diff --git a/linden/indra/newview/llspatialpartition.cpp b/linden/indra/newview/llspatialpartition.cpp
index 656b236..774bf6b 100644
--- a/linden/indra/newview/llspatialpartition.cpp
+++ b/linden/indra/newview/llspatialpartition.cpp
@@ -43,25 +43,47 @@
43#include "llviewerregion.h" 43#include "llviewerregion.h"
44#include "llcamera.h" 44#include "llcamera.h"
45#include "pipeline.h" 45#include "pipeline.h"
46 46#include "llglimmediate.h"
47static GLuint sBoxList = 0; 47#include "lloctree.h"
48 48
49const F32 SG_OCCLUSION_FUDGE = 1.01f; 49const F32 SG_OCCLUSION_FUDGE = 1.01f;
50//const S32 SG_LOD_PERIOD = 16; 50#define SG_DISCARD_TOLERANCE 0.01f
51
52#define SG_DISCARD_TOLERANCE 0.25f
53 51
54#if LL_OCTREE_PARANOIA_CHECK 52#if LL_OCTREE_PARANOIA_CHECK
55#define assert_octree_valid(x) x->validate() 53#define assert_octree_valid(x) x->validate()
54#define assert_states_valid(x) ((LLSpatialGroup*) x->mSpatialPartition->mOctree->getListener(0))->checkStates()
56#else 55#else
57#define assert_octree_valid(x) 56#define assert_octree_valid(x)
57#define assert_states_valid(x)
58#endif 58#endif
59 59
60
60static U32 sZombieGroups = 0; 61static U32 sZombieGroups = 0;
62U32 LLSpatialGroup::sNodeCount = 0;
61 63
62static F32 sLastMaxTexPriority = 1.f; 64static F32 sLastMaxTexPriority = 1.f;
63static F32 sCurMaxTexPriority = 1.f; 65static F32 sCurMaxTexPriority = 1.f;
64 66
67class LLOcclusionQueryPool : public LLGLNamePool
68{
69protected:
70 virtual GLuint allocateName()
71 {
72 GLuint name;
73 glGenQueriesARB(1, &name);
74 return name;
75 }
76
77 virtual void releaseName(GLuint name)
78 {
79 glDeleteQueriesARB(1, &name);
80 }
81};
82
83static LLOcclusionQueryPool sQueryPool;
84
85BOOL LLSpatialPartition::sFreezeState = FALSE;
86
65//static counter for frame to switch LOD on 87//static counter for frame to switch LOD on
66 88
67void sg_assert(BOOL expr) 89void sg_assert(BOOL expr)
@@ -90,6 +112,134 @@ void validate_drawable(LLDrawable* drawablep)
90#define validate_drawable(x) 112#define validate_drawable(x)
91#endif 113#endif
92 114
115
116S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad)
117{
118 F32 d = 0.f;
119 F32 t;
120 F32 r = rad*rad;
121
122 if ((min-origin).magVecSquared() < r &&
123 (max-origin).magVecSquared() < r)
124 {
125 return 2;
126 }
127
128 for (U32 i = 0; i < 3; i++)
129 {
130 if (origin.mV[i] < min.mV[i])
131 {
132 t = min.mV[i] - origin.mV[i];
133 d += t*t;
134 }
135 else if (origin.mV[i] > max.mV[i])
136 {
137 t = origin.mV[i] - max.mV[i];
138 d += t*t;
139 }
140
141 if (d > r)
142 {
143 return 0;
144 }
145 }
146
147 return 1;
148}
149
150
151typedef enum
152{
153 b000 = 0x00,
154 b001 = 0x01,
155 b010 = 0x02,
156 b011 = 0x03,
157 b100 = 0x04,
158 b101 = 0x05,
159 b110 = 0x06,
160 b111 = 0x07,
161} eLoveTheBits;
162
163//contact Runitai Linden for a copy of the SL object used to write this table
164//basically, you give the table a bitmask of the look-at vector to a node and it
165//gives you a triangle fan index array
166static U8 sOcclusionIndices[] =
167{
168 // 000
169 b111, b110, b010, b011, b001, b101, b100, b110,
170 //001
171 b110, b000, b010, b011, b111, b101, b100, b000,
172 //010
173 b101, b100, b110, b111, b011, b001, b000, b100,
174 //011
175 b100, b010, b110, b111, b101, b001, b000, b010,
176 //100
177 b011, b010, b000, b001, b101, b111, b110, b010,
178 //101
179 b010, b100, b000, b001, b011, b111, b110, b100,
180 //110
181 b001, b000, b100, b101, b111, b011, b010, b000,
182 //111
183 b000, b110, b100, b101, b001, b011, b010, b110,
184};
185
186U8* get_occlusion_indices(LLCamera* camera, const LLVector3& center)
187{
188 LLVector3 d = center - camera->getOrigin();
189
190 U8 cypher = 0;
191 if (d.mV[0] > 0)
192 {
193 cypher |= b100;
194 }
195 if (d.mV[1] > 0)
196 {
197 cypher |= b010;
198 }
199 if (d.mV[2] > 0)
200 {
201 cypher |= b001;
202 }
203
204 return sOcclusionIndices+cypher*8;
205}
206
207void LLSpatialGroup::buildOcclusion()
208{
209 if (!mOcclusionVerts)
210 {
211 mOcclusionVerts = new F32[8*3];
212 }
213
214 LLVector3 r = mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.1f,0.1f,0.1f);
215
216 for (U32 k = 0; k < 3; k++)
217 {
218 r.mV[k] = llmin(mBounds[1].mV[k]+0.25f, r.mV[k]);
219 }
220
221 F32* v = mOcclusionVerts;
222 F32* c = mBounds[0].mV;
223 F32* s = r.mV;
224
225 //vertex positions are encoded so the 3 bits of their vertex index
226 //correspond to their axis facing, with bit position 3,2,1 matching
227 //axis facing x,y,z, bit set meaning positive facing, bit clear
228 //meaning negative facing
229 v[0] = c[0]-s[0]; v[1] = c[1]-s[1]; v[2] = c[2]-s[2]; // 0 - 0000
230 v[3] = c[0]-s[0]; v[4] = c[1]-s[1]; v[5] = c[2]+s[2]; // 1 - 0001
231 v[6] = c[0]-s[0]; v[7] = c[1]+s[1]; v[8] = c[2]-s[2]; // 2 - 0010
232 v[9] = c[0]-s[0]; v[10] = c[1]+s[1]; v[11] = c[2]+s[2]; // 3 - 0011
233
234 v[12] = c[0]+s[0]; v[13] = c[1]-s[1]; v[14] = c[2]-s[2]; // 4 - 0100
235 v[15] = c[0]+s[0]; v[16] = c[1]-s[1]; v[17] = c[2]+s[2]; // 5 - 0101
236 v[18] = c[0]+s[0]; v[19] = c[1]+s[1]; v[20] = c[2]-s[2]; // 6 - 0110
237 v[21] = c[0]+s[0]; v[22] = c[1]+s[1]; v[23] = c[2]+s[2]; // 7 - 0111
238
239 clearState(LLSpatialGroup::OCCLUSION_DIRTY);
240}
241
242
93BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group); 243BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group);
94 244
95BOOL LLLineSegmentAABB(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size) 245BOOL LLLineSegmentAABB(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size)
@@ -150,6 +300,15 @@ LLSpatialGroup::~LLSpatialGroup()
150 sZombieGroups--; 300 sZombieGroups--;
151 } 301 }
152 302
303 sNodeCount--;
304
305 if (gGLManager.mHasOcclusionQuery && mOcclusionQuery)
306 {
307 sQueryPool.release(mOcclusionQuery);
308 }
309
310 delete [] mOcclusionVerts;
311
153 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 312 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
154 clearDrawMap(); 313 clearDrawMap();
155} 314}
@@ -159,55 +318,16 @@ void LLSpatialGroup::clearDrawMap()
159 mDrawMap.clear(); 318 mDrawMap.clear();
160} 319}
161 320
162class LLRelightPainter : public LLSpatialGroup::OctreeTraveler 321BOOL LLSpatialGroup::isVisible() const
163{ 322{
164public: 323 return mVisible == LLDrawable::getCurrentFrame() ? TRUE : FALSE;
165 LLVector3 mOrigin, mDir; 324}
166 F32 mRadius;
167
168 LLRelightPainter(LLVector3 origin, LLVector3 dir, F32 radius)
169 : mOrigin(origin), mDir(dir), mRadius(radius)
170 { }
171
172 virtual void traverse(const LLSpatialGroup::TreeNode* n)
173 {
174 LLSpatialGroup::OctreeNode* node = (LLSpatialGroup::OctreeNode*) n;
175
176 LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
177 group->setState(LLSpatialGroup::RESHADOW);
178
179 for (U32 i = 0; i < node->getChildCount(); i++)
180 {
181 const LLSpatialGroup::OctreeNode* child = node->getChild(i);
182 LLSpatialGroup* group = (LLSpatialGroup*) child->getListener(0);
183
184 LLVector3 res;
185
186 LLVector3 center, size;
187
188 center = group->mBounds[0];
189 size = group->mBounds[1];
190
191 if (child->isInside(LLVector3d(mOrigin)) || LLRayAABB(center, size, mOrigin, mDir, res, mRadius))
192 {
193 traverse(child);
194 }
195 }
196 }
197
198 virtual void visit(const LLSpatialGroup::OctreeState* branch) { }
199
200};
201 325
202BOOL LLSpatialGroup::isVisible() 326void LLSpatialGroup::setVisible()
203{ 327{
204 if (LLPipeline::sUseOcclusion) 328 if (!LLSpatialPartition::sFreezeState)
205 {
206 return !isState(CULLED | OCCLUDED);
207 }
208 else
209 { 329 {
210 return !isState(CULLED); 330 mVisible = LLDrawable::getCurrentFrame();
211 } 331 }
212} 332}
213 333
@@ -232,7 +352,7 @@ void LLSpatialGroup::validate()
232 sg_assert(drawable->getSpatialBridge() == mSpatialPartition->asBridge()); 352 sg_assert(drawable->getSpatialBridge() == mSpatialPartition->asBridge());
233 } 353 }
234 354
235 if (drawable->isSpatialBridge()) 355 /*if (drawable->isSpatialBridge())
236 { 356 {
237 LLSpatialPartition* part = drawable->asPartition(); 357 LLSpatialPartition* part = drawable->asPartition();
238 if (!part) 358 if (!part)
@@ -241,7 +361,7 @@ void LLSpatialGroup::validate()
241 } 361 }
242 LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); 362 LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0);
243 group->validate(); 363 group->validate();
244 } 364 }*/
245 } 365 }
246 366
247 for (U32 i = 0; i < mOctreeNode->getChildCount(); ++i) 367 for (U32 i = 0; i < mOctreeNode->getChildCount(); ++i)
@@ -267,6 +387,71 @@ void LLSpatialGroup::validate()
267#endif 387#endif
268} 388}
269 389
390
391
392class LLOctreeStateCheck : public LLOctreeTraveler<LLDrawable>
393{
394public:
395 U32 mInheritedMask;
396
397 LLOctreeStateCheck(): mInheritedMask(0) { }
398
399 virtual void traverse(const LLSpatialGroup::OctreeNode* node)
400 {
401 LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
402
403 node->accept(this);
404
405 U32 temp = mInheritedMask;
406 mInheritedMask |= group->getState() &
407 (LLSpatialGroup::OCCLUDED);
408
409 for (U32 i = 0; i < node->getChildCount(); i++)
410 {
411 traverse(node->getChild(i));
412 }
413
414 mInheritedMask = temp;
415 }
416
417 virtual void visit(const LLOctreeNode<LLDrawable>* state)
418 {
419 LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
420
421 if (mInheritedMask && !group->isState(mInheritedMask))
422 {
423 llerrs << "Spatial group failed inherited mask test." << llendl;
424 }
425
426 if (group->isState(LLSpatialGroup::DIRTY))
427 {
428 assert_parent_state(group, LLSpatialGroup::DIRTY);
429 }
430 }
431
432 void assert_parent_state(LLSpatialGroup* group, U32 state)
433 {
434 LLSpatialGroup* parent = group->getParent();
435 while (parent)
436 {
437 if (!parent->isState(state))
438 {
439 llerrs << "Spatial group failed parent state check." << llendl;
440 }
441 parent = parent->getParent();
442 }
443 }
444};
445
446
447void LLSpatialGroup::checkStates()
448{
449#if LL_OCTREE_PARANOIA_CHECK
450 LLOctreeStateCheck checker;
451 checker.traverse(mOctreeNode);
452#endif
453}
454
270void validate_draw_info(LLDrawInfo& params) 455void validate_draw_info(LLDrawInfo& params)
271{ 456{
272#if LL_OCTREE_PARANOIA_CHECK 457#if LL_OCTREE_PARANOIA_CHECK
@@ -316,8 +501,8 @@ void LLSpatialGroup::validateDrawMap()
316#if LL_OCTREE_PARANOIA_CHECK 501#if LL_OCTREE_PARANOIA_CHECK
317 for (draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i) 502 for (draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i)
318 { 503 {
319 std::vector<LLDrawInfo*>& draw_vec = i->second; 504 LLSpatialGroup::drawmap_elem_t& draw_vec = i->second;
320 for (std::vector<LLDrawInfo*>::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) 505 for (drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j)
321 { 506 {
322 LLDrawInfo& params = **j; 507 LLDrawInfo& params = **j;
323 508
@@ -327,32 +512,6 @@ void LLSpatialGroup::validateDrawMap()
327#endif 512#endif
328} 513}
329 514
330void LLSpatialGroup::makeStatic()
331{
332#if !LL_DARWIN
333 if (isState(GEOM_DIRTY | ALPHA_DIRTY))
334 {
335 return;
336 }
337
338 if (mSpatialPartition->mRenderByGroup && mBufferUsage != GL_STATIC_DRAW_ARB)
339 {
340 mBufferUsage = GL_STATIC_DRAW_ARB;
341 if (mVertexBuffer.notNull())
342 {
343 mVertexBuffer->makeStatic();
344 }
345
346 for (buffer_map_t::iterator i = mBufferMap.begin(); i != mBufferMap.end(); ++i)
347 {
348 i->second->makeStatic();
349 }
350
351 mBuilt = 1.f;
352 }
353#endif
354}
355
356BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) 515BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate)
357{ 516{
358 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 517 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -369,7 +528,7 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate)
369 { 528 {
370 unbound(); 529 unbound();
371 setState(OBJECT_DIRTY); 530 setState(OBJECT_DIRTY);
372 setState(GEOM_DIRTY); 531 //setState(GEOM_DIRTY);
373 validate_drawable(drawablep); 532 validate_drawable(drawablep);
374 return TRUE; 533 return TRUE;
375 } 534 }
@@ -389,8 +548,7 @@ BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_oc
389 { 548 {
390 drawablep->setSpatialGroup(this); 549 drawablep->setSpatialGroup(this);
391 validate_drawable(drawablep); 550 validate_drawable(drawablep);
392 setState(OBJECT_DIRTY | GEOM_DIRTY); 551 setState(OBJECT_DIRTY | GEOM_DIRTY | DISCARD_QUERY);
393 mLastAddTime = gFrameTimeSeconds;
394 if (drawablep->isSpatialBridge()) 552 if (drawablep->isSpatialBridge())
395 { 553 {
396 mBridgeList.push_back((LLSpatialBridge*) drawablep); 554 mBridgeList.push_back((LLSpatialBridge*) drawablep);
@@ -431,32 +589,27 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
431 group->clearDrawMap(); 589 group->clearDrawMap();
432 590
433 //get geometry count 591 //get geometry count
434 group->mIndexCount = 0; 592 U32 index_count = 0;
435 group->mVertexCount = 0; 593 U32 vertex_count = 0;
436 594
437 addGeometryCount(group, group->mVertexCount, group->mIndexCount); 595 addGeometryCount(group, vertex_count, index_count);
438 596
439 if (group->mVertexCount > 0 && group->mIndexCount > 0) 597 if (vertex_count > 0 && index_count > 0)
440 { //create vertex buffer containing volume geometry for this node 598 { //create vertex buffer containing volume geometry for this node
441 group->mBuilt = 1.f; 599 group->mBuilt = 1.f;
442 if (group->mVertexBuffer.isNull() || (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) 600 if (group->mVertexBuffer.isNull() || (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs))
443 { 601 {
444 //LLFastTimer ftm(LLFastTimer::FTM_REBUILD_NONE_VB);
445 group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); 602 group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage);
446 group->mVertexBuffer->allocateBuffer(group->mVertexCount, group->mIndexCount, true); 603 group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true);
447 stop_glerror(); 604 stop_glerror();
448 } 605 }
449 else 606 else
450 { 607 {
451 //LLFastTimer ftm(LLFastTimer::FTM_REBUILD_NONE_VB); 608 group->mVertexBuffer->resizeBuffer(vertex_count, index_count);
452 group->mVertexBuffer->resizeBuffer(group->mVertexCount, group->mIndexCount);
453 stop_glerror(); 609 stop_glerror();
454 } 610 }
455 611
456 { 612 getGeometry(group);
457 LLFastTimer ftm((LLFastTimer::EFastTimerType) ((U32) LLFastTimer::FTM_REBUILD_VOLUME_VB + mPartitionType));
458 getGeometry(group);
459 }
460 } 613 }
461 else 614 else
462 { 615 {
@@ -465,12 +618,12 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
465 } 618 }
466 619
467 group->mLastUpdateTime = gFrameTimeSeconds; 620 group->mLastUpdateTime = gFrameTimeSeconds;
468 group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MATRIX_DIRTY); 621 group->clearState(LLSpatialGroup::GEOM_DIRTY);
469} 622}
470 623
471BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxOut) 624BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxOut)
472{ 625{
473 const OctreeState* node = mOctreeNode->getOctState(); 626 const OctreeNode* node = mOctreeNode;
474 627
475 if (node->getData().empty()) 628 if (node->getData().empty())
476 { //don't do anything if there are no objects 629 { //don't do anything if there are no objects
@@ -489,7 +642,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO
489 clearState(OBJECT_DIRTY); 642 clearState(OBJECT_DIRTY);
490 643
491 //initialize bounding box to first element 644 //initialize bounding box to first element
492 OctreeState::const_element_iter i = node->getData().begin(); 645 OctreeNode::const_element_iter i = node->getData().begin();
493 LLDrawable* drawablep = *i; 646 LLDrawable* drawablep = *i;
494 const LLVector3* minMax = drawablep->getSpatialExtents(); 647 const LLVector3* minMax = drawablep->getSpatialExtents();
495 648
@@ -612,6 +765,11 @@ BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree)
612 } 765 }
613 } 766 }
614 } 767 }
768
769 if (getElementCount() == 0)
770 { //delete draw map on last element removal since a rebuild might never happen
771 clearDrawMap();
772 }
615 } 773 }
616 return TRUE; 774 return TRUE;
617} 775}
@@ -629,7 +787,21 @@ void LLSpatialGroup::shift(const LLVector3 &offset)
629 mObjectExtents[0] += offset; 787 mObjectExtents[0] += offset;
630 mObjectExtents[1] += offset; 788 mObjectExtents[1] += offset;
631 789
632 setState(GEOM_DIRTY | MATRIX_DIRTY | OCCLUSION_DIRTY); 790 if (!mSpatialPartition->mRenderByGroup)
791 {
792 setState(GEOM_DIRTY);
793 }
794
795 if (mOcclusionVerts)
796 {
797 for (U32 i = 0; i < 8; i++)
798 {
799 F32* v = mOcclusionVerts+i*3;
800 v[0] += offset.mV[0];
801 v[1] += offset.mV[1];
802 v[2] += offset.mV[2];
803 }
804 }
633} 805}
634 806
635class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler 807class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler
@@ -637,7 +809,7 @@ class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler
637public: 809public:
638 U32 mState; 810 U32 mState;
639 LLSpatialSetState(U32 state) : mState(state) { } 811 LLSpatialSetState(U32 state) : mState(state) { }
640 virtual void visit(const LLSpatialGroup::OctreeState* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); } 812 virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); }
641}; 813};
642 814
643class LLSpatialSetStateDiff : public LLSpatialSetState 815class LLSpatialSetStateDiff : public LLSpatialSetState
@@ -656,9 +828,22 @@ public:
656 } 828 }
657}; 829};
658 830
831void LLSpatialGroup::setState(U32 state)
832{
833 if (!LLSpatialPartition::sFreezeState)
834 {
835 mState |= state;
836 }
837}
838
659void LLSpatialGroup::setState(U32 state, S32 mode) 839void LLSpatialGroup::setState(U32 state, S32 mode)
660{ 840{
661 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 841 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
842 if (LLSpatialPartition::sFreezeState)
843 {
844 return;
845 }
846
662 if (mode > STATE_MODE_SINGLE) 847 if (mode > STATE_MODE_SINGLE)
663 { 848 {
664 if (mode == STATE_MODE_DIFF) 849 if (mode == STATE_MODE_DIFF)
@@ -683,7 +868,7 @@ class LLSpatialClearState : public LLSpatialGroup::OctreeTraveler
683public: 868public:
684 U32 mState; 869 U32 mState;
685 LLSpatialClearState(U32 state) : mState(state) { } 870 LLSpatialClearState(U32 state) : mState(state) { }
686 virtual void visit(const LLSpatialGroup::OctreeState* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); } 871 virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); }
687}; 872};
688 873
689class LLSpatialClearStateDiff : public LLSpatialClearState 874class LLSpatialClearStateDiff : public LLSpatialClearState
@@ -695,17 +880,29 @@ public:
695 { 880 {
696 LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); 881 LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
697 882
698 if (!group->isState(mState)) 883 if (group->isState(mState))
699 { 884 {
700 LLSpatialGroup::OctreeTraveler::traverse(n); 885 LLSpatialGroup::OctreeTraveler::traverse(n);
701 } 886 }
702 } 887 }
703}; 888};
704 889
890void LLSpatialGroup::clearState(U32 state)
891{
892 if (!LLSpatialPartition::sFreezeState)
893 {
894 mState &= ~state;
895 }
896}
705 897
706void LLSpatialGroup::clearState(U32 state, S32 mode) 898void LLSpatialGroup::clearState(U32 state, S32 mode)
707{ 899{
708 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 900 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
901 if (LLSpatialPartition::sFreezeState)
902 {
903 return;
904 }
905
709 if (mode > STATE_MODE_SINGLE) 906 if (mode > STATE_MODE_SINGLE)
710 { 907 {
711 if (mode == STATE_MODE_DIFF) 908 if (mode == STATE_MODE_DIFF)
@@ -723,20 +920,6 @@ void LLSpatialGroup::clearState(U32 state, S32 mode)
723 { 920 {
724 mState &= ~state; 921 mState &= ~state;
725 } 922 }
726
727#if LL_OCTREE_PARANOIA_CHECK
728 if (state & LLSpatialGroup::ACTIVE_OCCLUSION)
729 {
730 LLSpatialPartition* part = mSpatialPartition;
731 for (U32 i = 0; i < part->mOccludedList.size(); i++)
732 {
733 if (part->mOccludedList[i] == this)
734 {
735 llerrs << "LLSpatialGroup state error: " << mState << llendl;
736 }
737 }
738 }
739#endif
740} 923}
741 924
742//====================================== 925//======================================
@@ -750,15 +933,15 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
750 mSpatialPartition(part), 933 mSpatialPartition(part),
751 mVertexBuffer(NULL), 934 mVertexBuffer(NULL),
752 mBufferUsage(GL_STATIC_DRAW_ARB), 935 mBufferUsage(GL_STATIC_DRAW_ARB),
936 mVisible(0),
753 mDistance(0.f), 937 mDistance(0.f),
754 mDepth(0.f), 938 mDepth(0.f),
755 mLastUpdateDistance(-1.f), 939 mLastUpdateDistance(-1.f),
756 mLastUpdateTime(gFrameTimeSeconds), 940 mLastUpdateTime(gFrameTimeSeconds),
757 mLastAddTime(gFrameTimeSeconds),
758 mLastRenderTime(gFrameTimeSeconds),
759 mViewAngle(0.f), 941 mViewAngle(0.f),
760 mLastUpdateViewAngle(-1.f) 942 mLastUpdateViewAngle(-1.f)
761{ 943{
944 sNodeCount++;
762 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 945 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
763 946
764 sg_assert(mOctreeNode->getListenerCount() == 0); 947 sg_assert(mOctreeNode->getListenerCount() == 0);
@@ -771,6 +954,9 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
771 part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod; 954 part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod;
772 mLODHash = part->mLODSeed; 955 mLODHash = part->mLODSeed;
773 956
957 mOcclusionQuery = 0;
958 mOcclusionVerts = NULL;
959
774 mRadius = 1; 960 mRadius = 1;
775 mPixelArea = 1024.f; 961 mPixelArea = 1024.f;
776} 962}
@@ -783,7 +969,7 @@ void LLSpatialGroup::updateDistance(LLCamera &camera)
783 llerrs << "Spatial group dirty on distance update." << llendl; 969 llerrs << "Spatial group dirty on distance update." << llendl;
784 } 970 }
785#endif 971#endif
786 if (!getData().empty()) 972 if (!getData().empty() && !LLSpatialPartition::sFreezeState)
787 { 973 {
788 mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() : 974 mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() :
789 (F32) mOctreeNode->getSize().magVec(); 975 (F32) mOctreeNode->getSize().magVec();
@@ -805,19 +991,22 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera)
805 991
806 if (!group->isState(LLSpatialGroup::ALPHA_DIRTY)) 992 if (!group->isState(LLSpatialGroup::ALPHA_DIRTY))
807 { 993 {
808 LLVector3 view_angle = LLVector3(eye * LLVector3(1,0,0), 994 if (!group->mSpatialPartition->isBridge())
809 eye * LLVector3(0,1,0),
810 eye * LLVector3(0,0,1));
811
812 if ((view_angle-group->mLastUpdateViewAngle).magVec() > 0.64f)
813 { 995 {
814 group->mViewAngle = view_angle; 996 LLVector3 view_angle = LLVector3(eye * LLVector3(1,0,0),
815 group->mLastUpdateViewAngle = view_angle; 997 eye * LLVector3(0,1,0),
816 //for occasional alpha sorting within the group 998 eye * LLVector3(0,0,1));
817 //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order, 999
818 //not setting this node to dirty would be a very good thing 1000 if ((view_angle-group->mLastUpdateViewAngle).magVec() > 0.64f)
819 group->setState(LLSpatialGroup::ALPHA_DIRTY); 1001 {
820 } 1002 group->mViewAngle = view_angle;
1003 group->mLastUpdateViewAngle = view_angle;
1004 //for occasional alpha sorting within the group
1005 //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order,
1006 //not setting this node to dirty would be a very good thing
1007 group->setState(LLSpatialGroup::ALPHA_DIRTY);
1008 }
1009 }
821 } 1010 }
822 1011
823 //calculate depth of node for alpha sorting 1012 //calculate depth of node for alpha sorting
@@ -831,17 +1020,6 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera)
831 } 1020 }
832 1021
833 group->mDepth = v * at; 1022 group->mDepth = v * at;
834
835 F32 water_height = gAgent.getRegion()->getWaterHeight();
836 //figure out if this node is above or below water
837 if (group->mObjectBounds[0].mV[2] < water_height)
838 {
839 group->setState(LLSpatialGroup::BELOW_WATER);
840 }
841 else
842 {
843 group->clearState(LLSpatialGroup::BELOW_WATER);
844 }
845 } 1023 }
846 else 1024 else
847 { 1025 {
@@ -863,6 +1041,11 @@ F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
863 return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera); 1041 return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera);
864} 1042}
865 1043
1044BOOL LLSpatialGroup::needsUpdate()
1045{
1046 return (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE;
1047}
1048
866BOOL LLSpatialGroup::changeLOD() 1049BOOL LLSpatialGroup::changeLOD()
867{ 1050{
868 if (isState(ALPHA_DIRTY)) 1051 if (isState(ALPHA_DIRTY))
@@ -885,7 +1068,7 @@ BOOL LLSpatialGroup::changeLOD()
885 } 1068 }
886 } 1069 }
887 1070
888 if (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) 1071 if (needsUpdate())
889 { 1072 {
890 return TRUE; 1073 return TRUE;
891 } 1074 }
@@ -923,7 +1106,6 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node)
923 } 1106 }
924 1107
925 clearDrawMap(); 1108 clearDrawMap();
926 mOcclusionVerts = NULL;
927 mVertexBuffer = NULL; 1109 mVertexBuffer = NULL;
928 mBufferMap.clear(); 1110 mBufferMap.clear();
929 sZombieGroups++; 1111 sZombieGroups++;
@@ -954,6 +1136,8 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
954 } 1136 }
955 1137
956 unbound(); 1138 unbound();
1139
1140 assert_states_valid(this);
957} 1141}
958 1142
959void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNode* child) 1143void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNode* child)
@@ -963,17 +1147,23 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo
963 1147
964void LLSpatialGroup::destroyGL() 1148void LLSpatialGroup::destroyGL()
965{ 1149{
966 setState(LLSpatialGroup::GEOM_DIRTY | 1150 setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY);
967 LLSpatialGroup::OCCLUSION_DIRTY |
968 LLSpatialGroup::IMAGE_DIRTY);
969 mLastUpdateTime = gFrameTimeSeconds; 1151 mLastUpdateTime = gFrameTimeSeconds;
970 mVertexBuffer = NULL; 1152 mVertexBuffer = NULL;
971 mBufferMap.clear(); 1153 mBufferMap.clear();
972 1154
973 mOcclusionVerts = NULL;
974 mReflectionMap = NULL; 1155 mReflectionMap = NULL;
975 clearDrawMap(); 1156 clearDrawMap();
976 1157
1158 if (mOcclusionQuery)
1159 {
1160 sQueryPool.release(mOcclusionQuery);
1161 mOcclusionQuery = 0;
1162 }
1163
1164 delete [] mOcclusionVerts;
1165 mOcclusionVerts = NULL;
1166
977 for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i) 1167 for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i)
978 { 1168 {
979 LLDrawable* drawable = *i; 1169 LLDrawable* drawable = *i;
@@ -993,15 +1183,6 @@ BOOL LLSpatialGroup::rebound()
993 return TRUE; 1183 return TRUE;
994 } 1184 }
995 1185
996 LLVector3 oldBounds[2];
997
998 if (mSpatialPartition->isVolatile() && isState(QUERY_OUT))
999 { //a query has been issued, if our bounding box changes significantly
1000 //we need to discard the issued query
1001 oldBounds[0] = mBounds[0];
1002 oldBounds[1] = mBounds[1];
1003 }
1004
1005 if (mOctreeNode->getChildCount() == 1 && mOctreeNode->getElementCount() == 0) 1186 if (mOctreeNode->getChildCount() == 1 && mOctreeNode->getElementCount() == 0)
1006 { 1187 {
1007 LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0); 1188 LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0);
@@ -1015,7 +1196,7 @@ BOOL LLSpatialGroup::rebound()
1015 1196
1016 group->setState(SKIP_FRUSTUM_CHECK); 1197 group->setState(SKIP_FRUSTUM_CHECK);
1017 } 1198 }
1018 else if (mOctreeNode->hasLeafState()) 1199 else if (mOctreeNode->isLeaf())
1019 { //copy object bounding box if this is a leaf 1200 { //copy object bounding box if this is a leaf
1020 boundObjects(TRUE, mExtents[0], mExtents[1]); 1201 boundObjects(TRUE, mExtents[0], mExtents[1]);
1021 mBounds[0] = mObjectBounds[0]; 1202 mBounds[0] = mObjectBounds[0];
@@ -1060,19 +1241,6 @@ BOOL LLSpatialGroup::rebound()
1060 mBounds[1] = (newMax - newMin)*0.5f; 1241 mBounds[1] = (newMax - newMin)*0.5f;
1061 } 1242 }
1062 1243
1063 if (mSpatialPartition->isVolatile() && isState(QUERY_OUT))
1064 {
1065 for (U32 i = 0; i < 3 && !isState(DISCARD_QUERY); i++)
1066 {
1067 if (fabsf(mBounds[0].mV[i]-oldBounds[0].mV[i]) > SG_DISCARD_TOLERANCE ||
1068 fabsf(mBounds[1].mV[i]-oldBounds[1].mV[i]) > SG_DISCARD_TOLERANCE)
1069 { //bounding box changed significantly, discard last issued
1070 //occlusion query
1071 setState(DISCARD_QUERY);
1072 }
1073 }
1074 }
1075
1076 setState(OCCLUSION_DIRTY); 1244 setState(OCCLUSION_DIRTY);
1077 1245
1078 clearState(DIRTY); 1246 clearState(DIRTY);
@@ -1080,14 +1248,95 @@ BOOL LLSpatialGroup::rebound()
1080 return TRUE; 1248 return TRUE;
1081} 1249}
1082 1250
1251void LLSpatialGroup::checkOcclusion()
1252{
1253 if (LLPipeline::sUseOcclusion > 1)
1254 {
1255 LLSpatialGroup* parent = getParent();
1256 if (parent && parent->isState(LLSpatialGroup::OCCLUDED))
1257 { //if the parent has been marked as occluded, the child is implicitly occluded
1258 clearState(QUERY_PENDING | DISCARD_QUERY);
1259 }
1260 else if (isState(QUERY_PENDING))
1261 { //otherwise, if a query is pending, read it back
1262 LLFastTimer t(LLFastTimer::FTM_OCCLUSION_READBACK);
1263 GLuint res = 1;
1264 if (!isState(DISCARD_QUERY) && mOcclusionQuery)
1265 {
1266 glGetQueryObjectuivARB(mOcclusionQuery, GL_QUERY_RESULT_ARB, &res);
1267 }
1268
1269 if (res > 0)
1270 {
1271 assert_states_valid(this);
1272 clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
1273 assert_states_valid(this);
1274 }
1275 else
1276 {
1277 assert_states_valid(this);
1278 setState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
1279 assert_states_valid(this);
1280 }
1281
1282 clearState(QUERY_PENDING | DISCARD_QUERY);
1283 }
1284 else if (mSpatialPartition->mOcclusionEnabled)
1285 {
1286 assert_states_valid(this);
1287 clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
1288 assert_states_valid(this);
1289 }
1290 }
1291}
1292
1293void LLSpatialGroup::doOcclusion(LLCamera* camera)
1294{
1295 if (mSpatialPartition->mOcclusionEnabled && LLPipeline::sUseOcclusion > 1)
1296 {
1297 if (earlyFail(camera, this))
1298 {
1299 setState(LLSpatialGroup::DISCARD_QUERY);
1300 assert_states_valid(this);
1301 clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
1302 assert_states_valid(this);
1303 }
1304 else
1305 {
1306 {
1307 LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION);
1308
1309 if (!mOcclusionQuery)
1310 {
1311 mOcclusionQuery = sQueryPool.allocate();
1312 }
1313
1314 if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY))
1315 {
1316 buildOcclusion();
1317 }
1318
1319 glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery);
1320 glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts);
1321 glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
1322 GL_UNSIGNED_BYTE, get_occlusion_indices(camera, mBounds[0]));
1323 glEndQueryARB(GL_SAMPLES_PASSED_ARB);
1324 }
1325
1326 setState(LLSpatialGroup::QUERY_PENDING);
1327 clearState(LLSpatialGroup::DISCARD_QUERY);
1328 }
1329 }
1330}
1331
1083//============================================== 1332//==============================================
1084 1333
1085LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL is_volatile, U32 buffer_usage) 1334LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage)
1086{ 1335{
1087 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 1336 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
1337 mOcclusionEnabled = TRUE;
1088 mDrawableType = 0; 1338 mDrawableType = 0;
1089 mPartitionType = LLPipeline::PARTITION_NONE; 1339 mPartitionType = LLViewerRegion::PARTITION_NONE;
1090 mVolatile = is_volatile;
1091 mLODSeed = 0; 1340 mLODSeed = 0;
1092 mLODPeriod = 1; 1341 mLODPeriod = 1;
1093 mVertexDataMask = data_mask; 1342 mVertexDataMask = data_mask;
@@ -1096,10 +1345,13 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL is_volatile, U32 buff
1096 mSlopRatio = 0.25f; 1345 mSlopRatio = 0.25f;
1097 mRenderByGroup = TRUE; 1346 mRenderByGroup = TRUE;
1098 mImageEnabled = FALSE; 1347 mImageEnabled = FALSE;
1348 mInfiniteFarClip = FALSE;
1349
1350 LLGLNamePool::registerPool(&sQueryPool);
1099 1351
1100 mOctree = new LLSpatialGroup::OctreeNode(LLVector3d(0,0,0), 1352 mOctree = new LLSpatialGroup::OctreeRoot(LLVector3d(0,0,0),
1101 LLVector3d(1,1,1), 1353 LLVector3d(1,1,1),
1102 new LLSpatialGroup::OctreeRoot(), NULL); 1354 NULL);
1103 new LLSpatialGroup(mOctree, this); 1355 new LLSpatialGroup(mOctree, this);
1104} 1356}
1105 1357
@@ -1108,11 +1360,6 @@ LLSpatialPartition::~LLSpatialPartition()
1108{ 1360{
1109 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 1361 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
1110 1362
1111 for (U32 i = 0; i < mOcclusionQueries.size(); i++)
1112 {
1113 glDeleteQueriesARB(1, (GLuint*)(&(mOcclusionQueries[i])));
1114 }
1115
1116 delete mOctree; 1363 delete mOctree;
1117 mOctree = NULL; 1364 mOctree = NULL;
1118} 1365}
@@ -1121,22 +1368,6 @@ LLSpatialPartition::~LLSpatialPartition()
1121LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) 1368LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
1122{ 1369{
1123 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 1370 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
1124 const F32 MAX_MAG = 1000000.f*1000000.f; // 1 million
1125
1126 if (drawablep->getPositionGroup().magVecSquared() > MAX_MAG)
1127 {
1128#if 0 //ndef LL_RELEASE_FOR_DOWNLOAD
1129 llwarns << "LLSpatialPartition::put Object out of range!" << llendl;
1130 llinfos << drawablep->getPositionGroup() << llendl;
1131
1132 if (drawablep->getVObj())
1133 {
1134 llwarns << "Dumping debugging info: " << llendl;
1135 drawablep->getVObj()->dump();
1136 }
1137#endif
1138 return NULL;
1139 }
1140 1371
1141 drawablep->updateSpatialExtents(); 1372 drawablep->updateSpatialExtents();
1142 validate_drawable(drawablep); 1373 validate_drawable(drawablep);
@@ -1147,11 +1378,10 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
1147 assert_octree_valid(mOctree); 1378 assert_octree_valid(mOctree);
1148 mOctree->insert(drawablep); 1379 mOctree->insert(drawablep);
1149 assert_octree_valid(mOctree); 1380 assert_octree_valid(mOctree);
1150
1151 LLSpatialGroup::OctreeNode* node = mOctree->getNodeAt(drawablep);
1152 1381
1153 LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); 1382 LLSpatialGroup* group = drawablep->getSpatialGroup();
1154 if (was_visible && group->isState(LLSpatialGroup::QUERY_OUT)) 1383
1384 if (group && was_visible && group->isState(LLSpatialGroup::QUERY_PENDING))
1155 { 1385 {
1156 group->setState(LLSpatialGroup::DISCARD_QUERY); 1386 group->setState(LLSpatialGroup::DISCARD_QUERY);
1157 } 1387 }
@@ -1178,11 +1408,11 @@ BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp)
1178void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate) 1408void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate)
1179{ 1409{
1180 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 1410 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
1181 LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE); 1411
1182
1183 // sanity check submitted by open source user bushing Spatula 1412 // sanity check submitted by open source user bushing Spatula
1184 // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne) 1413 // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne)
1185 if (!drawablep) { 1414 if (!drawablep)
1415 {
1186 OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << llendl; 1416 OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << llendl;
1187 return; 1417 return;
1188 } 1418 }
@@ -1225,7 +1455,7 @@ class LLSpatialShift : public LLSpatialGroup::OctreeTraveler
1225{ 1455{
1226public: 1456public:
1227 LLSpatialShift(LLVector3 offset) : mOffset(offset) { } 1457 LLSpatialShift(LLVector3 offset) : mOffset(offset) { }
1228 virtual void visit(const LLSpatialGroup::OctreeState* branch) 1458 virtual void visit(const LLSpatialGroup::OctreeNode* branch)
1229 { 1459 {
1230 ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset); 1460 ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset);
1231 } 1461 }
@@ -1234,39 +1464,27 @@ public:
1234}; 1464};
1235 1465
1236void LLSpatialPartition::shift(const LLVector3 &offset) 1466void LLSpatialPartition::shift(const LLVector3 &offset)
1237{ 1467{ //shift octree node bounding boxes by offset
1238 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 1468 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
1239 llinfos << "Shifting octree: " << offset << llendl;
1240 LLSpatialShift shifter(offset); 1469 LLSpatialShift shifter(offset);
1241 shifter.traverse(mOctree); 1470 shifter.traverse(mOctree);
1242} 1471}
1243 1472
1244BOOL LLSpatialPartition::checkOcclusion(LLSpatialGroup* group, LLCamera* camera)
1245{
1246 if (LLPipeline::sUseOcclusion &&
1247 !group->isState(LLSpatialGroup::ACTIVE_OCCLUSION | LLSpatialGroup::OCCLUDED) &&
1248 (!camera || !earlyFail(camera, group)))
1249 {
1250 group->setState(LLSpatialGroup::ACTIVE_OCCLUSION);
1251 mQueryQueue.push(group);
1252 return TRUE;
1253 }
1254
1255 return FALSE;
1256}
1257
1258class LLOctreeCull : public LLSpatialGroup::OctreeTraveler 1473class LLOctreeCull : public LLSpatialGroup::OctreeTraveler
1259{ 1474{
1260public: 1475public:
1261 LLOctreeCull(LLCamera* camera) 1476 LLOctreeCull(LLCamera* camera)
1262 : mCamera(camera), mRes(0) { } 1477 : mCamera(camera), mRes(0) { }
1263 1478
1264 virtual bool earlyFail(const LLSpatialGroup* group) 1479 virtual bool earlyFail(LLSpatialGroup* group)
1265 { 1480 {
1481 group->checkOcclusion();
1482
1266 if (group->mOctreeNode->getParent() && //never occlusion cull the root node 1483 if (group->mOctreeNode->getParent() && //never occlusion cull the root node
1267 LLPipeline::sUseOcclusion && //never occlusion cull selection 1484 LLPipeline::sUseOcclusion && //ignore occlusion if disabled
1268 group->isState(LLSpatialGroup::OCCLUDED)) 1485 group->isState(LLSpatialGroup::OCCLUDED))
1269 { 1486 {
1487 gPipeline.markOccluder(group);
1270 return true; 1488 return true;
1271 } 1489 }
1272 1490
@@ -1289,31 +1507,39 @@ public:
1289 } 1507 }
1290 else 1508 else
1291 { 1509 {
1292 mRes = mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1]); 1510 mRes = frustumCheck(group);
1293 1511
1294 if (mRes) 1512 if (mRes)
1295 { //at least partially in, run on down 1513 { //at least partially in, run on down
1296 LLSpatialGroup::OctreeTraveler::traverse(n); 1514 LLSpatialGroup::OctreeTraveler::traverse(n);
1297 } 1515 }
1298 else 1516
1299 {
1300 lateFail(group);
1301 }
1302 mRes = 0; 1517 mRes = 0;
1303 } 1518 }
1304 } 1519 }
1305 1520
1306 virtual void lateFail(LLSpatialGroup* group) 1521 virtual S32 frustumCheck(const LLSpatialGroup* group)
1307 { 1522 {
1308 if (!group->isState(LLSpatialGroup::CULLED)) 1523 S32 res = mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]);
1309 { //totally culled, so are all its children 1524 if (res != 0)
1310 group->setState(LLSpatialGroup::CULLED, LLSpatialGroup::STATE_MODE_DIFF); 1525 {
1526 res = llmin(res, AABBSphereIntersect(group->mExtents[0], group->mExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist));
1311 } 1527 }
1528 return res;
1312 } 1529 }
1313 1530
1314 virtual bool checkObjects(const LLSpatialGroup::OctreeState* branch, const LLSpatialGroup* group) 1531 virtual S32 frustumCheckObjects(const LLSpatialGroup* group)
1532 {
1533 S32 res = mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]);
1534 if (res != 0)
1535 {
1536 res = llmin(res, AABBSphereIntersect(group->mObjectExtents[0], group->mObjectExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist));
1537 }
1538 return res;
1539 }
1540
1541 virtual bool checkObjects(const LLSpatialGroup::OctreeNode* branch, const LLSpatialGroup* group)
1315 { 1542 {
1316
1317 if (branch->getElementCount() == 0) //no elements 1543 if (branch->getElementCount() == 0) //no elements
1318 { 1544 {
1319 return false; 1545 return false;
@@ -1322,7 +1548,7 @@ public:
1322 { 1548 {
1323 return true; 1549 return true;
1324 } 1550 }
1325 else if (mRes == 1 && !mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1])) //no objects in frustum 1551 else if (mRes == 1 && !frustumCheckObjects(group)) //no objects in frustum
1326 { 1552 {
1327 return false; 1553 return false;
1328 } 1554 }
@@ -1332,20 +1558,9 @@ public:
1332 1558
1333 virtual void preprocess(LLSpatialGroup* group) 1559 virtual void preprocess(LLSpatialGroup* group)
1334 { 1560 {
1335 if (group->isState(LLSpatialGroup::CULLED))
1336 { //this is the first frame this node is visible
1337 group->clearState(LLSpatialGroup::CULLED);
1338 if (group->mOctreeNode->hasLeafState())
1339 { //if it's a leaf, force it onto the active occlusion list to prevent
1340 //massive frame stutters
1341 group->mSpatialPartition->checkOcclusion(group, mCamera);
1342 }
1343 }
1344
1345 if (LLPipeline::sDynamicReflections && 1561 if (LLPipeline::sDynamicReflections &&
1346 group->mOctreeNode->getSize().mdV[0] == 16.0 && 1562 group->mOctreeNode->getSize().mdV[0] == 16.0 &&
1347 group->mDistance < 64.f && 1563 group->mDistance < 64.f)
1348 group->mLastAddTime < gFrameTimeSeconds - 2.f)
1349 { 1564 {
1350 group->mSpatialPartition->markReimage(group); 1565 group->mSpatialPartition->markReimage(group);
1351 } 1566 }
@@ -1353,10 +1568,15 @@ public:
1353 1568
1354 virtual void processGroup(LLSpatialGroup* group) 1569 virtual void processGroup(LLSpatialGroup* group)
1355 { 1570 {
1571 if (group->needsUpdate() ||
1572 group->mVisible < LLDrawable::getCurrentFrame() - 1)
1573 {
1574 group->doOcclusion(mCamera);
1575 }
1356 gPipeline.markNotCulled(group, *mCamera); 1576 gPipeline.markNotCulled(group, *mCamera);
1357 } 1577 }
1358 1578
1359 virtual void visit(const LLSpatialGroup::OctreeState* branch) 1579 virtual void visit(const LLSpatialGroup::OctreeNode* branch)
1360 { 1580 {
1361 LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); 1581 LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0);
1362 1582
@@ -1372,6 +1592,17 @@ public:
1372 S32 mRes; 1592 S32 mRes;
1373}; 1593};
1374 1594
1595class LLOctreeCullNoFarClip : public LLOctreeCull
1596{
1597public:
1598 LLOctreeCullNoFarClip(LLCamera* camera)
1599 : LLOctreeCull(camera) { }
1600
1601 virtual S32 frustumCheck(const LLSpatialGroup* group)
1602 {
1603 return mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]);
1604 }
1605};
1375 1606
1376class LLOctreeSelect : public LLOctreeCull 1607class LLOctreeSelect : public LLOctreeCull
1377{ 1608{
@@ -1379,15 +1610,14 @@ public:
1379 LLOctreeSelect(LLCamera* camera, std::vector<LLDrawable*>* results) 1610 LLOctreeSelect(LLCamera* camera, std::vector<LLDrawable*>* results)
1380 : LLOctreeCull(camera), mResults(results) { } 1611 : LLOctreeCull(camera), mResults(results) { }
1381 1612
1382 virtual bool earlyFail(const LLSpatialGroup* group) { return false; } 1613 virtual bool earlyFail(LLSpatialGroup* group) { return false; }
1383 virtual void lateFail(LLSpatialGroup* group) { }
1384 virtual void preprocess(LLSpatialGroup* group) { } 1614 virtual void preprocess(LLSpatialGroup* group) { }
1385 1615
1386 virtual void processGroup(LLSpatialGroup* group) 1616 virtual void processGroup(LLSpatialGroup* group)
1387 { 1617 {
1388 LLSpatialGroup::OctreeState* branch = group->mOctreeNode->getOctState(); 1618 LLSpatialGroup::OctreeNode* branch = group->mOctreeNode;
1389 1619
1390 for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) 1620 for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
1391 { 1621 {
1392 LLDrawable* drawable = *i; 1622 LLDrawable* drawable = *i;
1393 1623
@@ -1408,67 +1638,41 @@ public:
1408 std::vector<LLDrawable*>* mResults; 1638 std::vector<LLDrawable*>* mResults;
1409}; 1639};
1410 1640
1411 1641void drawBox(const LLVector3& c, const LLVector3& r)
1412void genBoxList()
1413{ 1642{
1414 if (sBoxList != 0) 1643 gGL.begin(GL_TRIANGLE_STRIP);
1415 {
1416 return;
1417 }
1418
1419 sBoxList = glGenLists(1);
1420 glNewList(sBoxList, GL_COMPILE);
1421
1422 LLVector3 c,r;
1423 c = LLVector3(0,0,0);
1424 r = LLVector3(1,1,1);
1425
1426 glBegin(GL_TRIANGLE_STRIP);
1427 //left front 1644 //left front
1428 glVertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); 1645 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV);
1429 glVertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); 1646 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV);
1430 //right front 1647 //right front
1431 glVertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); 1648 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV);
1432 glVertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); 1649 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV);
1433 //right back 1650 //right back
1434 glVertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); 1651 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV);
1435 glVertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); 1652 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV);
1436 //left back 1653 //left back
1437 glVertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); 1654 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV);
1438 glVertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); 1655 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV);
1439 //left front 1656 //left front
1440 glVertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); 1657 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV);
1441 glVertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); 1658 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV);
1442 glEnd(); 1659 gGL.end();
1443 1660
1444 //bottom 1661 //bottom
1445 glBegin(GL_TRIANGLE_STRIP); 1662 gGL.begin(GL_TRIANGLE_STRIP);
1446 glVertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); 1663 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV);
1447 glVertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); 1664 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV);
1448 glVertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); 1665 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV);
1449 glVertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); 1666 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV);
1450 glEnd(); 1667 gGL.end();
1451 1668
1452 //top 1669 //top
1453 glBegin(GL_TRIANGLE_STRIP); 1670 gGL.begin(GL_TRIANGLE_STRIP);
1454 glVertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); 1671 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV);
1455 glVertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); 1672 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV);
1456 glVertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); 1673 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV);
1457 glVertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); 1674 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV);
1458 glEnd(); 1675 gGL.end();
1459
1460 glEndList();
1461}
1462
1463void drawBox(const LLVector3& c, const LLVector3& r)
1464{
1465 genBoxList();
1466
1467 glPushMatrix();
1468 glTranslatef(c.mV[0], c.mV[1], c.mV[2]);
1469 glScalef(r.mV[0], r.mV[1], r.mV[2]);
1470 glCallList(sBoxList);
1471 glPopMatrix();
1472} 1676}
1473 1677
1474void drawBoxOutline(const LLVector3& pos, const LLVector3& size) 1678void drawBoxOutline(const LLVector3& pos, const LLVector3& size)
@@ -1478,44 +1682,49 @@ void drawBoxOutline(const LLVector3& pos, const LLVector3& size)
1478 LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1)); 1682 LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1));
1479 LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1)); 1683 LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1));
1480 1684
1481 glBegin(GL_LINE_LOOP); //top 1685 gGL.begin(GL_LINES);
1482 glVertex3fv((pos+v1).mV); 1686
1483 glVertex3fv((pos+v2).mV); 1687 //top
1484 glVertex3fv((pos+v3).mV); 1688 gGL.vertex3fv((pos+v1).mV);
1485 glVertex3fv((pos+v4).mV); 1689 gGL.vertex3fv((pos+v2).mV);
1486 glEnd(); 1690 gGL.vertex3fv((pos+v2).mV);
1487 1691 gGL.vertex3fv((pos+v3).mV);
1488 glBegin(GL_LINE_LOOP); //bottom 1692 gGL.vertex3fv((pos+v3).mV);
1489 glVertex3fv((pos-v1).mV); 1693 gGL.vertex3fv((pos+v4).mV);
1490 glVertex3fv((pos-v2).mV); 1694 gGL.vertex3fv((pos+v4).mV);
1491 glVertex3fv((pos-v3).mV); 1695 gGL.vertex3fv((pos+v1).mV);
1492 glVertex3fv((pos-v4).mV); 1696
1493 glEnd(); 1697 //bottom
1494 1698 gGL.vertex3fv((pos-v1).mV);
1495 1699 gGL.vertex3fv((pos-v2).mV);
1496 glBegin(GL_LINES); 1700 gGL.vertex3fv((pos-v2).mV);
1497 1701 gGL.vertex3fv((pos-v3).mV);
1702 gGL.vertex3fv((pos-v3).mV);
1703 gGL.vertex3fv((pos-v4).mV);
1704 gGL.vertex3fv((pos-v4).mV);
1705 gGL.vertex3fv((pos-v1).mV);
1706
1498 //right 1707 //right
1499 glVertex3fv((pos+v1).mV); 1708 gGL.vertex3fv((pos+v1).mV);
1500 glVertex3fv((pos-v3).mV); 1709 gGL.vertex3fv((pos-v3).mV);
1501 1710
1502 glVertex3fv((pos+v4).mV); 1711 gGL.vertex3fv((pos+v4).mV);
1503 glVertex3fv((pos-v2).mV); 1712 gGL.vertex3fv((pos-v2).mV);
1504 1713
1505 //left 1714 //left
1506 glVertex3fv((pos+v2).mV); 1715 gGL.vertex3fv((pos+v2).mV);
1507 glVertex3fv((pos-v4).mV); 1716 gGL.vertex3fv((pos-v4).mV);
1508 1717
1509 glVertex3fv((pos+v3).mV); 1718 gGL.vertex3fv((pos+v3).mV);
1510 glVertex3fv((pos-v1).mV); 1719 gGL.vertex3fv((pos-v1).mV);
1511 1720
1512 glEnd(); 1721 gGL.end();
1513} 1722}
1514 1723
1515class LLOctreeDirty : public LLOctreeTraveler<LLDrawable> 1724class LLOctreeDirty : public LLOctreeTraveler<LLDrawable>
1516{ 1725{
1517public: 1726public:
1518 virtual void visit(const LLOctreeState<LLDrawable>* state) 1727 virtual void visit(const LLOctreeNode<LLDrawable>* state)
1519 { 1728 {
1520 LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); 1729 LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
1521 group->destroyGL(); 1730 group->destroyGL();
@@ -1540,47 +1749,45 @@ public:
1540void LLSpatialPartition::restoreGL() 1749void LLSpatialPartition::restoreGL()
1541{ 1750{
1542 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 1751 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
1543 mOcclusionQueries.clear();
1544 sBoxList = 0;
1545
1546 //generate query ids
1547 while (mOcclusionQueries.size() < mOccludedList.size())
1548 {
1549 GLuint id;
1550 glGenQueriesARB(1, &id);
1551 mOcclusionQueries.push_back(id);
1552 }
1553
1554 for (U32 i = 0; i < mOccludedList.size(); i++)
1555 { //previously issued queries are now invalid
1556 mOccludedList[i]->setState(LLSpatialGroup::DISCARD_QUERY);
1557 }
1558
1559 genBoxList();
1560} 1752}
1561 1753
1562void LLSpatialPartition::resetVertexBuffers() 1754void LLSpatialPartition::resetVertexBuffers()
1563{ 1755{
1564 LLOctreeDirty dirty; 1756 LLOctreeDirty dirty;
1565 dirty.traverse(mOctree); 1757 dirty.traverse(mOctree);
1566
1567 mOcclusionIndices = NULL;
1568} 1758}
1569 1759
1570S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select) 1760S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select)
1571{ 1761{
1572 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 1762 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
1763#if LL_OCTREE_PARANOIA_CHECK
1764 ((LLSpatialGroup*)mOctree->getListener(0))->checkStates();
1765#endif
1573 { 1766 {
1767 BOOL temp = sFreezeState;
1768 sFreezeState = FALSE;
1574 LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND); 1769 LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND);
1575 LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); 1770 LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
1576 group->rebound(); 1771 group->rebound();
1772 sFreezeState = temp;
1577 } 1773 }
1774
1775#if LL_OCTREE_PARANOIA_CHECK
1776 ((LLSpatialGroup*)mOctree->getListener(0))->validate();
1777#endif
1778
1578 1779
1579 if (for_select) 1780 if (for_select)
1580 { 1781 {
1581 LLOctreeSelect selecter(&camera, results); 1782 LLOctreeSelect selecter(&camera, results);
1582 selecter.traverse(mOctree); 1783 selecter.traverse(mOctree);
1583 } 1784 }
1785 else if (mInfiniteFarClip || !LLPipeline::sUseFarClip)
1786 {
1787 LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL);
1788 LLOctreeCullNoFarClip culler(&camera);
1789 culler.traverse(mOctree);
1790 }
1584 else 1791 else
1585 { 1792 {
1586 LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL); 1793 LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL);
@@ -1591,61 +1798,13 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
1591 return 0; 1798 return 0;
1592} 1799}
1593 1800
1594class LLOctreeClearOccludedNotActive : public LLSpatialGroup::OctreeTraveler
1595{
1596public:
1597 LLOctreeClearOccludedNotActive() { }
1598
1599 virtual void traverse(const LLSpatialGroup::TreeNode* n)
1600 {
1601 LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
1602 if ((!group->isState(LLSpatialGroup::ACTIVE_OCCLUSION)) //|| group->isState(LLSpatialGroup::QUERY_PENDING)
1603 || group->isState(LLSpatialGroup::DEACTIVATE_OCCLUSION))
1604 { //the children are all occluded or culled as well
1605 group->clearState(LLSpatialGroup::OCCLUDED);
1606 for (U32 i = 0; i < group->mOctreeNode->getChildCount(); i++)
1607 {
1608 traverse(group->mOctreeNode->getChild(i));
1609 }
1610 }
1611 }
1612
1613 virtual void visit(const LLSpatialGroup::OctreeState* branch) { }
1614};
1615
1616class LLQueueNonCulled : public LLSpatialGroup::OctreeTraveler
1617{
1618public:
1619 std::queue<LLSpatialGroup*>* mQueue;
1620 LLQueueNonCulled(std::queue<LLSpatialGroup*> *queue) : mQueue(queue) { }
1621
1622 virtual void traverse(const LLSpatialGroup::TreeNode* n)
1623 {
1624 LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
1625 if (group->isState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED))
1626 { //the children are all occluded or culled as well
1627 return;
1628 }
1629
1630 if (!group->isState(LLSpatialGroup::IN_QUEUE))
1631 {
1632 group->setState(LLSpatialGroup::IN_QUEUE);
1633 mQueue->push(group);
1634 }
1635
1636 LLSpatialGroup::OctreeTraveler::traverse(n);
1637 }
1638
1639 virtual void visit(const LLSpatialGroup::OctreeState* branch) { }
1640};
1641
1642BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group) 1801BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group)
1643{ 1802{
1803 const F32 vel = (gCamera->getVelocityStat()->getCurrent()+0.2f);
1644 LLVector3 c = group->mBounds[0]; 1804 LLVector3 c = group->mBounds[0];
1645 LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.2f,0.2f,0.2f); 1805 LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(vel,vel,vel);
1646 1806
1647 //if (group->isState(LLSpatialGroup::CULLED)) // || 1807 if (r.magVecSquared() > 1024.0*1024.0)
1648 if (!camera->AABBInFrustum(c, r))
1649 { 1808 {
1650 return TRUE; 1809 return TRUE;
1651 } 1810 }
@@ -1687,23 +1846,34 @@ void LLSpatialPartition::processImagery(LLCamera* camera)
1687 1846
1688 U32 process_count = 1; 1847 U32 process_count = 1;
1689 1848
1690 while (process_count > 0 && !mImageQueue.empty()) 1849 S32 pull_count = (S32) mImageQueue.size();
1850
1851 while (process_count > 0 && pull_count > 0 && !mImageQueue.empty())
1691 { 1852 {
1853 pull_count--;
1692 LLPointer<LLSpatialGroup> group = mImageQueue.front(); 1854 LLPointer<LLSpatialGroup> group = mImageQueue.front();
1693 mImageQueue.pop(); 1855 mImageQueue.pop();
1694 1856
1695 group->clearState(LLSpatialGroup::IN_IMAGE_QUEUE);
1696
1697 if (group->isDead()) 1857 if (group->isDead())
1698 { 1858 {
1699 continue; 1859 continue;
1700 } 1860 }
1701 1861
1862 if (group->isState(LLSpatialGroup::GEOM_DIRTY))
1863 { //put it back
1864 mImageQueue.push(group);
1865 continue;
1866 }
1867
1868 group->clearState(LLSpatialGroup::IN_IMAGE_QUEUE);
1702 if (LLPipeline::sDynamicReflections) 1869 if (LLPipeline::sDynamicReflections)
1703 { 1870 {
1704 process_count--; 1871 process_count--;
1705 LLVector3 origin = group->mBounds[0]; 1872 LLVector3 origin = group->mBounds[0];
1706 1873 /*LLVector3 at = camera->getOrigin()-origin;
1874 at.normVec();
1875 origin += at* (at * group->mBounds[1]);*/
1876
1707 LLCamera cube_cam; 1877 LLCamera cube_cam;
1708 cube_cam.setOrigin(origin); 1878 cube_cam.setOrigin(origin);
1709 cube_cam.setFar(64.f); 1879 cube_cam.setFar(64.f);
@@ -1716,15 +1886,8 @@ void LLSpatialPartition::processImagery(LLCamera* camera)
1716 cube_map->initGL(); 1886 cube_map->initGL();
1717 } 1887 }
1718 1888
1719 if (gPipeline.mCubeBuffer.isNull()) 1889 gPipeline.generateReflectionMap(gPipeline.mCubeBuffer, cube_cam);
1720 { 1890 gPipeline.blurReflectionMap(gPipeline.mCubeBuffer, cube_map);
1721 gPipeline.mCubeBuffer = new LLCubeMap();
1722 gPipeline.mCubeBuffer->initGL();
1723 }
1724
1725 S32 res = gSavedSettings.getS32("RenderReflectionRes");
1726 gPipeline.generateReflectionMap(gPipeline.mCubeBuffer, cube_cam, 128);
1727 gPipeline.blurReflectionMap(gPipeline.mCubeBuffer, cube_map, res);
1728 group->mReflectionMap = cube_map; 1891 group->mReflectionMap = cube_map;
1729 group->setState(LLSpatialGroup::GEOM_DIRTY); 1892 group->setState(LLSpatialGroup::GEOM_DIRTY);
1730 } 1893 }
@@ -1733,601 +1896,75 @@ void LLSpatialPartition::processImagery(LLCamera* camera)
1733 } 1896 }
1734} 1897}
1735 1898
1736void validate_occlusion_list(std::vector<LLPointer<LLSpatialGroup> >& occluded_list) 1899void pushVerts(LLDrawInfo* params, U32 mask)
1737{ 1900{
1738#if !LL_RELEASE_FOR_DOWNLOAD 1901 LLRenderPass::applyModelMatrix(*params);
1739 for (U32 i = 0; i < occluded_list.size(); i++) 1902 params->mVertexBuffer->setBuffer(mask);
1740 { 1903 U16* indicesp = (U16*) params->mVertexBuffer->getIndicesPointer();
1741 LLSpatialGroup* group = occluded_list[i]; 1904 glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount,
1742 for (U32 j = i+1; j < occluded_list.size(); j++) 1905 GL_UNSIGNED_SHORT, indicesp+params->mOffset);
1743 {
1744 if (occluded_list[i] == occluded_list[j])
1745 {
1746 llerrs << "Duplicate node in occlusion list." << llendl;
1747 }
1748 }
1749
1750 LLSpatialGroup::OctreeNode* parent = group->mOctreeNode->getOctParent();
1751 while (parent)
1752 {
1753 LLSpatialGroup* parent_group = (LLSpatialGroup*) parent->getListener(0);
1754 if (parent_group->isState(LLSpatialGroup::OCCLUDED))
1755 {
1756 llerrs << "Child node of occluded node in occlusion list (redundant query)." << llendl;
1757 }
1758 parent = parent->getOctParent();
1759 }
1760 }
1761#endif
1762} 1906}
1763 1907
1764void LLSpatialPartition::processOcclusion(LLCamera* camera) 1908void pushVerts(LLSpatialGroup* group, U32 mask)
1765{ 1909{
1766 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 1910 LLDrawInfo* params = NULL;
1767 LLSpatialGroup* rootGroup = (LLSpatialGroup*) mOctree->getListener(0);
1768 {
1769 LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND);
1770 rootGroup->rebound();
1771 }
1772
1773 //update potentials
1774 if (!rootGroup->isState(LLSpatialGroup::IN_QUEUE))
1775 {
1776 rootGroup->setState(LLSpatialGroup::IN_QUEUE);
1777 mOcclusionQueue.push(rootGroup);
1778 }
1779
1780 const U32 MAX_PULLED = 32;
1781 const U32 MAX_PUSHED = mOcclusionQueue.size();
1782 U32 count = 0;
1783 U32 pcount = 0;
1784
1785 while (pcount < MAX_PUSHED && count < MAX_PULLED && !mOcclusionQueue.empty())
1786 {
1787 LLFastTimer t(LLFastTimer::FTM_OCCLUSION);
1788
1789 LLPointer<LLSpatialGroup> group = mOcclusionQueue.front();
1790 if (!group->isState(LLSpatialGroup::IN_QUEUE))
1791 {
1792 OCT_ERRS << "Spatial Group State Error. Group in queue not tagged as such." << llendl;
1793 }
1794
1795 mOcclusionQueue.pop();
1796 group->clearState(LLSpatialGroup::IN_QUEUE);
1797
1798 if (group->isDead())
1799 {
1800 continue;
1801 }
1802
1803 if (group->isState(LLSpatialGroup::CULLED | LLSpatialGroup::OCCLUDED))
1804 { //already culled, skip it
1805 continue;
1806 }
1807
1808 //before we process, enqueue this group's children
1809 for (U32 i = 0; i < group->mOctreeNode->getChildCount(); i++)
1810 {
1811 LLSpatialGroup* child = (LLSpatialGroup*) group->mOctreeNode->getChild(i)->getListener(0);
1812
1813 //if (!child->isState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED)
1814 if (!child->isState(LLSpatialGroup::IN_QUEUE | LLSpatialGroup::ACTIVE_OCCLUSION))
1815 {
1816 child->setState(LLSpatialGroup::IN_QUEUE);
1817 mOcclusionQueue.push(child);
1818 }
1819 }
1820
1821 if (earlyFail(camera, group))
1822 {
1823 sg_assert(!group->isState(LLSpatialGroup::OCCLUDED));
1824 group->setState(LLSpatialGroup::IN_QUEUE);
1825 mOcclusionQueue.push(group);
1826 pcount++;
1827 continue;
1828 }
1829
1830 //add to pending queue
1831 if (!group->isState(LLSpatialGroup::ACTIVE_OCCLUSION))
1832 {
1833#if LL_OCTREE_PARANOIA_CHECK
1834 for (U32 i = 0; i < mOccludedList.size(); ++i)
1835 {
1836 sg_assert(mOccludedList[i] != group);
1837 }
1838#endif
1839 group->setState(LLSpatialGroup::ACTIVE_OCCLUSION);
1840 mQueryQueue.push(group);
1841 count++;
1842 }
1843 }
1844
1845 //read back results from last frame
1846 for (U32 i = 0; i < mOccludedList.size(); i++)
1847 {
1848 LLFastTimer t(LLFastTimer::FTM_OCCLUSION_READBACK);
1849
1850 if (mOccludedList[i]->isDead() || mOccludedList[i]->isState(LLSpatialGroup::DEACTIVATE_OCCLUSION))
1851 {
1852 continue;
1853 }
1854 GLuint res = 0;
1855
1856 if (mOccludedList[i]->isState(LLSpatialGroup::EARLY_FAIL | LLSpatialGroup::DISCARD_QUERY) ||
1857 !mOccludedList[i]->isState(LLSpatialGroup::QUERY_OUT))
1858 {
1859 mOccludedList[i]->clearState(LLSpatialGroup::EARLY_FAIL);
1860 mOccludedList[i]->clearState(LLSpatialGroup::DISCARD_QUERY);
1861 res = 1;
1862 }
1863 else
1864 {
1865 glGetQueryObjectuivARB(mOcclusionQueries[i], GL_QUERY_RESULT_ARB, &res);
1866 stop_glerror();
1867 }
1868
1869 if (res) //NOT OCCLUDED
1870 {
1871 if (mOccludedList[i]->isState(LLSpatialGroup::OCCLUDED))
1872 { //this node was occluded last frame
1873 LLSpatialGroup::OctreeNode* node = mOccludedList[i]->mOctreeNode;
1874 //add any immediate children to the queue that are not already there
1875 for (U32 j = 0; j < node->getChildCount(); j++)
1876 {
1877 LLSpatialGroup* group = (LLSpatialGroup*) node->getChild(j)->getListener(0);
1878 checkOcclusion(group, camera);
1879 }
1880 }
1881
1882 //clear occlusion status for everything not on the active list
1883 LLOctreeClearOccludedNotActive clear_occluded;
1884 mOccludedList[i]->setState(LLSpatialGroup::DEACTIVATE_OCCLUSION);
1885 mOccludedList[i]->clearState(LLSpatialGroup::OCCLUDED);
1886 mOccludedList[i]->clearState(LLSpatialGroup::OCCLUDING);
1887 clear_occluded.traverse(mOccludedList[i]->mOctreeNode);
1888 }
1889 else
1890 { //OCCLUDED
1891 if (mOccludedList[i]->isState(LLSpatialGroup::OCCLUDING))
1892 {
1893 if (!mOccludedList[i]->isState(LLSpatialGroup::OCCLUDED))
1894 {
1895 LLSpatialGroup::OctreeNode* oct_parent = (LLSpatialGroup::OctreeNode*) mOccludedList[i]->mOctreeNode->getParent();
1896 if (oct_parent)
1897 {
1898 LLSpatialGroup* parent = (LLSpatialGroup*) oct_parent->getListener(0);
1899
1900 if (checkOcclusion(parent, camera))
1901 { //force a guess on the parent and siblings
1902 for (U32 i = 0; i < parent->mOctreeNode->getChildCount(); i++)
1903 {
1904 LLSpatialGroup* child = (LLSpatialGroup*) parent->mOctreeNode->getChild(i)->getListener(0);
1905 checkOcclusion(child, camera);
1906 }
1907 }
1908 }
1909
1910 //take children off the active list
1911 mOccludedList[i]->setState(LLSpatialGroup::DEACTIVATE_OCCLUSION, LLSpatialGroup::STATE_MODE_BRANCH);
1912 mOccludedList[i]->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION);
1913 }
1914 mOccludedList[i]->setState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
1915 }
1916 else
1917 {
1918 //take children off the active list
1919 mOccludedList[i]->setState(LLSpatialGroup::DEACTIVATE_OCCLUSION, LLSpatialGroup::STATE_MODE_BRANCH);
1920
1921 //keep this node on the active list
1922 mOccludedList[i]->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION);
1923
1924 //this node is a top level occluder
1925 mOccludedList[i]->setState(LLSpatialGroup::OCCLUDING);
1926 }
1927 }
1928
1929 mOccludedList[i]->clearState(LLSpatialGroup::QUERY_OUT);
1930 }
1931 1911
1932 //remove non-occluded groups from occluded list 1912 for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
1933 for (U32 i = 0; i < mOccludedList.size(); )
1934 { 1913 {
1935 if (mOccludedList[i]->isDead() || //needs to be deleted 1914 for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
1936 !mOccludedList[i]->isState(LLSpatialGroup::OCCLUDING) || //is not occluding
1937 mOccludedList[i]->isState(LLSpatialGroup::DEACTIVATE_OCCLUSION)) //parent is occluded
1938 {
1939 LLSpatialGroup* groupp = mOccludedList[i];
1940 if (!groupp->isDead())
1941 {
1942 groupp->clearState(LLSpatialGroup::ACTIVE_OCCLUSION);
1943 groupp->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION);
1944 groupp->clearState(LLSpatialGroup::OCCLUDING);
1945 }
1946 mOccludedList.erase(mOccludedList.begin()+i);
1947 }
1948 else
1949 { 1915 {
1950 i++; 1916 params = *j;
1917 pushVerts(params, mask);
1951 } 1918 }
1952 } 1919 }
1953
1954 validate_occlusion_list(mOccludedList);
1955
1956 //pump some non-culled items onto the occlusion list
1957 //count = MAX_PULLED;
1958 while (!mQueryQueue.empty())
1959 {
1960 LLPointer<LLSpatialGroup> group = mQueryQueue.front();
1961 mQueryQueue.pop();
1962 //group->clearState(LLSpatialGroup::QUERY_PENDING);
1963 mOccludedList.push_back(group);
1964 }
1965
1966 //generate query ids
1967 while (mOcclusionQueries.size() < mOccludedList.size())
1968 {
1969 GLuint id;
1970 glGenQueriesARB(1, &id);
1971 mOcclusionQueries.push_back(id);
1972 }
1973} 1920}
1974 1921
1975class LLOcclusionIndexBuffer : public LLVertexBuffer 1922void pushVerts(LLFace* face, U32 mask)
1976{ 1923{
1977public: 1924 LLVertexBuffer* buffer = face->mVertexBuffer;
1978 LLOcclusionIndexBuffer(U32 size)
1979 : LLVertexBuffer(0, GL_STREAM_DRAW_ARB)
1980 {
1981 allocateBuffer(0, size, TRUE);
1982
1983 LLStrider<U32> idx;
1984
1985 getIndexStrider(idx);
1986
1987 //12 triangles' indices
1988 idx[0] = 1; idx[1] = 0; idx[2] = 2; //front
1989 idx[3] = 3; idx[4] = 2; idx[5] = 0;
1990
1991 idx[6] = 4; idx[7] = 5; idx[8] = 1; //top
1992 idx[9] = 0; idx[10] = 1; idx[11] = 5;
1993
1994 idx[12] = 5; idx[13] = 4; idx[14] = 6; //back
1995 idx[15] = 7; idx[16] = 6; idx[17] = 4;
1996
1997 idx[18] = 6; idx[19] = 7; idx[20] = 3; //bottom
1998 idx[21] = 2; idx[22] = 3; idx[23] = 7;
1999
2000 idx[24] = 0; idx[25] = 5; idx[26] = 3; //left
2001 idx[27] = 6; idx[28] = 3; idx[29] = 5;
2002
2003 idx[30] = 4; idx[31] = 1; idx[32] = 7; //right
2004 idx[33] = 2; idx[34] = 7; idx[35] = 1;
2005 }
2006
2007 //virtual BOOL useVBOs() const { return FALSE; }
2008
2009 void setBuffer(U32 data_mask)
2010 {
2011 if (useVBOs())
2012 {
2013 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);
2014 sIBOActive = TRUE;
2015 unmapBuffer();
2016 }
2017 else if (sIBOActive)
2018 {
2019 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
2020 sIBOActive = FALSE;
2021 }
2022
2023 sGLRenderIndices = mGLIndices;
2024 }
2025};
2026 1925
2027class LLOcclusionVertexBuffer : public LLVertexBuffer 1926 if (buffer)
2028{
2029public:
2030 LLOcclusionVertexBuffer(S32 usage)
2031 : LLVertexBuffer(MAP_VERTEX, usage)
2032 { 1927 {
2033 allocateBuffer(8, 0, TRUE); 1928 buffer->setBuffer(mask);
2034 } 1929 U16* indicesp = (U16*) buffer->getIndicesPointer();
2035 1930 U16 start = face->getGeomStart();
2036 //virtual BOOL useVBOs() const { return FALSE; } 1931 U16 end = start + face->getGeomCount()-1;
2037 1932 U32 count = face->getIndicesCount();
2038 void setBuffer(U32 data_mask) 1933 U16 offset = face->getIndicesStart();
2039 {
2040 if (useVBOs())
2041 {
2042 glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
2043 sVBOActive = TRUE;
2044 unmapBuffer();
2045 }
2046 else if (sVBOActive)
2047 {
2048 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
2049 sVBOActive = FALSE;
2050 }
2051
2052 if (data_mask)
2053 {
2054 glVertexPointer(3,GL_FLOAT, 0, useVBOs() ? 0 : mMappedData);
2055 }
2056
2057 sGLRenderBuffer = mGLBuffer;
2058 }
2059};
2060
2061void LLSpatialPartition::buildOcclusion()
2062{
2063 if (mOccludedList.empty())
2064 {
2065 return;
2066 }
2067
2068 BOOL reset_all = FALSE;
2069 if (mOcclusionIndices.isNull())
2070 {
2071 mOcclusionIndices = new LLOcclusionIndexBuffer(36);
2072 reset_all = TRUE;
2073 }
2074
2075 //fill occlusion vertex buffers
2076 for (U32 i = 0; i < mOccludedList.size(); i++)
2077 {
2078 LLSpatialGroup* group = mOccludedList[i];
2079
2080 if (group->isState(LLSpatialGroup::OCCLUSION_DIRTY) || reset_all)
2081 {
2082 LLFastTimer ftm(LLFastTimer::FTM_REBUILD_OCCLUSION_VB);
2083
2084 if (group->mOcclusionVerts.isNull())
2085 {
2086 group->mOcclusionVerts = new LLOcclusionVertexBuffer(GL_STREAM_DRAW_ARB);
2087 }
2088
2089 group->clearState(LLSpatialGroup::OCCLUSION_DIRTY);
2090
2091 LLStrider<LLVector3> vert;
2092
2093 group->mOcclusionVerts->getVertexStrider(vert);
2094
2095 LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.1f,0.1f,0.1f);
2096
2097 for (U32 k = 0; k < 3; k++)
2098 {
2099 r.mV[k] = llmin(group->mBounds[1].mV[k]+0.25f, r.mV[k]);
2100 }
2101
2102 *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,1,1)); // 0 - left top front
2103 *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,1,1)); // 1 - right top front
2104 *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,-1,1)); // 2 - right bottom front
2105 *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,-1,1)); // 3 - left bottom front
2106 1934
2107 *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,1,-1)); // 4 - left top back 1935 glDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_SHORT, indicesp + offset);
2108 *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,1,-1)); // 5 - right top back
2109 *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,-1,-1)); // 6 - right bottom back
2110 *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,-1,-1)); // 7 -left bottom back
2111 }
2112 } 1936 }
2113 1937
2114/* for (U32 i = 0; i < mOccludedList.size(); i++)
2115 {
2116 LLSpatialGroup* group = mOccludedList[i];
2117 if (!group->mOcclusionVerts.isNull() && group->mOcclusionVerts->isLocked())
2118 {
2119 LLFastTimer ftm(LLFastTimer::FTM_REBUILD_OCCLUSION_VB);
2120 group->mOcclusionVerts->setBuffer(0);
2121 }
2122 }*/
2123} 1938}
2124 1939
2125void LLSpatialPartition::doOcclusion(LLCamera* camera) 1940void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
2126{ 1941{
2127 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); 1942 if (buffer)
2128
2129 LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION);
2130
2131#if LL_OCTREE_PARANOIA_CHECK
2132 LLSpatialGroup* check = (LLSpatialGroup*) mOctree->getListener(0);
2133 check->validate();
2134#endif
2135
2136 stop_glerror();
2137
2138 U32 num_verts = mOccludedList.size() * 8;
2139
2140 if (num_verts == 0)
2141 { 1943 {
2142 return; 1944 buffer->setBuffer(mask);
1945 U16* indicesp = (U16*) buffer->getIndicesPointer();
1946 glDrawRangeElements(GL_TRIANGLES, 0, buffer->getRequestedVerts(), buffer->getRequestedIndices(),
1947 GL_UNSIGNED_SHORT, indicesp);
2143 } 1948 }
2144
2145 //actually perform the occlusion queries
2146 LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
2147 LLGLDisable(GL_TEXTURE_2D);
2148 gPipeline.disableLights();
2149 LLGLEnable cull_face(GL_CULL_FACE);
2150 LLGLDisable blend(GL_BLEND);
2151 LLGLDisable alpha_test(GL_ALPHA_TEST);
2152 LLGLDisable fog(GL_FOG);
2153 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2154 glColor4f(1,1,1,1);
2155
2156 mOcclusionIndices->setBuffer(0);
2157
2158 U32* indicesp = (U32*) mOcclusionIndices->getIndicesPointer();
2159
2160 glDisableClientState(GL_NORMAL_ARRAY);
2161 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2162 glDisableClientState(GL_COLOR_ARRAY);
2163#if !LL_RELEASE_FOR_DOWNLOAD
2164 LLGLState::checkClientArrays(LLVertexBuffer::MAP_VERTEX);
2165#endif
2166 for (U32 i = 0; i < mOccludedList.size(); i++)
2167 {
2168#if LL_OCTREE_PARANOIA_CHECK
2169 for (U32 j = i+1; j < mOccludedList.size(); j++)
2170 {
2171 sg_assert(mOccludedList[i] != mOccludedList[j]);
2172 }
2173#endif
2174 LLSpatialGroup* group = mOccludedList[i];
2175 if (group->isDead())
2176 {
2177 continue;
2178 }
2179
2180 if (earlyFail(camera, group))
2181 {
2182 group->setState(LLSpatialGroup::EARLY_FAIL);
2183 }
2184 else
2185 { //early rejection criteria passed, send some geometry to the query
2186 group->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX);
2187 glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQueries[i]);
2188 glDrawRangeElements(GL_TRIANGLES, 0, 7, 36,
2189 GL_UNSIGNED_INT, indicesp);
2190 glEndQueryARB(GL_SAMPLES_PASSED_ARB);
2191
2192 group->setState(LLSpatialGroup::QUERY_OUT);
2193 group->clearState(LLSpatialGroup::DISCARD_QUERY);
2194 }
2195 }
2196 stop_glerror();
2197
2198 gPipeline.mTrianglesDrawn += mOccludedList.size()*12;
2199
2200 glFlush();
2201
2202 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
2203} 1949}
2204 1950
2205class LLOctreeGet : public LLSpatialGroup::OctreeTraveler 1951void pushBufferVerts(LLSpatialGroup* group, U32 mask)
2206{ 1952{
2207public: 1953 if (!group->mDrawMap.empty())
2208 LLOctreeGet(LLVector3 pos, F32 rad, LLDrawable::drawable_set_t* results, BOOL lights)
2209 : mPosition(pos), mRad(rad), mResults(results), mLights(lights), mRes(0)
2210 {
2211
2212 }
2213
2214 virtual void traverse(const LLSpatialGroup::TreeNode* n)
2215 { 1954 {
2216 LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); 1955 LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin());
2217 1956 LLRenderPass::applyModelMatrix(*params);
2218 if (mRes == 2) 1957
2219 { //fully in, just add everything 1958 pushBufferVerts(group->mVertexBuffer, mask);
2220 LLSpatialGroup::OctreeTraveler::traverse(n);
2221 }
2222 else
2223 {
2224 LLVector3 center, size;
2225
2226 center = group->mBounds[0];
2227 size = group->mBounds[1];
2228
2229 mRes = LLSphereAABB(center, size, mPosition, mRad);
2230 if (mRes > 0)
2231 {
2232 LLSpatialGroup::OctreeTraveler::traverse(n);
2233 }
2234 mRes = 0;
2235 }
2236 }
2237
2238 static BOOL skip(LLDrawable* drawable, BOOL get_lights)
2239 {
2240 if (get_lights != drawable->isLight())
2241 {
2242 return TRUE;
2243 }
2244 if (get_lights && drawable->getVObj()->isHUDAttachment())
2245 {
2246 return TRUE; // no lighting from HUD objects
2247 }
2248 if (get_lights && drawable->isState(LLDrawable::ACTIVE))
2249 {
2250 return TRUE; // ignore active lights
2251 }
2252 return FALSE;
2253 }
2254 1959
2255 virtual void visit(const LLSpatialGroup::OctreeState* branch) 1960 for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i)
2256 {
2257 for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
2258 { 1961 {
2259 LLDrawable* drawable = *i; 1962 for (LLSpatialGroup::buffer_list_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
2260 if (!skip(drawable, mLights))
2261 { 1963 {
2262 if (mRes == 2) 1964 pushBufferVerts(*j, mask);
2263 {
2264 mResults->insert(drawable);
2265 }
2266 else
2267 {
2268 LLVector3 v = LLVector3(drawable->getPositionGroup())-mPosition;
2269 float dsq = v.magVecSquared();
2270 float maxd = mRad + drawable->getVisibilityRadius();
2271 if (dsq <= maxd*maxd)
2272 {
2273 mResults->insert(drawable);
2274 }
2275 }
2276 } 1965 }
2277 } 1966 }
2278 } 1967 }
2279
2280 LLVector3 mPosition;
2281 F32 mRad;
2282 LLDrawable::drawable_set_t* mResults;
2283 BOOL mLights;
2284 U32 mRes;
2285};
2286
2287S32 LLSpatialPartition::getDrawables(const LLVector3& pos, F32 rad,
2288 LLDrawable::drawable_set_t &results,
2289 BOOL get_lights)
2290{
2291 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
2292
2293 LLOctreeGet getter(pos, rad, &results, get_lights);
2294 getter.traverse(mOctree);
2295
2296 return results.size();
2297}
2298
2299S32 LLSpatialPartition::getObjects(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results)
2300{
2301 LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
2302 group->rebound();
2303 return getDrawables(pos, rad, results, FALSE);
2304}
2305
2306S32 LLSpatialPartition::getLights(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results)
2307{
2308 return getDrawables(pos, rad, results, TRUE);
2309}
2310
2311void pushVerts(LLDrawInfo* params, U32 mask)
2312{
2313 params->mVertexBuffer->setBuffer(mask);
2314 U32* indicesp = (U32*) params->mVertexBuffer->getIndicesPointer();
2315 glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount,
2316 GL_UNSIGNED_INT, indicesp+params->mOffset);
2317}
2318
2319void pushVerts(LLSpatialGroup* group, U32 mask)
2320{
2321 LLDrawInfo* params = NULL;
2322
2323 for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
2324 {
2325 for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
2326 {
2327 params = *j;
2328 pushVerts(params, mask);
2329 }
2330 }
2331} 1968}
2332 1969
2333void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) 1970void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)
@@ -2353,11 +1990,12 @@ void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)
2353 for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) 1990 for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
2354 { 1991 {
2355 params = *j; 1992 params = *j;
1993 LLRenderPass::applyModelMatrix(*params);
2356 glColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f); 1994 glColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f);
2357 params->mVertexBuffer->setBuffer(mask); 1995 params->mVertexBuffer->setBuffer(mask);
2358 U32* indicesp = (U32*) params->mVertexBuffer->getIndicesPointer(); 1996 U16* indicesp = (U16*) params->mVertexBuffer->getIndicesPointer();
2359 glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount, 1997 glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount,
2360 GL_UNSIGNED_INT, indicesp+params->mOffset); 1998 GL_UNSIGNED_SHORT, indicesp+params->mOffset);
2361 col = (col+1)%col_count; 1999 col = (col+1)%col_count;
2362 } 2000 }
2363 } 2001 }
@@ -2368,7 +2006,7 @@ void renderOctree(LLSpatialGroup* group)
2368 //render solid object bounding box, color 2006 //render solid object bounding box, color
2369 //coded by buffer usage and activity 2007 //coded by buffer usage and activity
2370 LLGLDepthTest depth(GL_TRUE, GL_FALSE); 2008 LLGLDepthTest depth(GL_TRUE, GL_FALSE);
2371 glBlendFunc(GL_SRC_ALPHA, GL_ONE); 2009 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
2372 LLVector4 col; 2010 LLVector4 col;
2373 if (group->mBuilt > 0.f) 2011 if (group->mBuilt > 0.f)
2374 { 2012 {
@@ -2385,34 +2023,59 @@ void renderOctree(LLSpatialGroup* group)
2385 2023
2386 if (group->mBufferUsage != GL_STATIC_DRAW_ARB) 2024 if (group->mBufferUsage != GL_STATIC_DRAW_ARB)
2387 { 2025 {
2388 if (group->mBufferUsage == GL_DYNAMIC_DRAW_ARB)
2389 {
2390 glColor4f(1,0,0,group->mBuilt);
2391 }
2392 else
2393 {
2394 glColor4f(1,1,0,group->mBuilt);
2395 }
2396
2397 LLGLDepthTest gl_depth(FALSE, FALSE); 2026 LLGLDepthTest gl_depth(FALSE, FALSE);
2398 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 2027 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2028
2029 gGL.color4f(1,0,0,group->mBuilt);
2030 gGL.flush();
2031 glLineWidth(5.f);
2032 drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
2033 gGL.flush();
2034 glLineWidth(1.f);
2035 gGL.stop();
2399 for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) 2036 for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
2400 { 2037 {
2401 LLDrawable* drawable = *i; 2038 LLDrawable* drawable = *i;
2039 if (!group->mSpatialPartition->isBridge())
2040 {
2041 glPushMatrix();
2042 LLVector3 trans = drawable->getRegion()->getOriginAgent();
2043 glTranslatef(trans.mV[0], trans.mV[1], trans.mV[2]);
2044 }
2045
2402 for (S32 j = 0; j < drawable->getNumFaces(); j++) 2046 for (S32 j = 0; j < drawable->getNumFaces(); j++)
2403 { 2047 {
2404 LLFace* face = drawable->getFace(j); 2048 LLFace* face = drawable->getFace(j);
2405 if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f && face->mVertexBuffer.notNull()) 2049 if (face->mVertexBuffer.notNull())
2406 { 2050 {
2051 if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f)
2052 {
2053 glColor4f(0, 1, 0, group->mBuilt);
2054 }
2055 else if (gFrameTimeSeconds - face->mLastMoveTime < 0.5f)
2056 {
2057 glColor4f(1, 0, 0, group->mBuilt);
2058 }
2059 else
2060 {
2061 continue;
2062 }
2063
2407 face->mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX); 2064 face->mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX);
2408 //drawBox((face->mExtents[0] + face->mExtents[1])*0.5f, 2065 //drawBox((face->mExtents[0] + face->mExtents[1])*0.5f,
2409 // (face->mExtents[1]-face->mExtents[0])*0.5f); 2066 // (face->mExtents[1]-face->mExtents[0])*0.5f);
2410 glDrawElements(GL_TRIANGLES, face->getIndicesCount(), GL_UNSIGNED_INT, 2067 glDrawElements(GL_TRIANGLES, face->getIndicesCount(), GL_UNSIGNED_SHORT,
2411 ((U32*) face->mVertexBuffer->getIndicesPointer())+face->getIndicesStart()); 2068 ((U16*) face->mVertexBuffer->getIndicesPointer())+face->getIndicesStart());
2412 } 2069 }
2413 } 2070 }
2071
2072 if (!group->mSpatialPartition->isBridge())
2073 {
2074 glPopMatrix();
2075 }
2414 } 2076 }
2415 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 2077 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2078 gGL.start();
2416 } 2079 }
2417 } 2080 }
2418 else 2081 else
@@ -2428,50 +2091,80 @@ void renderOctree(LLSpatialGroup* group)
2428 } 2091 }
2429 } 2092 }
2430 2093
2431 glColor4fv(col.mV); 2094 gGL.color4fv(col.mV);
2432 drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); 2095 drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f));
2096
2433 glDepthMask(GL_TRUE); 2097 glDepthMask(GL_TRUE);
2434 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2098 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2435 2099
2436 //draw opaque outline 2100 if (group->mBuilt <= 0.f)
2437 glColor4f(col.mV[0], col.mV[1], col.mV[2], 1.f);
2438 drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
2439
2440 if (group->mOctreeNode->hasLeafState())
2441 {
2442 glColor4f(1,1,1,1);
2443 }
2444 else
2445 { 2101 {
2446 glColor4f(0,1,1,1); 2102 //draw opaque outline
2103 gGL.color4f(col.mV[0], col.mV[1], col.mV[2], 1.f);
2104 drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
2105
2106 if (group->mOctreeNode->isLeaf())
2107 {
2108 gGL.color4f(1,1,1,1);
2109 }
2110 else
2111 {
2112 gGL.color4f(0,1,1,1);
2113 }
2114
2115 drawBoxOutline(group->mBounds[0],group->mBounds[1]);
2447 } 2116 }
2448
2449 drawBoxOutline(group->mBounds[0],group->mBounds[1]);
2450 2117
2451// LLSpatialGroup::OctreeNode* node = group->mOctreeNode; 2118// LLSpatialGroup::OctreeNode* node = group->mOctreeNode;
2452// glColor4f(0,1,0,1); 2119// gGL.color4f(0,1,0,1);
2453// drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize())); 2120// drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize()));
2454} 2121}
2455 2122
2456void renderVisibility(LLSpatialGroup* group) 2123void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
2457{ 2124{
2458 LLGLEnable blend(GL_BLEND); 2125 LLGLEnable blend(GL_BLEND);
2459 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2126 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2460 LLGLEnable cull(GL_CULL_FACE); 2127 LLGLEnable cull(GL_CULL_FACE);
2461 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 2128 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2129
2130 BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
2131 !group->getData().empty();
2132 if (render_objects)
2462 { 2133 {
2463 LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); 2134 LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER);
2464 glColor4f(0, 0.5f, 0, 0.5f); 2135 glColor4f(0, 0.5f, 0, 0.5f);
2465 pushVerts(group, LLVertexBuffer::MAP_VERTEX); 2136 pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
2466 } 2137 }
2467 2138
2468 { 2139 {
2469 LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL); 2140 LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL);
2470 pushVertsColorCoded(group, LLVertexBuffer::MAP_VERTEX); 2141
2142 if (render_objects)
2143 {
2144 glColor4f(0.f, 0.5f, 0.f,1.f);
2145 pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
2146 }
2471 2147
2472 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 2148 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2473 2149
2474 pushVertsColorCoded(group, LLVertexBuffer::MAP_VERTEX); 2150 if (render_objects)
2151 {
2152 glColor4f(0.f, 0.75f, 0.f,0.5f);
2153 pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
2154 }
2155 else if (camera && group->mOcclusionVerts)
2156 {
2157 LLVertexBuffer::unbind();
2158 glVertexPointer(3, GL_FLOAT, 0, group->mOcclusionVerts);
2159
2160 glColor4f(1.0f, 0.f, 0.f, 0.5f);
2161 glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_occlusion_indices(camera, group->mBounds[0]));
2162 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2163
2164 glColor4f(1.0f, 1.f, 1.f, 1.0f);
2165 glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_occlusion_indices(camera, group->mBounds[0]));
2166 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2167 }
2475 } 2168 }
2476} 2169}
2477 2170
@@ -2479,17 +2172,17 @@ void renderBoundingBox(LLDrawable* drawable)
2479{ 2172{
2480 if (drawable->isSpatialBridge()) 2173 if (drawable->isSpatialBridge())
2481 { 2174 {
2482 glColor4f(1,0.5f,0,1); 2175 gGL.color4f(1,0.5f,0,1);
2483 } 2176 }
2484 else if (drawable->getVOVolume()) 2177 else if (drawable->getVOVolume())
2485 { 2178 {
2486 if (drawable->isRoot()) 2179 if (drawable->isRoot())
2487 { 2180 {
2488 glColor4f(1,1,0,1); 2181 gGL.color4f(1,1,0,1);
2489 } 2182 }
2490 else 2183 else
2491 { 2184 {
2492 glColor4f(0,1,0,1); 2185 gGL.color4f(0,1,0,1);
2493 } 2186 }
2494 } 2187 }
2495 else if (drawable->getVObj()) 2188 else if (drawable->getVObj())
@@ -2497,27 +2190,27 @@ void renderBoundingBox(LLDrawable* drawable)
2497 switch (drawable->getVObj()->getPCode()) 2190 switch (drawable->getVObj()->getPCode())
2498 { 2191 {
2499 case LLViewerObject::LL_VO_SURFACE_PATCH: 2192 case LLViewerObject::LL_VO_SURFACE_PATCH:
2500 glColor4f(0,1,1,1); 2193 gGL.color4f(0,1,1,1);
2501 break; 2194 break;
2502 case LLViewerObject::LL_VO_CLOUDS: 2195 case LLViewerObject::LL_VO_CLOUDS:
2503 glColor4f(0.5f,0.5f,0.5f,1.0f); 2196 gGL.color4f(0.5f,0.5f,0.5f,1.0f);
2504 break; 2197 break;
2505 case LLViewerObject::LL_VO_PART_GROUP: 2198 case LLViewerObject::LL_VO_PART_GROUP:
2506 glColor4f(0,0,1,1); 2199 gGL.color4f(0,0,1,1);
2507 break; 2200 break;
2508 case LLViewerObject::LL_VO_WATER: 2201 case LLViewerObject::LL_VO_WATER:
2509 glColor4f(0,0.5f,1,1); 2202 gGL.color4f(0,0.5f,1,1);
2510 break; 2203 break;
2511 case LL_PCODE_LEGACY_TREE: 2204 case LL_PCODE_LEGACY_TREE:
2512 glColor4f(0,0.5f,0,1); 2205 gGL.color4f(0,0.5f,0,1);
2513 default: 2206 default:
2514 glColor4f(1,0,1,1); 2207 gGL.color4f(1,0,1,1);
2515 break; 2208 break;
2516 } 2209 }
2517 } 2210 }
2518 else 2211 else
2519 { 2212 {
2520 glColor4f(1,0,0,1); 2213 gGL.color4f(1,0,0,1);
2521 } 2214 }
2522 2215
2523 const LLVector3* ext; 2216 const LLVector3* ext;
@@ -2545,7 +2238,20 @@ void renderBoundingBox(LLDrawable* drawable)
2545 pos = (ext[0] + ext[1]) * 0.5f; 2238 pos = (ext[0] + ext[1]) * 0.5f;
2546 size = (ext[1] - ext[0]) * 0.5f; 2239 size = (ext[1] - ext[0]) * 0.5f;
2547 2240
2548 drawBoxOutline(pos,size); 2241 LLViewerObject* vobj = drawable->getVObj();
2242 if (vobj && vobj->onActiveList())
2243 {
2244 gGL.flush();
2245 glLineWidth(4.f*sinf(gFrameTimeSeconds*2.f)+1.f);
2246 drawBoxOutline(pos,size);
2247 gGL.flush();
2248 glLineWidth(1.f);
2249 }
2250 else
2251 {
2252 drawBoxOutline(pos,size);
2253 }
2254
2549} 2255}
2550 2256
2551void renderTexturePriority(LLDrawable* drawable) 2257void renderTexturePriority(LLDrawable* drawable)
@@ -2578,14 +2284,12 @@ void renderTexturePriority(LLDrawable* drawable)
2578 F32 t = vsize/sLastMaxTexPriority; 2284 F32 t = vsize/sLastMaxTexPriority;
2579 2285
2580 LLVector4 col = lerp(cold, hot, t); 2286 LLVector4 col = lerp(cold, hot, t);
2581 glColor4fv(col.mV); 2287 gGL.color4fv(col.mV);
2582 } 2288 }
2583 //else 2289 //else
2584 //{ 2290 //{
2585 // glColor4f(1,0,1,1); 2291 // gGL.color4f(1,0,1,1);
2586 //} 2292 //}
2587
2588
2589 2293
2590 LLVector3 center = (facep->mExtents[1]+facep->mExtents[0])*0.5f; 2294 LLVector3 center = (facep->mExtents[1]+facep->mExtents[0])*0.5f;
2591 LLVector3 size = (facep->mExtents[1]-facep->mExtents[0])*0.5f + LLVector3(0.01f, 0.01f, 0.01f); 2295 LLVector3 size = (facep->mExtents[1]-facep->mExtents[0])*0.5f + LLVector3(0.01f, 0.01f, 0.01f);
@@ -2597,10 +2301,10 @@ void renderTexturePriority(LLDrawable* drawable)
2597 F32 t = (F32) boost / (F32) (LLViewerImage::BOOST_MAX_LEVEL-1); 2301 F32 t = (F32) boost / (F32) (LLViewerImage::BOOST_MAX_LEVEL-1);
2598 LLVector4 col = lerp(boost_cold, boost_hot, t); 2302 LLVector4 col = lerp(boost_cold, boost_hot, t);
2599 LLGLEnable blend_on(GL_BLEND); 2303 LLGLEnable blend_on(GL_BLEND);
2600 glBlendFunc(GL_SRC_ALPHA, GL_ONE); 2304 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
2601 glColor4fv(col.mV); 2305 gGL.color4fv(col.mV);
2602 drawBox(center, size); 2306 drawBox(center, size);
2603 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2307 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2604 }*/ 2308 }*/
2605 } 2309 }
2606} 2310}
@@ -2608,14 +2312,17 @@ void renderTexturePriority(LLDrawable* drawable)
2608void renderPoints(LLDrawable* drawablep) 2312void renderPoints(LLDrawable* drawablep)
2609{ 2313{
2610 LLGLDepthTest depth(GL_FALSE, GL_FALSE); 2314 LLGLDepthTest depth(GL_FALSE, GL_FALSE);
2611 glBegin(GL_POINTS); 2315 if (drawablep->getNumFaces())
2612 glColor3f(1,1,1);
2613 LLVector3 center(drawablep->getPositionGroup());
2614 for (S32 i = 0; i < drawablep->getNumFaces(); i++)
2615 { 2316 {
2616 glVertex3fv(drawablep->getFace(i)->mCenterLocal.mV); 2317 gGL.begin(GL_POINTS);
2318 gGL.color3f(1,1,1);
2319 LLVector3 center(drawablep->getPositionGroup());
2320 for (S32 i = 0; i < drawablep->getNumFaces(); i++)
2321 {
2322 gGL.vertex3fv(drawablep->getFace(i)->mCenterLocal.mV);
2323 }
2324 gGL.end();
2617 } 2325 }
2618 glEnd();
2619} 2326}
2620 2327
2621void renderTextureAnim(LLDrawInfo* params) 2328void renderTextureAnim(LLDrawInfo* params)
@@ -2626,29 +2333,67 @@ void renderTextureAnim(LLDrawInfo* params)
2626 } 2333 }
2627 2334
2628 LLGLEnable blend(GL_BLEND); 2335 LLGLEnable blend(GL_BLEND);
2629 glColor4f(1,1,0,0.5f); 2336 gGL.color4f(1,1,0,0.5f);
2630 pushVerts(params, LLVertexBuffer::MAP_VERTEX); 2337 pushVerts(params, LLVertexBuffer::MAP_VERTEX);
2631} 2338}
2632 2339
2340void renderBatchSize(LLDrawInfo* params)
2341{
2342 glColor3ubv((GLubyte*) &(params->mDebugColor));
2343 pushVerts(params, LLVertexBuffer::MAP_VERTEX);
2344}
2345
2346void renderLights(LLDrawable* drawablep)
2347{
2348 if (!drawablep->isLight())
2349 {
2350 return;
2351 }
2352
2353 if (drawablep->getNumFaces())
2354 {
2355 LLGLEnable blend(GL_BLEND);
2356 glColor4f(0,1,1,0.5f);
2357
2358 for (S32 i = 0; i < drawablep->getNumFaces(); i++)
2359 {
2360 pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX);
2361 }
2362
2363 const LLVector3* ext = drawablep->getSpatialExtents();
2364
2365 LLVector3 pos = (ext[0] + ext[1]) * 0.5f;
2366 LLVector3 size = (ext[1] - ext[0]) * 0.5f;
2367
2368 {
2369 LLGLDepthTest depth(GL_FALSE, GL_TRUE);
2370 gGL.color4f(1,1,1,1);
2371 drawBoxOutline(pos, size);
2372 }
2373
2374 gGL.color4f(1,1,0,1);
2375 F32 rad = drawablep->getVOVolume()->getLightRadius();
2376 drawBoxOutline(pos, LLVector3(rad,rad,rad));
2377 }
2378}
2379
2633class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable> 2380class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable>
2634{ 2381{
2635public: 2382public:
2636 LLOctreeRenderNonOccluded() {} 2383 LLCamera* mCamera;
2384 LLOctreeRenderNonOccluded(LLCamera* camera): mCamera(camera) {}
2637 2385
2638 virtual void traverse(const LLSpatialGroup::OctreeNode* node) 2386 virtual void traverse(const LLSpatialGroup::OctreeNode* node)
2639 { 2387 {
2640 const LLSpatialGroup::OctreeState* state = node->getOctState();
2641 LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); 2388 LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
2642 2389
2643 2390 if (!mCamera || mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]))
2644 if ((!gPipeline.sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) &&
2645 !group->isState(LLSpatialGroup::CULLED))
2646 { 2391 {
2647 state->accept(this); 2392 node->accept(this);
2648 2393
2649 for (U32 i = 0; i < state->getChildCount(); i++) 2394 for (U32 i = 0; i < node->getChildCount(); i++)
2650 { 2395 {
2651 traverse(state->getChild(i)); 2396 traverse(node->getChild(i));
2652 } 2397 }
2653 2398
2654 //draw tight fit bounding boxes for spatial group 2399 //draw tight fit bounding boxes for spatial group
@@ -2659,19 +2404,25 @@ public:
2659 2404
2660 //render visibility wireframe 2405 //render visibility wireframe
2661 if (group->mSpatialPartition->mRenderByGroup && 2406 if (group->mSpatialPartition->mRenderByGroup &&
2662 gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) && 2407 gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
2663 !group->isState(LLSpatialGroup::GEOM_DIRTY))
2664 { 2408 {
2665 renderVisibility(group); 2409 gGL.stop();
2410 glPushMatrix();
2411 gGLLastMatrix = NULL;
2412 glLoadMatrixd(gGLModelView);
2413 renderVisibility(group, mCamera);
2414 gGLLastMatrix = NULL;
2415 glPopMatrix();
2416 gGL.start();
2666 } 2417 }
2667 } 2418 }
2668 } 2419 }
2669 2420
2670 virtual void visit(const LLSpatialGroup::OctreeState* branch) 2421 virtual void visit(const LLSpatialGroup::OctreeNode* branch)
2671 { 2422 {
2672 LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); 2423 LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0);
2673 2424
2674 if (group->isState(LLSpatialGroup::CULLED | LLSpatialGroup::OCCLUDED)) 2425 if (mCamera && !mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]))
2675 { 2426 {
2676 return; 2427 return;
2677 } 2428 }
@@ -2679,7 +2430,7 @@ public:
2679 LLVector3 nodeCenter = group->mBounds[0]; 2430 LLVector3 nodeCenter = group->mBounds[0];
2680 LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter()); 2431 LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter());
2681 2432
2682 for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) 2433 for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
2683 { 2434 {
2684 LLDrawable* drawable = *i; 2435 LLDrawable* drawable = *i;
2685 2436
@@ -2697,6 +2448,11 @@ public:
2697 { 2448 {
2698 renderPoints(drawable); 2449 renderPoints(drawable);
2699 } 2450 }
2451
2452 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LIGHTS))
2453 {
2454 renderLights(drawable);
2455 }
2700 } 2456 }
2701 2457
2702 for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) 2458 for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
@@ -2709,6 +2465,10 @@ public:
2709 { 2465 {
2710 renderTextureAnim(draw_info); 2466 renderTextureAnim(draw_info);
2711 } 2467 }
2468 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BATCH_SIZE))
2469 {
2470 renderBatchSize(draw_info);
2471 }
2712 } 2472 }
2713 } 2473 }
2714 } 2474 }
@@ -2718,6 +2478,8 @@ void LLSpatialPartition::renderDebug()
2718{ 2478{
2719 if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | 2479 if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE |
2720 LLPipeline::RENDER_DEBUG_OCCLUSION | 2480 LLPipeline::RENDER_DEBUG_OCCLUSION |
2481 LLPipeline::RENDER_DEBUG_LIGHTS |
2482 LLPipeline::RENDER_DEBUG_BATCH_SIZE |
2721 LLPipeline::RENDER_DEBUG_BBOXES | 2483 LLPipeline::RENDER_DEBUG_BBOXES |
2722 LLPipeline::RENDER_DEBUG_POINTS | 2484 LLPipeline::RENDER_DEBUG_POINTS |
2723 LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY | 2485 LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY |
@@ -2737,57 +2499,23 @@ void LLSpatialPartition::renderDebug()
2737 2499
2738 LLGLDisable cullface(GL_CULL_FACE); 2500 LLGLDisable cullface(GL_CULL_FACE);
2739 LLGLEnable blend(GL_BLEND); 2501 LLGLEnable blend(GL_BLEND);
2740 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2502 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2741 LLGLDisable tex(GL_TEXTURE_2D); 2503 LLImageGL::unbindTexture(0);
2742 gPipeline.disableLights(); 2504 gPipeline.disableLights();
2743
2744 LLOctreeRenderNonOccluded render_debug;
2745 render_debug.traverse(mOctree);
2746 2505
2747 LLGLDisable cull_face(GL_CULL_FACE); 2506 LLSpatialBridge* bridge = asBridge();
2507 LLCamera* camera = gCamera;
2748 2508
2749 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) && !mOccludedList.empty() && 2509 if (bridge)
2750 mOcclusionIndices.notNull())
2751 { 2510 {
2752 LLGLDisable fog(GL_FOG); 2511 camera = NULL;
2753 LLGLDepthTest gls_depth(GL_FALSE); 2512 }
2754 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
2755 mOcclusionIndices->setBuffer(0);
2756 U32* indicesp = (U32*) mOcclusionIndices->getIndicesPointer();
2757
2758 LLGLEnable blend(GL_BLEND);
2759 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2760 LLGLEnable cull(GL_CULL_FACE);
2761 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
2762
2763 for (U32 i = 0; i < mOccludedList.size(); i++)
2764 { //draw occluded nodes
2765 LLSpatialGroup* node = mOccludedList[i];
2766 if (node->isDead() ||
2767 !node->isState(LLSpatialGroup::OCCLUDED) ||
2768 node->mOcclusionVerts.isNull())
2769 {
2770 continue;
2771 }
2772
2773 node->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX);
2774 {
2775 LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER);
2776 glColor4f(0.5, 0.5f, 0, 0.25f);
2777 glDrawRangeElements(GL_TRIANGLES, 0, 7, 36,
2778 GL_UNSIGNED_INT, indicesp);
2779 }
2780 2513
2781 { 2514 LLOctreeStateCheck checker;
2782 LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL); 2515 checker.traverse(mOctree);
2783 glColor4f(0.0,1.0f,1.0f,1.0f);
2784 glDrawRangeElements(GL_TRIANGLES, 0, 7, 36,
2785 GL_UNSIGNED_INT, indicesp);
2786 }
2787 }
2788 2516
2789 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 2517 LLOctreeRenderNonOccluded render_debug(camera);
2790 } 2518 render_debug.traverse(mOctree);
2791} 2519}
2792 2520
2793 2521
@@ -2816,8 +2544,7 @@ public:
2816 2544
2817 virtual LLDrawable* check(const LLSpatialGroup::OctreeNode* node) 2545 virtual LLDrawable* check(const LLSpatialGroup::OctreeNode* node)
2818 { 2546 {
2819 const LLSpatialGroup::OctreeState* state = node->getOctState(); 2547 node->accept(this);
2820 state->accept(this);
2821 2548
2822 for (U32 i = 0; i < node->getChildCount(); i++) 2549 for (U32 i = 0; i < node->getChildCount(); i++)
2823 { 2550 {
@@ -2841,9 +2568,9 @@ public:
2841 return mRet; 2568 return mRet;
2842 } 2569 }
2843 2570
2844 virtual void visit(const LLSpatialGroup::OctreeState* branch) 2571 virtual void visit(const LLSpatialGroup::OctreeNode* branch)
2845 { 2572 {
2846 for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) 2573 for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
2847 { 2574 {
2848 check(*i); 2575 check(*i);
2849 } 2576 }
@@ -2869,13 +2596,14 @@ LLDrawable* LLSpatialPartition::pickDrawable(const LLVector3& start, const LLVec
2869 return ret; 2596 return ret;
2870} 2597}
2871 2598
2872LLDrawInfo::LLDrawInfo(U32 start, U32 end, U32 count, U32 offset, 2599LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
2873 LLViewerImage* texture, LLVertexBuffer* buffer, 2600 LLViewerImage* texture, LLVertexBuffer* buffer,
2874 BOOL fullbright, U8 bump, BOOL particle, F32 part_size) 2601 BOOL fullbright, U8 bump, BOOL particle, F32 part_size)
2875: 2602:
2876 mVertexBuffer(buffer), 2603 mVertexBuffer(buffer),
2877 mTexture(texture), 2604 mTexture(texture),
2878 mTextureMatrix(NULL), 2605 mTextureMatrix(NULL),
2606 mModelMatrix(NULL),
2879 mStart(start), 2607 mStart(start),
2880 mEnd(end), 2608 mEnd(end),
2881 mCount(count), 2609 mCount(count),
@@ -2884,8 +2612,10 @@ LLDrawInfo::LLDrawInfo(U32 start, U32 end, U32 count, U32 offset,
2884 mBump(bump), 2612 mBump(bump),
2885 mParticle(particle), 2613 mParticle(particle),
2886 mPartSize(part_size), 2614 mPartSize(part_size),
2887 mVSize(0.f) 2615 mVSize(0.f),
2616 mGroup(NULL)
2888{ 2617{
2618 mDebugColor = (rand() << 16) + rand();
2889} 2619}
2890 2620
2891LLDrawInfo::~LLDrawInfo() 2621LLDrawInfo::~LLDrawInfo()
@@ -2897,3 +2627,190 @@ LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage)
2897{ 2627{
2898 return new LLVertexBuffer(type_mask, usage); 2628 return new LLVertexBuffer(type_mask, usage);
2899} 2629}
2630
2631LLCullResult::LLCullResult()
2632{
2633 clear();
2634}
2635
2636void LLCullResult::clear()
2637{
2638 mVisibleGroupsSize = 0;
2639 mAlphaGroupsSize = 0;
2640 mOcclusionGroupsSize = 0;
2641 mDrawableGroupsSize = 0;
2642 mVisibleListSize = 0;
2643 mVisibleBridgeSize = 0;
2644
2645 for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++)
2646 {
2647 mRenderMapSize[i] = 0;
2648 }
2649}
2650
2651LLCullResult::sg_list_t::iterator LLCullResult::beginVisibleGroups()
2652{
2653 return mVisibleGroups.begin();
2654}
2655
2656LLCullResult::sg_list_t::iterator LLCullResult::endVisibleGroups()
2657{
2658 return mVisibleGroups.begin() + mVisibleGroupsSize;
2659}
2660
2661LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups()
2662{
2663 return mAlphaGroups.begin();
2664}
2665
2666LLCullResult::sg_list_t::iterator LLCullResult::endAlphaGroups()
2667{
2668 return mAlphaGroups.begin() + mAlphaGroupsSize;
2669}
2670
2671LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups()
2672{
2673 return mOcclusionGroups.begin();
2674}
2675
2676LLCullResult::sg_list_t::iterator LLCullResult::endOcclusionGroups()
2677{
2678 return mOcclusionGroups.begin() + mOcclusionGroupsSize;
2679}
2680
2681LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups()
2682{
2683 return mDrawableGroups.begin();
2684}
2685
2686LLCullResult::sg_list_t::iterator LLCullResult::endDrawableGroups()
2687{
2688 return mDrawableGroups.begin() + mDrawableGroupsSize;
2689}
2690
2691LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList()
2692{
2693 return mVisibleList.begin();
2694}
2695
2696LLCullResult::drawable_list_t::iterator LLCullResult::endVisibleList()
2697{
2698 return mVisibleList.begin() + mVisibleListSize;
2699}
2700
2701LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge()
2702{
2703 return mVisibleBridge.begin();
2704}
2705
2706LLCullResult::bridge_list_t::iterator LLCullResult::endVisibleBridge()
2707{
2708 return mVisibleBridge.begin() + mVisibleBridgeSize;
2709}
2710
2711LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type)
2712{
2713 return mRenderMap[type].begin();
2714}
2715
2716LLCullResult::drawinfo_list_t::iterator LLCullResult::endRenderMap(U32 type)
2717{
2718 return mRenderMap[type].begin() + mRenderMapSize[type];
2719}
2720
2721void LLCullResult::pushVisibleGroup(LLSpatialGroup* group)
2722{
2723 if (mVisibleGroupsSize < mVisibleGroups.size())
2724 {
2725 mVisibleGroups[mVisibleGroupsSize] = group;
2726 }
2727 else
2728 {
2729 mVisibleGroups.push_back(group);
2730 }
2731 ++mVisibleGroupsSize;
2732}
2733
2734void LLCullResult::pushAlphaGroup(LLSpatialGroup* group)
2735{
2736 if (mAlphaGroupsSize < mAlphaGroups.size())
2737 {
2738 mAlphaGroups[mAlphaGroupsSize] = group;
2739 }
2740 else
2741 {
2742 mAlphaGroups.push_back(group);
2743 }
2744 ++mAlphaGroupsSize;
2745}
2746
2747void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group)
2748{
2749 if (mOcclusionGroupsSize < mOcclusionGroups.size())
2750 {
2751 mOcclusionGroups[mOcclusionGroupsSize] = group;
2752 }
2753 else
2754 {
2755 mOcclusionGroups.push_back(group);
2756 }
2757 ++mOcclusionGroupsSize;
2758}
2759
2760void LLCullResult::pushDrawableGroup(LLSpatialGroup* group)
2761{
2762 if (mDrawableGroupsSize < mDrawableGroups.size())
2763 {
2764 mDrawableGroups[mDrawableGroupsSize] = group;
2765 }
2766 else
2767 {
2768 mDrawableGroups.push_back(group);
2769 }
2770 ++mDrawableGroupsSize;
2771}
2772
2773void LLCullResult::pushDrawable(LLDrawable* drawable)
2774{
2775 if (mVisibleListSize < mVisibleList.size())
2776 {
2777 mVisibleList[mVisibleListSize] = drawable;
2778 }
2779 else
2780 {
2781 mVisibleList.push_back(drawable);
2782 }
2783 ++mVisibleListSize;
2784}
2785
2786void LLCullResult::pushBridge(LLSpatialBridge* bridge)
2787{
2788 if (mVisibleBridgeSize < mVisibleBridge.size())
2789 {
2790 mVisibleBridge[mVisibleBridgeSize] = bridge;
2791 }
2792 else
2793 {
2794 mVisibleBridge.push_back(bridge);
2795 }
2796 ++mVisibleBridgeSize;
2797}
2798
2799void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info)
2800{
2801 if (mRenderMapSize[type] < mRenderMap[type].size())
2802 {
2803 mRenderMap[type][mRenderMapSize[type]] = draw_info;
2804 }
2805 else
2806 {
2807 mRenderMap[type].push_back(draw_info);
2808 }
2809 ++mRenderMapSize[type];
2810}
2811
2812
2813
2814
2815
2816