summaryrefslogtreecommitdiff
path: root/indra/newview/llspatialpartition.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llspatialpartition.cpp')
-rwxr-xr-x[-rw-r--r--]indra/newview/llspatialpartition.cpp3461
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;
}
}
}
-
-