summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llface.cpp6
-rw-r--r--indra/newview/llviewerobject.cpp16
-rw-r--r--indra/newview/llviewerobject.h2
-rw-r--r--indra/newview/llvoavatar.cpp275
-rw-r--r--indra/newview/llvoavatar.h9
-rw-r--r--indra/newview/llvovolume.cpp61
-rw-r--r--indra/newview/llvovolume.h5
7 files changed, 227 insertions, 147 deletions
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 3d5e2d356e..eebdb62aff 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -330,11 +330,7 @@ void LLFace::dirtyTexture()
{
vobj->mLODChanged = TRUE;
- LLVOAvatar* avatar = vobj->getAvatar();
- if (avatar)
- { //avatar render cost may have changed
- avatar->updateVisualComplexity();
- }
+ vobj->updateVisualComplexity();
}
gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, FALSE);
}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 616db8ae2f..94e1390c42 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -3627,6 +3627,22 @@ U32 LLViewerObject::getHighLODTriangleCount()
return 0;
}
+U32 LLViewerObject::recursiveGetTriangleCount(S32* vcount) const
+{
+ S32 total_tris = getTriangleCount(vcount);
+ LLViewerObject::const_child_list_t& child_list = getChildren();
+ for (LLViewerObject::const_child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); ++iter)
+ {
+ LLViewerObject* childp = *iter;
+ if (childp)
+ {
+ total_tris += childp->getTriangleCount(vcount);
+ }
+ }
+ return total_tris;
+}
+
void LLViewerObject::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax)
{
LLVector4a center;
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 345fd1fb27..a84b6da96c 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -364,6 +364,8 @@ public:
virtual U32 getTriangleCount(S32* vcount = NULL) const;
virtual U32 getHighLODTriangleCount();
+ U32 recursiveGetTriangleCount(S32* vcount = NULL) const;
+
void setObjectCost(F32 cost);
F32 getObjectCost();
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 0fcb4ffc55..d5301c38ba 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -620,6 +620,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
LLViewerObject(id, pcode, regionp),
mSpecialRenderMode(0),
mAttachmentSurfaceArea(0.f),
+ mAttachmentVisibleTriangleCount(0),
+ mAttachmentEstTriangleCount(0.f),
mReportedVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN),
mTurning(FALSE),
mLastSkeletonSerialNum( 0 ),
@@ -9167,8 +9169,13 @@ void LLVOAvatar::idleUpdateRenderComplexity()
{
if (isControlAvatar())
{
- // ARC for animated object attachments is accounted with the avatar they're attached to.
- return;
+ LLControlAvatar *cav = dynamic_cast<LLControlAvatar*>(this);
+ bool is_attachment = cav && cav->mRootVolp && cav->mRootVolp->isAttachment(); // For attached animated objects
+ if (is_attachment)
+ {
+ // ARC for animated object attachments is accounted with the avatar they're attached to.
+ return;
+ }
}
// Render Complexity
@@ -9218,10 +9225,14 @@ void LLVOAvatar::idleUpdateRenderComplexity()
// 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_color.set(isImpostor() ? LLColor4::grey : (isControlAvatar() ? LLColor4::yellow : LLColor4::white));
info_style = LLFontGL::NORMAL;
mText->addLine(info_line, info_color, info_style);
+ // Triangle count
+ mText->addLine(llformat("Tris %u",mAttachmentVisibleTriangleCount), info_color, info_style);
+ mText->addLine(llformat("Est Tris %f",mAttachmentEstTriangleCount), info_color, info_style);
+
// Attachment Surface Area
static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit", 1000.0f);
info_line = llformat("%.0f m^2", mAttachmentSurfaceArea);
@@ -9263,6 +9274,133 @@ void LLVOAvatar::updateVisualComplexity()
mVisualComplexityStale = true;
}
+// Account for the complexity of a single top-level object associated
+// with an avatar. This will be either an attached object or an animated
+// object.
+void LLVOAvatar::accountRenderComplexityForObject(
+ const LLViewerObject *attached_object,
+ const F32 max_attachment_complexity,
+ LLVOVolume::texture_cost_t& textures,
+ U32& cost,
+ hud_complexity_list_t& hud_complexity_list)
+{
+ if (attached_object && !attached_object->isHUDAttachment())
+ {
+ mAttachmentVisibleTriangleCount += attached_object->recursiveGetTriangleCount();
+ mAttachmentEstTriangleCount += attached_object->recursiveGetEstTrianglesMax();
+
+ textures.clear();
+ const LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable)
+ {
+ const LLVOVolume* volume = drawable->getVOVolume();
+ if (volume)
+ {
+ F32 attachment_total_cost = 0;
+ F32 attachment_volume_cost = 0;
+ F32 attachment_texture_cost = 0;
+ F32 attachment_children_cost = 0;
+ // AXON placeholder value, will revisit in testing.
+ const F32 animated_object_attachment_surcharge = 20000;
+
+ if (attached_object->isAnimatedObject())
+ {
+ attachment_volume_cost += animated_object_attachment_surcharge;
+ }
+ attachment_volume_cost += volume->getRenderCost(textures);
+
+ const_child_list_t children = volume->getChildren();
+ for (const_child_list_t::const_iterator child_iter = children.begin();
+ child_iter != children.end();
+ ++child_iter)
+ {
+ LLViewerObject* child_obj = *child_iter;
+ LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
+ if (child)
+ {
+ attachment_children_cost += child->getRenderCost(textures);
+ }
+ }
+
+ 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
+ attachment_texture_cost += volume_texture->second;
+ }
+ attachment_total_cost = attachment_volume_cost + attachment_texture_cost + attachment_children_cost;
+ LL_DEBUGS("ARCdetail") << "Attachment costs " << attached_object->getAttachmentItemID()
+ << " total: " << attachment_total_cost
+ << ", volume: " << attachment_volume_cost
+ << ", textures: " << attachment_texture_cost
+ << ", " << volume->numChildren()
+ << " children: " << attachment_children_cost
+ << LL_ENDL;
+ // Limit attachment complexity to avoid signed integer flipping of the wearer's ACI
+ cost += (U32)llclamp(attachment_total_cost, MIN_ATTACHMENT_COMPLEXITY, max_attachment_complexity);
+ }
+ }
+ }
+ if (isSelf()
+ && attached_object
+ && attached_object->isHUDAttachment()
+ && !attached_object->isTempAttachment()
+ && attached_object->mDrawable)
+ {
+ textures.clear();
+
+ const LLVOVolume* volume = attached_object->mDrawable->getVOVolume();
+ if (volume)
+ {
+ LLHUDComplexity hud_object_complexity;
+ hud_object_complexity.objectName = attached_object->getAttachmentItemName();
+ hud_object_complexity.objectId = attached_object->getAttachmentItemID();
+ std::string joint_name;
+ gAgentAvatarp->getAttachedPointName(attached_object->getAttachmentItemID(), joint_name);
+ hud_object_complexity.jointName = joint_name;
+ // get cost and individual textures
+ hud_object_complexity.objectsCost += volume->getRenderCost(textures);
+ hud_object_complexity.objectsCount++;
+
+ LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
+ for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
+ iter != child_list.end(); ++iter)
+ {
+ LLViewerObject* childp = *iter;
+ const LLVOVolume* chld_volume = dynamic_cast<LLVOVolume*>(childp);
+ if (chld_volume)
+ {
+ // get cost and individual textures
+ hud_object_complexity.objectsCost += chld_volume->getRenderCost(textures);
+ hud_object_complexity.objectsCount++;
+ }
+ }
+
+ hud_object_complexity.texturesCount += textures.size();
+
+ for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin();
+ volume_texture != textures.end();
+ ++volume_texture)
+ {
+ // add the cost of each individual texture (ignores duplicates)
+ hud_object_complexity.texturesCost += volume_texture->second;
+ LLViewerFetchedTexture *tex = LLViewerTextureManager::getFetchedTexture(volume_texture->first);
+ if (tex)
+ {
+ // Note: Texture memory might be incorect since texture might be still loading.
+ hud_object_complexity.texturesMemoryTotal += tex->getTextureMemory();
+ if (tex->getOriginalHeight() * tex->getOriginalWidth() >= HUD_OVERSIZED_TEXTURE_DATA_SIZE)
+ {
+ hud_object_complexity.largeTexturesCount++;
+ }
+ }
+ }
+ hud_complexity_list.push_back(hud_object_complexity);
+ }
+ }
+}
+
// Calculations for mVisualComplexity value
void LLVOAvatar::calculateUpdateRenderComplexity()
{
@@ -9301,7 +9439,24 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
}
LL_DEBUGS("ARCdetail") << "Avatar body parts complexity: " << cost << LL_ENDL;
+ mAttachmentVisibleTriangleCount = 0;
+ mAttachmentEstTriangleCount = 0.f;
+
+ // A standalone animated object needs to be accounted for
+ // using its associated volume. Attached animated objects
+ // will be covered by the subsequent loop over attachments.
+ LLControlAvatar *control_av = dynamic_cast<LLControlAvatar*>(this);
+ if (control_av)
+ {
+ LLVOVolume *volp = control_av->mRootVolp;
+ if (volp && !volp->isAttachment())
+ {
+ accountRenderComplexityForObject(volp, max_attachment_complexity,
+ textures, cost, hud_complexity_list);
+ }
+ }
+ // Account for complexity of all attachments.
for (attachment_map_t::const_iterator attachment_point = mAttachmentPoints.begin();
attachment_point != mAttachmentPoints.end();
++attachment_point)
@@ -9312,118 +9467,8 @@ void LLVOAvatar::calculateUpdateRenderComplexity()
++attachment_iter)
{
const LLViewerObject* attached_object = (*attachment_iter);
- if (attached_object && !attached_object->isHUDAttachment())
- {
- textures.clear();
- const LLDrawable* drawable = attached_object->mDrawable;
- if (drawable)
- {
- const LLVOVolume* volume = drawable->getVOVolume();
- if (volume)
- {
- F32 attachment_total_cost = 0;
- F32 attachment_volume_cost = 0;
- F32 attachment_texture_cost = 0;
- F32 attachment_children_cost = 0;
- // AXON placeholder value, will revisit in testing.
- const F32 animated_object_attachment_surcharge = 20000;
-
- if (attached_object->isAnimatedObject())
- {
- attachment_volume_cost += animated_object_attachment_surcharge;
- }
- attachment_volume_cost += volume->getRenderCost(textures);
-
- const_child_list_t children = volume->getChildren();
- for (const_child_list_t::const_iterator child_iter = children.begin();
- child_iter != children.end();
- ++child_iter)
- {
- LLViewerObject* child_obj = *child_iter;
- LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
- if (child)
- {
- attachment_children_cost += child->getRenderCost(textures);
- }
- }
-
- 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
- attachment_texture_cost += volume_texture->second;
- }
- attachment_total_cost = attachment_volume_cost + attachment_texture_cost + attachment_children_cost;
- LL_DEBUGS("ARCdetail") << "Attachment costs " << attached_object->getAttachmentItemID()
- << " total: " << attachment_total_cost
- << ", volume: " << attachment_volume_cost
- << ", textures: " << attachment_texture_cost
- << ", " << volume->numChildren()
- << " children: " << attachment_children_cost
- << LL_ENDL;
- // Limit attachment complexity to avoid signed integer flipping of the wearer's ACI
- cost += (U32)llclamp(attachment_total_cost, MIN_ATTACHMENT_COMPLEXITY, max_attachment_complexity);
- }
- }
- }
- if (isSelf()
- && attached_object
- && attached_object->isHUDAttachment()
- && !attached_object->isTempAttachment()
- && attached_object->mDrawable)
- {
- textures.clear();
-
- const LLVOVolume* volume = attached_object->mDrawable->getVOVolume();
- if (volume)
- {
- LLHUDComplexity hud_object_complexity;
- hud_object_complexity.objectName = attached_object->getAttachmentItemName();
- hud_object_complexity.objectId = attached_object->getAttachmentItemID();
- std::string joint_name;
- gAgentAvatarp->getAttachedPointName(attached_object->getAttachmentItemID(), joint_name);
- hud_object_complexity.jointName = joint_name;
- // get cost and individual textures
- hud_object_complexity.objectsCost += volume->getRenderCost(textures);
- hud_object_complexity.objectsCount++;
-
- LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); ++iter)
- {
- LLViewerObject* childp = *iter;
- const LLVOVolume* chld_volume = dynamic_cast<LLVOVolume*>(childp);
- if (chld_volume)
- {
- // get cost and individual textures
- hud_object_complexity.objectsCost += chld_volume->getRenderCost(textures);
- hud_object_complexity.objectsCount++;
- }
- }
-
- hud_object_complexity.texturesCount += textures.size();
-
- for (LLVOVolume::texture_cost_t::iterator volume_texture = textures.begin();
- volume_texture != textures.end();
- ++volume_texture)
- {
- // add the cost of each individual texture (ignores duplicates)
- hud_object_complexity.texturesCost += volume_texture->second;
- LLViewerFetchedTexture *tex = LLViewerTextureManager::getFetchedTexture(volume_texture->first);
- if (tex)
- {
- // Note: Texture memory might be incorect since texture might be still loading.
- hud_object_complexity.texturesMemoryTotal += tex->getTextureMemory();
- if (tex->getOriginalHeight() * tex->getOriginalWidth() >= HUD_OVERSIZED_TEXTURE_DATA_SIZE)
- {
- hud_object_complexity.largeTexturesCount++;
- }
- }
- }
- hud_complexity_list.push_back(hud_object_complexity);
- }
- }
+ accountRenderComplexityForObject(attached_object, max_attachment_complexity,
+ textures, cost, hud_complexity_list);
}
}
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 5a40a45eae..5f7d23050e 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -50,6 +50,8 @@
#include "llviewertexlayer.h"
#include "material_codes.h" // LL_MCODE_END
#include "llviewerstats.h"
+#include "llvovolume.h"
+#include "llavatarrendernotifier.h"
extern const LLUUID ANIM_AGENT_BODY_NOISE;
extern const LLUUID ANIM_AGENT_BREATHE_ROT;
@@ -268,6 +270,11 @@ public:
static void invalidateNameTags();
void addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font);
void idleUpdateRenderComplexity();
+ void accountRenderComplexityForObject(const LLViewerObject *attached_object,
+ const F32 max_attachment_complexity,
+ LLVOVolume::texture_cost_t& textures,
+ U32& cost,
+ hud_complexity_list_t& hud_complexity_list);
void calculateUpdateRenderComplexity();
static const U32 VISUAL_COMPLEXITY_UNKNOWN;
void updateVisualComplexity();
@@ -431,6 +438,8 @@ public:
private:
F32 mAttachmentSurfaceArea; //estimated surface area of attachments
+ U32 mAttachmentVisibleTriangleCount;
+ F32 mAttachmentEstTriangleCount;
bool shouldAlphaMask();
BOOL mNeedsSkin; // avatar has been animated and verts have not been updated
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index efddc9235e..7fec240d1b 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1103,16 +1103,26 @@ void LLVOVolume::updateSculptTexture()
}
+void LLVOVolume::updateVisualComplexity()
+{
+ LLVOAvatar* avatar = getAvatarAncestor();
+ if (avatar)
+ {
+ avatar->updateVisualComplexity();
+ }
+ LLVOAvatar* rigged_avatar = getAvatar();
+ if(rigged_avatar && (rigged_avatar != avatar))
+ {
+ rigged_avatar->updateVisualComplexity();
+ }
+}
+
void LLVOVolume::notifyMeshLoaded()
{
mSculptChanged = TRUE;
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
- LLVOAvatar* avatar = getAvatar();
- if (avatar)
- {
- avatar->updateVisualComplexity();
- }
+ updateVisualComplexity();
}
// sculpt replaces generate() for sculpted surfaces
@@ -1302,18 +1312,7 @@ BOOL LLVOVolume::calcLOD()
{
if (isRootEdit() && getChildren().size()>0)
{
- S32 total_tris = getTriangleCount();
- LLViewerObject::const_child_list_t& child_list = getChildren();
- for (LLViewerObject::const_child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); ++iter)
- {
- LLViewerObject* childp = *iter;
- LLVOVolume *child_volp = dynamic_cast<LLVOVolume*>(childp);
- if (child_volp)
- {
- total_tris += child_volp->getTriangleCount();
- }
- }
+ S32 total_tris = recursiveGetTriangleCount();
setDebugText(llformat("TRIS %d TOTAL %d", getTriangleCount(), total_tris));
}
else
@@ -1333,7 +1332,8 @@ BOOL LLVOVolume::calcLOD()
{
mAppAngle = ll_round((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
mLOD = cur_detail;
- return TRUE;
+
+ return TRUE;
}
return FALSE;
@@ -1691,6 +1691,11 @@ bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable, BOOL &compiled)
if ((new_lod != old_lod) || mSculptChanged)
{
+ if (mDrawable->isState(LLDrawable::RIGGED))
+ {
+ updateVisualComplexity();
+ }
+
compiled = TRUE;
sNumLODChanges += new_num_faces;
@@ -3342,7 +3347,7 @@ void LLVOVolume::setExtendedMeshFlags(U32 flags)
parameterChanged(LLNetworkData::PARAMS_EXTENDED_MESH, true);
if (isAttachment() && getAvatarAncestor())
{
- getAvatarAncestor()->updateVisualComplexity();
+ updateVisualComplexity();
if (flags & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG)
{
// Making a rigged mesh into an animated object
@@ -3392,7 +3397,7 @@ bool LLVOVolume::isAnimatedObject() const
if (root_is_animated_flag)
{
bool root_can_be_animated = root_vol->canBeAnimatedObject();
- bool this_can_be_animated = ((root_vol == this) && root_can_be_animated) || canBeAnimatedObject();
+ bool this_can_be_animated = (root_vol == this) ? root_can_be_animated : canBeAnimatedObject();
if (this_can_be_animated && root_can_be_animated)
{
return true;
@@ -4923,25 +4928,29 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
group->mBuilt = 1.f;
LLVOAvatar* pAvatarVO = NULL;
+ LLVOAvatar *attached_av = NULL;
LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge();
if (bridge)
{
+ LLViewerObject* vobj = bridge->mDrawable->getVObj();
if (bridge->mAvatar.isNull())
{
- LLViewerObject* vobj = bridge->mDrawable->getVObj();
if (vobj)
{
bridge->mAvatar = vobj->getAvatar();
}
}
-
+ if (vobj)
+ {
+ attached_av = vobj->getAvatarAncestor();
+ }
pAvatarVO = bridge->mAvatar;
}
- if (pAvatarVO)
+ if (attached_av)
{
- pAvatarVO->subtractAttachmentArea( group->mSurfaceArea );
+ attached_av->subtractAttachmentArea( group->mSurfaceArea );
}
group->mGeometryBytes = 0;
@@ -5518,9 +5527,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
mFaceList.clear();
- if (pAvatarVO)
+ if (attached_av)
{
- pAvatarVO->addAttachmentArea( group->mSurfaceArea );
+ attached_av->addAttachmentArea( group->mSurfaceArea );
}
}
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 24bcf41c74..bc8fa9a3d3 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -315,7 +315,10 @@ public:
bool hasMedia() const;
LLVector3 getApproximateFaceNormal(U8 face_id);
-
+
+ // Flag any corresponding avatars as needing update.
+ void updateVisualComplexity();
+
void notifyMeshLoaded();
// Returns 'true' iff the media data for this object is in flight