diff options
Diffstat (limited to 'indra/newview/llspatialpartition.cpp')
-rwxr-xr-x[-rw-r--r--] | indra/newview/llspatialpartition.cpp | 3461 |
1 files changed, 2003 insertions, 1458 deletions
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 8adb8c30e0..5e342099d7 100644..100755 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -28,60 +28,48 @@ #include "llspatialpartition.h" +#include "llappviewer.h" +#include "lltexturecache.h" +#include "lltexturefetch.h" +#include "llimageworker.h" #include "llviewerwindow.h" #include "llviewerobjectlist.h" #include "llvovolume.h" #include "llvolume.h" +#include "llvolumeoctree.h" #include "llviewercamera.h" #include "llface.h" +#include "llfloatertools.h" #include "llviewercontrol.h" #include "llviewerregion.h" #include "llcamera.h" #include "pipeline.h" +#include "llmeshrepository.h" #include "llrender.h" #include "lloctree.h" +#include "llphysicsshapebuilderutil.h" #include "llvoavatar.h" +#include "llvolumemgr.h" #include "lltextureatlas.h" +#include "llviewershadermgr.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 LLTrace::BlockTimerStatHandle FTM_FRUSTUM_CULL("Frustum Culling"); +static LLTrace::BlockTimerStatHandle FTM_CULL_REBOUND("Cull Rebound Partition"); +extern bool gShiftFrame; static U32 sZombieGroups = 0; U32 LLSpatialGroup::sNodeCount = 0; + +U32 gOctreeMaxCapacity; +F32 gOctreeMinSize; + 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; +BOOL LLSpatialPartition::sTeleportRequested = FALSE; //static counter for frame to switch LOD on @@ -90,161 +78,11 @@ void sg_assert(BOOL expr) #if LL_OCTREE_PARANOIA_CHECK if (!expr) { - llerrs << "Octree invalid!" << llendl; + LL_ERRS() << "Octree invalid!" << LL_ENDL; } #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 @@ -278,25 +116,21 @@ LLSpatialGroup::~LLSpatialGroup() { /*if (sNoDelete) { - llerrs << "Illegal deletion of LLSpatialGroup!" << llendl; + LL_ERRS() << "Illegal deletion of LLSpatialGroup!" << LL_ENDL; }*/ - if (isState(DEAD)) + if (gDebugGL) { - sZombieGroups--; + gPipeline.checkReferences(this); } - - sNodeCount--; - if (gGLManager.mHasOcclusionQuery && mOcclusionQuery[LLViewerCamera::sCurCameraID]) + if (hasState(DEAD)) { - sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]); + sZombieGroups--; } + + sNodeCount--; - delete [] mOcclusionVerts; - mOcclusionVerts = NULL; - - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); clearDrawMap(); clearAtlasList() ; } @@ -428,40 +262,33 @@ void LLSpatialGroup::clearDrawMap() mDrawMap.clear(); } -BOOL LLSpatialGroup::isRecentlyVisible() const -{ - return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < LLDrawable::getMinVisFrameRange() ; -} - -BOOL LLSpatialGroup::isVisible() const +BOOL LLSpatialGroup::isHUDGroup() { - return mVisible[LLViewerCamera::sCurCameraID] == LLDrawable::getCurrentFrame() ? TRUE : FALSE; -} - -void LLSpatialGroup::setVisible() -{ - mVisible[LLViewerCamera::sCurCameraID] = LLDrawable::getCurrentFrame(); + return getSpatialPartition() && getSpatialPartition()->isHUDPartition() ; } void LLSpatialGroup::validate() { + ll_assert_aligned(this,64); #if LL_OCTREE_PARANOIA_CHECK sg_assert(!isState(DIRTY)); sg_assert(!isDead()); - LLVector3 myMin = mBounds[0] - mBounds[1]; - LLVector3 myMax = mBounds[0] + mBounds[1]; + LLVector4a myMin; + myMin.setSub(mBounds[0], mBounds[1]); + LLVector4a myMax; + myMax.setAdd(mBounds[0], mBounds[1]); validateDrawMap(); - for (element_iter i = getData().begin(); i != getData().end(); ++i) + for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) { LLDrawable* drawable = *i; sg_assert(drawable->getSpatialGroup() == this); if (drawable->getSpatialBridge()) { - sg_assert(drawable->getSpatialBridge() == mSpatialPartition->asBridge()); + sg_assert(drawable->getSpatialBridge() == getSpatialPartition()->asBridge()); } /*if (drawable->isSpatialBridge()) @@ -469,7 +296,7 @@ void LLSpatialGroup::validate() LLSpatialPartition* part = drawable->asPartition(); if (!part) { - llerrs << "Drawable reports it is a spatial bridge but not a partition." << llendl; + LL_ERRS() << "Drawable reports it is a spatial bridge but not a partition." << LL_ENDL; } LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); group->validate(); @@ -483,74 +310,24 @@ void LLSpatialGroup::validate() group->validate(); //ensure all children are enclosed in this node - LLVector3 center = group->mBounds[0]; - LLVector3 size = group->mBounds[1]; + LLVector4a center = group->mBounds[0]; + LLVector4a size = group->mBounds[1]; - LLVector3 min = center - size; - LLVector3 max = center + size; + LLVector4a min; + min.setSub(center, size); + LLVector4a max; + max.setAdd(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); + sg_assert(min[j] >= myMin[j]-0.02f); + sg_assert(max[j] <= myMax[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 @@ -560,8 +337,8 @@ void LLSpatialGroup::validateDrawMap() for (drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) { LLDrawInfo& params = **j; - - validate_draw_info(params); + + params.validate(); } } #endif @@ -569,22 +346,18 @@ void LLSpatialGroup::validateDrawMap() 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))) + (mOctreeNode->contains(drawablep->getEntry()) || + (drawablep->getBinRadius() > mOctreeNode->getSize()[0] && + parent && parent->getElementCount() >= gOctreeMaxCapacity))) { unbound(); setState(OBJECT_DIRTY); //setState(GEOM_DIRTY); - validate_drawable(drawablep); return TRUE; } @@ -592,17 +365,14 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) } -BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_octree) +BOOL LLSpatialGroup::addObject(LLDrawable *drawablep) { - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - if (!from_octree) + if(!drawablep) { - mOctreeNode->insert(drawablep); + return FALSE; } - else { - drawablep->setSpatialGroup(this); - validate_drawable(drawablep); + drawablep->setGroup(this); setState(OBJECT_DIRTY | GEOM_DIRTY); setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); gPipeline.markRebuild(this, TRUE); @@ -621,10 +391,14 @@ BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_oc void LLSpatialGroup::rebuildGeom() { - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); if (!isDead()) { - mSpatialPartition->rebuildGeom(this); + getSpatialPartition()->rebuildGeom(this); + + if (hasState(LLSpatialGroup::MESH_DIRTY)) + { + gPipeline.markMeshDirty(this); + } } } @@ -632,26 +406,20 @@ void LLSpatialGroup::rebuildMesh() { if (!isDead()) { - mSpatialPartition->rebuildMesh(this); + getSpatialPartition()->rebuildMesh(this); } } -static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt"); +static LLTrace::BlockTimerStatHandle FTM_REBUILD_VBO("VBO Rebuilt"); +static LLTrace::BlockTimerStatHandle FTM_ADD_GEOMETRY_COUNT("Add Geometry"); +static LLTrace::BlockTimerStatHandle FTM_CREATE_VB("Create VB"); +static LLTrace::BlockTimerStatHandle FTM_GET_GEOMETRY("Get Geometry"); void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { - /*if (!gPipeline.hasRenderType(mDrawableType)) + if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY)) { return; - }*/ - - if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) - { - /*if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && mRenderByGroup) - { - llerrs << "WTF?" << llendl; - }*/ - return; } if (group->changeLOD()) @@ -660,32 +428,43 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) group->mLastUpdateViewAngle = group->mViewAngle; } - LLFastTimer ftm(FTM_REBUILD_VBO); + LL_RECORD_BLOCK_TIME(FTM_REBUILD_VBO); group->clearDrawMap(); //get geometry count U32 index_count = 0; U32 vertex_count = 0; - - addGeometryCount(group, vertex_count, index_count); + + { + LL_RECORD_BLOCK_TIME(FTM_ADD_GEOMETRY_COUNT); + 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(); + LL_RECORD_BLOCK_TIME(FTM_CREATE_VB); + group->mBuilt = 1.f; + if (group->mVertexBuffer.isNull() || + !group->mVertexBuffer->isWriteable() || + (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(); + } } - else + { - group->mVertexBuffer->resizeBuffer(vertex_count, index_count); - stop_glerror(); + LL_RECORD_BLOCK_TIME(FTM_GET_GEOMETRY); + getGeometry(group); } - - getGeometry(group); } else { @@ -703,145 +482,26 @@ 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; + return (LLSpatialGroup*)LLViewerOctreeGroup::getParent(); } - if(!mOctreeNode) +BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) { - return NULL; - } - OctreeNode* parent = mOctreeNode->getOctParent(); - - if (parent) + if(!drawablep) { - return (LLSpatialGroup*) parent->getListener(0); + return FALSE; } - 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; - } + drawablep->setGroup(NULL); } else { - drawablep->setSpatialGroup(NULL); + drawablep->setGroup(NULL); setState(GEOM_DIRTY); gPipeline.markRebuild(this, TRUE); @@ -865,43 +525,35 @@ BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) return TRUE; } -void LLSpatialGroup::shift(const LLVector3 &offset) +void LLSpatialGroup::shift(const LLVector4a &offset) { - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - LLVector3d offsetd(offset); - mOctreeNode->setCenter(mOctreeNode->getCenter()+offsetd); + LLVector4a t = mOctreeNode->getCenter(); + t.add(offset); + mOctreeNode->setCenter(t); mOctreeNode->updateMinMax(); - mBounds[0] += offset; - mExtents[0] += offset; - mExtents[1] += offset; - mObjectBounds[0] += offset; - mObjectExtents[0] += offset; - mObjectExtents[1] += offset; - - //if (!mSpatialPartition->mRenderByGroup) + mBounds[0].add(offset); + mExtents[0].add(offset); + mExtents[1].add(offset); + mObjectBounds[0].add(offset); + mObjectExtents[0].add(offset); + mObjectExtents[1].add(offset); + + if (!getSpatialPartition()->mRenderByGroup && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TREE && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TERRAIN && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_BRIDGE) { 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 +class LLSpatialSetState : public OctreeTraveler { public: U32 mState; LLSpatialSetState(U32 state) : mState(state) { } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); } + virtual void visit(const OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); } }; class LLSpatialSetStateDiff : public LLSpatialSetState @@ -909,36 +561,21 @@ class LLSpatialSetStateDiff : public LLSpatialSetState public: LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { } - virtual void traverse(const LLSpatialGroup::OctreeNode* n) + virtual void traverse(const OctreeNode* n) { LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - if (!group->isState(mState)) + if (!group->hasState(mState)) { - LLSpatialGroup::OctreeTraveler::traverse(n); + 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; - } - + llassert(state <= LLSpatialGroup::STATE_MASK); + if (mode > STATE_MODE_SINGLE) { if (mode == STATE_MODE_DIFF) @@ -958,12 +595,12 @@ void LLSpatialGroup::setState(U32 state, S32 mode) } } -class LLSpatialClearState : public LLSpatialGroup::OctreeTraveler +class LLSpatialClearState : public OctreeTraveler { public: U32 mState; LLSpatialClearState(U32 state) : mState(state) { } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); } + virtual void visit(const OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); } }; class LLSpatialClearStateDiff : public LLSpatialClearState @@ -971,36 +608,21 @@ class LLSpatialClearStateDiff : public LLSpatialClearState public: LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { } - virtual void traverse(const LLSpatialGroup::OctreeNode* n) + virtual void traverse(const OctreeNode* n) { LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - if (group->isState(mState)) + if (group->hasState(mState)) { - LLSpatialGroup::OctreeTraveler::traverse(n); + 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; - } + llassert(state <= LLSpatialGroup::STATE_MASK); - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - if (mode > STATE_MODE_SINGLE) { if (mode == STATE_MODE_DIFF) @@ -1020,177 +642,37 @@ 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 //====================================== -LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : - mState(0), +LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLOcclusionCullingGroup(node, part), + mObjectBoxSize(1.f), + mGeometryBytes(0), + mSurfaceArea(0.f), mBuilt(0.f), - mOctreeNode(node), - mSpatialPartition(part), mVertexBuffer(NULL), - mBufferUsage(GL_STATIC_DRAW_ARB), + mBufferUsage(part->mBufferUsage), 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) { + ll_assert_aligned(this,16); + sNodeCount++; - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + + mViewAngle.splat(0.f); + mLastUpdateViewAngle.splat(-1.f); 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; } @@ -1199,44 +681,57 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) { if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) { - llerrs << "WTF?" << llendl; + LL_WARNS() << "Attempted to update distance for camera other than world camera!" << LL_ENDL; + return; + } + + if (gShiftFrame) + { + return; } #if !LL_RELEASE_FOR_DOWNLOAD - if (isState(LLSpatialGroup::OBJECT_DIRTY)) + if (hasState(LLSpatialGroup::OBJECT_DIRTY)) { - llerrs << "Spatial group dirty on distance update." << llendl; + LL_ERRS() << "Spatial group dirty on distance update." << LL_ENDL; } #endif - if (!getData().empty()) + if (!isEmpty()) { - mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() : - (F32) mOctreeNode->getSize().magVec(); - mDistance = mSpatialPartition->calcDistance(this, camera); - mPixelArea = mSpatialPartition->calcPixelArea(this, camera); + mRadius = getSpatialPartition()->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() : + (F32) mOctreeNode->getSize().getLength3().getF32(); + mDistance = getSpatialPartition()->calcDistance(this, camera); + mPixelArea = getSpatialPartition()->calcPixelArea(this, camera); } } F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) { - LLVector3 eye = group->mObjectBounds[0] - camera.getOrigin(); + LLVector4a eye; + LLVector4a origin; + origin.load3(camera.getOrigin().mV); + + eye.setSub(group->mObjectBounds[0], origin); F32 dist = 0.f; if (group->mDrawMap.find(LLRenderPass::PASS_ALPHA) != group->mDrawMap.end()) { - LLVector3 v = eye; - dist = eye.normVec(); + LLVector4a v = eye; - if (!group->isState(LLSpatialGroup::ALPHA_DIRTY)) + dist = eye.getLength3().getF32(); + eye.normalize3fast(); + + if (!group->hasState(LLSpatialGroup::ALPHA_DIRTY)) { - if (!group->mSpatialPartition->isBridge()) + if (!group->getSpatialPartition()->isBridge()) { - LLVector3 view_angle = LLVector3(eye * LLVector3(1,0,0), - eye * LLVector3(0,1,0), - eye * LLVector3(0,0,1)); + LLVector4a view_angle = eye; + + LLVector4a diff; + diff.setSub(view_angle, group->mLastUpdateViewAngle); - if ((view_angle-group->mLastUpdateViewAngle).magVec() > 0.64f) + if (diff.getLength3().getF32() > 0.64f) { group->mViewAngle = view_angle; group->mLastUpdateViewAngle = view_angle; @@ -1253,17 +748,20 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) 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]; - } + LLVector4a ata; + ata.load3(at.mV); - group->mDepth = v * at; + LLVector4a t = ata; + //front of bounding box + t.mul(0.25f); + t.mul(group->mObjectBounds[1]); + v.sub(t); + + group->mDepth = v.dot3(ata).getF32(); } else { - dist = eye.magVec(); + dist = eye.getLength3().getF32(); } if (dist < 16.f) @@ -1289,32 +787,28 @@ F32 LLSpatialGroup::getUpdateUrgency() const } else { - return (gFrameTimeSeconds - mLastUpdateTime+4.f)/mDistance; + F32 time = gFrameTimeSeconds-mLastUpdateTime+4.f; + return time + (mObjectBounds[1].dot3(mObjectBounds[1]).getF32()+1.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 + if (hasState(ALPHA_DIRTY | OBJECT_DIRTY)) + { ///a rebuild is going to happen, update distance and LoD return TRUE; } - if (mSpatialPartition->mSlopRatio > 0.f) + if (getSpatialPartition()->mSlopRatio > 0.f) { F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius)); - if (fabsf(ratio) >= mSpatialPartition->mSlopRatio) + if (fabsf(ratio) >= getSpatialPartition()->mSlopRatio) { return TRUE; } - if (mDistance > mRadius) + if (mDistance > mRadius*2.f) { return FALSE; } @@ -1328,35 +822,53 @@ BOOL LLSpatialGroup::changeLOD() return FALSE; } -void LLSpatialGroup::handleInsertion(const TreeNode* node, LLDrawable* drawablep) +void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* entry) { - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - addObject(drawablep, FALSE, TRUE); + addObject((LLDrawable*)entry->getDrawable()); unbound(); setState(OBJECT_DIRTY); } -void LLSpatialGroup::handleRemoval(const TreeNode* node, LLDrawable* drawable) +void LLSpatialGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* entry) { - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - removeObject(drawable, TRUE); - setState(OBJECT_DIRTY); + removeObject((LLDrawable*)entry->getDrawable(), TRUE); + LLViewerOctreeGroup::handleRemoval(node, entry); } void LLSpatialGroup::handleDestruction(const TreeNode* node) { - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - setState(DEAD); - - for (element_iter i = getData().begin(); i != getData().end(); ++i) + if(isDead()) { - LLDrawable* drawable = *i; - if (drawable->getSpatialGroup() == this) + return; + } + setState(DEAD); + + for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) + { + LLViewerOctreeEntry* entry = *i; + + if (entry->getGroup() == this) { - drawable->setSpatialGroup(NULL); + if(entry->hasDrawable()) + { + ((LLDrawable*)entry->getDrawable())->setGroup(NULL); + } } } + //clean up avatar attachment stats + LLSpatialBridge* bridge = getSpatialPartition()->asBridge(); + if (bridge) + { + if (bridge->mAvatar.notNull()) + { + bridge->mAvatar->mAttachmentGeometryBytes -= mGeometryBytes; + bridge->mAvatar->mAttachmentGeometryBytes = llmax(bridge->mAvatar->mAttachmentGeometryBytes, 0); + bridge->mAvatar->mAttachmentSurfaceArea -= mSurfaceArea; + bridge->mAvatar->mAttachmentSurfaceArea = llmax(bridge->mAvatar->mAttachmentSurfaceArea, 0.f); + } + } + clearDrawMap(); mVertexBuffer = NULL; mBufferMap.clear(); @@ -1364,26 +876,15 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) 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); + new LLSpatialGroup(child, getSpatialPartition()); } else { - OCT_ERRS << "LLSpatialGroup redundancy detected." << llendl; + OCT_ERRS << "LLSpatialGroup redundancy detected." << LL_ENDL; } unbound(); @@ -1391,15 +892,14 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c assert_states_valid(this); } -void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNode* child) -{ - unbound(); -} - -void LLSpatialGroup::destroyGL() +void LLSpatialGroup::destroyGL(bool keep_occlusion) { setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); - gPipeline.markRebuild(this, TRUE); + + if (!keep_occlusion) + { //going to need a rebuild + gPipeline.markRebuild(this, TRUE); + } mLastUpdateTime = gFrameTimeSeconds; mVertexBuffer = NULL; @@ -1407,267 +907,67 @@ void LLSpatialGroup::destroyGL() 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) + if (!keep_occlusion) { - 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]; + releaseOcclusionQueryObjectNames(); } - 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) - { - LLFastTimer t(FTM_OCCLUSION_READBACK); - 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 - 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) + for (LLSpatialGroup::element_iter i = getDataBegin(); i != getDataEnd(); ++i) { - // Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension - if ((mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER && !gGLManager.mHasDepthClamp) || - earlyFail(camera, this)) + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) { - setOcclusionState(LLSpatialGroup::DISCARD_QUERY); - assert_states_valid(this); - clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); - assert_states_valid(this); + continue; } - else + for (S32 j = 0; j < drawable->getNumFaces(); j++) { + LLFace* facep = drawable->getFace(j); + if (facep) { - LLFastTimer t(FTM_RENDER_OCCLUSION); - - if (!mOcclusionQuery[LLViewerCamera::sCurCameraID]) - { - mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate(); - } - - if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY)) - { - buildOcclusion(); - } - - // Depth clamp all water to avoid it being culled as a result of being - // behind the far clip plane, and in the case of edge water to avoid - // it being culled while still visible. - bool const use_depth_clamp = gGLManager.mHasDepthClamp && - (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER || - mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER); - if (use_depth_clamp) - { - glEnable(GL_DEPTH_CLAMP); - } - - 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); - - if (use_depth_clamp) - { - glDisable(GL_DEPTH_CLAMP); - } + facep->clearVertexBuffer(); } - - setOcclusionState(LLSpatialGroup::QUERY_PENDING); - clearOcclusionState(LLSpatialGroup::DISCARD_QUERY); } } } //============================================== -LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage) -: mRenderByGroup(render_by_group) +LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage, LLViewerRegion* regionp) +: mRenderByGroup(render_by_group), mBridge(NULL) { - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - mOcclusionEnabled = TRUE; - mDrawableType = 0; + mRegionp = regionp; 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; + if(!drawablep->getGroup()) + { assert_octree_valid(mOctree); - mOctree->insert(drawablep); + mOctree->insert(drawablep->getEntry()); assert_octree_valid(mOctree); + } LLSpatialGroup* group = drawablep->getSpatialGroup(); + llassert(group != NULL); if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING)) { @@ -1679,13 +979,13 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) 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; + OCT_ERRS << "Failed to remove drawable from octree!" << LL_ENDL; + } + else + { + drawablep->setGroup(NULL); } assert_octree_valid(mOctree); @@ -1695,30 +995,28 @@ BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) 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; + OCT_ERRS << "LLSpatialPartition::move was passed a bad drawable." << LL_ENDL; return; } BOOL was_visible = curp ? curp->isVisible() : FALSE; - if (curp && curp->mSpatialPartition != this) + if (curp && curp->getSpatialPartition() != this) { //keep drawable from being garbage collected LLPointer<LLDrawable> ptr = drawablep; - if (curp->mSpatialPartition->remove(drawablep, curp)) + if (curp->getSpatialPartition()->remove(drawablep, curp)) { put(drawablep, was_visible); return; } else { - OCT_ERRS << "Drawable lost between spatial partitions on outbound transition." << llendl; + OCT_ERRS << "Drawable lost between spatial partitions on outbound transition." << LL_ENDL; } } @@ -1733,42 +1031,41 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL LLPointer<LLDrawable> ptr = drawablep; if (curp && !remove(drawablep, curp)) { - OCT_ERRS << "Move couldn't find existing spatial group!" << llendl; + OCT_ERRS << "Move couldn't find existing spatial group!" << LL_ENDL; } put(drawablep, was_visible); } -class LLSpatialShift : public LLSpatialGroup::OctreeTraveler +class LLSpatialShift : public OctreeTraveler { public: - LLSpatialShift(LLVector3 offset) : mOffset(offset) { } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) + const LLVector4a& mOffset; + + LLSpatialShift(const LLVector4a& offset) : mOffset(offset) { } + virtual void visit(const OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset); } - - LLVector3 mOffset; }; -void LLSpatialPartition::shift(const LLVector3 &offset) +void LLSpatialPartition::shift(const LLVector4a &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 +class LLOctreeCull : public LLViewerOctreeCull { public: - LLOctreeCull(LLCamera* camera) - : mCamera(camera), mRes(0) { } + LLOctreeCull(LLCamera* camera) : LLViewerOctreeCull(camera) {} - virtual bool earlyFail(LLSpatialGroup* group) + virtual bool earlyFail(LLViewerOctreeGroup* base_group) { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; group->checkOcclusion(); - if (group->mOctreeNode->getParent() && //never occlusion cull the root node + if (group->getOctreeNode()->getParent() && //never occlusion cull the root node LLPipeline::sUseOcclusion && //ignore occlusion if disabled group->isOcclusionState(LLSpatialGroup::OCCLUDED)) { @@ -1779,100 +1076,36 @@ public: return false; } - virtual void traverse(const LLSpatialGroup::OctreeNode* n) + virtual S32 frustumCheck(const LLViewerOctreeGroup* group) { - 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]); + S32 res = AABBInFrustumNoFarClipGroupBounds(group); if (res != 0) { - res = llmin(res, AABBSphereIntersect(group->mExtents[0], group->mExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist)); + res = llmin(res, AABBSphereIntersectGroupExtents(group)); } return res; } - virtual S32 frustumCheckObjects(const LLSpatialGroup* group) + virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) { - S32 res = mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]); + S32 res = AABBInFrustumNoFarClipObjectBounds(group); if (res != 0) { - res = llmin(res, AABBSphereIntersect(group->mObjectExtents[0], group->mObjectExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist)); + res = llmin(res, AABBSphereIntersectObjectExtents(group)); } 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) + virtual void processGroup(LLViewerOctreeGroup* base_group) { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; if (group->needsUpdate() || - group->mVisible[LLViewerCamera::sCurCameraID] < LLDrawable::getCurrentFrame() - 1) + group->getVisible(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 @@ -1881,14 +1114,14 @@ public: LLOctreeCullNoFarClip(LLCamera* camera) : LLOctreeCull(camera) { } - virtual S32 frustumCheck(const LLSpatialGroup* group) + virtual S32 frustumCheck(const LLViewerOctreeGroup* group) { - return mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]); + return AABBInFrustumNoFarClipGroupBounds(group); } - virtual S32 frustumCheckObjects(const LLSpatialGroup* group) + virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) { - S32 res = mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]); + S32 res = AABBInFrustumNoFarClipObjectBounds(group); return res; } }; @@ -1899,26 +1132,28 @@ public: LLOctreeCullShadow(LLCamera* camera) : LLOctreeCull(camera) { } - virtual S32 frustumCheck(const LLSpatialGroup* group) + virtual S32 frustumCheck(const LLViewerOctreeGroup* group) { - return mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1]); + return AABBInFrustumGroupBounds(group); } - virtual S32 frustumCheckObjects(const LLSpatialGroup* group) + virtual S32 frustumCheckObjects(const LLViewerOctreeGroup* group) { - return mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]); + return AABBInFrustumObjectBounds(group); } }; class LLOctreeCullVisExtents: public LLOctreeCullShadow { public: - LLOctreeCullVisExtents(LLCamera* camera, LLVector3& min, LLVector3& max) + LLOctreeCullVisExtents(LLCamera* camera, LLVector4a& min, LLVector4a& max) : LLOctreeCullShadow(camera), mMin(min), mMax(max), mEmpty(TRUE) { } - virtual bool earlyFail(LLSpatialGroup* group) + virtual bool earlyFail(LLViewerOctreeGroup* base_group) { - if (group->mOctreeNode->getParent() && //never occlusion cull the root node + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + + if (group->getOctreeNode()->getParent() && //never occlusion cull the root node LLPipeline::sUseOcclusion && //ignore occlusion if disabled group->isOcclusionState(LLSpatialGroup::OCCLUDED)) { @@ -1928,7 +1163,7 @@ public: return false; } - virtual void traverse(const LLSpatialGroup::OctreeNode* n) + virtual void traverse(const OctreeNode* n) { LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); @@ -1937,10 +1172,10 @@ public: return; } - if ((mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) || + if ((mRes && group->hasState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) || mRes == 2) { //don't need to do frustum check - LLSpatialGroup::OctreeTraveler::traverse(n); + OctreeTraveler::traverse(n); } else { @@ -1948,40 +1183,41 @@ public: if (mRes) { //at least partially in, run on down - LLSpatialGroup::OctreeTraveler::traverse(n); + OctreeTraveler::traverse(n); } mRes = 0; } } - virtual void processGroup(LLSpatialGroup* group) + virtual void processGroup(LLViewerOctreeGroup* base_group) { - if (group->isState(LLSpatialGroup::DIRTY) || group->getData().empty()) - { - llerrs << "WTF?" << llendl; - } - + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + + llassert(!group->hasState(LLSpatialGroup::DIRTY) && !group->isEmpty()); + if (mRes < 2) { - if (mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]) > 0) + if (AABBInFrustumObjectBounds(group) > 0) { mEmpty = FALSE; - update_min_max(mMin, mMax, group->mObjectExtents[0]); - update_min_max(mMin, mMax, group->mObjectExtents[1]); + const LLVector4a* exts = group->getObjectExtents(); + update_min_max(mMin, mMax, exts[0]); + update_min_max(mMin, mMax, exts[1]); } } else { mEmpty = FALSE; - update_min_max(mMin, mMax, group->mExtents[0]); - update_min_max(mMin, mMax, group->mExtents[1]); + const LLVector4a* exts = group->getExtents(); + update_min_max(mMin, mMax, exts[0]); + update_min_max(mMin, mMax, exts[1]); } } BOOL mEmpty; - LLVector3& mMin; - LLVector3& mMax; + LLVector4a& mMin; + LLVector4a& mMax; }; class LLOctreeCullDetectVisible: public LLOctreeCullShadow @@ -1990,10 +1226,12 @@ public: LLOctreeCullDetectVisible(LLCamera* camera) : LLOctreeCullShadow(camera), mResult(FALSE) { } - virtual bool earlyFail(LLSpatialGroup* group) + virtual bool earlyFail(LLViewerOctreeGroup* base_group) { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + if (mResult || //already found a node, don't check any more - (group->mOctreeNode->getParent() && //never occlusion cull the root node + (group->getOctreeNode()->getParent() && //never occlusion cull the root node LLPipeline::sUseOcclusion && //ignore occlusion if disabled group->isOcclusionState(LLSpatialGroup::OCCLUDED))) { @@ -2003,9 +1241,9 @@ public: return false; } - virtual void processGroup(LLSpatialGroup* group) + virtual void processGroup(LLViewerOctreeGroup* base_group) { - if (group->isVisible()) + if (base_group->isVisible()) { mResult = TRUE; } @@ -2020,17 +1258,21 @@ 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 bool earlyFail(LLViewerOctreeGroup* group) { return false; } + virtual void preprocess(LLViewerOctreeGroup* group) { } - virtual void processGroup(LLSpatialGroup* group) + virtual void processGroup(LLViewerOctreeGroup* base_group) { - LLSpatialGroup::OctreeNode* branch = group->mOctreeNode; + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + OctreeNode* branch = group->getOctreeNode(); - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { - LLDrawable* drawable = *i; - + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } if (!drawable->isDead()) { if (drawable->isSpatialBridge()) @@ -2050,6 +1292,8 @@ public: void drawBox(const LLVector3& c, const LLVector3& r) { + LLVertexBuffer::unbind(); + gGL.begin(LLRender::TRIANGLE_STRIP); //left front gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); @@ -2085,8 +1329,25 @@ void drawBox(const LLVector3& c, const LLVector3& r) gGL.end(); } +void drawBox(const LLVector4a& c, const LLVector4a& r) +{ + drawBox(reinterpret_cast<const LLVector3&>(c), reinterpret_cast<const LLVector3&>(r)); +} + void drawBoxOutline(const LLVector3& pos, const LLVector3& size) { + + llassert(pos.isFinite()); + llassert(size.isFinite()); + + llassert(!llisnan(pos.mV[0])); + llassert(!llisnan(pos.mV[1])); + llassert(!llisnan(pos.mV[2])); + + llassert(!llisnan(size.mV[0])); + llassert(!llisnan(size.mV[1])); + llassert(!llisnan(size.mV[2])); + LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1)); LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1)); LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1)); @@ -2131,18 +1392,29 @@ void drawBoxOutline(const LLVector3& pos, const LLVector3& size) gGL.end(); } -class LLOctreeDirty : public LLOctreeTraveler<LLDrawable> +void drawBoxOutline(const LLVector4a& pos, const LLVector4a& size) +{ + drawBoxOutline(reinterpret_cast<const LLVector3&>(pos), reinterpret_cast<const LLVector3&>(size)); +} + +class LLOctreeDirty : public OctreeTraveler { public: - virtual void visit(const LLOctreeNode<LLDrawable>* state) + LLOctreeDirty(bool no_rebuild) : mNoRebuild(no_rebuild){} + + virtual void visit(const OctreeNode* state) { LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); group->destroyGL(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawable = *i; - if (drawable->getVObj().notNull() && !group->mSpatialPartition->mRenderByGroup) + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + if (!mNoRebuild && drawable->getVObj().notNull() && !group->getSpatialPartition()->mRenderByGroup) { gPipeline.markRebuild(drawable, LLDrawable::REBUILD_ALL, TRUE); } @@ -2154,34 +1426,38 @@ public: traverse(bridge->mOctree); } } + +private: + BOOL mNoRebuild; }; void LLSpatialPartition::restoreGL() { - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); } void LLSpatialPartition::resetVertexBuffers() { - LLOctreeDirty dirty; + LLOctreeDirty dirty(sTeleportRequested); dirty.traverse(mOctree); } -BOOL LLSpatialPartition::isOcclusionEnabled() -{ - return mOcclusionEnabled || LLPipeline::sUseOcclusion > 2; -} - BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax) { + LLVector4a visMina, visMaxa; + visMina.load3(visMin.mV); + visMaxa.load3(visMax.mV); + { - LLFastTimer ftm(FTM_CULL_REBOUND); + LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); group->rebound(); } - LLOctreeCullVisExtents vis(&camera, visMin, visMax); + LLOctreeCullVisExtents vis(&camera, visMina, visMaxa); vis.traverse(mOctree); + + visMin.set(visMina.getF32ptr()); + visMax.set(visMaxa.getF32ptr()); return vis.mEmpty; } @@ -2194,12 +1470,11 @@ BOOL LLSpatialPartition::visibleObjectsInFrustum(LLCamera& camera) 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); + LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); group->rebound(); } @@ -2208,27 +1483,42 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result ((LLSpatialGroup*)mOctree->getListener(0))->validate(); #endif - - if (for_select) - { LLOctreeSelect selecter(&camera, results); selecter.traverse(mOctree); + + return 0; } - else if (LLPipeline::sShadowRender) + +S32 LLSpatialPartition::cull(LLCamera &camera, bool do_occlusion) +{ +#if LL_OCTREE_PARANOIA_CHECK + ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); +#endif { - LLFastTimer ftm(FTM_FRUSTUM_CULL); + LL_RECORD_BLOCK_TIME(FTM_CULL_REBOUND); + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); + } + +#if LL_OCTREE_PARANOIA_CHECK + ((LLSpatialGroup*)mOctree->getListener(0))->validate(); +#endif + + if (LLPipeline::sShadowRender) + { + LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); LLOctreeCullShadow culler(&camera); culler.traverse(mOctree); } else if (mInfiniteFarClip || !LLPipeline::sUseFarClip) { - LLFastTimer ftm(FTM_FRUSTUM_CULL); + LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); LLOctreeCullNoFarClip culler(&camera); culler.traverse(mOctree); } else { - LLFastTimer ftm(FTM_FRUSTUM_CULL); + LL_RECORD_BLOCK_TIME(FTM_FRUSTUM_CULL); LLOctreeCull culler(&camera); culler.traverse(mOctree); } @@ -2236,39 +1526,6 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result 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); @@ -2293,18 +1550,40 @@ void pushVerts(LLSpatialGroup* group, U32 mask) void pushVerts(LLFace* face, U32 mask) { - LLVertexBuffer* buffer = face->mVertexBuffer; + if (face) + { + llassert(face->verify()); - if (buffer) + LLVertexBuffer* buffer = face->getVertexBuffer(); + + if (buffer && (face->getGeomCount() >= 3)) + { + 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 pushVerts(LLDrawable* drawable, U32 mask) +{ + for (S32 i = 0; i < drawable->getNumFaces(); ++i) { - 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); + pushVerts(drawable->getFace(i), mask); } +} +void pushVerts(LLVolume* volume) +{ + LLVertexBuffer::unbind(); + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, face.mPositions, NULL, face.mNumIndices, face.mIndices); + } } void pushBufferVerts(LLVertexBuffer* buffer, U32 mask) @@ -2312,20 +1591,23 @@ void pushBufferVerts(LLVertexBuffer* buffer, U32 mask) if (buffer) { buffer->setBuffer(mask); - buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getRequestedVerts()-1, buffer->getRequestedIndices(), 0); + buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts()-1, buffer->getNumIndices(), 0); } } -void pushBufferVerts(LLSpatialGroup* group, U32 mask) +void pushBufferVerts(LLSpatialGroup* group, U32 mask, bool push_alpha = true) { - if (group->mSpatialPartition->mRenderByGroup) + if (group->getSpatialPartition()->mRenderByGroup) { if (!group->mDrawMap.empty()) { LLDrawInfo* params = *(group->mDrawMap.begin()->second.begin()); LLRenderPass::applyModelMatrix(*params); - pushBufferVerts(group->mVertexBuffer, mask); + if (push_alpha) + { + pushBufferVerts(group->mVertexBuffer, mask); + } for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) { @@ -2339,17 +1621,18 @@ void pushBufferVerts(LLSpatialGroup* group, U32 mask) } } } - else + /*else { - drawBox(group->mBounds[0], group->mBounds[1]); - } + //const LLVector4a* bounds = group->getBounds(); + //drawBox(bounds[0], bounds[1]); + }*/ } void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) { LLDrawInfo* params = NULL; - LLColor4 colors[] = { + static const LLColor4 colors[] = { LLColor4::green, LLColor4::green1, LLColor4::green2, @@ -2369,7 +1652,7 @@ void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) { params = *j; LLRenderPass::applyModelMatrix(*params); - glColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f); + gGL.diffuseColor4f(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); @@ -2382,12 +1665,11 @@ 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; + group->mBuilt -= 2.f * gFrameIntervalSeconds.value(); if (group->mBufferUsage == GL_STATIC_DRAW_ARB) { col.setVec(1.0f, 0, 0, group->mBuilt*0.5f); @@ -2403,61 +1685,67 @@ void renderOctree(LLSpatialGroup* group) LLGLDepthTest gl_depth(FALSE, FALSE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - gGL.color4f(1,0,0,group->mBuilt); + gGL.diffuseColor4f(1,0,0,group->mBuilt); gGL.flush(); glLineWidth(5.f); - drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]); + + const LLVector4a* bounds = group->getObjectBounds(); + drawBoxOutline(bounds[0], bounds[1]); gGL.flush(); glLineWidth(1.f); gGL.flush(); - for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawable = *i; - if (!group->mSpatialPartition->isBridge()) + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + if (!group->getSpatialPartition()->isBridge()) { - glPushMatrix(); + gGL.pushMatrix(); LLVector3 trans = drawable->getRegion()->getOriginAgent(); - glTranslatef(trans.mV[0], trans.mV[1], trans.mV[2]); + gGL.translatef(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 (face && face->getVertexBuffer()) { if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f) { - glColor4f(0, 1, 0, group->mBuilt); + gGL.diffuseColor4f(0, 1, 0, group->mBuilt); } else if (gFrameTimeSeconds - face->mLastMoveTime < 0.5f) { - glColor4f(1, 0, 0, group->mBuilt); + gGL.diffuseColor4f(1, 0, 0, group->mBuilt); } else { continue; } - face->mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX); + face->getVertexBuffer()->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()); + face->getVertexBuffer()->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart()); } } - if (!group->mSpatialPartition->isBridge()) + if (!group->getSpatialPartition()->isBridge()) { - glPopMatrix(); + gGL.popMatrix(); } } glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - gGL.color4f(1,1,1,1); + gGL.diffuseColor4f(1,1,1,1); } } else { - if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->getData().empty() - && group->mSpatialPartition->mRenderByGroup) + if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->isEmpty() + && group->getSpatialPartition()->mRenderByGroup) { col.setVec(0.8f, 0.4f, 0.1f, 0.1f); } @@ -2467,65 +1755,109 @@ void renderOctree(LLSpatialGroup* group) } } - gGL.color4fv(col.mV); - drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); + gGL.diffuseColor4fv(col.mV); + LLVector4a fudge; + fudge.splat(0.001f); + + //LLVector4a size = group->mObjectBounds[1]; + //size.mul(1.01f); + //size.add(fudge); + + //{ + // LLGLDepthTest depth(GL_TRUE, GL_FALSE); + // drawBox(group->mObjectBounds[0], fudge); + //} gGL.setSceneBlendType(LLRender::BT_ALPHA); - if (group->mBuilt <= 0.f) + //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]); + //gGL.diffuseColor4f(col.mV[0], col.mV[1], col.mV[2], 1.f); + //drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]); + gGL.diffuseColor4f(0,1,1,1); + const LLVector4a* bounds = group->getBounds(); + drawBoxOutline(bounds[0], bounds[1]); + //draw bounding box for draw info - if (group->mSpatialPartition->mRenderByGroup) + /*if (group->getSpatialPartition()->mRenderByGroup) { - gGL.color4f(1.0f, 0.75f, 0.25f, 0.6f); + gGL.diffuseColor4f(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; + LLVector4a center; + center.setAdd(draw_info->mExtents[1], draw_info->mExtents[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(draw_info->mExtents[1], draw_info->mExtents[0]); + size.mul(0.5f); drawBoxOutline(center, size); } } - } + }*/ } // LLSpatialGroup::OctreeNode* node = group->mOctreeNode; -// gGL.color4f(0,1,0,1); +// gGL.diffuseColor4f(0,1,0,1); // drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize())); } +std::set<LLSpatialGroup*> visible_selected_groups; + void renderVisibility(LLSpatialGroup* group, LLCamera* camera) { - LLGLEnable blend(GL_BLEND); + /*LLGLEnable blend(GL_BLEND); gGL.setSceneBlendType(LLRender::BT_ALPHA); LLGLEnable cull(GL_CULL_FACE); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);*/ + + /*BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && + !group->isEmpty(); + - BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && - !group->getData().empty(); if (render_objects) { + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + + LLGLDisable blend(GL_BLEND); + gGL.diffuseColor4f(0.f, 0.75f, 0.f,0.5f); + pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false); + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glLineWidth(4.f); + gGL.diffuseColor4f(0.f, 0.5f, 0.f, 1.f); + pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false); + glLineWidth(1.f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + bool selected = false; + + for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter) + { + LLDrawable* drawable = *iter; + if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected()) + { + selected = true; + break; + } + } + + if (selected) + { //store for rendering occlusion volume as overlay + visible_selected_groups.insert(group); + } + }*/ + + /*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); + gGL.diffuseColor4f(0, 0.5f, 0, 0.5f); + gGL.diffuseColor4f(0, 0.5f, 0, 0.5f); pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); } @@ -2534,8 +1866,8 @@ 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); + gGL.diffuseColor4f(0.f, 0.5f, 0.f,1.f); + gGL.diffuseColor4f(0.f, 0.5f, 0.f, 1.f); pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); } @@ -2543,22 +1875,62 @@ 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); + gGL.diffuseColor4f(0.f, 0.75f, 0.f,0.5f); + gGL.diffuseColor4f(0.f, 0.75f, 0.f, 0.5f); pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX); - } - else if (camera && group->mOcclusionVerts) + + bool selected = false; + + for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter) + { + LLDrawable* drawable = *iter; + if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected()) + { + selected = true; + break; + } + } + + if (selected) + { //store for rendering occlusion volume as overlay + visible_selected_groups.insert(group); + } + } + }*/ +} + +void renderXRay(LLSpatialGroup* group, LLCamera* camera) +{ + BOOL render_objects = (!LLPipeline::sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && group->isVisible() && + !group->isEmpty(); + + if (render_objects) + { + pushBufferVerts(group, LLVertexBuffer::MAP_VERTEX, false); + + bool selected = false; + + for (LLSpatialGroup::element_iter iter = group->getDataBegin(); iter != group->getDataEnd(); ++iter) { - LLVertexBuffer::unbind(); - glVertexPointer(3, GL_FLOAT, 0, group->mOcclusionVerts); + LLDrawable* drawable = (LLDrawable*)(*iter)->getDrawable(); + if (drawable->getVObj().notNull() && drawable->getVObj()->isSelected()) + { + selected = true; + break; + } + } - 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); + if (selected) + { //store for rendering occlusion volume as overlay + + if (!group->getSpatialPartition()->isBridge()) + { + visible_selected_groups.insert(group); + } + else + { + visible_selected_groups.insert(group->getSpatialPartition()->asBridge()->getSpatialGroup()); + } } } } @@ -2589,26 +1961,26 @@ void renderUpdateType(LLDrawable* drawablep) switch (vobj->getLastUpdateType()) { case OUT_FULL: - glColor4f(0,1,0,0.5f); + gGL.diffuseColor4f(0,1,0,0.5f); break; case OUT_TERSE_IMPROVED: - glColor4f(0,1,1,0.5f); + gGL.diffuseColor4f(0,1,1,0.5f); break; case OUT_FULL_COMPRESSED: if (vobj->getLastUpdateCached()) { - glColor4f(1,0,0,0.5f); + gGL.diffuseColor4f(1,0,0,0.5f); } else { - glColor4f(1,1,0,0.5f); + gGL.diffuseColor4f(1,1,0,0.5f); } break; case OUT_FULL_CACHED: - glColor4f(0,0,1,0.5f); + gGL.diffuseColor4f(0,0,1,0.5f); break; default: - llwarns << "Unknown update_type " << vobj->getLastUpdateType() << llendl; + LL_WARNS() << "Unknown update_type " << vobj->getLastUpdateType() << LL_ENDL; break; }; S32 num_faces = drawablep->getNumFaces(); @@ -2621,6 +1993,115 @@ void renderUpdateType(LLDrawable* drawablep) } } +void renderComplexityDisplay(LLDrawable* drawablep) +{ + LLViewerObject* vobj = drawablep->getVObj(); + if (!vobj) + { + return; + } + + LLVOVolume *voVol = dynamic_cast<LLVOVolume*>(vobj); + + if (!voVol) + { + return; + } + + if (!voVol->isRoot()) + { + return; + } + + LLVOVolume::texture_cost_t textures; + F32 cost = (F32) voVol->getRenderCost(textures); + + // add any child volumes + LLViewerObject::const_child_list_t children = voVol->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator iter = children.begin(); iter != children.end(); ++iter) + { + const LLViewerObject *child = *iter; + const LLVOVolume *child_volume = dynamic_cast<const LLVOVolume*>(child); + if (child_volume) + { + cost += child_volume->getRenderCost(textures); + } + } + + // add texture cost + for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) + { + // add the cost of each individual texture in the linkset + cost += iter->second; + } + + F32 cost_max = (F32) LLVOVolume::getRenderComplexityMax(); + + + + // allow user to set a static color scale + if (gSavedSettings.getS32("RenderComplexityStaticMax") > 0) + { + cost_max = gSavedSettings.getS32("RenderComplexityStaticMax"); + } + + F32 cost_ratio = cost / cost_max; + + // cap cost ratio at 1.0f in case cost_max is at a low threshold + cost_ratio = cost_ratio > 1.0f ? 1.0f : cost_ratio; + + LLGLEnable blend(GL_BLEND); + + LLColor4 color; + const LLColor4 color_min = gSavedSettings.getColor4("RenderComplexityColorMin"); + const LLColor4 color_mid = gSavedSettings.getColor4("RenderComplexityColorMid"); + const LLColor4 color_max = gSavedSettings.getColor4("RenderComplexityColorMax"); + + if (cost_ratio < 0.5f) + { + color = color_min * (1 - cost_ratio * 2) + color_mid * (cost_ratio * 2); + } + else + { + color = color_mid * (1 - (cost_ratio - 0.5) * 2) + color_max * ((cost_ratio - 0.5) * 2); + } + + LLSD color_val = color.getValue(); + + // don't highlight objects below the threshold + if (cost > gSavedSettings.getS32("RenderComplexityThreshold")) + { + glColor4f(color[0],color[1],color[2],0.5f); + + + S32 num_faces = drawablep->getNumFaces(); + if (num_faces) + { + for (S32 i = 0; i < num_faces; ++i) + { + pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); + } + } + LLViewerObject::const_child_list_t children = voVol->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator iter = children.begin(); iter != children.end(); ++iter) + { + const LLViewerObject *child = *iter; + if (child) + { + num_faces = child->getNumFaces(); + if (num_faces) + { + for (S32 i = 0; i < num_faces; ++i) + { + pushVerts(child->mDrawable->getFace(i), LLVertexBuffer::MAP_VERTEX); + } + } + } + } + } + + voVol->setDebugText(llformat("%4.0f", cost)); +} void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) { @@ -2628,17 +2109,17 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) { if (drawable->isSpatialBridge()) { - gGL.color4f(1,0.5f,0,1); + gGL.diffuseColor4f(1,0.5f,0,1); } else if (drawable->getVOVolume()) { if (drawable->isRoot()) { - gGL.color4f(1,1,0,1); + gGL.diffuseColor4f(1,1,0,1); } else { - gGL.color4f(0,1,0,1); + gGL.diffuseColor4f(0,1,0,1); } } else if (drawable->getVObj()) @@ -2646,57 +2127,63 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) switch (drawable->getVObj()->getPCode()) { case LLViewerObject::LL_VO_SURFACE_PATCH: - gGL.color4f(0,1,1,1); + gGL.diffuseColor4f(0,1,1,1); break; case LLViewerObject::LL_VO_CLOUDS: - gGL.color4f(0.5f,0.5f,0.5f,1.0f); + // no longer used break; case LLViewerObject::LL_VO_PART_GROUP: case LLViewerObject::LL_VO_HUD_PART_GROUP: - gGL.color4f(0,0,1,1); + gGL.diffuseColor4f(0,0,1,1); break; case LLViewerObject::LL_VO_VOID_WATER: case LLViewerObject::LL_VO_WATER: - gGL.color4f(0,0.5f,1,1); + gGL.diffuseColor4f(0,0.5f,1,1); break; case LL_PCODE_LEGACY_TREE: - gGL.color4f(0,0.5f,0,1); + gGL.diffuseColor4f(0,0.5f,0,1); break; default: - gGL.color4f(1,0,1,1); + gGL.diffuseColor4f(1,0,1,1); break; } } else { - gGL.color4f(1,0,0,1); + gGL.diffuseColor4f(1,0,0,1); } } - const LLVector3* ext; - LLVector3 pos, size; + const LLVector4a* ext; + LLVector4a pos, size; - //render face bounding boxes - for (S32 i = 0; i < drawable->getNumFaces(); i++) + if (drawable->getVOVolume()) { - LLFace* facep = drawable->getFace(i); - - ext = facep->mExtents; - - if (ext[0].isExactlyZero() && ext[1].isExactlyZero()) + //render face bounding boxes + for (S32 i = 0; i < drawable->getNumFaces(); i++) { - continue; + LLFace* facep = drawable->getFace(i); + if (facep) + { + ext = facep->mExtents; + + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + + drawBoxOutline(pos,size); + } } - 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; + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + size.setSub(ext[1], ext[0]); + size.mul(0.5f); LLViewerObject* vobj = drawable->getVObj(); if (vobj && vobj->onActiveList()) @@ -2713,7 +2200,515 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) { drawBoxOutline(pos,size); } - +} + +void renderNormals(LLDrawable* drawablep) +{ + LLVertexBuffer::unbind(); + + LLVOVolume* vol = drawablep->getVOVolume(); + if (vol) + { + LLVolume* volume = vol->getVolume(); + gGL.pushMatrix(); + gGL.multMatrix((F32*) vol->getRelativeXform().mMatrix); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + LLVector4a scale(gSavedSettings.getF32("RenderDebugNormalScale")); + + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + + for (S32 j = 0; j < face.mNumVertices; ++j) + { + gGL.begin(LLRender::LINES); + LLVector4a n,p; + + n.setMul(face.mNormals[j], scale); + p.setAdd(face.mPositions[j], n); + + gGL.diffuseColor4f(1,1,1,1); + gGL.vertex3fv(face.mPositions[j].getF32ptr()); + gGL.vertex3fv(p.getF32ptr()); + + if (face.mTangents) + { + n.setMul(face.mTangents[j], scale); + p.setAdd(face.mPositions[j], n); + + gGL.diffuseColor4f(0,1,1,1); + gGL.vertex3fv(face.mPositions[j].getF32ptr()); + gGL.vertex3fv(p.getF32ptr()); + } + gGL.end(); + } + } + + gGL.popMatrix(); + } +} + +S32 get_physics_detail(const LLVolumeParams& volume_params, const LLVector3& scale) +{ + const S32 DEFAULT_DETAIL = 1; + const F32 LARGE_THRESHOLD = 5.f; + const F32 MEGA_THRESHOLD = 25.f; + + S32 detail = DEFAULT_DETAIL; + F32 avg_scale = (scale[0]+scale[1]+scale[2])/3.f; + + if (avg_scale > LARGE_THRESHOLD) + { + detail += 1; + if (avg_scale > MEGA_THRESHOLD) + { + detail += 1; + } + } + + return detail; +} + +void renderMeshBaseHull(LLVOVolume* volume, U32 data_mask, LLColor4& color, LLColor4& line_color) +{ + LLUUID mesh_id = volume->getVolume()->getParams().getSculptID(); + LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id); + + const LLVector3 center(0,0,0); + const LLVector3 size(0.25f,0.25f,0.25f); + + if (decomp) + { + if (!decomp->mBaseHullMesh.empty()) + { + gGL.diffuseColor4fv(color.mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mBaseHullMesh.mPositions, decomp->mBaseHullMesh.mNormals); + } + else + { + gMeshRepo.buildPhysicsMesh(*decomp); + gGL.diffuseColor4f(0,1,1,1); + drawBoxOutline(center, size); + } + + } + else + { + gGL.diffuseColor3f(1,0,1); + drawBoxOutline(center, size); + } +} + +void render_hull(LLModel::PhysicsMesh& mesh, const LLColor4& color, const LLColor4& line_color) +{ + gGL.diffuseColor4fv(color.mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); + LLGLEnable offset(GL_POLYGON_OFFSET_LINE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glPolygonOffset(3.f, 3.f); + glLineWidth(3.f); + gGL.diffuseColor4fv(line_color.mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, mesh.mPositions, mesh.mNormals); + glLineWidth(1.f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +} + +void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) +{ + U8 physics_type = volume->getPhysicsShapeType(); + + if (physics_type == LLViewerObject::PHYSICS_SHAPE_NONE || volume->isFlexible()) + { + return; + } + + //not allowed to return at this point without rendering *something* + + F32 threshold = gSavedSettings.getF32("ObjectCostHighThreshold"); + F32 cost = volume->getObjectCost(); + + LLColor4 low = gSavedSettings.getColor4("ObjectCostLowColor"); + LLColor4 mid = gSavedSettings.getColor4("ObjectCostMidColor"); + LLColor4 high = gSavedSettings.getColor4("ObjectCostHighColor"); + + F32 normalizedCost = 1.f - exp( -(cost / threshold) ); + + LLColor4 color; + if ( normalizedCost <= 0.5f ) + { + color = lerp( low, mid, 2.f * normalizedCost ); + } + else + { + color = lerp( mid, high, 2.f * ( normalizedCost - 0.5f ) ); + } + + LLColor4 line_color = color*0.5f; + + U32 data_mask = LLVertexBuffer::MAP_VERTEX; + + LLVolumeParams volume_params = volume->getVolume()->getParams(); + + LLPhysicsVolumeParams physics_params(volume_params, + physics_type == LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); + + LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification physics_spec; + LLPhysicsShapeBuilderUtil::determinePhysicsShape(physics_params, volume->getScale(), physics_spec); + + U32 type = physics_spec.getType(); + + LLVector3 center(0,0,0); + LLVector3 size(0.25f,0.25f,0.25f); + + gGL.pushMatrix(); + gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix); + + if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_MESH) + { + LLUUID mesh_id = volume->getVolume()->getParams().getSculptID(); + LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id); + + if (decomp) + { //render a physics based mesh + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + if (!decomp->mHull.empty()) + { //decomposition exists, use that + + if (decomp->mMesh.empty()) + { + gMeshRepo.buildPhysicsMesh(*decomp); + } + + for (U32 i = 0; i < decomp->mMesh.size(); ++i) + { + render_hull(decomp->mMesh[i], color, line_color); + } + } + else if (!decomp->mPhysicsShapeMesh.empty()) + { + //decomp has physics mesh, render that mesh + gGL.diffuseColor4fv(color.mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals); + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.diffuseColor4fv(line_color.mV); + LLVertexBuffer::drawArrays(LLRender::TRIANGLES, decomp->mPhysicsShapeMesh.mPositions, decomp->mPhysicsShapeMesh.mNormals); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + else + { //no mesh or decomposition, render base hull + renderMeshBaseHull(volume, data_mask, color, line_color); + + if (decomp->mPhysicsShapeMesh.empty()) + { + //attempt to fetch physics shape mesh if available + gMeshRepo.fetchPhysicsShape(mesh_id); + } + } + } + else + { + gGL.diffuseColor3f(1,1,0); + drawBoxOutline(center, size); + } + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::USER_CONVEX || + type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX) + { + if (volume->isMesh()) + { + renderMeshBaseHull(volume, data_mask, color, line_color); + } + else + { + LLVolumeParams volume_params = volume->getVolume()->getParams(); + S32 detail = get_physics_detail(volume_params, volume->getScale()); + LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); + + if (!phys_volume->mHullPoints) + { //build convex hull + std::vector<LLVector3> pos; + std::vector<U16> index; + + S32 index_offset = 0; + + for (S32 i = 0; i < phys_volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = phys_volume->getVolumeFace(i); + if (index_offset + face.mNumVertices > 65535) + { + continue; + } + + for (S32 j = 0; j < face.mNumVertices; ++j) + { + pos.push_back(LLVector3(face.mPositions[j].getF32ptr())); + } + + for (S32 j = 0; j < face.mNumIndices; ++j) + { + index.push_back(face.mIndices[j]+index_offset); + } + + index_offset += face.mNumVertices; + } + + if (!pos.empty() && !index.empty()) + { + LLCDMeshData mesh; + mesh.mIndexBase = &index[0]; + mesh.mVertexBase = pos[0].mV; + mesh.mNumVertices = pos.size(); + mesh.mVertexStrideBytes = 12; + mesh.mIndexStrideBytes = 6; + mesh.mIndexType = LLCDMeshData::INT_16; + + mesh.mNumTriangles = index.size()/3; + + LLCDMeshData res; + + LLConvexDecomposition::getInstance()->generateSingleHullMeshFromMesh( &mesh, &res ); + + //copy res into phys_volume + phys_volume->mHullPoints = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*res.mNumVertices); + phys_volume->mNumHullPoints = res.mNumVertices; + + S32 idx_size = (res.mNumTriangles*3*2+0xF) & ~0xF; + phys_volume->mHullIndices = (U16*) ll_aligned_malloc_16(idx_size); + phys_volume->mNumHullIndices = res.mNumTriangles*3; + + const F32* v = res.mVertexBase; + + for (S32 i = 0; i < res.mNumVertices; ++i) + { + F32* p = (F32*) ((U8*)v+i*res.mVertexStrideBytes); + phys_volume->mHullPoints[i].load3(p); + } + + if (res.mIndexType == LLCDMeshData::INT_16) + { + for (S32 i = 0; i < res.mNumTriangles; ++i) + { + U16* idx = (U16*) (((U8*)res.mIndexBase)+i*res.mIndexStrideBytes); + + phys_volume->mHullIndices[i*3+0] = idx[0]; + phys_volume->mHullIndices[i*3+1] = idx[1]; + phys_volume->mHullIndices[i*3+2] = idx[2]; + } + } + else + { + for (S32 i = 0; i < res.mNumTriangles; ++i) + { + U32* idx = (U32*) (((U8*)res.mIndexBase)+i*res.mIndexStrideBytes); + + phys_volume->mHullIndices[i*3+0] = (U16) idx[0]; + phys_volume->mHullIndices[i*3+1] = (U16) idx[1]; + phys_volume->mHullIndices[i*3+2] = (U16) idx[2]; + } + } + } + } + + if (phys_volume->mHullPoints) + { + //render hull + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + gGL.diffuseColor4fv(line_color.mV); + LLVertexBuffer::unbind(); + + llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0); + + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + + gGL.diffuseColor4fv(color.mV); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + LLVertexBuffer::drawElements(LLRender::TRIANGLES, phys_volume->mHullPoints, NULL, phys_volume->mNumHullIndices, phys_volume->mHullIndices); + + } + else + { + gGL.diffuseColor4f(1,0,1,1); + drawBoxOutline(center, size); + } + + LLPrimitive::sVolumeManager->unrefVolume(phys_volume); + } + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::BOX) + { + LLVector3 center = physics_spec.getCenter(); + LLVector3 scale = physics_spec.getScale(); + LLVector3 vscale = volume->getScale()*2.f; + scale.set(scale[0]/vscale[0], scale[1]/vscale[1], scale[2]/vscale[2]); + + gGL.diffuseColor4fv(color.mV); + drawBox(center, scale); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SPHERE) + { + LLVolumeParams volume_params; + volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE ); + volume_params.setBeginAndEndS( 0.f, 1.f ); + volume_params.setBeginAndEndT( 0.f, 1.f ); + volume_params.setRatio ( 1, 1 ); + volume_params.setShear ( 0, 0 ); + LLVolume* sphere = LLPrimitive::sVolumeManager->refVolume(volume_params, 3); + + gGL.diffuseColor4fv(color.mV); + pushVerts(sphere); + LLPrimitive::sVolumeManager->unrefVolume(sphere); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::CYLINDER) + { + LLVolumeParams volume_params; + volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); + volume_params.setBeginAndEndS( 0.f, 1.f ); + volume_params.setBeginAndEndT( 0.f, 1.f ); + volume_params.setRatio ( 1, 1 ); + volume_params.setShear ( 0, 0 ); + LLVolume* cylinder = LLPrimitive::sVolumeManager->refVolume(volume_params, 3); + + gGL.diffuseColor4fv(color.mV); + pushVerts(cylinder); + LLPrimitive::sVolumeManager->unrefVolume(cylinder); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_MESH) + { + LLVolumeParams volume_params = volume->getVolume()->getParams(); + S32 detail = get_physics_detail(volume_params, volume->getScale()); + + LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + gGL.diffuseColor4fv(line_color.mV); + pushVerts(phys_volume); + + gGL.diffuseColor4fv(color.mV); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + pushVerts(phys_volume); + LLPrimitive::sVolumeManager->unrefVolume(phys_volume); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::PRIM_CONVEX) + { + LLVolumeParams volume_params = volume->getVolume()->getParams(); + S32 detail = get_physics_detail(volume_params, volume->getScale()); + + LLVolume* phys_volume = LLPrimitive::sVolumeManager->refVolume(volume_params, detail); + + if (phys_volume->mHullPoints && phys_volume->mHullIndices) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShader != 0); + LLVertexBuffer::unbind(); + glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints); + gGL.diffuseColor4fv(line_color.mV); + gGL.syncMatrices(); + glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices); + + gGL.diffuseColor4fv(color.mV); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glDrawElements(GL_TRIANGLES, phys_volume->mNumHullIndices, GL_UNSIGNED_SHORT, phys_volume->mHullIndices); + } + else + { + gGL.diffuseColor3f(1,0,1); + drawBoxOutline(center, size); + gMeshRepo.buildHull(volume_params, detail); + } + LLPrimitive::sVolumeManager->unrefVolume(phys_volume); + } + else if (type == LLPhysicsShapeBuilderUtil::PhysicsShapeSpecification::SCULPT) + { + //TODO: implement sculpted prim physics display + } + else + { + LL_ERRS() << "Unhandled type" << LL_ENDL; + } + + gGL.popMatrix(); +} + +void renderPhysicsShapes(LLSpatialGroup* group) +{ + for (OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + + if (drawable->isSpatialBridge()) + { + LLSpatialBridge* bridge = drawable->asPartition()->asBridge(); + + if (bridge) + { + gGL.pushMatrix(); + gGL.multMatrix((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); + bridge->renderPhysicsShapes(); + gGL.popMatrix(); + } + } + else + { + LLVOVolume* volume = drawable->getVOVolume(); + if (volume && !volume->isAttachment() && volume->getPhysicsShapeType() != LLViewerObject::PHYSICS_SHAPE_NONE ) + { + if (!group->getSpatialPartition()->isBridge()) + { + gGL.pushMatrix(); + LLVector3 trans = drawable->getRegion()->getOriginAgent(); + gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); + renderPhysicsShape(drawable, volume); + gGL.popMatrix(); + } + else + { + renderPhysicsShape(drawable, volume); + } + } + else + { + LLViewerObject* object = drawable->getVObj(); + if (object && object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) + { + gGL.pushMatrix(); + gGL.multMatrix((F32*) object->getRegion()->mRenderMatrix.mMatrix); + //push face vertices for terrain + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* face = drawable->getFace(i); + if (face) + { + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + buff->setBuffer(LLVertexBuffer::MAP_VERTEX); + gGL.diffuseColor3f(0.2f, 0.5f, 0.3f); + buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); + + gGL.diffuseColor3f(0.2f, 1.f, 0.3f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + buff->draw(LLRender::TRIANGLES, buff->getNumIndices(), 0); + } + } + } + gGL.popMatrix(); + } + } + } + } } void renderTexturePriority(LLDrawable* drawable) @@ -2732,6 +2727,7 @@ void renderTexturePriority(LLDrawable* drawable) //LLViewerTexture* imagep = facep->getTexture(); //if (imagep) + if (facep) { //F32 vsize = imagep->mMaxVirtualSize; @@ -2745,25 +2741,30 @@ void renderTexturePriority(LLDrawable* drawable) F32 t = vsize/sLastMaxTexPriority; LLVector4 col = lerp(cold, hot, t); - gGL.color4fv(col.mV); + gGL.diffuseColor4fv(col.mV); } //else //{ - // gGL.color4f(1,0,1,1); + // gGL.diffuseColor4f(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); + LLVector4a center; + center.setAdd(facep->mExtents[1],facep->mExtents[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(facep->mExtents[1],facep->mExtents[0]); + size.mul(0.5f); + size.add(LLVector4a(0.01f)); drawBox(center, size); /*S32 boost = imagep->getBoostLevel(); - if (boost>LLViewerTexture::BOOST_NONE) + if (boost>LLGLTexture::BOOST_NONE) { - F32 t = (F32) boost / (F32) (LLViewerTexture::BOOST_MAX_LEVEL-1); + F32 t = (F32) boost / (F32) (LLGLTexture::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); + gGL.diffuseColor4fv(col.mV); drawBox(center, size); gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }*/ @@ -2776,11 +2777,14 @@ void renderPoints(LLDrawable* drawablep) if (drawablep->getNumFaces()) { gGL.begin(LLRender::POINTS); - gGL.color3f(1,1,1); - LLVector3 center(drawablep->getPositionGroup()); + gGL.diffuseColor3f(1,1,1); for (S32 i = 0; i < drawablep->getNumFaces(); i++) { - gGL.vertex3fv(drawablep->getFace(i)->mCenterLocal.mV); + LLFace * face = drawablep->getFace(i); + if (face) + { + gGL.vertex3fv(face->mCenterLocal.mV); + } } gGL.end(); } @@ -2794,13 +2798,15 @@ void renderTextureAnim(LLDrawInfo* params) } LLGLEnable blend(GL_BLEND); - glColor4f(1,1,0,0.5f); + gGL.diffuseColor4f(1,1,0,0.5f); pushVerts(params, LLVertexBuffer::MAP_VERTEX); } void renderBatchSize(LLDrawInfo* params) { - glColor3ubv((GLubyte*) &(params->mDebugColor)); + LLGLEnable offset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.f, 1.f); + gGL.diffuseColor4ubv((GLubyte*) &(params->mDebugColor)); pushVerts(params, LLVertexBuffer::MAP_VERTEX); } @@ -2809,33 +2815,141 @@ 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; + LLVector4a center; + center.setAdd(params->mExtents[1], params->mExtents[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(params->mExtents[1],params->mExtents[0]); + size.mul(0.5f); if (gPipeline.mShadowCamera[4].AABBInFrustum(center, size)) { - glColor3f(1,0,0); + gGL.diffuseColor3f(1,0,0); pushVerts(params, LLVertexBuffer::MAP_VERTEX); } if (gPipeline.mShadowCamera[5].AABBInFrustum(center, size)) { - glColor3f(0,1,0); + gGL.diffuseColor3f(0,1,0); pushVerts(params, LLVertexBuffer::MAP_VERTEX); } if (gPipeline.mShadowCamera[6].AABBInFrustum(center, size)) { - glColor3f(0,0,1); + gGL.diffuseColor3f(0,0,1); pushVerts(params, LLVertexBuffer::MAP_VERTEX); } if (gPipeline.mShadowCamera[7].AABBInFrustum(center, size)) { - glColor3f(1,0,1); + gGL.diffuseColor3f(1,0,1); pushVerts(params, LLVertexBuffer::MAP_VERTEX); } gGL.setSceneBlendType(LLRender::BT_ALPHA); } +void renderTexelDensity(LLDrawable* drawable) +{ + if (LLViewerTexture::sDebugTexelsMode == LLViewerTexture::DEBUG_TEXELS_OFF + || LLViewerTexture::sCheckerBoardImagep.isNull()) + { + return; + } + + LLGLEnable _(GL_BLEND); + //gObjectFullbrightProgram.bind(); + + LLMatrix4 checkerboard_matrix; + S32 discard_level = -1; + + for (S32 f = 0; f < drawable->getNumFaces(); f++) + { + LLFace* facep = drawable->getFace(f); + LLVertexBuffer* buffer = facep->getVertexBuffer(); + LLViewerTexture* texturep = facep->getTexture(); + + if (texturep == NULL) continue; + + switch(LLViewerTexture::sDebugTexelsMode) + { + case LLViewerTexture::DEBUG_TEXELS_CURRENT: + discard_level = -1; + break; + case LLViewerTexture::DEBUG_TEXELS_DESIRED: + { + LLViewerFetchedTexture* fetched_texturep = dynamic_cast<LLViewerFetchedTexture*>(texturep); + discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; + break; + } + default: + case LLViewerTexture::DEBUG_TEXELS_FULL: + discard_level = 0; + break; + } + + checkerboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); + + gGL.getTexUnit(0)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); + gGL.matrixMode(LLRender::MM_TEXTURE); + gGL.loadMatrix((GLfloat*)&checkerboard_matrix.mMatrix); + + if (buffer && (facep->getGeomCount() >= 3)) + { + buffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + U16 start = facep->getGeomStart(); + U16 end = start + facep->getGeomCount()-1; + U32 count = facep->getIndicesCount(); + U16 offset = facep->getIndicesStart(); + buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } + + gGL.loadIdentity(); + gGL.matrixMode(LLRender::MM_MODELVIEW); + } + + //S32 num_textures = llmax(1, (S32)params->mTextureList.size()); + + //for (S32 i = 0; i < num_textures; i++) + //{ + // LLViewerTexture* texturep = params->mTextureList.empty() ? params->mTexture.get() : params->mTextureList[i].get(); + // if (texturep == NULL) continue; + + // LLMatrix4 checkboard_matrix; + // S32 discard_level = -1; + // switch(LLViewerTexture::sDebugTexelsMode) + // { + // case LLViewerTexture::DEBUG_TEXELS_CURRENT: + // discard_level = -1; + // break; + // case LLViewerTexture::DEBUG_TEXELS_DESIRED: + // { + // LLViewerFetchedTexture* fetched_texturep = dynamic_cast<LLViewerFetchedTexture*>(texturep); + // discard_level = fetched_texturep ? fetched_texturep->getDesiredDiscardLevel() : -1; + // break; + // } + // default: + // case LLViewerTexture::DEBUG_TEXELS_FULL: + // discard_level = 0; + // break; + // } + + // checkboard_matrix.initScale(LLVector3(texturep->getWidth(discard_level) / 8, texturep->getHeight(discard_level) / 8, 1.f)); + // gGL.getTexUnit(i)->activate(); + + // glMatrixMode(GL_TEXTURE); + // glPushMatrix(); + // glLoadIdentity(); + // //gGL.matrixMode(LLRender::MM_TEXTURE); + // glLoadMatrixf((GLfloat*) checkboard_matrix.mMatrix); + + // gGL.getTexUnit(i)->bind(LLViewerTexture::sCheckerBoardImagep, TRUE); + + // pushVerts(params, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL ); + + // glPopMatrix(); + // glMatrixMode(GL_MODELVIEW); + // //gGL.matrixMode(LLRender::MM_MODELVIEW); + //} +} + void renderLights(LLDrawable* drawablep) { @@ -2847,85 +2961,252 @@ void renderLights(LLDrawable* drawablep) if (drawablep->getNumFaces()) { LLGLEnable blend(GL_BLEND); - glColor4f(0,1,1,0.5f); + gGL.diffuseColor4f(0,1,1,0.5f); for (S32 i = 0; i < drawablep->getNumFaces(); i++) { - pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); + LLFace * face = drawablep->getFace(i); + if (face) + { + pushVerts(face, LLVertexBuffer::MAP_VERTEX); + } } - const LLVector3* ext = drawablep->getSpatialExtents(); + const LLVector4a* ext = drawablep->getSpatialExtents(); - LLVector3 pos = (ext[0] + ext[1]) * 0.5f; - LLVector3 size = (ext[1] - ext[0]) * 0.5f; + LLVector4a pos; + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); { LLGLDepthTest depth(GL_FALSE, GL_TRUE); - gGL.color4f(1,1,1,1); + gGL.diffuseColor4f(1,1,1,1); drawBoxOutline(pos, size); } - gGL.color4f(1,1,0,1); + gGL.diffuseColor4f(1,1,0,1); F32 rad = drawablep->getVOVolume()->getLightRadius(); - drawBoxOutline(pos, LLVector3(rad,rad,rad)); + drawBoxOutline(pos, LLVector4a(rad)); } } - -void renderRaycast(LLDrawable* drawablep) +class LLRenderOctreeRaycast : public LLOctreeTriangleRayIntersect { - if (drawablep->getVObj() != gDebugRaycastObject) +public: + + + LLRenderOctreeRaycast(const LLVector4a& start, const LLVector4a& dir, F32* closest_t) + : LLOctreeTriangleRayIntersect(start, dir, NULL, closest_t, NULL, NULL, NULL, NULL) { - return; + } - + + void visit(const LLOctreeNode<LLVolumeTriangle>* branch) + { + LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) branch->getListener(0); + + LLVector3 center, size; + + if (branch->isEmpty()) + { + gGL.diffuseColor3f(1.f,0.2f,0.f); + center.set(branch->getCenter().getF32ptr()); + size.set(branch->getSize().getF32ptr()); + } + else + { + gGL.diffuseColor3f(0.75f, 1.f, 0.f); + center.set(vl->mBounds[0].getF32ptr()); + size.set(vl->mBounds[1].getF32ptr()); + } + + drawBoxOutline(center, size); + + for (U32 i = 0; i < 2; i++) + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE, i == 1 ? GL_LEQUAL : GL_GREATER); + + if (i == 1) + { + gGL.diffuseColor4f(0,1,1,0.5f); + } + else + { + gGL.diffuseColor4f(0,0.5f,0.5f, 0.25f); + drawBoxOutline(center, size); + } + + if (i == 1) + { + gGL.flush(); + glLineWidth(3.f); + } + + gGL.begin(LLRender::TRIANGLES); + for (LLOctreeNode<LLVolumeTriangle>::const_element_iter iter = branch->getDataBegin(); + iter != branch->getDataEnd(); + ++iter) + { + const LLVolumeTriangle* tri = *iter; + + gGL.vertex3fv(tri->mV[0]->getF32ptr()); + gGL.vertex3fv(tri->mV[1]->getF32ptr()); + gGL.vertex3fv(tri->mV[2]->getF32ptr()); + } + gGL.end(); + + if (i == 1) + { + gGL.flush(); + glLineWidth(1.f); + } + } + } +}; + +void renderRaycast(LLDrawable* drawablep) +{ if (drawablep->getNumFaces()) { LLGLEnable blend(GL_BLEND); - gGL.color4f(0,1,1,0.5f); + gGL.diffuseColor4f(0,1,1,0.5f); - if (drawablep->getVOVolume() && gDebugRaycastFaceHit != -1) + if (drawablep->getVOVolume()) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - pushVerts(drawablep->getFace(gDebugRaycastFaceHit), LLVertexBuffer::MAP_VERTEX); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + //pushVerts(drawablep->getFace(gDebugRaycastFaceHit), LLVertexBuffer::MAP_VERTEX); + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + LLVOVolume* vobj = drawablep->getVOVolume(); + LLVolume* volume = vobj->getVolume(); + + bool transform = true; + if (drawablep->isState(LLDrawable::RIGGED)) + { + volume = vobj->getRiggedVolume(); + transform = false; + } + + if (volume) + { + LLVector3 trans = drawablep->getRegion()->getOriginAgent(); + + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + + gGL.pushMatrix(); + gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); + gGL.multMatrix((F32*) vobj->getRelativeXform().mMatrix); + + LLVector4a start, end; + if (transform) + { + LLVector3 v_start(gDebugRaycastStart.getF32ptr()); + LLVector3 v_end(gDebugRaycastEnd.getF32ptr()); + + v_start = vobj->agentPositionToVolume(v_start); + v_end = vobj->agentPositionToVolume(v_end); + + start.load3(v_start.mV); + end.load3(v_end.mV); + } + else + { + start = gDebugRaycastStart; + end = gDebugRaycastEnd; + } + + LLVector4a dir; + dir.setSub(end, start); + + gGL.flush(); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + { + //render face positions + LLVertexBuffer::unbind(); + gGL.diffuseColor4f(0,1,1,0.5f); + glVertexPointer(3, GL_FLOAT, sizeof(LLVector4a), face.mPositions); + gGL.syncMatrices(); + glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices); + } + + if (!volume->isUnique()) + { + F32 t = 1.f; + + if (!face.mOctree) + { + ((LLVolumeFace*) &face)->createOctree(); + } + + LLRenderOctreeRaycast render(start, dir, &t); + + render.traverse(face.mOctree); + } + + gGL.popMatrix(); + 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(); + if (drawablep->getVObj() == gDebugRaycastObject) + { + LLGLDepthTest depth(GL_FALSE); + LLVOAvatar* av = (LLVOAvatar*) drawablep->getVObj().get(); + av->renderCollisionVolumes(); + } + } - LLVector3 pos = (ext[0] + ext[1]) * 0.5f; - LLVector3 size = (ext[1] - ext[0]) * 0.5f; + if (drawablep->getVObj() == gDebugRaycastObject) + { + // draw intersection point + gGL.pushMatrix(); + gGL.loadMatrix(gGLModelView); + LLVector3 translate(gDebugRaycastIntersection.getF32ptr()); + gGL.translatef(translate.mV[0], translate.mV[1], translate.mV[2]); + LLCoordFrame orient; + LLVector4a debug_binormal; + + debug_binormal.setCross3(gDebugRaycastNormal, gDebugRaycastTangent); + debug_binormal.mul(gDebugRaycastTangent.getF32ptr()[3]); - LLGLDepthTest depth(GL_FALSE, GL_TRUE); - gGL.color4f(0,0.5f,0.5f,1); - drawBoxOutline(pos, size); + LLVector3 normal(gDebugRaycastNormal.getF32ptr()); + LLVector3 binormal(debug_binormal.getF32ptr()); + + orient.lookDir(normal, binormal); + LLMatrix4 rotation; + orient.getRotMatrixToParent(rotation); + gGL.multMatrix((float*)rotation.mMatrix); + + gGL.diffuseColor4f(1,0,0,0.5f); + drawBox(LLVector3(0, 0, 0), LLVector3(0.1f, 0.022f, 0.022f)); + gGL.diffuseColor4f(0,1,0,0.5f); + drawBox(LLVector3(0, 0, 0), LLVector3(0.021f, 0.1f, 0.021f)); + gGL.diffuseColor4f(0,0,1,0.5f); + drawBox(LLVector3(0, 0, 0), LLVector3(0.02f, 0.02f, 0.1f)); + gGL.popMatrix(); + + // draw bounding box of prim + const LLVector4a* ext = drawablep->getSpatialExtents(); + + LLVector4a pos; + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + LLGLDepthTest depth(GL_FALSE, GL_TRUE); + gGL.diffuseColor4f(0,0.5f,0.5f,1); + drawBoxOutline(pos, size); + } } } @@ -2941,24 +3222,24 @@ void renderAgentTarget(LLVOAvatar* avatar) 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->mDrawable->getPositionAgent(), 0.2f, LLColor4(0, 1, 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> +class LLOctreeRenderNonOccluded : public OctreeTraveler { public: LLCamera* mCamera; LLOctreeRenderNonOccluded(LLCamera* camera): mCamera(camera) {} - virtual void traverse(const LLSpatialGroup::OctreeNode* node) + virtual void traverse(const OctreeNode* node) { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - if (!mCamera || mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1])) + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) { node->accept(this); stop_glerror(); @@ -2986,59 +3267,71 @@ public: group->rebuildMesh(); gGL.flush(); - glPushMatrix(); + gGL.pushMatrix(); gGLLastMatrix = NULL; - glLoadMatrixd(gGLModelView); + gGL.loadMatrix(gGLModelView); renderVisibility(group, mCamera); stop_glerror(); gGLLastMatrix = NULL; - glPopMatrix(); - gGL.color4f(1,1,1,1); + gGL.popMatrix(); + gGL.diffuseColor4f(1,1,1,1); } } } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) + virtual void visit(const OctreeNode* branch) { LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); - - if (group->isState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]))) + const LLVector4a* bounds = group->getBounds(); + if (group->hasState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[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()) + if (!group->isEmpty()) { - gGL.color3f(0,0,1); - drawBoxOutline(group->mObjectBounds[0], - group->mObjectBounds[1]); + gGL.diffuseColor3f(0,0,1); + const LLVector4a* obj_bounds = group->getObjectBounds(); + drawBoxOutline(obj_bounds[0], obj_bounds[1]); } } - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { - LLDrawable* drawable = *i; - + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) { renderBoundingBox(drawable); } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_NORMALS)) + { + renderNormals(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); + gGL.diffuseColor4f(0.6f, 0.6f, 0.1f, 1.f); + const LLVector4a* ext = drawable->getSpatialExtents(); + LLVector4a center; + center.setAdd(ext[0], ext[1]); + center.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + drawBoxOutline(center, size); } } @@ -3065,6 +3358,14 @@ public: { renderUpdateType(drawable); } + if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY)) + { + renderComplexityDisplay(drawable); + } + if(gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) + { + renderTexelDensity(drawable); + } LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(drawable->getVObj().get()); @@ -3078,6 +3379,31 @@ public: renderAgentTarget(avatar); } + if (gDebugGL) + { + for (U32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* facep = drawable->getFace(i); + if (facep) + { + U8 index = facep->getTextureIndex(); + if (facep->mDrawInfo) + { + if (index < 255) + { + if (facep->mDrawInfo->mTextureList.size() <= index) + { + LL_ERRS() << "Face texture index out of bounds." << LL_ENDL; + } + else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) + { + LL_ERRS() << "Face texture index incorrect." << LL_ENDL; + } + } + } + } + } + } } for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) @@ -3103,17 +3429,97 @@ public: } }; -class LLOctreePushBBoxVerts : public LLOctreeTraveler<LLDrawable> +class LLOctreeRenderXRay : public OctreeTraveler +{ +public: + LLCamera* mCamera; + LLOctreeRenderXRay(LLCamera* camera): mCamera(camera) {} + + virtual void traverse(const OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) + { + node->accept(this); + stop_glerror(); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + stop_glerror(); + } + + //render visibility wireframe + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + { + group->rebuildGeom(); + group->rebuildMesh(); + + gGL.flush(); + gGL.pushMatrix(); + gGLLastMatrix = NULL; + gGL.loadMatrix(gGLModelView); + renderXRay(group, mCamera); + stop_glerror(); + gGLLastMatrix = NULL; + gGL.popMatrix(); + } + } + } + + virtual void visit(const OctreeNode* node) {} + +}; + +class LLOctreeRenderPhysicsShapes : public OctreeTraveler +{ +public: + LLCamera* mCamera; + LLOctreeRenderPhysicsShapes(LLCamera* camera): mCamera(camera) {} + + virtual void traverse(const OctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) + { + node->accept(this); + stop_glerror(); + + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + stop_glerror(); + } + + group->rebuildGeom(); + group->rebuildMesh(); + + renderPhysicsShapes(group); + } + } + + virtual void visit(const OctreeNode* branch) + { + + } +}; + +class LLOctreePushBBoxVerts : public OctreeTraveler { public: LLCamera* mCamera; LLOctreePushBBoxVerts(LLCamera* camera): mCamera(camera) {} - virtual void traverse(const LLSpatialGroup::OctreeNode* node) + virtual void traverse(const OctreeNode* node) { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - if (!mCamera || mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1])) + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustum(bounds[0], bounds[1])) { node->accept(this); @@ -3124,19 +3530,23 @@ public: } } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) + virtual void visit(const OctreeNode* branch) { LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); - if (group->isState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]))) + const LLVector4a* bounds = group->getBounds(); + if (group->hasState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1]))) { return; } - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { - LLDrawable* drawable = *i; - + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } renderBoundingBox(drawable, FALSE); } } @@ -3148,7 +3558,7 @@ void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera) pusher.traverse(mOctree); } -class LLOctreeStateCheck : public LLOctreeTraveler<LLDrawable> +class LLOctreeStateCheck : public OctreeTraveler { public: U32 mInheritedMask[LLViewerCamera::NUM_CAMERAS]; @@ -3161,7 +3571,7 @@ public: } } - virtual void traverse(const LLSpatialGroup::OctreeNode* node) + virtual void traverse(const OctreeNode* node) { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); @@ -3188,7 +3598,7 @@ public: } - virtual void visit(const LLOctreeNode<LLDrawable>* state) + virtual void visit(const OctreeNode* state) { LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); @@ -3196,11 +3606,11 @@ public: { if (mInheritedMask[i] && !(group->mOcclusionState[i] & mInheritedMask[i])) { - llerrs << "Spatial group failed inherited mask test." << llendl; + LL_ERRS() << "Spatial group failed inherited mask test." << LL_ENDL; } } - if (group->isState(LLSpatialGroup::DIRTY)) + if (group->hasState(LLSpatialGroup::DIRTY)) { assert_parent_state(group, LLSpatialGroup::DIRTY); } @@ -3211,9 +3621,9 @@ public: LLSpatialGroup* parent = group->getParent(); while (parent) { - if (!parent->isState(state)) + if (!parent->hasState(state)) { - llerrs << "Spatial group failed parent state check." << llendl; + LL_ERRS() << "Spatial group failed parent state check." << LL_ENDL; } parent = parent->getParent(); } @@ -3221,6 +3631,25 @@ public: }; +void LLSpatialPartition::renderPhysicsShapes() +{ + LLSpatialBridge* bridge = asBridge(); + LLCamera* camera = LLViewerCamera::getInstance(); + + if (bridge) + { + camera = NULL; + } + + gGL.flush(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + glLineWidth(3.f); + LLOctreeRenderPhysicsShapes render_physics(camera); + render_physics.traverse(mOctree); + gGL.flush(); + glLineWidth(1.f); +} + void LLSpatialPartition::renderDebug() { if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE | @@ -3229,18 +3658,26 @@ void LLSpatialPartition::renderDebug() LLPipeline::RENDER_DEBUG_BATCH_SIZE | LLPipeline::RENDER_DEBUG_UPDATE_TYPE | LLPipeline::RENDER_DEBUG_BBOXES | + LLPipeline::RENDER_DEBUG_NORMALS | 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)) + //LLPipeline::RENDER_DEBUG_BUILD_QUEUE | + LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA | + LLPipeline::RENDER_DEBUG_RENDER_COMPLEXITY | + LLPipeline::RENDER_DEBUG_TEXEL_DENSITY)) { return; } + if (LLGLSLShader::sNoFixedFunction) + { + gDebugProgram.bind(); + } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { //sLastMaxTexPriority = lerp(sLastMaxTexPriority, sCurMaxTexPriority, gFrameIntervalSeconds); @@ -3248,8 +3685,6 @@ void LLSpatialPartition::renderDebug() sCurMaxTexPriority = 0.f; } - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - LLGLDisable cullface(GL_CULL_FACE); LLGLEnable blend(GL_BLEND); gGL.setSceneBlendType(LLRender::BT_ALPHA); @@ -3269,14 +3704,47 @@ void LLSpatialPartition::renderDebug() LLOctreeRenderNonOccluded render_debug(camera); render_debug.traverse(mOctree); + + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + { + { + LLGLEnable cull(GL_CULL_FACE); + + LLGLEnable blend(GL_BLEND); + LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + gGL.diffuseColor4f(0.5f, 0.0f, 0, 0.25f); + + LLGLEnable offset(GL_POLYGON_OFFSET_LINE); + glPolygonOffset(-1.f, -1.f); + + LLOctreeRenderXRay xray(camera); + xray.traverse(mOctree); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + } + if (LLGLSLShader::sNoFixedFunction) + { + gDebugProgram.unbind(); + } } void LLSpatialGroup::drawObjectBox(LLColor4 col) { - gGL.color4fv(col.mV); - drawBox(mObjectBounds[0], mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); + gGL.diffuseColor4fv(col.mV); + LLVector4a size; + size = mObjectBounds[1]; + size.mul(1.01f); + size.add(LLVector4a(0.001f)); + drawBox(mObjectBounds[0], size); } +bool LLSpatialPartition::isHUDPartition() +{ + return mPartitionType == LLViewerRegion::PARTITION_HUD ; +} BOOL LLSpatialPartition::isVisible(const LLVector3& v) { @@ -3288,68 +3756,74 @@ BOOL LLSpatialPartition::isVisible(const LLVector3& v) return TRUE; } -class LLOctreeIntersect : public LLSpatialGroup::OctreeTraveler +LL_ALIGN_PREFIX(16) +class LLOctreeIntersect : public LLOctreeTraveler<LLViewerOctreeEntry> { public: - LLVector3 mStart; - LLVector3 mEnd; + LL_ALIGN_16(LLVector4a mStart); + LL_ALIGN_16(LLVector4a mEnd); + S32 *mFaceHit; - LLVector3 *mIntersection; + LLVector4a *mIntersection; LLVector2 *mTexCoord; - LLVector3 *mNormal; - LLVector3 *mBinormal; + LLVector4a *mNormal; + LLVector4a *mTangent; LLDrawable* mHit; BOOL mPickTransparent; - LLOctreeIntersect(LLVector3 start, LLVector3 end, BOOL pick_transparent, - S32* face_hit, LLVector3* intersection, LLVector2* tex_coord, LLVector3* normal, LLVector3* binormal) + LLOctreeIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, + S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, LLVector4a* normal, LLVector4a* tangent) : mStart(start), mEnd(end), mFaceHit(face_hit), mIntersection(intersection), mTexCoord(tex_coord), mNormal(normal), - mBinormal(binormal), + mTangent(tangent), mHit(NULL), mPickTransparent(pick_transparent) { } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) + virtual void visit(const OctreeNode* branch) { - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { check(*i); } } - virtual LLDrawable* check(const LLSpatialGroup::OctreeNode* node) + virtual LLDrawable* check(const OctreeNode* node) { node->accept(this); for (U32 i = 0; i < node->getChildCount(); i++) { - const LLSpatialGroup::OctreeNode* child = node->getChild(i); + const OctreeNode* child = node->getChild(i); LLVector3 res; LLSpatialGroup* group = (LLSpatialGroup*) child->getListener(0); - LLVector3 size; - LLVector3 center; + LLVector4a size; + LLVector4a center; - size = group->mBounds[1]; - center = group->mBounds[0]; + const LLVector4a* bounds = group->getBounds(); + size = bounds[1]; + center = bounds[0]; - LLVector3 local_start = mStart; - LLVector3 local_end = mEnd; + LLVector4a local_start = mStart; + LLVector4a local_end = mEnd; - if (group->mSpatialPartition->isBridge()) + if (group->getSpatialPartition()->isBridge()) { - LLMatrix4 local_matrix = group->mSpatialPartition->asBridge()->mDrawable->getRenderMatrix(); + LLMatrix4 local_matrix = group->getSpatialPartition()->asBridge()->mDrawable->getRenderMatrix(); local_matrix.invert(); - local_start = mStart * local_matrix; - local_end = mEnd * local_matrix; + LLMatrix4a local_matrix4a; + local_matrix4a.loadu(local_matrix); + + local_matrix4a.affineTransform(mStart, local_start); + local_matrix4a.affineTransform(mEnd, local_end); } if (LLLineSegmentBoxIntersect(local_start, local_end, center, size)) @@ -3361,12 +3835,11 @@ public: return mHit; } - virtual bool check(LLDrawable* drawable) + virtual bool check(LLViewerOctreeEntry* entry) { - LLVector3 local_start = mStart; - LLVector3 local_end = mEnd; - - if (!gPipeline.hasRenderType(drawable->getRenderType()) || !drawable->isVisible()) + LLDrawable* drawable = (LLDrawable*)entry->getDrawable(); + + if (!drawable || !gPipeline.hasRenderType(drawable->getRenderType()) || !drawable->isVisible()) { return false; } @@ -3386,8 +3859,30 @@ public: if (vobj) { - LLVector3 intersection; - if (vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal)) + LLVector4a intersection; + bool skip_check = false; + if (vobj->isAvatar()) + { + LLVOAvatar* avatar = (LLVOAvatar*) vobj; + if (avatar->isSelf() && LLFloater::isVisible(gFloaterTools)) + { + LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mTangent); + if (hit) + { + mEnd = intersection; + if (mIntersection) + { + *mIntersection = intersection; + } + + mHit = hit->mDrawable; + skip_check = true; + } + + } + } + + if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mTangent)) { mEnd = intersection; // shorten ray so we only find CLOSER hits if (mIntersection) @@ -3402,19 +3897,19 @@ public: return false; } -}; +} LL_ALIGN_POSTFIX(16); -LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, +LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, BOOL pick_transparent, S32* face_hit, // return the face hit - LLVector3* intersection, // return the intersection point + LLVector4a* 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 + LLVector4a* normal, // return the surface normal at the intersection point + LLVector4a* tangent // return the surface tangent at the intersection point ) { - LLOctreeIntersect intersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, bi_normal); + LLOctreeIntersect intersect(start, end, pick_transparent, face_hit, intersection, tex_coord, normal, tangent); LLDrawable* drawable = intersect.check(mOctree); return drawable; @@ -3423,7 +3918,7 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector3& start, con LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, LLViewerTexture* texture, LLVertexBuffer* buffer, BOOL fullbright, U8 bump, BOOL particle, F32 part_size) -: +: LLTrace::MemTrackableNonVirtual<LLDrawInfo, 16>("LLDrawInfo"), mVertexBuffer(buffer), mTexture(texture), mTextureMatrix(NULL), @@ -3440,33 +3935,43 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, mGroup(NULL), mFace(NULL), mDistance(0.f), - mDrawMode(LLRender::TRIANGLES) -{ + mDrawMode(LLRender::TRIANGLES), + mMaterial(NULL), + mShaderMask(0), + mSpecColor(1.0f, 1.0f, 1.0f, 0.5f), + mBlendFuncSrc(LLRender::BF_SOURCE_ALPHA), + mBlendFuncDst(LLRender::BF_ONE_MINUS_SOURCE_ALPHA), + mHasGlow(FALSE), + mEnvIntensity(0.0f), + mAlphaMaskCutoff(0.5f), + mDiffuseAlphaMode(0) +{ + mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); + 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; + LL_ERRS() << "LLDrawInfo deleted illegally!" << LL_ENDL; }*/ if (mFace) { mFace->setDrawInfo(NULL); } + + if (gDebugGL) + { + gPipeline.checkReferences(this); + } +} + +void LLDrawInfo::validate() +{ + mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); } LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) @@ -3476,28 +3981,70 @@ LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) LLCullResult::LLCullResult() { + mVisibleGroupsAllocated = 0; + mAlphaGroupsAllocated = 0; + mOcclusionGroupsAllocated = 0; + mDrawableGroupsAllocated = 0; + mVisibleListAllocated = 0; + mVisibleBridgeAllocated = 0; + + mVisibleGroups.clear(); + mVisibleGroups.push_back(NULL); + mVisibleGroupsEnd = &mVisibleGroups[0]; + mAlphaGroups.clear(); + mAlphaGroups.push_back(NULL); + mAlphaGroupsEnd = &mAlphaGroups[0]; + mOcclusionGroups.clear(); + mOcclusionGroups.push_back(NULL); + mOcclusionGroupsEnd = &mOcclusionGroups[0]; + mDrawableGroups.clear(); + mDrawableGroups.push_back(NULL); + mDrawableGroupsEnd = &mDrawableGroups[0]; + mVisibleList.clear(); + mVisibleList.push_back(NULL); + mVisibleListEnd = &mVisibleList[0]; + mVisibleBridge.clear(); + mVisibleBridge.push_back(NULL); + mVisibleBridgeEnd = &mVisibleBridge[0]; + + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) + { + mRenderMap[i].clear(); + mRenderMap[i].push_back(NULL); + mRenderMapEnd[i] = &mRenderMap[i][0]; + mRenderMapAllocated[i] = 0; + } + clear(); } +template <class T, class V> +void LLCullResult::pushBack(T& head, U32& count, V* val) +{ + head[count] = val; + head.push_back(NULL); + count++; +} + void LLCullResult::clear() { mVisibleGroupsSize = 0; - mVisibleGroupsEnd = mVisibleGroups.begin(); + mVisibleGroupsEnd = &mVisibleGroups[0]; mAlphaGroupsSize = 0; - mAlphaGroupsEnd = mAlphaGroups.begin(); + mAlphaGroupsEnd = &mAlphaGroups[0]; mOcclusionGroupsSize = 0; - mOcclusionGroupsEnd = mOcclusionGroups.begin(); + mOcclusionGroupsEnd = &mOcclusionGroups[0]; mDrawableGroupsSize = 0; - mDrawableGroupsEnd = mDrawableGroups.begin(); + mDrawableGroupsEnd = &mDrawableGroups[0]; mVisibleListSize = 0; - mVisibleListEnd = mVisibleList.begin(); + mVisibleListEnd = &mVisibleList[0]; mVisibleBridgeSize = 0; - mVisibleBridgeEnd = mVisibleBridge.begin(); + mVisibleBridgeEnd = &mVisibleBridge[0]; for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) @@ -3507,176 +4054,176 @@ void LLCullResult::clear() mRenderMap[i][j] = 0; } mRenderMapSize[i] = 0; - mRenderMapEnd[i] = mRenderMap[i].begin(); + mRenderMapEnd[i] = &(mRenderMap[i][0]); } } -LLCullResult::sg_list_t::iterator LLCullResult::beginVisibleGroups() +LLCullResult::sg_iterator LLCullResult::beginVisibleGroups() { - return mVisibleGroups.begin(); + return &mVisibleGroups[0]; } -LLCullResult::sg_list_t::iterator LLCullResult::endVisibleGroups() +LLCullResult::sg_iterator LLCullResult::endVisibleGroups() { return mVisibleGroupsEnd; } -LLCullResult::sg_list_t::iterator LLCullResult::beginAlphaGroups() +LLCullResult::sg_iterator LLCullResult::beginAlphaGroups() { - return mAlphaGroups.begin(); + return &mAlphaGroups[0]; } -LLCullResult::sg_list_t::iterator LLCullResult::endAlphaGroups() +LLCullResult::sg_iterator LLCullResult::endAlphaGroups() { return mAlphaGroupsEnd; } -LLCullResult::sg_list_t::iterator LLCullResult::beginOcclusionGroups() +LLCullResult::sg_iterator LLCullResult::beginOcclusionGroups() { - return mOcclusionGroups.begin(); + return &mOcclusionGroups[0]; } -LLCullResult::sg_list_t::iterator LLCullResult::endOcclusionGroups() +LLCullResult::sg_iterator LLCullResult::endOcclusionGroups() { return mOcclusionGroupsEnd; } -LLCullResult::sg_list_t::iterator LLCullResult::beginDrawableGroups() +LLCullResult::sg_iterator LLCullResult::beginDrawableGroups() { - return mDrawableGroups.begin(); + return &mDrawableGroups[0]; } -LLCullResult::sg_list_t::iterator LLCullResult::endDrawableGroups() +LLCullResult::sg_iterator LLCullResult::endDrawableGroups() { return mDrawableGroupsEnd; } -LLCullResult::drawable_list_t::iterator LLCullResult::beginVisibleList() +LLCullResult::drawable_iterator LLCullResult::beginVisibleList() { - return mVisibleList.begin(); + return &mVisibleList[0]; } -LLCullResult::drawable_list_t::iterator LLCullResult::endVisibleList() +LLCullResult::drawable_iterator LLCullResult::endVisibleList() { return mVisibleListEnd; } -LLCullResult::bridge_list_t::iterator LLCullResult::beginVisibleBridge() +LLCullResult::bridge_iterator LLCullResult::beginVisibleBridge() { - return mVisibleBridge.begin(); + return &mVisibleBridge[0]; } -LLCullResult::bridge_list_t::iterator LLCullResult::endVisibleBridge() +LLCullResult::bridge_iterator LLCullResult::endVisibleBridge() { return mVisibleBridgeEnd; } -LLCullResult::drawinfo_list_t::iterator LLCullResult::beginRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLCullResult::beginRenderMap(U32 type) { - return mRenderMap[type].begin(); + return &mRenderMap[type][0]; } -LLCullResult::drawinfo_list_t::iterator LLCullResult::endRenderMap(U32 type) +LLCullResult::drawinfo_iterator LLCullResult::endRenderMap(U32 type) { return mRenderMapEnd[type]; } void LLCullResult::pushVisibleGroup(LLSpatialGroup* group) { - if (mVisibleGroupsSize < mVisibleGroups.size()) + if (mVisibleGroupsSize < mVisibleGroupsAllocated) { mVisibleGroups[mVisibleGroupsSize] = group; } else { - mVisibleGroups.push_back(group); + pushBack(mVisibleGroups, mVisibleGroupsAllocated, group); } ++mVisibleGroupsSize; - mVisibleGroupsEnd = mVisibleGroups.begin()+mVisibleGroupsSize; + mVisibleGroupsEnd = &mVisibleGroups[mVisibleGroupsSize]; } void LLCullResult::pushAlphaGroup(LLSpatialGroup* group) { - if (mAlphaGroupsSize < mAlphaGroups.size()) + if (mAlphaGroupsSize < mAlphaGroupsAllocated) { mAlphaGroups[mAlphaGroupsSize] = group; } else { - mAlphaGroups.push_back(group); + pushBack(mAlphaGroups, mAlphaGroupsAllocated, group); } ++mAlphaGroupsSize; - mAlphaGroupsEnd = mAlphaGroups.begin()+mAlphaGroupsSize; + mAlphaGroupsEnd = &mAlphaGroups[mAlphaGroupsSize]; } void LLCullResult::pushOcclusionGroup(LLSpatialGroup* group) { - if (mOcclusionGroupsSize < mOcclusionGroups.size()) + if (mOcclusionGroupsSize < mOcclusionGroupsAllocated) { mOcclusionGroups[mOcclusionGroupsSize] = group; } else { - mOcclusionGroups.push_back(group); + pushBack(mOcclusionGroups, mOcclusionGroupsAllocated, group); } ++mOcclusionGroupsSize; - mOcclusionGroupsEnd = mOcclusionGroups.begin()+mOcclusionGroupsSize; + mOcclusionGroupsEnd = &mOcclusionGroups[mOcclusionGroupsSize]; } void LLCullResult::pushDrawableGroup(LLSpatialGroup* group) { - if (mDrawableGroupsSize < mDrawableGroups.size()) + if (mDrawableGroupsSize < mDrawableGroupsAllocated) { mDrawableGroups[mDrawableGroupsSize] = group; } else { - mDrawableGroups.push_back(group); + pushBack(mDrawableGroups, mDrawableGroupsAllocated, group); } ++mDrawableGroupsSize; - mDrawableGroupsEnd = mDrawableGroups.begin()+mDrawableGroupsSize; + mDrawableGroupsEnd = &mDrawableGroups[mDrawableGroupsSize]; } void LLCullResult::pushDrawable(LLDrawable* drawable) { - if (mVisibleListSize < mVisibleList.size()) + if (mVisibleListSize < mVisibleListAllocated) { mVisibleList[mVisibleListSize] = drawable; } else { - mVisibleList.push_back(drawable); + pushBack(mVisibleList, mVisibleListAllocated, drawable); } ++mVisibleListSize; - mVisibleListEnd = mVisibleList.begin()+mVisibleListSize; + mVisibleListEnd = &mVisibleList[mVisibleListSize]; } void LLCullResult::pushBridge(LLSpatialBridge* bridge) { - if (mVisibleBridgeSize < mVisibleBridge.size()) + if (mVisibleBridgeSize < mVisibleBridgeAllocated) { mVisibleBridge[mVisibleBridgeSize] = bridge; } else { - mVisibleBridge.push_back(bridge); + pushBack(mVisibleBridge, mVisibleBridgeAllocated, bridge); } ++mVisibleBridgeSize; - mVisibleBridgeEnd = mVisibleBridge.begin()+mVisibleBridgeSize; + mVisibleBridgeEnd = &mVisibleBridge[mVisibleBridgeSize]; } void LLCullResult::pushDrawInfo(U32 type, LLDrawInfo* draw_info) { - if (mRenderMapSize[type] < mRenderMap[type].size()) + if (mRenderMapSize[type] < mRenderMapAllocated[type]) { mRenderMap[type][mRenderMapSize[type]] = draw_info; } else { - mRenderMap[type].push_back(draw_info); + pushBack(mRenderMap[type], mRenderMapAllocated[type], draw_info); } ++mRenderMapSize[type]; - mRenderMapEnd[type] = mRenderMap[type].begin() + mRenderMapSize[type]; + mRenderMapEnd[type] = &(mRenderMap[type][mRenderMapSize[type]]); } @@ -3686,10 +4233,8 @@ void LLCullResult::assertDrawMapsEmpty() { if (mRenderMapSize[i] != 0) { - llerrs << "Stale LLDrawInfo's in LLCullResult!" << llendl; + LL_ERRS() << "Stale LLDrawInfo's in LLCullResult!" << LL_ENDL; } } } - - |