diff options
Diffstat (limited to 'indra/newview/llspatialpartition.cpp')
-rw-r--r-- | indra/newview/llspatialpartition.cpp | 2125 |
1 files changed, 1021 insertions, 1104 deletions
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index abb8d973aa..84e14ef341 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -43,25 +43,47 @@ #include "llviewerregion.h" #include "llcamera.h" #include "pipeline.h" - -static GLuint sBoxList = 0; +#include "llglimmediate.h" +#include "lloctree.h" const F32 SG_OCCLUSION_FUDGE = 1.01f; -//const S32 SG_LOD_PERIOD = 16; - -#define SG_DISCARD_TOLERANCE 0.25f +#define SG_DISCARD_TOLERANCE 0.01f #if LL_OCTREE_PARANOIA_CHECK #define assert_octree_valid(x) x->validate() +#define assert_states_valid(x) ((LLSpatialGroup*) x->mSpatialPartition->mOctree->getListener(0))->checkStates() #else #define assert_octree_valid(x) +#define assert_states_valid(x) #endif + static U32 sZombieGroups = 0; +U32 LLSpatialGroup::sNodeCount = 0; static F32 sLastMaxTexPriority = 1.f; static F32 sCurMaxTexPriority = 1.f; +class LLOcclusionQueryPool : public LLGLNamePool +{ +protected: + virtual GLuint allocateName() + { + GLuint name; + glGenQueriesARB(1, &name); + return name; + } + + virtual void releaseName(GLuint name) + { + glDeleteQueriesARB(1, &name); + } +}; + +static LLOcclusionQueryPool sQueryPool; + +BOOL LLSpatialPartition::sFreezeState = FALSE; + //static counter for frame to switch LOD on void sg_assert(BOOL expr) @@ -90,6 +112,134 @@ void validate_drawable(LLDrawable* drawablep) #define validate_drawable(x) #endif + +S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad) +{ + F32 d = 0.f; + F32 t; + F32 r = rad*rad; + + if ((min-origin).magVecSquared() < r && + (max-origin).magVecSquared() < r) + { + return 2; + } + + for (U32 i = 0; i < 3; i++) + { + if (origin.mV[i] < min.mV[i]) + { + t = min.mV[i] - origin.mV[i]; + d += t*t; + } + else if (origin.mV[i] > max.mV[i]) + { + t = origin.mV[i] - max.mV[i]; + d += t*t; + } + + if (d > r) + { + return 0; + } + } + + return 1; +} + + +typedef enum +{ + b000 = 0x00, + b001 = 0x01, + b010 = 0x02, + b011 = 0x03, + b100 = 0x04, + b101 = 0x05, + b110 = 0x06, + b111 = 0x07, +} eLoveTheBits; + +//contact Runitai Linden for a copy of the SL object used to write this table +//basically, you give the table a bitmask of the look-at vector to a node and it +//gives you a triangle fan index array +static U8 sOcclusionIndices[] = +{ + // 000 + b111, b110, b010, b011, b001, b101, b100, b110, + //001 + b110, b000, b010, b011, b111, b101, b100, b000, + //010 + b101, b100, b110, b111, b011, b001, b000, b100, + //011 + b100, b010, b110, b111, b101, b001, b000, b010, + //100 + b011, b010, b000, b001, b101, b111, b110, b010, + //101 + b010, b100, b000, b001, b011, b111, b110, b100, + //110 + b001, b000, b100, b101, b111, b011, b010, b000, + //111 + b000, b110, b100, b101, b001, b011, b010, b110, +}; + +U8* get_occlusion_indices(LLCamera* camera, const LLVector3& center) +{ + LLVector3 d = center - camera->getOrigin(); + + U8 cypher = 0; + if (d.mV[0] > 0) + { + cypher |= b100; + } + if (d.mV[1] > 0) + { + cypher |= b010; + } + if (d.mV[2] > 0) + { + cypher |= b001; + } + + return sOcclusionIndices+cypher*8; +} + +void LLSpatialGroup::buildOcclusion() +{ + if (!mOcclusionVerts) + { + mOcclusionVerts = new F32[8*3]; + } + + LLVector3 r = mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.1f,0.1f,0.1f); + + for (U32 k = 0; k < 3; k++) + { + r.mV[k] = llmin(mBounds[1].mV[k]+0.25f, r.mV[k]); + } + + F32* v = mOcclusionVerts; + F32* c = mBounds[0].mV; + F32* s = r.mV; + + //vertex positions are encoded so the 3 bits of their vertex index + //correspond to their axis facing, with bit position 3,2,1 matching + //axis facing x,y,z, bit set meaning positive facing, bit clear + //meaning negative facing + v[0] = c[0]-s[0]; v[1] = c[1]-s[1]; v[2] = c[2]-s[2]; // 0 - 0000 + v[3] = c[0]-s[0]; v[4] = c[1]-s[1]; v[5] = c[2]+s[2]; // 1 - 0001 + v[6] = c[0]-s[0]; v[7] = c[1]+s[1]; v[8] = c[2]-s[2]; // 2 - 0010 + v[9] = c[0]-s[0]; v[10] = c[1]+s[1]; v[11] = c[2]+s[2]; // 3 - 0011 + + v[12] = c[0]+s[0]; v[13] = c[1]-s[1]; v[14] = c[2]-s[2]; // 4 - 0100 + v[15] = c[0]+s[0]; v[16] = c[1]-s[1]; v[17] = c[2]+s[2]; // 5 - 0101 + v[18] = c[0]+s[0]; v[19] = c[1]+s[1]; v[20] = c[2]-s[2]; // 6 - 0110 + v[21] = c[0]+s[0]; v[22] = c[1]+s[1]; v[23] = c[2]+s[2]; // 7 - 0111 + + clearState(LLSpatialGroup::OCCLUSION_DIRTY); +} + + BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group); BOOL LLLineSegmentAABB(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size) @@ -150,6 +300,15 @@ LLSpatialGroup::~LLSpatialGroup() sZombieGroups--; } + sNodeCount--; + + if (gGLManager.mHasOcclusionQuery && mOcclusionQuery) + { + sQueryPool.release(mOcclusionQuery); + } + + delete [] mOcclusionVerts; + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); clearDrawMap(); } @@ -159,55 +318,16 @@ void LLSpatialGroup::clearDrawMap() mDrawMap.clear(); } -class LLRelightPainter : public LLSpatialGroup::OctreeTraveler +BOOL LLSpatialGroup::isVisible() const { -public: - LLVector3 mOrigin, mDir; - F32 mRadius; - - LLRelightPainter(LLVector3 origin, LLVector3 dir, F32 radius) - : mOrigin(origin), mDir(dir), mRadius(radius) - { } - - virtual void traverse(const LLSpatialGroup::TreeNode* n) - { - LLSpatialGroup::OctreeNode* node = (LLSpatialGroup::OctreeNode*) n; - - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - group->setState(LLSpatialGroup::RESHADOW); - - for (U32 i = 0; i < node->getChildCount(); i++) - { - const LLSpatialGroup::OctreeNode* child = node->getChild(i); - LLSpatialGroup* group = (LLSpatialGroup*) child->getListener(0); - - LLVector3 res; - - LLVector3 center, size; - - center = group->mBounds[0]; - size = group->mBounds[1]; - - if (child->isInside(LLVector3d(mOrigin)) || LLRayAABB(center, size, mOrigin, mDir, res, mRadius)) - { - traverse(child); - } - } - } - - virtual void visit(const LLSpatialGroup::OctreeState* branch) { } - -}; + return mVisible == LLDrawable::getCurrentFrame() ? TRUE : FALSE; +} -BOOL LLSpatialGroup::isVisible() +void LLSpatialGroup::setVisible() { - if (LLPipeline::sUseOcclusion) - { - return !isState(CULLED | OCCLUDED); - } - else + if (!LLSpatialPartition::sFreezeState) { - return !isState(CULLED); + mVisible = LLDrawable::getCurrentFrame(); } } @@ -232,7 +352,7 @@ void LLSpatialGroup::validate() sg_assert(drawable->getSpatialBridge() == mSpatialPartition->asBridge()); } - if (drawable->isSpatialBridge()) + /*if (drawable->isSpatialBridge()) { LLSpatialPartition* part = drawable->asPartition(); if (!part) @@ -241,7 +361,7 @@ void LLSpatialGroup::validate() } LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); group->validate(); - } + }*/ } for (U32 i = 0; i < mOctreeNode->getChildCount(); ++i) @@ -267,6 +387,71 @@ void LLSpatialGroup::validate() #endif } + + +class LLOctreeStateCheck : public LLOctreeTraveler<LLDrawable> +{ +public: + U32 mInheritedMask; + + LLOctreeStateCheck(): mInheritedMask(0) { } + + virtual void traverse(const LLSpatialGroup::OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + node->accept(this); + + U32 temp = mInheritedMask; + mInheritedMask |= group->getState() & + (LLSpatialGroup::OCCLUDED); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + } + + mInheritedMask = temp; + } + + virtual void visit(const LLOctreeNode<LLDrawable>* state) + { + LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); + + if (mInheritedMask && !group->isState(mInheritedMask)) + { + llerrs << "Spatial group failed inherited mask test." << llendl; + } + + if (group->isState(LLSpatialGroup::DIRTY)) + { + assert_parent_state(group, LLSpatialGroup::DIRTY); + } + } + + void assert_parent_state(LLSpatialGroup* group, U32 state) + { + LLSpatialGroup* parent = group->getParent(); + while (parent) + { + if (!parent->isState(state)) + { + llerrs << "Spatial group failed parent state check." << llendl; + } + parent = parent->getParent(); + } + } +}; + + +void LLSpatialGroup::checkStates() +{ +#if LL_OCTREE_PARANOIA_CHECK + LLOctreeStateCheck checker; + checker.traverse(mOctreeNode); +#endif +} + void validate_draw_info(LLDrawInfo& params) { #if LL_OCTREE_PARANOIA_CHECK @@ -316,8 +501,8 @@ void LLSpatialGroup::validateDrawMap() #if LL_OCTREE_PARANOIA_CHECK for (draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i) { - std::vector<LLDrawInfo*>& draw_vec = i->second; - for (std::vector<LLDrawInfo*>::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) + LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; + for (drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) { LLDrawInfo& params = **j; @@ -327,32 +512,6 @@ void LLSpatialGroup::validateDrawMap() #endif } -void LLSpatialGroup::makeStatic() -{ -#if !LL_DARWIN - if (isState(GEOM_DIRTY | ALPHA_DIRTY)) - { - return; - } - - if (mSpatialPartition->mRenderByGroup && mBufferUsage != GL_STATIC_DRAW_ARB) - { - mBufferUsage = GL_STATIC_DRAW_ARB; - if (mVertexBuffer.notNull()) - { - mVertexBuffer->makeStatic(); - } - - for (buffer_map_t::iterator i = mBufferMap.begin(); i != mBufferMap.end(); ++i) - { - i->second->makeStatic(); - } - - mBuilt = 1.f; - } -#endif -} - BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -369,7 +528,7 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) { unbound(); setState(OBJECT_DIRTY); - setState(GEOM_DIRTY); + //setState(GEOM_DIRTY); validate_drawable(drawablep); return TRUE; } @@ -389,8 +548,7 @@ BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_oc { drawablep->setSpatialGroup(this); validate_drawable(drawablep); - setState(OBJECT_DIRTY | GEOM_DIRTY); - mLastAddTime = gFrameTimeSeconds; + setState(OBJECT_DIRTY | GEOM_DIRTY | DISCARD_QUERY); if (drawablep->isSpatialBridge()) { mBridgeList.push_back((LLSpatialBridge*) drawablep); @@ -431,32 +589,27 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) group->clearDrawMap(); //get geometry count - group->mIndexCount = 0; - group->mVertexCount = 0; - - addGeometryCount(group, group->mVertexCount, group->mIndexCount); + U32 index_count = 0; + U32 vertex_count = 0; + + addGeometryCount(group, vertex_count, index_count); - if (group->mVertexCount > 0 && group->mIndexCount > 0) + if (vertex_count > 0 && index_count > 0) { //create vertex buffer containing volume geometry for this node group->mBuilt = 1.f; if (group->mVertexBuffer.isNull() || (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) { - //LLFastTimer ftm(LLFastTimer::FTM_REBUILD_NONE_VB); group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); - group->mVertexBuffer->allocateBuffer(group->mVertexCount, group->mIndexCount, true); + group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true); stop_glerror(); } else { - //LLFastTimer ftm(LLFastTimer::FTM_REBUILD_NONE_VB); - group->mVertexBuffer->resizeBuffer(group->mVertexCount, group->mIndexCount); + group->mVertexBuffer->resizeBuffer(vertex_count, index_count); stop_glerror(); } - { - LLFastTimer ftm((LLFastTimer::EFastTimerType) ((U32) LLFastTimer::FTM_REBUILD_VOLUME_VB + mPartitionType)); - getGeometry(group); - } + getGeometry(group); } else { @@ -465,12 +618,12 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) } group->mLastUpdateTime = gFrameTimeSeconds; - group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MATRIX_DIRTY); + group->clearState(LLSpatialGroup::GEOM_DIRTY); } BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxOut) { - const OctreeState* node = mOctreeNode->getOctState(); + const OctreeNode* node = mOctreeNode; if (node->getData().empty()) { //don't do anything if there are no objects @@ -489,7 +642,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO clearState(OBJECT_DIRTY); //initialize bounding box to first element - OctreeState::const_element_iter i = node->getData().begin(); + OctreeNode::const_element_iter i = node->getData().begin(); LLDrawable* drawablep = *i; const LLVector3* minMax = drawablep->getSpatialExtents(); @@ -612,6 +765,11 @@ BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) } } } + + if (getElementCount() == 0) + { //delete draw map on last element removal since a rebuild might never happen + clearDrawMap(); + } } return TRUE; } @@ -629,7 +787,21 @@ void LLSpatialGroup::shift(const LLVector3 &offset) mObjectExtents[0] += offset; mObjectExtents[1] += offset; - setState(GEOM_DIRTY | MATRIX_DIRTY | OCCLUSION_DIRTY); + if (!mSpatialPartition->mRenderByGroup) + { + setState(GEOM_DIRTY); + } + + if (mOcclusionVerts) + { + for (U32 i = 0; i < 8; i++) + { + F32* v = mOcclusionVerts+i*3; + v[0] += offset.mV[0]; + v[1] += offset.mV[1]; + v[2] += offset.mV[2]; + } + } } class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler @@ -637,7 +809,7 @@ class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler public: U32 mState; LLSpatialSetState(U32 state) : mState(state) { } - virtual void visit(const LLSpatialGroup::OctreeState* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); } + virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); } }; class LLSpatialSetStateDiff : public LLSpatialSetState @@ -656,9 +828,22 @@ public: } }; +void LLSpatialGroup::setState(U32 state) +{ + if (!LLSpatialPartition::sFreezeState) + { + mState |= state; + } +} + void LLSpatialGroup::setState(U32 state, S32 mode) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + if (LLSpatialPartition::sFreezeState) + { + return; + } + if (mode > STATE_MODE_SINGLE) { if (mode == STATE_MODE_DIFF) @@ -683,7 +868,7 @@ class LLSpatialClearState : public LLSpatialGroup::OctreeTraveler public: U32 mState; LLSpatialClearState(U32 state) : mState(state) { } - virtual void visit(const LLSpatialGroup::OctreeState* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); } + virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); } }; class LLSpatialClearStateDiff : public LLSpatialClearState @@ -695,17 +880,29 @@ public: { LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - if (!group->isState(mState)) + if (group->isState(mState)) { LLSpatialGroup::OctreeTraveler::traverse(n); } } }; +void LLSpatialGroup::clearState(U32 state) +{ + if (!LLSpatialPartition::sFreezeState) + { + mState &= ~state; + } +} void LLSpatialGroup::clearState(U32 state, S32 mode) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + if (LLSpatialPartition::sFreezeState) + { + return; + } + if (mode > STATE_MODE_SINGLE) { if (mode == STATE_MODE_DIFF) @@ -723,20 +920,6 @@ void LLSpatialGroup::clearState(U32 state, S32 mode) { mState &= ~state; } - -#if LL_OCTREE_PARANOIA_CHECK - if (state & LLSpatialGroup::ACTIVE_OCCLUSION) - { - LLSpatialPartition* part = mSpatialPartition; - for (U32 i = 0; i < part->mOccludedList.size(); i++) - { - if (part->mOccludedList[i] == this) - { - llerrs << "LLSpatialGroup state error: " << mState << llendl; - } - } - } -#endif } //====================================== @@ -750,15 +933,15 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mSpatialPartition(part), mVertexBuffer(NULL), mBufferUsage(GL_STATIC_DRAW_ARB), + mVisible(0), mDistance(0.f), mDepth(0.f), mLastUpdateDistance(-1.f), mLastUpdateTime(gFrameTimeSeconds), - mLastAddTime(gFrameTimeSeconds), - mLastRenderTime(gFrameTimeSeconds), mViewAngle(0.f), mLastUpdateViewAngle(-1.f) { + sNodeCount++; LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); sg_assert(mOctreeNode->getListenerCount() == 0); @@ -771,6 +954,9 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod; mLODHash = part->mLODSeed; + mOcclusionQuery = 0; + mOcclusionVerts = NULL; + mRadius = 1; mPixelArea = 1024.f; } @@ -783,7 +969,7 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) llerrs << "Spatial group dirty on distance update." << llendl; } #endif - if (!getData().empty()) + if (!getData().empty() && !LLSpatialPartition::sFreezeState) { mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() : (F32) mOctreeNode->getSize().magVec(); @@ -805,19 +991,22 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) if (!group->isState(LLSpatialGroup::ALPHA_DIRTY)) { - LLVector3 view_angle = LLVector3(eye * LLVector3(1,0,0), - eye * LLVector3(0,1,0), - eye * LLVector3(0,0,1)); - - if ((view_angle-group->mLastUpdateViewAngle).magVec() > 0.64f) + if (!group->mSpatialPartition->isBridge()) { - group->mViewAngle = view_angle; - group->mLastUpdateViewAngle = view_angle; - //for occasional alpha sorting within the group - //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order, - //not setting this node to dirty would be a very good thing - group->setState(LLSpatialGroup::ALPHA_DIRTY); - } + LLVector3 view_angle = LLVector3(eye * LLVector3(1,0,0), + eye * LLVector3(0,1,0), + eye * LLVector3(0,0,1)); + + if ((view_angle-group->mLastUpdateViewAngle).magVec() > 0.64f) + { + group->mViewAngle = view_angle; + group->mLastUpdateViewAngle = view_angle; + //for occasional alpha sorting within the group + //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order, + //not setting this node to dirty would be a very good thing + group->setState(LLSpatialGroup::ALPHA_DIRTY); + } + } } //calculate depth of node for alpha sorting @@ -831,17 +1020,6 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) } group->mDepth = v * at; - - F32 water_height = gAgent.getRegion()->getWaterHeight(); - //figure out if this node is above or below water - if (group->mObjectBounds[0].mV[2] < water_height) - { - group->setState(LLSpatialGroup::BELOW_WATER); - } - else - { - group->clearState(LLSpatialGroup::BELOW_WATER); - } } else { @@ -863,6 +1041,11 @@ F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera) return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera); } +BOOL LLSpatialGroup::needsUpdate() +{ + return (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE; +} + BOOL LLSpatialGroup::changeLOD() { if (isState(ALPHA_DIRTY)) @@ -885,7 +1068,7 @@ BOOL LLSpatialGroup::changeLOD() } } - if (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) + if (needsUpdate()) { return TRUE; } @@ -923,7 +1106,6 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) } clearDrawMap(); - mOcclusionVerts = NULL; mVertexBuffer = NULL; mBufferMap.clear(); sZombieGroups++; @@ -954,6 +1136,8 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c } unbound(); + + assert_states_valid(this); } void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNode* child) @@ -963,17 +1147,23 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo void LLSpatialGroup::destroyGL() { - setState(LLSpatialGroup::GEOM_DIRTY | - LLSpatialGroup::OCCLUSION_DIRTY | - LLSpatialGroup::IMAGE_DIRTY); + setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); mLastUpdateTime = gFrameTimeSeconds; mVertexBuffer = NULL; mBufferMap.clear(); - mOcclusionVerts = NULL; mReflectionMap = NULL; clearDrawMap(); + if (mOcclusionQuery) + { + sQueryPool.release(mOcclusionQuery); + mOcclusionQuery = 0; + } + + delete [] mOcclusionVerts; + mOcclusionVerts = NULL; + for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i) { LLDrawable* drawable = *i; @@ -993,15 +1183,6 @@ BOOL LLSpatialGroup::rebound() return TRUE; } - LLVector3 oldBounds[2]; - - if (mSpatialPartition->isVolatile() && isState(QUERY_OUT)) - { //a query has been issued, if our bounding box changes significantly - //we need to discard the issued query - oldBounds[0] = mBounds[0]; - oldBounds[1] = mBounds[1]; - } - if (mOctreeNode->getChildCount() == 1 && mOctreeNode->getElementCount() == 0) { LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0); @@ -1015,7 +1196,7 @@ BOOL LLSpatialGroup::rebound() group->setState(SKIP_FRUSTUM_CHECK); } - else if (mOctreeNode->hasLeafState()) + else if (mOctreeNode->isLeaf()) { //copy object bounding box if this is a leaf boundObjects(TRUE, mExtents[0], mExtents[1]); mBounds[0] = mObjectBounds[0]; @@ -1060,19 +1241,6 @@ BOOL LLSpatialGroup::rebound() mBounds[1] = (newMax - newMin)*0.5f; } - if (mSpatialPartition->isVolatile() && isState(QUERY_OUT)) - { - for (U32 i = 0; i < 3 && !isState(DISCARD_QUERY); i++) - { - if (fabsf(mBounds[0].mV[i]-oldBounds[0].mV[i]) > SG_DISCARD_TOLERANCE || - fabsf(mBounds[1].mV[i]-oldBounds[1].mV[i]) > SG_DISCARD_TOLERANCE) - { //bounding box changed significantly, discard last issued - //occlusion query - setState(DISCARD_QUERY); - } - } - } - setState(OCCLUSION_DIRTY); clearState(DIRTY); @@ -1080,14 +1248,95 @@ BOOL LLSpatialGroup::rebound() return TRUE; } +void LLSpatialGroup::checkOcclusion() +{ + if (LLPipeline::sUseOcclusion > 1) + { + LLSpatialGroup* parent = getParent(); + if (parent && parent->isState(LLSpatialGroup::OCCLUDED)) + { //if the parent has been marked as occluded, the child is implicitly occluded + clearState(QUERY_PENDING | DISCARD_QUERY); + } + else if (isState(QUERY_PENDING)) + { //otherwise, if a query is pending, read it back + LLFastTimer t(LLFastTimer::FTM_OCCLUSION_READBACK); + GLuint res = 1; + if (!isState(DISCARD_QUERY) && mOcclusionQuery) + { + glGetQueryObjectuivARB(mOcclusionQuery, GL_QUERY_RESULT_ARB, &res); + } + + if (res > 0) + { + assert_states_valid(this); + clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + assert_states_valid(this); + } + else + { + assert_states_valid(this); + setState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + assert_states_valid(this); + } + + clearState(QUERY_PENDING | DISCARD_QUERY); + } + else if (mSpatialPartition->mOcclusionEnabled) + { + assert_states_valid(this); + clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + assert_states_valid(this); + } + } +} + +void LLSpatialGroup::doOcclusion(LLCamera* camera) +{ + if (mSpatialPartition->mOcclusionEnabled && LLPipeline::sUseOcclusion > 1) + { + if (earlyFail(camera, this)) + { + setState(LLSpatialGroup::DISCARD_QUERY); + assert_states_valid(this); + clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + assert_states_valid(this); + } + else + { + { + LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION); + + if (!mOcclusionQuery) + { + mOcclusionQuery = sQueryPool.allocate(); + } + + if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY)) + { + buildOcclusion(); + } + + glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery); + glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, get_occlusion_indices(camera, mBounds[0])); + glEndQueryARB(GL_SAMPLES_PASSED_ARB); + } + + setState(LLSpatialGroup::QUERY_PENDING); + clearState(LLSpatialGroup::DISCARD_QUERY); + } + } +} + //============================================== -LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL is_volatile, U32 buffer_usage) +LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + mOcclusionEnabled = TRUE; mDrawableType = 0; - mPartitionType = LLPipeline::PARTITION_NONE; - mVolatile = is_volatile; + mPartitionType = LLViewerRegion::PARTITION_NONE; mLODSeed = 0; mLODPeriod = 1; mVertexDataMask = data_mask; @@ -1096,10 +1345,13 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL is_volatile, U32 buff mSlopRatio = 0.25f; mRenderByGroup = TRUE; mImageEnabled = FALSE; + mInfiniteFarClip = FALSE; + + LLGLNamePool::registerPool(&sQueryPool); - mOctree = new LLSpatialGroup::OctreeNode(LLVector3d(0,0,0), + mOctree = new LLSpatialGroup::OctreeRoot(LLVector3d(0,0,0), LLVector3d(1,1,1), - new LLSpatialGroup::OctreeRoot(), NULL); + NULL); new LLSpatialGroup(mOctree, this); } @@ -1108,11 +1360,6 @@ LLSpatialPartition::~LLSpatialPartition() { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - for (U32 i = 0; i < mOcclusionQueries.size(); i++) - { - glDeleteQueriesARB(1, (GLuint*)(&(mOcclusionQueries[i]))); - } - delete mOctree; mOctree = NULL; } @@ -1121,22 +1368,6 @@ LLSpatialPartition::~LLSpatialPartition() LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - const F32 MAX_MAG = 1000000.f*1000000.f; // 1 million - - if (drawablep->getPositionGroup().magVecSquared() > MAX_MAG) - { -#if 0 //ndef LL_RELEASE_FOR_DOWNLOAD - llwarns << "LLSpatialPartition::put Object out of range!" << llendl; - llinfos << drawablep->getPositionGroup() << llendl; - - if (drawablep->getVObj()) - { - llwarns << "Dumping debugging info: " << llendl; - drawablep->getVObj()->dump(); - } -#endif - return NULL; - } drawablep->updateSpatialExtents(); validate_drawable(drawablep); @@ -1147,11 +1378,10 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) assert_octree_valid(mOctree); mOctree->insert(drawablep); assert_octree_valid(mOctree); - - LLSpatialGroup::OctreeNode* node = mOctree->getNodeAt(drawablep); - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - if (was_visible && group->isState(LLSpatialGroup::QUERY_OUT)) + LLSpatialGroup* group = drawablep->getSpatialGroup(); + + if (group && was_visible && group->isState(LLSpatialGroup::QUERY_PENDING)) { group->setState(LLSpatialGroup::DISCARD_QUERY); } @@ -1178,11 +1408,11 @@ BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE); - + // sanity check submitted by open source user bushing Spatula // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne) - if (!drawablep) { + if (!drawablep) + { OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << llendl; return; } @@ -1225,7 +1455,7 @@ class LLSpatialShift : public LLSpatialGroup::OctreeTraveler { public: LLSpatialShift(LLVector3 offset) : mOffset(offset) { } - virtual void visit(const LLSpatialGroup::OctreeState* branch) + virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset); } @@ -1234,39 +1464,27 @@ public: }; void LLSpatialPartition::shift(const LLVector3 &offset) -{ +{ //shift octree node bounding boxes by offset LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - llinfos << "Shifting octree: " << offset << llendl; LLSpatialShift shifter(offset); shifter.traverse(mOctree); } -BOOL LLSpatialPartition::checkOcclusion(LLSpatialGroup* group, LLCamera* camera) -{ - if (LLPipeline::sUseOcclusion && - !group->isState(LLSpatialGroup::ACTIVE_OCCLUSION | LLSpatialGroup::OCCLUDED) && - (!camera || !earlyFail(camera, group))) - { - group->setState(LLSpatialGroup::ACTIVE_OCCLUSION); - mQueryQueue.push(group); - return TRUE; - } - - return FALSE; -} - class LLOctreeCull : public LLSpatialGroup::OctreeTraveler { public: LLOctreeCull(LLCamera* camera) : mCamera(camera), mRes(0) { } - virtual bool earlyFail(const LLSpatialGroup* group) + virtual bool earlyFail(LLSpatialGroup* group) { + group->checkOcclusion(); + if (group->mOctreeNode->getParent() && //never occlusion cull the root node - LLPipeline::sUseOcclusion && //never occlusion cull selection + LLPipeline::sUseOcclusion && //ignore occlusion if disabled group->isState(LLSpatialGroup::OCCLUDED)) { + gPipeline.markOccluder(group); return true; } @@ -1289,31 +1507,39 @@ public: } else { - mRes = mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1]); + mRes = frustumCheck(group); if (mRes) { //at least partially in, run on down LLSpatialGroup::OctreeTraveler::traverse(n); } - else - { - lateFail(group); - } + mRes = 0; } } - virtual void lateFail(LLSpatialGroup* group) + virtual S32 frustumCheck(const LLSpatialGroup* group) { - if (!group->isState(LLSpatialGroup::CULLED)) - { //totally culled, so are all its children - group->setState(LLSpatialGroup::CULLED, LLSpatialGroup::STATE_MODE_DIFF); + S32 res = mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]); + if (res != 0) + { + res = llmin(res, AABBSphereIntersect(group->mExtents[0], group->mExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist)); } + return res; } - virtual bool checkObjects(const LLSpatialGroup::OctreeState* branch, const LLSpatialGroup* group) + virtual S32 frustumCheckObjects(const LLSpatialGroup* group) + { + S32 res = mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]); + if (res != 0) + { + res = llmin(res, AABBSphereIntersect(group->mObjectExtents[0], group->mObjectExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist)); + } + return res; + } + + virtual bool checkObjects(const LLSpatialGroup::OctreeNode* branch, const LLSpatialGroup* group) { - if (branch->getElementCount() == 0) //no elements { return false; @@ -1322,7 +1548,7 @@ public: { return true; } - else if (mRes == 1 && !mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1])) //no objects in frustum + else if (mRes == 1 && !frustumCheckObjects(group)) //no objects in frustum { return false; } @@ -1332,20 +1558,9 @@ public: virtual void preprocess(LLSpatialGroup* group) { - if (group->isState(LLSpatialGroup::CULLED)) - { //this is the first frame this node is visible - group->clearState(LLSpatialGroup::CULLED); - if (group->mOctreeNode->hasLeafState()) - { //if it's a leaf, force it onto the active occlusion list to prevent - //massive frame stutters - group->mSpatialPartition->checkOcclusion(group, mCamera); - } - } - if (LLPipeline::sDynamicReflections && group->mOctreeNode->getSize().mdV[0] == 16.0 && - group->mDistance < 64.f && - group->mLastAddTime < gFrameTimeSeconds - 2.f) + group->mDistance < 64.f) { group->mSpatialPartition->markReimage(group); } @@ -1353,10 +1568,15 @@ public: virtual void processGroup(LLSpatialGroup* group) { + if (group->needsUpdate() || + group->mVisible < LLDrawable::getCurrentFrame() - 1) + { + group->doOcclusion(mCamera); + } gPipeline.markNotCulled(group, *mCamera); } - virtual void visit(const LLSpatialGroup::OctreeState* branch) + virtual void visit(const LLSpatialGroup::OctreeNode* branch) { LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); @@ -1372,6 +1592,17 @@ public: S32 mRes; }; +class LLOctreeCullNoFarClip : public LLOctreeCull +{ +public: + LLOctreeCullNoFarClip(LLCamera* camera) + : LLOctreeCull(camera) { } + + virtual S32 frustumCheck(const LLSpatialGroup* group) + { + return mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]); + } +}; class LLOctreeSelect : public LLOctreeCull { @@ -1379,15 +1610,14 @@ public: LLOctreeSelect(LLCamera* camera, std::vector<LLDrawable*>* results) : LLOctreeCull(camera), mResults(results) { } - virtual bool earlyFail(const LLSpatialGroup* group) { return false; } - virtual void lateFail(LLSpatialGroup* group) { } + virtual bool earlyFail(LLSpatialGroup* group) { return false; } virtual void preprocess(LLSpatialGroup* group) { } virtual void processGroup(LLSpatialGroup* group) { - LLSpatialGroup::OctreeState* branch = group->mOctreeNode->getOctState(); + LLSpatialGroup::OctreeNode* branch = group->mOctreeNode; - for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) { LLDrawable* drawable = *i; @@ -1408,67 +1638,41 @@ public: std::vector<LLDrawable*>* mResults; }; - -void genBoxList() +void drawBox(const LLVector3& c, const LLVector3& r) { - if (sBoxList != 0) - { - return; - } - - sBoxList = glGenLists(1); - glNewList(sBoxList, GL_COMPILE); - - LLVector3 c,r; - c = LLVector3(0,0,0); - r = LLVector3(1,1,1); - - glBegin(GL_TRIANGLE_STRIP); + gGL.begin(GL_TRIANGLE_STRIP); //left front - glVertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); - glVertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); //right front - glVertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); - glVertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); //right back - glVertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); - glVertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); //left back - glVertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); - glVertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); //left front - glVertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); - glVertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); - glEnd(); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); + gGL.end(); //bottom - glBegin(GL_TRIANGLE_STRIP); - glVertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); - glVertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); - glVertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); - glVertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); - glEnd(); + gGL.begin(GL_TRIANGLE_STRIP); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV); + gGL.end(); //top - glBegin(GL_TRIANGLE_STRIP); - glVertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); - glVertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); - glVertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); - glVertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); - glEnd(); - - glEndList(); -} - -void drawBox(const LLVector3& c, const LLVector3& r) -{ - genBoxList(); - - glPushMatrix(); - glTranslatef(c.mV[0], c.mV[1], c.mV[2]); - glScalef(r.mV[0], r.mV[1], r.mV[2]); - glCallList(sBoxList); - glPopMatrix(); + gGL.begin(GL_TRIANGLE_STRIP); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV); + gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV); + gGL.end(); } void drawBoxOutline(const LLVector3& pos, const LLVector3& size) @@ -1478,44 +1682,49 @@ void drawBoxOutline(const LLVector3& pos, const LLVector3& size) LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1)); LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1)); - glBegin(GL_LINE_LOOP); //top - glVertex3fv((pos+v1).mV); - glVertex3fv((pos+v2).mV); - glVertex3fv((pos+v3).mV); - glVertex3fv((pos+v4).mV); - glEnd(); - - glBegin(GL_LINE_LOOP); //bottom - glVertex3fv((pos-v1).mV); - glVertex3fv((pos-v2).mV); - glVertex3fv((pos-v3).mV); - glVertex3fv((pos-v4).mV); - glEnd(); - - - glBegin(GL_LINES); - + gGL.begin(GL_LINES); + + //top + gGL.vertex3fv((pos+v1).mV); + gGL.vertex3fv((pos+v2).mV); + gGL.vertex3fv((pos+v2).mV); + gGL.vertex3fv((pos+v3).mV); + gGL.vertex3fv((pos+v3).mV); + gGL.vertex3fv((pos+v4).mV); + gGL.vertex3fv((pos+v4).mV); + gGL.vertex3fv((pos+v1).mV); + + //bottom + gGL.vertex3fv((pos-v1).mV); + gGL.vertex3fv((pos-v2).mV); + gGL.vertex3fv((pos-v2).mV); + gGL.vertex3fv((pos-v3).mV); + gGL.vertex3fv((pos-v3).mV); + gGL.vertex3fv((pos-v4).mV); + gGL.vertex3fv((pos-v4).mV); + gGL.vertex3fv((pos-v1).mV); + //right - glVertex3fv((pos+v1).mV); - glVertex3fv((pos-v3).mV); + gGL.vertex3fv((pos+v1).mV); + gGL.vertex3fv((pos-v3).mV); - glVertex3fv((pos+v4).mV); - glVertex3fv((pos-v2).mV); + gGL.vertex3fv((pos+v4).mV); + gGL.vertex3fv((pos-v2).mV); //left - glVertex3fv((pos+v2).mV); - glVertex3fv((pos-v4).mV); + gGL.vertex3fv((pos+v2).mV); + gGL.vertex3fv((pos-v4).mV); - glVertex3fv((pos+v3).mV); - glVertex3fv((pos-v1).mV); + gGL.vertex3fv((pos+v3).mV); + gGL.vertex3fv((pos-v1).mV); - glEnd(); + gGL.end(); } class LLOctreeDirty : public LLOctreeTraveler<LLDrawable> { public: - virtual void visit(const LLOctreeState<LLDrawable>* state) + virtual void visit(const LLOctreeNode<LLDrawable>* state) { LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); group->destroyGL(); @@ -1540,47 +1749,45 @@ public: void LLSpatialPartition::restoreGL() { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - mOcclusionQueries.clear(); - sBoxList = 0; - - //generate query ids - while (mOcclusionQueries.size() < mOccludedList.size()) - { - GLuint id; - glGenQueriesARB(1, &id); - mOcclusionQueries.push_back(id); - } - - for (U32 i = 0; i < mOccludedList.size(); i++) - { //previously issued queries are now invalid - mOccludedList[i]->setState(LLSpatialGroup::DISCARD_QUERY); - } - - genBoxList(); } void LLSpatialPartition::resetVertexBuffers() { LLOctreeDirty dirty; dirty.traverse(mOctree); - - mOcclusionIndices = NULL; } S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); +#if LL_OCTREE_PARANOIA_CHECK + ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); +#endif { + BOOL temp = sFreezeState; + sFreezeState = FALSE; LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND); LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); group->rebound(); + sFreezeState = temp; } + +#if LL_OCTREE_PARANOIA_CHECK + ((LLSpatialGroup*)mOctree->getListener(0))->validate(); +#endif + if (for_select) { LLOctreeSelect selecter(&camera, results); selecter.traverse(mOctree); } + else if (mInfiniteFarClip || !LLPipeline::sUseFarClip) + { + LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL); + LLOctreeCullNoFarClip culler(&camera); + culler.traverse(mOctree); + } else { LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL); @@ -1591,61 +1798,13 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result return 0; } -class LLOctreeClearOccludedNotActive : public LLSpatialGroup::OctreeTraveler -{ -public: - LLOctreeClearOccludedNotActive() { } - - virtual void traverse(const LLSpatialGroup::TreeNode* n) - { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - if ((!group->isState(LLSpatialGroup::ACTIVE_OCCLUSION)) //|| group->isState(LLSpatialGroup::QUERY_PENDING) - || group->isState(LLSpatialGroup::DEACTIVATE_OCCLUSION)) - { //the children are all occluded or culled as well - group->clearState(LLSpatialGroup::OCCLUDED); - for (U32 i = 0; i < group->mOctreeNode->getChildCount(); i++) - { - traverse(group->mOctreeNode->getChild(i)); - } - } - } - - virtual void visit(const LLSpatialGroup::OctreeState* branch) { } -}; - -class LLQueueNonCulled : public LLSpatialGroup::OctreeTraveler -{ -public: - std::queue<LLSpatialGroup*>* mQueue; - LLQueueNonCulled(std::queue<LLSpatialGroup*> *queue) : mQueue(queue) { } - - virtual void traverse(const LLSpatialGroup::TreeNode* n) - { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - if (group->isState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED)) - { //the children are all occluded or culled as well - return; - } - - if (!group->isState(LLSpatialGroup::IN_QUEUE)) - { - group->setState(LLSpatialGroup::IN_QUEUE); - mQueue->push(group); - } - - LLSpatialGroup::OctreeTraveler::traverse(n); - } - - virtual void visit(const LLSpatialGroup::OctreeState* branch) { } -}; - BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group) { + const F32 vel = (gCamera->getVelocityStat()->getCurrent()+0.2f); LLVector3 c = group->mBounds[0]; - LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.2f,0.2f,0.2f); + LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(vel,vel,vel); - //if (group->isState(LLSpatialGroup::CULLED)) // || - if (!camera->AABBInFrustum(c, r)) + if (r.magVecSquared() > 1024.0*1024.0) { return TRUE; } @@ -1687,23 +1846,34 @@ void LLSpatialPartition::processImagery(LLCamera* camera) U32 process_count = 1; - while (process_count > 0 && !mImageQueue.empty()) + S32 pull_count = (S32) mImageQueue.size(); + + while (process_count > 0 && pull_count > 0 && !mImageQueue.empty()) { + pull_count--; LLPointer<LLSpatialGroup> group = mImageQueue.front(); mImageQueue.pop(); - - group->clearState(LLSpatialGroup::IN_IMAGE_QUEUE); - + if (group->isDead()) { continue; } + if (group->isState(LLSpatialGroup::GEOM_DIRTY)) + { //put it back + mImageQueue.push(group); + continue; + } + + group->clearState(LLSpatialGroup::IN_IMAGE_QUEUE); if (LLPipeline::sDynamicReflections) { process_count--; LLVector3 origin = group->mBounds[0]; - + /*LLVector3 at = camera->getOrigin()-origin; + at.normVec(); + origin += at* (at * group->mBounds[1]);*/ + LLCamera cube_cam; cube_cam.setOrigin(origin); cube_cam.setFar(64.f); @@ -1716,15 +1886,8 @@ void LLSpatialPartition::processImagery(LLCamera* camera) cube_map->initGL(); } - if (gPipeline.mCubeBuffer.isNull()) - { - gPipeline.mCubeBuffer = new LLCubeMap(); - gPipeline.mCubeBuffer->initGL(); - } - - S32 res = gSavedSettings.getS32("RenderReflectionRes"); - gPipeline.generateReflectionMap(gPipeline.mCubeBuffer, cube_cam, 128); - gPipeline.blurReflectionMap(gPipeline.mCubeBuffer, cube_map, res); + gPipeline.generateReflectionMap(gPipeline.mCubeBuffer, cube_cam); + gPipeline.blurReflectionMap(gPipeline.mCubeBuffer, cube_map); group->mReflectionMap = cube_map; group->setState(LLSpatialGroup::GEOM_DIRTY); } @@ -1733,601 +1896,75 @@ void LLSpatialPartition::processImagery(LLCamera* camera) } } -void validate_occlusion_list(std::vector<LLPointer<LLSpatialGroup> >& occluded_list) +void pushVerts(LLDrawInfo* params, U32 mask) { -#if !LL_RELEASE_FOR_DOWNLOAD - for (U32 i = 0; i < occluded_list.size(); i++) - { - LLSpatialGroup* group = occluded_list[i]; - for (U32 j = i+1; j < occluded_list.size(); j++) - { - if (occluded_list[i] == occluded_list[j]) - { - llerrs << "Duplicate node in occlusion list." << llendl; - } - } - - LLSpatialGroup::OctreeNode* parent = group->mOctreeNode->getOctParent(); - while (parent) - { - LLSpatialGroup* parent_group = (LLSpatialGroup*) parent->getListener(0); - if (parent_group->isState(LLSpatialGroup::OCCLUDED)) - { - llerrs << "Child node of occluded node in occlusion list (redundant query)." << llendl; - } - parent = parent->getOctParent(); - } - } -#endif + LLRenderPass::applyModelMatrix(*params); + params->mVertexBuffer->setBuffer(mask); + U16* indicesp = (U16*) params->mVertexBuffer->getIndicesPointer(); + glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount, + GL_UNSIGNED_SHORT, indicesp+params->mOffset); } -void LLSpatialPartition::processOcclusion(LLCamera* camera) +void pushVerts(LLSpatialGroup* group, U32 mask) { - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - LLSpatialGroup* rootGroup = (LLSpatialGroup*) mOctree->getListener(0); - { - LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND); - rootGroup->rebound(); - } - - //update potentials - if (!rootGroup->isState(LLSpatialGroup::IN_QUEUE)) - { - rootGroup->setState(LLSpatialGroup::IN_QUEUE); - mOcclusionQueue.push(rootGroup); - } - - const U32 MAX_PULLED = 32; - const U32 MAX_PUSHED = mOcclusionQueue.size(); - U32 count = 0; - U32 pcount = 0; - - while (pcount < MAX_PUSHED && count < MAX_PULLED && !mOcclusionQueue.empty()) - { - LLFastTimer t(LLFastTimer::FTM_OCCLUSION); - - LLPointer<LLSpatialGroup> group = mOcclusionQueue.front(); - if (!group->isState(LLSpatialGroup::IN_QUEUE)) - { - OCT_ERRS << "Spatial Group State Error. Group in queue not tagged as such." << llendl; - } - - mOcclusionQueue.pop(); - group->clearState(LLSpatialGroup::IN_QUEUE); - - if (group->isDead()) - { - continue; - } - - if (group->isState(LLSpatialGroup::CULLED | LLSpatialGroup::OCCLUDED)) - { //already culled, skip it - continue; - } - - //before we process, enqueue this group's children - for (U32 i = 0; i < group->mOctreeNode->getChildCount(); i++) - { - LLSpatialGroup* child = (LLSpatialGroup*) group->mOctreeNode->getChild(i)->getListener(0); - - //if (!child->isState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED) - if (!child->isState(LLSpatialGroup::IN_QUEUE | LLSpatialGroup::ACTIVE_OCCLUSION)) - { - child->setState(LLSpatialGroup::IN_QUEUE); - mOcclusionQueue.push(child); - } - } - - if (earlyFail(camera, group)) - { - sg_assert(!group->isState(LLSpatialGroup::OCCLUDED)); - group->setState(LLSpatialGroup::IN_QUEUE); - mOcclusionQueue.push(group); - pcount++; - continue; - } - - //add to pending queue - if (!group->isState(LLSpatialGroup::ACTIVE_OCCLUSION)) - { -#if LL_OCTREE_PARANOIA_CHECK - for (U32 i = 0; i < mOccludedList.size(); ++i) - { - sg_assert(mOccludedList[i] != group); - } -#endif - group->setState(LLSpatialGroup::ACTIVE_OCCLUSION); - mQueryQueue.push(group); - count++; - } - } - - //read back results from last frame - for (U32 i = 0; i < mOccludedList.size(); i++) - { - LLFastTimer t(LLFastTimer::FTM_OCCLUSION_READBACK); - - if (mOccludedList[i]->isDead() || mOccludedList[i]->isState(LLSpatialGroup::DEACTIVATE_OCCLUSION)) - { - continue; - } - GLuint res = 0; - - if (mOccludedList[i]->isState(LLSpatialGroup::EARLY_FAIL | LLSpatialGroup::DISCARD_QUERY) || - !mOccludedList[i]->isState(LLSpatialGroup::QUERY_OUT)) - { - mOccludedList[i]->clearState(LLSpatialGroup::EARLY_FAIL); - mOccludedList[i]->clearState(LLSpatialGroup::DISCARD_QUERY); - res = 1; - } - else - { - glGetQueryObjectuivARB(mOcclusionQueries[i], GL_QUERY_RESULT_ARB, &res); - stop_glerror(); - } - - if (res) //NOT OCCLUDED - { - if (mOccludedList[i]->isState(LLSpatialGroup::OCCLUDED)) - { //this node was occluded last frame - LLSpatialGroup::OctreeNode* node = mOccludedList[i]->mOctreeNode; - //add any immediate children to the queue that are not already there - for (U32 j = 0; j < node->getChildCount(); j++) - { - LLSpatialGroup* group = (LLSpatialGroup*) node->getChild(j)->getListener(0); - checkOcclusion(group, camera); - } - } - - //clear occlusion status for everything not on the active list - LLOctreeClearOccludedNotActive clear_occluded; - mOccludedList[i]->setState(LLSpatialGroup::DEACTIVATE_OCCLUSION); - mOccludedList[i]->clearState(LLSpatialGroup::OCCLUDED); - mOccludedList[i]->clearState(LLSpatialGroup::OCCLUDING); - clear_occluded.traverse(mOccludedList[i]->mOctreeNode); - } - else - { //OCCLUDED - if (mOccludedList[i]->isState(LLSpatialGroup::OCCLUDING)) - { - if (!mOccludedList[i]->isState(LLSpatialGroup::OCCLUDED)) - { - LLSpatialGroup::OctreeNode* oct_parent = (LLSpatialGroup::OctreeNode*) mOccludedList[i]->mOctreeNode->getParent(); - if (oct_parent) - { - LLSpatialGroup* parent = (LLSpatialGroup*) oct_parent->getListener(0); - - if (checkOcclusion(parent, camera)) - { //force a guess on the parent and siblings - for (U32 i = 0; i < parent->mOctreeNode->getChildCount(); i++) - { - LLSpatialGroup* child = (LLSpatialGroup*) parent->mOctreeNode->getChild(i)->getListener(0); - checkOcclusion(child, camera); - } - } - } - - //take children off the active list - mOccludedList[i]->setState(LLSpatialGroup::DEACTIVATE_OCCLUSION, LLSpatialGroup::STATE_MODE_BRANCH); - mOccludedList[i]->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION); - } - mOccludedList[i]->setState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); - } - else - { - //take children off the active list - mOccludedList[i]->setState(LLSpatialGroup::DEACTIVATE_OCCLUSION, LLSpatialGroup::STATE_MODE_BRANCH); - - //keep this node on the active list - mOccludedList[i]->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION); - - //this node is a top level occluder - mOccludedList[i]->setState(LLSpatialGroup::OCCLUDING); - } - } - - mOccludedList[i]->clearState(LLSpatialGroup::QUERY_OUT); - } + LLDrawInfo* params = NULL; - //remove non-occluded groups from occluded list - for (U32 i = 0; i < mOccludedList.size(); ) + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) { - if (mOccludedList[i]->isDead() || //needs to be deleted - !mOccludedList[i]->isState(LLSpatialGroup::OCCLUDING) || //is not occluding - mOccludedList[i]->isState(LLSpatialGroup::DEACTIVATE_OCCLUSION)) //parent is occluded - { - LLSpatialGroup* groupp = mOccludedList[i]; - if (!groupp->isDead()) - { - groupp->clearState(LLSpatialGroup::ACTIVE_OCCLUSION); - groupp->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION); - groupp->clearState(LLSpatialGroup::OCCLUDING); - } - mOccludedList.erase(mOccludedList.begin()+i); - } - else + for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) { - i++; + params = *j; + pushVerts(params, mask); } } - - validate_occlusion_list(mOccludedList); - - //pump some non-culled items onto the occlusion list - //count = MAX_PULLED; - while (!mQueryQueue.empty()) - { - LLPointer<LLSpatialGroup> group = mQueryQueue.front(); - mQueryQueue.pop(); - //group->clearState(LLSpatialGroup::QUERY_PENDING); - mOccludedList.push_back(group); - } - - //generate query ids - while (mOcclusionQueries.size() < mOccludedList.size()) - { - GLuint id; - glGenQueriesARB(1, &id); - mOcclusionQueries.push_back(id); - } } -class LLOcclusionIndexBuffer : public LLVertexBuffer +void pushVerts(LLFace* face, U32 mask) { -public: - LLOcclusionIndexBuffer(U32 size) - : LLVertexBuffer(0, GL_STREAM_DRAW_ARB) - { - allocateBuffer(0, size, TRUE); - - LLStrider<U32> idx; - - getIndexStrider(idx); - - //12 triangles' indices - idx[0] = 1; idx[1] = 0; idx[2] = 2; //front - idx[3] = 3; idx[4] = 2; idx[5] = 0; - - idx[6] = 4; idx[7] = 5; idx[8] = 1; //top - idx[9] = 0; idx[10] = 1; idx[11] = 5; - - idx[12] = 5; idx[13] = 4; idx[14] = 6; //back - idx[15] = 7; idx[16] = 6; idx[17] = 4; - - idx[18] = 6; idx[19] = 7; idx[20] = 3; //bottom - idx[21] = 2; idx[22] = 3; idx[23] = 7; - - idx[24] = 0; idx[25] = 5; idx[26] = 3; //left - idx[27] = 6; idx[28] = 3; idx[29] = 5; - - idx[30] = 4; idx[31] = 1; idx[32] = 7; //right - idx[33] = 2; idx[34] = 7; idx[35] = 1; - } - - //virtual BOOL useVBOs() const { return FALSE; } - - void setBuffer(U32 data_mask) - { - if (useVBOs()) - { - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices); - sIBOActive = TRUE; - unmapBuffer(); - } - else if (sIBOActive) - { - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - sIBOActive = FALSE; - } - - sGLRenderIndices = mGLIndices; - } -}; + LLVertexBuffer* buffer = face->mVertexBuffer; -class LLOcclusionVertexBuffer : public LLVertexBuffer -{ -public: - LLOcclusionVertexBuffer(S32 usage) - : LLVertexBuffer(MAP_VERTEX, usage) + if (buffer) { - allocateBuffer(8, 0, TRUE); - } - - //virtual BOOL useVBOs() const { return FALSE; } - - void setBuffer(U32 data_mask) - { - if (useVBOs()) - { - glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); - sVBOActive = TRUE; - unmapBuffer(); - } - else if (sVBOActive) - { - glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - sVBOActive = FALSE; - } - - if (data_mask) - { - glVertexPointer(3,GL_FLOAT, 0, useVBOs() ? 0 : mMappedData); - } - - sGLRenderBuffer = mGLBuffer; - } -}; - -void LLSpatialPartition::buildOcclusion() -{ - if (mOccludedList.empty()) - { - return; - } - - BOOL reset_all = FALSE; - if (mOcclusionIndices.isNull()) - { - mOcclusionIndices = new LLOcclusionIndexBuffer(36); - reset_all = TRUE; - } - - //fill occlusion vertex buffers - for (U32 i = 0; i < mOccludedList.size(); i++) - { - LLSpatialGroup* group = mOccludedList[i]; - - if (group->isState(LLSpatialGroup::OCCLUSION_DIRTY) || reset_all) - { - LLFastTimer ftm(LLFastTimer::FTM_REBUILD_OCCLUSION_VB); - - if (group->mOcclusionVerts.isNull()) - { - group->mOcclusionVerts = new LLOcclusionVertexBuffer(GL_STREAM_DRAW_ARB); - } - - group->clearState(LLSpatialGroup::OCCLUSION_DIRTY); - - LLStrider<LLVector3> vert; - - group->mOcclusionVerts->getVertexStrider(vert); - - LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.1f,0.1f,0.1f); - - for (U32 k = 0; k < 3; k++) - { - r.mV[k] = llmin(group->mBounds[1].mV[k]+0.25f, r.mV[k]); - } - - *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,1,1)); // 0 - left top front - *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,1,1)); // 1 - right top front - *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,-1,1)); // 2 - right bottom front - *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,-1,1)); // 3 - left bottom front + buffer->setBuffer(mask); + U16* indicesp = (U16*) buffer->getIndicesPointer(); + U16 start = face->getGeomStart(); + U16 end = start + face->getGeomCount()-1; + U32 count = face->getIndicesCount(); + U16 offset = face->getIndicesStart(); - *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,1,-1)); // 4 - left top back - *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,1,-1)); // 5 - right top back - *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,-1,-1)); // 6 - right bottom back - *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,-1,-1)); // 7 -left bottom back - } + glDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_SHORT, indicesp + offset); } -/* for (U32 i = 0; i < mOccludedList.size(); i++) - { - LLSpatialGroup* group = mOccludedList[i]; - if (!group->mOcclusionVerts.isNull() && group->mOcclusionVerts->isLocked()) - { - LLFastTimer ftm(LLFastTimer::FTM_REBUILD_OCCLUSION_VB); - group->mOcclusionVerts->setBuffer(0); - } - }*/ } -void LLSpatialPartition::doOcclusion(LLCamera* camera) +void pushBufferVerts(LLVertexBuffer* buffer, U32 mask) { - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - - LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION); - -#if LL_OCTREE_PARANOIA_CHECK - LLSpatialGroup* check = (LLSpatialGroup*) mOctree->getListener(0); - check->validate(); -#endif - - stop_glerror(); - - U32 num_verts = mOccludedList.size() * 8; - - if (num_verts == 0) + if (buffer) { - return; + buffer->setBuffer(mask); + U16* indicesp = (U16*) buffer->getIndicesPointer(); + glDrawRangeElements(GL_TRIANGLES, 0, buffer->getRequestedVerts(), buffer->getRequestedIndices(), + GL_UNSIGNED_SHORT, indicesp); } - - //actually perform the occlusion queries - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - LLGLDisable(GL_TEXTURE_2D); - gPipeline.disableLights(); - LLGLEnable cull_face(GL_CULL_FACE); - LLGLDisable blend(GL_BLEND); - LLGLDisable alpha_test(GL_ALPHA_TEST); - LLGLDisable fog(GL_FOG); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - glColor4f(1,1,1,1); - - mOcclusionIndices->setBuffer(0); - - U32* indicesp = (U32*) mOcclusionIndices->getIndicesPointer(); - - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); -#if !LL_RELEASE_FOR_DOWNLOAD - LLGLState::checkClientArrays(LLVertexBuffer::MAP_VERTEX); -#endif - for (U32 i = 0; i < mOccludedList.size(); i++) - { -#if LL_OCTREE_PARANOIA_CHECK - for (U32 j = i+1; j < mOccludedList.size(); j++) - { - sg_assert(mOccludedList[i] != mOccludedList[j]); - } -#endif - LLSpatialGroup* group = mOccludedList[i]; - if (group->isDead()) - { - continue; - } - - if (earlyFail(camera, group)) - { - group->setState(LLSpatialGroup::EARLY_FAIL); - } - else - { //early rejection criteria passed, send some geometry to the query - group->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX); - glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQueries[i]); - glDrawRangeElements(GL_TRIANGLES, 0, 7, 36, - GL_UNSIGNED_INT, indicesp); - glEndQueryARB(GL_SAMPLES_PASSED_ARB); - - group->setState(LLSpatialGroup::QUERY_OUT); - group->clearState(LLSpatialGroup::DISCARD_QUERY); - } - } - stop_glerror(); - - gPipeline.mTrianglesDrawn += mOccludedList.size()*12; - - glFlush(); - - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); } -class LLOctreeGet : public LLSpatialGroup::OctreeTraveler +void pushBufferVerts(LLSpatialGroup* group, U32 mask) { -public: - LLOctreeGet(LLVector3 pos, F32 rad, LLDrawable::drawable_set_t* results, BOOL lights) - : mPosition(pos), mRad(rad), mResults(results), mLights(lights), mRes(0) - { - - } - - virtual void traverse(const LLSpatialGroup::TreeNode* n) + if (!group->mDrawMap.empty()) { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - - if (mRes == 2) - { //fully in, just add everything - LLSpatialGroup::OctreeTraveler::traverse(n); - } - else - { - LLVector3 center, size; - - center = group->mBounds[0]; - size = group->mBounds[1]; - - mRes = LLSphereAABB(center, size, mPosition, mRad); - if (mRes > 0) - { - LLSpatialGroup::OctreeTraveler::traverse(n); - } - mRes = 0; - } - } - - static BOOL skip(LLDrawable* drawable, BOOL get_lights) - { - if (get_lights != drawable->isLight()) - { - return TRUE; - } - if (get_lights && drawable->getVObj()->isHUDAttachment()) - { - return TRUE; // no lighting from HUD objects - } - if (get_lights && drawable->isState(LLDrawable::ACTIVE)) - { - return TRUE; // ignore active lights - } - return FALSE; - } + LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin()); + LLRenderPass::applyModelMatrix(*params); + + pushBufferVerts(group->mVertexBuffer, mask); - virtual void visit(const LLSpatialGroup::OctreeState* branch) - { - for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) { - LLDrawable* drawable = *i; - if (!skip(drawable, mLights)) + for (LLSpatialGroup::buffer_list_t::iterator j = i->second.begin(); j != i->second.end(); ++j) { - if (mRes == 2) - { - mResults->insert(drawable); - } - else - { - LLVector3 v = LLVector3(drawable->getPositionGroup())-mPosition; - float dsq = v.magVecSquared(); - float maxd = mRad + drawable->getVisibilityRadius(); - if (dsq <= maxd*maxd) - { - mResults->insert(drawable); - } - } + pushBufferVerts(*j, mask); } } } - - LLVector3 mPosition; - F32 mRad; - LLDrawable::drawable_set_t* mResults; - BOOL mLights; - U32 mRes; -}; - -S32 LLSpatialPartition::getDrawables(const LLVector3& pos, F32 rad, - LLDrawable::drawable_set_t &results, - BOOL get_lights) -{ - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - - LLOctreeGet getter(pos, rad, &results, get_lights); - getter.traverse(mOctree); - - return results.size(); -} - -S32 LLSpatialPartition::getObjects(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results) -{ - LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); - group->rebound(); - return getDrawables(pos, rad, results, FALSE); -} - -S32 LLSpatialPartition::getLights(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results) -{ - return getDrawables(pos, rad, results, TRUE); -} - -void pushVerts(LLDrawInfo* params, U32 mask) -{ - params->mVertexBuffer->setBuffer(mask); - U32* indicesp = (U32*) params->mVertexBuffer->getIndicesPointer(); - glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount, - GL_UNSIGNED_INT, indicesp+params->mOffset); -} - -void pushVerts(LLSpatialGroup* group, U32 mask) -{ - LLDrawInfo* params = NULL; - - for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) - { - for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) - { - params = *j; - pushVerts(params, mask); - } - } } void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) @@ -2353,11 +1990,12 @@ void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) { params = *j; + LLRenderPass::applyModelMatrix(*params); glColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f); params->mVertexBuffer->setBuffer(mask); - U32* indicesp = (U32*) params->mVertexBuffer->getIndicesPointer(); + U16* indicesp = (U16*) params->mVertexBuffer->getIndicesPointer(); glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount, - GL_UNSIGNED_INT, indicesp+params->mOffset); + GL_UNSIGNED_SHORT, indicesp+params->mOffset); col = (col+1)%col_count; } } @@ -2368,7 +2006,7 @@ void renderOctree(LLSpatialGroup* group) //render solid object bounding box, color //coded by buffer usage and activity LLGLDepthTest depth(GL_TRUE, GL_FALSE); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); + gGL.blendFunc(GL_SRC_ALPHA, GL_ONE); LLVector4 col; if (group->mBuilt > 0.f) { @@ -2385,34 +2023,59 @@ void renderOctree(LLSpatialGroup* group) if (group->mBufferUsage != GL_STATIC_DRAW_ARB) { - if (group->mBufferUsage == GL_DYNAMIC_DRAW_ARB) - { - glColor4f(1,0,0,group->mBuilt); - } - else - { - glColor4f(1,1,0,group->mBuilt); - } - LLGLDepthTest gl_depth(FALSE, FALSE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + gGL.color4f(1,0,0,group->mBuilt); + gGL.flush(); + glLineWidth(5.f); + drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]); + gGL.flush(); + glLineWidth(1.f); + gGL.stop(); for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) { LLDrawable* drawable = *i; + if (!group->mSpatialPartition->isBridge()) + { + glPushMatrix(); + LLVector3 trans = drawable->getRegion()->getOriginAgent(); + glTranslatef(trans.mV[0], trans.mV[1], trans.mV[2]); + } + for (S32 j = 0; j < drawable->getNumFaces(); j++) { LLFace* face = drawable->getFace(j); - if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f && face->mVertexBuffer.notNull()) - { + if (face->mVertexBuffer.notNull()) + { + if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f) + { + glColor4f(0, 1, 0, group->mBuilt); + } + else if (gFrameTimeSeconds - face->mLastMoveTime < 0.5f) + { + glColor4f(1, 0, 0, group->mBuilt); + } + else + { + continue; + } + face->mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX); //drawBox((face->mExtents[0] + face->mExtents[1])*0.5f, // (face->mExtents[1]-face->mExtents[0])*0.5f); - glDrawElements(GL_TRIANGLES, face->getIndicesCount(), GL_UNSIGNED_INT, - ((U32*) face->mVertexBuffer->getIndicesPointer())+face->getIndicesStart()); + glDrawElements(GL_TRIANGLES, face->getIndicesCount(), GL_UNSIGNED_SHORT, + ((U16*) face->mVertexBuffer->getIndicesPointer())+face->getIndicesStart()); } } + + if (!group->mSpatialPartition->isBridge()) + { + glPopMatrix(); + } } glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.start(); } } else @@ -2428,50 +2091,80 @@ void renderOctree(LLSpatialGroup* group) } } - glColor4fv(col.mV); + gGL.color4fv(col.mV); drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); + glDepthMask(GL_TRUE); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //draw opaque outline - glColor4f(col.mV[0], col.mV[1], col.mV[2], 1.f); - drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]); - - if (group->mOctreeNode->hasLeafState()) - { - glColor4f(1,1,1,1); - } - else + if (group->mBuilt <= 0.f) { - glColor4f(0,1,1,1); + //draw opaque outline + gGL.color4f(col.mV[0], col.mV[1], col.mV[2], 1.f); + drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]); + + if (group->mOctreeNode->isLeaf()) + { + gGL.color4f(1,1,1,1); + } + else + { + gGL.color4f(0,1,1,1); + } + + drawBoxOutline(group->mBounds[0],group->mBounds[1]); } - - drawBoxOutline(group->mBounds[0],group->mBounds[1]); // LLSpatialGroup::OctreeNode* node = group->mOctreeNode; -// glColor4f(0,1,0,1); +// gGL.color4f(0,1,0,1); // drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize())); } -void renderVisibility(LLSpatialGroup* group) +void renderVisibility(LLSpatialGroup* group, LLCamera* camera) { LLGLEnable blend(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); LLGLEnable cull(GL_CULL_FACE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && + !group->getData().empty(); + if (render_objects) { LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); glColor4f(0, 0.5f, 0, 0.5f); - pushVerts(group, LLVertexBuffer::MAP_VERTEX); + pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); } { LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL); - pushVertsColorCoded(group, LLVertexBuffer::MAP_VERTEX); + + if (render_objects) + { + glColor4f(0.f, 0.5f, 0.f,1.f); + pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); + } glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - pushVertsColorCoded(group, LLVertexBuffer::MAP_VERTEX); + if (render_objects) + { + glColor4f(0.f, 0.75f, 0.f,0.5f); + pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); + } + else if (camera && group->mOcclusionVerts) + { + LLVertexBuffer::unbind(); + glVertexPointer(3, GL_FLOAT, 0, group->mOcclusionVerts); + + glColor4f(1.0f, 0.f, 0.f, 0.5f); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_occlusion_indices(camera, group->mBounds[0])); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + glColor4f(1.0f, 1.f, 1.f, 1.0f); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_occlusion_indices(camera, group->mBounds[0])); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } } } @@ -2479,17 +2172,17 @@ void renderBoundingBox(LLDrawable* drawable) { if (drawable->isSpatialBridge()) { - glColor4f(1,0.5f,0,1); + gGL.color4f(1,0.5f,0,1); } else if (drawable->getVOVolume()) { if (drawable->isRoot()) { - glColor4f(1,1,0,1); + gGL.color4f(1,1,0,1); } else { - glColor4f(0,1,0,1); + gGL.color4f(0,1,0,1); } } else if (drawable->getVObj()) @@ -2497,27 +2190,27 @@ void renderBoundingBox(LLDrawable* drawable) switch (drawable->getVObj()->getPCode()) { case LLViewerObject::LL_VO_SURFACE_PATCH: - glColor4f(0,1,1,1); + gGL.color4f(0,1,1,1); break; case LLViewerObject::LL_VO_CLOUDS: - glColor4f(0.5f,0.5f,0.5f,1.0f); + gGL.color4f(0.5f,0.5f,0.5f,1.0f); break; case LLViewerObject::LL_VO_PART_GROUP: - glColor4f(0,0,1,1); + gGL.color4f(0,0,1,1); break; case LLViewerObject::LL_VO_WATER: - glColor4f(0,0.5f,1,1); + gGL.color4f(0,0.5f,1,1); break; case LL_PCODE_LEGACY_TREE: - glColor4f(0,0.5f,0,1); + gGL.color4f(0,0.5f,0,1); default: - glColor4f(1,0,1,1); + gGL.color4f(1,0,1,1); break; } } else { - glColor4f(1,0,0,1); + gGL.color4f(1,0,0,1); } const LLVector3* ext; @@ -2545,7 +2238,20 @@ void renderBoundingBox(LLDrawable* drawable) pos = (ext[0] + ext[1]) * 0.5f; size = (ext[1] - ext[0]) * 0.5f; - drawBoxOutline(pos,size); + LLViewerObject* vobj = drawable->getVObj(); + if (vobj && vobj->onActiveList()) + { + gGL.flush(); + glLineWidth(4.f*sinf(gFrameTimeSeconds*2.f)+1.f); + drawBoxOutline(pos,size); + gGL.flush(); + glLineWidth(1.f); + } + else + { + drawBoxOutline(pos,size); + } + } void renderTexturePriority(LLDrawable* drawable) @@ -2578,14 +2284,12 @@ void renderTexturePriority(LLDrawable* drawable) F32 t = vsize/sLastMaxTexPriority; LLVector4 col = lerp(cold, hot, t); - glColor4fv(col.mV); + gGL.color4fv(col.mV); } //else //{ - // glColor4f(1,0,1,1); + // gGL.color4f(1,0,1,1); //} - - LLVector3 center = (facep->mExtents[1]+facep->mExtents[0])*0.5f; LLVector3 size = (facep->mExtents[1]-facep->mExtents[0])*0.5f + LLVector3(0.01f, 0.01f, 0.01f); @@ -2597,10 +2301,10 @@ void renderTexturePriority(LLDrawable* drawable) F32 t = (F32) boost / (F32) (LLViewerImage::BOOST_MAX_LEVEL-1); LLVector4 col = lerp(boost_cold, boost_hot, t); LLGLEnable blend_on(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glColor4fv(col.mV); + gGL.blendFunc(GL_SRC_ALPHA, GL_ONE); + gGL.color4fv(col.mV); drawBox(center, size); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }*/ } } @@ -2608,14 +2312,17 @@ void renderTexturePriority(LLDrawable* drawable) void renderPoints(LLDrawable* drawablep) { LLGLDepthTest depth(GL_FALSE, GL_FALSE); - glBegin(GL_POINTS); - glColor3f(1,1,1); - LLVector3 center(drawablep->getPositionGroup()); - for (S32 i = 0; i < drawablep->getNumFaces(); i++) + if (drawablep->getNumFaces()) { - glVertex3fv(drawablep->getFace(i)->mCenterLocal.mV); + gGL.begin(GL_POINTS); + gGL.color3f(1,1,1); + LLVector3 center(drawablep->getPositionGroup()); + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + gGL.vertex3fv(drawablep->getFace(i)->mCenterLocal.mV); + } + gGL.end(); } - glEnd(); } void renderTextureAnim(LLDrawInfo* params) @@ -2626,29 +2333,67 @@ void renderTextureAnim(LLDrawInfo* params) } LLGLEnable blend(GL_BLEND); - glColor4f(1,1,0,0.5f); + gGL.color4f(1,1,0,0.5f); pushVerts(params, LLVertexBuffer::MAP_VERTEX); } +void renderBatchSize(LLDrawInfo* params) +{ + glColor3ubv((GLubyte*) &(params->mDebugColor)); + pushVerts(params, LLVertexBuffer::MAP_VERTEX); +} + +void renderLights(LLDrawable* drawablep) +{ + if (!drawablep->isLight()) + { + return; + } + + if (drawablep->getNumFaces()) + { + LLGLEnable blend(GL_BLEND); + glColor4f(0,1,1,0.5f); + + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); + } + + const LLVector3* ext = drawablep->getSpatialExtents(); + + LLVector3 pos = (ext[0] + ext[1]) * 0.5f; + LLVector3 size = (ext[1] - ext[0]) * 0.5f; + + { + LLGLDepthTest depth(GL_FALSE, GL_TRUE); + gGL.color4f(1,1,1,1); + drawBoxOutline(pos, size); + } + + gGL.color4f(1,1,0,1); + F32 rad = drawablep->getVOVolume()->getLightRadius(); + drawBoxOutline(pos, LLVector3(rad,rad,rad)); + } +} + class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable> { public: - LLOctreeRenderNonOccluded() {} + LLCamera* mCamera; + LLOctreeRenderNonOccluded(LLCamera* camera): mCamera(camera) {} virtual void traverse(const LLSpatialGroup::OctreeNode* node) { - const LLSpatialGroup::OctreeState* state = node->getOctState(); LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - if ((!gPipeline.sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) && - !group->isState(LLSpatialGroup::CULLED)) + if (!mCamera || mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1])) { - state->accept(this); + node->accept(this); - for (U32 i = 0; i < state->getChildCount(); i++) + for (U32 i = 0; i < node->getChildCount(); i++) { - traverse(state->getChild(i)); + traverse(node->getChild(i)); } //draw tight fit bounding boxes for spatial group @@ -2659,19 +2404,25 @@ public: //render visibility wireframe if (group->mSpatialPartition->mRenderByGroup && - gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) && - !group->isState(LLSpatialGroup::GEOM_DIRTY)) + gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) { - renderVisibility(group); + gGL.stop(); + glPushMatrix(); + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + renderVisibility(group, mCamera); + gGLLastMatrix = NULL; + glPopMatrix(); + gGL.start(); } } } - virtual void visit(const LLSpatialGroup::OctreeState* branch) + virtual void visit(const LLSpatialGroup::OctreeNode* branch) { LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); - if (group->isState(LLSpatialGroup::CULLED | LLSpatialGroup::OCCLUDED)) + if (mCamera && !mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1])) { return; } @@ -2679,7 +2430,7 @@ public: LLVector3 nodeCenter = group->mBounds[0]; LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter()); - for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) { LLDrawable* drawable = *i; @@ -2697,6 +2448,11 @@ public: { renderPoints(drawable); } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LIGHTS)) + { + renderLights(drawable); + } } for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) @@ -2709,6 +2465,10 @@ public: { renderTextureAnim(draw_info); } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BATCH_SIZE)) + { + renderBatchSize(draw_info); + } } } } @@ -2718,6 +2478,8 @@ void LLSpatialPartition::renderDebug() { if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | LLPipeline::RENDER_DEBUG_OCCLUSION | + LLPipeline::RENDER_DEBUG_LIGHTS | + LLPipeline::RENDER_DEBUG_BATCH_SIZE | LLPipeline::RENDER_DEBUG_BBOXES | LLPipeline::RENDER_DEBUG_POINTS | LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY | @@ -2737,57 +2499,23 @@ void LLSpatialPartition::renderDebug() LLGLDisable cullface(GL_CULL_FACE); LLGLEnable blend(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - LLGLDisable tex(GL_TEXTURE_2D); + gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + LLImageGL::unbindTexture(0); gPipeline.disableLights(); - - LLOctreeRenderNonOccluded render_debug; - render_debug.traverse(mOctree); - LLGLDisable cull_face(GL_CULL_FACE); + LLSpatialBridge* bridge = asBridge(); + LLCamera* camera = gCamera; - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) && !mOccludedList.empty() && - mOcclusionIndices.notNull()) + if (bridge) { - LLGLDisable fog(GL_FOG); - LLGLDepthTest gls_depth(GL_FALSE); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - mOcclusionIndices->setBuffer(0); - U32* indicesp = (U32*) mOcclusionIndices->getIndicesPointer(); - - LLGLEnable blend(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - LLGLEnable cull(GL_CULL_FACE); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - - for (U32 i = 0; i < mOccludedList.size(); i++) - { //draw occluded nodes - LLSpatialGroup* node = mOccludedList[i]; - if (node->isDead() || - !node->isState(LLSpatialGroup::OCCLUDED) || - node->mOcclusionVerts.isNull()) - { - continue; - } - - node->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX); - { - LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); - glColor4f(0.5, 0.5f, 0, 0.25f); - glDrawRangeElements(GL_TRIANGLES, 0, 7, 36, - GL_UNSIGNED_INT, indicesp); - } + camera = NULL; + } - { - LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL); - glColor4f(0.0,1.0f,1.0f,1.0f); - glDrawRangeElements(GL_TRIANGLES, 0, 7, 36, - GL_UNSIGNED_INT, indicesp); - } - } + LLOctreeStateCheck checker; + checker.traverse(mOctree); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } + LLOctreeRenderNonOccluded render_debug(camera); + render_debug.traverse(mOctree); } @@ -2816,8 +2544,7 @@ public: virtual LLDrawable* check(const LLSpatialGroup::OctreeNode* node) { - const LLSpatialGroup::OctreeState* state = node->getOctState(); - state->accept(this); + node->accept(this); for (U32 i = 0; i < node->getChildCount(); i++) { @@ -2841,9 +2568,9 @@ public: return mRet; } - virtual void visit(const LLSpatialGroup::OctreeState* branch) + virtual void visit(const LLSpatialGroup::OctreeNode* branch) { - for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) { check(*i); } @@ -2869,13 +2596,14 @@ LLDrawable* LLSpatialPartition::pickDrawable(const LLVector3& start, const LLVec return ret; } -LLDrawInfo::LLDrawInfo(U32 start, U32 end, U32 count, U32 offset, +LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, LLViewerImage* texture, LLVertexBuffer* buffer, BOOL fullbright, U8 bump, BOOL particle, F32 part_size) : mVertexBuffer(buffer), mTexture(texture), mTextureMatrix(NULL), + mModelMatrix(NULL), mStart(start), mEnd(end), mCount(count), @@ -2884,8 +2612,10 @@ LLDrawInfo::LLDrawInfo(U32 start, U32 end, U32 count, U32 offset, mBump(bump), mParticle(particle), mPartSize(part_size), - mVSize(0.f) + mVSize(0.f), + mGroup(NULL) { + mDebugColor = (rand() << 16) + rand(); } LLDrawInfo::~LLDrawInfo() @@ -2897,3 +2627,190 @@ LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) { return new LLVertexBuffer(type_mask, usage); } + +LLCullResult::LLCullResult() +{ + clear(); +} + +void LLCullResult::clear() +{ + mVisibleGroupsSize = 0; + mAlphaGroupsSize = 0; + mOcclusionGroupsSize = 0; + mDrawableGroupsSize = 0; + mVisibleListSize = 0; + mVisibleBridgeSize = 0; + + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) + { + mRenderMapSize[i] = 0; + } +} + +LLCullResult::sg_list_t::iterator LLCullResult::beginVisibleGroups() +{ + return mVisibleGroups.begin(); +} + +LLCullResult::sg_list_t::iterator LLCullResult::endVisibleGroups() +{ + return mVisibleGroups.begin() + mVisibleGroupsSize; +} + +LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups() +{ + return mAlphaGroups.begin(); +} + +LLCullResult::sg_list_t::iterator LLCullResult::endAlphaGroups() +{ + return mAlphaGroups.begin() + mAlphaGroupsSize; +} + +LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups() +{ + return mOcclusionGroups.begin(); +} + +LLCullResult::sg_list_t::iterator LLCullResult::endOcclusionGroups() +{ + return mOcclusionGroups.begin() + mOcclusionGroupsSize; +} + +LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups() +{ + return mDrawableGroups.begin(); +} + +LLCullResult::sg_list_t::iterator LLCullResult::endDrawableGroups() +{ + return mDrawableGroups.begin() + mDrawableGroupsSize; +} + +LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList() +{ + return mVisibleList.begin(); +} + +LLCullResult::drawable_list_t::iterator LLCullResult::endVisibleList() +{ + return mVisibleList.begin() + mVisibleListSize; +} + +LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge() +{ + return mVisibleBridge.begin(); +} + +LLCullResult::bridge_list_t::iterator LLCullResult::endVisibleBridge() +{ + return mVisibleBridge.begin() + mVisibleBridgeSize; +} + +LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type) +{ + return mRenderMap[type].begin(); +} + +LLCullResult::drawinfo_list_t::iterator LLCullResult::endRenderMap(U32 type) +{ + return mRenderMap[type].begin() + mRenderMapSize[type]; +} + +void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) +{ + if (mVisibleGroupsSize < mVisibleGroups.size()) + { + mVisibleGroups[mVisibleGroupsSize] = group; + } + else + { + mVisibleGroups.push_back(group); + } + ++mVisibleGroupsSize; +} + +void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) +{ + if (mAlphaGroupsSize < mAlphaGroups.size()) + { + mAlphaGroups[mAlphaGroupsSize] = group; + } + else + { + mAlphaGroups.push_back(group); + } + ++mAlphaGroupsSize; +} + +void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) +{ + if (mOcclusionGroupsSize < mOcclusionGroups.size()) + { + mOcclusionGroups[mOcclusionGroupsSize] = group; + } + else + { + mOcclusionGroups.push_back(group); + } + ++mOcclusionGroupsSize; +} + +void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) +{ + if (mDrawableGroupsSize < mDrawableGroups.size()) + { + mDrawableGroups[mDrawableGroupsSize] = group; + } + else + { + mDrawableGroups.push_back(group); + } + ++mDrawableGroupsSize; +} + +void LLCullResult::pushDrawable(LLDrawable* drawable) +{ + if (mVisibleListSize < mVisibleList.size()) + { + mVisibleList[mVisibleListSize] = drawable; + } + else + { + mVisibleList.push_back(drawable); + } + ++mVisibleListSize; +} + +void LLCullResult::pushBridge(LLSpatialBridge* bridge) +{ + if (mVisibleBridgeSize < mVisibleBridge.size()) + { + mVisibleBridge[mVisibleBridgeSize] = bridge; + } + else + { + mVisibleBridge.push_back(bridge); + } + ++mVisibleBridgeSize; +} + +void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) +{ + if (mRenderMapSize[type] < mRenderMap[type].size()) + { + mRenderMap[type][mRenderMapSize[type]] = draw_info; + } + else + { + mRenderMap[type].push_back(draw_info); + } + ++mRenderMapSize[type]; +} + + + + + + |