diff options
author | Steven Bennetts <steve@lindenlab.com> | 2007-03-02 21:25:50 +0000 |
---|---|---|
committer | Steven Bennetts <steve@lindenlab.com> | 2007-03-02 21:25:50 +0000 |
commit | 4dabd9c0472deb49573fdafef2fa413e59703f19 (patch) | |
tree | 06c680d6a2047e03838d6548bccd26c7baf9d652 /indra/newview/llvoavatar.cpp | |
parent | d4462963c6ba5db2088723bbedc7b60f1184c594 (diff) |
merge release@58699 beta-1-14-0@58707 -> release
Diffstat (limited to 'indra/newview/llvoavatar.cpp')
-rw-r--r-- | indra/newview/llvoavatar.cpp | 620 |
1 files changed, 348 insertions, 272 deletions
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 193fd4e325..2c920ecde8 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -28,7 +28,6 @@ #include "timing.h" #include "llagent.h" // Get state values from here -#include "llagparray.h" #include "llviewercontrol.h" #include "llcriticaldamp.h" #include "lldir.h" @@ -191,7 +190,7 @@ const F32 UNDERWATER_FREQUENCY_DAMP = 0.33f; const F32 APPEARANCE_MORPH_TIME = 0.65f; const F32 CAMERA_SHAKE_ACCEL_THRESHOLD_SQUARED = 5.f * 5.f; const F32 TIME_BEFORE_MESH_CLEANUP = 5.f; // seconds -const S32 AVATAR_AGP_RELEASE_THRESHOLD = 10; // number of avatar instances before releasing AGP memory +const S32 AVATAR_RELEASE_THRESHOLD = 10; // number of avatar instances before releasing memory const F32 FOOT_GROUND_COLLISION_TOLERANCE = 0.25f; const F32 AVATAR_LOD_TWEAK_RANGE = 0.7f; const S32 MAX_LOD_CHANGES_PER_FRAME = 2; @@ -770,7 +769,6 @@ LLVOAvatar::LLVOAvatar( mEyesLayerSet( NULL ), mSkirtLayerSet( NULL ), mRenderPriority(1.0f), - mNumAGPVertices(0), mNameString(), mTitle(), mNameAway(FALSE), @@ -988,7 +986,7 @@ LLVOAvatar::LLVOAvatar( //------------------------------------------------------------------------- // register motions //------------------------------------------------------------------------- - if (LLCharacter::sInstances.getLength() == 1) + if (LLCharacter::sInstances.size() == 1) { LLKeyframeMotion::setVFS(gStaticVFS); addMotion( ANIM_AGENT_BUSY, LLNullMotion::create ); @@ -1132,7 +1130,8 @@ void LLVOAvatar::markDead() BOOL LLVOAvatar::isFullyBaked() { if (mIsDummy) return TRUE; - + if (getNumTEs() == 0) return FALSE; + BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); @@ -1161,10 +1160,10 @@ void LLVOAvatar::deleteLayerSetCaches() // static BOOL LLVOAvatar::areAllNearbyInstancesBaked() { - for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - inst; - inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* inst = (LLVOAvatar*) *iter; if( inst->isDead() ) { continue; @@ -1194,10 +1193,10 @@ void LLVOAvatar::dumpBakedStatus() { LLVector3d camera_pos_global = gAgent.getCameraPositionGlobal(); - for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - inst; - inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* inst = (LLVOAvatar*) *iter; llinfos << "Avatar "; LLNameValue* firstname = inst->getNVPair("FirstName"); @@ -1386,11 +1385,10 @@ void LLVOAvatar::initVertexPrograms() //static void LLVOAvatar::restoreGL() { - LLVOAvatar* inst; - for( inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - inst; - inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* inst = (LLVOAvatar*) *iter; inst->setCompositeUpdatesEnabled( TRUE ); inst->invalidateComposite( inst->mHeadLayerSet, FALSE ); inst->invalidateComposite( inst->mLowerBodyLayerSet, FALSE ); @@ -1414,10 +1412,10 @@ void LLVOAvatar::deleteCachedImages() if (LLTexLayerSet::sHasCaches) { lldebugs << "Deleting layer set caches" << llendl; - for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - inst; - inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* inst = (LLVOAvatar*) *iter; inst->deleteLayerSetCaches(); } LLTexLayerSet::sHasCaches = FALSE; @@ -1518,30 +1516,30 @@ void LLVOAvatar::initClass() sSkeletonInfo = new LLVOAvatarSkeletonInfo; if (!sSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) { - llerrs << "Error parsing skeleton XML file" << llendl; + llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl; } // parse avatar_lad.xml llassert(!sAvatarInfo); sAvatarInfo = new LLVOAvatarInfo; if (!sAvatarInfo->parseXmlSkeletonNode(root)) { - llerrs << "Error parsing skeleton node in avatar XML file" << llendl; + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } if (!sAvatarInfo->parseXmlMeshNodes(root)) { - llerrs << "Error parsing skeleton node in avatar XML file" << llendl; + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } if (!sAvatarInfo->parseXmlColorNodes(root)) { - llerrs << "Error parsing skeleton node in avatar XML file" << llendl; + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } if (!sAvatarInfo->parseXmlLayerNodes(root)) { - llerrs << "Error parsing skeleton node in avatar XML file" << llendl; + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } if (!sAvatarInfo->parseXmlDriverNodes(root)) { - llerrs << "Error parsing skeleton node in avatar XML file" << llendl; + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } } @@ -1557,6 +1555,19 @@ void LLVOAvatar::cleanupClass() } +void LLVOAvatar::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax) +{ + LLVector3 center = getRenderPosition(); + LLVector3 size = getScale(); + //maximum amount an animation can move avatar from drawable position + LLVector3 animation_buffer(5, 5, 5); + + newMin.setVec((center-size)-animation_buffer); + newMax.setVec(center+size+animation_buffer); + mDrawable->setPositionGroup((newMin + newMax) * 0.5f); +} + + //----------------------------------------------------------------------------- // parseSkeletonFile() //----------------------------------------------------------------------------- @@ -1709,10 +1720,13 @@ BOOL LLVOAvatar::buildSkeleton(LLVOAvatarSkeletonInfo *info) } // add special-purpose "screen" joint - mScreenp = new LLViewerJoint("mScreen", NULL); - // for now, put screen at origin, as it is only used during special - // HUD rendering mode - mScreenp->setWorldPosition(LLVector3::zero); + if (mIsSelf) + { + mScreenp = new LLViewerJoint("mScreen", NULL); + // for now, put screen at origin, as it is only used during special + // HUD rendering mode + mScreenp->setWorldPosition(LLVector3::zero); + } return TRUE; } @@ -1793,7 +1807,7 @@ void LLVOAvatar::buildCharacter() return; } - gPrintMessagesThisFrame = TRUE; +// gPrintMessagesThisFrame = TRUE; lldebugs << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << llendl; if ( ! status ) @@ -2076,7 +2090,7 @@ void LLVOAvatar::releaseMeshData() { LLMemType mt(LLMemType::MTYPE_AVATAR); - if (sInstances.getLength() < AVATAR_AGP_RELEASE_THRESHOLD || mIsDummy) + if (sInstances.size() < AVATAR_RELEASE_THRESHOLD || mIsDummy) { return; } @@ -2093,18 +2107,11 @@ void LLVOAvatar::releaseMeshData() mEyeBallRightLOD.setValid(FALSE, TRUE); mSkirtLOD.setValid(FALSE, TRUE); - //cleanup AGP data + //cleanup data if (mDrawable.notNull()) { LLFace* facep = mDrawable->getFace(0); facep->setSize(0, 0); - mNumAGPVertices = 0; - - // You need to reset the vertex data in order to guarantee - // that the data is deallocated, AND you start at the 0 index - // when you restore the face. We're assuming ONLY ONE FACE per - // avatar pool, this logic is broken if that isn't the case! - facep->getPool()->resetVertexData(0); } for (LLViewerJointAttachment *attachmentPoint = mAttachmentPoints.getFirstData(); @@ -2148,7 +2155,7 @@ void LLVOAvatar::restoreMeshData() } // force mesh update as LOD might not have changed to trigger this - updateMeshData(); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); } //----------------------------------------------------------------------------- @@ -2161,29 +2168,28 @@ void LLVOAvatar::updateMeshData() LLFace* facep = mDrawable->getFace(0); U32 num_vertices = 0; + U32 num_indices = 0; // this order is determined by number of LODS // if a mesh earlier in this list changed LODs while a later mesh doesn't, // the later mesh's index offset will be inaccurate - mEyeBallLeftLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mEyeBallRightLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mEyeLashLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mHeadLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mLowerBodyLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mSkirtLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mUpperBodyLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mHairLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - - if (num_vertices != mNumAGPVertices) - { - // resize immediately -// llinfos << "Resizing avatar AGP buffer!" << llendl; - facep->getPool()->resetVertexData(num_vertices); - facep->setSize(0,0); - facep->setSize(num_vertices, 0); - mNumAGPVertices = num_vertices; - } - + mEyeBallLeftLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mEyeBallRightLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mEyeLashLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mHeadLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mLowerBodyLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mSkirtLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mUpperBodyLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mHairLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + + // resize immediately + facep->setSize(num_vertices, num_indices); + + facep->mVertexBuffer = new LLVertexBufferAvatar(); + facep->mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE); + facep->setGeomIndex(0); + facep->setIndicesIndex(0); + // This is a hack! Avatars have their own pool, so we are detecting // the case of more than one avatar in the pool (thus > 0 instead of >= 0) if (facep->getGeomIndex() > 0) @@ -2366,13 +2372,8 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) setPixelAreaAndAngle(gAgent); // Update the LOD of the joints - static const F32 UPDATE_TIME = .5f; - if (mUpdateLODTimer.hasExpired()) - { - mUpdateLODTimer.setTimerExpirySec(UPDATE_TIME * (.75f + ll_frand(0.5f))); - updateJointLODs(); - } - + //static const F32 UPDATE_TIME = .5f; + // force asynchronous drawable update if(mDrawable.notNull() && !gNoRender) { @@ -2432,6 +2433,17 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) updateCharacter(agent); + + + if (LLVOAvatar::sJointDebug) + { + llinfos << getNVPair("FirstName")->getString() << getNVPair("LastName")->getString() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << llendl; + } + + LLJoint::sNumUpdates = 0; + LLJoint::sNumTouches = 0; + + if (gNoRender) { return TRUE; @@ -2440,7 +2452,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // *NOTE: this is necessary for the floating name text above your head. if (mDrawable.notNull()) { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_SHADOW, TRUE); } // update attachments positions @@ -2450,8 +2462,12 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) attachment; attachment = mAttachmentPoints.getNextData()) { - LLViewerObject *attached_object = attachment->getObject(0); - if (attached_object && !attached_object->isDead() && attachment->getValid()) + LLViewerObject *attached_object = attachment->getObject(); + + BOOL visibleAttachment = isVisible() || !(attached_object && attached_object->mDrawable->getSpatialBridge() + && (attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0)); + + if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid()) { // if selecting any attachments, update all of them as non-damped if (gSelectMgr->getSelection()->getObjectCount() && gSelectMgr->getSelection()->isAttachment()) @@ -2605,9 +2621,9 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) const F32 FADE_DURATION = gSavedSettings.getF32("RenderNameFadeDuration"); // seconds BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping); BOOL render_name = visible_chat || - (mVisible && - (sRenderName == RENDER_NAME_ALWAYS) || - (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME)); + (isVisible() && + ((sRenderName == RENDER_NAME_ALWAYS) || + (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME))); // If it's your own avatar, don't draw in mouselook, and don't // draw if we're specifically hiding our own name. if (mIsSelf) @@ -2984,6 +3000,15 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) { LLMemType mt(LLMemType::MTYPE_AVATAR); + // update screen joint size + if (mScreenp) + { + F32 aspect = gCamera->getAspect(); + LLVector3 scale(1.f, aspect, 1.f); + mScreenp->setScale(scale); + mScreenp->updateWorldMatrixChildren(); + } + // clear debug text mDebugText.clear(); @@ -3020,14 +3045,6 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) } } - if (LLVOAvatar::sJointDebug) - { - llinfos << getNVPair("FirstName")->getString() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << llendl; - - LLJoint::sNumUpdates = 0; - LLJoint::sNumTouches = 0; - } -// llinfos << mPixelArea << llendl; if (gNoRender) { // Hack if we're running drones... @@ -3046,10 +3063,15 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) return; } + if (!mIsSelf && !isVisible()) + { + return; + } + // change animation time quanta based on avatar render load if (!mIsSelf) { - F32 time_quantum = clamp_rescale((F32)sInstances.getLength(), 10.f, 35.f, 0.f, 0.25f); + F32 time_quantum = clamp_rescale((F32)sInstances.size(), 10.f, 35.f, 0.f, 0.25f); F32 pixel_area_scale = clamp_rescale(mPixelArea, 100, 5000, 1.f, 0.f); F32 time_step = time_quantum * pixel_area_scale; if (time_step != 0.f) @@ -3078,10 +3100,6 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) mTimeVisible.reset(); } - // update screen joint size - mScreenp->setScale(LLVector3(1.f, gCamera->getAspect(), 1.f)); - mScreenp->updateWorldMatrixChildren(); - //-------------------------------------------------------------------- // create local variables in world coords for region position values //-------------------------------------------------------------------- @@ -3092,6 +3110,8 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) xyVel.mV[VZ] = 0.0f; speed = xyVel.magVec(); + BOOL throttle = TRUE; + if (!(mIsSitting && getParent())) { //-------------------------------------------------------------------- @@ -3102,6 +3122,7 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) if (mTimeLast == 0.0f) { mTimeLast = animation_time; + throttle = FALSE; // put the pelvis at slaved position/mRotation mRoot.setWorldPosition( getPositionAgent() ); // first frame @@ -3145,7 +3166,16 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) // correct for the fact that the pelvis is not necessarily the center // of the agent's physical representation root_pos.mdV[VZ] -= (0.5f * mBodySize.mV[VZ]) - mPelvisToFoot; - mRoot.setWorldPosition(gAgent.getPosAgentFromGlobal(root_pos) ); // regular update + + + LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos); + + if (newPosition != mRoot.getXform()->getWorldPosition()) + { + mRoot.touch(); + mRoot.setWorldPosition(newPosition ); // regular update + } + //-------------------------------------------------------------------- // Propagate viewer object rotation to root of avatar @@ -3315,9 +3345,10 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) //} //end Ventrella - F32 u = llclamp((deltaTime / pelvis_lag_time), 0.0f, 1.0f); - + F32 u = llclamp((deltaTime / pelvis_lag_time), 0.0f, 1.0f); + mRoot.setWorldRotation( slerp(u, mRoot.getWorldRotation(), wQv) ); + } } else if (mDrawable.notNull()) @@ -3329,8 +3360,17 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) //-------------------------------------------------------------------- // the rest should only be done when close enough to see it //-------------------------------------------------------------------- + + + if (mPixelArea > 12.0f) + throttle = FALSE; + if (mPixelArea < 400.0f) + { + throttle = (LLDrawable::getCurrentFrame()+mID.mData[0])%2 != 0; + } + if ( !(mIsSitting && getParent()) && - ((mPixelArea < 12.0f) || + (throttle || (!isVisible() && (mPixelArea < MIN_PIXEL_AREA_FOR_COMPOSITE))) ) { mRoot.setWorldRotation( getRotation() ); @@ -3434,7 +3474,7 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) } } } - + mRoot.updateWorldMatrixChildren(); if (!mDebugText.size() && mText.notNull()) @@ -3491,10 +3531,8 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible) else if (!force_invisible) { // calculate avatar distance wrt head - LLVector3 pos = mDrawable->getPositionAgent(); - pos -= gCamera->getOrigin(); - mDrawable->mDistanceWRTCamera = pos.magVec(); - + mDrawable->updateDistance(*gCamera); + if (!mDrawable->getSpatialGroup() || mDrawable->getSpatialGroup()->isVisible()) { visible = TRUE; @@ -3566,9 +3604,9 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible) attachment; attachment = mAttachmentPoints.getNextData()) { - if (attachment->getObject(0)) + if (attachment->getObject()) { - if(attachment->getObject(0)->mDrawable->isVisible()) + if(attachment->getObject()->mDrawable->isVisible()) { llinfos << attachment->getName() << " visible" << llendl; } @@ -3592,7 +3630,6 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible) { restoreMeshData(); } - gPipeline.markVisible(mDrawable); } else { @@ -3619,11 +3656,12 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible) void LLVOAvatar::updateAllAvatarVisiblity() { LLVOAvatar::sNumVisibleAvatars = 0; - LLVOAvatar *avatarp; - + F32 render_priority = (F32)LLVOAvatar::sMaxVisible; - for (avatarp = (LLVOAvatar*)sInstances.getFirstData(); avatarp; avatarp = (LLVOAvatar*)sInstances.getNextData()) + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* avatarp = (LLVOAvatar*) *iter; if (avatarp->isDead()) { continue; @@ -3761,26 +3799,22 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) if (pass == AVATAR_RENDER_PASS_SINGLE) { + BOOL first_pass = TRUE; if (!mIsSelf || gAgent.needsRenderHead()) { num_indices += mHeadLOD.render(mAdjustedPixelArea); + first_pass = FALSE; } - num_indices += mUpperBodyLOD.render(mAdjustedPixelArea); - num_indices += mLowerBodyLOD.render(mAdjustedPixelArea); - if( isWearingWearableType( WT_SKIRT ) ) - { - glAlphaFunc(GL_GREATER,0.25f); - num_indices += mSkirtLOD.render(mAdjustedPixelArea); - glAlphaFunc(GL_GREATER,0.01f); - } + num_indices += mUpperBodyLOD.render(mAdjustedPixelArea, first_pass); + num_indices += mLowerBodyLOD.render(mAdjustedPixelArea, FALSE); - if (!mIsSelf || gAgent.needsRenderHead()) { - num_indices += mEyeLashLOD.render(mAdjustedPixelArea); - num_indices += mHairLOD.render(mAdjustedPixelArea); + LLGLEnable blend(GL_BLEND); + LLGLEnable test(GL_ALPHA_TEST); + num_indices += renderTransparent(); } } - else if (pass == AVATAR_RENDER_PASS_CLOTHING_INNER) + /*else if (pass == AVATAR_RENDER_PASS_CLOTHING_INNER) { if (!mIsSelf || gAgent.needsRenderHead()) { @@ -3813,7 +3847,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) LLViewerJointMesh::sClothingMaskImageName = mLowerMaskTexName; num_indices += mLowerBodyLOD.render(mAdjustedPixelArea); LLViewerJointMesh::sClothingMaskImageName = 0; - } + }*/ LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE; @@ -3824,6 +3858,27 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) return num_indices; } +U32 LLVOAvatar::renderTransparent() +{ + U32 num_indices = 0; + BOOL first_pass = FALSE; + if( isWearingWearableType( WT_SKIRT ) ) + { + glAlphaFunc(GL_GREATER,0.25f); + num_indices += mSkirtLOD.render(mAdjustedPixelArea, FALSE); + first_pass = FALSE; + glAlphaFunc(GL_GREATER,0.01f); + } + + if (!mIsSelf || gAgent.needsRenderHead()) + { + num_indices += mEyeLashLOD.render(mAdjustedPixelArea, first_pass); + num_indices += mHairLOD.render(mAdjustedPixelArea, FALSE); + } + + return num_indices; +} + //----------------------------------------------------------------------------- // renderRigid() //----------------------------------------------------------------------------- @@ -3852,6 +3907,39 @@ U32 LLVOAvatar::renderRigid() return num_indices; } +U32 LLVOAvatar::renderFootShadows() +{ + U32 num_indices = 0; + + if (!mIsBuilt) + { + return 0; + } + + if (mIsSelf && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead())) + { + return 0; + } + + if (!mIsBuilt) + { + return 0; + } + + U32 foot_mask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD; + + //render foot shadows + LLGLEnable blend(GL_BLEND); + mShadowImagep->bind(); + glColor4fv(mShadow0Facep->getRenderColor().mV); + mShadow0Facep->renderIndexed(foot_mask); + glColor4fv(mShadow1Facep->getRenderColor().mV); + mShadow1Facep->renderIndexed(foot_mask); + + return num_indices; +} + //----------------------------------------------------------------------------- // renderCollisionVolumes() //----------------------------------------------------------------------------- @@ -3868,6 +3956,7 @@ void LLVOAvatar::renderCollisionVolumes() //------------------------------------------------------------------------ void LLVOAvatar::updateTextures(LLAgent &agent) { + LLFastTimer ftm(LLFastTimer::FTM_TEMP5); BOOL render_avatar = TRUE; if (mIsDummy || gNoRender) @@ -3942,6 +4031,8 @@ void LLVOAvatar::updateTextures(LLAgent &agent) } */ + mMaxPixelArea = 0.f; + mMinPixelArea = 99999999.f; for (U32 i = 0; i < getNumTEs(); i++) { LLViewerImage *imagep = getTEImage(i); @@ -4039,40 +4130,35 @@ void LLVOAvatar::updateTextures(LLAgent &agent) case TEX_HEAD_BAKED: if (head_baked) { - imagep->setBoostLevel(boost_level); - imagep->addTextureStats(mPixelArea, texel_area_ratio); + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); } break; case TEX_UPPER_BAKED: if (upper_baked) { - imagep->setBoostLevel(boost_level); - imagep->addTextureStats(mPixelArea, texel_area_ratio); + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); } break; case TEX_LOWER_BAKED: if (lower_baked) { - imagep->setBoostLevel(boost_level); - imagep->addTextureStats(mPixelArea, texel_area_ratio); + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); } break; case TEX_EYES_BAKED: if (eyes_baked) { - imagep->setBoostLevel(boost_level); - imagep->addTextureStats(mPixelArea, texel_area_ratio); + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); } break; case TEX_SKIRT_BAKED: if (skirt_baked) { - imagep->setBoostLevel(boost_level); - imagep->addTextureStats(mPixelArea, texel_area_ratio); + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); } break; @@ -4080,15 +4166,8 @@ void LLVOAvatar::updateTextures(LLAgent &agent) // Hair is neither a local texture used for baking, nor the output // of the baking process. It's just a texture that happens to be // used to draw avatars. Hence BOOST_AVATAR. JC - if (mIsSelf) - { - imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR_SELF); - } - else - { - imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR); - } - imagep->addTextureStats(mPixelArea, texel_area_ratio); + boost_level = mIsSelf ? LLViewerImage::BOOST_AVATAR_SELF : LLViewerImage::BOOST_AVATAR; + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); break; default: @@ -4098,6 +4177,11 @@ void LLVOAvatar::updateTextures(LLAgent &agent) } } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + setDebugText(llformat("%4.0f:%4.0f", fsqrtf(mMinPixelArea),fsqrtf(mMaxPixelArea))); + } + if( render_avatar ) { mShadowImagep->addTextureStats(mPixelArea, 1.f); @@ -4127,6 +4211,15 @@ void LLVOAvatar::addLocalTextureStats( LLVOAvatar::ELocTexIndex idx, LLViewerIma } } + +void LLVOAvatar::addBakedTextureStats( LLViewerImage* 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); +} + //----------------------------------------------------------------------------- // resolveHeight() //----------------------------------------------------------------------------- @@ -4611,7 +4704,7 @@ F32 LLVOAvatar::getTimeDilation() //----------------------------------------------------------------------------- // LLVOAvatar::getPixelArea() //----------------------------------------------------------------------------- -F32 LLVOAvatar::getPixelArea() +F32 LLVOAvatar::getPixelArea() const { if (mIsDummy) { @@ -4973,6 +5066,11 @@ BOOL LLVOAvatar::loadSkeletonNode () iter != sAvatarInfo->mAttachmentInfoList.end(); iter++) { LLVOAvatarInfo::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); @@ -5323,15 +5421,6 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) { LLMemType mt(LLMemType::MTYPE_AVATAR); - LLVector3 viewer_pos_agent = agent.getCameraPositionAgent(); - LLVector3 pos_agent; - - pos_agent = getRenderPosition(); - - F32 dx = viewer_pos_agent.mV[VX] - pos_agent.mV[VX]; - F32 dy = viewer_pos_agent.mV[VY] - pos_agent.mV[VY]; - F32 dz = viewer_pos_agent.mV[VZ] - pos_agent.mV[VZ]; - F32 max_scale = getMaxScale(); F32 mid_scale = getMidScale(); F32 min_scale = llmin( getScale().mV[VX], llmin( getScale().mV[VY], getScale().mV[VZ] ) ); @@ -5340,7 +5429,7 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) // to try to get a min distance from face, subtract min_scale/2 from the range. // This means we'll load too much detail sometimes, but that's better than not enough // I don't think there's a better way to do this without calculating distance per-poly - F32 range = sqrt(dx*dx + dy*dy + dz*dz) - min_scale/2; + F32 range = (getRenderPosition()-gCamera->getOrigin()).magVec() - min_scale/2; if (range < 0.001f) // range == zero { @@ -5375,17 +5464,11 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) //----------------------------------------------------------------------------- // updateJointLODs() //----------------------------------------------------------------------------- -void LLVOAvatar::updateJointLODs() +BOOL LLVOAvatar::updateJointLODs() { - if (!mMeshValid) - { - return; - } - 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); - { if (mIsSelf) { @@ -5408,16 +5491,17 @@ void LLVOAvatar::updateJointLODs() mAdjustedPixelArea = (F32)mPixelArea * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; } - // now select meshes to render based on adjusted pixel area, and perform AGP data push as necessary + // now select meshes to render based on adjusted pixel area BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); if (res) { sNumLODChangesThisFrame++; - updateMeshData(); + dirtyMesh(); + return TRUE; } } - return; + return FALSE; } //----------------------------------------------------------------------------- @@ -5428,24 +5512,22 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) pipeline->allocDrawable(this); mDrawable->setLit(FALSE); - LLDrawPool *poolp = gPipeline.getPool(LLDrawPool::POOL_AVATAR); + LLDrawPoolAvatar *poolp = (LLDrawPoolAvatar*) gPipeline.getPool(LLDrawPool::POOL_AVATAR); // Only a single face (one per avatar) mDrawable->setState(LLDrawable::ACTIVE); mDrawable->addFace(poolp, NULL); + mDrawable->setRenderType(LLPipeline::RENDER_TYPE_AVATAR); - poolp = gPipeline.getPool(LLDrawPool::POOL_ALPHA); - LLFace *facep; // Add faces for the foot shadows - facep = mDrawable->addFace(poolp, mShadowImagep); + facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep); mShadow0Facep = facep; - facep = mDrawable->addFace(poolp, mShadowImagep); + facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep); mShadow1Facep = facep; - gPipeline.markMaterialed(mDrawable); dirtyMesh(); return mDrawable; } @@ -5456,6 +5538,7 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) //----------------------------------------------------------------------------- BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable) { + LLFastTimer ftm(LLFastTimer::FTM_UPDATE_AVATAR); if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR))) { return TRUE; @@ -5471,30 +5554,9 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable) llerrs << "LLVOAvatar::updateGeometry() called with NULL drawable" << llendl; } - // Update the shadow, tractor, and text label geometry. - - updateShadowFaces(); - - if (!drawable->isVisible()) - { - return TRUE; - } - - LLFace* facep = drawable->getFace(0); - if (!mDirtyMesh && !facep->getDirty()) - { - return TRUE; - } - - // U32 num_vertices = 0; - - updateMeshData(); - - mDirtyMesh = FALSE; return TRUE; } - //----------------------------------------------------------------------------- // updateShadowFaces() //----------------------------------------------------------------------------- @@ -5710,28 +5772,26 @@ void LLVOAvatar::removeChild(LLViewerObject *childp) detachObject(childp); } -//----------------------------------------------------------------------------- -// attachObject() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) +LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* viewer_object) { S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getState()); - //clamp((S32)(viewer_object->getState() & AGENT_ATTACH_MASK) >> AGENT_ATTACH_OFFSET, 1, 0xff); - - //if (mIsSelf) - //{ - // gSelectMgr->deselectObjectAndFamily(viewer_object); - //} LLViewerJointAttachment* attachment = mAttachmentPoints.getIfThere(attachmentID); if (!attachment) { - llwarns << "Tried to attach object to invalid attachment point: " << attachmentID << llendl; - return FALSE; + llwarns << "Object attachment point invalid: " << attachmentID << llendl; } -// LLQuaternion object_world_rot = viewer_object->getWorldRotation(); + return attachment; +} + +//----------------------------------------------------------------------------- +// attachObject() +//----------------------------------------------------------------------------- +BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) +{ + LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object); if (!attachment->addObject(viewer_object)) { @@ -5744,10 +5804,6 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) gSelectMgr->updatePointAt(); } -// LLQuaternion desired_rot = (object_world_rot * ~attachment->getWorldRotation()); - - lldebugs << "Attaching object (" << attachmentID << ") item_id=" << attachment->getItemID() << " task_id=" << viewer_object->getID() << "to " << attachment->getName() << llendl; - if (mIsSelf) { updateAttachmentVisibility(gAgent.getCameraMode()); @@ -5780,6 +5836,23 @@ void LLVOAvatar::lazyAttach() } } +void LLVOAvatar::resetHUDAttachments() +{ + for(LLViewerJointAttachment* attachment = mAttachmentPoints.getFirstData(); + attachment; + attachment = mAttachmentPoints.getNextData()) + { + if (attachment->getIsHUDAttachment()) + { + LLViewerObject* obj = attachment->getObject(); + if (obj && obj->mDrawable.notNull()) + { + gPipeline.markMoved(obj->mDrawable); + } + } + } +} + //----------------------------------------------------------------------------- // detachObject() //----------------------------------------------------------------------------- @@ -5790,7 +5863,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) attachment = mAttachmentPoints.getNextData()) { // only one object per attachment point for now - if (attachment->getObject(0) == viewer_object) + if (attachment->getObject() == viewer_object) { LLUUID item_id = attachment->getItemID(); attachment->removeObject(viewer_object); @@ -5983,7 +6056,7 @@ LLViewerObject* LLVOAvatar::getWornAttachment( const LLUUID& inv_item_id ) { if( attachment_point->getItemID() == inv_item_id ) { - return attachment_point->getObject(0); + return attachment_point->getObject(); } } return NULL; @@ -6321,10 +6394,10 @@ const LLUUID& LLVOAvatar::getLocalTextureID( S32 index ) void LLVOAvatar::dumpTotalLocalTextureByteCount() { S32 total_gl_bytes = 0; - for( LLVOAvatar* cur = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - cur; - cur = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* cur = (LLVOAvatar*) *iter; S32 gl_bytes = 0; cur->getLocalTextureByteCount(&gl_bytes ); total_gl_bytes += gl_bytes; @@ -7724,7 +7797,7 @@ BOOL LLVOAvatar::hasHUDAttachment() attachment; attachment = mAttachmentPoints.getNextData()) { - if (attachment->getIsHUDAttachment() && attachment->getObject(0)) + if (attachment->getIsHUDAttachment() && attachment->getObject()) { return TRUE; } @@ -7739,9 +7812,9 @@ LLBBox LLVOAvatar::getHUDBBox() attachment; attachment = mAttachmentPoints.getNextData()) { - if (attachment->getIsHUDAttachment() && attachment->getObject(0)) + if (attachment->getIsHUDAttachment() && attachment->getObject()) { - LLViewerObject* hud_object = attachment->getObject(0); + LLViewerObject* hud_object = attachment->getObject(); // initialize bounding box to contain identity orientation and center point for attached object bbox.addPointLocal(hud_object->getPosition()); @@ -7759,52 +7832,6 @@ LLBBox LLVOAvatar::getHUDBBox() void LLVOAvatar::rebuildHUD() { - if (!mIsSelf) - { - return; - } - - for(LLViewerJointAttachment *attachment = mAttachmentPoints.getFirstData(); - attachment; - attachment = mAttachmentPoints.getNextData()) - { - if (attachment->getIsHUDAttachment() && attachment->getObject(0)) - { - LLViewerObject* hud_object = attachment->getObject(0); - LLDrawable* hud_drawable = hud_object->mDrawable; - - if (hud_drawable) - { - // this assumes that an AGP sync will happen because face has been backlisted, - // so that pool has been rebuilt this frame and is scheduled for a sync - for(S32 face_index = 0; face_index < hud_drawable->getNumFaces(); ++face_index) - { - LLFace* facep = hud_drawable->getFace(face_index); - if (facep->isState(LLFace::BACKLIST)) - { - facep->restore(); - } - } - } - for (U32 child_num = 0; child_num < hud_object->mChildList.size(); ++child_num) - { - LLViewerObject* childp = hud_object->mChildList[child_num]; - LLDrawable* child_drawable = childp->mDrawable; - - if (child_drawable) - { - for(S32 face_index = 0; face_index < child_drawable->getNumFaces(); ++face_index) - { - LLFace* facep = child_drawable->getFace(face_index); - if (facep->isState(LLFace::BACKLIST)) - { - facep->restore(); - } - } - } - } - } - } } //----------------------------------------------------------------------------- @@ -8061,8 +8088,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, { if (!aux_src->getData()) { - llwarns << "No auxiliary source data for onBakedTextureMasksLoaded" << llendl; - src_vi->startImageDecode(); + llerrs << "No auxiliary source data for onBakedTextureMasksLoaded" << llendl; return; } @@ -8370,10 +8396,10 @@ void LLVOAvatar::dumpArchetypeXML( void* ) S32 LLVOAvatar::getUnbakedPixelAreaRank() { S32 rank = 1; - for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - inst; - inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* inst = (LLVOAvatar*) *iter; if( inst == this ) { return rank; @@ -8392,16 +8418,15 @@ S32 LLVOAvatar::getUnbakedPixelAreaRank() // static void LLVOAvatar::cullAvatarsByPixelArea() { - LLVOAvatar::sInstances.bubbleSortList(); - - + std::sort(LLCharacter::sInstances.begin(), LLCharacter::sInstances.end(), CompareScreenAreaGreater()); + // Update the avatars that have changed status S32 rank = 1; - for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - inst; - inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* inst = (LLVOAvatar*) *iter; BOOL culled; if( inst->isDead() ) { @@ -8591,8 +8616,6 @@ void LLVOAvatar::dumpLocalTextures() else { LLViewerImage* image = mLocalTexture[i]; - F32 data_progress = 0.0f; - F32 decode_progress = image->getDecodeProgress(&data_progress); llinfos << "LocTex " << names[i] << ": " << "Discard " << image->getDiscardLevel() << ", " @@ -8602,10 +8625,7 @@ void LLVOAvatar::dumpLocalTextures() // makes textures easier to steal << image->getID() << " " #endif - << "Data: " << (data_progress * 100) << "% " - << "Decode: " << (decode_progress * 100) << "% " - << "Priority: " << image->getDecodePriority() << " " - << (image->needsDecode() ? "pending decode" : "not pending decode") + << "Priority: " << image->getDecodePriority() << llendl; } } @@ -8707,7 +8727,7 @@ BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) } else { - llerrs << "Invalid node " << node->getName() << llendl; + llwarns << "Invalid node " << node->getName() << llendl; return FALSE; } @@ -8765,7 +8785,7 @@ BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); if (!node->getFastAttributeS32(num_bones_string, mNumBones)) { - llerrs << "Couldn't find number of bones." << llendl; + llwarns << "Couldn't find number of bones." << llendl; return FALSE; } @@ -8779,7 +8799,8 @@ BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) if (!info->parseXml(child)) { delete info; - llerrs << "Error parsing bone in skeleton file" << llendl; + llwarns << "Error parsing bone in skeleton file" << llendl; + return FALSE; } mBoneInfoList.push_back(info); } @@ -9210,7 +9231,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) attachment; attachment = mAttachmentPoints.getNextData()) { - LLViewerObject *attached_object = attachment->getObject(0); + LLViewerObject *attached_object = attachment->getObject(); if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull() && attached_object->getPCode() == LL_PCODE_VOLUME) { @@ -9231,7 +9252,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) attachment; attachment = mAttachmentPoints.getNextData()) { - LLViewerObject *attached_object = attachment->getObject(0); + LLViewerObject *attached_object = attachment->getObject(); if (attached_object && !attached_object->isDead() && attached_object->getPCode() == LL_PCODE_VOLUME) { LLVOVolume* attached_volume = (LLVOVolume*)attached_object; @@ -9443,3 +9464,58 @@ LLHost LLVOAvatar::getObjectHost() const return LLHost::invalid; } } + +BOOL LLVOAvatar::updateLOD() +{ + 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; + mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); + } + + if (facep->getPool()->getVertexShaderLevel() <= 0) + { + //generate animated mesh + mLowerBodyLOD.updateGeometry(); + mUpperBodyLOD.updateGeometry(); + + if( isWearingWearableType( WT_SKIRT ) ) + { + mSkirtLOD.updateGeometry(); + } + + if (!mIsSelf || gAgent.needsRenderHead()) + { + mEyeLashLOD.updateGeometry(); + mHeadLOD.updateGeometry(); + mHairLOD.updateGeometry(); + } + } + + // Update the shadow, tractor, and text label geometry. + if (mDrawable->isState(LLDrawable::REBUILD_SHADOW)) + { + updateShadowFaces(); + mDrawable->clearState(LLDrawable::REBUILD_SHADOW); + } + + return res; +} + +U32 LLVOAvatar::getPartitionType() const +{ //avatars merely exist as drawables in the bridge partition + return LLPipeline::PARTITION_BRIDGE; +} + |