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 }