llvoavatar.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:225k
- LLGLState test(GL_ALPHA_TEST, should_alpha_mask);
- if (should_alpha_mask)
- {
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);
- }
- if (isTextureVisible(TEX_EYES_BAKED) || mIsDummy)
- {
- num_indices += mMeshLOD[MESH_ID_EYEBALL_LEFT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
- num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea, TRUE, mIsDummy);
- }
- gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
-
- return num_indices;
- }
- U32 LLVOAvatar::renderFootShadows()
- {
- U32 num_indices = 0;
- if (!mIsBuilt)
- {
- return 0;
- }
- if (isSelf() && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead()))
- {
- return 0;
- }
-
- if (!mIsBuilt)
- {
- return 0;
- }
-
- // Don't render foot shadows if your lower body is completely invisible.
- // (non-humanoid avatars rule!)
- if (!isTextureVisible(TEX_LOWER_BAKED))
- {
- return 0;
- }
- // Update the shadow, tractor, and text label geometry.
- if (mDrawable->isState(LLDrawable::REBUILD_SHADOW) && !isImpostor())
- {
- updateShadowFaces();
- mDrawable->clearState(LLDrawable::REBUILD_SHADOW);
- }
- U32 foot_mask = LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_TEXCOORD0;
- LLGLDepthTest test(GL_TRUE, GL_FALSE);
- //render foot shadows
- LLGLEnable blend(GL_BLEND);
- gGL.getTexUnit(0)->bind(mShadowImagep, TRUE);
- glColor4fv(mShadow0Facep->getRenderColor().mV);
- mShadow0Facep->renderIndexed(foot_mask);
- glColor4fv(mShadow1Facep->getRenderColor().mV);
- mShadow1Facep->renderIndexed(foot_mask);
-
- return num_indices;
- }
- U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel)
- {
- if (!mImpostor.isComplete())
- {
- return 0;
- }
- LLVector3 pos(getRenderPosition()+mImpostorOffset);
- LLVector3 at = (pos - LLViewerCamera::getInstance()->getOrigin());
- at.normalize();
- LLVector3 left = LLViewerCamera::getInstance()->getUpAxis() % at;
- LLVector3 up = at%left;
- left *= mImpostorDim.mV[0];
- up *= mImpostorDim.mV[1];
- LLGLEnable test(GL_ALPHA_TEST);
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
- gGL.color4ubv(color.mV);
- gGL.getTexUnit(diffuse_channel)->bind(&mImpostor);
- gGL.begin(LLRender::QUADS);
- gGL.texCoord2f(0,0);
- gGL.vertex3fv((pos+left-up).mV);
- gGL.texCoord2f(1,0);
- gGL.vertex3fv((pos-left-up).mV);
- gGL.texCoord2f(1,1);
- gGL.vertex3fv((pos-left+up).mV);
- gGL.texCoord2f(0,1);
- gGL.vertex3fv((pos+left+up).mV);
- gGL.end();
- gGL.flush();
- return 6;
- }
- //------------------------------------------------------------------------
- // LLVOAvatar::updateTextures()
- //------------------------------------------------------------------------
- void LLVOAvatar::updateTextures()
- {
- BOOL render_avatar = TRUE;
- if (mIsDummy || gNoRender)
- {
- return;
- }
- if( isSelf() )
- {
- render_avatar = TRUE;
- }
- else
- {
- render_avatar = isVisible() && !mCulled;
- }
- std::vector<BOOL> layer_baked;
- // GL NOT ACTIVE HERE - *TODO
- for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
- {
- layer_baked.push_back(isTextureDefined(mBakedTextureDatas[i].mTextureIndex));
- // bind the texture so that they'll be decoded slightly
- // inefficient, we can short-circuit this if we have to
- if (render_avatar && !gGLManager.mIsDisabled)
- {
- if (layer_baked[i] && !mBakedTextureDatas[i].mIsLoaded)
- {
- gGL.getTexUnit(0)->bind(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ));
- }
- }
- }
- mMaxPixelArea = 0.f;
- mMinPixelArea = 99999999.f;
- mHasGrey = FALSE; // debug
- for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++)
- {
- EWearableType wearable_type = LLVOAvatarDictionary::getTEWearableType((ETextureIndex)texture_index);
- U32 num_wearables = gAgentWearables.getWearableCount(wearable_type);
- const LLTextureEntry *te = getTE(texture_index);
- const F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
- LLViewerFetchedTexture *imagep = NULL;
- for (U32 wearable_index = 0; wearable_index < num_wearables; wearable_index++)
- {
- imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE);
- if (imagep)
- {
- const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)texture_index);
- const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
- if (texture_dict->mIsLocalTexture)
- {
- addLocalTextureStats((ETextureIndex)texture_index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]);
- }
- }
- }
- if (isIndexBakedTexture((ETextureIndex) texture_index))
- {
- const S32 boost_level = getAvatarBakedBoostLevel();
- imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index,0), TRUE);
- // Spam if this is a baked texture, not set to default image, without valid host info
- if (isIndexBakedTexture((ETextureIndex)texture_index)
- && imagep->getID() != IMG_DEFAULT_AVATAR
- && imagep->getID() != IMG_INVISIBLE
- && !imagep->getTargetHost().isOk())
- {
- LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture "
- << imagep->getID() << " for avatar "
- << (isSelf() ? "<myself>" : getID().asString())
- << " on host " << getRegion()->getHost() << llendl;
- }
- addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level );
- }
- }
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
- {
- setDebugText(llformat("%4.0f:%4.0f", fsqrtf(mMinPixelArea),fsqrtf(mMaxPixelArea)));
- }
-
- if( render_avatar )
- {
- mShadowImagep->addTextureStats(mPixelArea);
- }
- }
- void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerFetchedTexture* imagep,
- F32 texel_area_ratio, BOOL render_avatar, BOOL covered_by_baked, U32 index )
- {
- // No local texture stats for non-self avatars
- return;
- }
-
- void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level)
- {
- mMaxPixelArea = llmax(pixel_area, mMaxPixelArea);
- mMinPixelArea = llmin(pixel_area, mMinPixelArea);
- imagep->addTextureStats(pixel_area / texel_area_ratio);
- imagep->setBoostLevel(boost_level);
- }
- //virtual
- void LLVOAvatar::setImage(const U8 te, LLViewerTexture *imagep, const U32 index)
- {
- setTEImage(te, imagep);
- }
- //virtual
- LLViewerTexture* LLVOAvatar::getImage(const U8 te, const U32 index) const
- {
- return getTEImage(te);
- }
- //virtual
- const LLTextureEntry* LLVOAvatar::getTexEntry(const U8 te_num) const
- {
- return getTE(te_num);
- }
- //virtual
- void LLVOAvatar::setTexEntry(const U8 index, const LLTextureEntry &te)
- {
- setTE(index, te);
- }
- //-----------------------------------------------------------------------------
- // resolveHeight()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::resolveHeightAgent(const LLVector3 &in_pos_agent, LLVector3 &out_pos_agent, LLVector3 &out_norm)
- {
- LLVector3d in_pos_global, out_pos_global;
- in_pos_global = gAgent.getPosGlobalFromAgent(in_pos_agent);
- resolveHeightGlobal(in_pos_global, out_pos_global, out_norm);
- out_pos_agent = gAgent.getPosAgentFromGlobal(out_pos_global);
- }
- void LLVOAvatar::resolveRayCollisionAgent(const LLVector3d start_pt, const LLVector3d end_pt, LLVector3d &out_pos, LLVector3 &out_norm)
- {
- LLViewerObject *obj;
- LLWorld::getInstance()->resolveStepHeightGlobal(this, start_pt, end_pt, out_pos, out_norm, &obj);
- }
- void LLVOAvatar::resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos, LLVector3 &outNorm)
- {
- LLVector3d zVec(0.0f, 0.0f, 0.5f);
- LLVector3d p0 = inPos + zVec;
- LLVector3d p1 = inPos - zVec;
- LLViewerObject *obj;
- LLWorld::getInstance()->resolveStepHeightGlobal(this, p0, p1, outPos, outNorm, &obj);
- if (!obj)
- {
- mStepOnLand = TRUE;
- mStepMaterial = 0;
- mStepObjectVelocity.setVec(0.0f, 0.0f, 0.0f);
- }
- else
- {
- mStepOnLand = FALSE;
- mStepMaterial = obj->getMaterial();
- // We want the primitive velocity, not our velocity... (which actually subtracts the
- // step object velocity)
- LLVector3 angularVelocity = obj->getAngularVelocity();
- LLVector3 relativePos = gAgent.getPosAgentFromGlobal(outPos) - obj->getPositionAgent();
- LLVector3 linearComponent = angularVelocity % relativePos;
- // llinfos << "Linear Component of Rotation Velocity " << linearComponent << llendl;
- mStepObjectVelocity = obj->getVelocity() + linearComponent;
- }
- }
- //-----------------------------------------------------------------------------
- // getStepSound()
- //-----------------------------------------------------------------------------
- const LLUUID& LLVOAvatar::getStepSound() const
- {
- if ( mStepOnLand )
- {
- return sStepSoundOnLand;
- }
- return sStepSounds[mStepMaterial];
- }
- //-----------------------------------------------------------------------------
- // processAnimationStateChanges()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::processAnimationStateChanges()
- {
- LLMemType mt(LLMemType::MTYPE_AVATAR);
-
- if (gNoRender)
- {
- return;
- }
- if ( isAnyAnimationSignaled(AGENT_WALK_ANIMS, NUM_AGENT_WALK_ANIMS) )
- {
- startMotion(ANIM_AGENT_WALK_ADJUST);
- stopMotion(ANIM_AGENT_FLY_ADJUST);
- }
- else if (mInAir && !mIsSitting)
- {
- stopMotion(ANIM_AGENT_WALK_ADJUST);
- startMotion(ANIM_AGENT_FLY_ADJUST);
- }
- else
- {
- stopMotion(ANIM_AGENT_WALK_ADJUST);
- stopMotion(ANIM_AGENT_FLY_ADJUST);
- }
- if ( isAnyAnimationSignaled(AGENT_GUN_AIM_ANIMS, NUM_AGENT_GUN_AIM_ANIMS) )
- {
- startMotion(ANIM_AGENT_TARGET);
- stopMotion(ANIM_AGENT_BODY_NOISE);
- }
- else
- {
- stopMotion(ANIM_AGENT_TARGET);
- startMotion(ANIM_AGENT_BODY_NOISE);
- }
-
- // clear all current animations
- AnimIterator anim_it;
- for (anim_it = mPlayingAnimations.begin(); anim_it != mPlayingAnimations.end();)
- {
- AnimIterator found_anim = mSignaledAnimations.find(anim_it->first);
- // playing, but not signaled, so stop
- if (found_anim == mSignaledAnimations.end())
- {
- processSingleAnimationStateChange(anim_it->first, FALSE);
- mPlayingAnimations.erase(anim_it++);
- continue;
- }
- ++anim_it;
- }
- // start up all new anims
- for (anim_it = mSignaledAnimations.begin(); anim_it != mSignaledAnimations.end();)
- {
- AnimIterator found_anim = mPlayingAnimations.find(anim_it->first);
- // signaled but not playing, or different sequence id, start motion
- if (found_anim == mPlayingAnimations.end() || found_anim->second != anim_it->second)
- {
- if (processSingleAnimationStateChange(anim_it->first, TRUE))
- {
- mPlayingAnimations[anim_it->first] = anim_it->second;
- ++anim_it;
- continue;
- }
- }
- ++anim_it;
- }
- // clear source information for animations which have been stopped
- if (isSelf())
- {
- AnimSourceIterator source_it = mAnimationSources.begin();
- for (source_it = mAnimationSources.begin(); source_it != mAnimationSources.end();)
- {
- if (mSignaledAnimations.find(source_it->second) == mSignaledAnimations.end())
- {
- mAnimationSources.erase(source_it++);
- }
- else
- {
- ++source_it;
- }
- }
- }
- stop_glerror();
- }
- //-----------------------------------------------------------------------------
- // processSingleAnimationStateChange();
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL start )
- {
- LLMemType mt(LLMemType::MTYPE_AVATAR);
-
- BOOL result = FALSE;
- if ( start ) // start animation
- {
- if (anim_id == ANIM_AGENT_TYPE)
- {
- if (gAudiop)
- {
- LLVector3d char_pos_global = gAgent.getPosGlobalFromAgent(getCharacterPosition());
- if (LLViewerParcelMgr::getInstance()->canHearSound(char_pos_global)
- && !LLMuteList::getInstance()->isMuted(getID(), LLMute::flagObjectSounds))
- {
- // RN: uncomment this to play on typing sound at fixed volume once sound engine is fixed
- // to support both spatialized and non-spatialized instances of the same sound
- //if (isSelf())
- //{
- // gAudiop->triggerSound(LLUUID(gSavedSettings.getString("UISndTyping")), 1.0f, LLAudioEngine::AUDIO_TYPE_UI);
- //}
- //else
- {
- LLUUID sound_id = LLUUID(gSavedSettings.getString("UISndTyping"));
- gAudiop->triggerSound(sound_id, getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_SFX, char_pos_global);
- }
- }
- }
- }
- else if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED)
- {
- sitDown(TRUE);
- }
- if (startMotion(anim_id))
- {
- result = TRUE;
- }
- else
- {
- llwarns << "Failed to start motion!" << llendl;
- }
- }
- else //stop animation
- {
- if (anim_id == ANIM_AGENT_SIT_GROUND_CONSTRAINED)
- {
- sitDown(FALSE);
- }
- stopMotion(anim_id);
- result = TRUE;
- }
- return result;
- }
- //-----------------------------------------------------------------------------
- // isAnyAnimationSignaled()
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims) const
- {
- for (S32 i = 0; i < num_anims; i++)
- {
- if(mSignaledAnimations.find(anim_array[i]) != mSignaledAnimations.end())
- {
- return TRUE;
- }
- }
- return FALSE;
- }
- //-----------------------------------------------------------------------------
- // resetAnimations()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::resetAnimations()
- {
- LLKeyframeMotion::flushKeyframeCache();
- flushAllMotions();
- }
- //-----------------------------------------------------------------------------
- // startMotion()
- // id is the asset if of the animation to start
- // time_offset is the offset into the animation at which to start playing
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset)
- {
- LLMemType mt(LLMemType::MTYPE_AVATAR);
-
- // start special case female walk for female avatars
- if (getSex() == SEX_FEMALE)
- {
- if (id == ANIM_AGENT_WALK)
- {
- return LLCharacter::startMotion(ANIM_AGENT_FEMALE_WALK, time_offset);
- }
- else if (id == ANIM_AGENT_SIT)
- {
- return LLCharacter::startMotion(ANIM_AGENT_SIT_FEMALE, time_offset);
- }
- }
- if (isSelf() && id == ANIM_AGENT_AWAY)
- {
- gAgent.setAFK();
- }
- return LLCharacter::startMotion(id, time_offset);
- }
- //-----------------------------------------------------------------------------
- // stopMotion()
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate)
- {
- if (isSelf())
- {
- gAgent.onAnimStop(id);
- }
- if (id == ANIM_AGENT_WALK)
- {
- LLCharacter::stopMotion(ANIM_AGENT_FEMALE_WALK, stop_immediate);
- }
- else if (id == ANIM_AGENT_SIT)
- {
- LLCharacter::stopMotion(ANIM_AGENT_SIT_FEMALE, stop_immediate);
- }
- return LLCharacter::stopMotion(id, stop_immediate);
- }
- //-----------------------------------------------------------------------------
- // stopMotionFromSource()
- //-----------------------------------------------------------------------------
- // virtual
- void LLVOAvatar::stopMotionFromSource(const LLUUID& source_id)
- {
- }
- //-----------------------------------------------------------------------------
- // getVolumePos()
- //-----------------------------------------------------------------------------
- LLVector3 LLVOAvatar::getVolumePos(S32 joint_index, LLVector3& volume_offset)
- {
- if (joint_index > mNumCollisionVolumes)
- {
- return LLVector3::zero;
- }
- return mCollisionVolumes[joint_index].getVolumePos(volume_offset);
- }
- //-----------------------------------------------------------------------------
- // findCollisionVolume()
- //-----------------------------------------------------------------------------
- LLJoint* LLVOAvatar::findCollisionVolume(U32 volume_id)
- {
- if ((S32)volume_id > mNumCollisionVolumes)
- {
- return NULL;
- }
-
- return &mCollisionVolumes[volume_id];
- }
- //-----------------------------------------------------------------------------
- // findCollisionVolume()
- //-----------------------------------------------------------------------------
- S32 LLVOAvatar::getCollisionVolumeID(std::string &name)
- {
- for (S32 i = 0; i < mNumCollisionVolumes; i++)
- {
- if (mCollisionVolumes[i].getName() == name)
- {
- return i;
- }
- }
- return -1;
- }
- //-----------------------------------------------------------------------------
- // addDebugText()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::addDebugText(const std::string& text)
- {
- mDebugText.append(1, 'n');
- mDebugText.append(text);
- }
- //-----------------------------------------------------------------------------
- // getID()
- //-----------------------------------------------------------------------------
- const LLUUID& LLVOAvatar::getID()
- {
- return mID;
- }
- //-----------------------------------------------------------------------------
- // getJoint()
- //-----------------------------------------------------------------------------
- // RN: avatar joints are multi-rooted to include screen-based attachments
- LLJoint *LLVOAvatar::getJoint( const std::string &name )
- {
- LLJoint* jointp = mRoot.findJoint(name);
- return jointp;
- }
- //-----------------------------------------------------------------------------
- // getCharacterPosition()
- //-----------------------------------------------------------------------------
- LLVector3 LLVOAvatar::getCharacterPosition()
- {
- if (mDrawable.notNull())
- {
- return mDrawable->getPositionAgent();
- }
- else
- {
- return getPositionAgent();
- }
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatar::getCharacterRotation()
- //-----------------------------------------------------------------------------
- LLQuaternion LLVOAvatar::getCharacterRotation()
- {
- return getRotation();
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatar::getCharacterVelocity()
- //-----------------------------------------------------------------------------
- LLVector3 LLVOAvatar::getCharacterVelocity()
- {
- return getVelocity() - mStepObjectVelocity;
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatar::getCharacterAngularVelocity()
- //-----------------------------------------------------------------------------
- LLVector3 LLVOAvatar::getCharacterAngularVelocity()
- {
- return getAngularVelocity();
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatar::getGround()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::getGround(const LLVector3 &in_pos_agent, LLVector3 &out_pos_agent, LLVector3 &outNorm)
- {
- LLVector3d z_vec(0.0f, 0.0f, 1.0f);
- LLVector3d p0_global, p1_global;
- if (gNoRender || mIsDummy)
- {
- outNorm.setVec(z_vec);
- out_pos_agent = in_pos_agent;
- return;
- }
-
- p0_global = gAgent.getPosGlobalFromAgent(in_pos_agent) + z_vec;
- p1_global = gAgent.getPosGlobalFromAgent(in_pos_agent) - z_vec;
- LLViewerObject *obj;
- LLVector3d out_pos_global;
- LLWorld::getInstance()->resolveStepHeightGlobal(this, p0_global, p1_global, out_pos_global, outNorm, &obj);
- out_pos_agent = gAgent.getPosAgentFromGlobal(out_pos_global);
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatar::getTimeDilation()
- //-----------------------------------------------------------------------------
- F32 LLVOAvatar::getTimeDilation()
- {
- return mTimeDilation;
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatar::getPixelArea()
- //-----------------------------------------------------------------------------
- F32 LLVOAvatar::getPixelArea() const
- {
- if (mIsDummy)
- {
- return 100000.f;
- }
- return mPixelArea;
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatar::getHeadMesh()
- //-----------------------------------------------------------------------------
- LLPolyMesh* LLVOAvatar::getHeadMesh()
- {
- return mMeshLOD[MESH_ID_HEAD]->mMeshParts[0]->getMesh();
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatar::getUpperBodyMesh()
- //-----------------------------------------------------------------------------
- LLPolyMesh* LLVOAvatar::getUpperBodyMesh()
- {
- return mMeshLOD[MESH_ID_UPPER_BODY]->mMeshParts[0]->getMesh();
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatar::getPosGlobalFromAgent()
- //-----------------------------------------------------------------------------
- LLVector3d LLVOAvatar::getPosGlobalFromAgent(const LLVector3 &position)
- {
- return gAgent.getPosGlobalFromAgent(position);
- }
- //-----------------------------------------------------------------------------
- // getPosAgentFromGlobal()
- //-----------------------------------------------------------------------------
- LLVector3 LLVOAvatar::getPosAgentFromGlobal(const LLVector3d &position)
- {
- return gAgent.getPosAgentFromGlobal(position);
- }
- //-----------------------------------------------------------------------------
- // allocateCharacterJoints()
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::allocateCharacterJoints( U32 num )
- {
- deleteAndClearArray(mSkeleton);
- mNumJoints = 0;
- mSkeleton = new LLViewerJoint[num];
-
- for(S32 joint_num = 0; joint_num < (S32)num; joint_num++)
- {
- mSkeleton[joint_num].setJointNum(joint_num);
- }
- if (!mSkeleton)
- {
- return FALSE;
- }
- mNumJoints = num;
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // allocateCollisionVolumes()
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::allocateCollisionVolumes( U32 num )
- {
- deleteAndClearArray(mCollisionVolumes);
- mNumCollisionVolumes = 0;
- mCollisionVolumes = new LLViewerJointCollisionVolume[num];
- if (!mCollisionVolumes)
- {
- return FALSE;
- }
- mNumCollisionVolumes = num;
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // getCharacterJoint()
- //-----------------------------------------------------------------------------
- LLJoint *LLVOAvatar::getCharacterJoint( U32 num )
- {
- if ((S32)num >= mNumJoints
- || (S32)num < 0)
- {
- return NULL;
- }
- return (LLJoint*)&mSkeleton[num];
- }
- //-----------------------------------------------------------------------------
- // requestStopMotion()
- //-----------------------------------------------------------------------------
- // virtual
- void LLVOAvatar::requestStopMotion( LLMotion* motion )
- {
- // Only agent avatars should handle the stop motion notifications.
- }
- //-----------------------------------------------------------------------------
- // loadAvatar()
- //-----------------------------------------------------------------------------
- static LLFastTimer::DeclareTimer FTM_LOAD_AVATAR("Load Avatar");
- BOOL LLVOAvatar::loadAvatar()
- {
- // LLFastTimer t(FTM_LOAD_AVATAR);
-
- // avatar_skeleton.xml
- if( !buildSkeleton(sAvatarSkeletonInfo) )
- {
- llwarns << "avatar file: buildSkeleton() failed" << llendl;
- return FALSE;
- }
- // avatar_lad.xml : <skeleton>
- if( !loadSkeletonNode() )
- {
- llwarns << "avatar file: loadNodeSkeleton() failed" << llendl;
- return FALSE;
- }
-
- // avatar_lad.xml : <mesh>
- if( !loadMeshNodes() )
- {
- llwarns << "avatar file: loadNodeMesh() failed" << llendl;
- return FALSE;
- }
-
- // avatar_lad.xml : <global_color>
- if( sAvatarXmlInfo->mTexSkinColorInfo )
- {
- mTexSkinColor = new LLTexGlobalColor( this );
- if( !mTexSkinColor->setInfo( sAvatarXmlInfo->mTexSkinColorInfo ) )
- {
- llwarns << "avatar file: mTexSkinColor->setInfo() failed" << llendl;
- return FALSE;
- }
- }
- else
- {
- llwarns << "<global_color> name="skin_color" not found" << llendl;
- return FALSE;
- }
- if( sAvatarXmlInfo->mTexHairColorInfo )
- {
- mTexHairColor = new LLTexGlobalColor( this );
- if( !mTexHairColor->setInfo( sAvatarXmlInfo->mTexHairColorInfo ) )
- {
- llwarns << "avatar file: mTexHairColor->setInfo() failed" << llendl;
- return FALSE;
- }
- }
- else
- {
- llwarns << "<global_color> name="hair_color" not found" << llendl;
- return FALSE;
- }
- if( sAvatarXmlInfo->mTexEyeColorInfo )
- {
- mTexEyeColor = new LLTexGlobalColor( this );
- if( !mTexEyeColor->setInfo( sAvatarXmlInfo->mTexEyeColorInfo ) )
- {
- llwarns << "avatar file: mTexEyeColor->setInfo() failed" << llendl;
- return FALSE;
- }
- }
- else
- {
- llwarns << "<global_color> name="eye_color" not found" << llendl;
- return FALSE;
- }
-
- // avatar_lad.xml : <layer_set>
- if (sAvatarXmlInfo->mLayerInfoList.empty())
- {
- llwarns << "avatar file: missing <layer_set> node" << llendl;
- return FALSE;
- }
- if (sAvatarXmlInfo->mMorphMaskInfoList.empty())
- {
- llwarns << "avatar file: missing <morph_masks> node" << llendl;
- return FALSE;
- }
- // avatar_lad.xml : <morph_masks>
- for (LLVOAvatarXmlInfo::morph_info_list_t::iterator iter = sAvatarXmlInfo->mMorphMaskInfoList.begin();
- iter != sAvatarXmlInfo->mMorphMaskInfoList.end();
- ++iter)
- {
- LLVOAvatarXmlInfo::LLVOAvatarMorphInfo *info = *iter;
- EBakedTextureIndex baked = LLVOAvatarDictionary::findBakedByRegionName(info->mRegion);
- if (baked != BAKED_NUM_INDICES)
- {
- LLPolyMorphTarget *morph_param;
- const std::string *name = &info->mName;
- morph_param = (LLPolyMorphTarget *)(getVisualParam(name->c_str()));
- if (morph_param)
- {
- BOOL invert = info->mInvert;
- addMaskedMorph(baked, morph_param, invert, info->mLayer);
- }
- }
- }
- loadLayersets();
-
- // avatar_lad.xml : <driver_parameters>
- for (LLVOAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin();
- iter != sAvatarXmlInfo->mDriverInfoList.end();
- ++iter)
- {
- LLDriverParamInfo *info = *iter;
- LLDriverParam* driver_param = new LLDriverParam( this );
- if (driver_param->setInfo(info))
- {
- addVisualParam( driver_param );
- LLVisualParam*(LLVOAvatar::*avatar_function)(S32)const = &LLVOAvatar::getVisualParam;
- if( !driver_param->linkDrivenParams(boost::bind(avatar_function,(LLVOAvatar*)this,_1 ), false))
- {
- llwarns << "could not link driven params for avatar " << this->getFullname() << " id: " << driver_param->getID() << llendl;
- continue;
- }
- }
- else
- {
- delete driver_param;
- llwarns << "avatar file: driver_param->parseData() failed" << llendl;
- return FALSE;
- }
- }
- // Uncomment to enable avatar_lad.xml debugging.
- /* std::ofstream file;
- file.open("avatar_lad.log");
- for( LLViewerVisualParam* param = (LLViewerVisualParam*) getFirstVisualParam();
- param;
- param = (LLViewerVisualParam*) getNextVisualParam() )
- {
- param->getInfo()->toStream(file);
- file << std::endl;
- }
- file.close();*/
-
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // loadSkeletonNode(): loads <skeleton> node from XML tree
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::loadSkeletonNode ()
- {
- mRoot.addChild( &mSkeleton[0] );
- for (std::vector<LLViewerJoint *>::iterator iter = mMeshLOD.begin();
- iter != mMeshLOD.end();
- ++iter)
- {
- LLViewerJoint *joint = (LLViewerJoint *) *iter;
- joint->mUpdateXform = FALSE;
- joint->setMeshesToChildren();
- }
- mRoot.addChild(mMeshLOD[MESH_ID_HEAD]);
- mRoot.addChild(mMeshLOD[MESH_ID_EYELASH]);
- mRoot.addChild(mMeshLOD[MESH_ID_UPPER_BODY]);
- mRoot.addChild(mMeshLOD[MESH_ID_LOWER_BODY]);
- mRoot.addChild(mMeshLOD[MESH_ID_SKIRT]);
- mRoot.addChild(mMeshLOD[MESH_ID_HEAD]);
- LLViewerJoint *skull = (LLViewerJoint*)mRoot.findJoint("mSkull");
- if (skull)
- {
- skull->addChild(mMeshLOD[MESH_ID_HAIR] );
- }
- LLViewerJoint *eyeL = (LLViewerJoint*)mRoot.findJoint("mEyeLeft");
- if (eyeL)
- {
- eyeL->addChild( mMeshLOD[MESH_ID_EYEBALL_LEFT] );
- }
- LLViewerJoint *eyeR = (LLViewerJoint*)mRoot.findJoint("mEyeRight");
- if (eyeR)
- {
- eyeR->addChild( mMeshLOD[MESH_ID_EYEBALL_RIGHT] );
- }
- // SKELETAL DISTORTIONS
- {
- LLVOAvatarXmlInfo::skeletal_distortion_info_list_t::iterator iter;
- for (iter = sAvatarXmlInfo->mSkeletalDistortionInfoList.begin();
- iter != sAvatarXmlInfo->mSkeletalDistortionInfoList.end();
- ++iter)
- {
- LLPolySkeletalDistortionInfo *info = *iter;
- LLPolySkeletalDistortion *param = new LLPolySkeletalDistortion(this);
- if (!param->setInfo(info))
- {
- delete param;
- return FALSE;
- }
- else
- {
- addVisualParam(param);
- }
- }
- }
-
- // ATTACHMENTS
- {
- LLVOAvatarXmlInfo::attachment_info_list_t::iterator iter;
- for (iter = sAvatarXmlInfo->mAttachmentInfoList.begin();
- iter != sAvatarXmlInfo->mAttachmentInfoList.end();
- ++iter)
- {
- LLVOAvatarXmlInfo::LLVOAvatarAttachmentInfo *info = *iter;
- if (!isSelf() && info->mJointName == "mScreen")
- { //don't process screen joint for other avatars
- continue;
- }
- LLViewerJointAttachment* attachment = new LLViewerJointAttachment();
- attachment->setName(info->mName);
- LLJoint *parentJoint = getJoint(info->mJointName);
- if (!parentJoint)
- {
- llwarns << "No parent joint by name " << info->mJointName << " found for attachment point " << info->mName << llendl;
- delete attachment;
- continue;
- }
- if (info->mHasPosition)
- {
- attachment->setOriginalPosition(info->mPosition);
- }
- if (info->mHasRotation)
- {
- LLQuaternion rotation;
- rotation.setQuat(info->mRotationEuler.mV[VX] * DEG_TO_RAD,
- info->mRotationEuler.mV[VY] * DEG_TO_RAD,
- info->mRotationEuler.mV[VZ] * DEG_TO_RAD);
- attachment->setRotation(rotation);
- }
- int group = info->mGroup;
- if (group >= 0)
- {
- if (group < 0 || group >= 9)
- {
- llwarns << "Invalid group number (" << group << ") for attachment point " << info->mName << llendl;
- }
- else
- {
- attachment->setGroup(group);
- }
- }
- S32 attachmentID = info->mAttachmentID;
- if (attachmentID < 1 || attachmentID > 255)
- {
- llwarns << "Attachment point out of range [1-255]: " << attachmentID << " on attachment point " << info->mName << llendl;
- delete attachment;
- continue;
- }
- if (mAttachmentPoints.find(attachmentID) != mAttachmentPoints.end())
- {
- llwarns << "Attachment point redefined with id " << attachmentID << " on attachment point " << info->mName << llendl;
- delete attachment;
- continue;
- }
- attachment->setPieSlice(info->mPieMenuSlice);
- attachment->setVisibleInFirstPerson(info->mVisibleFirstPerson);
- attachment->setIsHUDAttachment(info->mIsHUDAttachment);
- mAttachmentPoints[attachmentID] = attachment;
- // now add attachment joint
- parentJoint->addChild(attachment);
- }
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // loadMeshNodes(): loads <mesh> nodes from XML tree
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::loadMeshNodes()
- {
- for (LLVOAvatarXmlInfo::mesh_info_list_t::const_iterator meshinfo_iter = sAvatarXmlInfo->mMeshInfoList.begin();
- meshinfo_iter != sAvatarXmlInfo->mMeshInfoList.end();
- ++meshinfo_iter)
- {
- const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo *info = *meshinfo_iter;
- const std::string &type = info->mType;
- S32 lod = info->mLOD;
- LLViewerJointMesh* mesh = NULL;
- U8 mesh_id = 0;
- BOOL found_mesh_id = FALSE;
- /* if (type == "hairMesh")
- switch(lod)
- case 0:
- mesh = &mHairMesh0; */
- for (LLVOAvatarDictionary::Meshes::const_iterator mesh_iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
- mesh_iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
- ++mesh_iter)
- {
- const EMeshIndex mesh_index = mesh_iter->first;
- const LLVOAvatarDictionary::MeshEntry *mesh_dict = mesh_iter->second;
- if (type.compare(mesh_dict->mName) == 0)
- {
- mesh_id = mesh_index;
- found_mesh_id = TRUE;
- break;
- }
- }
- if (found_mesh_id)
- {
- if (lod < (S32)mMeshLOD[mesh_id]->mMeshParts.size())
- {
- mesh = mMeshLOD[mesh_id]->mMeshParts[lod];
- }
- else
- {
- llwarns << "Avatar file: <mesh> has invalid lod setting " << lod << llendl;
- return FALSE;
- }
- }
- else
- {
- llwarns << "Ignoring unrecognized mesh type: " << type << llendl;
- return FALSE;
- }
- // llinfos << "Parsing mesh data for " << type << "..." << llendl;
- // If this isn't set to white (1.0), avatars will *ALWAYS* be darker than their surroundings.
- // Do not touch!!!
- mesh->setColor( 1.0f, 1.0f, 1.0f, 1.0f );
- LLPolyMesh *poly_mesh = NULL;
- if (!info->mReferenceMeshName.empty())
- {
- polymesh_map_t::const_iterator polymesh_iter = mMeshes.find(info->mReferenceMeshName);
- if (polymesh_iter != mMeshes.end())
- {
- poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName, polymesh_iter->second);
- poly_mesh->setAvatar(this);
- }
- else
- {
- // This should never happen
- LL_WARNS("Avatar") << "Could not find avatar mesh: " << info->mReferenceMeshName << LL_ENDL;
- }
- }
- else
- {
- poly_mesh = LLPolyMesh::getMesh(info->mMeshFileName);
- poly_mesh->setAvatar(this);
- }
- if( !poly_mesh )
- {
- llwarns << "Failed to load mesh of type " << type << llendl;
- return FALSE;
- }
- // Multimap insert
- mMeshes.insert(std::make_pair(info->mMeshFileName, poly_mesh));
-
- mesh->setMesh( poly_mesh );
- mesh->setLOD( info->mMinPixelArea );
- for (LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_list_t::const_iterator xmlinfo_iter = info->mPolyMorphTargetInfoList.begin();
- xmlinfo_iter != info->mPolyMorphTargetInfoList.end();
- ++xmlinfo_iter)
- {
- const LLVOAvatarXmlInfo::LLVOAvatarMeshInfo::morph_info_pair_t *info_pair = &(*xmlinfo_iter);
- LLPolyMorphTarget *param = new LLPolyMorphTarget(mesh->getMesh());
- if (!param->setInfo(info_pair->first))
- {
- delete param;
- return FALSE;
- }
- else
- {
- if (info_pair->second)
- {
- addSharedVisualParam(param);
- }
- else
- {
- addVisualParam(param);
- }
- }
- }
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // loadLayerSets()
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::loadLayersets()
- {
- BOOL success = TRUE;
- for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator layerset_iter = sAvatarXmlInfo->mLayerInfoList.begin();
- layerset_iter != sAvatarXmlInfo->mLayerInfoList.end();
- ++layerset_iter)
- {
- // Construct a layerset for each one specified in avatar_lad.xml and initialize it as such.
- LLTexLayerSetInfo *layerset_info = *layerset_iter;
- layerset_info->createVisualParams(this);
- }
- return success;
- }
- //-----------------------------------------------------------------------------
- // updateVisualParams()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::updateVisualParams()
- {
- if (gNoRender)
- {
- return;
- }
- setSex( (getVisualParamWeight( "male" ) > 0.5f) ? SEX_MALE : SEX_FEMALE );
- LLCharacter::updateVisualParams();
- if (mLastSkeletonSerialNum != mSkeletonSerialNum)
- {
- computeBodySize();
- mLastSkeletonSerialNum = mSkeletonSerialNum;
- mRoot.updateWorldMatrixChildren();
- }
- dirtyMesh();
- updateHeadOffset();
- }
- //-----------------------------------------------------------------------------
- // isActive()
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::isActive() const
- {
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // setPixelAreaAndAngle()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent)
- {
- LLMemType mt(LLMemType::MTYPE_AVATAR);
- if (mDrawable.isNull())
- {
- return;
- }
- const LLVector3* ext = mDrawable->getSpatialExtents();
- LLVector3 center = (ext[1] + ext[0]) * 0.5f;
- LLVector3 size = (ext[1]-ext[0])*0.5f;
- mImpostorPixelArea = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance());
- F32 range = mDrawable->mDistanceWRTCamera;
- if (range < 0.001f) // range == zero
- {
- mAppAngle = 180.f;
- }
- else
- {
- F32 radius = size.length();
- mAppAngle = (F32) atan2( radius, range) * RAD_TO_DEG;
- }
- // We always want to look good to ourselves
- if( isSelf() )
- {
- mPixelArea = llmax( mPixelArea, F32(getTexImageSize() / 16) );
- }
- }
- //-----------------------------------------------------------------------------
- // updateJointLODs()
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::updateJointLODs()
- {
- const F32 MAX_PIXEL_AREA = 100000000.f;
- F32 lod_factor = (sLODFactor * AVATAR_LOD_TWEAK_RANGE + (1.f - AVATAR_LOD_TWEAK_RANGE));
- F32 avatar_num_min_factor = clamp_rescale(sLODFactor, 0.f, 1.f, 0.25f, 0.6f);
- F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor);
- F32 area_scale = 0.16f;
- {
- if (isSelf())
- {
- if(gAgent.cameraCustomizeAvatar() || gAgent.cameraMouselook())
- {
- mAdjustedPixelArea = MAX_PIXEL_AREA;
- }
- else
- {
- mAdjustedPixelArea = mPixelArea*area_scale;
- }
- }
- else if (mIsDummy)
- {
- mAdjustedPixelArea = MAX_PIXEL_AREA;
- }
- else
- {
- // reported avatar pixel area is dependent on avatar render load, based on number of visible avatars
- mAdjustedPixelArea = (F32)mPixelArea * area_scale * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor;
- }
- // now select meshes to render based on adjusted pixel area
- BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE);
- if (res)
- {
- sNumLODChangesThisFrame++;
- dirtyMesh();
- return TRUE;
- }
- }
- return FALSE;
- }
- //-----------------------------------------------------------------------------
- // createDrawable()
- //-----------------------------------------------------------------------------
- LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline)
- {
- pipeline->allocDrawable(this);
- mDrawable->setLit(FALSE);
- LLDrawPoolAvatar *poolp = (LLDrawPoolAvatar*) gPipeline.getPool(LLDrawPool::POOL_AVATAR);
- // Only a single face (one per avatar)
- //this face will be splitted into several if its vertex buffer is too long.
- mDrawable->setState(LLDrawable::ACTIVE);
- mDrawable->addFace(poolp, NULL);
- mDrawable->setRenderType(LLPipeline::RENDER_TYPE_AVATAR);
-
- LLFace *facep;
- // Add faces for the foot shadows
- facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep);
- mShadow0Facep = facep;
- facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep);
- mShadow1Facep = facep;
- mNumInitFaces = mDrawable->getNumFaces() ;
- dirtyMesh();
- return mDrawable;
- }
- void LLVOAvatar::updateGL()
- {
- if (mMeshTexturesDirty)
- {
- updateMeshTextures();
- mMeshTexturesDirty = FALSE;
- }
- }
- //-----------------------------------------------------------------------------
- // updateGeometry()
- //-----------------------------------------------------------------------------
- static LLFastTimer::DeclareTimer FTM_UPDATE_AVATAR("Update Avatar");
- BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
- {
- LLFastTimer ftm(FTM_UPDATE_AVATAR);
- if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR)))
- {
- return TRUE;
- }
-
- if (!mMeshValid)
- {
- return TRUE;
- }
- if (!drawable)
- {
- llerrs << "LLVOAvatar::updateGeometry() called with NULL drawable" << llendl;
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // updateShadowFaces()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::updateShadowFaces()
- {
- LLFace *face0p = mShadow0Facep;
- LLFace *face1p = mShadow1Facep;
- //
- // render avatar shadows
- //
- if (mInAir || mUpdatePeriod >= IMPOSTOR_PERIOD)
- {
- face0p->setSize(0, 0);
- face1p->setSize(0, 0);
- return;
- }
- LLSprite sprite(mShadowImagep.notNull() ? mShadowImagep->getID() : LLUUID::null);
- sprite.setFollow(FALSE);
- const F32 cos_angle = gSky.getSunDirection().mV[2];
- F32 cos_elev = sqrt(1 - cos_angle * cos_angle);
- if (cos_angle < 0) cos_elev = -cos_elev;
- sprite.setSize(0.4f + cos_elev * 0.8f, 0.3f);
- LLVector3 sun_vec = gSky.mVOSkyp ? gSky.mVOSkyp->getToSun() : LLVector3(0.f, 0.f, 0.f);
- if (mShadowImagep->hasGLTexture())
- {
- LLVector3 normal;
- LLVector3d shadow_pos;
- LLVector3 shadow_pos_agent;
- F32 foot_height;
- if (mFootLeftp)
- {
- LLVector3 joint_world_pos = mFootLeftp->getWorldPosition();
- // this only does a ray straight down from the foot, as our client-side ray-tracing is very limited now
- // but we make an explicit ray trace call in expectation of future improvements
- resolveRayCollisionAgent(gAgent.getPosGlobalFromAgent(joint_world_pos),
- gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal);
- shadow_pos_agent = gAgent.getPosAgentFromGlobal(shadow_pos);
- foot_height = joint_world_pos.mV[VZ] - shadow_pos_agent.mV[VZ];
- // Pull sprite in direction of surface normal
- shadow_pos_agent += normal * SHADOW_OFFSET_AMT;
- // Render sprite
- sprite.setNormal(normal);
- if (isSelf() && gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
- {
- sprite.setColor(0.f, 0.f, 0.f, 0.f);
- }
- else
- {
- sprite.setColor(0.f, 0.f, 0.f, clamp_rescale(foot_height, MIN_SHADOW_HEIGHT, MAX_SHADOW_HEIGHT, 0.5f, 0.f));
- }
- sprite.setPosition(shadow_pos_agent);
- LLVector3 foot_to_knee = mKneeLeftp->getWorldPosition() - joint_world_pos;
- //foot_to_knee.normalize();
- foot_to_knee -= projected_vec(foot_to_knee, sun_vec);
- sprite.setYaw(azimuth(sun_vec - foot_to_knee));
-
- sprite.updateFace(*face0p);
- }
- if (mFootRightp)
- {
- LLVector3 joint_world_pos = mFootRightp->getWorldPosition();
- // this only does a ray straight down from the foot, as our client-side ray-tracing is very limited now
- // but we make an explicit ray trace call in expectation of future improvements
- resolveRayCollisionAgent(gAgent.getPosGlobalFromAgent(joint_world_pos),
- gAgent.getPosGlobalFromAgent(gSky.getSunDirection() + joint_world_pos), shadow_pos, normal);
- shadow_pos_agent = gAgent.getPosAgentFromGlobal(shadow_pos);
- foot_height = joint_world_pos.mV[VZ] - shadow_pos_agent.mV[VZ];
- // Pull sprite in direction of surface normal
- shadow_pos_agent += normal * SHADOW_OFFSET_AMT;
- // Render sprite
- sprite.setNormal(normal);
- if (isSelf() && gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
- {
- sprite.setColor(0.f, 0.f, 0.f, 0.f);
- }
- else
- {
- sprite.setColor(0.f, 0.f, 0.f, clamp_rescale(foot_height, MIN_SHADOW_HEIGHT, MAX_SHADOW_HEIGHT, 0.5f, 0.f));
- }
- sprite.setPosition(shadow_pos_agent);
- LLVector3 foot_to_knee = mKneeRightp->getWorldPosition() - joint_world_pos;
- //foot_to_knee.normalize();
- foot_to_knee -= projected_vec(foot_to_knee, sun_vec);
- sprite.setYaw(azimuth(sun_vec - foot_to_knee));
-
- sprite.updateFace(*face1p);
- }
- }
- }
- //-----------------------------------------------------------------------------
- // updateSexDependentLayerSets()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::updateSexDependentLayerSets( BOOL upload_bake )
- {
- invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
- invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake );
- invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, upload_bake );
- }
- //-----------------------------------------------------------------------------
- // dirtyMesh()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::dirtyMesh()
- {
- mDirtyMesh = TRUE;
- }
- //-----------------------------------------------------------------------------
- // hideSkirt()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::hideSkirt()
- {
- mMeshLOD[MESH_ID_SKIRT]->setVisible(FALSE, TRUE);
- }
- BOOL LLVOAvatar::setParent(LLViewerObject* parent)
- {
- BOOL ret ;
- if (parent == NULL)
- {
- getOffObject();
- ret = LLViewerObject::setParent(parent);
- if (isSelf())
- {
- gAgent.resetCamera();
- }
- }
- else
- {
- ret = LLViewerObject::setParent(parent);
- if(ret)
- {
- sitOnObject(parent);
- }
- }
- return ret ;
- }
- void LLVOAvatar::addChild(LLViewerObject *childp)
- {
- LLViewerObject::addChild(childp);
- if (childp->mDrawable)
- {
- attachObject(childp);
- }
- else
- {
- mPendingAttachment.push_back(childp);
- }
- }
- void LLVOAvatar::removeChild(LLViewerObject *childp)
- {
- LLViewerObject::removeChild(childp);
- if (!detachObject(childp))
- {
- llwarns << "Calling detach on non-attached object " << llendl;
- }
- }
- LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* viewer_object)
- {
- S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getState());
- LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);
- if (!attachment)
- {
- llwarns << "Object attachment point invalid: " << attachmentID << llendl;
- }
- return attachment;
- }
- //-----------------------------------------------------------------------------
- // attachObject()
- //-----------------------------------------------------------------------------
- const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
- {
- LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object);
- if (!attachment || !attachment->addObject(viewer_object))
- {
- return 0;
- }
- if (viewer_object->isSelected())
- {
- LLSelectMgr::getInstance()->updateSelectionCenter();
- LLSelectMgr::getInstance()->updatePointAt();
- }
- return attachment;
- }
- //-----------------------------------------------------------------------------
- // attachObject()
- //-----------------------------------------------------------------------------
- U32 LLVOAvatar::getNumAttachments() const
- {
- U32 num_attachments = 0;
- for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- const LLViewerJointAttachment *attachment_pt = (*iter).second;
- num_attachments += attachment_pt->getNumObjects();
- }
- return num_attachments;
- }
- //-----------------------------------------------------------------------------
- // canAttachMoreObjects()
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::canAttachMoreObjects() const
- {
- return (getNumAttachments() < MAX_AGENT_ATTACHMENTS);
- }
- //-----------------------------------------------------------------------------
- // lazyAttach()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::lazyAttach()
- {
- std::vector<LLPointer<LLViewerObject> > still_pending;
-
- for (U32 i = 0; i < mPendingAttachment.size(); i++)
- {
- if (mPendingAttachment[i]->mDrawable)
- {
- attachObject(mPendingAttachment[i]);
- }
- else
- {
- still_pending.push_back(mPendingAttachment[i]);
- }
- }
- mPendingAttachment = still_pending;
- }
- void LLVOAvatar::resetHUDAttachments()
- {
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment* attachment = iter->second;
- if (attachment->getIsHUDAttachment())
- {
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- const LLViewerObject* attached_object = (*attachment_iter);
- if (attached_object && attached_object->mDrawable.notNull())
- {
- gPipeline.markMoved(attached_object->mDrawable);
- }
- }
- }
- }
- }
- //-----------------------------------------------------------------------------
- // detachObject()
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)
- {
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment* attachment = iter->second;
- if (attachment->isObjectAttached(viewer_object))
- {
- attachment->removeObject(viewer_object);
- lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl;
- return TRUE;
- }
- }
- return FALSE;
- }
- //-----------------------------------------------------------------------------
- // sitDown()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::sitDown(BOOL bSitting)
- {
- mIsSitting = bSitting;
- if (isSelf())
- {
- // Update Movement Controls according to own Sitting mode
- LLFloaterMove::setSittingMode(bSitting);
- }
- }
- //-----------------------------------------------------------------------------
- // sitOnObject()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::sitOnObject(LLViewerObject *sit_object)
- {
- if (isSelf())
- {
- // Might be first sit
- //LLFirstUse::useSit();
- gAgent.setFlying(FALSE);
- gAgent.setThirdPersonHeadOffset(LLVector3::zero);
- //interpolate to new camera position
- gAgent.startCameraAnimation();
- // make sure we are not trying to autopilot
- gAgent.stopAutoPilot();
- gAgent.setupSitCamera();
- if (gAgent.getForceMouselook())
- {
- gAgent.changeCameraToMouselook();
- }
- }
- if (mDrawable.isNull())
- {
- return;
- }
- LLQuaternion inv_obj_rot = ~sit_object->getRenderRotation();
- LLVector3 obj_pos = sit_object->getRenderPosition();
- LLVector3 rel_pos = getRenderPosition() - obj_pos;
- rel_pos.rotVec(inv_obj_rot);
- mDrawable->mXform.setPosition(rel_pos);
- mDrawable->mXform.setRotation(mDrawable->getWorldRotation() * inv_obj_rot);
- gPipeline.markMoved(mDrawable, TRUE);
- sitDown(TRUE);
- mRoot.getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject
- mRoot.setPosition(getPosition());
- mRoot.updateWorldMatrixChildren();
- stopMotion(ANIM_AGENT_BODY_NOISE);
- }
- //-----------------------------------------------------------------------------
- // getOffObject()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::getOffObject()
- {
- if (mDrawable.isNull())
- {
- return;
- }
-
- LLViewerObject* sit_object = (LLViewerObject*)getParent();
- if (sit_object)
- {
- stopMotionFromSource(sit_object->getID());
- LLFollowCamMgr::setCameraActive(sit_object->getID(), FALSE);
- LLViewerObject::const_child_list_t& child_list = sit_object->getChildren();
- for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
- iter != child_list.end(); ++iter)
- {
- LLViewerObject* child_objectp = *iter;
- stopMotionFromSource(child_objectp->getID());
- LLFollowCamMgr::setCameraActive(child_objectp->getID(), FALSE);
- }
- }
- // assumes that transform will not be updated with drawable still having a parent
- LLVector3 cur_position_world = mDrawable->getWorldPosition();
- LLQuaternion cur_rotation_world = mDrawable->getWorldRotation();
- // set *local* position based on last *world* position, since we're unparenting the avatar
- mDrawable->mXform.setPosition(cur_position_world);
- mDrawable->mXform.setRotation(cur_rotation_world);
-
- gPipeline.markMoved(mDrawable, TRUE);
- sitDown(FALSE);
- mRoot.getXform()->setParent(NULL); // LLVOAvatar::getOffObject
- mRoot.setPosition(cur_position_world);
- mRoot.setRotation(cur_rotation_world);
- mRoot.getXform()->update();
- startMotion(ANIM_AGENT_BODY_NOISE);
- if (isSelf())
- {
- LLQuaternion av_rot = gAgent.getFrameAgent().getQuaternion();
- LLQuaternion obj_rot = sit_object ? sit_object->getRenderRotation() : LLQuaternion::DEFAULT;
- av_rot = av_rot * obj_rot;
- LLVector3 at_axis = LLVector3::x_axis;
- at_axis = at_axis * av_rot;
- at_axis.mV[VZ] = 0.f;
- at_axis.normalize();
- gAgent.resetAxes(at_axis);
- //reset orientation
- // mRoot.setRotation(avWorldRot);
- gAgent.setThirdPersonHeadOffset(LLVector3(0.f, 0.f, 1.f));
- gAgent.setSitCamera(LLUUID::null);
- }
- }
- //-----------------------------------------------------------------------------
- // findAvatarFromAttachment()
- //-----------------------------------------------------------------------------
- // static
- LLVOAvatar* LLVOAvatar::findAvatarFromAttachment( LLViewerObject* obj )
- {
- if( obj->isAttachment() )
- {
- do
- {
- obj = (LLViewerObject*) obj->getParent();
- }
- while( obj && !obj->isAvatar() );
- if( obj && !obj->isDead() )
- {
- return (LLVOAvatar*)obj;
- }
- }
- return NULL;
- }
- // warning: order(N) not order(1)
- S32 LLVOAvatar::getAttachmentCount()
- {
- S32 count = mAttachmentPoints.size();
- return count;
- }
- LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const
- {
- if (color_name=="skin_color" && mTexSkinColor)
- {
- return mTexSkinColor->getColor();
- }
- else if(color_name=="hair_color" && mTexHairColor)
- {
- return mTexHairColor->getColor();
- }
- if(color_name=="eye_color" && mTexEyeColor)
- {
- return mTexEyeColor->getColor();
- }
- else
- {
- // return LLColor4( .5f, .5f, .5f, .5f );
- return LLColor4( 0.f, 1.f, 1.f, 1.f ); // good debugging color
- }
- }
- // virtual
- void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL upload_result )
- {
- }
- void LLVOAvatar::invalidateAll()
- {
- }
- // virtual
- void LLVOAvatar::setCompositeUpdatesEnabled( BOOL b )
- {
- }
- void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL upload_bake )
- {
- if (global_color == mTexSkinColor)
- {
- invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
- invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, upload_bake );
- invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, upload_bake );
- }
- else if (global_color == mTexHairColor)
- {
- invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, upload_bake );
- invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet, upload_bake );
-
- // ! BACKWARDS COMPATIBILITY !
- // Fix for dealing with avatars from viewers that don't bake hair.
- if (!isTextureDefined(mBakedTextureDatas[BAKED_HAIR].mTextureIndex))
- {
- LLColor4 color = mTexHairColor->getColor();
- for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++)
- {
- mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
- }
- }
- }
- else if (global_color == mTexEyeColor)
- {
- // llinfos << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << llendl;
- invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet, upload_bake );
- }
- updateMeshTextures();
- }
- BOOL LLVOAvatar::isVisible() const
- {
- return mDrawable.notNull()
- && (mDrawable->isVisible() || mIsDummy);
- }
- // call periodically to keep isFullyLoaded up to date.
- // returns true if the value has changed.
- BOOL LLVOAvatar::updateIsFullyLoaded()
- {
- // a "heuristic" to determine if we have enough avatar data to render
- // (to avoid rendering a "Ruth" - DEV-3168)
- BOOL loading = FALSE;
- // do we have a shape?
- if (visualParamWeightsAreDefault())
- {
- loading = TRUE;
- }
- if (!isTextureDefined(TEX_LOWER_BAKED) ||
- !isTextureDefined(TEX_UPPER_BAKED) ||
- !isTextureDefined(TEX_HEAD_BAKED))
- {
- loading = TRUE;
- }
-
- updateRuthTimer(loading);
- return processFullyLoadedChange(loading);
- }
- void LLVOAvatar::updateRuthTimer(bool loading)
- {
- if (isSelf() || !loading)
- {
- return;
- }
- if (mPreviousFullyLoaded)
- {
- mRuthTimer.reset();
- }
-
- const F32 LOADING_TIMEOUT = 120.f;
- if (mRuthTimer.getElapsedTimeF32() > LOADING_TIMEOUT)
- {
- /*
- llinfos << "Ruth Timer timeout: Missing texture data for '" << getFullname() << "' "
- << "( Params loaded : " << !visualParamWeightsAreDefault() << " ) "
- << "( Lower : " << isTextureDefined(TEX_LOWER_BAKED) << " ) "
- << "( Upper : " << isTextureDefined(TEX_UPPER_BAKED) << " ) "
- << "( Head : " << isTextureDefined(TEX_HEAD_BAKED) << " )."
- << llendl;
- */
- LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID());
- mRuthTimer.reset();
- }
- }
- BOOL LLVOAvatar::processFullyLoadedChange(bool loading)
- {
- // we wait a little bit before giving the all clear,
- // to let textures settle down
- const F32 PAUSE = 1.f;
- if (loading)
- mFullyLoadedTimer.reset();
-
- mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > PAUSE);
-
- // did our loading state "change" from last call?
- const S32 UPDATE_RATE = 30;
- BOOL changed =
- ((mFullyLoaded != mPreviousFullyLoaded) || // if the value is different from the previous call
- (!mFullyLoadedInitialized) || // if we've never been called before
- (mFullyLoadedFrameCounter % UPDATE_RATE == 0)); // every now and then issue a change
- mPreviousFullyLoaded = mFullyLoaded;
- mFullyLoadedInitialized = TRUE;
- mFullyLoadedFrameCounter++;
-
- return changed;
- }
- BOOL LLVOAvatar::isFullyLoaded() const
- {
- if (gSavedSettings.getBOOL("RenderUnloadedAvatar"))
- return TRUE;
- else
- return mFullyLoaded;
- }
- //-----------------------------------------------------------------------------
- // findMotion()
- //-----------------------------------------------------------------------------
- LLMotion* LLVOAvatar::findMotion(const LLUUID& id) const
- {
- return mMotionController.findMotion(id);
- }
- //-----------------------------------------------------------------------------
- // updateMeshTextures()
- // Uses the current TE values to set the meshes' and layersets' textures.
- //-----------------------------------------------------------------------------
- void LLVOAvatar::updateMeshTextures()
- {
- // llinfos << "updateMeshTextures" << llendl;
- if (gNoRender) return;
- // if user has never specified a texture, assign the default
- for (U32 i=0; i < getNumTEs(); i++)
- {
- const LLViewerTexture* te_image = getImage(i, 0);
- if(!te_image || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT))
- {
- setImage(i, LLViewerTextureManager::getFetchedTexture(i == TEX_HAIR ? IMG_DEFAULT : IMG_DEFAULT_AVATAR), 0); // IMG_DEFAULT_AVATAR = a special texture that's never rendered.
- }
- }
- const BOOL self_customizing = isSelf() && gAgent.cameraCustomizeAvatar(); // During face edit mode, we don't use baked textures
- const BOOL other_culled = !isSelf() && mCulled;
- std::vector<BOOL> is_layer_baked;
- is_layer_baked.resize(mBakedTextureDatas.size(), false);
- std::vector<BOOL> use_lkg_baked_layer; // lkg = "last known good"
- use_lkg_baked_layer.resize(mBakedTextureDatas.size(), false);
- for (U32 i=0; i < mBakedTextureDatas.size(); i++)
- {
- is_layer_baked[i] = isTextureDefined(mBakedTextureDatas[i].mTextureIndex);
- if (!other_culled)
- {
- // When an avatar is changing clothes and not in Appearance mode,
- // use the last-known good baked texture until it finish the first
- // render of the new layerset.
- use_lkg_baked_layer[i] = (!is_layer_baked[i]
- && (mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR)
- && mBakedTextureDatas[i].mTexLayerSet
- && !mBakedTextureDatas[i].mTexLayerSet->getComposite()->isInitialized());
- if (use_lkg_baked_layer[i])
- {
- mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(TRUE);
- }
- }
- else
- {
- use_lkg_baked_layer[i] = (!is_layer_baked[i]
- && mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR);
- if (mBakedTextureDatas[i].mTexLayerSet)
- {
- mBakedTextureDatas[i].mTexLayerSet->destroyComposite();
- }
- }
- }
- // Turn on alpha masking correctly for yourself and other avatars on 1.23+
- mSupportsAlphaLayers = isSelf() || is_layer_baked[BAKED_HAIR];
- // Baked textures should be requested from the sim this avatar is on. JC
- const LLHost target_host = getObjectHost();
- if (!target_host.isOk())
- {
- llwarns << "updateMeshTextures: invalid host for object: " << getID() << llendl;
- }
-
- for (U32 i=0; i < mBakedTextureDatas.size(); i++)
- {
- if (use_lkg_baked_layer[i] && !self_customizing )
- {
- LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTextureFromHost( mBakedTextureDatas[i].mLastTextureIndex, target_host );
- mBakedTextureDatas[i].mIsUsed = TRUE;
- for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++)
- {
- mBakedTextureDatas[i].mMeshes[k]->setTexture( baked_img );
- }
- }
- else if (!self_customizing && is_layer_baked[i])
- {
- LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ;
- if( baked_img->getID() == mBakedTextureDatas[i].mLastTextureIndex )
- {
- // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing).
- useBakedTexture( baked_img->getID() );
- }
- else
- {
- mBakedTextureDatas[i].mIsLoaded = FALSE;
- if ( (baked_img->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) )
- {
- baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));
- }
- baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ) );
- }
- }
- else if (mBakedTextureDatas[i].mTexLayerSet
- && !other_culled)
- {
- mBakedTextureDatas[i].mTexLayerSet->createComposite();
- mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled( TRUE );
- mBakedTextureDatas[i].mIsUsed = FALSE;
- for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++)
- {
- mBakedTextureDatas[i].mMeshes[k]->setLayerSet( mBakedTextureDatas[i].mTexLayerSet );
- }
- }
- }
- // set texture and color of hair manually if we are not using a baked image.
- // This can happen while loading hair for yourself, or for clients that did not
- // bake a hair texture. Still needed for yourself after 1.22 is depricated.
- if (!is_layer_baked[BAKED_HAIR] || self_customizing)
- {
- const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1);
- LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 );
- for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++)
- {
- mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
- mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setTexture( hair_img );
- }
- }
-
-
- for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
- baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
- ++baked_iter)
- {
- const EBakedTextureIndex baked_index = baked_iter->first;
- const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second;
-
- for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
- local_tex_iter != baked_dict->mLocalTextures.end();
- ++local_tex_iter)
- {
- const ETextureIndex texture_index = *local_tex_iter;
- const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureDatas[baked_index].mIsLoaded) || other_culled;
- if (isSelf())
- {
- setBakedReady(texture_index, is_baked_ready);
- }
- }
- }
- removeMissingBakedTextures();
- }
- // virtual
- //-----------------------------------------------------------------------------
- // setLocalTexture()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::setLocalTexture( ETextureIndex type, LLViewerTexture* in_tex, BOOL baked_version_ready, U32 index )
- {
- // invalid for anyone but self
- llassert(0);
- }
- //virtual
- void LLVOAvatar::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index)
- {
- // invalid for anyone but self
- llassert(0);
- }
- void LLVOAvatar::addChat(const LLChat& chat)
- {
- std::deque<LLChat>::iterator chat_iter;
- mChats.push_back(chat);
- S32 chat_length = 0;
- for( chat_iter = mChats.begin(); chat_iter != mChats.end(); ++chat_iter)
- {
- chat_length += chat_iter->mText.size();
- }
- // remove any excess chat
- chat_iter = mChats.begin();
- while ((chat_length > MAX_BUBBLE_CHAT_LENGTH || mChats.size() > MAX_BUBBLE_CHAT_UTTERANCES) && chat_iter != mChats.end())
- {
- chat_length -= chat_iter->mText.size();
- mChats.pop_front();
- chat_iter = mChats.begin();
- }
- mChatTimer.reset();
- }
- void LLVOAvatar::clearChat()
- {
- mChats.clear();
- }
- // adds a morph mask to the appropriate baked texture structure
- void LLVOAvatar::addMaskedMorph(EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer)
- {
- if (index < BAKED_NUM_INDICES)
- {
- LLMaskedMorph *morph = new LLMaskedMorph(morph_target, invert, layer);
- mBakedTextureDatas[index].mMaskedMorphs.push_front(morph);
- }
- }
- // returns TRUE if morph masks are present and not valid for a given baked texture, FALSE otherwise
- BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index)
- {
- if (index >= BAKED_NUM_INDICES)
- {
- return FALSE;
- }
- if (!mBakedTextureDatas[index].mMaskedMorphs.empty())
- {
- if (isSelf())
- {
- LLTexLayerSet *layer_set = mBakedTextureDatas[index].mTexLayerSet;
- if (layer_set)
- {
- return !layer_set->isMorphValid();
- }
- }
- else
- {
- return FALSE;
- }
- }
- return FALSE;
- }
- void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index)
- {
- if (index >= BAKED_NUM_INDICES)
- {
- llwarns << "invalid baked texture index passed to applyMorphMask" << llendl;
- return;
- }
- for (morph_list_t::const_iterator iter = mBakedTextureDatas[index].mMaskedMorphs.begin();
- iter != mBakedTextureDatas[index].mMaskedMorphs.end(); ++iter)
- {
- const LLMaskedMorph* maskedMorph = (*iter);
- maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert);
- }
- }
- //-----------------------------------------------------------------------------
- // releaseComponentTextures()
- // release any component texture UUIDs for which we have a baked texture
- // ! BACKWARDS COMPATIBILITY !
- // This is only called for non-self avatars, it can be taken out once component
- // textures aren't communicated by non-self avatars.
- //-----------------------------------------------------------------------------
- void LLVOAvatar::releaseComponentTextures()
- {
- // ! BACKWARDS COMPATIBILITY !
- // Detect if the baked hair texture actually wasn't sent, and if so set to default
- if (isTextureDefined(TEX_HAIR_BAKED) && getImage(TEX_HAIR_BAKED,0)->getID() == getImage(TEX_SKIRT_BAKED,0)->getID())
- {
- if (getImage(TEX_HAIR_BAKED,0)->getID() != IMG_INVISIBLE)
- {
- // Regression case of messaging system. Expected 21 textures, received 20. last texture is not valid so set to default
- setTETexture(TEX_HAIR_BAKED, IMG_DEFAULT_AVATAR);
- }
- }
- for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
- {
- const LLVOAvatarDictionary::BakedEntry * bakedDicEntry = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
- // skip if this is a skirt and av is not wearing one, or if we don't have a baked texture UUID
- if (!isTextureDefined(bakedDicEntry->mTextureIndex)
- && ( (baked_index != BAKED_SKIRT) || isWearingWearableType(WT_SKIRT) ))
- {
- continue;
- }
- for (U8 texture = 0; texture < bakedDicEntry->mLocalTextures.size(); texture++)
- {
- const U8 te = (ETextureIndex)bakedDicEntry->mLocalTextures[texture];
- setTETexture(te, IMG_DEFAULT_AVATAR);
- }
- }
- }
- //static
- BOOL LLVOAvatar::teToColorParams( ETextureIndex te, U32 *param_name )
- {
- switch( te )
- {
- case TEX_UPPER_SHIRT:
- param_name[0] = 803; //"shirt_red";
- param_name[1] = 804; //"shirt_green";
- param_name[2] = 805; //"shirt_blue";
- break;
- case TEX_LOWER_PANTS:
- param_name[0] = 806; //"pants_red";
- param_name[1] = 807; //"pants_green";
- param_name[2] = 808; //"pants_blue";
- break;
- case TEX_LOWER_SHOES:
- param_name[0] = 812; //"shoes_red";
- param_name[1] = 813; //"shoes_green";
- param_name[2] = 817; //"shoes_blue";
- break;
- case TEX_LOWER_SOCKS:
- param_name[0] = 818; //"socks_red";
- param_name[1] = 819; //"socks_green";
- param_name[2] = 820; //"socks_blue";
- break;
- case TEX_UPPER_JACKET:
- case TEX_LOWER_JACKET:
- param_name[0] = 834; //"jacket_red";
- param_name[1] = 835; //"jacket_green";
- param_name[2] = 836; //"jacket_blue";
- break;
- case TEX_UPPER_GLOVES:
- param_name[0] = 827; //"gloves_red";
- param_name[1] = 829; //"gloves_green";
- param_name[2] = 830; //"gloves_blue";
- break;
- case TEX_UPPER_UNDERSHIRT:
- param_name[0] = 821; //"undershirt_red";
- param_name[1] = 822; //"undershirt_green";
- param_name[2] = 823; //"undershirt_blue";
- break;
-
- case TEX_LOWER_UNDERPANTS:
- param_name[0] = 824; //"underpants_red";
- param_name[1] = 825; //"underpants_green";
- param_name[2] = 826; //"underpants_blue";
- break;
- case TEX_SKIRT:
- param_name[0] = 921; //"skirt_red";
- param_name[1] = 922; //"skirt_green";
- param_name[2] = 923; //"skirt_blue";
- break;
- default:
- llassert(0);
- return FALSE;
- }
- return TRUE;
- }
- void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL upload_bake )
- {
- U32 param_name[3];
- if( teToColorParams( te, param_name ) )
- {
- setVisualParamWeight( param_name[0], new_color.mV[VX], upload_bake );
- setVisualParamWeight( param_name[1], new_color.mV[VY], upload_bake );
- setVisualParamWeight( param_name[2], new_color.mV[VZ], upload_bake );
- }
- }
- LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te )
- {
- LLColor4 color;
- U32 param_name[3];
- if( teToColorParams( te, param_name ) )
- {
- color.mV[VX] = getVisualParamWeight( param_name[0] );
- color.mV[VY] = getVisualParamWeight( param_name[1] );
- color.mV[VZ] = getVisualParamWeight( param_name[2] );
- }
- return color;
- }
- // static
- LLColor4 LLVOAvatar::getDummyColor()
- {
- return DUMMY_COLOR;
- }
- void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const
- {
- /* const char* te_name[] = {
- "TEX_HEAD_BODYPAINT ",
- "TEX_UPPER_SHIRT ", */
- llinfos << (isSelf() ? "Self: " : "Other: ") << context << llendl;
- for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
- iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- ++iter)
- {
- const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
- // TODO: handle multiple textures for self
- const LLViewerTexture* te_image = getImage(iter->first,0);
- if( !te_image )
- {
- llinfos << " " << texture_dict->mName << ": null ptr" << llendl;
- }
- else if( te_image->getID().isNull() )
- {
- llinfos << " " << texture_dict->mName << ": null UUID" << llendl;
- }
- else if( te_image->getID() == IMG_DEFAULT )
- {
- llinfos << " " << texture_dict->mName << ": IMG_DEFAULT" << llendl;
- }
- else if( te_image->getID() == IMG_DEFAULT_AVATAR )
- {
- llinfos << " " << texture_dict->mName << ": IMG_DEFAULT_AVATAR" << llendl;
- }
- else
- {
- llinfos << " " << texture_dict->mName << ": " << te_image->getID() << llendl;
- }
- }
- }
- // Unlike most wearable functions, this works for both self and other.
- BOOL LLVOAvatar::isWearingWearableType(EWearableType type) const
- {
- if (mIsDummy) return TRUE;
- switch(type)
- {
- case WT_SHAPE:
- case WT_SKIN:
- case WT_HAIR:
- case WT_EYES:
- return TRUE; // everyone has all bodyparts
- default:
- break; // Do nothing
- }
- /* switch(type)
- case WT_SHIRT:
- indicator_te = TEX_UPPER_SHIRT; */
- for (LLVOAvatarDictionary::Textures::const_iterator tex_iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
- tex_iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- ++tex_iter)
- {
- const LLVOAvatarDictionary::TextureEntry *texture_dict = tex_iter->second;
- if (texture_dict->mWearableType == type)
- {
- // If you're checking another avatar's clothing, you don't have component textures.
- // Thus, you must check to see if the corresponding baked texture is defined.
- // NOTE: this is a poor substitute if you actually want to know about individual pieces of clothing
- // this works for detecting a skirt (most important), but is ineffective at any piece of clothing that
- // gets baked into a texture that always exists (upper or lower).
- if (texture_dict->mIsUsedByBakedTexture)
- {
- const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
- return isTextureDefined(LLVOAvatarDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex);
- }
- return FALSE;
- }
- }
- return FALSE;
- }
- //-----------------------------------------------------------------------------
- // clampAttachmentPositions()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::clampAttachmentPositions()
- {
- if (isDead())
- {
- return;
- }
- for (attachment_map_t::iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment* attachment = iter->second;
- if (attachment)
- {
- attachment->clampObjectPosition();
- }
- }
- }
- BOOL LLVOAvatar::hasHUDAttachment() const
- {
- for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment* attachment = iter->second;
- if (attachment->getIsHUDAttachment() && attachment->getNumObjects() > 0)
- {
- return TRUE;
- }
- }
- return FALSE;
- }
- LLBBox LLVOAvatar::getHUDBBox() const
- {
- LLBBox bbox;
- for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment* attachment = iter->second;
- if (attachment->getIsHUDAttachment())
- {
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- const LLViewerObject* attached_object = (*attachment_iter);
- if (attached_object == NULL)
- {
- llwarns << "HUD attached object is NULL!" << llendl;
- continue;
- }
- // initialize bounding box to contain identity orientation and center point for attached object
- bbox.addPointLocal(attached_object->getPosition());
- // add rotated bounding box for attached object
- bbox.addBBoxAgent(attached_object->getBoundingBoxAgent());
- 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)
- {
- const LLViewerObject* child_objectp = *iter;
- bbox.addBBoxAgent(child_objectp->getBoundingBoxAgent());
- }
- }
- }
- }
- return bbox;
- }
- void LLVOAvatar::rebuildHUD()
- {
- }
- //-----------------------------------------------------------------------------
- // onFirstTEMessageReceived()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::onFirstTEMessageReceived()
- {
- if( !mFirstTEMessageReceived )
- {
- mFirstTEMessageReceived = TRUE;
- for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
- {
- const BOOL layer_baked = isTextureDefined(mBakedTextureDatas[i].mTextureIndex);
- // Use any baked textures that we have even if they haven't downloaded yet.
- // (That is, don't do a transition from unbaked to baked.)
- if (layer_baked)
- {
- LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ;
- mBakedTextureDatas[i].mLastTextureIndex = image->getID();
- // If we have more than one texture for the other baked layers, we'll want to call this for them too.
- if ( (image->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) )
- {
- image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ));
- }
- image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ) );
- }
- }
- mMeshTexturesDirty = TRUE;
- gPipeline.markGLRebuild(this);
- }
- }
- //-----------------------------------------------------------------------------
- // processAvatarAppearance()
- //-----------------------------------------------------------------------------
- void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
- {
- if (gSavedSettings.getBOOL("BlockAvatarAppearanceMessages"))
- {
- llwarns << "Blocking AvatarAppearance message" << llendl;
- return;
- }
-
- LLMemType mt(LLMemType::MTYPE_AVATAR);
- // llinfos << "processAvatarAppearance start " << mID << llendl;
- BOOL is_first_appearance_message = !mFirstAppearanceMessageReceived;
- mFirstAppearanceMessageReceived = TRUE;
- if( isSelf() )
- {
- llwarns << "Received AvatarAppearance for self" << llendl;
- if( mFirstTEMessageReceived )
- {
- // llinfos << "processAvatarAppearance end " << mID << llendl;
- return;
- }
- }
- if (gNoRender)
- {
- return;
- }
- ESex old_sex = getSex();
- // llinfos << "LLVOAvatar::processAvatarAppearance()" << llendl;
- // dumpAvatarTEs( "PRE processAvatarAppearance()" );
- unpackTEMessage(mesgsys, _PREHASH_ObjectData);
- // dumpAvatarTEs( "POST processAvatarAppearance()" );
- // prevent the overwriting of valid baked textures with invalid baked textures
- for (U8 baked_index = 0; baked_index < mBakedTextureDatas.size(); baked_index++)
- {
- if (!isTextureDefined(mBakedTextureDatas[baked_index].mTextureIndex)
- && mBakedTextureDatas[baked_index].mLastTextureIndex != IMG_DEFAULT
- && baked_index != BAKED_SKIRT)
- {
- setTEImage(mBakedTextureDatas[baked_index].mTextureIndex,
- LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
- }
- }
- if( !is_first_appearance_message )
- {
- onFirstTEMessageReceived();
- }
- setCompositeUpdatesEnabled( FALSE );
- mMeshTexturesDirty = TRUE;
- gPipeline.markGLRebuild(this);
- // ! BACKWARDS COMPATIBILITY !
- // Non-self avatars will no longer have component textures
- if (!isSelf())
- {
- releaseComponentTextures();
- }
-
-
- // parse visual params
- S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam);
- if( num_blocks > 1 )
- {
- BOOL params_changed = FALSE;
- BOOL interp_params = FALSE;
-
- LLVisualParam* param = getFirstVisualParam();
- if (!param)
- {
- llwarns << "No visual params!" << llendl;
- }
- else
- {
- for( S32 i = 0; i < num_blocks; i++ )
- {
- while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) )
- {
- param = getNextVisualParam();
- }
-
- if( !param )
- {
- llwarns << "Number of params in AvatarAppearance msg does not match number of params in avatar xml file." << llendl;
- return;
- }
- U8 value;
- mesgsys->getU8Fast(_PREHASH_VisualParam, _PREHASH_ParamValue, value, i);
- F32 newWeight = U8_to_F32(value, param->getMinWeight(), param->getMaxWeight());
- if (is_first_appearance_message || (param->getWeight() != newWeight))
- {
- //llinfos << "Received update for param " << param->getDisplayName() << " at value " << newWeight << llendl;
- params_changed = TRUE;
- if(is_first_appearance_message)
- {
- param->setWeight(newWeight, FALSE);
- }
- else
- {
- interp_params = TRUE;
- param->setAnimationTarget(newWeight, FALSE);
- }
- }
- param = getNextVisualParam();
- }
- }
- while( param && (param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) )
- {
- param = getNextVisualParam();
- }
- if( param )
- {
- llwarns << "Number of params in AvatarAppearance msg does not match number of params in avatar xml file." << llendl;
- return;
- }
- if (params_changed)
- {
- if (interp_params)
- {
- startAppearanceAnimation();
- }
- updateVisualParams();
- ESex new_sex = getSex();
- if( old_sex != new_sex )
- {
- updateSexDependentLayerSets( FALSE );
- }
- }
- }
- else
- {
- llwarns << "AvatarAppearance msg received without any parameters, object: " << getID() << llendl;
- }
- setCompositeUpdatesEnabled( TRUE );
- llassert( getSex() == ((getVisualParamWeight( "male" ) > 0.5f) ? SEX_MALE : SEX_FEMALE) );
- // If all of the avatars are completely baked, release the global image caches to conserve memory.
- LLVOAvatar::cullAvatarsByPixelArea();
- // llinfos << "processAvatarAppearance end " << mID << llendl;
- }
- // static
- void LLVOAvatar::getAnimLabels( LLDynamicArray<std::string>* labels )
- {
- S32 i;
- for( i = 0; i < gUserAnimStatesCount; i++ )
- {
- labels->put( LLAnimStateLabels::getStateLabel( gUserAnimStates[i].mName ) );
- }
- // Special case to trigger away (AFK) state
- labels->put( "Away From Keyboard" );
- }
- // static
- void LLVOAvatar::getAnimNames( LLDynamicArray<std::string>* names )
- {
- S32 i;
- for( i = 0; i < gUserAnimStatesCount; i++ )
- {
- names->put( std::string(gUserAnimStates[i].mName) );
- }
- // Special case to trigger away (AFK) state
- names->put( "enter_away_from_keyboard_state" );
- }
- void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
- {
- if (!userdata) return;
- //llinfos << "onBakedTextureMasksLoaded: " << src_vi->getID() << llendl;
- const LLMemType mt(LLMemType::MTYPE_AVATAR);
- const LLUUID id = src_vi->getID();
-
- LLTextureMaskData* maskData = (LLTextureMaskData*) userdata;
- LLVOAvatar* self = (LLVOAvatar*) gObjectList.findObject( maskData->mAvatarID );
- // if discard level is 2 less than last discard level we processed, or we hit 0,
- // then generate morph masks
- if(self && success && (discard_level < maskData->mLastDiscardLevel - 2 || discard_level == 0))
- {
- if(aux_src && aux_src->getComponents() == 1)
- {
- if (!aux_src->getData())
- {
- llerrs << "No auxiliary source data for onBakedTextureMasksLoaded" << llendl;
- return;
- }
- U32 gl_name;
- LLImageGL::generateTextures(1, &gl_name );
- stop_glerror();
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, gl_name);
- stop_glerror();
- LLImageGL::setManualImage(
- GL_TEXTURE_2D, 0, GL_ALPHA8,
- aux_src->getWidth(), aux_src->getHeight(),
- GL_ALPHA, GL_UNSIGNED_BYTE, aux_src->getData());
- stop_glerror();
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
- /* if( id == head_baked->getID() )
- if (self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet)
- //llinfos << "onBakedTextureMasksLoaded for head " << id << " discard = " << discard_level << llendl;
- self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1);
- maskData->mLastDiscardLevel = discard_level; */
- BOOL found_texture_id = false;
- for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
- iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- ++iter)
- {
- const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
- if (texture_dict->mIsUsedByBakedTexture)
- {
- const ETextureIndex texture_index = iter->first;
- const LLViewerTexture *baked_img = self->getImage(texture_index, 0);
- if (baked_img && id == baked_img->getID())
- {
- const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
- self->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1, baked_index);
- maskData->mLastDiscardLevel = discard_level;
- if (self->mBakedTextureDatas[baked_index].mMaskTexName)
- {
- LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName));
- }
- self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name;
- found_texture_id = true;
- break;
- }
- }
- }
- if (!found_texture_id)
- {
- llinfos << "onBakedTextureMasksLoaded(): unexpected image id: " << id << llendl;
- }
- self->dirtyMesh();
- }
- else
- {
- // this can happen when someone uses an old baked texture possibly provided by
- // viewer-side baked texture caching
- llwarns << "Masks loaded callback but NO aux source!" << llendl;
- }
- }
- if (final || !success)
- {
- delete maskData;
- }
- }
- // static
- void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata )
- {
- LLUUID *avatar_idp = (LLUUID *)userdata;
- LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp);
- if (!success && selfp)
- {
- selfp->removeMissingBakedTextures();
- }
- if (final || !success )
- {
- delete avatar_idp;
- }
- }
- void LLVOAvatar::onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata)
- {
- //llinfos << "onBakedTextureLoaded: " << src_vi->getID() << llendl;
- LLUUID id = src_vi->getID();
- LLUUID *avatar_idp = (LLUUID *)userdata;
- LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp);
- if (selfp && !success)
- {
- selfp->removeMissingBakedTextures();
- }
- if( final || !success )
- {
- delete avatar_idp;
- }
- if( selfp && success && final )
- {
- selfp->useBakedTexture( id );
- }
- }
- // Called when baked texture is loaded and also when we start up with a baked texture
- void LLVOAvatar::useBakedTexture( const LLUUID& id )
- {
- /* if(id == head_baked->getID())
- mHeadBakedLoaded = TRUE;
- mLastHeadBakedID = id;
- mHeadMesh0.setTexture( head_baked );
- mHeadMesh1.setTexture( head_baked ); */
- for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
- {
- LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 );
- if (id == image_baked->getID())
- {
- mBakedTextureDatas[i].mIsLoaded = true;
- mBakedTextureDatas[i].mLastTextureIndex = id;
- mBakedTextureDatas[i].mIsUsed = true;
- for (U32 k = 0; k < mBakedTextureDatas[i].mMeshes.size(); k++)
- {
- mBakedTextureDatas[i].mMeshes[k]->setTexture( image_baked );
- }
- if (mBakedTextureDatas[i].mTexLayerSet)
- {
- //mBakedTextureDatas[i].mTexLayerSet->destroyComposite();
- }
- const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i);
- for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin();
- local_tex_iter != baked_dict->mLocalTextures.end();
- ++local_tex_iter)
- {
- if (isSelf()) setBakedReady(*local_tex_iter, TRUE);
- }
- // ! BACKWARDS COMPATIBILITY !
- // Workaround for viewing avatars from old viewers that haven't baked hair textures.
- // This is paired with similar code in updateMeshTextures that sets hair mesh color.
- if (i == BAKED_HAIR)
- {
- for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++)
- {
- mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f );
- }
- }
- }
- }
- dirtyMesh();
- }
- // static
- void LLVOAvatar::dumpArchetypeXML( void* )
- {
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- LLAPRFile outfile ;
- outfile.open(gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"new archetype.xml"), LL_APR_WB );
- apr_file_t* file = outfile.getFileHandle() ;
- if (!file)
- {
- return;
- }
- apr_file_printf( file, "<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>n" );
- apr_file_printf( file, "<linden_genepool version="1.0">n" );
- apr_file_printf( file, "nt<archetype name="???">n" );
- // only body parts, not clothing.
- for (S32 type = WT_SHAPE; type <= WT_EYES; type++)
- {
- const std::string& wearable_name = LLWearableDictionary::getTypeName((EWearableType)type);
- apr_file_printf( file, "ntt<!-- wearable: %s -->n", wearable_name.c_str() );
- for (LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam())
- {
- LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param;
- if( (viewer_param->getWearableType() == type) &&
- (viewer_param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) )
- {
- apr_file_printf(file, "tt<param id="%d" name="%s" value="%.3f"/>n",
- viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getWeight());
- }
- }
- for (U8 te = 0; te < TEX_NUM_INDICES; te++)
- {
- if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te) == type)
- {
- // MULTIPLE_WEARABLES: extend to multiple wearables?
- LLViewerTexture* te_image = avatar->getImage((ETextureIndex)te, 0);
- if( te_image )
- {
- std::string uuid_str;
- te_image->getID().toString( uuid_str );
- apr_file_printf( file, "tt<texture te="%i" uuid="%s"/>n", te, uuid_str.c_str());
- }
- }
- }
- }
- apr_file_printf( file, "t</archetype>n" );
- apr_file_printf( file, "n</linden_genepool>n" );
- }
- void LLVOAvatar::setVisibilityRank(U32 rank)
- {
- if (mDrawable.isNull() || mDrawable->isDead())
- {
- // do nothing
- return;
- }
- mVisibilityRank = rank;
- }
- // Assumes LLVOAvatar::sInstances has already been sorted.
- S32 LLVOAvatar::getUnbakedPixelAreaRank()
- {
- S32 rank = 1;
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- LLVOAvatar* inst = (LLVOAvatar*) *iter;
- if (inst == this)
- {
- return rank;
- }
- else if (!inst->isDead() && !inst->isFullyBaked())
- {
- rank++;
- }
- }
- llassert(0);
- return 0;
- }
- struct CompareScreenAreaGreater
- {
- BOOL operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs)
- {
- return lhs->getPixelArea() > rhs->getPixelArea();
- }
- };
- // static
- void LLVOAvatar::cullAvatarsByPixelArea()
- {
- std::sort(LLCharacter::sInstances.begin(), LLCharacter::sInstances.end(), CompareScreenAreaGreater());
-
- // Update the avatars that have changed status
- U32 rank = 0;
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- LLVOAvatar* inst = (LLVOAvatar*) *iter;
- BOOL culled;
- if (inst->isSelf() || inst->isFullyBaked())
- {
- culled = FALSE;
- }
- else
- {
- culled = TRUE;
- }
- if (inst->mCulled != culled)
- {
- inst->mCulled = culled;
- lldebugs << "avatar " << inst->getID() << (culled ? " start culled" : " start not culled" ) << llendl;
- inst->updateMeshTextures();
- }
- if (inst->isSelf())
- {
- inst->setVisibilityRank(0);
- }
- else if (inst->mDrawable.notNull() && inst->mDrawable->isVisible())
- {
- inst->setVisibilityRank(rank++);
- }
- }
- S32 grey_avatars = 0;
- if (LLVOAvatar::areAllNearbyInstancesBaked(grey_avatars))
- {
- LLVOAvatar::deleteCachedImages(false);
- }
- else
- {
- if (gFrameTimeSeconds != sUnbakedUpdateTime) // only update once per frame
- {
- sUnbakedUpdateTime = gFrameTimeSeconds;
- sUnbakedTime += gFrameIntervalSeconds;
- }
- if (grey_avatars > 0)
- {
- if (gFrameTimeSeconds != sGreyUpdateTime) // only update once per frame
- {
- sGreyUpdateTime = gFrameTimeSeconds;
- sGreyTime += gFrameIntervalSeconds;
- }
- }
- }
- }
- void LLVOAvatar::startAppearanceAnimation()
- {
- if(!mAppearanceAnimating)
- {
- mAppearanceAnimating = TRUE;
- mAppearanceMorphTimer.reset();
- mLastAppearanceBlendTime = 0.f;
- }
- }
- // virtual
- void LLVOAvatar::removeMissingBakedTextures()
- {
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatarXmlInfo
- //-----------------------------------------------------------------------------
- LLVOAvatar::LLVOAvatarXmlInfo::LLVOAvatarXmlInfo()
- : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0)
- {
- }
- LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo()
- {
- std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer());
- std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer());
- std::for_each(mAttachmentInfoList.begin(), mAttachmentInfoList.end(), DeletePointer());
- deleteAndClear(mTexSkinColorInfo);
- deleteAndClear(mTexHairColorInfo);
- deleteAndClear(mTexEyeColorInfo);
- std::for_each(mLayerInfoList.begin(), mLayerInfoList.end(), DeletePointer());
- std::for_each(mDriverInfoList.begin(), mDriverInfoList.end(), DeletePointer());
- std::for_each(mMorphMaskInfoList.begin(), mMorphMaskInfoList.end(), DeletePointer());
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatarBoneInfo::parseXml()
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
- {
- if (node->hasName("bone"))
- {
- mIsJoint = TRUE;
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- if (!node->getFastAttributeString(name_string, mName))
- {
- llwarns << "Bone without name" << llendl;
- return FALSE;
- }
- }
- else if (node->hasName("collision_volume"))
- {
- mIsJoint = FALSE;
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- if (!node->getFastAttributeString(name_string, mName))
- {
- mName = "Collision Volume";
- }
- }
- else
- {
- llwarns << "Invalid node " << node->getName() << llendl;
- return FALSE;
- }
- static LLStdStringHandle pos_string = LLXmlTree::addAttributeString("pos");
- if (!node->getFastAttributeVector3(pos_string, mPos))
- {
- llwarns << "Bone without position" << llendl;
- return FALSE;
- }
- static LLStdStringHandle rot_string = LLXmlTree::addAttributeString("rot");
- if (!node->getFastAttributeVector3(rot_string, mRot))
- {
- llwarns << "Bone without rotation" << llendl;
- return FALSE;
- }
-
- static LLStdStringHandle scale_string = LLXmlTree::addAttributeString("scale");
- if (!node->getFastAttributeVector3(scale_string, mScale))
- {
- llwarns << "Bone without scale" << llendl;
- return FALSE;
- }
- if (mIsJoint)
- {
- static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot");
- if (!node->getFastAttributeVector3(pivot_string, mPivot))
- {
- llwarns << "Bone without pivot" << llendl;
- return FALSE;
- }
- }
- // parse children
- LLXmlTreeNode* child;
- for( child = node->getFirstChild(); child; child = node->getNextChild() )
- {
- LLVOAvatarBoneInfo *child_info = new LLVOAvatarBoneInfo;
- if (!child_info->parseXml(child))
- {
- delete child_info;
- return FALSE;
- }
- mChildList.push_back(child_info);
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // LLVOAvatarSkeletonInfo::parseXml()
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)
- {
- static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones");
- if (!node->getFastAttributeS32(num_bones_string, mNumBones))
- {
- llwarns << "Couldn't find number of bones." << llendl;
- return FALSE;
- }
- static LLStdStringHandle num_collision_volumes_string = LLXmlTree::addAttributeString("num_collision_volumes");
- node->getFastAttributeS32(num_collision_volumes_string, mNumCollisionVolumes);
- LLXmlTreeNode* child;
- for( child = node->getFirstChild(); child; child = node->getNextChild() )
- {
- LLVOAvatarBoneInfo *info = new LLVOAvatarBoneInfo;
- if (!info->parseXml(child))
- {
- delete info;
- llwarns << "Error parsing bone in skeleton file" << llendl;
- return FALSE;
- }
- mBoneInfoList.push_back(info);
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root)
- {
- LLXmlTreeNode* node = root->getChildByName( "skeleton" );
- if( !node )
- {
- llwarns << "avatar file: missing <skeleton>" << llendl;
- return FALSE;
- }
- LLXmlTreeNode* child;
- // SKELETON DISTORTIONS
- for (child = node->getChildByName( "param" );
- child;
- child = node->getNextNamedChild())
- {
- if (!child->getChildByName("param_skeleton"))
- {
- if (child->getChildByName("param_morph"))
- {
- llwarns << "Can't specify morph param in skeleton definition." << llendl;
- }
- else
- {
- llwarns << "Unknown param type." << llendl;
- }
- continue;
- }
-
- LLPolySkeletalDistortionInfo *info = new LLPolySkeletalDistortionInfo;
- if (!info->parseXml(child))
- {
- delete info;
- return FALSE;
- }
- mSkeletalDistortionInfoList.push_back(info);
- }
- // ATTACHMENT POINTS
- for (child = node->getChildByName( "attachment_point" );
- child;
- child = node->getNextNamedChild())
- {
- LLVOAvatarAttachmentInfo* info = new LLVOAvatarAttachmentInfo();
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- if (!child->getFastAttributeString(name_string, info->mName))
- {
- llwarns << "No name supplied for attachment point." << llendl;
- delete info;
- continue;
- }
- static LLStdStringHandle joint_string = LLXmlTree::addAttributeString("joint");
- if (!child->getFastAttributeString(joint_string, info->mJointName))
- {
- llwarns << "No bone declared in attachment point " << info->mName << llendl;
- delete info;
- continue;
- }
- static LLStdStringHandle position_string = LLXmlTree::addAttributeString("position");
- if (child->getFastAttributeVector3(position_string, info->mPosition))
- {
- info->mHasPosition = TRUE;
- }
- static LLStdStringHandle rotation_string = LLXmlTree::addAttributeString("rotation");
- if (child->getFastAttributeVector3(rotation_string, info->mRotationEuler))
- {
- info->mHasRotation = TRUE;
- }
- static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group");
- if (child->getFastAttributeS32(group_string, info->mGroup))
- {
- if (info->mGroup == -1)
- info->mGroup = -1111; // -1 = none parsed, < -1 = bad value
- }
- static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id");
- if (!child->getFastAttributeS32(id_string, info->mAttachmentID))
- {
- llwarns << "No id supplied for attachment point " << info->mName << llendl;
- delete info;
- continue;
- }
- static LLStdStringHandle slot_string = LLXmlTree::addAttributeString("pie_slice");
- child->getFastAttributeS32(slot_string, info->mPieMenuSlice);
-
- static LLStdStringHandle visible_in_first_person_string = LLXmlTree::addAttributeString("visible_in_first_person");
- child->getFastAttributeBOOL(visible_in_first_person_string, info->mVisibleFirstPerson);
- static LLStdStringHandle hud_attachment_string = LLXmlTree::addAttributeString("hud");
- child->getFastAttributeBOOL(hud_attachment_string, info->mIsHUDAttachment);
- mAttachmentInfoList.push_back(info);
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // parseXmlMeshNodes(): parses <mesh> nodes from XML tree
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root)
- {
- for (LLXmlTreeNode* node = root->getChildByName( "mesh" );
- node;
- node = root->getNextNamedChild())
- {
- LLVOAvatarMeshInfo *info = new LLVOAvatarMeshInfo;
- // attribute: type
- static LLStdStringHandle type_string = LLXmlTree::addAttributeString("type");
- if( !node->getFastAttributeString( type_string, info->mType ) )
- {
- llwarns << "Avatar file: <mesh> is missing type attribute. Ignoring element. " << llendl;
- delete info;
- return FALSE; // Ignore this element
- }
-
- static LLStdStringHandle lod_string = LLXmlTree::addAttributeString("lod");
- if (!node->getFastAttributeS32( lod_string, info->mLOD ))
- {
- llwarns << "Avatar file: <mesh> is missing lod attribute. Ignoring element. " << llendl;
- delete info;
- return FALSE; // Ignore this element
- }
- static LLStdStringHandle file_name_string = LLXmlTree::addAttributeString("file_name");
- if( !node->getFastAttributeString( file_name_string, info->mMeshFileName ) )
- {
- llwarns << "Avatar file: <mesh> is missing file_name attribute. Ignoring: " << info->mType << llendl;
- delete info;
- return FALSE; // Ignore this element
- }
- static LLStdStringHandle reference_string = LLXmlTree::addAttributeString("reference");
- node->getFastAttributeString( reference_string, info->mReferenceMeshName );
-
- // attribute: min_pixel_area
- static LLStdStringHandle min_pixel_area_string = LLXmlTree::addAttributeString("min_pixel_area");
- static LLStdStringHandle min_pixel_width_string = LLXmlTree::addAttributeString("min_pixel_width");
- if (!node->getFastAttributeF32( min_pixel_area_string, info->mMinPixelArea ))
- {
- F32 min_pixel_area = 0.1f;
- if (node->getFastAttributeF32( min_pixel_width_string, min_pixel_area ))
- {
- // this is square root of pixel area (sensible to use linear space in defining lods)
- min_pixel_area = min_pixel_area * min_pixel_area;
- }
- info->mMinPixelArea = min_pixel_area;
- }
-
- // Parse visual params for this node only if we haven't already
- for (LLXmlTreeNode* child = node->getChildByName( "param" );
- child;
- child = node->getNextNamedChild())
- {
- if (!child->getChildByName("param_morph"))
- {
- if (child->getChildByName("param_skeleton"))
- {
- llwarns << "Can't specify skeleton param in a mesh definition." << llendl;
- }
- else
- {
- llwarns << "Unknown param type." << llendl;
- }
- continue;
- }
- LLPolyMorphTargetInfo *morphinfo = new LLPolyMorphTargetInfo();
- if (!morphinfo->parseXml(child))
- {
- delete morphinfo;
- delete info;
- return -1;
- }
- BOOL shared = FALSE;
- static LLStdStringHandle shared_string = LLXmlTree::addAttributeString("shared");
- child->getFastAttributeBOOL(shared_string, shared);
- info->mPolyMorphTargetInfoList.push_back(LLVOAvatarMeshInfo::morph_info_pair_t(morphinfo, shared));
- }
- mMeshInfoList.push_back(info);
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // parseXmlColorNodes(): parses <global_color> nodes from XML tree
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root)
- {
- for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" );
- color_node;
- color_node = root->getNextNamedChild())
- {
- std::string global_color_name;
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
- if (color_node->getFastAttributeString( name_string, global_color_name ) )
- {
- if( global_color_name == "skin_color" )
- {
- if (mTexSkinColorInfo)
- {
- llwarns << "avatar file: multiple instances of skin_color" << llendl;
- return FALSE;
- }
- mTexSkinColorInfo = new LLTexGlobalColorInfo;
- if( !mTexSkinColorInfo->parseXml( color_node ) )
- {
- deleteAndClear(mTexSkinColorInfo);
- llwarns << "avatar file: mTexSkinColor->parseXml() failed" << llendl;
- return FALSE;
- }
- }
- else if( global_color_name == "hair_color" )
- {
- if (mTexHairColorInfo)
- {
- llwarns << "avatar file: multiple instances of hair_color" << llendl;
- return FALSE;
- }
- mTexHairColorInfo = new LLTexGlobalColorInfo;
- if( !mTexHairColorInfo->parseXml( color_node ) )
- {
- deleteAndClear(mTexHairColorInfo);
- llwarns << "avatar file: mTexHairColor->parseXml() failed" << llendl;
- return FALSE;
- }
- }
- else if( global_color_name == "eye_color" )
- {
- if (mTexEyeColorInfo)
- {
- llwarns << "avatar file: multiple instances of eye_color" << llendl;
- return FALSE;
- }
- mTexEyeColorInfo = new LLTexGlobalColorInfo;
- if( !mTexEyeColorInfo->parseXml( color_node ) )
- {
- llwarns << "avatar file: mTexEyeColor->parseXml() failed" << llendl;
- return FALSE;
- }
- }
- }
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // parseXmlLayerNodes(): parses <layer_set> nodes from XML tree
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root)
- {
- for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" );
- layer_node;
- layer_node = root->getNextNamedChild())
- {
- LLTexLayerSetInfo* layer_info = new LLTexLayerSetInfo();
- if( layer_info->parseXml( layer_node ) )
- {
- mLayerInfoList.push_back(layer_info);
- }
- else
- {
- delete layer_info;
- llwarns << "avatar file: layer_set->parseXml() failed" << llendl;
- return FALSE;
- }
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root)
- {
- LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" );
- if( driver )
- {
- for (LLXmlTreeNode* grand_child = driver->getChildByName( "param" );
- grand_child;
- grand_child = driver->getNextNamedChild())
- {
- if( grand_child->getChildByName( "param_driver" ) )
- {
- LLDriverParamInfo* driver_info = new LLDriverParamInfo();
- if( driver_info->parseXml( grand_child ) )
- {
- mDriverInfoList.push_back(driver_info);
- }
- else
- {
- delete driver_info;
- llwarns << "avatar file: driver_param->parseXml() failed" << llendl;
- return FALSE;
- }
- }
- }
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------------
- // parseXmlDriverNodes(): parses <driver_parameters> nodes from XML tree
- //-----------------------------------------------------------------------------
- BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMorphNodes(LLXmlTreeNode* root)
- {
- LLXmlTreeNode* masks = root->getChildByName( "morph_masks" );
- if( !masks )
- {
- return FALSE;
- }
- for (LLXmlTreeNode* grand_child = masks->getChildByName( "mask" );
- grand_child;
- grand_child = masks->getNextNamedChild())
- {
- LLVOAvatarMorphInfo* info = new LLVOAvatarMorphInfo();
- static LLStdStringHandle name_string = LLXmlTree::addAttributeString("morph_name");
- if (!grand_child->getFastAttributeString(name_string, info->mName))
- {
- llwarns << "No name supplied for morph mask." << llendl;
- delete info;
- continue;
- }
- static LLStdStringHandle region_string = LLXmlTree::addAttributeString("body_region");
- if (!grand_child->getFastAttributeString(region_string, info->mRegion))
- {
- llwarns << "No region supplied for morph mask." << llendl;
- delete info;
- continue;
- }
- static LLStdStringHandle layer_string = LLXmlTree::addAttributeString("layer");
- if (!grand_child->getFastAttributeString(layer_string, info->mLayer))
- {
- llwarns << "No layer supplied for morph mask." << llendl;
- delete info;
- continue;
- }
- // optional parameter. don't throw a warning if not present.
- static LLStdStringHandle invert_string = LLXmlTree::addAttributeString("invert");
- grand_child->getFastAttributeBOOL(invert_string, info->mInvert);
- mMorphMaskInfoList.push_back(info);
- }
- return TRUE;
- }
- //virtual
- void LLVOAvatar::updateRegion(LLViewerRegion *regionp)
- {
- }
- std::string LLVOAvatar::getFullname() const
- {
- std::string name;
- LLNameValue* first = getNVPair("FirstName");
- LLNameValue* last = getNVPair("LastName");
- if (first && last)
- {
- name += first->getString();
- name += " ";
- name += last->getString();
- }
- return name;
- }
- LLHost LLVOAvatar::getObjectHost() const
- {
- LLViewerRegion* region = getRegion();
- if (region && !isDead())
- {
- return region->getHost();
- }
- else
- {
- return LLHost::invalid;
- }
- }
- //static
- void LLVOAvatar::updateFreezeCounter(S32 counter)
- {
- if(counter)
- {
- sFreezeCounter = counter;
- }
- else if(sFreezeCounter > 0)
- {
- sFreezeCounter--;
- }
- else
- {
- sFreezeCounter = 0;
- }
- }
- BOOL LLVOAvatar::updateLOD()
- {
- if (isImpostor())
- {
- return TRUE;
- }
- BOOL res = updateJointLODs();
- LLFace* facep = mDrawable->getFace(0);
- if (facep->mVertexBuffer.isNull() ||
- (LLVertexBuffer::sEnableVBOs &&
- ((facep->mVertexBuffer->getUsage() == GL_STATIC_DRAW ? TRUE : FALSE) !=
- (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE))))
- {
- mDirtyMesh = TRUE;
- }
- if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY))
- { //LOD changed or new mesh created, allocate new vertex buffer if needed
- updateMeshData();
- mDirtyMesh = FALSE;
- mNeedsSkin = TRUE;
- mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY);
- }
-
- updateVisibility();
- return res;
- }
- U32 LLVOAvatar::getPartitionType() const
- {
- // Avatars merely exist as drawables in the bridge partition
- return LLViewerRegion::PARTITION_BRIDGE;
- }
- //static
- void LLVOAvatar::updateImpostors()
- {
- for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- iter != LLCharacter::sInstances.end(); ++iter)
- {
- LLVOAvatar* avatar = (LLVOAvatar*) *iter;
- if (!avatar->isDead() && avatar->needsImpostorUpdate() && avatar->isVisible() && avatar->isImpostor())
- {
- gPipeline.generateImpostor(avatar);
- }
- }
- }
- BOOL LLVOAvatar::isImpostor() const
- {
- return (sUseImpostors && mUpdatePeriod >= IMPOSTOR_PERIOD) ? TRUE : FALSE;
- }
- BOOL LLVOAvatar::needsImpostorUpdate() const
- {
- return mNeedsImpostorUpdate;
- }
- const LLVector3& LLVOAvatar::getImpostorOffset() const
- {
- return mImpostorOffset;
- }
- const LLVector2& LLVOAvatar::getImpostorDim() const
- {
- return mImpostorDim;
- }
- void LLVOAvatar::setImpostorDim(const LLVector2& dim)
- {
- mImpostorDim = dim;
- }
- void LLVOAvatar::cacheImpostorValues()
- {
- getImpostorValues(mImpostorExtents, mImpostorAngle, mImpostorDistance);
- }
- void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) const
- {
- const LLVector3* ext = mDrawable->getSpatialExtents();
- extents[0] = ext[0];
- extents[1] = ext[1];
- LLVector3 at = LLViewerCamera::getInstance()->getOrigin()-(getRenderPosition()+mImpostorOffset);
- distance = at.normalize();
- F32 da = 1.f - (at*LLViewerCamera::getInstance()->getAtAxis());
- angle.mV[0] = LLViewerCamera::getInstance()->getYaw()*da;
- angle.mV[1] = LLViewerCamera::getInstance()->getPitch()*da;
- angle.mV[2] = da;
- }
- void LLVOAvatar::idleUpdateRenderCost()
- {
- static const U32 ARC_BODY_PART_COST = 20;
- static const U32 ARC_LIMIT = 2048;
- if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME))
- {
- return;
- }
- U32 cost = 0;
- std::set<LLUUID> textures;
- for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)
- {
- const LLVOAvatarDictionary::BakedEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index);
- ETextureIndex tex_index = baked_dict->mTextureIndex;
- if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(WT_SKIRT)))
- {
- if (isTextureVisible(tex_index))
- {
- cost +=ARC_BODY_PART_COST;
- }
- }
- }
- for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end();
- ++iter)
- {
- LLViewerJointAttachment* attachment = iter->second;
- for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
- attachment_iter != attachment->mAttachedObjects.end();
- ++attachment_iter)
- {
- const LLViewerObject* attached_object = (*attachment_iter);
- if (attached_object && !attached_object->isHUDAttachment())
- {
- const LLDrawable* drawable = attached_object->mDrawable;
- if (drawable)
- {
- const LLVOVolume* volume = drawable->getVOVolume();
- if (volume)
- {
- cost += volume->getRenderCost(textures);
- }
- }
- }
- }
- }
- cost += textures.size() * LLVOVolume::ARC_TEXTURE_COST;
- setDebugText(llformat("%d", cost));
- F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f);
- F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f);
- mText->setColor(LLColor4(red,green,0,1));
- }
- // static
- BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index)
- {
- if (index < 0 || index >= TEX_NUM_INDICES) return false;
- return LLVOAvatarDictionary::getInstance()->getTexture(index)->mIsLocalTexture;
- }
- // static
- BOOL LLVOAvatar::isIndexBakedTexture(ETextureIndex index)
- {
- if (index < 0 || index >= TEX_NUM_INDICES) return false;
- return LLVOAvatarDictionary::getInstance()->getTexture(index)->mIsBakedTexture;
- }
- const std::string LLVOAvatar::getBakedStatusForPrintout() const
- {
- std::string line;
- for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
- iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- ++iter)
- {
- const ETextureIndex index = iter->first;
- const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
- if (texture_dict->mIsBakedTexture)
- {
- line += texture_dict->mName;
- if (isTextureDefined(index))
- {
- line += "_baked";
- }
- line += " ";
- }
- }
- return line;
- }
- //virtual
- S32 LLVOAvatar::getTexImageSize() const
- {
- return TEX_IMAGE_SIZE_OTHER;
- }
- //-----------------------------------------------------------------------------
- // Utility functions
- //-----------------------------------------------------------------------------
- F32 calc_bouncy_animation(F32 x)
- {
- return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f;
- }
- //virtual
- BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 index ) const
- {
- if (isIndexLocalTexture(te))
- {
- return FALSE;
- }
- return (getImage(te, index)->getID() != IMG_DEFAULT_AVATAR &&
- getImage(te, index)->getID() != IMG_DEFAULT);
- }