llflexibleobject.cpp

Go to the documentation of this file.
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 /*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f;
00053 
00054 // LLFlexibleObjectData::pack/unpack now in llprimitive.cpp
00055 
00056 //-----------------------------------------------
00057 // constructor
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                 // Generate all from section 0
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                 // Copy, skipping sections
00133 
00134                 S32 num_steps = 1<<(source_sections-dest_sections);
00135 
00136                 // Copy from left to right since it may be an in-place computation
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                 // Interpolate section info
00146                 // Iterate from right to left since it may be an in-place computation
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                         // Cubic interpolation of position
00155                         // At^3 + Bt^2 + Ct + D = f(t)
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; // Helper var
00159                         LLVector3 X = (source_section->mPosition - D - C); // Helper var
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                                 // Evaluate output interpolated values
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                 // numbers are equal. copy info
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 &params = 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 // This calculates the physics of the flexible object. Note that it has to be 0
00261 // updated every time step. In the future, perhaps there could be an 
00262 // optimization similar to what Havok does for objects that are stationary. 
00263 //---------------------------------------------------------------------------------
00264 BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
00265 {
00266         if (mVO->mDrawable.isNull())
00267         {
00268                 // Don't do anything until we have a drawable
00269                 return FALSE; // (we are not initialized or updated)
00270         }
00271 
00272         BOOL force_update = mSimulateRes == 0 ? TRUE : FALSE;
00273 
00274         //flexible objects never go static
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         //number of segments only cares about z axis
00287         F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, mVO->mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
00288 
00289         // Rendering sections increases with visible angle on the screen
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         // Bottom cap at 1/4 the original number of sections
00298         if (mRenderRes < mAttributes->getSimulateLOD()-1)
00299         {
00300                 mRenderRes = mAttributes->getSimulateLOD()-1;
00301         }
00302         // Throttle back simulation of segments we're not rendering
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; // (we are not initialized or updated)
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; // we did not get updated or initialized, proceeding without can be dangerous
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         // ANCHOR position is offset from BASE position (centroid) by half the length
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         // Coefficients which are constant across sections
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         // Update simulated sections
00426         for (i=1; i<=num_sections; ++i)
00427         {
00428                 LLVector3 parentSectionVector;
00429                 LLVector3 parentSectionPosition;
00430                 LLVector3 parentDirection;
00431 
00432                 //---------------------------------------------------
00433                 // save value of position as lastPosition
00434                 //---------------------------------------------------
00435                 lastPosition = mSection[i].mPosition;
00436 
00437                 //------------------------------------------------------------------------------------------
00438                 // gravity
00439                 //------------------------------------------------------------------------------------------
00440                 mSection[i].mPosition.mV[2] -= mAttributes->getGravity() * force_factor;
00441 
00442                 //------------------------------------------------------------------------------------------
00443                 // wind force
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                 // user-defined force
00452                 //------------------------------------------------------------------------------------------
00453                 mSection[i].mPosition += mAttributes->getUserForce() * force_factor;
00454 
00455                 //---------------------------------------------------
00456                 // tension (rigidity, stiffness)
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                 // sphere collision, currently not used
00479                 //------------------------------------------------------------------------------------------
00480                 /*if ( mAttributes->mUsingCollisionSphere )
00481                 {
00482                         LLVector3 vectorToCenterOfCollisionSphere = mCollisionSpherePosition - mSection[i].mPosition;
00483                         if ( vectorToCenterOfCollisionSphere.magVecSquared() < mCollisionSphereRadius * mCollisionSphereRadius )
00484                         {
00485                                 F32 distanceToCenterOfCollisionSphere = vectorToCenterOfCollisionSphere.magVec();
00486                                 F32 penetration = mCollisionSphereRadius - distanceToCenterOfCollisionSphere;
00487 
00488                                 LLVector3 normalToCenterOfCollisionSphere;
00489                                 
00490                                 if ( distanceToCenterOfCollisionSphere > 0.0f )
00491                                 {
00492                                         normalToCenterOfCollisionSphere = vectorToCenterOfCollisionSphere / distanceToCenterOfCollisionSphere;
00493                                 }
00494                                 else // rare
00495                                 {
00496                                         normalToCenterOfCollisionSphere = LLVector3::x_axis; // arbitrary
00497                                 }
00498 
00499                                 // push the position out to the surface of the collision sphere
00500                                 mSection[i].mPosition -= normalToCenterOfCollisionSphere * penetration;
00501                         }
00502                 }*/
00503 
00504                 //------------------------------------------------------------------------------------------
00505                 // inertia
00506                 //------------------------------------------------------------------------------------------
00507                 mSection[i].mPosition += mSection[i].mVelocity * momentum;
00508 
00509                 //------------------------------------------------------------------------------------------
00510                 // clamp length & rotation
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                         //angle = 0.5f*(angle+max_angle);
00524                         deltaRotation.setQuat(max_angle, axis);
00525                 } else if (angle < -max_angle)
00526                 {
00527                         //angle = 0.5f*(angle-max_angle);
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                         // Propogate half the rotation up to the parent
00540                         LLQuaternion halfDeltaRotation(angle/2, axis);
00541                         mSection[i-1].mRotation = mSection[i-1].mRotation * halfDeltaRotation;
00542                 }
00543 
00544                 //------------------------------------------------------------------------------------------
00545                 // calculate velocity
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         // Calculate derivatives (not necessary until normals are automagically generated)
00555         mSection[0].mdPosition = (mSection[1].mPosition - mSection[0].mPosition) * inv_section_length;
00556         // i = 1..NumSections-1
00557         for (i=1; i<num_sections; ++i)
00558         {
00559                 // Quadratic numerical derivative of position
00560 
00561                 // f(-L1) = aL1^2 - bL1 + c = f1
00562                 // f(0)   =               c = f2
00563                 // f(L2)  = aL2^2 + bL2 + c = f3
00564                 // f = ax^2 + bx + c
00565                 // d/dx f = 2ax + b
00566                 // d/dx f(0) = b
00567 
00568                 // c = f2
00569                 // a = [(f1-c)/L1 + (f3-c)/L2] / (L1+L2)
00570                 // b = (f3-c-aL2^2)/L2
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         // i = NumSections
00581         mSection[i].mdPosition = (mSection[i].mPosition - mSection[i-1].mPosition) * inv_section_length;
00582 
00583         // Create points
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         //generate transform from global to prim space
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         // Vertex transform (4x4)
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         {       //don't update flexible attachments for impostored avatars unless the 
00664                 //impostor is being updated this frame (w00!)
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; // No update to complete
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         // Object may have been rotated, which means it needs a rebuild.  See SL-47220
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         // clear UV flag
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         //matrix from local space to parent relative/global space
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         // Vertex transform (4x4)
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 }

Generated on Fri May 16 08:33:21 2008 for SecondLife by  doxygen 1.5.5