diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lldrawable.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/lldrawable.cpp')
-rw-r--r-- | linden/indra/newview/lldrawable.cpp | 1340 |
1 files changed, 1340 insertions, 0 deletions
diff --git a/linden/indra/newview/lldrawable.cpp b/linden/indra/newview/lldrawable.cpp new file mode 100644 index 0000000..af4f205 --- /dev/null +++ b/linden/indra/newview/lldrawable.cpp | |||
@@ -0,0 +1,1340 @@ | |||
1 | /** | ||
2 | * @file lldrawable.cpp | ||
3 | * @brief LLDrawable class implementation | ||
4 | * | ||
5 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "llviewerprecompiledheaders.h" | ||
29 | |||
30 | #include "lldrawable.h" | ||
31 | |||
32 | // library includes | ||
33 | #include "material_codes.h" | ||
34 | |||
35 | // viewer includes | ||
36 | #include "llagparray.h" | ||
37 | #include "llagparray.inl" | ||
38 | #include "llcriticaldamp.h" | ||
39 | #include "llface.h" | ||
40 | #include "lllightconstants.h" | ||
41 | #include "llsky.h" | ||
42 | #include "llsurfacepatch.h" | ||
43 | #include "llviewercamera.h" | ||
44 | #include "llviewerregion.h" | ||
45 | #include "llvolume.h" | ||
46 | #include "llvoavatar.h" | ||
47 | #include "llvovolume.h" | ||
48 | #include "llvosurfacepatch.h" // for debugging | ||
49 | #include "llworld.h" | ||
50 | #include "pipeline.h" | ||
51 | #include "llspatialpartition.h" | ||
52 | #include "llviewerobjectlist.h" | ||
53 | #include "llviewerwindow.h" | ||
54 | |||
55 | const F32 MIN_INTERPOLATE_DISTANCE_SQUARED = 0.001f * 0.001f; | ||
56 | const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f; | ||
57 | const F32 OBJECT_DAMPING_TIME_CONSTANT = 0.06f; | ||
58 | const F32 MIN_SHADOW_CASTER_RADIUS = 2.0f; | ||
59 | |||
60 | //////////////////////// | ||
61 | // | ||
62 | // Inline implementations. | ||
63 | // | ||
64 | // | ||
65 | |||
66 | |||
67 | |||
68 | ////////////////////////////// | ||
69 | // | ||
70 | // Drawable code | ||
71 | // | ||
72 | // | ||
73 | |||
74 | // static | ||
75 | U32 LLDrawable::sCurVisible = 0; | ||
76 | U32 LLDrawable::sNumZombieDrawables = 0; | ||
77 | F32 LLDrawable::sCurPixelAngle = 0; | ||
78 | LLDynamicArrayPtr<LLPointer<LLDrawable> > LLDrawable::sDeadList; | ||
79 | |||
80 | // static | ||
81 | void LLDrawable::incrementVisible() | ||
82 | { | ||
83 | sCurVisible++; | ||
84 | sCurPixelAngle = (F32) gViewerWindow->getWindowDisplayHeight()/gCamera->getView(); | ||
85 | } | ||
86 | void LLDrawable::init() | ||
87 | { | ||
88 | // mXform | ||
89 | mParent = NULL; | ||
90 | mRenderType = 0; | ||
91 | mCurrentScale = LLVector3(1,1,1); | ||
92 | mDistanceWRTCamera = 0.0f; | ||
93 | // mUVRect | ||
94 | mUVZ = 0.f; | ||
95 | // mLightSet | ||
96 | // mBlockSet | ||
97 | // mSavePos | ||
98 | mQuietCount = 0; | ||
99 | |||
100 | mState = 0; | ||
101 | mVObjp = NULL; | ||
102 | // mFaces | ||
103 | mSpatialGroupp = NULL; | ||
104 | mSpatialGroupOffset = -1; | ||
105 | mVisible = 0; | ||
106 | mRadius = 0.f; | ||
107 | mSunShadowFactor = 1.f; | ||
108 | |||
109 | mGeneration = -1; | ||
110 | mBinRadius = 1.f; | ||
111 | mSpatialBridge = NULL; | ||
112 | } | ||
113 | |||
114 | // static | ||
115 | void LLDrawable::initClass() | ||
116 | { | ||
117 | } | ||
118 | |||
119 | |||
120 | void LLDrawable::destroy() | ||
121 | { | ||
122 | if (isDead()) | ||
123 | { | ||
124 | sNumZombieDrawables--; | ||
125 | } | ||
126 | |||
127 | std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); | ||
128 | mFaces.clear(); | ||
129 | |||
130 | /* | ||
131 | if (!(sNumZombieDrawables % 10)) | ||
132 | { | ||
133 | llinfos << "- Zombie drawables: " << sNumZombieDrawables << llendl; | ||
134 | } | ||
135 | */ | ||
136 | } | ||
137 | |||
138 | void LLDrawable::markDead() | ||
139 | { | ||
140 | if (isDead()) | ||
141 | { | ||
142 | llwarns << "Warning! Marking dead multiple times!" << llendl; | ||
143 | return; | ||
144 | } | ||
145 | |||
146 | if (mSpatialBridge) | ||
147 | { | ||
148 | mSpatialBridge->markDead(); | ||
149 | mSpatialBridge = NULL; | ||
150 | } | ||
151 | |||
152 | sNumZombieDrawables++; | ||
153 | |||
154 | // We're dead. Free up all of our references to other objects | ||
155 | setState(DEAD); | ||
156 | cleanupReferences(); | ||
157 | // sDeadList.put(this); | ||
158 | } | ||
159 | |||
160 | LLVOVolume* LLDrawable::getVOVolume() const | ||
161 | { | ||
162 | LLViewerObject* objectp = mVObjp; | ||
163 | if ( !isDead() && objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) | ||
164 | { | ||
165 | return ((LLVOVolume*)objectp); | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | return NULL; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | BOOL LLDrawable::isLight() const | ||
174 | { | ||
175 | LLViewerObject* objectp = mVObjp; | ||
176 | if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME) && !isDead()) | ||
177 | { | ||
178 | return ((LLVOVolume*)objectp)->getIsLight(); | ||
179 | } | ||
180 | else | ||
181 | { | ||
182 | return FALSE; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | void LLDrawable::clearLightSet() | ||
187 | { | ||
188 | // Remove this object from any object which has it as a light | ||
189 | for (drawable_set_t::iterator iter = mLightSet.begin(); iter != mLightSet.end(); iter++) | ||
190 | { | ||
191 | LLDrawable *targetp = *iter; | ||
192 | if (targetp != this && !targetp->isDead()) | ||
193 | { | ||
194 | targetp->mLightSet.erase(this); | ||
195 | gPipeline.markRelight(targetp); | ||
196 | } | ||
197 | } | ||
198 | mLightSet.clear(); | ||
199 | } | ||
200 | |||
201 | void LLDrawable::cleanupReferences() | ||
202 | { | ||
203 | LLFastTimer t(LLFastTimer::FTM_PIPELINE); | ||
204 | |||
205 | std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); | ||
206 | mFaces.clear(); | ||
207 | |||
208 | clearLightSet(); | ||
209 | |||
210 | gObjectList.removeDrawable(this); | ||
211 | |||
212 | mBlockSet.clear(); | ||
213 | |||
214 | gPipeline.unlinkDrawable(this); | ||
215 | |||
216 | // Cleanup references to other objects | ||
217 | mVObjp = NULL; | ||
218 | mParent = NULL; | ||
219 | } | ||
220 | |||
221 | void LLDrawable::cleanupDeadDrawables() | ||
222 | { | ||
223 | /* | ||
224 | S32 i; | ||
225 | for (i = 0; i < sDeadList.count(); i++) | ||
226 | { | ||
227 | if (sDeadList[i]->getNumRefs() > 1) | ||
228 | { | ||
229 | llwarns << "Dead drawable has " << sDeadList[i]->getNumRefs() << " remaining refs" << llendl; | ||
230 | gPipeline.findReferences(sDeadList[i]); | ||
231 | } | ||
232 | } | ||
233 | */ | ||
234 | sDeadList.reset(); | ||
235 | } | ||
236 | |||
237 | S32 LLDrawable::findReferences(LLDrawable *drawablep) | ||
238 | { | ||
239 | S32 count = 0; | ||
240 | if (mLightSet.count(drawablep) > 0) | ||
241 | { | ||
242 | llinfos << this << ": lightset reference" << llendl; | ||
243 | count++; | ||
244 | } | ||
245 | if (mBlockSet.count(drawablep) > 0) | ||
246 | { | ||
247 | llinfos << this << ": blockset reference" << llendl; | ||
248 | count++; | ||
249 | } | ||
250 | if (mParent == drawablep) | ||
251 | { | ||
252 | llinfos << this << ": parent reference" << llendl; | ||
253 | count++; | ||
254 | } | ||
255 | return count; | ||
256 | } | ||
257 | |||
258 | #if 0 | ||
259 | // SJB: This is SLOW, so we don't want to allow it (we don't currently use it) | ||
260 | void LLDrawable::removeFace(const S32 i) | ||
261 | { | ||
262 | LLFace *face= mFaces[i]; | ||
263 | |||
264 | if (face) | ||
265 | { | ||
266 | mFaces.erase(mFaces.begin() + i); | ||
267 | delete face; | ||
268 | } | ||
269 | } | ||
270 | #endif | ||
271 | |||
272 | LLFace* LLDrawable::addFace(LLDrawPool *poolp, LLViewerImage *texturep, const BOOL shared_geom) | ||
273 | { | ||
274 | LLMemType mt(LLMemType::MTYPE_DRAWABLE); | ||
275 | |||
276 | LLFace *face = new LLFace(this, mVObjp); | ||
277 | |||
278 | if (face) | ||
279 | { | ||
280 | mFaces.push_back(face); | ||
281 | face->setPool(poolp, texturep); | ||
282 | |||
283 | if (shared_geom) | ||
284 | { | ||
285 | face->setState(LLFace::SHARED_GEOM); | ||
286 | } | ||
287 | else if (!isVisible()) | ||
288 | { | ||
289 | face->setState(LLFace::BACKLIST); | ||
290 | } | ||
291 | if (isState(UNLIT)) | ||
292 | { | ||
293 | face->setState(LLFace::FULLBRIGHT); | ||
294 | } | ||
295 | } | ||
296 | return face; | ||
297 | } | ||
298 | |||
299 | void LLDrawable::setNumFaces(const S32 newFaces, LLDrawPool *poolp, LLViewerImage *texturep) | ||
300 | { | ||
301 | if (newFaces == (S32)mFaces.size()) | ||
302 | { | ||
303 | return; | ||
304 | } | ||
305 | else if (newFaces < (S32)mFaces.size()) | ||
306 | { | ||
307 | std::for_each(mFaces.begin() + newFaces, mFaces.end(), DeletePointer()); | ||
308 | mFaces.erase(mFaces.begin() + newFaces, mFaces.end()); | ||
309 | } | ||
310 | else // (newFaces > mFaces.size()) | ||
311 | { | ||
312 | mFaces.reserve(newFaces); | ||
313 | for (int i = mFaces.size(); i<newFaces; i++) | ||
314 | { | ||
315 | addFace(poolp, texturep); | ||
316 | } | ||
317 | } | ||
318 | } | ||
319 | |||
320 | void LLDrawable::setNumFacesFast(const S32 newFaces, LLDrawPool *poolp, LLViewerImage *texturep) | ||
321 | { | ||
322 | if (newFaces <= (S32)mFaces.size() && newFaces >= (S32)mFaces.size()/2) | ||
323 | { | ||
324 | return; | ||
325 | } | ||
326 | else if (newFaces < (S32)mFaces.size()) | ||
327 | { | ||
328 | std::for_each(mFaces.begin() + newFaces, mFaces.end(), DeletePointer()); | ||
329 | mFaces.erase(mFaces.begin() + newFaces, mFaces.end()); | ||
330 | } | ||
331 | else // (newFaces > mFaces.size()) | ||
332 | { | ||
333 | mFaces.reserve(newFaces); | ||
334 | for (int i = mFaces.size(); i<newFaces; i++) | ||
335 | { | ||
336 | addFace(poolp, texturep); | ||
337 | } | ||
338 | } | ||
339 | } | ||
340 | |||
341 | void LLDrawable::mergeFaces(LLDrawable* src) | ||
342 | { | ||
343 | U32 face_count = mFaces.size() + src->mFaces.size(); | ||
344 | |||
345 | mFaces.reserve(face_count); | ||
346 | for (U32 i = 0; i < src->mFaces.size(); i++) | ||
347 | { | ||
348 | LLFace* facep = src->mFaces[i]; | ||
349 | facep->setDrawable(this); | ||
350 | mFaces.push_back(facep); | ||
351 | } | ||
352 | src->mFaces.clear(); | ||
353 | } | ||
354 | |||
355 | void LLDrawable::deleteFaces(S32 offset, S32 count) | ||
356 | { | ||
357 | face_list_t::iterator face_begin = mFaces.begin() + offset; | ||
358 | face_list_t::iterator face_end = face_begin + count; | ||
359 | std::for_each(face_begin, face_end, DeletePointer()); | ||
360 | mFaces.erase(face_begin, face_end); | ||
361 | } | ||
362 | |||
363 | void LLDrawable::update() | ||
364 | { | ||
365 | llerrs << "Shouldn't be called!" << llendl; | ||
366 | } | ||
367 | |||
368 | |||
369 | void LLDrawable::updateMaterial() | ||
370 | { | ||
371 | } | ||
372 | |||
373 | void LLDrawable::makeActive() | ||
374 | { | ||
375 | if (!isState(ACTIVE)) // && mGeneration > 0) | ||
376 | { | ||
377 | setState(ACTIVE); | ||
378 | |||
379 | if (!isRoot() && !mParent->isActive()) | ||
380 | { | ||
381 | mParent->makeActive(); | ||
382 | } | ||
383 | |||
384 | gPipeline.setActive(this, TRUE); | ||
385 | |||
386 | //all child objects must also be active | ||
387 | for (U32 i = 0; i < getChildCount(); i++) | ||
388 | { | ||
389 | getChild(i)->makeActive(); | ||
390 | } | ||
391 | |||
392 | if (mVObjp->getPCode() == LL_PCODE_VOLUME) | ||
393 | { | ||
394 | if (mVObjp->getVolume()->getPathType() == LL_PCODE_PATH_FLEXIBLE) | ||
395 | { | ||
396 | return; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | clearState(LLDrawable::LIGHTING_BUILT); | ||
401 | if (mVObjp->getPCode() == LL_PCODE_VOLUME) | ||
402 | { | ||
403 | gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE); | ||
404 | } | ||
405 | } | ||
406 | mQuietCount = 0; | ||
407 | } | ||
408 | |||
409 | |||
410 | void LLDrawable::makeStatic() | ||
411 | { | ||
412 | if (isState(ACTIVE)) | ||
413 | { | ||
414 | clearState(ACTIVE); | ||
415 | gPipeline.setActive(this, FALSE); | ||
416 | |||
417 | if (mParent.notNull() && mParent->isActive()) | ||
418 | { | ||
419 | llerrs << "Drawable became static with active parent!" << llendl; | ||
420 | } | ||
421 | |||
422 | S32 child_count = mVObjp->mChildList.size(); | ||
423 | for (S32 child_num = 0; child_num < child_count; child_num++) | ||
424 | { | ||
425 | LLDrawable* child_drawable = mVObjp->mChildList[child_num]->mDrawable; | ||
426 | if (child_drawable) | ||
427 | { | ||
428 | child_drawable->makeStatic(); | ||
429 | } | ||
430 | } | ||
431 | |||
432 | gPipeline.markRelight(this); | ||
433 | if (mVObjp->getPCode() == LL_PCODE_VOLUME) | ||
434 | { | ||
435 | gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE); | ||
436 | } | ||
437 | |||
438 | if (mSpatialBridge) | ||
439 | { | ||
440 | mSpatialBridge->markDead(); | ||
441 | setSpatialBridge(NULL); | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | |||
446 | // Returns "distance" between target destination and resulting xfrom | ||
447 | F32 LLDrawable::updateXform(BOOL undamped) | ||
448 | { | ||
449 | BOOL damped = !undamped; | ||
450 | |||
451 | // Position | ||
452 | LLVector3 old_pos(mXform.getPosition()); | ||
453 | LLVector3 target_pos; | ||
454 | if (mXform.isRoot()) | ||
455 | { | ||
456 | // get root position in your agent's region | ||
457 | target_pos = mVObjp->getPositionAgent(); | ||
458 | } | ||
459 | else | ||
460 | { | ||
461 | // parent-relative position | ||
462 | target_pos = mVObjp->getPosition(); | ||
463 | } | ||
464 | |||
465 | // Rotation | ||
466 | LLQuaternion old_rot(mXform.getRotation()); | ||
467 | LLQuaternion target_rot = mVObjp->getRotation(); | ||
468 | //scaling | ||
469 | LLVector3 target_scale = mVObjp->getScale(); | ||
470 | LLVector3 old_scale = mCurrentScale; | ||
471 | LLVector3 dest_scale = target_scale; | ||
472 | |||
473 | // Damping | ||
474 | F32 dist_squared = 0.f; | ||
475 | F32 scaled = 0.f; | ||
476 | |||
477 | if (damped && mDistanceWRTCamera > 0.0f) | ||
478 | { | ||
479 | F32 lerp_amt = llclamp(LLCriticalDamp::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f); | ||
480 | LLVector3 new_pos = lerp(old_pos, target_pos, lerp_amt); | ||
481 | dist_squared = dist_vec_squared(new_pos, target_pos); | ||
482 | |||
483 | LLQuaternion new_rot = nlerp(lerp_amt, old_rot, target_rot); | ||
484 | dist_squared += (1.f - dot(new_rot, target_rot)) * 10.f; | ||
485 | |||
486 | LLVector3 new_scale = lerp(old_scale, target_scale, lerp_amt); | ||
487 | scaled = dist_vec_squared(new_scale, target_scale); | ||
488 | |||
489 | dist_squared += scaled; | ||
490 | F32 camdist2 = (mDistanceWRTCamera * mDistanceWRTCamera); | ||
491 | if ((dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED * camdist2) && | ||
492 | (dist_squared <= MAX_INTERPOLATE_DISTANCE_SQUARED)) | ||
493 | { | ||
494 | // interpolate | ||
495 | target_pos = new_pos; | ||
496 | target_rot = new_rot; | ||
497 | target_scale = new_scale; | ||
498 | |||
499 | if (scaled >= MIN_INTERPOLATE_DISTANCE_SQUARED) | ||
500 | { | ||
501 | //scaling requires an immediate rebuild | ||
502 | gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE); | ||
503 | } | ||
504 | |||
505 | } | ||
506 | else | ||
507 | { | ||
508 | // snap to final position | ||
509 | dist_squared = 0.0f; | ||
510 | } | ||
511 | } | ||
512 | |||
513 | // Update | ||
514 | mXform.setPosition(target_pos); | ||
515 | mXform.setRotation(target_rot); | ||
516 | mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!) | ||
517 | mXform.updateMatrix(); | ||
518 | |||
519 | mCurrentScale = target_scale; | ||
520 | |||
521 | if (!getVOVolume()) | ||
522 | { | ||
523 | movePartition(); | ||
524 | } | ||
525 | else if (mSpatialBridge) | ||
526 | { | ||
527 | gPipeline.markMoved(mSpatialBridge, FALSE); | ||
528 | } | ||
529 | else | ||
530 | { | ||
531 | //a child prim moved and needs its verts regenerated | ||
532 | gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE); | ||
533 | } | ||
534 | |||
535 | return dist_squared; | ||
536 | } | ||
537 | |||
538 | void LLDrawable::setRadius(F32 radius) | ||
539 | { | ||
540 | if (mRadius != radius) | ||
541 | { | ||
542 | mRadius = radius; | ||
543 | updateBinRadius(); | ||
544 | if (!getVOVolume()) | ||
545 | { | ||
546 | movePartition(); | ||
547 | } | ||
548 | } | ||
549 | } | ||
550 | |||
551 | void LLDrawable::moveUpdatePipeline(BOOL moved) | ||
552 | { | ||
553 | makeActive(); | ||
554 | |||
555 | // Update the face centers. | ||
556 | for (S32 i = 0; i < getNumFaces(); i++) | ||
557 | { | ||
558 | getFace(i)->updateCenterAgent(); | ||
559 | } | ||
560 | |||
561 | if (moved || !isState(LLDrawable::BUILT)) // moved since last frame | ||
562 | { | ||
563 | LLVector3 tmp = mSavePos - mXform.getPositionW(); | ||
564 | F32 dist = tmp.magVecSquared(); // moved since last _update_ | ||
565 | |||
566 | if (dist > 1.0f || !isState(LLDrawable::BUILT) || isLight()) | ||
567 | { | ||
568 | mSavePos = mXform.getPositionW(); | ||
569 | gPipeline.markRelight(this); | ||
570 | } | ||
571 | } | ||
572 | } | ||
573 | |||
574 | void LLDrawable::movePartition() | ||
575 | { | ||
576 | if (getSpatialGroup() || getVOVolume()) | ||
577 | { | ||
578 | LLSpatialPartition* part = getSpatialPartition(); | ||
579 | if (part) | ||
580 | { | ||
581 | part->move(this, getSpatialGroup()); | ||
582 | } | ||
583 | } | ||
584 | } | ||
585 | |||
586 | BOOL LLDrawable::updateMove() | ||
587 | { | ||
588 | if (isDead()) | ||
589 | { | ||
590 | llwarns << "Update move on dead drawable!" << llendl; | ||
591 | return TRUE; | ||
592 | } | ||
593 | |||
594 | if (mVObjp.isNull()) | ||
595 | { | ||
596 | return FALSE; | ||
597 | } | ||
598 | |||
599 | makeActive(); | ||
600 | |||
601 | BOOL done; | ||
602 | |||
603 | if (isState(MOVE_UNDAMPED)) | ||
604 | { | ||
605 | done = updateMoveUndamped(); | ||
606 | } | ||
607 | else | ||
608 | { | ||
609 | done = updateMoveDamped(); | ||
610 | } | ||
611 | return done; | ||
612 | } | ||
613 | |||
614 | BOOL LLDrawable::updateMoveUndamped() | ||
615 | { | ||
616 | F32 dist_squared = updateXform(TRUE); | ||
617 | |||
618 | mGeneration++; | ||
619 | |||
620 | if (!isState(LLDrawable::INVISIBLE)) | ||
621 | { | ||
622 | BOOL moved = (dist_squared > 0.001f && dist_squared < 255.99f); | ||
623 | moveUpdatePipeline(moved); | ||
624 | mVObjp->updateText(); | ||
625 | } | ||
626 | |||
627 | mVObjp->clearChanged(LLXform::MOVED); | ||
628 | |||
629 | return TRUE; | ||
630 | } | ||
631 | |||
632 | BOOL LLDrawable::updateMoveDamped() | ||
633 | { | ||
634 | F32 dist_squared = updateXform(FALSE); | ||
635 | |||
636 | mGeneration++; | ||
637 | |||
638 | if (!isState(LLDrawable::INVISIBLE)) | ||
639 | { | ||
640 | BOOL moved = (dist_squared > 0.001f && dist_squared < 128.0f); | ||
641 | moveUpdatePipeline(moved); | ||
642 | mVObjp->updateText(); | ||
643 | } | ||
644 | |||
645 | BOOL done_moving = (dist_squared == 0.0f) ? TRUE : FALSE; | ||
646 | |||
647 | if (done_moving) | ||
648 | { | ||
649 | mVObjp->clearChanged(LLXform::MOVED); | ||
650 | } | ||
651 | |||
652 | return done_moving; | ||
653 | } | ||
654 | |||
655 | void LLDrawable::updateDistance(LLCamera& camera) | ||
656 | { | ||
657 | if (mVObjp->isHUDAttachment()) | ||
658 | { | ||
659 | mDistanceWRTCamera = 1.0f; | ||
660 | if (sCurVisible % 16 == 0) | ||
661 | { | ||
662 | mVObjp->updateLOD(); | ||
663 | } | ||
664 | return; | ||
665 | } | ||
666 | |||
667 | LLVector3 pos(getPositionGroup()); | ||
668 | |||
669 | pos -= camera.getOrigin(); | ||
670 | mDistanceWRTCamera = pos.magVec(); | ||
671 | |||
672 | //switch LOD with the spatial group to avoid artifacts | ||
673 | LLSpatialGroup* sg = getSpatialGroup(); | ||
674 | if (!sg || sg->changeLOD()) | ||
675 | { | ||
676 | mVObjp->updateLOD(); | ||
677 | } | ||
678 | } | ||
679 | |||
680 | void LLDrawable::updateTexture() | ||
681 | { | ||
682 | LLMemType mt(LLMemType::MTYPE_DRAWABLE); | ||
683 | |||
684 | if (isDead()) | ||
685 | { | ||
686 | llwarns << "Dead drawable updating texture!" << llendl; | ||
687 | return; | ||
688 | } | ||
689 | |||
690 | // *FIX: this updates textures on all faces in this drawable, not | ||
691 | // just the viewer object we care about | ||
692 | if (mVObjp->getNumTEs()) | ||
693 | { | ||
694 | // For each face in this drawable, change the drawpool if necessary. | ||
695 | for (S32 i = 0; i < getNumFaces(); i++) | ||
696 | { | ||
697 | LLFace *facep = mFaces[i]; | ||
698 | U32 pool_type = facep->getPool()->getType(); | ||
699 | |||
700 | if ((pool_type == LLDrawPool::POOL_SIMPLE) || | ||
701 | (pool_type == LLDrawPool::POOL_ALPHA) || | ||
702 | (pool_type == LLDrawPool::POOL_HUD) || | ||
703 | (pool_type == LLDrawPool::POOL_MEDIA) || | ||
704 | (pool_type == LLDrawPool::POOL_BUMP)) | ||
705 | { | ||
706 | LLViewerObject* objp = facep->getViewerObject(); | ||
707 | S32 te_offset = facep->getTEOffset(); | ||
708 | |||
709 | if (te_offset >= objp->getNumTEs()) // Shouldn't happen | ||
710 | { | ||
711 | llwarns << "TE offsets don't match!" << llendl; | ||
712 | facep->setTEOffset(-1); | ||
713 | continue; | ||
714 | } | ||
715 | |||
716 | LLDrawPool* poolp = NULL; | ||
717 | LLViewerImage* imagep = (te_offset >= 0) ? objp->getTEImage(te_offset) : facep->getTexture(); | ||
718 | if (facep->isState(LLFace::HUD_RENDER)) | ||
719 | { | ||
720 | poolp = gPipeline.getPool(LLDrawPool::POOL_HUD); | ||
721 | } | ||
722 | else if (te_offset >= 0) | ||
723 | { | ||
724 | // This face actually uses texture entries... | ||
725 | const LLTextureEntry* te = facep->getTextureEntry(); | ||
726 | poolp = LLPipeline::getPoolFromTE(te, imagep); | ||
727 | } | ||
728 | else | ||
729 | { | ||
730 | // No texture entry for this face. | ||
731 | if (!imagep) | ||
732 | { | ||
733 | poolp = gPipeline.getPool(LLDrawPool::POOL_SIMPLE, NULL); | ||
734 | } | ||
735 | else if ((imagep->getComponents() == 4) || (imagep->getComponents() == 2)) | ||
736 | { | ||
737 | poolp = gPipeline.getPool(LLDrawPool::POOL_ALPHA); | ||
738 | } | ||
739 | else | ||
740 | { | ||
741 | poolp = gPipeline.getPool(LLDrawPool::POOL_SIMPLE, imagep); | ||
742 | } | ||
743 | } | ||
744 | facep->setPool(poolp, imagep); | ||
745 | } | ||
746 | } | ||
747 | } | ||
748 | } | ||
749 | |||
750 | |||
751 | BOOL LLDrawable::updateGeometry(BOOL priority) | ||
752 | { | ||
753 | llassert(mVObjp.notNull()); | ||
754 | BOOL res = mVObjp->updateGeometry(this); | ||
755 | if (isState(REBUILD_LIGHTING)) | ||
756 | { | ||
757 | updateLighting(priority ? FALSE : TRUE); // only do actual lighting for non priority updates | ||
758 | if (priority) | ||
759 | { | ||
760 | gPipeline.markRelight(this); // schedule non priority update | ||
761 | } | ||
762 | else | ||
763 | { | ||
764 | clearState(REBUILD_LIGHTING); | ||
765 | } | ||
766 | } | ||
767 | return res; | ||
768 | } | ||
769 | |||
770 | void LLDrawable::shiftPos(const LLVector3 &shift_vector) | ||
771 | { | ||
772 | if (isDead()) | ||
773 | { | ||
774 | llwarns << "Shifting dead drawable" << llendl; | ||
775 | return; | ||
776 | } | ||
777 | |||
778 | if (mParent) | ||
779 | { | ||
780 | mXform.setPosition(mVObjp->getPosition()); | ||
781 | } | ||
782 | else | ||
783 | { | ||
784 | mXform.setPosition(mVObjp->getPositionAgent()); | ||
785 | } | ||
786 | |||
787 | mXform.setRotation(mVObjp->getRotation()); | ||
788 | mXform.setScale(1,1,1); | ||
789 | mXform.updateMatrix(); | ||
790 | |||
791 | if (isStatic() || // *FIX: don't know why this is happening, but | ||
792 | // some terrain patches are becoming active | ||
793 | // (earth quake, maybe?) DP | ||
794 | getRenderType() == LLPipeline::RENDER_TYPE_TERRAIN) | ||
795 | { | ||
796 | LLStrider<LLVector3> verticesp; | ||
797 | |||
798 | for (S32 i = 0; i < getNumFaces(); i++) | ||
799 | { | ||
800 | LLFace *facep = getFace(i); | ||
801 | facep->mCenterAgent += shift_vector; | ||
802 | facep->mExtents[0] += shift_vector; | ||
803 | facep->mExtents[1] += shift_vector; | ||
804 | |||
805 | if (facep->hasGeometry() && !facep->isState(LLFace::SHARED_GEOM)) | ||
806 | { | ||
807 | S32 index = facep->getVertices(verticesp); | ||
808 | if (index >= 0) | ||
809 | { | ||
810 | S32 vertex_count = facep->getGeomCount(); | ||
811 | for (S32 j = 0; j < vertex_count; j++) | ||
812 | { | ||
813 | *verticesp += shift_vector; | ||
814 | verticesp++; | ||
815 | } | ||
816 | } | ||
817 | } | ||
818 | } | ||
819 | } | ||
820 | else | ||
821 | { | ||
822 | // Update the face centers. | ||
823 | for (S32 i = 0; i < getNumFaces(); i++) | ||
824 | { | ||
825 | LLFace *facep = getFace(i); | ||
826 | facep->mCenterAgent += shift_vector; | ||
827 | } | ||
828 | } | ||
829 | |||
830 | //update spatial extents | ||
831 | if (!getVOVolume() || isStatic()) | ||
832 | { | ||
833 | mExtents[0] += shift_vector; | ||
834 | mExtents[1] += shift_vector; | ||
835 | mPositionGroup += LLVector3d(shift_vector); | ||
836 | } | ||
837 | else if (mSpatialBridge) | ||
838 | { | ||
839 | mSpatialBridge->shiftPos(shift_vector); | ||
840 | } | ||
841 | |||
842 | mSavePos = mXform.getPositionW(); | ||
843 | |||
844 | mVObjp->onShift(shift_vector); | ||
845 | } | ||
846 | |||
847 | const LLVector3& LLDrawable::getBounds(LLVector3& min, LLVector3& max) const | ||
848 | { | ||
849 | mXform.getMinMax(min,max); | ||
850 | return mXform.getPositionW(); | ||
851 | } | ||
852 | |||
853 | const LLVector3* LLDrawable::getSpatialExtents() const | ||
854 | { | ||
855 | return mExtents; | ||
856 | } | ||
857 | |||
858 | void LLDrawable::setSpatialExtents(LLVector3 min, LLVector3 max) | ||
859 | { | ||
860 | LLVector3 size = max - min; | ||
861 | mExtents[0] = min; | ||
862 | mExtents[1] = max; | ||
863 | } | ||
864 | |||
865 | void LLDrawable::setPositionGroup(const LLVector3d& pos) | ||
866 | { | ||
867 | mPositionGroup.setVec(pos); | ||
868 | } | ||
869 | |||
870 | void LLDrawable::updateSpatialExtents() | ||
871 | { | ||
872 | if (mVObjp) | ||
873 | { | ||
874 | mVObjp->updateSpatialExtents(mExtents[0], mExtents[1]); | ||
875 | } | ||
876 | |||
877 | if (mSpatialBridge.notNull()) | ||
878 | { | ||
879 | mPositionGroup.setVec(0,0,0); | ||
880 | } | ||
881 | } | ||
882 | |||
883 | |||
884 | void LLDrawable::updateBinRadius() | ||
885 | { | ||
886 | S32 binLOD = mVObjp ? mVObjp->getLOD() : 2; | ||
887 | static F64 detail_bins[] = { 8, 4, 2, 1 }; | ||
888 | F32 radius = getVOVolume() && isStatic() ? | ||
889 | (mExtents[1]-mExtents[0]).magVec() : getRadius(); | ||
890 | mBinRadius = detail_bins[binLOD] * llmax((F64) radius, (3-binLOD)*0.25); | ||
891 | } | ||
892 | |||
893 | void LLDrawable::updateLightSet() | ||
894 | { | ||
895 | if (isDead()) | ||
896 | { | ||
897 | llwarns << "Updating light set for dead drawable!" << llendl; | ||
898 | return; | ||
899 | } | ||
900 | |||
901 | LLVOVolume* light = getVOVolume(); | ||
902 | if (isLight() && light) | ||
903 | { | ||
904 | // mLightSet points to lit objects | ||
905 | for (drawable_set_t::iterator iter = mLightSet.begin(); iter != mLightSet.end(); iter++) | ||
906 | { | ||
907 | gPipeline.markRelight(*iter); | ||
908 | } | ||
909 | mLightSet.clear(); | ||
910 | gPipeline.mObjectPartition->getObjects(getPositionAgent(), light->getLightRadius(), mLightSet); | ||
911 | for (drawable_set_t::iterator iter = mLightSet.begin(); iter != mLightSet.end(); iter++) | ||
912 | { | ||
913 | gPipeline.markRelight(*iter); | ||
914 | } | ||
915 | } | ||
916 | else | ||
917 | { | ||
918 | // mLightSet points to nearby lights | ||
919 | mLightSet.clear(); | ||
920 | gPipeline.mObjectPartition->getLights(getPositionAgent(), getRadius(), mLightSet); | ||
921 | const U32 max_lights = 16; | ||
922 | if (mLightSet.size() > max_lights) | ||
923 | { | ||
924 | typedef std::set<std::pair<F32,LLPointer<LLDrawable> > > sorted_pair_set_t; | ||
925 | sorted_pair_set_t sorted_set; | ||
926 | for (drawable_set_t::iterator iter = mLightSet.begin(); iter != mLightSet.end(); iter++) | ||
927 | { | ||
928 | LLDrawable* drawable = *iter; | ||
929 | LLVector3 dvec = drawable->getPositionAgent() - getPositionAgent(); | ||
930 | F32 dist2 = dvec.magVecSquared(); | ||
931 | sorted_set.insert(std::make_pair(dist2, drawable)); | ||
932 | } | ||
933 | mLightSet.clear(); | ||
934 | S32 count = 0; | ||
935 | for (sorted_pair_set_t::iterator iter = sorted_set.begin(); iter != sorted_set.end(); iter++) | ||
936 | { | ||
937 | if (++count > 16) | ||
938 | break; | ||
939 | mLightSet.insert((*iter).second); | ||
940 | } | ||
941 | } | ||
942 | } | ||
943 | } | ||
944 | |||
945 | void LLDrawable::updateSpecialHoverCursor(BOOL enabled) | ||
946 | { | ||
947 | // TODO: maintain a list of objects that have special | ||
948 | // hover cursors, then use that list for per-frame | ||
949 | // hover cursor selection. JC | ||
950 | } | ||
951 | |||
952 | BOOL LLDrawable::updateLighting(BOOL do_lighting) | ||
953 | { | ||
954 | if (do_lighting) | ||
955 | { | ||
956 | if (gPipeline.getLightingDetail() >= 2 && (getLit() || isLight())) | ||
957 | { | ||
958 | LLFastTimer t(LLFastTimer::FTM_UPDATE_LIGHTS); | ||
959 | updateLightSet(); | ||
960 | do_lighting = isLight() ? FALSE : TRUE; | ||
961 | } | ||
962 | else | ||
963 | { | ||
964 | do_lighting = FALSE; | ||
965 | } | ||
966 | } | ||
967 | if (gPipeline.getLightingDetail() >= 2) | ||
968 | { | ||
969 | LLFastTimer t(LLFastTimer::FTM_GEO_LIGHT); | ||
970 | if (mVObjp->updateLighting(do_lighting)) | ||
971 | { | ||
972 | setState(LIGHTING_BUILT); | ||
973 | } | ||
974 | } | ||
975 | |||
976 | return TRUE; | ||
977 | } | ||
978 | |||
979 | void LLDrawable::applyLightsAsPoint(LLColor4& result) | ||
980 | { | ||
981 | LLMemType mt1(LLMemType::MTYPE_DRAWABLE); | ||
982 | |||
983 | LLVector3 point_agent(getPositionAgent()); | ||
984 | LLVector3 normal(-gCamera->getXAxis()); // make point agent face camera | ||
985 | |||
986 | F32 sun_int = normal * gPipeline.mSunDir; | ||
987 | LLColor4 color(gSky.getTotalAmbientColor()); | ||
988 | color += gPipeline.mSunDiffuse * sun_int; | ||
989 | |||
990 | for (drawable_set_t::iterator iter = mLightSet.begin(); | ||
991 | iter != mLightSet.end(); ++iter) | ||
992 | { | ||
993 | LLDrawable* drawable = *iter; | ||
994 | LLVOVolume* light = drawable->getVOVolume(); | ||
995 | if (!light) | ||
996 | { | ||
997 | continue; | ||
998 | } | ||
999 | LLColor4 light_color; | ||
1000 | light->calcLightAtPoint(point_agent, normal, light_color); | ||
1001 | color += light_color; | ||
1002 | } | ||
1003 | |||
1004 | // Clamp the color... | ||
1005 | color.mV[0] = llmax(color.mV[0], 0.f); | ||
1006 | color.mV[1] = llmax(color.mV[1], 0.f); | ||
1007 | color.mV[2] = llmax(color.mV[2], 0.f); | ||
1008 | |||
1009 | F32 max_color = llmax(color.mV[0], color.mV[1], color.mV[2]); | ||
1010 | if (max_color > 1.f) | ||
1011 | { | ||
1012 | color *= 1.f/max_color; | ||
1013 | } | ||
1014 | |||
1015 | result = color; | ||
1016 | } | ||
1017 | |||
1018 | F32 LLDrawable::getVisibilityRadius() const | ||
1019 | { | ||
1020 | if (isDead()) | ||
1021 | { | ||
1022 | return 0.f; | ||
1023 | } | ||
1024 | else if (isLight()) | ||
1025 | { | ||
1026 | return llmax(getRadius(), getVOVolume()->getLightRadius()); | ||
1027 | } | ||
1028 | else | ||
1029 | { | ||
1030 | return getRadius(); | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | void LLDrawable::updateUVMinMax() | ||
1035 | { | ||
1036 | } | ||
1037 | |||
1038 | void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp, const S32 offset) | ||
1039 | { | ||
1040 | mSpatialGroupp = groupp; | ||
1041 | |||
1042 | if (mSpatialGroupp) | ||
1043 | { | ||
1044 | mSpatialGroupOffset = offset; | ||
1045 | } | ||
1046 | else | ||
1047 | { | ||
1048 | mSpatialGroupOffset = -1; | ||
1049 | } | ||
1050 | } | ||
1051 | |||
1052 | LLSpatialPartition* LLDrawable::getSpatialPartition() | ||
1053 | { | ||
1054 | LLSpatialPartition* retval = NULL; | ||
1055 | |||
1056 | if (mVObjp->isHUDAttachment()) | ||
1057 | { //HUD attachments don't get space partitioned | ||
1058 | return NULL; | ||
1059 | } | ||
1060 | |||
1061 | if (!mVObjp || | ||
1062 | !getVOVolume() || | ||
1063 | isStatic()) | ||
1064 | { | ||
1065 | retval = gPipeline.mObjectPartition; | ||
1066 | } | ||
1067 | |||
1068 | //must be an active volume | ||
1069 | if (!retval && isRoot()) | ||
1070 | { | ||
1071 | if (!mSpatialBridge) | ||
1072 | { | ||
1073 | setSpatialBridge(new LLSpatialBridge(this)); | ||
1074 | } | ||
1075 | return mSpatialBridge->asPartition(); | ||
1076 | } | ||
1077 | else if (!retval) | ||
1078 | { | ||
1079 | retval = getParent()->getSpatialPartition(); | ||
1080 | } | ||
1081 | |||
1082 | if (retval && mSpatialBridge.notNull()) | ||
1083 | { | ||
1084 | mSpatialBridge->markDead(); | ||
1085 | setSpatialBridge(NULL); | ||
1086 | } | ||
1087 | |||
1088 | return retval; | ||
1089 | } | ||
1090 | |||
1091 | //======================================= | ||
1092 | // Spatial Partition Bridging Drawable | ||
1093 | //======================================= | ||
1094 | |||
1095 | LLSpatialBridge::LLSpatialBridge(LLDrawable* root) | ||
1096 | { | ||
1097 | mDrawable = root; | ||
1098 | root->setSpatialBridge(this); | ||
1099 | |||
1100 | mRenderType = mDrawable->mRenderType; //w00! magic! | ||
1101 | |||
1102 | mOctree->balance(); | ||
1103 | |||
1104 | gPipeline.mObjectPartition->put(this); | ||
1105 | } | ||
1106 | |||
1107 | LLSpatialBridge::~LLSpatialBridge() | ||
1108 | { | ||
1109 | if (getSpatialGroup()) | ||
1110 | { | ||
1111 | gPipeline.mObjectPartition->remove(this, getSpatialGroup()); | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1115 | void LLSpatialBridge::updateSpatialExtents() | ||
1116 | { | ||
1117 | LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0); | ||
1118 | |||
1119 | if (mOctree->getChildCount() > 0) | ||
1120 | { | ||
1121 | LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND); | ||
1122 | root->rebound(); | ||
1123 | } | ||
1124 | |||
1125 | LLXformMatrix* mat = mDrawable->getXform(); | ||
1126 | |||
1127 | LLVector3 offset = root->mBounds[0]; | ||
1128 | LLVector3 size = root->mBounds[1]; | ||
1129 | |||
1130 | LLVector3 center = LLVector3(0,0,0) * mat->getWorldMatrix(); | ||
1131 | LLQuaternion rotation = LLQuaternion(mat->getWorldMatrix()); | ||
1132 | |||
1133 | offset *= rotation; | ||
1134 | center += offset; | ||
1135 | |||
1136 | LLVector3 v[4]; | ||
1137 | //get 4 corners of bounding box | ||
1138 | v[0] = (size * rotation); | ||
1139 | v[1] = (LLVector3(-size.mV[0], -size.mV[1], size.mV[2]) * rotation); | ||
1140 | v[2] = (LLVector3(size.mV[0], -size.mV[1], -size.mV[2]) * rotation); | ||
1141 | v[3] = (LLVector3(-size.mV[0], size.mV[1], -size.mV[2]) * rotation); | ||
1142 | |||
1143 | LLVector3& newMin = mExtents[0]; | ||
1144 | LLVector3& newMax = mExtents[1]; | ||
1145 | |||
1146 | newMin = newMax = center; | ||
1147 | |||
1148 | for (U32 i = 0; i < 4; i++) | ||
1149 | { | ||
1150 | for (U32 j = 0; j < 3; j++) | ||
1151 | { | ||
1152 | F32 delta = fabsf(v[i].mV[j]); | ||
1153 | F32 min = center.mV[j] - delta; | ||
1154 | F32 max = center.mV[j] + delta; | ||
1155 | |||
1156 | if (min < newMin.mV[j]) | ||
1157 | { | ||
1158 | newMin.mV[j] = min; | ||
1159 | } | ||
1160 | |||
1161 | if (max > newMax.mV[j]) | ||
1162 | { | ||
1163 | newMax.mV[j] = max; | ||
1164 | } | ||
1165 | } | ||
1166 | } | ||
1167 | |||
1168 | mPositionGroup.setVec((newMin + newMax) * 0.5f); | ||
1169 | updateBinRadius(); | ||
1170 | } | ||
1171 | |||
1172 | void LLSpatialBridge::updateBinRadius() | ||
1173 | { | ||
1174 | F32 rad = ((mExtents[1]-mExtents[0])*0.5f).magVec(); | ||
1175 | mBinRadius = llmax(rad, 2.f); | ||
1176 | mRadius = rad; | ||
1177 | } | ||
1178 | |||
1179 | LLCamera LLSpatialBridge::transformCamera(LLCamera& camera) | ||
1180 | { | ||
1181 | LLCamera ret = camera; | ||
1182 | LLXformMatrix* mat = mDrawable->getXform(); | ||
1183 | LLVector3 center = LLVector3(0,0,0) * mat->getWorldMatrix(); | ||
1184 | //LLQuaternion rotation = LLQuaternion(mat->getWorldMatrix()); | ||
1185 | |||
1186 | //ret.rotate(~mat->getRotation()); | ||
1187 | LLVector3 delta = ret.getOrigin() - center; | ||
1188 | delta *= ~mat->getRotation(); | ||
1189 | ret.setOrigin(delta); | ||
1190 | |||
1191 | return ret; | ||
1192 | } | ||
1193 | |||
1194 | void LLDrawable::setVisible(LLCamera& camera, std::vector<LLDrawable*>* results, BOOL for_select) | ||
1195 | { | ||
1196 | mVisible = sCurVisible; | ||
1197 | } | ||
1198 | |||
1199 | void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results, BOOL for_select) | ||
1200 | { | ||
1201 | LLVector3 center = (mExtents[0] + mExtents[1]) * 0.5f; | ||
1202 | LLVector3 size = (mExtents[1]-mExtents[0]) * 0.5f; | ||
1203 | |||
1204 | if (camera_in.AABBInFrustum(center, size)) | ||
1205 | { | ||
1206 | LLVector3 lookAt = center - camera_in.getOrigin(); | ||
1207 | F32 distSqr = lookAt.magVecSquared(); | ||
1208 | F32 objRad = size.magVecSquared(); | ||
1209 | |||
1210 | if (objRad/distSqr < SG_MIN_DIST_RATIO*4) | ||
1211 | { | ||
1212 | return; | ||
1213 | } | ||
1214 | |||
1215 | LLDrawable::setVisible(camera_in); | ||
1216 | |||
1217 | if (for_select) | ||
1218 | { | ||
1219 | results->push_back(mDrawable); | ||
1220 | for (U32 i = 0; i < mDrawable->getChildCount(); i++) | ||
1221 | { | ||
1222 | results->push_back(mDrawable->getChild(i)); | ||
1223 | } | ||
1224 | } | ||
1225 | else | ||
1226 | { | ||
1227 | const LLVector3* extents = mDrawable->getSpatialExtents(); | ||
1228 | objRad = mDrawable->getRadius(); | ||
1229 | objRad *= objRad; | ||
1230 | |||
1231 | if (objRad/distSqr > SG_MIN_DIST_RATIO) | ||
1232 | { | ||
1233 | gPipeline.markNotCulled(mDrawable, camera_in); | ||
1234 | } | ||
1235 | |||
1236 | for (U32 i = 0; i < mDrawable->getChildCount(); i++) | ||
1237 | { | ||
1238 | LLDrawable* child = mDrawable->getChild(i); | ||
1239 | extents = child->getSpatialExtents(); | ||
1240 | objRad = child->getRadius(); | ||
1241 | objRad *= objRad; | ||
1242 | |||
1243 | if (objRad/distSqr > SG_MIN_DIST_RATIO) | ||
1244 | { | ||
1245 | gPipeline.markNotCulled(mDrawable->getChild(i), camera_in); | ||
1246 | } | ||
1247 | } | ||
1248 | } | ||
1249 | } | ||
1250 | } | ||
1251 | |||
1252 | void LLSpatialBridge::updateDistance(LLCamera& camera_in) | ||
1253 | { | ||
1254 | LLCamera camera = transformCamera(camera_in); | ||
1255 | |||
1256 | mDrawable->updateDistance(camera); | ||
1257 | |||
1258 | for (U32 i = 0; i < mDrawable->getChildCount(); ++i) | ||
1259 | { | ||
1260 | mDrawable->getChild(i)->updateDistance(camera); | ||
1261 | } | ||
1262 | } | ||
1263 | |||
1264 | void LLSpatialBridge::makeActive() | ||
1265 | { //it is an error to make a spatial bridge active (it's already active) | ||
1266 | llerrs << "makeActive called on spatial bridge" << llendl; | ||
1267 | } | ||
1268 | |||
1269 | void LLSpatialBridge::makeStatic() | ||
1270 | { | ||
1271 | llerrs << "makeStatic called on spatial bridge" << llendl; | ||
1272 | } | ||
1273 | |||
1274 | void LLSpatialBridge::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate) | ||
1275 | { | ||
1276 | LLSpatialPartition::move(drawablep, curp, immediate); | ||
1277 | gPipeline.markMoved(this, FALSE); | ||
1278 | } | ||
1279 | |||
1280 | BOOL LLSpatialBridge::updateMove() | ||
1281 | { | ||
1282 | mOctree->balance(); | ||
1283 | gPipeline.mObjectPartition->move(this, getSpatialGroup(), TRUE); | ||
1284 | return TRUE; | ||
1285 | } | ||
1286 | |||
1287 | void LLSpatialBridge::shiftPos(const LLVector3& vec) | ||
1288 | { | ||
1289 | mExtents[0] += vec; | ||
1290 | mExtents[1] += vec; | ||
1291 | mPositionGroup += LLVector3d(vec); | ||
1292 | } | ||
1293 | |||
1294 | void LLSpatialBridge::cleanupReferences() | ||
1295 | { | ||
1296 | LLDrawable::cleanupReferences(); | ||
1297 | if (mDrawable) | ||
1298 | { | ||
1299 | mDrawable->setSpatialGroup(NULL, -1); | ||
1300 | for (U32 i = 0; i < mDrawable->getChildCount(); i++) | ||
1301 | { | ||
1302 | LLDrawable* drawable = mDrawable->getChild(i); | ||
1303 | if (drawable && drawable->getVOVolume()) | ||
1304 | { | ||
1305 | drawable->setSpatialGroup(NULL, -1); | ||
1306 | } | ||
1307 | } | ||
1308 | |||
1309 | LLDrawable* drawablep = mDrawable; | ||
1310 | mDrawable = NULL; | ||
1311 | drawablep->setSpatialBridge(NULL); | ||
1312 | } | ||
1313 | } | ||
1314 | |||
1315 | const LLVector3 LLDrawable::getPositionAgent() const | ||
1316 | { | ||
1317 | if (getVOVolume()) | ||
1318 | { | ||
1319 | if (isActive()) | ||
1320 | { | ||
1321 | if (isRoot()) | ||
1322 | { | ||
1323 | return LLVector3(0,0,0) * getWorldMatrix(); | ||
1324 | } | ||
1325 | else | ||
1326 | { | ||
1327 | return mVObjp->getPosition() * getParent()->getWorldMatrix(); | ||
1328 | } | ||
1329 | } | ||
1330 | else | ||
1331 | { | ||
1332 | return mVObjp->getPositionAgent(); | ||
1333 | } | ||
1334 | } | ||
1335 | else | ||
1336 | { | ||
1337 | return getWorldPosition(); | ||
1338 | } | ||
1339 | } | ||
1340 | |||