Prototype code for "simple imposter" mode rendering of avatars.

Reviewed by Kelly
meow-7.2.2
simon 2013-03-20 15:25:14 -07:00
parent 5dbb0a31da
commit 8e54ae95d1
9 changed files with 438 additions and 125 deletions

View File

@ -9370,7 +9370,7 @@
<key>RenderAutoMuteRenderCostLimit</key>
<map>
<key>Comment</key>
<string>Maximum render cost before an avatar is automatically visually muted (0 for no limit).</string>
<string>Maximum render weight before an avatar is automatically visually muted (0 to not use this limit).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -9381,7 +9381,7 @@
<key>RenderAutoMuteSurfaceAreaLimit</key>
<map>
<key>Comment</key>
<string>Maximum surface area of attachments before an avatar is automatically visually muted (0 for no limit).</string>
<string>Maximum surface area of attachments before an avatar is automatically visually muted (0 to not use this limit).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -9389,6 +9389,28 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderAutoMuteEnabled</key>
<map>
<key>Comment</key>
<string>Apply visual muting to high cost, non-friends, not in IM, or somewhat distant avatars</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderAutoMuteVisibilityRank</key>
<map>
<key>Comment</key>
<string>Number of avatars to show normally for visual muting mode.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderAutoHideSurfaceAreaLimit</key>
<map>

View File

@ -1163,87 +1163,84 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
else if (pass >= 3 && pass <= 9)
{ //render rigged attachments
if (!avatarp->isVisuallyMuted())
if (!avatarp->isVisuallyMuted()) // These details are skipped for visually muted (plain imposter) avatars
{
if (pass == 3)
{
if (is_deferred_render)
{
renderDeferredRiggedSimple(avatarp);
}
else
{
renderRiggedSimple(avatarp);
}
}
if (pass == 3) // To do - use switch statement
{
if (is_deferred_render)
{
renderDeferredRiggedSimple(avatarp);
}
else
{
renderRiggedSimple(avatarp);
}
}
else if (pass == 4)
{
if (is_deferred_render)
{
renderDeferredRiggedBump(avatarp);
}
else
{
renderRiggedFullbright(avatarp);
}
}
{
if (is_deferred_render)
{
renderDeferredRiggedBump(avatarp);
}
else
{
renderRiggedFullbright(avatarp);
}
}
else if (pass == 5)
{
renderRiggedShinySimple(avatarp);
}
{
renderRiggedShinySimple(avatarp);
}
else if (pass == 6)
{
renderRiggedFullbrightShiny(avatarp);
}
else if (pass >= 7 && pass < 9)
{
if (pass == 7)
{
renderRiggedAlpha(avatarp);
}
else if (pass == 8)
{
renderRiggedFullbrightAlpha(avatarp);
}
}
{
renderRiggedFullbrightShiny(avatarp);
}
else if (pass == 7)
{
renderRiggedAlpha(avatarp);
}
else if (pass == 8)
{
renderRiggedFullbrightAlpha(avatarp);
}
else if (pass == 9)
{
renderRiggedGlow(avatarp);
}
{
renderRiggedGlow(avatarp);
}
}
}
else
{
if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
{
LLMatrix4 rot_mat;
LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat);
LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
rot_mat *= cfr;
if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
{
LLMatrix4 rot_mat;
LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat);
LLMatrix4 cfr(OGL_TO_CFR_ROTATION);
rot_mat *= cfr;
LLVector4 wind;
wind.setVec(avatarp->mWindVec);
wind.mV[VW] = 0;
wind = wind * rot_mat;
wind.mV[VW] = avatarp->mWindVec.mV[VW];
LLVector4 wind;
wind.setVec(avatarp->mWindVec);
wind.mV[VW] = 0;
wind = wind * rot_mat;
wind.mV[VW] = avatarp->mWindVec.mV[VW];
sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV);
F32 phase = -1.f * (avatarp->mRipplePhase);
sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV);
F32 phase = -1.f * (avatarp->mRipplePhase);
F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f);
LLVector4 sin_params(freq, freq, freq, phase);
sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV);
F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f);
LLVector4 sin_params(freq, freq, freq, phase);
sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV);
LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f);
gravity = gravity * rot_mat;
sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV);
LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f);
gravity = gravity * rot_mat;
sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV);
}
if( !single_avatar || (avatarp == single_avatar) )
{
avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
}
}
if( !single_avatar || (avatarp == single_avatar) )
{
avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
}
}
}
void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)

