llbvhloader.cpp

Go to the documentation of this file.
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];             /* Flawfinder: ignore */
00057 char gOutFile[1024];            /* Flawfinder: ignore */
00058 
00059 //------------------------------------------------------------------------
00060 // Status Codes
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 // find_next_whitespace()
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 // bvhStringToOrder()
00107 //
00108 // XYZ order in BVH files must be passed to mayaQ() as ZYX.
00109 // This function reverses the input string before passing it on
00110 // to StringToOrder().
00111 //------------------------------------------------------------------------
00112 LLQuaternion::Order bvhStringToOrder( char *str )
00113 {
00114         char order[4];          /* Flawfinder: ignore */
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 // LLBVHLoader()
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];           /* Flawfinder: ignore */
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 // LLBVHLoader::loadTranslationTable()
00168 //------------------------------------------------------------------------
00169 LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName)
00170 {
00171         mLineNumber = 0;
00172         mTranslations.clear();
00173         mConstraints.clear();
00174 
00175         //--------------------------------------------------------------------
00176         // open file
00177         //--------------------------------------------------------------------
00178         char path[LL_MAX_PATH];         /* Flawfinder: ignore */
00179 
00180         snprintf( path, sizeof(path), "%s",     /* Flawfinder: ignore */
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         // register file to be closed on function exit
00192         //--------------------------------------------------------------------
00193         FileCloser fileCloser(fp);
00194 
00195         //--------------------------------------------------------------------
00196         // load header
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         // load data one line at a time
00205         //--------------------------------------------------------------------
00206         BOOL loadingGlobals = FALSE;
00207         Translation *trans = NULL;
00208         while ( getLine(fp) )
00209         {
00210                 //----------------------------------------------------------------
00211                 // check the 1st token on the line to determine if it's empty or a comment
00212                 //----------------------------------------------------------------
00213                 char token[128]; /* Flawfinder: ignore */
00214                 if ( sscanf(mLine, " %127s", token) != 1 )      /* Flawfinder: ignore */
00215                         continue;
00216 
00217                 if (token[0] == '#')
00218                         continue;
00219 
00220                 //----------------------------------------------------------------
00221                 // check if a [jointName] or [GLOBALS] was specified.
00222                 //----------------------------------------------------------------
00223                 if (token[0] == '[')
00224                 {
00225                         char name[128]; /* Flawfinder: ignore */
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                 // check for optional emote 
00245                 //----------------------------------------------------------------
00246                 if (loadingGlobals && LLString::compareInsensitive(token, "emote")==0)
00247                 {
00248                         char emote_str[1024];   /* Flawfinder: ignore */
00249                         if ( sscanf(mLine, " %*s = %1023s", emote_str) != 1 )   /* Flawfinder: ignore */
00250                                 return ST_NO_XLT_EMOTE;
00251 
00252                         mEmoteName.assign( emote_str );
00253 //                      llinfos << "NOTE: Emote: " << mEmoteName.c_str() << llendl;
00254                         continue;
00255                 }
00256 
00257 
00258                 //----------------------------------------------------------------
00259                 // check for global priority setting
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 //                      llinfos << "NOTE: Priority: " << mPriority << llendl;
00269                         continue;
00270                 }
00271 
00272                 //----------------------------------------------------------------
00273                 // check for global loop setting
00274                 //----------------------------------------------------------------
00275                 if (loadingGlobals && LLString::compareInsensitive(token, "loop")==0)
00276                 {
00277                         char trueFalse[128];            /* Flawfinder: ignore */
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 )       /* Flawfinder: ignore */        
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                 // check for global easeIn setting
00304                 //----------------------------------------------------------------
00305                 if (loadingGlobals && LLString::compareInsensitive(token, "easein")==0)
00306                 {
00307                         F32 duration;
00308                         char type[128]; /* Flawfinder: ignore */
00309                         if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 )   /* Flawfinder: ignore */
00310                                 return ST_NO_XLT_EASEIN;
00311 
00312                         mEaseIn = duration;
00313                         continue;
00314                 }
00315 
00316                 //----------------------------------------------------------------
00317                 // check for global easeOut setting
00318                 //----------------------------------------------------------------
00319                 if (loadingGlobals && LLString::compareInsensitive(token, "easeout")==0)
00320                 {
00321                         F32 duration;
00322                         char type[128];         /* Flawfinder: ignore */
00323                         if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 )   /* Flawfinder: ignore */
00324                                 return ST_NO_XLT_EASEOUT;
00325 
00326                         mEaseOut = duration;
00327                         continue;
00328                 }
00329 
00330                 //----------------------------------------------------------------
00331                 // check for global handMorph setting
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                         // try reading optional target direction
00348                         if(sscanf( /* Flawfinder: ignore */
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( /* Flawfinder: ignore */
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                                 // normalize direction
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                         // try reading optional target direction
00408                         if(sscanf( /* Flawfinder: ignore */
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( /* Flawfinder: ignore */
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                                 // normalize direction
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                 // at this point there must be a valid trans pointer
00466                 //----------------------------------------------------------------
00467                 if ( ! trans )
00468                         return ST_NO_XLT_NAME;
00469 
00470                 //----------------------------------------------------------------
00471                 // check for ignore flag
00472                 //----------------------------------------------------------------
00473                 if ( LLString::compareInsensitive(token, "ignore")==0 )
00474                 {
00475                         char trueFalse[128];    /* Flawfinder: ignore */
00476                         if ( sscanf(mLine, " %*s = %127s", trueFalse) != 1 )    /* Flawfinder: ignore */
00477                                 return ST_NO_XLT_IGNORE;
00478 
00479                         trans->mIgnore = (LLString::compareInsensitive(trueFalse, "true")==0);
00480                         continue;
00481                 }
00482 
00483                 //----------------------------------------------------------------
00484                 // check for relativepos flag
00485                 //----------------------------------------------------------------
00486                 if ( LLString::compareInsensitive(token, "relativepos")==0 )
00487                 {
00488                         F32 x, y, z;
00489                         char relpos[128];       /* Flawfinder: ignore */
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 )  /* Flawfinder: ignore */
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                 // check for relativerot flag
00515                 //----------------------------------------------------------------
00516                 if ( LLString::compareInsensitive(token, "relativerot")==0 )
00517                 {
00518                         //F32 x, y, z;
00519                         char relpos[128];       /* Flawfinder: ignore */
00520                         if ( sscanf(mLine, " %*s = %127s", relpos) == 1 )       /* Flawfinder: ignore */
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                 // check for outname value
00541                 //----------------------------------------------------------------
00542                 if ( LLString::compareInsensitive(token, "outname")==0 )
00543                 {
00544                         char outName[128];      /* Flawfinder: ignore */
00545                         if ( sscanf(mLine, " %*s = %127s", outName) != 1 )      /* Flawfinder: ignore */
00546                                 return ST_NO_XLT_OUTNAME;
00547 
00548                         trans->mOutName = outName;
00549                         continue;
00550                 }
00551 
00552                 //----------------------------------------------------------------
00553                 // check for frame matrix value
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                 // check for offset matrix value
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                 // check for mergeparent value
00586                 //----------------------------------------------------------------
00587                 if ( LLString::compareInsensitive(token, "mergeparent")==0 )
00588                 {
00589                         char mergeParentName[128];      /* Flawfinder: ignore */
00590                         if ( sscanf(mLine, " %*s = %127s", mergeParentName) != 1 )      /* Flawfinder: ignore */
00591                                 return ST_NO_XLT_MERGEPARENT;
00592 
00593                         trans->mMergeParentName = mergeParentName;
00594                         continue;
00595                 }
00596 
00597                 //----------------------------------------------------------------
00598                 // check for mergechild value
00599                 //----------------------------------------------------------------
00600                 if ( LLString::compareInsensitive(token, "mergechild")==0 )
00601                 {
00602                         char mergeChildName[128];       /* Flawfinder: ignore */
00603                         if ( sscanf(mLine, " %*s = %127s", mergeChildName) != 1 )       /* Flawfinder: ignore */
00604                                 return ST_NO_XLT_MERGECHILD;
00605 
00606                         trans->mMergeChildName = mergeChildName;
00607                         continue;
00608                 }
00609 
00610                 //----------------------------------------------------------------
00611                 // check for per-joint priority
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 // LLBVHLoader::loadBVHFile()
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         // consume  hierarchy
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 //              llinfos << line << llendl;
00660                 return ST_NO_HIER;
00661         }
00662 
00663         //--------------------------------------------------------------------
00664         // consume joints
00665         //--------------------------------------------------------------------
00666         while (TRUE)
00667         {
00668                 //----------------------------------------------------------------
00669                 // get next line
00670                 //----------------------------------------------------------------
00671                 if (iter == tokens.end())
00672                         return ST_EOF;
00673                 line = (*(iter++));
00674                 err_line++;
00675 
00676                 //----------------------------------------------------------------
00677                 // consume }
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                 // if MOTION, break out
00690                 //----------------------------------------------------------------
00691                 if ( strstr(line.c_str(), "MOTION") )
00692                         break;
00693 
00694                 //----------------------------------------------------------------
00695                 // it must be either ROOT or JOINT or EndSite
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++; //     OFFSET
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); /* Flawfinder: ignore */
00722                         return ST_NO_JOINT;
00723                 }
00724 
00725                 //----------------------------------------------------------------
00726                 // get the joint name
00727                 //----------------------------------------------------------------
00728                 char jointName[80];     /* Flawfinder: ignore */
00729                 if ( sscanf(line.c_str(), "%*s %79s", jointName) != 1 ) /* Flawfinder: ignore */
00730                 {
00731                         strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */
00732                         return ST_NO_NAME;
00733                 }
00734 
00735                 //----------------------------------------------------------------
00736                 // add a set of keyframes for this joint
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                 // get next line
00754                 //----------------------------------------------------------------
00755                 if (iter == tokens.end())
00756                 {
00757                         return ST_EOF;
00758                 }
00759                 line = (*(iter++));
00760                 err_line++;
00761 
00762                 //----------------------------------------------------------------
00763                 // it must be {
00764                 //----------------------------------------------------------------
00765                 if ( !strstr(line.c_str(), "{") )
00766                 {
00767                         strncpy(error_text, line.c_str(), 127);         /*Flawfinder: ignore*/
00768                         return ST_NO_OFFSET;
00769                 }
00770                 else
00771                 {
00772                         parent_joints.push_back((S32)mJoints.size() - 1);
00773                 }
00774 
00775                 //----------------------------------------------------------------
00776                 // get next line
00777                 //----------------------------------------------------------------
00778                 if (iter == tokens.end())
00779                 {
00780                         return ST_EOF;
00781                 }
00782                 line = (*(iter++));
00783                 err_line++;
00784 
00785                 //----------------------------------------------------------------
00786                 // it must be OFFSET
00787                 //----------------------------------------------------------------
00788                 if ( !strstr(line.c_str(), "OFFSET") )
00789                 {
00790                         strncpy(error_text, line.c_str(), 127);         /*Flawfinder: ignore*/
00791                         return ST_NO_OFFSET;
00792                 }
00793 
00794                 //----------------------------------------------------------------
00795                 // get next line
00796                 //----------------------------------------------------------------
00797                 if (iter == tokens.end())
00798                 {
00799                         return ST_EOF;
00800                 }
00801                 line = (*(iter++));
00802                 err_line++;
00803 
00804                 //----------------------------------------------------------------
00805                 // it must be CHANNELS
00806                 //----------------------------------------------------------------
00807                 if ( !strstr(line.c_str(), "CHANNELS") )
00808                 {
00809                         strncpy(error_text, line.c_str(), 127);         /*Flawfinder: ignore*/
00810                         return ST_NO_CHANNELS;
00811                 }
00812 
00813                 //----------------------------------------------------------------
00814                 // get rotation order
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);         /*Flawfinder: ignore*/
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);         /*Flawfinder: ignore*/
00830                                 return ST_NO_AXIS;
00831                         }
00832 
00833                         joint->mOrder[i] = axis;
00834 
00835                         p++;
00836                 }
00837         }
00838 
00839         //--------------------------------------------------------------------
00840         // consume motion
00841         //--------------------------------------------------------------------
00842         if ( !strstr(line.c_str(), "MOTION") )
00843         {
00844                 strncpy(error_text, line.c_str(), 127);         /*Flawfinder: ignore*/
00845                 return ST_NO_MOTION;
00846         }
00847 
00848         //--------------------------------------------------------------------
00849         // get number of frames
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); /*Flawfinder: ignore*/
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);         /*Flawfinder: ignore*/
00867                 return ST_NO_FRAMES;
00868         }
00869 
00870         //--------------------------------------------------------------------
00871         // get frame time
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);         /*Flawfinder: ignore*/
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);         /*Flawfinder: ignore*/
00889                 return ST_NO_FRAME_TIME;
00890         }
00891 
00892         mDuration = (F32)mNumFrames * mFrameTime;
00893         if (!mLoop)
00894         {
00895                 mLoopOutPoint = mDuration;
00896         }
00897 
00898         //--------------------------------------------------------------------
00899         // load frames
00900         //--------------------------------------------------------------------
00901         for (S32 i=0; i<mNumFrames; i++)
00902         {
00903                 // get next line
00904                 if (iter == tokens.end())
00905                 {
00906                         return ST_EOF;
00907                 }
00908                 line = (*(iter++));
00909                 err_line++;
00910 
00911                 // read and store values
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                         // get 3 pos values for root joint only
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); /*Flawfinder: ignore*/
00925                                         return ST_NO_POS;
00926                                 }
00927                         }
00928 
00929                         // skip to next 3 values in the line
00930                         p = find_next_whitespace(p);
00931                         if (!p) 
00932                         {
00933                                 strncpy(error_text, line.c_str(), 127);         /*Flawfinder: ignore*/
00934                                 return ST_NO_ROT;
00935                         }
00936                         p = find_next_whitespace(++p);
00937                         if (!p) 
00938                         {
00939                                 strncpy(error_text, line.c_str(), 127);         /*Flawfinder: ignore*/
00940                                 return ST_NO_ROT;
00941                         }
00942                         p = find_next_whitespace(++p);
00943                         if (!p)
00944                         {
00945                                 strncpy(error_text, line.c_str(), 127);         /*Flawfinder: ignore*/
00946                                 return ST_NO_ROT;
00947                         }
00948 
00949                         // get 3 rot values for joint
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);         /*Flawfinder: ignore*/
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 // LLBVHLoader::applyTranslation()
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                 // Look for a translation for this joint.
00980                 // If none, skip to next joint
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                 // Set the ignore flag if necessary
00992                 //----------------------------------------------------------------
00993                 if ( trans.mIgnore )
00994                 {
00995                         //llinfos << "NOTE: Ignoring " << joint->mName.c_str() << llendl;
00996                         joint->mIgnore = TRUE;
00997                         continue;
00998                 }
00999 
01000                 //----------------------------------------------------------------
01001                 // Set the output name
01002                 //----------------------------------------------------------------
01003                 if ( ! trans.mOutName.empty() )
01004                 {
01005                         //llinfos << "NOTE: Changing " << joint->mName.c_str() << " to " << trans.mOutName.c_str() << llendl;
01006                         joint->mOutName = trans.mOutName;
01007                 }
01008 
01009                 //----------------------------------------------------------------
01010                 // Set the ignorepos flag if necessary
01011                 //----------------------------------------------------------------
01012                 if ( joint->mOutName == std::string("mPelvis") )
01013                 {
01014                         joint->mIgnorePositions = FALSE;
01015                 }
01016 
01017                 //----------------------------------------------------------------
01018                 // Set the relativepos flags if necessary
01019                 //----------------------------------------------------------------
01020                 if ( trans.mRelativePositionKey )
01021                 {
01022 //                      llinfos << "NOTE: Removing 1st position offset from all keys for " << joint->mOutName.c_str() << llendl;
01023                         joint->mRelativePositionKey = TRUE;
01024                 }
01025 
01026                 if ( trans.mRelativeRotationKey )
01027                 {
01028 //                      llinfos << "NOTE: Removing 1st rotation from all keys for " << joint->mOutName.c_str() << llendl;
01029                         joint->mRelativeRotationKey = TRUE;
01030                 }
01031                 
01032                 if ( trans.mRelativePosition.magVec() > 0.0f )
01033                 {
01034                         joint->mRelativePosition = trans.mRelativePosition;
01035 //                      llinfos << "NOTE: Removing " <<
01036 //                              joint->mRelativePosition.mV[0] << " " <<
01037 //                              joint->mRelativePosition.mV[1] << " " <<
01038 //                              joint->mRelativePosition.mV[2] <<
01039 //                              " from all position keys in " <<
01040 //                              joint->mOutName.c_str() << llendl;
01041                 }
01042 
01043                 //----------------------------------------------------------------
01044                 // Set change of coordinate frame
01045                 //----------------------------------------------------------------
01046                 joint->mFrameMatrix = trans.mFrameMatrix;
01047                 joint->mOffsetMatrix = trans.mOffsetMatrix;
01048 
01049                 //----------------------------------------------------------------
01050                 // Set mergeparent name
01051                 //----------------------------------------------------------------
01052                 if ( ! trans.mMergeParentName.empty() )
01053                 {
01054 //                      llinfos << "NOTE: Merging "  << joint->mOutName.c_str() << 
01055 //                              " with parent " << 
01056 //                              trans.mMergeParentName.c_str() << llendl;
01057                         joint->mMergeParentName = trans.mMergeParentName;
01058                 }
01059 
01060                 //----------------------------------------------------------------
01061                 // Set mergechild name
01062                 //----------------------------------------------------------------
01063                 if ( ! trans.mMergeChildName.empty() )
01064                 {
01065 //                      llinfos << "NOTE: Merging " << joint->mName.c_str() <<
01066 //                              " with child " << trans.mMergeChildName.c_str() << llendl;
01067                         joint->mMergeChildName = trans.mMergeChildName;
01068                 }
01069 
01070                 //----------------------------------------------------------------
01071                 // Set joint priority
01072                 //----------------------------------------------------------------
01073                 joint->mPriority = mPriority + trans.mPriorityModifier;
01074 
01075         }
01076 }
01077 
01078 //-----------------------------------------------------------------------------
01079 // LLBVHLoader::optimize()
01080 //-----------------------------------------------------------------------------
01081 void LLBVHLoader::optimize()
01082 {
01083         //RN: assumes motion blend, which is the default now
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                         // no keys?
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                         // skip first key
01117                         KeyVector::iterator ki = joint->mKeys.begin();
01118                         if (joint->mKeys.size() == 1)
01119                         {
01120                                 // *FIX: use single frame to move pelvis
01121                                 // if only one keyframe force output for this joint
01122                                 rot_changed = TRUE;
01123                         }
01124                         else
01125                         {
01126                                 // if more than one keyframe, use first frame as reference and skip to second
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                                         //check position for noticeable effect
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                                         //check rotation for noticeable effect
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                 // don't output joints with no motion
01232                 if (!(pos_changed || rot_changed))
01233                 {
01234                         //llinfos << "Ignoring joint " << joint->mName << llendl;
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 // LLBVHLoader::getLine()
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 // returns required size of output buffer
01278 U32 LLBVHLoader::getOutputSize()
01279 {
01280         LLDataPackerBinaryBuffer dp;
01281         serialize(dp);
01282 
01283         return dp.getCurrentSize();
01284 }
01285 
01286 // writes contents to datapacker
01287 BOOL LLBVHLoader::serialize(LLDataPacker& dp)
01288 {
01289         JointVector::iterator ji;
01290         KeyVector::iterator ki;
01291         F32 time;
01292 
01293         // count number of non-ignored joints
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         // print header
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                 // if ignored, skip it
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                 // compute coordinate frame rotation
01332                 LLQuaternion frameRot( joint->mFrameMatrix );
01333                 LLQuaternion frameRotInv = ~frameRot;
01334 
01335                 LLQuaternion offsetRot( joint->mOffsetMatrix );
01336 
01337                 // find mergechild and mergeparent joints, if specified
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                 // output position keys (only for 1st joint)
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;// * fixup_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 }

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