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