00001 
00032 
00033 
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 
00047 
00048 
00049 
00050 
00051 
00052 
00053 BOOL LLKeyframeMotionParam::sortFunc(ParameterizedMotion *new_motion, ParameterizedMotion *tested_motion)
00054 {
00055         return (new_motion->second < tested_motion->second);
00056 }
00057 
00058 
00059 
00060 
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 
00077 
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 
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 
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 
00166 
00167 BOOL LLKeyframeMotionParam::onUpdate(F32 time, U8* joint_mask)
00168 {
00169         F32 weightFactor = 1.f / (F32)mParameterizedMotions.length();
00170         U32 i;
00171 
00172         
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 
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) 
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                                 
00208                                 firstMotion = paramMotion;
00209                         }
00210                         else
00211                         {
00212                                 
00213                                 
00214                                 if (firstMotion && !secondMotion )
00215                                 {
00216                                         secondMotion = paramMotion;
00217                                 }
00218                                 
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                 
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 
00265 
00266                         }
00267                 }
00268                 else if (firstMotion && !secondMotion)
00269                 {
00270                         firstPose->setWeight(weightFactor);
00271                 }
00272         }
00273 
00274         
00275         mPoseBlender.blendAndApply();
00276 
00277         llinfos << "Param Motion weight " << mPoseBlender.getBlendedPose()->getWeight() << llendl;
00278 
00279         return TRUE;
00280 }
00281 
00282 
00283 
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 
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         
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         
00325         ParameterizedMotion *parameterizedMotion = new ParameterizedMotion(newMotion, value);
00326 
00327         motionList->addDataSorted(parameterizedMotion);
00328 
00329         return TRUE;
00330 }
00331 
00332 
00333 
00334 
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 
00353 
00354 BOOL LLKeyframeMotionParam::loadMotions()
00355 {
00356         
00357         
00358         
00359         
00360         char path[LL_MAX_PATH];         
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         
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         
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         
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         
00407         
00408         apr_file_close( fp );
00409 
00410         
00411         
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         
00426         
00427         p = text;
00428         S32 num;
00429         char strA[80]; 
00430         char strB[80]; 
00431         F32 floatA = 0.0f;
00432 
00433 
00434         
00435         
00436         
00437         BOOL isFirstMotion = TRUE;
00438         num = sscanf(p, "%79s %79s %f", strA, strB, &floatA);   
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);   
00465         }
00466 
00467         delete [] text;
00468         return TRUE;
00469 }
00470 
00471