diff options
Diffstat (limited to 'indra/llcharacter')
-rw-r--r-- | indra/llcharacter/CMakeLists.txt | 16 | ||||
-rw-r--r-- | indra/llcharacter/llbvhloader.cpp | 461 | ||||
-rw-r--r-- | indra/llcharacter/llbvhloader.h | 14 | ||||
-rw-r--r-- | indra/llcharacter/lleditingmotion.cpp | 6 | ||||
-rw-r--r-- | indra/llcharacter/lljoint.cpp | 183 | ||||
-rw-r--r-- | indra/llcharacter/lljoint.h | 75 | ||||
-rw-r--r-- | indra/llcharacter/llkeyframemotion.cpp | 107 | ||||
-rw-r--r-- | indra/llcharacter/llkeyframemotion.h | 1 | ||||
-rw-r--r-- | indra/llcharacter/llkeyframestandmotion.cpp | 4 | ||||
-rw-r--r-- | indra/llcharacter/llmotion.cpp | 14 | ||||
-rw-r--r-- | indra/llcharacter/llmotion.h | 2 | ||||
-rw-r--r-- | indra/llcharacter/llmotioncontroller.cpp | 12 | ||||
-rw-r--r-- | indra/llcharacter/llmotioncontroller.h | 2 | ||||
-rw-r--r-- | indra/llcharacter/llpose.cpp | 3 | ||||
-rw-r--r-- | indra/llcharacter/llvisualparam.h | 1 | ||||
-rw-r--r-- | indra/llcharacter/tests/lljoint_test.cpp | 2 |
16 files changed, 577 insertions, 326 deletions
diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt index 2573417b26..a17a5b0aa6 100644 --- a/indra/llcharacter/CMakeLists.txt +++ b/indra/llcharacter/CMakeLists.txt @@ -91,12 +91,12 @@ target_link_libraries( # Add tests -if (LL_TESTS) - include(LLAddBuildTest) - # UNIT TESTS - SET(llcharacter_TEST_SOURCE_FILES - lljoint.cpp - ) - LL_ADD_PROJECT_UNIT_TESTS(llcharacter "${llcharacter_TEST_SOURCE_FILES}") -endif (LL_TESTS) +#if (LL_TESTS) +# include(LLAddBuildTest) +# # UNIT TESTS +# SET(llcharacter_TEST_SOURCE_FILES +# lljoint.cpp +# ) +# LL_ADD_PROJECT_UNIT_TESTS(llcharacter "${llcharacter_TEST_SOURCE_FILES}") +#endif (LL_TESTS) diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index 0d558aeaa2..e906d81ce1 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -11,7 +11,7 @@ * License as published by the Free Software Foundation; * version 2.1 of the License only. * - * This library is distributed in the hope that it will be useful, + * This library is distributed in the hope that it will be useful,7 * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. @@ -29,6 +29,7 @@ #include "llbvhloader.h" #include <boost/tokenizer.hpp> +#include <boost/lexical_cast.hpp> #include "lldatapacker.h" #include "lldir.h" @@ -36,6 +37,7 @@ #include "llquantize.h" #include "llstl.h" #include "llapr.h" +#include "llsdserialize.h" using namespace std; @@ -121,52 +123,16 @@ LLQuaternion::Order bvhStringToOrder( char *str ) // LLBVHLoader() //----------------------------------------------------------------------------- -/* - LLBVHLoader::LLBVHLoader(const char* buffer) -{ - reset(); - - mStatus = loadTranslationTable("anim.ini"); - - if (mStatus == LLBVHLoader::ST_NO_XLT_FILE) - { - LL_WARNS() << "NOTE: No translation table found." << LL_ENDL; - return; - } - else - { - if (mStatus != LLBVHLoader::ST_OK) - { - LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; - return; - } - } - - char error_text[128]; // Flawfinder: ignore - S32 error_line; - mStatus = loadBVHFile(buffer, error_text, error_line); - if (mStatus != LLBVHLoader::ST_OK) - { - LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; - return; - } - - applyTranslations(); - optimize(); - - mInitialized = TRUE; -} -*/ -LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine) +LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map<std::string, std::string>& joint_alias_map ) { reset(); errorLine = 0; mStatus = loadTranslationTable("anim.ini"); loadStatus = mStatus; - LL_INFOS()<<"Load Status 00 : "<< loadStatus << LL_ENDL; + LL_INFOS("BVH") << "Load Status 00 : " << loadStatus << LL_ENDL; if (mStatus == E_ST_NO_XLT_FILE) { - //LL_WARNS() << "NOTE: No translation table found." << LL_ENDL; + LL_WARNS("BVH") << "NOTE: No translation table found." << LL_ENDL; loadStatus = mStatus; return; } @@ -174,28 +140,43 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error { if (mStatus != E_ST_OK) { - //LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; + LL_WARNS("BVH") << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; errorLine = getLineNumber(); loadStatus = mStatus; return; } } + + // Recognize all names we've been told are legal. + std::map<std::string, std::string>::iterator iter; + for (iter = joint_alias_map.begin(); iter != joint_alias_map.end(); iter++) + { + makeTranslation( iter->first , iter->second ); + } char error_text[128]; /* Flawfinder: ignore */ S32 error_line; - mStatus = loadBVHFile(buffer, error_text, error_line); + mStatus = loadBVHFile(buffer, error_text, error_line); //Reads all joints in BVH file. + + LL_DEBUGS("BVH") << "============================================================" << LL_ENDL; + LL_DEBUGS("BVH") << "Raw data from file" << LL_ENDL; + dumpBVHInfo(); if (mStatus != E_ST_OK) { - //LL_WARNS() << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; + LL_WARNS("BVH") << "ERROR: [line: " << getLineNumber() << "] " << mStatus << LL_ENDL; loadStatus = mStatus; errorLine = getLineNumber(); return; } - applyTranslations(); + applyTranslations(); //Maps between joints found in file and the aliased names. optimize(); + LL_DEBUGS("BVH") << "============================================================" << LL_ENDL; + LL_DEBUGS("BVH") << "After translations and optimize" << LL_ENDL; + dumpBVHInfo(); + mInitialized = TRUE; } @@ -211,10 +192,6 @@ LLBVHLoader::~LLBVHLoader() //------------------------------------------------------------------------ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) { - mLineNumber = 0; - mTranslations.clear(); - mConstraints.clear(); - //-------------------------------------------------------------------- // open file //-------------------------------------------------------------------- @@ -226,7 +203,7 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) if (!fp) return E_ST_NO_XLT_FILE; - LL_INFOS() << "NOTE: Loading translation table: " << fileName << LL_ENDL; + LL_INFOS("BVH") << "NOTE: Loading translation table: " << fileName << LL_ENDL; //-------------------------------------------------------------------- // register file to be closed on function exit @@ -244,7 +221,6 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) // load data one line at a time //-------------------------------------------------------------------- BOOL loadingGlobals = FALSE; - Translation *trans = NULL; while ( getLine(fp) ) { //---------------------------------------------------------------- @@ -271,13 +247,6 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) loadingGlobals = TRUE; continue; } - else - { - loadingGlobals = FALSE; - Translation &newTrans = mTranslations[ name ]; - trans = &newTrans; - continue; - } } //---------------------------------------------------------------- @@ -499,174 +468,102 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) mConstraints.push_back(constraint); continue; } + } + infile.close() ; + return E_ST_OK; +} +void LLBVHLoader::makeTranslation(std::string alias_name, std::string joint_name) +{ + //Translation &newTrans = (foomap.insert(value_type(alias_name, Translation()))).first(); + Translation &newTrans = mTranslations[ alias_name ]; //Uses []'s implicit call to ctor. + + newTrans.mOutName = joint_name; + LLMatrix3 fm; + LLVector3 vect1(0, 1, 0); + LLVector3 vect2(0, 0, 1); + LLVector3 vect3(1, 0, 0); + fm.setRows(vect1, vect2, vect3); + + newTrans.mFrameMatrix = fm; + +if (joint_name == "mPelvis") + { + newTrans.mRelativePositionKey = TRUE; + newTrans.mRelativeRotationKey = TRUE; + } - //---------------------------------------------------------------- - // at this point there must be a valid trans pointer - //---------------------------------------------------------------- - if ( ! trans ) - return E_ST_NO_XLT_NAME; - - //---------------------------------------------------------------- - // check for ignore flag - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "ignore")==0 ) - { - char trueFalse[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %127s", trueFalse) != 1 ) /* Flawfinder: ignore */ - return E_ST_NO_XLT_IGNORE; - - trans->mIgnore = (LLStringUtil::compareInsensitive(trueFalse, "true")==0); - continue; - } - - //---------------------------------------------------------------- - // check for relativepos flag - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "relativepos")==0 ) - { - F32 x, y, z; - char relpos[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %f %f %f", &x, &y, &z) == 3 ) - { - trans->mRelativePosition.setVec( x, y, z ); - } - else if ( sscanf(mLine, " %*s = %127s", relpos) == 1 ) /* Flawfinder: ignore */ - { - if ( LLStringUtil::compareInsensitive(relpos, "firstkey")==0 ) - { - trans->mRelativePositionKey = TRUE; - } - else - { - return E_ST_NO_XLT_RELATIVE; - } - } - else - { - return E_ST_NO_XLT_RELATIVE; - } - - continue; - } - - //---------------------------------------------------------------- - // check for relativerot flag - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "relativerot")==0 ) - { - //F32 x, y, z; - char relpos[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %127s", relpos) == 1 ) /* Flawfinder: ignore */ - { - if ( LLStringUtil::compareInsensitive(relpos, "firstkey")==0 ) - { - trans->mRelativeRotationKey = TRUE; - } - else - { - return E_ST_NO_XLT_RELATIVE; - } - } - else - { - return E_ST_NO_XLT_RELATIVE; - } - - continue; - } - - //---------------------------------------------------------------- - // check for outname value - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "outname")==0 ) - { - char outName[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %127s", outName) != 1 ) /* Flawfinder: ignore */ - return E_ST_NO_XLT_OUTNAME; - - trans->mOutName = outName; - continue; - } - - //---------------------------------------------------------------- - // check for frame matrix value - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "frame")==0 ) - { - LLMatrix3 fm; - if ( sscanf(mLine, " %*s = %f %f %f, %f %f %f, %f %f %f", - &fm.mMatrix[0][0], &fm.mMatrix[0][1], &fm.mMatrix[0][2], - &fm.mMatrix[1][0], &fm.mMatrix[1][1], &fm.mMatrix[1][2], - &fm.mMatrix[2][0], &fm.mMatrix[2][1], &fm.mMatrix[2][2] ) != 9 ) - return E_ST_NO_XLT_MATRIX; - - trans->mFrameMatrix = fm; - continue; - } - - //---------------------------------------------------------------- - // check for offset matrix value - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "offset")==0 ) - { - LLMatrix3 om; - if ( sscanf(mLine, " %*s = %f %f %f, %f %f %f, %f %f %f", - &om.mMatrix[0][0], &om.mMatrix[0][1], &om.mMatrix[0][2], - &om.mMatrix[1][0], &om.mMatrix[1][1], &om.mMatrix[1][2], - &om.mMatrix[2][0], &om.mMatrix[2][1], &om.mMatrix[2][2] ) != 9 ) - return E_ST_NO_XLT_MATRIX; - - trans->mOffsetMatrix = om; - continue; - } - - //---------------------------------------------------------------- - // check for mergeparent value - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "mergeparent")==0 ) - { - char mergeParentName[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %127s", mergeParentName) != 1 ) /* Flawfinder: ignore */ - return E_ST_NO_XLT_MERGEPARENT; - - trans->mMergeParentName = mergeParentName; - continue; - } - - //---------------------------------------------------------------- - // check for mergechild value - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "mergechild")==0 ) - { - char mergeChildName[128]; /* Flawfinder: ignore */ - if ( sscanf(mLine, " %*s = %127s", mergeChildName) != 1 ) /* Flawfinder: ignore */ - return E_ST_NO_XLT_MERGECHILD; +} - trans->mMergeChildName = mergeChildName; - continue; - } +ELoadStatus LLBVHLoader::loadAliases(const char * filename) +{ + LLSD aliases_sd; + + std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,filename); + + llifstream input_stream; + input_stream.open(fullpath.c_str(), std::ios::in | std::ios::binary); + + if(input_stream.is_open()) + { + if ( LLSDSerialize::fromXML(aliases_sd, input_stream) ) + { + for(LLSD::map_iterator alias_iter = aliases_sd.beginMap(); + alias_iter != aliases_sd.endMap(); + ++alias_iter) + { + LLSD::String alias_name = alias_iter->first; + LLSD::String joint_name = alias_iter->second; + makeTranslation(alias_name, joint_name); + + } + } + else + { + return E_ST_NO_XLT_HEADER; + } + input_stream.close(); + } + else + { + LL_WARNS("BVH") << "Can't open joint alias file " << fullpath << LL_ENDL; + return E_ST_NO_XLT_FILE; + } + + return E_ST_OK; +} - //---------------------------------------------------------------- - // check for per-joint priority - //---------------------------------------------------------------- - if ( LLStringUtil::compareInsensitive(token, "priority")==0 ) +void LLBVHLoader::dumpBVHInfo() +{ + for (U32 j=0; j<mJoints.size(); j++) + { + Joint *joint = mJoints[j]; + LL_DEBUGS("BVH") << joint->mName << LL_ENDL; + for (S32 i=0; i<mNumFrames; i++) { - S32 priority; - if ( sscanf(mLine, " %*s = %d", &priority) != 1 ) - return E_ST_NO_XLT_PRIORITY; - - trans->mPriorityModifier = priority; - continue; + if (i<joint->mKeys.size()) // Check this in case file load failed. + { + Key &prevkey = joint->mKeys[llmax(i-1,0)]; + Key &key = joint->mKeys[i]; + if ((i==0) || + (key.mPos[0] != prevkey.mPos[0]) || + (key.mPos[1] != prevkey.mPos[1]) || + (key.mPos[2] != prevkey.mPos[2]) || + (key.mRot[0] != prevkey.mRot[0]) || + (key.mRot[1] != prevkey.mRot[1]) || + (key.mRot[2] != prevkey.mRot[2]) + ) + { + LL_DEBUGS("BVH") << "FRAME " << i + << " POS " << key.mPos[0] << "," << key.mPos[1] << "," << key.mPos[2] + << " ROT " << key.mRot[0] << "," << key.mRot[1] << "," << key.mRot[2] << LL_ENDL; + } + } } - } - infile.close() ; - return E_ST_OK; } - //------------------------------------------------------------------------ // LLBVHLoader::loadBVHFile() //------------------------------------------------------------------------ @@ -746,6 +643,7 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 & { iter++; // { iter++; // OFFSET + iter++; // } S32 depth = 0; for (S32 j = (S32)parent_joints.size() - 1; j >= 0; j--) { @@ -777,12 +675,19 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 & //--------------------------------------------------------------- // we require the root joint be "hip" - DEV-26188 //--------------------------------------------------------------- - const char* FORCED_ROOT_NAME = "hip"; - if ( (mJoints.size() == 0 ) && ( !strstr(jointName, FORCED_ROOT_NAME) ) ) - { - strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */ - return E_ST_BAD_ROOT; - } + if (mJoints.size() == 0 ) + { + //The root joint of the BVH file must be hip (mPelvis) or an alias of mPelvis. + const char* FORCED_ROOT_NAME = "hip"; + + TranslationMap::iterator hip_joint = mTranslations.find( FORCED_ROOT_NAME ); + TranslationMap::iterator root_joint = mTranslations.find( jointName ); + if ( hip_joint == mTranslations.end() || root_joint == mTranslations.end() || root_joint->second.mOutName != hip_joint->second.mOutName ) + { + strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */ + return E_ST_BAD_ROOT; + } + } //---------------------------------------------------------------- @@ -790,11 +695,14 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 & //---------------------------------------------------------------- mJoints.push_back( new Joint( jointName ) ); Joint *joint = mJoints.back(); + LL_DEBUGS("BVH") << "Created joint " << jointName << LL_ENDL; + LL_DEBUGS("BVH") << "- index " << mJoints.size()-1 << LL_ENDL; S32 depth = 1; for (S32 j = (S32)parent_joints.size() - 1; j >= 0; j--) { Joint *pjoint = mJoints[parent_joints[j]]; + LL_DEBUGS("BVH") << "- ancestor " << pjoint->mName << LL_ENDL; if (depth > pjoint->mChildTreeMaxDepth) { pjoint->mChildTreeMaxDepth = depth; @@ -863,6 +771,21 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 & return E_ST_NO_CHANNELS; } + // Animating position (via mNumChannels = 6) is only supported for mPelvis. + int res = sscanf(line.c_str(), " CHANNELS %d", &joint->mNumChannels); + if ( res != 1 ) + { + // Assume default if not otherwise specified. + if (mJoints.size()==1) + { + joint->mNumChannels = 6; + } + else + { + joint->mNumChannels = 3; + } + } + //---------------------------------------------------------------- // get rotation order //---------------------------------------------------------------- @@ -961,57 +884,49 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 & line = (*(iter++)); err_line++; - // read and store values - const char *p = line.c_str(); + // Split line into a collection of floats. + std::deque<F32> floats; + boost::char_separator<char> whitespace_sep("\t "); + tokenizer float_tokens(line, whitespace_sep); + tokenizer::iterator float_token_iter = float_tokens.begin(); + while (float_token_iter != float_tokens.end()) + { + try + { + F32 val = boost::lexical_cast<float>(*float_token_iter); + floats.push_back(val); + } + catch (const boost::bad_lexical_cast&) + { + strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ + return E_ST_NO_POS; + } + float_token_iter++; + } + LL_DEBUGS("BVH") << "Got " << floats.size() << " floats " << LL_ENDL; for (U32 j=0; j<mJoints.size(); j++) { Joint *joint = mJoints[j]; joint->mKeys.push_back( Key() ); Key &key = joint->mKeys.back(); - // get 3 pos values for root joint only - if (j==0) + if (floats.size() < joint->mNumChannels) { - if ( sscanf(p, "%f %f %f", key.mPos, key.mPos+1, key.mPos+2) != 3 ) - { - strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return E_ST_NO_POS; - } + strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ + return E_ST_NO_POS; } - // skip to next 3 values in the line - p = find_next_whitespace(p); - if (!p) + // assume either numChannels == 6, in which case we have pos + rot, + // or numChannels == 3, in which case we have only rot. + if (joint->mNumChannels == 6) { - strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return E_ST_NO_ROT; + key.mPos[0] = floats.front(); floats.pop_front(); + key.mPos[1] = floats.front(); floats.pop_front(); + key.mPos[2] = floats.front(); floats.pop_front(); } - p = find_next_whitespace(++p); - if (!p) - { - strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return E_ST_NO_ROT; - } - p = find_next_whitespace(++p); - if (!p) - { - strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return E_ST_NO_ROT; - } - - // get 3 rot values for joint - F32 rot[3]; - if ( sscanf(p, " %f %f %f", rot, rot+1, rot+2) != 3 ) - { - strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return E_ST_NO_ROT; - } - - p++; - - key.mRot[ joint->mOrder[0]-'X' ] = rot[0]; - key.mRot[ joint->mOrder[1]-'X' ] = rot[1]; - key.mRot[ joint->mOrder[2]-'X' ] = rot[2]; + key.mRot[ joint->mOrder[0]-'X' ] = floats.front(); floats.pop_front(); + key.mRot[ joint->mOrder[1]-'X' ] = floats.front(); floats.pop_front(); + key.mRot[ joint->mOrder[2]-'X' ] = floats.front(); floats.pop_front(); } } @@ -1045,7 +960,7 @@ void LLBVHLoader::applyTranslations() //---------------------------------------------------------------- if ( trans.mIgnore ) { - //LL_INFOS() << "NOTE: Ignoring " << joint->mName.c_str() << LL_ENDL; + //LL_INFOS() << "NOTE: Ignoring " << joint->mName.c_str() << LL_ENDL; joint->mIgnore = TRUE; continue; } @@ -1059,13 +974,12 @@ void LLBVHLoader::applyTranslations() joint->mOutName = trans.mOutName; } - //---------------------------------------------------------------- - // Set the ignorepos flag if necessary - //---------------------------------------------------------------- - if ( joint->mOutName == std::string("mPelvis") ) - { - joint->mIgnorePositions = FALSE; - } + //Allow joint position changes as of SL-318 + joint->mIgnorePositions = FALSE; + if (joint->mNumChannels == 3) + { + joint->mIgnorePositions = TRUE; + } //---------------------------------------------------------------- // Set the relativepos flags if necessary @@ -1334,6 +1248,9 @@ void LLBVHLoader::reset() mInitialized = FALSE; mEmoteName = ""; + mLineNumber = 0; + mTranslations.clear(); + mConstraints.clear(); } //------------------------------------------------------------------------ @@ -1508,8 +1425,8 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp) frame++; } - // output position keys (only for 1st joint) - if ( ji == mJoints.begin() && !joint->mIgnorePositions ) + // output position keys if joint has motion. + if ( !joint->mIgnorePositions ) { dp.packS32(joint->mNumPosKeys, "num_pos_keys"); @@ -1539,6 +1456,7 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp) outPos *= INCHES_TO_METERS; + //SL-318 Pelvis position can only move 5m. Limiting all joint position offsets to this dist. outPos -= relPos; outPos.clamp(-LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); @@ -1586,5 +1504,6 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp) dp.packF32(constraint_it->mEaseOutStop, "ease_out_stop"); } + return TRUE; } diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h index f816b76277..47fe409047 100644 --- a/indra/llcharacter/llbvhloader.h +++ b/indra/llcharacter/llbvhloader.h @@ -102,6 +102,7 @@ struct Joint mNumRotKeys = 0; mChildTreeMaxDepth = 0; mPriority = 0; + mNumChannels = 3; } // Include aligned members first @@ -123,6 +124,7 @@ struct Joint S32 mNumRotKeys; S32 mChildTreeMaxDepth; S32 mPriority; + S32 mNumChannels; }; @@ -225,8 +227,7 @@ class LLBVHLoader friend class LLKeyframeMotion; public: // Constructor -// LLBVHLoader(const char* buffer); - LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine); + LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map<std::string, std::string>& joint_alias_map ); ~LLBVHLoader(); /* @@ -265,13 +266,22 @@ public: static const char *ST_NO_XLT_EMOTE; static const char *ST_BAD_ROOT; */ + // Loads the specified translation table. ELoadStatus loadTranslationTable(const char *fileName); + //Create a new joint alias + void makeTranslation(std::string key, std::string value); + + // Loads joint aliases from XML file. + ELoadStatus loadAliases(const char * filename); + // Load the specified BVH file. // Returns status code. ELoadStatus loadBVHFile(const char *buffer, char *error_text, S32 &error_line); + void dumpBVHInfo(); + // Applies translations to BVH data loaded. void applyTranslations(); diff --git a/indra/llcharacter/lleditingmotion.cpp b/indra/llcharacter/lleditingmotion.cpp index f4a37a139a..ddf89f30f2 100644 --- a/indra/llcharacter/lleditingmotion.cpp +++ b/indra/llcharacter/lleditingmotion.cpp @@ -117,6 +117,7 @@ LLMotion::LLMotionInitStatus LLEditingMotion::onInitialize(LLCharacter *characte addJointState( mWristState ); // propagate joint positions to kinematic chain + // SL-315 mParentJoint.setPosition( mParentState->getJoint()->getWorldPosition() ); mShoulderJoint.setPosition( mShoulderState->getJoint()->getPosition() ); mElbowJoint.setPosition( mElbowState->getJoint()->getPosition() ); @@ -143,6 +144,7 @@ LLMotion::LLMotionInitStatus LLEditingMotion::onInitialize(LLCharacter *characte BOOL LLEditingMotion::onActivate() { // propagate joint positions to kinematic chain + // SL-315 mParentJoint.setPosition( mParentState->getJoint()->getWorldPosition() ); mShoulderJoint.setPosition( mShoulderState->getJoint()->getPosition() ); mElbowJoint.setPosition( mElbowState->getJoint()->getPosition() ); @@ -181,6 +183,7 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask) focus_pt += mCharacter->getCharacterPosition(); // propagate joint positions to kinematic chain + // SL-315 mParentJoint.setPosition( mParentState->getJoint()->getWorldPosition() ); mShoulderJoint.setPosition( mShoulderState->getJoint()->getPosition() ); mElbowJoint.setPosition( mElbowState->getJoint()->getPosition() ); @@ -217,7 +220,8 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask) " and focus point " << focus_pt << LL_ENDL; target.setVec(1.f, 1.f, 1.f); } - + + // SL-315 mTarget.setPosition( target + mParentJoint.getPosition()); // LL_INFOS() << "Point At: " << mTarget.getPosition() << LL_ENDL; diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 8fa08a2a6c..c4eda0b432 100644 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -32,6 +32,8 @@ #include "lljoint.h" #include "llmath.h" +#include "llcallstack.h" +#include <boost/algorithm/string.hpp> S32 LLJoint::sNumUpdates = 0; S32 LLJoint::sNumTouches = 0; @@ -108,6 +110,8 @@ void LLJoint::init() mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f)); mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY; mUpdateXform = TRUE; + mSupport = SUPPORT_BASE; + mEnd = LLVector3(0.0f, 0.0f, 0.0f); } LLJoint::LLJoint() : @@ -124,13 +128,12 @@ LLJoint::LLJoint(S32 joint_num) : touch(); } - //----------------------------------------------------------------------------- // LLJoint() // Class Constructor //----------------------------------------------------------------------------- LLJoint::LLJoint(const std::string &name, LLJoint *parent) : - mJointNum(0) + mJointNum(-2) { init(); mUpdateXform = FALSE; @@ -170,6 +173,27 @@ void LLJoint::setup(const std::string &name, LLJoint *parent) } //----------------------------------------------------------------------------- +// setSupport() +//----------------------------------------------------------------------------- +void LLJoint::setSupport(const std::string& support_name) +{ + if (support_name == "extended") + { + setSupport(SUPPORT_EXTENDED); + } + else if (support_name == "base") + { + setSupport(SUPPORT_BASE); + } + else + { + LL_WARNS() << "unknown support string " << support_name << LL_ENDL; + setSupport(SUPPORT_BASE); + } +} + + +//----------------------------------------------------------------------------- // touch() // Sets all dirty flags for all children, recursively. //----------------------------------------------------------------------------- @@ -195,6 +219,18 @@ void LLJoint::touch(U32 flags) } //----------------------------------------------------------------------------- +// setJointNum() +//----------------------------------------------------------------------------- +void LLJoint::setJointNum(S32 joint_num) +{ + mJointNum = joint_num; + if (mJointNum + 2 >= LL_CHARACTER_MAX_ANIMATED_JOINTS) + { + LL_INFOS() << "LL_CHARACTER_MAX_ANIMATED_JOINTS needs to be increased" << LL_ENDL; + LL_ERRS() << "joint_num " << joint_num << " + 2 is too large for " << LL_CHARACTER_MAX_ANIMATED_JOINTS << LL_ENDL; + } +} +//----------------------------------------------------------------------------- // getRoot() //----------------------------------------------------------------------------- LLJoint *LLJoint::getRoot() @@ -290,25 +326,54 @@ const LLVector3& LLJoint::getPosition() bool do_debug_joint(const std::string& name) { - return false; + if (std::find(LLJoint::s_debugJointNames.begin(), LLJoint::s_debugJointNames.end(),name) != LLJoint::s_debugJointNames.end()) + { + return true; + } + return false; } //-------------------------------------------------------------------- // setPosition() //-------------------------------------------------------------------- -void LLJoint::setPosition( const LLVector3& pos ) -{ - if (pos != getPosition()) +void LLJoint::setPosition( const LLVector3& requested_pos, bool apply_attachment_overrides ) +{ + LLVector3 pos(requested_pos); + + LLVector3 active_override; + LLUUID mesh_id; + if (apply_attachment_overrides && m_attachmentOverrides.findActiveOverride(mesh_id,active_override)) + { + if (pos != active_override && do_debug_joint(getName())) + { + LLScopedContextString str("setPosition"); + LL_DEBUGS("Avatar") << " joint " << getName() << " requested_pos " << requested_pos + << " overriden by attachment " << active_override << LL_ENDL; + } + pos = active_override; + } + if ((pos != getPosition()) && do_debug_joint(getName())) { - if (do_debug_joint(getName())) - { - LL_DEBUGS("Avatar") << " joint " << getName() << " set pos " << pos << LL_ENDL; - } + LLScopedContextString str("setPosition"); + LLCallStack cs; + LLContextStatus con_status; + LL_DEBUGS("Avatar") << " joint " << getName() << " set pos " << pos << LL_ENDL; + LL_DEBUGS("Avatar") << "CONTEXT:\n" << "====================\n" << con_status << "====================" << LL_ENDL; + LL_DEBUGS("Avatar") << "STACK:\n" << "====================\n" << cs << "====================" << LL_ENDL; } mXform.setPosition(pos); touch(MATRIX_DIRTY | POSITION_DIRTY); } +void LLJoint::setDefaultPosition( const LLVector3& pos ) +{ + mDefaultPosition = pos; +} + +const LLVector3& LLJoint::getDefaultPosition() const +{ + return mDefaultPosition; +} void showJointPosOverrides( const LLJoint& joint, const std::string& note, const std::string& av_info ) { std::ostringstream os; @@ -317,6 +382,13 @@ void showJointPosOverrides( const LLJoint& joint, const std::string& note, const LL_DEBUGS("Avatar") << av_info << " joint " << joint.getName() << " " << note << " " << os.str() << LL_ENDL; } +bool above_joint_pos_threshold(const LLVector3& diff) +{ + //return !diff.isNull(); + const F32 max_joint_pos_offset = 0.0001f; // 0.1 mm + return diff.lengthSquared() > max_joint_pos_offset * max_joint_pos_offset; +} + //-------------------------------------------------------------------- // addAttachmentPosOverride() //-------------------------------------------------------------------- @@ -326,6 +398,15 @@ void LLJoint::addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh { return; } + if (!above_joint_pos_threshold(pos-getDefaultPosition())) + { + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "Attachment pos override ignored for " << getName() + << ", pos " << pos << " is same as default pos" << LL_ENDL; + } + return; + } if (!m_attachmentOverrides.count()) { if (do_debug_joint(getName())) @@ -385,6 +466,49 @@ void LLJoint::clearAttachmentPosOverrides() } //-------------------------------------------------------------------- +// showAttachmentPosOverrides() +//-------------------------------------------------------------------- +void LLJoint::showAttachmentPosOverrides(const std::string& av_info) const +{ + LLVector3 active_override; + bool has_active_override; + LLUUID mesh_id; + has_active_override = m_attachmentOverrides.findActiveOverride(mesh_id,active_override); + U32 count = m_attachmentOverrides.count(); + if (count==1) + { + LLPosOverrideMap::map_type::const_iterator it = m_attachmentOverrides.getMap().begin(); + std::string highlight = (has_active_override && (it->second == active_override)) ? "*" : ""; + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() + << " has single attachment pos override " << highlight << "" << it->second << " default " << mDefaultPosition << LL_ENDL; + } + else if (count>1) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " has " << count << " attachment pos overrides" << LL_ENDL; + std::set<LLVector3> distinct_offsets; + LLPosOverrideMap::map_type::const_iterator it = m_attachmentOverrides.getMap().begin(); + for (; it != m_attachmentOverrides.getMap().end(); ++it) + { + distinct_offsets.insert(it->second); + } + if (distinct_offsets.size()>1) + { + LL_DEBUGS("Avatar") << "CONFLICTS, " << distinct_offsets.size() << " different values" << LL_ENDL; + } + else + { + LL_DEBUGS("Avatar") << "no conflicts" << LL_ENDL; + } + std::set<LLVector3>::iterator dit = distinct_offsets.begin(); + for ( ; dit != distinct_offsets.end(); ++dit) + { + std::string highlight = (has_active_override && *dit == active_override) ? "*" : ""; + LL_DEBUGS("Avatar") << " POS " << highlight << "" << (*dit) << " default " << mDefaultPosition << LL_ENDL; + } + } +} + +//-------------------------------------------------------------------- // updatePos() //-------------------------------------------------------------------- void LLJoint::updatePos(const std::string& av_info) @@ -393,17 +517,40 @@ void LLJoint::updatePos(const std::string& av_info) LLUUID mesh_id; if (m_attachmentOverrides.findActiveOverride(mesh_id,found_pos)) { - LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner of " << m_attachmentOverrides.count() << " is mesh " << mesh_id << " pos " << found_pos << LL_ENDL; + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner of " << m_attachmentOverrides.count() << " is mesh " << mesh_id << " pos " << found_pos << LL_ENDL; + } pos = found_pos; } else { - LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner is posBeforeOverrides " << m_posBeforeOverrides << LL_ENDL; + if (do_debug_joint(getName())) + { + LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner is posBeforeOverrides " << m_posBeforeOverrides << LL_ENDL; + } pos = m_posBeforeOverrides; } setPosition(pos); } +// init static +LLJoint::debug_joint_name_t LLJoint::s_debugJointNames = debug_joint_name_t(); + +//-------------------------------------------------------------------- +// setDebugJointNames +//-------------------------------------------------------------------- +void LLJoint::setDebugJointNames(const debug_joint_name_t& names) +{ + s_debugJointNames = names; +} +void LLJoint::setDebugJointNames(const std::string& names_string) +{ + debug_joint_name_t names; + boost::split(names, names_string, boost::is_any_of(" :,")); + setDebugJointNames(names); +} + //-------------------------------------------------------------------- // getWorldPosition() //-------------------------------------------------------------------- @@ -531,11 +678,17 @@ const LLVector3& LLJoint::getScale() //-------------------------------------------------------------------- void LLJoint::setScale( const LLVector3& scale ) { -// if (mXform.getScale() != scale) + if ((mXform.getScale() != scale) && do_debug_joint(getName())) { - mXform.setScale(scale); - touch(); + LLScopedContextString str("setScale"); + LLCallStack cs; + LLContextStatus con_status; + LL_DEBUGS("Avatar") << " joint " << getName() << " set scale " << scale << LL_ENDL; + LL_DEBUGS("Avatar") << "CONTEXT:\n" << "====================\n" << con_status << LL_ENDL; + LL_DEBUGS("Avatar") << "STACK:\n" << "====================\n" << cs << "====================" << LL_ENDL; } + mXform.setScale(scale); + touch(); } diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 2abe1d6db1..d2c573864b 100644 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -40,9 +40,15 @@ #include "xform.h" const S32 LL_CHARACTER_MAX_JOINTS_PER_MESH = 15; -const U32 LL_CHARACTER_MAX_JOINTS = 32; // must be divisible by 4! -const U32 LL_HAND_JOINT_NUM = 31; -const U32 LL_FACE_JOINT_NUM = 30; +// BENTO JOINT COUNT LIMIT - need to set this to final skeleton size +// (bones + attachments) + 2, rounded to next multiple of 4. +const U32 LL_CHARACTER_MAX_ANIMATED_JOINTS = 192; // must be divisible by 4! +const U32 LL_MAX_JOINTS_PER_MESH_OBJECT = 110; + +// These should be higher than the joint_num of any +// other joint, to avoid conflicts in updateMotionsByType() +const U32 LL_HAND_JOINT_NUM = (LL_CHARACTER_MAX_ANIMATED_JOINTS-1); +const U32 LL_FACE_JOINT_NUM = (LL_CHARACTER_MAX_ANIMATED_JOINTS-2); const S32 LL_CHARACTER_MAX_PRIORITY = 7; const F32 LL_MAX_PELVIS_OFFSET = 5.f; @@ -56,8 +62,10 @@ public: void add(const LLUUID& mesh_id, const LLVector3& pos); bool remove(const LLUUID& mesh_id); void clear(); -private: + typedef std::map<LLUUID,LLVector3> map_type; + const map_type& getMap() const { return m_map; } +private: map_type m_map; }; @@ -86,9 +94,17 @@ public: POSITION_DIRTY = 0x1 << 2, ALL_DIRTY = 0x7 }; +public: + enum SupportCategory + { + SUPPORT_BASE, + SUPPORT_EXTENDED + }; protected: std::string mName; + SupportCategory mSupport; + // parent joint LLJoint *mParent; @@ -97,6 +113,8 @@ protected: LLUUID mId; + LLVector3 mDefaultPosition; + public: U32 mDirtyFlags; BOOL mUpdateXform; @@ -104,6 +122,10 @@ public: // describes the skin binding pose LLVector3 mSkinOffset; + // Endpoint of the bone, if applicable. This is only relevant for + // external programs like Blender, and for diagnostic display. + LLVector3 mEnd; + S32 mJointNum; // child joints @@ -113,6 +135,10 @@ public: // debug statics static S32 sNumTouches; static S32 sNumUpdates; + typedef std::set<std::string> debug_joint_name_t; + static debug_joint_name_t s_debugJointNames; + static void setDebugJointNames(const debug_joint_name_t& names); + static void setDebugJointNames(const std::string& names_string); LLPosOverrideMap m_attachmentOverrides; LLVector3 m_posBeforeOverrides; @@ -121,7 +147,22 @@ public: public: LLJoint(); - LLJoint(S32 joint_num); + + // Note: these joint_num constructors are a bad idea because there + // are only a couple of places in the code where it is useful to + // have a joint num for a joint (for joints that are used in + // animations), and including them as part of the constructor then + // forces us to maintain an alternate path through the entire + // large-ish class hierarchy of joint types. The only reason they + // are still here now is to avoid breaking the baking service + // (appearanceutility) builds; these constructors are not used in + // the viewer. Once the appearance utility is updated to remove + // these joint num references, which it shouldn't ever need, from + // its own classes, we can also remove all the joint_num + // constructors from LLJoint, LLViewerJoint, LLAvatarJoint, and + // createAvatarJoint. + LLJoint(S32 joint_num); + // *TODO: Only used for LLVOAvatarSelf::mScreenp. *DOES NOT INITIALIZE mResetAfterRestoreOldXform* LLJoint( const std::string &name, LLJoint *parent=NULL ); virtual ~LLJoint(); @@ -139,6 +180,19 @@ public: const std::string& getName() const { return mName; } void setName( const std::string &name ) { mName = name; } + // joint num + S32 getJointNum() const { return mJointNum; } + void setJointNum(S32 joint_num); + + // get/set support + SupportCategory getSupport() const { return mSupport; } + void setSupport( const SupportCategory& support) { mSupport = support; } + void setSupport( const std::string& support_string); + + // get/set end point + void setEnd( const LLVector3& end) { mEnd = end; } + const LLVector3& getEnd() const { return mEnd; } + // getParent LLJoint *getParent() { return mParent; } @@ -155,10 +209,12 @@ public: // get/set local position const LLVector3& getPosition(); - void setPosition( const LLVector3& pos ); - + void setPosition( const LLVector3& pos, bool apply_attachment_overrides = false ); + + // Tracks the default position defined by the skeleton void setDefaultPosition( const LLVector3& pos ); - + const LLVector3& getDefaultPosition() const; + // get/set world position LLVector3 getWorldPosition(); LLVector3 getLastWorldPosition(); @@ -198,12 +254,11 @@ public: virtual BOOL isAnimatable() const { return TRUE; } - S32 getJointNum() const { return mJointNum; } - void addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info ); void removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info ); bool hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const; void clearAttachmentPosOverrides(); + void showAttachmentPosOverrides(const std::string& av_info) const; //Accessor for the joint id LLUUID getId( void ) { return mId; } diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index cd201a65b4..052ca3be58 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -1380,7 +1380,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) LL_WARNS() << "no joints in animation" << LL_ENDL; return FALSE; } - else if (num_motions > LL_CHARACTER_MAX_JOINTS) + else if (num_motions > LL_CHARACTER_MAX_ANIMATED_JOINTS) { LL_WARNS() << "too many joints in animation" << LL_ENDL; return FALSE; @@ -1419,7 +1419,14 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) LLJoint *joint = mCharacter->getJoint( joint_name ); if (joint) { + S32 joint_num = joint->getJointNum(); // LL_INFOS() << " joint: " << joint_name << LL_ENDL; + if ((joint_num >= (S32)LL_CHARACTER_MAX_ANIMATED_JOINTS) || (joint_num < 0)) + { + LL_WARNS() << "Joint will be omitted from animation: joint_num " << joint_num << " is outside of legal range [0-" + << LL_CHARACTER_MAX_ANIMATED_JOINTS << ") for joint " << joint->getName() << LL_ENDL; + joint = NULL; + } } else { @@ -1603,6 +1610,12 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp) if (old_version) { success = dp.unpackVector3(pos_key.mPosition, "pos"); + + //MAINT-6162 + pos_key.mPosition.mV[VX] = llclamp( pos_key.mPosition.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mPosition.mV[VY] = llclamp( pos_key.mPosition.mV[VY], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + pos_key.mPosition.mV[VZ] = llclamp( pos_key.mPosition.mV[VZ], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); + } else { @@ -1868,6 +1881,8 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const { BOOL success = TRUE; + LL_DEBUGS("BVH") << "serializing" << LL_ENDL; + success &= dp.packU16(KEYFRAME_MOTION_VERSION, "version"); success &= dp.packU16(KEYFRAME_MOTION_SUBVERSION, "sub_version"); success &= dp.packS32(mJointMotionList->mBasePriority, "base_priority"); @@ -1881,6 +1896,19 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packU32(mJointMotionList->mHandPose, "hand_pose"); success &= dp.packU32(mJointMotionList->getNumJointMotions(), "num_joints"); + LL_DEBUGS("BVH") << "version " << KEYFRAME_MOTION_VERSION << LL_ENDL; + LL_DEBUGS("BVH") << "sub_version " << KEYFRAME_MOTION_SUBVERSION << LL_ENDL; + LL_DEBUGS("BVH") << "base_priority " << mJointMotionList->mBasePriority << LL_ENDL; + LL_DEBUGS("BVH") << "duration " << mJointMotionList->mDuration << LL_ENDL; + LL_DEBUGS("BVH") << "emote_name " << mJointMotionList->mEmoteName << LL_ENDL; + LL_DEBUGS("BVH") << "loop_in_point " << mJointMotionList->mLoopInPoint << LL_ENDL; + LL_DEBUGS("BVH") << "loop_out_point " << mJointMotionList->mLoopOutPoint << LL_ENDL; + LL_DEBUGS("BVH") << "loop " << mJointMotionList->mLoop << LL_ENDL; + LL_DEBUGS("BVH") << "ease_in_duration " << mJointMotionList->mEaseInDuration << LL_ENDL; + LL_DEBUGS("BVH") << "ease_out_duration " << mJointMotionList->mEaseOutDuration << LL_ENDL; + LL_DEBUGS("BVH") << "hand_pose " << mJointMotionList->mHandPose << LL_ENDL; + LL_DEBUGS("BVH") << "num_joints " << mJointMotionList->getNumJointMotions() << LL_ENDL; + for (U32 i = 0; i < mJointMotionList->getNumJointMotions(); i++) { JointMotion* joint_motionp = mJointMotionList->getJointMotion(i); @@ -1888,6 +1916,7 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packS32(joint_motionp->mPriority, "joint_priority"); success &= dp.packS32(joint_motionp->mRotationCurve.mNumKeys, "num_rot_keys"); + LL_DEBUGS("BVH") << "Joint " << joint_motionp->mJointName << LL_ENDL; for (RotationCurve::key_map_t::iterator iter = joint_motionp->mRotationCurve.mKeys.begin(); iter != joint_motionp->mRotationCurve.mKeys.end(); ++iter) { @@ -1905,6 +1934,8 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packU16(x, "rot_angle_x"); success &= dp.packU16(y, "rot_angle_y"); success &= dp.packU16(z, "rot_angle_z"); + + LL_DEBUGS("BVH") << " rot: t " << rot_key.mTime << " angles " << rot_angles.mV[VX] <<","<< rot_angles.mV[VY] <<","<< rot_angles.mV[VZ] << LL_ENDL; } success &= dp.packS32(joint_motionp->mPositionCurve.mNumKeys, "num_pos_keys"); @@ -1923,37 +1954,54 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const success &= dp.packU16(x, "pos_x"); success &= dp.packU16(y, "pos_y"); success &= dp.packU16(z, "pos_z"); + + LL_DEBUGS("BVH") << " pos: t " << pos_key.mTime << " pos " << pos_key.mPosition.mV[VX] <<","<< pos_key.mPosition.mV[VY] <<","<< pos_key.mPosition.mV[VZ] << LL_ENDL; } } success &= dp.packS32(mJointMotionList->mConstraints.size(), "num_constraints"); + LL_DEBUGS("BVH") << "num_constraints " << mJointMotionList->mConstraints.size() << LL_ENDL; for (JointMotionList::constraint_list_t::const_iterator iter = mJointMotionList->mConstraints.begin(); iter != mJointMotionList->mConstraints.end(); ++iter) { JointConstraintSharedData* shared_constraintp = *iter; success &= dp.packU8(shared_constraintp->mChainLength, "chain_length"); success &= dp.packU8(shared_constraintp->mConstraintType, "constraint_type"); - char volume_name[16]; /* Flawfinder: ignore */ - snprintf(volume_name, sizeof(volume_name), "%s", /* Flawfinder: ignore */ + char source_volume[16]; /* Flawfinder: ignore */ + snprintf(source_volume, sizeof(source_volume), "%s", /* Flawfinder: ignore */ mCharacter->findCollisionVolume(shared_constraintp->mSourceConstraintVolume)->getName().c_str()); - success &= dp.packBinaryDataFixed((U8*)volume_name, 16, "source_volume"); + + success &= dp.packBinaryDataFixed((U8*)source_volume, 16, "source_volume"); success &= dp.packVector3(shared_constraintp->mSourceConstraintOffset, "source_offset"); + char target_volume[16]; /* Flawfinder: ignore */ if (shared_constraintp->mConstraintTargetType == CONSTRAINT_TARGET_TYPE_GROUND) { - snprintf(volume_name,sizeof(volume_name), "%s", "GROUND"); /* Flawfinder: ignore */ + snprintf(target_volume,sizeof(target_volume), "%s", "GROUND"); /* Flawfinder: ignore */ } else { - snprintf(volume_name, sizeof(volume_name),"%s", /* Flawfinder: ignore */ + snprintf(target_volume, sizeof(target_volume),"%s", /* Flawfinder: ignore */ mCharacter->findCollisionVolume(shared_constraintp->mTargetConstraintVolume)->getName().c_str()); } - success &= dp.packBinaryDataFixed((U8*)volume_name, 16, "target_volume"); + success &= dp.packBinaryDataFixed((U8*)target_volume, 16, "target_volume"); success &= dp.packVector3(shared_constraintp->mTargetConstraintOffset, "target_offset"); success &= dp.packVector3(shared_constraintp->mTargetConstraintDir, "target_dir"); success &= dp.packF32(shared_constraintp->mEaseInStartTime, "ease_in_start"); success &= dp.packF32(shared_constraintp->mEaseInStopTime, "ease_in_stop"); success &= dp.packF32(shared_constraintp->mEaseOutStartTime, "ease_out_start"); success &= dp.packF32(shared_constraintp->mEaseOutStopTime, "ease_out_stop"); + + LL_DEBUGS("BVH") << " chain_length " << shared_constraintp->mChainLength << LL_ENDL; + LL_DEBUGS("BVH") << " constraint_type " << (S32)shared_constraintp->mConstraintType << LL_ENDL; + LL_DEBUGS("BVH") << " source_volume " << source_volume << LL_ENDL; + LL_DEBUGS("BVH") << " source_offset " << shared_constraintp->mSourceConstraintOffset << LL_ENDL; + LL_DEBUGS("BVH") << " target_volume " << target_volume << LL_ENDL; + LL_DEBUGS("BVH") << " target_offset " << shared_constraintp->mTargetConstraintOffset << LL_ENDL; + LL_DEBUGS("BVH") << " target_dir " << shared_constraintp->mTargetConstraintDir << LL_ENDL; + LL_DEBUGS("BVH") << " ease_in_start " << shared_constraintp->mEaseInStartTime << LL_ENDL; + LL_DEBUGS("BVH") << " ease_in_stop " << shared_constraintp->mEaseInStopTime << LL_ENDL; + LL_DEBUGS("BVH") << " ease_out_start " << shared_constraintp->mEaseOutStartTime << LL_ENDL; + LL_DEBUGS("BVH") << " ease_out_stop " << shared_constraintp->mEaseOutStopTime << LL_ENDL; } return success; @@ -1972,6 +2020,51 @@ U32 LLKeyframeMotion::getFileSize() } //----------------------------------------------------------------------------- +// dumpToFile() +//----------------------------------------------------------------------------- +void LLKeyframeMotion::dumpToFile(const std::string& name) +{ + if (isLoaded()) + { + std::string outfile_base; + if (!name.empty()) + { + outfile_base = name; + } + else if (!getName().empty()) + { + outfile_base = getName(); + } + else + { + const LLUUID& id = getID(); + outfile_base = id.asString(); + } + std::string outfilename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfile_base + ".anim"); + if (LLFile::isfile(outfilename)) + { + return; + } + + S32 file_size = getFileSize(); + U8* buffer = new U8[file_size]; + + LL_DEBUGS("BVH") << "Dumping " << outfilename << LL_ENDL; + LLDataPackerBinaryBuffer dp(buffer, file_size); + if (serialize(dp)) + { + LLAPRFile outfile; + outfile.open(outfilename, LL_APR_WPB); + if (outfile.getFileHandle()) + { + outfile.write(buffer, file_size); + } + } + delete [] buffer; + } +} + +//----------------------------------------------------------------------------- // getPelvisBBox() //----------------------------------------------------------------------------- const LLBBoxLocal &LLKeyframeMotion::getPelvisBBox() diff --git a/indra/llcharacter/llkeyframemotion.h b/indra/llcharacter/llkeyframemotion.h index b1422b2b90..f1fa56d731 100644 --- a/indra/llcharacter/llkeyframemotion.h +++ b/indra/llcharacter/llkeyframemotion.h @@ -153,6 +153,7 @@ public: BOOL serialize(LLDataPacker& dp) const; BOOL deserialize(LLDataPacker& dp); BOOL isLoaded() { return mJointMotionList != NULL; } + void dumpToFile(const std::string& name); // setters for modifying a keyframe animation diff --git a/indra/llcharacter/llkeyframestandmotion.cpp b/indra/llcharacter/llkeyframestandmotion.cpp index fdeddf55e1..02c1d3cdbd 100644 --- a/indra/llcharacter/llkeyframestandmotion.cpp +++ b/indra/llcharacter/llkeyframestandmotion.cpp @@ -201,10 +201,12 @@ BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask) //------------------------------------------------------------------------- // propagate joint positions to internal versions //------------------------------------------------------------------------- + // SL-315 mPelvisJoint.setPosition( root_world_pos + mPelvisState->getPosition() ); + // SL-315 mHipLeftJoint.setPosition( mHipLeftState->getJoint()->getPosition() ); mKneeLeftJoint.setPosition( mKneeLeftState->getJoint()->getPosition() ); mAnkleLeftJoint.setPosition( mAnkleLeftState->getJoint()->getPosition() ); @@ -213,6 +215,7 @@ BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask) mKneeLeftJoint.setScale( mKneeLeftState->getJoint()->getScale() ); mAnkleLeftJoint.setScale( mAnkleLeftState->getJoint()->getScale() ); + // SL-315 mHipRightJoint.setPosition( mHipRightState->getJoint()->getPosition() ); mKneeRightJoint.setPosition( mKneeRightState->getJoint()->getPosition() ); mAnkleRightJoint.setPosition( mAnkleRightState->getJoint()->getPosition() ); @@ -265,6 +268,7 @@ BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask) mCharacter->getGround( mAnkleLeftJoint.getWorldPosition(), mPositionLeft, mNormalLeft); mCharacter->getGround( mAnkleRightJoint.getWorldPosition(), mPositionRight, mNormalRight); + // SL-315 mTargetLeft.setPosition( mPositionLeft ); mTargetRight.setPosition( mPositionRight ); } diff --git a/indra/llcharacter/llmotion.cpp b/indra/llcharacter/llmotion.cpp index 4803f855de..697efc8157 100644 --- a/indra/llcharacter/llmotion.cpp +++ b/indra/llcharacter/llmotion.cpp @@ -55,7 +55,7 @@ LLMotion::LLMotion( const LLUUID &id ) : mDeactivateCallbackUserData(NULL) { for (S32 i=0; i<3; ++i) - memset(&mJointSignature[i][0], 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS); + memset(&mJointSignature[i][0], 0, sizeof(U8) * LL_CHARACTER_MAX_ANIMATED_JOINTS); } //----------------------------------------------------------------------------- @@ -111,9 +111,15 @@ void LLMotion::addJointState(const LLPointer<LLJointState>& jointState) U32 usage = jointState->getUsage(); // for now, usage is everything - mJointSignature[0][jointState->getJoint()->getJointNum()] = (usage & LLJointState::POS) ? (0xff >> (7 - priority)) : 0; - mJointSignature[1][jointState->getJoint()->getJointNum()] = (usage & LLJointState::ROT) ? (0xff >> (7 - priority)) : 0; - mJointSignature[2][jointState->getJoint()->getJointNum()] = (usage & LLJointState::SCALE) ? (0xff >> (7 - priority)) : 0; + S32 joint_num = jointState->getJoint()->getJointNum(); + if ((joint_num >= (S32)LL_CHARACTER_MAX_ANIMATED_JOINTS) || (joint_num < 0)) + { + LL_WARNS() << "joint_num " << joint_num << " is outside of legal range [0-" << LL_CHARACTER_MAX_ANIMATED_JOINTS << ") for joint " << jointState->getJoint()->getName() << LL_ENDL; + return; + } + mJointSignature[0][joint_num] = (usage & LLJointState::POS) ? (0xff >> (7 - priority)) : 0; + mJointSignature[1][joint_num] = (usage & LLJointState::ROT) ? (0xff >> (7 - priority)) : 0; + mJointSignature[2][joint_num] = (usage & LLJointState::SCALE) ? (0xff >> (7 - priority)) : 0; } void LLMotion::setDeactivateCallback( void (*cb)(void *), void* userdata ) diff --git a/indra/llcharacter/llmotion.h b/indra/llcharacter/llmotion.h index 5e37f094b8..2dfc3afc7f 100644 --- a/indra/llcharacter/llmotion.h +++ b/indra/llcharacter/llmotion.h @@ -181,7 +181,7 @@ protected: F32 mSendStopTimestamp; // time when simulator should be told to stop this motion F32 mResidualWeight; // blend weight at beginning of stop motion phase F32 mFadeWeight; // for fading in and out based on LOD - U8 mJointSignature[3][LL_CHARACTER_MAX_JOINTS]; // signature of which joints are animated at what priority + U8 mJointSignature[3][LL_CHARACTER_MAX_ANIMATED_JOINTS]; // signature of which joints are animated at what priority void (*mDeactivateCallback)(void* data); void* mDeactivateCallbackUserData; }; diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index e02b139608..d8185aa693 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -37,7 +37,8 @@ #include "llanimationstates.h" #include "llstl.h" -const S32 NUM_JOINT_SIGNATURE_STRIDES = LL_CHARACTER_MAX_JOINTS / 4; +// This is why LL_CHARACTER_MAX_ANIMATED_JOINTS needs to be a multiple of 4. +const S32 NUM_JOINT_SIGNATURE_STRIDES = LL_CHARACTER_MAX_ANIMATED_JOINTS / 4; const U32 MAX_MOTION_INSTANCES = 32; //----------------------------------------------------------------------------- @@ -488,8 +489,8 @@ void LLMotionController::updateAdditiveMotions() //----------------------------------------------------------------------------- void LLMotionController::resetJointSignatures() { - memset(&mJointSignature[0][0], 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS); - memset(&mJointSignature[1][0], 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS); + memset(&mJointSignature[0][0], 0, sizeof(U8) * LL_CHARACTER_MAX_ANIMATED_JOINTS); + memset(&mJointSignature[1][0], 0, sizeof(U8) * LL_CHARACTER_MAX_ANIMATED_JOINTS); } //----------------------------------------------------------------------------- @@ -553,9 +554,9 @@ static LLTrace::BlockTimerStatHandle FTM_MOTION_ON_UPDATE("Motion onUpdate"); void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_type) { BOOL update_result = TRUE; - U8 last_joint_signature[LL_CHARACTER_MAX_JOINTS]; + U8 last_joint_signature[LL_CHARACTER_MAX_ANIMATED_JOINTS]; - memset(&last_joint_signature, 0, sizeof(U8) * LL_CHARACTER_MAX_JOINTS); + memset(&last_joint_signature, 0, sizeof(U8) * LL_CHARACTER_MAX_ANIMATED_JOINTS); // iterate through active motions in chronological order for (motion_list_t::iterator iter = mActiveMotions.begin(); @@ -576,7 +577,6 @@ void LLMotionController::updateMotionsByType(LLMotion::LLMotionBlendType anim_ty } else { - // NUM_JOINT_SIGNATURE_STRIDES should be multiple of 4 for (S32 i = 0; i < NUM_JOINT_SIGNATURE_STRIDES; i++) { U32 *current_signature = (U32*)&(mJointSignature[0][i * 4]); diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h index 2bd5271c4f..72de331694 100644 --- a/indra/llcharacter/llmotioncontroller.h +++ b/indra/llcharacter/llmotioncontroller.h @@ -223,7 +223,7 @@ protected: S32 mTimeStepCount; F32 mLastInterp; - U8 mJointSignature[2][LL_CHARACTER_MAX_JOINTS]; + U8 mJointSignature[2][LL_CHARACTER_MAX_ANIMATED_JOINTS]; }; //----------------------------------------------------------------------------- diff --git a/indra/llcharacter/llpose.cpp b/indra/llcharacter/llpose.cpp index b1a7ebb159..fc95fafd61 100644 --- a/indra/llcharacter/llpose.cpp +++ b/indra/llcharacter/llpose.cpp @@ -386,6 +386,7 @@ void LLJointStateBlender::blendJointStates(BOOL apply_now) } // apply transforms + // SL-315 target_joint->setPosition(blended_pos + added_pos); target_joint->setScale(blended_scale + added_scale); target_joint->setRotation(added_rot * blended_rot); @@ -417,6 +418,7 @@ void LLJointStateBlender::interpolate(F32 u) return; } + // SL-315 target_joint->setPosition(lerp(target_joint->getPosition(), mJointCache.getPosition(), u)); target_joint->setScale(lerp(target_joint->getScale(), mJointCache.getScale(), u)); target_joint->setRotation(nlerp(u, target_joint->getRotation(), mJointCache.getRotation())); @@ -444,6 +446,7 @@ void LLJointStateBlender::resetCachedJoint() return; } LLJoint* source_joint = mJointStates[0]->getJoint(); + // SL-315 mJointCache.setPosition(source_joint->getPosition()); mJointCache.setScale(source_joint->getScale()); mJointCache.setRotation(source_joint->getRotation()); diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h index c6b97d7e8b..0ad063fd1e 100644 --- a/indra/llcharacter/llvisualparam.h +++ b/indra/llcharacter/llvisualparam.h @@ -150,6 +150,7 @@ public: F32 getWeight() const { return mIsAnimating ? mTargetWeight : mCurWeight; } F32 getCurrentWeight() const { return mCurWeight; } F32 getLastWeight() const { return mLastWeight; } + void setLastWeight(F32 val) { mLastWeight = val; } BOOL isAnimating() const { return mIsAnimating; } BOOL isTweakable() const { return (getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) || (getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT); } diff --git a/indra/llcharacter/tests/lljoint_test.cpp b/indra/llcharacter/tests/lljoint_test.cpp index da151808f2..617f31b0e4 100644 --- a/indra/llcharacter/tests/lljoint_test.cpp +++ b/indra/llcharacter/tests/lljoint_test.cpp @@ -88,6 +88,7 @@ namespace tut { LLJoint lljoint; LLVector3 vec3(2.3f,30.f,10.f); + // SL-315 lljoint.setPosition(vec3); LLVector3 pos = lljoint.getPosition(); ensure("setPosition()/getPosition() failed ", (vec3 == pos)); @@ -98,6 +99,7 @@ namespace tut { LLJoint lljoint; LLVector3 vec3(2.3f,30.f,10.f); + // SL-315 lljoint.setWorldPosition(vec3); LLVector3 pos = lljoint.getWorldPosition(); ensure("1:setWorldPosition()/getWorldPosition() failed ", (vec3 == pos)); |