summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/llcontrolavatar.cpp77
-rw-r--r--indra/newview/llcontrolavatar.h7
-rw-r--r--indra/newview/lldrawable.cpp5
-rw-r--r--indra/newview/lldrawpoolavatar.cpp27
-rw-r--r--indra/newview/llfloaterpreference.cpp4
-rw-r--r--indra/newview/llviewermenu.cpp1
-rw-r--r--indra/newview/llviewerpartsource.cpp2
-rw-r--r--indra/newview/llvoavatar.cpp917
-rw-r--r--indra/newview/llvoavatar.h64
-rw-r--r--indra/newview/llvoavatarself.cpp2
-rw-r--r--indra/newview/llvoavatarself.h2
-rw-r--r--indra/newview/pipeline.cpp9
13 files changed, 809 insertions, 310 deletions
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 0438a6cd91..df41a3918c 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.4.13
+6.4.14
diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index 5a6b66df52..fab249f988 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -78,6 +78,24 @@ void LLControlAvatar::initInstance()
mInitFlags |= 1<<4;
}
+const LLVOAvatar *LLControlAvatar::getAttachedAvatar() const
+{
+ if (mRootVolp && mRootVolp->isAttachment())
+ {
+ return mRootVolp->getAvatarAncestor();
+ }
+ return NULL;
+}
+
+LLVOAvatar *LLControlAvatar::getAttachedAvatar()
+{
+ if (mRootVolp && mRootVolp->isAttachment())
+ {
+ return mRootVolp->getAvatarAncestor();
+ }
+ return NULL;
+}
+
void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_scale_fixup) const
{
@@ -165,7 +183,7 @@ void LLControlAvatar::matchVolumeTransform()
if (mRootVolp->isAttachment())
{
- LLVOAvatar *attached_av = mRootVolp->getAvatarAncestor();
+ LLVOAvatar *attached_av = getAttachedAvatar();
if (attached_av)
{
LLViewerJointAttachment *attach = attached_av->getTargetAttachmentPoint(mRootVolp);
@@ -360,7 +378,34 @@ void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time)
}
}
-BOOL LLControlAvatar::updateCharacter(LLAgent &agent)
+bool LLControlAvatar::computeNeedsUpdate()
+{
+ computeUpdatePeriod();
+
+ // Animesh attachments are a special case. Should have the same update cadence as their attached parent avatar.
+ LLVOAvatar *attached_av = getAttachedAvatar();
+ if (attached_av)
+ {
+ // Have to run computeNeedsUpdate() for attached av in
+ // case it hasn't run updateCharacter() already this
+ // frame. Note this means that the attached av will
+ // run computeNeedsUpdate() multiple times per frame
+ // if it has animesh attachments. Results will be
+ // consistent except for the corner case of exceeding
+ // MAX_IMPOSTOR_INTERVAL in one call but not another,
+ // which should be rare.
+ attached_av->computeNeedsUpdate();
+ mNeedsImpostorUpdate = attached_av->mNeedsImpostorUpdate;
+ if (mNeedsImpostorUpdate)
+ {
+ mLastImpostorUpdateReason = 12;
+ }
+ return mNeedsImpostorUpdate;
+ }
+ return LLVOAvatar::computeNeedsUpdate();
+}
+
+bool LLControlAvatar::updateCharacter(LLAgent &agent)
{
return LLVOAvatar::updateCharacter(agent);
}
@@ -634,29 +679,23 @@ std::string LLControlAvatar::getFullname() const
// virtual
bool LLControlAvatar::shouldRenderRigged() const
{
- if (mRootVolp && mRootVolp->isAttachment())
- {
- LLVOAvatar *attached_av = mRootVolp->getAvatarAncestor();
- if (attached_av)
- {
- return attached_av->shouldRenderRigged();
- }
- }
+ const LLVOAvatar *attached_av = getAttachedAvatar();
+ if (attached_av)
+ {
+ return attached_av->shouldRenderRigged();
+ }
return true;
}
// virtual
BOOL LLControlAvatar::isImpostor()
{
- if (mRootVolp && mRootVolp->isAttachment())
- {
- // Attached animated objects should match state of their attached av.
- LLVOAvatar *attached_av = mRootVolp->getAvatarAncestor();
- if (attached_av)
- {
- return attached_av->isImpostor();
- }
- }
+ // Attached animated objects should match state of their attached av.
+ LLVOAvatar *attached_av = getAttachedAvatar();
+ if (attached_av)
+ {
+ return attached_av->isImpostor();
+ }
return LLVOAvatar::isImpostor();
}
diff --git a/indra/newview/llcontrolavatar.h b/indra/newview/llcontrolavatar.h
index 288d07cd48..8e87299f3e 100644
--- a/indra/newview/llcontrolavatar.h
+++ b/indra/newview/llcontrolavatar.h
@@ -40,6 +40,10 @@ public:
virtual void initInstance(); // Called after construction to initialize the class.
virtual ~LLControlAvatar();
+ // If this is an attachment, return the avatar it is attached to. Otherwise NULL.
+ virtual const LLVOAvatar *getAttachedAvatar() const;
+ virtual LLVOAvatar *getAttachedAvatar();
+
void getNewConstraintFixups(LLVector3& new_pos_constraint, F32& new_scale_constraint) const;
void matchVolumeTransform();
void updateVolumeGeom();
@@ -53,7 +57,8 @@ public:
void markForDeath();
virtual void idleUpdate(LLAgent &agent, const F64 &time);
- virtual BOOL updateCharacter(LLAgent &agent);
+ virtual bool computeNeedsUpdate();
+ virtual bool updateCharacter(LLAgent &agent);
void getAnimatedVolumes(std::vector<LLVOVolume*>& volumes);
void updateAnimations();
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 2219f20272..5034bd1c5e 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -1485,7 +1485,7 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>*
LLVOAvatar* avatarp = (LLVOAvatar*) objparent;
if (avatarp->isVisible())
{
- impostor = objparent->isAvatar() && ((LLVOAvatar*) objparent)->isImpostor();
+ impostor = objparent->isAvatar() && !LLPipeline::sImpostorRender && ((LLVOAvatar*) objparent)->isImpostor();
loaded = objparent->isAvatar() && ((LLVOAvatar*) objparent)->isFullyLoaded();
}
else
@@ -1569,7 +1569,8 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update)
if (mDrawable->getVObj())
{
- if (mDrawable->getVObj()->isAttachment())
+ // Don't update if we are part of impostor, unles it's an impostor pass
+ if (!LLPipeline::sImpostorRender && mDrawable->getVObj()->isAttachment())
{
LLDrawable* parent = mDrawable->getParent();
if (parent && parent->getVObj())
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 87772d9eb6..687b13d2c8 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -572,12 +572,12 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
{
return;
}
-
- BOOL impostor = avatarp->isImpostor();
- if (impostor
- && LLVOAvatar::AV_DO_NOT_RENDER != avatarp->getVisualMuteSettings()
- && LLVOAvatar::AV_ALWAYS_RENDER != avatarp->getVisualMuteSettings())
+ LLVOAvatar::AvatarOverallAppearance oa = avatarp->getOverallAppearance();
+ BOOL impostor = !LLPipeline::sImpostorRender && avatarp->isImpostor();
+ if (oa == LLVOAvatar::AOA_INVISIBLE ||
+ (impostor && oa == LLVOAvatar::AOA_JELLYDOLL))
{
+ // No shadows for jellydolled or invisible avs.
return;
}
@@ -1464,7 +1464,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
return;
}
- LLVOAvatar *avatarp;
+ LLVOAvatar *avatarp = NULL;
if (single_avatar)
{
@@ -1510,11 +1510,12 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
return;
}
- BOOL impostor = avatarp->isImpostor() && !single_avatar;
+ BOOL impostor = !LLPipeline::sImpostorRender && avatarp->isImpostor() && !single_avatar;
if (( avatarp->isInMuteList()
|| impostor
- || (LLVOAvatar::AV_DO_NOT_RENDER == avatarp->getVisualMuteSettings() && !avatarp->needsImpostorUpdate()) ) && pass != 0)
+ || (LLVOAvatar::AOA_NORMAL != avatarp->getOverallAppearance() && !avatarp->needsImpostorUpdate()) ) && pass != 0)
+// || (LLVOAvatar::AV_DO_NOT_RENDER == avatarp->getVisualMuteSettings() && !avatarp->needsImpostorUpdate()) ) && pass != 0)
{ //don't draw anything but the impostor for impostored avatars
return;
}
@@ -1524,6 +1525,13 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
return;
}
+ LLVOAvatar *attached_av = avatarp->getAttachedAvatar();
+ if (attached_av && LLVOAvatar::AOA_NORMAL != attached_av->getOverallAppearance())
+ {
+ // Animesh attachment of a jellydolled or invisible parent - don't show
+ return;
+ }
+
if (pass == 0)
{
if (!LLPipeline::sReflectionRender)
@@ -1531,7 +1539,8 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
LLVOAvatar::sNumVisibleAvatars++;
}
- if (impostor || (LLVOAvatar::AV_DO_NOT_RENDER == avatarp->getVisualMuteSettings() && !avatarp->needsImpostorUpdate()))
+// if (impostor || (LLVOAvatar::AV_DO_NOT_RENDER == avatarp->getVisualMuteSettings() && !avatarp->needsImpostorUpdate()))
+ if (impostor || (LLVOAvatar::AOA_NORMAL != avatarp->getOverallAppearance() && !avatarp->needsImpostorUpdate()))
{
if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender && avatarp->mImpostor.isComplete())
{
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 1cd8841bb4..bafebf7bc1 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1479,7 +1479,7 @@ void LLAvatarComplexityControls::setIndirectMaxNonImpostors()
{
U32 max_non_impostors = gSavedSettings.getU32("RenderAvatarMaxNonImpostors");
// for this one, we just need to make zero, which means off, the max value of the slider
- U32 indirect_max_non_impostors = (0 == max_non_impostors) ? LLVOAvatar::IMPOSTORS_OFF : max_non_impostors;
+ U32 indirect_max_non_impostors = (0 == max_non_impostors) ? LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER : max_non_impostors;
gSavedSettings.setU32("IndirectMaxNonImpostors", indirect_max_non_impostors);
}
@@ -1979,7 +1979,7 @@ void LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors()
LLSliderCtrl* ctrl = getChild<LLSliderCtrl>("IndirectMaxNonImpostors",true);
U32 value = ctrl->getValue().asInteger();
- if (0 == value || LLVOAvatar::IMPOSTORS_OFF <= value)
+ if (0 == value || LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER <= value)
{
value=0;
}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index b2c2634e91..29888fe9fd 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -3184,6 +3184,7 @@ class LLObjectMute : public view_listener_t
if (avatar)
{
avatar->mNeedsImpostorUpdate = TRUE;
+ avatar->mLastImpostorUpdateReason = 9;
id = avatar->getID();
diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp
index 998ae52fe0..f042040e98 100644
--- a/indra/newview/llviewerpartsource.cpp
+++ b/indra/newview/llviewerpartsource.cpp
@@ -136,7 +136,7 @@ void LLViewerPartSourceScript::update(const F32 dt)
{
mOwnerAvatarp = find_avatar(mOwnerUUID);
}
- if (mOwnerAvatarp.notNull() && LLVOAvatar::AV_DO_NOT_RENDER == mOwnerAvatarp->getVisualMuteSettings())
+ if (mOwnerAvatarp.notNull() && LLVOAvatar::AOA_NORMAL != mOwnerAvatarp->getOverallAppearance())
{
return;
}
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index ba931bcbb2..e085a945a8 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -207,6 +207,8 @@ enum ERenderName
RENDER_NAME_FADE
};
+#define JELLYDOLLS_SHOULD_IMPOSTOR
+
//-----------------------------------------------------------------------------
// Callback data
//-----------------------------------------------------------------------------
@@ -574,7 +576,8 @@ private:
// Static Data
//-----------------------------------------------------------------------------
S32 LLVOAvatar::sFreezeCounter = 0;
-U32 LLVOAvatar::sMaxNonImpostors = 12; // overridden based on graphics setting
+U32 LLVOAvatar::sMaxNonImpostors = 12; // Set from RenderAvatarMaxNonImpostors
+bool LLVOAvatar::sLimitNonImpostors = false; // True unless RenderAvatarMaxNonImpostors is 0 (unlimited)
F32 LLVOAvatar::sRenderDistance = 256.f;
S32 LLVOAvatar::sNumVisibleAvatars = 0;
S32 LLVOAvatar::sNumLODChangesThisFrame = 0;
@@ -601,7 +604,6 @@ BOOL LLVOAvatar::sShowFootPlane = FALSE;
BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE;
F32 LLVOAvatar::sLODFactor = 1.f;
F32 LLVOAvatar::sPhysicsLODFactor = 1.f;
-bool LLVOAvatar::sUseImpostors = false; // overwridden by RenderAvatarMaxNonImpostors
BOOL LLVOAvatar::sJointDebug = FALSE;
F32 LLVOAvatar::sUnbakedTime = 0.f;
F32 LLVOAvatar::sUnbakedUpdateTime = 0.f;
@@ -634,6 +636,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mMeshValid(FALSE),
mVisible(FALSE),
mLastImpostorUpdateFrameTime(0.f),
+ mLastImpostorUpdateReason(0),
mWindFreq(0.f),
mRipplePhase( 0.f ),
mBelowWater(FALSE),
@@ -656,6 +659,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mNeedsSkin(FALSE),
mLastSkinTime(0.f),
mUpdatePeriod(1),
+ mOverallAppearance(AOA_INVISIBLE),
mVisualComplexityStale(true),
mVisuallyMuteSetting(AV_RENDER_NORMALLY),
mMutedAVColor(LLColor4::white /* used for "uninitialize" */),
@@ -700,6 +704,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
setAnimationData("Speed", &mSpeed);
mNeedsImpostorUpdate = TRUE;
+ mLastImpostorUpdateReason = 0;
mNeedsAnimUpdate = TRUE;
mNeedsExtentUpdate = true;
@@ -755,8 +760,8 @@ std::string LLVOAvatar::avString() const
}
else
{
- std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus());
- return " Avatar '" + getFullname() + "' " + viz_string + " ";
+ std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus());
+ return " Avatar '" + getFullname() + "' " + viz_string + " ";
}
}
@@ -1075,6 +1080,7 @@ void LLVOAvatar::resetImpostors()
LLVOAvatar* avatar = (LLVOAvatar*) *iter;
avatar->mImpostor.release();
avatar->mNeedsImpostorUpdate = TRUE;
+ avatar->mLastImpostorUpdateReason = 1;
}
}
@@ -1319,72 +1325,84 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
LL_RECORD_BLOCK_TIME(FTM_AVATAR_EXTENT_UPDATE);
S32 box_detail = gSavedSettings.getS32("AvatarBoundingBoxComplexity");
+ if (getOverallAppearance() != AOA_NORMAL)
+ {
+ if (isControlAvatar())
+ {
+ // Animated objects don't show system avatar but do need to include rigged meshes in their bounding box.
+ box_detail = 3;
+ }
+ else
+ {
+ // Jellydolled avatars ignore attachments, etc, use only system avatar.
+ box_detail = 1;
+ }
+ }
// FIXME the update_min_max function used below assumes there is a
// known starting point, but in general there isn't. Ideally the
// box update logic should be modified to handle the no-point-yet
// case. For most models, starting with the pelvis is safe though.
LLVector3 zero_pos;
- LLVector4a pos;
+ LLVector4a pos;
if (dist_vec(zero_pos, mPelvisp->getWorldPosition())<0.001)
{
// Don't use pelvis until av initialized
- pos.load3(getRenderPosition().mV);
+ pos.load3(getRenderPosition().mV);
}
else
{
pos.load3(mPelvisp->getWorldPosition().mV);
}
- newMin = pos;
- newMax = pos;
+ newMin = pos;
+ newMax = pos;
- //stretch bounding box by joint positions. Doing this for
- //control avs, where the polymeshes aren't maintained or
- //displayed, can give inaccurate boxes due to joints stuck at (0,0,0).
- if ((box_detail>=1) && !isControlAvatar())
+ if (box_detail>=1 && !isControlAvatar())
{
- for (polymesh_map_t::iterator i = mPolyMeshes.begin(); i != mPolyMeshes.end(); ++i)
- {
- LLPolyMesh* mesh = i->second;
- for (S32 joint_num = 0; joint_num < mesh->mJointRenderData.size(); joint_num++)
- {
- LLVector4a trans;
- trans.load3( mesh->mJointRenderData[joint_num]->mWorldMatrix->getTranslation().mV);
- update_min_max(newMin, newMax, trans);
- }
- }
-
+ //stretch bounding box by joint positions. Doing this for
+ //control avs, where the polymeshes aren't maintained or
+ //displayed, can give inaccurate boxes due to joints stuck at (0,0,0).
+ for (polymesh_map_t::iterator i = mPolyMeshes.begin(); i != mPolyMeshes.end(); ++i)
+ {
+ LLPolyMesh* mesh = i->second;
+ for (S32 joint_num = 0; joint_num < mesh->mJointRenderData.size(); joint_num++)
+ {
+ LLVector4a trans;
+ trans.load3( mesh->mJointRenderData[joint_num]->mWorldMatrix->getTranslation().mV);
+ update_min_max(newMin, newMax, trans);
+ }
+ }
}
- // Pad bounding box for starting joint, plus polymesh if
- // applicable. Subsequent calcs should be accurate enough to not
- // need padding.
- LLVector4a padding(0.25);
- newMin.sub(padding);
- newMax.add(padding);
+ // Pad bounding box for starting joint, plus polymesh if
+ // applicable. Subsequent calcs should be accurate enough to not
+ // need padding.
+ LLVector4a padding(0.25);
+ newMin.sub(padding);
+ newMax.add(padding);
- //stretch bounding box by static attachments
+ //stretch bounding box by static attachments
if (box_detail >= 2)
{
float max_attachment_span = get_default_max_prim_scale() * 5.0f;
-
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment* attachment = iter->second;
+
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
- if (attachment->getValid())
- {
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
+ if (attachment->getValid())
+ {
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
// Don't we need to look at children of attached_object as well?
- const LLViewerObject* attached_object = attachment_iter->get();
- if (attached_object && !attached_object->isHUDAttachment())
- {
+ const LLViewerObject* attached_object = attachment_iter->get();
+ if (attached_object && !attached_object->isHUDAttachment())
+ {
const LLVOVolume *vol = dynamic_cast<const LLVOVolume*>(attached_object);
if (vol && vol->isAnimatedObject())
{
@@ -1406,39 +1424,39 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
{
continue;
}
- LLDrawable* drawable = attached_object->mDrawable;
- if (drawable && !drawable->isState(LLDrawable::RIGGED))
- {
- LLSpatialBridge* bridge = drawable->getSpatialBridge();
- if (bridge)
- {
- const LLVector4a* ext = bridge->getSpatialExtents();
- LLVector4a distance;
- distance.setSub(ext[1], ext[0]);
- LLVector4a max_span(max_attachment_span);
-
- S32 lt = distance.lessThan(max_span).getGatheredBits() & 0x7;
-
- // Only add the prim to spatial extents calculations if it isn't a megaprim.
- // max_attachment_span calculated at the start of the function
- // (currently 5 times our max prim size)
- if (lt == 0x7)
- {
- update_min_max(newMin,newMax,ext[0]);
- update_min_max(newMin,newMax,ext[1]);
- }
- }
- }
- }
- }
- }
- }
+ LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable && !drawable->isState(LLDrawable::RIGGED))
+ {
+ LLSpatialBridge* bridge = drawable->getSpatialBridge();
+ if (bridge)
+ {
+ const LLVector4a* ext = bridge->getSpatialExtents();
+ LLVector4a distance;
+ distance.setSub(ext[1], ext[0]);
+ LLVector4a max_span(max_attachment_span);
+
+ S32 lt = distance.lessThan(max_span).getGatheredBits() & 0x7;
+
+ // Only add the prim to spatial extents calculations if it isn't a megaprim.
+ // max_attachment_span calculated at the start of the function
+ // (currently 5 times our max prim size)
+ if (lt == 0x7)
+ {
+ update_min_max(newMin,newMax,ext[0]);
+ update_min_max(newMin,newMax,ext[1]);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
// Stretch bounding box by rigged mesh joint boxes
if (box_detail>=3)
{
- updateRiggingInfo();
+ updateRiggingInfo();
for (S32 joint_num = 0; joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS; joint_num++)
{
LLJoint *joint = getJoint(joint_num);
@@ -2024,6 +2042,38 @@ void LLVOAvatar::resetVisualParams()
}
}
+void LLVOAvatar::applyDefaultParams()
+{
+ // These are params from avs with newly created copies of shape,
+ // skin, hair, eyes, plus gender set as noted. Run arche_tool.py
+ // to get params from some other xml appearance dump.
+ std::map<S32, U8> male_params = {
+ {1,33}, {2,61}, {4,85}, {5,23}, {6,58}, {7,127}, {8,63}, {10,85}, {11,63}, {12,42}, {13,0}, {14,85}, {15,63}, {16,36}, {17,85}, {18,95}, {19,153}, {20,63}, {21,34}, {22,0}, {23,63}, {24,109}, {25,88}, {27,132}, {31,63}, {33,136}, {34,81}, {35,85}, {36,103}, {37,136}, {38,127}, {80,255}, {93,203}, {98,0}, {99,0}, {105,127}, {108,0}, {110,0}, {111,127}, {112,0}, {113,0}, {114,127}, {115,0}, {116,0}, {117,0}, {119,127}, {130,114}, {131,127}, {132,99}, {133,63}, {134,127}, {135,140}, {136,127}, {137,127}, {140,0}, {141,0}, {142,0}, {143,191}, {150,0}, {155,104}, {157,0}, {162,0}, {163,0}, {165,0}, {166,0}, {167,0}, {168,0}, {169,0}, {177,0}, {181,145}, {182,216}, {183,133}, {184,0}, {185,127}, {192,0}, {193,127}, {196,170}, {198,0}, {503,0}, {505,127}, {506,127}, {507,109}, {508,85}, {513,127}, {514,127}, {515,63}, {517,85}, {518,42}, {603,100}, {604,216}, {605,214}, {606,204}, {607,204}, {608,204}, {609,51}, {616,25}, {617,89}, {619,76}, {624,204}, {625,0}, {629,127}, {637,0}, {638,0}, {646,144}, {647,85}, {649,127}, {650,132}, {652,127}, {653,85}, {654,0}, {656,127}, {659,127}, {662,127}, {663,127}, {664,127}, {665,127}, {674,59}, {675,127}, {676,85}, {678,127}, {682,127}, {683,106}, {684,47}, {685,79}, {690,127}, {692,127}, {693,204}, {700,63}, {701,0}, {702,0}, {703,0}, {704,0}, {705,127}, {706,127}, {707,0}, {708,0}, {709,0}, {710,0}, {711,127}, {712,0}, {713,159}, {714,0}, {715,0}, {750,178}, {752,127}, {753,36}, {754,85}, {755,131}, {756,127}, {757,127}, {758,127}, {759,153}, {760,95}, {762,0}, {763,140}, {764,74}, {765,27}, {769,127}, {773,127}, {775,0}, {779,214}, {780,204}, {781,198}, {785,0}, {789,0}, {795,63}, {796,30}, {799,127}, {800,226}, {801,255}, {802,198}, {803,255}, {804,255}, {805,255}, {806,255}, {807,255}, {808,255}, {812,255}, {813,255}, {814,255}, {815,204}, {816,0}, {817,255}, {818,255}, {819,255}, {820,255}, {821,255}, {822,255}, {823,255}, {824,255}, {825,255}, {826,255}, {827,255}, {828,0}, {829,255}, {830,255}, {834,255}, {835,255}, {836,255}, {840,0}, {841,127}, {842,127}, {844,255}, {848,25}, {858,100}, {859,255}, {860,255}, {861,255}, {862,255}, {863,84}, {868,0}, {869,0}, {877,0}, {879,51}, {880,132}, {921,255}, {922,255}, {923,255}, {10000,0}, {10001,0}, {10002,25}, {10003,0}, {10004,25}, {10005,23}, {10006,51}, {10007,0}, {10008,25}, {10009,23}, {10010,51}, {10011,0}, {10012,0}, {10013,25}, {10014,0}, {10015,25}, {10016,23}, {10017,51}, {10018,0}, {10019,0}, {10020,25}, {10021,0}, {10022,25}, {10023,23}, {10024,51}, {10025,0}, {10026,25}, {10027,23}, {10028,51}, {10029,0}, {10030,25}, {10031,23}, {10032,51}, {11000,1}, {11001,127}
+ };
+ std::map<S32, U8> female_params = {
+ {1,33}, {2,61}, {4,85}, {5,23}, {6,58}, {7,127}, {8,63}, {10,85}, {11,63}, {12,42}, {13,0}, {14,85}, {15,63}, {16,36}, {17,85}, {18,95}, {19,153}, {20,63}, {21,34}, {22,0}, {23,63}, {24,109}, {25,88}, {27,132}, {31,63}, {33,136}, {34,81}, {35,85}, {36,103}, {37,136}, {38,127}, {80,0}, {93,203}, {98,0}, {99,0}, {105,127}, {108,0}, {110,0}, {111,127}, {112,0}, {113,0}, {114,127}, {115,0}, {116,0}, {117,0}, {119,127}, {130,114}, {131,127}, {132,99}, {133,63}, {134,127}, {135,140}, {136,127}, {137,127}, {140,0}, {141,0}, {142,0}, {143,191}, {150,0}, {155,104}, {157,0}, {162,0}, {163,0}, {165,0}, {166,0}, {167,0}, {168,0}, {169,0}, {177,0}, {181,145}, {182,216}, {183,133}, {184,0}, {185,127}, {192,0}, {193,127}, {196,170}, {198,0}, {503,0}, {505,127}, {506,127}, {507,109}, {508,85}, {513,127}, {514,127}, {515,63}, {517,85}, {518,42}, {603,100}, {604,216}, {605,214}, {606,204}, {607,204}, {608,204}, {609,51}, {616,25}, {617,89}, {619,76}, {624,204}, {625,0}, {629,127}, {637,0}, {638,0}, {646,144}, {647,85}, {649,127}, {650,132}, {652,127}, {653,85}, {654,0}, {656,127}, {659,127}, {662,127}, {663,127}, {664,127}, {665,127}, {674,59}, {675,127}, {676,85}, {678,127}, {682,127}, {683,106}, {684,47}, {685,79}, {690,127}, {692,127}, {693,204}, {700,63}, {701,0}, {702,0}, {703,0}, {704,0}, {705,127}, {706,127}, {707,0}, {708,0}, {709,0}, {710,0}, {711,127}, {712,0}, {713,159}, {714,0}, {715,0}, {750,178}, {752,127}, {753,36}, {754,85}, {755,131}, {756,127}, {757,127}, {758,127}, {759,153}, {760,95}, {762,0}, {763,140}, {764,74}, {765,27}, {769,127}, {773,127}, {775,0}, {779,214}, {780,204}, {781,198}, {785,0}, {789,0}, {795,63}, {796,30}, {799,127}, {800,226}, {801,255}, {802,198}, {803,255}, {804,255}, {805,255}, {806,255}, {807,255}, {808,255}, {812,255}, {813,255}, {814,255}, {815,204}, {816,0}, {817,255}, {818,255}, {819,255}, {820,255}, {821,255}, {822,255}, {823,255}, {824,255}, {825,255}, {826,255}, {827,255}, {828,0}, {829,255}, {830,255}, {834,255}, {835,255}, {836,255}, {840,0}, {841,127}, {842,127}, {844,255}, {848,25}, {858,100}, {859,255}, {860,255}, {861,255}, {862,255}, {863,84}, {868,0}, {869,0}, {877,0}, {879,51}, {880,132}, {921,255}, {922,255}, {923,255}, {10000,0}, {10001,0}, {10002,25}, {10003,0}, {10004,25}, {10005,23}, {10006,51}, {10007,0}, {10008,25}, {10009,23}, {10010,51}, {10011,0}, {10012,0}, {10013,25}, {10014,0}, {10015,25}, {10016,23}, {10017,51}, {10018,0}, {10019,0}, {10020,25}, {10021,0}, {10022,25}, {10023,23}, {10024,51}, {10025,0}, {10026,25}, {10027,23}, {10028,51}, {10029,0}, {10030,25}, {10031,23}, {10032,51}, {11000,1}, {11001,127}
+ };
+ std::map<S32, U8> *params = NULL;
+ if (getSex() == SEX_MALE)
+ params = &male_params;
+ else
+ params = &female_params;
+
+ for( auto it = params->begin(); it != params->end(); ++it)
+ {
+ LLVisualParam* param = getVisualParam(it->first);
+ if( !param )
+ {
+ // invalid id
+ break;
+ }
+
+ U8 value = it->second;
+ F32 newWeight = U8_to_F32(value, param->getMinWeight(), param->getMaxWeight());
+ param->setWeight(newWeight);
+ }
+}
+
//-----------------------------------------------------------------------------
// resetSkeleton()
//-----------------------------------------------------------------------------
@@ -2086,15 +2136,30 @@ void LLVOAvatar::resetSkeleton(bool reset_animations)
}
// Reset tweakable params to preserved state
- if (mLastProcessedAppearance)
- {
- bool slam_params = true;
- applyParsedAppearanceMessage(*mLastProcessedAppearance, slam_params);
- }
+ if (getOverallAppearance() == AOA_NORMAL)
+ {
+ if (mLastProcessedAppearance)
+ {
+ bool slam_params = true;
+ applyParsedAppearanceMessage(*mLastProcessedAppearance, slam_params);
+ }
+ }
+ else
+ {
+ // Stripped down approximation of
+ // applyParsedAppearanceMessage, but with alternative default
+ // (jellydoll) params
+ setCompositeUpdatesEnabled( FALSE );
+ gPipeline.markGLRebuild(this);
+ applyDefaultParams();
+ setCompositeUpdatesEnabled( TRUE );
+ updateMeshTextures();
+ updateMeshVisibility();
+ }
updateVisualParams();
// Restore attachment pos overrides
- updateAttachmentOverrides();
+ updateAttachmentOverrides();
// Animations
if (reset_animations)
@@ -2729,7 +2794,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
BOOL visible = isVisible() || mNeedsAnimUpdate;
// update attachments positions
- if (detailed_update || !sUseImpostors)
+ if (detailed_update)
{
LL_RECORD_BLOCK_TIME(FTM_ATTACHMENT_UPDATE);
for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
@@ -2789,6 +2854,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
if (angle_diff > F_PI/512.f*distance*mUpdatePeriod)
{
mNeedsImpostorUpdate = TRUE;
+ mLastImpostorUpdateReason = 2;
}
}
@@ -2800,6 +2866,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
if (dist_diff/mImpostorDistance > 0.1f)
{
mNeedsImpostorUpdate = TRUE;
+ mLastImpostorUpdateReason = 3;
}
else
{
@@ -2812,6 +2879,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
if (diff.getLength3().getF32() > 0.05f)
{
mNeedsImpostorUpdate = TRUE;
+ mLastImpostorUpdateReason = 4;
}
else
{
@@ -2819,6 +2887,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
if (diff.getLength3().getF32() > 0.05f)
{
mNeedsImpostorUpdate = TRUE;
+ mLastImpostorUpdateReason = 5;
}
}
}
@@ -2827,13 +2896,13 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
if (mDrawable.notNull())
{
- mDrawable->movePartition();
+ mDrawable->movePartition();
- //force a move if sitting on an active object
- if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive())
- {
- gPipeline.markMoved(mDrawable, TRUE);
- }
+ //force a move if sitting on an active object
+ if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive())
+ {
+ gPipeline.markMoved(mDrawable, TRUE);
+ }
}
}
@@ -3562,14 +3631,19 @@ bool LLVOAvatar::isVisuallyMuted()
muted = false;
}
else if (mVisuallyMuteSetting == AV_DO_NOT_RENDER)
- { // Always want to see this AV as an impostor
+ {
+#ifdef JELLYDOLLS_SHOULD_IMPOSTOR
muted = true;
+ // Always want to see this AV as an impostor
+#else
+ muted = false;
+#endif
}
else if (isInMuteList())
{
muted = true;
}
- else
+ else
{
muted = isTooComplex();
}
@@ -3578,7 +3652,7 @@ bool LLVOAvatar::isVisuallyMuted()
return muted;
}
-bool LLVOAvatar::isInMuteList()
+bool LLVOAvatar::isInMuteList() const
{
bool muted = false;
F64 now = LLFrameTimer::getTotalSeconds();
@@ -3640,9 +3714,14 @@ void LLVOAvatar::updateAppearanceMessageDebugText()
if (hover_offset[2] != 0.0)
{
debug_line += llformat(" hov_z: %.3f", hover_offset[2]);
- debug_line += llformat(" %s", (isSitting() ? "S" : "T"));
+ debug_line += llformat(" %s", (isSitting() ? "S" : "T"));
debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-"));
}
+ if (mInAir)
+ {
+ debug_line += " A";
+
+ }
LLVector3 ankle_right_pos_agent = mFootRightp->getWorldPosition();
LLVector3 normal;
@@ -3655,9 +3734,38 @@ void LLVOAvatar::updateAppearanceMessageDebugText()
LLVector3 pelvis_pos = mPelvisp->getPosition();
debug_line += llformat(" rp %.3f pp %.3f", root_pos[2], pelvis_pos[2]);
- S32 is_visible = (S32) isVisible();
- S32 is_m_visible = (S32) mVisible;
- debug_line += llformat(" v %d/%d", is_visible, is_m_visible);
+ const LLVector3& scale = getScale();
+ debug_line += llformat(" scale-z %.3f", scale[2]);
+ S32 is_visible = (S32) isVisible();
+ S32 is_m_visible = (S32) mVisible;
+ debug_line += llformat(" v %d/%d", is_visible, is_m_visible);
+
+ AvatarOverallAppearance aoa = getOverallAppearance();
+ if (aoa == AOA_NORMAL)
+ {
+ debug_line += " N";
+ }
+ else if (aoa == AOA_JELLYDOLL)
+ {
+ debug_line += " J";
+ }
+ else
+ {
+ debug_line += " I";
+ }
+
+ if (mMeshValid)
+ {
+ debug_line += "m";
+ }
+ else
+ {
+ debug_line += "-";
+ }
+ if (isImpostor())
+ {
+ debug_line += " Imp" + llformat("%d[%d]:%.1f", mUpdatePeriod, mLastImpostorUpdateReason, ((F32)(gFrameTimeSeconds-mLastImpostorUpdateFrameTime)));
+ }
addDebugText(debug_line);
}
@@ -3699,13 +3807,13 @@ LLViewerInventoryItem* recursiveGetObjectInventoryItem(LLViewerObject *vobj, LLU
void LLVOAvatar::updateAnimationDebugText()
{
- for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin();
- iter != mMotionController.getActiveMotions().end(); ++iter)
+ for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin();
+ iter != mMotionController.getActiveMotions().end(); ++iter)
+ {
+ LLMotion* motionp = *iter;
+ if (motionp->getMinPixelArea() < getPixelArea())
{
- LLMotion* motionp = *iter;
- if (motionp->getMinPixelArea() < getPixelArea())
- {
- std::string output;
+ std::string output;
std::string motion_name = motionp->getName();
if (motion_name.empty())
{
@@ -3722,73 +3830,74 @@ void LLVOAvatar::updateAnimationDebugText()
}
}
if (motion_name.empty())
+ {
+ std::string name;
+ if (gAgent.isGodlikeWithoutAdminMenuFakery() || isSelf())
{
- std::string name;
- if (gAgent.isGodlikeWithoutAdminMenuFakery() || isSelf())
+ name = motionp->getID().asString();
+ LLVOAvatar::AnimSourceIterator anim_it = mAnimationSources.begin();
+ for (; anim_it != mAnimationSources.end(); ++anim_it)
{
- name = motionp->getID().asString();
- LLVOAvatar::AnimSourceIterator anim_it = mAnimationSources.begin();
- for (; anim_it != mAnimationSources.end(); ++anim_it)
+ if (anim_it->second == motionp->getID())
{
- if (anim_it->second == motionp->getID())
+ LLViewerObject* object = gObjectList.findObject(anim_it->first);
+ if (!object)
+ {
+ break;
+ }
+ if (object->isAvatar())
+ {
+ if (mMotionController.mIsSelf)
+ {
+ // Searching inventory by asset id is really long
+ // so just mark as inventory
+ // Also item is likely to be named by LLPreviewAnim
+ name += "(inventory)";
+ }
+ }
+ else
{
- LLViewerObject* object = gObjectList.findObject(anim_it->first);
- if (!object)
+ LLViewerInventoryItem* item = NULL;
+ if (!object->isInventoryDirty())
{
- break;
+ item = object->getInventoryItemByAsset(motionp->getID());
}
- if (object->isAvatar())
+ if (item)
{
- if (mMotionController.mIsSelf)
- {
- // Searching inventory by asset id is really long
- // so just mark as inventory
- // Also item is likely to be named by LLPreviewAnim
- name += "(inventory)";
- }
+ name = item->getName();
+ }
+ else if (object->isAttachment())
+ {
+ name += "(att:" + getAttachmentItemName() + ")";
}
else
{
- LLViewerInventoryItem* item = NULL;
- if (!object->isInventoryDirty())
- {
- item = object->getInventoryItemByAsset(motionp->getID());
- }
- if (item)
- {
- name = item->getName();
- }
- else if (object->isAttachment())
- {
- name += "(" + getAttachmentItemName() + ")";
- }
- else
- {
- // in-world object, name or content unknown
- name += "(in-world)";
- }
+ // in-world object, name or content unknown
+ name += "(in-world)";
}
- break;
}
+ break;
}
}
- else
- {
- name = LLUUID::null.asString();
- }
- output = llformat("%s - %d",
- name.c_str(),
- (U32)motionp->getPriority());
}
else
{
- output = llformat("%s - %d",
- motion_name.c_str(),
- (U32)motionp->getPriority());
+ name = LLUUID::null.asString();
}
- addDebugText(output);
+ motion_name = name;
+ }
+ std::string motion_tag = "";
+ if (mPlayingAnimations.find(motionp->getID()) != mPlayingAnimations.end())
+ {
+ motion_tag = "*";
}
+ output = llformat("%s%s - %d",
+ motion_name.c_str(),
+ motion_tag.c_str(),
+ (U32)motionp->getPriority());
+ addDebugText(output);
}
+ }
}
void LLVOAvatar::updateDebugText()
@@ -3917,7 +4026,14 @@ void LLVOAvatar::updateFootstepSounds()
// computeUpdatePeriod()
// Factored out from updateCharacter()
// Set new value for mUpdatePeriod based on distance and various other factors.
-//------------------------------------------------------------------------
+//
+// Note 10-2020: it turns out that none of these update period
+// calculations have been having any effect, because
+// mNeedsImpostorUpdate was not being set in updateCharacter(). So
+// it's really open to question whether we want to enable time based updates, and if
+// so, at what rate. Leaving the rates as given would lead to
+// drastically more frequent impostor updates than we've been doing all these years.
+// ------------------------------------------------------------------------
void LLVOAvatar::computeUpdatePeriod()
{
bool visually_muted = isVisuallyMuted();
@@ -3925,7 +4041,7 @@ void LLVOAvatar::computeUpdatePeriod()
&& isVisible()
&& (!isSelf() || visually_muted)
&& !isUIAvatar()
- && sUseImpostors
+ && (sLimitNonImpostors || visually_muted)
&& !mNeedsAnimUpdate
&& !sFreezeCounter)
{
@@ -3933,11 +4049,14 @@ void LLVOAvatar::computeUpdatePeriod()
LLVector4a size;
size.setSub(ext[1],ext[0]);
F32 mag = size.getLength3().getF32()*0.5f;
+
+ const S32 UPDATE_RATE_SLOW = 64;
+ const S32 UPDATE_RATE_MED = 48;
+ const S32 UPDATE_RATE_FAST = 32;
- F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f);
if (visually_muted)
- { // visually muted avatars update at 16 hz
- mUpdatePeriod = 16;
+ { // visually muted avatars update at lowest rate
+ mUpdatePeriod = UPDATE_RATE_SLOW;
}
else if (! shouldImpostor()
|| mDrawable->mDistanceWRTCamera < 1.f + mag)
@@ -3946,34 +4065,29 @@ void LLVOAvatar::computeUpdatePeriod()
// impostor camera near clip plane
mUpdatePeriod = 1;
}
- else if ( shouldImpostor(4) )
+ else if ( shouldImpostor(4.0) )
{ //background avatars are REALLY slow updating impostors
- mUpdatePeriod = 16;
+ mUpdatePeriod = UPDATE_RATE_SLOW;
}
else if (mLastRezzedStatus <= 0)
{
// Don't update cloud avatars too often
- mUpdatePeriod = 8;
+ mUpdatePeriod = UPDATE_RATE_SLOW;
}
- else if ( shouldImpostor(3) )
+ else if ( shouldImpostor(3.0) )
{ //back 25% of max visible avatars are slow updating impostors
- mUpdatePeriod = 8;
- }
- else if (mImpostorPixelArea <= impostor_area)
- { // stuff in between gets an update period based on pixel area
- mUpdatePeriod = llclamp((S32) sqrtf(impostor_area*4.f/mImpostorPixelArea), 2, 8);
+ mUpdatePeriod = UPDATE_RATE_MED;
}
- else
+ else
{
//nearby avatars, update the impostors more frequently.
- mUpdatePeriod = 4;
+ mUpdatePeriod = UPDATE_RATE_FAST;
}
}
else
{
mUpdatePeriod = 1;
}
-
}
//------------------------------------------------------------------------
@@ -4244,7 +4358,33 @@ void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool w
if (!isSitting() && !was_sit_ground_constrained)
{
root_pos += LLVector3d(getHoverOffset());
- }
+ if (getOverallAppearance() == AOA_JELLYDOLL)
+ {
+ F32 offz = -0.5 * (getScale()[VZ] - mBodySize.mV[VZ]);
+ root_pos[2] += offz;
+ // if (!isSelf() && !isControlAvatar())
+ // {
+ // LL_DEBUGS("Avatar") << "av " << getFullname()
+ // << " frame " << LLFrameTimer::getFrameCount()
+ // << " root adjust offz " << offz
+ // << " scalez " << getScale()[VZ]
+ // << " bsz " << mBodySize.mV[VZ]
+ // << LL_ENDL;
+ // }
+ }
+ }
+ // if (!isSelf() && !isControlAvatar())
+ // {
+ // LL_DEBUGS("Avatar") << "av " << getFullname() << " aoa " << (S32) getOverallAppearance()
+ // << " frame " << LLFrameTimer::getFrameCount()
+ // << " scalez " << getScale()[VZ]
+ // << " bsz " << mBodySize.mV[VZ]
+ // << " root pos " << root_pos[2]
+ // << " curr rootz " << mRoot->getPosition()[2]
+ // << " pp-z " << mPelvisp->getPosition()[2]
+ // << " renderpos " << getRenderPosition()
+ // << LL_ENDL;
+ // }
LLControlAvatar *cav = dynamic_cast<LLControlAvatar*>(this);
if (cav)
@@ -4255,6 +4395,14 @@ void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool w
else
{
LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos);
+ // if (!isSelf() && !isControlAvatar())
+ // {
+ // LL_DEBUGS("Avatar") << "av " << getFullname()
+ // << " frame " << LLFrameTimer::getFrameCount()
+ // << " newPosition " << newPosition
+ // << " renderpos " << getRenderPosition()
+ // << LL_ENDL;
+ // }
if (newPosition != mRoot->getXform()->getWorldPosition())
{
mRoot->touch();
@@ -4285,6 +4433,37 @@ void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool w
}
//------------------------------------------------------------------------
+// LLVOAvatar::computeNeedsUpdate()
+//
+// Most of the logic here is to figure out when to periodically update impostors.
+// Non-impostors have mUpdatePeriod == 1 and will need update every frame.
+//------------------------------------------------------------------------
+bool LLVOAvatar::computeNeedsUpdate()
+{
+ const F32 MAX_IMPOSTOR_INTERVAL = 4.0f;
+ computeUpdatePeriod();
+
+ bool needs_update_by_frame_count = ((LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0);
+
+ bool needs_update_by_max_time = ((gFrameTimeSeconds-mLastImpostorUpdateFrameTime)> MAX_IMPOSTOR_INTERVAL);
+ bool needs_update = needs_update_by_frame_count || needs_update_by_max_time;
+
+ if (needs_update && !isSelf())
+ {
+ if (needs_update_by_max_time)
+ {
+ mNeedsImpostorUpdate = TRUE;
+ mLastImpostorUpdateReason = 11;
+ }
+ else
+ {
+ //mNeedsImpostorUpdate = TRUE;
+ //mLastImpostorUpdateReason = 10;
+ }
+ }
+ return needs_update;
+}
+
// updateCharacter()
//
// This is called for all avatars, so there are 4 possible situations:
@@ -4307,7 +4486,7 @@ void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool w
// simulator.
//
//------------------------------------------------------------------------
-BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
+bool LLVOAvatar::updateCharacter(LLAgent &agent)
{
updateDebugText();
@@ -4319,6 +4498,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
BOOL visible = isVisible();
bool is_control_avatar = isControlAvatar(); // capture state to simplify tracing
bool is_attachment = false;
+
if (is_control_avatar)
{
LLControlAvatar *cav = dynamic_cast<LLControlAvatar*>(this);
@@ -4338,11 +4518,11 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
//--------------------------------------------------------------------
// The rest should only be done occasionally for far away avatars.
- // Set mUpdatePeriod and visible based on distance and other criteria.
+ // Set mUpdatePeriod and visible based on distance and other criteria,
+ // and flag for impostor update if needed.
//--------------------------------------------------------------------
- computeUpdatePeriod();
- bool needs_update = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0;
-
+ bool needs_update = computeNeedsUpdate();
+
//--------------------------------------------------------------------
// Early out if does not need update and not self
// don't early out for your own avatar, as we rely on your animations playing reliably
@@ -4356,6 +4536,12 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
}
//--------------------------------------------------------------------
+ // Handle transitions between regular rendering, jellydoll, or invisible.
+ // Can trigger skeleton reset or animation changes
+ //--------------------------------------------------------------------
+ updateOverallAppearance();
+
+ //--------------------------------------------------------------------
// change animation time quanta based on avatar render load
//--------------------------------------------------------------------
// SL-763 the time step quantization does not currently work.
@@ -4438,8 +4624,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
if (visible)
{
- // System avatar mesh vertices need to be reskinned.
- mNeedsSkin = TRUE;
+ // System avatar mesh vertices need to be reskinned.
+ mNeedsSkin = TRUE;
}
return visible;
@@ -4885,7 +5071,8 @@ U32 LLVOAvatar::renderSkinned()
}
if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
{
- if (isTextureVisible(TEX_HEAD_BAKED) || isUIAvatar())
+
+ if (isTextureVisible(TEX_HEAD_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar())
{
LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD);
if (head_mesh)
@@ -4895,7 +5082,7 @@ U32 LLVOAvatar::renderSkinned()
first_pass = FALSE;
}
}
- if (isTextureVisible(TEX_UPPER_BAKED) || isUIAvatar())
+ if (isTextureVisible(TEX_UPPER_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar())
{
LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY);
if (upper_mesh)
@@ -4905,7 +5092,7 @@ U32 LLVOAvatar::renderSkinned()
first_pass = FALSE;
}
- if (isTextureVisible(TEX_LOWER_BAKED) || isUIAvatar())
+ if (isTextureVisible(TEX_LOWER_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar())
{
LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY);
if (lower_mesh)
@@ -4962,7 +5149,7 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)
}
first_pass = FALSE;
}
- if (isTextureVisible(TEX_HAIR_BAKED))
+ if (isTextureVisible(TEX_HAIR_BAKED) && (getOverallAppearance() != AOA_JELLYDOLL))
{
LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR);
if (hair_mesh)
@@ -5010,7 +5197,7 @@ U32 LLVOAvatar::renderRigid()
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
}
- if (isTextureVisible(TEX_EYES_BAKED) || isUIAvatar())
+ if (isTextureVisible(TEX_EYES_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar())
{
LLViewerJoint* eyeball_left = getViewerJoint(MESH_ID_EYEBALL_LEFT);
LLViewerJoint* eyeball_right = getViewerJoint(MESH_ID_EYEBALL_RIGHT);
@@ -5639,8 +5826,8 @@ void LLVOAvatar::processAnimationStateChanges()
stopMotion(ANIM_AGENT_TARGET);
if (mEnableDefaultMotions)
{
- startMotion(ANIM_AGENT_BODY_NOISE);
- }
+ startMotion(ANIM_AGENT_BODY_NOISE);
+ }
}
// clear all current animations
@@ -5660,23 +5847,32 @@ void LLVOAvatar::processAnimationStateChanges()
++anim_it;
}
+ // if jellydolled, shelve all playing animations
+ if (getOverallAppearance() != AOA_NORMAL)
+ {
+ mPlayingAnimations.clear();
+ }
+
// start up all new anims
- for (anim_it = mSignaledAnimations.begin(); anim_it != mSignaledAnimations.end();)
+ if (getOverallAppearance() == AOA_NORMAL)
{
- AnimIterator found_anim = mPlayingAnimations.find(anim_it->first);
-
- // signaled but not playing, or different sequence id, start motion
- if (found_anim == mPlayingAnimations.end() || found_anim->second != anim_it->second)
+ for (anim_it = mSignaledAnimations.begin(); anim_it != mSignaledAnimations.end();)
{
- if (processSingleAnimationStateChange(anim_it->first, TRUE))
+ AnimIterator found_anim = mPlayingAnimations.find(anim_it->first);
+
+ // signaled but not playing, or different sequence id, start motion
+ if (found_anim == mPlayingAnimations.end() || found_anim->second != anim_it->second)
{
- mPlayingAnimations[anim_it->first] = anim_it->second;
- ++anim_it;
- continue;
+ if (processSingleAnimationStateChange(anim_it->first, TRUE))
+ {
+ mPlayingAnimations[anim_it->first] = anim_it->second;
+ ++anim_it;
+ continue;
+ }
}
- }
- ++anim_it;
+ ++anim_it;
+ }
}
// clear source information for animations which have been stopped
@@ -6239,6 +6435,11 @@ void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo, std::set<LL
}
LLScopedContextString str("addAttachmentOverridesForObject " + getFullname());
+
+ if (getOverallAppearance() != AOA_NORMAL)
+ {
+ return;
+ }
LL_DEBUGS("AnimatedObjects") << "adding" << LL_ENDL;
dumpStack("AnimatedObjectsStack");
@@ -7658,9 +7859,15 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color)
}
// virtual
+// Do rigged mesh attachments display with this av?
bool LLVOAvatar::shouldRenderRigged() const
{
- return true;
+ if (getOverallAppearance() == AOA_NORMAL)
+ {
+ return true;
+ }
+ // TBD - render for AOA_JELLYDOLL?
+ return false;
}
// FIXME: We have an mVisible member, set in updateVisibility(), but this
@@ -7941,12 +8148,14 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading)
}
// did our loading state "change" from last call?
- // runway - why are we updating every 30 calls even if nothing has changed?
+ // FIXME runway - why are we updating every 30 calls even if nothing has changed?
+ // This causes updateLOD() to run every 30 frames, among other things.
const S32 UPDATE_RATE = 30;
BOOL changed =
((mFullyLoaded != mPreviousFullyLoaded) || // if the value is different from the previous call
(!mFullyLoadedInitialized) || // if we've never been called before
(mFullyLoadedFrameCounter % UPDATE_RATE == 0)); // every now and then issue a change
+ BOOL fully_loaded_changed = (mFullyLoaded != mPreviousFullyLoaded);
mPreviousFullyLoaded = mFullyLoaded;
mFullyLoadedInitialized = TRUE;
@@ -7957,7 +8166,13 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading)
// to know about outfit switching
LLAvatarRenderNotifier::getInstance()->updateNotificationState();
}
-
+
+ if (fully_loaded_changed && !isSelf() && mFullyLoaded && isImpostor())
+ {
+ // Fix for jellydoll initially invisible
+ mNeedsImpostorUpdate = TRUE;
+ mLastImpostorUpdateReason = 6;
+ }
return changed;
}
@@ -8029,47 +8244,25 @@ void LLVOAvatar::updateMeshVisibility()
bool bake_flag[BAKED_NUM_INDICES];
memset(bake_flag, 0, BAKED_NUM_INDICES*sizeof(bool));
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
+ if (getOverallAppearance() == AOA_NORMAL)
{
- LLViewerJointAttachment* attachment = iter->second;
- if (attachment)
+ for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
{
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
+ LLViewerJointAttachment* attachment = iter->second;
+ if (attachment)
{
- LLViewerObject *objectp = attachment_iter->get();
- if (objectp)
- {
- for (int face_index = 0; face_index < objectp->getNumTEs(); face_index++)
- {
- LLTextureEntry* tex_entry = objectp->getTE(face_index);
- bake_flag[BAKED_HEAD] |= (tex_entry->getID() == IMG_USE_BAKED_HEAD);
- bake_flag[BAKED_EYES] |= (tex_entry->getID() == IMG_USE_BAKED_EYES);
- bake_flag[BAKED_HAIR] |= (tex_entry->getID() == IMG_USE_BAKED_HAIR);
- bake_flag[BAKED_LOWER] |= (tex_entry->getID() == IMG_USE_BAKED_LOWER);
- bake_flag[BAKED_UPPER] |= (tex_entry->getID() == IMG_USE_BAKED_UPPER);
- bake_flag[BAKED_SKIRT] |= (tex_entry->getID() == IMG_USE_BAKED_SKIRT);
- bake_flag[BAKED_LEFT_ARM] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTARM);
- bake_flag[BAKED_LEFT_LEG] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTLEG);
- bake_flag[BAKED_AUX1] |= (tex_entry->getID() == IMG_USE_BAKED_AUX1);
- bake_flag[BAKED_AUX2] |= (tex_entry->getID() == IMG_USE_BAKED_AUX2);
- bake_flag[BAKED_AUX3] |= (tex_entry->getID() == IMG_USE_BAKED_AUX3);
- }
- }
-
- LLViewerObject::const_child_list_t& child_list = objectp->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter1 = child_list.begin();
- iter1 != child_list.end(); ++iter1)
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLViewerObject* objectchild = *iter1;
- if (objectchild)
+ LLViewerObject *objectp = attachment_iter->get();
+ if (objectp)
{
- for (int face_index = 0; face_index < objectchild->getNumTEs(); face_index++)
+ for (int face_index = 0; face_index < objectp->getNumTEs(); face_index++)
{
- LLTextureEntry* tex_entry = objectchild->getTE(face_index);
+ LLTextureEntry* tex_entry = objectp->getTE(face_index);
bake_flag[BAKED_HEAD] |= (tex_entry->getID() == IMG_USE_BAKED_HEAD);
bake_flag[BAKED_EYES] |= (tex_entry->getID() == IMG_USE_BAKED_EYES);
bake_flag[BAKED_HAIR] |= (tex_entry->getID() == IMG_USE_BAKED_HAIR);
@@ -8083,6 +8276,31 @@ void LLVOAvatar::updateMeshVisibility()
bake_flag[BAKED_AUX3] |= (tex_entry->getID() == IMG_USE_BAKED_AUX3);
}
}
+
+ LLViewerObject::const_child_list_t& child_list = objectp->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter1 = child_list.begin();
+ iter1 != child_list.end(); ++iter1)
+ {
+ LLViewerObject* objectchild = *iter1;
+ if (objectchild)
+ {
+ for (int face_index = 0; face_index < objectchild->getNumTEs(); face_index++)
+ {
+ LLTextureEntry* tex_entry = objectchild->getTE(face_index);
+ bake_flag[BAKED_HEAD] |= (tex_entry->getID() == IMG_USE_BAKED_HEAD);
+ bake_flag[BAKED_EYES] |= (tex_entry->getID() == IMG_USE_BAKED_EYES);
+ bake_flag[BAKED_HAIR] |= (tex_entry->getID() == IMG_USE_BAKED_HAIR);
+ bake_flag[BAKED_LOWER] |= (tex_entry->getID() == IMG_USE_BAKED_LOWER);
+ bake_flag[BAKED_UPPER] |= (tex_entry->getID() == IMG_USE_BAKED_UPPER);
+ bake_flag[BAKED_SKIRT] |= (tex_entry->getID() == IMG_USE_BAKED_SKIRT);
+ bake_flag[BAKED_LEFT_ARM] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTARM);
+ bake_flag[BAKED_LEFT_LEG] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTLEG);
+ bake_flag[BAKED_AUX1] |= (tex_entry->getID() == IMG_USE_BAKED_AUX1);
+ bake_flag[BAKED_AUX2] |= (tex_entry->getID() == IMG_USE_BAKED_AUX2);
+ bake_flag[BAKED_AUX3] |= (tex_entry->getID() == IMG_USE_BAKED_AUX3);
+ }
+ }
+ }
}
}
}
@@ -9013,7 +9231,11 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
mLastProcessedAppearance = contents;
bool slam_params = false;
- applyParsedAppearanceMessage(*contents, slam_params);
+ applyParsedAppearanceMessage(*contents, slam_params);
+ if (getOverallAppearance() != AOA_NORMAL)
+ {
+ resetSkeleton(false);
+ }
}
void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& contents, bool slam_params)
@@ -9906,7 +10128,7 @@ BOOL LLVOAvatar::updateLOD()
return FALSE;
}
- if (isImpostor() && 0 != mDrawable->getNumFaces() && mDrawable->getFace(0)->hasGeometry())
+ if (!LLPipeline::sImpostorRender && isImpostor() && 0 != mDrawable->getNumFaces() && mDrawable->getFace(0)->hasGeometry())
{
return TRUE;
}
@@ -10097,10 +10319,10 @@ void LLVOAvatar::updateImpostors()
iter != instances_copy.end(); ++iter)
{
LLVOAvatar* avatar = (LLVOAvatar*) *iter;
- if (!avatar->isDead() && avatar->isVisible()
- && (
- (avatar->isImpostor() || LLVOAvatar::AV_DO_NOT_RENDER == avatar->getVisualMuteSettings()) && avatar->needsImpostorUpdate())
- )
+ if (!avatar->isDead()
+ && avatar->isVisible()
+ && avatar->isImpostor()
+ && avatar->needsImpostorUpdate())
{
avatar->calcMutedAVColor();
gPipeline.generateImpostor(avatar);
@@ -10113,12 +10335,20 @@ void LLVOAvatar::updateImpostors()
// virtual
BOOL LLVOAvatar::isImpostor()
{
- return sUseImpostors && (isVisuallyMuted() || (mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE;
+ return isVisuallyMuted() || (sLimitNonImpostors && (mUpdatePeriod > 1));
}
-BOOL LLVOAvatar::shouldImpostor(const U32 rank_factor) const
+BOOL LLVOAvatar::shouldImpostor(const F32 rank_factor)
{
- return (!isSelf() && sUseImpostors && mVisibilityRank > (sMaxNonImpostors * rank_factor));
+ if (isSelf())
+ {
+ return false;
+ }
+ if (isVisuallyMuted())
+ {
+ return true;
+ }
+ return sLimitNonImpostors && (mVisibilityRank > sMaxNonImpostors * rank_factor);
}
BOOL LLVOAvatar::needsImpostorUpdate() const
@@ -10161,16 +10391,16 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d
}
// static
-const U32 LLVOAvatar::IMPOSTORS_OFF = 66; /* Must equal the maximum allowed the RenderAvatarMaxNonImpostors
+const U32 LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER = 66; /* Must equal the maximum allowed the RenderAvatarMaxNonImpostors
* slider in panel_preferences_graphics1.xml */
// static
void LLVOAvatar::updateImpostorRendering(U32 newMaxNonImpostorsValue)
{
U32 oldmax = sMaxNonImpostors;
- bool oldflg = sUseImpostors;
+ bool oldflg = sLimitNonImpostors;
- if (IMPOSTORS_OFF <= newMaxNonImpostorsValue)
+ if (NON_IMPOSTORS_MAX_SLIDER <= newMaxNonImpostorsValue)
{
sMaxNonImpostors = 0;
}
@@ -10178,13 +10408,13 @@ void LLVOAvatar::updateImpostorRendering(U32 newMaxNonImpostorsValue)
{
sMaxNonImpostors = newMaxNonImpostorsValue;
}
- // the sUseImpostors flag depends on whether or not sMaxNonImpostors is set to the no-limit value (0)
- sUseImpostors = (0 != sMaxNonImpostors);
- if ( oldflg != sUseImpostors )
+ // the sLimitNonImpostors flag depends on whether or not sMaxNonImpostors is set to the no-limit value (0)
+ sLimitNonImpostors = (0 != sMaxNonImpostors);
+ if ( oldflg != sLimitNonImpostors )
{
LL_DEBUGS("AvatarRender")
<< "was " << (oldflg ? "use" : "don't use" ) << " impostors (max " << oldmax << "); "
- << "now " << (sUseImpostors ? "use" : "don't use" ) << " impostors (max " << sMaxNonImpostors << "); "
+ << "now " << (sLimitNonImpostors ? "use" : "don't use" ) << " impostors (max " << sMaxNonImpostors << "); "
<< LL_ENDL;
}
}
@@ -10582,10 +10812,178 @@ void LLVOAvatar::setVisualMuteSettings(VisualMuteSettings set)
{
mVisuallyMuteSetting = set;
mNeedsImpostorUpdate = TRUE;
+ mLastImpostorUpdateReason = 7;
LLRenderMuteList::getInstance()->saveVisualMuteSetting(getID(), S32(set));
}
+
+void LLVOAvatar::setOverallAppearanceNormal()
+{
+ if (isControlAvatar())
+ return;
+
+ LLVector3 pelvis_pos = getJoint("mPelvis")->getPosition();
+ resetSkeleton(false);
+ getJoint("mPelvis")->setPosition(pelvis_pos);
+
+ for (auto it = mJellyAnims.begin(); it != mJellyAnims.end(); ++it)
+ {
+ bool is_playing = (mPlayingAnimations.find(*it) != mPlayingAnimations.end());
+ LL_DEBUGS("Avatar") << "jelly anim " << *it << " " << is_playing << LL_ENDL;
+ if (!is_playing)
+ {
+ // Anim was not requested for this av by sim, but may be playing locally
+ stopMotion(*it);
+ }
+ }
+ mJellyAnims.clear();
+
+ processAnimationStateChanges();
+}
+
+void LLVOAvatar::setOverallAppearanceJellyDoll()
+{
+ if (isControlAvatar())
+ return;
+
+ // stop current animations
+ {
+ for ( LLVOAvatar::AnimIterator anim_it= mPlayingAnimations.begin();
+ anim_it != mPlayingAnimations.end();
+ ++anim_it)
+ {
+ {
+ stopMotion(anim_it->first, TRUE);
+ }
+ }
+ }
+ processAnimationStateChanges();
+
+ // Start any needed anims for jellydoll
+ updateOverallAppearanceAnimations();
+
+ LLVector3 pelvis_pos = getJoint("mPelvis")->getPosition();
+ resetSkeleton(false);
+ getJoint("mPelvis")->setPosition(pelvis_pos);
+
+}
+
+void LLVOAvatar::setOverallAppearanceInvisible()
+{
+}
+
+void LLVOAvatar::updateOverallAppearance()
+{
+ AvatarOverallAppearance new_overall = getOverallAppearance();
+ if (new_overall != mOverallAppearance)
+ {
+ switch (new_overall)
+ {
+ case AOA_NORMAL:
+ setOverallAppearanceNormal();
+ break;
+ case AOA_JELLYDOLL:
+ setOverallAppearanceJellyDoll();
+ break;
+ case AOA_INVISIBLE:
+ setOverallAppearanceInvisible();
+ break;
+ }
+ mOverallAppearance = new_overall;
+ if (!isSelf())
+ {
+ mNeedsImpostorUpdate = TRUE;
+ mLastImpostorUpdateReason = 8;
+ }
+ updateMeshVisibility();
+ }
+
+ // This needs to be done even if overall appearance has not
+ // changed, since sit/stand status can be different.
+ updateOverallAppearanceAnimations();
+}
+
+void LLVOAvatar::updateOverallAppearanceAnimations()
+{
+ if (isControlAvatar())
+ return;
+
+ if (getOverallAppearance() == AOA_JELLYDOLL)
+ {
+ LLUUID motion_id;
+ if (isSitting() && getParent()) // sitting on object
+ {
+ motion_id = ANIM_AGENT_SIT_FEMALE;
+ }
+ else if (isSitting()) // sitting on ground
+ {
+ motion_id = ANIM_AGENT_SIT_GROUND_CONSTRAINED;
+ }
+ else // standing
+ {
+ motion_id = ANIM_AGENT_STAND;
+ }
+ if (mJellyAnims.find(motion_id) == mJellyAnims.end())
+ {
+ for (auto it = mJellyAnims.begin(); it != mJellyAnims.end(); ++it)
+ {
+ bool is_playing = (mPlayingAnimations.find(*it) != mPlayingAnimations.end());
+ LL_DEBUGS("Avatar") << "jelly anim " << *it << " " << is_playing << LL_ENDL;
+ if (!is_playing)
+ {
+ // Anim was not requested for this av by sim, but may be playing locally
+ stopMotion(*it, TRUE);
+ }
+ }
+ mJellyAnims.clear();
+
+ startMotion(motion_id);
+ mJellyAnims.insert(motion_id);
+
+ processAnimationStateChanges();
+ }
+ }
+}
+
+// Based on isVisuallyMuted(), but has 3 possible results.
+LLVOAvatar::AvatarOverallAppearance LLVOAvatar::getOverallAppearance() const
+{
+ AvatarOverallAppearance result = AOA_NORMAL;
+
+ // Priority order (highest priority first)
+ // * own avatar is always drawn normally
+ // * if on the "always draw normally" list, draw them normally
+ // * if on the "always visually mute" list, show as jellydoll
+ // * if explicitly muted (blocked), show as invisible
+ // * check against the render cost and attachment limits - if too complex, show as jellydoll
+ if (isSelf())
+ {
+ result = AOA_NORMAL;
+ }
+ else // !isSelf()
+ {
+ if (isInMuteList())
+ {
+ result = AOA_INVISIBLE;
+ }
+ else if (mVisuallyMuteSetting == AV_ALWAYS_RENDER)
+ {
+ result = AOA_NORMAL;
+ }
+ else if (mVisuallyMuteSetting == AV_DO_NOT_RENDER)
+ { // Always want to see this AV as an impostor
+ result = AOA_JELLYDOLL;
+ }
+ else if (isTooComplex())
+ {
+ result = AOA_JELLYDOLL;
+ }
+ }
+
+ return result;
+}
+
void LLVOAvatar::calcMutedAVColor()
{
LLColor4 new_color(mMutedAVColor);
@@ -10595,8 +10993,8 @@ void LLVOAvatar::calcMutedAVColor()
if (getVisualMuteSettings() == AV_DO_NOT_RENDER)
{
// explicitly not-rendered avatars are light grey
- new_color = LLColor4::grey3;
- change_msg = " not rendered: color is grey3";
+ new_color = LLColor4::grey4;
+ change_msg = " not rendered: color is grey4";
}
else if (LLMuteList::getInstance()->isMuted(av_id)) // the user blocked them
{
@@ -10609,26 +11007,31 @@ void LLVOAvatar::calcMutedAVColor()
new_color = LLColor4::white;
change_msg = " simple imposter ";
}
+#ifdef COLORIZE_JELLYDOLLS
else if ( mMutedAVColor == LLColor4::white || mMutedAVColor == LLColor4::grey3 || mMutedAVColor == LLColor4::grey4 )
- {
+ {
// select a color based on the first byte of the agents uuid so any muted agent is always the same color
F32 color_value = (F32) (av_id.mData[0]);
- F32 spectrum = (color_value / 256.0); // spectrum is between 0 and 1.f
+ F32 spectrum = (color_value / 256.0); // spectrum is between 0 and 1.f
- // Array of colors. These are arranged so only one RGB color changes between each step,
+ // Array of colors. These are arranged so only one RGB color changes between each step,
// and it loops back to red so there is an even distribution. It is not a heat map
- const S32 NUM_SPECTRUM_COLORS = 7;
+ const S32 NUM_SPECTRUM_COLORS = 7;
static LLColor4 * spectrum_color[NUM_SPECTRUM_COLORS] = { &LLColor4::red, &LLColor4::magenta, &LLColor4::blue, &LLColor4::cyan, &LLColor4::green, &LLColor4::yellow, &LLColor4::red };
-
- spectrum = spectrum * (NUM_SPECTRUM_COLORS - 1); // Scale to range of number of colors
- S32 spectrum_index_1 = floor(spectrum); // Desired color will be after this index
- S32 spectrum_index_2 = spectrum_index_1 + 1; // and before this index (inclusive)
+
+ spectrum = spectrum * (NUM_SPECTRUM_COLORS - 1); // Scale to range of number of colors
+ S32 spectrum_index_1 = floor(spectrum); // Desired color will be after this index
+ S32 spectrum_index_2 = spectrum_index_1 + 1; // and before this index (inclusive)
F32 fractBetween = spectrum - (F32)(spectrum_index_1); // distance between the two indexes (0-1)
-
- new_color = lerp(*spectrum_color[spectrum_index_1], *spectrum_color[spectrum_index_2], fractBetween);
- new_color.normalize();
- new_color *= 0.28f; // Tone it down
+ new_color = lerp(*spectrum_color[spectrum_index_1], *spectrum_color[spectrum_index_2], fractBetween);
+ new_color.normalize();
+ new_color *= 0.28f; // Tone it down
+ }
+#endif
+ else
+ {
+ new_color = LLColor4::grey4;
change_msg = " over limit color ";
}
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 79f31ba5b5..74ef589ca4 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -91,6 +91,7 @@ class LLVOAvatar :
public:
friend class LLVOAvatarSelf;
+ friend class LLAvatarCheckImpostorMode;
/********************************************************************************
** **
@@ -131,6 +132,7 @@ protected:
public:
/*virtual*/ void updateGL();
/*virtual*/ LLVOAvatar* asAvatar();
+
virtual U32 processUpdateMessage(LLMessageSystem *mesgsys,
void **user_data,
U32 block_num,
@@ -252,6 +254,11 @@ public:
virtual bool isControlAvatar() const { return mIsControlAvatar; } // True if this avatar is a control av (no associated user)
virtual bool isUIAvatar() const { return mIsUIAvatar; } // True if this avatar is a supplemental av used in some UI views (no associated user)
+ // If this is an attachment, return the avatar it is attached to. Otherwise NULL.
+ virtual const LLVOAvatar *getAttachedAvatar() const { return NULL; }
+ virtual LLVOAvatar *getAttachedAvatar() { return NULL; }
+
+
private: //aligned members
LL_ALIGN_16(LLVector4a mImpostorExtents[2]);
@@ -262,7 +269,8 @@ public:
void updateAppearanceMessageDebugText();
void updateAnimationDebugText();
virtual void updateDebugText();
- virtual BOOL updateCharacter(LLAgent &agent);
+ virtual bool computeNeedsUpdate();
+ virtual bool updateCharacter(LLAgent &agent);
void updateFootstepSounds();
void computeUpdatePeriod();
void updateOrientation(LLAgent &agent, F32 speed, F32 delta_time);
@@ -314,12 +322,12 @@ public:
public:
static S32 sRenderName;
static BOOL sRenderGroupTitles;
- static const U32 IMPOSTORS_OFF; /* Must equal the maximum allowed the RenderAvatarMaxNonImpostors
- * slider in panel_preferences_graphics1.xml */
- static U32 sMaxNonImpostors; //(affected by control "RenderAvatarMaxNonImpostors")
- static F32 sRenderDistance; //distance at which avatars will render.
+ static const U32 NON_IMPOSTORS_MAX_SLIDER; /* Must equal the maximum allowed the RenderAvatarMaxNonImpostors
+ * slider in panel_preferences_graphics1.xml */
+ static U32 sMaxNonImpostors; // affected by control "RenderAvatarMaxNonImpostors"
+ static bool sLimitNonImpostors; // use impostors for far away avatars
+ static F32 sRenderDistance; // distance at which avatars will render.
static BOOL sShowAnimationDebug; // show animation debug info
- static bool sUseImpostors; //use impostors for far away avatars
static BOOL sShowFootPlane; // show foot collision plane reported by server
static BOOL sShowCollisionVolumes; // show skeletal collision volumes
static BOOL sVisibleInFirstPerson;
@@ -407,6 +415,7 @@ public:
void initAttachmentPoints(bool ignore_hud_joints = false);
/*virtual*/ void buildCharacter();
void resetVisualParams();
+ void applyDefaultParams();
void resetSkeleton(bool reset_animations);
LLVector3 mCurRootToHeadOffset;
@@ -427,9 +436,12 @@ public:
public:
U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0);
bool isVisuallyMuted();
- bool isInMuteList();
+ bool isInMuteList() const;
void forceUpdateVisualMuteSettings();
+ // Visual Mute Setting is an input. Does not necessarily determine
+ // what the avatar looks like, because it interacts with other
+ // settings like muting, complexity threshold. Should be private or protected.
enum VisualMuteSettings
{
AV_RENDER_NORMALLY = 0,
@@ -437,8 +449,36 @@ public:
AV_ALWAYS_RENDER = 2
};
void setVisualMuteSettings(VisualMuteSettings set);
+
+protected:
+ // If you think you need to access this outside LLVOAvatar, you probably want getOverallAppearance()
VisualMuteSettings getVisualMuteSettings() { return mVisuallyMuteSetting; };
+public:
+
+ // Overall Appearance is an output. Depending on whether the
+ // avatar is blocked/muted, whether it exceeds the complexity
+ // threshold, etc, avatar will want to be displayed in one of
+ // these ways. Rendering code that wants to know how to display an
+ // avatar should be looking at this value, NOT the visual mute
+ // settings
+ enum AvatarOverallAppearance
+ {
+ AOA_NORMAL,
+ AOA_JELLYDOLL,
+ AOA_INVISIBLE
+ };
+
+ AvatarOverallAppearance getOverallAppearance() const;
+ void setOverallAppearanceNormal();
+ void setOverallAppearanceJellyDoll();
+ void setOverallAppearanceInvisible();
+
+ void updateOverallAppearance();
+ void updateOverallAppearanceAnimations();
+
+ std::set<LLUUID> mJellyAnims;
+
U32 renderRigid();
U32 renderSkinned();
F32 getLastSkinTime() { return mLastSkinTime; }
@@ -451,7 +491,8 @@ public:
static void restoreGL();
S32 mSpecialRenderMode; // special lighting
- private:
+private:
+ AvatarOverallAppearance mOverallAppearance;
F32 mAttachmentSurfaceArea; //estimated surface area of attachments
U32 mAttachmentVisibleTriangleCount;
F32 mAttachmentEstTriangleCount;
@@ -468,8 +509,8 @@ public:
mutable bool mVisualComplexityStale;
U32 mReportedVisualComplexity; // from other viewers through the simulator
- bool mCachedInMuteList;
- F64 mCachedMuteListUpdateTime;
+ mutable bool mCachedInMuteList;
+ mutable F64 mCachedMuteListUpdateTime;
VisualMuteSettings mVisuallyMuteSetting; // Always or never visually mute this AV
@@ -520,7 +561,7 @@ private:
//--------------------------------------------------------------------
public:
virtual BOOL isImpostor();
- BOOL shouldImpostor(const U32 rank_factor = 1) const;
+ BOOL shouldImpostor(const F32 rank_factor = 1.0);
BOOL needsImpostorUpdate() const;
const LLVector3& getImpostorOffset() const;
const LLVector2& getImpostorDim() const;
@@ -531,6 +572,7 @@ public:
static void updateImpostors();
LLRenderTarget mImpostor;
BOOL mNeedsImpostorUpdate;
+ S32 mLastImpostorUpdateReason;
F32SecondsImplicit mLastImpostorUpdateFrameTime;
const LLVector3* getLastAnimExtents() const { return mLastAnimExtents; }
void setNeedsExtentUpdate(bool val) { mNeedsExtentUpdate = val; }
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 58109b838e..458d8ced65 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -668,7 +668,7 @@ LLVOAvatarSelf::~LLVOAvatarSelf()
*********************************************************************************/
// virtual
-BOOL LLVOAvatarSelf::updateCharacter(LLAgent &agent)
+bool LLVOAvatarSelf::updateCharacter(LLAgent &agent)
{
// update screen joint size
if (mScreenp)
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index b0fdae9bf0..279dbd61a6 100644
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -116,7 +116,7 @@ public:
// Updates
//--------------------------------------------------------------------
public:
- /*virtual*/ BOOL updateCharacter(LLAgent &agent);
+ /*virtual*/ bool updateCharacter(LLAgent &agent);
/*virtual*/ void idleUpdateTractorBeam();
bool checkStuckAppearance();
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 15738c618c..7ba7e545f4 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -3083,9 +3083,10 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
if (vobj) // this test may not be needed, see above
{
LLVOAvatar* av = vobj->asAvatar();
- if (av && (av->isImpostor()
- || av->isInMuteList()
- || (LLVOAvatar::AV_DO_NOT_RENDER == av->getVisualMuteSettings() && !av->needsImpostorUpdate()) ))
+ if (av &&
+ ((!sImpostorRender && av->isImpostor()) //ignore impostor flag during impostor pass
+ || av->isInMuteList()
+ || (LLVOAvatar::AOA_JELLYDOLL == av->getOverallAppearance() && !av->needsImpostorUpdate()) ))
{
return;
}
@@ -10953,7 +10954,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
{
LL_RECORD_BLOCK_TIME(FTM_IMPOSTOR_MARK_VISIBLE);
markVisible(avatar->mDrawable, *viewer_camera);
- LLVOAvatar::sUseImpostors = false; // @TODO ???
LLVOAvatar::attachment_map_t::iterator iter;
for (iter = avatar->mAttachmentPoints.begin();
@@ -11193,7 +11193,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
avatar->setImpostorDim(tdim);
- LLVOAvatar::sUseImpostors = (0 != LLVOAvatar::sMaxNonImpostors);
sUseOcclusion = occlusion;
sReflectionRender = false;
sImpostorRender = false;