llvovolume.cpp

Go to the documentation of this file.
00001 
00032 // A "volume" is a box, cylinder, sphere, or other primitive shape.
00033 
00034 #include "llviewerprecompiledheaders.h"
00035 
00036 #include "llvovolume.h"
00037 
00038 #include "llviewercontrol.h"
00039 #include "lldir.h"
00040 #include "llflexibleobject.h"
00041 #include "llmaterialtable.h"
00042 #include "llprimitive.h"
00043 #include "llvolume.h"
00044 #include "llvolumemgr.h"
00045 #include "llvolumemessage.h"
00046 #include "material_codes.h"
00047 #include "message.h"
00048 #include "object_flags.h"
00049 #include "llagent.h"
00050 #include "lldrawable.h"
00051 #include "lldrawpoolbump.h"
00052 #include "llface.h"
00053 #include "llspatialpartition.h"
00054 
00055 // TEMP HACK ventrella
00056 #include "llhudmanager.h"
00057 #include "llflexibleobject.h"
00058 
00059 #include "llsky.h"
00060 #include "llviewercamera.h"
00061 #include "llviewerimagelist.h"
00062 #include "llviewerregion.h"
00063 #include "llviewertextureanim.h"
00064 #include "llworld.h"
00065 #include "llselectmgr.h"
00066 #include "pipeline.h"
00067 
00068 const S32 MIN_QUIET_FRAMES_COALESCE = 30;
00069 const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
00070 const F32 FORCE_CULL_AREA = 8.f;
00071 const S32 SCULPT_REZ = 128;
00072 
00073 BOOL gAnimateTextures = TRUE;
00074 extern BOOL gHideSelectedObjects;
00075 
00076 F32 LLVOVolume::sLODFactor = 1.f;
00077 F32     LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop 
00078 F32 LLVOVolume::sDistanceFactor = 1.0f;
00079 S32 LLVOVolume::sNumLODChanges = 0;
00080 
00081 LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
00082         : LLViewerObject(id, pcode, regionp),
00083           mVolumeImpl(NULL)
00084 {
00085         mTexAnimMode = 0;
00086         mRelativeXform.setIdentity();
00087         mRelativeXformInvTrans.setIdentity();
00088 
00089         mLOD = MIN_LOD;
00090         mTextureAnimp = NULL;
00091         mVObjRadius = LLVector3(1,1,0.5f).magVec();
00092         mNumFaces = 0;
00093         mLODChanged = FALSE;
00094         mSculptChanged = FALSE;
00095 }
00096 
00097 LLVOVolume::~LLVOVolume()
00098 {
00099         delete mTextureAnimp;
00100         mTextureAnimp = NULL;
00101         delete mVolumeImpl;
00102         mVolumeImpl = NULL;
00103 }
00104 
00105 
00106 // static
00107 void LLVOVolume::initClass()
00108 {
00109 }
00110 
00111 
00112 U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
00113                                                                                   void **user_data,
00114                                                                                   U32 block_num, EObjectUpdateType update_type,
00115                                                                                   LLDataPacker *dp)
00116 {
00117         LLColor4U color;
00118 
00119         // Do base class updates...
00120         U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp);
00121 
00122         LLUUID sculpt_id;
00123         U8 sculpt_type = 0;
00124         if (isSculpted())
00125         {
00126                 LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
00127                 sculpt_id = sculpt_params->getSculptTexture();
00128                 sculpt_type = sculpt_params->getSculptType();
00129         }
00130 
00131         if (!dp)
00132         {
00133                 if (update_type == OUT_FULL)
00134                 {
00136                         //
00137                         // Unpack texture animation data
00138                         //
00139                         //
00140 
00141                         if (mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureAnim))
00142                         {
00143                                 if (!mTextureAnimp)
00144                                 {
00145                                         mTextureAnimp = new LLViewerTextureAnim();
00146                                 }
00147                                 else
00148                                 {
00149                                         if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH))
00150                                         {
00151                                                 mTextureAnimp->reset();
00152                                         }
00153                                 }
00154                                 mTexAnimMode = 0;
00155                                 mTextureAnimp->unpackTAMessage(mesgsys, block_num);
00156                         }
00157                         else
00158                         {
00159                                 if (mTextureAnimp)
00160                                 {
00161                                         delete mTextureAnimp;
00162                                         mTextureAnimp = NULL;
00163                                         gPipeline.markTextured(mDrawable);
00164                                         mFaceMappingChanged = TRUE;
00165                                         mTexAnimMode = 0;
00166                                 }
00167                         }
00168 
00169                         // Unpack volume data
00170                         LLVolumeParams volume_params;
00171                         LLVolumeMessage::unpackVolumeParams(&volume_params, mesgsys, _PREHASH_ObjectData, block_num);
00172                         volume_params.setSculptID(sculpt_id, sculpt_type);
00173 
00174                         if (setVolume(volume_params, 0))
00175                         {
00176                                 markForUpdate(TRUE);
00177                         }
00178                 }
00179 
00180                 // Sigh, this needs to be done AFTER the volume is set as well, otherwise bad stuff happens...
00182                 //
00183                 // Unpack texture entry data
00184                 //
00185                 if (unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num) & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR))
00186                 {
00187                         updateTEData();
00188                 }
00189         }
00190         else
00191         {
00192                 // CORY TO DO: Figure out how to get the value here
00193                 if (update_type != OUT_TERSE_IMPROVED)
00194                 {
00195                         LLVolumeParams volume_params;
00196                         BOOL res = LLVolumeMessage::unpackVolumeParams(&volume_params, *dp);
00197                         if (!res)
00198                         {
00199                                 llwarns << "Bogus volume parameters in object " << getID() << llendl;
00200                                 llwarns << getRegion()->getOriginGlobal() << llendl;
00201                         }
00202 
00203                         volume_params.setSculptID(sculpt_id, sculpt_type);
00204 
00205                         if (setVolume(volume_params, 0))
00206                         {
00207                                 markForUpdate(TRUE);
00208                         }
00209                         S32 res2 = unpackTEMessage(*dp);
00210                         if (TEM_INVALID == res2)
00211                         {
00212                                 // Well, crap, there's something bogus in the data that we're unpacking.
00213                                 dp->dumpBufferToLog();
00214                                 llwarns << "Flushing cache files" << llendl;
00215                                 char mask[LL_MAX_PATH];         /* Flawfinder: ignore */
00216                                 snprintf(mask, LL_MAX_PATH, "%s*.slc", gDirUtilp->getDirDelimiter().c_str());           /* Flawfinder: ignore */
00217                                 gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(),mask);
00218 //                              llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl;
00219                                 llwarns << "Bogus TE data in " << getID() << llendl;
00220                         }
00221                         else if (res2 & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR))
00222                         {
00223                                 updateTEData();
00224                         }
00225 
00226                         U32 value = dp->getPassFlags();
00227 
00228                         if (value & 0x40)
00229                         {
00230                                 if (!mTextureAnimp)
00231                                 {
00232                                         mTextureAnimp = new LLViewerTextureAnim();
00233                                 }
00234                                 else
00235                                 {
00236                                         if (!(mTextureAnimp->mMode & LLTextureAnim::SMOOTH))
00237                                         {
00238                                                 mTextureAnimp->reset();
00239                                         }
00240                                 }
00241                                 mTexAnimMode = 0;
00242                                 mTextureAnimp->unpackTAMessage(*dp);
00243                         }
00244                         else if (mTextureAnimp)
00245                         {
00246                                 delete mTextureAnimp;
00247                                 mTextureAnimp = NULL;
00248                                 gPipeline.markTextured(mDrawable);
00249                                 mFaceMappingChanged = TRUE;
00250                                 mTexAnimMode = 0;
00251                         }
00252                 }
00253                 else
00254                 {
00255                         S32 texture_length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_TextureEntry);
00256                         if (texture_length)
00257                         {
00258                                 U8                                                      tdpbuffer[1024];
00259                                 LLDataPackerBinaryBuffer        tdp(tdpbuffer, 1024);
00260                                 mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num);
00261                                 if ( unpackTEMessage(tdp) & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR))
00262                                 {
00263                                         updateTEData();
00264                                 }
00265                         }
00266                 }
00267         }
00268         
00269         return retval;
00270 }
00271 
00272 
00273 void LLVOVolume::animateTextures()
00274 {
00275         F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f;
00276         S32 result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot);
00277         
00278         if (result)
00279         {
00280                 if (!mTexAnimMode)
00281                 {
00282                         mFaceMappingChanged = TRUE;
00283                         gPipeline.markTextured(mDrawable);
00284                 }
00285                 mTexAnimMode = result | mTextureAnimp->mMode;
00286                                 
00287                 S32 start=0, end=mDrawable->getNumFaces()-1;
00288                 if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end)
00289                 {
00290                         start = end = mTextureAnimp->mFace;
00291                 }
00292                 
00293                 for (S32 i = start; i <= end; i++)
00294                 {
00295                         LLFace* facep = mDrawable->getFace(i);
00296                         if(facep->getVirtualSize() <= MIN_TEX_ANIM_SIZE && facep->mTextureMatrix) continue;
00297 
00298                         const LLTextureEntry* te = facep->getTextureEntry();
00299                         
00300                         if (!te)
00301                         {
00302                                 continue;
00303                         }
00304                 
00305                         if (!(result & LLViewerTextureAnim::ROTATE))
00306                         {
00307                                 te->getRotation(&rot);
00308                         }
00309                         if (!(result & LLViewerTextureAnim::TRANSLATE))
00310                         {
00311                                 te->getOffset(&off_s,&off_t);
00312                         }                       
00313                         if (!(result & LLViewerTextureAnim::SCALE))
00314                         {
00315                                 te->getScale(&scale_s, &scale_t);
00316                         }
00317 
00318                         LLVector3 scale(scale_s, scale_t, 1.f);
00319                         LLVector3 trans(off_s+0.5f, off_t+0.5f, 0.f);
00320                         LLQuaternion quat;
00321                         quat.setQuat(rot, 0, 0, -1.f);
00322                 
00323                         if (!facep->mTextureMatrix)
00324                         {
00325                                 facep->mTextureMatrix = new LLMatrix4();
00326                         }
00327 
00328                         LLMatrix4& tex_mat = *facep->mTextureMatrix;
00329                         tex_mat.setIdentity();
00330                         tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f));
00331                         tex_mat.rotate(quat);                           
00332 
00333                         LLMatrix4 mat;
00334                         mat.initAll(scale, LLQuaternion(), LLVector3());
00335                         tex_mat *= mat;
00336                 
00337                         tex_mat.translate(trans);
00338                 }
00339         }
00340         else
00341         {
00342                 if (mTexAnimMode && mTextureAnimp->mRate == 0)
00343                 {
00344                         U8 start, count;
00345 
00346                         if (mTextureAnimp->mFace == -1)
00347                         {
00348                                 start = 0;
00349                                 count = getNumTEs();
00350                         }
00351                         else
00352                         {
00353                                 start = (U8) mTextureAnimp->mFace;
00354                                 count = 1;
00355                         }
00356 
00357                         for (S32 i = start; i < start + count; i++)
00358                         {
00359                                 if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE)
00360                                 {
00361                                         setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT);                             
00362                                 }
00363                                 if (mTexAnimMode & LLViewerTextureAnim::SCALE)
00364                                 {
00365                                         setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT);  
00366                                 }
00367                                 if (mTexAnimMode & LLViewerTextureAnim::ROTATE)
00368                                 {
00369                                         setTERotation(i, mTextureAnimp->mRot);
00370                                 }
00371                         }
00372 
00373                         gPipeline.markTextured(mDrawable);
00374                         mFaceMappingChanged = TRUE;
00375                         mTexAnimMode = 0;
00376                 }
00377         }
00378 }
00379 BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
00380 {
00381         LLViewerObject::idleUpdate(agent, world, time);
00382 
00383         if (mDead || mDrawable.isNull())
00384         {
00385                 return TRUE;
00386         }
00387         
00389         //
00390         // Do texture animation stuff
00391         //
00392 
00393         if (mTextureAnimp && gAnimateTextures)
00394         {
00395                 animateTextures();
00396         }
00397 
00398         // Dispatch to implementation
00399         if (mVolumeImpl)
00400         {
00401                 mVolumeImpl->doIdleUpdate(agent, world, time);
00402         }
00403 
00404         return TRUE;
00405 }
00406 
00407 void LLVOVolume::updateTextures(LLAgent &agent)
00408 {
00409         const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds
00410         if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME)
00411         {
00412                 if (mDrawable->isVisible())
00413                 {
00414                         updateTextures();
00415                 }
00416         }
00417 }
00418 
00419 void LLVOVolume::updateTextures()
00420 {
00421         // Update the pixel area of all faces
00422 
00423         if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE))
00424         {
00425                 return;
00426         }
00427         
00428         if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull()) // || !mDrawable->isVisible())
00429         {
00430                 return;
00431         }
00432 
00433         mTextureUpdateTimer.reset();
00434         
00435         F32 old_area = mPixelArea;
00436         mPixelArea = 0.f;
00437 
00438         const S32 num_faces = mDrawable->getNumFaces();
00439         F32 min_vsize=999999999.f, max_vsize=0.f;
00440         for (S32 i = 0; i < num_faces; i++)
00441         {
00442                 LLFace* face = mDrawable->getFace(i);
00443                 const LLTextureEntry *te = face->getTextureEntry();
00444                 LLViewerImage *imagep = face->getTexture();
00445                 if (!imagep || !te ||
00446                         face->mExtents[0] == face->mExtents[1])
00447                 {
00448                         continue;
00449                 }
00450                 
00451                 F32 vsize;
00452                 
00453                 if (isHUDAttachment())
00454                 {
00455                         F32 area = (F32) LLViewerCamera::getInstance()->getScreenPixelArea();
00456                         vsize = area;
00457                         imagep->setBoostLevel(LLViewerImage::BOOST_HUD);
00458                         face->setPixelArea(area); // treat as full screen
00459                 }
00460                 else
00461                 {
00462                         vsize = getTextureVirtualSize(face);
00463                 }
00464 
00465                 mPixelArea = llmax(mPixelArea, face->getPixelArea());
00466 
00467                 F32 old_size = face->getVirtualSize();
00468 
00469                 if (face->getPoolType() == LLDrawPool::POOL_ALPHA)
00470                 {
00471                         
00472                         if (LLPipeline::sFastAlpha &&
00473                                 vsize < MIN_ALPHA_SIZE && old_size > MIN_ALPHA_SIZE ||
00474                                 vsize > MIN_ALPHA_SIZE && old_size < MIN_ALPHA_SIZE)
00475                         {
00476                                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_COLOR, FALSE);
00477                         }
00478                 }
00479 
00480                 if (face->mTextureMatrix != NULL)
00481                 {
00482                         if (vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE ||
00483                                 vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)
00484                         {
00485                                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE);
00486                         }
00487                 }
00488                 
00489                 face->setVirtualSize(vsize);
00490                 imagep->addTextureStats(vsize);
00491                 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
00492                 {
00493                         if (vsize < min_vsize) min_vsize = vsize;
00494                         if (vsize > max_vsize) max_vsize = vsize;
00495                 }
00496                 else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
00497                 {
00498                         F32 pri = imagep->getDecodePriority();
00499                         if (pri < min_vsize) min_vsize = pri;
00500                         if (pri > max_vsize) max_vsize = pri;
00501                 }
00502                 else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
00503                 {
00504                         F32 pri = mPixelArea;
00505                         if (pri < min_vsize) min_vsize = pri;
00506                         if (pri > max_vsize) max_vsize = pri;
00507                 }       
00508         }
00509         
00510         if (isSculpted())
00511         {
00512                 LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
00513                 LLUUID id =  sculpt_params->getSculptTexture(); 
00514                 mSculptTexture = gImageList.getImage(id);
00515                 if (mSculptTexture.notNull())
00516                 {
00517                         mSculptTexture->addTextureStats(SCULPT_REZ * SCULPT_REZ);
00518                         mSculptTexture->setBoostLevel(LLViewerImage::BOOST_SCULPTED);
00519                 }
00520 
00521                 S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture
00522                 S32 current_discard = getVolume()->getSculptLevel();
00523                 
00524                 if (texture_discard >= 0 && //texture has some data available
00525                         (texture_discard < current_discard || //texture has more data than last rebuild
00526                         current_discard < 0)) //no previous rebuild
00527                 {
00528                         gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
00529                         mSculptChanged = TRUE;
00530                 }
00531                 
00532         }
00533 
00534 
00535         if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
00536         {
00537                 setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
00538         }
00539         else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY))
00540         {
00541                 setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
00542         }
00543         else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
00544         {
00545                 setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
00546         }
00547 
00548         if (mPixelArea == 0)
00549         { //flexi phasing issues make this happen
00550                 mPixelArea = old_area;
00551         }
00552 }
00553 
00554 F32 LLVOVolume::getTextureVirtualSize(LLFace* face)
00555 {
00556         //get area of circle around face
00557         LLVector3 center = face->getPositionAgent();
00558         LLVector3 size = (face->mExtents[1] - face->mExtents[0]) * 0.5f;
00559         
00560         F32 face_area = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance());
00561 
00562         face->setPixelArea(face_area);
00563 
00564         if (face_area <= 0)
00565         {
00566                 return 0.f;
00567         }
00568 
00569         //get area of circle in texture space
00570         LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0];
00571         F32 texel_area = (tdim * 0.5f).magVecSquared()*3.14159f;
00572         if (texel_area <= 0)
00573         {
00574                 // Probably animated, use default
00575                 texel_area = 1.f;
00576         }
00577 
00578         //apply texel area to face area to get accurate ratio
00579         face_area /= llclamp(texel_area, 1.f/64.f, 16.f);
00580 
00581         return face_area;
00582 }
00583 
00584 BOOL LLVOVolume::isActive() const
00585 {
00586         return !mStatic || mTextureAnimp || (mVolumeImpl && mVolumeImpl->isActive());
00587 }
00588 
00589 BOOL LLVOVolume::setMaterial(const U8 material)
00590 {
00591         BOOL res = LLViewerObject::setMaterial(material);
00592         
00593         return res;
00594 }
00595 
00596 void LLVOVolume::setTexture(const S32 face)
00597 {
00598         llassert(face < getNumTEs());
00599         LLViewerImage::bindTexture(getTEImage(face));
00600 }
00601 
00602 void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped)
00603 {
00604         if (scale != getScale())
00605         {
00606                 // store local radius
00607                 LLViewerObject::setScale(scale);
00608 
00609                 if (mVolumeImpl)
00610                 {
00611                         mVolumeImpl->onSetScale(scale, damped);
00612                 }
00613                 
00614                 updateRadius();
00615 
00616                 //since drawable transforms do not include scale, changing volume scale
00617                 //requires an immediate rebuild of volume verts.
00618                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE);
00619         }
00620 }
00621 
00622 LLFace* LLVOVolume::addFace(S32 f)
00623 {
00624         const LLTextureEntry* te = getTE(f);
00625         LLViewerImage* imagep = getTEImage(f);
00626         return mDrawable->addFace(te, imagep);
00627 }
00628 
00629 LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
00630 {
00631         pipeline->allocDrawable(this);
00632                 
00633         mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME);
00634 
00635         S32 max_tes_to_set = getNumTEs();
00636         for (S32 i = 0; i < max_tes_to_set; i++)
00637         {
00638                 addFace(i);
00639         }
00640         mNumFaces = max_tes_to_set;
00641 
00642         if (isAttachment())
00643         {
00644                 mDrawable->makeActive();
00645         }
00646 
00647         if (getIsLight())
00648         {
00649                 // Add it to the pipeline mLightSet
00650                 gPipeline.setLight(mDrawable, TRUE);
00651         }
00652         
00653         updateRadius();
00654         mDrawable->updateDistance(*LLViewerCamera::getInstance());
00655 
00656         return mDrawable;
00657 }
00658 
00659 
00660 BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume)
00661 {
00662         // Check if we need to change implementations
00663         bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE);
00664         if (is_flexible)
00665         {
00666                 setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, false);
00667                 if (!mVolumeImpl)
00668                 {
00669                         LLFlexibleObjectData* data = (LLFlexibleObjectData*)getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
00670                         mVolumeImpl = new LLVolumeImplFlexible(this, data);
00671                 }
00672         }
00673         else
00674         {
00675                 // Mark the parameter not in use
00676                 setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, false);
00677                 if (mVolumeImpl)
00678                 {
00679                         delete mVolumeImpl;
00680                         mVolumeImpl = NULL;
00681                         if (mDrawable.notNull())
00682                         {
00683                                 // Undo the damage we did to this matrix
00684                                 mDrawable->updateXform(FALSE);
00685                         }
00686                 }
00687         }
00688         
00689         if ((LLPrimitive::setVolume(volume_params, mLOD, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged)
00690         {
00691                 mFaceMappingChanged = TRUE;
00692                 
00693                 if (mVolumeImpl)
00694                 {
00695                         mVolumeImpl->onSetVolume(volume_params, detail);
00696                 }
00697                 
00698                 if (isSculpted())
00699                 {
00700                         mSculptTexture = gImageList.getImage(volume_params.getSculptID());
00701                         if (mSculptTexture.notNull())
00702                         {
00703                                 sculpt();
00704                         }
00705                 }
00706                 else
00707                 {
00708                         mSculptTexture = NULL;
00709                 }
00710 
00711                 return TRUE;
00712         }
00713         return FALSE;
00714 }
00715 
00716 // sculpt replaces generate() for sculpted surfaces
00717 void LLVOVolume::sculpt()
00718 {
00719         U16 sculpt_height = 0;
00720         U16 sculpt_width = 0;
00721         S8 sculpt_components = 0;
00722         const U8* sculpt_data = NULL;
00723 
00724         if (mSculptTexture.notNull())
00725         {
00726                 S32 discard_level;
00727                 S32 desired_discard = 0; // lower discard levels have MUCH less resolution 
00728 
00729                 discard_level = desired_discard;
00730                 
00731                 S32 max_discard = mSculptTexture->getMaxDiscardLevel();
00732                 if (discard_level > max_discard)
00733                         discard_level = max_discard;    // clamp to the best we can do
00734 
00735                 S32 best_discard = mSculptTexture->getDiscardLevel();
00736                 if (discard_level < best_discard)
00737                         discard_level = best_discard;   // clamp to what we have
00738 
00739                 if (best_discard == -1)
00740                         discard_level = -1;  // and if we have nothing, set to nothing
00741 
00742                 
00743                 S32 current_discard = getVolume()->getSculptLevel();
00744                 if(current_discard < -2)
00745                 {
00746                         llwarns << "WARNING!!: Current discard of sculpty at " << current_discard 
00747                                 << " is less than -2." << llendl;
00748                         
00749                         // corrupted volume... don't update the sculpty
00750                         return;
00751                 }
00752                 else if (current_discard > max_discard)
00753                 {
00754                         llwarns << "WARNING!!: Current discard of sculpty at " << current_discard 
00755                                 << " is more than than allowed max of " << max_discard << llendl;
00756                         
00757                         // corrupted volume... don't update the sculpty                 
00758                         return;
00759                 }
00760 
00761                 if (current_discard == discard_level)  // no work to do here
00762                         return;
00763                 
00764                 LLPointer<LLImageRaw> raw_image = new LLImageRaw();
00765                 BOOL is_valid = mSculptTexture->readBackRaw(discard_level, raw_image, FALSE);
00766 
00767                 sculpt_height = raw_image->getHeight();
00768                 sculpt_width = raw_image->getWidth();
00769                 sculpt_components = raw_image->getComponents();         
00770 
00771                 if(is_valid)
00772                 {
00773                         is_valid = mSculptTexture->isValidForSculpt(discard_level, sculpt_width, sculpt_height, sculpt_components) ;
00774                 }
00775                 if(!is_valid)
00776                 {
00777                         sculpt_width = 0;
00778                         sculpt_height = 0;
00779                         sculpt_data = NULL ;
00780                 }
00781                 else
00782                 {
00783                         if (raw_image->getDataSize() < sculpt_height * sculpt_width * sculpt_components)
00784                                 llerrs << "Sculpt: image data size = " << raw_image->getDataSize()
00785                                            << " < " << sculpt_height << " x " << sculpt_width << " x " <<sculpt_components << llendl;
00786                                            
00787                         sculpt_data = raw_image->getData();
00788                 }
00789                 getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level);
00790         }
00791 }
00792 
00793 S32     LLVOVolume::computeLODDetail(F32 distance, F32 radius)
00794 {
00795         S32     cur_detail;
00796         if (LLPipeline::sDynamicLOD)
00797         {
00798                 // We've got LOD in the profile, and in the twist.  Use radius.
00799                 F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance;
00800                 cur_detail = LLVolumeLODGroup::getDetailFromTan(llround(tan_angle, 0.01f));
00801         }
00802         else
00803         {
00804                 cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3);           
00805         }
00806         return cur_detail;
00807 }
00808 
00809 BOOL LLVOVolume::calcLOD()
00810 {
00811         if (mDrawable.isNull())
00812         {
00813                 return FALSE;
00814         }
00815 
00816         //update face texture sizes on lod calculation
00817         updateTextures();
00818 
00819         S32 cur_detail = 0;
00820         
00821         F32 radius = getVolume()->mLODScaleBias.scaledVec(getScale()).magVec();
00822         F32 distance = mDrawable->mDistanceWRTCamera;
00823         distance *= sDistanceFactor;
00824                         
00825         F32 rampDist = LLVOVolume::sLODFactor * 2;
00826         
00827         if (distance < rampDist)
00828         {
00829                 // Boost LOD when you're REALLY close
00830                 distance *= 1.0f/rampDist;
00831                 distance *= distance;
00832                 distance *= rampDist;
00833         }
00834         
00835         // DON'T Compensate for field of view changing on FOV zoom.
00836         distance *= 3.14159f/3.f;
00837 
00838         cur_detail = computeLODDetail(llround(distance, 0.01f), 
00839                                                                         llround(radius, 0.01f));
00840 
00841         if (cur_detail != mLOD)
00842         {
00843                 mAppAngle = llround((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
00844                 mLOD = cur_detail;              
00845                 return TRUE;
00846         }
00847         else
00848         {
00849                 return FALSE;
00850         }
00851 }
00852 
00853 BOOL LLVOVolume::updateLOD()
00854 {
00855         if (mDrawable.isNull())
00856         {
00857                 return FALSE;
00858         }
00859         
00860         BOOL lod_changed = calcLOD();
00861 
00862         if (lod_changed)
00863         {
00864                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
00865                 mLODChanged = TRUE;
00866         }
00867 
00868         lod_changed |= LLViewerObject::updateLOD();
00869         
00870         return lod_changed;
00871 }
00872 
00873 BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp)
00874 {
00875         if (!LLViewerObject::setDrawableParent(parentp))
00876         {
00877                 // no change in drawable parent
00878                 return FALSE;
00879         }
00880 
00881         if (!mDrawable->isRoot())
00882         {
00883                 // rebuild vertices in parent relative space
00884                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
00885 
00886                 if (mDrawable->isActive() && !parentp->isActive())
00887                 {
00888                         parentp->makeActive();
00889                 }
00890                 else if (mDrawable->isStatic() && parentp->isActive())
00891                 {
00892                         mDrawable->makeActive();
00893                 }
00894         }
00895         
00896         return TRUE;
00897 }
00898 
00899 void LLVOVolume::updateFaceFlags()
00900 {
00901         for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
00902         {
00903                 LLFace *face = mDrawable->getFace(i);
00904                 BOOL fullbright = getTE(i)->getFullbright();
00905                 face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT);
00906 
00907                 if (fullbright || (mMaterial == LL_MCODE_LIGHT))
00908                 {
00909                         face->setState(LLFace::FULLBRIGHT);
00910                 }
00911                 if (mDrawable->isLight())
00912                 {
00913                         face->setState(LLFace::LIGHT);
00914                 }
00915                 if (isHUDAttachment())
00916                 {
00917                         face->setState(LLFace::HUD_RENDER);
00918                 }
00919         }
00920 }
00921 
00922 void LLVOVolume::setParent(LLViewerObject* parent)
00923 {
00924         if (parent != getParent())
00925         {
00926                 LLViewerObject::setParent(parent);
00927                 if (mDrawable)
00928                 {
00929                         gPipeline.markMoved(mDrawable);
00930                         gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
00931                 }
00932         }
00933 }
00934 
00935 // NOTE: regenFaces() MUST be followed by genTriangles()!
00936 void LLVOVolume::regenFaces()
00937 {
00938         // remove existing faces
00939         BOOL count_changed = mNumFaces != getNumTEs();
00940         
00941         if (count_changed)
00942         {
00943                 deleteFaces();          
00944                 // add new faces
00945                 mNumFaces = getNumTEs();
00946         }
00947                 
00948         for (S32 i = 0; i < mNumFaces; i++)
00949         {
00950                 LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i);
00951                 facep->setTEOffset(i);
00952                 facep->setTexture(getTEImage(i));
00953                 facep->setViewerObject(this);
00954         }
00955         
00956         if (!count_changed)
00957         {
00958                 updateFaceFlags();
00959         }
00960 }
00961 
00962 BOOL LLVOVolume::genBBoxes(BOOL force_global)
00963 {
00964         BOOL res = TRUE;
00965 
00966         LLVector3 min,max;
00967 
00968         BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION);
00969 
00970         for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
00971         {
00972                 LLFace *face = mDrawable->getFace(i);
00973                 res &= face->genVolumeBBoxes(*getVolume(), i,
00974                                                                                 mRelativeXform, mRelativeXformInvTrans,
00975                                                                                 (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global);
00976                 
00977                 if (rebuild)
00978                 {
00979                         if (i == 0)
00980                         {
00981                                 min = face->mExtents[0];
00982                                 max = face->mExtents[1];
00983                         }
00984                         else
00985                         {
00986                                 for (U32 i = 0; i < 3; i++)
00987                                 {
00988                                         if (face->mExtents[0].mV[i] < min.mV[i])
00989                                         {
00990                                                 min.mV[i] = face->mExtents[0].mV[i];
00991                                         }
00992                                         if (face->mExtents[1].mV[i] > max.mV[i])
00993                                         {
00994                                                 max.mV[i] = face->mExtents[1].mV[i];
00995                                         }
00996                                 }
00997                         }
00998                 }
00999         }
01000         
01001         if (rebuild)
01002         {
01003                 mDrawable->setSpatialExtents(min,max);
01004                 mDrawable->setPositionGroup((min+max)*0.5f);    
01005         }
01006 
01007         updateRadius();
01008         mDrawable->movePartition();
01009                         
01010         return res;
01011 }
01012 
01013 void LLVOVolume::preRebuild()
01014 {
01015         if (mVolumeImpl != NULL)
01016         {
01017                 mVolumeImpl->preRebuild();
01018         }
01019 }
01020 
01021 void LLVOVolume::updateRelativeXform()
01022 {
01023         if (mVolumeImpl)
01024         {
01025                 mVolumeImpl->updateRelativeXform();
01026                 return;
01027         }
01028         
01029         LLDrawable* drawable = mDrawable;
01030         
01031         if (drawable->isActive())
01032         {                               
01033                 // setup relative transforms
01034                 LLQuaternion delta_rot;
01035                 LLVector3 delta_pos, delta_scale;
01036                 
01037                 //matrix from local space to parent relative/global space
01038                 delta_rot = drawable->isSpatialRoot() ? LLQuaternion() : mDrawable->getRotation();
01039                 delta_pos = drawable->isSpatialRoot() ? LLVector3(0,0,0) : mDrawable->getPosition();
01040                 delta_scale = mDrawable->getScale();
01041 
01042                 // Vertex transform (4x4)
01043                 LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot;
01044                 LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot;
01045                 LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot;
01046 
01047                 mRelativeXform.initRows(LLVector4(x_axis, 0.f),
01048                                                                 LLVector4(y_axis, 0.f),
01049                                                                 LLVector4(z_axis, 0.f),
01050                                                                 LLVector4(delta_pos, 1.f));
01051 
01052                 
01053                 // compute inverse transpose for normals
01054                 // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
01055                 // mRelativeXformInvTrans.invert(); 
01056                 // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
01057                 // grumble - invert is NOT a matrix invert, so we do it by hand:
01058 
01059                 LLMatrix3 rot_inverse = LLMatrix3(~delta_rot);
01060 
01061                 LLMatrix3 scale_inverse;
01062                 scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX],
01063                                                           LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY],
01064                                                           LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]);
01065                                                            
01066                 
01067                 mRelativeXformInvTrans = rot_inverse * scale_inverse;
01068 
01069                 mRelativeXformInvTrans.transpose();
01070         }
01071         else
01072         {
01073                 LLVector3 pos = getPosition();
01074                 LLVector3 scale = getScale();
01075                 LLQuaternion rot = getRotation();
01076         
01077                 if (mParent)
01078                 {
01079                         pos *= mParent->getRotation();
01080                         pos += mParent->getPosition();
01081                         rot *= mParent->getRotation();
01082                 }
01083                 
01084                 //LLViewerRegion* region = getRegion();
01085                 //pos += region->getOriginAgent();
01086                 
01087                 LLVector3 x_axis = LLVector3(scale.mV[VX], 0.f, 0.f) * rot;
01088                 LLVector3 y_axis = LLVector3(0.f, scale.mV[VY], 0.f) * rot;
01089                 LLVector3 z_axis = LLVector3(0.f, 0.f, scale.mV[VZ]) * rot;
01090 
01091                 mRelativeXform.initRows(LLVector4(x_axis, 0.f),
01092                                                                 LLVector4(y_axis, 0.f),
01093                                                                 LLVector4(z_axis, 0.f),
01094                                                                 LLVector4(pos, 1.f));
01095 
01096                 // compute inverse transpose for normals
01097                 LLMatrix3 rot_inverse = LLMatrix3(~rot);
01098 
01099                 LLMatrix3 scale_inverse;
01100                 scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX],
01101                                                           LLVector3(0.0, 1.0, 0.0) / scale.mV[VY],
01102                                                           LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]);
01103                                                            
01104                 
01105                 mRelativeXformInvTrans = rot_inverse * scale_inverse;
01106 
01107                 mRelativeXformInvTrans.transpose();
01108         }
01109 }
01110 
01111 BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
01112 {
01113         LLFastTimer t(LLFastTimer::FTM_UPDATE_PRIMITIVES);
01114         
01115         if (mVolumeImpl != NULL)
01116         {
01117                 BOOL res;
01118                 {
01119                         LLFastTimer t(LLFastTimer::FTM_GEN_FLEX);
01120                         res = mVolumeImpl->doUpdateGeometry(drawable);
01121                 }
01122                 updateFaceFlags();
01123                 return res;
01124         }
01125         
01126         dirtySpatialGroup();
01127 
01128         BOOL compiled = FALSE;
01129                         
01130         updateRelativeXform();
01131         
01132         if (mDrawable.isNull()) // Not sure why this is happening, but it is...
01133         {
01134                 return TRUE; // No update to complete
01135         }
01136 
01137         if (mVolumeChanged || mFaceMappingChanged )
01138         {
01139                 compiled = TRUE;
01140 
01141                 if (mVolumeChanged)
01142                 {
01143                         LLFastTimer ftm(LLFastTimer::FTM_GEN_VOLUME);
01144                         LLVolumeParams volume_params = getVolume()->getParams();
01145                         setVolume(volume_params, 0);
01146                         drawable->setState(LLDrawable::REBUILD_VOLUME);
01147                 }
01148 
01149                 {
01150                         LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
01151                         regenFaces();
01152                         genBBoxes(FALSE);
01153                 }
01154         }
01155         else if ((mLODChanged) || (mSculptChanged))
01156         {
01157                 LLVolume *old_volumep, *new_volumep;
01158                 F32 old_lod, new_lod;
01159                 S32 old_num_faces, new_num_faces ;
01160 
01161                 old_volumep = getVolume();
01162                 old_lod = old_volumep->getDetail();
01163                 old_num_faces = old_volumep->getNumFaces() ;
01164                 old_volumep = NULL ;
01165 
01166                 {
01167                         LLFastTimer ftm(LLFastTimer::FTM_GEN_VOLUME);
01168                         LLVolumeParams volume_params = getVolume()->getParams();
01169                         setVolume(volume_params, 0);
01170                 }
01171 
01172                 new_volumep = getVolume();
01173                 new_lod = new_volumep->getDetail();
01174                 new_num_faces = new_volumep->getNumFaces() ;
01175                 new_volumep = NULL ;
01176 
01177                 if ((new_lod != old_lod) || mSculptChanged)
01178                 {
01179                         compiled = TRUE;
01180                         sNumLODChanges += new_num_faces ;
01181         
01182                         drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
01183 
01184                         {
01185                                 LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
01186                                 if (new_num_faces != old_num_faces)
01187                                 {
01188                                         regenFaces();
01189                                 }
01190                                 genBBoxes(FALSE);
01191                         }
01192                 }
01193         }
01194         // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local
01195         else
01196         {
01197                 compiled = TRUE;
01198                 // All it did was move or we changed the texture coordinate offset
01199                 LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
01200                 genBBoxes(FALSE);
01201         }
01202 
01203         // Update face flags
01204         updateFaceFlags();
01205         
01206         if(compiled)
01207         {
01208                 LLPipeline::sCompiles++;
01209         }
01210         
01211         mVolumeChanged = FALSE;
01212         mLODChanged = FALSE;
01213         mSculptChanged = FALSE;
01214         mFaceMappingChanged = FALSE;
01215 
01216         return LLViewerObject::updateGeometry(drawable);
01217 }
01218 
01219 void LLVOVolume::updateFaceSize(S32 idx)
01220 {
01221         LLFace* facep = mDrawable->getFace(idx);
01222         if (idx >= getVolume()->getNumVolumeFaces())
01223         {
01224                 facep->setSize(0,0);
01225         }
01226         else
01227         {
01228                 const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx);
01229                 facep->setSize(vol_face.mVertices.size(), vol_face.mIndices.size());
01230         }
01231 }
01232 
01233 BOOL LLVOVolume::isRootEdit() const
01234 {
01235         if (mParent && !((LLViewerObject*)mParent)->isAvatar())
01236         {
01237                 return FALSE;
01238         }
01239         return TRUE;
01240 }
01241 
01242 void LLVOVolume::setTEImage(const U8 te, LLViewerImage *imagep)
01243 {
01244         BOOL changed = (mTEImages[te] != imagep);
01245         LLViewerObject::setTEImage(te, imagep);
01246         if (changed)
01247         {
01248                 gPipeline.markTextured(mDrawable);
01249                 mFaceMappingChanged = TRUE;
01250         }
01251 }
01252 
01253 S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid)
01254 {
01255         S32 res = LLViewerObject::setTETexture(te, uuid);
01256         if (res)
01257         {
01258                 gPipeline.markTextured(mDrawable);
01259                 mFaceMappingChanged = TRUE;
01260         }
01261         return res;
01262 }
01263 
01264 S32 LLVOVolume::setTEColor(const U8 te, const LLColor3& color)
01265 {
01266         return setTEColor(te, LLColor4(color));
01267 }
01268 
01269 S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color)
01270 {
01271         S32 res = LLViewerObject::setTEColor(te, color);
01272         if (res)
01273         {
01274                 gPipeline.markTextured(mDrawable);
01275                 mFaceMappingChanged = TRUE;
01276         }
01277         return  res;
01278 }
01279 
01280 S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap)
01281 {
01282         S32 res = LLViewerObject::setTEBumpmap(te, bumpmap);
01283         if (res)
01284         {
01285                 gPipeline.markTextured(mDrawable);
01286                 mFaceMappingChanged = TRUE;
01287         }
01288         return  res;
01289 }
01290 
01291 S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen)
01292 {
01293         S32 res = LLViewerObject::setTETexGen(te, texgen);
01294         if (res)
01295         {
01296                 gPipeline.markTextured(mDrawable);
01297                 mFaceMappingChanged = TRUE;
01298         }
01299         return  res;
01300 }
01301 
01302 S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny)
01303 {
01304         S32 res = LLViewerObject::setTEShiny(te, shiny);
01305         if (res)
01306         {
01307                 gPipeline.markTextured(mDrawable);
01308                 mFaceMappingChanged = TRUE;
01309         }
01310         return  res;
01311 }
01312 
01313 S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright)
01314 {
01315         S32 res = LLViewerObject::setTEFullbright(te, fullbright);
01316         if (res)
01317         {
01318                 gPipeline.markTextured(mDrawable);
01319                 mFaceMappingChanged = TRUE;
01320         }
01321         return  res;
01322 }
01323 
01324 S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags)
01325 {
01326         S32 res = LLViewerObject::setTEMediaFlags(te, media_flags);
01327         if (res)
01328         {
01329                 gPipeline.markTextured(mDrawable);
01330                 mFaceMappingChanged = TRUE;
01331         }
01332         return  res;
01333 }
01334 
01335 S32 LLVOVolume::setTEGlow(const U8 te, const F32 glow)
01336 {
01337         S32 res = LLViewerObject::setTEGlow(te, glow);
01338         if (res)
01339         {
01340                 gPipeline.markTextured(mDrawable);
01341                 mFaceMappingChanged = TRUE;
01342         }
01343         return  res;
01344 }
01345 
01346 S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t)
01347 {
01348         S32 res = LLViewerObject::setTEScale(te, s, t);
01349         if (res)
01350         {
01351                 gPipeline.markTextured(mDrawable);
01352                 mFaceMappingChanged = TRUE;
01353         }
01354         return res;
01355 }
01356 
01357 S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s)
01358 {
01359         S32 res = LLViewerObject::setTEScaleS(te, s);
01360         if (res)
01361         {
01362                 gPipeline.markTextured(mDrawable);
01363                 mFaceMappingChanged = TRUE;
01364         }
01365         return res;
01366 }
01367 
01368 S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t)
01369 {
01370         S32 res = LLViewerObject::setTEScaleT(te, t);
01371         if (res)
01372         {
01373                 gPipeline.markTextured(mDrawable);
01374                 mFaceMappingChanged = TRUE;
01375         }
01376         return res;
01377 }
01378 
01379 void LLVOVolume::updateTEData()
01380 {
01381         if (mDrawable.notNull())
01382         {
01383                 mFaceMappingChanged = TRUE;
01384                 gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE);
01385         }
01386 }
01387 
01388 //----------------------------------------------------------------------------
01389 
01390 void LLVOVolume::setIsLight(BOOL is_light)
01391 {
01392         if (is_light != getIsLight())
01393         {
01394                 if (is_light)
01395                 {
01396                         setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, TRUE, true);
01397                 }
01398                 else
01399                 {
01400                         setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT, FALSE, true);
01401                 }
01402 
01403                 if (is_light)
01404                 {
01405                         // Add it to the pipeline mLightSet
01406                         gPipeline.setLight(mDrawable, TRUE);
01407                 }
01408                 else
01409                 {
01410                         // Not a light.  Remove it from the pipeline's light set.
01411                         gPipeline.setLight(mDrawable, FALSE);
01412                 }
01413         }
01414 }
01415 
01416 void LLVOVolume::setLightColor(const LLColor3& color)
01417 {
01418         LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
01419         if (param_block)
01420         {
01421                 if (param_block->getColor() != color)
01422                 {
01423                         param_block->setColor(LLColor4(color, param_block->getColor().mV[3]));
01424                         parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
01425                         gPipeline.markTextured(mDrawable);
01426                         mFaceMappingChanged = TRUE;
01427                 }
01428         }
01429 }
01430 
01431 void LLVOVolume::setLightIntensity(F32 intensity)
01432 {
01433         LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
01434         if (param_block)
01435         {
01436                 if (param_block->getColor().mV[3] != intensity)
01437                 {
01438                         param_block->setColor(LLColor4(LLColor3(param_block->getColor()), intensity));
01439                         parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
01440                 }
01441         }
01442 }
01443 
01444 void LLVOVolume::setLightRadius(F32 radius)
01445 {
01446         LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
01447         if (param_block)
01448         {
01449                 if (param_block->getRadius() != radius)
01450                 {
01451                         param_block->setRadius(radius);
01452                         parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
01453                 }
01454         }
01455 }
01456 
01457 void LLVOVolume::setLightFalloff(F32 falloff)
01458 {
01459         LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
01460         if (param_block)
01461         {
01462                 if (param_block->getFalloff() != falloff)
01463                 {
01464                         param_block->setFalloff(falloff);
01465                         parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
01466                 }
01467         }
01468 }
01469 
01470 void LLVOVolume::setLightCutoff(F32 cutoff)
01471 {
01472         LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
01473         if (param_block)
01474         {
01475                 if (param_block->getCutoff() != cutoff)
01476                 {
01477                         param_block->setCutoff(cutoff);
01478                         parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
01479                 }
01480         }
01481 }
01482 
01483 //----------------------------------------------------------------------------
01484 
01485 BOOL LLVOVolume::getIsLight() const
01486 {
01487         return getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT);
01488 }
01489 
01490 LLColor3 LLVOVolume::getLightBaseColor() const
01491 {
01492         const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
01493         if (param_block)
01494         {
01495                 return LLColor3(param_block->getColor());
01496         }
01497         else
01498         {
01499                 return LLColor3(1,1,1);
01500         }
01501 }
01502 
01503 LLColor3 LLVOVolume::getLightColor() const
01504 {
01505         const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
01506         if (param_block)
01507         {
01508                 return LLColor3(param_block->getColor()) * param_block->getColor().mV[3];
01509         }
01510         else
01511         {
01512                 return LLColor3(1,1,1);
01513         }
01514 }
01515 
01516 F32 LLVOVolume::getLightIntensity() const
01517 {
01518         const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
01519         if (param_block)
01520         {
01521                 return param_block->getColor().mV[3];
01522         }
01523         else
01524         {
01525                 return 1.f;
01526         }
01527 }
01528 
01529 F32 LLVOVolume::getLightRadius() const
01530 {
01531         const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
01532         if (param_block)
01533         {
01534                 return param_block->getRadius();
01535         }
01536         else
01537         {
01538                 return 0.f;
01539         }
01540 }
01541 
01542 F32 LLVOVolume::getLightFalloff() const
01543 {
01544         const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
01545         if (param_block)
01546         {
01547                 return param_block->getFalloff();
01548         }
01549         else
01550         {
01551                 return 0.f;
01552         }
01553 }
01554 
01555 F32 LLVOVolume::getLightCutoff() const
01556 {
01557         const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
01558         if (param_block)
01559         {
01560                 return param_block->getCutoff();
01561         }
01562         else
01563         {
01564                 return 0.f;
01565         }
01566 }
01567 
01568 U32 LLVOVolume::getVolumeInterfaceID() const
01569 {
01570         if (mVolumeImpl)
01571         {
01572                 return mVolumeImpl->getID();
01573         }
01574 
01575         return 0;
01576 }
01577 
01578 BOOL LLVOVolume::isFlexible() const
01579 {
01580         if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE))
01581         {
01582                 LLVolume* volume = getVolume();
01583                 if (volume && volume->getParams().getPathParams().getCurveType() != LL_PCODE_PATH_FLEXIBLE)
01584                 {
01585                         LLVolumeParams volume_params = getVolume()->getParams();
01586                         U8 profile_and_hole = volume_params.getProfileParams().getCurveType();
01587                         volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE);
01588                 }
01589                 return TRUE;
01590         }
01591         else
01592         {
01593                 return FALSE;
01594         }
01595 }
01596 
01597 BOOL LLVOVolume::isSculpted() const
01598 {
01599         if (getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
01600         {
01601                 return TRUE;
01602         }
01603         
01604         return FALSE;
01605 }
01606 
01607 BOOL LLVOVolume::isVolumeGlobal() const
01608 {
01609         if (mVolumeImpl)
01610         {
01611                 return mVolumeImpl->isVolumeGlobal() ? TRUE : FALSE;
01612         }
01613         return FALSE;
01614 }
01615 
01616 BOOL LLVOVolume::canBeFlexible() const
01617 {
01618         U8 path = getVolume()->getParams().getPathParams().getCurveType();
01619         return (path == LL_PCODE_PATH_FLEXIBLE || path == LL_PCODE_PATH_LINE);
01620 }
01621 
01622 BOOL LLVOVolume::setIsFlexible(BOOL is_flexible)
01623 {
01624         BOOL res = FALSE;
01625         BOOL was_flexible = isFlexible();
01626         LLVolumeParams volume_params;
01627         if (is_flexible)
01628         {
01629                 if (!was_flexible)
01630                 {
01631                         volume_params = getVolume()->getParams();
01632                         U8 profile_and_hole = volume_params.getProfileParams().getCurveType();
01633                         volume_params.setType(profile_and_hole, LL_PCODE_PATH_FLEXIBLE);
01634                         res = TRUE;
01635                         setFlags(FLAGS_USE_PHYSICS, FALSE);
01636                         setFlags(FLAGS_PHANTOM, TRUE);
01637                         setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, TRUE, true);
01638                         if (mDrawable)
01639                         {
01640                                 mDrawable->makeActive();
01641                         }
01642                 }
01643         }
01644         else
01645         {
01646                 if (was_flexible)
01647                 {
01648                         volume_params = getVolume()->getParams();
01649                         U8 profile_and_hole = volume_params.getProfileParams().getCurveType();
01650                         volume_params.setType(profile_and_hole, LL_PCODE_PATH_LINE);
01651                         res = TRUE;
01652                         setFlags(FLAGS_PHANTOM, FALSE);
01653                         setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, true);
01654                 }
01655         }
01656         if (res)
01657         {
01658                 res = setVolume(volume_params, 1);
01659                 if (res)
01660                 {
01661                         markForUpdate(TRUE);
01662                 }
01663         }
01664         return res;
01665 }
01666 
01667 //----------------------------------------------------------------------------
01668 
01669 void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point)
01670 {
01671         LLVolume *volume = getVolume();
01672 
01673         if (volume)
01674         {
01675                 LLVector3 view_vector;
01676                 view_vector = view_point; 
01677 
01678                 //transform view vector into volume space
01679                 view_vector -= getRenderPosition();
01680                 mDrawable->mDistanceWRTCamera = view_vector.magVec();
01681                 LLQuaternion worldRot = getRenderRotation();
01682                 view_vector = view_vector * ~worldRot;
01683                 if (!isVolumeGlobal())
01684                 {
01685                         LLVector3 objScale = getScale();
01686                         LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]);
01687                         view_vector.scaleVec(invObjScale);
01688                 }
01689                 
01690                 updateRelativeXform();
01691                 LLMatrix4 trans_mat = mRelativeXform;
01692                 if (mDrawable->isStatic())
01693                 {
01694                         trans_mat.translate(getRegion()->getOriginAgent());
01695                 }
01696 
01697                 volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, nodep->mSilhouetteSegments, view_vector, trans_mat, mRelativeXformInvTrans);
01698 
01699                 nodep->mSilhouetteExists = TRUE;
01700         }
01701 }
01702 
01703 void LLVOVolume::deleteFaces()
01704 {
01705         S32 face_count = mNumFaces;
01706         if (mDrawable.notNull())
01707         {
01708                 mDrawable->deleteFaces(0, face_count);
01709         }
01710 
01711         mNumFaces = 0;
01712 }
01713 
01714 void LLVOVolume::updateRadius()
01715 {
01716         if (mDrawable.isNull())
01717         {
01718                 return;
01719         }
01720         
01721         mVObjRadius = getScale().magVec();
01722         mDrawable->setRadius(mVObjRadius);
01723 }
01724 
01725 
01726 BOOL LLVOVolume::isAttachment() const
01727 {
01728         if (mState == 0)
01729         {
01730                 return FALSE;
01731         }
01732         else
01733         {
01734                 return TRUE;
01735         }
01736 }
01737 
01738 BOOL LLVOVolume::isHUDAttachment() const
01739 {
01740         // *NOTE: we assume hud attachment points are in defined range
01741         // since this range is constant for backwards compatibility
01742         // reasons this is probably a reasonable assumption to make
01743         S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mState);
01744         return ( attachment_id >= 31 && attachment_id <= 38 );
01745 }
01746 
01747 
01748 const LLMatrix4 LLVOVolume::getRenderMatrix() const
01749 {
01750         if (mDrawable->isActive() && !mDrawable->isRoot())
01751         {
01752                 return mDrawable->getParent()->getWorldMatrix();
01753         }
01754         return mDrawable->getWorldMatrix();
01755 }
01756 
01757 //static
01758 void LLVOVolume::preUpdateGeom()
01759 {
01760         sNumLODChanges = 0;
01761 }
01762 
01763 void LLVOVolume::parameterChanged(U16 param_type, bool local_origin)
01764 {
01765         LLViewerObject::parameterChanged(param_type, local_origin);
01766 }
01767 
01768 void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin)
01769 {
01770         LLViewerObject::parameterChanged(param_type, data, in_use, local_origin);
01771         if (mVolumeImpl)
01772         {
01773                 mVolumeImpl->onParameterChanged(param_type, data, in_use, local_origin);
01774         }
01775         if (mDrawable.notNull())
01776         {
01777                 BOOL is_light = getIsLight();
01778                 if (is_light != mDrawable->isState(LLDrawable::LIGHT))
01779                 {
01780                         gPipeline.setLight(mDrawable, is_light);
01781                 }
01782         }
01783 }
01784 
01785 void LLVOVolume::setSelected(BOOL sel)
01786 {
01787         LLViewerObject::setSelected(sel);
01788         if (mDrawable.notNull())
01789         {
01790                 markForUpdate(TRUE);
01791         }
01792 }
01793 
01794 void LLVOVolume::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax)
01795 {               
01796 }
01797 
01798 F32 LLVOVolume::getBinRadius()
01799 {
01800         F32 radius;
01801         
01802         const LLVector3* ext = mDrawable->getSpatialExtents();
01803         
01804         BOOL shrink_wrap = mDrawable->isAnimating();
01805         BOOL alpha_wrap = FALSE;
01806 
01807         if (!isHUDAttachment())
01808         {
01809                 for (S32 i = 0; i < mDrawable->getNumFaces(); i++)
01810                 {
01811                         LLFace* face = mDrawable->getFace(i);
01812                         if (face->getPoolType() == LLDrawPool::POOL_ALPHA &&
01813                                 (!LLPipeline::sFastAlpha || face->getVirtualSize() > MIN_ALPHA_SIZE))
01814                         {
01815                                 alpha_wrap = TRUE;
01816                                 break;
01817                         }
01818                 }
01819         }
01820         else
01821         {
01822                 shrink_wrap = FALSE;
01823         }
01824 
01825         if (alpha_wrap)
01826         {
01827                 LLVector3 bounds = getScale();
01828                 radius = llmin(bounds.mV[1], bounds.mV[2]);
01829                 radius = llmin(radius, bounds.mV[0]);
01830                 radius *= 0.5f;
01831         }
01832         else if (shrink_wrap)
01833         {
01834                 radius = (ext[1]-ext[0]).magVec()*0.5f;
01835         }
01836         else if (mDrawable->isStatic())
01837         {
01838                 if (mDrawable->getRadius() < 2.0f)
01839                 {
01840                         radius = 16.f;
01841                 }
01842                 else
01843                 {
01844                         radius = 32.f;
01845                 }
01846         }
01847         else
01848         {
01849                 radius = 8.f;
01850         }
01851 
01852         return llclamp(radius, 0.5f, 256.f);
01853 }
01854 
01855 const LLVector3 LLVOVolume::getPivotPositionAgent() const
01856 {
01857         if (mVolumeImpl)
01858         {
01859                 return mVolumeImpl->getPivotPosition();
01860         }
01861         return LLViewerObject::getPivotPositionAgent();
01862 }
01863 
01864 void LLVOVolume::onShift(const LLVector3 &shift_vector)
01865 {
01866         if (mVolumeImpl)
01867         {
01868                 mVolumeImpl->onShift(shift_vector);
01869         }
01870 
01871         updateRelativeXform();
01872 }
01873 
01874 const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const
01875 {
01876         if (mVolumeImpl)
01877         {
01878                 return mVolumeImpl->getWorldMatrix(xform);
01879         }
01880         return xform->getWorldMatrix();
01881 }
01882 
01883 LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const
01884 {
01885         LLVector3 ret = pos - getRenderPosition();
01886         ret = ret * ~getRenderRotation();
01887         LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale();
01888         LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]);
01889         ret.scaleVec(invObjScale);
01890         
01891         return ret;
01892 }
01893 
01894 LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const
01895 {
01896         return dir * ~getRenderRotation();
01897 }
01898 
01899 LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const
01900 {
01901         LLVector3 ret = dir;
01902         ret.scaleVec(getScale());
01903         ret = ret * getRenderRotation();
01904         ret += getRenderPosition();
01905         
01906         return ret;
01907 }
01908 
01909 BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const
01910 {
01911         return FALSE;
01912         
01913 #if 0 // needs to be rewritten to use face extents instead of volume bounds
01914         LLVolume* volume = getVolume();
01915         BOOL ret = FALSE;
01916         if (volume)
01917         {       
01918                 LLVector3 v_start, v_end, v_dir;
01919         
01920                 v_start = agentPositionToVolume(start);
01921                 v_end = agentPositionToVolume(end);
01922                 
01923                 if (LLLineSegmentAABB(v_start, v_end, volume->mBounds[0], volume->mBounds[1]))
01924                 {
01925                         if (volume->lineSegmentIntersect(v_start, v_end) >= 0)
01926                         {
01927                                 end = volumePositionToAgent(v_end);
01928                                 ret = TRUE;
01929                         }
01930                 }
01931         }
01932         return ret;
01933 #endif
01934 }
01935 
01936 U32 LLVOVolume::getPartitionType() const
01937 {
01938         if (isHUDAttachment())
01939         {
01940                 return LLViewerRegion::PARTITION_HUD;
01941         }
01942 
01943         return LLViewerRegion::PARTITION_VOLUME;
01944 }
01945 
01946 LLVolumePartition::LLVolumePartition()
01947 : LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, FALSE)
01948 {
01949         mLODPeriod = 16;
01950         mDepthMask = FALSE;
01951         mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
01952         mPartitionType = LLViewerRegion::PARTITION_VOLUME;
01953         mSlopRatio = 0.25f;
01954         mBufferUsage = GL_DYNAMIC_DRAW_ARB;
01955         mImageEnabled = TRUE;
01956 }
01957 
01958 LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep)
01959 : LLSpatialBridge(drawablep, LLVOVolume::VERTEX_DATA_MASK)
01960 {
01961         mDepthMask = FALSE;
01962         mLODPeriod = 16;
01963         mDrawableType = LLPipeline::RENDER_TYPE_VOLUME;
01964         mPartitionType = LLViewerRegion::PARTITION_BRIDGE;
01965         
01966         mBufferUsage = GL_DYNAMIC_DRAW_ARB;
01967 
01968         mSlopRatio = 0.25f;
01969 }
01970 
01971 void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)
01972 {
01973         LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
01974 
01975         if (facep->getViewerObject()->isSelected() && gHideSelectedObjects)
01976         {
01977                 return;
01978         }
01979 
01980         //add face to drawmap
01981         LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type];       
01982 
01983         S32 idx = draw_vec.size()-1;
01984 
01985 
01986         BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT ||
01987                                           type == LLRenderPass::PASS_ALPHA) ? facep->isState(LLFace::FULLBRIGHT) : FALSE;
01988 
01989         const LLMatrix4* tex_mat = NULL;
01990         if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE)
01991         {
01992                 tex_mat = facep->mTextureMatrix;        
01993         }
01994 
01995         const LLMatrix4* model_mat = NULL;
01996 
01997         LLDrawable* drawable = facep->getDrawable();
01998         if (drawable->isActive())
01999         {
02000                 model_mat = &(drawable->getRenderMatrix());
02001         }
02002         else
02003         {
02004                 model_mat = &(drawable->getRegion()->mRenderMatrix);
02005         }
02006 
02007         U8 bump = (type == LLRenderPass::PASS_BUMP ? facep->getTextureEntry()->getBumpmap() : 0);
02008         
02009         LLViewerImage* tex = facep->getTexture();
02010 
02011         U8 glow = 0;
02012                 
02013         if (type == LLRenderPass::PASS_GLOW)
02014         {
02015                 glow = (U8) (facep->getTextureEntry()->getGlow() * 255);
02016         }
02017 
02018         if (idx >= 0 && 
02019                 draw_vec[idx]->mVertexBuffer == facep->mVertexBuffer &&
02020                 draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
02021                 (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex) &&
02022 #if LL_DARWIN
02023                 draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
02024                 draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
02025 #endif
02026                 draw_vec[idx]->mGlowColor.mV[3] == glow &&
02027                 draw_vec[idx]->mFullbright == fullbright &&
02028                 draw_vec[idx]->mBump == bump &&
02029                 draw_vec[idx]->mTextureMatrix == tex_mat &&
02030                 draw_vec[idx]->mModelMatrix == model_mat)
02031         {
02032                 draw_vec[idx]->mCount += facep->getIndicesCount();
02033                 draw_vec[idx]->mEnd += facep->getGeomCount();
02034                 draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize());
02035                 validate_draw_info(*draw_vec[idx]);
02036         }
02037         else
02038         {
02039                 U32 start = facep->getGeomIndex();
02040                 U32 end = start + facep->getGeomCount()-1;
02041                 U32 offset = facep->getIndicesStart();
02042                 U32 count = facep->getIndicesCount();
02043                 LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset,tex, 
02044                         facep->mVertexBuffer, fullbright, bump); 
02045                 draw_info->mGroup = group;
02046                 draw_info->mVSize = facep->getVirtualSize();
02047                 draw_vec.push_back(draw_info);
02048                 draw_info->mReflectionMap = group->mReflectionMap;
02049                 draw_info->mTextureMatrix = tex_mat;
02050                 draw_info->mModelMatrix = model_mat;
02051                 draw_info->mGlowColor.setVec(0,0,0,glow);
02052                 validate_draw_info(*draw_info);
02053         }
02054 }
02055 
02056 void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group)
02057 {
02058 
02059 }
02060 
02061 void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
02062 {
02063         if (LLPipeline::sSkipUpdate)
02064         {
02065                 return;
02066         }
02067 
02068         if (group->changeLOD())
02069         {
02070                 group->mLastUpdateDistance = group->mDistance;
02071         }
02072 
02073         group->mLastUpdateViewAngle = group->mViewAngle;
02074 
02075         if (!group->isState(LLSpatialGroup::GEOM_DIRTY |
02076                                                 LLSpatialGroup::ALPHA_DIRTY))
02077         {
02078                 if (group->isState(LLSpatialGroup::MESH_DIRTY))
02079                 {
02080                         S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ;
02081 
02082                         group->mBuilt = 1.f;
02083                         LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO);  
02084 
02085                         LLFastTimer ftm2(LLFastTimer::FTM_REBUILD_VOLUME_VB);
02086 
02087                         for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)
02088                         {
02089                                 LLDrawable* drawablep = *drawable_iter;
02090 
02091                                 if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) )
02092                                 {
02093                                         continue;
02094                                 }
02095 
02096                                 if (drawablep->isState(LLDrawable::REBUILD_ALL))
02097                                 {
02098                                         LLVOVolume* vobj = drawablep->getVOVolume();
02099                                         vobj->preRebuild();
02100                                         LLVolume* volume = vobj->getVolume();
02101                                         for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
02102                                         {
02103                                                 LLFace* face = drawablep->getFace(i);
02104                                                 if (face && face->mVertexBuffer.notNull())
02105                                                 {
02106                                                         face->getGeometryVolume(*volume, face->getTEOffset(), 
02107                                                                 vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex());
02108                                                 }
02109                                         }
02110 
02111                                         drawablep->clearState(LLDrawable::REBUILD_ALL);
02112                                 }
02113                         }
02114                         
02115                         //unmap all the buffers
02116                         for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i)
02117                         {
02118                                 LLSpatialGroup::buffer_list_t& list = i->second;
02119                                 for (LLSpatialGroup::buffer_list_t::iterator j = list.begin(); j != list.end(); ++j)
02120                                 {
02121                                         LLVertexBuffer* buffer = *j;
02122                                         if (buffer->isLocked())
02123                                         {
02124                                                 buffer->setBuffer(0);
02125                                         }
02126                                 }
02127                         }
02128                         
02129                         // don't forget alpha
02130                         if(     group != NULL && 
02131                                 !group->mVertexBuffer.isNull() && 
02132                                 group->mVertexBuffer->isLocked())
02133                         {
02134                                 group->mVertexBuffer->setBuffer(0);
02135                         }
02136 
02137                         //if not all buffers are unmapped
02138                         if(num_mapped_veretx_buffer != LLVertexBuffer::sMappedCount) 
02139                         {
02140                                 llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ; 
02141                                 for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)
02142                                 {
02143                                         LLDrawable* drawablep = *drawable_iter;
02144                                         for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
02145                                         {
02146                                                 LLFace* face = drawablep->getFace(i);
02147                                                 if (face && face->mVertexBuffer.notNull() && face->mVertexBuffer->isLocked())
02148                                                 {
02149                                                         face->mVertexBuffer->setBuffer(0) ;
02150                                                 }
02151                                         }
02152                                 } 
02153                         }
02154 
02155                         group->clearState(LLSpatialGroup::MESH_DIRTY);
02156                 }
02157 
02158                 return;
02159         }
02160 
02161         group->mBuilt = 1.f;
02162         LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO);  
02163 
02164         LLFastTimer ftm2(LLFastTimer::FTM_REBUILD_VOLUME_VB);
02165 
02166         //find reflection map
02167         if (group->mSpatialPartition->mImageEnabled && LLPipeline::sDynamicReflections)
02168         {
02169                 if (group->mReflectionMap.isNull())
02170                 {
02171                         LLSpatialGroup* parent = group->getParent();
02172                         while (parent && group->mReflectionMap.isNull())
02173                         {
02174                                 group->mReflectionMap = parent->mReflectionMap;
02175                                 parent = parent->getParent();
02176                         }
02177                 }
02178         }
02179 
02180         group->clearDrawMap();
02181 
02182         mFaceList.clear();
02183 
02184         std::vector<LLFace*> alpha_faces;
02185         U32 vertex_count = 0;
02186         U32 index_count = 0;
02187         U32 useage = group->mSpatialPartition->mBufferUsage;
02188 
02189         U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask);
02190         max_vertices = llmin(max_vertices, (U32) 65535);
02191 
02192         //get all the faces into a list, putting alpha faces in their own list
02193         for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)
02194         {
02195                 LLDrawable* drawablep = *drawable_iter;
02196                 
02197                 if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) )
02198                 {
02199                         continue;
02200                 }
02201         
02202                 if (drawablep->isAnimating())
02203                 { //fall back to stream draw for animating verts
02204                         useage = GL_STREAM_DRAW_ARB;
02205                 }
02206 
02207                 LLVOVolume* vobj = drawablep->getVOVolume();
02208                 vobj->updateTextures();
02209                 vobj->preRebuild();
02210 
02211                 //for each face
02212                 for (S32 i = 0; i < drawablep->getNumFaces(); i++)
02213                 {
02214                         //sum up face verts and indices
02215                         drawablep->updateFaceSize(i);
02216                         LLFace* facep = drawablep->getFace(i);
02217                         if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA)
02218                         {
02219                                 const LLTextureEntry* te = facep->getTextureEntry();
02220                                 LLViewerImage* tex = facep->getTexture();
02221 
02222                                 BOOL force_simple = (facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA);
02223                                 U32 type = gPipeline.getPoolTypeFromTE(te, tex);
02224                                 if (type != LLDrawPool::POOL_ALPHA && force_simple)
02225                                 {
02226                                         type = LLDrawPool::POOL_SIMPLE;
02227                                 }
02228                                 facep->setPoolType(type);
02229 
02230                                 if (vobj->isHUDAttachment())
02231                                 {
02232                                         facep->setState(LLFace::FULLBRIGHT);
02233                                 }
02234 
02235                                 if (vobj->mTextureAnimp && vobj->mTexAnimMode)
02236                                 {
02237                                         if (vobj->mTextureAnimp->mFace <= -1)
02238                                         {
02239                                                 S32 face;
02240                                                 for (face = 0; face < vobj->getNumTEs(); face++)
02241                                                 {
02242                                                         drawablep->getFace(face)->setState(LLFace::TEXTURE_ANIM);
02243                                                 }
02244                                         }
02245                                         else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs())
02246                                         {
02247                                                 drawablep->getFace(vobj->mTextureAnimp->mFace)->setState(LLFace::TEXTURE_ANIM);
02248                                         }
02249                                 }
02250 
02251                                 if (type == LLDrawPool::POOL_ALPHA)
02252                                 {
02253                                         BOOL alpha_opt = LLPipeline::sFastAlpha && gPipeline.canUseWindLightShadersOnObjects() && facep->getVirtualSize() < MIN_ALPHA_SIZE;
02254 
02255                                         const LLColor4& col = facep->getTextureEntry()->getColor();
02256 
02257                                         if (alpha_opt)
02258                                         { //if we're applying the alpha optimization, only blend faces that have alpha (0.15, 0.5]
02259                                           //for faces with alpha (0.5, 1.0], render with an alpha mask
02260                                           //for faces with alpha [0.0, 0.15], don't render
02261                                                 if (col.mV[3] > 0.5f)
02262                                                 {
02263                                                         mFaceList.push_back(facep);
02264                                                 }
02265                                                 else if (col.mV[3] > 0.15f)
02266                                                 {
02267                                                         vertex_count += facep->getGeomCount();
02268                                                         index_count += facep->getIndicesCount();
02269                                                         alpha_faces.push_back(facep);
02270                                                 }
02271                                                 else
02272                                                 {       //face has no renderable geometry
02273                                                         facep->mVertexBuffer = NULL;
02274                                                         facep->mLastVertexBuffer = NULL;
02275                                                         //don't alpha wrap drawables that have only tiny tiny alpha faces
02276                                                         facep->setPoolType(LLDrawPool::POOL_SIMPLE);
02277                                                 }
02278                                         }
02279                                         else
02280                                         {
02281                                                 vertex_count += facep->getGeomCount();
02282                                                 index_count += facep->getIndicesCount();
02283                                                 alpha_faces.push_back(facep);
02284                                         }
02285                                 }
02286                                 else
02287                                 {
02288                                         if (drawablep->isState(LLDrawable::REBUILD_VOLUME))
02289                                         {
02290                                                 facep->mLastUpdateTime = gFrameTimeSeconds;
02291                                         }
02292                                         mFaceList.push_back(facep);
02293                                 }
02294                         }
02295                         else
02296                         {       //face has no renderable geometry
02297                                 facep->mVertexBuffer = NULL;
02298                                 facep->mLastVertexBuffer = NULL;
02299                                 //don't alpha wrap drawables that have only tiny tiny alpha faces
02300                                 facep->setPoolType(LLDrawPool::POOL_SIMPLE);
02301                         }               
02302                 }
02303         }
02304 
02305         U16 alpha_vertex_count = vertex_count > 65535 ? 65535 : vertex_count;
02306         U32 alpha_index_count = index_count;
02307 
02308         group->mBufferUsage = useage;
02309 
02310         //PROCESS NON-ALPHA FACES
02311         {
02312                 //sort faces by things that break batches
02313                 std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareBatchBreaker());
02314                                         
02315                 std::vector<LLFace*>::iterator face_iter = mFaceList.begin();
02316                 
02317                 LLSpatialGroup::buffer_map_t buffer_map;
02318 
02319                 LLViewerImage* last_tex = NULL;
02320                 U32 buffer_index = 0;
02321 
02322                 while (face_iter != mFaceList.end())
02323                 {
02324                         //pull off next face
02325                         LLFace* facep = *face_iter;
02326                         LLViewerImage* tex = facep->getTexture();
02327 
02328                         if (last_tex == tex)
02329                         {
02330                                 buffer_index++;
02331                         }
02332                         else
02333                         {
02334                                 last_tex = tex;
02335                                 buffer_index = 0;
02336                         }
02337 
02338                         U32 index_count = facep->getIndicesCount();
02339                         U32 geom_count = facep->getGeomCount();
02340 
02341                         //sum up vertices needed for this texture
02342                         std::vector<LLFace*>::iterator i = face_iter;
02343                         ++i;
02344                         
02345                         while (i != mFaceList.end() && 
02346                                 (LLPipeline::sTextureBindTest || (*i)->getTexture() == tex))
02347                         {
02348                                 facep = *i;
02349                                 
02350                                 if (geom_count + facep->getGeomCount() > max_vertices)
02351                                 { //cut vertex buffers on geom count too big
02352                                         break;
02353                                 }
02354 
02355                                 ++i;
02356                                 index_count += facep->getIndicesCount();
02357                                 geom_count += facep->getGeomCount();
02358                         }
02359                 
02360                         //create/delete/resize vertex buffer if needed
02361                         LLVertexBuffer* buffer = NULL;
02362                         LLSpatialGroup::buffer_map_t::iterator found_iter = group->mBufferMap.find(tex);
02363                         if (found_iter != group->mBufferMap.end())
02364                         {
02365                                 if (buffer_index < found_iter->second.size())
02366                                 {
02367                                         buffer = found_iter->second[buffer_index];
02368                                 }
02369                         }
02370                                                         
02371                         if (!buffer)
02372                         { //create new buffer if needed
02373                                 buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, 
02374                                                                                                 group->mBufferUsage);
02375                                 buffer->allocateBuffer(geom_count, index_count, TRUE);
02376                         }
02377                         else 
02378                         {
02379                                 if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage)
02380                                 {
02381                                         buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, 
02382                                                                                                 group->mBufferUsage);
02383                                         buffer->allocateBuffer(geom_count, index_count, TRUE);
02384                                 }
02385                                 else
02386                                 {
02387                                         buffer->resizeBuffer(geom_count, index_count);
02388                                 }
02389                         }
02390 
02391                         buffer_map[tex].push_back(buffer);
02392 
02393                         //add face geometry
02394 
02395                         U32 indices_index = 0;
02396                         U16 index_offset = 0;
02397 
02398                         while (face_iter < i)
02399                         {
02400                                 facep = *face_iter;
02401                                 LLDrawable* drawablep = facep->getDrawable();
02402                                 LLVOVolume* vobj = drawablep->getVOVolume();
02403                                 LLVolume* volume = vobj->getVolume();
02404 
02405                                 U32 te_idx = facep->getTEOffset();
02406                                 facep->mIndicesIndex = indices_index;
02407                                 facep->mGeomIndex = index_offset;
02408                                 facep->mVertexBuffer = buffer;
02409                                 {
02410                                         if (facep->getGeometryVolume(*volume, te_idx, 
02411                                                 vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset))
02412                                         {
02413                                                 buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(), 
02414                                                         facep->getIndicesStart(), facep->getIndicesCount());
02415                                         }
02416                                 }
02417 
02418                                 index_offset += facep->getGeomCount();
02419                                 indices_index += facep->mIndicesCount;
02420 
02421                                 BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA;
02422                                 BOOL fullbright = facep->isState(LLFace::FULLBRIGHT);
02423                                 const LLTextureEntry* te = facep->getTextureEntry();
02424 
02425                                 BOOL is_alpha = facep->getPoolType() == LLDrawPool::POOL_ALPHA ? TRUE : FALSE;
02426 
02427                                 if (!is_alpha 
02428                                         && gPipeline.canUseWindLightShadersOnObjects()
02429                                         && LLPipeline::sRenderBump 
02430                                         && te->getShiny())
02431                                 {
02432                                         if (tex->getPrimaryFormat() == GL_ALPHA)
02433                                         {
02434                                                 registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY);
02435                                                 registerFace(group, facep, LLRenderPass::PASS_INVISIBLE);
02436                                         }
02437                                         else if (fullbright)
02438                                         {                                               
02439                                                 registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_SHINY);
02440                                         }
02441                                         else
02442                                         {
02443                                                 registerFace(group, facep, LLRenderPass::PASS_SHINY);
02444                                         }
02445                                 }
02446                                 else
02447                                 {
02448                                         if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA)
02449                                         {
02450                                                 registerFace(group, facep, LLRenderPass::PASS_INVISIBLE);
02451                                         }
02452                                         else if (fullbright)
02453                                         {
02454                                                 registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
02455                                         }
02456                                         else
02457                                         {
02458                                                 registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
02459                                         }
02460                                         
02461                                         if (!is_alpha && te->getShiny())
02462                                         {
02463                                                 registerFace(group, facep, LLRenderPass::PASS_SHINY);
02464                                         }
02465                                 }
02466                                 
02467                                 if (!is_alpha)
02468                                 {
02469                                         facep->setPoolType(LLDrawPool::POOL_SIMPLE);
02470                                         
02471                                         if (!force_simple && te->getBumpmap())
02472                                         {
02473                                                 registerFace(group, facep, LLRenderPass::PASS_BUMP);
02474                                         }
02475                                 }
02476 
02477                                 if (LLPipeline::sRenderGlow && te->getGlow() > 0.f)
02478                                 {
02479                                         registerFace(group, facep, LLRenderPass::PASS_GLOW);
02480                                 }
02481                                                         
02482                                 ++face_iter;
02483                         }
02484 
02485                         buffer->setBuffer(0);
02486                 }
02487 
02488                 group->mBufferMap.clear();
02489                 for (LLSpatialGroup::buffer_map_t::iterator i = buffer_map.begin(); i != buffer_map.end(); ++i)
02490                 {
02491                         group->mBufferMap[i->first] = i->second;
02492                 }
02493         }
02494 
02495         //PROCESS ALPHA FACES
02496         if (!alpha_faces.empty())
02497         {
02498                 //sort alpha faces by distance
02499                 std::sort(alpha_faces.begin(), alpha_faces.end(), LLFace::CompareDistanceGreater());
02500 
02501                 //store alpha faces in root vertex buffer
02502                 if (group->mVertexBuffer.isNull() || (LLVertexBuffer::sEnableVBOs && group->mBufferUsage != group->mVertexBuffer->getUsage()))
02503                 {
02504                         group->mVertexBuffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, 
02505                                                                                                           group->mBufferUsage);
02506                         group->mVertexBuffer->allocateBuffer(alpha_vertex_count, alpha_index_count, true);
02507                         stop_glerror();
02508                 }
02509                 else
02510                 {
02511                         group->mVertexBuffer->resizeBuffer(alpha_vertex_count, alpha_index_count);
02512                         stop_glerror();
02513                 }
02514 
02515                 //get vertex buffer striders
02516                 LLVertexBuffer* buffer = group->mVertexBuffer;
02517 
02518                 U32 index_offset = 0;
02519                 U32 indices_index = 0;
02520 
02521                 for (std::vector<LLFace*>::iterator i = alpha_faces.begin(); i != alpha_faces.end(); ++i)
02522                 {
02523                         LLFace* facep = *i;
02524 
02525                         if (facep->mGeomCount + index_offset > 65535)
02526                         { //cut off alpha nodes at 64k vertices
02527                                 facep->mVertexBuffer = NULL ;
02528                                 facep->mLastVertexBuffer = NULL ;
02529                                 continue ;
02530                         }
02531 
02532                         LLDrawable* drawablep = facep->getDrawable();
02533                         LLVOVolume* vobj = drawablep->getVOVolume();
02534                         LLVolume* volume = vobj->getVolume();
02535 
02536                         U32 te_idx = facep->getTEOffset();
02537                         facep->mIndicesIndex = indices_index;
02538                         facep->mGeomIndex = index_offset;
02539                         facep->mVertexBuffer = group->mVertexBuffer;
02540                         if (facep->getGeometryVolume(*volume, te_idx, 
02541                                                                                 vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), 
02542                                                                                 index_offset))
02543                         {
02544                                 buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(), 
02545                                         facep->getIndicesStart(), facep->getIndicesCount());
02546                         }
02547 
02548                         index_offset += facep->getGeomCount();
02549                         indices_index += facep->mIndicesCount;
02550 
02551                         registerFace(group, facep, LLRenderPass::PASS_ALPHA);
02552 
02553                         if (LLPipeline::sRenderGlow && facep->getTextureEntry()->getGlow() > 0.f)
02554                         {
02555                                 registerFace(group, facep, LLRenderPass::PASS_GLOW);
02556                         }                               
02557                 }
02558 
02559                 buffer->setBuffer(0);
02560         }
02561         else
02562         {
02563                 group->mVertexBuffer = NULL;
02564         }
02565 
02566         //drawables have been rebuilt, clear rebuild status
02567         for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)
02568         {
02569                 LLDrawable* drawablep = *drawable_iter;
02570                 drawablep->clearState(LLDrawable::REBUILD_ALL);
02571         }
02572 
02573         group->mLastUpdateTime = gFrameTimeSeconds;
02574         group->mBuilt = 1.f;
02575         group->clearState(LLSpatialGroup::GEOM_DIRTY |
02576                                                 LLSpatialGroup::ALPHA_DIRTY | LLSpatialGroup::MESH_DIRTY);
02577 
02578         mFaceList.clear();
02579 }
02580 
02581 void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count)
02582 {       
02583         //initialize to default usage for this partition
02584         U32 usage = group->mSpatialPartition->mBufferUsage;
02585         
02586         //clear off any old faces
02587         mFaceList.clear();
02588 
02589         //for each drawable
02590         for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter)
02591         {
02592                 LLDrawable* drawablep = *drawable_iter;
02593                 
02594                 if (drawablep->isDead())
02595                 {
02596                         continue;
02597                 }
02598         
02599                 if (drawablep->isAnimating())
02600                 { //fall back to stream draw for animating verts
02601                         usage = GL_STREAM_DRAW_ARB;
02602                 }
02603 
02604                 //for each face
02605                 for (S32 i = 0; i < drawablep->getNumFaces(); i++)
02606                 {
02607                         //sum up face verts and indices
02608                         drawablep->updateFaceSize(i);
02609                         LLFace* facep = drawablep->getFace(i);
02610                         if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA)
02611                         {
02612                                 vertex_count += facep->getGeomCount();
02613                                 index_count += facep->getIndicesCount();
02614 
02615                                 //remember face (for sorting)
02616                                 mFaceList.push_back(facep);
02617                         }
02618                         else
02619                         {
02620                                 facep->mVertexBuffer = NULL;
02621                                 facep->mLastVertexBuffer = NULL;
02622                         }
02623                 }
02624         }
02625         
02626         group->mBufferUsage = usage;
02627 }
02628 
02629 LLHUDPartition::LLHUDPartition()
02630 {
02631         mPartitionType = LLViewerRegion::PARTITION_HUD;
02632         mDrawableType = LLPipeline::RENDER_TYPE_HUD;
02633         mSlopRatio = 0.f;
02634         mLODPeriod = 16;
02635 }
02636 
02637 void LLHUDPartition::shift(const LLVector3 &offset)
02638 {
02639         //HUD objects don't shift with region crossing.  That would be silly.
02640 }
02641 
02642 

Generated on Fri May 16 08:34:24 2008 for SecondLife by  doxygen 1.5.5