View File

@ -2934,6 +2934,63 @@ bool enable_object_unmute()
}
}
// 0 = normal, 1 = always, 2 = never
class LLAvatarCheckImposterMode : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
if (!object) return false;
LLVOAvatar* avatar = find_avatar_from_object(object);
if (!avatar) return false;
U32 mode = userdata.asInteger();
switch (mode)
{
case 0:
return (avatar->getVisualMuteSettings() == LLVOAvatar::VISUAL_MUTE_NOT_SET);
case 1:
return (avatar->getVisualMuteSettings() == LLVOAvatar::ALWAYS_VISUAL_MUTE);
case 2:
return (avatar->getVisualMuteSettings() == LLVOAvatar::NEVER_VISUAL_MUTE);
default:
return false;
}
} // handleEvent()
};
// 0 = normal, 1 = always, 2 = never
class LLAvatarSetImposterMode : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
if (!object) return false;
LLVOAvatar* avatar = find_avatar_from_object(object);
if (!avatar) return false;
U32 mode = userdata.asInteger();
switch (mode)
{
case 0:
avatar->setVisualMuteSettings(LLVOAvatar::VISUAL_MUTE_NOT_SET);
return true;
case 1:
avatar->setVisualMuteSettings(LLVOAvatar::VISUAL_MUTE_NOT_SET);
return true;
case 2:
avatar->setVisualMuteSettings(LLVOAvatar::NEVER_VISUAL_MUTE);
return true;
default:
return false;
}
} // handleEvent()
};
class LLObjectMute : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@ -8644,6 +8701,8 @@ void initialize_menus()
view_listener_t::addMenu( new LLCheckPanelPeopleTab(), "SideTray.CheckPanelPeopleTab");
// Avatar pie menu
view_listener_t::addMenu(new LLAvatarCheckImposterMode(), "Avatar.CheckImposterMode");
view_listener_t::addMenu(new LLAvatarSetImposterMode(), "Avatar.SetImposterMode");
view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute");
view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend");
view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact");

View File

