00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llspatialpartition.h"
00035
00036 #include "llviewerwindow.h"
00037 #include "llviewerobjectlist.h"
00038 #include "llvovolume.h"
00039 #include "llviewercamera.h"
00040 #include "llface.h"
00041 #include "llviewercontrol.h"
00042 #include "llagent.h"
00043 #include "llviewerregion.h"
00044 #include "llcamera.h"
00045 #include "pipeline.h"
00046 #include "llglimmediate.h"
00047 #include "lloctree.h"
00048
00049 const F32 SG_OCCLUSION_FUDGE = 1.01f;
00050 #define SG_DISCARD_TOLERANCE 0.01f
00051
00052 #if LL_OCTREE_PARANOIA_CHECK
00053 #define assert_octree_valid(x) x->validate()
00054 #define assert_states_valid(x) ((LLSpatialGroup*) x->mSpatialPartition->mOctree->getListener(0))->checkStates()
00055 #else
00056 #define assert_octree_valid(x)
00057 #define assert_states_valid(x)
00058 #endif
00059
00060
00061 static U32 sZombieGroups = 0;
00062 U32 LLSpatialGroup::sNodeCount = 0;
00063
00064 static F32 sLastMaxTexPriority = 1.f;
00065 static F32 sCurMaxTexPriority = 1.f;
00066
00067 class LLOcclusionQueryPool : public LLGLNamePool
00068 {
00069 protected:
00070 virtual GLuint allocateName()
00071 {
00072 GLuint name;
00073 glGenQueriesARB(1, &name);
00074 return name;
00075 }
00076
00077 virtual void releaseName(GLuint name)
00078 {
00079 glDeleteQueriesARB(1, &name);
00080 }
00081 };
00082
00083 static LLOcclusionQueryPool sQueryPool;
00084
00085 BOOL LLSpatialPartition::sFreezeState = FALSE;
00086
00087
00088
00089 void sg_assert(BOOL expr)
00090 {
00091 #if LL_OCTREE_PARANOIA_CHECK
00092 if (!expr)
00093 {
00094 llerrs << "Octree invalid!" << llendl;
00095 }
00096 #endif
00097 }
00098
00099 #if LL_DEBUG
00100 void validate_drawable(LLDrawable* drawablep)
00101 {
00102 F64 rad = drawablep->getBinRadius();
00103 const LLVector3* ext = drawablep->getSpatialExtents();
00104
00105 if (rad < 0 || rad > 4096 ||
00106 (ext[1]-ext[0]).magVec() > 4096)
00107 {
00108 llwarns << "Invalid drawable found in octree." << llendl;
00109 }
00110 }
00111 #else
00112 #define validate_drawable(x)
00113 #endif
00114
00115
00116 S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad)
00117 {
00118 F32 d = 0.f;
00119 F32 t;
00120 F32 r = rad*rad;
00121
00122 if ((min-origin).magVecSquared() < r &&
00123 (max-origin).magVecSquared() < r)
00124 {
00125 return 2;
00126 }
00127
00128 for (U32 i = 0; i < 3; i++)
00129 {
00130 if (origin.mV[i] < min.mV[i])
00131 {
00132 t = min.mV[i] - origin.mV[i];
00133 d += t*t;
00134 }
00135 else if (origin.mV[i] > max.mV[i])
00136 {
00137 t = origin.mV[i] - max.mV[i];
00138 d += t*t;
00139 }
00140
00141 if (d > r)
00142 {
00143 return 0;
00144 }
00145 }
00146
00147 return 1;
00148 }
00149
00150
00151 typedef enum
00152 {
00153 b000 = 0x00,
00154 b001 = 0x01,
00155 b010 = 0x02,
00156 b011 = 0x03,
00157 b100 = 0x04,
00158 b101 = 0x05,
00159 b110 = 0x06,
00160 b111 = 0x07,
00161 } eLoveTheBits;
00162
00163
00164
00165
00166 static U8 sOcclusionIndices[] =
00167 {
00168
00169 b111, b110, b010, b011, b001, b101, b100, b110,
00170
00171 b110, b000, b010, b011, b111, b101, b100, b000,
00172
00173 b101, b100, b110, b111, b011, b001, b000, b100,
00174
00175 b100, b010, b110, b111, b101, b001, b000, b010,
00176
00177 b011, b010, b000, b001, b101, b111, b110, b010,
00178
00179 b010, b100, b000, b001, b011, b111, b110, b100,
00180
00181 b001, b000, b100, b101, b111, b011, b010, b000,
00182
00183 b000, b110, b100, b101, b001, b011, b010, b110,
00184 };
00185
00186 U8* get_occlusion_indices(LLCamera* camera, const LLVector3& center)
00187 {
00188 LLVector3 d = center - camera->getOrigin();
00189
00190 U8 cypher = 0;
00191 if (d.mV[0] > 0)
00192 {
00193 cypher |= b100;
00194 }
00195 if (d.mV[1] > 0)
00196 {
00197 cypher |= b010;
00198 }
00199 if (d.mV[2] > 0)
00200 {
00201 cypher |= b001;
00202 }
00203
00204 return sOcclusionIndices+cypher*8;
00205 }
00206
00207 void LLSpatialGroup::buildOcclusion()
00208 {
00209 if (!mOcclusionVerts)
00210 {
00211 mOcclusionVerts = new F32[8*3];
00212 }
00213
00214 LLVector3 r = mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.1f,0.1f,0.1f);
00215
00216 for (U32 k = 0; k < 3; k++)
00217 {
00218 r.mV[k] = llmin(mBounds[1].mV[k]+0.25f, r.mV[k]);
00219 }
00220
00221 F32* v = mOcclusionVerts;
00222 F32* c = mBounds[0].mV;
00223 F32* s = r.mV;
00224
00225
00226
00227
00228
00229 v[0] = c[0]-s[0]; v[1] = c[1]-s[1]; v[2] = c[2]-s[2];
00230 v[3] = c[0]-s[0]; v[4] = c[1]-s[1]; v[5] = c[2]+s[2];
00231 v[6] = c[0]-s[0]; v[7] = c[1]+s[1]; v[8] = c[2]-s[2];
00232 v[9] = c[0]-s[0]; v[10] = c[1]+s[1]; v[11] = c[2]+s[2];
00233
00234 v[12] = c[0]+s[0]; v[13] = c[1]-s[1]; v[14] = c[2]-s[2];
00235 v[15] = c[0]+s[0]; v[16] = c[1]-s[1]; v[17] = c[2]+s[2];
00236 v[18] = c[0]+s[0]; v[19] = c[1]+s[1]; v[20] = c[2]-s[2];
00237 v[21] = c[0]+s[0]; v[22] = c[1]+s[1]; v[23] = c[2]+s[2];
00238
00239 clearState(LLSpatialGroup::OCCLUSION_DIRTY);
00240 }
00241
00242
00243 BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group);
00244
00245 BOOL LLLineSegmentAABB(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size)
00246 {
00247 float fAWdU[3];
00248 LLVector3 dir;
00249 LLVector3 diff;
00250
00251 for (U32 i = 0; i < 3; i++)
00252 {
00253 dir.mV[i] = 0.5f * (end.mV[i] - start.mV[i]);
00254 diff.mV[i] = (0.5f * (end.mV[i] + start.mV[i])) - center.mV[i];
00255 fAWdU[i] = fabsf(dir.mV[i]);
00256 if(fabsf(diff.mV[i])>size.mV[i] + fAWdU[i]) return false;
00257 }
00258
00259 float f;
00260 f = dir.mV[1] * diff.mV[2] - dir.mV[2] * diff.mV[1]; if(fabsf(f)>size.mV[1]*fAWdU[2] + size.mV[2]*fAWdU[1]) return false;
00261 f = dir.mV[2] * diff.mV[0] - dir.mV[0] * diff.mV[2]; if(fabsf(f)>size.mV[0]*fAWdU[2] + size.mV[2]*fAWdU[0]) return false;
00262 f = dir.mV[0] * diff.mV[1] - dir.mV[1] * diff.mV[0]; if(fabsf(f)>size.mV[0]*fAWdU[1] + size.mV[1]*fAWdU[0]) return false;
00263
00264 return true;
00265 }
00266
00267
00268
00269
00270
00271
00272 S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3& pos, const F32 &rad)
00273 {
00274 S32 ret = 2;
00275
00276 LLVector3 min = center - size;
00277 LLVector3 max = center + size;
00278 for (U32 i = 0; i < 3; i++)
00279 {
00280 if (min.mV[i] > pos.mV[i] + rad ||
00281 max.mV[i] < pos.mV[i] - rad)
00282 {
00283 return 0;
00284 }
00285
00286 if (min.mV[i] < pos.mV[i] - rad ||
00287 max.mV[i] > pos.mV[i] + rad)
00288 {
00289 ret = 1;
00290 }
00291 }
00292
00293 return ret;
00294 }
00295
00296 LLSpatialGroup::~LLSpatialGroup()
00297 {
00298 if (isState(DEAD))
00299 {
00300 sZombieGroups--;
00301 }
00302
00303 sNodeCount--;
00304
00305 if (gGLManager.mHasOcclusionQuery && mOcclusionQuery)
00306 {
00307 sQueryPool.release(mOcclusionQuery);
00308 }
00309
00310 delete [] mOcclusionVerts;
00311
00312 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
00313 clearDrawMap();
00314 }
00315
00316 void LLSpatialGroup::clearDrawMap()
00317 {
00318 mDrawMap.clear();
00319 }
00320
00321 BOOL LLSpatialGroup::isVisible() const
00322 {
00323 return mVisible == LLDrawable::getCurrentFrame() ? TRUE : FALSE;
00324 }
00325
00326 void LLSpatialGroup::setVisible()
00327 {
00328 if (!LLSpatialPartition::sFreezeState)
00329 {
00330 mVisible = LLDrawable::getCurrentFrame();
00331 }
00332 }
00333
00334 void LLSpatialGroup::validate()
00335 {
00336 #if LL_OCTREE_PARANOIA_CHECK
00337
00338 sg_assert(!isState(DIRTY));
00339 sg_assert(!isDead());
00340
00341 LLVector3 myMin = mBounds[0] - mBounds[1];
00342 LLVector3 myMax = mBounds[0] + mBounds[1];
00343
00344 validateDrawMap();
00345
00346 for (element_iter i = getData().begin(); i != getData().end(); ++i)
00347 {
00348 LLDrawable* drawable = *i;
00349 sg_assert(drawable->getSpatialGroup() == this);
00350 if (drawable->getSpatialBridge())
00351 {
00352 sg_assert(drawable->getSpatialBridge() == mSpatialPartition->asBridge());
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 }
00366
00367 for (U32 i = 0; i < mOctreeNode->getChildCount(); ++i)
00368 {
00369 LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0);
00370
00371 group->validate();
00372
00373
00374 LLVector3 center = group->mBounds[0];
00375 LLVector3 size = group->mBounds[1];
00376
00377 LLVector3 min = center - size;
00378 LLVector3 max = center + size;
00379
00380 for (U32 j = 0; j < 3; j++)
00381 {
00382 sg_assert(min.mV[j] >= myMin.mV[j]-0.02f);
00383 sg_assert(max.mV[j] <= myMax.mV[j]+0.02f);
00384 }
00385 }
00386
00387 #endif
00388 }
00389
00390
00391
00392 class LLOctreeStateCheck : public LLOctreeTraveler<LLDrawable>
00393 {
00394 public:
00395 U32 mInheritedMask;
00396
00397 LLOctreeStateCheck(): mInheritedMask(0) { }
00398
00399 virtual void traverse(const LLSpatialGroup::OctreeNode* node)
00400 {
00401 LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
00402
00403 node->accept(this);
00404
00405 U32 temp = mInheritedMask;
00406 mInheritedMask |= group->getState() &
00407 (LLSpatialGroup::OCCLUDED);
00408
00409 for (U32 i = 0; i < node->getChildCount(); i++)
00410 {
00411 traverse(node->getChild(i));
00412 }
00413
00414 mInheritedMask = temp;
00415 }
00416
00417 virtual void visit(const LLOctreeNode<LLDrawable>* state)
00418 {
00419 LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
00420
00421 if (mInheritedMask && !group->isState(mInheritedMask))
00422 {
00423 llerrs << "Spatial group failed inherited mask test." << llendl;
00424 }
00425
00426 if (group->isState(LLSpatialGroup::DIRTY))
00427 {
00428 assert_parent_state(group, LLSpatialGroup::DIRTY);
00429 }
00430 }
00431
00432 void assert_parent_state(LLSpatialGroup* group, U32 state)
00433 {
00434 LLSpatialGroup* parent = group->getParent();
00435 while (parent)
00436 {
00437 if (!parent->isState(state))
00438 {
00439 llerrs << "Spatial group failed parent state check." << llendl;
00440 }
00441 parent = parent->getParent();
00442 }
00443 }
00444 };
00445
00446
00447 void LLSpatialGroup::checkStates()
00448 {
00449 #if LL_OCTREE_PARANOIA_CHECK
00450 LLOctreeStateCheck checker;
00451 checker.traverse(mOctreeNode);
00452 #endif
00453 }
00454
00455 void validate_draw_info(LLDrawInfo& params)
00456 {
00457 #if LL_OCTREE_PARANOIA_CHECK
00458 if (params.mVertexBuffer.isNull())
00459 {
00460 llerrs << "Draw batch has no vertex buffer." << llendl;
00461 }
00462
00463
00464 if (params.mStart >= params.mEnd)
00465 {
00466 llerrs << "Draw batch has invalid range." << llendl;
00467 }
00468
00469 if (params.mEnd >= (U32) params.mVertexBuffer->getNumVerts())
00470 {
00471 llerrs << "Draw batch has buffer overrun error." << llendl;
00472 }
00473
00474 if (params.mOffset + params.mCount > (U32) params.mVertexBuffer->getNumIndices())
00475 {
00476 llerrs << "Draw batch has index buffer ovverrun error." << llendl;
00477 }
00478
00479
00480 U32* indicesp = (U32*) params.mVertexBuffer->getIndicesPointer();
00481 if (indicesp)
00482 {
00483 for (U32 i = params.mOffset; i < params.mOffset+params.mCount; i++)
00484 {
00485 if (indicesp[i] < params.mStart)
00486 {
00487 llerrs << "Draw batch has vertex buffer index out of range error (index too low)." << llendl;
00488 }
00489
00490 if (indicesp[i] > params.mEnd)
00491 {
00492 llerrs << "Draw batch has vertex buffer index out of range error (index too high)." << llendl;
00493 }
00494 }
00495 }
00496 #endif
00497 }
00498
00499 void LLSpatialGroup::validateDrawMap()
00500 {
00501 #if LL_OCTREE_PARANOIA_CHECK
00502 for (draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i)
00503 {
00504 LLSpatialGroup::drawmap_elem_t& draw_vec = i->second;
00505 for (drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j)
00506 {
00507 LLDrawInfo& params = **j;
00508
00509 validate_draw_info(params);
00510 }
00511 }
00512 #endif
00513 }
00514
00515 BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate)
00516 {
00517 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
00518
00519 drawablep->updateSpatialExtents();
00520 validate_drawable(drawablep);
00521
00522 OctreeNode* parent = mOctreeNode->getOctParent();
00523
00524 if (mOctreeNode->isInside(drawablep->getPositionGroup()) &&
00525 (mOctreeNode->contains(drawablep) ||
00526 (drawablep->getBinRadius() > mOctreeNode->getSize().mdV[0] &&
00527 parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY)))
00528 {
00529 unbound();
00530 setState(OBJECT_DIRTY);
00531
00532 validate_drawable(drawablep);
00533 return TRUE;
00534 }
00535
00536 return FALSE;
00537 }
00538
00539
00540 BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_octree)
00541 {
00542 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
00543 if (!from_octree)
00544 {
00545 mOctreeNode->insert(drawablep);
00546 }
00547 else
00548 {
00549 drawablep->setSpatialGroup(this);
00550 validate_drawable(drawablep);
00551 setState(OBJECT_DIRTY | GEOM_DIRTY | DISCARD_QUERY);
00552 if (drawablep->isSpatialBridge())
00553 {
00554 mBridgeList.push_back((LLSpatialBridge*) drawablep);
00555 }
00556 if (drawablep->getRadius() > 1.f)
00557 {
00558 setState(IMAGE_DIRTY);
00559 }
00560 }
00561
00562 return TRUE;
00563 }
00564
00565 void LLSpatialGroup::rebuildGeom()
00566 {
00567 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
00568 if (!isDead())
00569 {
00570 mSpatialPartition->rebuildGeom(this);
00571 }
00572 }
00573
00574 void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
00575 {
00576 if (group->changeLOD())
00577 {
00578 group->mLastUpdateDistance = group->mDistance;
00579 group->mLastUpdateViewAngle = group->mViewAngle;
00580 }
00581
00582 if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY))
00583 {
00584 return;
00585 }
00586
00587 LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO);
00588
00589 group->clearDrawMap();
00590
00591
00592 U32 index_count = 0;
00593 U32 vertex_count = 0;
00594
00595 addGeometryCount(group, vertex_count, index_count);
00596
00597 if (vertex_count > 0 && index_count > 0)
00598 {
00599 group->mBuilt = 1.f;
00600 if (group->mVertexBuffer.isNull() || (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs))
00601 {
00602 group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage);
00603 group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true);
00604 stop_glerror();
00605 }
00606 else
00607 {
00608 group->mVertexBuffer->resizeBuffer(vertex_count, index_count);
00609 stop_glerror();
00610 }
00611
00612 getGeometry(group);
00613 }
00614 else
00615 {
00616 group->mVertexBuffer = NULL;
00617 group->mBufferMap.clear();
00618 }
00619
00620 group->mLastUpdateTime = gFrameTimeSeconds;
00621 group->clearState(LLSpatialGroup::GEOM_DIRTY);
00622 }
00623
00624 BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxOut)
00625 {
00626 const OctreeNode* node = mOctreeNode;
00627
00628 if (node->getData().empty())
00629 {
00630 if (empty && mOctreeNode->getParent())
00631 {
00632 OCT_ERRS << "Empty leaf found in octree." << llendl;
00633 }
00634 return FALSE;
00635 }
00636
00637 LLVector3& newMin = mObjectExtents[0];
00638 LLVector3& newMax = mObjectExtents[1];
00639
00640 if (isState(OBJECT_DIRTY))
00641 {
00642 clearState(OBJECT_DIRTY);
00643
00644
00645 OctreeNode::const_element_iter i = node->getData().begin();
00646 LLDrawable* drawablep = *i;
00647 const LLVector3* minMax = drawablep->getSpatialExtents();
00648
00649 newMin.setVec(minMax[0]);
00650 newMax.setVec(minMax[1]);
00651
00652 for (++i; i != node->getData().end(); ++i)
00653 {
00654 drawablep = *i;
00655 minMax = drawablep->getSpatialExtents();
00656
00657
00658 for (U32 i = 0; i < 3; i++)
00659 {
00660 if (minMax[0].mV[i] < newMin.mV[i])
00661 {
00662 newMin.mV[i] = minMax[0].mV[i];
00663 }
00664 if (minMax[1].mV[i] > newMax.mV[i])
00665 {
00666 newMax.mV[i] = minMax[1].mV[i];
00667 }
00668 }
00669 }
00670
00671 mObjectBounds[0] = (newMin + newMax) * 0.5f;
00672 mObjectBounds[1] = (newMax - newMin) * 0.5f;
00673 }
00674
00675 if (empty)
00676 {
00677 minOut = newMin;
00678 maxOut = newMax;
00679 }
00680 else
00681 {
00682 for (U32 i = 0; i < 3; i++)
00683 {
00684 if (newMin.mV[i] < minOut.mV[i])
00685 {
00686 minOut.mV[i] = newMin.mV[i];
00687 }
00688 if (newMax.mV[i] > maxOut.mV[i])
00689 {
00690 maxOut.mV[i] = newMax.mV[i];
00691 }
00692 }
00693 }
00694
00695 return TRUE;
00696 }
00697
00698 void LLSpatialGroup::unbound()
00699 {
00700 if (isState(DIRTY))
00701 {
00702 return;
00703 }
00704
00705 setState(DIRTY);
00706
00707
00708 if (mOctreeNode)
00709 {
00710 OctreeNode* parent = (OctreeNode*) mOctreeNode->getParent();
00711 while (parent != NULL)
00712 {
00713 LLSpatialGroup* group = (LLSpatialGroup*) parent->getListener(0);
00714 if (group->isState(DIRTY))
00715 {
00716 return;
00717 }
00718
00719 group->setState(DIRTY);
00720 parent = (OctreeNode*) parent->getParent();
00721 }
00722 }
00723 }
00724
00725 LLSpatialGroup* LLSpatialGroup::getParent()
00726 {
00727 if (isDead())
00728 {
00729 return NULL;
00730 }
00731
00732 OctreeNode* parent = mOctreeNode->getOctParent();
00733
00734 if (parent)
00735 {
00736 return (LLSpatialGroup*) parent->getListener(0);
00737 }
00738
00739 return NULL;
00740 }
00741
00742 BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree)
00743 {
00744 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
00745 unbound();
00746 if (mOctreeNode && !from_octree)
00747 {
00748 if (!mOctreeNode->remove(drawablep))
00749 {
00750 OCT_ERRS << "Could not remove drawable from spatial group" << llendl;
00751 }
00752 }
00753 else
00754 {
00755 drawablep->setSpatialGroup(NULL);
00756 setState(GEOM_DIRTY);
00757 if (drawablep->isSpatialBridge())
00758 {
00759 for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i)
00760 {
00761 if (*i == drawablep)
00762 {
00763 mBridgeList.erase(i);
00764 break;
00765 }
00766 }
00767 }
00768
00769 if (getElementCount() == 0)
00770 {
00771 clearDrawMap();
00772 }
00773 }
00774 return TRUE;
00775 }
00776
00777 void LLSpatialGroup::shift(const LLVector3 &offset)
00778 {
00779 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
00780 LLVector3d offsetd(offset);
00781 mOctreeNode->setCenter(mOctreeNode->getCenter()+offsetd);
00782 mOctreeNode->updateMinMax();
00783 mBounds[0] += offset;
00784 mExtents[0] += offset;
00785 mExtents[1] += offset;
00786 mObjectBounds[0] += offset;
00787 mObjectExtents[0] += offset;
00788 mObjectExtents[1] += offset;
00789
00790 if (!mSpatialPartition->mRenderByGroup)
00791 {
00792 setState(GEOM_DIRTY);
00793 }
00794
00795 if (mOcclusionVerts)
00796 {
00797 for (U32 i = 0; i < 8; i++)
00798 {
00799 F32* v = mOcclusionVerts+i*3;
00800 v[0] += offset.mV[0];
00801 v[1] += offset.mV[1];
00802 v[2] += offset.mV[2];
00803 }
00804 }
00805 }
00806
00807 class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler
00808 {
00809 public:
00810 U32 mState;
00811 LLSpatialSetState(U32 state) : mState(state) { }
00812 virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); }
00813 };
00814
00815 class LLSpatialSetStateDiff : public LLSpatialSetState
00816 {
00817 public:
00818 LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { }
00819
00820 virtual void traverse(const LLSpatialGroup::TreeNode* n)
00821 {
00822 LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
00823
00824 if (!group->isState(mState))
00825 {
00826 LLSpatialGroup::OctreeTraveler::traverse(n);
00827 }
00828 }
00829 };
00830
00831 void LLSpatialGroup::setState(U32 state)
00832 {
00833 if (!LLSpatialPartition::sFreezeState)
00834 {
00835 mState |= state;
00836 }
00837 }
00838
00839 void LLSpatialGroup::setState(U32 state, S32 mode)
00840 {
00841 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
00842 if (LLSpatialPartition::sFreezeState)
00843 {
00844 return;
00845 }
00846
00847 if (mode > STATE_MODE_SINGLE)
00848 {
00849 if (mode == STATE_MODE_DIFF)
00850 {
00851 LLSpatialSetStateDiff setter(state);
00852 setter.traverse(mOctreeNode);
00853 }
00854 else
00855 {
00856 LLSpatialSetState setter(state);
00857 setter.traverse(mOctreeNode);
00858 }
00859 }
00860 else
00861 {
00862 mState |= state;
00863 }
00864 }
00865
00866 class LLSpatialClearState : public LLSpatialGroup::OctreeTraveler
00867 {
00868 public:
00869 U32 mState;
00870 LLSpatialClearState(U32 state) : mState(state) { }
00871 virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); }
00872 };
00873
00874 class LLSpatialClearStateDiff : public LLSpatialClearState
00875 {
00876 public:
00877 LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { }
00878
00879 virtual void traverse(const LLSpatialGroup::TreeNode* n)
00880 {
00881 LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
00882
00883 if (group->isState(mState))
00884 {
00885 LLSpatialGroup::OctreeTraveler::traverse(n);
00886 }
00887 }
00888 };
00889
00890 void LLSpatialGroup::clearState(U32 state)
00891 {
00892 if (!LLSpatialPartition::sFreezeState)
00893 {
00894 mState &= ~state;
00895 }
00896 }
00897
00898 void LLSpatialGroup::clearState(U32 state, S32 mode)
00899 {
00900 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
00901 if (LLSpatialPartition::sFreezeState)
00902 {
00903 return;
00904 }
00905
00906 if (mode > STATE_MODE_SINGLE)
00907 {
00908 if (mode == STATE_MODE_DIFF)
00909 {
00910 LLSpatialClearStateDiff clearer(state);
00911 clearer.traverse(mOctreeNode);
00912 }
00913 else
00914 {
00915 LLSpatialClearState clearer(state);
00916 clearer.traverse(mOctreeNode);
00917 }
00918 }
00919 else
00920 {
00921 mState &= ~state;
00922 }
00923 }
00924
00925
00926
00927
00928
00929 LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
00930 mState(0),
00931 mBuilt(0.f),
00932 mOctreeNode(node),
00933 mSpatialPartition(part),
00934 mVertexBuffer(NULL),
00935 mBufferUsage(GL_STATIC_DRAW_ARB),
00936 mVisible(0),
00937 mDistance(0.f),
00938 mDepth(0.f),
00939 mLastUpdateDistance(-1.f),
00940 mLastUpdateTime(gFrameTimeSeconds),
00941 mViewAngle(0.f),
00942 mLastUpdateViewAngle(-1.f)
00943 {
00944 sNodeCount++;
00945 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
00946
00947 sg_assert(mOctreeNode->getListenerCount() == 0);
00948 mOctreeNode->addListener(this);
00949 setState(SG_INITIAL_STATE_MASK);
00950
00951 mBounds[0] = LLVector3(node->getCenter());
00952 mBounds[1] = LLVector3(node->getSize());
00953
00954 part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod;
00955 mLODHash = part->mLODSeed;
00956
00957 mOcclusionQuery = 0;
00958 mOcclusionVerts = NULL;
00959
00960 mRadius = 1;
00961 mPixelArea = 1024.f;
00962 }
00963
00964 void LLSpatialGroup::updateDistance(LLCamera &camera)
00965 {
00966 #if !LL_RELEASE_FOR_DOWNLOAD
00967 if (isState(LLSpatialGroup::OBJECT_DIRTY))
00968 {
00969 llerrs << "Spatial group dirty on distance update." << llendl;
00970 }
00971 #endif
00972 if (!getData().empty() && !LLSpatialPartition::sFreezeState)
00973 {
00974 mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() :
00975 (F32) mOctreeNode->getSize().magVec();
00976 mDistance = mSpatialPartition->calcDistance(this, camera);
00977 mPixelArea = mSpatialPartition->calcPixelArea(this, camera);
00978 }
00979 }
00980
00981 F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera)
00982 {
00983 LLVector3 eye = group->mObjectBounds[0] - camera.getOrigin();
00984
00985 F32 dist = 0.f;
00986
00987 if (group->mDrawMap.find(LLRenderPass::PASS_ALPHA) != group->mDrawMap.end())
00988 {
00989 LLVector3 v = eye;
00990 dist = eye.normVec();
00991
00992 if (!group->isState(LLSpatialGroup::ALPHA_DIRTY))
00993 {
00994 if (!group->mSpatialPartition->isBridge())
00995 {
00996 LLVector3 view_angle = LLVector3(eye * LLVector3(1,0,0),
00997 eye * LLVector3(0,1,0),
00998 eye * LLVector3(0,0,1));
00999
01000 if ((view_angle-group->mLastUpdateViewAngle).magVec() > 0.64f)
01001 {
01002 group->mViewAngle = view_angle;
01003 group->mLastUpdateViewAngle = view_angle;
01004
01005
01006
01007 group->setState(LLSpatialGroup::ALPHA_DIRTY);
01008 }
01009 }
01010 }
01011
01012
01013
01014 LLVector3 at = camera.getAtAxis();
01015
01016
01017 for (U32 i = 0; i < 3; i++)
01018 {
01019 v.mV[i] -= group->mObjectBounds[1].mV[i]*0.25f * at.mV[i];
01020 }
01021
01022 group->mDepth = v * at;
01023 }
01024 else
01025 {
01026 dist = eye.magVec();
01027 }
01028
01029 if (dist < 16.f)
01030 {
01031 dist /= 16.f;
01032 dist *= dist;
01033 dist *= 16.f;
01034 }
01035
01036 return dist;
01037 }
01038
01039 F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
01040 {
01041 return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera);
01042 }
01043
01044 BOOL LLSpatialGroup::needsUpdate()
01045 {
01046 return (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE;
01047 }
01048
01049 BOOL LLSpatialGroup::changeLOD()
01050 {
01051 if (isState(ALPHA_DIRTY))
01052 {
01053 return TRUE;
01054 }
01055
01056 if (mSpatialPartition->mSlopRatio > 0.f)
01057 {
01058 F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius));
01059
01060 if (fabsf(ratio) >= mSpatialPartition->mSlopRatio)
01061 {
01062 return TRUE;
01063 }
01064
01065 if (mDistance > mRadius)
01066 {
01067 return FALSE;
01068 }
01069 }
01070
01071 if (needsUpdate())
01072 {
01073 return TRUE;
01074 }
01075
01076 return FALSE;
01077 }
01078
01079 void LLSpatialGroup::handleInsertion(const TreeNode* node, LLDrawable* drawablep)
01080 {
01081 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01082 addObject(drawablep, FALSE, TRUE);
01083 unbound();
01084 setState(OBJECT_DIRTY);
01085 }
01086
01087 void LLSpatialGroup::handleRemoval(const TreeNode* node, LLDrawable* drawable)
01088 {
01089 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01090 removeObject(drawable, TRUE);
01091 setState(OBJECT_DIRTY);
01092 }
01093
01094 void LLSpatialGroup::handleDestruction(const TreeNode* node)
01095 {
01096 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01097 setState(DEAD);
01098
01099 for (element_iter i = getData().begin(); i != getData().end(); ++i)
01100 {
01101 LLDrawable* drawable = *i;
01102 if (drawable->getSpatialGroup() == this)
01103 {
01104 drawable->setSpatialGroup(NULL);
01105 }
01106 }
01107
01108 clearDrawMap();
01109 mVertexBuffer = NULL;
01110 mBufferMap.clear();
01111 sZombieGroups++;
01112 mOctreeNode = NULL;
01113 }
01114
01115 void LLSpatialGroup::handleStateChange(const TreeNode* node)
01116 {
01117
01118 if (mOctreeNode != node)
01119 {
01120 mOctreeNode = (OctreeNode*) node;
01121 }
01122 unbound();
01123 }
01124
01125 void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child)
01126 {
01127 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01128 if (child->getListenerCount() == 0)
01129 {
01130 LLSpatialGroup* group = new LLSpatialGroup(child, mSpatialPartition);
01131 group->setState(mState & SG_STATE_INHERIT_MASK);
01132 }
01133 else
01134 {
01135 OCT_ERRS << "LLSpatialGroup redundancy detected." << llendl;
01136 }
01137
01138 unbound();
01139
01140 assert_states_valid(this);
01141 }
01142
01143 void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNode* child)
01144 {
01145 unbound();
01146 }
01147
01148 void LLSpatialGroup::destroyGL()
01149 {
01150 setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY);
01151 mLastUpdateTime = gFrameTimeSeconds;
01152 mVertexBuffer = NULL;
01153 mBufferMap.clear();
01154
01155 mReflectionMap = NULL;
01156 clearDrawMap();
01157
01158 if (mOcclusionQuery)
01159 {
01160 sQueryPool.release(mOcclusionQuery);
01161 mOcclusionQuery = 0;
01162 }
01163
01164 delete [] mOcclusionVerts;
01165 mOcclusionVerts = NULL;
01166
01167 for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i)
01168 {
01169 LLDrawable* drawable = *i;
01170 for (S32 j = 0; j < drawable->getNumFaces(); j++)
01171 {
01172 LLFace* facep = drawable->getFace(j);
01173 facep->mVertexBuffer = NULL;
01174 facep->mLastVertexBuffer = NULL;
01175 }
01176 }
01177 }
01178
01179 BOOL LLSpatialGroup::rebound()
01180 {
01181 if (!isState(DIRTY))
01182 {
01183 return TRUE;
01184 }
01185
01186 if (mOctreeNode->getChildCount() == 1 && mOctreeNode->getElementCount() == 0)
01187 {
01188 LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0);
01189 group->rebound();
01190
01191
01192 mBounds[0] = group->mBounds[0];
01193 mBounds[1] = group->mBounds[1];
01194 mExtents[0] = group->mExtents[0];
01195 mExtents[1] = group->mExtents[1];
01196
01197 group->setState(SKIP_FRUSTUM_CHECK);
01198 }
01199 else if (mOctreeNode->isLeaf())
01200 {
01201 boundObjects(TRUE, mExtents[0], mExtents[1]);
01202 mBounds[0] = mObjectBounds[0];
01203 mBounds[1] = mObjectBounds[1];
01204 }
01205 else
01206 {
01207 LLVector3& newMin = mExtents[0];
01208 LLVector3& newMax = mExtents[1];
01209 LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0);
01210 group->clearState(SKIP_FRUSTUM_CHECK);
01211 group->rebound();
01212
01213 newMin = group->mExtents[0];
01214 newMax = group->mExtents[1];
01215
01216
01217 for (U32 i = 1; i < mOctreeNode->getChildCount(); i++)
01218 {
01219 group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0);
01220 group->clearState(SKIP_FRUSTUM_CHECK);
01221 group->rebound();
01222 const LLVector3& max = group->mExtents[1];
01223 const LLVector3& min = group->mExtents[0];
01224
01225 for (U32 j = 0; j < 3; j++)
01226 {
01227 if (max.mV[j] > newMax.mV[j])
01228 {
01229 newMax.mV[j] = max.mV[j];
01230 }
01231 if (min.mV[j] < newMin.mV[j])
01232 {
01233 newMin.mV[j] = min.mV[j];
01234 }
01235 }
01236 }
01237
01238 boundObjects(FALSE, newMin, newMax);
01239
01240 mBounds[0] = (newMin + newMax)*0.5f;
01241 mBounds[1] = (newMax - newMin)*0.5f;
01242 }
01243
01244 setState(OCCLUSION_DIRTY);
01245
01246 clearState(DIRTY);
01247
01248 return TRUE;
01249 }
01250
01251 void LLSpatialGroup::checkOcclusion()
01252 {
01253 if (LLPipeline::sUseOcclusion > 1)
01254 {
01255 LLSpatialGroup* parent = getParent();
01256 if (parent && parent->isState(LLSpatialGroup::OCCLUDED))
01257 {
01258 clearState(QUERY_PENDING | DISCARD_QUERY);
01259 }
01260 else if (isState(QUERY_PENDING))
01261 {
01262 LLFastTimer t(LLFastTimer::FTM_OCCLUSION_READBACK);
01263 GLuint res = 1;
01264 if (!isState(DISCARD_QUERY) && mOcclusionQuery)
01265 {
01266 glGetQueryObjectuivARB(mOcclusionQuery, GL_QUERY_RESULT_ARB, &res);
01267 }
01268
01269 if (res > 0)
01270 {
01271 assert_states_valid(this);
01272 clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
01273 assert_states_valid(this);
01274 }
01275 else
01276 {
01277 assert_states_valid(this);
01278 setState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
01279 assert_states_valid(this);
01280 }
01281
01282 clearState(QUERY_PENDING | DISCARD_QUERY);
01283 }
01284 else if (mSpatialPartition->mOcclusionEnabled)
01285 {
01286 assert_states_valid(this);
01287 clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
01288 assert_states_valid(this);
01289 }
01290 }
01291 }
01292
01293 void LLSpatialGroup::doOcclusion(LLCamera* camera)
01294 {
01295 if (mSpatialPartition->mOcclusionEnabled && LLPipeline::sUseOcclusion > 1)
01296 {
01297 if (earlyFail(camera, this))
01298 {
01299 setState(LLSpatialGroup::DISCARD_QUERY);
01300 assert_states_valid(this);
01301 clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
01302 assert_states_valid(this);
01303 }
01304 else
01305 {
01306 {
01307 LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION);
01308
01309 if (!mOcclusionQuery)
01310 {
01311 mOcclusionQuery = sQueryPool.allocate();
01312 }
01313
01314 if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY))
01315 {
01316 buildOcclusion();
01317 }
01318
01319 glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery);
01320 glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts);
01321 glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
01322 GL_UNSIGNED_BYTE, get_occlusion_indices(camera, mBounds[0]));
01323 glEndQueryARB(GL_SAMPLES_PASSED_ARB);
01324 }
01325
01326 setState(LLSpatialGroup::QUERY_PENDING);
01327 clearState(LLSpatialGroup::DISCARD_QUERY);
01328 }
01329 }
01330 }
01331
01332
01333
01334 LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage)
01335 {
01336 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01337 mOcclusionEnabled = TRUE;
01338 mDrawableType = 0;
01339 mPartitionType = LLViewerRegion::PARTITION_NONE;
01340 mLODSeed = 0;
01341 mLODPeriod = 1;
01342 mVertexDataMask = data_mask;
01343 mBufferUsage = buffer_usage;
01344 mDepthMask = FALSE;
01345 mSlopRatio = 0.25f;
01346 mRenderByGroup = TRUE;
01347 mImageEnabled = FALSE;
01348 mInfiniteFarClip = FALSE;
01349
01350 LLGLNamePool::registerPool(&sQueryPool);
01351
01352 mOctree = new LLSpatialGroup::OctreeRoot(LLVector3d(0,0,0),
01353 LLVector3d(1,1,1),
01354 NULL);
01355 new LLSpatialGroup(mOctree, this);
01356 }
01357
01358
01359 LLSpatialPartition::~LLSpatialPartition()
01360 {
01361 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01362
01363 delete mOctree;
01364 mOctree = NULL;
01365 }
01366
01367
01368 LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
01369 {
01370 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01371
01372 drawablep->updateSpatialExtents();
01373 validate_drawable(drawablep);
01374
01375
01376 LLPointer<LLDrawable> ptr = drawablep;
01377
01378 assert_octree_valid(mOctree);
01379 mOctree->insert(drawablep);
01380 assert_octree_valid(mOctree);
01381
01382 LLSpatialGroup* group = drawablep->getSpatialGroup();
01383
01384 if (group && was_visible && group->isState(LLSpatialGroup::QUERY_PENDING))
01385 {
01386 group->setState(LLSpatialGroup::DISCARD_QUERY);
01387 }
01388
01389 return group;
01390 }
01391
01392 BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp)
01393 {
01394 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01395
01396 drawablep->setSpatialGroup(NULL);
01397
01398 if (!curp->removeObject(drawablep))
01399 {
01400 OCT_ERRS << "Failed to remove drawable from octree!" << llendl;
01401 }
01402
01403 assert_octree_valid(mOctree);
01404
01405 return TRUE;
01406 }
01407
01408 void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate)
01409 {
01410 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01411
01412
01413
01414 if (!drawablep)
01415 {
01416 OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << llendl;
01417 return;
01418 }
01419
01420 BOOL was_visible = curp ? curp->isVisible() : FALSE;
01421
01422 if (curp && curp->mSpatialPartition != this)
01423 {
01424
01425 LLPointer<LLDrawable> ptr = drawablep;
01426 if (curp->mSpatialPartition->remove(drawablep, curp))
01427 {
01428 put(drawablep, was_visible);
01429 return;
01430 }
01431 else
01432 {
01433 OCT_ERRS << "Drawable lost between spatial partitions on outbound transition." << llendl;
01434 }
01435 }
01436
01437 if (curp && curp->updateInGroup(drawablep, immediate))
01438 {
01439
01440 assert_octree_valid(mOctree);
01441 return;
01442 }
01443
01444
01445 LLPointer<LLDrawable> ptr = drawablep;
01446 if (curp && !remove(drawablep, curp))
01447 {
01448 OCT_ERRS << "Move couldn't find existing spatial group!" << llendl;
01449 }
01450
01451 put(drawablep, was_visible);
01452 }
01453
01454 class LLSpatialShift : public LLSpatialGroup::OctreeTraveler
01455 {
01456 public:
01457 LLSpatialShift(LLVector3 offset) : mOffset(offset) { }
01458 virtual void visit(const LLSpatialGroup::OctreeNode* branch)
01459 {
01460 ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset);
01461 }
01462
01463 LLVector3 mOffset;
01464 };
01465
01466 void LLSpatialPartition::shift(const LLVector3 &offset)
01467 {
01468 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01469 LLSpatialShift shifter(offset);
01470 shifter.traverse(mOctree);
01471 }
01472
01473 class LLOctreeCull : public LLSpatialGroup::OctreeTraveler
01474 {
01475 public:
01476 LLOctreeCull(LLCamera* camera)
01477 : mCamera(camera), mRes(0) { }
01478
01479 virtual bool earlyFail(LLSpatialGroup* group)
01480 {
01481 group->checkOcclusion();
01482
01483 if (group->mOctreeNode->getParent() &&
01484 LLPipeline::sUseOcclusion &&
01485 group->isState(LLSpatialGroup::OCCLUDED))
01486 {
01487 gPipeline.markOccluder(group);
01488 return true;
01489 }
01490
01491 return false;
01492 }
01493
01494 virtual void traverse(const LLSpatialGroup::TreeNode* n)
01495 {
01496 LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
01497
01498 if (earlyFail(group))
01499 {
01500 return;
01501 }
01502
01503 if (mRes == 2 ||
01504 (mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)))
01505 {
01506 LLSpatialGroup::OctreeTraveler::traverse(n);
01507 }
01508 else
01509 {
01510 mRes = frustumCheck(group);
01511
01512 if (mRes)
01513 {
01514 LLSpatialGroup::OctreeTraveler::traverse(n);
01515 }
01516
01517 mRes = 0;
01518 }
01519 }
01520
01521 virtual S32 frustumCheck(const LLSpatialGroup* group)
01522 {
01523 S32 res = mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]);
01524 if (res != 0)
01525 {
01526 res = llmin(res, AABBSphereIntersect(group->mExtents[0], group->mExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist));
01527 }
01528 return res;
01529 }
01530
01531 virtual S32 frustumCheckObjects(const LLSpatialGroup* group)
01532 {
01533 S32 res = mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]);
01534 if (res != 0)
01535 {
01536 res = llmin(res, AABBSphereIntersect(group->mObjectExtents[0], group->mObjectExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist));
01537 }
01538 return res;
01539 }
01540
01541 virtual bool checkObjects(const LLSpatialGroup::OctreeNode* branch, const LLSpatialGroup* group)
01542 {
01543 if (branch->getElementCount() == 0)
01544 {
01545 return false;
01546 }
01547 else if (branch->getChildCount() == 0)
01548 {
01549 return true;
01550 }
01551 else if (mRes == 1 && !frustumCheckObjects(group))
01552 {
01553 return false;
01554 }
01555
01556 return true;
01557 }
01558
01559 virtual void preprocess(LLSpatialGroup* group)
01560 {
01561 if (LLPipeline::sDynamicReflections &&
01562 group->mOctreeNode->getSize().mdV[0] == 16.0 &&
01563 group->mDistance < 64.f)
01564 {
01565 group->mSpatialPartition->markReimage(group);
01566 }
01567 }
01568
01569 virtual void processGroup(LLSpatialGroup* group)
01570 {
01571 if (group->needsUpdate() ||
01572 group->mVisible < LLDrawable::getCurrentFrame() - 1)
01573 {
01574 group->doOcclusion(mCamera);
01575 }
01576 gPipeline.markNotCulled(group, *mCamera);
01577 }
01578
01579 virtual void visit(const LLSpatialGroup::OctreeNode* branch)
01580 {
01581 LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0);
01582
01583 preprocess(group);
01584
01585 if (checkObjects(branch, group))
01586 {
01587 processGroup(group);
01588 }
01589 }
01590
01591 LLCamera *mCamera;
01592 S32 mRes;
01593 };
01594
01595 class LLOctreeCullNoFarClip : public LLOctreeCull
01596 {
01597 public:
01598 LLOctreeCullNoFarClip(LLCamera* camera)
01599 : LLOctreeCull(camera) { }
01600
01601 virtual S32 frustumCheck(const LLSpatialGroup* group)
01602 {
01603 return mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]);
01604 }
01605
01606 virtual S32 frustumCheckObjects(const LLSpatialGroup* group)
01607 {
01608 S32 res = mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]);
01609 return res;
01610 }
01611 };
01612
01613 class LLOctreeSelect : public LLOctreeCull
01614 {
01615 public:
01616 LLOctreeSelect(LLCamera* camera, std::vector<LLDrawable*>* results)
01617 : LLOctreeCull(camera), mResults(results) { }
01618
01619 virtual bool earlyFail(LLSpatialGroup* group) { return false; }
01620 virtual void preprocess(LLSpatialGroup* group) { }
01621
01622 virtual void processGroup(LLSpatialGroup* group)
01623 {
01624 LLSpatialGroup::OctreeNode* branch = group->mOctreeNode;
01625
01626 for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
01627 {
01628 LLDrawable* drawable = *i;
01629
01630 if (!drawable->isDead())
01631 {
01632 if (drawable->isSpatialBridge())
01633 {
01634 drawable->setVisible(*mCamera, mResults, TRUE);
01635 }
01636 else
01637 {
01638 mResults->push_back(drawable);
01639 }
01640 }
01641 }
01642 }
01643
01644 std::vector<LLDrawable*>* mResults;
01645 };
01646
01647 void drawBox(const LLVector3& c, const LLVector3& r)
01648 {
01649 gGL.begin(LLVertexBuffer::TRIANGLE_STRIP);
01650
01651 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV);
01652 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV);
01653
01654 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV);
01655 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV);
01656
01657 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV);
01658 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV);
01659
01660 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV);
01661 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV);
01662
01663 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV);
01664 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV);
01665 gGL.end();
01666
01667
01668 gGL.begin(LLVertexBuffer::TRIANGLE_STRIP);
01669 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV);
01670 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV);
01671 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV);
01672 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV);
01673 gGL.end();
01674
01675
01676 gGL.begin(LLVertexBuffer::TRIANGLE_STRIP);
01677 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV);
01678 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV);
01679 gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV);
01680 gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV);
01681 gGL.end();
01682 }
01683
01684 void drawBoxOutline(const LLVector3& pos, const LLVector3& size)
01685 {
01686 LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1));
01687 LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1));
01688 LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1));
01689 LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1));
01690
01691 gGL.begin(LLVertexBuffer::LINES);
01692
01693
01694 gGL.vertex3fv((pos+v1).mV);
01695 gGL.vertex3fv((pos+v2).mV);
01696 gGL.vertex3fv((pos+v2).mV);
01697 gGL.vertex3fv((pos+v3).mV);
01698 gGL.vertex3fv((pos+v3).mV);
01699 gGL.vertex3fv((pos+v4).mV);
01700 gGL.vertex3fv((pos+v4).mV);
01701 gGL.vertex3fv((pos+v1).mV);
01702
01703
01704 gGL.vertex3fv((pos-v1).mV);
01705 gGL.vertex3fv((pos-v2).mV);
01706 gGL.vertex3fv((pos-v2).mV);
01707 gGL.vertex3fv((pos-v3).mV);
01708 gGL.vertex3fv((pos-v3).mV);
01709 gGL.vertex3fv((pos-v4).mV);
01710 gGL.vertex3fv((pos-v4).mV);
01711 gGL.vertex3fv((pos-v1).mV);
01712
01713
01714 gGL.vertex3fv((pos+v1).mV);
01715 gGL.vertex3fv((pos-v3).mV);
01716
01717 gGL.vertex3fv((pos+v4).mV);
01718 gGL.vertex3fv((pos-v2).mV);
01719
01720
01721 gGL.vertex3fv((pos+v2).mV);
01722 gGL.vertex3fv((pos-v4).mV);
01723
01724 gGL.vertex3fv((pos+v3).mV);
01725 gGL.vertex3fv((pos-v1).mV);
01726
01727 gGL.end();
01728 }
01729
01730 class LLOctreeDirty : public LLOctreeTraveler<LLDrawable>
01731 {
01732 public:
01733 virtual void visit(const LLOctreeNode<LLDrawable>* state)
01734 {
01735 LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
01736 group->destroyGL();
01737
01738 for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
01739 {
01740 LLDrawable* drawable = *i;
01741 if (drawable->getVObj().notNull() && !group->mSpatialPartition->mRenderByGroup)
01742 {
01743 gPipeline.markRebuild(drawable, LLDrawable::REBUILD_ALL, TRUE);
01744 }
01745 }
01746
01747 for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
01748 {
01749 LLSpatialBridge* bridge = *i;
01750 traverse(bridge->mOctree);
01751 }
01752 }
01753 };
01754
01755 void LLSpatialPartition::restoreGL()
01756 {
01757 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01758 }
01759
01760 void LLSpatialPartition::resetVertexBuffers()
01761 {
01762 LLOctreeDirty dirty;
01763 dirty.traverse(mOctree);
01764 }
01765
01766 S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select)
01767 {
01768 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01769 #if LL_OCTREE_PARANOIA_CHECK
01770 ((LLSpatialGroup*)mOctree->getListener(0))->checkStates();
01771 #endif
01772 {
01773 BOOL temp = sFreezeState;
01774 sFreezeState = FALSE;
01775 LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND);
01776 LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
01777 group->rebound();
01778 sFreezeState = temp;
01779 }
01780
01781 #if LL_OCTREE_PARANOIA_CHECK
01782 ((LLSpatialGroup*)mOctree->getListener(0))->validate();
01783 #endif
01784
01785
01786 if (for_select)
01787 {
01788 LLOctreeSelect selecter(&camera, results);
01789 selecter.traverse(mOctree);
01790 }
01791 else if (mInfiniteFarClip || !LLPipeline::sUseFarClip)
01792 {
01793 LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL);
01794 LLOctreeCullNoFarClip culler(&camera);
01795 culler.traverse(mOctree);
01796 }
01797 else
01798 {
01799 LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL);
01800 LLOctreeCull culler(&camera);
01801 culler.traverse(mOctree);
01802 }
01803
01804 return 0;
01805 }
01806
01807 BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group)
01808 {
01809 const F32 vel = (LLViewerCamera::getInstance()->getVelocityStat()->getCurrent()+0.2f);
01810 LLVector3 c = group->mBounds[0];
01811 LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(vel,vel,vel);
01812
01813 if (r.magVecSquared() > 1024.0*1024.0)
01814 {
01815 return TRUE;
01816 }
01817
01818 LLVector3 e = camera->getOrigin();
01819
01820 LLVector3 min = c - r;
01821 LLVector3 max = c + r;
01822
01823 for (U32 j = 0; j < 3; j++)
01824 {
01825 if (e.mV[j] < min.mV[j] || e.mV[j] > max.mV[j])
01826 {
01827 return FALSE;
01828 }
01829 }
01830
01831 return TRUE;
01832 }
01833
01834 void LLSpatialPartition::markReimage(LLSpatialGroup* group)
01835 {
01836 if (mImageEnabled && group->isState(LLSpatialGroup::IMAGE_DIRTY))
01837 {
01838 if (!group->isState(LLSpatialGroup::IN_IMAGE_QUEUE))
01839 {
01840 group->setState(LLSpatialGroup::IN_IMAGE_QUEUE);
01841 mImageQueue.push(group);
01842 }
01843 }
01844 }
01845
01846 void LLSpatialPartition::processImagery(LLCamera* camera)
01847 {
01848 if (!mImageEnabled)
01849 {
01850 return;
01851 }
01852
01853 U32 process_count = 1;
01854
01855 S32 pull_count = (S32) mImageQueue.size();
01856
01857 while (process_count > 0 && pull_count > 0 && !mImageQueue.empty())
01858 {
01859 pull_count--;
01860 LLPointer<LLSpatialGroup> group = mImageQueue.front();
01861 mImageQueue.pop();
01862
01863 if (group->isDead())
01864 {
01865 continue;
01866 }
01867
01868 if (group->isState(LLSpatialGroup::GEOM_DIRTY))
01869 {
01870 mImageQueue.push(group);
01871 continue;
01872 }
01873
01874 group->clearState(LLSpatialGroup::IN_IMAGE_QUEUE);
01875 if (LLPipeline::sDynamicReflections)
01876 {
01877 process_count--;
01878 LLVector3 origin = group->mBounds[0];
01879
01880
01881
01882
01883 LLCamera cube_cam;
01884 cube_cam.setOrigin(origin);
01885 cube_cam.setFar(64.f);
01886
01887 LLPointer<LLCubeMap> cube_map = group->mReflectionMap;
01888 group->mReflectionMap = NULL;
01889 if (cube_map.isNull())
01890 {
01891 cube_map = new LLCubeMap();
01892 cube_map->initGL();
01893 }
01894
01895 gPipeline.generateReflectionMap(gPipeline.mCubeBuffer, cube_cam);
01896 gPipeline.blurReflectionMap(gPipeline.mCubeBuffer, cube_map);
01897 group->mReflectionMap = cube_map;
01898 group->setState(LLSpatialGroup::GEOM_DIRTY);
01899 }
01900
01901 group->clearState(LLSpatialGroup::IMAGE_DIRTY);
01902 }
01903 }
01904
01905 void pushVerts(LLDrawInfo* params, U32 mask)
01906 {
01907 LLRenderPass::applyModelMatrix(*params);
01908 params->mVertexBuffer->setBuffer(mask);
01909 params->mVertexBuffer->drawRange(params->mParticle ? LLVertexBuffer::POINTS : LLVertexBuffer::TRIANGLES,
01910 params->mStart, params->mEnd, params->mCount, params->mOffset);
01911 }
01912
01913 void pushVerts(LLSpatialGroup* group, U32 mask)
01914 {
01915 LLDrawInfo* params = NULL;
01916
01917 for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
01918 {
01919 for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
01920 {
01921 params = *j;
01922 pushVerts(params, mask);
01923 }
01924 }
01925 }
01926
01927 void pushVerts(LLFace* face, U32 mask)
01928 {
01929 LLVertexBuffer* buffer = face->mVertexBuffer;
01930
01931 if (buffer)
01932 {
01933 buffer->setBuffer(mask);
01934 U16 start = face->getGeomStart();
01935 U16 end = start + face->getGeomCount()-1;
01936 U32 count = face->getIndicesCount();
01937 U16 offset = face->getIndicesStart();
01938 buffer->drawRange(LLVertexBuffer::TRIANGLES, start, end, count, offset);
01939 }
01940
01941 }
01942
01943 void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
01944 {
01945 if (buffer)
01946 {
01947 buffer->setBuffer(mask);
01948 buffer->drawRange(LLVertexBuffer::TRIANGLES, 0, buffer->getRequestedVerts()-1, buffer->getRequestedIndices(), 0);
01949 }
01950 }
01951
01952 void pushBufferVerts(LLSpatialGroup* group, U32 mask)
01953 {
01954 if (!group->mDrawMap.empty())
01955 {
01956 LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin());
01957 LLRenderPass::applyModelMatrix(*params);
01958
01959 pushBufferVerts(group->mVertexBuffer, mask);
01960
01961 for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i)
01962 {
01963 for (LLSpatialGroup::buffer_list_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
01964 {
01965 pushBufferVerts(*j, mask);
01966 }
01967 }
01968 }
01969 }
01970
01971 void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)
01972 {
01973 LLDrawInfo* params = NULL;
01974
01975 LLColor4 colors[] = {
01976 LLColor4::green,
01977 LLColor4::green1,
01978 LLColor4::green2,
01979 LLColor4::green3,
01980 LLColor4::green4,
01981 LLColor4::green5,
01982 LLColor4::green6
01983 };
01984
01985 static const U32 col_count = sizeof(colors)/sizeof(LLColor4);
01986
01987 U32 col = 0;
01988
01989 for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
01990 {
01991 for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
01992 {
01993 params = *j;
01994 LLRenderPass::applyModelMatrix(*params);
01995 glColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f);
01996 params->mVertexBuffer->setBuffer(mask);
01997 params->mVertexBuffer->drawRange(params->mParticle ? LLVertexBuffer::POINTS : LLVertexBuffer::TRIANGLES,
01998 params->mStart, params->mEnd, params->mCount, params->mOffset);
01999 col = (col+1)%col_count;
02000 }
02001 }
02002 }
02003
02004 void renderOctree(LLSpatialGroup* group)
02005 {
02006
02007
02008 LLGLDepthTest depth(GL_TRUE, GL_FALSE);
02009 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
02010 LLVector4 col;
02011 if (group->mBuilt > 0.f)
02012 {
02013 group->mBuilt -= 2.f * gFrameIntervalSeconds;
02014 if (group->mBufferUsage == GL_STATIC_DRAW_ARB)
02015 {
02016 col.setVec(1.0f, 0, 0, group->mBuilt*0.5f);
02017 }
02018 else
02019 {
02020 col.setVec(0.1f,0.1f,1,0.1f);
02021
02022 }
02023
02024 if (group->mBufferUsage != GL_STATIC_DRAW_ARB)
02025 {
02026 LLGLDepthTest gl_depth(FALSE, FALSE);
02027 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
02028
02029 gGL.color4f(1,0,0,group->mBuilt);
02030 gGL.flush();
02031 glLineWidth(5.f);
02032 drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
02033 gGL.flush();
02034 glLineWidth(1.f);
02035 gGL.flush();
02036 for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
02037 {
02038 LLDrawable* drawable = *i;
02039 if (!group->mSpatialPartition->isBridge())
02040 {
02041 glPushMatrix();
02042 LLVector3 trans = drawable->getRegion()->getOriginAgent();
02043 glTranslatef(trans.mV[0], trans.mV[1], trans.mV[2]);
02044 }
02045
02046 for (S32 j = 0; j < drawable->getNumFaces(); j++)
02047 {
02048 LLFace* face = drawable->getFace(j);
02049 if (face->mVertexBuffer.notNull())
02050 {
02051 if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f)
02052 {
02053 glColor4f(0, 1, 0, group->mBuilt);
02054 }
02055 else if (gFrameTimeSeconds - face->mLastMoveTime < 0.5f)
02056 {
02057 glColor4f(1, 0, 0, group->mBuilt);
02058 }
02059 else
02060 {
02061 continue;
02062 }
02063
02064 face->mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX);
02065
02066
02067 face->mVertexBuffer->draw(LLVertexBuffer::TRIANGLES, face->getIndicesCount(), face->getIndicesStart());
02068 }
02069 }
02070
02071 if (!group->mSpatialPartition->isBridge())
02072 {
02073 glPopMatrix();
02074 }
02075 }
02076 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
02077 gGL.color4f(1,1,1,1);
02078 }
02079 }
02080 else
02081 {
02082 if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->getData().empty()
02083 && group->mSpatialPartition->mRenderByGroup)
02084 {
02085 col.setVec(0.8f, 0.4f, 0.1f, 0.1f);
02086 }
02087 else
02088 {
02089 col.setVec(0.1f, 0.1f, 1.f, 0.1f);
02090 }
02091 }
02092
02093 gGL.color4fv(col.mV);
02094 drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f));
02095
02096 glDepthMask(GL_TRUE);
02097 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
02098
02099 if (group->mBuilt <= 0.f)
02100 {
02101
02102 gGL.color4f(col.mV[0], col.mV[1], col.mV[2], 1.f);
02103 drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
02104
02105 if (group->mOctreeNode->isLeaf())
02106 {
02107 gGL.color4f(1,1,1,1);
02108 }
02109 else
02110 {
02111 gGL.color4f(0,1,1,1);
02112 }
02113
02114 drawBoxOutline(group->mBounds[0],group->mBounds[1]);
02115 }
02116
02117
02118
02119
02120 }
02121
02122 void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
02123 {
02124 LLGLEnable blend(GL_BLEND);
02125 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
02126 LLGLEnable cull(GL_CULL_FACE);
02127 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
02128
02129 BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
02130 !group->getData().empty();
02131 if (render_objects)
02132 {
02133 LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER);
02134 glColor4f(0, 0.5f, 0, 0.5f);
02135 pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
02136 }
02137
02138 {
02139 LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL);
02140
02141 if (render_objects)
02142 {
02143 glColor4f(0.f, 0.5f, 0.f,1.f);
02144 pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
02145 }
02146
02147 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
02148
02149 if (render_objects)
02150 {
02151 glColor4f(0.f, 0.75f, 0.f,0.5f);
02152 pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
02153 }
02154 else if (camera && group->mOcclusionVerts)
02155 {
02156 LLVertexBuffer::unbind();
02157 glVertexPointer(3, GL_FLOAT, 0, group->mOcclusionVerts);
02158
02159 glColor4f(1.0f, 0.f, 0.f, 0.5f);
02160 glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_occlusion_indices(camera, group->mBounds[0]));
02161 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
02162
02163 glColor4f(1.0f, 1.f, 1.f, 1.0f);
02164 glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_occlusion_indices(camera, group->mBounds[0]));
02165 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
02166 }
02167 }
02168 }
02169
02170 void renderBoundingBox(LLDrawable* drawable)
02171 {
02172 if (drawable->isSpatialBridge())
02173 {
02174 gGL.color4f(1,0.5f,0,1);
02175 }
02176 else if (drawable->getVOVolume())
02177 {
02178 if (drawable->isRoot())
02179 {
02180 gGL.color4f(1,1,0,1);
02181 }
02182 else
02183 {
02184 gGL.color4f(0,1,0,1);
02185 }
02186 }
02187 else if (drawable->getVObj())
02188 {
02189 switch (drawable->getVObj()->getPCode())
02190 {
02191 case LLViewerObject::LL_VO_SURFACE_PATCH:
02192 gGL.color4f(0,1,1,1);
02193 break;
02194 case LLViewerObject::LL_VO_CLOUDS:
02195 gGL.color4f(0.5f,0.5f,0.5f,1.0f);
02196 break;
02197 case LLViewerObject::LL_VO_PART_GROUP:
02198 gGL.color4f(0,0,1,1);
02199 break;
02200 case LLViewerObject::LL_VO_WATER:
02201 gGL.color4f(0,0.5f,1,1);
02202 break;
02203 case LL_PCODE_LEGACY_TREE:
02204 gGL.color4f(0,0.5f,0,1);
02205 default:
02206 gGL.color4f(1,0,1,1);
02207 break;
02208 }
02209 }
02210 else
02211 {
02212 gGL.color4f(1,0,0,1);
02213 }
02214
02215 const LLVector3* ext;
02216 LLVector3 pos, size;
02217
02218
02219 for (S32 i = 0; i < drawable->getNumFaces(); i++)
02220 {
02221 LLFace* facep = drawable->getFace(i);
02222
02223 ext = facep->mExtents;
02224
02225 if (ext[0].isExactlyZero() && ext[1].isExactlyZero())
02226 {
02227 continue;
02228 }
02229 pos = (ext[0] + ext[1]) * 0.5f;
02230 size = (ext[1] - ext[0]) * 0.5f;
02231 drawBoxOutline(pos,size);
02232 }
02233
02234
02235 ext = drawable->getSpatialExtents();
02236
02237 pos = (ext[0] + ext[1]) * 0.5f;
02238 size = (ext[1] - ext[0]) * 0.5f;
02239
02240 LLViewerObject* vobj = drawable->getVObj();
02241 if (vobj && vobj->onActiveList())
02242 {
02243 gGL.flush();
02244 glLineWidth(4.f*sinf(gFrameTimeSeconds*2.f)+1.f);
02245 drawBoxOutline(pos,size);
02246 gGL.flush();
02247 glLineWidth(1.f);
02248 }
02249 else
02250 {
02251 drawBoxOutline(pos,size);
02252 }
02253
02254 }
02255
02256 void renderTexturePriority(LLDrawable* drawable)
02257 {
02258 for (int face=0; face<drawable->getNumFaces(); ++face)
02259 {
02260 LLFace *facep = drawable->getFace(face);
02261
02262 LLVector4 cold(0,0,0.25f);
02263 LLVector4 hot(1,0.25f,0.25f);
02264
02265 LLVector4 boost_cold(0,0,0,0);
02266 LLVector4 boost_hot(0,1,0,1);
02267
02268 LLGLDisable blend(GL_BLEND);
02269
02270
02271
02272 {
02273
02274
02275
02276 F32 vsize = facep->getPixelArea();
02277
02278 if (vsize > sCurMaxTexPriority)
02279 {
02280 sCurMaxTexPriority = vsize;
02281 }
02282
02283 F32 t = vsize/sLastMaxTexPriority;
02284
02285 LLVector4 col = lerp(cold, hot, t);
02286 gGL.color4fv(col.mV);
02287 }
02288
02289
02290
02291
02292
02293 LLVector3 center = (facep->mExtents[1]+facep->mExtents[0])*0.5f;
02294 LLVector3 size = (facep->mExtents[1]-facep->mExtents[0])*0.5f + LLVector3(0.01f, 0.01f, 0.01f);
02295 drawBox(center, size);
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308 }
02309 }
02310
02311 void renderPoints(LLDrawable* drawablep)
02312 {
02313 LLGLDepthTest depth(GL_FALSE, GL_FALSE);
02314 if (drawablep->getNumFaces())
02315 {
02316 gGL.begin(LLVertexBuffer::POINTS);
02317 gGL.color3f(1,1,1);
02318 LLVector3 center(drawablep->getPositionGroup());
02319 for (S32 i = 0; i < drawablep->getNumFaces(); i++)
02320 {
02321 gGL.vertex3fv(drawablep->getFace(i)->mCenterLocal.mV);
02322 }
02323 gGL.end();
02324 }
02325 }
02326
02327 void renderTextureAnim(LLDrawInfo* params)
02328 {
02329 if (!params->mTextureMatrix)
02330 {
02331 return;
02332 }
02333
02334 LLGLEnable blend(GL_BLEND);
02335 gGL.color4f(1,1,0,0.5f);
02336 pushVerts(params, LLVertexBuffer::MAP_VERTEX);
02337 }
02338
02339 void renderBatchSize(LLDrawInfo* params)
02340 {
02341 glColor3ubv((GLubyte*) &(params->mDebugColor));
02342 pushVerts(params, LLVertexBuffer::MAP_VERTEX);
02343 }
02344
02345 void renderLights(LLDrawable* drawablep)
02346 {
02347 if (!drawablep->isLight())
02348 {
02349 return;
02350 }
02351
02352 if (drawablep->getNumFaces())
02353 {
02354 LLGLEnable blend(GL_BLEND);
02355 glColor4f(0,1,1,0.5f);
02356
02357 for (S32 i = 0; i < drawablep->getNumFaces(); i++)
02358 {
02359 pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX);
02360 }
02361
02362 const LLVector3* ext = drawablep->getSpatialExtents();
02363
02364 LLVector3 pos = (ext[0] + ext[1]) * 0.5f;
02365 LLVector3 size = (ext[1] - ext[0]) * 0.5f;
02366
02367 {
02368 LLGLDepthTest depth(GL_FALSE, GL_TRUE);
02369 gGL.color4f(1,1,1,1);
02370 drawBoxOutline(pos, size);
02371 }
02372
02373 gGL.color4f(1,1,0,1);
02374 F32 rad = drawablep->getVOVolume()->getLightRadius();
02375 drawBoxOutline(pos, LLVector3(rad,rad,rad));
02376 }
02377 }
02378
02379 class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable>
02380 {
02381 public:
02382 LLCamera* mCamera;
02383 LLOctreeRenderNonOccluded(LLCamera* camera): mCamera(camera) {}
02384
02385 virtual void traverse(const LLSpatialGroup::OctreeNode* node)
02386 {
02387 LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
02388
02389 if (!mCamera || mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]))
02390 {
02391 node->accept(this);
02392
02393 for (U32 i = 0; i < node->getChildCount(); i++)
02394 {
02395 traverse(node->getChild(i));
02396 }
02397
02398
02399 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE))
02400 {
02401 renderOctree(group);
02402 }
02403
02404
02405 if (group->mSpatialPartition->mRenderByGroup &&
02406 gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
02407 {
02408 gGL.flush();
02409 glPushMatrix();
02410 gGLLastMatrix = NULL;
02411 glLoadMatrixd(gGLModelView);
02412 renderVisibility(group, mCamera);
02413 gGLLastMatrix = NULL;
02414 glPopMatrix();
02415 gGL.color4f(1,1,1,1);
02416 }
02417 }
02418 }
02419
02420 virtual void visit(const LLSpatialGroup::OctreeNode* branch)
02421 {
02422 LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0);
02423
02424 if (group->isState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1])))
02425 {
02426 return;
02427 }
02428
02429 LLVector3 nodeCenter = group->mBounds[0];
02430 LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter());
02431
02432 for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
02433 {
02434 LLDrawable* drawable = *i;
02435
02436 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES))
02437 {
02438 renderBoundingBox(drawable);
02439 }
02440
02441 if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
02442 {
02443 renderTexturePriority(drawable);
02444 }
02445
02446 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_POINTS))
02447 {
02448 renderPoints(drawable);
02449 }
02450
02451 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LIGHTS))
02452 {
02453 renderLights(drawable);
02454 }
02455 }
02456
02457 for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
02458 {
02459 LLSpatialGroup::drawmap_elem_t& draw_vec = i->second;
02460 for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j)
02461 {
02462 LLDrawInfo* draw_info = *j;
02463 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_ANIM))
02464 {
02465 renderTextureAnim(draw_info);
02466 }
02467 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BATCH_SIZE))
02468 {
02469 renderBatchSize(draw_info);
02470 }
02471 }
02472 }
02473 }
02474 };
02475
02476 void LLSpatialPartition::renderDebug()
02477 {
02478 if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE |
02479 LLPipeline::RENDER_DEBUG_OCCLUSION |
02480 LLPipeline::RENDER_DEBUG_LIGHTS |
02481 LLPipeline::RENDER_DEBUG_BATCH_SIZE |
02482 LLPipeline::RENDER_DEBUG_BBOXES |
02483 LLPipeline::RENDER_DEBUG_POINTS |
02484 LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY |
02485 LLPipeline::RENDER_DEBUG_TEXTURE_ANIM))
02486 {
02487 return;
02488 }
02489
02490 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
02491 {
02492
02493 sLastMaxTexPriority = (F32) LLViewerCamera::getInstance()->getScreenPixelArea();
02494 sCurMaxTexPriority = 0.f;
02495 }
02496
02497 LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
02498
02499 LLGLDisable cullface(GL_CULL_FACE);
02500 LLGLEnable blend(GL_BLEND);
02501 gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
02502 LLImageGL::unbindTexture(0);
02503 gPipeline.disableLights();
02504
02505 LLSpatialBridge* bridge = asBridge();
02506 LLCamera* camera = LLViewerCamera::getInstance();
02507
02508 if (bridge)
02509 {
02510 camera = NULL;
02511 }
02512
02513 LLOctreeStateCheck checker;
02514 checker.traverse(mOctree);
02515
02516 LLOctreeRenderNonOccluded render_debug(camera);
02517 render_debug.traverse(mOctree);
02518 }
02519
02520
02521 BOOL LLSpatialPartition::isVisible(const LLVector3& v)
02522 {
02523 if (!LLViewerCamera::getInstance()->sphereInFrustum(v, 4.0f))
02524 {
02525 return FALSE;
02526 }
02527
02528 return TRUE;
02529 }
02530
02531 class LLOctreePick : public LLSpatialGroup::OctreeTraveler
02532 {
02533 public:
02534 LLVector3 mStart;
02535 LLVector3 mEnd;
02536 LLDrawable* mRet;
02537
02538 LLOctreePick(LLVector3 start, LLVector3 end)
02539 : mStart(start), mEnd(end)
02540 {
02541 mRet = NULL;
02542 }
02543
02544 virtual LLDrawable* check(const LLSpatialGroup::OctreeNode* node)
02545 {
02546 node->accept(this);
02547
02548 for (U32 i = 0; i < node->getChildCount(); i++)
02549 {
02550 const LLSpatialGroup::OctreeNode* child = node->getChild(i);
02551 LLVector3 res;
02552
02553 LLSpatialGroup* group = (LLSpatialGroup*) child->getListener(0);
02554
02555 LLVector3 size;
02556 LLVector3 center;
02557
02558 size = group->mBounds[1];
02559 center = group->mBounds[0];
02560
02561 if (LLLineSegmentAABB(mStart, mEnd, center, size))
02562 {
02563 check(child);
02564 }
02565 }
02566
02567 return mRet;
02568 }
02569
02570 virtual void visit(const LLSpatialGroup::OctreeNode* branch)
02571 {
02572 for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
02573 {
02574 check(*i);
02575 }
02576 }
02577
02578 virtual bool check(LLDrawable* drawable)
02579 {
02580 LLViewerObject* vobj = drawable->getVObj();
02581 if (vobj->lineSegmentIntersect(mStart, mEnd))
02582 {
02583 mRet = vobj->mDrawable;
02584 }
02585
02586 return false;
02587 }
02588 };
02589
02590 LLDrawable* LLSpatialPartition::pickDrawable(const LLVector3& start, const LLVector3& end, LLVector3& collision)
02591 {
02592 LLOctreePick pick(start, end);
02593 LLDrawable* ret = pick.check(mOctree);
02594 collision.setVec(pick.mEnd);
02595 return ret;
02596 }
02597
02598 LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
02599 LLViewerImage* texture, LLVertexBuffer* buffer,
02600 BOOL fullbright, U8 bump, BOOL particle, F32 part_size)
02601 :
02602 mVertexBuffer(buffer),
02603 mTexture(texture),
02604 mTextureMatrix(NULL),
02605 mModelMatrix(NULL),
02606 mStart(start),
02607 mEnd(end),
02608 mCount(count),
02609 mOffset(offset),
02610 mFullbright(fullbright),
02611 mBump(bump),
02612 mParticle(particle),
02613 mPartSize(part_size),
02614 mVSize(0.f),
02615 mGroup(NULL)
02616 {
02617 mDebugColor = (rand() << 16) + rand();
02618 }
02619
02620 LLDrawInfo::~LLDrawInfo()
02621 {
02622
02623 }
02624
02625 LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage)
02626 {
02627 return new LLVertexBuffer(type_mask, usage);
02628 }
02629
02630 LLCullResult::LLCullResult()
02631 {
02632 clear();
02633 }
02634
02635 void LLCullResult::clear()
02636 {
02637 mVisibleGroupsSize = 0;
02638 mAlphaGroupsSize = 0;
02639 mOcclusionGroupsSize = 0;
02640 mDrawableGroupsSize = 0;
02641 mVisibleListSize = 0;
02642 mVisibleBridgeSize = 0;
02643
02644 for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++)
02645 {
02646 for (U32 j = 0; j < mRenderMapSize[i]; j++)
02647 {
02648 mRenderMap[i][j] = 0;
02649 }
02650 mRenderMapSize[i] = 0;
02651 }
02652 }
02653
02654 LLCullResult::sg_list_t::iterator LLCullResult::beginVisibleGroups()
02655 {
02656 return mVisibleGroups.begin();
02657 }
02658
02659 LLCullResult::sg_list_t::iterator LLCullResult::endVisibleGroups()
02660 {
02661 return mVisibleGroups.begin() + mVisibleGroupsSize;
02662 }
02663
02664 LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups()
02665 {
02666 return mAlphaGroups.begin();
02667 }
02668
02669 LLCullResult::sg_list_t::iterator LLCullResult::endAlphaGroups()
02670 {
02671 return mAlphaGroups.begin() + mAlphaGroupsSize;
02672 }
02673
02674 LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups()
02675 {
02676 return mOcclusionGroups.begin();
02677 }
02678
02679 LLCullResult::sg_list_t::iterator LLCullResult::endOcclusionGroups()
02680 {
02681 return mOcclusionGroups.begin() + mOcclusionGroupsSize;
02682 }
02683
02684 LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups()
02685 {
02686 return mDrawableGroups.begin();
02687 }
02688
02689 LLCullResult::sg_list_t::iterator LLCullResult::endDrawableGroups()
02690 {
02691 return mDrawableGroups.begin() + mDrawableGroupsSize;
02692 }
02693
02694 LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList()
02695 {
02696 return mVisibleList.begin();
02697 }
02698
02699 LLCullResult::drawable_list_t::iterator LLCullResult::endVisibleList()
02700 {
02701 return mVisibleList.begin() + mVisibleListSize;
02702 }
02703
02704 LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge()
02705 {
02706 return mVisibleBridge.begin();
02707 }
02708
02709 LLCullResult::bridge_list_t::iterator LLCullResult::endVisibleBridge()
02710 {
02711 return mVisibleBridge.begin() + mVisibleBridgeSize;
02712 }
02713
02714 LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type)
02715 {
02716 return mRenderMap[type].begin();
02717 }
02718
02719 LLCullResult::drawinfo_list_t::iterator LLCullResult::endRenderMap(U32 type)
02720 {
02721 return mRenderMap[type].begin() + mRenderMapSize[type];
02722 }
02723
02724 void LLCullResult::pushVisibleGroup(LLSpatialGroup* group)
02725 {
02726 if (mVisibleGroupsSize < mVisibleGroups.size())
02727 {
02728 mVisibleGroups[mVisibleGroupsSize] = group;
02729 }
02730 else
02731 {
02732 mVisibleGroups.push_back(group);
02733 }
02734 ++mVisibleGroupsSize;
02735 }
02736
02737 void LLCullResult::pushAlphaGroup(LLSpatialGroup* group)
02738 {
02739 if (mAlphaGroupsSize < mAlphaGroups.size())
02740 {
02741 mAlphaGroups[mAlphaGroupsSize] = group;
02742 }
02743 else
02744 {
02745 mAlphaGroups.push_back(group);
02746 }
02747 ++mAlphaGroupsSize;
02748 }
02749
02750 void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group)
02751 {
02752 if (mOcclusionGroupsSize < mOcclusionGroups.size())
02753 {
02754 mOcclusionGroups[mOcclusionGroupsSize] = group;
02755 }
02756 else
02757 {
02758 mOcclusionGroups.push_back(group);
02759 }
02760 ++mOcclusionGroupsSize;
02761 }
02762
02763 void LLCullResult::pushDrawableGroup(LLSpatialGroup* group)
02764 {
02765 if (mDrawableGroupsSize < mDrawableGroups.size())
02766 {
02767 mDrawableGroups[mDrawableGroupsSize] = group;
02768 }
02769 else
02770 {
02771 mDrawableGroups.push_back(group);
02772 }
02773 ++mDrawableGroupsSize;
02774 }
02775
02776 void LLCullResult::pushDrawable(LLDrawable* drawable)
02777 {
02778 if (mVisibleListSize < mVisibleList.size())
02779 {
02780 mVisibleList[mVisibleListSize] = drawable;
02781 }
02782 else
02783 {
02784 mVisibleList.push_back(drawable);
02785 }
02786 ++mVisibleListSize;
02787 }
02788
02789 void LLCullResult::pushBridge(LLSpatialBridge* bridge)
02790 {
02791 if (mVisibleBridgeSize < mVisibleBridge.size())
02792 {
02793 mVisibleBridge[mVisibleBridgeSize] = bridge;
02794 }
02795 else
02796 {
02797 mVisibleBridge.push_back(bridge);
02798 }
02799 ++mVisibleBridgeSize;
02800 }
02801
02802 void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info)
02803 {
02804 if (mRenderMapSize[type] < mRenderMap[type].size())
02805 {
02806 mRenderMap[type][mRenderMapSize[type]] = draw_info;
02807 }
02808 else
02809 {
02810 mRenderMap[type].push_back(draw_info);
02811 }
02812 ++mRenderMapSize[type];
02813 }
02814
02815
02816
02817
02818
02819