/indra/newview/llvovolume.cpp
C++ | 2586 lines | 2053 code | 357 blank | 176 comment | 423 complexity | 72a4750d007eb3fabf818833a5f8f90a MD5 | raw file
Possible License(s): LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- /**
- * @file llvovolume.cpp
- * @brief LLVOVolume class implementation
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
- // A "volume" is a box, cylinder, sphere, or other primitive shape.
- #include "llviewerprecompiledheaders.h"
- #include "llvovolume.h"
- #include <sstream>
- #include "llviewercontrol.h"
- #include "lldir.h"
- #include "llflexibleobject.h"
- #include "llfloatertools.h"
- #include "llmaterialtable.h"
- #include "llprimitive.h"
- #include "llvolume.h"
- #include "llvolumeoctree.h"
- #include "llvolumemgr.h"
- #include "llvolumemessage.h"
- #include "material_codes.h"
- #include "message.h"
- #include "llpluginclassmedia.h" // for code in the mediaEvent handler
- #include "object_flags.h"
- #include "llagentconstants.h"
- #include "lldrawable.h"
- #include "lldrawpoolavatar.h"
- #include "lldrawpoolbump.h"
- #include "llface.h"
- #include "llspatialpartition.h"
- #include "llhudmanager.h"
- #include "llflexibleobject.h"
- #include "llsky.h"
- #include "lltexturefetch.h"
- #include "llvector4a.h"
- #include "llviewercamera.h"
- #include "llviewertexturelist.h"
- #include "llviewerobjectlist.h"
- #include "llviewerregion.h"
- #include "llviewertextureanim.h"
- #include "llworld.h"
- #include "llselectmgr.h"
- #include "pipeline.h"
- #include "llsdutil.h"
- #include "llmatrix4a.h"
- #include "llmediaentry.h"
- #include "llmediadataclient.h"
- #include "llmeshrepository.h"
- #include "llagent.h"
- #include "llviewermediafocus.h"
- #include "lldatapacker.h"
- #include "llviewershadermgr.h"
- #include "llvoavatar.h"
- #include "llvocache.h"
- const S32 MIN_QUIET_FRAMES_COALESCE = 30;
- const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
- const F32 FORCE_CULL_AREA = 8.f;
- const F32 MAX_LOD_DISTANCE = 24.f;
- BOOL gAnimateTextures = TRUE;
- //extern BOOL gHideSelectedObjects;
- F32 LLVOVolume::sLODFactor = 1.f;
- F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop
- F32 LLVOVolume::sDistanceFactor = 1.0f;
- S32 LLVOVolume::sNumLODChanges = 0;
- S32 LLVOVolume::mRenderComplexity_last = 0;
- S32 LLVOVolume::mRenderComplexity_current = 0;
- LLPointer<LLObjectMediaDataClient> LLVOVolume::sObjectMediaClient = NULL;
- LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient = NULL;
- static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles");
- static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes");
- static LLFastTimer::DeclareTimer FTM_VOLUME_TEXTURES("Volume Textures");
- // Implementation class of LLMediaDataClientObject. See llmediadataclient.h
- class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
- {
- public:
- LLMediaDataClientObjectImpl(LLVOVolume *obj, bool isNew) : mObject(obj), mNew(isNew)
- {
- mObject->addMDCImpl();
- }
- ~LLMediaDataClientObjectImpl()
- {
- mObject->removeMDCImpl();
- }
-
- virtual U8 getMediaDataCount() const
- { return mObject->getNumTEs(); }
- virtual LLSD getMediaDataLLSD(U8 index) const
- {
- LLSD result;
- LLTextureEntry *te = mObject->getTE(index);
- if (NULL != te)
- {
- llassert((te->getMediaData() != NULL) == te->hasMedia());
- if (te->getMediaData() != NULL)
- {
- result = te->getMediaData()->asLLSD();
- // XXX HACK: workaround bug in asLLSD() where whitelist is not set properly
- // See DEV-41949
- if (!result.has(LLMediaEntry::WHITELIST_KEY))
- {
- result[LLMediaEntry::WHITELIST_KEY] = LLSD::emptyArray();
- }
- }
- }
- return result;
- }
- virtual bool isCurrentMediaUrl(U8 index, const std::string &url) const
- {
- LLTextureEntry *te = mObject->getTE(index);
- if (te)
- {
- if (te->getMediaData())
- {
- return (te->getMediaData()->getCurrentURL() == url);
- }
- }
- return url.empty();
- }
- virtual LLUUID getID() const
- { return mObject->getID(); }
- virtual void mediaNavigateBounceBack(U8 index)
- { mObject->mediaNavigateBounceBack(index); }
-
- virtual bool hasMedia() const
- { return mObject->hasMedia(); }
-
- virtual void updateObjectMediaData(LLSD const &data, const std::string &version_string)
- { mObject->updateObjectMediaData(data, version_string); }
-
- virtual F64 getMediaInterest() const
- {
- F64 interest = mObject->getTotalMediaInterest();
- if (interest < (F64)0.0)
- {
- // media interest not valid yet, try pixel area
- interest = mObject->getPixelArea();
- // HACK: force recalculation of pixel area if interest is the "magic default" of 1024.
- if (interest == 1024.f)
- {
- const_cast<LLVOVolume*>(static_cast<LLVOVolume*>(mObject))->setPixelAreaAndAngle(gAgent);
- interest = mObject->getPixelArea();
- }
- }
- return interest;
- }
-
- virtual bool isInterestingEnough() const
- {
- return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest());
- }
- virtual std::string getCapabilityUrl(const std::string &name) const
- { return mObject->getRegion()->getCapability(name); }
-
- virtual bool isDead() const
- { return mObject->isDead(); }
-
- virtual U32 getMediaVersion() const
- { return LLTextureEntry::getVersionFromMediaVersionString(mObject->getMediaURL()); }
-
- virtual bool isNew() const
- { return mNew; }
- private:
- LLPointer<LLVOVolume> mObject;
- bool mNew;
- };
- LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
- : LLViewerObject(id, pcode, regionp),
- mVolumeImpl(NULL)
- {
- mTexAnimMode = 0;
- mRelativeXform.setIdentity();
- mRelativeXformInvTrans.setIdentity();
- mFaceMappingChanged = FALSE;
- mLOD = MIN_LOD;
- mTextureAnimp = NULL;
- mVolumeChanged = FALSE;
- mVObjRadius = LLVector3(1,1,0.5f).length();
- mNumFaces = 0;
- mLODChanged = FALSE;
- mSculptChanged = FALSE;
- mSpotLightPriority = 0.f;
- mMediaImplList.resize(getNumTEs());
- mLastFetchedMediaVersion = -1;
- mIndexInTex = 0;
- mMDCImplCount = 0;
- }
- LLVOVolume::~LLVOVolume()
- {
- delete mTextureAnimp;
- mTextureAnimp = NULL;
- delete mVolumeImpl;
- mVolumeImpl = NULL;
- if(!mMediaImplList.empty())
- {
- for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
- {
- if(mMediaImplList[i].notNull())
- {
- mMediaImplList[i]->removeObject(this) ;
- }
- }
- }
- }
- void LLVOVolume::markDead()
- {
- if (!mDead)
- {
- if(getMDCImplCount() > 0)
- {
- LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false);
- if (sObjectMediaClient) sObjectMediaClient->removeFromQueue(obj);
- if (sObjectMediaNavigateClient) sObjectMediaNavigateClient->removeFromQueue(obj);
- }
-
- // Detach all media impls from this object
- for(U32 i = 0 ; i < mMediaImplList.size() ; i++)
- {
- removeMediaImpl(i);
- }
- if (mSculptTexture.notNull())
- {
- mSculptTexture->removeVolume(this);
- }
- }
-
- LLViewerObject::markDead();
- }
- // static
- void LLVOVolume::initClass()
- {
- // gSavedSettings better be around
- if (gSavedSettings.getBOOL("PrimMediaMasterEnabled"))
- {
- const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay");
- const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay");
- const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries");
- const U32 max_sorted_queue_size = gSavedSettings.getU32("PrimMediaMaxSortedQueueSize");
- const U32 max_round_robin_queue_size = gSavedSettings.getU32("PrimMediaMaxRoundRobinQueueSize");
- sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries,
- max_sorted_queue_size, max_round_robin_queue_size);
- sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay,
- max_retries, max_sorted_queue_size, max_round_robin_queue_size);
- }
- }
- // static
- void LLVOVolume::cleanupClass()
- {
- sObjectMediaClient = NULL;
- sObjectMediaNavigateClient = NULL;
- }
- U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
- void **user_data,
- U32 block_num, EObjectUpdateType update_type,
- LLDataPacker *dp)
- {
- LLColor4U color;
- const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA);
- // Do base class updates...
- U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
- LLUUID sculpt_id;
- U8 sculpt_type = 0;
- if (isSculpted())
- {
- LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
- sculpt_id = sculpt_params->getSculptTexture();
- sculpt_type = sculpt_params->getSculptType();
- }
- if (!dp)
- {
- if (update_type == OUT_FULL)
- {
- ////////////////////////////////
- //
- // Unpack texture animation data
- //
- //
- if (mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureAnim))
- {
- if (!mTextureAnimp)
- {
- mTextureAnimp = new LLViewerTextureAnim();
- }
- else
- {
- if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH))
- {
- mTextureAnimp->reset();
- }
- }
- mTexAnimMode = 0;
- mTextureAnimp->unpackTAMessage(mesgsys, block_num);
- }
- else
- {
- if (mTextureAnimp)
- {
- delete mTextureAnimp;
- mTextureAnimp = NULL;
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- mTexAnimMode = 0;
- }
- }
- // Unpack volume data
- LLVolumeParams volume_params;
- LLVolumeMessage::unpackVolumeParams(&volume_params, mesgsys, _PREHASH_ObjectData, block_num);
- volume_params.setSculptID(sculpt_id, sculpt_type);
- if (setVolume(volume_params, 0))
- {
- markForUpdate(TRUE);
- }
- }
- // Sigh, this needs to be done AFTER the volume is set as well, otherwise bad stuff happens...
- ////////////////////////////
- //
- // Unpack texture entry data
- //
- S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num);
- if (result & teDirtyBits)
- {
- updateTEData();
- }
- if (result & TEM_CHANGE_MEDIA)
- {
- retval |= MEDIA_FLAGS_CHANGED;
- }
- }
- else
- {
- // CORY TO DO: Figure out how to get the value here
- if (update_type != OUT_TERSE_IMPROVED)
- {
- LLVolumeParams volume_params;
- BOOL res = LLVolumeMessage::unpackVolumeParams(&volume_params, *dp);
- if (!res)
- {
- llwarns << "Bogus volume parameters in object " << getID() << llendl;
- llwarns << getRegion()->getOriginGlobal() << llendl;
- }
- volume_params.setSculptID(sculpt_id, sculpt_type);
- if (setVolume(volume_params, 0))
- {
- markForUpdate(TRUE);
- }
- S32 res2 = unpackTEMessage(*dp);
- if (TEM_INVALID == res2)
- {
- // There's something bogus in the data that we're unpacking.
- dp->dumpBufferToLog();
- llwarns << "Flushing cache files" << llendl;
- if(LLVOCache::hasInstance() && getRegion())
- {
- LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ;
- }
-
- llwarns << "Bogus TE data in " << getID() << llendl;
- }
- else
- {
- if (res2 & teDirtyBits)
- {
- updateTEData();
- }
- if (res2 & TEM_CHANGE_MEDIA)
- {
- retval |= MEDIA_FLAGS_CHANGED;
- }
- }
- U32 value = dp->getPassFlags();
- if (value & 0x40)
- {
- if (!mTextureAnimp)
- {
- mTextureAnimp = new LLViewerTextureAnim();
- }
- else
- {
- if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH))
- {
- mTextureAnimp->reset();
- }
- }
- mTexAnimMode = 0;
- mTextureAnimp->unpackTAMessage(*dp);
- }
- else if (mTextureAnimp)
- {
- delete mTextureAnimp;
- mTextureAnimp = NULL;
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- mTexAnimMode = 0;
- }
- }
- else
- {
- S32 texture_length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureEntry);
- if (texture_length)
- {
- U8 tdpbuffer[1024];
- LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024);
- mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num);
- S32 result = unpackTEMessage(tdp);
- if (result & teDirtyBits)
- {
- updateTEData();
- }
- if (result & TEM_CHANGE_MEDIA)
- {
- retval |= MEDIA_FLAGS_CHANGED;
- }
- }
- }
- }
- if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED))
- {
- // If only the media URL changed, and it isn't a media version URL,
- // ignore it
- if ( ! ( retval & (MEDIA_URL_ADDED | MEDIA_URL_UPDATED) &&
- mMedia && ! mMedia->mMediaURL.empty() &&
- ! LLTextureEntry::isMediaVersionString(mMedia->mMediaURL) ) )
- {
- // If the media changed at all, request new media data
- LL_DEBUGS("MediaOnAPrim") << "Media update: " << getID() << ": retval=" << retval << " Media URL: " <<
- ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL;
- requestMediaDataUpdate(retval & MEDIA_FLAGS_CHANGED);
- }
- else {
- LL_INFOS("MediaOnAPrim") << "Ignoring media update for: " << getID() << " Media URL: " <<
- ((mMedia) ? mMedia->mMediaURL : std::string("")) << LL_ENDL;
- }
- }
- // ...and clean up any media impls
- cleanUpMediaImpls();
- return retval;
- }
- void LLVOVolume::animateTextures()
- {
- F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f;
- S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot);
-
- if (result)
- {
- if (!mTexAnimMode)
- {
- mFaceMappingChanged = TRUE;
- gPipeline.markTextured(mDrawable);
- }
- mTexAnimMode = result | mTextureAnimp->mMode;
-
- S32 start=0, end=mDrawable->getNumFaces()-1;
- if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end)
- {
- start = end = mTextureAnimp->mFace;
- }
-
- for (S32 i = start; i <= end; i++)
- {
- LLFace* facep = mDrawable->getFace(i);
- if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue;
- const LLTextureEntry* te = facep->getTextureEntry();
-
- if (!te)
- {
- continue;
- }
-
- if (!(result & LLViewerTextureAnim::ROTATE))
- {
- te->getRotation(&rot);
- }
- if (!(result & LLViewerTextureAnim::TRANSLATE))
- {
- te->getOffset(&off_s,&off_t);
- }
- if (!(result & LLViewerTextureAnim::SCALE))
- {
- te->getScale(&scale_s, &scale_t);
- }
- if (!facep->mTextureMatrix)
- {
- facep->mTextureMatrix = new LLMatrix4();
- }
- LLMatrix4& tex_mat = *facep->mTextureMatrix;
- tex_mat.setIdentity();
- LLVector3 trans ;
- if(facep->isAtlasInUse())
- {
- //
- //if use atlas for animated texture
- //apply the following transform to the animation matrix.
- //
- F32 tcoord_xoffset = 0.f ;
- F32 tcoord_yoffset = 0.f ;
- F32 tcoord_xscale = 1.f ;
- F32 tcoord_yscale = 1.f ;
- if(facep->isAtlasInUse())
- {
- const LLVector2* tmp = facep->getTexCoordOffset() ;
- tcoord_xoffset = tmp->mV[0] ;
- tcoord_yoffset = tmp->mV[1] ;
- tmp = facep->getTexCoordScale() ;
- tcoord_xscale = tmp->mV[0] ;
- tcoord_yscale = tmp->mV[1] ;
- }
- trans.set(LLVector3(tcoord_xoffset + tcoord_xscale * (off_s+0.5f), tcoord_yoffset + tcoord_yscale * (off_t+0.5f), 0.f));
- tex_mat.translate(LLVector3(-(tcoord_xoffset + tcoord_xscale * 0.5f), -(tcoord_yoffset + tcoord_yscale * 0.5f), 0.f));
- }
- else //non atlas
- {
- trans.set(LLVector3(off_s+0.5f, off_t+0.5f, 0.f));
- tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
- }
- LLVector3 scale(scale_s, scale_t, 1.f);
- LLQuaternion quat;
- quat.setQuat(rot, 0, 0, -1.f);
-
- tex_mat.rotate(quat);
- LLMatrix4 mat;
- mat.initAll(scale, LLQuaternion(), LLVector3());
- tex_mat *= mat;
-
- tex_mat.translate(trans);
- }
- }
- else
- {
- if (mTexAnimMode && mTextureAnimp->mRate == 0)
- {
- U8 start, count;
- if (mTextureAnimp->mFace == -1)
- {
- start = 0;
- count = getNumTEs();
- }
- else
- {
- start = (U8) mTextureAnimp->mFace;
- count = 1;
- }
- for (S32 i = start; i < start + count; i++)
- {
- if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE)
- {
- setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT);
- }
- if (mTexAnimMode & LLViewerTextureAnim::SCALE)
- {
- setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT);
- }
- if (mTexAnimMode & LLViewerTextureAnim::ROTATE)
- {
- setTERotation(i, mTextureAnimp->mRot);
- }
- }
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- mTexAnimMode = 0;
- }
- }
- }
- BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
- {
- LLViewerObject::idleUpdate(agent, world, time);
- static LLFastTimer::DeclareTimer ftm("Volume");
- LLFastTimer t(ftm);
- if (mDead || mDrawable.isNull())
- {
- return TRUE;
- }
-
- ///////////////////////
- //
- // Do texture animation stuff
- //
- if (mTextureAnimp && gAnimateTextures)
- {
- animateTextures();
- }
- // Dispatch to implementation
- if (mVolumeImpl)
- {
- mVolumeImpl->doIdleUpdate(agent, world, time);
- }
- const S32 MAX_ACTIVE_OBJECT_QUIET_FRAMES = 40;
- if (mDrawable->isActive())
- {
- if (mDrawable->isRoot() &&
- mDrawable->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES &&
- (!mDrawable->getParent() || !mDrawable->getParent()->isActive()))
- {
- mDrawable->makeStatic();
- }
- }
- return TRUE;
- }
- void LLVOVolume::updateTextures()
- {
- const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds
- if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME)
- {
- updateTextureVirtualSize();
- }
- }
- BOOL LLVOVolume::isVisible() const
- {
- if(mDrawable.notNull() && mDrawable->isVisible())
- {
- return TRUE ;
- }
- if(isAttachment())
- {
- LLViewerObject* objp = (LLViewerObject*)getParent() ;
- while(objp && !objp->isAvatar())
- {
- objp = (LLViewerObject*)objp->getParent() ;
- }
- return objp && objp->mDrawable.notNull() && objp->mDrawable->isVisible() ;
- }
- return FALSE ;
- }
- void LLVOVolume::updateTextureVirtualSize(bool forced)
- {
- LLFastTimer ftm(FTM_VOLUME_TEXTURES);
- // Update the pixel area of all faces
- if(!forced)
- {
- if(!isVisible())
- {
- return ;
- }
- if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE))
- {
- return;
- }
- }
- static LLCachedControl<bool> dont_load_textures(gSavedSettings,"TextureDisable");
-
- if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible())
- {
- return;
- }
- mTextureUpdateTimer.reset();
-
- F32 old_area = mPixelArea;
- mPixelArea = 0.f;
- const S32 num_faces = mDrawable->getNumFaces();
- F32 min_vsize=999999999.f, max_vsize=0.f;
- LLViewerCamera* camera = LLViewerCamera::getInstance();
- for (S32 i = 0; i < num_faces; i++)
- {
- LLFace* face = mDrawable->getFace(i);
- const LLTextureEntry *te = face->getTextureEntry();
- LLViewerTexture *imagep = face->getTexture();
- if (!imagep || !te ||
- face->mExtents[0].equals3(face->mExtents[1]))
- {
- continue;
- }
-
- F32 vsize;
- F32 old_size = face->getVirtualSize();
- if (isHUDAttachment())
- {
- F32 area = (F32) camera->getScreenPixelArea();
- vsize = area;
- imagep->setBoostLevel(LLViewerTexture::BOOST_HUD);
- face->setPixelArea(area); // treat as full screen
- face->setVirtualSize(vsize);
- }
- else
- {
- vsize = face->getTextureVirtualSize();
- }
- mPixelArea = llmax(mPixelArea, face->getPixelArea());
- if (face->mTextureMatrix != NULL)
- {
- if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) ||
- (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE))
- {
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE);
- }
- }
-
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
- {
- if (vsize < min_vsize) min_vsize = vsize;
- if (vsize > max_vsize) max_vsize = vsize;
- }
- else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
- {
- LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ;
- if(img)
- {
- F32 pri = img->getDecodePriority();
- pri = llmax(pri, 0.0f);
- if (pri < min_vsize) min_vsize = pri;
- if (pri > max_vsize) max_vsize = pri;
- }
- }
- else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
- {
- F32 pri = mPixelArea;
- if (pri < min_vsize) min_vsize = pri;
- if (pri > max_vsize) max_vsize = pri;
- }
- }
-
- if (isSculpted())
- {
- LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
- LLUUID id = sculpt_params->getSculptTexture();
-
- updateSculptTexture();
-
-
- if (mSculptTexture.notNull())
- {
- mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(),
- (S32)LLViewerTexture::BOOST_SCULPTED));
- mSculptTexture->setForSculpt() ;
-
- if(!mSculptTexture->isCachedRawImageReady())
- {
- S32 lod = llmin(mLOD, 3);
- F32 lodf = ((F32)(lod + 1.0f)/4.f);
- F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ;
- mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE);
-
- //if the sculpty very close to the view point, load first
- {
- LLVector3 lookAt = getPositionAgent() - camera->getOrigin();
- F32 dist = lookAt.normVec() ;
- F32 cos_angle_to_view_dir = lookAt * camera->getXAxis() ;
- mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ;
- }
- }
-
- S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture
- S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ;
- if (texture_discard >= 0 && //texture has some data available
- (texture_discard < current_discard || //texture has more data than last rebuild
- current_discard < 0)) //no previous rebuild
- {
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
- mSculptChanged = TRUE;
- }
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED))
- {
- setDebugText(llformat("T%d C%d V%d\n%dx%d",
- texture_discard, current_discard, getVolume()->getSculptLevel(),
- mSculptTexture->getHeight(), mSculptTexture->getWidth()));
- }
- }
- }
- if (getLightTextureID().notNull())
- {
- LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
- LLUUID id = params->getLightTexture();
- mLightTexture = LLViewerTextureManager::getFetchedTexture(id);
- if (mLightTexture.notNull())
- {
- F32 rad = getLightRadius();
- mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(),
- LLVector3(rad,rad,rad),
- *camera));
- }
- }
-
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
- {
- setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize)));
- }
- else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
- {
- setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize)));
- }
- else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
- {
- setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize)));
- }
- if (mPixelArea == 0)
- { //flexi phasing issues make this happen
- mPixelArea = old_area;
- }
- }
- BOOL LLVOVolume::isActive() const
- {
- return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive()) ||
- (mDrawable.notNull() && mDrawable->isActive());
- }
- BOOL LLVOVolume::setMaterial(const U8 material)
- {
- BOOL res = LLViewerObject::setMaterial(material);
-
- return res;
- }
- void LLVOVolume::setTexture(const S32 face)
- {
- llassert(face < getNumTEs());
- gGL.getTexUnit(0)->bind(getTEImage(face));
- }
- void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped)
- {
- if (scale != getScale())
- {
- // store local radius
- LLViewerObject::setScale(scale);
- if (mVolumeImpl)
- {
- mVolumeImpl->onSetScale(scale, damped);
- }
-
- updateRadius();
- //since drawable transforms do not include scale, changing volume scale
- //requires an immediate rebuild of volume verts.
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE);
- }
- }
- LLFace* LLVOVolume::addFace(S32 f)
- {
- const LLTextureEntry* te = getTE(f);
- LLViewerTexture* imagep = getTEImage(f);
- return mDrawable->addFace(te, imagep);
- }
- LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
- {
- pipeline->allocDrawable(this);
-
- mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME);
- S32 max_tes_to_set = getNumTEs();
- for (S32 i = 0; i < max_tes_to_set; i++)
- {
- addFace(i);
- }
- mNumFaces = max_tes_to_set;
- if (isAttachment())
- {
- mDrawable->makeActive();
- }
- if (getIsLight())
- {
- // Add it to the pipeline mLightSet
- gPipeline.setLight(mDrawable, TRUE);
- }
-
- updateRadius();
- bool force_update = true; // avoid non-alpha mDistance update being optimized away
- mDrawable->updateDistance(*LLViewerCamera::getInstance(), force_update);
- return mDrawable;
- }
- BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bool unique_volume)
- {
- LLVolumeParams volume_params = params_in;
- S32 last_lod = mVolumep.notNull() ? LLVolumeLODGroup::getVolumeDetailFromScale(mVolumep->getDetail()) : -1;
- S32 lod = mLOD;
- BOOL is404 = FALSE;
-
- if (isSculpted())
- {
- // if it's a mesh
- if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
- { //meshes might not have all LODs, get the force detail to best existing LOD
- LLUUID mesh_id = volume_params.getSculptID();
- lod = gMeshRepo.getActualMeshLOD(volume_params, lod);
- if (lod == -1)
- {
- is404 = TRUE;
- lod = 0;
- }
- }
- }
- // Check if we need to change implementations
- bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE);
- if (is_flexible)
- {
- setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, false);
- if (!mVolumeImpl)
- {
- LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
- mVolumeImpl = new LLVolumeImplFlexible(this, data);
- }
- }
- else
- {
- // Mark the parameter not in use
- setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, false);
- if (mVolumeImpl)
- {
- delete mVolumeImpl;
- mVolumeImpl = NULL;
- if (mDrawable.notNull())
- {
- // Undo the damage we did to this matrix
- mDrawable->updateXform(FALSE);
- }
- }
- }
-
- if (is404)
- {
- setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", TRUE, LLViewerTexture::BOOST_UI));
- //render prim proxy when mesh loading attempts give up
- volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE);
- }
- if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged)
- {
- mFaceMappingChanged = TRUE;
-
- if (mVolumeImpl)
- {
- mVolumeImpl->onSetVolume(volume_params, mLOD);
- }
-
- updateSculptTexture();
- if (isSculpted())
- {
- updateSculptTexture();
- // if it's a mesh
- if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
- {
- if (!getVolume()->isMeshAssetLoaded())
- {
- //load request not yet issued, request pipeline load this mesh
- LLUUID asset_id = volume_params.getSculptID();
- S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod);
- if (available_lod != lod)
- {
- LLPrimitive::setVolume(volume_params, available_lod);
- }
- }
-
- }
- else // otherwise is sculptie
- {
- if (mSculptTexture.notNull())
- {
- sculpt();
- }
- }
- }
- return TRUE;
- }
- return FALSE;
- }
- void LLVOVolume::updateSculptTexture()
- {
- LLPointer<LLViewerFetchedTexture> old_sculpt = mSculptTexture;
- if (isSculpted() && !isMesh())
- {
- LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
- LLUUID id = sculpt_params->getSculptTexture();
- if (id.notNull())
- {
- mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
- }
- }
- else
- {
- mSculptTexture = NULL;
- }
- if (mSculptTexture != old_sculpt)
- {
- if (old_sculpt.notNull())
- {
- old_sculpt->removeVolume(this);
- }
- if (mSculptTexture.notNull())
- {
- mSculptTexture->addVolume(this);
- }
- }
-
- }
- void LLVOVolume::notifyMeshLoaded()
- {
- mSculptChanged = TRUE;
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
- }
- // sculpt replaces generate() for sculpted surfaces
- void LLVOVolume::sculpt()
- {
- if (mSculptTexture.notNull())
- {
- U16 sculpt_height = 0;
- U16 sculpt_width = 0;
- S8 sculpt_components = 0;
- const U8* sculpt_data = NULL;
-
- S32 discard_level = mSculptTexture->getDiscardLevel() ;
- LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ;
-
- S32 max_discard = mSculptTexture->getMaxDiscardLevel();
- if (discard_level > max_discard)
- discard_level = max_discard; // clamp to the best we can do
- S32 current_discard = getVolume()->getSculptLevel() ;
- if(current_discard < -2)
- {
- llwarns << "WARNING!!: Current discard of sculpty at " << current_discard
- << " is less than -2." << llendl;
-
- // corrupted volume... don't update the sculpty
- return;
- }
- else if (current_discard > MAX_DISCARD_LEVEL)
- {
- llwarns << "WARNING!!: Current discard of sculpty at " << current_discard
- << " is more than than allowed max of " << MAX_DISCARD_LEVEL << llendl;
-
- // corrupted volume... don't update the sculpty
- return;
- }
- if (current_discard == discard_level) // no work to do here
- return;
-
- if(!raw_image)
- {
- llassert(discard_level < 0) ;
- sculpt_width = 0;
- sculpt_height = 0;
- sculpt_data = NULL ;
- if(LLViewerTextureManager::sTesterp)
- {
- LLViewerTextureManager::sTesterp->updateGrayTextureBinding();
- }
- }
- else
- {
- sculpt_height = raw_image->getHeight();
- sculpt_width = raw_image->getWidth();
- sculpt_components = raw_image->getComponents();
-
- sculpt_data = raw_image->getData();
- if(LLViewerTextureManager::sTesterp)
- {
- mSculptTexture->updateBindStatsForTester() ;
- }
- }
- 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);
- }
- }
- }
- }
- S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius)
- {
- S32 cur_detail;
- if (LLPipeline::sDynamicLOD)
- {
- // We've got LOD in the profile, and in the twist. Use radius.
- F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance;
- cur_detail = LLVolumeLODGroup::getDetailFromTan(llround(tan_angle, 0.01f));
- }
- else
- {
- cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3);
- }
- return cur_detail;
- }
- BOOL LLVOVolume::calcLOD()
- {
- if (mDrawable.isNull())
- {
- return FALSE;
- }
- S32 cur_detail = 0;
-
- F32 radius;
- F32 distance;
- if (mDrawable->isState(LLDrawable::RIGGED))
- {
- LLVOAvatar* avatar = getAvatar();
- distance = avatar->mDrawable->mDistanceWRTCamera;
- radius = avatar->getBinRadius();
- }
- else
- {
- distance = mDrawable->mDistanceWRTCamera;
- radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length();
- }
-
- //hold onto unmodified distance for debugging
- //F32 debug_distance = distance;
-
- distance *= sDistanceFactor;
- F32 rampDist = LLVOVolume::sLODFactor * 2;
-
- if (distance < rampDist)
- {
- // Boost LOD when you're REALLY close
- distance *= 1.0f/rampDist;
- distance *= distance;
- distance *= rampDist;
- }
-
- // DON'T Compensate for field of view changing on FOV zoom.
- distance *= F_PI/3.f;
- cur_detail = computeLODDetail(llround(distance, 0.01f),
- llround(radius, 0.01f));
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO))
- {
- //setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail));
- setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex()));
- }
- if (cur_detail != mLOD)
- {
- mAppAngle = llround((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
- mLOD = cur_detail;
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
- BOOL LLVOVolume::updateLOD()
- {
- if (mDrawable.isNull())
- {
- return FALSE;
- }
-
- BOOL lod_changed = calcLOD();
- if (lod_changed)
- {
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
- mLODChanged = TRUE;
- }
- else
- {
- F32 new_radius = getBinRadius();
- F32 old_radius = mDrawable->getBinRadius();
- if (new_radius < old_radius * 0.9f || new_radius > old_radius*1.1f)
- {
- gPipeline.markPartitionMove(mDrawable);
- }
- }
- lod_changed = lod_changed || LLViewerObject::updateLOD();
-
- return lod_changed;
- }
- BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp)
- {
- if (!LLViewerObject::setDrawableParent(parentp))
- {
- // no change in drawable parent
- return FALSE;
- }
- if (!mDrawable->isRoot())
- {
- // rebuild vertices in parent relative space
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
- if (mDrawable->isActive() && !parentp->isActive())
- {
- parentp->makeActive();
- }
- else if (mDrawable->isStatic() && parentp->isActive())
- {
- mDrawable->makeActive();
- }
- }
-
- return TRUE;
- }
- void LLVOVolume::updateFaceFlags()
- {
- for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
- {
- LLFace *face = mDrawable->getFace(i);
- if (!face)
- {
- return;
- }
- BOOL fullbright = getTE(i)->getFullbright();
- face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT);
- if (fullbright || (mMaterial == LL_MCODE_LIGHT))
- {
- face->setState(LLFace::FULLBRIGHT);
- }
- if (mDrawable->isLight())
- {
- face->setState(LLFace::LIGHT);
- }
- if (isHUDAttachment())
- {
- face->setState(LLFace::HUD_RENDER);
- }
- }
- }
- BOOL LLVOVolume::setParent(LLViewerObject* parent)
- {
- BOOL ret = FALSE ;
- if (parent != getParent())
- {
- ret = LLViewerObject::setParent(parent);
- if (ret && mDrawable)
- {
- gPipeline.markMoved(mDrawable);
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
- }
- }
- return ret ;
- }
- // NOTE: regenFaces() MUST be followed by genTriangles()!
- void LLVOVolume::regenFaces()
- {
- // remove existing faces
- BOOL count_changed = mNumFaces != getNumTEs();
-
- if (count_changed)
- {
- deleteFaces();
- // add new faces
- mNumFaces = getNumTEs();
- }
-
- for (S32 i = 0; i < mNumFaces; i++)
- {
- LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i);
- facep->setTEOffset(i);
- facep->setTexture(getTEImage(i));
- facep->setViewerObject(this);
-
- // If the face had media on it, this will have broken the link between the LLViewerMediaTexture and the face.
- // Re-establish the link.
- if((int)mMediaImplList.size() > i)
- {
- if(mMediaImplList[i])
- {
- LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[i]->getMediaTextureID()) ;
- if(media_tex)
- {
- media_tex->addMediaToFace(facep) ;
- }
- }
- }
- }
-
- if (!count_changed)
- {
- updateFaceFlags();
- }
- }
- BOOL LLVOVolume::genBBoxes(BOOL force_global)
- {
- BOOL res = TRUE;
- LLVector4a min,max;
- min.clear();
- max.clear();
- BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED);
- // bool rigged = false;
- LLVolume* volume = mRiggedVolume;
- if (!volume)
- {
- volume = getVolume();
- }
- for (S32 i = 0; i < getVolume()->getNumVolumeFaces(); i++)
- {
- LLFace *face = mDrawable->getFace(i);
- if (!face)
- {
- continue;
- }
- res &= face->genVolumeBBoxes(*volume, i,
- mRelativeXform, mRelativeXformInvTrans,
- (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global);
-
- if (rebuild)
- {
- if (i == 0)
- {
- min = face->mExtents[0];
- max = face->mExtents[1];
- }
- else
- {
- min.setMin(min, face->mExtents[0]);
- max.setMax(max, face->mExtents[1]);
- }
- }
- }
-
- if (rebuild)
- {
- mDrawable->setSpatialExtents(min,max);
- min.add(max);
- min.mul(0.5f);
- mDrawable->setPositionGroup(min);
- }
- updateRadius();
- mDrawable->movePartition();
-
- return res;
- }
- void LLVOVolume::preRebuild()
- {
- if (mVolumeImpl != NULL)
- {
- mVolumeImpl->preRebuild();
- }
- }
- void LLVOVolume::updateRelativeXform()
- {
- if (mVolumeImpl)
- {
- mVolumeImpl->updateRelativeXform();
- return;
- }
-
- LLDrawable* drawable = mDrawable;
-
- if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull())
- { //rigged volume (which is in agent space) is used for generating bounding boxes etc
- //inverse of render matrix should go to partition space
- mRelativeXform = getRenderMatrix();
- F32* dst = (F32*) mRelativeXformInvTrans.mMatrix;
- F32* src = (F32*) mRelativeXform.mMatrix;
- dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2];
- dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6];
- dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10];
-
- mRelativeXform.invert();
- mRelativeXformInvTrans.transpose();
- }
- else if (drawable->isActive())
- {
- // setup relative transforms
- LLQuaternion delta_rot;
- LLVector3 delta_pos, delta_scale;
-
- //matrix from local space to parent relative/global space
- delta_rot = drawable->isSpatialRoot() ? LLQuaternion() : mDrawable->getRotation();
- delta_pos = drawable->isSpatialRoot() ? LLVector3(0,0,0) : mDrawable->getPosition();
- delta_scale = mDrawable->getScale();
- // Vertex transform (4x4)
- LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot;
- LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot;
- LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot;
- mRelativeXform.initRows(LLVector4(x_axis, 0.f),
- LLVector4(y_axis, 0.f),
- LLVector4(z_axis, 0.f),
- LLVector4(delta_pos, 1.f));
-
- // compute inverse transpose for normals
- // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
- // mRelativeXformInvTrans.invert();
- // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
- // grumble - invert is NOT a matrix invert, so we do it by hand:
- LLMatrix3 rot_inverse = LLMatrix3(~delta_rot);
- LLMatrix3 scale_inverse;
- scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX],
- LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY],
- LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]);
-
-
- mRelativeXformInvTrans = rot_inverse * scale_inverse;
- mRelativeXformInvTrans.transpose();
- }
- else
- {
- LLVector3 pos = getPosition();
- LLVector3 scale = getScale();
- LLQuaternion rot = getRotation();
-
- if (mParent)
- {
- pos *= mParent->getRotation();
- pos += mParent->getPosition();
- rot *= mParent->getRotation();
- }
-
- //LLViewerRegion* region = getRegion();
- //pos += region->getOriginAgent();
-
- LLVector3 x_axis = LLVector3(scale.mV[VX], 0.f, 0.f) * rot;
- LLVector3 y_axis = LLVector3(0.f, scale.mV[VY], 0.f) * rot;
- LLVector3 z_axis = LLVector3(0.f, 0.f, scale.mV[VZ]) * rot;
- mRelativeXform.initRows(LLVector4(x_axis, 0.f),
- LLVector4(y_axis, 0.f),
- LLVector4(z_axis, 0.f),
- LLVector4(pos, 1.f));
- // compute inverse transpose for normals
- LLMatrix3 rot_inverse = LLMatrix3(~rot);
- LLMatrix3 scale_inverse;
- scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX],
- LLVector3(0.0, 1.0, 0.0) / scale.mV[VY],
- LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]);
-
-
- mRelativeXformInvTrans = rot_inverse * scale_inverse;
- mRelativeXformInvTrans.transpose();
- }
- }
- static LLFastTimer::DeclareTimer FTM_GEN_FLEX("Generate Flexies");
- static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives");
- static LLFastTimer::DeclareTimer FTM_UPDATE_RIGGED_VOLUME("Update Rigged");
- BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
- {
- LLFastTimer t(FTM_UPDATE_PRIMITIVES);
-
- if (mDrawable->isState(LLDrawable::REBUILD_RIGGED))
- {
- {
- LLFastTimer t(FTM_UPDATE_RIGGED_VOLUME);
- updateRiggedVolume();
- }
- genBBoxes(FALSE);
- mDrawable->clearState(LLDrawable::REBUILD_RIGGED);
- }
- if (mVolumeImpl != NULL)
- {
- BOOL res;
- {
- LLFastTimer t(FTM_GEN_FLEX);
- res = mVolumeImpl->doUpdateGeometry(drawable);
- }
- updateFaceFlags();
- return res;
- }
-
- dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));
- BOOL compiled = FALSE;
-
- updateRelativeXform();
-
- if (mDrawable.isNull()) // Not sure why this is happening, but it is...
- {
- return TRUE; // No update to complete
- }
- if (mVolumeChanged || mFaceMappingChanged )
- {
- compiled = TRUE;
- if (mVolumeChanged)
- {
- LLFastTimer ftm(FTM_GEN_VOLUME);
- LLVolumeParams volume_params = getVolume()->getParams();
- setVolume(volume_params, 0);
- drawable->setState(LLDrawable::REBUILD_VOLUME);
- }
- {
- LLFastTimer t(FTM_GEN_TRIANGLES);
- regenFaces();
- genBBoxes(FALSE);
- }
- }
- else if ((mLODChanged) || (mSculptChanged))
- {
- LLVolume *old_volumep, *new_volumep;
- F32 old_lod, new_lod;
- S32 old_num_faces, new_num_faces ;
- old_volumep = getVolume();
- old_lod = old_volumep->getDetail();
- old_num_faces = old_volumep->getNumFaces() ;
- old_volumep = NULL ;
- {
- LLFastTimer ftm(FTM_GEN_VOLUME);
- LLVolumeParams volume_params = getVolume()->getParams();
- setVolume(volume_params, 0);
- }
- new_volumep = getVolume();
- new_lod = new_volumep->getDetail();
- new_num_faces = new_volumep->getNumFaces() ;
- new_volumep = NULL ;
- if ((new_lod != old_lod) || mSculptChanged)
- {
- compiled = TRUE;
- sNumLODChanges += new_num_faces ;
-
- if((S32)getNumTEs() != getVolume()->getNumFaces())
- {
- setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces.
- }
- drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
- {
- LLFastTimer t(FTM_GEN_TRIANGLES);
- if (new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs())
- {
- regenFaces();
- }
- genBBoxes(FALSE);
- if (mSculptChanged)
- { //changes in sculpt maps can thrash an object bounding box without
- //triggering a spatial group bounding box update -- force spatial group
- //to update bounding boxes
- LLSpatialGroup* group = mDrawable->getSpatialGroup();
- if (group)
- {
- group->unbound();
- }
- }
- }
- }
- }
- // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local
- else
- {
- compiled = TRUE;
- // All it did was move or we changed the texture coordinate offset
- LLFastTimer t(FTM_GEN_TRIANGLES);
- genBBoxes(FALSE);
- }
- // Update face flags
- updateFaceFlags();
-
- if(compiled)
- {
- LLPipeline::sCompiles++;
- }
-
- mVolumeChanged = FALSE;
- mLODChanged = FALSE;
- mSculptChanged = FALSE;
- mFaceMappingChanged = FALSE;
-
- return LLViewerObject::updateGeometry(drawable);
- }
- void LLVOVolume::updateFaceSize(S32 idx)
- {
- LLFace* facep = mDrawable->getFace(idx);
- if (idx >= getVolume()->getNumVolumeFaces())
- {
- facep->setSize(0,0, true);
- }
- else
- {
- const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx);
- facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices,
- true); // <--- volume faces should be padded for 16-byte alignment
-
- }
- }
- BOOL LLVOVolume::isRootEdit() const
- {
- if (mParent && !((LLViewerObject*)mParent)->isAvatar())
- {
- return FALSE;
- }
- return TRUE;
- }
- //virtual
- void LLVOVolume::setNumTEs(const U8 num_tes)
- {
- const U8 old_num_tes = getNumTEs() ;
-
- if(old_num_tes && old_num_tes < num_tes) //new faces added
- {
- LLViewerObject::setNumTEs(num_tes) ;
- if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists.
- {
- mMediaImplList.resize(num_tes) ;
- const LLTextureEntry* te = getTE(old_num_tes - 1) ;
- for(U8 i = old_num_tes; i < num_tes ; i++)
- {
- setTE(i, *te) ;
- mMediaImplList[i] = mMediaImplList[old_num_tes -1] ;
- }
- mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ;
- }
- }
- else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed
- {
- U8 end = mMediaImplList.size() ;
- for(U8 i = num_tes; i < end ; i++)
- {
- removeMediaImpl(i) ;
- }
- mMediaImplList.resize(num_tes) ;
- LLViewerObject::setNumTEs(num_tes) ;
- }
- else
- {
- LLViewerObject::setNumTEs(num_tes) ;
- }
- return ;
- }
- void LLVOVolume::setTEImage(const U8 te, LLViewerTexture *imagep)
- {
- BOOL changed = (mTEImages[te] != imagep);
- LLViewerObject::setTEImage(te, imagep);
- if (changed)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- }
- S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid)
- {
- S32 res = LLViewerObject::setTETexture(te, uuid);
- if (res)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- return res;
- }
- S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color)
- {
- return setTEColor(te, LLColor4(color));
- }
- S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color)
- {
- S32 retval = 0;
- const LLTextureEntry *tep = getTE(te);
- if (!tep)
- {
- llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
- }
- else if (color != tep->getColor())
- {
- if (color.mV[3] != tep->getColor().mV[3])
- {
- gPipeline.markTextured(mDrawable);
- }
- retval = LLPrimitive::setTEColor(te, color);
- if (mDrawable.notNull() && retval)
- {
- // These should only happen on updates which are not the initial update.
- mDrawable->setState(LLDrawable::REBUILD_COLOR);
- dirtyMesh();
- }
- }
- return retval;
- }
- S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap)
- {
- S32 res = LLViewerObject::setTEBumpmap(te, bumpmap);
- if (res)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- return res;
- }
- S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen)
- {
- S32 res = LLViewerObject::setTETexGen(te, texgen);
- if (res)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- return res;
- }
- S32 LLVOVolume::setTEMediaTexGen(const U8 te, const U8 media)
- {
- S32 res = LLViewerObject::setTEMediaTexGen(te, media);
- if (res)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- return res;
- }
- S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny)
- {
- S32 res = LLViewerObject::setTEShiny(te, shiny);
- if (res)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- return res;
- }
- S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright)
- {
- S32 res = LLViewerObject::setTEFullbright(te, fullbright);
- if (res)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- return res;
- }
- S32 LLVOVolume::setTEBumpShinyFullbright(const U8 te, const U8 bump)
- {
- S32 res = LLViewerObject::setTEBumpShinyFullbright(te, bump);
- if (res)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- return res;
- }
- S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags)
- {
- S32 res = LLViewerObject::setTEMediaFlags(te, media_flags);
- if (res)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- return res;
- }
- S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow)
- {
- S32 res = LLViewerObject::setTEGlow(te, glow);
- if (res)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- return res;
- }
- S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t)
- {
- S32 res = LLViewerObject::setTEScale(te, s, t);
- if (res)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- return res;
- }
- S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s)
- {
- S32 res = LLViewerObject::setTEScaleS(te, s);
- if (res)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- return res;
- }
- S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t)
- {
- S32 res = LLViewerObject::setTEScaleT(te, t);
- if (res)
- {
- gPipeline.markTextured(mDrawable);
- mFaceMappingChanged = TRUE;
- }
- return res;
- }
- void LLVOVolume::updateTEData()
- {
- /*if (mDrawable.notNull())
- {
- mFaceMappingChanged = TRUE;
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE);
- }*/
- }
- bool LLVOVolume::hasMedia() const
- {
- bool result = false;
- const U8 numTEs = getNumTEs();
- for (U8 i = 0; i < numTEs; i++)
- {
- const LLTextureEntry* te = getTE(i);
- if(te->hasMedia())
- {
- result = true;
- break;
- }
- }
- return result;
- }
- LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id)
- {
- LLVolume* volume = getVolume();
- LLVector4a result;
- result.clear();
- LLVector3 ret;
- if (volume && face_id < volume->getNumVolumeFaces())
- {
- const LLVolumeFace& face = volume->getVolumeFace(face_id);
- for (S32 i = 0; i < (S32)face.mNumVertices; ++i)
- {
- result.add(face.mNormals[i]);
- }
- LLVector3 ret(result.getF32ptr());
- ret = volumeDirectionToAgent(ret);
- ret.normVec();
- }
-
- return ret;
- }
- void LLVOVolume::requestMediaDataUpdate(bool isNew)
- {
- if (sObjectMediaClient)
- sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this, isNew));
- }
- bool LLVOVolume::isMediaDataBeingFetched() const
- {
- // I know what I'm doing by const_casting this away: this is just
- // a wrapper class that is only going to do a lookup.
- return (sObjectMediaClient) ? sObjectMediaClient->isInQueue(new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false)) : false;
- }
- void LLVOVolume::cleanUpMediaImpls()
- {
- // Iterate through our TEs and remove any Impls that are no longer used
- const U8 numTEs = getNumTEs();
- for (U8 i = 0; i < numTEs; i++)
- {
- const LLTextureEntry* te = getTE(i);
- if( ! te->hasMedia())
- {
- // Delete the media IMPL!
- removeMediaImpl(i) ;
- }
- }
- }
- void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array, const std::string &media_version)
- {
- // media_data_array is an array of media entry maps
- // media_version is the version string in the response.
- U32 fetched_versi…
Large files files are truncated, but you can click here to view the full file