From 4e6303792a49e4db7a30ab5774668eb54b6a50b2 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 22 Jun 2023 00:53:18 +0300 Subject: SL-5161 Don't render meshes that are waiting for skin data --- indra/newview/llmeshrepository.cpp | 54 ++++++++++++++++++++++++++++++++ indra/newview/llmeshrepository.h | 4 +++ indra/newview/llvovolume.cpp | 63 ++++++++++++++++++++++++++++---------- indra/newview/llvovolume.h | 3 +- 4 files changed, 107 insertions(+), 17 deletions(-) diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 67bf6827ad..9f90e132f8 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -4255,6 +4255,37 @@ bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id) return false; } +bool LLMeshRepository::hasSkinInfo(const LLUUID& mesh_id) +{ + if (mesh_id.isNull()) + { + return false; + } + + if (mThread->hasSkinInfoInHeader(mesh_id)) + { + return true; + } + + const LLMeshSkinInfo* skininfo = getSkinInfo(mesh_id); + if (skininfo) + { + return true; + } + + return false; +} + +bool LLMeshRepository::hasHeader(const LLUUID& mesh_id) +{ + if (mesh_id.isNull()) + { + return false; + } + + return mThread->hasHeader(mesh_id); +} + bool LLMeshRepoThread::hasPhysicsShapeInHeader(const LLUUID& mesh_id) { LLMutexLock lock(mHeaderMutex); @@ -4271,6 +4302,29 @@ bool LLMeshRepoThread::hasPhysicsShapeInHeader(const LLUUID& mesh_id) return false; } +bool LLMeshRepoThread::hasSkinInfoInHeader(const LLUUID& mesh_id) +{ + LLMutexLock lock(mHeaderMutex); + mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); + if (iter != mMeshHeader.end() && iter->second.first > 0) + { + LLMeshHeader& mesh = iter->second.second; + if (mesh.mSkinOffset >= 0 + && mesh.mSkinSize > 0) + { + return true; + } + } + + return false; +} + +bool LLMeshRepoThread::hasHeader(const LLUUID& mesh_id) +{ + LLMutexLock lock(mHeaderMutex); + mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); + return iter != mMeshHeader.end(); +} void LLMeshRepository::uploadModel(std::vector& data, LLVector3& scale, bool upload_textures, bool upload_skin, bool upload_joints, bool lock_scale_if_joint_position, diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 619e076fa6..89cd2d867f 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -401,6 +401,8 @@ public: bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size); EMeshProcessingResult physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size); bool hasPhysicsShapeInHeader(const LLUUID& mesh_id); + bool hasSkinInfoInHeader(const LLUUID& mesh_id); + bool hasHeader(const LLUUID& mesh_id); void notifyLoadedMeshes(); S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); @@ -650,6 +652,8 @@ public: LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id); void fetchPhysicsShape(const LLUUID& mesh_id); bool hasPhysicsShape(const LLUUID& mesh_id); + bool hasSkinInfo(const LLUUID& mesh_id); + bool hasHeader(const LLUUID& mesh_id); void buildHull(const LLVolumeParams& params, S32 detail); void buildPhysicsMesh(LLModel::Decomposition& decomp); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 8160785d75..805eb47431 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -230,7 +230,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mColorChanged = FALSE; mSpotLightPriority = 0.f; - mSkinInfoFailed = false; + mSkinInfoUnavaliable = false; mSkinInfo = NULL; mMediaImplList.resize(getNumTEs()); @@ -1132,7 +1132,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo if (mSkinInfo && mSkinInfo->mMeshID != volume_params.getSculptID()) { mSkinInfo = NULL; - mSkinInfoFailed = false; + mSkinInfoUnavaliable = false; } if (!getVolume()->isMeshAssetLoaded()) @@ -1145,13 +1145,24 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo } } - if (!mSkinInfo && !mSkinInfoFailed) + if (!mSkinInfo && !mSkinInfoUnavaliable) { - const LLMeshSkinInfo* skin_info = gMeshRepo.getSkinInfo(volume_params.getSculptID(), this); - if (skin_info) - { - notifySkinInfoLoaded(skin_info); - } + LLUUID mesh_id = volume_params.getSculptID(); + if (gMeshRepo.hasHeader(mesh_id) && !gMeshRepo.hasSkinInfo(mesh_id)) + { + // If header is present but has no data about skin, + // no point fetching + mSkinInfoUnavaliable = true; + } + + if (!mSkinInfoUnavaliable) + { + const LLMeshSkinInfo* skin_info = gMeshRepo.getSkinInfo(mesh_id, this); + if (skin_info) + { + notifySkinInfoLoaded(skin_info); + } + } } } else // otherwise is sculptie @@ -1186,7 +1197,7 @@ void LLVOVolume::updateSculptTexture() mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); } - mSkinInfoFailed = false; + mSkinInfoUnavaliable = false; mSkinInfo = NULL; } else @@ -1227,6 +1238,16 @@ void LLVOVolume::notifyMeshLoaded() mSculptChanged = TRUE; gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); + if (!mSkinInfo && !mSkinInfoUnavaliable) + { + // Header was loaded, update skin info state from header + LLUUID mesh_id = getVolume()->getParams().getSculptID(); + if (!gMeshRepo.hasSkinInfo(mesh_id)) + { + mSkinInfoUnavaliable = true; + } + } + LLVOAvatar *av = getAvatar(); if (av && !isAnimatedObject()) { @@ -1244,7 +1265,7 @@ void LLVOVolume::notifyMeshLoaded() void LLVOVolume::notifySkinInfoLoaded(const LLMeshSkinInfo* skin) { - mSkinInfoFailed = false; + mSkinInfoUnavaliable = false; mSkinInfo = skin; notifyMeshLoaded(); @@ -1252,7 +1273,7 @@ void LLVOVolume::notifySkinInfoLoaded(const LLMeshSkinInfo* skin) void LLVOVolume::notifySkinInfoUnavailable() { - mSkinInfoFailed = true; + mSkinInfoUnavaliable = true; mSkinInfo = nullptr; } @@ -5589,11 +5610,21 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) std::string vobj_name = llformat("Vol%p", vobj); bool is_mesh = vobj->isMesh(); - if (is_mesh && - ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) - { - continue; - } + if (is_mesh) + { + if ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) + || !gMeshRepo.meshRezEnabled()) + { + // Waiting for asset to fetch + continue; + } + + if (!vobj->getSkinInfo() && !vobj->isSkinInfoUnavaliable()) + { + // Waiting for skin info to fetch + continue; + } + } LLVolume* volume = vobj->getVolume(); if (volume) diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index acba18383f..aadc1fbcf3 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -330,6 +330,7 @@ public: BOOL setIsFlexible(BOOL is_flexible); const LLMeshSkinInfo* getSkinInfo() const; + const bool isSkinInfoUnavaliable() const { return mSkinInfoUnavaliable; } //convenience accessor for mesh ID (which is stored in sculpt id for legacy reasons) const LLUUID& getMeshID() const { return getVolume()->getParams().getSculptID(); } @@ -480,7 +481,7 @@ private: LLPointer mRiggedVolume; - bool mSkinInfoFailed; + bool mSkinInfoUnavaliable; LLConstPointer mSkinInfo; // statics public: -- cgit v1.2.3 From ca84e0e0c0b4b2844f478a549cb2cb1fbb52c898 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 22 Jun 2023 22:09:42 +0300 Subject: SL-5161 Avatars should stay hidden longer if they are waiting for meshes or skin data --- indra/llmath/llvolume.cpp | 25 ++++++++++-- indra/llmath/llvolume.h | 9 +++-- indra/newview/llmeshrepository.cpp | 8 +++- indra/newview/llvoavatar.cpp | 80 ++++++++++++++++++++++++++++++++++++++ indra/newview/llvoavatar.h | 1 + 5 files changed, 116 insertions(+), 7 deletions(-) diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 91e463cc32..0e3792fda3 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2056,7 +2056,8 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mDetail = detail; mSculptLevel = -2; mSurfaceArea = 1.f; //only calculated for sculpts, defaults to 1 for all other prims - mIsMeshAssetLoaded = FALSE; + mIsMeshAssetLoaded = false; + mIsMeshAssetUnavaliable = false; mLODScaleBias.setVec(1,1,1); mHullPoints = NULL; mHullIndices = NULL; @@ -2804,14 +2805,32 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) } -BOOL LLVolume::isMeshAssetLoaded() +bool LLVolume::isMeshAssetLoaded() { return mIsMeshAssetLoaded; } -void LLVolume::setMeshAssetLoaded(BOOL loaded) +void LLVolume::setMeshAssetLoaded(bool loaded) { mIsMeshAssetLoaded = loaded; + if (loaded) + { + mIsMeshAssetUnavaliable = false; + } +} + +void LLVolume::setMeshAssetUnavaliable(bool unavaliable) +{ + // Don't set it if at least one lod loaded + if (!mIsMeshAssetLoaded) + { + mIsMeshAssetUnavaliable = unavaliable; + } +} + +bool LLVolume::isMeshAssetUnavaliable() +{ + return mIsMeshAssetUnavaliable; } void LLVolume::copyFacesTo(std::vector &faces) const diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index ad6a669531..afed98ff36 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -1111,15 +1111,18 @@ private: bool unpackVolumeFacesInternal(const LLSD& mdl); public: - virtual void setMeshAssetLoaded(BOOL loaded); - virtual BOOL isMeshAssetLoaded(); + virtual void setMeshAssetLoaded(bool loaded); + virtual bool isMeshAssetLoaded(); + virtual void setMeshAssetUnavaliable(bool unavaliable); + virtual bool isMeshAssetUnavaliable(); protected: BOOL mUnique; F32 mDetail; S32 mSculptLevel; F32 mSurfaceArea; //unscaled surface area - BOOL mIsMeshAssetLoaded; + bool mIsMeshAssetLoaded; + bool mIsMeshAssetUnavaliable; const LLVolumeParams mParams; LLPath *mPathp; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 9f90e132f8..57ac111fdf 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -4067,7 +4067,7 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol if (sys_volume) { sys_volume->copyVolumeFaces(volume); - sys_volume->setMeshAssetLoaded(TRUE); + sys_volume->setMeshAssetLoaded(true); LLPrimitive::getVolumeManager()->unrefVolume(sys_volume); } else @@ -4099,6 +4099,12 @@ void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params, { F32 detail = LLVolumeLODGroup::getVolumeScaleFromDetail(lod); + LLVolume* sys_volume = LLPrimitive::getVolumeManager()->refVolume(mesh_params, detail); + if (sys_volume) + { + sys_volume->setMeshAssetUnavaliable(true); + } + for (LLVOVolume* vobj : obj_iter->second) { if (vobj) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index c7a2cea627..22cd9f71b3 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -7574,6 +7574,85 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO ) } } +bool LLVOAvatar::hasPendingAttachedMeshes() +{ + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (attachment) + { + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject* objectp = attachment_iter->get(); + if (objectp) + { + LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter1 = child_list.begin(); + iter1 != child_list.end(); ++iter1) + { + LLViewerObject* objectchild = *iter1; + if (objectchild && objectchild->getVolume()) + { + const LLUUID& mesh_id = objectchild->getVolume()->getParams().getSculptID(); + if (mesh_id.isNull()) + { + // No mesh nor skin info needed + continue; + } + + if (objectchild->getVolume()->isMeshAssetUnavaliable()) + { + // Mesh failed to load, do not expect it + continue; + } + + if (objectchild->mDrawable) + { + LLVOVolume* pvobj = objectchild->mDrawable->getVOVolume(); + if (pvobj) + { + if (!pvobj->isMesh()) + { + // Not a mesh + continue; + } + + if (!objectchild->getVolume()->isMeshAssetLoaded()) + { + // Waiting for mesh + return true; + } + + const LLMeshSkinInfo* skin_data = pvobj->getSkinInfo(); + if (skin_data) + { + // Skin info present, done + continue; + } + + if (pvobj->isSkinInfoUnavaliable()) + { + // Load failed or info not present, don't expect it + continue; + } + } + + // objectchild is not ready + return true; + } + } + } + } + } + } + } + return false; +} + //----------------------------------------------------------------------------- // detachObject() //----------------------------------------------------------------------------- @@ -8150,6 +8229,7 @@ BOOL LLVOAvatar::updateIsFullyLoaded() || (mLoadedCallbackTextures < mCallbackTextureList.size() && mLastTexCallbackAddedTime.getElapsedTimeF32() < MAX_TEXTURE_WAIT_TIME_SEC) || !mPendingAttachment.empty() || (rez_status < 3 && !isFullyBaked()) + || hasPendingAttachedMeshes() ); } updateRezzedStatusTimers(rez_status); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index f1dc503c9e..48bfd5293a 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -917,6 +917,7 @@ public: virtual BOOL detachObject(LLViewerObject *viewer_object); static bool getRiggedMeshID( LLViewerObject* pVO, LLUUID& mesh_id ); void cleanupAttachedMesh( LLViewerObject* pVO ); + bool hasPendingAttachedMeshes(); static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj); /*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type ) const; LLViewerObject * findAttachmentByID( const LLUUID & target_id ) const; -- cgit v1.2.3