00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "pipeline.h"
00035 #include "lldrawpoolbump.h"
00036 #include "llface.h"
00037 #include "llflexibleobject.h"
00038 #include "llglheaders.h"
00039 #include "llrendersphere.h"
00040 #include "llviewerobject.h"
00041 #include "llimagegl.h"
00042 #include "llagent.h"
00043 #include "llsky.h"
00044 #include "llviewercamera.h"
00045 #include "llviewerimagelist.h"
00046 #include "llviewercontrol.h"
00047 #include "llviewerobjectlist.h"
00048 #include "llviewerregion.h"
00049 #include "llworld.h"
00050 #include "llvoavatar.h"
00051
00052 F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f;
00053
00054
00055
00056
00057
00058
00059 LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectData* attributes) :
00060 mVO(vo), mAttributes(attributes)
00061 {
00062 static U32 seed = 0;
00063 mID = seed++;
00064 mInitialized = FALSE;
00065 mUpdated = FALSE;
00066 mInitializedRes = -1;
00067 mSimulateRes = 0;
00068 mFrameNum = 0;
00069 mRenderRes = 1;
00070
00071 if(mVO->mDrawable.notNull())
00072 {
00073 mVO->mDrawable->makeActive() ;
00074 }
00075 }
00076
00077 LLVector3 LLVolumeImplFlexible::getFramePosition() const
00078 {
00079 return mVO->getRenderPosition();
00080 }
00081
00082 LLQuaternion LLVolumeImplFlexible::getFrameRotation() const
00083 {
00084 return mVO->getRenderRotation();
00085 }
00086
00087 void LLVolumeImplFlexible::onParameterChanged(U16 param_type, LLNetworkData *data, BOOL in_use, bool local_origin)
00088 {
00089 if (param_type == LLNetworkData::PARAMS_FLEXIBLE)
00090 {
00091 mAttributes = (LLFlexibleObjectData*)data;
00092 setAttributesOfAllSections();
00093 }
00094 }
00095
00096 void LLVolumeImplFlexible::onShift(const LLVector3 &shift_vector)
00097 {
00098 for (int section = 0; section < (1<<FLEXIBLE_OBJECT_MAX_SECTIONS)+1; ++section)
00099 {
00100 mSection[section].mPosition += shift_vector;
00101 }
00102 }
00103
00104
00105 void LLVolumeImplFlexible::setParentPositionAndRotationDirectly( LLVector3 p, LLQuaternion r )
00106 {
00107 mParentPosition = p;
00108 mParentRotation = r;
00109
00110 }
00111
00112 void LLVolumeImplFlexible::remapSections(LLFlexibleObjectSection *source, S32 source_sections,
00113 LLFlexibleObjectSection *dest, S32 dest_sections)
00114 {
00115 S32 num_output_sections = 1<<dest_sections;
00116 LLVector3 scale = mVO->mDrawable->getScale();
00117 F32 source_section_length = scale.mV[VZ] / (F32)(1<<source_sections);
00118 F32 section_length = scale.mV[VZ] / (F32)num_output_sections;
00119 if (source_sections == -1)
00120 {
00121
00122 dest[0] = source[0];
00123 for (S32 section=0; section<num_output_sections; ++section)
00124 {
00125 dest[section+1] = dest[section];
00126 dest[section+1].mPosition += dest[section].mDirection * section_length;
00127 dest[section+1].mVelocity.setVec( LLVector3::zero );
00128 }
00129 }
00130 else if (source_sections > dest_sections)
00131 {
00132
00133
00134 S32 num_steps = 1<<(source_sections-dest_sections);
00135
00136
00137 for (S32 section=0; section<num_output_sections; ++section)
00138 {
00139 dest[section+1] = source[(section+1)*num_steps];
00140 }
00141 dest[0] = source[0];
00142 }
00143 else if (source_sections < dest_sections)
00144 {
00145
00146
00147 S32 step_shift = dest_sections-source_sections;
00148 S32 num_steps = 1<<step_shift;
00149 for (S32 section=num_output_sections-num_steps; section>=0; section -= num_steps)
00150 {
00151 LLFlexibleObjectSection *last_source_section = &source[section>>step_shift];
00152 LLFlexibleObjectSection *source_section = &source[(section>>step_shift)+1];
00153
00154
00155
00156 LLVector3 D = last_source_section->mPosition;
00157 LLVector3 C = last_source_section->mdPosition * source_section_length;
00158 LLVector3 Y = source_section->mdPosition * source_section_length - C;
00159 LLVector3 X = (source_section->mPosition - D - C);
00160 LLVector3 A = Y - 2*X;
00161 LLVector3 B = X - A;
00162
00163 F32 t_inc = 1.f/F32(num_steps);
00164 F32 t = t_inc;
00165 for (S32 step=1; step<num_steps; ++step)
00166 {
00167 dest[section+step].mScale =
00168 lerp(last_source_section->mScale, source_section->mScale, t);
00169 dest[section+step].mAxisRotation =
00170 slerp(t, last_source_section->mAxisRotation, source_section->mAxisRotation);
00171
00172
00173 F32 t_sq = t*t;
00174 dest[section+step].mPosition = t_sq*(t*A + B) + t*C + D;
00175 dest[section+step].mRotation =
00176 slerp(t, last_source_section->mRotation, source_section->mRotation);
00177 dest[section+step].mVelocity = lerp(last_source_section->mVelocity, source_section->mVelocity, t);
00178 dest[section+step].mDirection = lerp(last_source_section->mDirection, source_section->mDirection, t);
00179 dest[section+step].mdPosition = lerp(last_source_section->mdPosition, source_section->mdPosition, t);
00180 dest[section+num_steps] = *source_section;
00181 t += t_inc;
00182 }
00183 }
00184 dest[0] = source[0];
00185 }
00186 else
00187 {
00188
00189 for (S32 section=0; section <= num_output_sections; ++section)
00190 {
00191 dest[section] = source[section];
00192 }
00193 }
00194 }
00195
00196
00197
00198 void LLVolumeImplFlexible::setAttributesOfAllSections(LLVector3* inScale)
00199 {
00200 LLVector2 bottom_scale, top_scale;
00201 F32 begin_rot = 0, end_rot = 0;
00202 if (mVO->getVolume())
00203 {
00204 const LLPathParams ¶ms = mVO->getVolume()->getParams().getPathParams();
00205 bottom_scale = params.getBeginScale();
00206 top_scale = params.getEndScale();
00207 begin_rot = F_PI * params.getTwistBegin();
00208 end_rot = F_PI * params.getTwist();
00209 }
00210
00211 if (!mVO->mDrawable)
00212 {
00213 return;
00214 }
00215
00216 S32 num_sections = 1 << mSimulateRes;
00217
00218 LLVector3 scale;
00219 if (inScale == (LLVector3*)NULL)
00220 {
00221 scale = mVO->mDrawable->getScale();
00222 }
00223 else
00224 {
00225 scale = *inScale;
00226 }
00227
00228 mSection[0].mPosition = getAnchorPosition();
00229 mSection[0].mDirection = LLVector3::z_axis * getFrameRotation();
00230 mSection[0].mdPosition = mSection[0].mDirection;
00231 mSection[0].mScale.setVec(scale.mV[VX]*bottom_scale.mV[0], scale.mV[VY]*bottom_scale.mV[1]);
00232 mSection[0].mVelocity.setVec(0,0,0);
00233 mSection[0].mAxisRotation.setQuat(begin_rot,0,0,1);
00234
00235 LLVector3 parentSectionPosition = mSection[0].mPosition;
00236 LLVector3 last_direction = mSection[0].mDirection;
00237
00238 remapSections(mSection, mInitializedRes, mSection, mSimulateRes);
00239 mInitializedRes = mSimulateRes;
00240
00241 F32 t_inc = 1.f/F32(num_sections);
00242 F32 t = t_inc;
00243
00244 for ( int i=1; i<= num_sections; i++)
00245 {
00246 mSection[i].mAxisRotation.setQuat(lerp(begin_rot,end_rot,t),0,0,1);
00247 mSection[i].mScale = LLVector2(
00248 scale.mV[VX] * lerp(bottom_scale.mV[0], top_scale.mV[0], t),
00249 scale.mV[VY] * lerp(bottom_scale.mV[1], top_scale.mV[1], t));
00250 t += t_inc;
00251 }
00252 }
00253
00254
00255 void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, const S32 detail)
00256 {
00257 }
00258
00259
00260
00261
00262
00263
00264 BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
00265 {
00266 if (mVO->mDrawable.isNull())
00267 {
00268
00269 return FALSE;
00270 }
00271
00272 BOOL force_update = mSimulateRes == 0 ? TRUE : FALSE;
00273
00274
00275 mVO->mDrawable->mQuietCount = 0;
00276 if (!mVO->mDrawable->isRoot())
00277 {
00278 LLViewerObject* parent = (LLViewerObject*) mVO->getParent();
00279 parent->mDrawable->mQuietCount = 0;
00280 }
00281
00282 LLFastTimer ftm(LLFastTimer::FTM_FLEXIBLE_UPDATE);
00283
00284 S32 new_res = mAttributes->getSimulateLOD();
00285
00286
00287 F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, mVO->mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
00288
00289
00290 mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle*DEG_TO_RAD/LLViewerCamera::getInstance()->getView());
00291 if (mRenderRes > FLEXIBLE_OBJECT_MAX_SECTIONS)
00292 {
00293 mRenderRes = FLEXIBLE_OBJECT_MAX_SECTIONS;
00294 }
00295
00296
00297
00298 if (mRenderRes < mAttributes->getSimulateLOD()-1)
00299 {
00300 mRenderRes = mAttributes->getSimulateLOD()-1;
00301 }
00302
00303 if (mRenderRes < new_res)
00304 {
00305 new_res = mRenderRes;
00306 }
00307
00308 if (!mInitialized)
00309 {
00310 mSimulateRes = new_res;
00311 setAttributesOfAllSections();
00312 mInitialized = TRUE;
00313 }
00314 if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE))
00315 {
00316 return FALSE;
00317 }
00318
00319 if (force_update)
00320 {
00321 gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE);
00322 }
00323 else if (mVO->mDrawable->isVisible() &&
00324 !mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) &&
00325 mVO->getPixelArea() > 256.f)
00326 {
00327 U32 id;
00328 F32 pixel_area = mVO->getPixelArea();
00329
00330 if (mVO->isRootEdit())
00331 {
00332 id = mID;
00333 }
00334 else
00335 {
00336 LLVOVolume* parent = (LLVOVolume*) mVO->getParent();
00337 id = parent->getVolumeInterfaceID();
00338 }
00339
00340 U32 update_period = (U32) (LLViewerCamera::getInstance()->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1;
00341
00342 if ((LLDrawable::getCurrentFrame()+id)%update_period == 0)
00343 {
00344 gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE);
00345 }
00346 }
00347
00348 return force_update;
00349 }
00350
00351 inline S32 log2(S32 x)
00352 {
00353 S32 ret = 0;
00354 while (x > 1)
00355 {
00356 ++ret;
00357 x >>= 1;
00358 }
00359 return ret;
00360 }
00361
00362 void LLVolumeImplFlexible::doFlexibleUpdate()
00363 {
00364 LLVolume* volume = mVO->getVolume();
00365 LLPath *path = &volume->getPath();
00366 if (mSimulateRes == 0)
00367 {
00368 mVO->markForUpdate(TRUE);
00369 if (!doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0))
00370 {
00371 return;
00372 }
00373 }
00374
00375 llassert_always(mInitialized);
00376
00377 S32 num_sections = 1 << mSimulateRes;
00378
00379 F32 secondsThisFrame = mTimer.getElapsedTimeAndResetF32();
00380 if (secondsThisFrame > 0.2f)
00381 {
00382 secondsThisFrame = 0.2f;
00383 }
00384
00385 LLVector3 BasePosition = getFramePosition();
00386 LLQuaternion BaseRotation = getFrameRotation();
00387 LLQuaternion parentSegmentRotation = BaseRotation;
00388 LLVector3 anchorDirectionRotated = LLVector3::z_axis * parentSegmentRotation;
00389 LLVector3 anchorScale = mVO->mDrawable->getScale();
00390
00391 F32 section_length = anchorScale.mV[VZ] / (F32)num_sections;
00392 F32 inv_section_length = 1.f / section_length;
00393
00394 S32 i;
00395
00396
00397 LLVector3 AnchorPosition = BasePosition - (anchorScale.mV[VZ]/2 * anchorDirectionRotated);
00398
00399 mSection[0].mPosition = AnchorPosition;
00400 mSection[0].mDirection = anchorDirectionRotated;
00401 mSection[0].mRotation = BaseRotation;
00402
00403 LLQuaternion deltaRotation;
00404
00405 LLVector3 lastPosition;
00406
00407
00408 F32 t_factor = mAttributes->getTension() * 0.1f;
00409 t_factor = t_factor*(1 - pow(0.85f, secondsThisFrame*30));
00410 if ( t_factor > FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE )
00411 {
00412 t_factor = FLEXIBLE_OBJECT_MAX_INTERNAL_TENSION_FORCE;
00413 }
00414
00415 F32 friction_coeff = (mAttributes->getAirFriction()*2+1);
00416 friction_coeff = pow(10.f, friction_coeff*secondsThisFrame);
00417 friction_coeff = (friction_coeff > 1) ? friction_coeff : 1;
00418 F32 momentum = 1.0f / friction_coeff;
00419
00420 F32 wind_factor = (mAttributes->getWindSensitivity()*0.1f) * section_length * secondsThisFrame;
00421 F32 max_angle = atan(section_length*2.f);
00422
00423 F32 force_factor = section_length * secondsThisFrame;
00424
00425
00426 for (i=1; i<=num_sections; ++i)
00427 {
00428 LLVector3 parentSectionVector;
00429 LLVector3 parentSectionPosition;
00430 LLVector3 parentDirection;
00431
00432
00433
00434
00435 lastPosition = mSection[i].mPosition;
00436
00437
00438
00439
00440 mSection[i].mPosition.mV[2] -= mAttributes->getGravity() * force_factor;
00441
00442
00443
00444
00445 if (mAttributes->getWindSensitivity() > 0.001f)
00446 {
00447 mSection[i].mPosition += gAgent.getRegion()->mWind.getVelocity( mSection[i].mPosition ) * wind_factor;
00448 }
00449
00450
00451
00452
00453 mSection[i].mPosition += mAttributes->getUserForce() * force_factor;
00454
00455
00456
00457
00458 parentSectionPosition = mSection[i-1].mPosition;
00459 parentDirection = mSection[i-1].mDirection;
00460
00461 if ( i == 1 )
00462 {
00463 parentSectionVector = mSection[0].mDirection;
00464 }
00465 else
00466 {
00467 parentSectionVector = mSection[i-2].mDirection;
00468 }
00469
00470 LLVector3 currentVector = mSection[i].mPosition - parentSectionPosition;
00471
00472 LLVector3 difference = (parentSectionVector*section_length) - currentVector;
00473 LLVector3 tensionForce = difference * t_factor;
00474
00475 mSection[i].mPosition += tensionForce;
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 mSection[i].mPosition += mSection[i].mVelocity * momentum;
00508
00509
00510
00511
00512 mSection[i].mDirection = mSection[i].mPosition - parentSectionPosition;
00513 mSection[i].mDirection.normVec();
00514 deltaRotation.shortestArc( parentDirection, mSection[i].mDirection );
00515
00516 F32 angle;
00517 LLVector3 axis;
00518 deltaRotation.getAngleAxis(&angle, axis);
00519 if (angle > F_PI) angle -= 2.f*F_PI;
00520 if (angle < -F_PI) angle += 2.f*F_PI;
00521 if (angle > max_angle)
00522 {
00523
00524 deltaRotation.setQuat(max_angle, axis);
00525 } else if (angle < -max_angle)
00526 {
00527
00528 deltaRotation.setQuat(-max_angle, axis);
00529 }
00530 LLQuaternion segment_rotation = parentSegmentRotation * deltaRotation;
00531 parentSegmentRotation = segment_rotation;
00532
00533 mSection[i].mDirection = (parentDirection * deltaRotation);
00534 mSection[i].mPosition = parentSectionPosition + mSection[i].mDirection * section_length;
00535 mSection[i].mRotation = segment_rotation;
00536
00537 if (i > 1)
00538 {
00539
00540 LLQuaternion halfDeltaRotation(angle/2, axis);
00541 mSection[i-1].mRotation = mSection[i-1].mRotation * halfDeltaRotation;
00542 }
00543
00544
00545
00546
00547 mSection[i].mVelocity = mSection[i].mPosition - lastPosition;
00548 if (mSection[i].mVelocity.magVecSquared() > 1.f)
00549 {
00550 mSection[i].mVelocity.normVec();
00551 }
00552 }
00553
00554
00555 mSection[0].mdPosition = (mSection[1].mPosition - mSection[0].mPosition) * inv_section_length;
00556
00557 for (i=1; i<num_sections; ++i)
00558 {
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 LLVector3 a = (mSection[i-1].mPosition-mSection[i].mPosition +
00573 mSection[i+1].mPosition-mSection[i].mPosition) * 0.5f * inv_section_length * inv_section_length;
00574 LLVector3 b = (mSection[i+1].mPosition-mSection[i].mPosition - a*(section_length*section_length));
00575 b *= inv_section_length;
00576
00577 mSection[i].mdPosition = b;
00578 }
00579
00580
00581 mSection[i].mdPosition = (mSection[i].mPosition - mSection[i-1].mPosition) * inv_section_length;
00582
00583
00584 S32 num_render_sections = 1<<mRenderRes;
00585 if (path->getPathLength() != num_render_sections+1)
00586 {
00587 ((LLVOVolume*) mVO)->mVolumeChanged = TRUE;
00588 volume->resizePath(num_render_sections+1);
00589 }
00590
00591 LLPath::PathPt *new_point;
00592
00593 LLFlexibleObjectSection newSection[ (1<<FLEXIBLE_OBJECT_MAX_SECTIONS)+1 ];
00594 remapSections(mSection, mSimulateRes, newSection, mRenderRes);
00595
00596
00597 LLVector3 delta_scale = LLVector3(1,1,1);
00598 LLVector3 delta_pos;
00599 LLQuaternion delta_rot;
00600
00601 delta_rot = ~getFrameRotation();
00602 delta_pos = -getFramePosition()*delta_rot;
00603
00604
00605 LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot;
00606 LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot;
00607 LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot;
00608
00609 LLMatrix4 rel_xform;
00610 rel_xform.initRows(LLVector4(x_axis, 0.f),
00611 LLVector4(y_axis, 0.f),
00612 LLVector4(z_axis, 0.f),
00613 LLVector4(delta_pos, 1.f));
00614
00615 for (i=0; i<=num_render_sections; ++i)
00616 {
00617 new_point = &path->mPath[i];
00618 LLVector3 pos = newSection[i].mPosition * rel_xform;
00619 LLQuaternion rot = mSection[i].mAxisRotation * newSection[i].mRotation * delta_rot;
00620
00621 if (!mUpdated || (new_point->mPos-pos).magVec()/mVO->mDrawable->mDistanceWRTCamera > 0.001f)
00622 {
00623 new_point->mPos = newSection[i].mPosition * rel_xform;
00624 mUpdated = FALSE;
00625 }
00626
00627 new_point->mRot = rot;
00628 new_point->mScale = newSection[i].mScale;
00629 new_point->mTexT = ((F32)i)/(num_render_sections);
00630 }
00631
00632 mLastSegmentRotation = parentSegmentRotation;
00633 }
00634
00635 void LLVolumeImplFlexible::preRebuild()
00636 {
00637 if (!mUpdated)
00638 {
00639 doFlexibleRebuild();
00640 }
00641 }
00642
00643 void LLVolumeImplFlexible::doFlexibleRebuild()
00644 {
00645 LLVolume* volume = mVO->getVolume();
00646 volume->regen();
00647
00648 mUpdated = TRUE;
00649 }
00650
00651
00652
00653 void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, BOOL damped)
00654 {
00655 setAttributesOfAllSections((LLVector3*) &scale);
00656 }
00657
00658 BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
00659 {
00660 LLVOVolume *volume = (LLVOVolume*)mVO;
00661
00662 if (mVO->isAttachment())
00663 {
00664
00665 LLViewerObject* parent = (LLViewerObject*) mVO->getParent();
00666 while (parent && !parent->isAvatar())
00667 {
00668 parent = (LLViewerObject*) parent->getParent();
00669 }
00670
00671 if (parent)
00672 {
00673 LLVOAvatar* avatar = (LLVOAvatar*) parent;
00674 if (avatar->isImpostor() && !avatar->needsImpostorUpdate())
00675 {
00676 return TRUE;
00677 }
00678 }
00679 }
00680
00681 if (volume->mDrawable.isNull())
00682 {
00683 return TRUE;
00684 }
00685
00686 if (volume->mLODChanged)
00687 {
00688 LLVolumeParams volume_params = volume->getVolume()->getParams();
00689 volume->setVolume(volume_params, 0);
00690 mUpdated = FALSE;
00691 }
00692
00693 volume->updateRelativeXform();
00694 doFlexibleUpdate();
00695
00696
00697 BOOL rotated = FALSE;
00698 LLQuaternion cur_rotation = getFrameRotation();
00699 if ( cur_rotation != mLastFrameRotation )
00700 {
00701 mLastFrameRotation = cur_rotation;
00702 rotated = TRUE;
00703 }
00704
00705 if (volume->mLODChanged || volume->mFaceMappingChanged ||
00706 volume->mVolumeChanged)
00707 {
00708 volume->regenFaces();
00709 volume->mDrawable->setState(LLDrawable::REBUILD_VOLUME);
00710 volume->dirtySpatialGroup();
00711 doFlexibleRebuild();
00712 volume->genBBoxes(isVolumeGlobal());
00713 }
00714 else if (!mUpdated || rotated)
00715 {
00716 volume->mDrawable->setState(LLDrawable::REBUILD_POSITION);
00717 volume->dirtyMesh();
00718 volume->genBBoxes(isVolumeGlobal());
00719 }
00720
00721 volume->mVolumeChanged = FALSE;
00722 volume->mLODChanged = FALSE;
00723 volume->mFaceMappingChanged = FALSE;
00724
00725
00726 drawable->clearState(LLDrawable::UV);
00727
00728 return TRUE;
00729 }
00730
00731
00732 void LLVolumeImplFlexible::setCollisionSphere( LLVector3 p, F32 r )
00733 {
00734 mCollisionSpherePosition = p;
00735 mCollisionSphereRadius = r;
00736
00737 }
00738
00739
00740
00741 void LLVolumeImplFlexible::setUsingCollisionSphere( bool u )
00742 {
00743 }
00744
00745
00746
00747 void LLVolumeImplFlexible::setRenderingCollisionSphere( bool r )
00748 {
00749 }
00750
00751
00752 LLVector3 LLVolumeImplFlexible::getEndPosition()
00753 {
00754 S32 num_sections = 1 << mAttributes->getSimulateLOD();
00755 return mSection[ num_sections ].mPosition;
00756
00757 }
00758
00759
00760
00761 LLVector3 LLVolumeImplFlexible::getNodePosition( int nodeIndex )
00762 {
00763 S32 num_sections = 1 << mAttributes->getSimulateLOD();
00764 if ( nodeIndex > num_sections - 1 )
00765 {
00766 nodeIndex = num_sections - 1;
00767 }
00768 else if ( nodeIndex < 0 )
00769 {
00770 nodeIndex = 0;
00771 }
00772
00773 return mSection[ nodeIndex ].mPosition;
00774
00775 }
00776
00777 LLVector3 LLVolumeImplFlexible::getPivotPosition() const
00778 {
00779 return getAnchorPosition();
00780 }
00781
00782
00783 LLVector3 LLVolumeImplFlexible::getAnchorPosition() const
00784 {
00785 LLVector3 BasePosition = getFramePosition();
00786 LLQuaternion parentSegmentRotation = getFrameRotation();
00787 LLVector3 anchorDirectionRotated = LLVector3::z_axis * parentSegmentRotation;
00788 LLVector3 anchorScale = mVO->mDrawable->getScale();
00789 return BasePosition - (anchorScale.mV[VZ]/2 * anchorDirectionRotated);
00790
00791 }
00792
00793
00794
00795 LLQuaternion LLVolumeImplFlexible::getEndRotation()
00796 {
00797 return mLastSegmentRotation;
00798
00799 }
00800
00801
00802 void LLVolumeImplFlexible::updateRelativeXform()
00803 {
00804 LLQuaternion delta_rot;
00805 LLVector3 delta_pos, delta_scale;
00806 LLVOVolume* vo = (LLVOVolume*) mVO;
00807
00808
00809 delta_rot = vo->mDrawable->isSpatialRoot() ? LLQuaternion() : vo->mDrawable->getRotation();
00810 delta_pos = vo->mDrawable->isSpatialRoot() ? LLVector3(0,0,0) : vo->mDrawable->getPosition();
00811 delta_scale = LLVector3(1,1,1);
00812
00813
00814 LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot;
00815 LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot;
00816 LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot;
00817
00818 vo->mRelativeXform.initRows(LLVector4(x_axis, 0.f),
00819 LLVector4(y_axis, 0.f),
00820 LLVector4(z_axis, 0.f),
00821 LLVector4(delta_pos, 1.f));
00822
00823 x_axis.normVec();
00824 y_axis.normVec();
00825 z_axis.normVec();
00826
00827 vo->mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis);
00828 }
00829
00830 const LLMatrix4& LLVolumeImplFlexible::getWorldMatrix(LLXformMatrix* xform) const
00831 {
00832 return xform->getWorldMatrix();
00833 }