summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Gavriliuk <alexandrgproductengine@lindenlab.com>2023-05-31 12:45:22 +0200
committerGuru <alexandrgproductengine@lindenlab.com>2023-06-02 23:10:46 +0200
commitbbd0a09fbaaa354f522bf77241b9039288f10479 (patch)
tree52be14b510cb10b2245dd050702f9b3c4e987b94
parent0a342cfe7cc92cdfe308bc75753750c99b0327e6 (diff)
SL-18251 Expand extents to include the Control Avatar bounds
-rw-r--r--indra/newview/llcontrolavatar.cpp7
-rw-r--r--indra/newview/llcontrolavatar.h6
-rw-r--r--indra/newview/lldrawable.cpp22
-rw-r--r--indra/newview/llspatialpartition.cpp53
-rw-r--r--indra/newview/llspatialpartition.h3
-rw-r--r--indra/newview/llvovolume.cpp22
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())