aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llflexibleobject.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llflexibleobject.cpp
parentREADME.txt (diff)
downloadmeta-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/llflexibleobject.cpp')
-rw-r--r--linden/indra/newview/llflexibleobject.cpp851
1 files changed, 851 insertions, 0 deletions
diff --git a/linden/indra/newview/llflexibleobject.cpp b/linden/indra/newview/llflexibleobject.cpp
new file mode 100644
index 0000000..7e748f6
--- /dev/null
+++ b/linden/indra/newview/llflexibleobject.cpp
@@ -0,0 +1,851 @@
1/**
2 * @file llflexibleobject.cpp
3 * @brief Flexible object implementation
4 *
5 * Copyright (c) 2006-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 "pipeline.h"
31#include "lldrawpoolbump.h"
32#include "llface.h"
33#include "llflexibleobject.h"
34#include "llglheaders.h"
35#include "llsphere.h"
36#include "llviewerobject.h"
37#include "llimagegl.h"
38#include "llagent.h"
39#include "llsky.h"
40#include "llviewercamera.h"
41#include "llviewerimagelist.h"
42#include "llviewercontrol.h"
43#include "llviewerobjectlist.h"
44#include "llviewerregion.h"
45#include "llworld.h"
46
47/*static*/ LLVolumeImplFlexible::lodset_t LLVolumeImplFlexible::sLODBins[ FLEXIBLE_OBJECT_MAX_LOD ];
48/*static*/ U64 LLVolumeImplFlexible::sCurrentUpdateFrame = 0;
49/*static*/ U32 LLVolumeImplFlexible::sDebugInserted = 0;
50/*static*/ U32 LLVolumeImplFlexible::sDebugVisible = 0;
51
52/*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f;
53
54// LLFlexibleObjectData::pack/unpack now in llprimitive.cpp
55
56//-----------------------------------------------
57// constructor
58//-----------------------------------------------
59LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectData* attributes) :
60 mVO(vo), mAttributes(attributes)
61{
62 mInitialized = FALSE;
63 mUpdated = FALSE;
64 mJustShifted = FALSE;
65 mInitializedRes = -1;
66 mSimulateRes = 0;
67 mFrameNum = 0;
68 mLastUpdate = 0;
69
70}//-----------------------------------------------
71
72LLVector3 LLVolumeImplFlexible::getFramePosition() const
73{
74 return mVO->getRenderPosition();
75}
76
77LLQuaternion LLVolumeImplFlexible::getFrameRotation() const
78{
79 return mVO->getRenderRotation();
80}
81
82void LLVolumeImplFlexible::onParameterChanged(U16 param_type, LLNetworkData *data, BOOL in_use, bool local_origin)
83{
84 if (param_type == LLNetworkData::PARAMS_FLEXIBLE)
85 {
86 mAttributes = (LLFlexibleObjectData*)data;
87 setAttributesOfAllSections();
88 }
89}
90
91void LLVolumeImplFlexible::onShift(const LLVector3 &shift_vector)
92{
93 for (int section = 0; section < (1<<FLEXIBLE_OBJECT_MAX_SECTIONS)+1; ++section)
94 {
95 mSection[section].mPosition += shift_vector;
96 }
97 mVO->getVolume()->mBounds[0] += shift_vector;
98}
99
100//-----------------------------------------------------------------------------------------------
101void LLVolumeImplFlexible::setParentPositionAndRotationDirectly( LLVector3 p, LLQuaternion r )
102{
103 mParentPosition = p;
104 mParentRotation = r;
105
106}//-----------------------------------------------------------------------------------------------------
107
108void LLVolumeImplFlexible::remapSections(LLFlexibleObjectSection *source, S32 source_sections,
109 LLFlexibleObjectSection *dest, S32 dest_sections)
110{
111 S32 num_output_sections = 1<<dest_sections;
112 LLVector3 scale = mVO->mDrawable->getScale();
113 F32 source_section_length = scale.mV[VZ] / (F32)(1<<source_sections);
114 F32 section_length = scale.mV[VZ] / (F32)num_output_sections;
115 if (source_sections == -1)
116 {
117 // Generate all from section 0
118 dest[0] = source[0];
119 for (S32 section=0; section<num_output_sections; ++section)
120 {
121 dest[section+1] = dest[section];
122 dest[section+1].mPosition += dest[section].mDirection * section_length;
123 dest[section+1].mVelocity.setVec( LLVector3::zero );
124 }
125 }
126 else if (source_sections > dest_sections)
127 {
128 // Copy, skipping sections
129
130 S32 num_steps = 1<<(source_sections-dest_sections);
131
132 // Copy from left to right since it may be an in-place computation
133 for (S32 section=0; section<num_output_sections; ++section)
134 {
135 dest[section+1] = source[(section+1)*num_steps];
136 }
137 dest[0] = source[0];
138 }
139 else if (source_sections < dest_sections)
140 {
141 // Interpolate section info
142 // Iterate from right to left since it may be an in-place computation
143 S32 step_shift = dest_sections-source_sections;
144 S32 num_steps = 1<<step_shift;
145 for (S32 section=num_output_sections-num_steps; section>=0; section -= num_steps)
146 {
147 LLFlexibleObjectSection *last_source_section = &source[section>>step_shift];
148 LLFlexibleObjectSection *source_section = &source[(section>>step_shift)+1];
149
150 // Cubic interpolation of position
151 // At^3 + Bt^2 + Ct + D = f(t)
152 LLVector3 D = last_source_section->mPosition;
153 LLVector3 C = last_source_section->mdPosition * source_section_length;
154 LLVector3 Y = source_section->mdPosition * source_section_length - C; // Helper var
155 LLVector3 X = (source_section->mPosition - D - C); // Helper var
156 LLVector3 A = Y - 2*X;
157 LLVector3 B = X - A;
158
159 F32 t_inc = 1.f/F32(num_steps);
160 F32 t = t_inc;
161 for (S32 step=1; step<num_steps; ++step)
162 {
163 dest[section+step].mScale =
164 lerp(last_source_section->mScale, source_section->mScale, t);
165 dest[section+step].mAxisRotation =
166 slerp(t, last_source_section->mAxisRotation, source_section->mAxisRotation);
167
168 // Evaluate output interpolated values
169 F32 t_sq = t*t;
170 dest[section+step].mPosition = t_sq*(t*A + B) + t*C + D;
171 dest[section+step].mRotation =
172 slerp(t, last_source_section->mRotation, source_section->mRotation);
173 dest[section+step].mVelocity = lerp(last_source_section->mVelocity, source_section->mVelocity, t);
174 dest[section+step].mDirection = lerp(last_source_section->mDirection, source_section->mDirection, t);
175 dest[section+step].mdPosition = lerp(last_source_section->mdPosition, source_section->mdPosition, t);
176 dest[section+num_steps] = *source_section;
177 t += t_inc;
178 }
179 }
180 dest[0] = source[0];
181 }
182 else
183 {
184 // numbers are equal. copy info
185 for (S32 section=0; section <= num_output_sections; ++section)
186 {
187 dest[section] = source[section];
188 }
189 }
190}
191
192
193//-----------------------------------------------------------------------------
194void LLVolumeImplFlexible::setAttributesOfAllSections()
195{
196 LLVector2 bottom_scale, top_scale;
197 F32 begin_rot = 0, end_rot = 0;
198 if (mVO->getVolume())
199 {
200 const LLPathParams &params = mVO->getVolume()->getParams().getPathParams();
201 bottom_scale = params.getBeginScale();
202 top_scale = params.getEndScale();
203 begin_rot = F_PI * params.getTwistBegin();
204 end_rot = F_PI * params.getTwist();
205 }
206
207 S32 num_sections = 1 << mSimulateRes;
208
209
210 LLVector3 scale = mVO->mDrawable->getScale();
211
212 mSection[0].mPosition = getAnchorPosition();
213 mSection[0].mDirection = LLVector3::z_axis * getFrameRotation();
214 mSection[0].mdPosition = mSection[0].mDirection;
215 mSection[0].mScale.setVec(scale.mV[VX]*bottom_scale.mV[0], scale.mV[VY]*bottom_scale.mV[1]);
216 mSection[0].mVelocity.setVec(0,0,0);
217 mSection[0].mAxisRotation.setQuat(begin_rot,0,0,1);
218
219 LLVector3 parentSectionPosition = mSection[0].mPosition;
220 LLVector3 last_direction = mSection[0].mDirection;
221
222 remapSections(mSection, mInitializedRes, mSection, mSimulateRes);
223 mInitializedRes = mSimulateRes;
224
225 F32 t_inc = 1.f/F32(num_sections);
226 F32 t = t_inc;
227 for ( int i=1; i<= num_sections; i++)
228 {
229 mSection[i].mAxisRotation.setQuat(lerp(begin_rot,end_rot,t),0,0,1);
230 mSection[i].mScale = LLVector2(
231 scale.mV[VX] * lerp(bottom_scale.mV[0], top_scale.mV[0], t),
232 scale.mV[VY] * lerp(bottom_scale.mV[1], top_scale.mV[1], t));
233 t += t_inc;
234 }
235 mLastUpdate = 0;
236}//-----------------------------------------------------------------------------------
237
238
239void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, const S32 detail)
240{
241 doIdleUpdate(gAgent, *gWorldp, 0.0);
242 if (mVO && mVO->mDrawable.notNull())
243 {
244 gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
245 gPipeline.markMoved(mVO->mDrawable);
246 }
247}
248
249//---------------------------------------------------------------------------------
250// This calculates the physics of the flexible object. Note that it has to be 0
251// updated every time step. In the future, perhaps there could be an
252// optimization similar to what Havok does for objects that are stationary.
253//---------------------------------------------------------------------------------
254BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
255{
256 if (mVO->mDrawable.isNull())
257 {
258 // Don't do anything until we have a drawable
259 return TRUE;
260 }
261
262 //flexible objects never go static
263 mVO->mDrawable->mQuietCount = 0;
264 if (!mVO->mDrawable->isRoot())
265 {
266 mVO->mDrawable->getParent()->mQuietCount = 0;
267 }
268
269 if (((LLVOVolume*)mVO)->mLODChanged ||
270 mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1))
271 {
272 mLastUpdate = 0; // Force an immediate update
273 }
274 // Relegate invisible objects to the lowest priority bin
275 S32 lod = 0;
276 F32 app_angle = mVO->getAppAngle()*DEG_TO_RAD/gCamera->getView();
277 if (mVO->mDrawable->isVisible())
278 {
279 sDebugVisible++;
280 if (mVO->isSelected())
281 {
282 // Force selected objects to update *every* frame
283 lod = FLEXIBLE_OBJECT_MAX_LOD-1;
284 }
285 else
286 {
287 if (app_angle > 0)
288 {
289 lod = 5 - (S32)(1.0f/sqrtf(app_angle));
290 if (lod < 1)
291 {
292 lod = 1;
293 }
294 }
295
296 if (mVO->isAttachment())
297 {
298 lod += 3;
299 }
300 }
301 }
302
303 S32 new_res = mAttributes->getSimulateLOD();
304 // Rendering sections increases with visible angle on the screen
305 mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle);
306 if (mRenderRes > FLEXIBLE_OBJECT_MAX_SECTIONS)
307 {
308 mRenderRes = FLEXIBLE_OBJECT_MAX_SECTIONS;
309 }
310 // Bottom cap at 1/4 the original number of sections
311 if (mRenderRes < mAttributes->getSimulateLOD()-1)
312 {
313 mRenderRes = mAttributes->getSimulateLOD()-1;
314 }
315 // Throttle back simulation of segments we're not rendering
316 if (mRenderRes < new_res)
317 {
318 new_res = mRenderRes;
319 }
320
321 if (!mInitialized || (mSimulateRes != new_res))
322 {
323 mSimulateRes = new_res;
324 setAttributesOfAllSections();
325 mInitialized = TRUE;
326 }
327
328 sLODBins[lod].insert(this);
329 sDebugInserted++;
330 return TRUE;
331}
332
333// static
334void LLVolumeImplFlexible::resetUpdateBins()
335{
336 U32 lod;
337 for (lod=0; lod<FLEXIBLE_OBJECT_MAX_LOD; ++lod)
338 {
339 sLODBins[lod].clear();
340 }
341 ++sCurrentUpdateFrame;
342 sDebugInserted = 0;
343 sDebugVisible = 0;
344}
345
346inline S32 log2(S32 x)
347{
348 S32 ret = 0;
349 while (x > 1)
350 {
351 ++ret;
352 x >>= 1;
353 }
354 return ret;
355}
356
357// static
358void LLVolumeImplFlexible::doFlexibleUpdateBins()
359{
360 U32 lod;
361 U32 updated = 0;
362 U32 regen = 0;
363 U32 newflexies = 0;
364 F32 time_alloc[FLEXIBLE_OBJECT_MAX_LOD];
365 F32 total_time_alloc = 0;
366
367 bool new_objects_only = false;
368
369 if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))
370 {
371 new_objects_only = true;
372 }
373
374 for (lod=0; lod<FLEXIBLE_OBJECT_MAX_LOD; ++lod)
375 {
376 int count = sLODBins[lod].size();
377 if (count > 0)
378 {
379 time_alloc[lod] = (F32)((lod+1)*(log2(count)));
380 }
381 else
382 {
383 time_alloc[lod] = 0;
384 }
385 total_time_alloc += time_alloc[lod];
386 }
387 total_time_alloc = FLEXIBLE_OBJECT_TIMESLICE * (sUpdateFactor+0.01f) / total_time_alloc;
388
389 {
390 LLFastTimer t(LLFastTimer::FTM_FLEXIBLE_UPDATE);
391 LLTimer timer;
392 for (lod=0; lod<FLEXIBLE_OBJECT_MAX_LOD; ++lod)
393 {
394 LLVolumeImplFlexible::lodset_t::iterator itor = sLODBins[lod].begin();
395 int bin_count = 0;
396 if (!new_objects_only)
397 {
398 timer.reset();
399 double end_time = time_alloc[lod] * total_time_alloc;
400 for (; itor!=sLODBins[lod].end(); ++itor)
401 {
402
403 (*itor)->doFlexibleUpdate();
404 ++updated;
405 (*itor)->doFlexibleRebuild();
406 ++bin_count;
407 ++regen;
408 if (timer.getElapsedTimeF64() > end_time)
409 {
410 break;
411 }
412 }
413 }
414 for (; itor != sLODBins[lod].end(); ++itor)
415 {
416 if ((*itor)->getLastUpdate() == 0)
417 {
418 // *Always* update newly-created objects, or objects which have changed LOD
419 (*itor)->doFlexibleUpdate();
420 (*itor)->doFlexibleRebuild();
421 ++newflexies;
422 }
423 }
424 }
425 }
426}
427
428void LLVolumeImplFlexible::doFlexibleUpdate()
429{
430 LLPath *path = &mVO->getVolume()->getPath();
431 S32 num_sections = 1 << mSimulateRes;
432
433 F32 secondsThisFrame = mTimer.getElapsedTimeAndResetF32();
434 if (secondsThisFrame > 0.2f)
435 {
436 secondsThisFrame = 0.2f;
437 }
438
439 LLVector3 BasePosition = getFramePosition();
440 LLQuaternion BaseRotation = getFrameRotation();
441 LLQuaternion parentSegmentRotation = BaseRotation;
442 LLVector3 anchorDirectionRotated = LLVector3::z_axis * parentSegmentRotation;
443 LLVector3 anchorScale = mVO->mDrawable->getScale();
444
445 F32 section_length = anchorScale.mV[VZ] / (F32)num_sections;
446 F32 inv_section_length = 1.f / section_length;
447
448 S32 i;
449
450 // ANCHOR position is offset from BASE position (centroid) by half the length
451 LLVector3 AnchorPosition = BasePosition - (anchorScale.mV[VZ]/2 * anchorDirectionRotated);
452
453 mSection[0].mPosition = AnchorPosition;
454 mSection[0].mDirection = anchorDirectionRotated;
455 mSection[0].mRotation = BaseRotation;
456
457 LLQuaternion deltaRotation;
458
459 LLVector3 lastPosition;
460
461 // Coefficients which are constant across sections
462 F32 t_factor = mAttributes->getTension() * 0.1f;
463 t_factor = t_factor*(1 - pow(0.85f, secondsThisFrame*30));
464 if ( t_factor > FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE )
465 {
466 t_factor = FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE;
467 }
468
469 F32 friction_coeff = (mAttributes->getAirFriction()*2+1);
470 friction_coeff = pow(10.f, friction_coeff*secondsThisFrame);
471 friction_coeff = (friction_coeff > 1) ? friction_coeff : 1;
472 F32 momentum = 1.0f / friction_coeff;
473
474 F32 wind_factor = (mAttributes->getWindSensitivity()*0.1f) * section_length * secondsThisFrame;
475 F32 max_angle = atan(section_length*2.f);
476
477 F32 force_factor = section_length * secondsThisFrame;
478
479 // Update simulated sections
480 for (i=1; i<=num_sections; ++i)
481 {
482 LLVector3 parentSectionVector;
483 LLVector3 parentSectionPosition;
484 LLVector3 parentDirection;
485
486 //---------------------------------------------------
487 // save value of position as lastPosition
488 //---------------------------------------------------
489 lastPosition = mSection[i].mPosition;
490
491 //------------------------------------------------------------------------------------------
492 // gravity
493 //------------------------------------------------------------------------------------------
494 mSection[i].mPosition.mV[2] -= mAttributes->getGravity() * force_factor;
495
496 //------------------------------------------------------------------------------------------
497 // wind force
498 //------------------------------------------------------------------------------------------
499 if (mAttributes->getWindSensitivity() > 0.001f)
500 {
501 mSection[i].mPosition += gAgent.getRegion()->mWind.getVelocity( mSection[i].mPosition ) * wind_factor;
502 }
503
504 //------------------------------------------------------------------------------------------
505 // user-defined force
506 //------------------------------------------------------------------------------------------
507 mSection[i].mPosition += mAttributes->getUserForce() * force_factor;
508
509 //---------------------------------------------------
510 // tension (rigidity, stiffness)
511 //---------------------------------------------------
512 parentSectionPosition = mSection[i-1].mPosition;
513 parentDirection = mSection[i-1].mDirection;
514
515 if ( i == 1 )
516 {
517 parentSectionVector = mSection[0].mDirection;
518 }
519 else
520 {
521 parentSectionVector = mSection[i-2].mDirection;
522 }
523
524 LLVector3 currentVector = mSection[i].mPosition - parentSectionPosition;
525
526 LLVector3 difference = (parentSectionVector*section_length) - currentVector;
527 LLVector3 tensionForce = difference * t_factor;
528
529 mSection[i].mPosition += tensionForce;
530
531 //------------------------------------------------------------------------------------------
532 // sphere collision, currently not used
533 //------------------------------------------------------------------------------------------
534 /*if ( mAttributes->mUsingCollisionSphere )
535 {
536 LLVector3 vectorToCenterOfCollisionSphere = mCollisionSpherePosition - mSection[i].mPosition;
537 if ( vectorToCenterOfCollisionSphere.magVecSquared() < mCollisionSphereRadius * mCollisionSphereRadius )
538 {
539 F32 distanceToCenterOfCollisionSphere = vectorToCenterOfCollisionSphere.magVec();
540 F32 penetration = mCollisionSphereRadius - distanceToCenterOfCollisionSphere;
541
542 LLVector3 normalToCenterOfCollisionSphere;
543
544 if ( distanceToCenterOfCollisionSphere > 0.0f )
545 {
546 normalToCenterOfCollisionSphere = vectorToCenterOfCollisionSphere / distanceToCenterOfCollisionSphere;
547 }
548 else // rare
549 {
550 normalToCenterOfCollisionSphere = LLVector3::x_axis; // arbitrary
551 }
552
553 // push the position out to the surface of the collision sphere
554 mSection[i].mPosition -= normalToCenterOfCollisionSphere * penetration;
555 }
556 }*/
557
558 //------------------------------------------------------------------------------------------
559 // inertia
560 //------------------------------------------------------------------------------------------
561 mSection[i].mPosition += mSection[i].mVelocity * momentum;
562
563 //------------------------------------------------------------------------------------------
564 // clamp length & rotation
565 //------------------------------------------------------------------------------------------
566 mSection[i].mDirection = mSection[i].mPosition - parentSectionPosition;
567 mSection[i].mDirection.normVec();
568 deltaRotation.shortestArc( parentDirection, mSection[i].mDirection );
569
570 F32 angle;
571 LLVector3 axis;
572 deltaRotation.getAngleAxis(&angle, axis);
573 if (angle > F_PI) angle -= 2.f*F_PI;
574 if (angle < -F_PI) angle += 2.f*F_PI;
575 if (angle > max_angle)
576 {
577 //angle = 0.5f*(angle+max_angle);
578 deltaRotation.setQuat(max_angle, axis);
579 } else if (angle < -max_angle)
580 {
581 //angle = 0.5f*(angle-max_angle);
582 deltaRotation.setQuat(-max_angle, axis);
583 }
584 LLQuaternion segment_rotation = parentSegmentRotation * deltaRotation;
585 parentSegmentRotation = segment_rotation;
586
587 mSection[i].mDirection = (parentDirection * deltaRotation);
588 mSection[i].mPosition = parentSectionPosition + mSection[i].mDirection * section_length;
589 mSection[i].mRotation = segment_rotation;
590
591 if (i > 1)
592 {
593 // Propogate half the rotation up to the parent
594 LLQuaternion halfDeltaRotation(angle/2, axis);
595 mSection[i-1].mRotation = mSection[i-1].mRotation * halfDeltaRotation;
596 }
597
598 //------------------------------------------------------------------------------------------
599 // calculate velocity
600 //------------------------------------------------------------------------------------------
601 mSection[i].mVelocity = mSection[i].mPosition - lastPosition;
602 }
603
604 // Calculate derivatives (not necessary until normals are automagically generated)
605 mSection[0].mdPosition = (mSection[1].mPosition - mSection[0].mPosition) * inv_section_length;
606 // i = 1..NumSections-1
607 for (i=1; i<num_sections; ++i)
608 {
609 // Quadratic numerical derivative of position
610
611 // f(-L1) = aL1^2 - bL1 + c = f1
612 // f(0) = c = f2
613 // f(L2) = aL2^2 + bL2 + c = f3
614 // f = ax^2 + bx + c
615 // d/dx f = 2ax + b
616 // d/dx f(0) = b
617
618 // c = f2
619 // a = [(f1-c)/L1 + (f3-c)/L2] / (L1+L2)
620 // b = (f3-c-aL2^2)/L2
621
622 LLVector3 a = (mSection[i-1].mPosition-mSection[i].mPosition +
623 mSection[i+1].mPosition-mSection[i].mPosition) * 0.5f * inv_section_length * inv_section_length;
624 LLVector3 b = (mSection[i+1].mPosition-mSection[i].mPosition - a*(section_length*section_length));
625 b *= inv_section_length;
626
627 mSection[i].mdPosition = b;
628 }
629
630 // i = NumSections
631 mSection[i].mdPosition = (mSection[i].mPosition - mSection[i-1].mPosition) * inv_section_length;
632
633 // Create points
634 S32 num_render_sections = 1<<mRenderRes;
635 path->resizePath(num_render_sections+1);
636
637 LLPath::PathPt *new_point;
638
639 LLFlexibleObjectSection newSection[ (1<<FLEXIBLE_OBJECT_MAX_SECTIONS)+1 ];
640 remapSections(mSection, mSimulateRes, newSection, mRenderRes);
641
642 for (i=0; i<=num_render_sections; ++i)
643 {
644 new_point = &path->mPath[i];
645 new_point->mPos = newSection[i].mPosition;
646 new_point->mRot = mSection[i].mAxisRotation * newSection[i].mRotation;
647 new_point->mScale = newSection[i].mScale;
648 new_point->mTexT = ((F32)i)/(num_render_sections);
649 }
650
651 mLastSegmentRotation = parentSegmentRotation;
652}
653
654void LLVolumeImplFlexible::doFlexibleRebuild()
655{
656 mVO->getVolume()->regen();
657
658 mVO->markForUpdate(TRUE);
659
660 mUpdated = TRUE;
661
662 mLastUpdate = sCurrentUpdateFrame;
663}//------------------------------------------------------------------
664
665void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, BOOL damped)
666{
667 setAttributesOfAllSections();
668}
669
670BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
671{
672 BOOL compiled = FALSE;
673
674 LLVOVolume *volume = (LLVOVolume*)mVO;
675
676 if (volume->mDrawable.isNull()) // Not sure why this is happening, but it is...
677 {
678 return TRUE; // No update to complete
679 }
680
681 volume->calcAllTEsSame();
682
683 if (volume->mVolumeChanged || volume->mFaceMappingChanged)
684 {
685 compiled = TRUE;
686 volume->regenFaces();
687 }
688 else if (volume->mLODChanged)
689 {
690 LLPointer<LLVolume> old_volumep, new_volumep;
691 F32 old_lod, new_lod;
692
693 old_volumep = volume->getVolume();
694 old_lod = old_volumep->getDetail();
695
696 LLVolumeParams volume_params = volume->getVolume()->getParams();
697 volume->setVolume(volume_params, 0);
698 doFlexibleUpdate();
699 volume->getVolume()->regen();
700
701 new_volumep = volume->getVolume();
702 new_lod = new_volumep->getDetail();
703
704 if (new_lod != old_lod)
705 {
706 compiled = TRUE;
707 if (new_volumep->getNumFaces() != old_volumep->getNumFaces())
708 {
709 volume->regenFaces();
710 }
711 }
712 }
713
714 if (mUpdated)
715 {
716 compiled = TRUE;
717 mUpdated = FALSE;
718 }
719
720 if(compiled)
721 {
722 volume->updateRelativeXform(isVolumeGlobal());
723 volume->genTriangles(isVolumeGlobal());
724 LLPipeline::sCompiles++;
725 }
726
727 volume->mVolumeChanged = FALSE;
728 volume->mLODChanged = FALSE;
729 volume->mFaceMappingChanged = FALSE;
730
731 // clear UV flag
732 drawable->clearState(LLDrawable::UV);
733
734 drawable->movePartition();
735
736 return TRUE;
737}
738
739//----------------------------------------------------------------------------------
740void LLVolumeImplFlexible::setCollisionSphere( LLVector3 p, F32 r )
741{
742 mCollisionSpherePosition = p;
743 mCollisionSphereRadius = r;
744
745}//------------------------------------------------------------------
746
747
748//----------------------------------------------------------------------------------
749void LLVolumeImplFlexible::setUsingCollisionSphere( bool u )
750{
751}//------------------------------------------------------------------
752
753
754//----------------------------------------------------------------------------------
755void LLVolumeImplFlexible::setRenderingCollisionSphere( bool r )
756{
757}//------------------------------------------------------------------
758
759//------------------------------------------------------------------
760LLVector3 LLVolumeImplFlexible::getEndPosition()
761{
762 S32 num_sections = 1 << mAttributes->getSimulateLOD();
763 return mSection[ num_sections ].mPosition;
764
765}//------------------------------------------------------------------
766
767
768//------------------------------------------------------------------
769LLVector3 LLVolumeImplFlexible::getNodePosition( int nodeIndex )
770{
771 S32 num_sections = 1 << mAttributes->getSimulateLOD();
772 if ( nodeIndex > num_sections - 1 )
773 {
774 nodeIndex = num_sections - 1;
775 }
776 else if ( nodeIndex < 0 )
777 {
778 nodeIndex = 0;
779 }
780
781 return mSection[ nodeIndex ].mPosition;
782
783}//------------------------------------------------------------------
784
785LLVector3 LLVolumeImplFlexible::getPivotPosition() const
786{
787 return getAnchorPosition();
788}
789
790//------------------------------------------------------------------
791LLVector3 LLVolumeImplFlexible::getAnchorPosition() const
792{
793 LLVector3 BasePosition = getFramePosition();
794 LLQuaternion parentSegmentRotation = getFrameRotation();
795 LLVector3 anchorDirectionRotated = LLVector3::z_axis * parentSegmentRotation;
796 LLVector3 anchorScale = mVO->mDrawable->getScale();
797 return BasePosition - (anchorScale.mV[VZ]/2 * anchorDirectionRotated);
798
799}//------------------------------------------------------------------
800
801
802//------------------------------------------------------------------
803LLQuaternion LLVolumeImplFlexible::getEndRotation()
804{
805 return mLastSegmentRotation;
806
807}//------------------------------------------------------------------
808
809
810void LLVolumeImplFlexible::updateRelativeXform(BOOL global_volume)
811{
812 LLVOVolume* vo = (LLVOVolume*) mVO;
813
814 LLVector3 delta_scale = LLVector3(1,1,1);
815 LLVector3 delta_pos;
816 LLQuaternion delta_rot;
817
818 if (!mVO->mDrawable->isRoot())
819 { //global to parent relative
820 LLViewerObject* parent = (LLViewerObject*) vo->getParent();
821 delta_rot = ~parent->getRenderRotation();
822 delta_pos = -parent->getRenderPosition()*delta_rot;
823 }
824 else
825 { //global to local
826 delta_rot = ~getFrameRotation();
827 delta_pos = -getFramePosition()*delta_rot;
828 }
829
830 // Vertex transform (4x4)
831 LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot;
832 LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot;
833 LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot;
834
835 vo->mRelativeXform.initRows(LLVector4(x_axis, 0.f),
836 LLVector4(y_axis, 0.f),
837 LLVector4(z_axis, 0.f),
838 LLVector4(delta_pos, 1.f));
839
840 x_axis.normVec();
841 y_axis.normVec();
842 z_axis.normVec();
843
844 vo->mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
845
846}
847
848const LLMatrix4& LLVolumeImplFlexible::getWorldMatrix(LLXformMatrix* xform) const
849{
850 return xform->getWorldMatrix();
851}