summaryrefslogtreecommitdiff
path: root/indra/newview/llvoavatar.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llvoavatar.cpp')
-rw-r--r--indra/newview/llvoavatar.cpp243
1 files changed, 168 insertions, 75 deletions
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 80c6805ead..eab5206828 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -44,6 +44,7 @@
#include "llavatarnamecache.h"
#include "llavatarpropertiesprocessor.h"
#include "llavatarrendernotifier.h"
+#include "llcontrolavatar.h"
#include "llexperiencecache.h"
#include "llphysicsmotion.h"
#include "llviewercontrol.h"
@@ -663,7 +664,9 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mLastUpdateRequestCOFVersion(-1),
mLastUpdateReceivedCOFVersion(-1),
mCachedMuteListUpdateTime(0),
- mCachedInMuteList(false)
+ mCachedInMuteList(false),
+ mIsControlAvatar(false),
+ mEnableDefaultMotions(true)
{
LL_DEBUGS("AvatarRender") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL;
@@ -718,6 +721,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mCurrentGesticulationLevel = 0;
+
mRuthTimer.reset();
mRuthDebugTimer.reset();
mDebugExistenceTimer.reset();
@@ -1222,8 +1226,6 @@ const LLVector3 LLVOAvatar::getRenderPosition() const
{
return getPosition() * mDrawable->getParent()->getRenderMatrix();
}
-
-
}
void LLVOAvatar::updateDrawable(BOOL force_damped)
@@ -1240,6 +1242,10 @@ void LLVOAvatar::onShift(const LLVector4a& shift_vector)
void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax)
{
+ if (mDrawable.isNull())
+ {
+ return;
+ }
if (isImpostor() && !needsImpostorUpdate())
{
LLVector3 delta = getRenderPosition() -
@@ -1404,13 +1410,29 @@ void LLVOAvatar::renderCollisionVolumes()
static F32 sphere_scale = 1.0f;
static F32 center_dot_scale = 0.05f;
- static LLVector3 CV_COLOR_OCCLUDED(0.0f, 0.0f, 1.0f);
- static LLVector3 CV_COLOR_VISIBLE(0.5f, 0.5f, 1.0f);
- static LLVector3 DOT_COLOR_OCCLUDED(1.0f, 1.0f, 1.0f);
- static LLVector3 DOT_COLOR_VISIBLE(1.0f, 1.0f, 1.0f);
+ static LLVector3 BLUE(0.0f, 0.0f, 1.0f);
+ static LLVector3 PASTEL_BLUE(0.5f, 0.5f, 1.0f);
+ static LLVector3 RED(1.0f, 0.0f, 0.0f);
+ static LLVector3 PASTEL_RED(1.0f, 0.5f, 0.5f);
+ static LLVector3 WHITE(1.0f, 1.0f, 1.0f);
+
- render_sphere_and_line(begin_pos, end_pos, sphere_scale, CV_COLOR_OCCLUDED, CV_COLOR_VISIBLE);
- render_sphere_and_line(begin_pos, end_pos, center_dot_scale, DOT_COLOR_OCCLUDED, DOT_COLOR_VISIBLE);
+ LLVector3 cv_color_occluded;
+ LLVector3 cv_color_visible;
+ LLVector3 dot_color_occluded(WHITE);
+ LLVector3 dot_color_visible(WHITE);
+ if (isControlAvatar())
+ {
+ cv_color_occluded = RED;
+ cv_color_visible = PASTEL_RED;
+ }
+ else
+ {
+ cv_color_occluded = BLUE;
+ cv_color_visible = PASTEL_BLUE;
+ }
+ render_sphere_and_line(begin_pos, end_pos, sphere_scale, cv_color_occluded, cv_color_visible);
+ render_sphere_and_line(begin_pos, end_pos, center_dot_scale, dot_color_occluded, dot_color_visible);
gGL.popMatrix();
}
@@ -1422,9 +1444,6 @@ void LLVOAvatar::renderCollisionVolumes()
mNameText->lineSegmentIntersect(unused, unused, unused, TRUE);
}
-
- mDebugText.clear();
- addDebugText(ostr.str());
}
void LLVOAvatar::renderBones()
@@ -1595,6 +1614,11 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
return FALSE;
}
+ if (isControlAvatar())
+ {
+ return FALSE;
+ }
+
if (lineSegmentBoundingBox(start, end))
{
for (S32 i = 0; i < mNumCollisionVolumes; ++i)
@@ -1680,6 +1704,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
return FALSE;
}
+// virtual
LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end,
S32 face,
BOOL pick_transparent,
@@ -1796,7 +1821,11 @@ void LLVOAvatar::buildCharacter()
mAahMorph = getVisualParam( "Express_Open_Mouth" );
}
- startDefaultMotions();
+ // Currently disabled for control avatars (animated objects), enabled for all others.
+ if (mEnableDefaultMotions)
+ {
+ startDefaultMotions();
+ }
//-------------------------------------------------------------------------
// restart any currently active motions
@@ -1942,6 +1971,8 @@ void LLVOAvatar::resetSkeleton(bool reset_animations)
//-----------------------------------------------------------------------------
void LLVOAvatar::releaseMeshData()
{
+ // AXON what should we be doing here for control avs? Why are
+ // dummies treated differently in the first place?
if (sInstances.size() < AVATAR_RELEASE_THRESHOLD || mIsDummy)
{
return;
@@ -1962,15 +1993,15 @@ void LLVOAvatar::releaseMeshData()
LLFace* facep = mDrawable->getFace(0);
if (facep)
{
- facep->setSize(0, 0);
- for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++)
- {
- facep = mDrawable->getFace(i);
+ facep->setSize(0, 0);
+ for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++)
+ {
+ facep = mDrawable->getFace(i);
if (facep)
{
- facep->setSize(0, 0);
- }
- }
+ facep->setSize(0, 0);
+ }
+ }
}
}
@@ -1994,6 +2025,10 @@ void LLVOAvatar::releaseMeshData()
void LLVOAvatar::restoreMeshData()
{
llassert(!isSelf());
+ if (mDrawable.isNull())
+ {
+ return;
+ }
//LL_INFOS() << "Restoring" << LL_ENDL;
mMeshValid = TRUE;
@@ -2571,13 +2606,16 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)
}
}
- mDrawable->movePartition();
-
- //force a move if sitting on an active object
- if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive())
- {
- gPipeline.markMoved(mDrawable, TRUE);
- }
+ if (mDrawable.notNull())
+ {
+ mDrawable->movePartition();
+
+ //force a move if sitting on an active object
+ if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive())
+ {
+ gPipeline.markMoved(mDrawable, TRUE);
+ }
+ }
}
void LLVOAvatar::idleUpdateAppearanceAnimation()
@@ -2738,7 +2776,8 @@ void LLVOAvatar::idleUpdateLoadingEffect()
LLPartData::LL_PART_EMISSIVE_MASK | // LLPartData::LL_PART_FOLLOW_SRC_MASK |
LLPartData::LL_PART_TARGET_POS_MASK );
- if (!isTooComplex()) // do not generate particles for overly-complex avatars
+ // AXON skip cloud effects for dummy avs as well
+ if (!mIsDummy && !isTooComplex()) // do not generate particles for overly-complex avatars
{
setParticleSource(particle_parameters, getID());
}
@@ -3338,8 +3377,7 @@ bool LLVOAvatar::isInMuteList()
void LLVOAvatar::updateDebugText()
{
- // clear debug text
- mDebugText.clear();
+ // Leave mDebugText uncleared here, in case a derived class has added some state first
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
{
@@ -3406,6 +3444,7 @@ void LLVOAvatar::updateDebugText()
addDebugText(mBakedTextureDebugText);
}
+ // Develop -> Avatar -> Animation Info
if (LLVOAvatar::sShowAnimationDebug)
{
for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin();
@@ -3415,8 +3454,27 @@ void LLVOAvatar::updateDebugText()
if (motionp->getMinPixelArea() < getPixelArea())
{
std::string output;
- if (motionp->getName().empty())
+ std::string motion_name = motionp->getName();
+ if (motion_name.empty())
{
+ if (isControlAvatar())
+ {
+ LLControlAvatar *control_av = dynamic_cast<LLControlAvatar*>(this);
+ // Try to get name from inventory of associated object
+ LLVOVolume *volp = control_av->mRootVolp;
+ if (volp)
+ {
+ volp->requestInventory(); // AXON should be a no-op if already requested or fetched?
+ LLViewerInventoryItem* item = volp->getInventoryItemByAsset(motionp->getID());
+ if (item)
+ {
+ motion_name = item->getName();
+ }
+ }
+ }
+ }
+ if (motion_name.empty())
+ {
output = llformat("%s - %d",
gAgent.isGodlikeWithoutAdminMenuFakery() ?
motionp->getID().asString().c_str() :
@@ -3426,8 +3484,8 @@ void LLVOAvatar::updateDebugText()
else
{
output = llformat("%s - %d",
- motionp->getName().c_str(),
- (U32)motionp->getPriority());
+ motion_name.c_str(),
+ (U32)motionp->getPriority());
}
addDebugText(output);
}
@@ -3443,8 +3501,7 @@ void LLVOAvatar::updateDebugText()
{
setDebugText(mDebugText);
}
- mDebugText.clear();
-
+ mDebugText.clear();
}
//------------------------------------------------------------------------
@@ -3474,7 +3531,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
//--------------------------------------------------------------------
bool visually_muted = isVisuallyMuted();
- if (visible && (!isSelf() || visually_muted) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)
+ // AXON FIXME this expression is a crawling horror
+ if (mDrawable.notNull() && visible && (!isSelf() || visually_muted) &&
+ !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)
{
const LLVector4a* ext = mDrawable->getSpatialExtents();
LLVector4a size;
@@ -3530,7 +3589,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
}
// change animation time quanta based on avatar render load
- if (!isSelf() && !mIsDummy)
+ // AXON how should control avs be handled here?
+ bool is_pure_dummy = mIsDummy && !isControlAvatar();
+ if (!isSelf() && !is_pure_dummy)
{
F32 time_quantum = clamp_rescale((F32)sInstances.size(), 10.f, 35.f, 0.f, 0.25f);
F32 pixel_area_scale = clamp_rescale(mPixelArea, 100, 5000, 1.f, 0.f);
@@ -3652,7 +3713,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
//--------------------------------------------------------------------
// Propagate viewer object rotation to root of avatar
//--------------------------------------------------------------------
- if (!isAnyAnimationSignaled(AGENT_NO_ROTATE_ANIMS, NUM_AGENT_NO_ROTATE_ANIMS))
+ // AXON - also skip for control avatars
+ if (!isControlAvatar() && !isAnyAnimationSignaled(AGENT_NO_ROTATE_ANIMS, NUM_AGENT_NO_ROTATE_ANIMS))
{
LLQuaternion iQ;
LLVector3 upDir( 0.0f, 0.0f, 1.0f );
@@ -4041,7 +4103,7 @@ void LLVOAvatar::updateVisibility()
if (mIsDummy)
{
- visible = TRUE;
+ visible = FALSE;
}
else if (mDrawable.isNull())
{
@@ -4190,6 +4252,11 @@ U32 LLVOAvatar::renderSkinned()
return num_indices;
}
+ if (mDrawable.isNull())
+ {
+ return num_indices;
+ }
+
LLFace* face = mDrawable->getFace(0);
bool needs_rebuild = !face || !face->getVertexBuffer() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY);
@@ -4352,11 +4419,12 @@ U32 LLVOAvatar::renderSkinned()
}
BOOL first_pass = TRUE;
+ bool is_pure_dummy = mIsDummy && !isControlAvatar();
if (!LLDrawPoolAvatar::sSkipOpaque)
{
if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)
{
- if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy)
+ if (isTextureVisible(TEX_HEAD_BAKED) || is_pure_dummy)
{
LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD);
if (head_mesh)
@@ -4366,7 +4434,7 @@ U32 LLVOAvatar::renderSkinned()
first_pass = FALSE;
}
}
- if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy)
+ if (isTextureVisible(TEX_UPPER_BAKED) || is_pure_dummy)
{
LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY);
if (upper_mesh)
@@ -4376,7 +4444,7 @@ U32 LLVOAvatar::renderSkinned()
first_pass = FALSE;
}
- if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy)
+ if (isTextureVisible(TEX_LOWER_BAKED) || is_pure_dummy)
{
LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY);
if (lower_mesh)
@@ -4433,18 +4501,15 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)
}
first_pass = FALSE;
}
- // 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)
- {
- LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR);
- if (hair_mesh)
- {
- num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy);
- }
- first_pass = FALSE;
- }
+ if (isTextureVisible(TEX_HAIR_BAKED))
+ {
+ LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR);
+ if (hair_mesh)
+ {
+ num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy);
+ }
+ first_pass = FALSE;
+ }
if (LLPipeline::sImpostorRender)
{
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
@@ -4484,7 +4549,9 @@ U32 LLVOAvatar::renderRigid()
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
}
- if (isTextureVisible(TEX_EYES_BAKED) || mIsDummy)
+ bool is_pure_dummy = mIsDummy && !isControlAvatar();
+
+ if (isTextureVisible(TEX_EYES_BAKED) || is_pure_dummy)
{
LLViewerJoint* eyeball_left = getViewerJoint(MESH_ID_EYEBALL_LEFT);
LLViewerJoint* eyeball_right = getViewerJoint(MESH_ID_EYEBALL_RIGHT);
@@ -5034,7 +5101,10 @@ void LLVOAvatar::processAnimationStateChanges()
else if (mInAir && !mIsSitting)
{
stopMotion(ANIM_AGENT_WALK_ADJUST);
- startMotion(ANIM_AGENT_FLY_ADJUST);
+ if (mEnableDefaultMotions)
+ {
+ startMotion(ANIM_AGENT_FLY_ADJUST);
+ }
}
else
{
@@ -5044,13 +5114,19 @@ void LLVOAvatar::processAnimationStateChanges()
if ( isAnyAnimationSignaled(AGENT_GUN_AIM_ANIMS, NUM_AGENT_GUN_AIM_ANIMS) )
{
- startMotion(ANIM_AGENT_TARGET);
+ if (mEnableDefaultMotions)
+ {
+ startMotion(ANIM_AGENT_TARGET);
+ }
stopMotion(ANIM_AGENT_BODY_NOISE);
}
else
{
stopMotion(ANIM_AGENT_TARGET);
- startMotion(ANIM_AGENT_BODY_NOISE);
+ if (mEnableDefaultMotions)
+ {
+ startMotion(ANIM_AGENT_BODY_NOISE);
+ }
}
// clear all current animations
@@ -5521,14 +5597,13 @@ void LLVOAvatar::rebuildAttachmentOverrides()
//-----------------------------------------------------------------------------
void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo)
{
- LLVOAvatar *av = vo->getAvatarAncestor();
- if (!av || (av != this))
- {
+ if (vo->getAvatar() != this)
+ {
LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL;
return;
- }
+ }
- LLScopedContextString str("addAttachmentOverridesForObject " + av->getFullname());
+ LLScopedContextString str("addAttachmentOverridesForObject " + vo->getAvatar()->getFullname());
// Process all children
LLViewerObject::const_child_list_t& children = vo->getChildren();
@@ -5554,7 +5629,7 @@ void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo)
LLUUID currentId = vobj->getVolume()->getParams().getSculptID();
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj );
- if ( vobj && vobj->isAttachment() && vobj->isMesh() && pSkinData )
+ if ( vobj && vobj->isMesh() && pSkinData )
{
const int bindCnt = pSkinData->mAlternateBindMatrix.size();
const int jointCnt = pSkinData->mJointNames.size();
@@ -5736,14 +5811,15 @@ void LLVOAvatar::showAttachmentOverrides(bool verbose) const
}
//-----------------------------------------------------------------------------
-// resetJointsOnDetach
+// removeAttachmentOverridesForObject
//-----------------------------------------------------------------------------
-void LLVOAvatar::resetJointsOnDetach(LLViewerObject *vo)
+// AXON handle NPC case
+void LLVOAvatar::removeAttachmentOverridesForObject(LLViewerObject *vo)
{
- LLVOAvatar *av = vo->getAvatarAncestor();
- if (!av || (av != this))
+ if (vo->getAvatar() != this)
{
LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL;
+ return;
}
// Process all children
@@ -5752,21 +5828,22 @@ void LLVOAvatar::resetJointsOnDetach(LLViewerObject *vo)
it != children.end(); ++it)
{
LLViewerObject *childp = *it;
- resetJointsOnDetach(childp);
+ removeAttachmentOverridesForObject(childp);
}
// Process self.
LLUUID mesh_id;
if (getRiggedMeshID(vo,mesh_id))
{
- resetJointsOnDetach(mesh_id);
+ removeAttachmentOverridesForObject(mesh_id);
}
}
//-----------------------------------------------------------------------------
-// resetJointsOnDetach
+// removeAttachmentOverridesForObject
//-----------------------------------------------------------------------------
-void LLVOAvatar::resetJointsOnDetach(const LLUUID& mesh_id)
+// AXON handle NPC case
+void LLVOAvatar::removeAttachmentOverridesForObject(const LLUUID& mesh_id)
{
//Subsequent joints are relative to pelvis
avatar_joint_list_t::iterator iter = mSkeleton.begin();
@@ -5844,6 +5921,7 @@ void LLVOAvatar::getGround(const LLVector3 &in_pos_agent, LLVector3 &out_pos_age
LLVector3d z_vec(0.0f, 0.0f, 1.0f);
LLVector3d p0_global, p1_global;
+ // AXON update for control avs?
if (mIsDummy)
{
outNorm.setVec(z_vec);
@@ -5873,6 +5951,7 @@ F32 LLVOAvatar::getTimeDilation()
//-----------------------------------------------------------------------------
F32 LLVOAvatar::getPixelArea() const
{
+ // AXON update for control avatars
if (mIsDummy)
{
return 100000.f;
@@ -6288,7 +6367,7 @@ void LLVOAvatar::removeChild(LLViewerObject *childp)
LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* viewer_object)
{
- S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getState());
+ S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getAttachmentState());
// This should never happen unless the server didn't process the attachment point
// correctly, but putting this check in here to be safe.
@@ -6483,7 +6562,7 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
LLUUID mesh_id;
if (getRiggedMeshID(pVO, mesh_id))
{
- resetJointsOnDetach(mesh_id);
+ removeAttachmentOverridesForObject(mesh_id);
if ( gAgentCamera.cameraCustomizeAvatar() )
{
gAgent.unpauseAnimation();
@@ -6644,7 +6723,10 @@ void LLVOAvatar::getOffObject()
mRoot->setRotation(cur_rotation_world);
mRoot->getXform()->update();
- startMotion(ANIM_AGENT_BODY_NOISE);
+ if (mEnableDefaultMotions)
+ {
+ startMotion(ANIM_AGENT_BODY_NOISE);
+ }
if (isSelf())
{
@@ -6804,6 +6886,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color)
BOOL LLVOAvatar::isVisible() const
{
+ // AXON should we flag control avs as invisible?
return mDrawable.notNull()
&& (!mOrphaned || isSelf())
&& (mDrawable->isVisible() || mIsDummy);
@@ -6812,6 +6895,11 @@ BOOL LLVOAvatar::isVisible() const
// Determine if we have enough avatar data to render
bool LLVOAvatar::getIsCloud() const
{
+ if (mIsDummy)
+ {
+ return false;
+ }
+
return ( ((const_cast<LLVOAvatar*>(this))->visualParamWeightsAreDefault())// Do we have a shape?
|| ( !isTextureDefined(TEX_LOWER_BAKED)
|| !isTextureDefined(TEX_UPPER_BAKED)
@@ -8776,6 +8864,11 @@ void LLVOAvatar::updateFreezeCounter(S32 counter)
BOOL LLVOAvatar::updateLOD()
{
+ if (mDrawable.isNull())
+ {
+ return FALSE;
+ }
+
if (isImpostor() && 0 != mDrawable->getNumFaces() && mDrawable->getFace(0)->hasGeometry())
{
return TRUE;