00001
00032
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
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;
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
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
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
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
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
00182
00183
00184
00185 if (unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num) & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR))
00186 {
00187 updateTEData();
00188 }
00189 }
00190 else
00191 {
00192
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
00213 dp->dumpBufferToLog();
00214 llwarns << "Flushing cache files" << llendl;
00215 char mask[LL_MAX_PATH];
00216 snprintf(mask, LL_MAX_PATH, "%s*.slc", gDirUtilp->getDirDelimiter().c_str());
00217 gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(),mask);
00218
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
00391
00392
00393 if (mTextureAnimp && gAnimateTextures)
00394 {
00395 animateTextures();
00396 }
00397
00398
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;
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
00422
00423 if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE))
00424 {
00425 return;
00426 }
00427
00428 if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull())
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);
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();
00522 S32 current_discard = getVolume()->getSculptLevel();
00523
00524 if (texture_discard >= 0 &&
00525 (texture_discard < current_discard ||
00526 current_discard < 0))
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 {
00550 mPixelArea = old_area;
00551 }
00552 }
00553
00554 F32 LLVOVolume::getTextureVirtualSize(LLFace* face)
00555 {
00556
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
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
00575 texel_area = 1.f;
00576 }
00577
00578
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
00607 LLViewerObject::setScale(scale);
00608
00609 if (mVolumeImpl)
00610 {
00611 mVolumeImpl->onSetScale(scale, damped);
00612 }
00613
00614 updateRadius();
00615
00616
00617
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
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
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
00676 setParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE, FALSE, false);
00677 if (mVolumeImpl)
00678 {
00679 delete mVolumeImpl;
00680 mVolumeImpl = NULL;
00681 if (mDrawable.notNull())
00682 {
00683
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
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;
00728
00729 discard_level = desired_discard;
00730
00731 S32 max_discard = mSculptTexture->getMaxDiscardLevel();
00732 if (discard_level > max_discard)
00733 discard_level = max_discard;
00734
00735 S32 best_discard = mSculptTexture->getDiscardLevel();
00736 if (discard_level < best_discard)
00737 discard_level = best_discard;
00738
00739 if (best_discard == -1)
00740 discard_level = -1;
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
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
00758 return;
00759 }
00760
00761 if (current_discard == discard_level)
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
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
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
00830 distance *= 1.0f/rampDist;
00831 distance *= distance;
00832 distance *= rampDist;
00833 }
00834
00835
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
00878 return FALSE;
00879 }
00880
00881 if (!mDrawable->isRoot())
00882 {
00883
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
00936 void LLVOVolume::regenFaces()
00937 {
00938
00939 BOOL count_changed = mNumFaces != getNumTEs();
00940
00941 if (count_changed)
00942 {
00943 deleteFaces();
00944
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
01034 LLQuaternion delta_rot;
01035 LLVector3 delta_pos, delta_scale;
01036
01037
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
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
01054
01055
01056
01057
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
01085
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
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())
01133 {
01134 return TRUE;
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);
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
01195 else
01196 {
01197 compiled = TRUE;
01198
01199 LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES);
01200 genBBoxes(FALSE);
01201 }
01202
01203
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
01406 gPipeline.setLight(mDrawable, TRUE);
01407 }
01408 else
01409 {
01410
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
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
01741
01742
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
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
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
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
02130 if( group != NULL &&
02131 !group->mVertexBuffer.isNull() &&
02132 group->mVertexBuffer->isLocked())
02133 {
02134 group->mVertexBuffer->setBuffer(0);
02135 }
02136
02137
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
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
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 {
02204 useage = GL_STREAM_DRAW_ARB;
02205 }
02206
02207 LLVOVolume* vobj = drawablep->getVOVolume();
02208 vobj->updateTextures();
02209 vobj->preRebuild();
02210
02211
02212 for (S32 i = 0; i < drawablep->getNumFaces(); i++)
02213 {
02214
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 {
02259
02260
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 {
02273 facep->mVertexBuffer = NULL;
02274 facep->mLastVertexBuffer = NULL;
02275
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 {
02297 facep->mVertexBuffer = NULL;
02298 facep->mLastVertexBuffer = NULL;
02299
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
02311 {
02312
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
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
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 {
02352 break;
02353 }
02354
02355 ++i;
02356 index_count += facep->getIndicesCount();
02357 geom_count += facep->getGeomCount();
02358 }
02359
02360
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 {
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
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
02496 if (!alpha_faces.empty())
02497 {
02498
02499 std::sort(alpha_faces.begin(), alpha_faces.end(), LLFace::CompareDistanceGreater());
02500
02501
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
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 {
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
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
02584 U32 usage = group->mSpatialPartition->mBufferUsage;
02585
02586
02587 mFaceList.clear();
02588
02589
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 {
02601 usage = GL_STREAM_DRAW_ARB;
02602 }
02603
02604
02605 for (S32 i = 0; i < drawablep->getNumFaces(); i++)
02606 {
02607
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
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
02640 }
02641
02642