Newer
Older
Brad Payne (Vir Linden)
committed
/**
* @file llcontrolavatar.cpp
* @brief Implementation for special dummy avatar used to drive rigged meshes.
*
* $LicenseInfo:firstyear=2017&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2017, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llcontrolavatar.h"
#include "llagent.h" // Get state values from here
#include "llviewerobjectlist.h"
#include "pipeline.h"
#include "llanimationstates.h"
Brad Payne (Vir Linden)
committed
#include "llviewercontrol.h"
Brad Payne (Vir Linden)
committed
#include "llmeshrepository.h"
Brad Payne (Vir Linden)
committed
#include "llviewerregion.h"
Brad Payne (Vir Linden)
committed
#include "llskinningutil.h"
Brad Payne (Vir Linden)
committed
Brad Payne (Vir Linden)
committed
//#pragma optimize("", off)
Brad Payne (Vir Linden)
committed
const F32 LLControlAvatar::MAX_LEGAL_OFFSET = 3.0f;
const F32 LLControlAvatar::MAX_LEGAL_SIZE = 64.0f;
Brad Payne (Vir Linden)
committed
Brad Payne (Vir Linden)
committed
LLControlAvatar::LLControlAvatar(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp) :
LLVOAvatar(id, pcode, regionp),
Brad Payne (Vir Linden)
committed
mPlaying(false),
Brad Payne (Vir Linden)
committed
mGlobalScale(1.0f),
Brad Payne (Vir Linden)
committed
mMarkedForDeath(false),
Brad Payne (Vir Linden)
committed
mRootVolp(NULL),
mScaleConstraintFixup(1.0)
Brad Payne (Vir Linden)
committed
{
Brad Payne (Vir Linden)
committed
mIsDummy = TRUE;
Brad Payne (Vir Linden)
committed
mIsControlAvatar = true;
Brad Payne (Vir Linden)
committed
mEnableDefaultMotions = false;
Brad Payne (Vir Linden)
committed
}
// virtual
LLControlAvatar::~LLControlAvatar()
{
}
// virtual
void LLControlAvatar::initInstance()
{
Brad Payne (Vir Linden)
committed
// Potential optimizations here: avoid creating system
Brad Payne (Vir Linden)
committed
// avatar mesh content since it's not used. For now we just clean some
// things up after the fact in releaseMeshData().
LLVOAvatar::initInstance();
Brad Payne (Vir Linden)
committed
createDrawable(&gPipeline);
updateJointLODs();
updateGeometry(mDrawable);
hideSkirt();
mInitFlags |= 1<<4;
Brad Payne (Vir Linden)
committed
void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_scale_fixup) const
{
Brad Payne (Vir Linden)
committed
F32 max_legal_offset = MAX_LEGAL_OFFSET;
if (gSavedSettings.getControl("AnimatedObjectsMaxLegalOffset"))
{
max_legal_offset = gSavedSettings.getF32("AnimatedObjectsMaxLegalOffset");
}
max_legal_offset = llmax(max_legal_offset,0.f);
Brad Payne (Vir Linden)
committed
F32 max_legal_size = MAX_LEGAL_SIZE;
if (gSavedSettings.getControl("AnimatedObjectsMaxLegalSize"))
{
max_legal_size = gSavedSettings.getF32("AnimatedObjectsMaxLegalSize");
}
max_legal_size = llmax(max_legal_size, 1.f);
Brad Payne (Vir Linden)
committed
Brad Payne (Vir Linden)
committed
new_pos_fixup = LLVector3();
new_scale_fixup = 1.0f;
LLVector3 vol_pos = mRootVolp->getRenderPosition();
Brad Payne (Vir Linden)
committed
// Fix up position if needed to prevent visual encroachment
if (box_valid_and_non_zero(getLastAnimExtents())) // wait for state to settle down
{
// The goal here is to ensure that the extent of the avatar's
// bounding box does not wander too far from the
// official position of the corresponding volume. We
// do this by tracking the distance and applying a
// correction to the control avatar position if
// needed.
const LLVector3 *extents = getLastAnimExtents();
LLVector3 unshift_extents[2];
unshift_extents[0] = extents[0] - mPositionConstraintFixup;
unshift_extents[1] = extents[1] - mPositionConstraintFixup;
LLVector3 box_dims = extents[1]-extents[0];
F32 box_size = llmax(box_dims[0],box_dims[1],box_dims[2]);
if (!mRootVolp->isAttachment())
{
LLVector3 pos_box_offset = point_to_box_offset(vol_pos, unshift_extents);
F32 offset_dist = pos_box_offset.length();
if (offset_dist > max_legal_offset && offset_dist > 0.f)
{
F32 target_dist = (offset_dist - max_legal_offset);
new_pos_fixup = (target_dist/offset_dist)*pos_box_offset;
}
if (new_pos_fixup != mPositionConstraintFixup)
{
LL_DEBUGS("ConstraintFix") << getFullname() << " pos fix, offset_dist " << offset_dist << " pos fixup "
<< new_pos_fixup << " was " << mPositionConstraintFixup << LL_ENDL;
LL_DEBUGS("ConstraintFix") << "vol_pos " << vol_pos << LL_ENDL;
LL_DEBUGS("ConstraintFix") << "extents " << extents[0] << " " << extents[1] << LL_ENDL;
LL_DEBUGS("ConstraintFix") << "unshift_extents " << unshift_extents[0] << " " << unshift_extents[1] << LL_ENDL;
}
}
if (box_size/mScaleConstraintFixup > max_legal_size)
new_scale_fixup = mScaleConstraintFixup*max_legal_size/box_size;
LL_DEBUGS("ConstraintFix") << getFullname() << " scale fix, box_size " << box_size << " fixup "
<< mScaleConstraintFixup << " max legal " << max_legal_size
<< " -> new scale " << new_scale_fixup << LL_ENDL;
Brad Payne (Vir Linden)
committed
}
}
}
Brad Payne (Vir Linden)
committed
void LLControlAvatar::matchVolumeTransform()
Brad Payne (Vir Linden)
committed
{
if (mRootVolp)
{
LLVector3 new_pos_fixup;
F32 new_scale_fixup;
getNewConstraintFixups(new_pos_fixup, new_scale_fixup);
mPositionConstraintFixup = new_pos_fixup;
mScaleConstraintFixup = new_scale_fixup;
if (mRootVolp->isAttachment())
{
LLVOAvatar *attached_av = mRootVolp->getAvatarAncestor();
if (attached_av)
{
LLViewerJointAttachment *attach = attached_av->getTargetAttachmentPoint(mRootVolp);
setPositionAgent(mRootVolp->getRenderPosition());
Brad Payne (Vir Linden)
committed
attach->updateWorldPRSParent();
LLVector3 joint_pos = attach->getWorldPosition();
LLQuaternion joint_rot = attach->getWorldRotation();
LLVector3 obj_pos = mRootVolp->mDrawable->getPosition();
LLQuaternion obj_rot = mRootVolp->mDrawable->getRotation();
obj_pos.rotVec(joint_rot);
mRoot->setWorldPosition(obj_pos + joint_pos);
Brad Payne (Vir Linden)
committed
mRoot->setWorldRotation(obj_rot * joint_rot);
Brad Payne (Vir Linden)
committed
setRotation(mRoot->getRotation());
F32 global_scale = gSavedSettings.getF32("AnimatedObjectsGlobalScale");
setGlobalScale(global_scale * mScaleConstraintFixup);
}
else
{
LL_WARNS_ONCE() << "can't find attached av!" << LL_ENDL;
}
}
else
{
Brad Payne (Vir Linden)
committed
LLVector3 vol_pos = mRootVolp->getRenderPosition();
Brad Payne (Vir Linden)
committed
// FIXME: Currently if you're doing something like playing an
// animation that moves the pelvis (on an avatar or
// animated object), the name tag and debug text will be
// left behind. Ideally setPosition() would follow the
// skeleton around in a smarter way, so name tags,
// complexity info and such line up better. Should defer
// this until avatars also get fixed.
Brad Payne (Vir Linden)
committed
Brad Payne (Vir Linden)
committed
LLQuaternion obj_rot;
if (mRootVolp->mDrawable)
{
obj_rot = mRootVolp->mDrawable->getRotation();
}
else
{
obj_rot = mRootVolp->getRotation();
}
Brad Payne (Vir Linden)
committed
LLMatrix3 bind_mat;
LLQuaternion bind_rot;
#define MATCH_BIND_SHAPE
#ifdef MATCH_BIND_SHAPE
// MAINT-8671 - based on a patch from Beq Janus
const LLMeshSkinInfo* skin_info = mRootVolp->getSkinInfo();
if (skin_info)
{
LL_DEBUGS("BindShape") << getFullname() << " bind shape " << skin_info->mBindShapeMatrix << LL_ENDL;
Brad Payne (Vir Linden)
committed
bind_rot = LLSkinningUtil::getUnscaledQuaternion(skin_info->mBindShapeMatrix);
Brad Payne (Vir Linden)
committed
}
#endif
setRotation(bind_rot*obj_rot);
mRoot->setWorldRotation(bind_rot*obj_rot);
setPositionAgent(vol_pos);
mRoot->setPosition(vol_pos + mPositionConstraintFixup);
Brad Payne (Vir Linden)
committed
F32 global_scale = gSavedSettings.getF32("AnimatedObjectsGlobalScale");
setGlobalScale(global_scale * mScaleConstraintFixup);
}
}
Brad Payne (Vir Linden)
committed
}
Brad Payne (Vir Linden)
committed
void LLControlAvatar::setGlobalScale(F32 scale)
{
if (scale <= 0.0)
{
LL_WARNS() << "invalid global scale " << scale << LL_ENDL;
return;
}
if (scale != mGlobalScale)
{
F32 adjust_scale = scale/mGlobalScale;
LL_INFOS() << "scale " << scale << " adjustment " << adjust_scale << LL_ENDL;
Brad Payne (Vir Linden)
committed
// should we be scaling from the pelvis or the root?
Brad Payne (Vir Linden)
committed
recursiveScaleJoint(mPelvisp,adjust_scale);
mGlobalScale = scale;
}
}
void LLControlAvatar::recursiveScaleJoint(LLJoint* joint, F32 factor)
{
joint->setScale(factor * joint->getScale());
for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
iter != joint->mChildren.end(); ++iter)
{
LLJoint* child = *iter;
recursiveScaleJoint(child, factor);
}
}
Brad Payne (Vir Linden)
committed
// Based on LLViewerJointAttachment::setupDrawable(), without the attaching part.
Brad Payne (Vir Linden)
committed
void LLControlAvatar::updateVolumeGeom()
Brad Payne (Vir Linden)
committed
{
Brad Payne (Vir Linden)
committed
if (!mRootVolp->mDrawable)
Brad Payne (Vir Linden)
committed
return;
Brad Payne (Vir Linden)
committed
if (mRootVolp->mDrawable->isActive())
Brad Payne (Vir Linden)
committed
{
Brad Payne (Vir Linden)
committed
mRootVolp->mDrawable->makeStatic(FALSE);
Brad Payne (Vir Linden)
committed
}
Brad Payne (Vir Linden)
committed
mRootVolp->mDrawable->makeActive();
gPipeline.markMoved(mRootVolp->mDrawable);
gPipeline.markTextured(mRootVolp->mDrawable); // face may need to change draw pool to/from POOL_HUD
mRootVolp->mDrawable->setState(LLDrawable::USE_BACKLIGHT);
Brad Payne (Vir Linden)
committed
Brad Payne (Vir Linden)
committed
LLViewerObject::const_child_list_t& child_list = mRootVolp->getChildren();
Brad Payne (Vir Linden)
committed
for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
iter != child_list.end(); ++iter)
{
LLViewerObject* childp = *iter;
if (childp && childp->mDrawable.notNull())
{
childp->mDrawable->setState(LLDrawable::USE_BACKLIGHT);
gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD
gPipeline.markMoved(childp->mDrawable);
}
}
Brad Payne (Vir Linden)
committed
gPipeline.markRebuild(mRootVolp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
mRootVolp->markForUpdate(TRUE);
Brad Payne (Vir Linden)
committed
Brad Payne (Vir Linden)
committed
// Note that attachment overrides aren't needed here, have already
// been applied at the time the mControlAvatar was created, in
// llvovolume.cpp.
Brad Payne (Vir Linden)
committed
matchVolumeTransform();
Brad Payne (Vir Linden)
committed
Brad Payne (Vir Linden)
committed
// Initial exploration of allowing scaling skeleton to match root
// prim bounding box. If enabled, would probably be controlled by
// an additional checkbox and default to off. Not enabled for
// initial release.
Brad Payne (Vir Linden)
committed
// What should the scale be? What we really want is the ratio
// between the scale at which the object was originally designed
// and rigged, and the scale to which it has been subsequently
// modified - for example, if the object has been scaled down by a
// factor of 2 then we should use 0.5 as the global scale. But we
// don't have the original scale stored anywhere, just the current
// scale. Possibilities - 1) remember the original scale
// somewhere, 2) add another field to let the user specify the
// global scale, 3) approximate the original scale by looking at
// the proportions of the skeleton after joint positions have
// been applied
//LLVector3 obj_scale = obj->getScale();
//F32 obj_scale_z = llmax(obj_scale[2],0.1f);
//setGlobalScale(obj_scale_z/2.0f); // roughly fit avatar height range (2m) into object height
Brad Payne (Vir Linden)
committed
}
LLControlAvatar *LLControlAvatar::createControlAvatar(LLVOVolume *obj)
{
LLControlAvatar *cav = (LLControlAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), CO_FLAG_CONTROL_AVATAR);
Brad Payne (Vir Linden)
committed
Brad Payne (Vir Linden)
committed
cav->mRootVolp = obj;
Brad Payne (Vir Linden)
committed
// Sync up position/rotation with object
Brad Payne (Vir Linden)
committed
cav->matchVolumeTransform();
Brad Payne (Vir Linden)
committed
return cav;
}
Brad Payne (Vir Linden)
committed
void LLControlAvatar::markForDeath()
{
mMarkedForDeath = true;
}
void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time)
{
if (mMarkedForDeath)
{
markDead();
mMarkedForDeath = false;
}
else
{
LLVOAvatar::idleUpdate(agent,time);
}
}
BOOL LLControlAvatar::updateCharacter(LLAgent &agent)
{
return LLVOAvatar::updateCharacter(agent);
}
Brad Payne (Vir Linden)
committed
//virtual
void LLControlAvatar::updateDebugText()
{
Brad Payne (Vir Linden)
committed
if (gSavedSettings.getBOOL("DebugAnimatedObjects"))
Brad Payne (Vir Linden)
committed
{
Brad Payne (Vir Linden)
committed
S32 total_linkset_count = 0;
if (mRootVolp)
Brad Payne (Vir Linden)
committed
{
Brad Payne (Vir Linden)
committed
total_linkset_count = 1 + mRootVolp->getChildren().size();
}
std::vector<LLVOVolume*> volumes;
getAnimatedVolumes(volumes);
S32 animated_volume_count = volumes.size();
std::string active_string;
Brad Payne (Vir Linden)
committed
std::string type_string;
std::string lod_string;
Brad Payne (Vir Linden)
committed
std::string animated_object_flag_string;
S32 total_tris = 0;
Brad Payne (Vir Linden)
committed
S32 total_verts = 0;
Brad Payne (Vir Linden)
committed
F32 est_tris = 0.f;
F32 est_streaming_tris = 0.f;
Brad Payne (Vir Linden)
committed
F32 streaming_cost = 0.f;
Brad Payne (Vir Linden)
committed
std::string cam_dist_string = "";
S32 cam_dist_count = 0;
F32 lod_radius = mRootVolp->mLODRadius;
Brad Payne (Vir Linden)
committed
for (std::vector<LLVOVolume*>::iterator it = volumes.begin();
it != volumes.end(); ++it)
{
LLVOVolume *volp = *it;
Brad Payne (Vir Linden)
committed
S32 verts = 0;
total_tris += volp->getTriangleCount(&verts);
total_verts += verts;
est_tris += volp->getEstTrianglesMax();
Brad Payne (Vir Linden)
committed
est_streaming_tris += volp->getEstTrianglesStreamingCost();
Brad Payne (Vir Linden)
committed
streaming_cost += volp->getStreamingCost();
lod_string += llformat("%d",volp->getLOD());
if (volp && volp->mDrawable)
Brad Payne (Vir Linden)
committed
{
Brad Payne (Vir Linden)
committed
bool is_animated_flag = volp->getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG;
if (is_animated_flag)
{
animated_object_flag_string += "1";
}
else
{
animated_object_flag_string += "0";
}
Brad Payne (Vir Linden)
committed
if (volp->mDrawable->isActive())
{
active_string += "A";
}
else
{
active_string += "S";
}
Brad Payne (Vir Linden)
committed
if (volp->isRiggedMesh())
{
Brad Payne (Vir Linden)
committed
// Rigged/animatable mesh
Brad Payne (Vir Linden)
committed
type_string += "R";
Brad Payne (Vir Linden)
committed
lod_radius = volp->mLODRadius;
Brad Payne (Vir Linden)
committed
}
else if (volp->isMesh())
{
// Static mesh
type_string += "M";
}
else
{
// Any other prim
type_string += "P";
}
Brad Payne (Vir Linden)
committed
if (cam_dist_count < 4)
{
cam_dist_string += LLStringOps::getReadableNumber(volp->mLODDistance) + "/" +
LLStringOps::getReadableNumber(volp->mLODAdjustedDistance) + " ";
cam_dist_count++;
}
Brad Payne (Vir Linden)
committed
}
else
{
Brad Payne (Vir Linden)
committed
active_string += "-";
Brad Payne (Vir Linden)
committed
type_string += "-";
Brad Payne (Vir Linden)
committed
}
}
addDebugText(llformat("CAV obj %d anim %d active %s impost %d upprd %d strcst %f",
Brad Payne (Vir Linden)
committed
total_linkset_count, animated_volume_count,
active_string.c_str(), (S32) isImpostor(), getUpdatePeriod(), streaming_cost));
Brad Payne (Vir Linden)
committed
addDebugText(llformat("types %s lods %s", type_string.c_str(), lod_string.c_str()));
Brad Payne (Vir Linden)
committed
addDebugText(llformat("flags %s", animated_object_flag_string.c_str()));
Brad Payne (Vir Linden)
committed
addDebugText(llformat("tris %d (est %.1f, streaming %.1f), verts %d", total_tris, est_tris, est_streaming_tris, total_verts));
Brad Payne (Vir Linden)
committed
addDebugText(llformat("pxarea %s rank %d", LLStringOps::getReadableNumber(getPixelArea()).c_str(), getVisibilityRank()));
Brad Payne (Vir Linden)
committed
addDebugText(llformat("lod_radius %s dists %s", LLStringOps::getReadableNumber(lod_radius).c_str(),cam_dist_string.c_str()));
Brad Payne (Vir Linden)
committed
if (mPositionConstraintFixup.length() > 0.0f || mScaleConstraintFixup != 1.0f)
Brad Payne (Vir Linden)
committed
{
Brad Payne (Vir Linden)
committed
addDebugText(llformat("pos fix (%.1f %.1f %.1f) scale %f",
mPositionConstraintFixup[0],
mPositionConstraintFixup[1],
mPositionConstraintFixup[2],
mScaleConstraintFixup));
Brad Payne (Vir Linden)
committed
}
#if 0
Brad Payne (Vir Linden)
committed
std::string region_name = "no region";
if (mRootVolp->getRegion())
{
region_name = mRootVolp->getRegion()->getName();
}
std::string skel_region_name = "skel no region";
if (getRegion())
{
skel_region_name = getRegion()->getName();
}
addDebugText(llformat("region %x %s skel %x %s",
mRootVolp->getRegion(), region_name.c_str(),
getRegion(), skel_region_name.c_str()));
#endif
Brad Payne (Vir Linden)
committed
}
Brad Payne (Vir Linden)
committed
LLVOAvatar::updateDebugText();
}
Brad Payne (Vir Linden)
committed
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
void LLControlAvatar::getAnimatedVolumes(std::vector<LLVOVolume*>& volumes)
{
if (!mRootVolp)
{
return;
}
volumes.push_back(mRootVolp);
LLViewerObject::const_child_list_t& child_list = mRootVolp->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 && child_volp->isAnimatedObject())
{
volumes.push_back(child_volp);
}
}
}
// This is called after an associated object receives an animation
// message. Combine the signaled animations for all associated objects
// and process any resulting state changes.
void LLControlAvatar::updateAnimations()
{
if (!mRootVolp)
{
Brad Payne (Vir Linden)
committed
LL_WARNS_ONCE("AnimatedObjectsNotify") << "No root vol" << LL_ENDL;
Brad Payne (Vir Linden)
committed
return;
}
std::vector<LLVOVolume*> volumes;
getAnimatedVolumes(volumes);
// Rebuild mSignaledAnimations from the associated volumes.
std::map<LLUUID, S32> anims;
for (std::vector<LLVOVolume*>::iterator vol_it = volumes.begin(); vol_it != volumes.end(); ++vol_it)
{
LLVOVolume *volp = *vol_it;
Brad Payne (Vir Linden)
committed
//LL_INFOS("AnimatedObjects") << "updating anim for vol " << volp->getID() << " root " << mRootVolp->getID() << LL_ENDL;
Brad Payne (Vir Linden)
committed
signaled_animation_map_t& signaled_animations = LLObjectSignaledAnimationMap::instance().getMap()[volp->getID()];
for (std::map<LLUUID,S32>::iterator anim_it = signaled_animations.begin();
anim_it != signaled_animations.end();
Brad Payne (Vir Linden)
committed
++anim_it)
{
std::map<LLUUID,S32>::iterator found_anim_it = anims.find(anim_it->first);
if (found_anim_it != anims.end())
{
// Animation already present, use the larger sequence id
anims[anim_it->first] = llmax(found_anim_it->second, anim_it->second);
}
else
{
// Animation not already present, use this sequence id.
anims[anim_it->first] = anim_it->second;
}
Brad Payne (Vir Linden)
committed
LL_DEBUGS("AnimatedObjectsNotify") << "found anim for vol " << volp->getID() << " anim " << anim_it->first << " root " << mRootVolp->getID() << LL_ENDL;
Brad Payne (Vir Linden)
committed
}
}
Brad Payne (Vir Linden)
committed
if (!mPlaying)
Brad Payne (Vir Linden)
committed
{
mPlaying = true;
Brad Payne (Vir Linden)
committed
//if (!mRootVolp->isAnySelected())
Brad Payne (Vir Linden)
committed
{
updateVolumeGeom();
mRootVolp->recursiveMarkForUpdate(TRUE);
}
}
Brad Payne (Vir Linden)
committed
Brad Payne (Vir Linden)
committed
mSignaledAnimations = anims;
Brad Payne (Vir Linden)
committed
processAnimationStateChanges();
}
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
// virtual
LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end,
S32 face,
BOOL pick_transparent,
BOOL pick_rigged,
S32* face_hit,
LLVector4a* intersection,
LLVector2* tex_coord,
LLVector4a* normal,
LLVector4a* tangent)
{
LLViewerObject* hit = NULL;
if (lineSegmentBoundingBox(start, end))
{
LLVector4a local_end = end;
LLVector4a local_intersection;
if (mRootVolp &&
mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
{
local_end = local_intersection;
if (intersection)
{
*intersection = local_intersection;
}
hit = mRootVolp;
}
}
return hit;
}
Brad Payne (Vir Linden)
committed
// virtual
std::string LLControlAvatar::getFullname() const
{
if (mRootVolp)
{
return "AO_" + mRootVolp->getID().getString();
}
else
{
return "AO_no_root_vol";
}
}
Brad Payne (Vir Linden)
committed
// virtual
bool LLControlAvatar::shouldRenderRigged() const
{
if (mRootVolp && mRootVolp->isAttachment())
{
LLVOAvatar *attached_av = mRootVolp->getAvatarAncestor();
if (attached_av)
{
return attached_av->shouldRenderRigged();
}
}
return true;
}
Brad Payne (Vir Linden)
committed
// 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();
}
}
return LLVOAvatar::isImpostor();
}