From 981e88b92549cae661a077490df693f1d207c808 Mon Sep 17 00:00:00 2001 From: thickbrick Date: Mon, 24 Jan 2011 19:40:13 +0200 Subject: Additional Fix #772 and other sculpt problems Port from V2 (Snowglobe2) that adds to each texture a list of faces and sculpt volumes that use that texture, and rebuild all sculpts when the texture is decoded. This is needed so that we don't depend on LOD changes which may never/rarely happen for some megaprim sculpts. --- linden/indra/newview/llface.h | 4 + linden/indra/newview/llviewerimage.cpp | 131 ++++++++++++++++++++++++++++++--- linden/indra/newview/llviewerimage.h | 26 ++++++- linden/indra/newview/llvovolume.cpp | 56 +++++++++++--- linden/indra/newview/llvovolume.h | 6 +- 5 files changed, 195 insertions(+), 28 deletions(-) diff --git a/linden/indra/newview/llface.h b/linden/indra/newview/llface.h index 4893e82..e31b93f 100644 --- a/linden/indra/newview/llface.h +++ b/linden/indra/newview/llface.h @@ -106,6 +106,9 @@ public: F32 getVirtualSize() const { return mVSize; } F32 getPixelArea() const { return mPixelArea; } + S32 getIndexInTex() const {return mIndexInTex ;} + void setIndexInTex(S32 index) { mIndexInTex = index ;} + void renderSetColor() const; S32 renderElements(const U16 *index_array) const; S32 renderIndexed (); @@ -225,6 +228,7 @@ private: U16 mGeomIndex; // index into draw pool U32 mIndicesCount; U32 mIndicesIndex; // index into draw pool for indices (yeah, I know!) + S32 mIndexInTex ; //previous rebuild's geometry info U16 mLastGeomCount; diff --git a/linden/indra/newview/llviewerimage.cpp b/linden/indra/newview/llviewerimage.cpp index a600dc5..28561ed 100644 --- a/linden/indra/newview/llviewerimage.cpp +++ b/linden/indra/newview/llviewerimage.cpp @@ -61,6 +61,7 @@ #include "llappviewer.h" #include "llface.h" #include "llviewercamera.h" +#include "llvovolume.h" /////////////////////////////////////////////////////////////////////////////// // statics @@ -352,6 +353,11 @@ void LLViewerImage::init(bool firstinit) mDesiredSavedRawDiscardLevel = -1 ; mCanUseHTTP = true; //default on if cap/settings allows us + + mNumFaces = 0 ; + mNumVolumes = 0; + mFaceList.clear() ; + mVolumeList.clear(); } // virtual @@ -388,6 +394,7 @@ LLViewerImage::~LLViewerImage() void LLViewerImage::cleanup() { mFaceList.clear() ; + mVolumeList.clear(); for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) { @@ -754,19 +761,19 @@ void LLViewerImage::updateVirtualSize() { addTextureStats(0.f, FALSE) ;//reset } - if(mFaceList.size() > 0) + for(U32 i = 0 ; i < mNumFaces ; i++) { - for(std::list::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + LLFace* facep = mFaceList[i] ; + if(facep->getDrawable()->isRecentlyVisible()) { - LLFace* facep = *iter ; - if(facep->getDrawable()->isRecentlyVisible()) - { - addTextureStats(facep->getVirtualSize()) ; - setAdditionalDecodePriority(facep->getImportanceToCamera()) ; - } - } + addTextureStats(facep->getVirtualSize()) ; + setAdditionalDecodePriority(facep->getImportanceToCamera()) ; + } } + mNeedsResetMaxVirtualSize = TRUE ; + reorganizeFaceList(); + reorganizeVolumeList(); #endif } void LLViewerImage::scaleDown() @@ -1817,11 +1824,111 @@ void LLViewerImage::setForSculpt() checkCachedRawSculptImage() ; } +//virtual void LLViewerImage::addFace(LLFace* facep) { - mFaceList.push_back(facep) ; + if(mNumFaces >= mFaceList.size()) + { + mFaceList.resize(2 * mNumFaces + 1) ; + } + mFaceList[mNumFaces] = facep ; + facep->setIndexInTex(mNumFaces) ; + mNumFaces++ ; + mLastFaceListUpdateTimer.reset() ; +} + +//virtual +void LLViewerImage::removeFace(LLFace* facep) +{ + if(mNumFaces > 1) + { + S32 index = facep->getIndexInTex() ; + mFaceList[index] = mFaceList[--mNumFaces] ; + mFaceList[index]->setIndexInTex(index) ; + } + else + { + mFaceList.clear() ; + mNumFaces = 0 ; + } + mLastFaceListUpdateTimer.reset() ; +} + +S32 LLViewerImage::getNumFaces() const +{ + return mNumFaces ; +} + + +//virtual +void LLViewerImage::addVolume(LLVOVolume* volumep) +{ + if( mNumVolumes >= mVolumeList.size()) + { + mVolumeList.resize(2 * mNumVolumes + 1) ; + } + mVolumeList[mNumVolumes] = volumep ; + volumep->setIndexInTex(mNumVolumes) ; + mNumVolumes++ ; + mLastVolumeListUpdateTimer.reset() ; } -void LLViewerImage::removeFace(LLFace* facep) + +//virtual +void LLViewerImage::removeVolume(LLVOVolume* volumep) { - mFaceList.remove(facep) ; + if(mNumVolumes > 1) + { + S32 index = volumep->getIndexInTex() ; + mVolumeList[index] = mVolumeList[--mNumVolumes] ; + mVolumeList[index]->setIndexInTex(index) ; + } + else + { + mVolumeList.clear() ; + mNumVolumes = 0 ; + } + mLastVolumeListUpdateTimer.reset() ; +} + +S32 LLViewerImage::getNumVolumes() const +{ + return mNumVolumes ; +} + +void LLViewerImage::reorganizeFaceList() +{ + static const F32 MAX_WAIT_TIME = 20.f; // seconds + static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ; + + if(mNumFaces + MAX_EXTRA_BUFFER_SIZE > mFaceList.size()) + { + return ; + } + + if(mLastFaceListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME) + { + return ; + } + + mLastFaceListUpdateTimer.reset() ; + mFaceList.erase(mFaceList.begin() + mNumFaces, mFaceList.end()); +} + +void LLViewerImage::reorganizeVolumeList() +{ + static const F32 MAX_WAIT_TIME = 20.f; // seconds + static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ; + + if(mNumVolumes + MAX_EXTRA_BUFFER_SIZE > mVolumeList.size()) + { + return ; + } + + if(mLastVolumeListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME) + { + return ; + } + + mLastVolumeListUpdateTimer.reset() ; + mVolumeList.erase(mVolumeList.begin() + mNumVolumes, mVolumeList.end()); } diff --git a/linden/indra/newview/llviewerimage.h b/linden/indra/newview/llviewerimage.h index 3bee51c..c2e3303 100644 --- a/linden/indra/newview/llviewerimage.h +++ b/linden/indra/newview/llviewerimage.h @@ -51,6 +51,7 @@ typedef void (*loaded_callback_func)( BOOL success, LLViewerImage *src_vi, LLIma class LLVFile; class LLMessageSystem; +class LLVOVolume; class LLLoadedCallbackEntry { @@ -209,6 +210,9 @@ public: INVALID_DISCARD_LEVEL = 0x7fff }; + typedef std::vector ll_face_list_t; + typedef std::vector ll_volume_list_t; + protected: /*virtual*/ ~LLViewerImage(); @@ -311,8 +315,17 @@ public: BOOL isSameTexture(const LLViewerImage* tex) const ; - void addFace(LLFace* facep) ; - void removeFace(LLFace* facep) ; + virtual void addFace(LLFace* facep) ; + virtual void removeFace(LLFace* facep) ; + S32 getNumFaces() const; + const ll_face_list_t* getFaceList() const {return &mFaceList;} + void reorganizeFaceList() ; + + virtual void addVolume(LLVOVolume* volumep); + virtual void removeVolume(LLVOVolume* volumep); + S32 getNumVolumes() const; + const ll_volume_list_t* getVolumeList() const { return &mVolumeList; } + void reorganizeVolumeList() ; void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;}; @@ -417,8 +430,13 @@ private: BOOL mForSculpt ; //a flag if the texture is used for a sculpt data. mutable BOOL mNeedsResetMaxVirtualSize ; - typedef std::list ll_face_list_t ; - ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture + ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture + U32 mNumFaces ; + LLFrameTimer mLastFaceListUpdateTimer ; + + ll_volume_list_t mVolumeList; + U32 mNumVolumes; + LLFrameTimer mLastVolumeListUpdateTimer; bool mCanUseHTTP; // can this image be fetched by http diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp index 632bca2..e4a0d0c 100644 --- a/linden/indra/newview/llvovolume.cpp +++ b/linden/indra/newview/llvovolume.cpp @@ -89,12 +89,12 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mRelativeXformInvTrans.setIdentity(); mLOD = MIN_LOD; - mSculptLevel = -2; mTextureAnimp = NULL; mVObjRadius = LLVector3(1,1,0.5f).length(); mNumFaces = 0; mLODChanged = FALSE; mSculptChanged = FALSE; + mIndexInTex = 0; } LLVOVolume::~LLVOVolume() @@ -502,9 +502,8 @@ void LLVOVolume::updateTextureVirtualSize() if (isSculpted()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - mSculptTexture = gImageList.getImage(id); + updateSculptTexture(); + if (mSculptTexture.notNull()) { mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(), @@ -682,25 +681,52 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail mVolumeImpl->onSetVolume(volume_params, detail); } + updateSculptTexture(); + if (isSculpted()) { - mSculptTexture = gImageList.getImage(volume_params.getSculptID()); if (mSculptTexture.notNull()) { sculpt(); - mSculptLevel = getVolume()->getSculptLevel(); } } - else - { - mSculptTexture = NULL; - } return TRUE; } return FALSE; } +void LLVOVolume::updateSculptTexture() +{ + LLPointer old_sculpt = mSculptTexture; + + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID id = sculpt_params->getSculptTexture(); + if (id.notNull()) + { + mSculptTexture = gImageList::getImage(id); + } + } + else + { + mSculptTexture = NULL; + } + + if (mSculptTexture != old_sculpt) + { + if (old_sculpt.notNull()) + { + old_sculpt->removeVolume(this); + } + if (mSculptTexture.notNull()) + { + mSculptTexture->addVolume(this); + } + } +} + // sculpt replaces generate() for sculpted surfaces void LLVOVolume::sculpt() { @@ -754,6 +780,16 @@ void LLVOVolume::sculpt() sculpt_data = raw_image->getData(); } getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level); + + //notify rebuild any other VOVolumes that reference this sculpty volume + for (S32 i = 0; i < mSculptTexture->getNumVolumes(); ++i) + { + LLVOVolume* volume = (*(mSculptTexture->getVolumeList()))[i]; + if (volume != this && volume->getVolume() == getVolume()) + { + gPipeline.markRebuild(volume->mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE); + } + } } } diff --git a/linden/indra/newview/llvovolume.h b/linden/indra/newview/llvovolume.h index a78aa37..7c8a68d 100644 --- a/linden/indra/newview/llvovolume.h +++ b/linden/indra/newview/llvovolume.h @@ -169,8 +169,10 @@ public: /*virtual*/ BOOL setMaterial(const U8 material); void setTexture(const S32 face); - + S32 getIndexInTex() const {return mIndexInTex ;} /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false); + void updateSculptTexture(); + void setIndexInTex(S32 index) { mIndexInTex = index ;} void sculpt(); void updateRelativeXform(); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); @@ -231,7 +233,6 @@ private: LLFrameTimer mTextureUpdateTimer; S32 mLOD; BOOL mLODChanged; - S32 mSculptLevel; BOOL mSculptChanged; LLMatrix4 mRelativeXform; LLMatrix3 mRelativeXformInvTrans; @@ -239,6 +240,7 @@ private: F32 mVObjRadius; LLVolumeInterface *mVolumeImpl; LLPointer mSculptTexture; + S32 mIndexInTex; // statics public: -- cgit v1.1