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

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