llspatialpartition.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:84k
源码类别:
游戏引擎
开发平台:
C++ Builder
- /**
- * @file llspatialpartition.cpp
- * @brief LLSpatialGroup class implementation and supporting functions
- *
- * $LicenseInfo:firstyear=2003&license=viewergpl$
- *
- * Copyright (c) 2003-2010, Linden Research, Inc.
- *
- * 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://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * 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://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * 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.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- #include "llspatialpartition.h"
- #include "llviewerwindow.h"
- #include "llviewerobjectlist.h"
- #include "llvovolume.h"
- #include "llvolume.h"
- #include "llviewercamera.h"
- #include "llface.h"
- #include "llviewercontrol.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
- #if LL_OCTREE_PARANOIA_CHECK
- #define assert_octree_valid(x) x->validate()
- #define assert_states_valid(x) ((LLSpatialGroup*) x->mSpatialPartition->mOctree->getListener(0))->checkStates()
- #else
- #define assert_octree_valid(x)
- #define assert_states_valid(x)
- #endif
- static U32 sZombieGroups = 0;
- U32 LLSpatialGroup::sNodeCount = 0;
- BOOL LLSpatialGroup::sNoDelete = FALSE;
- static F32 sLastMaxTexPriority = 1.f;
- static F32 sCurMaxTexPriority = 1.f;
- class LLOcclusionQueryPool : public LLGLNamePool
- {
- protected:
- virtual GLuint allocateName()
- {
- GLuint name;
- glGenQueriesARB(1, &name);
- return name;
- }
- virtual void releaseName(GLuint name)
- {
- glDeleteQueriesARB(1, &name);
- }
- };
- static LLOcclusionQueryPool sQueryPool;
- //static counter for frame to switch LOD on
- void sg_assert(BOOL expr)
- {
- #if LL_OCTREE_PARANOIA_CHECK
- if (!expr)
- {
- llerrs << "Octree invalid!" << llendl;
- }
- #endif
- }
- #if LL_DEBUG
- void validate_drawable(LLDrawable* drawablep)
- {
- F64 rad = drawablep->getBinRadius();
- const LLVector3* ext = drawablep->getSpatialExtents();
- if (rad < 0 || rad > 4096 ||
- (ext[1]-ext[0]).magVec() > 4096)
- {
- llwarns << "Invalid drawable found in octree." << llendl;
- }
- }
- #else
- #define validate_drawable(x)
- #endif
- 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;
- if ((min-origin).magVecSquared() < r &&
- (max-origin).magVecSquared() < r)
- {
- return 2;
- }
- for (U32 i = 0; i < 3; i++)
- {
- if (origin.mV[i] < min.mV[i])
- {
- t = min.mV[i] - origin.mV[i];
- d += t*t;
- }
- else if (origin.mV[i] > max.mV[i])
- {
- t = origin.mV[i] - max.mV[i];
- d += t*t;
- }
- if (d > r)
- {
- return 0;
- }
- }
- return 1;
- }
- typedef enum
- {
- b000 = 0x00,
- b001 = 0x01,
- b010 = 0x02,
- b011 = 0x03,
- b100 = 0x04,
- b101 = 0x05,
- b110 = 0x06,
- b111 = 0x07,
- } eLoveTheBits;
- //contact Runitai Linden for a copy of the SL object used to write this table
- //basically, you give the table a bitmask of the look-at vector to a node and it
- //gives you a triangle fan index array
- static U8 sOcclusionIndices[] =
- {
- // 000
- b111, b110, b010, b011, b001, b101, b100, b110,
- //001
- b110, b000, b010, b011, b111, b101, b100, b000,
- //010
- b101, b100, b110, b111, b011, b001, b000, b100,
- //011
- b100, b010, b110, b111, b101, b001, b000, b010,
- //100
- b011, b010, b000, b001, b101, b111, b110, b010,
- //101
- b010, b100, b000, b001, b011, b111, b110, b100,
- //110
- b001, b000, b100, b101, b111, b011, b010, b000,
- //111
- b000, b110, b100, b101, b001, b011, b010, b110,
- };
- U8* get_box_fan_indices(LLCamera* camera, const LLVector3& center)
- {
- LLVector3 d = center - camera->getOrigin();
- U8 cypher = 0;
- if (d.mV[0] > 0)
- {
- cypher |= b100;
- }
- if (d.mV[1] > 0)
- {
- cypher |= b010;
- }
- if (d.mV[2] > 0)
- {
- cypher |= b001;
- }
- return sOcclusionIndices+cypher*8;
- }
- void LLSpatialGroup::buildOcclusion()
- {
- if (!mOcclusionVerts)
- {
- mOcclusionVerts = new F32[8*3];
- }
- LLVector3 r = mBounds[1] + LLVector3(SG_OCCLUSION_FUDGE, SG_OCCLUSION_FUDGE, SG_OCCLUSION_FUDGE);
- for (U32 k = 0; k < 3; k++)
- {
- r.mV[k] = llmin(mBounds[1].mV[k]+0.25f, r.mV[k]);
- }
- F32* v = mOcclusionVerts;
- F32* c = mBounds[0].mV;
- F32* s = r.mV;
- //vertex positions are encoded so the 3 bits of their vertex index
- //correspond to their axis facing, with bit position 3,2,1 matching
- //axis facing x,y,z, bit set meaning positive facing, bit clear
- //meaning negative facing
- v[0] = c[0]-s[0]; v[1] = c[1]-s[1]; v[2] = c[2]-s[2]; // 0 - 0000
- v[3] = c[0]-s[0]; v[4] = c[1]-s[1]; v[5] = c[2]+s[2]; // 1 - 0001
- v[6] = c[0]-s[0]; v[7] = c[1]+s[1]; v[8] = c[2]-s[2]; // 2 - 0010
- v[9] = c[0]-s[0]; v[10] = c[1]+s[1]; v[11] = c[2]+s[2]; // 3 - 0011
- v[12] = c[0]+s[0]; v[13] = c[1]-s[1]; v[14] = c[2]-s[2]; // 4 - 0100
- v[15] = c[0]+s[0]; v[16] = c[1]-s[1]; v[17] = c[2]+s[2]; // 5 - 0101
- v[18] = c[0]+s[0]; v[19] = c[1]+s[1]; v[20] = c[2]-s[2]; // 6 - 0110
- v[21] = c[0]+s[0]; v[22] = c[1]+s[1]; v[23] = c[2]+s[2]; // 7 - 0111
- clearState(LLSpatialGroup::OCCLUSION_DIRTY);
- }
- BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group);
- //returns:
- // 0 if sphere and AABB are not intersecting
- // 1 if they are
- // 2 if AABB is entirely inside sphere
- S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3& pos, const F32 &rad)
- {
- S32 ret = 2;
- LLVector3 min = center - size;
- LLVector3 max = center + size;
- for (U32 i = 0; i < 3; i++)
- {
- if (min.mV[i] > pos.mV[i] + rad ||
- max.mV[i] < pos.mV[i] - rad)
- { //totally outside
- return 0;
- }
- if (min.mV[i] < pos.mV[i] - rad ||
- max.mV[i] > pos.mV[i] + rad)
- { //intersecting
- ret = 1;
- }
- }
- return ret;
- }
- LLSpatialGroup::~LLSpatialGroup()
- {
- /*if (sNoDelete)
- {
- llerrs << "Illegal deletion of LLSpatialGroup!" << llendl;
- }*/
- if (isState(DEAD))
- {
- sZombieGroups--;
- }
- sNodeCount--;
- if (gGLManager.mHasOcclusionQuery && mOcclusionQuery[LLViewerCamera::sCurCameraID])
- {
- 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()
- {
- mDrawMap.clear();
- }
- BOOL LLSpatialGroup::isRecentlyVisible() const
- {
- return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < LLDrawable::getMinVisFrameRange() ;
- }
- BOOL LLSpatialGroup::isVisible() const
- {
- return mVisible[LLViewerCamera::sCurCameraID] == LLDrawable::getCurrentFrame() ? TRUE : FALSE;
- }
- void LLSpatialGroup::setVisible()
- {
- mVisible[LLViewerCamera::sCurCameraID] = LLDrawable::getCurrentFrame();
- }
- void LLSpatialGroup::validate()
- {
- #if LL_OCTREE_PARANOIA_CHECK
- sg_assert(!isState(DIRTY));
- sg_assert(!isDead());
- LLVector3 myMin = mBounds[0] - mBounds[1];
- LLVector3 myMax = mBounds[0] + mBounds[1];
- validateDrawMap();
- for (element_iter i = getData().begin(); i != getData().end(); ++i)
- {
- LLDrawable* drawable = *i;
- sg_assert(drawable->getSpatialGroup() == this);
- if (drawable->getSpatialBridge())
- {
- sg_assert(drawable->getSpatialBridge() == mSpatialPartition->asBridge());
- }
- /*if (drawable->isSpatialBridge())
- {
- LLSpatialPartition* part = drawable->asPartition();
- if (!part)
- {
- llerrs << "Drawable reports it is a spatial bridge but not a partition." << llendl;
- }
- LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0);
- group->validate();
- }*/
- }
- for (U32 i = 0; i < mOctreeNode->getChildCount(); ++i)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0);
- group->validate();
- //ensure all children are enclosed in this node
- LLVector3 center = group->mBounds[0];
- LLVector3 size = group->mBounds[1];
- LLVector3 min = center - size;
- LLVector3 max = center + size;
- for (U32 j = 0; j < 3; j++)
- {
- sg_assert(min.mV[j] >= myMin.mV[j]-0.02f);
- sg_assert(max.mV[j] <= myMax.mV[j]+0.02f);
- }
- }
- #endif
- }
- void LLSpatialGroup::checkStates()
- {
- #if LL_OCTREE_PARANOIA_CHECK
- LLOctreeStateCheck checker;
- checker.traverse(mOctreeNode);
- #endif
- }
- void validate_draw_info(LLDrawInfo& params)
- {
- #if LL_OCTREE_PARANOIA_CHECK
- if (params.mVertexBuffer.isNull())
- {
- llerrs << "Draw batch has no vertex buffer." << llendl;
- }
- //bad range
- if (params.mStart >= params.mEnd)
- {
- llerrs << "Draw batch has invalid range." << llendl;
- }
- if (params.mEnd >= (U32) params.mVertexBuffer->getNumVerts())
- {
- llerrs << "Draw batch has buffer overrun error." << llendl;
- }
- if (params.mOffset + params.mCount > (U32) params.mVertexBuffer->getNumIndices())
- {
- llerrs << "Draw batch has index buffer ovverrun error." << llendl;
- }
- //bad indices
- U16* indicesp = (U16*) params.mVertexBuffer->getIndicesPointer();
- if (indicesp)
- {
- for (U32 i = params.mOffset; i < params.mOffset+params.mCount; i++)
- {
- if (indicesp[i] < (U16)params.mStart)
- {
- llerrs << "Draw batch has vertex buffer index out of range error (index too low)." << llendl;
- }
- if (indicesp[i] > (U16)params.mEnd)
- {
- llerrs << "Draw batch has vertex buffer index out of range error (index too high)." << llendl;
- }
- }
- }
- #endif
- }
- void LLSpatialGroup::validateDrawMap()
- {
- #if LL_OCTREE_PARANOIA_CHECK
- for (draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i)
- {
- LLSpatialGroup::drawmap_elem_t& draw_vec = i->second;
- for (drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j)
- {
- LLDrawInfo& params = **j;
- validate_draw_info(params);
- }
- }
- #endif
- }
- BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- drawablep->updateSpatialExtents();
- validate_drawable(drawablep);
- OctreeNode* parent = mOctreeNode->getOctParent();
- if (mOctreeNode->isInside(drawablep->getPositionGroup()) &&
- (mOctreeNode->contains(drawablep) ||
- (drawablep->getBinRadius() > mOctreeNode->getSize().mdV[0] &&
- parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY)))
- {
- unbound();
- setState(OBJECT_DIRTY);
- //setState(GEOM_DIRTY);
- validate_drawable(drawablep);
- return TRUE;
- }
- return FALSE;
- }
- BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_octree)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (!from_octree)
- {
- mOctreeNode->insert(drawablep);
- }
- else
- {
- drawablep->setSpatialGroup(this);
- validate_drawable(drawablep);
- 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);
- }
- if (drawablep->getRadius() > 1.f)
- {
- setState(IMAGE_DIRTY);
- }
- }
- return TRUE;
- }
- void LLSpatialGroup::rebuildGeom()
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (!isDead())
- {
- mSpatialPartition->rebuildGeom(this);
- }
- }
- void LLSpatialGroup::rebuildMesh()
- {
- if (!isDead())
- {
- 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;
- }
- if (group->changeLOD())
- {
- group->mLastUpdateDistance = group->mDistance;
- group->mLastUpdateViewAngle = group->mViewAngle;
- }
- LLFastTimer ftm(FTM_REBUILD_VBO);
- group->clearDrawMap();
- //get geometry count
- U32 index_count = 0;
- U32 vertex_count = 0;
- addGeometryCount(group, vertex_count, index_count);
- if (vertex_count > 0 && index_count > 0)
- { //create vertex buffer containing volume geometry for this node
- group->mBuilt = 1.f;
- if (group->mVertexBuffer.isNull() || (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs))
- {
- group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage);
- group->mVertexBuffer->allocateBuffer(vertex_count, index_count, true);
- stop_glerror();
- }
- else
- {
- group->mVertexBuffer->resizeBuffer(vertex_count, index_count);
- stop_glerror();
- }
- getGeometry(group);
- }
- else
- {
- group->mVertexBuffer = NULL;
- group->mBufferMap.clear();
- }
- group->mLastUpdateTime = gFrameTimeSeconds;
- group->clearState(LLSpatialGroup::GEOM_DIRTY);
- }
- void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group)
- {
- }
- BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxOut)
- {
- const OctreeNode* node = mOctreeNode;
- if (node->getData().empty())
- { //don't do anything if there are no objects
- if (empty && mOctreeNode->getParent())
- { //only root is allowed to be empty
- OCT_ERRS << "Empty leaf found in octree." << llendl;
- }
- return FALSE;
- }
- LLVector3& newMin = mObjectExtents[0];
- LLVector3& newMax = mObjectExtents[1];
- if (isState(OBJECT_DIRTY))
- { //calculate new bounding box
- clearState(OBJECT_DIRTY);
- //initialize bounding box to first element
- OctreeNode::const_element_iter i = node->getData().begin();
- LLDrawable* drawablep = *i;
- const LLVector3* minMax = drawablep->getSpatialExtents();
- newMin.setVec(minMax[0]);
- newMax.setVec(minMax[1]);
- for (++i; i != node->getData().end(); ++i)
- {
- 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++)
- {
- if (minMax[0].mV[i] < newMin.mV[i])
- {
- newMin.mV[i] = minMax[0].mV[i];
- }
- if (minMax[1].mV[i] > newMax.mV[i])
- {
- newMax.mV[i] = minMax[1].mV[i];
- }
- }*/
- }
- mObjectBounds[0] = (newMin + newMax) * 0.5f;
- mObjectBounds[1] = (newMax - newMin) * 0.5f;
- }
- if (empty)
- {
- minOut = newMin;
- maxOut = newMax;
- }
- else
- {
- for (U32 i = 0; i < 3; i++)
- {
- if (newMin.mV[i] < minOut.mV[i])
- {
- minOut.mV[i] = newMin.mV[i];
- }
- if (newMax.mV[i] > maxOut.mV[i])
- {
- maxOut.mV[i] = newMax.mV[i];
- }
- }
- }
- return TRUE;
- }
- void LLSpatialGroup::unbound()
- {
- if (isState(DIRTY))
- {
- return;
- }
- setState(DIRTY);
- //all the parent nodes need to rebound this child
- if (mOctreeNode)
- {
- OctreeNode* parent = (OctreeNode*) mOctreeNode->getParent();
- while (parent != NULL)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) parent->getListener(0);
- if (group->isState(DIRTY))
- {
- return;
- }
- group->setState(DIRTY);
- parent = (OctreeNode*) parent->getParent();
- }
- }
- }
- LLSpatialGroup* LLSpatialGroup::getParent()
- {
- if (isDead())
- {
- return NULL;
- }
- if(!mOctreeNode)
- {
- return NULL;
- }
- OctreeNode* parent = mOctreeNode->getOctParent();
- if (parent)
- {
- return (LLSpatialGroup*) parent->getListener(0);
- }
- return NULL;
- }
- BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- unbound();
- if (mOctreeNode && !from_octree)
- {
- if (!mOctreeNode->remove(drawablep))
- {
- OCT_ERRS << "Could not remove drawable from spatial group" << llendl;
- }
- }
- else
- {
- 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)
- {
- if (*i == drawablep)
- {
- mBridgeList.erase(i);
- break;
- }
- }
- }
- if (getElementCount() == 0)
- { //delete draw map on last element removal since a rebuild might never happen
- clearDrawMap();
- }
- }
- return TRUE;
- }
- void LLSpatialGroup::shift(const LLVector3 &offset)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- LLVector3d offsetd(offset);
- mOctreeNode->setCenter(mOctreeNode->getCenter()+offsetd);
- mOctreeNode->updateMinMax();
- mBounds[0] += offset;
- mExtents[0] += offset;
- mExtents[1] += offset;
- mObjectBounds[0] += offset;
- mObjectExtents[0] += offset;
- mObjectExtents[1] += offset;
- //if (!mSpatialPartition->mRenderByGroup)
- {
- setState(GEOM_DIRTY);
- gPipeline.markRebuild(this, TRUE);
- }
- if (mOcclusionVerts)
- {
- for (U32 i = 0; i < 8; i++)
- {
- F32* v = mOcclusionVerts+i*3;
- v[0] += offset.mV[0];
- v[1] += offset.mV[1];
- v[2] += offset.mV[2];
- }
- }
- }
- class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler
- {
- public:
- U32 mState;
- LLSpatialSetState(U32 state) : mState(state) { }
- virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); }
- };
- class LLSpatialSetStateDiff : public LLSpatialSetState
- {
- public:
- LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { }
- virtual void traverse(const LLSpatialGroup::OctreeNode* n)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
- if (!group->isState(mState))
- {
- LLSpatialGroup::OctreeTraveler::traverse(n);
- }
- }
- };
- void LLSpatialGroup::setState(U32 state)
- {
- mState |= state;
- if (state > LLSpatialGroup::STATE_MASK)
- {
- llerrs << "WTF?" << llendl;
- }
- }
- void LLSpatialGroup::setState(U32 state, S32 mode)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (state > LLSpatialGroup::STATE_MASK)
- {
- llerrs << "WTF?" << llendl;
- }
- if (mode > STATE_MODE_SINGLE)
- {
- if (mode == STATE_MODE_DIFF)
- {
- LLSpatialSetStateDiff setter(state);
- setter.traverse(mOctreeNode);
- }
- else
- {
- LLSpatialSetState setter(state);
- setter.traverse(mOctreeNode);
- }
- }
- else
- {
- mState |= state;
- }
- }
- class LLSpatialClearState : public LLSpatialGroup::OctreeTraveler
- {
- public:
- U32 mState;
- LLSpatialClearState(U32 state) : mState(state) { }
- virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); }
- };
- class LLSpatialClearStateDiff : public LLSpatialClearState
- {
- public:
- LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { }
- virtual void traverse(const LLSpatialGroup::OctreeNode* n)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
- if (group->isState(mState))
- {
- LLSpatialGroup::OctreeTraveler::traverse(n);
- }
- }
- };
- void LLSpatialGroup::clearState(U32 state)
- {
- if (state > LLSpatialGroup::STATE_MASK)
- {
- llerrs << "WTF?" << llendl;
- }
- mState &= ~state;
- }
- void LLSpatialGroup::clearState(U32 state, S32 mode)
- {
- if (state > LLSpatialGroup::STATE_MASK)
- {
- llerrs << "WTF?" << llendl;
- }
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (mode > STATE_MODE_SINGLE)
- {
- if (mode == STATE_MODE_DIFF)
- {
- LLSpatialClearStateDiff clearer(state);
- clearer.traverse(mOctreeNode);
- }
- else
- {
- LLSpatialClearState clearer(state);
- clearer.traverse(mOctreeNode);
- }
- }
- else
- {
- mState &= ~state;
- }
- }
- 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
- //======================================
- LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
- mState(0),
- mBuilt(0.f),
- mOctreeNode(node),
- mSpatialPartition(part),
- mVertexBuffer(NULL),
- mBufferUsage(GL_STATIC_DRAW_ARB),
- mDistance(0.f),
- mDepth(0.f),
- mLastUpdateDistance(-1.f),
- mLastUpdateTime(gFrameTimeSeconds),
- mViewAngle(0.f),
- mLastUpdateViewAngle(-1.f),
- mAtlasList(4),
- mCurUpdatingTime(0),
- mCurUpdatingSlotp(NULL),
- mCurUpdatingTexture (NULL)
- {
- sNodeCount++;
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- 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;
- 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;
- mPixelArea = 1024.f;
- }
- 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())
- {
- mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() :
- (F32) mOctreeNode->getSize().magVec();
- mDistance = mSpatialPartition->calcDistance(this, camera);
- mPixelArea = mSpatialPartition->calcPixelArea(this, camera);
- }
- }
- F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera)
- {
- LLVector3 eye = group->mObjectBounds[0] - camera.getOrigin();
- F32 dist = 0.f;
- if (group->mDrawMap.find(LLRenderPass::PASS_ALPHA) != group->mDrawMap.end())
- {
- LLVector3 v = eye;
- dist = eye.normVec();
- if (!group->isState(LLSpatialGroup::ALPHA_DIRTY))
- {
- if (!group->mSpatialPartition->isBridge())
- {
- LLVector3 view_angle = LLVector3(eye * LLVector3(1,0,0),
- eye * LLVector3(0,1,0),
- eye * LLVector3(0,0,1));
- if ((view_angle-group->mLastUpdateViewAngle).magVec() > 0.64f)
- {
- group->mViewAngle = view_angle;
- group->mLastUpdateViewAngle = view_angle;
- //for occasional alpha sorting within the group
- //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order,
- //not setting this node to dirty would be a very good thing
- group->setState(LLSpatialGroup::ALPHA_DIRTY);
- gPipeline.markRebuild(group, FALSE);
- }
- }
- }
- //calculate depth of node for alpha sorting
- LLVector3 at = camera.getAtAxis();
- //front of bounding box
- for (U32 i = 0; i < 3; i++)
- {
- v.mV[i] -= group->mObjectBounds[1].mV[i]*0.25f * at.mV[i];
- }
- group->mDepth = v * at;
- }
- else
- {
- dist = eye.magVec();
- }
- if (dist < 16.f)
- {
- dist /= 16.f;
- dist *= dist;
- dist *= 16.f;
- }
- return dist;
- }
- 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;
- }
- BOOL LLSpatialGroup::changeLOD()
- {
- if (isState(ALPHA_DIRTY))
- { ///an alpha sort is going to happen, update distance and LOD
- return TRUE;
- }
- if (mSpatialPartition->mSlopRatio > 0.f)
- {
- F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius));
- if (fabsf(ratio) >= mSpatialPartition->mSlopRatio)
- {
- return TRUE;
- }
- if (mDistance > mRadius)
- {
- return FALSE;
- }
- }
- if (needsUpdate())
- {
- return TRUE;
- }
- return FALSE;
- }
- void LLSpatialGroup::handleInsertion(const TreeNode* node, LLDrawable* drawablep)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- addObject(drawablep, FALSE, TRUE);
- unbound();
- setState(OBJECT_DIRTY);
- }
- void LLSpatialGroup::handleRemoval(const TreeNode* node, LLDrawable* drawable)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- removeObject(drawable, TRUE);
- setState(OBJECT_DIRTY);
- }
- void LLSpatialGroup::handleDestruction(const TreeNode* node)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- setState(DEAD);
- for (element_iter i = getData().begin(); i != getData().end(); ++i)
- {
- LLDrawable* drawable = *i;
- if (drawable->getSpatialGroup() == this)
- {
- drawable->setSpatialGroup(NULL);
- }
- }
- clearDrawMap();
- mVertexBuffer = NULL;
- mBufferMap.clear();
- sZombieGroups++;
- mOctreeNode = NULL;
- }
- void LLSpatialGroup::handleStateChange(const TreeNode* node)
- {
- //drop bounding box upon state change
- if (mOctreeNode != node)
- {
- mOctreeNode = (OctreeNode*) node;
- }
- unbound();
- }
- void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- if (child->getListenerCount() == 0)
- {
- new LLSpatialGroup(child, mSpatialPartition);
- }
- else
- {
- OCT_ERRS << "LLSpatialGroup redundancy detected." << llendl;
- }
- unbound();
- assert_states_valid(this);
- }
- void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNode* child)
- {
- unbound();
- }
- void LLSpatialGroup::destroyGL()
- {
- setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY);
- gPipeline.markRebuild(this, TRUE);
- mLastUpdateTime = gFrameTimeSeconds;
- mVertexBuffer = NULL;
- mBufferMap.clear();
- clearDrawMap();
- for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
- {
- if (mOcclusionQuery[i])
- {
- sQueryPool.release(mOcclusionQuery[i]);
- mOcclusionQuery[i] = 0;
- }
- }
- delete [] mOcclusionVerts;
- mOcclusionVerts = NULL;
- for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i)
- {
- LLDrawable* drawable = *i;
- for (S32 j = 0; j < drawable->getNumFaces(); j++)
- {
- LLFace* facep = drawable->getFace(j);
- facep->mVertexBuffer = NULL;
- facep->mLastVertexBuffer = NULL;
- }
- }
- }
- BOOL LLSpatialGroup::rebound()
- {
- if (!isState(DIRTY))
- { //return TRUE if we're not empty
- return TRUE;
- }
- if (mOctreeNode->getChildCount() == 1 && mOctreeNode->getElementCount() == 0)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0);
- group->rebound();
- //copy single child's bounding box
- mBounds[0] = group->mBounds[0];
- mBounds[1] = group->mBounds[1];
- mExtents[0] = group->mExtents[0];
- mExtents[1] = group->mExtents[1];
- group->setState(SKIP_FRUSTUM_CHECK);
- }
- else if (mOctreeNode->isLeaf())
- { //copy object bounding box if this is a leaf
- boundObjects(TRUE, mExtents[0], mExtents[1]);
- mBounds[0] = mObjectBounds[0];
- mBounds[1] = mObjectBounds[1];
- }
- else
- {
- LLVector3& newMin = mExtents[0];
- LLVector3& newMax = mExtents[1];
- LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0);
- group->clearState(SKIP_FRUSTUM_CHECK);
- group->rebound();
- //initialize to first child
- newMin = group->mExtents[0];
- newMax = group->mExtents[1];
- //first, rebound children
- for (U32 i = 1; i < mOctreeNode->getChildCount(); i++)
- {
- group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0);
- group->clearState(SKIP_FRUSTUM_CHECK);
- group->rebound();
- const LLVector3& max = group->mExtents[1];
- const LLVector3& min = group->mExtents[0];
- for (U32 j = 0; j < 3; j++)
- {
- if (max.mV[j] > newMax.mV[j])
- {
- newMax.mV[j] = max.mV[j];
- }
- if (min.mV[j] < newMin.mV[j])
- {
- newMin.mV[j] = min.mV[j];
- }
- }
- }
- boundObjects(FALSE, newMin, newMax);
- mBounds[0] = (newMin + newMax)*0.5f;
- mBounds[1] = (newMax - newMin)*0.5f;
- }
- setState(OCCLUSION_DIRTY);
- clearState(DIRTY);
- return TRUE;
- }
- static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion");
- void LLSpatialGroup::checkOcclusion()
- {
- if (LLPipeline::sUseOcclusion > 1)
- {
- LLSpatialGroup* parent = getParent();
- if (parent && parent->isOcclusionState(LLSpatialGroup::OCCLUDED))
- { //if the parent has been marked as occluded, the child is implicitly occluded
- clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
- }
- else if (isOcclusionState(QUERY_PENDING))
- { //otherwise, if a query is pending, read it back
- LLFastTimer t(FTM_OCCLUSION_READBACK);
- GLuint res = 1;
- if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
- {
- glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res);
- }
- if (isOcclusionState(DISCARD_QUERY))
- {
- res = 2;
- }
- if (res > 0)
- {
- assert_states_valid(this);
- clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
- assert_states_valid(this);
- }
- else
- {
- assert_states_valid(this);
- setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
- assert_states_valid(this);
- }
- clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
- }
- 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);
- clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
- assert_states_valid(this);
- }
- }
- }
- void LLSpatialGroup::doOcclusion(LLCamera* camera)
- {
- if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1)
- {
- if (earlyFail(camera, this))
- {
- setOcclusionState(LLSpatialGroup::DISCARD_QUERY);
- assert_states_valid(this);
- clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF);
- assert_states_valid(this);
- }
- else
- {
- {
- LLFastTimer t(FTM_RENDER_OCCLUSION);
- if (!mOcclusionQuery[LLViewerCamera::sCurCameraID])
- {
- mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate();
- }
- if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY))
- {
- buildOcclusion();
- }
- glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
- glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts);
- 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);
- }
- setOcclusionState(LLSpatialGroup::QUERY_PENDING);
- clearOcclusionState(LLSpatialGroup::DISCARD_QUERY);
- }
- }
- }
- //==============================================
- LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage)
- : mRenderByGroup(render_by_group)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- mOcclusionEnabled = TRUE;
- mDrawableType = 0;
- mPartitionType = LLViewerRegion::PARTITION_NONE;
- mLODSeed = 0;
- mLODPeriod = 1;
- mVertexDataMask = data_mask;
- mBufferUsage = buffer_usage;
- mDepthMask = FALSE;
- mSlopRatio = 0.25f;
- mInfiniteFarClip = FALSE;
- LLGLNamePool::registerPool(&sQueryPool);
- mOctree = new LLSpatialGroup::OctreeRoot(LLVector3d(0,0,0),
- LLVector3d(1,1,1),
- NULL);
- new LLSpatialGroup(mOctree, this);
- }
- LLSpatialPartition::~LLSpatialPartition()
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- delete mOctree;
- mOctree = NULL;
- }
- LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- drawablep->updateSpatialExtents();
- validate_drawable(drawablep);
- //keep drawable from being garbage collected
- LLPointer<LLDrawable> ptr = drawablep;
- assert_octree_valid(mOctree);
- mOctree->insert(drawablep);
- assert_octree_valid(mOctree);
- LLSpatialGroup* group = drawablep->getSpatialGroup();
- if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING))
- {
- group->setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS);
- }
- return group;
- }
- BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- drawablep->setSpatialGroup(NULL);
- if (!curp->removeObject(drawablep))
- {
- OCT_ERRS << "Failed to remove drawable from octree!" << llendl;
- }
- assert_octree_valid(mOctree);
- return TRUE;
- }
- void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate)
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- // sanity check submitted by open source user bushing Spatula
- // who was seeing crashing here. (See VWR-424 reported by Bunny Mayne)
- if (!drawablep)
- {
- OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << llendl;
- return;
- }
- BOOL was_visible = curp ? curp->isVisible() : FALSE;
- if (curp && curp->mSpatialPartition != this)
- {
- //keep drawable from being garbage collected
- LLPointer<LLDrawable> ptr = drawablep;
- if (curp->mSpatialPartition->remove(drawablep, curp))
- {
- put(drawablep, was_visible);
- return;
- }
- else
- {
- OCT_ERRS << "Drawable lost between spatial partitions on outbound transition." << llendl;
- }
- }
- if (curp && curp->updateInGroup(drawablep, immediate))
- {
- // Already updated, don't need to do anything
- assert_octree_valid(mOctree);
- return;
- }
- //keep drawable from being garbage collected
- LLPointer<LLDrawable> ptr = drawablep;
- if (curp && !remove(drawablep, curp))
- {
- OCT_ERRS << "Move couldn't find existing spatial group!" << llendl;
- }
- put(drawablep, was_visible);
- }
- class LLSpatialShift : public LLSpatialGroup::OctreeTraveler
- {
- public:
- LLSpatialShift(LLVector3 offset) : mOffset(offset) { }
- virtual void visit(const LLSpatialGroup::OctreeNode* branch)
- {
- ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset);
- }
- LLVector3 mOffset;
- };
- void LLSpatialPartition::shift(const LLVector3 &offset)
- { //shift octree node bounding boxes by offset
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- LLSpatialShift shifter(offset);
- shifter.traverse(mOctree);
- }
- class LLOctreeCull : public LLSpatialGroup::OctreeTraveler
- {
- public:
- LLOctreeCull(LLCamera* camera)
- : mCamera(camera), mRes(0) { }
- virtual bool earlyFail(LLSpatialGroup* group)
- {
- group->checkOcclusion();
- if (group->mOctreeNode->getParent() && //never occlusion cull the root node
- LLPipeline::sUseOcclusion && //ignore occlusion if disabled
- group->isOcclusionState(LLSpatialGroup::OCCLUDED))
- {
- gPipeline.markOccluder(group);
- return true;
- }
- return false;
- }
- virtual void traverse(const LLSpatialGroup::OctreeNode* n)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0);
- if (earlyFail(group))
- {
- return;
- }
- if (mRes == 2 ||
- (mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)))
- { //fully in, just add everything
- LLSpatialGroup::OctreeTraveler::traverse(n);
- }
- else
- {
- mRes = frustumCheck(group);
- if (mRes)
- { //at least partially in, run on down
- LLSpatialGroup::OctreeTraveler::traverse(n);
- }
- mRes = 0;
- }
- }
- virtual S32 frustumCheck(const LLSpatialGroup* group)
- {
- S32 res = mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]);
- if (res != 0)
- {
- res = llmin(res, AABBSphereIntersect(group->mExtents[0], group->mExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist));
- }
- return res;
- }
- virtual S32 frustumCheckObjects(const LLSpatialGroup* group)
- {
- S32 res = mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]);
- if (res != 0)
- {
- res = llmin(res, AABBSphereIntersect(group->mObjectExtents[0], group->mObjectExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist));
- }
- return res;
- }
- virtual bool checkObjects(const LLSpatialGroup::OctreeNode* branch, const LLSpatialGroup* group)
- {
- if (branch->getElementCount() == 0) //no elements
- {
- return false;
- }
- else if (branch->getChildCount() == 0) //leaf state, already checked tightest bounding box
- {
- return true;
- }
- else if (mRes == 1 && !frustumCheckObjects(group)) //no objects in frustum
- {
- return false;
- }
- return true;
- }
- virtual void preprocess(LLSpatialGroup* group)
- {
- }
- virtual void processGroup(LLSpatialGroup* group)
- {
- if (group->needsUpdate() ||
- group->mVisible[LLViewerCamera::sCurCameraID] < LLDrawable::getCurrentFrame() - 1)
- {
- group->doOcclusion(mCamera);
- }
- gPipeline.markNotCulled(group, *mCamera);
- }
- virtual void visit(const LLSpatialGroup::OctreeNode* branch)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0);
- preprocess(group);
- if (checkObjects(branch, group))
- {
- processGroup(group);
- }
- }
- LLCamera *mCamera;
- S32 mRes;
- };
- class LLOctreeCullNoFarClip : public LLOctreeCull
- {
- public:
- LLOctreeCullNoFarClip(LLCamera* camera)
- : LLOctreeCull(camera) { }
- virtual S32 frustumCheck(const LLSpatialGroup* group)
- {
- return mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]);
- }
- 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 == 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->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
- {
- public:
- LLOctreeSelect(LLCamera* camera, std::vector<LLDrawable*>* results)
- : LLOctreeCull(camera), mResults(results) { }
- virtual bool earlyFail(LLSpatialGroup* group) { return false; }
- virtual void preprocess(LLSpatialGroup* group) { }
- virtual void processGroup(LLSpatialGroup* group)
- {
- LLSpatialGroup::OctreeNode* branch = group->mOctreeNode;
- for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i)
- {
- LLDrawable* drawable = *i;
- if (!drawable->isDead())
- {
- if (drawable->isSpatialBridge())
- {
- drawable->setVisible(*mCamera, mResults, TRUE);
- }
- else
- {
- mResults->push_back(drawable);
- }
- }
- }
- }
- std::vector<LLDrawable*>* mResults;
- };
- void drawBox(const LLVector3& c, const LLVector3& r)
- {
- 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);
- //right front
- gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,-1))).mV);
- gGL.vertex3fv((c+r.scaledVec(LLVector3(1,1,1))).mV);
- //right back
- gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,-1))).mV);
- gGL.vertex3fv((c+r.scaledVec(LLVector3(1,-1,1))).mV);
- //left back
- gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV);
- gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV);
- //left front
- gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV);
- gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,1))).mV);
- gGL.end();
- //bottom
- 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);
- gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,-1))).mV);
- gGL.end();
- //top
- 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);
- gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,-1,1))).mV);
- gGL.end();
- }
- void drawBoxOutline(const LLVector3& pos, const LLVector3& size)
- {
- LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1));
- LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1));
- LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1));
- LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1));
- gGL.begin(LLRender::LINES);
- //top
- gGL.vertex3fv((pos+v1).mV);
- gGL.vertex3fv((pos+v2).mV);
- gGL.vertex3fv((pos+v2).mV);
- gGL.vertex3fv((pos+v3).mV);
- gGL.vertex3fv((pos+v3).mV);
- gGL.vertex3fv((pos+v4).mV);
- gGL.vertex3fv((pos+v4).mV);
- gGL.vertex3fv((pos+v1).mV);
- //bottom
- gGL.vertex3fv((pos-v1).mV);
- gGL.vertex3fv((pos-v2).mV);
- gGL.vertex3fv((pos-v2).mV);
- gGL.vertex3fv((pos-v3).mV);
- gGL.vertex3fv((pos-v3).mV);
- gGL.vertex3fv((pos-v4).mV);
- gGL.vertex3fv((pos-v4).mV);
- gGL.vertex3fv((pos-v1).mV);
- //right
- gGL.vertex3fv((pos+v1).mV);
- gGL.vertex3fv((pos-v3).mV);
- gGL.vertex3fv((pos+v4).mV);
- gGL.vertex3fv((pos-v2).mV);
- //left
- gGL.vertex3fv((pos+v2).mV);
- gGL.vertex3fv((pos-v4).mV);
- gGL.vertex3fv((pos+v3).mV);
- gGL.vertex3fv((pos-v1).mV);
- gGL.end();
- }
- class LLOctreeDirty : public LLOctreeTraveler<LLDrawable>
- {
- public:
- virtual void visit(const LLOctreeNode<LLDrawable>* state)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
- group->destroyGL();
- for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
- {
- LLDrawable* drawable = *i;
- if (drawable->getVObj().notNull() && !group->mSpatialPartition->mRenderByGroup)
- {
- gPipeline.markRebuild(drawable, LLDrawable::REBUILD_ALL, TRUE);
- }
- }
- for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
- {
- LLSpatialBridge* bridge = *i;
- traverse(bridge->mOctree);
- }
- }
- };
- void LLSpatialPartition::restoreGL()
- {
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- }
- void LLSpatialPartition::resetVertexBuffers()
- {
- LLOctreeDirty dirty;
- 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);
- #if LL_OCTREE_PARANOIA_CHECK
- ((LLSpatialGroup*)mOctree->getListener(0))->checkStates();
- #endif
- {
- LLFastTimer ftm(FTM_CULL_REBOUND);
- LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0);
- group->rebound();
- }
- #if LL_OCTREE_PARANOIA_CHECK
- ((LLSpatialGroup*)mOctree->getListener(0))->validate();
- #endif
- if (for_select)
- {
- 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(FTM_FRUSTUM_CULL);
- LLOctreeCullNoFarClip culler(&camera);
- culler.traverse(mOctree);
- }
- else
- {
- LLFastTimer ftm(FTM_FRUSTUM_CULL);
- LLOctreeCull culler(&camera);
- culler.traverse(mOctree);
- }
- return 0;
- }
- 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);
- /*if (r.magVecSquared() > 1024.0*1024.0)
- {
- return TRUE;
- }*/
- LLVector3 e = camera->getOrigin();
- LLVector3 min = c - r;
- LLVector3 max = c + r;
- for (U32 j = 0; j < 3; j++)
- {
- if (e.mV[j] < min.mV[j] || e.mV[j] > max.mV[j])
- {
- return FALSE;
- }
- }
- return TRUE;
- }
- void pushVerts(LLDrawInfo* params, U32 mask)
- {
- LLRenderPass::applyModelMatrix(*params);
- params->mVertexBuffer->setBuffer(mask);
- params->mVertexBuffer->drawRange(params->mParticle ? LLRender::POINTS : LLRender::TRIANGLES,
- params->mStart, params->mEnd, params->mCount, params->mOffset);
- }
- void pushVerts(LLSpatialGroup* group, U32 mask)
- {
- LLDrawInfo* params = NULL;
- for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
- {
- for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
- {
- params = *j;
- pushVerts(params, mask);
- }
- }
- }
- void pushVerts(LLFace* face, U32 mask)
- {
- LLVertexBuffer* buffer = face->mVertexBuffer;
- if (buffer)
- {
- buffer->setBuffer(mask);
- U16 start = face->getGeomStart();
- U16 end = start + face->getGeomCount()-1;
- U32 count = face->getIndicesCount();
- U16 offset = face->getIndicesStart();
- buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset);
- }
- }
- void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
- {
- if (buffer)
- {
- buffer->setBuffer(mask);
- buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getRequestedVerts()-1, buffer->getRequestedIndices(), 0);
- }
- }
- void pushBufferVerts(LLSpatialGroup* group, U32 mask)
- {
- if (group->mSpatialPartition->mRenderByGroup)
- {
- if (!group->mDrawMap.empty())
- {
- 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)
- {
- 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)
- {
- LLDrawInfo* params = NULL;
- LLColor4 colors[] = {
- LLColor4::green,
- LLColor4::green1,
- LLColor4::green2,
- LLColor4::green3,
- LLColor4::green4,
- LLColor4::green5,
- LLColor4::green6
- };
- static const U32 col_count = LL_ARRAY_SIZE(colors);
- U32 col = 0;
- for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
- {
- for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j)
- {
- params = *j;
- LLRenderPass::applyModelMatrix(*params);
- glColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f);
- params->mVertexBuffer->setBuffer(mask);
- params->mVertexBuffer->drawRange(params->mParticle ? LLRender::POINTS : LLRender::TRIANGLES,
- params->mStart, params->mEnd, params->mCount, params->mOffset);
- col = (col+1)%col_count;
- }
- }
- }
- void renderOctree(LLSpatialGroup* group)
- {
- //render solid object bounding box, color
- //coded by buffer usage and activity
- LLGLDepthTest depth(GL_TRUE, GL_FALSE);
- gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
- LLVector4 col;
- if (group->mBuilt > 0.f)
- {
- group->mBuilt -= 2.f * gFrameIntervalSeconds;
- if (group->mBufferUsage == GL_STATIC_DRAW_ARB)
- {
- col.setVec(1.0f, 0, 0, group->mBuilt*0.5f);
- }
- else
- {
- col.setVec(0.1f,0.1f,1,0.1f);
- //col.setVec(1.0f, 1.0f, 0, sinf(group->mBuilt*3.14159f)*0.5f);
- }
- if (group->mBufferUsage != GL_STATIC_DRAW_ARB)
- {
- LLGLDepthTest gl_depth(FALSE, FALSE);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- gGL.color4f(1,0,0,group->mBuilt);
- gGL.flush();
- glLineWidth(5.f);
- drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
- gGL.flush();
- glLineWidth(1.f);
- gGL.flush();
- for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
- {
- LLDrawable* drawable = *i;
- if (!group->mSpatialPartition->isBridge())
- {
- glPushMatrix();
- LLVector3 trans = drawable->getRegion()->getOriginAgent();
- glTranslatef(trans.mV[0], trans.mV[1], trans.mV[2]);
- }
- for (S32 j = 0; j < drawable->getNumFaces(); j++)
- {
- LLFace* face = drawable->getFace(j);
- if (face->mVertexBuffer.notNull())
- {
- if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f)
- {
- glColor4f(0, 1, 0, group->mBuilt);
- }
- else if (gFrameTimeSeconds - face->mLastMoveTime < 0.5f)
- {
- glColor4f(1, 0, 0, group->mBuilt);
- }
- else
- {
- continue;
- }
- face->mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX);
- //drawBox((face->mExtents[0] + face->mExtents[1])*0.5f,
- // (face->mExtents[1]-face->mExtents[0])*0.5f);
- face->mVertexBuffer->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart());
- }
- }
- if (!group->mSpatialPartition->isBridge())
- {
- glPopMatrix();
- }
- }
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- gGL.color4f(1,1,1,1);
- }
- }
- else
- {
- if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->getData().empty()
- && group->mSpatialPartition->mRenderByGroup)
- {
- col.setVec(0.8f, 0.4f, 0.1f, 0.1f);
- }
- else
- {
- col.setVec(0.1f, 0.1f, 1.f, 0.1f);
- }
- }
- gGL.color4fv(col.mV);
- drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f));
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- if (group->mBuilt <= 0.f)
- {
- //draw opaque outline
- gGL.color4f(col.mV[0], col.mV[1], col.mV[2], 1.f);
- drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]);
- if (group->mOctreeNode->isLeaf())
- {
- gGL.color4f(1,1,1,1);
- }
- else
- {
- gGL.color4f(0,1,1,1);
- }
- drawBoxOutline(group->mBounds[0],group->mBounds[1]);
- //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;
- // gGL.color4f(0,1,0,1);
- // drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize()));
- }
- void renderVisibility(LLSpatialGroup* group, LLCamera* camera)
- {
- LLGLEnable blend(GL_BLEND);
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- LLGLEnable cull(GL_CULL_FACE);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- 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);
- }
- {
- LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL);
- 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);
- }
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- 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)
- {
- LLVertexBuffer::unbind();
- glVertexPointer(3, GL_FLOAT, 0, group->mOcclusionVerts);
- glColor4f(1.0f, 0.f, 0.f, 0.5f);
- glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, GL_UNSIGNED_BYTE, get_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_box_fan_indices(camera, group->mBounds[0]));
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- }
- }
- }
- void renderCrossHairs(LLVector3 position, F32 size, LLColor4 color)
- {
- gGL.color4fv(color.mV);
- gGL.begin(LLRender::LINES);
- {
- 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);
- }
- gGL.end();
- }
- void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
- {
- if (set_color)
- {
- if (drawable->isSpatialBridge())
- {
- gGL.color4f(1,0.5f,0,1);
- }
- else if (drawable->getVOVolume())
- {
- if (drawable->isRoot())
- {
- gGL.color4f(1,1,0,1);
- }
- else
- {
- gGL.color4f(0,1,0,1);
- }
- }
- else if (drawable->getVObj())
- {
- 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);
- }
- }
- const LLVector3* ext;
- LLVector3 pos, size;
- //render face bounding boxes
- for (S32 i = 0; i < drawable->getNumFaces(); i++)
- {
- LLFace* facep = drawable->getFace(i);
- ext = facep->mExtents;
- if (ext[0].isExactlyZero() && ext[1].isExactlyZero())
- {
- continue;
- }
- pos = (ext[0] + ext[1]) * 0.5f;
- size = (ext[1] - ext[0]) * 0.5f;
- drawBoxOutline(pos,size);
- }
- //render drawable bounding box
- ext = drawable->getSpatialExtents();
- pos = (ext[0] + ext[1]) * 0.5f;
- size = (ext[1] - ext[0]) * 0.5f;
- LLViewerObject* vobj = drawable->getVObj();
- if (vobj && vobj->onActiveList())
- {
- gGL.flush();
- 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);
- }
- else
- {
- drawBoxOutline(pos,size);
- }
- }
- void renderTexturePriority(LLDrawable* drawable)
- {
- for (int face=0; face<drawable->getNumFaces(); ++face)
- {
- LLFace *facep = drawable->getFace(face);
- LLVector4 cold(0,0,0.25f);
- LLVector4 hot(1,0.25f,0.25f);
- LLVector4 boost_cold(0,0,0,0);
- LLVector4 boost_hot(0,1,0,1);
- LLGLDisable blend(GL_BLEND);
- //LLViewerTexture* imagep = facep->getTexture();
- //if (imagep)
- {
- //F32 vsize = imagep->mMaxVirtualSize;
- F32 vsize = facep->getPixelArea();
- if (vsize > sCurMaxTexPriority)
- {
- sCurMaxTexPriority = vsize;
- }
- F32 t = vsize/sLastMaxTexPriority;
- LLVector4 col = lerp(cold, hot, t);
- gGL.color4fv(col.mV);
- }
- //else
- //{
- // gGL.color4f(1,0,1,1);
- //}
- LLVector3 center = (facep->mExtents[1]+facep->mExtents[0])*0.5f;
- LLVector3 size = (facep->mExtents[1]-facep->mExtents[0])*0.5f + LLVector3(0.01f, 0.01f, 0.01f);
- drawBox(center, size);
- /*S32 boost = imagep->getBoostLevel();
- if (boost>LLViewerTexture::BOOST_NONE)
- {
- 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);
- gGL.color4fv(col.mV);
- drawBox(center, size);
- gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }*/
- }
- }
- void renderPoints(LLDrawable* drawablep)
- {
- LLGLDepthTest depth(GL_FALSE, GL_FALSE);
- if (drawablep->getNumFaces())
- {
- gGL.begin(LLRender::POINTS);
- gGL.color3f(1,1,1);
- LLVector3 center(drawablep->getPositionGroup());
- for (S32 i = 0; i < drawablep->getNumFaces(); i++)
- {
- gGL.vertex3fv(drawablep->getFace(i)->mCenterLocal.mV);
- }
- gGL.end();
- }
- }
- void renderTextureAnim(LLDrawInfo* params)
- {
- if (!params->mTextureMatrix)
- {
- return;
- }
- LLGLEnable blend(GL_BLEND);
- glColor4f(1,1,0,0.5f);
- pushVerts(params, LLVertexBuffer::MAP_VERTEX);
- }
- void renderBatchSize(LLDrawInfo* params)
- {
- glColor3ubv((GLubyte*) &(params->mDebugColor));
- 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())
- {
- return;
- }
- if (drawablep->getNumFaces())
- {
- LLGLEnable blend(GL_BLEND);
- glColor4f(0,1,1,0.5f);
- for (S32 i = 0; i < drawablep->getNumFaces(); i++)
- {
- pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX);
- }
- const LLVector3* ext = drawablep->getSpatialExtents();
- LLVector3 pos = (ext[0] + ext[1]) * 0.5f;
- LLVector3 size = (ext[1] - ext[0]) * 0.5f;
- {
- LLGLDepthTest depth(GL_FALSE, GL_TRUE);
- gGL.color4f(1,1,1,1);
- drawBoxOutline(pos, size);
- }
- gGL.color4f(1,1,0,1);
- F32 rad = drawablep->getVOVolume()->getLightRadius();
- drawBoxOutline(pos, LLVector3(rad,rad,rad));
- }
- }
- 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:
- LLCamera* mCamera;
- LLOctreeRenderNonOccluded(LLCamera* camera): mCamera(camera) {}
- virtual void traverse(const LLSpatialGroup::OctreeNode* node)
- {
- LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0);
- 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 (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
- {
- group->rebuildGeom();
- group->rebuildMesh();
- gGL.flush();
- glPushMatrix();
- gGLLastMatrix = NULL;
- glLoadMatrixd(gGLModelView);
- renderVisibility(group, mCamera);
- stop_glerror();
- gGLLastMatrix = NULL;
- glPopMatrix();
- gGL.color4f(1,1,1,1);
- }
- }
- }
- 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;
- }
- 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;
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES))
- {
- 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);
- }
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_POINTS))
- {
- renderPoints(drawable);
- }
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LIGHTS))
- {
- 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)
- {
- LLSpatialGroup::drawmap_elem_t& draw_vec = i->second;
- for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j)
- {
- LLDrawInfo* draw_info = *j;
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_ANIM))
- {
- renderTextureAnim(draw_info);
- }
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BATCH_SIZE))
- {
- 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 |
- LLPipeline::RENDER_DEBUG_OCCLUSION |
- LLPipeline::RENDER_DEBUG_LIGHTS |
- LLPipeline::RENDER_DEBUG_BATCH_SIZE |
- LLPipeline::RENDER_DEBUG_BBOXES |
- LLPipeline::RENDER_DEBUG_POINTS |
- LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY |
- 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;
- }
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
- {
- //sLastMaxTexPriority = lerp(sLastMaxTexPriority, sCurMaxTexPriority, gFrameIntervalSeconds);
- sLastMaxTexPriority = (F32) LLViewerCamera::getInstance()->getScreenPixelArea();
- sCurMaxTexPriority = 0.f;
- }
- LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
- LLGLDisable cullface(GL_CULL_FACE);
- LLGLEnable blend(GL_BLEND);
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gPipeline.disableLights();
- LLSpatialBridge* bridge = asBridge();
- LLCamera* camera = LLViewerCamera::getInstance();
- if (bridge)
- {
- camera = NULL;
- }
- LLOctreeStateCheck checker;
- checker.traverse(mOctree);
- LLOctreeRenderNonOccluded render_debug(camera);
- 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 (!LLViewerCamera::getInstance()->sphereInFrustum(v, 4.0f))
- {
- return FALSE;
- }
- return TRUE;
- }
- class LLOctreeIntersect : public LLSpatialGroup::OctreeTraveler
- {
- public:
- LLVector3 mStart;
- LLVector3 mEnd;
- 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)
- {
- }
- 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)
- {
- node->accept(this);
- for (U32 i = 0; i < node->getChildCount(); i++)
- {
- const LLSpatialGroup::OctreeNode* child = node->getChild(i);
- LLVector3 res;
- LLSpatialGroup* group = (LLSpatialGroup*) child->getListener(0);
- LLVector3 size;
- LLVector3 center;
- size = group->mBounds[1];
- center = group->mBounds[0];
- 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 mHit;
- }
- virtual bool check(LLDrawable* drawable)
- {
- LLVector3 local_start = mStart;
- LLVector3 local_end = mEnd;
- if (!gPipeline.hasRenderType(drawable->getRenderType()) || !drawable->isVisible())
- {
- return false;
- }
- if (drawable->isSpatialBridge())
- {
- 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::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
- )
- {
- 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,
- LLViewerTexture* texture, LLVertexBuffer* buffer,
- BOOL fullbright, U8 bump, BOOL particle, F32 part_size)
- :
- mVertexBuffer(buffer),
- mTexture(texture),
- mTextureMatrix(NULL),
- mModelMatrix(NULL),
- mStart(start),
- mEnd(end),
- mCount(count),
- mOffset(offset),
- mFullbright(fullbright),
- mBump(bump),
- mParticle(particle),
- mPartSize(part_size),
- mVSize(0.f),
- mGroup(NULL),
- mFace(NULL),
- mDistance(0.f)
- {
- 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)
- {
- return new LLVertexBuffer(type_mask, usage);
- }
- LLCullResult::LLCullResult()
- {
- clear();
- }
- void LLCullResult::clear()
- {
- mVisibleGroupsSize = 0;
- mAlphaGroupsSize = 0;
- mOcclusionGroupsSize = 0;
- mDrawableGroupsSize = 0;
- mVisibleListSize = 0;
- mVisibleBridgeSize = 0;
- for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++)
- {
- for (U32 j = 0; j < mRenderMapSize[i]; j++)
- {
- mRenderMap[i][j] = 0;
- }
- mRenderMapSize[i] = 0;
- }
- }
- LLCullResult::sg_list_t::iterator LLCullResult::beginVisibleGroups()
- {
- return mVisibleGroups.begin();
- }
- LLCullResult::sg_list_t::iterator LLCullResult::endVisibleGroups()
- {
- return mVisibleGroups.begin() + mVisibleGroupsSize;
- }
- LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups()
- {
- return mAlphaGroups.begin();
- }
- LLCullResult::sg_list_t::iterator LLCullResult::endAlphaGroups()
- {
- return mAlphaGroups.begin() + mAlphaGroupsSize;
- }
- LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups()
- {
- return mOcclusionGroups.begin();
- }
- LLCullResult::sg_list_t::iterator LLCullResult::endOcclusionGroups()
- {
- return mOcclusionGroups.begin() + mOcclusionGroupsSize;
- }
- LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups()
- {
- return mDrawableGroups.begin();
- }
- LLCullResult::sg_list_t::iterator LLCullResult::endDrawableGroups()
- {
- return mDrawableGroups.begin() + mDrawableGroupsSize;
- }
- LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList()
- {
- return mVisibleList.begin();
- }
- LLCullResult::drawable_list_t::iterator LLCullResult::endVisibleList()
- {
- return mVisibleList.begin() + mVisibleListSize;
- }
- LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge()
- {
- return mVisibleBridge.begin();
- }
- LLCullResult::bridge_list_t::iterator LLCullResult::endVisibleBridge()
- {
- return mVisibleBridge.begin() + mVisibleBridgeSize;
- }
- LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type)
- {
- return mRenderMap[type].begin();
- }
- LLCullResult::drawinfo_list_t::iterator LLCullResult::endRenderMap(U32 type)
- {
- return mRenderMap[type].begin() + mRenderMapSize[type];
- }
- void LLCullResult::pushVisibleGroup(LLSpatialGroup* group)
- {
- if (mVisibleGroupsSize < mVisibleGroups.size())
- {
- mVisibleGroups[mVisibleGroupsSize] = group;
- }
- else
- {
- mVisibleGroups.push_back(group);
- }
- ++mVisibleGroupsSize;
- }
- void LLCullResult::pushAlphaGroup(LLSpatialGroup* group)
- {
- if (mAlphaGroupsSize < mAlphaGroups.size())
- {
- mAlphaGroups[mAlphaGroupsSize] = group;
- }
- else
- {
- mAlphaGroups.push_back(group);
- }
- ++mAlphaGroupsSize;
- }
- void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group)
- {
- if (mOcclusionGroupsSize < mOcclusionGroups.size())
- {
- mOcclusionGroups[mOcclusionGroupsSize] = group;
- }
- else
- {
- mOcclusionGroups.push_back(group);
- }
- ++mOcclusionGroupsSize;
- }
- void LLCullResult::pushDrawableGroup(LLSpatialGroup* group)
- {
- if (mDrawableGroupsSize < mDrawableGroups.size())
- {
- mDrawableGroups[mDrawableGroupsSize] = group;
- }
- else
- {
- mDrawableGroups.push_back(group);
- }
- ++mDrawableGroupsSize;
- }
- void LLCullResult::pushDrawable(LLDrawable* drawable)
- {
- if (mVisibleListSize < mVisibleList.size())
- {
- mVisibleList[mVisibleListSize] = drawable;
- }
- else
- {
- mVisibleList.push_back(drawable);
- }
- ++mVisibleListSize;
- }
- void LLCullResult::pushBridge(LLSpatialBridge* bridge)
- {
- if (mVisibleBridgeSize < mVisibleBridge.size())
- {
- mVisibleBridge[mVisibleBridgeSize] = bridge;
- }
- else
- {
- mVisibleBridge.push_back(bridge);
- }
- ++mVisibleBridgeSize;
- }
- void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info)
- {
- if (mRenderMapSize[type] < mRenderMap[type].size())
- {
- mRenderMap[type][mRenderMapSize[type]] = draw_info;
- }
- else
- {
- mRenderMap[type].push_back(draw_info);
- }
- ++mRenderMapSize[type];
- }
- void LLCullResult::assertDrawMapsEmpty()
- {
- for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++)
- {
- if (mRenderMapSize[i] != 0)
- {
- llerrs << "Stale LLDrawInfo's in LLCullResult!" << llendl;
- }
- }
- }