summaryrefslogtreecommitdiff
path: root/indra/newview/llvoavatar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llvoavatar.cpp')
-rwxr-xr-xindra/newview/llvoavatar.cpp438
1 files changed, 244 insertions, 194 deletions
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 6e0d77b10a..c3cc5a5fae 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -114,8 +114,6 @@ extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG;
const F32 MAX_HOVER_Z = 2.0;
const F32 MIN_HOVER_Z = -2.0;
-// #define OUTPUT_BREAST_DATA
-
using namespace LLAvatarAppearanceDefines;
//-----------------------------------------------------------------------------
@@ -182,6 +180,8 @@ const F32 NAMETAG_UPDATE_THRESHOLD = 0.3f;
const F32 NAMETAG_VERTICAL_SCREEN_OFFSET = 25.f;
const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f;
+const S32 LLVOAvatar::VISUAL_COMPLEXITY_UNKNOWN = 0;
+
enum ERenderName
{
RENDER_NAME_NEVER,
@@ -618,7 +618,7 @@ private:
//-----------------------------------------------------------------------------
LLAvatarAppearanceDictionary *LLVOAvatar::sAvatarDictionary = NULL;
S32 LLVOAvatar::sFreezeCounter = 0;
-U32 LLVOAvatar::sMaxVisible = 12;
+U32 LLVOAvatar::sMaxNonImpostors = 12; // overridden based on graphics setting
F32 LLVOAvatar::sRenderDistance = 256.f;
S32 LLVOAvatar::sNumVisibleAvatars = 0;
S32 LLVOAvatar::sNumLODChangesThisFrame = 0;
@@ -645,7 +645,7 @@ BOOL LLVOAvatar::sShowFootPlane = FALSE;
BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE;
F32 LLVOAvatar::sLODFactor = 1.f;
F32 LLVOAvatar::sPhysicsLODFactor = 1.f;
-BOOL LLVOAvatar::sUseImpostors = FALSE;
+bool LLVOAvatar::sUseImpostors = false; // overwridden by RenderAvatarMaxNonImpostors
BOOL LLVOAvatar::sJointDebug = FALSE;
F32 LLVOAvatar::sUnbakedTime = 0.f;
F32 LLVOAvatar::sUnbakedUpdateTime = 0.f;
@@ -668,7 +668,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mSpecialRenderMode(0),
mAttachmentGeometryBytes(-1),
mAttachmentSurfaceArea(-1.f),
- mReportedVisualComplexity(-1),
+ mReportedVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN),
mTurning(FALSE),
mLastSkeletonSerialNum( 0 ),
mIsSitting(FALSE),
@@ -698,12 +698,14 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mNeedsSkin(FALSE),
mLastSkinTime(0.f),
mUpdatePeriod(1),
+ mVisualComplexityStale(true),
+ mVisuallyMuteSetting(VISUAL_MUTE_NOT_SET),
+ mMutedAVColor(calcMutedAVColor(getID())),
mFirstFullyVisible(TRUE),
mFullyLoaded(FALSE),
mPreviousFullyLoaded(FALSE),
mFullyLoadedInitialized(FALSE),
- mVisualComplexity(0),
- mVisualComplexityStale(TRUE),
+ mVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN),
mLoadedCallbacksPaused(FALSE),
mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar", false)),
mLastRezzedStatus(-1),
@@ -714,6 +716,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mCachedMuteListUpdateTime(0),
mCachedInMuteList(false)
{
+ LL_DEBUGS("AvatarRender") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL;
+
//VTResume(); // VTune
setHoverOffset(LLVector3(0.0, 0.0, 0.0));
@@ -721,8 +725,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
const BOOL needsSendToSim = false; // currently, this HUD effect doesn't need to pack and unpack data to do its job
mVoiceVisualizer = ( LLVoiceVisualizer *)LLHUDManager::getInstance()->createViewerEffect( LLHUDObject::LL_HUD_EFFECT_VOICE_VISUALIZER, needsSendToSim );
- LL_DEBUGS("Avatar") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL;
-
mPelvisp = NULL;
mDirtyMesh = 2; // Dirty geometry, need to regenerate.
@@ -773,15 +775,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
if(LLSceneMonitor::getInstance()->isEnabled())
{
- LLSceneMonitor::getInstance()->freezeAvatar((LLCharacter*)this);
+ LLSceneMonitor::getInstance()->freezeAvatar((LLCharacter*)this);
}
-
- mCachedVisualMute = !isSelf();
- mCachedVisualMuteUpdateTime = LLFrameTimer::getTotalSeconds() + 5.0;
- mVisuallyMuteSetting = VISUAL_MUTE_NOT_SET;
-
- F32 color_value = (F32) (getID().mData[0]);
- mMutedAVColor = calcMutedAVColor(color_value, 0, 256);
}
std::string LLVOAvatar::avString() const
@@ -2150,7 +2145,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
}
idleUpdateNameTag( root_pos_last );
- idleUpdateRenderCost();
+ idleUpdateRenderComplexity();
}
void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
@@ -2490,19 +2485,22 @@ void LLVOAvatar::idleUpdateLoadingEffect()
// update visibility when avatar is partially loaded
if (updateIsFullyLoaded()) // changed?
{
- if (isFullyLoaded() && mFirstFullyVisible && isSelf())
- {
- LL_INFOS("Avatar") << avString() << "self isFullyLoaded, mFirstFullyVisible" << LL_ENDL;
- mFirstFullyVisible = FALSE;
- LLAppearanceMgr::instance().onFirstFullyVisible();
- }
- if (isFullyLoaded() && mFirstFullyVisible && !isSelf())
- {
- LL_INFOS("Avatar") << avString() << "other isFullyLoaded, mFirstFullyVisible" << LL_ENDL;
- mFirstFullyVisible = FALSE;
- }
if (isFullyLoaded())
{
+ if (mFirstFullyVisible)
+ {
+ mFirstFullyVisible = FALSE;
+ if (isSelf())
+ {
+ LL_INFOS("Avatar") << avString() << "self isFullyLoaded, mFirstFullyVisible" << LL_ENDL;
+ LLAppearanceMgr::instance().onFirstFullyVisible();
+ }
+ else
+ {
+ LL_INFOS("Avatar") << avString() << "other isFullyLoaded, mFirstFullyVisible" << LL_ENDL;
+ }
+ }
+
deleteParticleSource();
updateLOD();
}
@@ -3081,90 +3079,9 @@ void LLVOAvatar::slamPosition()
mRoot->updateWorldMatrixChildren();
}
-bool LLVOAvatar::isVisuallyMuted()
+bool LLVOAvatar::isVisuallyMuted() const
{
- bool muted = false;
-
- if (!isSelf())
- {
- static LLCachedControl<U32> render_auto_mute_functions(gSavedSettings, "RenderAutoMuteFunctions", 0);
- if (render_auto_mute_functions) // Hacky debug switch for developing feature
- {
- // Priority order (highest priority first)
- // * own avatar is never visually muted
- // * if on the "always draw normally" list, draw them normally
- // * if on the "always visually mute" list, mute them
- // * draw them normally if they meet the following criteria:
- // - within the closest N avatars OR on friends list OR in an IM chat
- // - AND aren't over the thresholds
- // * otherwise visually mute all other avatars
-
- static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit", 0);
- static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 0.0);
- static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderWeightLimit", 0);
-
- if (mVisuallyMuteSetting == ALWAYS_VISUAL_MUTE)
- { // Always want to see this AV as an impostor
- muted = true;
- }
- else if (mVisuallyMuteSetting == NEVER_VISUAL_MUTE)
- { // Never show as impostor
- muted = false;
- }
- else
- {
- F64 now = LLFrameTimer::getTotalSeconds();
-
- if (now < mCachedVisualMuteUpdateTime)
- { // Use cached mute value
- muted = mCachedVisualMute;
- }
- else
- { // Determine if visually muted or not
-
- U32 max_cost = (U32) (max_render_cost*(LLVOAvatar::sLODFactor+0.5));
-
- muted = (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) ||
- (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) ||
- (mVisualComplexity > max_cost && max_render_cost > 0);
-
- // Could be part of the grand || collection above, but yanked out to make the logic visible
- if (!muted)
- {
- if (sMaxVisible > 0)
- { // They are above the visibilty rank - mute them
- muted = (mVisibilityRank > sMaxVisible);
- }
-
- // Always draw friends or those in IMs. Needs UI?
- if ((render_auto_mute_functions & 0x02) &&
- (muted || sMaxVisible == 0)) // Don't mute friends or IMs
- {
- muted = !(LLAvatarTracker::instance().isBuddy(getID()));
- if (muted)
- { // Not a friend, so they are muted ... are they in an IM?
- LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL,getID());
- muted = !gIMMgr->hasSession(session_id);
- }
- }
- }
-
- // Save visual mute state and set interval for updating
- const F64 SECONDS_BETWEEN_RENDER_AUTO_MUTE_UPDATES = 1.5;
- mCachedVisualMuteUpdateTime = now + SECONDS_BETWEEN_RENDER_AUTO_MUTE_UPDATES;
- mCachedVisualMute = muted;
- }
- }
- }
- }
-
- return muted || isInMuteList();
-}
-
-void LLVOAvatar::forceUpdateVisualMuteSettings()
-{
- // Set the cache time so it's updated ASAP
- mCachedVisualMuteUpdateTime = LLFrameTimer::getTotalSeconds() - 1.0;
+ return ( mVisuallyMuteSetting == ALWAYS_VISUAL_MUTE );
}
bool LLVOAvatar::isInMuteList()
@@ -3185,7 +3102,6 @@ bool LLVOAvatar::isInMuteList()
}
return muted;
}
-
void LLVOAvatar::updateDebugText()
{
// clear debug text
@@ -3329,18 +3245,18 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
{ // visually muted avatars update at 16 hz
mUpdatePeriod = 16;
}
- else if (mVisibilityRank <= LLVOAvatar::sMaxVisible ||
- mDrawable->mDistanceWRTCamera < 1.f + mag)
- { //first 25% of max visible avatars are not impostored
- //also, don't impostor avatars whose bounding box may be penetrating the
- //impostor camera near clip plane
+ else if ( ! isImpostor()
+ || mDrawable->mDistanceWRTCamera < 1.f + mag)
+ { // first 25% of max visible avatars are not impostored
+ // also, don't impostor avatars whose bounding box may be penetrating the
+ // impostor camera near clip plane
mUpdatePeriod = 1;
}
- else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 4)
+ else if ( isImpostor(4) )
{ //background avatars are REALLY slow updating impostors
mUpdatePeriod = 16;
}
- else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 3)
+ else if ( isImpostor(3) )
{ //back 25% of max visible avatars are slow updating impostors
mUpdatePeriod = 8;
}
@@ -3924,6 +3840,10 @@ void LLVOAvatar::updateVisibility()
}
}
+ if ( visible != mVisible )
+ {
+ LL_DEBUGS("AvatarRender") << "visible was " << mVisible << " now " << visible << LL_ENDL;
+ }
mVisible = visible;
}
@@ -4196,8 +4116,8 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)
}
// Can't test for baked hair being defined, since that won't always be the case (not all viewers send baked hair)
// TODO: 1.25 will be able to switch this logic back to calling isTextureVisible();
- if ( ( getImage(TEX_HAIR_BAKED, 0) &&
- getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE ) || LLDrawPoolAlpha::sShowDebugAlpha)
+ if ( (getImage(TEX_HAIR_BAKED, 0) && getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE)
+ || LLDrawPoolAlpha::sShowDebugAlpha)
{
LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR);
if (hair_mesh)
@@ -5815,7 +5735,7 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o
return 0;
}
- mVisualComplexityStale = TRUE;
+ updateVisualComplexity();
if (viewer_object->isSelected())
{
@@ -5964,7 +5884,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
if (attachment->isObjectAttached(viewer_object))
{
- mVisualComplexityStale = TRUE;
+ updateVisualComplexity();
cleanupAttachedMesh( viewer_object );
attachment->removeObject(viewer_object);
@@ -6255,26 +6175,14 @@ BOOL LLVOAvatar::isVisible() const
}
// Determine if we have enough avatar data to render
-BOOL LLVOAvatar::getIsCloud() const
+bool LLVOAvatar::getIsCloud() const
{
- // Do we have a shape?
- if ((const_cast<LLVOAvatar*>(this))->visualParamWeightsAreDefault())
- {
- return TRUE;
- }
-
- if (!isTextureDefined(TEX_LOWER_BAKED) ||
- !isTextureDefined(TEX_UPPER_BAKED) ||
- !isTextureDefined(TEX_HEAD_BAKED))
- {
- return TRUE;
- }
-
- if (isTooComplex())
- {
- return TRUE;
- }
- return FALSE;
+ return ( ((const_cast<LLVOAvatar*>(this))->visualParamWeightsAreDefault())// Do we have a shape?
+ || ( !isTextureDefined(TEX_LOWER_BAKED)
+ || !isTextureDefined(TEX_UPPER_BAKED)
+ || !isTextureDefined(TEX_HEAD_BAKED)
+ )
+ );
}
void LLVOAvatar::updateRezzedStatusTimers()
@@ -6452,7 +6360,7 @@ void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapse
// returns true if the value has changed.
BOOL LLVOAvatar::updateIsFullyLoaded()
{
- const BOOL loading = getIsCloud();
+ const bool loading = getIsCloud();
updateRezzedStatusTimers();
updateRuthTimer(loading);
return processFullyLoadedChange(loading);
@@ -6524,14 +6432,30 @@ BOOL LLVOAvatar::isFullyLoaded() const
bool LLVOAvatar::isTooComplex() const
{
- if (gSavedSettings.getS32("RenderAvatarComplexityLimit") > 0 && mVisualComplexity >= gSavedSettings.getS32("RenderAvatarComplexityLimit"))
- {
- return true;
- }
+ static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0);
+ static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit", 0);
+ static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 0.0);
+ bool too_complex;
- return false;
+ if (isSelf())
+ {
+ too_complex = false;
+ }
+ else
+ {
+ too_complex = ( (max_render_cost > 0 && mVisualComplexity > max_render_cost)
+ || (max_attachment_bytes > 0 && mAttachmentGeometryBytes > max_attachment_bytes)
+ || (max_attachment_area > 0.f && mAttachmentSurfaceArea > max_attachment_area)
+ );
+ }
+
+ return too_complex;
}
+bool LLVOAvatar::isImpostor(const U32 rank_factor) const
+{
+ return (!isSelf() && sMaxNonImpostors != 0 && mVisibilityRank > (sMaxNonImpostors * rank_factor));
+}
//-----------------------------------------------------------------------------
// findMotion()
@@ -8136,20 +8060,29 @@ void LLVOAvatar::updateImpostors()
iter != LLCharacter::sInstances.end(); ++iter)
{
LLVOAvatar* avatar = (LLVOAvatar*) *iter;
- if (!avatar->isDead() && avatar->needsImpostorUpdate() && avatar->isVisible() && avatar->isImpostor())
+
+ if (!avatar->isDead() && avatar->isVisible()
+ && ( (avatar->isImpostor() && avatar->needsImpostorUpdate())
+ || avatar->isTooComplex()
+ ))
{
gPipeline.generateImpostor(avatar);
}
+ else
+ {
+ LL_DEBUGS_ONCE("AvatarRender") << "Avatar " << avatar->getID()
+ << (avatar->isDead() ? " _is_ " : " is not ") << "dead"
+ << (avatar->needsImpostorUpdate() ? " needs " : " _does_not_need_ ") << "impostor update"
+ << (avatar->isVisible() ? " is " : " _is_not_ ") << "visible"
+ << (avatar->isImpostor() ? " is " : " is not ") << "impostor"
+ << (avatar->isTooComplex() ? " is " : " is not ") << "too complex"
+ << LL_ENDL;
+ }
}
LLCharacter::sAllowInstancesChange = TRUE ;
}
-BOOL LLVOAvatar::isImpostor()
-{
- return (sUseImpostors && (isVisuallyMuted() || (mUpdatePeriod >= IMPOSTOR_PERIOD))) || isInMuteList() ? TRUE : FALSE;
-}
-
BOOL LLVOAvatar::needsImpostorUpdate() const
{
@@ -8190,68 +8123,172 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d
angle.mV[2] = da;
}
+// static
+const U32 LLVOAvatar::IMPOSTORS_OFF = 66; /* Must equal the maximum allowed the RenderAvatarMaxNonImpostors
+ * slider in panel_preferences_graphics1.xml */
-void LLVOAvatar::idleUpdateRenderCost()
+// static
+void LLVOAvatar::updateImpostorRendering(U32 newMaxNonImpostorsValue)
{
- static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderWeightLimit", 0);
- static const U32 ARC_LIMIT = 20000;
-
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES))
- { //set debug text to attachment geometry bytes here so render cost will override
- setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea));
+ U32 oldmax = sMaxNonImpostors;
+ bool oldflg = sUseImpostors;
+
+ if (IMPOSTORS_OFF <= newMaxNonImpostorsValue)
+ {
+ sMaxNonImpostors = 0;
}
-
- if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME) && max_render_cost == 0)
+ else
{
- return;
+ 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 )
+ {
+ LL_DEBUGS("AvatarRender")
+ << "was " << (oldflg ? "use" : "don't use" ) << " impostors (max " << oldmax << "); "
+ << "now " << (sUseImpostors ? "use" : "don't use" ) << " impostors (max " << sMaxNonImpostors << "); "
+ << LL_ENDL;
+ }
+}
- calculateUpdateRenderCost(); // Update mVisualComplexity if needed
-
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
+
+void LLVOAvatar::idleUpdateRenderComplexity()
+{
+ // Render Complexity
+ calculateUpdateRenderComplexity(); // Update mVisualComplexity if needed
+
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_DRAW_INFO))
{
- std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus());
- setDebugText(llformat("%s %d", viz_string.c_str(), mVisualComplexity));
- F32 green = 1.f-llclamp(((F32) mVisualComplexity-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
- F32 red = llmin((F32) mVisualComplexity/(F32)ARC_LIMIT, 1.f);
- mText->setColor(LLColor4(red,green,0,1));
+ std::string info_line;
+ F32 red_level;
+ F32 green_level;
+ LLColor4 info_color;
+ LLFontGL::StyleFlags info_style;
+
+ if ( !mText )
+ {
+ initDebugTextHud();
+ mText->setFadeDistance(20.0, 5.0); // limit clutter in large crowds
+ }
+ else
+ {
+ mText->clearString(); // clear debug text
+ }
+
+ /*
+ * NOTE: the logic for whether or not each of the values below
+ * controls muting MUST match that in the isVisuallyMuted and isTooComplex methods.
+ */
+
+ static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAvatarMaxComplexity", 0);
+ info_line = llformat("%d Complexity", mVisualComplexity);
+
+ if (max_render_cost != 0) // zero means don't care, so don't bother coloring based on this
+ {
+ green_level = 1.f-llclamp(((F32) mVisualComplexity-(F32)max_render_cost)/(F32)max_render_cost, 0.f, 1.f);
+ red_level = llmin((F32) mVisualComplexity/(F32)max_render_cost, 1.f);
+ info_color.set(red_level, green_level, 0.0, 1.0);
+ info_style = ( mVisualComplexity > max_render_cost
+ ? LLFontGL::BOLD : LLFontGL::NORMAL );
+ }
+ else
+ {
+ info_color.set(LLColor4::grey);
+ info_style = LLFontGL::NORMAL;
+ }
+ mText->addLine(info_line, info_color, info_style);
+
+ // Visual rank
+ info_line = llformat("%d rank", mVisibilityRank);
+ // Use grey for imposters, white for normal rendering or no impostors
+ info_color.set(isImpostor() ? LLColor4::grey : LLColor4::white);
+ info_style = LLFontGL::NORMAL;
+ mText->addLine(info_line, info_color, info_style);
+
+ // Attachment Surface Area
+ static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 0);
+ info_line = llformat("%.2f m^2", mAttachmentSurfaceArea);
+
+ if (max_attachment_area != 0) // zero means don't care, so don't bother coloring based on this
+ {
+ green_level = 1.f-llclamp((mAttachmentSurfaceArea-max_attachment_area)/max_attachment_area, 0.f, 1.f);
+ red_level = llmin(mAttachmentSurfaceArea/max_attachment_area, 1.f);
+ info_color.set(red_level, green_level, 0.0, 1.0);
+ info_style = ( mAttachmentSurfaceArea > max_attachment_area
+ ? LLFontGL::BOLD : LLFontGL::NORMAL );
+
+ }
+ else
+ {
+ info_color.set(LLColor4::grey);
+ info_style = LLFontGL::NORMAL;
+ }
+ mText->addLine(info_line, info_color, info_style);
+
+ // Attachment byte limit
+ static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit", 0);
+ info_line = llformat("%.1f KB", mAttachmentGeometryBytes/1024.f);
+ if (max_attachment_bytes != 0) // zero means don't care, so don't bother coloring based on this
+ {
+ green_level = 1.f-llclamp(((F32) mAttachmentGeometryBytes-(F32)max_attachment_bytes)/(F32)max_attachment_bytes, 0.f, 1.f);
+ red_level = llmin((F32) mAttachmentGeometryBytes/(F32)max_attachment_bytes, 1.f);
+ info_color.set(red_level, green_level, 0.0, 1.0);
+ info_style = ( mAttachmentGeometryBytes > max_attachment_bytes
+ ? LLFontGL::BOLD : LLFontGL::NORMAL );
+ }
+ else
+ {
+ info_color.set(LLColor4::grey);
+ info_style = LLFontGL::NORMAL;
+ }
+ mText->addLine(info_line, info_color, info_style);
+
+ updateText(); // corrects position
}
}
+void LLVOAvatar::updateVisualComplexity()
+{
+ LL_DEBUGS("AvatarRender") << "avatar " << this->getID() << " appearance changed" << LL_ENDL;
+ // Set the cache time to in the past so it's updated ASAP
+ mVisualComplexityStale = true;
+}
+
// Calculations for mVisualComplexity value
-void LLVOAvatar::calculateUpdateRenderCost()
+void LLVOAvatar::calculateUpdateRenderComplexity()
{
- static const U32 ARC_BODY_PART_COST = 200;
+ static const U32 COMPLEXITY_BODY_PART_COST = 200;
// Diagnostic list of all textures on our avatar
static std::set<LLUUID> all_textures;
if (mVisualComplexityStale)
{
- mVisualComplexityStale = FALSE;
- U32 cost = 0;
+ U32 cost = VISUAL_COMPLEXITY_UNKNOWN;
LLVOVolume::texture_cost_t textures;
for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
{
- const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
+ const LLAvatarAppearanceDictionary::BakedEntry *baked_dict
+ = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
ETextureIndex tex_index = baked_dict->mTextureIndex;
if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))
{
if (isTextureVisible(tex_index))
{
- cost +=ARC_BODY_PART_COST;
+ cost +=COMPLEXITY_BODY_PART_COST;
}
}
}
- for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
+ for (attachment_map_t::const_iterator attachment_point = mAttachmentPoints.begin();
+ attachment_point != mAttachmentPoints.end();
+ ++attachment_point)
{
- LLViewerJointAttachment* attachment = iter->second;
+ LLViewerJointAttachment* attachment = attachment_point->second;
for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
attachment_iter != attachment->mAttachedObjects.end();
++attachment_iter)
@@ -8281,10 +8318,12 @@ void LLVOAvatar::calculateUpdateRenderCost()
}
}
- for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter)
+ for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin();
+ volume_texture != textures.end();
+ ++volume_texture)
{
// add the cost of each individual texture in the linkset
- cost += iter->second;
+ cost += volume_texture->second;
}
}
}
@@ -8331,17 +8370,31 @@ void LLVOAvatar::calculateUpdateRenderCost()
}
}
+ if ( cost != mVisualComplexity )
+ {
+ LL_DEBUGS("AvatarRender") << "Avatar "<< getID()
+ << " complexity updated was " << mVisualComplexity << " now " << cost
+ << " reported " << mReportedVisualComplexity
+ << LL_ENDL;
+ }
+ {
+ LL_DEBUGS("AvatarRender") << "Avatar "<< getID()
+ << " complexity updated no change " << mVisualComplexity
+ << " reported " << mReportedVisualComplexity
+ << LL_ENDL;
+ }
mVisualComplexity = cost;
+ mVisualComplexityStale = false;
}
}
// static
-LLColor4 LLVOAvatar::calcMutedAVColor(F32 value, S32 range_low, S32 range_high)
+LLColor4 LLVOAvatar::calcMutedAVColor(const LLUUID av_id)
{
- F32 clamped_value = llmin(value, (F32) range_high);
- clamped_value = llmax(value, (F32) range_low);
- F32 spectrum = (clamped_value / range_high); // spectrum is between 0 and 1.f
+ // 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
// 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
@@ -8355,12 +8408,9 @@ LLColor4 LLVOAvatar::calcMutedAVColor(F32 value, S32 range_low, S32 range_high)
LLColor4 new_color = lerp(*spectrum_color[spectrum_index_1], *spectrum_color[spectrum_index_2], fractBetween);
new_color.normalize();
- new_color *= 0.7f; // Tone it down a bit
+ new_color *= 0.5f; // Tone it down
- //LL_INFOS() << "From value " << std::setprecision(3) << value << " returning color " << new_color
- // << " using indexes " << spectrum_index_1 << ", " << spectrum_index_2
- // << " and fractBetween " << fractBetween
- // << LL_ENDL;
+ LL_DEBUGS("AvatarRender") << "avatar "<< av_id << " muted color " << std::setprecision(3) << new_color << LL_ENDL;
return new_color;
}