diff options
Diffstat (limited to 'indra/newview/llvoavatar.cpp')
| -rw-r--r-- | indra/newview/llvoavatar.cpp | 149 |
1 files changed, 111 insertions, 38 deletions
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 4d15126271..f4226df5f7 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -602,6 +602,8 @@ bool LLVOAvatar::sLimitNonImpostors = false; // True unless RenderAvatarMaxNonIm F32 LLVOAvatar::sRenderDistance = 256.f; S32 LLVOAvatar::sNumVisibleAvatars = 0; S32 LLVOAvatar::sNumLODChangesThisFrame = 0; +bool LLVOAvatar::sAvatarCullNeedsUpdate = true; +F64 LLVOAvatar::sLastCullUpdateTime = 0.0; const LLUUID LLVOAvatar::sStepSoundOnLand("e8af4a28-aa83-4310-a7c4-c047e15ea0df"); const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] = @@ -615,6 +617,8 @@ const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] = SND_RUBBER_RUBBER }; +uuid_list_t LLVOAvatar::sEarlyAppearanceList; + S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS; S32 LLVOAvatar::sRenderGroupTitles = RENDER_GROUP_TITLE_ALWAYS; S32 LLVOAvatar::sNumVisibleChatBubbles = 0; @@ -701,7 +705,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN), mLoadedCallbacksPaused(false), mLoadedCallbackTextures(0), - mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar", false)), mLastRezzedStatus(-1), mIsEditingAppearance(false), mUseLocalAppearance(false), @@ -783,6 +786,21 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mVisuallyMuteSetting = LLVOAvatar::VisualMuteSettings(LLRenderMuteList::getInstance()->getSavedVisualMuteSetting(getID())); sInstances.push_back(this); + + uuid_list_t::iterator it = sEarlyAppearanceList.find(id); + if (it != sEarlyAppearanceList.end()) + { + // Note: aside from LLVOAvatar::resetEarlyAppearanceList() (called on + // teleport), this is the only place where we remove from + // sEarlyAppearanceList, which means any agent who receives an + // AvatarAppearance message but is never actually instantiated will + // remain on the list until the next teleport. This is a resource leak + // but we expect it to be small enough per-session to not cause problems. + sEarlyAppearanceList.erase(it); + LL_INFOS("Avatar") << "Re-requesting AvatarAppearance for new avatar " << id << LL_ENDL; + LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID()); + } + sOverrideAnimations = LLCachedControl<bool>(gSavedPerAccountSettings, "OverrideAnimations", false); } @@ -2586,6 +2604,10 @@ void LLVOAvatar::updateMeshData() f_num++ ; } } + + mDirtyMesh = 0; + mNeedsSkin = true; + mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); } } @@ -2805,6 +2827,28 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) // force immediate pixel area update on avatars using last frames data (before drawable or camera updates) setPixelAreaAndAngle(gAgent); + if (!isSelf()) + { + F32 current_pixel_area = getPixelArea(); + if (mLastCulledPixelArea >= 0.f) + { + // Avoid rapidly switching two avatars back and forth between ranks. + // And update frequency reduction + F32 pixel_area_change = fabsf(current_pixel_area - mLastCulledPixelArea) / mLastCulledPixelArea; + if (pixel_area_change > 0.1f) // 10% threshold + { + sAvatarCullNeedsUpdate = true; + mLastCulledPixelArea = current_pixel_area; + } + } + else + { + // First frame + sAvatarCullNeedsUpdate = true; + mLastCulledPixelArea = current_pixel_area; + } + } + // force asynchronous drawable update if(mDrawable.notNull()) { @@ -3119,7 +3163,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (isImpostor() && !mNeedsImpostorUpdate) { - LL_ALIGN_16(LLVector4a ext[2]); + LLVector4a ext[2]; F32 distance; LLVector3 angle; @@ -5262,9 +5306,11 @@ void LLVOAvatar::updateVisibility() LL_DEBUGS("AvatarRender") << "visible was " << mVisible << " now " << visible << LL_ENDL; } + if (mVisible != visible) + { + setCullNeedsUpdate(); + } mVisible = visible; - - mVisibilityPreference = visible ? getPixelArea() : 0; } // private @@ -5305,9 +5351,6 @@ U32 LLVOAvatar::renderSkinned() if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4) { updateMeshData(); - mDirtyMesh = 0; - mNeedsSkin = true; - mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); } } @@ -5576,7 +5619,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel) gGL.begin(LLRender::LINES); gGL.color4f(1.f,1.f,1.f,1.f); F32 thickness = llmax(F32(5.0f-5.0f*(gFrameTimeSeconds-mLastImpostorUpdateFrameTime)),1.0f); - //glLineWidth(thickness); + //gGL.setLineWidth(thickness); gGL.vertex3fv((pos+left-up).mV); gGL.vertex3fv((pos-left-up).mV); gGL.vertex3fv((pos-left-up).mV); @@ -8857,7 +8900,8 @@ bool LLVOAvatar::processFullyLoadedChange(bool loading) bool LLVOAvatar::isFullyLoaded() const { - return (mRenderUnloadedAvatar && !isSelf()) || mFullyLoaded; + static LLCachedControl<bool> render_unloaded_avatar(gSavedSettings, "RenderUnloadedAvatar", false); + return (render_unloaded_avatar && !isSelf()) || mFullyLoaded; } bool LLVOAvatar::hasFirstFullAttachmentData() const @@ -10179,7 +10223,7 @@ void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& conte if (visualParamWeightsAreDefault() && mRuthTimer.getElapsedTimeF32() > LOADING_TIMEOUT_SECONDS) { // re-request appearance, hoping that it comes back with a shape next time - LL_INFOS() << "Re-requesting AvatarAppearance for object: " << getID() << LL_ENDL; + LL_INFOS() << "Re-requesting AvatarAppearance for agent: " << getID() << LL_ENDL; LLAvatarPropertiesProcessor::getInstance()->sendAvatarTexturesRequest(getID()); mRuthTimer.reset(); } @@ -10209,7 +10253,7 @@ void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& conte setCompositeUpdatesEnabled( true ); // If all of the avatars are completely baked, release the global image caches to conserve memory. - cullAvatarsByPixelArea(); + setCullNeedsUpdate(); if (isSelf()) { @@ -10873,39 +10917,71 @@ S32 LLVOAvatar::getUnbakedPixelAreaRank() return 0; } -// static +// static, gets called once per frame from updateApparentAngles. void LLVOAvatar::cullAvatarsByPixelArea() { - LLCharacter::sInstances.sort([](LLCharacter* lhs, LLCharacter* rhs) - { - return ((LLVOAvatar*)lhs)->mVisibilityPreference > ((LLVOAvatar*)rhs)->mVisibilityPreference; - }); + F64 current_time = LLFrameTimer::getElapsedSeconds(); + bool needs_resort = sAvatarCullNeedsUpdate || ((current_time - sLastCullUpdateTime) >= 1.0); - // Update the avatars that have changed status - U32 rank = 2; // Rank 1 is reserved for self. - for (LLCharacter* character : LLCharacter::sInstances) + if (needs_resort) { - LLVOAvatar* inst = (LLVOAvatar*)character; - bool culled = !inst->isSelf() && !inst->isFullyBaked(); - - if (inst->mCulled != culled) + LLCharacter::sInstances.sort([](LLCharacter* lhs, LLCharacter* rhs) { - inst->mCulled = culled; - LL_DEBUGS() << "avatar " << inst->getID() << (culled ? " start culled" : " start not culled" ) << LL_ENDL; - inst->updateMeshTextures(); - } + LLVOAvatar* lhs_av = (LLVOAvatar*)lhs; + LLVOAvatar* rhs_av = (LLVOAvatar*)rhs; + if (lhs_av->mVisible != rhs_av->mVisible) + { + return lhs_av->mVisible; + } + // Sort by pixel area in descending order (larger pixel area = higher priority) + return lhs_av->getPixelArea() > rhs_av->getPixelArea(); + }); - if (inst->isSelf()) - { - inst->setVisibilityRank(1); - } - else if (inst->mDrawable.notNull() && inst->mDrawable->isVisible()) + // Update the avatars that have changed status + U32 rank = 2; // Rank 1 is reserved for self. + for (LLCharacter* character : LLCharacter::sInstances) { - inst->setVisibilityRank(rank++); + LLVOAvatar* inst = (LLVOAvatar*)character; + bool culled = !inst->isSelf() && !inst->isFullyBaked(); + + if (inst->mCulled != culled) + { + inst->mCulled = culled; + LL_DEBUGS() << "avatar " << inst->getID() << (culled ? " start culled" : " start not culled" ) << LL_ENDL; + inst->updateMeshTextures(); + } + + if (inst->isSelf()) + { + inst->setVisibilityRank(1); + } + else if (inst->mDrawable.notNull() && inst->mDrawable->isVisible()) + { + inst->setVisibilityRank(rank++); + } + else + { + inst->setVisibilityRank(sMaxNonImpostors * 5); + } + inst->mLastCulledPixelArea = inst->getPixelArea(); } - else + sAvatarCullNeedsUpdate = false; + sLastCullUpdateTime = current_time; + } + else + { + for (LLCharacter* character : LLCharacter::sInstances) { - inst->setVisibilityRank(sMaxNonImpostors * 5); + // Todo: this can be optimized by tracking baked's callbacks + LLVOAvatar* inst = (LLVOAvatar*)character; + bool culled = !inst->isSelf() && !inst->isFullyBaked(); + + if (inst->mCulled != culled) + { + inst->mCulled = culled; + LL_DEBUGS() << "avatar " << inst->getID() << (culled ? " start culled" : " start not culled") << LL_ENDL; + inst->updateMeshTextures(); + } } } @@ -11001,9 +11077,6 @@ bool LLVOAvatar::updateLOD() if (mDirtyMesh >= 2 || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY)) { //LOD changed or new mesh created, allocate new vertex buffer if needed updateMeshData(); - mDirtyMesh = 0; - mNeedsSkin = true; - mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); } updateVisibility(); |
