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