diff options
Diffstat (limited to 'indra/newview/llspatialpartition.cpp')
| -rw-r--r-- | indra/newview/llspatialpartition.cpp | 779 | 
1 files changed, 622 insertions, 157 deletions
| diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index f8b824732f..514d8facb4 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -41,13 +41,16 @@  #include "llviewercamera.h"  #include "llface.h"  #include "llviewercontrol.h" -#include "llagent.h"  #include "llviewerregion.h"  #include "llcamera.h"  #include "pipeline.h"  #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");  const F32 SG_OCCLUSION_FUDGE = 0.25f;  #define SG_DISCARD_TOLERANCE 0.01f @@ -86,8 +89,6 @@ protected:  static LLOcclusionQueryPool sQueryPool; -BOOL LLSpatialPartition::sFreezeState = FALSE; -  //static counter for frame to switch LOD on  void sg_assert(BOOL expr) @@ -281,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))  	{ @@ -295,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() @@ -309,17 +433,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() @@ -378,63 +504,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 @@ -468,17 +537,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;  			} @@ -539,7 +608,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); @@ -570,11 +641,22 @@ void LLSpatialGroup::rebuildMesh()  	}  } +static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); +  void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)  { -	if (!gPipeline.hasRenderType(mDrawableType)) +	/*if (!gPipeline.hasRenderType(mDrawableType))  	{  		return; +	}*/ + +	if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) +	{ +		/*if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && mRenderByGroup) +		{ +			llerrs << "WTF?" << llendl; +		}*/ +		return;  	}  	if (group->changeLOD()) @@ -582,13 +664,8 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)  		group->mLastUpdateDistance = group->mDistance;  		group->mLastUpdateViewAngle = group->mViewAngle;  	} - -	if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) -	{ -		return; -	} - -	LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO);	 +	 +	LLFastTimer ftm(FTM_REBUILD_VBO);	  	group->clearDrawMap(); @@ -625,6 +702,7 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)  	group->clearState(LLSpatialGroup::GEOM_DIRTY);  } +  void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group)  { @@ -663,8 +741,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])  				{ @@ -674,7 +755,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO  				{  					newMax.mV[i] = minMax[1].mV[i];  				} -			} +			}*/  		}  		mObjectBounds[0] = (newMin + newMax) * 0.5f; @@ -738,6 +819,10 @@ LLSpatialGroup* LLSpatialGroup::getParent()  		return NULL;  	} +	if(!mOctreeNode) +	{ +		return NULL; +	}  	OctreeNode* parent = mOctreeNode->getOctParent();  	if (parent) @@ -763,6 +848,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) @@ -799,6 +886,7 @@ void LLSpatialGroup::shift(const LLVector3 &offset)  	//if (!mSpatialPartition->mRenderByGroup)  	{  		setState(GEOM_DIRTY); +		gPipeline.markRebuild(this, TRUE);  	}  	if (mOcclusionVerts) @@ -826,7 +914,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); @@ -839,18 +927,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) @@ -885,7 +976,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); @@ -898,20 +989,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) @@ -931,6 +1025,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  //====================================== @@ -942,13 +1158,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); @@ -956,14 +1175,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; @@ -972,13 +1202,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(); @@ -1014,6 +1249,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);  				}  			}  		} @@ -1050,6 +1286,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; @@ -1136,8 +1384,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  	{ @@ -1157,16 +1404,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; @@ -1256,43 +1508,49 @@ BOOL LLSpatialGroup::rebound()  	return TRUE;  } +static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion");  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(LLFastTimer::FTM_OCCLUSION_READBACK); +			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);  		}  	} @@ -1304,19 +1562,19 @@ 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  		{  			{ -				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)) @@ -1324,22 +1582,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; @@ -1351,7 +1620,6 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, U32 buffer_usage)  	mBufferUsage = buffer_usage;  	mDepthMask = FALSE;  	mSlopRatio = 0.25f; -	mRenderByGroup = TRUE;  	mInfiniteFarClip = FALSE;  	LLGLNamePool::registerPool(&sQueryPool); @@ -1388,9 +1656,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; @@ -1489,7 +1757,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; @@ -1498,7 +1766,7 @@ public:  		return false;  	} -	virtual void traverse(const LLSpatialGroup::TreeNode* n) +	virtual void traverse(const LLSpatialGroup::OctreeNode* n)  	{  		LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); @@ -1571,7 +1839,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);  		} @@ -1639,7 +1907,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;  		} @@ -1647,13 +1915,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]);  		}  	} @@ -1671,9 +1983,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;  		} @@ -1852,6 +2164,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; @@ -1871,12 +2189,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 @@ -1891,19 +2206,19 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result  	}  	else if (LLPipeline::sShadowRender)  	{ -		LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL); +		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);  	} @@ -1913,6 +2228,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); @@ -2140,7 +2460,6 @@ 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.setSceneBlendType(LLRender::BT_ALPHA);  	if (group->mBuilt <= 0.f) @@ -2190,7 +2509,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)  	{ @@ -2356,11 +2675,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(); @@ -2384,9 +2702,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); @@ -2431,6 +2749,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()) @@ -2566,6 +2917,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();  			} @@ -2573,6 +2927,9 @@ public:  			//render visibility wireframe  			if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))  			{ +				group->rebuildGeom(); +				group->rebuildMesh(); +  				gGL.flush();  				glPushMatrix();  				gGLLastMatrix = NULL; @@ -2598,6 +2955,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; @@ -2607,6 +2977,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); @@ -2655,6 +3035,10 @@ public:  				{  					renderBatchSize(draw_info);  				} +				if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) +				{ +					renderShadowFrusta(draw_info); +				}  			}  		}  	} @@ -2705,6 +3089,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 | @@ -2717,7 +3174,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;  	} @@ -2752,6 +3211,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)  { @@ -2896,7 +3361,7 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector3& start, con  }  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), @@ -2932,10 +3397,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)  	{ | 
