00001
00032 #include "linden_common.h"
00033
00034 #include "llbvhloader.h"
00035
00036 #include <boost/tokenizer.hpp>
00037
00038 #include "lldatapacker.h"
00039 #include "lldir.h"
00040 #include "llkeyframemotion.h"
00041 #include "llquantize.h"
00042 #include "llstl.h"
00043 #include "llapr.h"
00044
00045
00046 using namespace std;
00047
00048 #define INCHES_TO_METERS 0.02540005f
00049
00050 const F32 POSITION_KEYFRAME_THRESHOLD = 0.03f;
00051 const F32 ROTATION_KEYFRAME_THRESHOLD = 0.01f;
00052
00053 const F32 POSITION_MOTION_THRESHOLD = 0.001f;
00054 const F32 ROTATION_MOTION_THRESHOLD = 0.001f;
00055
00056 char gInFile[1024];
00057 char gOutFile[1024];
00058
00059
00060
00061
00062 char *LLBVHLoader::ST_OK = "Ok";
00063 char *LLBVHLoader::ST_EOF = "Premature end of file.";
00064 char *LLBVHLoader::ST_NO_CONSTRAINT = "Can't read constraint definition.";
00065 char *LLBVHLoader::ST_NO_FILE = "Can't open BVH file.";
00066 char *LLBVHLoader::ST_NO_HIER = "Invalid HIERARCHY header.";
00067 char *LLBVHLoader::ST_NO_JOINT = "Can't find ROOT or JOINT.";
00068 char *LLBVHLoader::ST_NO_NAME = "Can't get JOINT name.";
00069 char *LLBVHLoader::ST_NO_OFFSET = "Can't find OFFSET.";
00070 char *LLBVHLoader::ST_NO_CHANNELS = "Can't find CHANNELS.";
00071 char *LLBVHLoader::ST_NO_ROTATION = "Can't get rotation order.";
00072 char *LLBVHLoader::ST_NO_AXIS = "Can't get rotation axis.";
00073 char *LLBVHLoader::ST_NO_MOTION = "Can't find MOTION.";
00074 char *LLBVHLoader::ST_NO_FRAMES = "Can't get number of frames.";
00075 char *LLBVHLoader::ST_NO_FRAME_TIME = "Can't get frame time.";
00076 char *LLBVHLoader::ST_NO_POS = "Can't get position values.";
00077 char *LLBVHLoader::ST_NO_ROT = "Can't get rotation values.";
00078 char *LLBVHLoader::ST_NO_XLT_FILE = "Can't open translation file.";
00079 char *LLBVHLoader::ST_NO_XLT_HEADER = "Can't read translation header.";
00080 char *LLBVHLoader::ST_NO_XLT_NAME = "Can't read translation names.";
00081 char *LLBVHLoader::ST_NO_XLT_IGNORE = "Can't read translation ignore value.";
00082 char *LLBVHLoader::ST_NO_XLT_RELATIVE = "Can't read translation relative value.";
00083 char *LLBVHLoader::ST_NO_XLT_OUTNAME = "Can't read translation outname value.";
00084 char *LLBVHLoader::ST_NO_XLT_MATRIX = "Can't read translation matrix.";
00085 char *LLBVHLoader::ST_NO_XLT_MERGECHILD = "Can't get mergechild name.";
00086 char *LLBVHLoader::ST_NO_XLT_MERGEPARENT = "Can't get mergeparent name.";
00087 char *LLBVHLoader::ST_NO_XLT_PRIORITY = "Can't get priority value.";
00088 char *LLBVHLoader::ST_NO_XLT_LOOP = "Can't get loop value.";
00089 char *LLBVHLoader::ST_NO_XLT_EASEIN = "Can't get easeIn values.";
00090 char *LLBVHLoader::ST_NO_XLT_EASEOUT = "Can't get easeOut values.";
00091 char *LLBVHLoader::ST_NO_XLT_HAND = "Can't get hand morph value.";
00092 char *LLBVHLoader::ST_NO_XLT_EMOTE = "Can't read emote name.";
00093
00094
00095
00096
00097 const char *find_next_whitespace(const char *p)
00098 {
00099 while(*p && isspace(*p)) p++;
00100 while(*p && !isspace(*p)) p++;
00101 return p;
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 LLQuaternion::Order bvhStringToOrder( char *str )
00113 {
00114 char order[4];
00115 order[0] = str[2];
00116 order[1] = str[1];
00117 order[2] = str[0];
00118 order[3] = 0;
00119 LLQuaternion::Order retVal = StringToOrder( order );
00120 return retVal;
00121 }
00122
00123
00124
00125
00126 LLBVHLoader::LLBVHLoader(const char* buffer)
00127 {
00128 reset();
00129
00130 mStatus = loadTranslationTable("anim.ini");
00131
00132 if (mStatus == LLBVHLoader::ST_NO_XLT_FILE)
00133 {
00134 llwarns << "NOTE: No translation table found." << llendl;
00135 return;
00136 }
00137 else
00138 {
00139 if (mStatus != LLBVHLoader::ST_OK)
00140 {
00141 llwarns << "ERROR: [line: " << getLineNumber() << "] " << mStatus << llendl;
00142 return;
00143 }
00144 }
00145
00146 char error_text[128];
00147 S32 error_line;
00148 mStatus = loadBVHFile(buffer, error_text, error_line);
00149 if (mStatus != LLBVHLoader::ST_OK)
00150 {
00151 llwarns << "ERROR: [line: " << getLineNumber() << "] " << mStatus << llendl;
00152 return;
00153 }
00154
00155 applyTranslations();
00156 optimize();
00157
00158 mInitialized = TRUE;
00159 }
00160
00161 LLBVHLoader::~LLBVHLoader()
00162 {
00163 std::for_each(mJoints.begin(),mJoints.end(),DeletePointer());
00164 }
00165
00166
00167
00168
00169 LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
00170 {
00171 mLineNumber = 0;
00172 mTranslations.clear();
00173 mConstraints.clear();
00174
00175
00176
00177
00178 char path[LL_MAX_PATH];
00179
00180 snprintf( path, sizeof(path), "%s",
00181 gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,fileName).c_str());
00182
00183
00184 apr_file_t *fp = ll_apr_file_open(path, LL_APR_R);
00185 if (!fp)
00186 return ST_NO_XLT_FILE;
00187
00188 llinfos << "NOTE: Loading translation table: " << fileName << llendl;
00189
00190
00191
00192
00193 FileCloser fileCloser(fp);
00194
00195
00196
00197
00198 if ( ! getLine(fp) )
00199 return ST_EOF;
00200 if ( strncmp(mLine, "Translations 1.0", 16) )
00201 return ST_NO_XLT_HEADER;
00202
00203
00204
00205
00206 BOOL loadingGlobals = FALSE;
00207 Translation *trans = NULL;
00208 while ( getLine(fp) )
00209 {
00210
00211
00212
00213 char token[128];
00214 if ( sscanf(mLine, " %127s", token) != 1 )
00215 continue;
00216
00217 if (token[0] == '#')
00218 continue;
00219
00220
00221
00222
00223 if (token[0] == '[')
00224 {
00225 char name[128];
00226 if ( sscanf(mLine, " [%127[^]]", name) != 1 )
00227 return ST_NO_XLT_NAME;
00228
00229 if (strcmp(name, "GLOBALS")==0)
00230 {
00231 loadingGlobals = TRUE;
00232 continue;
00233 }
00234 else
00235 {
00236 loadingGlobals = FALSE;
00237 Translation &newTrans = mTranslations[ name ];
00238 trans = &newTrans;
00239 continue;
00240 }
00241 }
00242
00243
00244
00245
00246 if (loadingGlobals && LLString::compareInsensitive(token, "emote")==0)
00247 {
00248 char emote_str[1024];
00249 if ( sscanf(mLine, " %*s = %1023s", emote_str) != 1 )
00250 return ST_NO_XLT_EMOTE;
00251
00252 mEmoteName.assign( emote_str );
00253
00254 continue;
00255 }
00256
00257
00258
00259
00260
00261 if (loadingGlobals && LLString::compareInsensitive(token, "priority")==0)
00262 {
00263 S32 priority;
00264 if ( sscanf(mLine, " %*s = %d", &priority) != 1 )
00265 return ST_NO_XLT_PRIORITY;
00266
00267 mPriority = priority;
00268
00269 continue;
00270 }
00271
00272
00273
00274
00275 if (loadingGlobals && LLString::compareInsensitive(token, "loop")==0)
00276 {
00277 char trueFalse[128];
00278 trueFalse[0] = '\0';
00279
00280 F32 loop_in = 0.f;
00281 F32 loop_out = 1.f;
00282
00283 if ( sscanf(mLine, " %*s = %f %f", &loop_in, &loop_out) == 2 )
00284 {
00285 mLoop = TRUE;
00286 }
00287 else if ( sscanf(mLine, " %*s = %127s", trueFalse) == 1 )
00288 {
00289 mLoop = (LLString::compareInsensitive(trueFalse, "true")==0);
00290 }
00291 else
00292 {
00293 return ST_NO_XLT_LOOP;
00294 }
00295
00296 mLoopInPoint = loop_in * mDuration;
00297 mLoopOutPoint = loop_out * mDuration;
00298
00299 continue;
00300 }
00301
00302
00303
00304
00305 if (loadingGlobals && LLString::compareInsensitive(token, "easein")==0)
00306 {
00307 F32 duration;
00308 char type[128];
00309 if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 )
00310 return ST_NO_XLT_EASEIN;
00311
00312 mEaseIn = duration;
00313 continue;
00314 }
00315
00316
00317
00318
00319 if (loadingGlobals && LLString::compareInsensitive(token, "easeout")==0)
00320 {
00321 F32 duration;
00322 char type[128];
00323 if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 )
00324 return ST_NO_XLT_EASEOUT;
00325
00326 mEaseOut = duration;
00327 continue;
00328 }
00329
00330
00331
00332
00333 if (loadingGlobals && LLString::compareInsensitive(token, "hand")==0)
00334 {
00335 S32 handMorph;
00336 if (sscanf(mLine, " %*s = %d", &handMorph) != 1)
00337 return ST_NO_XLT_HAND;
00338
00339 mHand = handMorph;
00340 continue;
00341 }
00342
00343 if (loadingGlobals && LLString::compareInsensitive(token, "constraint")==0)
00344 {
00345 Constraint constraint;
00346
00347
00348 if(sscanf(
00349 mLine,
00350 " %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f %f %f %f",
00351 &constraint.mChainLength,
00352 &constraint.mEaseInStart,
00353 &constraint.mEaseInStop,
00354 &constraint.mEaseOutStart,
00355 &constraint.mEaseOutStop,
00356 constraint.mSourceJointName,
00357 &constraint.mSourceOffset.mV[VX],
00358 &constraint.mSourceOffset.mV[VY],
00359 &constraint.mSourceOffset.mV[VZ],
00360 constraint.mTargetJointName,
00361 &constraint.mTargetOffset.mV[VX],
00362 &constraint.mTargetOffset.mV[VY],
00363 &constraint.mTargetOffset.mV[VZ],
00364 &constraint.mTargetDir.mV[VX],
00365 &constraint.mTargetDir.mV[VY],
00366 &constraint.mTargetDir.mV[VZ]) != 16)
00367 {
00368 if(sscanf(
00369 mLine,
00370 " %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f",
00371 &constraint.mChainLength,
00372 &constraint.mEaseInStart,
00373 &constraint.mEaseInStop,
00374 &constraint.mEaseOutStart,
00375 &constraint.mEaseOutStop,
00376 constraint.mSourceJointName,
00377 &constraint.mSourceOffset.mV[VX],
00378 &constraint.mSourceOffset.mV[VY],
00379 &constraint.mSourceOffset.mV[VZ],
00380 constraint.mTargetJointName,
00381 &constraint.mTargetOffset.mV[VX],
00382 &constraint.mTargetOffset.mV[VY],
00383 &constraint.mTargetOffset.mV[VZ]) != 13)
00384 {
00385 return ST_NO_CONSTRAINT;
00386 }
00387 }
00388 else
00389 {
00390
00391 if (!constraint.mTargetDir.isExactlyZero())
00392 {
00393 constraint.mTargetDir.normVec();
00394 }
00395
00396 }
00397
00398 constraint.mConstraintType = CONSTRAINT_TYPE_POINT;
00399 mConstraints.push_back(constraint);
00400 continue;
00401 }
00402
00403 if (loadingGlobals && LLString::compareInsensitive(token, "planar_constraint")==0)
00404 {
00405 Constraint constraint;
00406
00407
00408 if(sscanf(
00409 mLine,
00410 " %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f %f %f %f",
00411 &constraint.mChainLength,
00412 &constraint.mEaseInStart,
00413 &constraint.mEaseInStop,
00414 &constraint.mEaseOutStart,
00415 &constraint.mEaseOutStop,
00416 constraint.mSourceJointName,
00417 &constraint.mSourceOffset.mV[VX],
00418 &constraint.mSourceOffset.mV[VY],
00419 &constraint.mSourceOffset.mV[VZ],
00420 constraint.mTargetJointName,
00421 &constraint.mTargetOffset.mV[VX],
00422 &constraint.mTargetOffset.mV[VY],
00423 &constraint.mTargetOffset.mV[VZ],
00424 &constraint.mTargetDir.mV[VX],
00425 &constraint.mTargetDir.mV[VY],
00426 &constraint.mTargetDir.mV[VZ]) != 16)
00427 {
00428 if(sscanf(
00429 mLine,
00430 " %*s = %d %f %f %f %f %15s %f %f %f %15s %f %f %f",
00431 &constraint.mChainLength,
00432 &constraint.mEaseInStart,
00433 &constraint.mEaseInStop,
00434 &constraint.mEaseOutStart,
00435 &constraint.mEaseOutStop,
00436 constraint.mSourceJointName,
00437 &constraint.mSourceOffset.mV[VX],
00438 &constraint.mSourceOffset.mV[VY],
00439 &constraint.mSourceOffset.mV[VZ],
00440 constraint.mTargetJointName,
00441 &constraint.mTargetOffset.mV[VX],
00442 &constraint.mTargetOffset.mV[VY],
00443 &constraint.mTargetOffset.mV[VZ]) != 13)
00444 {
00445 return ST_NO_CONSTRAINT;
00446 }
00447 }
00448 else
00449 {
00450
00451 if (!constraint.mTargetDir.isExactlyZero())
00452 {
00453 constraint.mTargetDir.normVec();
00454 }
00455
00456 }
00457
00458 constraint.mConstraintType = CONSTRAINT_TYPE_PLANE;
00459 mConstraints.push_back(constraint);
00460 continue;
00461 }
00462
00463
00464
00465
00466
00467 if ( ! trans )
00468 return ST_NO_XLT_NAME;
00469
00470
00471
00472
00473 if ( LLString::compareInsensitive(token, "ignore")==0 )
00474 {
00475 char trueFalse[128];
00476 if ( sscanf(mLine, " %*s = %127s", trueFalse) != 1 )
00477 return ST_NO_XLT_IGNORE;
00478
00479 trans->mIgnore = (LLString::compareInsensitive(trueFalse, "true")==0);
00480 continue;
00481 }
00482
00483
00484
00485
00486 if ( LLString::compareInsensitive(token, "relativepos")==0 )
00487 {
00488 F32 x, y, z;
00489 char relpos[128];
00490 if ( sscanf(mLine, " %*s = %f %f %f", &x, &y, &z) == 3 )
00491 {
00492 trans->mRelativePosition.setVec( x, y, z );
00493 }
00494 else if ( sscanf(mLine, " %*s = %127s", relpos) == 1 )
00495 {
00496 if ( LLString::compareInsensitive(relpos, "firstkey")==0 )
00497 {
00498 trans->mRelativePositionKey = TRUE;
00499 }
00500 else
00501 {
00502 return ST_NO_XLT_RELATIVE;
00503 }
00504 }
00505 else
00506 {
00507 return ST_NO_XLT_RELATIVE;
00508 }
00509
00510 continue;
00511 }
00512
00513
00514
00515
00516 if ( LLString::compareInsensitive(token, "relativerot")==0 )
00517 {
00518
00519 char relpos[128];
00520 if ( sscanf(mLine, " %*s = %127s", relpos) == 1 )
00521 {
00522 if ( LLString::compareInsensitive(relpos, "firstkey")==0 )
00523 {
00524 trans->mRelativeRotationKey = TRUE;
00525 }
00526 else
00527 {
00528 return ST_NO_XLT_RELATIVE;
00529 }
00530 }
00531 else
00532 {
00533 return ST_NO_XLT_RELATIVE;
00534 }
00535
00536 continue;
00537 }
00538
00539
00540
00541
00542 if ( LLString::compareInsensitive(token, "outname")==0 )
00543 {
00544 char outName[128];
00545 if ( sscanf(mLine, " %*s = %127s", outName) != 1 )
00546 return ST_NO_XLT_OUTNAME;
00547
00548 trans->mOutName = outName;
00549 continue;
00550 }
00551
00552
00553
00554
00555 if ( LLString::compareInsensitive(token, "frame")==0 )
00556 {
00557 LLMatrix3 fm;
00558 if ( sscanf(mLine, " %*s = %f %f %f, %f %f %f, %f %f %f",
00559 &fm.mMatrix[0][0], &fm.mMatrix[0][1], &fm.mMatrix[0][2],
00560 &fm.mMatrix[1][0], &fm.mMatrix[1][1], &fm.mMatrix[1][2],
00561 &fm.mMatrix[2][0], &fm.mMatrix[2][1], &fm.mMatrix[2][2] ) != 9 )
00562 return ST_NO_XLT_MATRIX;
00563
00564 trans->mFrameMatrix = fm;
00565 continue;
00566 }
00567
00568
00569
00570
00571 if ( LLString::compareInsensitive(token, "offset")==0 )
00572 {
00573 LLMatrix3 om;
00574 if ( sscanf(mLine, " %*s = %f %f %f, %f %f %f, %f %f %f",
00575 &om.mMatrix[0][0], &om.mMatrix[0][1], &om.mMatrix[0][2],
00576 &om.mMatrix[1][0], &om.mMatrix[1][1], &om.mMatrix[1][2],
00577 &om.mMatrix[2][0], &om.mMatrix[2][1], &om.mMatrix[2][2] ) != 9 )
00578 return ST_NO_XLT_MATRIX;
00579
00580 trans->mOffsetMatrix = om;
00581 continue;
00582 }
00583
00584
00585
00586
00587 if ( LLString::compareInsensitive(token, "mergeparent")==0 )
00588 {
00589 char mergeParentName[128];
00590 if ( sscanf(mLine, " %*s = %127s", mergeParentName) != 1 )
00591 return ST_NO_XLT_MERGEPARENT;
00592
00593 trans->mMergeParentName = mergeParentName;
00594 continue;
00595 }
00596
00597
00598
00599
00600 if ( LLString::compareInsensitive(token, "mergechild")==0 )
00601 {
00602 char mergeChildName[128];
00603 if ( sscanf(mLine, " %*s = %127s", mergeChildName) != 1 )
00604 return ST_NO_XLT_MERGECHILD;
00605
00606 trans->mMergeChildName = mergeChildName;
00607 continue;
00608 }
00609
00610
00611
00612
00613 if ( LLString::compareInsensitive(token, "priority")==0 )
00614 {
00615 S32 priority;
00616 if ( sscanf(mLine, " %*s = %d", &priority) != 1 )
00617 return ST_NO_XLT_PRIORITY;
00618
00619 trans->mPriorityModifier = priority;
00620 continue;
00621 }
00622
00623 }
00624 return ST_OK;
00625 }
00626
00627
00628
00629
00630
00631 LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &err_line)
00632 {
00633 std::string line;
00634
00635 err_line = 0;
00636 error_text[127] = '\0';
00637
00638 std::string str(buffer);
00639 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00640 boost::char_separator<char> sep("\r\n");
00641 tokenizer tokens(str, sep);
00642 tokenizer::iterator iter = tokens.begin();
00643
00644 mLineNumber = 0;
00645 mJoints.clear();
00646
00647 std::vector<S32> parent_joints;
00648
00649
00650
00651
00652 if (iter == tokens.end())
00653 return ST_EOF;
00654 line = (*(iter++));
00655 err_line++;
00656
00657 if ( !strstr(line.c_str(), "HIERARCHY") )
00658 {
00659
00660 return ST_NO_HIER;
00661 }
00662
00663
00664
00665
00666 while (TRUE)
00667 {
00668
00669
00670
00671 if (iter == tokens.end())
00672 return ST_EOF;
00673 line = (*(iter++));
00674 err_line++;
00675
00676
00677
00678
00679 if ( strstr(line.c_str(), "}") )
00680 {
00681 if (parent_joints.size() > 0)
00682 {
00683 parent_joints.pop_back();
00684 }
00685 continue;
00686 }
00687
00688
00689
00690
00691 if ( strstr(line.c_str(), "MOTION") )
00692 break;
00693
00694
00695
00696
00697 if ( strstr(line.c_str(), "ROOT") )
00698 {
00699 }
00700 else if ( strstr(line.c_str(), "JOINT") )
00701 {
00702 }
00703 else if ( strstr(line.c_str(), "End Site") )
00704 {
00705 iter++;
00706 iter++;
00707 S32 depth = 0;
00708 for (S32 j = (S32)parent_joints.size() - 1; j >= 0; j--)
00709 {
00710 Joint *joint = mJoints[parent_joints[j]];
00711 if (depth > joint->mChildTreeMaxDepth)
00712 {
00713 joint->mChildTreeMaxDepth = depth;
00714 }
00715 depth++;
00716 }
00717 continue;
00718 }
00719 else
00720 {
00721 strncpy(error_text, line.c_str(), 127);
00722 return ST_NO_JOINT;
00723 }
00724
00725
00726
00727
00728 char jointName[80];
00729 if ( sscanf(line.c_str(), "%*s %79s", jointName) != 1 )
00730 {
00731 strncpy(error_text, line.c_str(), 127);
00732 return ST_NO_NAME;
00733 }
00734
00735
00736
00737
00738 mJoints.push_back( new Joint( jointName ) );
00739 Joint *joint = mJoints.back();
00740
00741 S32 depth = 1;
00742 for (S32 j = (S32)parent_joints.size() - 1; j >= 0; j--)
00743 {
00744 Joint *pjoint = mJoints[parent_joints[j]];
00745 if (depth > pjoint->mChildTreeMaxDepth)
00746 {
00747 pjoint->mChildTreeMaxDepth = depth;
00748 }
00749 depth++;
00750 }
00751
00752
00753
00754
00755 if (iter == tokens.end())
00756 {
00757 return ST_EOF;
00758 }
00759 line = (*(iter++));
00760 err_line++;
00761
00762
00763
00764
00765 if ( !strstr(line.c_str(), "{") )
00766 {
00767 strncpy(error_text, line.c_str(), 127);
00768 return ST_NO_OFFSET;
00769 }
00770 else
00771 {
00772 parent_joints.push_back((S32)mJoints.size() - 1);
00773 }
00774
00775
00776
00777
00778 if (iter == tokens.end())
00779 {
00780 return ST_EOF;
00781 }
00782 line = (*(iter++));
00783 err_line++;
00784
00785
00786
00787
00788 if ( !strstr(line.c_str(), "OFFSET") )
00789 {
00790 strncpy(error_text, line.c_str(), 127);
00791 return ST_NO_OFFSET;
00792 }
00793
00794
00795
00796
00797 if (iter == tokens.end())
00798 {
00799 return ST_EOF;
00800 }
00801 line = (*(iter++));
00802 err_line++;
00803
00804
00805
00806
00807 if ( !strstr(line.c_str(), "CHANNELS") )
00808 {
00809 strncpy(error_text, line.c_str(), 127);
00810 return ST_NO_CHANNELS;
00811 }
00812
00813
00814
00815
00816 const char *p = line.c_str();
00817 for (S32 i=0; i<3; i++)
00818 {
00819 p = strstr(p, "rotation");
00820 if (!p)
00821 {
00822 strncpy(error_text, line.c_str(), 127);
00823 return ST_NO_ROTATION;
00824 }
00825
00826 const char axis = *(p - 1);
00827 if ((axis != 'X') && (axis != 'Y') && (axis != 'Z'))
00828 {
00829 strncpy(error_text, line.c_str(), 127);
00830 return ST_NO_AXIS;
00831 }
00832
00833 joint->mOrder[i] = axis;
00834
00835 p++;
00836 }
00837 }
00838
00839
00840
00841
00842 if ( !strstr(line.c_str(), "MOTION") )
00843 {
00844 strncpy(error_text, line.c_str(), 127);
00845 return ST_NO_MOTION;
00846 }
00847
00848
00849
00850
00851 if (iter == tokens.end())
00852 {
00853 return ST_EOF;
00854 }
00855 line = (*(iter++));
00856 err_line++;
00857
00858 if ( !strstr(line.c_str(), "Frames:") )
00859 {
00860 strncpy(error_text, line.c_str(), 127);
00861 return ST_NO_FRAMES;
00862 }
00863
00864 if ( sscanf(line.c_str(), "Frames: %d", &mNumFrames) != 1 )
00865 {
00866 strncpy(error_text, line.c_str(), 127);
00867 return ST_NO_FRAMES;
00868 }
00869
00870
00871
00872
00873 if (iter == tokens.end())
00874 {
00875 return ST_EOF;
00876 }
00877 line = (*(iter++));
00878 err_line++;
00879
00880 if ( !strstr(line.c_str(), "Frame Time:") )
00881 {
00882 strncpy(error_text, line.c_str(), 127);
00883 return ST_NO_FRAME_TIME;
00884 }
00885
00886 if ( sscanf(line.c_str(), "Frame Time: %f", &mFrameTime) != 1 )
00887 {
00888 strncpy(error_text, line.c_str(), 127);
00889 return ST_NO_FRAME_TIME;
00890 }
00891
00892 mDuration = (F32)mNumFrames * mFrameTime;
00893 if (!mLoop)
00894 {
00895 mLoopOutPoint = mDuration;
00896 }
00897
00898
00899
00900
00901 for (S32 i=0; i<mNumFrames; i++)
00902 {
00903
00904 if (iter == tokens.end())
00905 {
00906 return ST_EOF;
00907 }
00908 line = (*(iter++));
00909 err_line++;
00910
00911
00912 const char *p = line.c_str();
00913 for (U32 j=0; j<mJoints.size(); j++)
00914 {
00915 Joint *joint = mJoints[j];
00916 joint->mKeys.push_back( Key() );
00917 Key &key = joint->mKeys.back();
00918
00919
00920 if (j==0)
00921 {
00922 if ( sscanf(p, "%f %f %f", key.mPos, key.mPos+1, key.mPos+2) != 3 )
00923 {
00924 strncpy(error_text, line.c_str(), 127);
00925 return ST_NO_POS;
00926 }
00927 }
00928
00929
00930 p = find_next_whitespace(p);
00931 if (!p)
00932 {
00933 strncpy(error_text, line.c_str(), 127);
00934 return ST_NO_ROT;
00935 }
00936 p = find_next_whitespace(++p);
00937 if (!p)
00938 {
00939 strncpy(error_text, line.c_str(), 127);
00940 return ST_NO_ROT;
00941 }
00942 p = find_next_whitespace(++p);
00943 if (!p)
00944 {
00945 strncpy(error_text, line.c_str(), 127);
00946 return ST_NO_ROT;
00947 }
00948
00949
00950 F32 rot[3];
00951 if ( sscanf(p, " %f %f %f", rot, rot+1, rot+2) != 3 )
00952 {
00953 strncpy(error_text, line.c_str(), 127);
00954 return ST_NO_ROT;
00955 }
00956
00957 p++;
00958
00959 key.mRot[ joint->mOrder[0]-'X' ] = rot[0];
00960 key.mRot[ joint->mOrder[1]-'X' ] = rot[1];
00961 key.mRot[ joint->mOrder[2]-'X' ] = rot[2];
00962 }
00963 }
00964
00965 return ST_OK;
00966 }
00967
00968
00969
00970
00971
00972 void LLBVHLoader::applyTranslations()
00973 {
00974 JointVector::iterator ji;
00975 for (ji = mJoints.begin(); ji != mJoints.end(); ++ji )
00976 {
00977 Joint *joint = *ji;
00978
00979
00980
00981
00982 TranslationMap::iterator ti = mTranslations.find( joint->mName );
00983 if ( ti == mTranslations.end() )
00984 {
00985 continue;
00986 }
00987
00988 Translation &trans = ti->second;
00989
00990
00991
00992
00993 if ( trans.mIgnore )
00994 {
00995
00996 joint->mIgnore = TRUE;
00997 continue;
00998 }
00999
01000
01001
01002
01003 if ( ! trans.mOutName.empty() )
01004 {
01005
01006 joint->mOutName = trans.mOutName;
01007 }
01008
01009
01010
01011
01012 if ( joint->mOutName == std::string("mPelvis") )
01013 {
01014 joint->mIgnorePositions = FALSE;
01015 }
01016
01017
01018
01019
01020 if ( trans.mRelativePositionKey )
01021 {
01022
01023 joint->mRelativePositionKey = TRUE;
01024 }
01025
01026 if ( trans.mRelativeRotationKey )
01027 {
01028
01029 joint->mRelativeRotationKey = TRUE;
01030 }
01031
01032 if ( trans.mRelativePosition.magVec() > 0.0f )
01033 {
01034 joint->mRelativePosition = trans.mRelativePosition;
01035
01036
01037
01038
01039
01040
01041 }
01042
01043
01044
01045
01046 joint->mFrameMatrix = trans.mFrameMatrix;
01047 joint->mOffsetMatrix = trans.mOffsetMatrix;
01048
01049
01050
01051
01052 if ( ! trans.mMergeParentName.empty() )
01053 {
01054
01055
01056
01057 joint->mMergeParentName = trans.mMergeParentName;
01058 }
01059
01060
01061
01062
01063 if ( ! trans.mMergeChildName.empty() )
01064 {
01065
01066
01067 joint->mMergeChildName = trans.mMergeChildName;
01068 }
01069
01070
01071
01072
01073 joint->mPriority = mPriority + trans.mPriorityModifier;
01074
01075 }
01076 }
01077
01078
01079
01080
01081 void LLBVHLoader::optimize()
01082 {
01083
01084 if (!mLoop && mEaseIn + mEaseOut > mDuration && mDuration != 0.f)
01085 {
01086 F32 factor = mDuration / (mEaseIn + mEaseOut);
01087 mEaseIn *= factor;
01088 mEaseOut *= factor;
01089 }
01090
01091 JointVector::iterator ji;
01092 for (ji = mJoints.begin(); ji != mJoints.end(); ++ji)
01093 {
01094 Joint *joint = *ji;
01095 BOOL pos_changed = FALSE;
01096 BOOL rot_changed = FALSE;
01097
01098 if ( ! joint->mIgnore )
01099 {
01100 joint->mNumPosKeys = 0;
01101 joint->mNumRotKeys = 0;
01102 LLQuaternion::Order order = bvhStringToOrder( joint->mOrder );
01103
01104 KeyVector::iterator first_key = joint->mKeys.begin();
01105
01106
01107 if (first_key == joint->mKeys.end())
01108 {
01109 joint->mIgnore = TRUE;
01110 continue;
01111 }
01112
01113 LLVector3 first_frame_pos(first_key->mPos);
01114 LLQuaternion first_frame_rot = mayaQ( first_key->mRot[0], first_key->mRot[1], first_key->mRot[2], order);
01115
01116
01117 KeyVector::iterator ki = joint->mKeys.begin();
01118 if (joint->mKeys.size() == 1)
01119 {
01120
01121
01122 rot_changed = TRUE;
01123 }
01124 else
01125 {
01126
01127 first_key->mIgnorePos = TRUE;
01128 first_key->mIgnoreRot = TRUE;
01129 ++ki;
01130 }
01131
01132 KeyVector::iterator ki_prev = ki;
01133 KeyVector::iterator ki_last_good_pos = ki;
01134 KeyVector::iterator ki_last_good_rot = ki;
01135 S32 numPosFramesConsidered = 2;
01136 S32 numRotFramesConsidered = 2;
01137
01138 F32 rot_threshold = ROTATION_KEYFRAME_THRESHOLD / llmax((F32)joint->mChildTreeMaxDepth * 0.33f, 1.f);
01139
01140 for (; ki != joint->mKeys.end(); ++ki)
01141 {
01142 if (ki_prev == ki_last_good_pos)
01143 {
01144 joint->mNumPosKeys++;
01145 if (dist_vec(LLVector3(ki_prev->mPos), first_frame_pos) > POSITION_MOTION_THRESHOLD)
01146 {
01147 pos_changed = TRUE;
01148 }
01149 }
01150 else
01151 {
01152
01153 LLVector3 test_pos(ki_prev->mPos);
01154 LLVector3 last_good_pos(ki_last_good_pos->mPos);
01155 LLVector3 current_pos(ki->mPos);
01156 LLVector3 interp_pos = lerp(current_pos, last_good_pos, 1.f / (F32)numPosFramesConsidered);
01157
01158 if (dist_vec(current_pos, first_frame_pos) > POSITION_MOTION_THRESHOLD)
01159 {
01160 pos_changed = TRUE;
01161 }
01162
01163 if (dist_vec(interp_pos, test_pos) < POSITION_KEYFRAME_THRESHOLD)
01164 {
01165 ki_prev->mIgnorePos = TRUE;
01166 numPosFramesConsidered++;
01167 }
01168 else
01169 {
01170 numPosFramesConsidered = 2;
01171 ki_last_good_pos = ki_prev;
01172 joint->mNumPosKeys++;
01173 }
01174 }
01175
01176 if (ki_prev == ki_last_good_rot)
01177 {
01178 joint->mNumRotKeys++;
01179 LLQuaternion test_rot = mayaQ( ki_prev->mRot[0], ki_prev->mRot[1], ki_prev->mRot[2], order);
01180 F32 x_delta = dist_vec(LLVector3::x_axis * first_frame_rot, LLVector3::x_axis * test_rot);
01181 F32 y_delta = dist_vec(LLVector3::y_axis * first_frame_rot, LLVector3::y_axis * test_rot);
01182 F32 rot_test = x_delta + y_delta;
01183
01184 if (rot_test > ROTATION_MOTION_THRESHOLD)
01185 {
01186 rot_changed = TRUE;
01187 }
01188 }
01189 else
01190 {
01191
01192 LLQuaternion test_rot = mayaQ( ki_prev->mRot[0], ki_prev->mRot[1], ki_prev->mRot[2], order);
01193 LLQuaternion last_good_rot = mayaQ( ki_last_good_rot->mRot[0], ki_last_good_rot->mRot[1], ki_last_good_rot->mRot[2], order);
01194 LLQuaternion current_rot = mayaQ( ki->mRot[0], ki->mRot[1], ki->mRot[2], order);
01195 LLQuaternion interp_rot = lerp(1.f / (F32)numRotFramesConsidered, current_rot, last_good_rot);
01196
01197 F32 x_delta;
01198 F32 y_delta;
01199 F32 rot_test;
01200
01201 x_delta = dist_vec(LLVector3::x_axis * first_frame_rot, LLVector3::x_axis * test_rot);
01202 y_delta = dist_vec(LLVector3::y_axis * first_frame_rot, LLVector3::y_axis * test_rot);
01203 rot_test = x_delta + y_delta;
01204
01205 if (rot_test > ROTATION_MOTION_THRESHOLD)
01206 {
01207 rot_changed = TRUE;
01208 }
01209
01210 x_delta = dist_vec(LLVector3::x_axis * interp_rot, LLVector3::x_axis * test_rot);
01211 y_delta = dist_vec(LLVector3::y_axis * interp_rot, LLVector3::y_axis * test_rot);
01212 rot_test = x_delta + y_delta;
01213
01214 if (rot_test < rot_threshold)
01215 {
01216 ki_prev->mIgnoreRot = TRUE;
01217 numRotFramesConsidered++;
01218 }
01219 else
01220 {
01221 numRotFramesConsidered = 2;
01222 ki_last_good_rot = ki_prev;
01223 joint->mNumRotKeys++;
01224 }
01225 }
01226
01227 ki_prev = ki;
01228 }
01229 }
01230
01231
01232 if (!(pos_changed || rot_changed))
01233 {
01234
01235 joint->mIgnore = TRUE;
01236 }
01237 }
01238 }
01239
01240 void LLBVHLoader::reset()
01241 {
01242 mLineNumber = 0;
01243 mNumFrames = 0;
01244 mFrameTime = 0.0f;
01245 mDuration = 0.0f;
01246
01247 mPriority = 2;
01248 mLoop = FALSE;
01249 mLoopInPoint = 0.f;
01250 mLoopOutPoint = 0.f;
01251 mEaseIn = 0.3f;
01252 mEaseOut = 0.3f;
01253 mHand = 1;
01254 mInitialized = FALSE;
01255
01256 mEmoteName = "";
01257 }
01258
01259
01260
01261
01262 BOOL LLBVHLoader::getLine(apr_file_t* fp)
01263 {
01264 if (apr_file_eof(fp) == APR_EOF)
01265 {
01266 return FALSE;
01267 }
01268 if ( apr_file_gets(mLine, BVH_PARSER_LINE_SIZE, fp) == APR_SUCCESS)
01269 {
01270 mLineNumber++;
01271 return TRUE;
01272 }
01273
01274 return FALSE;
01275 }
01276
01277
01278 U32 LLBVHLoader::getOutputSize()
01279 {
01280 LLDataPackerBinaryBuffer dp;
01281 serialize(dp);
01282
01283 return dp.getCurrentSize();
01284 }
01285
01286
01287 BOOL LLBVHLoader::serialize(LLDataPacker& dp)
01288 {
01289 JointVector::iterator ji;
01290 KeyVector::iterator ki;
01291 F32 time;
01292
01293
01294 S32 numJoints = 0;
01295 for (ji=mJoints.begin(); ji!=mJoints.end(); ++ji)
01296 {
01297 Joint *joint = *ji;
01298 if ( ! joint->mIgnore )
01299 numJoints++;
01300 }
01301
01302
01303 dp.packU16(KEYFRAME_MOTION_VERSION, "version");
01304 dp.packU16(KEYFRAME_MOTION_SUBVERSION, "sub_version");
01305 dp.packS32(mPriority, "base_priority");
01306 dp.packF32(mDuration, "duration");
01307 dp.packString(mEmoteName.c_str(), "emote_name");
01308 dp.packF32(mLoopInPoint, "loop_in_point");
01309 dp.packF32(mLoopOutPoint, "loop_out_point");
01310 dp.packS32(mLoop, "loop");
01311 dp.packF32(mEaseIn, "ease_in_duration");
01312 dp.packF32(mEaseOut, "ease_out_duration");
01313 dp.packU32(mHand, "hand_pose");
01314 dp.packU32(numJoints, "num_joints");
01315
01316 for ( ji = mJoints.begin();
01317 ji != mJoints.end();
01318 ++ji )
01319 {
01320 Joint *joint = *ji;
01321
01322 if ( joint->mIgnore )
01323 continue;
01324
01325 LLQuaternion first_frame_rot;
01326 LLQuaternion fixup_rot;
01327
01328 dp.packString(joint->mOutName.c_str(), "joint_name");
01329 dp.packS32(joint->mPriority, "joint_priority");
01330
01331
01332 LLQuaternion frameRot( joint->mFrameMatrix );
01333 LLQuaternion frameRotInv = ~frameRot;
01334
01335 LLQuaternion offsetRot( joint->mOffsetMatrix );
01336
01337
01338 LLQuaternion mergeParentRot;
01339 LLQuaternion mergeChildRot;
01340 Joint *mergeParent = NULL;
01341 Joint *mergeChild = NULL;
01342
01343 JointVector::iterator mji;
01344 for (mji=mJoints.begin(); mji!=mJoints.end(); ++mji)
01345 {
01346 Joint *mjoint = *mji;
01347 if ( !joint->mMergeParentName.empty() && (mjoint->mName == joint->mMergeParentName) )
01348 {
01349 mergeParent = *mji;
01350 }
01351 if ( !joint->mMergeChildName.empty() && (mjoint->mName == joint->mMergeChildName) )
01352 {
01353 mergeChild = *mji;
01354 }
01355 }
01356
01357 dp.packS32(joint->mNumRotKeys, "num_rot_keys");
01358
01359 LLQuaternion::Order order = bvhStringToOrder( joint->mOrder );
01360 S32 outcount = 0;
01361 S32 frame = 1;
01362 for ( ki = joint->mKeys.begin();
01363 ki != joint->mKeys.end();
01364 ++ki )
01365 {
01366 if ((frame == 1) && joint->mRelativeRotationKey)
01367 {
01368 first_frame_rot = mayaQ( ki->mRot[0], ki->mRot[1], ki->mRot[2], order);
01369
01370 fixup_rot.shortestArc(LLVector3::z_axis * first_frame_rot * frameRot, LLVector3::z_axis);
01371 }
01372
01373 if (ki->mIgnoreRot)
01374 {
01375 frame++;
01376 continue;
01377 }
01378
01379 time = (F32)frame * mFrameTime;
01380
01381 if (mergeParent)
01382 {
01383 mergeParentRot = mayaQ( mergeParent->mKeys[frame-1].mRot[0],
01384 mergeParent->mKeys[frame-1].mRot[1],
01385 mergeParent->mKeys[frame-1].mRot[2],
01386 bvhStringToOrder(mergeParent->mOrder) );
01387 LLQuaternion parentFrameRot( mergeParent->mFrameMatrix );
01388 LLQuaternion parentOffsetRot( mergeParent->mOffsetMatrix );
01389 mergeParentRot = ~parentFrameRot * mergeParentRot * parentFrameRot * parentOffsetRot;
01390 }
01391 else
01392 {
01393 mergeParentRot.loadIdentity();
01394 }
01395
01396 if (mergeChild)
01397 {
01398 mergeChildRot = mayaQ( mergeChild->mKeys[frame-1].mRot[0],
01399 mergeChild->mKeys[frame-1].mRot[1],
01400 mergeChild->mKeys[frame-1].mRot[2],
01401 bvhStringToOrder(mergeChild->mOrder) );
01402 LLQuaternion childFrameRot( mergeChild->mFrameMatrix );
01403 LLQuaternion childOffsetRot( mergeChild->mOffsetMatrix );
01404 mergeChildRot = ~childFrameRot * mergeChildRot * childFrameRot * childOffsetRot;
01405
01406 }
01407 else
01408 {
01409 mergeChildRot.loadIdentity();
01410 }
01411
01412 LLQuaternion inRot = mayaQ( ki->mRot[0], ki->mRot[1], ki->mRot[2], order);
01413
01414 LLQuaternion outRot = frameRotInv* mergeChildRot * inRot * mergeParentRot * ~first_frame_rot * frameRot * offsetRot;
01415
01416 U16 time_short = F32_to_U16(time, 0.f, mDuration);
01417 dp.packU16(time_short, "time");
01418 U16 x, y, z;
01419 LLVector3 rot_vec = outRot.packToVector3();
01420 rot_vec.quantize16(-1.f, 1.f, -1.f, 1.f);
01421 x = F32_to_U16(rot_vec.mV[VX], -1.f, 1.f);
01422 y = F32_to_U16(rot_vec.mV[VY], -1.f, 1.f);
01423 z = F32_to_U16(rot_vec.mV[VZ], -1.f, 1.f);
01424 dp.packU16(x, "rot_angle_x");
01425 dp.packU16(y, "rot_angle_y");
01426 dp.packU16(z, "rot_angle_z");
01427 outcount++;
01428 frame++;
01429 }
01430
01431
01432 if ( ji == mJoints.begin() && !joint->mIgnorePositions )
01433 {
01434 dp.packS32(joint->mNumPosKeys, "num_pos_keys");
01435
01436 LLVector3 relPos = joint->mRelativePosition;
01437 LLVector3 relKey;
01438
01439 frame = 1;
01440 for ( ki = joint->mKeys.begin();
01441 ki != joint->mKeys.end();
01442 ++ki )
01443 {
01444 if ((frame == 1) && joint->mRelativePositionKey)
01445 {
01446 relKey.setVec(ki->mPos);
01447 }
01448
01449 if (ki->mIgnorePos)
01450 {
01451 frame++;
01452 continue;
01453 }
01454
01455 time = (F32)frame * mFrameTime;
01456
01457 LLVector3 inPos = (LLVector3(ki->mPos) - relKey) * ~first_frame_rot;
01458 LLVector3 outPos = inPos * frameRot * offsetRot;
01459
01460 outPos *= INCHES_TO_METERS;
01461
01462 outPos -= relPos;
01463 outPos.clamp(-LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
01464
01465 U16 time_short = F32_to_U16(time, 0.f, mDuration);
01466 dp.packU16(time_short, "time");
01467
01468 U16 x, y, z;
01469 outPos.quantize16(-LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
01470 x = F32_to_U16(outPos.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
01471 y = F32_to_U16(outPos.mV[VY], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
01472 z = F32_to_U16(outPos.mV[VZ], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET);
01473 dp.packU16(x, "pos_x");
01474 dp.packU16(y, "pos_y");
01475 dp.packU16(z, "pos_z");
01476
01477 frame++;
01478 }
01479 }
01480 else
01481 {
01482 dp.packS32(0, "num_pos_keys");
01483 }
01484 }
01485
01486 S32 num_constraints = (S32)mConstraints.size();
01487 dp.packS32(num_constraints, "num_constraints");
01488
01489 for (ConstraintVector::iterator constraint_it = mConstraints.begin();
01490 constraint_it != mConstraints.end();
01491 constraint_it++)
01492 {
01493 U8 byte = constraint_it->mChainLength;
01494 dp.packU8(byte, "chain_lenght");
01495
01496 byte = constraint_it->mConstraintType;
01497 dp.packU8(byte, "constraint_type");
01498 dp.packBinaryDataFixed((U8*)constraint_it->mSourceJointName, 16, "source_volume");
01499 dp.packVector3(constraint_it->mSourceOffset, "source_offset");
01500 dp.packBinaryDataFixed((U8*)constraint_it->mTargetJointName, 16, "target_volume");
01501 dp.packVector3(constraint_it->mTargetOffset, "target_offset");
01502 dp.packVector3(constraint_it->mTargetDir, "target_dir");
01503 dp.packF32(constraint_it->mEaseInStart, "ease_in_start");
01504 dp.packF32(constraint_it->mEaseInStop, "ease_in_stop");
01505 dp.packF32(constraint_it->mEaseOutStart, "ease_out_start");
01506 dp.packF32(constraint_it->mEaseOutStop, "ease_out_stop");
01507 }
01508
01509 return TRUE;
01510 }