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 "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 /*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f;
00052 
00053 // LLFlexibleObjectData::pack/unpack now in llprimitive.cpp
00054 
00055 //-----------------------------------------------
00056 // constructor
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                 // Generate all from section 0
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                 // Copy, skipping sections
00127 
00128                 S32 num_steps = 1<<(source_sections-dest_sections);
00129 
00130                 // Copy from left to right since it may be an in-place computation
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                 // Interpolate section info
00140                 // Iterate from right to left since it may be an in-place computation
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                         // Cubic interpolation of position
00149                         // At^3 + Bt^2 + Ct + D = f(t)
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; // Helper var
00153                         LLVector3 X = (source_section->mPosition - D - C); // Helper var
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                                 // Evaluate output interpolated values
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                 // numbers are equal. copy info
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 &params = 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         /*doIdleUpdate(gAgent, *gWorldp, 0.0);
00244         if (mVO && mVO->mDrawable.notNull())
00245         {
00246                 gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
00247                 gPipeline.markMoved(mVO->mDrawable);
00248         }*/
00249 }
00250 
00251 //---------------------------------------------------------------------------------
00252 // This calculates the physics of the flexible object. Note that it has to be 0
00253 // updated every time step. In the future, perhaps there could be an 
00254 // optimization similar to what Havok does for objects that are stationary. 
00255 //---------------------------------------------------------------------------------
00256 BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
00257 {
00258 
00259         if (mVO->mDrawable.isNull())
00260         {
00261                 // Don't do anything until we have a drawable
00262                 return FALSE; // (we are not initialized or updated)
00263         }
00264 
00265         //flexible objects never go static
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         //number of segments only cares about z axis
00278         F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, mVO->mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f);
00279 
00280         // Rendering sections increases with visible angle on the screen
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         // Bottom cap at 1/4 the original number of sections
00289         if (mRenderRes < mAttributes->getSimulateLOD()-1)
00290         {
00291                 mRenderRes = mAttributes->getSimulateLOD()-1;
00292         }
00293         // Throttle back simulation of segments we're not rendering
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; // (we are not initialized or updated)
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; // we did not get updated or initialized, proceeding without can be dangerous
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         // ANCHOR position is offset from BASE position (centroid) by half the length
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         // Coefficients which are constant across sections
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         // Update simulated sections
00412         for (i=1; i<=num_sections; ++i)
00413         {
00414                 LLVector3 parentSectionVector;
00415                 LLVector3 parentSectionPosition;
00416                 LLVector3 parentDirection;
00417 
00418                 //---------------------------------------------------
00419                 // save value of position as lastPosition
00420                 //---------------------------------------------------
00421                 lastPosition = mSection[i].mPosition;
00422 
00423                 //------------------------------------------------------------------------------------------
00424                 // gravity
00425                 //------------------------------------------------------------------------------------------
00426                 mSection[i].mPosition.mV[2] -= mAttributes->getGravity() * force_factor;
00427 
00428                 //------------------------------------------------------------------------------------------
00429                 // wind force
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                 // user-defined force
00438                 //------------------------------------------------------------------------------------------
00439                 mSection[i].mPosition += mAttributes->getUserForce() * force_factor;
00440 
00441                 //---------------------------------------------------
00442                 // tension (rigidity, stiffness)
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                 // sphere collision, currently not used
00465                 //------------------------------------------------------------------------------------------
00466                 /*if ( mAttributes->mUsingCollisionSphere )
00467                 {
00468                         LLVector3 vectorToCenterOfCollisionSphere = mCollisionSpherePosition - mSection[i].mPosition;
00469                         if ( vectorToCenterOfCollisionSphere.magVecSquared() < mCollisionSphereRadius * mCollisionSphereRadius )
00470                         {
00471                                 F32 distanceToCenterOfCollisionSphere = vectorToCenterOfCollisionSphere.magVec();
00472                                 F32 penetration = mCollisionSphereRadius - distanceToCenterOfCollisionSphere;
00473 
00474                                 LLVector3 normalToCenterOfCollisionSphere;
00475                                 
00476                                 if ( distanceToCenterOfCollisionSphere > 0.0f )
00477                                 {
00478                                         normalToCenterOfCollisionSphere = vectorToCenterOfCollisionSphere / distanceToCenterOfCollisionSphere;
00479                                 }
00480                                 else // rare
00481                                 {
00482                                         normalToCenterOfCollisionSphere = LLVector3::x_axis; // arbitrary
00483                                 }
00484 
00485                                 // push the position out to the surface of the collision sphere
00486                                 mSection[i].mPosition -= normalToCenterOfCollisionSphere * penetration;
00487                         }
00488                 }*/
00489 
00490                 //------------------------------------------------------------------------------------------
00491                 // inertia
00492                 //------------------------------------------------------------------------------------------
00493                 mSection[i].mPosition += mSection[i].mVelocity * momentum;
00494 
00495                 //------------------------------------------------------------------------------------------
00496                 // clamp length & rotation
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                         //angle = 0.5f*(angle+max_angle);
00510                         deltaRotation.setQuat(max_angle, axis);
00511                 } else if (angle < -max_angle)
00512                 {
00513                         //angle = 0.5f*(angle-max_angle);
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                         // Propogate half the rotation up to the parent
00526                         LLQuaternion halfDeltaRotation(angle/2, axis);
00527                         mSection[i-1].mRotation = mSection[i-1].mRotation * halfDeltaRotation;
00528                 }
00529 
00530                 //------------------------------------------------------------------------------------------
00531                 // calculate velocity
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         // Calculate derivatives (not necessary until normals are automagically generated)
00541         mSection[0].mdPosition = (mSection[1].mPosition - mSection[0].mPosition) * inv_section_length;
00542         // i = 1..NumSections-1
00543         for (i=1; i<num_sections; ++i)
00544         {
00545                 // Quadratic numerical derivative of position
00546 
00547                 // f(-L1) = aL1^2 - bL1 + c = f1
00548                 // f(0)   =               c = f2
00549                 // f(L2)  = aL2^2 + bL2 + c = f3
00550                 // f = ax^2 + bx + c
00551                 // d/dx f = 2ax + b
00552                 // d/dx f(0) = b
00553 
00554                 // c = f2
00555                 // a = [(f1-c)/L1 + (f3-c)/L2] / (L1+L2)
00556                 // b = (f3-c-aL2^2)/L2
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         // i = NumSections
00567         mSection[i].mdPosition = (mSection[i].mPosition - mSection[i-1].mPosition) * inv_section_length;
00568 
00569         // Create points
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         //generate transform from global to prim space
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         // Vertex transform (4x4)
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()) // Not sure why this is happening, but it is...
00635         {
00636                 return TRUE; // No update to complete
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         // Object may have been rotated, which means it needs a rebuild.  See SL-47220
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         // clear UV flag
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         //matrix from local space to parent relative/global space
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         // Vertex transform (4x4)
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 }

Generated on Thu Jul 1 06:08:30 2010 for Second Life Viewer by  doxygen 1.4.7