@ -62,6 +62,7 @@
#include "llhudmanager.h"
#include "llhudnametag.h"
#include "llhudtext.h" // for mText/mDebugText
#include "llimview.h"
#include "llinitparam.h"
#include "llkeyframefallmotion.h"
#include "llkeyframestandmotion.h"
@ -784,6 +785,13 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mLastPelvisToFoot = 0.0f;
mPelvisFixup = 0.0f;
mLastPelvisFixup = 0.0f;
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
@ -3435,24 +3443,82 @@ void LLVOAvatar::slamPosition()
mRoot.updateWorldMatrixChildren();
}
bool LLVOAvatar::isVisuallyMuted() const
bool LLVOAvatar::isVisuallyMuted()
{
bool ret = false;
bool muted = false;
// 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
if (!isSelf())
{
static LLCachedControl<bool> render_mute_enabled(gSavedSettings, "RenderAutoMuteEnabled");
static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit");
static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit");
static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit");
U32 max_cost = (U32) (max_render_cost*(LLVOAvatar::sLODFactor+0.5));
static LLCachedControl<U32> visibility_rank(gSavedSettings, "RenderAutoMuteVisibilityRank");
ret = LLMuteList::getInstance()->isMuted(getID()) ||
(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) ||
(mVisualComplexity > max_cost && max_render_cost > 0);
if (mVisuallyMuteSetting == ALWAYS_VISUAL_MUTE)
{ // Always want to see this AV as an imposter
muted = true;
}
else if (mVisuallyMuteSetting == NEVER_VISUAL_MUTE)
{ // Never show as imposter
muted = false;
}
else if (render_mute_enabled)
{
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 = LLMuteList::getInstance()->isMuted(getID()) ||
(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 (visibility_rank > 0)
{ // They are above the visibilty rank - mute them
muted = (mVisibilityRank > visibility_rank);
}
if (muted || // Don't mute friends or IMs
visibility_rank == 0)
{
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 ret;
return muted;
}
//------------------------------------------------------------------------
@ -3509,7 +3575,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
// the rest should only be done occasionally for far away avatars
//--------------------------------------------------------------------
if (visible && (!isSelf() || isVisuallyMuted()) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)
bool visually_muted = isVisuallyMuted();
if (visible && (!isSelf() || visually_muted) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)
{
const LLVector4a* ext = mDrawable->getSpatialExtents();
LLVector4a size;
@ -3518,8 +3585,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f);
if (isVisuallyMuted())
{ // muted avatars update at 16 hz
if (visually_muted)
{ // visually muted avatars update at 16 hz
mUpdatePeriod = 16;
}
else if (mVisibilityRank <= LLVOAvatar::sMaxVisible ||
@ -4295,23 +4362,23 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
BOOL first_pass = TRUE;
if (!LLDrawPoolAvatar::sSkipOpaque)
{
bool muted = isVisuallyMuted();
bool visually_muted = isVisuallyMuted();
if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
{
if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy || muted)
if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy || visually_muted)
{
num_indices += mMeshLOD[MESH_ID_HEAD]->render(mAdjustedPixelArea, TRUE, mIsDummy);
first_pass = FALSE;
}
}
if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy || muted)
if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy || visually_muted)
{
num_indices += mMeshLOD[MESH_ID_UPPER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);
first_pass = FALSE;
}
if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy || muted)
if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy || visually_muted)
{
num_indices += mMeshLOD[MESH_ID_LOWER_BODY]->render(mAdjustedPixelArea, first_pass, mIsDummy);
first_pass = FALSE;
@ -8396,7 +8463,7 @@ void LLVOAvatar::updateImpostors()
LLCharacter::sAllowInstancesChange = TRUE ;
}
BOOL LLVOAvatar::isImpostor() const
BOOL LLVOAvatar::isImpostor()
{
return sUseImpostors && (isVisuallyMuted() || (mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE;
}
@ -8441,15 +8508,13 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d
angle.mV[2] = da;
}
void LLVOAvatar::idleUpdateRenderCost()
{
static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit");
static const U32 ARC_BODY_PART_COST = 200;
static const U32 ARC_LIMIT = 20000;
static std::set<LLUUID> all_textures;
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));
@ -8460,6 +8525,69 @@ void LLVOAvatar::idleUpdateRenderCost()
return;
}
calculateUpdateRenderCost(); // Update mVisualComplexity if needed
doRenderCostNagging(max_render_cost); // Remind the user their AV is too complex
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
{
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));
}
}
// Remind the user about their expensive avatar
void LLVOAvatar::doRenderCostNagging(U32 max_render_cost)
{
if (isSelf())
{
static S32 sOldComplexity = 0;
static F64 sLastRenderCostNagTime = 0.0;
const F64 RENDER_NAG_INTERVAL = 60.0;
F64 now = LLFrameTimer::getTotalSeconds();
if (sLastRenderCostNagTime > 0.0 &&
(now - sLastRenderCostNagTime) > RENDER_NAG_INTERVAL &&
sOldComplexity != mVisualComplexity)
{
sOldComplexity = mVisualComplexity;
if (max_render_cost > 0)
{ //pop up notification that you have exceeded a render cost limit
if (mVisualComplexity > max_render_cost+max_render_cost/2)
{
LLNotificationsUtil::add("ExceededHighDetailRenderCost");
sLastRenderCostNagTime = now;
}
else if (mVisualComplexity > max_render_cost)
{
LLNotificationsUtil::add("ExceededMidDetailRenderCost");
sLastRenderCostNagTime = now;
}
else if (mVisualComplexity > max_render_cost/2)
{
LLNotificationsUtil::add("ExceededLowDetailRenderCost");
sLastRenderCostNagTime = now;
}
}
}
}
}
// Calculations for mVisualComplexity value
void LLVOAvatar::calculateUpdateRenderCost()
{
static const U32 ARC_BODY_PART_COST = 200;
// Diagnostic list of all textures on our avatar
static std::set<LLUUID> all_textures;
if (mVisualComplexityStale)
{
mVisualComplexityStale = FALSE;
@ -8526,8 +8654,6 @@ void LLVOAvatar::idleUpdateRenderCost()
}
// Diagnostic output to identify all avatar-related textures.
// Does not affect rendering cost calculation.
// Could be wrapped in a debug option if output becomes problematic.
@ -8568,34 +8694,37 @@ void LLVOAvatar::idleUpdateRenderCost()
}
}
if (isSelf() && max_render_cost > 0 && mVisualComplexity != cost)
{ //pop up notification that you have exceeded a render cost limit
if (cost > max_render_cost+max_render_cost/2)
{
LLNotificationsUtil::add("ExceededHighDetailRenderCost");
}
else if (cost > max_render_cost)
{
LLNotificationsUtil::add("ExceededMidDetailRenderCost");
}
else if (cost > max_render_cost/2)
{
LLNotificationsUtil::add("ExceededLowDetailRenderCost");
}
}
mVisualComplexity = cost;
}
}
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
{
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));
}
// static
LLColor4 LLVOAvatar::calcMutedAVColor(F32 value, S32 range_low, S32 range_high)
{
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
// 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;
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)
F32 fractBetween = spectrum - (F32)(spectrum_index_1); // distance between the two indexes (0-1)
LLColor4 new_color = lerp(*spectrum_color[spectrum_index_1], *spectrum_color[spectrum_index_2], fractBetween);
//new_color.normalize();
//llinfos << "From value " << std::setprecision(3) << value << " returning color " << new_color
// << " using indexes " << spectrum_index_1 << ", " << spectrum_index_2
// << " and fractBetween " << fractBetween
// << llendl;
return new_color;
}
// static

