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