summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Payne (Vir Linden) <vir@lindenlab.com>2018-02-21 22:02:34 +0000
committerBrad Payne (Vir Linden) <vir@lindenlab.com>2018-02-21 22:02:34 +0000
commit3f9b3e01b9d7ea3a6662adb55027839840198b4c (patch)
treea48b8d4d7079ad688e816eec043006681bf5f771
parent2b7966302131975e8d270bbf2985b678f37d4b24 (diff)
MAINT-8264 - prevent at least some cases of LODs getting stuck at too-low values.
-rw-r--r--indra/llmath/llmatrix4a.h6
-rw-r--r--indra/llmath/llvector4a.h7
-rw-r--r--indra/llmath/llvolume.cpp11
-rw-r--r--indra/llprimitive/lldaeloader.cpp10
-rw-r--r--indra/llprimitive/llmodel.cpp1
-rw-r--r--indra/newview/lldrawable.cpp4
-rw-r--r--indra/newview/llface.cpp17
-rw-r--r--indra/newview/llspatialpartition.cpp48
-rw-r--r--indra/newview/llvieweroctree.cpp2
-rw-r--r--indra/newview/llvovolume.cpp38
-rw-r--r--indra/newview/skins/default/xui/en/menu_object.xml2
11 files changed, 121 insertions, 25 deletions
diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h
index 216334752a..baa3a89176 100644
--- a/indra/llmath/llmatrix4a.h
+++ b/indra/llmath/llmatrix4a.h
@@ -176,4 +176,10 @@ inline void matMul(const LLMatrix4a &a, const LLMatrix4a &b, LLMatrix4a &res)
res.mMatrix[3] = row3;
}
+inline std::ostream& operator<<(std::ostream& s, const LLMatrix4a& m)
+{
+ s << "[" << m.mMatrix[0] << ", " << m.mMatrix[1] << ", " << m.mMatrix[2] << ", " << m.mMatrix[3] << "]";
+ return s;
+}
+
#endif
diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h
index 79d0a44551..222f3cf235 100644
--- a/indra/llmath/llvector4a.h
+++ b/indra/llmath/llvector4a.h
@@ -320,7 +320,7 @@ public:
inline const LLVector4a& operator= ( const LLQuad& rhs );
inline operator LLQuad() const;
-
+
private:
LLQuad mQ;
} LL_ALIGN_POSTFIX(16);
@@ -331,4 +331,9 @@ inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p
max.setMax(max, p);
}
+inline std::ostream& operator<<(std::ostream& s, const LLVector4a& v)
+{
+ s << "(" << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << ")";
+ return s;
+}
#endif
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index f1e9817cb2..8556e5294c 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2636,6 +2636,7 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
}
//calculate bounding box
+ // VFExtents change
LLVector4a& min = face.mExtents[0];
LLVector4a& max = face.mExtents[1];
@@ -4721,6 +4722,7 @@ LLVolumeFace::~LLVolumeFace()
{
ll_aligned_free_16(mExtents);
mExtents = NULL;
+ mCenter = NULL;
freeData();
}
@@ -5496,7 +5498,7 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
// S32 i;
S32 grid_size = (profile.size()-1)/4;
-
+ // VFExtents change
LLVector4a& min = mExtents[0];
LLVector4a& max = mExtents[1];
@@ -5773,7 +5775,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)
LLVector2 cuv;
LLVector2 min_uv, max_uv;
-
+ // VFExtents change
LLVector4a& min = mExtents[0];
LLVector4a& max = mExtents[1];
@@ -6398,14 +6400,17 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
if (offset == 0 && i == 0)
{ //initialize bounding box
+ // VFExtents change
mExtents[0] = mExtents[1] = dst_pos[i];
}
else
{
//stretch bounding box
+ // VFExtents change
update_min_max(mExtents[0], mExtents[1], dst_pos[i]);
}
}
+ LL_DEBUGS("RiggedBox") << "appendFace got extents " << mExtents[0] << ", " << mExtents[1] << " from dst_pos " << LL_ENDL;
new_count = mNumIndices + face.mNumIndices;
@@ -6568,7 +6573,7 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
{
update_min_max(face_min, face_max, *cur_pos++);
}
-
+ // VFExtents change
mExtents[0] = face_min;
mExtents[1] = face_max;
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 8401cb976e..8f75d89e5a 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -192,7 +192,7 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
{
return LLModel::BAD_ELEMENT;
}
-
+ // VFExtents change
face.mExtents[0].set(v[0], v[1], v[2]);
face.mExtents[1].set(v[0], v[1], v[2]);
}
@@ -254,6 +254,7 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
if (!found)
{
+ // VFExtents change
update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition());
verts.push_back(cv);
if (verts.size() >= 65535)
@@ -305,6 +306,7 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
}
face = LLVolumeFace();
+ // VFExtents change
face.mExtents[0].set(v[0], v[1], v[2]);
face.mExtents[1].set(v[0], v[1], v[2]);
point_map.clear();
@@ -383,6 +385,7 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
if (pos_source)
{
v = pos_source->getFloat_array()->getValue();
+ // VFExtents change
face.mExtents[0].set(v[0], v[1], v[2]);
face.mExtents[1].set(v[0], v[1], v[2]);
}
@@ -482,6 +485,7 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
if (!found)
{
+ // VFExtents change
update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition());
verts.push_back(cv);
if (verts.size() >= 65535)
@@ -551,6 +555,7 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
}
face = LLVolumeFace();
+ // VFExtents change
face.mExtents[0].set(v[0], v[1], v[2]);
face.mExtents[1].set(v[0], v[1], v[2]);
verts.clear();
@@ -734,7 +739,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
{
return LLModel::NO_ERRORS;
}
-
+ // VFExtents change
face.mExtents[0] = verts[0].getPosition();
face.mExtents[1] = verts[0].getPosition();
@@ -758,6 +763,7 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
for (std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.begin(); iter != vert_idx.end(); ++iter)
{
new_verts[iter->second] = iter->first;
+ // VFExtents change
update_min_max(face.mExtents[0], face.mExtents[1], iter->first.getPosition());
}
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index db6d00bc2c..597cc66088 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -276,6 +276,7 @@ void LLModel::normalizeVolumeFaces()
// We shrink the extents so
// that they fall within
// the unit cube.
+ // VFExtents change
face.mExtents[0].add(trans);
face.mExtents[0].mul(scale);
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 6799c3f862..7e51389655 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -51,6 +51,7 @@
#include "llviewerwindow.h"
#include "llvocache.h"
#include "llcontrolavatar.h"
+#include "llcallstack.h"
const F32 MIN_INTERPOLATE_DISTANCE_SQUARED = 0.001f * 0.001f;
const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f;
@@ -1086,7 +1087,8 @@ void LLDrawable::setGroup(LLViewerOctreeGroup *groupp)
llassert(!groupp || (LLSpatialGroup*)groupp->hasElement(this));
if (cur_groupp != groupp && getVOVolume())
- { //NULL out vertex buffer references for volumes on spatial group change to maintain
+ {
+ //NULL out vertex buffer references for volumes on spatial group change to maintain
//requirement that every face vertex buffer is either NULL or points to a vertex buffer
//contained by its drawable's spatial group
for (S32 i = 0; i < getNumFaces(); ++i)
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 0a7e0c92be..efd57ec39f 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -831,6 +831,9 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
min = face.mExtents[0];
max = face.mExtents[1];
+ LL_DEBUGS("RiggedBox") << "updating extents for face " << f << " starting extents " << mExtents[0] << ", " << mExtents[1] << LL_ENDL;
+ LL_DEBUGS("RiggedBox") << "updating extents for face " << f << " starting vf extents " << face.mExtents[0] << ", " << face.mExtents[1] << " num verts " << face.mNumVertices << LL_ENDL;
+
llassert(less_than_max_mag(min));
llassert(less_than_max_mag(max));
@@ -859,6 +862,14 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
v[6] = min;
v[7] = max;
+ // MAINT-8264 - stray vertices, especially in low LODs, cause bounding box errors.
+ if (face.mNumVertices < 3)
+ {
+ LL_DEBUGS("RiggedBox") << "skipping face " << f << ", bad num vertices "
+ << face.mNumVertices << " " << face.mNumIndices << " " << face.mWeights << LL_ENDL;
+ return FALSE;
+ }
+
for (U32 i = 0; i < 6; ++i)
{
v[i].setSelectWithMask(mask[i], min, max);
@@ -866,10 +877,13 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
LLVector4a tv[8];
+ LL_DEBUGS("RiggedBox") << "updating extents for face " << f << " mat is " << mat_vert << LL_ENDL;
+
//transform bounding box into drawable space
for (U32 i = 0; i < 8; ++i)
{
mat_vert.affineTransform(v[i], tv[i]);
+ LL_DEBUGS("RiggedBox") << "updating extents for face " << f << " i " << i << " v and tv " << v[i] << ", " << tv[i] << LL_ENDL;
}
//find bounding box
@@ -883,6 +897,7 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
newMin.setMin(newMin, tv[i]);
newMax.setMax(newMax, tv[i]);
}
+ LL_DEBUGS("RiggedBox") << "updating extents for face " << f << " bbox gave extents " << mExtents[0] << ", " << mExtents[1] << LL_ENDL;
if (!mDrawablep->isActive())
{ // Shift position for region
@@ -890,8 +905,10 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
offset.load3(mDrawablep->getRegion()->getOriginAgent().mV);
newMin.add(offset);
newMax.add(offset);
+ LL_DEBUGS("RiggedBox") << "updating extents for face " << f << " not active, added offset " << offset << LL_ENDL;
}
+ LL_DEBUGS("RiggedBox") << "updated extents for face " << f << " to " << mExtents[0] << ", " << mExtents[1] << LL_ENDL;
LLVector4a t;
t.setAdd(newMin,newMax);
t.mul(0.5f);
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index d0328a7539..8b1a23fe89 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -29,6 +29,7 @@
#include "llspatialpartition.h"
#include "llappviewer.h"
+#include "llcallstack.h"
#include "lltexturecache.h"
#include "lltexturefetch.h"
#include "llimageworker.h"
@@ -777,6 +778,10 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera)
dist = eye.getLength3().getF32();
}
+ LL_DEBUGS("RiggedBox") << "calcDistance, group " << group << " camera " << origin << " obj bounds "
+ << group->mObjectBounds[0] << ", " << group->mObjectBounds[1]
+ << " dist " << dist << " radius " << group->mRadius << LL_ENDL;
+
if (dist < 16.f)
{
dist /= 16.f;
@@ -808,7 +813,8 @@ F32 LLSpatialGroup::getUpdateUrgency() const
BOOL LLSpatialGroup::changeLOD()
{
if (hasState(ALPHA_DIRTY | OBJECT_DIRTY))
- { ///a rebuild is going to happen, update distance and LoD
+ {
+ //a rebuild is going to happen, update distance and LoD
return TRUE;
}
@@ -816,8 +822,28 @@ BOOL LLSpatialGroup::changeLOD()
{
F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius));
+ // MAINT-8264 - this check is not robust if it needs to work
+ // for bounding boxes much larger than the actual enclosed
+ // objects, and using distance to box center is also
+ // problematic. Consider the case that you have a large box
+ // where the enclosed object is in one corner. As you zoom in
+ // on the corner, the object gets much closer to the camera,
+ // but the distance to the box center changes very little, and
+ // an LOD change will not trigger, so object LOD gets "stuck"
+ // at a too-low value. In the case of the above JIRA, the box
+ // was large only due to another error, so this logic did not
+ // need to be changed.
+
if (fabsf(ratio) >= getSpatialPartition()->mSlopRatio)
{
+ LL_DEBUGS("RiggedBox") << "changeLOD true because of ratio compare "
+ << fabsf(ratio) << " " << getSpatialPartition()->mSlopRatio << LL_ENDL;
+ LL_DEBUGS("RiggedBox") << "sg " << this << "\nmDistance " << mDistance
+ << " mLastUpdateDistance " << mLastUpdateDistance
+ << " mRadius " << mRadius
+ << " fab ratio " << fabsf(ratio)
+ << " slop " << getSpatialPartition()->mSlopRatio << LL_ENDL;
+
return TRUE;
}
@@ -2109,17 +2135,17 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
{
if (drawable->isSpatialBridge())
{
- gGL.diffuseColor4f(1,0.5f,0,1);
+ gGL.diffuseColor4f(1,0.5f,0,1); // orange
}
else if (drawable->getVOVolume())
- {
- if (drawable->isRoot())
+ {
+ if (drawable->isRoot())
{
- gGL.diffuseColor4f(1,1,0,1);
+ gGL.diffuseColor4f(1,1,0,1); // yellow
}
else
{
- gGL.diffuseColor4f(0,1,0,1);
+ gGL.diffuseColor4f(0,1,0,1); // green
}
}
else if (drawable->getVObj())
@@ -2127,24 +2153,24 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
switch (drawable->getVObj()->getPCode())
{
case LLViewerObject::LL_VO_SURFACE_PATCH:
- gGL.diffuseColor4f(0,1,1,1);
+ gGL.diffuseColor4f(0,1,1,1); // cyan
break;
case LLViewerObject::LL_VO_CLOUDS:
// no longer used
break;
case LLViewerObject::LL_VO_PART_GROUP:
case LLViewerObject::LL_VO_HUD_PART_GROUP:
- gGL.diffuseColor4f(0,0,1,1);
+ gGL.diffuseColor4f(0,0,1,1); // blue
break;
case LLViewerObject::LL_VO_VOID_WATER:
case LLViewerObject::LL_VO_WATER:
- gGL.diffuseColor4f(0,0.5f,1,1);
+ gGL.diffuseColor4f(0,0.5f,1,1); // medium blue
break;
case LL_PCODE_LEGACY_TREE:
- gGL.diffuseColor4f(0,0.5f,0,1);
+ gGL.diffuseColor4f(0,0.5f,0,1); // dark green
break;
default:
- gGL.diffuseColor4f(1,0,1,1);
+ gGL.diffuseColor4f(1,0,1,1); // magenta
break;
}
}
diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp
index 023f1b92ba..e7916ebd3b 100644
--- a/indra/newview/llvieweroctree.cpp
+++ b/indra/newview/llvieweroctree.cpp
@@ -731,7 +731,7 @@ bool LLViewerOctreeGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4
update_min_max(newMin, newMax, minMax[0]);
update_min_max(newMin, newMax, minMax[1]);
}
-
+
mObjectBounds[0].setAdd(newMin, newMax);
mObjectBounds[0].mul(0.5f);
mObjectBounds[1].setSub(newMax, newMin);
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index c007b446f7..a07e3f8be1 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1515,14 +1515,22 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED);
- // bool rigged = false;
+ if (getRiggedVolume())
+ {
+ updateRiggedVolume(TRUE);
+ }
+
LLVolume* volume = mRiggedVolume;
if (!volume)
{
volume = getVolume();
}
- // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces()
+ if (getRiggedVolume())
+ {
+ LL_DEBUGS("RiggedBox") << "rebuilding box, volume face count " << getVolume()->getNumVolumeFaces() << " drawable face count " << mDrawable->getNumFaces() << LL_ENDL;
+ }
+ // There's no guarantee that getVolume()->getNumFaces() == mDrawable->getNumFaces()
for (S32 i = 0;
i < getVolume()->getNumVolumeFaces() && i < mDrawable->getNumFaces() && i < getNumTEs();
i++)
@@ -1532,12 +1540,18 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
{
continue;
}
- res &= face->genVolumeBBoxes(*volume, i,
- mRelativeXform,
- (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global);
+
+ BOOL face_res = face->genVolumeBBoxes(*volume, i,
+ mRelativeXform,
+ (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global);
+ res &= face_res; // note that this result is never used
if (rebuild)
{
+ if (getRiggedVolume())
+ {
+ LL_DEBUGS("RiggedBox") << "rebuilding box, face " << i << " extents " << face->mExtents[0] << ", " << face->mExtents[1] << LL_ENDL;
+ }
if (i == 0)
{
min = face->mExtents[0];
@@ -1545,6 +1559,11 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
}
else
{
+ if (!face_res)
+ {
+ // MAINT-8264 - ignore bboxes of ill-formed faces.
+ continue;
+ }
min.setMin(min, face->mExtents[0]);
max.setMax(max, face->mExtents[1]);
}
@@ -1553,6 +1572,10 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
if (rebuild)
{
+ if (getRiggedVolume())
+ {
+ LL_DEBUGS("RiggedBox") << "rebuilding got extents " << min << ", " << max << LL_ENDL;
+ }
mDrawable->setSpatialExtents(min,max);
min.add(max);
min.mul(0.5f);
@@ -4512,6 +4535,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
}
//update bounding box
+ // VFExtents change
LLVector4a& min = dst_face.mExtents[0];
LLVector4a& max = dst_face.mExtents[1];
@@ -4528,6 +4552,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
min.setMin(min, pos[j]);
max.setMax(max, pos[j]);
}
+
box_min.setMin(min,box_min);
box_max.setMax(max,box_max);
@@ -5065,6 +5090,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
<< " is_animated " << vobj->isAnimatedObject()
<< " can_animate " << vobj->canBeAnimatedObject()
<< " cav " << vobj->getControlAvatar()
+ << " lod " << vobj->getLOD()
+ << " drawable rigged " << (drawablep->isState(LLDrawable::RIGGED))
+ << " drawable state " << drawablep->getState()
<< " playing " << (U32) (vobj->getControlAvatar() ? vobj->getControlAvatar()->mPlaying : false)
<< " frame " << LLFrameTimer::getFrameCount()
<< LL_ENDL;
diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml
index 91e7328979..ce34508303 100644
--- a/indra/newview/skins/default/xui/en/menu_object.xml
+++ b/indra/newview/skins/default/xui/en/menu_object.xml
@@ -228,6 +228,6 @@
<menu_item_call.on_click
function="Avatar.ResetSkeleton" />
<menu_item_call.on_visible
- function="Advanced.EnableResetSkeleton"/>
+ function="Avatar.EnableResetSkeleton"/>
</menu_item_call>
</context_menu>