diff options
author | Alexander Gavriliuk <alexandrgproductengine@lindenlab.com> | 2023-05-31 12:45:22 +0200 |
---|---|---|
committer | Guru <alexandrgproductengine@lindenlab.com> | 2023-06-02 23:10:46 +0200 |
commit | bbd0a09fbaaa354f522bf77241b9039288f10479 (patch) | |
tree | 52be14b510cb10b2245dd050702f9b3c4e987b94 | |
parent | 0a342cfe7cc92cdfe308bc75753750c99b0327e6 (diff) |
SL-18251 Expand extents to include the Control Avatar bounds
-rw-r--r-- | indra/newview/llcontrolavatar.cpp | 7 | ||||
-rw-r--r-- | indra/newview/llcontrolavatar.h | 6 | ||||
-rw-r--r-- | indra/newview/lldrawable.cpp | 22 | ||||
-rw-r--r-- | indra/newview/llspatialpartition.cpp | 53 | ||||
-rw-r--r-- | indra/newview/llspatialpartition.h | 3 | ||||
-rw-r--r-- | indra/newview/llvovolume.cpp | 22 |
6 files changed, 108 insertions, 5 deletions
diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp index 4a87273372..91031034c6 100644 --- a/indra/newview/llcontrolavatar.cpp +++ b/indra/newview/llcontrolavatar.cpp @@ -47,6 +47,7 @@ LLControlAvatar::LLControlAvatar(const LLUUID& id, const LLPCode pcode, LLViewer mGlobalScale(1.0f), mMarkedForDeath(false), mRootVolp(NULL), + mControlAVBridge(NULL), mScaleConstraintFixup(1.0), mRegionChanged(false) { @@ -376,6 +377,12 @@ void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time) } } +void LLControlAvatar::markDead() +{ + super::markDead(); + mControlAVBridge = NULL; +} + bool LLControlAvatar::computeNeedsUpdate() { computeUpdatePeriod(); diff --git a/indra/newview/llcontrolavatar.h b/indra/newview/llcontrolavatar.h index 8e87299f3e..50e02d2d91 100644 --- a/indra/newview/llcontrolavatar.h +++ b/indra/newview/llcontrolavatar.h @@ -35,9 +35,12 @@ class LLControlAvatar: { LOG_CLASS(LLControlAvatar); + using super = LLVOAvatar; + public: LLControlAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); - virtual void initInstance(); // Called after construction to initialize the class. + virtual void initInstance(); // Called after construction to initialize the class. + virtual void markDead(); virtual ~LLControlAvatar(); // If this is an attachment, return the avatar it is attached to. Otherwise NULL. @@ -87,6 +90,7 @@ public: F32 mGlobalScale; LLVOVolume *mRootVolp; + class LLControlAVBridge* mControlAVBridge; bool mMarkedForDeath; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 4a0c9d399f..bb4174d3b6 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -763,6 +763,19 @@ void LLDrawable::movePartition() if (part) { part->move(this, getSpatialGroup()); + + // SL-18251 "On-screen animesh characters using pelvis offset animations + // disappear when root goes off-screen" + // + // Update extents of the root node when Control Avatar changes it's bounds + if (mRenderType == LLPipeline::RENDER_TYPE_CONTROL_AV && isRoot()) + { + LLControlAvatar* controlAvatar = dynamic_cast<LLControlAvatar*>(getVObj().get()); + if (controlAvatar && controlAvatar->mControlAVBridge) + { + ((LLSpatialGroup*)controlAvatar->mControlAVBridge->mOctree->getListener(0))->setState(LLViewerOctreeGroup::DIRTY); + } + } } } @@ -1216,10 +1229,11 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() { setSpatialBridge(new LLHUDBridge(this, getRegion())); } - else if (mVObjp->isAnimatedObject() && mVObjp->getControlAvatar()) - { - setSpatialBridge(new LLControlAVBridge(this, getRegion())); - } + else if (mVObjp->isAnimatedObject() && mVObjp->getControlAvatar()) + { + setSpatialBridge(new LLControlAVBridge(this, getRegion())); + mVObjp->getControlAvatar()->mControlAVBridge = (LLControlAVBridge*)getSpatialBridge(); + } // check HUD first, because HUD is also attachment else if (mVObjp->isAttachment()) { diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 42cd1133a2..3e801a47d7 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -237,6 +237,59 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) return FALSE; } +void LLSpatialGroup::expandExtents(const LLVector4a* addingExtents, const LLXformMatrix& currentTransform) +{ + // Get coordinates of the adding extents + const LLVector4a& min = addingExtents[0]; + const LLVector4a& max = addingExtents[1]; + + // Get coordinates of all corners of the bounding box + LLVector3 corners[] = + { + LLVector3(min[0], min[1], min[2]), + LLVector3(min[0], min[1], max[2]), + LLVector3(min[0], max[1], min[2]), + LLVector3(min[0], max[1], max[2]), + LLVector3(max[0], min[1], min[2]), + LLVector3(max[0], min[1], max[2]), + LLVector3(max[0], max[1], min[2]), + LLVector3(max[0], max[1], max[2]) + }; + + // New extents (to be expanded) + LLVector3 extents[] = + { + LLVector3(mExtents[0].getF32ptr()), + LLVector3(mExtents[1].getF32ptr()) + }; + + LLQuaternion backwardRotation = ~currentTransform.getRotation(); + for (LLVector3& corner : corners) + { + // Make coordinates relative to the current position + corner -= currentTransform.getPosition(); + // Rotate coordinates backward to the current rotation + corner.rotVec(backwardRotation); + // Expand root extents on the current corner + for (int j = 0; j < 3; ++j) + { + if (corner[j] < extents[0][j]) + extents[0][j] = corner[j]; + if (corner[j] > extents[1][j]) + extents[1][j] = corner[j]; + } + } + + // Set new expanded extents + mExtents[0].load3(extents[0].mV); + mExtents[1].load3(extents[1].mV); + + // Calculate new center and size + mBounds[0].setAdd(mExtents[0], mExtents[1]); + mBounds[0].mul(0.5f); + mBounds[1].setSub(mExtents[0], mExtents[1]); + mBounds[1].mul(0.5f); +} BOOL LLSpatialGroup::addObject(LLDrawable *drawablep) { diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 6d3ef33801..cdb591083c 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -298,6 +298,7 @@ public: BOOL addObject(LLDrawable *drawablep); BOOL removeObject(LLDrawable *drawablep, BOOL from_octree = FALSE); BOOL updateInGroup(LLDrawable *drawablep, BOOL immediate = FALSE); // Update position if it's in the group + void expandExtents(const LLVector4a* addingExtents, const LLXformMatrix& currentTransform); void shift(const LLVector4a &offset); void destroyGL(bool keep_occlusion = false); @@ -699,8 +700,10 @@ public: class LLControlAVBridge : public LLVolumeBridge { + using super = LLVolumeBridge; public: LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regionp); + virtual void updateSpatialExtents(); }; class LLHUDBridge : public LLVolumeBridge diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index e9a1724639..3842dfff7c 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5110,6 +5110,28 @@ LLControlAVBridge::LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regi mPartitionType = LLViewerRegion::PARTITION_CONTROL_AV; } +void LLControlAVBridge::updateSpatialExtents() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWABLE + + LLControlAvatar* controlAvatar = getVObj()->getControlAvatar(); + + LLSpatialGroup* root = (LLSpatialGroup*)mOctree->getListener(0); + + bool rootWasDirty = root->isDirty(); + + super::updateSpatialExtents(); // root becomes non-dirty here + + // SL-18251 "On-screen animesh characters using pelvis offset animations + // disappear when root goes off-screen" + // + // Expand extents to include Control Avatar placed outside of the bounds + if (controlAvatar && (rootWasDirty || controlAvatar->mPlaying)) + { + root->expandExtents(controlAvatar->mDrawable->getSpatialExtents(), *mDrawable->getXform()); + } +} + bool can_batch_texture(LLFace* facep) { if (facep->getTextureEntry()->getBumpmap()) |