diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/llvovolume.cpp | 1662 |
1 files changed, 1059 insertions, 603 deletions
diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp index 6791acd..f425687 100644 --- a/linden/indra/newview/llvovolume.cpp +++ b/linden/indra/newview/llvovolume.cpp | |||
@@ -42,7 +42,6 @@ | |||
42 | #include "material_codes.h" | 42 | #include "material_codes.h" |
43 | #include "message.h" | 43 | #include "message.h" |
44 | #include "object_flags.h" | 44 | #include "object_flags.h" |
45 | |||
46 | #include "llagent.h" | 45 | #include "llagent.h" |
47 | #include "lldrawable.h" | 46 | #include "lldrawable.h" |
48 | #include "lldrawpoolsimple.h" | 47 | #include "lldrawpoolsimple.h" |
@@ -64,14 +63,14 @@ | |||
64 | #include "pipeline.h" | 63 | #include "pipeline.h" |
65 | 64 | ||
66 | const S32 MIN_QUIET_FRAMES_COALESCE = 30; | 65 | const S32 MIN_QUIET_FRAMES_COALESCE = 30; |
67 | 66 | const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; | |
68 | //#define LLDEBUG_DISPLAY_LODS 1 | 67 | const F32 FORCE_CULL_AREA = 8.f; |
69 | 68 | ||
70 | BOOL gAnimateTextures = TRUE; | 69 | BOOL gAnimateTextures = TRUE; |
70 | extern BOOL gHideSelectedObjects; | ||
71 | 71 | ||
72 | F32 LLVOVolume::sLODFactor = 1.f; | 72 | F32 LLVOVolume::sLODFactor = 1.f; |
73 | F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop | 73 | F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop |
74 | F32 LLVOVolume::sLODComplexityDistanceBias = 0.0f;//Changing this to zero makes all prims LOD equally regardless of complexity | ||
75 | F32 LLVOVolume::sDistanceFactor = 1.0f; | 74 | F32 LLVOVolume::sDistanceFactor = 1.0f; |
76 | S32 LLVOVolume::sNumLODChanges = 0; | 75 | S32 LLVOVolume::sNumLODChanges = 0; |
77 | 76 | ||
@@ -79,17 +78,14 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re | |||
79 | : LLViewerObject(id, pcode, regionp), | 78 | : LLViewerObject(id, pcode, regionp), |
80 | mVolumeImpl(NULL) | 79 | mVolumeImpl(NULL) |
81 | { | 80 | { |
81 | mTexAnimMode = 0; | ||
82 | mRelativeXform.identity(); | 82 | mRelativeXform.identity(); |
83 | mRelativeXformInvTrans.identity(); | 83 | mRelativeXformInvTrans.identity(); |
84 | 84 | ||
85 | mLOD = MIN_LOD; | 85 | mLOD = MIN_LOD; |
86 | mInited = FALSE; | 86 | mInited = FALSE; |
87 | mAllTEsSame = FALSE; | ||
88 | mTextureAnimp = NULL; | 87 | mTextureAnimp = NULL; |
89 | mGlobalVolume = FALSE; | 88 | mGlobalVolume = FALSE; |
90 | |||
91 | mTextureAnimp = NULL; | ||
92 | mAllTEsSame = FALSE; | ||
93 | mVObjRadius = LLVector3(1,1,0.5f).magVec(); | 89 | mVObjRadius = LLVector3(1,1,0.5f).magVec(); |
94 | mNumFaces = 0; | 90 | mNumFaces = 0; |
95 | } | 91 | } |
@@ -142,12 +138,19 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, | |||
142 | mTextureAnimp->reset(); | 138 | mTextureAnimp->reset(); |
143 | } | 139 | } |
144 | } | 140 | } |
141 | mTexAnimMode = 0; | ||
145 | mTextureAnimp->unpackTAMessage(mesgsys, block_num); | 142 | mTextureAnimp->unpackTAMessage(mesgsys, block_num); |
146 | } | 143 | } |
147 | else | 144 | else |
148 | { | 145 | { |
149 | delete mTextureAnimp; | 146 | if (mTextureAnimp) |
150 | mTextureAnimp = NULL; | 147 | { |
148 | delete mTextureAnimp; | ||
149 | mTextureAnimp = NULL; | ||
150 | gPipeline.markTextured(mDrawable); | ||
151 | mFaceMappingChanged = TRUE; | ||
152 | mTexAnimMode = 0; | ||
153 | } | ||
151 | } | 154 | } |
152 | 155 | ||
153 | // Unpack volume data | 156 | // Unpack volume data |
@@ -193,8 +196,8 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, | |||
193 | // Well, crap, there's something bogus in the data that we're unpacking. | 196 | // Well, crap, there's something bogus in the data that we're unpacking. |
194 | dp->dumpBufferToLog(); | 197 | dp->dumpBufferToLog(); |
195 | llwarns << "Flushing cache files" << llendl; | 198 | llwarns << "Flushing cache files" << llendl; |
196 | char mask[LL_MAX_PATH]; | 199 | char mask[LL_MAX_PATH]; /* Flawfinder: ignore */ |
197 | sprintf(mask, "%s*.slc", gDirUtilp->getDirDelimiter().c_str()); | 200 | snprintf(mask, LL_MAX_PATH, "%s*.slc", gDirUtilp->getDirDelimiter().c_str()); /* Flawfinder: ignore */ |
198 | gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(),mask); | 201 | gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(),mask); |
199 | // llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl; | 202 | // llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl; |
200 | llwarns << "Bogus TE data in " << getID() << llendl; | 203 | llwarns << "Bogus TE data in " << getID() << llendl; |
@@ -219,12 +222,16 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, | |||
219 | mTextureAnimp->reset(); | 222 | mTextureAnimp->reset(); |
220 | } | 223 | } |
221 | } | 224 | } |
225 | mTexAnimMode = 0; | ||
222 | mTextureAnimp->unpackTAMessage(*dp); | 226 | mTextureAnimp->unpackTAMessage(*dp); |
223 | } | 227 | } |
224 | else | 228 | else if (mTextureAnimp) |
225 | { | 229 | { |
226 | delete mTextureAnimp; | 230 | delete mTextureAnimp; |
227 | mTextureAnimp = NULL; | 231 | mTextureAnimp = NULL; |
232 | gPipeline.markTextured(mDrawable); | ||
233 | mFaceMappingChanged = TRUE; | ||
234 | mTexAnimMode = 0; | ||
228 | } | 235 | } |
229 | } | 236 | } |
230 | else | 237 | else |
@@ -247,65 +254,142 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, | |||
247 | } | 254 | } |
248 | 255 | ||
249 | 256 | ||
250 | BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) | 257 | void LLVOVolume::animateTextures() |
251 | { | 258 | { |
252 | LLViewerObject::idleUpdate(agent, world, time); | 259 | F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; |
253 | 260 | S32 result; | |
254 | /////////////////////// | 261 | |
255 | // | 262 | if (result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot)) |
256 | // Do texture animation stuff | ||
257 | // | ||
258 | |||
259 | if (mTextureAnimp && gAnimateTextures) | ||
260 | { | 263 | { |
261 | F32 off_s, off_t, scale_s, scale_t, rot; | 264 | if (!mTexAnimMode) |
262 | S32 result; | 265 | { |
263 | if ((result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot))) | 266 | mFaceMappingChanged = TRUE; |
267 | gPipeline.markTextured(mDrawable); | ||
268 | } | ||
269 | mTexAnimMode = result | mTextureAnimp->mMode; | ||
270 | |||
271 | S32 start=0, end=mDrawable->getNumFaces()-1; | ||
272 | if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) | ||
273 | { | ||
274 | start = end = mTextureAnimp->mFace; | ||
275 | } | ||
276 | |||
277 | for (S32 i = start; i <= end; i++) | ||
264 | { | 278 | { |
265 | U8 has_bump = 0; | 279 | LLQuaternion quat; |
266 | if (mTextureAnimp->mFace <= -1) | 280 | LLVector3 scale(1,1,1); |
281 | |||
282 | LLFace* facep = mDrawable->getFace(i); | ||
283 | const LLTextureEntry* te = facep->getTextureEntry(); | ||
284 | LLMatrix4& tex_mat = facep->mTextureMatrix; | ||
285 | |||
286 | if (!te) | ||
287 | { | ||
288 | continue; | ||
289 | } | ||
290 | if (!(result & LLViewerTextureAnim::ROTATE)) | ||
291 | { | ||
292 | te->getRotation(&rot); | ||
293 | } | ||
294 | |||
267 | { | 295 | { |
268 | S32 face; | 296 | F32 axis = -1; |
269 | for (face = 0; face < getNumTEs(); face++) | 297 | F32 s,t; |
298 | te->getScale(&s,&t); | ||
299 | if (s < 0) | ||
270 | { | 300 | { |
271 | if (result & LLViewerTextureAnim::TRANSLATE) | 301 | axis = -axis; |
272 | { | ||
273 | setTEOffset(face, off_s, off_t); | ||
274 | } | ||
275 | if (result & LLViewerTextureAnim::SCALE) | ||
276 | { | ||
277 | setTEScale(face, scale_s, scale_t); | ||
278 | } | ||
279 | if (result & LLViewerTextureAnim::ROTATE) | ||
280 | { | ||
281 | setTERotation(face, rot); | ||
282 | } | ||
283 | has_bump |= getTE(face)->getBumpmap(); | ||
284 | } | 302 | } |
303 | if (t < 0) | ||
304 | { | ||
305 | axis = -axis; | ||
306 | } | ||
307 | quat.setQuat(rot, 0, 0, axis); | ||
285 | } | 308 | } |
286 | else if (mTextureAnimp->mFace < getNumTEs()) | 309 | |
310 | if (!(result & LLViewerTextureAnim::TRANSLATE)) | ||
287 | { | 311 | { |
288 | if (result & LLViewerTextureAnim::TRANSLATE) | 312 | te->getOffset(&off_s,&off_t); |
313 | } | ||
314 | |||
315 | LLVector3 trans(off_s+0.5f, off_t+0.5f, 0.f); | ||
316 | |||
317 | tex_mat.identity(); | ||
318 | tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); | ||
319 | tex_mat.rotate(quat); | ||
320 | |||
321 | if (!(result & LLViewerTextureAnim::SCALE)) | ||
322 | { | ||
323 | te->getScale(&scale_s, &scale_t); | ||
324 | } | ||
325 | |||
326 | { | ||
327 | scale.setVec(scale_s, scale_t, 1.f); | ||
328 | LLMatrix4 mat; | ||
329 | mat.initAll(scale, LLQuaternion(), LLVector3()); | ||
330 | tex_mat *= mat; | ||
331 | } | ||
332 | |||
333 | tex_mat.translate(trans); | ||
334 | } | ||
335 | } | ||
336 | else | ||
337 | { | ||
338 | if (mTexAnimMode && mTextureAnimp->mRate == 0) | ||
339 | { | ||
340 | U8 start, count; | ||
341 | |||
342 | if (mTextureAnimp->mFace == -1) | ||
343 | { | ||
344 | start = 0; | ||
345 | count = getNumTEs(); | ||
346 | } | ||
347 | else | ||
348 | { | ||
349 | start = (U8) mTextureAnimp->mFace; | ||
350 | count = 1; | ||
351 | } | ||
352 | |||
353 | for (S32 i = start; i < start + count; i++) | ||
354 | { | ||
355 | if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) | ||
289 | { | 356 | { |
290 | setTEOffset(mTextureAnimp->mFace, off_s, off_t); | 357 | setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT); |
291 | } | 358 | } |
292 | if (result & LLViewerTextureAnim::SCALE) | 359 | if (mTexAnimMode & LLViewerTextureAnim::SCALE) |
293 | { | 360 | { |
294 | setTEScale(mTextureAnimp->mFace, scale_s, scale_t); | 361 | setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT); |
295 | } | 362 | } |
296 | if (result & LLViewerTextureAnim::ROTATE) | 363 | if (mTexAnimMode & LLViewerTextureAnim::ROTATE) |
297 | { | 364 | { |
298 | setTERotation(mTextureAnimp->mFace, rot); | 365 | setTERotation(i, mTextureAnimp->mRot); |
299 | } | 366 | } |
300 | has_bump |= getTE(mTextureAnimp->mFace)->getBumpmap(); | ||
301 | } | ||
302 | // mFaceMappingChanged = TRUE; | ||
303 | if (mDrawable->isVisible()) | ||
304 | { | ||
305 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, TRUE); | ||
306 | } | 367 | } |
368 | |||
369 | gPipeline.markTextured(mDrawable); | ||
370 | mFaceMappingChanged = TRUE; | ||
371 | mTexAnimMode = 0; | ||
307 | } | 372 | } |
308 | } | 373 | } |
374 | } | ||
375 | BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) | ||
376 | { | ||
377 | LLViewerObject::idleUpdate(agent, world, time); | ||
378 | |||
379 | if (mDead || mDrawable.isNull()) | ||
380 | { | ||
381 | return TRUE; | ||
382 | } | ||
383 | |||
384 | /////////////////////// | ||
385 | // | ||
386 | // Do texture animation stuff | ||
387 | // | ||
388 | |||
389 | if (mTextureAnimp && gAnimateTextures) | ||
390 | { | ||
391 | animateTextures(); | ||
392 | } | ||
309 | 393 | ||
310 | // Dispatch to implementation | 394 | // Dispatch to implementation |
311 | if (mVolumeImpl) | 395 | if (mVolumeImpl) |
@@ -318,75 +402,45 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) | |||
318 | 402 | ||
319 | void LLVOVolume::updateTextures(LLAgent &agent) | 403 | void LLVOVolume::updateTextures(LLAgent &agent) |
320 | { | 404 | { |
321 | 405 | // LLFastTimer t(LLFastTimer::FTM_TEMP6); | |
406 | const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds | ||
407 | if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) | ||
408 | { | ||
409 | if (mDrawable->isVisible()) | ||
410 | { | ||
411 | updateTextures(); | ||
412 | } | ||
413 | } | ||
322 | } | 414 | } |
323 | 415 | ||
324 | //static | 416 | void LLVOVolume::updateTextures() |
325 | F32 LLVOVolume::getTextureVirtualSize(const LLFace* face) | ||
326 | { | 417 | { |
327 | //LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0]; | 418 | // Update the pixel area of all faces |
328 | //F32 pixel_area = 1.f/llmin(llmax(tdim.mV[0] * tdim.mV[1], 1.f), 10.f); | ||
329 | LLVector3 cross_vec = (face->mExtents[1] - face->mExtents[0]); | ||
330 | |||
331 | |||
332 | LLVector3 lookAt = (face->getPositionAgent()-gCamera->getOrigin()); | ||
333 | F32 dist = lookAt.normVec(); | ||
334 | 419 | ||
335 | F32 face_area; | 420 | if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) |
336 | |||
337 | if (face->isState(LLFace::GLOBAL)) | ||
338 | { | 421 | { |
339 | face_area = cross_vec.mV[0]*cross_vec.mV[1]*fabsf(lookAt.mV[2]) + | 422 | return; |
340 | cross_vec.mV[1]*cross_vec.mV[2]*fabsf(lookAt.mV[0]) + | ||
341 | cross_vec.mV[0]*cross_vec.mV[2]*fabsf(lookAt.mV[1]); | ||
342 | } | ||
343 | else | ||
344 | { | ||
345 | face_area = cross_vec.mV[0]*cross_vec.mV[1] + | ||
346 | cross_vec.mV[1]*cross_vec.mV[2] + | ||
347 | cross_vec.mV[0]*cross_vec.mV[2]; | ||
348 | } | 423 | } |
349 | 424 | ||
350 | if (face_area <= 0) | 425 | if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull()) // || !mDrawable->isVisible()) |
351 | { | 426 | { |
352 | return 0.f; | 427 | return; |
353 | } | 428 | } |
354 | 429 | ||
355 | F32 view = llmax(lookAt*gCamera->getAtAxis(), 0.5f); | 430 | mTextureUpdateTimer.reset(); |
356 | F32 dist_ramp = dist * view/face_area; | ||
357 | //ramp down distance for things closer than 16 m * lookAt | ||
358 | dist /= dist_ramp; | ||
359 | dist *= dist; | ||
360 | dist *= dist_ramp; | ||
361 | |||
362 | F32 dist_ratio = face_area / llmax(dist, 0.1f); | ||
363 | F32 pixel_area = dist_ratio*gCamera->getScreenPixelArea(); | ||
364 | 431 | ||
365 | return view*pixel_area; | 432 | F32 old_area = mPixelArea; |
366 | } | 433 | mPixelArea = 0.f; |
367 | |||
368 | void LLVOVolume::updateTextures(S32 lod) | ||
369 | { | ||
370 | // Update the image levels of all textures... | ||
371 | // First we do some quick checks. | ||
372 | 434 | ||
373 | // This doesn't take into account whether the object is in front | ||
374 | // or behind... | ||
375 | |||
376 | if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull() || !mDrawable->isVisible()) | ||
377 | { | ||
378 | return; | ||
379 | } | ||
380 | |||
381 | const S32 num_faces = mDrawable->getNumFaces(); | 435 | const S32 num_faces = mDrawable->getNumFaces(); |
382 | 436 | F32 min_vsize=999999999.f, max_vsize=0.f; | |
383 | for (S32 i = 0; i < num_faces; i++) | 437 | for (S32 i = 0; i < num_faces; i++) |
384 | { | 438 | { |
385 | const LLFace* face = mDrawable->getFace(i); | 439 | LLFace* face = mDrawable->getFace(i); |
386 | const LLTextureEntry *te = face->getTextureEntry(); | 440 | const LLTextureEntry *te = face->getTextureEntry(); |
387 | LLViewerImage *imagep = face->getTexture(); | 441 | LLViewerImage *imagep = face->getTexture(); |
388 | 442 | if (!imagep || !te || | |
389 | if (!imagep || !te) | 443 | face->mExtents[0] == face->mExtents[1]) |
390 | { | 444 | { |
391 | continue; | 445 | continue; |
392 | } | 446 | } |
@@ -395,25 +449,87 @@ void LLVOVolume::updateTextures(S32 lod) | |||
395 | 449 | ||
396 | if (isHUDAttachment()) | 450 | if (isHUDAttachment()) |
397 | { | 451 | { |
398 | vsize = (F32) (imagep->getWidth(0) * imagep->getHeight(0)); | 452 | F32 area = (F32) gCamera->getScreenPixelArea(); |
453 | vsize = area; | ||
399 | imagep->setBoostLevel(LLViewerImage::BOOST_HUD); | 454 | imagep->setBoostLevel(LLViewerImage::BOOST_HUD); |
455 | face->setPixelArea(area); // treat as full screen | ||
400 | } | 456 | } |
401 | else | 457 | else |
402 | { | 458 | { |
403 | vsize = getTextureVirtualSize(face); | 459 | vsize = getTextureVirtualSize(face); |
404 | } | 460 | } |
405 | 461 | ||
462 | mPixelArea = llmax(mPixelArea, face->getPixelArea()); | ||
463 | face->setVirtualSize(vsize); | ||
406 | imagep->addTextureStats(vsize); | 464 | imagep->addTextureStats(vsize); |
407 | 465 | if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) | |
408 | 466 | { | |
409 | U8 bump = te->getBumpmap(); | 467 | if (vsize < min_vsize) min_vsize = vsize; |
410 | if( te && bump) | 468 | if (vsize > max_vsize) max_vsize = vsize; |
469 | } | ||
470 | else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) | ||
411 | { | 471 | { |
412 | gBumpImageList.addTextureStats( bump, imagep->getID(), vsize, 1, 1); | 472 | F32 pri = imagep->getDecodePriority(); |
473 | if (pri < min_vsize) min_vsize = pri; | ||
474 | if (pri > max_vsize) max_vsize = pri; | ||
413 | } | 475 | } |
476 | else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) | ||
477 | { | ||
478 | F32 pri = mPixelArea; | ||
479 | if (pri < min_vsize) min_vsize = pri; | ||
480 | if (pri > max_vsize) max_vsize = pri; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) | ||
485 | { | ||
486 | setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); | ||
487 | } | ||
488 | else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) | ||
489 | { | ||
490 | setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); | ||
491 | } | ||
492 | else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) | ||
493 | { | ||
494 | setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); | ||
495 | } | ||
496 | |||
497 | if (mPixelArea == 0) | ||
498 | { //flexi phasing issues make this happen | ||
499 | mPixelArea = old_area; | ||
414 | } | 500 | } |
415 | } | 501 | } |
416 | 502 | ||
503 | F32 LLVOVolume::getTextureVirtualSize(LLFace* face) | ||
504 | { | ||
505 | //get area of circle around face | ||
506 | LLVector3 center = face->getPositionAgent(); | ||
507 | LLVector3 size = (face->mExtents[1] - face->mExtents[0]) * 0.5f; | ||
508 | |||
509 | F32 face_area = LLPipeline::calcPixelArea(center, size, *gCamera); | ||
510 | |||
511 | face->setPixelArea(face_area); | ||
512 | |||
513 | if (face_area <= 0) | ||
514 | { | ||
515 | return 0.f; | ||
516 | } | ||
517 | |||
518 | //get area of circle in texture space | ||
519 | LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0]; | ||
520 | F32 texel_area = (tdim * 0.5f).magVecSquared()*3.14159f; | ||
521 | if (texel_area <= 0) | ||
522 | { | ||
523 | // Probably animated, use default | ||
524 | texel_area = 1.f; | ||
525 | } | ||
526 | |||
527 | //apply texel area to face area to get accurate ratio | ||
528 | face_area /= llclamp(texel_area, 1.f/64.f, 16.f); | ||
529 | |||
530 | return face_area; | ||
531 | } | ||
532 | |||
417 | BOOL LLVOVolume::isActive() const | 533 | BOOL LLVOVolume::isActive() const |
418 | { | 534 | { |
419 | return !mStatic || mTextureAnimp || isAttachment() || (mVolumeImpl && mVolumeImpl->isActive()); | 535 | return !mStatic || mTextureAnimp || isAttachment() || (mVolumeImpl && mVolumeImpl->isActive()); |
@@ -455,7 +571,7 @@ void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped) | |||
455 | 571 | ||
456 | //since drawable transforms do not include scale, changing volume scale | 572 | //since drawable transforms do not include scale, changing volume scale |
457 | //requires an immediate rebuild of volume verts. | 573 | //requires an immediate rebuild of volume verts. |
458 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); | 574 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE); |
459 | } | 575 | } |
460 | } | 576 | } |
461 | 577 | ||
@@ -463,16 +579,7 @@ LLFace* LLVOVolume::addFace(S32 f) | |||
463 | { | 579 | { |
464 | const LLTextureEntry* te = getTE(f); | 580 | const LLTextureEntry* te = getTE(f); |
465 | LLViewerImage* imagep = getTEImage(f); | 581 | LLViewerImage* imagep = getTEImage(f); |
466 | LLDrawPool* poolp; | 582 | return mDrawable->addFace(te, imagep); |
467 | if (isHUDAttachment()) | ||
468 | { | ||
469 | poolp = gPipeline.getPool(LLDrawPool::POOL_HUD); | ||
470 | } | ||
471 | else | ||
472 | { | ||
473 | poolp = LLPipeline::getPoolFromTE(te, imagep); | ||
474 | } | ||
475 | return mDrawable->addFace(poolp, imagep); | ||
476 | } | 583 | } |
477 | 584 | ||
478 | LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) | 585 | LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) |
@@ -480,7 +587,7 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) | |||
480 | pipeline->allocDrawable(this); | 587 | pipeline->allocDrawable(this); |
481 | mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); | 588 | mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); |
482 | 589 | ||
483 | S32 max_tes_to_set = calcAllTEsSame() ? 1 : getNumTEs(); | 590 | S32 max_tes_to_set = getNumTEs(); |
484 | for (S32 i = 0; i < max_tes_to_set; i++) | 591 | for (S32 i = 0; i < max_tes_to_set; i++) |
485 | { | 592 | { |
486 | LLFace* face = addFace(i); | 593 | LLFace* face = addFace(i); |
@@ -537,10 +644,6 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail | |||
537 | } | 644 | } |
538 | mGlobalVolume = (mVolumeImpl && mVolumeImpl->isVolumeGlobal()); | 645 | mGlobalVolume = (mVolumeImpl && mVolumeImpl->isVolumeGlobal()); |
539 | 646 | ||
540 | //MSMSM Recompute LOD here in case the object was just created, | ||
541 | // its LOD might be incorrectly set to minumum detail... | ||
542 | calcLOD(); | ||
543 | |||
544 | if (LLPrimitive::setVolume(volume_params, mLOD, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) | 647 | if (LLPrimitive::setVolume(volume_params, mLOD, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) |
545 | { | 648 | { |
546 | mFaceMappingChanged = TRUE; | 649 | mFaceMappingChanged = TRUE; |
@@ -555,45 +658,12 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail | |||
555 | return FALSE; | 658 | return FALSE; |
556 | } | 659 | } |
557 | 660 | ||
558 | |||
559 | F32 LLVOVolume::computeLODProfilePathComplexityBias(){ | ||
560 | //compute a complexity cost from 0 to 1.0 where the 'simplest' prim has a cost of 0.0 | ||
561 | // and the 'heaviest' prim has a cost of 1.0 | ||
562 | // LLVolume* volume = getVolume(); | ||
563 | F32 complexity = 0.0f; | ||
564 | // const LLVolumeParams& params = volume->getParams(); | ||
565 | // U8 type = volume->getPathType(); | ||
566 | // U8 pcode = this->getPCode(); | ||
567 | // U8 proftype = volume->getProfileType(); | ||
568 | |||
569 | //if(params.getHollow()>0.0f){// || (proftype == 1) || (proftype == 0)){ | ||
570 | //If it is hollow, or a cube/pyramid(subdivided), the complexity is roughly doubled | ||
571 | // complexity+=0.5f; | ||
572 | //} | ||
573 | |||
574 | if(this->getVolume()->getProfile().mParams.getCurveType()==LL_PCODE_PROFILE_SQUARE && | ||
575 | this->getVolume()->getPath().mParams.getCurveType()==LL_PCODE_PATH_LINE) | ||
576 | { | ||
577 | //Object is a cube so bias it heavily since cubes are subdivided alot. | ||
578 | // this->setDebugText("CUBE"); | ||
579 | complexity += 1.0f; | ||
580 | } | ||
581 | |||
582 | // if(params.getTwist() != params.getTwistBegin()){ | ||
583 | //if there is twist.. the complexity is bumped | ||
584 | // complexity+=0.25f; | ||
585 | // } | ||
586 | // if(type != LL_PCODE_PATH_LINE)//If the path is not a line it is more complex | ||
587 | // complexity+=0.2f; | ||
588 | return complexity * sLODComplexityDistanceBias; | ||
589 | } | ||
590 | |||
591 | S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius) | 661 | S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius) |
592 | { | 662 | { |
593 | S32 cur_detail; | 663 | S32 cur_detail; |
594 | // We've got LOD in the profile, and in the twist. Use radius. | 664 | // We've got LOD in the profile, and in the twist. Use radius. |
595 | F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance; | 665 | F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance; |
596 | cur_detail = LLVolumeLODGroup::getDetailFromTan(tan_angle); | 666 | cur_detail = LLVolumeLODGroup::getDetailFromTan(llround(tan_angle, 0.01f)); |
597 | return cur_detail; | 667 | return cur_detail; |
598 | } | 668 | } |
599 | 669 | ||
@@ -603,62 +673,32 @@ BOOL LLVOVolume::calcLOD() | |||
603 | { | 673 | { |
604 | return FALSE; | 674 | return FALSE; |
605 | } | 675 | } |
676 | |||
606 | S32 cur_detail = 0; | 677 | S32 cur_detail = 0; |
607 | /*if (isHUDAttachment()) | 678 | |
679 | F32 radius = mVolumep->mLODScaleBias.scaledVec(getScale()).magVec(); | ||
680 | F32 distance = mDrawable->mDistanceWRTCamera; | ||
681 | distance *= sDistanceFactor; | ||
682 | |||
683 | F32 rampDist = LLVOVolume::sLODFactor * 2; | ||
684 | |||
685 | if (distance < rampDist) | ||
608 | { | 686 | { |
609 | cur_detail = LLVolumeLODGroup::NUM_LODS-1; // max detail | 687 | // Boost LOD when you're REALLY close |
688 | distance *= 1.0f/rampDist; | ||
689 | distance *= distance; | ||
690 | distance *= rampDist; | ||
610 | } | 691 | } |
611 | else*/ | 692 | |
612 | { | 693 | // DON'T Compensate for field of view changing on FOV zoom. |
613 | F32 radius = (mVolumep->mLODScaleBias.scaledVec(getScale())).magVec(); | 694 | distance *= 3.14159f/3.f; |
614 | F32 distance = mDrawable->mDistanceWRTCamera; | ||
615 | distance *= sDistanceFactor; | ||
616 | |||
617 | F32 rampDist = LLVOVolume::sLODFactor * 2; | ||
618 | |||
619 | if (distance < rampDist) | ||
620 | { | ||
621 | // Boost LOD when you're REALLY close | ||
622 | distance *= 1.0f/rampDist; | ||
623 | distance *= distance; | ||
624 | distance *= rampDist; | ||
625 | } | ||
626 | else | ||
627 | { | ||
628 | //Now adjust the computed distance by some factor based on the geometric complexity of the primitive | ||
629 | distance += computeLODProfilePathComplexityBias(); | ||
630 | } | ||
631 | // Compensate for field of view changing on FOV zoom. | ||
632 | distance *= gCamera->getView(); | ||
633 | |||
634 | cur_detail = computeLODDetail(distance, radius); | ||
635 | 695 | ||
636 | //update textures with what the real LOD is | 696 | cur_detail = computeLODDetail(llround(distance, 0.01f), |
637 | updateTextures(cur_detail); | 697 | llround(radius, 0.01f)); |
638 | |||
639 | if(cur_detail != mLOD) | ||
640 | { | ||
641 | // Here we test whether the LOD is increasing or decreasing to introduce a slop factor | ||
642 | if(cur_detail < mLOD) | ||
643 | { | ||
644 | // Viewer is moving away from the object | ||
645 | // so bias our LOD by adding a fixed amount to the distance. | ||
646 | // This will reduce the problem of LOD twitching when the | ||
647 | // user makes slight movements near the LOD transition threshhold. | ||
648 | F32 test_distance = distance - (distance*sLODSlopDistanceFactor/(1.0f+sLODFactor)); | ||
649 | if(test_distance < 0.0f) test_distance = 0.0f; | ||
650 | S32 potential_detail = computeLODDetail( test_distance, radius ); | ||
651 | if(potential_detail >= mLOD ) | ||
652 | { //The LOD has truly not changed | ||
653 | cur_detail = mLOD; | ||
654 | } | ||
655 | } | ||
656 | } | ||
657 | } | ||
658 | 698 | ||
659 | if (cur_detail != mLOD) | 699 | if (cur_detail != mLOD) |
660 | { | 700 | { |
661 | mAppAngle = (F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG; | 701 | mAppAngle = llround((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); |
662 | mLOD = cur_detail; | 702 | mLOD = cur_detail; |
663 | return TRUE; | 703 | return TRUE; |
664 | } | 704 | } |
@@ -676,17 +716,10 @@ BOOL LLVOVolume::updateLOD() | |||
676 | } | 716 | } |
677 | 717 | ||
678 | BOOL lod_changed = calcLOD(); | 718 | BOOL lod_changed = calcLOD(); |
679 | 719 | ||
680 | #if LLDEBUG_DISPLAY_LODS | ||
681 | //MS Enable this to display LOD numbers on objects | ||
682 | std::ostringstream msg; | ||
683 | msg << cur_detail;//((cur_detail<mLOD)?"-":cur_detail==mLOD?"=":"+") << (int)cur_detail << " , " << mDrawable->mDistanceWRTCamera << " , " << ((LLVOVolume::sLODFactor*mVObjRadius)/mDrawable->mDistanceWRTCamera); | ||
684 | this->setDebugText(msg.str()); | ||
685 | #endif | ||
686 | |||
687 | if (lod_changed) | 720 | if (lod_changed) |
688 | { | 721 | { |
689 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE); | 722 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); |
690 | mLODChanged = TRUE; | 723 | mLODChanged = TRUE; |
691 | } | 724 | } |
692 | 725 | ||
@@ -703,8 +736,8 @@ BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp) | |||
703 | 736 | ||
704 | if (!mDrawable->isRoot()) | 737 | if (!mDrawable->isRoot()) |
705 | { | 738 | { |
706 | // parent is dynamic, so I'll need to share its drawable, must rebuild to share drawables | 739 | // rebuild vertices in parent relative space |
707 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); | 740 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); |
708 | 741 | ||
709 | if (mDrawable->isActive() && !parentp->isActive()) | 742 | if (mDrawable->isActive() && !parentp->isActive()) |
710 | { | 743 | { |
@@ -723,7 +756,7 @@ void LLVOVolume::updateFaceFlags() | |||
723 | { | 756 | { |
724 | for (S32 i = 0; i < getVolume()->getNumFaces(); i++) | 757 | for (S32 i = 0; i < getVolume()->getNumFaces(); i++) |
725 | { | 758 | { |
726 | LLFace *face = mDrawable->getFace(i + mFaceIndexOffset); | 759 | LLFace *face = mDrawable->getFace(i); |
727 | BOOL fullbright = getTE(i)->getFullbright(); | 760 | BOOL fullbright = getTE(i)->getFullbright(); |
728 | face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); | 761 | face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); |
729 | 762 | ||
@@ -739,10 +772,17 @@ void LLVOVolume::updateFaceFlags() | |||
739 | { | 772 | { |
740 | face->setState(LLFace::HUD_RENDER); | 773 | face->setState(LLFace::HUD_RENDER); |
741 | } | 774 | } |
742 | if (getAllTEsSame()) | 775 | } |
743 | { | 776 | } |
744 | break; // only 1 face | 777 | |
745 | } | 778 | void LLVOVolume::setParent(LLViewerObject* parent) |
779 | { | ||
780 | LLViewerObject::setParent(parent); | ||
781 | if (mDrawable) | ||
782 | { | ||
783 | gPipeline.markMoved(mDrawable); | ||
784 | mVolumeChanged = TRUE; | ||
785 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); | ||
746 | } | 786 | } |
747 | } | 787 | } |
748 | 788 | ||
@@ -750,104 +790,87 @@ void LLVOVolume::updateFaceFlags() | |||
750 | void LLVOVolume::regenFaces() | 790 | void LLVOVolume::regenFaces() |
751 | { | 791 | { |
752 | // remove existing faces | 792 | // remove existing faces |
753 | // use mDrawable->getVOVolume() in case of shared drawables | 793 | BOOL count_changed = mNumFaces != getNumTEs(); |
754 | mDrawable->getVOVolume()->deleteFaces(this); | 794 | |
755 | mFaceIndexOffset = mDrawable->getNumFaces(); | 795 | if (count_changed) |
756 | // add new faces | 796 | { |
757 | mNumFaces = getAllTEsSame() ? 1 : getNumTEs(); | 797 | deleteFaces(); |
798 | // add new faces | ||
799 | mNumFaces = getNumTEs(); | ||
800 | } | ||
801 | |||
758 | for (S32 i = 0; i < mNumFaces; i++) | 802 | for (S32 i = 0; i < mNumFaces; i++) |
759 | { | 803 | { |
760 | LLFace* facep = addFace(i); | 804 | LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); |
761 | facep->setViewerObject(this); | ||
762 | facep->setTEOffset(i); | 805 | facep->setTEOffset(i); |
806 | facep->setTexture(getTEImage(i)); | ||
807 | facep->setViewerObject(this); | ||
808 | } | ||
809 | |||
810 | if (!count_changed) | ||
811 | { | ||
812 | updateFaceFlags(); | ||
763 | } | 813 | } |
764 | // Need to do this as texture entries may not correspond to faces any more! | ||
765 | mDrawable->updateTexture(); | ||
766 | gPipeline.markMaterialed(mDrawable); | ||
767 | } | 814 | } |
768 | 815 | ||
769 | BOOL LLVOVolume::genTriangles(BOOL force_global) | 816 | BOOL LLVOVolume::genBBoxes(BOOL force_global) |
770 | { | 817 | { |
771 | BOOL res = TRUE; | 818 | BOOL res = TRUE; |
772 | 819 | ||
773 | LLVector3 min,max; | 820 | LLVector3 min,max; |
774 | 821 | ||
775 | if (getAllTEsSame()) | 822 | BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION); |
823 | |||
824 | for (S32 i = 0; i < getVolume()->getNumFaces(); i++) | ||
776 | { | 825 | { |
777 | setupSingleFace(mFaceIndexOffset); | 826 | LLFace *face = mDrawable->getFace(i); |
778 | LLFace *face = mDrawable->getFace(mFaceIndexOffset); | 827 | res &= face->genVolumeBBoxes(*getVolume(), i, |
779 | S32 num_faces = getVolume()->getNumFaces(); | 828 | mRelativeXform, mRelativeXformInvTrans, |
780 | res = face->genVolumeTriangles(*getVolume(), 0, num_faces-1, | 829 | mGlobalVolume | force_global); |
781 | mRelativeXform, mRelativeXformInvTrans, | ||
782 | mGlobalVolume | force_global); | ||
783 | 830 | ||
784 | if (mDrawable->isState(LLDrawable::REBUILD_VOLUME)) | 831 | if (rebuild) |
785 | { | ||
786 | min = face->mExtents[0]; | ||
787 | max = face->mExtents[1]; | ||
788 | } | ||
789 | mWereAllTEsSame = TRUE; | ||
790 | } | ||
791 | else | ||
792 | { | ||
793 | for (S32 i = 0; i < getVolume()->getNumFaces(); i++) | ||
794 | { | 832 | { |
795 | LLFace *face = mDrawable->getFace(i + mFaceIndexOffset); | 833 | if (i == 0) |
796 | res &= face->genVolumeTriangles(*getVolume(), i, | ||
797 | mRelativeXform, mRelativeXformInvTrans, | ||
798 | mGlobalVolume | force_global); | ||
799 | |||
800 | if (mDrawable->isState(LLDrawable::REBUILD_VOLUME)) | ||
801 | { | 834 | { |
802 | if (i == 0) | 835 | min = face->mExtents[0]; |
803 | { | 836 | max = face->mExtents[1]; |
804 | min = face->mExtents[0]; | 837 | } |
805 | max = face->mExtents[1]; | 838 | else |
806 | } | 839 | { |
807 | else | 840 | for (U32 i = 0; i < 3; i++) |
808 | { | 841 | { |
809 | for (U32 i = 0; i < 3; i++) | 842 | if (face->mExtents[0].mV[i] < min.mV[i]) |
810 | { | 843 | { |
811 | if (face->mExtents[0].mV[i] < min.mV[i]) | 844 | min.mV[i] = face->mExtents[0].mV[i]; |
812 | { | 845 | } |
813 | min.mV[i] = face->mExtents[0].mV[i]; | 846 | if (face->mExtents[1].mV[i] > max.mV[i]) |
814 | } | 847 | { |
815 | if (face->mExtents[1].mV[i] > max.mV[i]) | 848 | max.mV[i] = face->mExtents[1].mV[i]; |
816 | { | ||
817 | max.mV[i] = face->mExtents[1].mV[i]; | ||
818 | } | ||
819 | } | 849 | } |
820 | } | 850 | } |
821 | } | 851 | } |
822 | } | 852 | } |
823 | mWereAllTEsSame = FALSE; | ||
824 | } | 853 | } |
825 | 854 | ||
826 | if (mDrawable->isState(LLDrawable::REBUILD_VOLUME)) | 855 | if (rebuild) |
827 | { | 856 | { |
828 | mDrawable->setSpatialExtents(min,max); | 857 | mDrawable->setSpatialExtents(min,max); |
829 | if (!isVolumeGlobal()) | 858 | mDrawable->setPositionGroup((min+max)*0.5f); |
830 | { | 859 | //bounding boxes changed, update texture priorities |
831 | mDrawable->setPositionGroup((min+max)*0.5f); | 860 | updateTextures(); |
832 | } | ||
833 | else | ||
834 | { | ||
835 | mDrawable->setPositionGroup(getPosition()); | ||
836 | } | ||
837 | |||
838 | updateRadius(); | ||
839 | mDrawable->updateBinRadius(); | ||
840 | mDrawable->movePartition(); | ||
841 | } | 861 | } |
842 | 862 | ||
863 | updateRadius(); | ||
864 | mDrawable->movePartition(); | ||
865 | |||
843 | return res; | 866 | return res; |
844 | } | 867 | } |
845 | 868 | ||
846 | void LLVOVolume::updateRelativeXform(BOOL global_volume) | 869 | void LLVOVolume::updateRelativeXform() |
847 | { | 870 | { |
848 | if (mVolumeImpl) | 871 | if (mVolumeImpl) |
849 | { | 872 | { |
850 | mVolumeImpl->updateRelativeXform(global_volume); | 873 | mVolumeImpl->updateRelativeXform(); |
851 | return; | 874 | return; |
852 | } | 875 | } |
853 | 876 | ||
@@ -873,12 +896,25 @@ void LLVOVolume::updateRelativeXform(BOOL global_volume) | |||
873 | LLVector4(y_axis, 0.f), | 896 | LLVector4(y_axis, 0.f), |
874 | LLVector4(z_axis, 0.f), | 897 | LLVector4(z_axis, 0.f), |
875 | LLVector4(delta_pos, 1.f)); | 898 | LLVector4(delta_pos, 1.f)); |
876 | 899 | ||
877 | x_axis.normVec(); | ||
878 | y_axis.normVec(); | ||
879 | z_axis.normVec(); | ||
880 | 900 | ||
881 | mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); | 901 | // compute inverse transpose for normals |
902 | // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); | ||
903 | // mRelativeXformInvTrans.invert(); | ||
904 | // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); | ||
905 | // grumble - invert is NOT a matrix invert, so we do it by hand: | ||
906 | |||
907 | LLMatrix3 rot_inverse = LLMatrix3(~delta_rot); | ||
908 | |||
909 | LLMatrix3 scale_inverse; | ||
910 | scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX], | ||
911 | LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY], | ||
912 | LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]); | ||
913 | |||
914 | |||
915 | mRelativeXformInvTrans = rot_inverse * scale_inverse; | ||
916 | |||
917 | mRelativeXformInvTrans.transpose(); | ||
882 | } | 918 | } |
883 | else | 919 | else |
884 | { | 920 | { |
@@ -905,34 +941,35 @@ void LLVOVolume::updateRelativeXform(BOOL global_volume) | |||
905 | LLVector4(z_axis, 0.f), | 941 | LLVector4(z_axis, 0.f), |
906 | LLVector4(pos, 1.f)); | 942 | LLVector4(pos, 1.f)); |
907 | 943 | ||
908 | x_axis.normVec(); | 944 | // compute inverse transpose for normals |
909 | y_axis.normVec(); | 945 | LLMatrix3 rot_inverse = LLMatrix3(~rot); |
910 | z_axis.normVec(); | 946 | |
911 | 947 | LLMatrix3 scale_inverse; | |
912 | mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); | 948 | scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX], |
949 | LLVector3(0.0, 1.0, 0.0) / scale.mV[VY], | ||
950 | LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]); | ||
951 | |||
952 | |||
953 | mRelativeXformInvTrans = rot_inverse * scale_inverse; | ||
954 | |||
955 | mRelativeXformInvTrans.transpose(); | ||
913 | } | 956 | } |
914 | } | 957 | } |
915 | 958 | ||
916 | BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) | 959 | BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) |
917 | { | 960 | { |
918 | LLFastTimer t(LLFastTimer::FTM_UPDATE_PRIMITIVES); | 961 | LLFastTimer t(LLFastTimer::FTM_UPDATE_PRIMITIVES); |
919 | 962 | ||
920 | if (mVolumeImpl != NULL) | 963 | if (mVolumeImpl != NULL) |
921 | { | 964 | { |
922 | LLFastTimer t(LLFastTimer::FTM_GEN_FLEX); | 965 | LLFastTimer t(LLFastTimer::FTM_GEN_FLEX); |
923 | BOOL res = mVolumeImpl->doUpdateGeometry(drawable); | 966 | BOOL res = mVolumeImpl->doUpdateGeometry(drawable); |
924 | updateFaceFlags(); | 967 | updateFaceFlags(); |
925 | if (res) | ||
926 | { | ||
927 | drawable->clearState(LLDrawable::REBUILD_GEOMETRY); | ||
928 | } | ||
929 | |||
930 | return res; | 968 | return res; |
931 | } | 969 | } |
932 | 970 | ||
933 | BOOL compiled = FALSE; | 971 | BOOL compiled = FALSE; |
934 | BOOL change_shared = FALSE; | 972 | |
935 | |||
936 | updateRelativeXform(); | 973 | updateRelativeXform(); |
937 | 974 | ||
938 | if (mDrawable.isNull()) // Not sure why this is happening, but it is... | 975 | if (mDrawable.isNull()) // Not sure why this is happening, but it is... |
@@ -940,28 +977,23 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) | |||
940 | return TRUE; // No update to complete | 977 | return TRUE; // No update to complete |
941 | } | 978 | } |
942 | 979 | ||
943 | calcAllTEsSame(); | 980 | if (mVolumeChanged || mFaceMappingChanged ) |
944 | |||
945 | if (mVolumeChanged || mFaceMappingChanged || change_shared) | ||
946 | { | 981 | { |
947 | compiled = TRUE; | 982 | compiled = TRUE; |
948 | mInited = TRUE; | 983 | mInited = TRUE; |
949 | 984 | ||
985 | if (mVolumeChanged) | ||
950 | { | 986 | { |
951 | LLFastTimer ftm(LLFastTimer::FTM_GEN_VOLUME); | 987 | LLFastTimer ftm(LLFastTimer::FTM_GEN_VOLUME); |
952 | LLVolumeParams volume_params = getVolume()->getParams(); | 988 | LLVolumeParams volume_params = getVolume()->getParams(); |
953 | setVolume(volume_params, 0); | 989 | setVolume(volume_params, 0); |
954 | } | 990 | drawable->setState(LLDrawable::REBUILD_VOLUME); |
955 | drawable->setState(LLDrawable::REBUILD_GEOMETRY); | ||
956 | if (mVolumeChanged || change_shared) | ||
957 | { | ||
958 | drawable->setState(LLDrawable::REBUILD_LIGHTING); | ||
959 | } | 991 | } |
960 | 992 | ||
961 | { | 993 | { |
962 | LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); | 994 | LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); |
963 | regenFaces(); | 995 | regenFaces(); |
964 | genTriangles(FALSE); | 996 | genBBoxes(FALSE); |
965 | } | 997 | } |
966 | } | 998 | } |
967 | else if (mLODChanged) | 999 | else if (mLODChanged) |
@@ -983,9 +1015,9 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) | |||
983 | if (new_lod != old_lod) | 1015 | if (new_lod != old_lod) |
984 | { | 1016 | { |
985 | compiled = TRUE; | 1017 | compiled = TRUE; |
986 | sNumLODChanges += (getAllTEsSame() ? 1 : getVolume()->getNumFaces()); | 1018 | sNumLODChanges += getVolume()->getNumFaces(); |
987 | 1019 | ||
988 | drawable->setState(LLDrawable::REBUILD_ALL); // for face->genVolumeTriangles() | 1020 | drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() |
989 | 1021 | ||
990 | { | 1022 | { |
991 | LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); | 1023 | LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); |
@@ -993,7 +1025,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) | |||
993 | { | 1025 | { |
994 | regenFaces(); | 1026 | regenFaces(); |
995 | } | 1027 | } |
996 | genTriangles(FALSE); | 1028 | genBBoxes(FALSE); |
997 | } | 1029 | } |
998 | } | 1030 | } |
999 | } | 1031 | } |
@@ -1003,7 +1035,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) | |||
1003 | compiled = TRUE; | 1035 | compiled = TRUE; |
1004 | // All it did was move or we changed the texture coordinate offset | 1036 | // All it did was move or we changed the texture coordinate offset |
1005 | LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); | 1037 | LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); |
1006 | genTriangles(FALSE); | 1038 | genBBoxes(FALSE); |
1007 | } | 1039 | } |
1008 | 1040 | ||
1009 | // Update face flags | 1041 | // Update face flags |
@@ -1018,11 +1050,16 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) | |||
1018 | mLODChanged = FALSE; | 1050 | mLODChanged = FALSE; |
1019 | mFaceMappingChanged = FALSE; | 1051 | mFaceMappingChanged = FALSE; |
1020 | 1052 | ||
1021 | drawable->clearState(LLDrawable::REBUILD_GEOMETRY); | ||
1022 | |||
1023 | return TRUE; | 1053 | return TRUE; |
1024 | } | 1054 | } |
1025 | 1055 | ||
1056 | void LLVOVolume::updateFaceSize(S32 idx) | ||
1057 | { | ||
1058 | const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); | ||
1059 | LLFace* facep = mDrawable->getFace(idx); | ||
1060 | facep->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); | ||
1061 | } | ||
1062 | |||
1026 | BOOL LLVOVolume::isRootEdit() const | 1063 | BOOL LLVOVolume::isRootEdit() const |
1027 | { | 1064 | { |
1028 | if (mParent && !((LLViewerObject*)mParent)->isAvatar()) | 1065 | if (mParent && !((LLViewerObject*)mParent)->isAvatar()) |
@@ -1034,178 +1071,121 @@ BOOL LLVOVolume::isRootEdit() const | |||
1034 | 1071 | ||
1035 | void LLVOVolume::setTEImage(const U8 te, LLViewerImage *imagep) | 1072 | void LLVOVolume::setTEImage(const U8 te, LLViewerImage *imagep) |
1036 | { | 1073 | { |
1037 | // llinfos << "SetTEImage:" << llendl; | ||
1038 | BOOL changed = (mTEImages[te] != imagep); | 1074 | BOOL changed = (mTEImages[te] != imagep); |
1039 | LLViewerObject::setTEImage(te, imagep); | 1075 | LLViewerObject::setTEImage(te, imagep); |
1040 | if (mDrawable.notNull()) | 1076 | if (changed) |
1041 | { | 1077 | { |
1042 | if (changed) | 1078 | gPipeline.markTextured(mDrawable); |
1043 | { | 1079 | mFaceMappingChanged = TRUE; |
1044 | calcAllTEsSame(); | ||
1045 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); | ||
1046 | mFaceMappingChanged = TRUE; | ||
1047 | } | ||
1048 | } | 1080 | } |
1049 | } | 1081 | } |
1050 | 1082 | ||
1051 | S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid) | 1083 | S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid) |
1052 | { | 1084 | { |
1053 | BOOL changed = (uuid != getTE(te)->getID() || (uuid == LLUUID::null)); | ||
1054 | |||
1055 | S32 res = LLViewerObject::setTETexture(te, uuid); | 1085 | S32 res = LLViewerObject::setTETexture(te, uuid); |
1056 | if (mDrawable.notNull()) | 1086 | if (res) |
1057 | { | 1087 | { |
1058 | if (changed) | 1088 | gPipeline.markTextured(mDrawable); |
1059 | { | 1089 | mFaceMappingChanged = TRUE; |
1060 | calcAllTEsSame(); | ||
1061 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); | ||
1062 | mFaceMappingChanged = TRUE; | ||
1063 | } | ||
1064 | } | 1090 | } |
1065 | return res; | 1091 | return res; |
1066 | } | 1092 | } |
1067 | 1093 | ||
1068 | S32 LLVOVolume::setTEColor(const U8 te, const LLColor4 &color) | 1094 | S32 LLVOVolume::setTEColor(const U8 te, const LLColor4 &color) |
1069 | { | 1095 | { |
1070 | BOOL changed = (color != getTE(te)->getColor()); | ||
1071 | S32 res = LLViewerObject::setTEColor(te, color); | 1096 | S32 res = LLViewerObject::setTEColor(te, color); |
1072 | if (mDrawable.notNull()) | 1097 | if (res) |
1073 | { | 1098 | { |
1074 | if (changed) | 1099 | gPipeline.markTextured(mDrawable); |
1075 | { | 1100 | mFaceMappingChanged = TRUE; |
1076 | calcAllTEsSame(); | ||
1077 | // mFaceMappingChanged = TRUE; | ||
1078 | } | ||
1079 | } | 1101 | } |
1080 | return res; | 1102 | return res; |
1081 | } | 1103 | } |
1082 | 1104 | ||
1083 | S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap) | 1105 | S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap) |
1084 | { | 1106 | { |
1085 | BOOL changed = (bumpmap != getTE(te)->getBumpmap()); | ||
1086 | S32 res = LLViewerObject::setTEBumpmap(te, bumpmap); | 1107 | S32 res = LLViewerObject::setTEBumpmap(te, bumpmap); |
1087 | if (mDrawable.notNull()) | 1108 | if (res) |
1088 | { | 1109 | { |
1089 | if (changed) | 1110 | gPipeline.markTextured(mDrawable); |
1090 | { | 1111 | mFaceMappingChanged = TRUE; |
1091 | calcAllTEsSame(); | ||
1092 | mFaceMappingChanged = TRUE; | ||
1093 | } | ||
1094 | } | 1112 | } |
1095 | return res; | 1113 | return res; |
1096 | } | 1114 | } |
1097 | 1115 | ||
1098 | S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen) | 1116 | S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen) |
1099 | { | 1117 | { |
1100 | BOOL changed = (texgen != getTE(te)->getTexGen()); | ||
1101 | S32 res = LLViewerObject::setTETexGen(te, texgen); | 1118 | S32 res = LLViewerObject::setTETexGen(te, texgen); |
1102 | if (mDrawable.notNull()) | 1119 | if (res) |
1103 | { | 1120 | { |
1104 | if (changed) | 1121 | gPipeline.markTextured(mDrawable); |
1105 | { | 1122 | mFaceMappingChanged = TRUE; |
1106 | calcAllTEsSame(); | ||
1107 | mFaceMappingChanged = TRUE; | ||
1108 | } | ||
1109 | } | 1123 | } |
1110 | return res; | 1124 | return res; |
1111 | } | 1125 | } |
1112 | 1126 | ||
1113 | S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny) | 1127 | S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny) |
1114 | { | 1128 | { |
1115 | BOOL changed = (shiny != getTE(te)->getShiny()); | ||
1116 | S32 res = LLViewerObject::setTEShiny(te, shiny); | 1129 | S32 res = LLViewerObject::setTEShiny(te, shiny); |
1117 | if (mDrawable.notNull()) | 1130 | if (res) |
1118 | { | 1131 | { |
1119 | if (changed) | 1132 | gPipeline.markTextured(mDrawable); |
1120 | { | 1133 | mFaceMappingChanged = TRUE; |
1121 | calcAllTEsSame(); | ||
1122 | mFaceMappingChanged = TRUE; | ||
1123 | } | ||
1124 | } | 1134 | } |
1125 | return res; | 1135 | return res; |
1126 | } | 1136 | } |
1127 | 1137 | ||
1128 | S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) | 1138 | S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) |
1129 | { | 1139 | { |
1130 | BOOL changed = (fullbright != getTE(te)->getFullbright()); | ||
1131 | S32 res = LLViewerObject::setTEFullbright(te, fullbright); | 1140 | S32 res = LLViewerObject::setTEFullbright(te, fullbright); |
1132 | if (mDrawable.notNull()) | 1141 | if (res) |
1133 | { | 1142 | { |
1134 | if (changed) | 1143 | gPipeline.markTextured(mDrawable); |
1135 | { | 1144 | mFaceMappingChanged = TRUE; |
1136 | calcAllTEsSame(); | ||
1137 | if (!mDrawable->isState(LLDrawable::REBUILD_VOLUME)) | ||
1138 | { | ||
1139 | updateFaceFlags(); | ||
1140 | } | ||
1141 | mFaceMappingChanged = TRUE; | ||
1142 | } | ||
1143 | } | 1145 | } |
1144 | return res; | 1146 | return res; |
1145 | } | 1147 | } |
1146 | 1148 | ||
1147 | S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags) | 1149 | S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags) |
1148 | { | 1150 | { |
1149 | bool changed = (media_flags != getTE(te)->getMediaFlags()); | ||
1150 | S32 res = LLViewerObject::setTEMediaFlags(te, media_flags); | 1151 | S32 res = LLViewerObject::setTEMediaFlags(te, media_flags); |
1151 | if (mDrawable.notNull()) | 1152 | if (res) |
1152 | { | 1153 | { |
1153 | if (changed) | 1154 | gPipeline.markTextured(mDrawable); |
1154 | { | 1155 | mFaceMappingChanged = TRUE; |
1155 | calcAllTEsSame(); | ||
1156 | mFaceMappingChanged = TRUE; | ||
1157 | } | ||
1158 | } | 1156 | } |
1159 | return res; | 1157 | return res; |
1160 | } | 1158 | } |
1161 | 1159 | ||
1162 | S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t) | 1160 | S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t) |
1163 | { | 1161 | { |
1164 | F32 olds,oldt; | ||
1165 | getTE(te)->getScale(&olds, &oldt); | ||
1166 | bool changed = (s != olds || t != oldt); | ||
1167 | S32 res = LLViewerObject::setTEScale(te, s, t); | 1162 | S32 res = LLViewerObject::setTEScale(te, s, t); |
1168 | if (mDrawable.notNull()) | 1163 | if (res) |
1169 | { | 1164 | { |
1170 | if (changed) | 1165 | gPipeline.markTextured(mDrawable); |
1171 | { | 1166 | mFaceMappingChanged = TRUE; |
1172 | calcAllTEsSame(); | ||
1173 | mFaceMappingChanged = TRUE; | ||
1174 | } | ||
1175 | } | 1167 | } |
1176 | return res; | 1168 | return res; |
1177 | } | 1169 | } |
1178 | 1170 | ||
1179 | S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s) | 1171 | S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s) |
1180 | { | 1172 | { |
1181 | F32 olds,oldt; | ||
1182 | getTE(te)->getScale(&olds, &oldt); | ||
1183 | bool changed = (s != olds); | ||
1184 | S32 res = LLViewerObject::setTEScaleS(te, s); | 1173 | S32 res = LLViewerObject::setTEScaleS(te, s); |
1185 | if (mDrawable.notNull()) | 1174 | if (res) |
1186 | { | 1175 | { |
1187 | if (changed) | 1176 | gPipeline.markTextured(mDrawable); |
1188 | { | 1177 | mFaceMappingChanged = TRUE; |
1189 | calcAllTEsSame(); | ||
1190 | mFaceMappingChanged = TRUE; | ||
1191 | } | ||
1192 | } | 1178 | } |
1193 | return res; | 1179 | return res; |
1194 | } | 1180 | } |
1195 | 1181 | ||
1196 | S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t) | 1182 | S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t) |
1197 | { | 1183 | { |
1198 | F32 olds,oldt; | ||
1199 | getTE(te)->getScale(&olds, &oldt); | ||
1200 | bool changed = (t != oldt); | ||
1201 | S32 res = LLViewerObject::setTEScaleT(te, t); | 1184 | S32 res = LLViewerObject::setTEScaleT(te, t); |
1202 | if (mDrawable.notNull()) | 1185 | if (res) |
1203 | { | 1186 | { |
1204 | if (changed) | 1187 | gPipeline.markTextured(mDrawable); |
1205 | { | 1188 | mFaceMappingChanged = TRUE; |
1206 | calcAllTEsSame(); | ||
1207 | mFaceMappingChanged = TRUE; | ||
1208 | } | ||
1209 | } | 1189 | } |
1210 | return res; | 1190 | return res; |
1211 | } | 1191 | } |
@@ -1214,137 +1194,11 @@ void LLVOVolume::updateTEData() | |||
1214 | { | 1194 | { |
1215 | if (mDrawable.notNull()) | 1195 | if (mDrawable.notNull()) |
1216 | { | 1196 | { |
1217 | calcAllTEsSame(); | ||
1218 | mFaceMappingChanged = TRUE; | 1197 | mFaceMappingChanged = TRUE; |
1219 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); | 1198 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE); |
1220 | } | 1199 | } |
1221 | } | 1200 | } |
1222 | 1201 | ||
1223 | BOOL LLVOVolume::calcAllTEsSame() | ||
1224 | { | ||
1225 | BOOL is_alpha = FALSE; | ||
1226 | BOOL was_same = mAllTEsSame; | ||
1227 | BOOL all_same = TRUE; | ||
1228 | S32 num_tes = getNumTEs(); | ||
1229 | |||
1230 | LLViewerImage *first_texturep = getTEImage(0); | ||
1231 | if (!first_texturep) | ||
1232 | { | ||
1233 | return FALSE; | ||
1234 | } | ||
1235 | |||
1236 | const LLTextureEntry *tep = getTE(0); | ||
1237 | if (!tep) | ||
1238 | { | ||
1239 | llwarns << "Volume with zero textures!" << llendl; | ||
1240 | return FALSE; | ||
1241 | } | ||
1242 | |||
1243 | if (tep->getColor().mV[3] != 1.f) | ||
1244 | { | ||
1245 | is_alpha = TRUE; | ||
1246 | } | ||
1247 | const LLColor4 first_color = tep->getColor(); | ||
1248 | const U8 first_bump = tep->getBumpShinyFullbright(); | ||
1249 | const U8 first_media_flags = tep->getMediaTexGen(); | ||
1250 | |||
1251 | if (first_texturep->getComponents() == 4) | ||
1252 | { | ||
1253 | is_alpha = TRUE; | ||
1254 | } | ||
1255 | |||
1256 | F32 s_scale, t_scale; | ||
1257 | tep->getScale(&s_scale, &t_scale); | ||
1258 | |||
1259 | for (S32 f = 1; f < num_tes; f++) | ||
1260 | { | ||
1261 | LLViewerImage *texturep = getTEImage(f); | ||
1262 | if (texturep != first_texturep) | ||
1263 | { | ||
1264 | all_same = FALSE; | ||
1265 | break; | ||
1266 | } | ||
1267 | |||
1268 | tep = getTE(f); | ||
1269 | |||
1270 | if( tep->getBumpShinyFullbright() != first_bump ) | ||
1271 | { | ||
1272 | all_same = FALSE; | ||
1273 | break; | ||
1274 | } | ||
1275 | |||
1276 | if (first_bump) | ||
1277 | { | ||
1278 | F32 cur_s, cur_t; | ||
1279 | tep->getScale(&cur_s, &cur_t); | ||
1280 | if ((cur_s != s_scale) || (cur_t != t_scale)) | ||
1281 | { | ||
1282 | all_same = FALSE; | ||
1283 | break; | ||
1284 | } | ||
1285 | } | ||
1286 | |||
1287 | if ((texturep->getComponents() == 4) || (tep->getColor().mV[3] != 1.f)) | ||
1288 | { | ||
1289 | if (!is_alpha) | ||
1290 | { | ||
1291 | all_same = FALSE; | ||
1292 | break; | ||
1293 | } | ||
1294 | } | ||
1295 | else if (is_alpha) | ||
1296 | { | ||
1297 | all_same = FALSE; | ||
1298 | break; | ||
1299 | } | ||
1300 | |||
1301 | if (tep->getColor() != first_color) | ||
1302 | { | ||
1303 | all_same = FALSE; | ||
1304 | break; | ||
1305 | } | ||
1306 | |||
1307 | if (tep->getMediaTexGen() != first_media_flags) | ||
1308 | { | ||
1309 | all_same = FALSE; | ||
1310 | break; | ||
1311 | } | ||
1312 | } | ||
1313 | |||
1314 | mAllTEsSame = all_same; | ||
1315 | if (was_same != all_same) | ||
1316 | { | ||
1317 | gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); // rebuild NOW | ||
1318 | mFaceMappingChanged = TRUE; | ||
1319 | } | ||
1320 | return mAllTEsSame; | ||
1321 | } | ||
1322 | |||
1323 | void LLVOVolume::setupSingleFace(S32 face_offset) | ||
1324 | { | ||
1325 | S32 num_indices = 0; | ||
1326 | S32 num_vertices = 0; | ||
1327 | |||
1328 | if (mDrawable.isNull()) | ||
1329 | { | ||
1330 | llerrs << "setupSingleFace called with NULL mDrawable" << llendl; | ||
1331 | } | ||
1332 | if (face_offset >= mDrawable->getNumFaces()) | ||
1333 | { | ||
1334 | llerrs << "setupSingleFace called with invalid face_offset" << llendl; | ||
1335 | } | ||
1336 | |||
1337 | const S32 num_faces = getVolume()->getNumFaces(); | ||
1338 | for (S32 i = 0; i < num_faces; i++) | ||
1339 | { | ||
1340 | const LLVolumeFace &vf = getVolume()->getVolumeFace(i); | ||
1341 | num_vertices += vf.mVertices.size(); | ||
1342 | num_indices += vf.mIndices.size(); | ||
1343 | } | ||
1344 | LLFace *facep = mDrawable->getFace(face_offset); | ||
1345 | facep->setSize(num_vertices, num_indices); | ||
1346 | } | ||
1347 | |||
1348 | //---------------------------------------------------------------------------- | 1202 | //---------------------------------------------------------------------------- |
1349 | 1203 | ||
1350 | void LLVOVolume::setIsLight(BOOL is_light) | 1204 | void LLVOVolume::setIsLight(BOOL is_light) |
@@ -1388,6 +1242,8 @@ void LLVOVolume::setLightColor(const LLColor3& color) | |||
1388 | { | 1242 | { |
1389 | param_block->setColor(LLColor4(color, param_block->getColor().mV[3])); | 1243 | param_block->setColor(LLColor4(color, param_block->getColor().mV[3])); |
1390 | parameterChanged(LLNetworkData::PARAMS_LIGHT, true); | 1244 | parameterChanged(LLNetworkData::PARAMS_LIGHT, true); |
1245 | gPipeline.markTextured(mDrawable); | ||
1246 | mFaceMappingChanged = TRUE; | ||
1391 | } | 1247 | } |
1392 | } | 1248 | } |
1393 | } | 1249 | } |
@@ -1551,7 +1407,7 @@ F32 LLVOVolume::calcLightAtPoint(const LLVector3& pos, const LLVector3& norm, LL | |||
1551 | LLVector3 light_dir = light_pos - pos; | 1407 | LLVector3 light_dir = light_pos - pos; |
1552 | F32 dist = light_dir.normVec(); | 1408 | F32 dist = light_dir.normVec(); |
1553 | F32 dp = norm * light_dir; | 1409 | F32 dp = norm * light_dir; |
1554 | if ((gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)) | 1410 | if ((gPipeline.getLightingDetail() > 2)) |
1555 | { | 1411 | { |
1556 | if (dp <= 0) | 1412 | if (dp <= 0) |
1557 | { | 1413 | { |
@@ -1590,7 +1446,7 @@ F32 LLVOVolume::calcLightAtPoint(const LLVector3& pos, const LLVector3& norm, LL | |||
1590 | BOOL LLVOVolume::updateLighting(BOOL do_lighting) | 1446 | BOOL LLVOVolume::updateLighting(BOOL do_lighting) |
1591 | { | 1447 | { |
1592 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | 1448 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); |
1593 | 1449 | #if 0 | |
1594 | if (mDrawable->isStatic()) | 1450 | if (mDrawable->isStatic()) |
1595 | { | 1451 | { |
1596 | do_lighting = FALSE; | 1452 | do_lighting = FALSE; |
@@ -1600,31 +1456,31 @@ BOOL LLVOVolume::updateLighting(BOOL do_lighting) | |||
1600 | const LLMatrix3& mat_normal = LLMatrix3(mDrawable->getWorldRotation()); | 1456 | const LLMatrix3& mat_normal = LLMatrix3(mDrawable->getWorldRotation()); |
1601 | 1457 | ||
1602 | LLVolume* volume = getVolume(); | 1458 | LLVolume* volume = getVolume(); |
1603 | if (getAllTEsSame()) | 1459 | |
1460 | for (S32 i = 0; i < volume->getNumFaces(); i++) | ||
1604 | { | 1461 | { |
1605 | LLFace *face = mDrawable->getFace(mFaceIndexOffset); | 1462 | LLFace *face = mDrawable->getFace(i); |
1606 | S32 num_faces = volume->getNumFaces(); | ||
1607 | if (face && face->getGeomCount()) | 1463 | if (face && face->getGeomCount()) |
1608 | { | 1464 | { |
1609 | face->genLighting(volume, mDrawable, 0, num_faces-1, mat_vert, mat_normal, do_lighting); | 1465 | face->genLighting(volume, mDrawable, i, i, mat_vert, mat_normal, do_lighting); |
1610 | } | ||
1611 | } | ||
1612 | else | ||
1613 | { | ||
1614 | for (S32 i = 0; i < volume->getNumFaces(); i++) | ||
1615 | { | ||
1616 | LLFace *face = mDrawable->getFace(i + mFaceIndexOffset); | ||
1617 | if (face && face->getGeomCount()) | ||
1618 | { | ||
1619 | face->genLighting(volume, mDrawable, i, i, mat_vert, mat_normal, do_lighting); | ||
1620 | } | ||
1621 | } | 1466 | } |
1622 | } | 1467 | } |
1468 | #endif | ||
1623 | return TRUE; | 1469 | return TRUE; |
1624 | } | 1470 | } |
1625 | 1471 | ||
1626 | //---------------------------------------------------------------------------- | 1472 | //---------------------------------------------------------------------------- |
1627 | 1473 | ||
1474 | U32 LLVOVolume::getVolumeInterfaceID() const | ||
1475 | { | ||
1476 | if (mVolumeImpl) | ||
1477 | { | ||
1478 | return mVolumeImpl->getID(); | ||
1479 | } | ||
1480 | |||
1481 | return 0; | ||
1482 | } | ||
1483 | |||
1628 | BOOL LLVOVolume::isFlexible() const | 1484 | BOOL LLVOVolume::isFlexible() const |
1629 | { | 1485 | { |
1630 | if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) | 1486 | if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) |
@@ -1715,16 +1571,18 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p | |||
1715 | LLVector3 view_vector; | 1571 | LLVector3 view_vector; |
1716 | view_vector = view_point; | 1572 | view_vector = view_point; |
1717 | 1573 | ||
1574 | //transform view vector into volume space | ||
1575 | view_vector -= getRenderPosition(); | ||
1576 | mDrawable->mDistanceWRTCamera = view_vector.magVec(); | ||
1577 | LLQuaternion worldRot = getRenderRotation(); | ||
1578 | view_vector = view_vector * ~worldRot; | ||
1718 | if (!isVolumeGlobal()) | 1579 | if (!isVolumeGlobal()) |
1719 | { //transform view vector into volume space | 1580 | { |
1720 | view_vector -= getRenderPosition(); | ||
1721 | LLQuaternion worldRot = getRenderRotation(); | ||
1722 | view_vector = view_vector * ~worldRot; | ||
1723 | LLVector3 objScale = getScale(); | 1581 | LLVector3 objScale = getScale(); |
1724 | LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); | 1582 | LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); |
1725 | view_vector.scaleVec(invObjScale); | 1583 | view_vector.scaleVec(invObjScale); |
1726 | } | 1584 | } |
1727 | 1585 | ||
1728 | updateRelativeXform(); | 1586 | updateRelativeXform(); |
1729 | volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, nodep->mSilhouetteSegments, view_vector, mRelativeXform, mRelativeXformInvTrans); | 1587 | volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, nodep->mSilhouetteSegments, view_vector, mRelativeXform, mRelativeXformInvTrans); |
1730 | 1588 | ||
@@ -1732,33 +1590,15 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p | |||
1732 | } | 1590 | } |
1733 | } | 1591 | } |
1734 | 1592 | ||
1735 | void LLVOVolume::deleteFaces(LLVOVolume* childp) | 1593 | void LLVOVolume::deleteFaces() |
1736 | { | 1594 | { |
1737 | S32 face_count = childp->mNumFaces; | 1595 | S32 face_count = mNumFaces; |
1738 | S32 start_index = childp->mFaceIndexOffset; | ||
1739 | if (mDrawable.notNull()) | 1596 | if (mDrawable.notNull()) |
1740 | { | 1597 | { |
1741 | mDrawable->deleteFaces(start_index, face_count); | 1598 | mDrawable->deleteFaces(0, face_count); |
1742 | } | ||
1743 | if (mFaceIndexOffset > start_index) | ||
1744 | { | ||
1745 | mFaceIndexOffset -= face_count; | ||
1746 | } | 1599 | } |
1747 | 1600 | ||
1748 | for (U32 i = 0; i < mChildList.size(); i++) | 1601 | mNumFaces = 0; |
1749 | { | ||
1750 | LLViewerObject* siblingp = mChildList[i]; | ||
1751 | if (siblingp != childp) | ||
1752 | { | ||
1753 | if (siblingp->getPCode() == LL_PCODE_VOLUME && | ||
1754 | ((LLVOVolume*)siblingp)->mFaceIndexOffset > start_index) | ||
1755 | { | ||
1756 | ((LLVOVolume*)siblingp)->mFaceIndexOffset -= face_count; | ||
1757 | } | ||
1758 | } | ||
1759 | } | ||
1760 | childp->mFaceIndexOffset = 0; | ||
1761 | childp->mNumFaces = 0; | ||
1762 | } | 1602 | } |
1763 | 1603 | ||
1764 | void LLVOVolume::updateRadius() | 1604 | void LLVOVolume::updateRadius() |
@@ -1806,7 +1646,8 @@ const LLMatrix4 LLVOVolume::getRenderMatrix() const | |||
1806 | 1646 | ||
1807 | 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) | 1647 | 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) |
1808 | { | 1648 | { |
1809 | LLPointer<LLImageTGA> tga_image = new LLImageTGA; | 1649 | #if 0 |
1650 | LLImageTGA tga_image; | ||
1810 | 1651 | ||
1811 | if (mDrawable.isNull()) | 1652 | if (mDrawable.isNull()) |
1812 | { | 1653 | { |
@@ -1878,8 +1719,8 @@ void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file | |||
1878 | my_texture = texture_index++; | 1719 | my_texture = texture_index++; |
1879 | 1720 | ||
1880 | //...and export texture as image file | 1721 | //...and export texture as image file |
1881 | char filename[MAX_PATH]; | 1722 | char filename[MAX_PATH]; /* Flawfinder: ignore */ |
1882 | sprintf(filename, "%s\\%s_material_tex_%d.tga", path.c_str(), file_base.c_str(), my_texture); | 1723 | snprintf(filename, MAX_PATH, "%s\\%s_material_tex_%d.tga", path.c_str(), file_base.c_str(), my_texture); /* Flawfinder: ignore */ |
1883 | 1724 | ||
1884 | LLViewerImage* imagep = facep->getTexture(); | 1725 | LLViewerImage* imagep = facep->getTexture(); |
1885 | if (imagep->getTexName() == 0) | 1726 | if (imagep->getTexName() == 0) |
@@ -1887,10 +1728,10 @@ void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file | |||
1887 | llinfos << "No image data available for " << filename << llendl; | 1728 | llinfos << "No image data available for " << filename << llendl; |
1888 | continue; | 1729 | continue; |
1889 | } | 1730 | } |
1890 | LLPointer<LLImageRaw> raw_image = new LLImageRaw; | 1731 | LLImageRaw raw_image; |
1891 | imagep->readBackRaw(-1, raw_image); | 1732 | imagep->readBackRaw(-1, raw_image); |
1892 | BOOL success = tga_image->encode(raw_image); | 1733 | BOOL success = tga_image.encode(raw_image); |
1893 | success = tga_image->save(filename); | 1734 | success = tga_image.save(filename); |
1894 | } | 1735 | } |
1895 | 1736 | ||
1896 | material_info = new LLMaterialExportInfo(my_material, my_texture, face_color); | 1737 | material_info = new LLMaterialExportInfo(my_material, my_texture, face_color); |
@@ -1931,6 +1772,7 @@ void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file | |||
1931 | { | 1772 | { |
1932 | ((LLVOVolume*)(LLViewerObject*)mChildList[i])->writeCAL3D(fp, path, file_base, joint_num, final_pos, final_rot, material_index, texture_index, material_map); | 1773 | ((LLVOVolume*)(LLViewerObject*)mChildList[i])->writeCAL3D(fp, path, file_base, joint_num, final_pos, final_rot, material_index, texture_index, material_map); |
1933 | } | 1774 | } |
1775 | #endif | ||
1934 | } | 1776 | } |
1935 | 1777 | ||
1936 | //static | 1778 | //static |
@@ -1961,10 +1803,67 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u | |||
1961 | } | 1803 | } |
1962 | } | 1804 | } |
1963 | 1805 | ||
1806 | void LLVOVolume::setSelected(BOOL sel) | ||
1807 | { | ||
1808 | LLViewerObject::setSelected(sel); | ||
1809 | if (mDrawable.notNull()) | ||
1810 | { | ||
1811 | mDrawable->movePartition(); | ||
1812 | } | ||
1813 | } | ||
1814 | |||
1964 | void LLVOVolume::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax) | 1815 | void LLVOVolume::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax) |
1965 | { | 1816 | { |
1966 | } | 1817 | } |
1967 | 1818 | ||
1819 | F32 LLVOVolume::getBinRadius() | ||
1820 | { | ||
1821 | F32 radius; | ||
1822 | |||
1823 | const LLVector3* ext = mDrawable->getSpatialExtents(); | ||
1824 | |||
1825 | BOOL shrink_wrap = mDrawable->isAnimating(); | ||
1826 | BOOL alpha_wrap = FALSE; | ||
1827 | |||
1828 | if (!isHUDAttachment()) | ||
1829 | { | ||
1830 | for (S32 i = 0; i < mDrawable->getNumFaces(); i++) | ||
1831 | { | ||
1832 | if (mDrawable->getFace(i)->getPoolType() == LLDrawPool::POOL_ALPHA) | ||
1833 | { | ||
1834 | alpha_wrap = TRUE; | ||
1835 | break; | ||
1836 | } | ||
1837 | } | ||
1838 | } | ||
1839 | else | ||
1840 | { | ||
1841 | shrink_wrap = FALSE; | ||
1842 | } | ||
1843 | |||
1844 | if (alpha_wrap) | ||
1845 | { | ||
1846 | LLVector3 bounds = getScale(); | ||
1847 | radius = llmin(bounds.mV[1], bounds.mV[2]); | ||
1848 | radius = llmin(radius, bounds.mV[0]); | ||
1849 | radius *= 0.5f; | ||
1850 | } | ||
1851 | else if (shrink_wrap) | ||
1852 | { | ||
1853 | radius = (ext[1]-ext[0]).magVec()*0.5f; | ||
1854 | } | ||
1855 | else if (mDrawable->isStatic()) | ||
1856 | { | ||
1857 | radius = 32.f; | ||
1858 | } | ||
1859 | else | ||
1860 | { | ||
1861 | radius = 8.f; | ||
1862 | } | ||
1863 | |||
1864 | return llclamp(radius, 0.5f, 256.f); | ||
1865 | } | ||
1866 | |||
1968 | const LLVector3 LLVOVolume::getPivotPositionAgent() const | 1867 | const LLVector3 LLVOVolume::getPivotPositionAgent() const |
1969 | { | 1868 | { |
1970 | if (mVolumeImpl) | 1869 | if (mVolumeImpl) |
@@ -1980,6 +1879,8 @@ void LLVOVolume::onShift(const LLVector3 &shift_vector) | |||
1980 | { | 1879 | { |
1981 | mVolumeImpl->onShift(shift_vector); | 1880 | mVolumeImpl->onShift(shift_vector); |
1982 | } | 1881 | } |
1882 | |||
1883 | updateRelativeXform(); | ||
1983 | } | 1884 | } |
1984 | 1885 | ||
1985 | const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const | 1886 | const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const |
@@ -1993,14 +1894,9 @@ const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const | |||
1993 | 1894 | ||
1994 | LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const | 1895 | LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const |
1995 | { | 1896 | { |
1996 | if (isVolumeGlobal()) | ||
1997 | { | ||
1998 | return pos; | ||
1999 | } | ||
2000 | |||
2001 | LLVector3 ret = pos - getRenderPosition(); | 1897 | LLVector3 ret = pos - getRenderPosition(); |
2002 | ret = ret * ~getRenderRotation(); | 1898 | ret = ret * ~getRenderRotation(); |
2003 | LLVector3 objScale = getScale(); | 1899 | LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); |
2004 | LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); | 1900 | LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); |
2005 | ret.scaleVec(invObjScale); | 1901 | ret.scaleVec(invObjScale); |
2006 | 1902 | ||
@@ -2009,7 +1905,7 @@ LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const | |||
2009 | 1905 | ||
2010 | LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const | 1906 | LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const |
2011 | { | 1907 | { |
2012 | return isVolumeGlobal() ? dir : (dir * ~getRenderRotation()); | 1908 | return dir * ~getRenderRotation(); |
2013 | } | 1909 | } |
2014 | 1910 | ||
2015 | LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const | 1911 | LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const |
@@ -2024,6 +1920,9 @@ LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const | |||
2024 | 1920 | ||
2025 | BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const | 1921 | BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const |
2026 | { | 1922 | { |
1923 | return FALSE; | ||
1924 | |||
1925 | #if 0 // needs to be rewritten to use face extents instead of volume bounds | ||
2027 | LLVolume* volume = getVolume(); | 1926 | LLVolume* volume = getVolume(); |
2028 | BOOL ret = FALSE; | 1927 | BOOL ret = FALSE; |
2029 | if (volume) | 1928 | if (volume) |
@@ -2043,4 +1942,561 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) co | |||
2043 | } | 1942 | } |
2044 | } | 1943 | } |
2045 | return ret; | 1944 | return ret; |
1945 | #endif | ||
1946 | } | ||
1947 | |||
1948 | U32 LLVOVolume::getPartitionType() const | ||
1949 | { | ||
1950 | if (isHUDAttachment()) | ||
1951 | { | ||
1952 | return LLPipeline::PARTITION_HUD; | ||
1953 | } | ||
1954 | |||
1955 | return LLPipeline::PARTITION_VOLUME; | ||
1956 | } | ||
1957 | |||
1958 | LLVolumePartition::LLVolumePartition() | ||
1959 | : LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, FALSE) | ||
1960 | { | ||
1961 | mLODPeriod = 16; | ||
1962 | mDepthMask = FALSE; | ||
1963 | mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; | ||
1964 | mPartitionType = LLPipeline::PARTITION_VOLUME; | ||
1965 | mSlopRatio = 0.25f; | ||
1966 | mBufferUsage = GL_DYNAMIC_DRAW_ARB; | ||
1967 | mImageEnabled = TRUE; | ||
1968 | } | ||
1969 | |||
1970 | LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) | ||
1971 | : LLSpatialBridge(drawablep, LLVOVolume::VERTEX_DATA_MASK) | ||
1972 | { | ||
1973 | mDepthMask = FALSE; | ||
1974 | mLODPeriod = 16; | ||
1975 | mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; | ||
1976 | mPartitionType = LLPipeline::PARTITION_BRIDGE; | ||
1977 | |||
1978 | mBufferUsage = GL_DYNAMIC_DRAW_ARB; | ||
1979 | |||
1980 | mSlopRatio = 0.25f; | ||
1981 | } | ||
1982 | |||
1983 | void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) | ||
1984 | { | ||
1985 | LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); | ||
1986 | |||
1987 | if (facep->getViewerObject()->isSelected() && gHideSelectedObjects) | ||
1988 | { | ||
1989 | return; | ||
1990 | } | ||
1991 | |||
1992 | //add face to drawmap | ||
1993 | std::vector<LLDrawInfo*>& draw_vec = group->mDrawMap[type]; | ||
1994 | |||
1995 | S32 idx = draw_vec.size()-1; | ||
1996 | |||
1997 | |||
1998 | BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT || | ||
1999 | type == LLRenderPass::PASS_ALPHA) ? facep->isState(LLFace::FULLBRIGHT) : FALSE; | ||
2000 | |||
2001 | const LLMatrix4* tex_mat = NULL; | ||
2002 | if (type != LLRenderPass::PASS_SHINY && facep->isState(LLFace::TEXTURE_ANIM)) | ||
2003 | { | ||
2004 | tex_mat = &(facep->mTextureMatrix); | ||
2005 | } | ||
2006 | |||
2007 | U8 bump = (type == LLRenderPass::PASS_BUMP ? facep->getTextureEntry()->getBumpmap() : 0); | ||
2008 | |||
2009 | //LLViewerImage* tex = facep->mAppAngle < FORCE_SIMPLE_RENDER_ANGLE ? NULL : facep->getTexture(); | ||
2010 | LLViewerImage* tex = facep->getTexture(); | ||
2011 | |||
2012 | if (type == LLRenderPass::PASS_GLOW) | ||
2013 | { | ||
2014 | U32 start = facep->getGeomIndex(); | ||
2015 | U32 end = start + facep->getGeomCount()-1; | ||
2016 | U32 offset = facep->getIndicesStart(); | ||
2017 | U32 count = facep->getIndicesCount(); | ||
2018 | LLDrawInfo* draw_info = new LLDrawInfo(start,end,count,offset,tex, | ||
2019 | facep->mVertexBuffer, fullbright, bump); | ||
2020 | draw_info->mVSize = facep->getVirtualSize(); | ||
2021 | draw_vec.push_back(draw_info); | ||
2022 | LLVOVolume* volume = (LLVOVolume*) facep->getViewerObject(); | ||
2023 | BOOL is_light = volume->mDrawable->isLight(); | ||
2024 | |||
2025 | // U8 alpha = is_light ? 196 : 160; | ||
2026 | LLColor3 col = is_light ? volume->getLightColor() : LLColor3(0,0,0); | ||
2027 | LLColor4 col2 = facep->getRenderColor(); | ||
2028 | draw_info->mGlowColor.setVec((U8) (col.mV[0]*col2.mV[0]*255), | ||
2029 | (U8) (col.mV[1]*col2.mV[1]*255), | ||
2030 | (U8) (col.mV[2]*col2.mV[2]*255), | ||
2031 | 196); | ||
2032 | draw_info->mTextureMatrix = tex_mat; | ||
2033 | validate_draw_info(*draw_info); | ||
2034 | } | ||
2035 | else if (idx >= 0 && | ||
2036 | draw_vec[idx]->mVertexBuffer == facep->mVertexBuffer && | ||
2037 | draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && | ||
2038 | draw_vec[idx]->mTexture == tex && | ||
2039 | #if LL_DARWIN | ||
2040 | draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && | ||
2041 | draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && | ||
2042 | #endif | ||
2043 | draw_vec[idx]->mFullbright == fullbright && | ||
2044 | draw_vec[idx]->mBump == bump && | ||
2045 | draw_vec[idx]->mTextureMatrix == tex_mat) | ||
2046 | { | ||
2047 | draw_vec[idx]->mCount += facep->getIndicesCount(); | ||
2048 | draw_vec[idx]->mEnd += facep->getGeomCount(); | ||
2049 | draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); | ||
2050 | validate_draw_info(*draw_vec[idx]); | ||
2051 | } | ||
2052 | else | ||
2053 | { | ||
2054 | U32 start = facep->getGeomIndex(); | ||
2055 | U32 end = start + facep->getGeomCount()-1; | ||
2056 | U32 offset = facep->getIndicesStart(); | ||
2057 | U32 count = facep->getIndicesCount(); | ||
2058 | LLDrawInfo* draw_info = new LLDrawInfo(start,end,count,offset,tex, | ||
2059 | facep->mVertexBuffer, fullbright, bump); | ||
2060 | draw_info->mVSize = facep->getVirtualSize(); | ||
2061 | draw_vec.push_back(draw_info); | ||
2062 | draw_info->mReflectionMap = group->mReflectionMap; | ||
2063 | draw_info->mTextureMatrix = tex_mat; | ||
2064 | validate_draw_info(*draw_info); | ||
2065 | } | ||
2066 | } | ||
2067 | |||
2068 | void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) | ||
2069 | { | ||
2070 | |||
2071 | } | ||
2072 | |||
2073 | void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) | ||
2074 | { | ||
2075 | if (group->changeLOD()) | ||
2076 | { | ||
2077 | group->mLastUpdateDistance = group->mDistance; | ||
2078 | } | ||
2079 | |||
2080 | group->mLastUpdateViewAngle = group->mViewAngle; | ||
2081 | |||
2082 | if (!group->isState(LLSpatialGroup::GEOM_DIRTY | | ||
2083 | LLSpatialGroup::ALPHA_DIRTY)) | ||
2084 | { | ||
2085 | return; | ||
2086 | } | ||
2087 | |||
2088 | group->mBuilt = 1.f; | ||
2089 | LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO); | ||
2090 | |||
2091 | LLFastTimer ftm2(LLFastTimer::FTM_REBUILD_VOLUME_VB); | ||
2092 | |||
2093 | //find reflection map | ||
2094 | if (group->mSpatialPartition->mImageEnabled) | ||
2095 | { | ||
2096 | if (group->mReflectionMap.isNull()) | ||
2097 | { | ||
2098 | LLSpatialGroup* parent = group->getParent(); | ||
2099 | while (parent && group->mReflectionMap.isNull()) | ||
2100 | { | ||
2101 | group->mReflectionMap = parent->mReflectionMap; | ||
2102 | parent = parent->getParent(); | ||
2103 | } | ||
2104 | } | ||
2105 | } | ||
2106 | |||
2107 | group->clearDrawMap(); | ||
2108 | |||
2109 | mFaceList.clear(); | ||
2110 | |||
2111 | std::vector<LLFace*> alpha_faces; | ||
2112 | U32 vertex_count = 0; | ||
2113 | U32 index_count = 0; | ||
2114 | U32 useage = group->mSpatialPartition->mBufferUsage; | ||
2115 | |||
2116 | //get all the faces into a list, putting alpha faces in their own list | ||
2117 | for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) | ||
2118 | { | ||
2119 | LLDrawable* drawablep = *drawable_iter; | ||
2120 | |||
2121 | if (drawablep->isDead()) | ||
2122 | { | ||
2123 | continue; | ||
2124 | } | ||
2125 | |||
2126 | if (drawablep->isAnimating()) | ||
2127 | { //fall back to stream draw for animating verts | ||
2128 | useage = GL_STREAM_DRAW_ARB; | ||
2129 | } | ||
2130 | |||
2131 | LLVOVolume* vobj = drawablep->getVOVolume(); | ||
2132 | |||
2133 | //for each face | ||
2134 | for (S32 i = 0; i < drawablep->getNumFaces(); i++) | ||
2135 | { | ||
2136 | //sum up face verts and indices | ||
2137 | drawablep->updateFaceSize(i); | ||
2138 | LLFace* facep = drawablep->getFace(i); | ||
2139 | if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA) | ||
2140 | { | ||
2141 | const LLTextureEntry* te = facep->getTextureEntry(); | ||
2142 | LLViewerImage* tex = facep->getTexture(); | ||
2143 | |||
2144 | BOOL force_simple = (facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA); | ||
2145 | U32 type = gPipeline.getPoolTypeFromTE(te, tex); | ||
2146 | if (type != LLDrawPool::POOL_ALPHA && force_simple) | ||
2147 | { | ||
2148 | type = LLDrawPool::POOL_SIMPLE; | ||
2149 | } | ||
2150 | facep->setPoolType(type); | ||
2151 | |||
2152 | if (vobj->isHUDAttachment()) | ||
2153 | { | ||
2154 | facep->setState(LLFace::FULLBRIGHT); | ||
2155 | } | ||
2156 | |||
2157 | if (vobj->mTextureAnimp && vobj->mTexAnimMode) | ||
2158 | { | ||
2159 | if (vobj->mTextureAnimp->mFace <= -1) | ||
2160 | { | ||
2161 | S32 face; | ||
2162 | for (face = 0; face < vobj->getNumTEs(); face++) | ||
2163 | { | ||
2164 | drawablep->getFace(face)->setState(LLFace::TEXTURE_ANIM); | ||
2165 | } | ||
2166 | } | ||
2167 | else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) | ||
2168 | { | ||
2169 | drawablep->getFace(vobj->mTextureAnimp->mFace)->setState(LLFace::TEXTURE_ANIM); | ||
2170 | } | ||
2171 | } | ||
2172 | |||
2173 | if (type == LLDrawPool::POOL_ALPHA) | ||
2174 | { | ||
2175 | vertex_count += facep->getGeomCount(); | ||
2176 | index_count += facep->getIndicesCount(); | ||
2177 | alpha_faces.push_back(facep); | ||
2178 | } | ||
2179 | else | ||
2180 | { | ||
2181 | if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) | ||
2182 | { | ||
2183 | facep->mLastUpdateTime = gFrameTimeSeconds; | ||
2184 | } | ||
2185 | mFaceList.push_back(facep); | ||
2186 | } | ||
2187 | } | ||
2188 | else | ||
2189 | { //face has no renderable geometry | ||
2190 | facep->mVertexBuffer = NULL; | ||
2191 | facep->mLastVertexBuffer = NULL; | ||
2192 | //don't alpha wrap drawables that have only tiny tiny alpha faces | ||
2193 | facep->setPoolType(LLDrawPool::POOL_SIMPLE); | ||
2194 | } | ||
2195 | |||
2196 | vobj->updateTextures(); | ||
2197 | } | ||
2198 | } | ||
2199 | |||
2200 | group->mVertexCount = vertex_count; | ||
2201 | group->mIndexCount = index_count; | ||
2202 | group->mBufferUsage = useage; | ||
2203 | |||
2204 | LLStrider<LLVector3> vertices; | ||
2205 | LLStrider<LLVector3> normals; | ||
2206 | LLStrider<LLVector2> texcoords2; | ||
2207 | LLStrider<LLVector2> texcoords; | ||
2208 | LLStrider<LLColor4U> colors; | ||
2209 | LLStrider<U32> indices; | ||
2210 | |||
2211 | //PROCESS NON-ALPHA FACES | ||
2212 | { | ||
2213 | //sort faces by texture | ||
2214 | std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareTextureAndTime()); | ||
2215 | |||
2216 | std::vector<LLFace*>::iterator face_iter = mFaceList.begin(); | ||
2217 | |||
2218 | LLSpatialGroup::buffer_map_t buffer_map; | ||
2219 | |||
2220 | while (face_iter != mFaceList.end()) | ||
2221 | { | ||
2222 | //pull off next face | ||
2223 | LLFace* facep = *face_iter; | ||
2224 | LLViewerImage* tex = facep->getTexture(); | ||
2225 | |||
2226 | U32 index_count = facep->getIndicesCount(); | ||
2227 | U32 geom_count = facep->getGeomCount(); | ||
2228 | |||
2229 | //sum up vertices needed for this texture | ||
2230 | std::vector<LLFace*>::iterator i = face_iter; | ||
2231 | ++i; | ||
2232 | while (i != mFaceList.end() && (*i)->getTexture() == tex) | ||
2233 | { | ||
2234 | facep = *i; | ||
2235 | ++i; | ||
2236 | index_count += facep->getIndicesCount(); | ||
2237 | geom_count += facep->getGeomCount(); | ||
2238 | } | ||
2239 | |||
2240 | //create/delete/resize vertex buffer if needed | ||
2241 | LLVertexBuffer* buffer = NULL; | ||
2242 | LLSpatialGroup::buffer_map_t::iterator found_iter = group->mBufferMap.find(tex); | ||
2243 | if (found_iter != group->mBufferMap.end()) | ||
2244 | { | ||
2245 | buffer = found_iter->second; | ||
2246 | } | ||
2247 | |||
2248 | if (!buffer) | ||
2249 | { //create new buffer if needed | ||
2250 | buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, | ||
2251 | group->mBufferUsage); | ||
2252 | buffer->allocateBuffer(geom_count, index_count, TRUE); | ||
2253 | } | ||
2254 | else | ||
2255 | { | ||
2256 | if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage) | ||
2257 | { | ||
2258 | buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, | ||
2259 | group->mBufferUsage); | ||
2260 | buffer->allocateBuffer(geom_count, index_count, TRUE); | ||
2261 | } | ||
2262 | else | ||
2263 | { | ||
2264 | buffer->resizeBuffer(geom_count, index_count); | ||
2265 | } | ||
2266 | } | ||
2267 | |||
2268 | BOOL clean = TRUE; | ||
2269 | buffer_map[tex] = buffer; | ||
2270 | |||
2271 | //add face geometry | ||
2272 | |||
2273 | //get vertex buffer striders | ||
2274 | buffer->getVertexStrider(vertices); | ||
2275 | buffer->getNormalStrider(normals); | ||
2276 | buffer->getTexCoordStrider(texcoords); | ||
2277 | buffer->getTexCoord2Strider(texcoords2); | ||
2278 | buffer->getColorStrider(colors); | ||
2279 | buffer->getIndexStrider(indices); | ||
2280 | |||
2281 | U32 indices_index = 0; | ||
2282 | U32 index_offset = 0; | ||
2283 | |||
2284 | while (face_iter < i) | ||
2285 | { | ||
2286 | facep = *face_iter; | ||
2287 | LLDrawable* drawablep = facep->getDrawable(); | ||
2288 | LLVOVolume* vobj = drawablep->getVOVolume(); | ||
2289 | LLVolume* volume = vobj->getVolume(); | ||
2290 | |||
2291 | U32 te_idx = facep->getTEOffset(); | ||
2292 | facep->mIndicesIndex = indices_index; | ||
2293 | facep->mGeomIndex = index_offset; | ||
2294 | facep->mVertexBuffer = buffer; | ||
2295 | { | ||
2296 | if (facep->getGeometryVolume(*volume, te_idx, vertices, normals, texcoords, texcoords2, colors, indices, | ||
2297 | vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset)) | ||
2298 | { | ||
2299 | clean = FALSE; | ||
2300 | buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(), | ||
2301 | facep->getIndicesStart(), facep->getIndicesCount()); | ||
2302 | } | ||
2303 | } | ||
2304 | |||
2305 | indices_index += facep->mIndicesCount; | ||
2306 | |||
2307 | BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA; | ||
2308 | BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); | ||
2309 | const LLTextureEntry* te = facep->getTextureEntry(); | ||
2310 | |||
2311 | if (tex->getPrimaryFormat() == GL_ALPHA) | ||
2312 | { | ||
2313 | registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); | ||
2314 | } | ||
2315 | else if (fullbright) | ||
2316 | { | ||
2317 | registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); | ||
2318 | } | ||
2319 | else | ||
2320 | { | ||
2321 | registerFace(group, facep, LLRenderPass::PASS_SIMPLE); | ||
2322 | } | ||
2323 | |||
2324 | facep->setPoolType(LLDrawPool::POOL_SIMPLE); | ||
2325 | |||
2326 | if (te->getShiny()) | ||
2327 | { | ||
2328 | registerFace(group, facep, LLRenderPass::PASS_SHINY); | ||
2329 | } | ||
2330 | |||
2331 | if (!force_simple && te->getBumpmap()) | ||
2332 | { | ||
2333 | registerFace(group, facep, LLRenderPass::PASS_BUMP); | ||
2334 | } | ||
2335 | |||
2336 | if (vobj->getIsLight()) | ||
2337 | { | ||
2338 | registerFace(group, facep, LLRenderPass::PASS_GLOW); | ||
2339 | } | ||
2340 | |||
2341 | |||
2342 | ++face_iter; | ||
2343 | } | ||
2344 | |||
2345 | if (clean) | ||
2346 | { | ||
2347 | buffer->markClean(); | ||
2348 | } | ||
2349 | } | ||
2350 | |||
2351 | group->mBufferMap.clear(); | ||
2352 | for (LLSpatialGroup::buffer_map_t::iterator i = buffer_map.begin(); i != buffer_map.end(); ++i) | ||
2353 | { | ||
2354 | group->mBufferMap[i->first] = i->second; | ||
2355 | } | ||
2356 | } | ||
2357 | |||
2358 | //PROCESS ALPHA FACES | ||
2359 | if (!alpha_faces.empty()) | ||
2360 | { | ||
2361 | //sort alpha faces by distance | ||
2362 | std::sort(alpha_faces.begin(), alpha_faces.end(), LLFace::CompareDistanceGreater()); | ||
2363 | |||
2364 | //store alpha faces in root vertex buffer | ||
2365 | if (group->mVertexBuffer.isNull() || (LLVertexBuffer::sEnableVBOs && group->mBufferUsage != group->mVertexBuffer->getUsage())) | ||
2366 | { | ||
2367 | group->mVertexBuffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, | ||
2368 | group->mBufferUsage); | ||
2369 | group->mVertexBuffer->allocateBuffer(group->mVertexCount, group->mIndexCount, true); | ||
2370 | stop_glerror(); | ||
2371 | } | ||
2372 | else | ||
2373 | { | ||
2374 | group->mVertexBuffer->resizeBuffer(group->mVertexCount, group->mIndexCount); | ||
2375 | stop_glerror(); | ||
2376 | } | ||
2377 | |||
2378 | //get vertex buffer striders | ||
2379 | LLVertexBuffer* buffer = group->mVertexBuffer; | ||
2380 | |||
2381 | BOOL clean = TRUE; | ||
2382 | |||
2383 | buffer->getVertexStrider(vertices); | ||
2384 | buffer->getNormalStrider(normals); | ||
2385 | buffer->getTexCoordStrider(texcoords); | ||
2386 | buffer->getTexCoord2Strider(texcoords2); | ||
2387 | buffer->getColorStrider(colors); | ||
2388 | buffer->getIndexStrider(indices); | ||
2389 | |||
2390 | U32 index_offset = 0; | ||
2391 | U32 indices_index = 0; | ||
2392 | |||
2393 | for (std::vector<LLFace*>::iterator i = alpha_faces.begin(); i != alpha_faces.end(); ++i) | ||
2394 | { | ||
2395 | LLFace* facep = *i; | ||
2396 | LLDrawable* drawablep = facep->getDrawable(); | ||
2397 | LLVOVolume* vobj = drawablep->getVOVolume(); | ||
2398 | LLVolume* volume = vobj->getVolume(); | ||
2399 | |||
2400 | U32 te_idx = facep->getTEOffset(); | ||
2401 | facep->mIndicesIndex = indices_index; | ||
2402 | facep->mGeomIndex = index_offset; | ||
2403 | facep->mVertexBuffer = group->mVertexBuffer; | ||
2404 | if (facep->getGeometryVolume(*volume, te_idx, vertices, normals, texcoords, texcoords2, colors, indices, | ||
2405 | vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset)) | ||
2406 | { | ||
2407 | clean = FALSE; | ||
2408 | buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(), | ||
2409 | facep->getIndicesStart(), facep->getIndicesCount()); | ||
2410 | } | ||
2411 | |||
2412 | indices_index += facep->mIndicesCount; | ||
2413 | |||
2414 | registerFace(group, facep, LLRenderPass::PASS_ALPHA); | ||
2415 | } | ||
2416 | |||
2417 | if (clean) | ||
2418 | { | ||
2419 | buffer->markClean(); | ||
2420 | } | ||
2421 | } | ||
2422 | else | ||
2423 | { | ||
2424 | group->mVertexBuffer = NULL; | ||
2425 | } | ||
2426 | |||
2427 | //get all the faces into a list, putting alpha faces in their own list | ||
2428 | for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) | ||
2429 | { | ||
2430 | LLDrawable* drawablep = *drawable_iter; | ||
2431 | drawablep->clearState(LLDrawable::REBUILD_ALL); | ||
2432 | } | ||
2433 | |||
2434 | group->mLastUpdateTime = gFrameTimeSeconds; | ||
2435 | group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MATRIX_DIRTY | | ||
2436 | LLSpatialGroup::ALPHA_DIRTY); | ||
2437 | |||
2438 | mFaceList.clear(); | ||
2046 | } | 2439 | } |
2440 | |||
2441 | void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) | ||
2442 | { | ||
2443 | //initialize to default usage for this partition | ||
2444 | U32 usage = group->mSpatialPartition->mBufferUsage; | ||
2445 | |||
2446 | //clear off any old faces | ||
2447 | mFaceList.clear(); | ||
2448 | |||
2449 | //for each drawable | ||
2450 | for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) | ||
2451 | { | ||
2452 | LLDrawable* drawablep = *drawable_iter; | ||
2453 | |||
2454 | if (drawablep->isDead()) | ||
2455 | { | ||
2456 | continue; | ||
2457 | } | ||
2458 | |||
2459 | if (drawablep->isAnimating()) | ||
2460 | { //fall back to stream draw for animating verts | ||
2461 | usage = GL_STREAM_DRAW_ARB; | ||
2462 | } | ||
2463 | |||
2464 | //for each face | ||
2465 | for (S32 i = 0; i < drawablep->getNumFaces(); i++) | ||
2466 | { | ||
2467 | //sum up face verts and indices | ||
2468 | drawablep->updateFaceSize(i); | ||
2469 | LLFace* facep = drawablep->getFace(i); | ||
2470 | if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA) | ||
2471 | { | ||
2472 | vertex_count += facep->getGeomCount(); | ||
2473 | index_count += facep->getIndicesCount(); | ||
2474 | |||
2475 | //remember face (for sorting) | ||
2476 | mFaceList.push_back(facep); | ||
2477 | } | ||
2478 | else | ||
2479 | { | ||
2480 | facep->mVertexBuffer = NULL; | ||
2481 | facep->mLastVertexBuffer = NULL; | ||
2482 | } | ||
2483 | } | ||
2484 | } | ||
2485 | |||
2486 | group->mBufferUsage = usage; | ||
2487 | } | ||
2488 | |||
2489 | LLHUDPartition::LLHUDPartition() | ||
2490 | { | ||
2491 | mPartitionType = LLPipeline::PARTITION_HUD; | ||
2492 | mDrawableType = LLPipeline::RENDER_TYPE_HUD; | ||
2493 | mSlopRatio = 0.f; | ||
2494 | mLODPeriod = 16; | ||
2495 | } | ||
2496 | |||
2497 | void LLHUDPartition::shift(const LLVector3 &offset) | ||
2498 | { | ||
2499 | //HUD objects don't shift with region crossing. That would be silly. | ||
2500 | } | ||
2501 | |||
2502 | |||