llkeyframemotionparam.cpp

Go to the documentation of this file.
00001 
00032 //-----------------------------------------------------------------------------
00033 // Header Files
00034 //-----------------------------------------------------------------------------
00035 #include "linden_common.h"
00036 
00037 #include "llkeyframemotionparam.h"
00038 #include "llcharacter.h"
00039 #include "llmath.h"
00040 #include "m3math.h"
00041 #include "lldir.h"
00042 #include "llanimationstates.h"
00043 
00044 //-----------------------------------------------------------------------------
00045 //-----------------------------------------------------------------------------
00046 // LLKeyframeMotionParam class
00047 //-----------------------------------------------------------------------------
00048 //-----------------------------------------------------------------------------
00049 
00050 //-----------------------------------------------------------------------------
00051 // LLKeyframeMotionParam()
00052 // Class Constructor
00053 //-----------------------------------------------------------------------------
00054 LLKeyframeMotionParam::LLKeyframeMotionParam( const LLUUID &id) : LLMotion(id)
00055 {
00056         mDefaultKeyframeMotion = NULL;
00057         mCharacter = NULL;
00058 
00059         mEaseInDuration = 0.f;
00060         mEaseOutDuration = 0.f;
00061         mDuration = 0.f;
00062         mPriority = LLJoint::LOW_PRIORITY;
00063 }
00064 
00065 
00066 //-----------------------------------------------------------------------------
00067 // ~LLKeyframeMotionParam()
00068 // Class Destructor
00069 //-----------------------------------------------------------------------------
00070 LLKeyframeMotionParam::~LLKeyframeMotionParam()
00071 {
00072         for (motion_map_t::iterator iter = mParameterizedMotions.begin();
00073                  iter != mParameterizedMotions.end(); ++iter)
00074         {
00075                 motion_list_t& motionList = iter->second;
00076                 for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
00077                 {
00078                         const ParameterizedMotion& paramMotion = *iter2;
00079                         delete paramMotion.first; // note - deletes the structure; ParameterizedMotion pair remains intact
00080                 }
00081                 motionList.clear();
00082         }
00083         mParameterizedMotions.clear();
00084 }
00085 
00086 //-----------------------------------------------------------------------------
00087 // LLKeyframeMotionParam::onInitialize(LLCharacter *character)
00088 //-----------------------------------------------------------------------------
00089 LLMotion::LLMotionInitStatus LLKeyframeMotionParam::onInitialize(LLCharacter *character)
00090 {
00091         mCharacter = character;
00092 
00093         if (!loadMotions())
00094         {
00095                 return STATUS_FAILURE;  
00096         }
00097         
00098         for (motion_map_t::iterator iter = mParameterizedMotions.begin();
00099                  iter != mParameterizedMotions.end(); ++iter)
00100         {
00101                 motion_list_t& motionList = iter->second;
00102                 for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
00103                 {
00104                         const ParameterizedMotion& paramMotion = *iter2;
00105 
00106                         paramMotion.first->onInitialize(character);
00107 
00108                         if (paramMotion.first->getDuration() > mEaseInDuration)
00109                         {
00110                                 mEaseInDuration = paramMotion.first->getEaseInDuration();
00111                         }
00112 
00113                         if (paramMotion.first->getEaseOutDuration() > mEaseOutDuration)
00114                         {
00115                                 mEaseOutDuration = paramMotion.first->getEaseOutDuration();
00116                         }
00117 
00118                         if (paramMotion.first->getDuration() > mDuration)
00119                         {
00120                                 mDuration = paramMotion.first->getDuration();
00121                         }
00122 
00123                         if (paramMotion.first->getPriority() > mPriority)
00124                         {
00125                                 mPriority = paramMotion.first->getPriority();
00126                         }
00127 
00128                         LLPose *pose = paramMotion.first->getPose();
00129 
00130                         mPoseBlender.addMotion(paramMotion.first);
00131                         for (LLJointState *jsp = pose->getFirstJointState(); jsp; jsp = pose->getNextJointState())
00132                         {
00133                                 LLPose *blendedPose = mPoseBlender.getBlendedPose();
00134                                 blendedPose->addJointState(jsp);
00135                         }
00136                 }
00137         }
00138 
00139         return STATUS_SUCCESS;
00140 }
00141 
00142 //-----------------------------------------------------------------------------
00143 // LLKeyframeMotionParam::onActivate()
00144 //-----------------------------------------------------------------------------
00145 BOOL LLKeyframeMotionParam::onActivate()
00146 {
00147         for (motion_map_t::iterator iter = mParameterizedMotions.begin();
00148                  iter != mParameterizedMotions.end(); ++iter)
00149         {
00150                 motion_list_t& motionList = iter->second;
00151                 for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
00152                 {
00153                         const ParameterizedMotion& paramMotion = *iter2;
00154                         paramMotion.first->activate();
00155                 }
00156         }
00157         return TRUE;
00158 }
00159 
00160 
00161 //-----------------------------------------------------------------------------
00162 // LLKeyframeMotionParam::onUpdate()
00163 //-----------------------------------------------------------------------------
00164 BOOL LLKeyframeMotionParam::onUpdate(F32 time, U8* joint_mask)
00165 {
00166         F32 weightFactor = 1.f / (F32)mParameterizedMotions.size();
00167 
00168         // zero out all pose weights
00169         for (motion_map_t::iterator iter = mParameterizedMotions.begin();
00170                  iter != mParameterizedMotions.end(); ++iter)
00171         {
00172                 motion_list_t& motionList = iter->second;
00173                 for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
00174                 {
00175                         const ParameterizedMotion& paramMotion = *iter2;
00176 //                      llinfos << "Weight for pose " << paramMotion.first->getName() << " is " << paramMotion.first->getPose()->getWeight() << llendl;
00177                         paramMotion.first->getPose()->setWeight(0.f);
00178                 }
00179         }
00180 
00181 
00182         for (motion_map_t::iterator iter = mParameterizedMotions.begin();
00183                  iter != mParameterizedMotions.end(); ++iter)
00184         {
00185                 const std::string& paramName = iter->first;
00186                 F32* paramValue = (F32 *)mCharacter->getAnimationData(paramName);
00187                 if (NULL == paramValue) // unexpected, but...
00188                 {
00189                         llwarns << "paramValue == NULL" << llendl;
00190                         continue;
00191                 }
00192 
00193                 const ParameterizedMotion* firstMotion = NULL;
00194                 const ParameterizedMotion* secondMotion = NULL;
00195 
00196                 motion_list_t& motionList = iter->second;
00197                 for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
00198                 {
00199                         const ParameterizedMotion& paramMotion = *iter2;
00200                         paramMotion.first->onUpdate(time, joint_mask);
00201                         
00202                         F32 distToParam = paramMotion.second - *paramValue;
00203                         
00204                         if ( distToParam <= 0.f)
00205                         {
00206                                 // keep track of the motion closest to the parameter value
00207                                 firstMotion = &paramMotion;
00208                         }
00209                         else
00210                         {
00211                                 // we've passed the parameter value
00212                                 // so store the first motion we find as the second one we want to blend...
00213                                 if (firstMotion && !secondMotion )
00214                                 {
00215                                         secondMotion = &paramMotion;
00216                                 }
00217                                 //...or, if we've seen no other motion so far, make sure we blend to this only
00218                                 else if (!firstMotion)
00219                                 {
00220                                         firstMotion = &paramMotion;
00221                                         secondMotion = &paramMotion;
00222                                 }
00223                         }
00224                 }
00225 
00226                 LLPose *firstPose;
00227                 LLPose *secondPose;
00228 
00229                 if (firstMotion)
00230                         firstPose = firstMotion->first->getPose();
00231                 else
00232                         firstPose = NULL;
00233 
00234                 if (secondMotion)
00235                         secondPose = secondMotion->first->getPose();
00236                 else
00237                         secondPose = NULL;
00238                 
00239                 // now modify weight of the subanim (only if we are blending between two motions)
00240                 if (firstMotion && secondMotion)
00241                 {
00242                         if (firstMotion == secondMotion)
00243                         {
00244                                 firstPose->setWeight(weightFactor);
00245                         }
00246                         else if (firstMotion->second == secondMotion->second)
00247                         {
00248                                 firstPose->setWeight(0.5f * weightFactor);
00249                                 secondPose->setWeight(0.5f * weightFactor);
00250                         }
00251                         else
00252                         {
00253                                 F32 first_weight = 1.f - 
00254                                         ((llclamp(*paramValue - firstMotion->second, 0.f, (secondMotion->second - firstMotion->second))) / 
00255                                                 (secondMotion->second - firstMotion->second));
00256                                 first_weight = llclamp(first_weight, 0.f, 1.f);
00257                                 
00258                                 F32 second_weight = 1.f - first_weight;
00259                                 
00260                                 firstPose->setWeight(first_weight * weightFactor);
00261                                 secondPose->setWeight(second_weight * weightFactor);
00262 
00263 //                              llinfos << "Parameter " << *paramName << ": " << *paramValue << llendl;
00264 //                              llinfos << "Weights " << firstPose->getWeight() << " " << secondPose->getWeight() << llendl;
00265                         }
00266                 }
00267                 else if (firstMotion && !secondMotion)
00268                 {
00269                         firstPose->setWeight(weightFactor);
00270                 }
00271         }
00272 
00273         // blend poses
00274         mPoseBlender.blendAndApply();
00275 
00276         llinfos << "Param Motion weight " << mPoseBlender.getBlendedPose()->getWeight() << llendl;
00277 
00278         return TRUE;
00279 }
00280 
00281 //-----------------------------------------------------------------------------
00282 // LLKeyframeMotionParam::onDeactivate()
00283 //-----------------------------------------------------------------------------
00284 void LLKeyframeMotionParam::onDeactivate()
00285 {
00286         for (motion_map_t::iterator iter = mParameterizedMotions.begin();
00287                  iter != mParameterizedMotions.end(); ++iter)
00288         {
00289                 motion_list_t& motionList = iter->second;
00290                 for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
00291                 {
00292                         const ParameterizedMotion& paramMotion = *iter2;
00293                         paramMotion.first->onDeactivate();
00294                 }
00295         }
00296 }
00297 
00298 //-----------------------------------------------------------------------------
00299 // LLKeyframeMotionParam::addKeyframeMotion()
00300 //-----------------------------------------------------------------------------
00301 BOOL LLKeyframeMotionParam::addKeyframeMotion(char *name, const LLUUID &id, char *param, F32 value)
00302 {
00303         LLMotion *newMotion = mCharacter->createMotion( id );
00304         
00305         if (!newMotion)
00306         {
00307                 return FALSE;
00308         }
00309         
00310         newMotion->setName(name);
00311 
00312         // now add motion to this list
00313         mParameterizedMotions[param].insert(ParameterizedMotion(newMotion, value));
00314 
00315         return TRUE;
00316 }
00317 
00318 
00319 //-----------------------------------------------------------------------------
00320 // LLKeyframeMotionParam::setDefaultKeyframeMotion()
00321 //-----------------------------------------------------------------------------
00322 void LLKeyframeMotionParam::setDefaultKeyframeMotion(char *name)
00323 {
00324         for (motion_map_t::iterator iter = mParameterizedMotions.begin();
00325                  iter != mParameterizedMotions.end(); ++iter)
00326         {
00327                 motion_list_t& motionList = iter->second;
00328                 for (motion_list_t::iterator iter2 = motionList.begin(); iter2 != motionList.end(); ++iter2)
00329                 {
00330                         const ParameterizedMotion& paramMotion = *iter2;
00331                         if (paramMotion.first->getName() == name)
00332                         {
00333                                 mDefaultKeyframeMotion = paramMotion.first;
00334                         }
00335                 }
00336         }
00337 }
00338 
00339 //-----------------------------------------------------------------------------
00340 // loadMotions()
00341 //-----------------------------------------------------------------------------
00342 BOOL LLKeyframeMotionParam::loadMotions()
00343 {
00344         //-------------------------------------------------------------------------
00345         // Load named file by concatenating the character prefix with the motion name.
00346         // Load data into a buffer to be parsed.
00347         //-------------------------------------------------------------------------
00348         char path[LL_MAX_PATH];         /* Flawfinder: ignore */
00349         snprintf( path,sizeof(path), "%s_%s.llp",
00350                 gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix()).c_str(),
00351                 getName().c_str() );    
00352 
00353         //-------------------------------------------------------------------------
00354         // open the file
00355         //-------------------------------------------------------------------------
00356         S32 fileSize = 0;
00357         apr_file_t* fp = ll_apr_file_open(path, LL_APR_R, &fileSize);
00358         if (!fp || fileSize == 0)
00359         {
00360                 llinfos << "ERROR: can't open: " << path << llendl;
00361                 return FALSE;
00362         }
00363 
00364         // allocate a text buffer
00365         char *text = new char[ fileSize+1 ];
00366         if ( !text )
00367         {
00368                 llinfos << "ERROR: can't allocated keyframe text buffer." << llendl;
00369                 apr_file_close(fp);
00370                 return FALSE;
00371         }
00372 
00373         //-------------------------------------------------------------------------
00374         // load data from file into buffer
00375         //-------------------------------------------------------------------------
00376         bool error = false;
00377         char *p = text;
00378         while ( 1 )
00379         {
00380                 if (apr_file_eof(fp) == APR_EOF)
00381                 {
00382                         break;
00383                 }
00384                 if (apr_file_gets(p, 1024, fp) != APR_SUCCESS)
00385                 {
00386                         error = true;
00387                         break;
00388                 }
00389                 while ( *(++p) )
00390                         ;
00391         }
00392 
00393         //-------------------------------------------------------------------------
00394         // close the file
00395         //-------------------------------------------------------------------------
00396         apr_file_close( fp );
00397 
00398         //-------------------------------------------------------------------------
00399         // check for error
00400         //-------------------------------------------------------------------------
00401         llassert( p <= (text+fileSize) );
00402 
00403         if ( error )
00404         {
00405                 llinfos << "ERROR: error while reading from " << path << llendl;
00406                 delete [] text;
00407                 return FALSE;
00408         }
00409 
00410         llinfos << "Loading parametric keyframe data for: " << getName() << llendl;
00411 
00412         //-------------------------------------------------------------------------
00413         // parse the text and build keyframe data structures
00414         //-------------------------------------------------------------------------
00415         p = text;
00416         S32 num;
00417         char strA[80]; /* Flawfinder: ignore */
00418         char strB[80]; /* Flawfinder: ignore */
00419         F32 floatA = 0.0f;
00420 
00421 
00422         //-------------------------------------------------------------------------
00423         // get priority
00424         //-------------------------------------------------------------------------
00425         BOOL isFirstMotion = TRUE;
00426         num = sscanf(p, "%79s %79s %f", strA, strB, &floatA);   /* Flawfinder: ignore */
00427 
00428         while(1)
00429         {
00430                 if (num == 0 || num == EOF) break;
00431                 if ((num != 3))
00432                 {
00433                         llinfos << "WARNING: can't read parametric motion" << llendl;
00434                         delete [] text;
00435                         return FALSE;
00436                 }
00437 
00438                 addKeyframeMotion(strA, gAnimLibrary.stringToAnimState(strA), strB, floatA);
00439                 if (isFirstMotion)
00440                 {
00441                         isFirstMotion = FALSE;
00442                         setDefaultKeyframeMotion(strA);
00443                 }
00444                 
00445                 p = strstr(p, "\n");
00446                 if (!p)
00447                 {
00448                         break;
00449                 }
00450                         
00451                 p++;
00452                 num = sscanf(p, "%79s %79s %f", strA, strB, &floatA);   /* Flawfinder: ignore */
00453         }
00454 
00455         delete [] text;
00456         return TRUE;
00457 }
00458 
00459 // End

Generated on Fri May 16 08:31:59 2008 for SecondLife by  doxygen 1.5.5