summaryrefslogtreecommitdiff
path: root/indra/newview/llspatialpartition.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llspatialpartition.cpp')
-rw-r--r--indra/newview/llspatialpartition.cpp734
1 files changed, 594 insertions, 140 deletions
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index dea9af0657..4e13cb17a2 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -47,6 +47,7 @@
#include "llrender.h"
#include "lloctree.h"
#include "llvoavatar.h"
+#include "lltextureatlas.h"
static LLFastTimer::DeclareTimer FTM_FRUSTUM_CULL("Frustum Culling");
static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound");
@@ -88,8 +89,6 @@ protected:
static LLOcclusionQueryPool sQueryPool;
-BOOL LLSpatialPartition::sFreezeState = FALSE;
-
//static counter for frame to switch LOD on
void sg_assert(BOOL expr)
@@ -283,10 +282,10 @@ S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3
LLSpatialGroup::~LLSpatialGroup()
{
- if (sNoDelete)
+ /*if (sNoDelete)
{
llerrs << "Illegal deletion of LLSpatialGroup!" << llendl;
- }
+ }*/
if (isState(DEAD))
{
@@ -297,13 +296,136 @@ LLSpatialGroup::~LLSpatialGroup()
if (gGLManager.mHasOcclusionQuery && mOcclusionQuery)
{
- sQueryPool.release(mOcclusionQuery);
+ sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
}
delete [] mOcclusionVerts;
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
clearDrawMap();
+ clearAtlasList() ;
+}
+
+BOOL LLSpatialGroup::hasAtlas(LLTextureAtlas* atlasp)
+{
+ S8 type = atlasp->getComponents() - 1 ;
+ for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter)
+ {
+ if(atlasp == *iter)
+ {
+ return TRUE ;
+ }
+ }
+ return FALSE ;
+}
+
+void LLSpatialGroup::addAtlas(LLTextureAtlas* atlasp, S8 recursive_level)
+{
+ if(!hasAtlas(atlasp))
+ {
+ mAtlasList[atlasp->getComponents() - 1].push_back(atlasp) ;
+ atlasp->addSpatialGroup(this) ;
+ }
+
+ --recursive_level;
+ if(recursive_level)//levels propagating up.
+ {
+ LLSpatialGroup* parent = getParent() ;
+ if(parent)
+ {
+ parent->addAtlas(atlasp, recursive_level) ;
+ }
+ }
+}
+
+void LLSpatialGroup::removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group, S8 recursive_level)
+{
+ mAtlasList[atlasp->getComponents() - 1].remove(atlasp) ;
+ if(remove_group)
+ {
+ atlasp->removeSpatialGroup(this) ;
+ }
+
+ --recursive_level;
+ if(recursive_level)//levels propagating up.
+ {
+ LLSpatialGroup* parent = getParent() ;
+ if(parent)
+ {
+ parent->removeAtlas(atlasp, recursive_level) ;
+ }
+ }
+}
+
+void LLSpatialGroup::clearAtlasList()
+{
+ std::list<LLTextureAtlas*>::iterator iter ;
+ for(S8 i = 0 ; i < 4 ; i++)
+ {
+ if(mAtlasList[i].size() > 0)
+ {
+ for(iter = mAtlasList[i].begin(); iter != mAtlasList[i].end() ; ++iter)
+ {
+ ((LLTextureAtlas*)*iter)->removeSpatialGroup(this) ;
+ }
+ mAtlasList[i].clear() ;
+ }
+ }
+}
+
+LLTextureAtlas* LLSpatialGroup::getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level)
+{
+ S8 type = ncomponents - 1 ;
+ if(mAtlasList[type].size() > 0)
+ {
+ for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter)
+ {
+ if(!((LLTextureAtlas*)*iter)->isFull(to_be_reserved))
+ {
+ return *iter ;
+ }
+ }
+ }
+
+ --recursive_level;
+ if(recursive_level)
+ {
+ LLSpatialGroup* parent = getParent() ;
+ if(parent)
+ {
+ return parent->getAtlas(ncomponents, to_be_reserved, recursive_level) ;
+ }
+ }
+ return NULL ;
+}
+
+void LLSpatialGroup::setCurUpdatingSlot(LLTextureAtlasSlot* slotp)
+{
+ mCurUpdatingSlotp = slotp;
+
+ //if(!hasAtlas(mCurUpdatingSlotp->getAtlas()))
+ //{
+ // addAtlas(mCurUpdatingSlotp->getAtlas()) ;
+ //}
+}
+
+LLTextureAtlasSlot* LLSpatialGroup::getCurUpdatingSlot(LLViewerTexture* imagep, S8 recursive_level)
+{
+ if(gFrameCount && mCurUpdatingTime == gFrameCount && mCurUpdatingTexture == imagep)
+ {
+ return mCurUpdatingSlotp ;
+ }
+
+ //--recursive_level ;
+ //if(recursive_level)
+ //{
+ // LLSpatialGroup* parent = getParent() ;
+ // if(parent)
+ // {
+ // return parent->getCurUpdatingSlot(imagep, recursive_level) ;
+ // }
+ //}
+ return NULL ;
}
void LLSpatialGroup::clearDrawMap()
@@ -313,15 +435,12 @@ void LLSpatialGroup::clearDrawMap()
BOOL LLSpatialGroup::isVisible() const
{
- return mVisible == LLDrawable::getCurrentFrame() ? TRUE : FALSE;
+ return mVisible[LLViewerCamera::sCurCameraID] == LLDrawable::getCurrentFrame() ? TRUE : FALSE;
}
void LLSpatialGroup::setVisible()
{
- if (!LLSpatialPartition::sFreezeState)
- {
- mVisible = LLDrawable::getCurrentFrame();
- }
+ mVisible[LLViewerCamera::sCurCameraID] = LLDrawable::getCurrentFrame();
}
void LLSpatialGroup::validate()
@@ -380,63 +499,6 @@ 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
@@ -470,17 +532,17 @@ void validate_draw_info(LLDrawInfo& params)
}
//bad indices
- U32* indicesp = (U32*) params.mVertexBuffer->getIndicesPointer();
+ U16* indicesp = (U16*) params.mVertexBuffer->getIndicesPointer();
if (indicesp)
{
for (U32 i = params.mOffset; i < params.mOffset+params.mCount; i++)
{
- if (indicesp[i] < params.mStart)
+ if (indicesp[i] < (U16)params.mStart)
{
llerrs << "Draw batch has vertex buffer index out of range error (index too low)." << llendl;
}
- if (indicesp[i] > params.mEnd)
+ if (indicesp[i] > (U16)params.mEnd)
{
llerrs << "Draw batch has vertex buffer index out of range error (index too high)." << llendl;
}
@@ -541,7 +603,9 @@ BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_oc
{
drawablep->setSpatialGroup(this);
validate_drawable(drawablep);
- setState(OBJECT_DIRTY | GEOM_DIRTY | DISCARD_QUERY);
+ setState(OBJECT_DIRTY | GEOM_DIRTY);
+ setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS);
+ gPipeline.markRebuild(this, TRUE);
if (drawablep->isSpatialBridge())
{
mBridgeList.push_back((LLSpatialBridge*) drawablep);
@@ -576,22 +640,23 @@ static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt");
void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
{
- if (!gPipeline.hasRenderType(mDrawableType))
+ /*if (!gPipeline.hasRenderType(mDrawableType))
{
return;
- }
-
- if (!LLPipeline::sSkipUpdate && group->changeLOD())
- {
- group->mLastUpdateDistance = group->mDistance;
- group->mLastUpdateViewAngle = group->mViewAngle;
- }
+ }*/
if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY))
{
+ /*if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && mRenderByGroup)
+ {
+ llerrs << "WTF?" << llendl;
+ }*/
return;
}
+ group->mLastUpdateDistance = group->mDistance;
+ group->mLastUpdateViewAngle = group->mViewAngle;
+
LLFastTimer ftm(FTM_REBUILD_VBO);
group->clearDrawMap();
@@ -629,6 +694,7 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
group->clearState(LLSpatialGroup::GEOM_DIRTY);
}
+
void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group)
{
@@ -667,8 +733,11 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO
drawablep = *i;
minMax = drawablep->getSpatialExtents();
+ update_min_max(newMin, newMax, minMax[0]);
+ update_min_max(newMin, newMax, minMax[1]);
+
//bin up the object
- for (U32 i = 0; i < 3; i++)
+ /*for (U32 i = 0; i < 3; i++)
{
if (minMax[0].mV[i] < newMin.mV[i])
{
@@ -678,7 +747,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO
{
newMax.mV[i] = minMax[1].mV[i];
}
- }
+ }*/
}
mObjectBounds[0] = (newMin + newMax) * 0.5f;
@@ -742,6 +811,10 @@ LLSpatialGroup* LLSpatialGroup::getParent()
return NULL;
}
+ if(!mOctreeNode)
+ {
+ return NULL;
+ }
OctreeNode* parent = mOctreeNode->getOctParent();
if (parent)
@@ -767,6 +840,8 @@ BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree)
{
drawablep->setSpatialGroup(NULL);
setState(GEOM_DIRTY);
+ gPipeline.markRebuild(this, TRUE);
+
if (drawablep->isSpatialBridge())
{
for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i)
@@ -803,6 +878,7 @@ void LLSpatialGroup::shift(const LLVector3 &offset)
//if (!mSpatialPartition->mRenderByGroup)
{
setState(GEOM_DIRTY);
+ gPipeline.markRebuild(this, TRUE);
}
if (mOcclusionVerts)
@@ -843,18 +919,21 @@ public:
void LLSpatialGroup::setState(U32 state)
{
- if (!LLSpatialPartition::sFreezeState)
+ mState |= state;
+
+ if (state > LLSpatialGroup::STATE_MASK)
{
- mState |= state;
+ llerrs << "WTF?" << llendl;
}
}
void LLSpatialGroup::setState(U32 state, S32 mode)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (LLSpatialPartition::sFreezeState)
+
+ if (state > LLSpatialGroup::STATE_MASK)
{
- return;
+ llerrs << "WTF?" << llendl;
}
if (mode > STATE_MODE_SINGLE)
@@ -902,20 +981,23 @@ public:
void LLSpatialGroup::clearState(U32 state)
{
- if (!LLSpatialPartition::sFreezeState)
+ if (state > LLSpatialGroup::STATE_MASK)
{
- mState &= ~state;
+ llerrs << "WTF?" << llendl;
}
+
+ mState &= ~state;
}
void LLSpatialGroup::clearState(U32 state, S32 mode)
{
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (LLSpatialPartition::sFreezeState)
+ if (state > LLSpatialGroup::STATE_MASK)
{
- return;
+ llerrs << "WTF?" << llendl;
}
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+
if (mode > STATE_MODE_SINGLE)
{
if (mode == STATE_MODE_DIFF)
@@ -935,6 +1017,128 @@ void LLSpatialGroup::clearState(U32 state, S32 mode)
}
}
+BOOL LLSpatialGroup::isState(U32 state) const
+{
+ if (state > LLSpatialGroup::STATE_MASK)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
+ return mState & state ? TRUE : FALSE;
+}
+
+//=====================================
+// Occlusion State Set/Clear
+//=====================================
+class LLSpatialSetOcclusionState : public LLSpatialGroup::OctreeTraveler
+{
+public:
+ U32 mState;
+ LLSpatialSetOcclusionState(U32 state) : mState(state) { }
+ virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setOcclusionState(mState); }
+};
+
+class LLSpatialSetOcclusionStateDiff : public LLSpatialSetOcclusionState
+{
+public:
+ LLSpatialSetOcclusionStateDiff(U32 state) : LLSpatialSetOcclusionState(state) { }
+
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
+
+ if (!group->isOcclusionState(mState))
+ {
+ LLSpatialGroup::OctreeTraveler::traverse(n);
+ }
+ }
+};
+
+
+void LLSpatialGroup::setOcclusionState(U32 state, S32 mode)
+{
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+
+ if (mode > STATE_MODE_SINGLE)
+ {
+ if (mode == STATE_MODE_DIFF)
+ {
+ LLSpatialSetOcclusionStateDiff setter(state);
+ setter.traverse(mOctreeNode);
+ }
+ else if (mode == STATE_MODE_BRANCH)
+ {
+ LLSpatialSetOcclusionState setter(state);
+ setter.traverse(mOctreeNode);
+ }
+ else
+ {
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mOcclusionState[i] |= state;
+ }
+ }
+ }
+ else
+ {
+ mOcclusionState[LLViewerCamera::sCurCameraID] |= state;
+ }
+}
+
+class LLSpatialClearOcclusionState : public LLSpatialGroup::OctreeTraveler
+{
+public:
+ U32 mState;
+
+ LLSpatialClearOcclusionState(U32 state) : mState(state) { }
+ virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearOcclusionState(mState); }
+};
+
+class LLSpatialClearOcclusionStateDiff : public LLSpatialClearOcclusionState
+{
+public:
+ LLSpatialClearOcclusionStateDiff(U32 state) : LLSpatialClearOcclusionState(state) { }
+
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
+
+ if (group->isOcclusionState(mState))
+ {
+ LLSpatialGroup::OctreeTraveler::traverse(n);
+ }
+ }
+};
+
+void LLSpatialGroup::clearOcclusionState(U32 state, S32 mode)
+{
+ LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+
+ if (mode > STATE_MODE_SINGLE)
+ {
+ if (mode == STATE_MODE_DIFF)
+ {
+ LLSpatialClearOcclusionStateDiff clearer(state);
+ clearer.traverse(mOctreeNode);
+ }
+ else if (mode == STATE_MODE_BRANCH)
+ {
+ LLSpatialClearOcclusionState clearer(state);
+ clearer.traverse(mOctreeNode);
+ }
+ else
+ {
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mOcclusionState[i] &= ~state;
+ }
+ }
+ }
+ else
+ {
+ mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state;
+ }
+}
//======================================
// Octree Listener Implementation
//======================================
@@ -946,13 +1150,16 @@ 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),
mViewAngle(0.f),
- mLastUpdateViewAngle(-1.f)
+ mLastUpdateViewAngle(-1.f),
+ mAtlasList(4),
+ mCurUpdatingTime(0),
+ mCurUpdatingSlotp(NULL),
+ mCurUpdatingTexture (NULL)
{
sNodeCount++;
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -960,14 +1167,25 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
sg_assert(mOctreeNode->getListenerCount() == 0);
mOctreeNode->addListener(this);
setState(SG_INITIAL_STATE_MASK);
+ gPipeline.markRebuild(this, TRUE);
mBounds[0] = LLVector3(node->getCenter());
mBounds[1] = LLVector3(node->getSize());
part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod;
mLODHash = part->mLODSeed;
-
- mOcclusionQuery = 0;
+
+ OctreeNode* oct_parent = node->getOctParent();
+
+ LLSpatialGroup* parent = oct_parent ? (LLSpatialGroup*) oct_parent->getListener(0) : NULL;
+
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mOcclusionQuery[i] = 0;
+ mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0;
+ mVisible[i] = 0;
+ }
+
mOcclusionVerts = NULL;
mRadius = 1;
@@ -976,13 +1194,18 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
void LLSpatialGroup::updateDistance(LLCamera &camera)
{
+ if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
#if !LL_RELEASE_FOR_DOWNLOAD
if (isState(LLSpatialGroup::OBJECT_DIRTY))
{
llerrs << "Spatial group dirty on distance update." << llendl;
}
#endif
- if (!getData().empty() && !LLSpatialPartition::sFreezeState)
+ if (!getData().empty())
{
mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() :
(F32) mOctreeNode->getSize().magVec();
@@ -1018,6 +1241,7 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera)
//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);
+ gPipeline.markRebuild(group, FALSE);
}
}
}
@@ -1054,6 +1278,18 @@ F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera)
return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera);
}
+F32 LLSpatialGroup::getUpdateUrgency() const
+{
+ if (!isVisible())
+ {
+ return 0.f;
+ }
+ else
+ {
+ return (gFrameTimeSeconds - mLastUpdateTime+4.f)/mDistance;
+ }
+}
+
BOOL LLSpatialGroup::needsUpdate()
{
return (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE;
@@ -1140,8 +1376,7 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
if (child->getListenerCount() == 0)
{
- LLSpatialGroup* group = new LLSpatialGroup(child, mSpatialPartition);
- group->setState(mState & SG_STATE_INHERIT_MASK);
+ new LLSpatialGroup(child, mSpatialPartition);
}
else
{
@@ -1161,16 +1396,21 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo
void LLSpatialGroup::destroyGL()
{
setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY);
+ gPipeline.markRebuild(this, TRUE);
+
mLastUpdateTime = gFrameTimeSeconds;
mVertexBuffer = NULL;
mBufferMap.clear();
clearDrawMap();
- if (mOcclusionQuery)
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
{
- sQueryPool.release(mOcclusionQuery);
- mOcclusionQuery = 0;
+ if (mOcclusionQuery[i])
+ {
+ sQueryPool.release(mOcclusionQuery[i]);
+ mOcclusionQuery[i] = 0;
+ }
}
delete [] mOcclusionVerts;
@@ -1266,38 +1506,43 @@ void LLSpatialGroup::checkOcclusion()
if (LLPipeline::sUseOcclusion > 1)
{
LLSpatialGroup* parent = getParent();
- if (parent && parent->isState(LLSpatialGroup::OCCLUDED))
+ if (parent && parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
{ //if the parent has been marked as occluded, the child is implicitly occluded
- clearState(QUERY_PENDING | DISCARD_QUERY);
+ clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
}
- else if (isState(QUERY_PENDING))
+ else if (isOcclusionState(QUERY_PENDING))
{ //otherwise, if a query is pending, read it back
LLFastTimer t(FTM_OCCLUSION_READBACK);
GLuint res = 1;
- if (!isState(DISCARD_QUERY) && mOcclusionQuery)
+ if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
{
- glGetQueryObjectuivARB(mOcclusionQuery, GL_QUERY_RESULT_ARB, &res);
+ glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res);
+ }
+
+ if (isOcclusionState(DISCARD_QUERY))
+ {
+ res = 2;
}
if (res > 0)
{
assert_states_valid(this);
- clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
+ clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
else
{
assert_states_valid(this);
- setState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
+ setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
- clearState(QUERY_PENDING | DISCARD_QUERY);
+ clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
}
- else if (mSpatialPartition->isOcclusionEnabled() && isState(LLSpatialGroup::OCCLUDED))
+ else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLSpatialGroup::OCCLUDED))
{ //check occlusion has been issued for occluded node that has not had a query issued
assert_states_valid(this);
- clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
+ clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
}
@@ -1309,9 +1554,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
{
if (earlyFail(camera, this))
{
- setState(LLSpatialGroup::DISCARD_QUERY);
+ setOcclusionState(LLSpatialGroup::DISCARD_QUERY);
assert_states_valid(this);
- clearState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
+ clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
assert_states_valid(this);
}
else
@@ -1319,9 +1564,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
{
LLFastTimer t(FTM_RENDER_OCCLUSION);
- if (!mOcclusionQuery)
+ if (!mOcclusionQuery[LLViewerCamera::sCurCameraID])
{
- mOcclusionQuery = sQueryPool.allocate();
+ mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate();
}
if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY))
@@ -1329,22 +1574,33 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
buildOcclusion();
}
- glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery);
+ glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts);
- glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
- GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0]));
+ if (camera->getOrigin().isExactlyZero())
+ { //origin is invalid, draw entire box
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, sOcclusionIndices);
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, sOcclusionIndices+b111*8);
+ }
+ else
+ {
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0]));
+ }
glEndQueryARB(GL_SAMPLES_PASSED_ARB);
}
- setState(LLSpatialGroup::QUERY_PENDING);
- clearState(LLSpatialGroup::DISCARD_QUERY);
+ setOcclusionState(LLSpatialGroup::QUERY_PENDING);
+ clearOcclusionState(LLSpatialGroup::DISCARD_QUERY);
}
}
}
//==============================================
-LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage)
+LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage)
+: mRenderByGroup(render_by_group)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
mOcclusionEnabled = TRUE;
@@ -1356,7 +1612,6 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage)
mBufferUsage = buffer_usage;
mDepthMask = FALSE;
mSlopRatio = 0.25f;
- mRenderByGroup = TRUE;
mInfiniteFarClip = FALSE;
LLGLNamePool::registerPool(&sQueryPool);
@@ -1393,9 +1648,9 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
LLSpatialGroup* group = drawablep->getSpatialGroup();
- if (group && was_visible && group->isState(LLSpatialGroup::QUERY_PENDING))
+ if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING))
{
- group->setState(LLSpatialGroup::DISCARD_QUERY);
+ group->setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS);
}
return group;
@@ -1494,7 +1749,7 @@ public:
if (group->mOctreeNode->getParent() && //never occlusion cull the root node
LLPipeline::sUseOcclusion && //ignore occlusion if disabled
- group->isState(LLSpatialGroup::OCCLUDED))
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
gPipeline.markOccluder(group);
return true;
@@ -1576,7 +1831,7 @@ public:
virtual void processGroup(LLSpatialGroup* group)
{
if (group->needsUpdate() ||
- group->mVisible < LLDrawable::getCurrentFrame() - 1)
+ group->mVisible[LLViewerCamera::sCurCameraID] < LLDrawable::getCurrentFrame() - 1)
{
group->doOcclusion(mCamera);
}
@@ -1644,7 +1899,7 @@ public:
{
if (group->mOctreeNode->getParent() && //never occlusion cull the root node
LLPipeline::sUseOcclusion && //ignore occlusion if disabled
- group->isState(LLSpatialGroup::OCCLUDED))
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
return true;
}
@@ -1652,13 +1907,57 @@ public:
return false;
}
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
+
+ if (earlyFail(group))
+ {
+ return;
+ }
+
+ if (mRes == 2)
+ {
+ //fully in, don't traverse further (won't effect extents
+ }
+ else if (mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK))
+ { //don't need to do frustum check
+ LLSpatialGroup::OctreeTraveler::traverse(n);
+ }
+ else
+ {
+ mRes = frustumCheck(group);
+
+ if (mRes)
+ { //at least partially in, run on down
+ LLSpatialGroup::OctreeTraveler::traverse(n);
+ }
+
+ mRes = 0;
+ }
+ }
+
virtual void processGroup(LLSpatialGroup* group)
{
- if (group->mObjectBounds[1].magVecSquared() < 256.f * 256.f)
- { //megaprims and water edge patches be damned!
+ if (group->isState(LLSpatialGroup::DIRTY) || group->getData().empty())
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
+ if (mRes < 2)
+ {
+ if (mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]) > 0)
+ {
+ mEmpty = FALSE;
+ update_min_max(mMin, mMax, group->mObjectExtents[0]);
+ update_min_max(mMin, mMax, group->mObjectExtents[1]);
+ }
+ }
+ else
+ {
mEmpty = FALSE;
- update_min_max(mMin, mMax, group->mObjectExtents[0]);
- update_min_max(mMin, mMax, group->mObjectExtents[1]);
+ update_min_max(mMin, mMax, group->mExtents[0]);
+ update_min_max(mMin, mMax, group->mExtents[1]);
}
}
@@ -1676,9 +1975,9 @@ public:
virtual bool earlyFail(LLSpatialGroup* group)
{
if (mResult || //already found a node, don't check any more
- group->mOctreeNode->getParent() && //never occlusion cull the root node
- LLPipeline::sUseOcclusion && //ignore occlusion if disabled
- group->isState(LLSpatialGroup::OCCLUDED))
+ (group->mOctreeNode->getParent() && //never occlusion cull the root node
+ LLPipeline::sUseOcclusion && //ignore occlusion if disabled
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED)))
{
return true;
}
@@ -1857,6 +2156,12 @@ BOOL LLSpatialPartition::isOcclusionEnabled()
BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax)
{
+ {
+ LLFastTimer ftm(FTM_CULL_REBOUND);
+ LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
+ group->rebound();
+ }
+
LLOctreeCullVisExtents vis(&camera, visMin, visMax);
vis.traverse(mOctree);
return vis.mEmpty;
@@ -1876,12 +2181,9 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
((LLSpatialGroup*)mOctree->getListener(0))->checkStates();
#endif
{
- BOOL temp = sFreezeState;
- sFreezeState = FALSE;
LLFastTimer ftm(FTM_CULL_REBOUND);
LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
group->rebound();
- sFreezeState = temp;
}
#if LL_OCTREE_PARANOIA_CHECK
@@ -1918,6 +2220,11 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group)
{
+ if (camera->getOrigin().isExactlyZero())
+ {
+ return FALSE;
+ }
+
const F32 vel = SG_OCCLUSION_FUDGE*2.f;
LLVector3 c = group->mBounds[0];
LLVector3 r = group->mBounds[1] + LLVector3(vel,vel,vel);
@@ -2195,7 +2502,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
LLGLEnable cull(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
+ BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() &&
!group->getData().empty();
if (render_objects)
{
@@ -2436,6 +2743,39 @@ void renderBatchSize(LLDrawInfo* params)
pushVerts(params, LLVertexBuffer::MAP_VERTEX);
}
+void renderShadowFrusta(LLDrawInfo* params)
+{
+ LLGLEnable blend(GL_BLEND);
+ gGL.setSceneBlendType(LLRender::BT_ADD);
+
+ LLVector3 center = (params->mExtents[1]+params->mExtents[0])*0.5f;
+ LLVector3 size = (params->mExtents[1]-params->mExtents[0])*0.5f;
+
+ if (gPipeline.mShadowCamera[4].AABBInFrustum(center, size))
+ {
+ glColor3f(1,0,0);
+ pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ }
+ if (gPipeline.mShadowCamera[5].AABBInFrustum(center, size))
+ {
+ glColor3f(0,1,0);
+ pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ }
+ if (gPipeline.mShadowCamera[6].AABBInFrustum(center, size))
+ {
+ glColor3f(0,0,1);
+ pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ }
+ if (gPipeline.mShadowCamera[7].AABBInFrustum(center, size))
+ {
+ glColor3f(1,0,1);
+ pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ }
+
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+}
+
+
void renderLights(LLDrawable* drawablep)
{
if (!drawablep->isLight())
@@ -2571,6 +2911,9 @@ public:
//draw tight fit bounding boxes for spatial group
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE))
{
+ group->rebuildGeom();
+ group->rebuildMesh();
+
renderOctree(group);
stop_glerror();
}
@@ -2578,6 +2921,9 @@ public:
//render visibility wireframe
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
{
+ group->rebuildGeom();
+ group->rebuildMesh();
+
gGL.flush();
glPushMatrix();
gGLLastMatrix = NULL;
@@ -2603,6 +2949,19 @@ public:
LLVector3 nodeCenter = group->mBounds[0];
LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter());
+ group->rebuildGeom();
+ group->rebuildMesh();
+
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES))
+ {
+ if (!group->getData().empty())
+ {
+ gGL.color3f(0,0,1);
+ drawBoxOutline(group->mObjectBounds[0],
+ group->mObjectBounds[1]);
+ }
+ }
+
for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
{
LLDrawable* drawable = *i;
@@ -2612,6 +2971,16 @@ public:
renderBoundingBox(drawable);
}
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BUILD_QUEUE))
+ {
+ if (drawable->isState(LLDrawable::IN_REBUILD_Q2))
+ {
+ gGL.color4f(0.6f, 0.6f, 0.1f, 1.f);
+ const LLVector3* ext = drawable->getSpatialExtents();
+ drawBoxOutline((ext[0]+ext[1])*0.5f, (ext[1]-ext[0])*0.5f);
+ }
+ }
+
if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
renderTexturePriority(drawable);
@@ -2660,6 +3029,10 @@ public:
{
renderBatchSize(draw_info);
}
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ renderShadowFrusta(draw_info);
+ }
}
}
}
@@ -2710,6 +3083,79 @@ void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera)
pusher.traverse(mOctree);
}
+class LLOctreeStateCheck : public LLOctreeTraveler<LLDrawable>
+{
+public:
+ U32 mInheritedMask[LLViewerCamera::NUM_CAMERAS];
+
+ LLOctreeStateCheck()
+ {
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mInheritedMask[i] = 0;
+ }
+ }
+
+ virtual void traverse(const LLSpatialGroup::OctreeNode* node)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
+
+ node->accept(this);
+
+
+ U32 temp[LLViewerCamera::NUM_CAMERAS];
+
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ temp[i] = mInheritedMask[i];
+ mInheritedMask[i] |= group->mOcclusionState[i] & LLSpatialGroup::OCCLUDED;
+ }
+
+ for (U32 i = 0; i < node->getChildCount(); i++)
+ {
+ traverse(node->getChild(i));
+ }
+
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mInheritedMask[i] = temp[i];
+ }
+ }
+
+
+ virtual void visit(const LLOctreeNode<LLDrawable>* state)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
+
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ if (mInheritedMask[i] && !(group->mOcclusionState[i] & mInheritedMask[i]))
+ {
+ 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 LLSpatialPartition::renderDebug()
{
if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE |
@@ -2722,7 +3168,9 @@ void LLSpatialPartition::renderDebug()
LLPipeline::RENDER_DEBUG_TEXTURE_ANIM |
LLPipeline::RENDER_DEBUG_RAYCAST |
LLPipeline::RENDER_DEBUG_AVATAR_VOLUME |
- LLPipeline::RENDER_DEBUG_AGENT_TARGET))
+ LLPipeline::RENDER_DEBUG_AGENT_TARGET |
+ LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
+ LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
return;
}
@@ -2757,6 +3205,12 @@ void LLSpatialPartition::renderDebug()
render_debug.traverse(mOctree);
}
+void LLSpatialGroup::drawObjectBox(LLColor4 col)
+{
+ gGL.color4fv(col.mV);
+ drawBox(mObjectBounds[0], mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f));
+}
+
BOOL LLSpatialPartition::isVisible(const LLVector3& v)
{
@@ -2937,10 +3391,10 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
LLDrawInfo::~LLDrawInfo()
{
- if (LLSpatialGroup::sNoDelete)
+ /*if (LLSpatialGroup::sNoDelete)
{
llerrs << "LLDrawInfo deleted illegally!" << llendl;
- }
+ }*/
if (mFace)
{