View File

@ -253,7 +253,14 @@ public:
static void invalidateNameTags();
void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font);
void idleUpdateRenderCost();
void doRenderCostNagging(U32 max_render_cost);
void calculateUpdateRenderCost();
void updateVisualComplexity() { mVisualComplexityStale = TRUE; }
S32 getVisualComplexity() { return mVisualComplexity; };
S32 getUpdatePeriod() { return mUpdatePeriod; };
const LLColor4 & getMutedAVColor() { return mMutedAVColor; };
void idleUpdateBelowWater();
//--------------------------------------------------------------------
@ -304,11 +311,14 @@ public:
return mPhases;
}
static LLColor4 calcMutedAVColor(F32 value, S32 range_low, S32 range_high);
protected:
BOOL updateIsFullyLoaded();
BOOL processFullyLoadedChange(bool loading);
void updateRuthTimer(bool loading);
F32 calcMorphAmount();
private:
BOOL mFirstFullyVisible;
BOOL mFullyLoaded;
@ -317,6 +327,7 @@ private:
S32 mFullyLoadedFrameCounter;
S32 mVisualComplexity;
BOOL mVisualComplexityStale;
LLColor4 mMutedAVColor;
LLFrameTimer mFullyLoadedTimer;
LLFrameTimer mRuthTimer;
@ -437,7 +448,16 @@ private:
public:
U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0);
bool isVisuallyMuted() const;
bool isVisuallyMuted();
enum VisualMuteSettings
{
VISUAL_MUTE_NOT_SET = 0,
ALWAYS_VISUAL_MUTE = 1,
NEVER_VISUAL_MUTE = 2
};
void setVisualMuteSettings(VisualMuteSettings set) { mVisuallyMuteSetting = set; };
VisualMuteSettings getVisualMuteSettings() { return mVisuallyMuteSetting; };
U32 renderRigid();
U32 renderSkinned(EAvatarRenderPass pass);
@ -461,6 +481,11 @@ private:
S32 mUpdatePeriod;
S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer.
bool mCachedVisualMute; // cached return value for isVisuallyMuted()
F64 mCachedVisualMuteUpdateTime; // Time to update mCachedVisualMute
VisualMuteSettings mVisuallyMuteSetting; // Always or never visually mute this AV
//--------------------------------------------------------------------
// Morph masks
//--------------------------------------------------------------------
@ -493,7 +518,7 @@ private:
// Impostors
//--------------------------------------------------------------------
public:
BOOL isImpostor() const;
BOOL isImpostor();
BOOL needsImpostorUpdate() const;
const LLVector3& getImpostorOffset() const;
const LLVector2& getImpostorDim() const;

View File

