From 217df36656fb1a3d309fa0b42de192c369309211 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 2 Oct 2017 21:52:24 +0100 Subject: SL-808 - updated ARC display to largely work with animated objects. Gives some triangle information that we may or may not ultimately keep. Surface area calcs still not working --- indra/newview/llface.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'indra/newview/llface.cpp') diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 3d5e2d356e..eebdb62aff 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -330,11 +330,7 @@ void LLFace::dirtyTexture() { vobj->mLODChanged = TRUE; - LLVOAvatar* avatar = vobj->getAvatar(); - if (avatar) - { //avatar render cost may have changed - avatar->updateVisualComplexity(); - } + vobj->updateVisualComplexity(); } gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, FALSE); } -- cgit v1.3 From 3f9b3e01b9d7ea3a6662adb55027839840198b4c Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 21 Feb 2018 22:02:34 +0000 Subject: MAINT-8264 - prevent at least some cases of LODs getting stuck at too-low values. --- indra/llmath/llmatrix4a.h | 6 +++ indra/llmath/llvector4a.h | 7 +++- indra/llmath/llvolume.cpp | 11 +++-- indra/llprimitive/lldaeloader.cpp | 10 ++++- indra/llprimitive/llmodel.cpp | 1 + indra/newview/lldrawable.cpp | 4 +- indra/newview/llface.cpp | 17 ++++++++ indra/newview/llspatialpartition.cpp | 48 +++++++++++++++++----- indra/newview/llvieweroctree.cpp | 2 +- indra/newview/llvovolume.cpp | 38 ++++++++++++++--- indra/newview/skins/default/xui/en/menu_object.xml | 2 +- 11 files changed, 121 insertions(+), 25 deletions(-) (limited to 'indra/newview/llface.cpp') 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& 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& 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& 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& 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& 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& 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& 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& fac for (std::map::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 @@ + function="Avatar.EnableResetSkeleton"/> -- cgit v1.3 From e86839fac19753d0fa4006296c7f8909fe781013 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 1 Jun 2018 15:08:59 +0100 Subject: SL-915 - WIP on dynamic joint box tracking --- indra/llcharacter/lljoint.cpp | 53 +++++++++++++++++++++++++ indra/llcharacter/lljoint.h | 22 +++++++++++ indra/llmath/CMakeLists.txt | 1 + indra/llmath/llmatrix4a.cpp | 80 +++++++++++++++++++++++++++++++++++++ indra/llmath/llmatrix4a.h | 8 ++-- indra/llprimitive/llmodel.h | 1 - indra/newview/llface.cpp | 92 +++++++++++-------------------------------- indra/newview/llvoavatar.cpp | 39 ++++++++++++++++-- 8 files changed, 218 insertions(+), 78 deletions(-) create mode 100644 indra/llmath/llmatrix4a.cpp (limited to 'indra/newview/llface.cpp') diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 07fcd99701..68355cbbdc 100644 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -96,6 +96,46 @@ void LLVector3OverrideMap::clear() m_map.clear(); } +//----------------------------------------------------------------------------- +// LLJointRiggingInfo +//----------------------------------------------------------------------------- +LLJointRiggingInfo::LLJointRiggingInfo() +{ + mRiggedExtents[0].clear(); + mRiggedExtents[1].clear(); + mIsRiggedTo = false; +} + +bool LLJointRiggingInfo::isRiggedTo() const +{ + return mIsRiggedTo; +} + +void LLJointRiggingInfo::setIsRiggedTo(bool val) +{ + mIsRiggedTo = val; +} + +LLVector4a *LLJointRiggingInfo::getRiggedExtents() +{ + return mRiggedExtents; +} + +const LLVector4a *LLJointRiggingInfo::getRiggedExtents() const +{ + return mRiggedExtents; +} + +// Combine two rigging info states. +// - isRiggedTo if either of the source infos are rigged to +// - box is union of the two sources +void LLJointRiggingInfo::merge(const LLJointRiggingInfo& other) +{ + mIsRiggedTo = mIsRiggedTo || other.mIsRiggedTo; + update_min_max(mRiggedExtents[0], mRiggedExtents[1], other.mRiggedExtents[0]); + update_min_max(mRiggedExtents[0], mRiggedExtents[1], other.mRiggedExtents[1]); +} + //----------------------------------------------------------------------------- // LLJoint() // Class Constructor @@ -597,6 +637,19 @@ void LLJoint::showAttachmentPosOverrides(const std::string& av_info) const } } +//-------------------------------------------------------------------- +// getRiggingInfo() +//-------------------------------------------------------------------- +LLJointRiggingInfo& LLJoint::getRiggingInfo() +{ + return mRiggingInfo; +} + +const LLJointRiggingInfo& LLJoint::getRiggingInfo() const +{ + return mRiggingInfo; +} + //-------------------------------------------------------------------- // updatePos() //-------------------------------------------------------------------- diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 8112d246f2..ff1e967188 100644 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -70,6 +70,23 @@ private: map_type m_map; }; +// Stores information related to associated rigged mesh vertices +// Extents are in joint space +// isRiggedTo is based on the state of all currently associated rigged meshes +class LLJointRiggingInfo +{ +public: + LLJointRiggingInfo(); + bool isRiggedTo() const; + void setIsRiggedTo(bool val); + LLVector4a *getRiggedExtents(); + const LLVector4a *getRiggedExtents() const; + void merge(const LLJointRiggingInfo& other); +private: + LL_ALIGN_16(LLVector4a mRiggedExtents[2]); + bool mIsRiggedTo; +}; + inline bool operator==(const LLVector3OverrideMap& a, const LLVector3OverrideMap& b) { return a.getMap() == b.getMap(); @@ -158,6 +175,11 @@ public: LLVector3OverrideMap m_attachmentScaleOverrides; LLVector3 m_scaleBeforeOverrides; + // Rigging Info + LLJointRiggingInfo mRiggingInfo; + LLJointRiggingInfo& getRiggingInfo(); + const LLJointRiggingInfo& getRiggingInfo() const; + void updatePos(const std::string& av_info); void updateScale(const std::string& av_info); diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index 4c8bcdac91..dab566da56 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -20,6 +20,7 @@ set(llmath_SOURCE_FILES llcoordframe.cpp llline.cpp llmatrix3a.cpp + llmatrix4a.cpp llmodularmath.cpp lloctree.cpp llperlin.cpp diff --git a/indra/llmath/llmatrix4a.cpp b/indra/llmath/llmatrix4a.cpp new file mode 100644 index 0000000000..fe8f0b98f3 --- /dev/null +++ b/indra/llmath/llmatrix4a.cpp @@ -0,0 +1,80 @@ +/** +* @file llmatrix4a.cpp +* @brief Functions for vectorized matrix/vector operations +* +* $LicenseInfo:firstyear=2018&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2018, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "llmath.h" +#include "llmatrix4a.h" + +// Convert a bounding box into other coordinate system. Should give +// the same results as transforming every corner of the bounding box +// and extracting the bounding box of that, although that's not +// necessarily the fastest way to implement. +void matMulBoundBox(const LLMatrix4a &mat, const LLVector4a *in_extents, LLVector4a *out_extents) +{ + //get 8 corners of bounding box + LLVector4Logical mask[6]; + + for (U32 i = 0; i < 6; ++i) + { + mask[i].clear(); + } + + mask[0].setElement<2>(); //001 + mask[1].setElement<1>(); //010 + mask[2].setElement<1>(); //011 + mask[2].setElement<2>(); + mask[3].setElement<0>(); //100 + mask[4].setElement<0>(); //101 + mask[4].setElement<2>(); + mask[5].setElement<0>(); //110 + mask[5].setElement<1>(); + + LLVector4a v[8]; + + v[6] = in_extents[0]; + v[7] = in_extents[1]; + + for (U32 i = 0; i < 6; ++i) + { + v[i].setSelectWithMask(mask[i], in_extents[0], in_extents[1]); + } + + LLVector4a tv[8]; + + //transform bounding box into drawable space + for (U32 i = 0; i < 8; ++i) + { + mat.affineTransform(v[i], tv[i]); + } + + //find bounding box + out_extents[0] = out_extents[1] = tv[0]; + + for (U32 i = 1; i < 8; ++i) + { + out_extents[0].setMin(out_extents[0], tv[i]); + out_extents[1].setMax(out_extents[1], tv[i]); + } +} diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index baa3a89176..7ba347062f 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -121,7 +121,7 @@ public: res.add(z); } - inline void affineTransformSSE(const LLVector4a& v, LLVector4a& res) + inline void affineTransformSSE(const LLVector4a& v, LLVector4a& res) const { LLVector4a x,y,z; @@ -138,7 +138,7 @@ public: res.setAdd(x,z); } - inline void affineTransformNonSSE(const LLVector4a& v, LLVector4a& res) + inline void affineTransformNonSSE(const LLVector4a& v, LLVector4a& res) const { F32 x = v[0] * mMatrix[0][0] + v[1] * mMatrix[1][0] + v[2] * mMatrix[2][0] + mMatrix[3][0]; F32 y = v[0] * mMatrix[0][1] + v[1] * mMatrix[1][1] + v[2] * mMatrix[2][1] + mMatrix[3][1]; @@ -147,7 +147,7 @@ public: res.set(x,y,z,w); } - inline void affineTransform(const LLVector4a& v, LLVector4a& res) + inline void affineTransform(const LLVector4a& v, LLVector4a& res) const { affineTransformSSE(v,res); } @@ -182,4 +182,6 @@ inline std::ostream& operator<<(std::ostream& s, const LLMatrix4a& m) return s; } +void matMulBoundBox(const LLMatrix4a &a, const LLVector4a *in_extents, LLVector4a *out_extents); + #endif diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index 097558ef67..53585d2e04 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -38,7 +38,6 @@ class domMesh; #define MAX_MODEL_FACES 8 - class LLMeshSkinInfo { public: diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index efd57ec39f..7bc7814392 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -810,17 +810,11 @@ bool less_than_max_mag(const LLVector4a& vec) } BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, - const LLMatrix4& mat_vert_in, BOOL global_volume) + const LLMatrix4& mat_vert_in, BOOL global_volume) { //get bounding box if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED)) { - //VECTORIZE THIS - LLMatrix4a mat_vert; - mat_vert.loadu(mat_vert_in); - - LLVector4a min,max; - if (f >= volume.getNumVolumeFaces()) { LL_WARNS() << "Generating bounding box for invalid face index!" << LL_ENDL; @@ -828,39 +822,11 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, } const LLVolumeFace &face = volume.getVolumeFace(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)); - - //min, max are in volume space, convert to drawable render space - - //get 8 corners of bounding box - LLVector4Logical mask[6]; - - for (U32 i = 0; i < 6; ++i) - { - mask[i].clear(); - } - - mask[0].setElement<2>(); //001 - mask[1].setElement<1>(); //010 - mask[2].setElement<1>(); //011 - mask[2].setElement<2>(); - mask[3].setElement<0>(); //100 - mask[4].setElement<0>(); //101 - mask[4].setElement<2>(); - mask[5].setElement<0>(); //110 - mask[5].setElement<1>(); - - LLVector4a v[8]; - - v[6] = min; - v[7] = max; + LL_DEBUGS("RiggedBox") << "updating extents for face " << f + << " starting extents " << mExtents[0] << ", " << mExtents[1] + << " starting vf extents " << face.mExtents[0] << ", " << face.mExtents[1] + << " num verts " << face.mNumVertices << LL_ENDL; // MAINT-8264 - stray vertices, especially in low LODs, cause bounding box errors. if (face.mNumVertices < 3) @@ -870,52 +836,38 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, return FALSE; } - for (U32 i = 0; i < 6; ++i) - { - v[i].setSelectWithMask(mask[i], min, max); - } - - LLVector4a tv[8]; - - LL_DEBUGS("RiggedBox") << "updating extents for face " << f << " mat is " << mat_vert << LL_ENDL; + //VECTORIZE THIS + LLMatrix4a mat_vert; + mat_vert.loadu(mat_vert_in); + LLVector4a new_extents[2]; - //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 - LLVector4a& newMin = mExtents[0]; - LLVector4a& newMax = mExtents[1]; + llassert(less_than_max_mag(face.mExtents[0])); + llassert(less_than_max_mag(face.mExtents[1])); - newMin = newMax = tv[0]; + matMulBoundBox(mat_vert, face.mExtents, mExtents); - for (U32 i = 1; i < 8; ++i) - { - 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; + LL_DEBUGS("RiggedBox") << "updated extents for face " << f + << " bbox gave extents " << mExtents[0] << ", " << mExtents[1] << LL_ENDL; if (!mDrawablep->isActive()) { // Shift position for region LLVector4a offset; 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; + mExtents[0].add(offset); + mExtents[1].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; + LL_DEBUGS("RiggedBox") << "updated extents for face " << f + << " to " << mExtents[0] << ", " << mExtents[1] << LL_ENDL; LLVector4a t; - t.setAdd(newMin,newMax); + t.setAdd(mExtents[0],mExtents[1]); t.mul(0.5f); mCenterLocal.set(t.getF32ptr()); - t.setSub(newMax,newMin); + t.setSub(mExtents[1],mExtents[0]); mBoundingSphereRadius = t.getLength3().getF32()*0.5f; updateCenterAgent(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 0ea29bae58..277f8e4533 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1277,13 +1277,11 @@ void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) mImpostorOffset = LLVector3(pos_group.getF32ptr())-getRenderPosition(); mDrawable->setPositionGroup(pos_group); } - - } void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) { - LLVector4a buffer(0.25f); + LLVector4a buffer(0.0); LLVector4a pos; pos.load3(getRenderPosition().mV); newMin.setSub(pos, buffer); @@ -1312,7 +1310,7 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) mPixelArea = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); - //stretch bounding box by attachments + //stretch bounding box by static attachments for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter) @@ -1356,6 +1354,39 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) } } + // Stretch bounding box by rigged mesh joint boxes + for (S32 joint_num = 0; joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS; joint_num++) + { + LLJoint *joint = getJoint(joint_num); + + // FIXME TEMP HACK FOR TESTING + if (joint) + { + joint->getRiggingInfo().setIsRiggedTo(true); + } + + if (joint && joint->getRiggingInfo().isRiggedTo()) + { + LLViewerJointAttachment *as_joint_attach = dynamic_cast(joint); + if (as_joint_attach && as_joint_attach->getIsHUDAttachment()) + { + // Ignore bounding box of HUD joints + continue; + } + LLMatrix4a mat; + LLVector4a new_extents[2]; + mat.loadu(joint->getWorldMatrix()); + matMulBoundBox(mat, joint->getRiggingInfo().getRiggedExtents(), new_extents); + update_min_max(newMin, newMax, new_extents[0]); + update_min_max(newMin, newMax, new_extents[1]); + //if (isSelf()) + //{ + // LL_INFOS() << joint->getName() << " extents " << new_extents[0] << "," << new_extents[1] << LL_ENDL; + // LL_INFOS() << joint->getName() << " av box is " << newMin << "," << newMax << LL_ENDL; + //} + } + } + //pad bounding box newMin.sub(buffer); -- cgit v1.3