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