@ -2862,7 +2862,7 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)
llassert(vobj); // trying to catch a bad assumption
if (vobj) // this test may not be needed, see above
{
const LLVOAvatar* av = vobj->asAvatar();
LLVOAvatar* av = vobj->asAvatar();
if (av && av->isImpostor())
{
return;
@ -10103,11 +10103,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
assertInitialized();
bool muted = avatar->isVisuallyMuted();
bool visually_muted = avatar->isVisuallyMuted();
pushRenderTypeMask();
if (muted)
if (visually_muted)
{
andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
}
@ -10251,7 +10251,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha;
if (muted)
if (visually_muted)
{ //disable alpha masking for muted avatars (get whole skin silhouette)
LLDrawPoolAvatar::sMinimumAlpha = 0.f;
}
@ -10282,7 +10282,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
LLGLDisable blend(GL_BLEND);
if (muted)
if (visually_muted)
{
gGL.setColorMask(true, true);
@ -10317,8 +10317,8 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
gGL.diffuseColor4ub(64,64,64,255);
}
else
{ //blue visually muted avatar
gGL.diffuseColor4ub(72,61,139,255);
{ // Visually muted avatar
gGL.diffuseColor4fv( avatar->getMutedAVColor().mV );
}
{

View File

@ -104,8 +104,43 @@
<menu_item_call.on_enable
function="Object.EnableInspect" />
</menu_item_call>
<menu_item_separator />
<menu_item_check
name="Normal"
label="Normal">
<menu_item_check.on_check
function="Avatar.CheckImposterMode"
parameter="0" />
<menu_item_check.on_click
function="Avatar.SetImposterMode"
parameter="0" />
</menu_item_check>
<menu_item_check
name="Always use imposter"
label="Always use imposter">
<menu_item_check.on_check
function="Avatar.CheckImposterMode"
parameter="1" />
<menu_item_check.on_click
function="Avatar.SetImposterMode"
parameter="1" />
</menu_item_check>
<menu_item_check
name="Never use imposter"
label="Never use imposter">
<menu_item_check.on_check
function="Avatar.CheckImposterMode"
parameter="2" />
<menu_item_check.on_click
function="Avatar.SetImposterMode"
parameter="2" />
</menu_item_check>
<menu_item_separator
layout="topleft" />
<menu_item_call
enabled="false"
label="Mute Particle Owner"

View File

@ -39,8 +39,10 @@
<menu_item_call.on_click
function="Avatar.InviteToGroup" />
</menu_item_call>
<menu_item_separator />
<menu_item_call
<menu_item_call
enabled="false"
label="Block"
name="Avatar Mute">
@ -95,8 +97,43 @@
<menu_item_call.on_enable
function="EnablePayAvatar" />
</menu_item_call>
<menu_item_separator />
<menu_item_check
name="Normal"
label="Normal">
<menu_item_check.on_check
function="Avatar.CheckImposterMode"
parameter="0" />
<menu_item_check.on_click
function="Avatar.SetImposterMode"
parameter="0" />
</menu_item_check>
<menu_item_check
name="Always use imposter"
label="Always use imposter">
<menu_item_check.on_check
function="Avatar.CheckImposterMode"
parameter="1" />
<menu_item_check.on_click
function="Avatar.SetImposterMode"
parameter="1" />
</menu_item_check>
<menu_item_check
name="Never use imposter"
label="Never use imposter">
<menu_item_check.on_check
function="Avatar.CheckImposterMode"
parameter="2" />
<menu_item_check.on_click
function="Avatar.SetImposterMode"
parameter="2" />
</menu_item_check>
<menu_item_separator
layout="topleft" />
<menu_item_call
enabled="false"
label="Mute Particle Owner"

View File

@ -543,6 +543,15 @@
<menu_item_check.on_check
control="NavBarShowParcelProperties" />
</menu_item_check>
<menu_item_check
label="Simple Imposters"
name="RenderAutoMuteEnabled">
<menu_item_check.on_check
control="RenderAutoMuteEnabled" />
<menu_item_check.on_click
function="ToggleControl"
parameter="RenderAutoMuteEnabled" />
</menu_item_check>
<menu_item_separator />
<menu_item_check
label="Advanced Menu"