llspatialpartition.cpp

Go to the documentation of this file.
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 //static counter for frame to switch LOD on
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 //contact Runitai Linden for a copy of the SL object used to write this table
00164 //basically, you give the table a bitmask of the look-at vector to a node and it
00165 //gives you a triangle fan index array
00166 static U8 sOcclusionIndices[] =
00167 {
00168          // 000
00169                 b111, b110, b010, b011, b001, b101, b100, b110,
00170         //001 
00171                 b110, b000, b010, b011, b111, b101, b100, b000,
00172          //010
00173                 b101, b100, b110, b111, b011, b001, b000, b100,
00174          //011 
00175                 b100, b010, b110, b111, b101, b001, b000, b010,
00176         //100 
00177                 b011, b010, b000, b001, b101, b111, b110, b010,
00178          //101 
00179                 b010, b100, b000, b001, b011, b111, b110, b100,
00180          //110
00181                 b001, b000, b100, b101, b111, b011, b010, b000,
00182          //111
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         //vertex positions are encoded so the 3 bits of their vertex index 
00226         //correspond to their axis facing, with bit position 3,2,1 matching
00227         //axis facing x,y,z, bit set meaning positive facing, bit clear 
00228         //meaning negative facing
00229         v[0] = c[0]-s[0]; v[1]  = c[1]-s[1]; v[2]  = c[2]-s[2];  // 0 - 0000 
00230         v[3] = c[0]-s[0]; v[4]  = c[1]-s[1]; v[5]  = c[2]+s[2];  // 1 - 0001
00231         v[6] = c[0]-s[0]; v[7]  = c[1]+s[1]; v[8]  = c[2]-s[2];  // 2 - 0010
00232         v[9] = c[0]-s[0]; v[10] = c[1]+s[1]; v[11] = c[2]+s[2];  // 3 - 0011
00233                                                                                                                                                                            
00234         v[12] = c[0]+s[0]; v[13] = c[1]-s[1]; v[14] = c[2]-s[2]; // 4 - 0100
00235         v[15] = c[0]+s[0]; v[16] = c[1]-s[1]; v[17] = c[2]+s[2]; // 5 - 0101
00236         v[18] = c[0]+s[0]; v[19] = c[1]+s[1]; v[20] = c[2]-s[2]; // 6 - 0110
00237         v[21] = c[0]+s[0]; v[22] = c[1]+s[1]; v[23] = c[2]+s[2]; // 7 - 0111
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 //returns:
00268 //      0 if sphere and AABB are not intersecting 
00269 //      1 if they are
00270 //      2 if AABB is entirely inside sphere
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                 {       //totally outside
00283                         return 0;
00284                 }
00285                 
00286                 if (min.mV[i] < pos.mV[i] - rad ||
00287                         max.mV[i] > pos.mV[i] + rad)
00288                 {       //intersecting
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                 /*if (drawable->isSpatialBridge())
00356                 {
00357                         LLSpatialPartition* part = drawable->asPartition();
00358                         if (!part)
00359                         {
00360                                 llerrs << "Drawable reports it is a spatial bridge but not a partition." << llendl;
00361                         }
00362                         LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0);
00363                         group->validate();
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                 //ensure all children are enclosed in this node
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         //bad range
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         //bad indices
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                 //setState(GEOM_DIRTY);
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         //get geometry count
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         { //create vertex buffer containing volume geometry for this node
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         {       //don't do anything if there are no objects
00630                 if (empty && mOctreeNode->getParent())
00631                 {       //only root is allowed to be empty
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         { //calculate new bounding box
00642                 clearState(OBJECT_DIRTY);
00643 
00644                 //initialize bounding box to first element
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                         //bin up the object
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         //all the parent nodes need to rebound this child
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                 { //delete draw map on last element removal since a rebuild might never happen
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 //              Octree Listener Implementation
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                                         //for occasional alpha sorting within the group
01005                                         //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order,
01006                                         //not setting this node to dirty would be a very good thing
01007                                         group->setState(LLSpatialGroup::ALPHA_DIRTY);
01008                                 }
01009                         }
01010                 }
01011 
01012                 //calculate depth of node for alpha sorting
01013 
01014                 LLVector3 at = camera.getAtAxis();
01015 
01016                 //front of bounding box
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         //drop bounding box upon state change
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         {       //return TRUE if we're not empty
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                 //copy single child's bounding box
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         { //copy object bounding box if this is a leaf
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                 //initialize to first child
01213                 newMin = group->mExtents[0];
01214                 newMax = group->mExtents[1];
01215 
01216                 //first, rebound children
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                 {       //if the parent has been marked as occluded, the child is implicitly occluded
01258                         clearState(QUERY_PENDING | DISCARD_QUERY);
01259                 }
01260                 else if (isState(QUERY_PENDING))
01261                 {       //otherwise, if a query is pending, read it back
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         //keep drawable from being garbage collected
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         // sanity check submitted by open source user bushing Spatula
01413         // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne)
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                 //keep drawable from being garbage collected
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                 // Already updated, don't need to do anything
01440                 assert_octree_valid(mOctree);
01441                 return;
01442         }
01443 
01444         //keep drawable from being garbage collected
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 { //shift octree node bounding boxes by offset
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() &&  //never occlusion cull the root node
01484                         LLPipeline::sUseOcclusion &&                    //ignore occlusion if disabled
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                 {       //fully in, just add everything
01506                         LLSpatialGroup::OctreeTraveler::traverse(n);
01507                 }
01508                 else
01509                 {
01510                         mRes = frustumCheck(group);
01511                                 
01512                         if (mRes)
01513                         { //at least partially in, run on down
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) //no elements
01544                 {
01545                         return false;
01546                 }
01547                 else if (branch->getChildCount() == 0) //leaf state, already checked tightest bounding box
01548                 {
01549                         return true;
01550                 }
01551                 else if (mRes == 1 && !frustumCheckObjects(group)) //no objects in frustum
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         //left front
01651         gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV);
01652         gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV);
01653         //right front
01654         gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV);
01655         gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV);
01656         //right back
01657         gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV);
01658         gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV);
01659         //left back
01660         gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV);
01661         gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV);
01662         //left front
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         //bottom
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         //top
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         //top
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         //bottom
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         //right
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         //left
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                 { //put it back
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                         /*LLVector3 at = camera->getOrigin()-origin;
01880                         at.normVec();
01881                         origin += at* (at * group->mBounds[1]);*/
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         //render solid object bounding box, color
02007         //coded by buffer usage and activity
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                         //col.setVec(1.0f, 1.0f, 0, sinf(group->mBuilt*3.14159f)*0.5f);
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                                                 //drawBox((face->mExtents[0] + face->mExtents[1])*0.5f,
02066                                                 //              (face->mExtents[1]-face->mExtents[0])*0.5f);
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                 //draw opaque outline
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 //      LLSpatialGroup::OctreeNode* node = group->mOctreeNode;
02118 //      gGL.color4f(0,1,0,1);
02119 //      drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize()));
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         //render face bounding boxes
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         //render drawable bounding box
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                 //LLViewerImage* imagep = facep->getTexture();
02271                 //if (imagep)
02272                 {
02273         
02274                         //F32 vsize = LLVOVolume::getTextureVirtualSize(facep);
02275                         //F32 vsize = imagep->mMaxVirtualSize;
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                 //else
02289                 //{
02290                 //      gGL.color4f(1,0,1,1);
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                 /*S32 boost = imagep->getBoostLevel();
02298                 if (boost)
02299                 {
02300                         F32 t = (F32) boost / (F32) (LLViewerImage::BOOST_MAX_LEVEL-1);
02301                         LLVector4 col = lerp(boost_cold, boost_hot, t);
02302                         LLGLEnable blend_on(GL_BLEND);
02303                         gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
02304                         gGL.color4fv(col.mV);
02305                         drawBox(center, size);
02306                         gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
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                         //draw tight fit bounding boxes for spatial group
02399                         if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE))
02400                         {       
02401                                 renderOctree(group);
02402                         }
02403 
02404                         //render visibility wireframe
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                 //sLastMaxTexPriority = lerp(sLastMaxTexPriority, sCurMaxTexPriority, gFrameIntervalSeconds);
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 

Generated on Fri May 16 08:34:01 2008 for SecondLife by  doxygen 1.5.5