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