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.cpp1590
1 files changed, 1201 insertions, 389 deletions
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 84e14ef341..fb984a7c62 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -2,30 +2,25 @@
* @file llspatialpartition.cpp
* @brief LLSpatialGroup class implementation and supporting functions
*
- * $LicenseInfo:firstyear=2003&license=viewergpl$
- *
- * Copyright (c) 2003-2007, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlife.com/developers/opensource/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at http://secondlife.com/developers/opensource/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,17 +31,22 @@
#include "llviewerwindow.h"
#include "llviewerobjectlist.h"
#include "llvovolume.h"
+#include "llvolume.h"
#include "llviewercamera.h"
#include "llface.h"
#include "llviewercontrol.h"
-#include "llagent.h"
#include "llviewerregion.h"
#include "llcamera.h"
#include "pipeline.h"
-#include "llglimmediate.h"
+#include "llrender.h"
#include "lloctree.h"
+#include "llvoavatar.h"
+#include "lltextureatlas.h"
-const F32 SG_OCCLUSION_FUDGE = 1.01f;
+static LLFastTimer::DeclareTimer FTM_FRUSTUM_CULL("Frustum Culling");
+static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound");
+
+const F32 SG_OCCLUSION_FUDGE = 0.25f;
#define SG_DISCARD_TOLERANCE 0.01f
#if LL_OCTREE_PARANOIA_CHECK
@@ -60,6 +60,7 @@ const F32 SG_OCCLUSION_FUDGE = 1.01f;
static U32 sZombieGroups = 0;
U32 LLSpatialGroup::sNodeCount = 0;
+BOOL LLSpatialGroup::sNoDelete = FALSE;
static F32 sLastMaxTexPriority = 1.f;
static F32 sCurMaxTexPriority = 1.f;
@@ -82,8 +83,6 @@ protected:
static LLOcclusionQueryPool sQueryPool;
-BOOL LLSpatialPartition::sFreezeState = FALSE;
-
//static counter for frame to switch LOD on
void sg_assert(BOOL expr)
@@ -115,10 +114,14 @@ void validate_drawable(LLDrawable* drawablep)
S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad)
{
+ return AABBSphereIntersectR2(min, max, origin, rad*rad);
+}
+
+S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &r)
+{
F32 d = 0.f;
F32 t;
- F32 r = rad*rad;
-
+
if ((min-origin).magVecSquared() < r &&
(max-origin).magVecSquared() < r)
{
@@ -183,7 +186,7 @@ static U8 sOcclusionIndices[] =
b000, b110, b100, b101, b001, b011, b010, b110,
};
-U8* get_occlusion_indices(LLCamera* camera, const LLVector3& center)
+U8* get_box_fan_indices(LLCamera* camera, const LLVector3& center)
{
LLVector3 d = center - camera->getOrigin();
@@ -211,7 +214,7 @@ void LLSpatialGroup::buildOcclusion()
mOcclusionVerts = new F32[8*3];
}
- LLVector3 r = mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.1f,0.1f,0.1f);
+ LLVector3 r = mBounds[1] + LLVector3(SG_OCCLUSION_FUDGE, SG_OCCLUSION_FUDGE, SG_OCCLUSION_FUDGE);
for (U32 k = 0; k < 3; k++)
{
@@ -242,28 +245,6 @@ void LLSpatialGroup::buildOcclusion()
BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group);
-BOOL LLLineSegmentAABB(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size)
-{
- float fAWdU[3];
- LLVector3 dir;
- LLVector3 diff;
-
- for (U32 i = 0; i < 3; i++)
- {
- dir.mV[i] = 0.5f * (end.mV[i] - start.mV[i]);
- diff.mV[i] = (0.5f * (end.mV[i] + start.mV[i])) - center.mV[i];
- fAWdU[i] = fabsf(dir.mV[i]);
- if(fabsf(diff.mV[i])>size.mV[i] + fAWdU[i]) return false;
- }
-
- float f;
- f = dir.mV[1] * diff.mV[2] - dir.mV[2] * diff.mV[1]; if(fabsf(f)>size.mV[1]*fAWdU[2] + size.mV[2]*fAWdU[1]) return false;
- f = dir.mV[2] * diff.mV[0] - dir.mV[0] * diff.mV[2]; if(fabsf(f)>size.mV[0]*fAWdU[2] + size.mV[2]*fAWdU[0]) return false;
- f = dir.mV[0] * diff.mV[1] - dir.mV[1] * diff.mV[0]; if(fabsf(f)>size.mV[0]*fAWdU[1] + size.mV[1]*fAWdU[0]) return false;
-
- return true;
-}
-
//returns:
// 0 if sphere and AABB are not intersecting
// 1 if they are
@@ -295,6 +276,11 @@ S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3
LLSpatialGroup::~LLSpatialGroup()
{
+ /*if (sNoDelete)
+ {
+ llerrs << "Illegal deletion of LLSpatialGroup!" << llendl;
+ }*/
+
if (isState(DEAD))
{
sZombieGroups--;
@@ -302,15 +288,139 @@ LLSpatialGroup::~LLSpatialGroup()
sNodeCount--;
- if (gGLManager.mHasOcclusionQuery && mOcclusionQuery)
+ if (gGLManager.mHasOcclusionQuery && mOcclusionQuery[LLViewerCamera::sCurCameraID])
{
- sQueryPool.release(mOcclusionQuery);
+ sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
}
delete [] mOcclusionVerts;
+ mOcclusionVerts = NULL;
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()
@@ -318,17 +428,19 @@ void LLSpatialGroup::clearDrawMap()
mDrawMap.clear();
}
+BOOL LLSpatialGroup::isRecentlyVisible() const
+{
+ return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < LLDrawable::getMinVisFrameRange() ;
+}
+
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()
@@ -387,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
@@ -477,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;
}
@@ -548,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);
@@ -571,20 +628,39 @@ void LLSpatialGroup::rebuildGeom()
}
}
-void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
+void LLSpatialGroup::rebuildMesh()
{
- if (group->changeLOD())
+ if (!isDead())
{
- group->mLastUpdateDistance = group->mDistance;
- group->mLastUpdateViewAngle = group->mViewAngle;
+ mSpatialPartition->rebuildMesh(this);
}
+}
+
+static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt");
+
+void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
+{
+ /*if (!gPipeline.hasRenderType(mDrawableType))
+ {
+ return;
+ }*/
if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY))
{
+ /*if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && mRenderByGroup)
+ {
+ llerrs << "WTF?" << llendl;
+ }*/
return;
}
- LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO);
+ if (group->changeLOD())
+ {
+ group->mLastUpdateDistance = group->mDistance;
+ group->mLastUpdateViewAngle = group->mViewAngle;
+ }
+
+ LLFastTimer ftm(FTM_REBUILD_VBO);
group->clearDrawMap();
@@ -621,6 +697,12 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
group->clearState(LLSpatialGroup::GEOM_DIRTY);
}
+
+void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group)
+{
+
+}
+
BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxOut)
{
const OctreeNode* node = mOctreeNode;
@@ -654,8 +736,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])
{
@@ -665,7 +750,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO
{
newMax.mV[i] = minMax[1].mV[i];
}
- }
+ }*/
}
mObjectBounds[0] = (newMin + newMax) * 0.5f;
@@ -729,6 +814,10 @@ LLSpatialGroup* LLSpatialGroup::getParent()
return NULL;
}
+ if(!mOctreeNode)
+ {
+ return NULL;
+ }
OctreeNode* parent = mOctreeNode->getOctParent();
if (parent)
@@ -754,6 +843,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)
@@ -787,9 +878,10 @@ void LLSpatialGroup::shift(const LLVector3 &offset)
mObjectExtents[0] += offset;
mObjectExtents[1] += offset;
- if (!mSpatialPartition->mRenderByGroup)
+ //if (!mSpatialPartition->mRenderByGroup)
{
setState(GEOM_DIRTY);
+ gPipeline.markRebuild(this, TRUE);
}
if (mOcclusionVerts)
@@ -817,7 +909,7 @@ class LLSpatialSetStateDiff : public LLSpatialSetState
public:
LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { }
- virtual void traverse(const LLSpatialGroup::TreeNode* n)
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
{
LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
@@ -830,18 +922,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)
@@ -876,7 +971,7 @@ class LLSpatialClearStateDiff : public LLSpatialClearState
public:
LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { }
- virtual void traverse(const LLSpatialGroup::TreeNode* n)
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
{
LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
@@ -889,20 +984,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)
@@ -922,6 +1020,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
//======================================
@@ -933,13 +1153,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);
@@ -947,14 +1170,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;
@@ -963,13 +1197,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();
@@ -1005,6 +1244,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);
}
}
}
@@ -1041,6 +1281,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;
@@ -1127,8 +1379,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
{
@@ -1148,17 +1399,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();
- mReflectionMap = NULL;
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;
@@ -1248,43 +1503,49 @@ BOOL LLSpatialGroup::rebound()
return TRUE;
}
+static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion");
void LLSpatialGroup::checkOcclusion()
{
if (LLPipeline::sUseOcclusion > 1)
{
+ LLFastTimer t(FTM_OCCLUSION_READBACK);
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(LLFastTimer::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->mOcclusionEnabled)
- {
+ 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);
}
}
@@ -1292,23 +1553,23 @@ void LLSpatialGroup::checkOcclusion()
void LLSpatialGroup::doOcclusion(LLCamera* camera)
{
- if (mSpatialPartition->mOcclusionEnabled && LLPipeline::sUseOcclusion > 1)
+ if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1)
{
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
{
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION);
+ 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))
@@ -1316,22 +1577,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_occlusion_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;
@@ -1343,8 +1615,6 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage)
mBufferUsage = buffer_usage;
mDepthMask = FALSE;
mSlopRatio = 0.25f;
- mRenderByGroup = TRUE;
- mImageEnabled = FALSE;
mInfiniteFarClip = FALSE;
LLGLNamePool::registerPool(&sQueryPool);
@@ -1381,9 +1651,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;
@@ -1481,8 +1751,8 @@ public:
group->checkOcclusion();
if (group->mOctreeNode->getParent() && //never occlusion cull the root node
- LLPipeline::sUseOcclusion && //ignore occlusion if disabled
- group->isState(LLSpatialGroup::OCCLUDED))
+ LLPipeline::sUseOcclusion && //ignore occlusion if disabled
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED))
{
gPipeline.markOccluder(group);
return true;
@@ -1491,7 +1761,7 @@ public:
return false;
}
- virtual void traverse(const LLSpatialGroup::TreeNode* n)
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
{
LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
@@ -1558,18 +1828,13 @@ public:
virtual void preprocess(LLSpatialGroup* group)
{
- if (LLPipeline::sDynamicReflections &&
- group->mOctreeNode->getSize().mdV[0] == 16.0 &&
- group->mDistance < 64.f)
- {
- group->mSpatialPartition->markReimage(group);
- }
+
}
virtual void processGroup(LLSpatialGroup* group)
{
if (group->needsUpdate() ||
- group->mVisible < LLDrawable::getCurrentFrame() - 1)
+ group->mVisible[LLViewerCamera::sCurCameraID] < LLDrawable::getCurrentFrame() - 1)
{
group->doOcclusion(mCamera);
}
@@ -1602,6 +1867,133 @@ public:
{
return mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]);
}
+
+ virtual S32 frustumCheckObjects(const LLSpatialGroup* group)
+ {
+ S32 res = mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]);
+ return res;
+ }
+};
+
+class LLOctreeCullShadow : public LLOctreeCull
+{
+public:
+ LLOctreeCullShadow(LLCamera* camera)
+ : LLOctreeCull(camera) { }
+
+ virtual S32 frustumCheck(const LLSpatialGroup* group)
+ {
+ return mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1]);
+ }
+
+ virtual S32 frustumCheckObjects(const LLSpatialGroup* group)
+ {
+ return mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]);
+ }
+};
+
+class LLOctreeCullVisExtents: public LLOctreeCullShadow
+{
+public:
+ LLOctreeCullVisExtents(LLCamera* camera, LLVector3& min, LLVector3& max)
+ : LLOctreeCullShadow(camera), mMin(min), mMax(max), mEmpty(TRUE) { }
+
+ virtual bool earlyFail(LLSpatialGroup* group)
+ {
+ if (group->mOctreeNode->getParent() && //never occlusion cull the root node
+ LLPipeline::sUseOcclusion && //ignore occlusion if disabled
+ group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ virtual void traverse(const LLSpatialGroup::OctreeNode* n)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
+
+ if (earlyFail(group))
+ {
+ return;
+ }
+
+ if ((mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) ||
+ mRes == 2)
+ { //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->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->mExtents[0]);
+ update_min_max(mMin, mMax, group->mExtents[1]);
+ }
+ }
+
+ BOOL mEmpty;
+ LLVector3& mMin;
+ LLVector3& mMax;
+};
+
+class LLOctreeCullDetectVisible: public LLOctreeCullShadow
+{
+public:
+ LLOctreeCullDetectVisible(LLCamera* camera)
+ : LLOctreeCullShadow(camera), mResult(FALSE) { }
+
+ 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->isOcclusionState(LLSpatialGroup::OCCLUDED)))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ virtual void processGroup(LLSpatialGroup* group)
+ {
+ if (group->isVisible())
+ {
+ mResult = TRUE;
+ }
+ }
+
+ BOOL mResult;
};
class LLOctreeSelect : public LLOctreeCull
@@ -1640,7 +2032,7 @@ public:
void drawBox(const LLVector3& c, const LLVector3& r)
{
- gGL.begin(GL_TRIANGLE_STRIP);
+ gGL.begin(LLRender::TRIANGLE_STRIP);
//left front
gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV);
gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV);
@@ -1659,7 +2051,7 @@ void drawBox(const LLVector3& c, const LLVector3& r)
gGL.end();
//bottom
- gGL.begin(GL_TRIANGLE_STRIP);
+ gGL.begin(LLRender::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);
@@ -1667,7 +2059,7 @@ void drawBox(const LLVector3& c, const LLVector3& r)
gGL.end();
//top
- gGL.begin(GL_TRIANGLE_STRIP);
+ gGL.begin(LLRender::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);
@@ -1682,7 +2074,7 @@ void drawBoxOutline(const LLVector3& pos, const LLVector3& size)
LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1));
LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1));
- gGL.begin(GL_LINES);
+ gGL.begin(LLRender::LINES);
//top
gGL.vertex3fv((pos+v1).mV);
@@ -1757,6 +2149,31 @@ void LLSpatialPartition::resetVertexBuffers()
dirty.traverse(mOctree);
}
+BOOL LLSpatialPartition::isOcclusionEnabled()
+{
+ return mOcclusionEnabled || LLPipeline::sUseOcclusion > 2;
+}
+
+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;
+}
+
+BOOL LLSpatialPartition::visibleObjectsInFrustum(LLCamera& camera)
+{
+ LLOctreeCullDetectVisible vis(&camera);
+ vis.traverse(mOctree);
+ return vis.mResult;
+}
+
S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -1764,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(LLFastTimer::FTM_CULL_REBOUND);
+ LLFastTimer ftm(FTM_CULL_REBOUND);
LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
group->rebound();
- sFreezeState = temp;
}
#if LL_OCTREE_PARANOIA_CHECK
@@ -1782,15 +2196,21 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
LLOctreeSelect selecter(&camera, results);
selecter.traverse(mOctree);
}
+ else if (LLPipeline::sShadowRender)
+ {
+ LLFastTimer ftm(FTM_FRUSTUM_CULL);
+ LLOctreeCullShadow culler(&camera);
+ culler.traverse(mOctree);
+ }
else if (mInfiniteFarClip || !LLPipeline::sUseFarClip)
{
- LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL);
+ LLFastTimer ftm(FTM_FRUSTUM_CULL);
LLOctreeCullNoFarClip culler(&camera);
culler.traverse(mOctree);
}
else
{
- LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL);
+ LLFastTimer ftm(FTM_FRUSTUM_CULL);
LLOctreeCull culler(&camera);
culler.traverse(mOctree);
}
@@ -1800,14 +2220,19 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result
BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group)
{
- const F32 vel = (gCamera->getVelocityStat()->getCurrent()+0.2f);
+ if (camera->getOrigin().isExactlyZero())
+ {
+ return FALSE;
+ }
+
+ const F32 vel = SG_OCCLUSION_FUDGE*2.f;
LLVector3 c = group->mBounds[0];
- LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(vel,vel,vel);
+ LLVector3 r = group->mBounds[1] + LLVector3(vel,vel,vel);
- if (r.magVecSquared() > 1024.0*1024.0)
+ /*if (r.magVecSquared() > 1024.0*1024.0)
{
return TRUE;
- }
+ }*/
LLVector3 e = camera->getOrigin();
@@ -1825,84 +2250,13 @@ BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group)
return TRUE;
}
-void LLSpatialPartition::markReimage(LLSpatialGroup* group)
-{
- if (mImageEnabled && group->isState(LLSpatialGroup::IMAGE_DIRTY))
- {
- if (!group->isState(LLSpatialGroup::IN_IMAGE_QUEUE))
- {
- group->setState(LLSpatialGroup::IN_IMAGE_QUEUE);
- mImageQueue.push(group);
- }
- }
-}
-
-void LLSpatialPartition::processImagery(LLCamera* camera)
-{
- if (!mImageEnabled)
- {
- return;
- }
-
- U32 process_count = 1;
-
- S32 pull_count = (S32) mImageQueue.size();
-
- while (process_count > 0 && pull_count > 0 && !mImageQueue.empty())
- {
- pull_count--;
- LLPointer<LLSpatialGroup> group = mImageQueue.front();
- mImageQueue.pop();
-
- 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);
-
- LLPointer<LLCubeMap> cube_map = group->mReflectionMap;
- group->mReflectionMap = NULL;
- if (cube_map.isNull())
- {
- cube_map = new LLCubeMap();
- cube_map->initGL();
- }
-
- gPipeline.generateReflectionMap(gPipeline.mCubeBuffer, cube_cam);
- gPipeline.blurReflectionMap(gPipeline.mCubeBuffer, cube_map);
- group->mReflectionMap = cube_map;
- group->setState(LLSpatialGroup::GEOM_DIRTY);
- }
-
- group->clearState(LLSpatialGroup::IMAGE_DIRTY);
- }
-}
void pushVerts(LLDrawInfo* params, U32 mask)
{
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);
+ params->mVertexBuffer->drawRange(params->mParticle ? LLRender::POINTS : LLRender::TRIANGLES,
+ params->mStart, params->mEnd, params->mCount, params->mOffset);
}
void pushVerts(LLSpatialGroup* group, U32 mask)
@@ -1926,13 +2280,11 @@ void pushVerts(LLFace* face, U32 mask)
if (buffer)
{
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();
-
- glDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_SHORT, indicesp + offset);
+ buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset);
}
}
@@ -1942,29 +2294,37 @@ void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
if (buffer)
{
buffer->setBuffer(mask);
- U16* indicesp = (U16*) buffer->getIndicesPointer();
- glDrawRangeElements(GL_TRIANGLES, 0, buffer->getRequestedVerts(), buffer->getRequestedIndices(),
- GL_UNSIGNED_SHORT, indicesp);
+ buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getRequestedVerts()-1, buffer->getRequestedIndices(), 0);
}
}
void pushBufferVerts(LLSpatialGroup* group, U32 mask)
{
- if (!group->mDrawMap.empty())
+ if (group->mSpatialPartition->mRenderByGroup)
{
- LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin());
- LLRenderPass::applyModelMatrix(*params);
-
- pushBufferVerts(group->mVertexBuffer, mask);
-
- for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i)
+ if (!group->mDrawMap.empty())
{
- for (LLSpatialGroup::buffer_list_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
+ LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin());
+ LLRenderPass::applyModelMatrix(*params);
+
+ pushBufferVerts(group->mVertexBuffer, mask);
+
+ for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i)
{
- pushBufferVerts(*j, mask);
+ for (LLSpatialGroup::buffer_texture_map_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
+ {
+ for (LLSpatialGroup::buffer_list_t::iterator k = j->second.begin(); k != j->second.end(); ++k)
+ {
+ pushBufferVerts(*k, mask);
+ }
+ }
}
}
}
+ else
+ {
+ drawBox(group->mBounds[0], group->mBounds[1]);
+ }
}
void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)
@@ -1981,7 +2341,7 @@ void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)
LLColor4::green6
};
- static const U32 col_count = sizeof(colors)/sizeof(LLColor4);
+ static const U32 col_count = LL_ARRAY_SIZE(colors);
U32 col = 0;
@@ -1993,9 +2353,8 @@ void pushVertsColorCoded(LLSpatialGroup* group, U32 mask)
LLRenderPass::applyModelMatrix(*params);
glColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f);
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);
+ params->mVertexBuffer->drawRange(params->mParticle ? LLRender::POINTS : LLRender::TRIANGLES,
+ params->mStart, params->mEnd, params->mCount, params->mOffset);
col = (col+1)%col_count;
}
}
@@ -2006,7 +2365,7 @@ void renderOctree(LLSpatialGroup* group)
//render solid object bounding box, color
//coded by buffer usage and activity
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
- gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
+ gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
LLVector4 col;
if (group->mBuilt > 0.f)
{
@@ -2032,7 +2391,7 @@ void renderOctree(LLSpatialGroup* group)
drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
gGL.flush();
glLineWidth(1.f);
- gGL.stop();
+ gGL.flush();
for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
LLDrawable* drawable = *i;
@@ -2064,8 +2423,7 @@ void renderOctree(LLSpatialGroup* group)
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_SHORT,
- ((U16*) face->mVertexBuffer->getIndicesPointer())+face->getIndicesStart());
+ face->mVertexBuffer->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart());
}
}
@@ -2075,7 +2433,7 @@ void renderOctree(LLSpatialGroup* group)
}
}
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- gGL.start();
+ gGL.color4f(1,1,1,1);
}
}
else
@@ -2094,8 +2452,7 @@ void renderOctree(LLSpatialGroup* group)
gGL.color4fv(col.mV);
drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f));
- glDepthMask(GL_TRUE);
- gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
if (group->mBuilt <= 0.f)
{
@@ -2113,6 +2470,23 @@ void renderOctree(LLSpatialGroup* group)
}
drawBoxOutline(group->mBounds[0],group->mBounds[1]);
+
+
+ //draw bounding box for draw info
+ if (group->mSpatialPartition->mRenderByGroup)
+ {
+ gGL.color4f(1.0f, 0.75f, 0.25f, 0.6f);
+ 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)
+ {
+ LLDrawInfo* draw_info = *j;
+ LLVector3 center = (draw_info->mExtents[1] + draw_info->mExtents[0])*0.5f;
+ LLVector3 size = (draw_info->mExtents[1] - draw_info->mExtents[0])*0.5f;
+ drawBoxOutline(center, size);
+ }
+ }
+ }
}
// LLSpatialGroup::OctreeNode* node = group->mOctreeNode;
@@ -2123,16 +2497,17 @@ void renderOctree(LLSpatialGroup* group)
void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
{
LLGLEnable blend(GL_BLEND);
- gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
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)
{
LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER);
glColor4f(0, 0.5f, 0, 0.5f);
+ gGL.color4f(0, 0.5f, 0, 0.5f);
pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
}
@@ -2142,6 +2517,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
if (render_objects)
{
glColor4f(0.f, 0.5f, 0.f,1.f);
+ gGL.color4f(0.f, 0.5f, 0.f, 1.f);
pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
}
@@ -2150,6 +2526,7 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
if (render_objects)
{
glColor4f(0.f, 0.75f, 0.f,0.5f);
+ gGL.color4f(0.f, 0.75f, 0.f, 0.5f);
pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX);
}
else if (camera && group->mOcclusionVerts)
@@ -2158,59 +2535,80 @@ void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
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]));
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_box_fan_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]));
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_box_fan_indices(camera, group->mBounds[0]));
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
}
}
-void renderBoundingBox(LLDrawable* drawable)
+void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color)
{
- if (drawable->isSpatialBridge())
+ gGL.color4fv(color.mV);
+ gGL.begin(LLRender::LINES);
{
- gGL.color4f(1,0.5f,0,1);
+ gGL.vertex3fv((position - LLVector3(size, 0.f, 0.f)).mV);
+ gGL.vertex3fv((position + LLVector3(size, 0.f, 0.f)).mV);
+ gGL.vertex3fv((position - LLVector3(0.f, size, 0.f)).mV);
+ gGL.vertex3fv((position + LLVector3(0.f, size, 0.f)).mV);
+ gGL.vertex3fv((position - LLVector3(0.f, 0.f, size)).mV);
+ gGL.vertex3fv((position + LLVector3(0.f, 0.f, size)).mV);
}
- else if (drawable->getVOVolume())
+ gGL.end();
+}
+
+
+void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
+{
+ if (set_color)
{
- if (drawable->isRoot())
+ if (drawable->isSpatialBridge())
{
- gGL.color4f(1,1,0,1);
+ gGL.color4f(1,0.5f,0,1);
}
- else
+ else if (drawable->getVOVolume())
{
- gGL.color4f(0,1,0,1);
+ if (drawable->isRoot())
+ {
+ gGL.color4f(1,1,0,1);
+ }
+ else
+ {
+ gGL.color4f(0,1,0,1);
+ }
}
- }
- else if (drawable->getVObj())
- {
- switch (drawable->getVObj()->getPCode())
+ else if (drawable->getVObj())
{
- case LLViewerObject::LL_VO_SURFACE_PATCH:
- gGL.color4f(0,1,1,1);
- break;
- case LLViewerObject::LL_VO_CLOUDS:
- gGL.color4f(0.5f,0.5f,0.5f,1.0f);
- break;
- case LLViewerObject::LL_VO_PART_GROUP:
- gGL.color4f(0,0,1,1);
- break;
- case LLViewerObject::LL_VO_WATER:
- gGL.color4f(0,0.5f,1,1);
- break;
- case LL_PCODE_LEGACY_TREE:
- gGL.color4f(0,0.5f,0,1);
- default:
- gGL.color4f(1,0,1,1);
- break;
+ switch (drawable->getVObj()->getPCode())
+ {
+ case LLViewerObject::LL_VO_SURFACE_PATCH:
+ gGL.color4f(0,1,1,1);
+ break;
+ case LLViewerObject::LL_VO_CLOUDS:
+ gGL.color4f(0.5f,0.5f,0.5f,1.0f);
+ break;
+ case LLViewerObject::LL_VO_PART_GROUP:
+ case LLViewerObject::LL_VO_HUD_PART_GROUP:
+ gGL.color4f(0,0,1,1);
+ break;
+ case LLViewerObject::LL_VO_WATER:
+ gGL.color4f(0,0.5f,1,1);
+ break;
+ case LL_PCODE_LEGACY_TREE:
+ gGL.color4f(0,0.5f,0,1);
+ break;
+ default:
+ gGL.color4f(1,0,1,1);
+ break;
+ }
+ }
+ else
+ {
+ gGL.color4f(1,0,0,1);
}
- }
- else
- {
- gGL.color4f(1,0,0,1);
}
const LLVector3* ext;
@@ -2242,7 +2640,9 @@ void renderBoundingBox(LLDrawable* drawable)
if (vobj && vobj->onActiveList())
{
gGL.flush();
- glLineWidth(4.f*sinf(gFrameTimeSeconds*2.f)+1.f);
+ glLineWidth(llmax(4.f*sinf(gFrameTimeSeconds*2.f)+1.f, 1.f));
+ //glLineWidth(4.f*(sinf(gFrameTimeSeconds*2.f)*0.25f+0.75f));
+ stop_glerror();
drawBoxOutline(pos,size);
gGL.flush();
glLineWidth(1.f);
@@ -2268,11 +2668,10 @@ void renderTexturePriority(LLDrawable* drawable)
LLGLDisable blend(GL_BLEND);
- //LLViewerImage* imagep = facep->getTexture();
+ //LLViewerTexture* imagep = facep->getTexture();
//if (imagep)
{
-
- //F32 vsize = LLVOVolume::getTextureVirtualSize(facep);
+
//F32 vsize = imagep->mMaxVirtualSize;
F32 vsize = facep->getPixelArea();
@@ -2296,9 +2695,9 @@ void renderTexturePriority(LLDrawable* drawable)
drawBox(center, size);
/*S32 boost = imagep->getBoostLevel();
- if (boost)
+ if (boost>LLViewerTexture::BOOST_NONE)
{
- F32 t = (F32) boost / (F32) (LLViewerImage::BOOST_MAX_LEVEL-1);
+ F32 t = (F32) boost / (F32) (LLViewerTexture::BOOST_MAX_LEVEL-1);
LLVector4 col = lerp(boost_cold, boost_hot, t);
LLGLEnable blend_on(GL_BLEND);
gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
@@ -2314,7 +2713,7 @@ void renderPoints(LLDrawable* drawablep)
LLGLDepthTest depth(GL_FALSE, GL_FALSE);
if (drawablep->getNumFaces())
{
- gGL.begin(GL_POINTS);
+ gGL.begin(LLRender::POINTS);
gGL.color3f(1,1,1);
LLVector3 center(drawablep->getPositionGroup());
for (S32 i = 0; i < drawablep->getNumFaces(); i++)
@@ -2333,7 +2732,7 @@ void renderTextureAnim(LLDrawInfo* params)
}
LLGLEnable blend(GL_BLEND);
- gGL.color4f(1,1,0,0.5f);
+ glColor4f(1,1,0,0.5f);
pushVerts(params, LLVertexBuffer::MAP_VERTEX);
}
@@ -2343,6 +2742,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())
@@ -2377,6 +2809,83 @@ void renderLights(LLDrawable* drawablep)
}
}
+
+void renderRaycast(LLDrawable* drawablep)
+{
+ if (drawablep->getVObj() != gDebugRaycastObject)
+ {
+ return;
+ }
+
+ if (drawablep->getNumFaces())
+ {
+ LLGLEnable blend(GL_BLEND);
+ gGL.color4f(0,1,1,0.5f);
+
+ if (drawablep->getVOVolume() && gDebugRaycastFaceHit != -1)
+ {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ pushVerts(drawablep->getFace(gDebugRaycastFaceHit), LLVertexBuffer::MAP_VERTEX);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+ else if (drawablep->isAvatar())
+ {
+ LLGLDepthTest depth(GL_FALSE);
+ LLVOAvatar* av = (LLVOAvatar*) drawablep->getVObj().get();
+ av->renderCollisionVolumes();
+ }
+
+ // draw intersection point
+ glPushMatrix();
+ glLoadMatrixd(gGLModelView);
+ LLVector3 translate = gDebugRaycastIntersection;
+ glTranslatef(translate.mV[0], translate.mV[1], translate.mV[2]);
+ LLCoordFrame orient;
+ orient.lookDir(gDebugRaycastNormal, gDebugRaycastBinormal);
+ LLMatrix4 rotation;
+ orient.getRotMatrixToParent(rotation);
+ glMultMatrixf((float*)rotation.mMatrix);
+
+ gGL.color4f(1,0,0,0.5f);
+ drawBox(LLVector3(0, 0, 0), LLVector3(0.1f, 0.022f, 0.022f));
+ gGL.color4f(0,1,0,0.5f);
+ drawBox(LLVector3(0, 0, 0), LLVector3(0.021f, 0.1f, 0.021f));
+ gGL.color4f(0,0,1,0.5f);
+ drawBox(LLVector3(0, 0, 0), LLVector3(0.02f, 0.02f, 0.1f));
+ glPopMatrix();
+
+ // draw bounding box of prim
+ 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(0,0.5f,0.5f,1);
+ drawBoxOutline(pos, size);
+
+ }
+}
+
+
+void renderAvatarCollisionVolumes(LLVOAvatar* avatar)
+{
+ avatar->renderCollisionVolumes();
+}
+
+void renderAgentTarget(LLVOAvatar* avatar)
+{
+ // render these for self only (why, i don't know)
+ if (avatar->isSelf())
+ {
+ renderCrossHairs(avatar->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f));
+ renderCrossHairs(avatar->mDrawable->getPositionAgent(), 0.2f, LLColor4(1, 0, 0, 0.8f));
+ renderCrossHairs(avatar->mRoot.getWorldPosition(), 0.2f, LLColor4(1, 1, 1, 0.8f));
+ renderCrossHairs(avatar->mPelvisp->getWorldPosition(), 0.2f, LLColor4(0, 0, 1, 0.8f));
+ }
+}
+
+
class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable>
{
public:
@@ -2390,30 +2899,39 @@ public:
if (!mCamera || mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]))
{
node->accept(this);
+ stop_glerror();
for (U32 i = 0; i < node->getChildCount(); i++)
{
traverse(node->getChild(i));
+ stop_glerror();
}
//draw tight fit bounding boxes for spatial group
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE))
{
+ group->rebuildGeom();
+ group->rebuildMesh();
+
renderOctree(group);
+ stop_glerror();
}
//render visibility wireframe
- if (group->mSpatialPartition->mRenderByGroup &&
- gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
{
- gGL.stop();
+ group->rebuildGeom();
+ group->rebuildMesh();
+
+ gGL.flush();
glPushMatrix();
gGLLastMatrix = NULL;
glLoadMatrixd(gGLModelView);
renderVisibility(group, mCamera);
+ stop_glerror();
gGLLastMatrix = NULL;
glPopMatrix();
- gGL.start();
+ gGL.color4f(1,1,1,1);
}
}
}
@@ -2422,7 +2940,7 @@ public:
{
LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0);
- if (mCamera && !mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]))
+ if (group->isState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1])))
{
return;
}
@@ -2430,6 +2948,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;
@@ -2439,6 +2970,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);
@@ -2453,6 +2994,24 @@ public:
{
renderLights(drawable);
}
+
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST))
+ {
+ renderRaycast(drawable);
+ }
+
+ LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get());
+
+ if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_VOLUME))
+ {
+ renderAvatarCollisionVolumes(avatar);
+ }
+
+ if (avatar && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AGENT_TARGET))
+ {
+ renderAgentTarget(avatar);
+ }
+
}
for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
@@ -2469,11 +3028,133 @@ public:
{
renderBatchSize(draw_info);
}
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ renderShadowFrusta(draw_info);
+ }
+ }
+ }
+ }
+};
+
+class LLOctreePushBBoxVerts : public LLOctreeTraveler<LLDrawable>
+{
+public:
+ LLCamera* mCamera;
+ LLOctreePushBBoxVerts(LLCamera* camera): mCamera(camera) {}
+
+ virtual void traverse(const LLSpatialGroup::OctreeNode* node)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
+
+ if (!mCamera || mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1]))
+ {
+ node->accept(this);
+
+ for (U32 i = 0; i < node->getChildCount(); i++)
+ {
+ traverse(node->getChild(i));
}
}
}
+
+ virtual void visit(const LLSpatialGroup::OctreeNode* branch)
+ {
+ LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0);
+
+ if (group->isState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1])))
+ {
+ return;
+ }
+
+ for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
+ {
+ LLDrawable* drawable = *i;
+
+ renderBoundingBox(drawable, FALSE);
+ }
+ }
};
+void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera)
+{
+ LLOctreePushBBoxVerts pusher(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 |
@@ -2483,7 +3164,12 @@ void LLSpatialPartition::renderDebug()
LLPipeline::RENDER_DEBUG_BBOXES |
LLPipeline::RENDER_DEBUG_POINTS |
LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY |
- LLPipeline::RENDER_DEBUG_TEXTURE_ANIM))
+ LLPipeline::RENDER_DEBUG_TEXTURE_ANIM |
+ LLPipeline::RENDER_DEBUG_RAYCAST |
+ LLPipeline::RENDER_DEBUG_AVATAR_VOLUME |
+ LLPipeline::RENDER_DEBUG_AGENT_TARGET |
+ LLPipeline::RENDER_DEBUG_BUILD_QUEUE |
+ LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
return;
}
@@ -2491,7 +3177,7 @@ void LLSpatialPartition::renderDebug()
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
{
//sLastMaxTexPriority = lerp(sLastMaxTexPriority, sCurMaxTexPriority, gFrameIntervalSeconds);
- sLastMaxTexPriority = (F32) gCamera->getScreenPixelArea();
+ sLastMaxTexPriority = (F32) LLViewerCamera::getInstance()->getScreenPixelArea();
sCurMaxTexPriority = 0.f;
}
@@ -2499,12 +3185,12 @@ void LLSpatialPartition::renderDebug()
LLGLDisable cullface(GL_CULL_FACE);
LLGLEnable blend(GL_BLEND);
- gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- LLImageGL::unbindTexture(0);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gPipeline.disableLights();
LLSpatialBridge* bridge = asBridge();
- LLCamera* camera = gCamera;
+ LLCamera* camera = LLViewerCamera::getInstance();
if (bridge)
{
@@ -2518,10 +3204,16 @@ 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)
{
- if (!gCamera->sphereInFrustum(v, 4.0f))
+ if (!LLViewerCamera::getInstance()->sphereInFrustum(v, 4.0f))
{
return FALSE;
}
@@ -2529,17 +3221,39 @@ BOOL LLSpatialPartition::isVisible(const LLVector3& v)
return TRUE;
}
-class LLOctreePick : public LLSpatialGroup::OctreeTraveler
+class LLOctreeIntersect : public LLSpatialGroup::OctreeTraveler
{
public:
LLVector3 mStart;
LLVector3 mEnd;
- LLDrawable* mRet;
-
- LLOctreePick(LLVector3 start, LLVector3 end)
- : mStart(start), mEnd(end)
+ S32 *mFaceHit;
+ LLVector3 *mIntersection;
+ LLVector2 *mTexCoord;
+ LLVector3 *mNormal;
+ LLVector3 *mBinormal;
+ LLDrawable* mHit;
+ BOOL mPickTransparent;
+
+ LLOctreeIntersect(LLVector3 start, LLVector3 end, BOOL pick_transparent,
+ S32* face_hit, LLVector3* intersection, LLVector2* tex_coord, LLVector3* normal, LLVector3* binormal)
+ : mStart(start),
+ mEnd(end),
+ mFaceHit(face_hit),
+ mIntersection(intersection),
+ mTexCoord(tex_coord),
+ mNormal(normal),
+ mBinormal(binormal),
+ mHit(NULL),
+ mPickTransparent(pick_transparent)
{
- mRet = NULL;
+ }
+
+ virtual void visit(const LLSpatialGroup::OctreeNode* branch)
+ {
+ for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
+ {
+ check(*i);
+ }
}
virtual LLDrawable* check(const LLSpatialGroup::OctreeNode* node)
@@ -2559,45 +3273,88 @@ public:
size = group->mBounds[1];
center = group->mBounds[0];
- if (LLLineSegmentAABB(mStart, mEnd, center, size))
+ LLVector3 local_start = mStart;
+ LLVector3 local_end = mEnd;
+
+ if (group->mSpatialPartition->isBridge())
+ {
+ LLMatrix4 local_matrix = group->mSpatialPartition->asBridge()->mDrawable->getRenderMatrix();
+ local_matrix.invert();
+
+ local_start = mStart * local_matrix;
+ local_end = mEnd * local_matrix;
+ }
+
+ if (LLLineSegmentBoxIntersect(local_start, local_end, center, size))
{
check(child);
}
}
- return mRet;
+ return mHit;
}
- virtual void visit(const LLSpatialGroup::OctreeNode* branch)
+ virtual bool check(LLDrawable* drawable)
{
- for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
+ LLVector3 local_start = mStart;
+ LLVector3 local_end = mEnd;
+
+ if (!gPipeline.hasRenderType(drawable->getRenderType()) || !drawable->isVisible())
{
- check(*i);
+ return false;
}
- }
- virtual bool check(LLDrawable* drawable)
- {
- LLViewerObject* vobj = drawable->getVObj();
- if (vobj->lineSegmentIntersect(mStart, mEnd))
+ if (drawable->isSpatialBridge())
{
- mRet = vobj->mDrawable;
+ LLSpatialPartition *part = drawable->asPartition();
+ LLSpatialBridge* bridge = part->asBridge();
+ if (bridge && gPipeline.hasRenderType(bridge->mDrawableType))
+ {
+ check(part->mOctree);
+ }
}
-
+ else
+ {
+ LLViewerObject* vobj = drawable->getVObj();
+
+ if (vobj)
+ {
+ LLVector3 intersection;
+ if (vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal))
+ {
+ mEnd = intersection; // shorten ray so we only find CLOSER hits
+ if (mIntersection)
+ {
+ *mIntersection = intersection;
+ }
+
+ mHit = vobj->mDrawable;
+ }
+ }
+ }
+
return false;
}
};
-LLDrawable* LLSpatialPartition::pickDrawable(const LLVector3& start, const LLVector3& end, LLVector3& collision)
+LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
+ BOOL pick_transparent,
+ S32* face_hit, // return the face hit
+ LLVector3* intersection, // return the intersection point
+ LLVector2* tex_coord, // return the texture coordinates of the intersection point
+ LLVector3* normal, // return the surface normal at the intersection point
+ LLVector3* bi_normal // return the surface bi-normal at the intersection point
+ )
+
{
- LLOctreePick pick(start, end);
- LLDrawable* ret = pick.check(mOctree);
- collision.setVec(pick.mEnd);
- return ret;
+ LLOctreeIntersect intersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, bi_normal);
+ LLDrawable* drawable = intersect.check(mOctree);
+
+ return drawable;
}
LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
- LLViewerImage* texture, LLVertexBuffer* buffer,
+ LLViewerTexture* texture, LLVertexBuffer* buffer,
BOOL fullbright, U8 bump, BOOL particle, F32 part_size)
:
mVertexBuffer(buffer),
@@ -2613,14 +3370,36 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,
mParticle(particle),
mPartSize(part_size),
mVSize(0.f),
- mGroup(NULL)
+ mGroup(NULL),
+ mFace(NULL),
+ mDistance(0.f),
+ mDrawMode(LLRender::TRIANGLES)
{
mDebugColor = (rand() << 16) + rand();
+ if (mStart >= mVertexBuffer->getRequestedVerts() ||
+ mEnd >= mVertexBuffer->getRequestedVerts())
+ {
+ llerrs << "Invalid draw info vertex range." << llendl;
+ }
+
+ if (mOffset >= (U32) mVertexBuffer->getRequestedIndices() ||
+ mOffset + mCount > (U32) mVertexBuffer->getRequestedIndices())
+ {
+ llerrs << "Invalid draw info index range." << llendl;
+ }
}
LLDrawInfo::~LLDrawInfo()
{
+ /*if (LLSpatialGroup::sNoDelete)
+ {
+ llerrs << "LLDrawInfo deleted illegally!" << llendl;
+ }*/
+ if (mFace)
+ {
+ mFace->setDrawInfo(NULL);
+ }
}
LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage)
@@ -2636,15 +3415,32 @@ LLCullResult::LLCullResult()
void LLCullResult::clear()
{
mVisibleGroupsSize = 0;
+ mVisibleGroupsEnd = mVisibleGroups.begin();
+
mAlphaGroupsSize = 0;
+ mAlphaGroupsEnd = mAlphaGroups.begin();
+
mOcclusionGroupsSize = 0;
+ mOcclusionGroupsEnd = mOcclusionGroups.begin();
+
mDrawableGroupsSize = 0;
+ mDrawableGroupsEnd = mDrawableGroups.begin();
+
mVisibleListSize = 0;
+ mVisibleListEnd = mVisibleList.begin();
+
mVisibleBridgeSize = 0;
+ mVisibleBridgeEnd = mVisibleBridge.begin();
+
for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++)
{
+ for (U32 j = 0; j < mRenderMapSize[i]; j++)
+ {
+ mRenderMap[i][j] = 0;
+ }
mRenderMapSize[i] = 0;
+ mRenderMapEnd[i] = mRenderMap[i].begin();
}
}
@@ -2655,7 +3451,7 @@ LLCullResult::sg_list_t::iterator LLCullResult::beginVisibleGroups()
LLCullResult::sg_list_t::iterator LLCullResult::endVisibleGroups()
{
- return mVisibleGroups.begin() + mVisibleGroupsSize;
+ return mVisibleGroupsEnd;
}
LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups()
@@ -2665,7 +3461,7 @@ LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups()
LLCullResult::sg_list_t::iterator LLCullResult::endAlphaGroups()
{
- return mAlphaGroups.begin() + mAlphaGroupsSize;
+ return mAlphaGroupsEnd;
}
LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups()
@@ -2675,7 +3471,7 @@ LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups()
LLCullResult::sg_list_t::iterator LLCullResult::endOcclusionGroups()
{
- return mOcclusionGroups.begin() + mOcclusionGroupsSize;
+ return mOcclusionGroupsEnd;
}
LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups()
@@ -2685,7 +3481,7 @@ LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups()
LLCullResult::sg_list_t::iterator LLCullResult::endDrawableGroups()
{
- return mDrawableGroups.begin() + mDrawableGroupsSize;
+ return mDrawableGroupsEnd;
}
LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList()
@@ -2695,7 +3491,7 @@ LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList()
LLCullResult::drawable_list_t::iterator LLCullResult::endVisibleList()
{
- return mVisibleList.begin() + mVisibleListSize;
+ return mVisibleListEnd;
}
LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge()
@@ -2705,7 +3501,7 @@ LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge()
LLCullResult::bridge_list_t::iterator LLCullResult::endVisibleBridge()
{
- return mVisibleBridge.begin() + mVisibleBridgeSize;
+ return mVisibleBridgeEnd;
}
LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type)
@@ -2715,7 +3511,7 @@ LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type)
LLCullResult::drawinfo_list_t::iterator LLCullResult::endRenderMap(U32 type)
{
- return mRenderMap[type].begin() + mRenderMapSize[type];
+ return mRenderMapEnd[type];
}
void LLCullResult::pushVisibleGroup(LLSpatialGroup* group)
@@ -2729,6 +3525,7 @@ void LLCullResult::pushVisibleGroup(LLSpatialGroup* group)
mVisibleGroups.push_back(group);
}
++mVisibleGroupsSize;
+ mVisibleGroupsEnd = mVisibleGroups.begin()+mVisibleGroupsSize;
}
void LLCullResult::pushAlphaGroup(LLSpatialGroup* group)
@@ -2742,6 +3539,7 @@ void LLCullResult::pushAlphaGroup(LLSpatialGroup* group)
mAlphaGroups.push_back(group);
}
++mAlphaGroupsSize;
+ mAlphaGroupsEnd = mAlphaGroups.begin()+mAlphaGroupsSize;
}
void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group)
@@ -2755,6 +3553,7 @@ void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group)
mOcclusionGroups.push_back(group);
}
++mOcclusionGroupsSize;
+ mOcclusionGroupsEnd = mOcclusionGroups.begin()+mOcclusionGroupsSize;
}
void LLCullResult::pushDrawableGroup(LLSpatialGroup* group)
@@ -2768,6 +3567,7 @@ void LLCullResult::pushDrawableGroup(LLSpatialGroup* group)
mDrawableGroups.push_back(group);
}
++mDrawableGroupsSize;
+ mDrawableGroupsEnd = mDrawableGroups.begin()+mDrawableGroupsSize;
}
void LLCullResult::pushDrawable(LLDrawable* drawable)
@@ -2781,6 +3581,7 @@ void LLCullResult::pushDrawable(LLDrawable* drawable)
mVisibleList.push_back(drawable);
}
++mVisibleListSize;
+ mVisibleListEnd = mVisibleList.begin()+mVisibleListSize;
}
void LLCullResult::pushBridge(LLSpatialBridge* bridge)
@@ -2794,6 +3595,7 @@ void LLCullResult::pushBridge(LLSpatialBridge* bridge)
mVisibleBridge.push_back(bridge);
}
++mVisibleBridgeSize;
+ mVisibleBridgeEnd = mVisibleBridge.begin()+mVisibleBridgeSize;
}
void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info)
@@ -2807,10 +3609,20 @@ void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info)
mRenderMap[type].push_back(draw_info);
}
++mRenderMapSize[type];
+ mRenderMapEnd[type] = mRenderMap[type].begin() + mRenderMapSize[type];
}
-
+void LLCullResult::assertDrawMapsEmpty()
+{
+ for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++)
+ {
+ if (mRenderMapSize[i] != 0)
+ {
+ llerrs << "Stale LLDrawInfo's in LLCullResult!" << llendl;
+ }
+ }
+}