summaryrefslogtreecommitdiff
path: root/indra/llcharacter
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcharacter')
-rw-r--r--indra/llcharacter/CMakeLists.txt16
-rw-r--r--indra/llcharacter/llbvhloader.cpp461
-rw-r--r--indra/llcharacter/llbvhloader.h14
-rw-r--r--indra/llcharacter/lleditingmotion.cpp6
-rw-r--r--indra/llcharacter/lljoint.cpp183
-rw-r--r--indra/llcharacter/lljoint.h75
-rw-r--r--indra/llcharacter/llkeyframemotion.cpp107
-rw-r--r--indra/llcharacter/llkeyframemotion.h1
-rw-r--r--indra/llcharacter/llkeyframestandmotion.cpp4
-rw-r--r--indra/llcharacter/llmotion.cpp14
-rw-r--r--indra/llcharacter/llmotion.h2
-rw-r--r--indra/llcharacter/llmotioncontroller.cpp12
-rw-r--r--indra/llcharacter/llmotioncontroller.h2
-rw-r--r--indra/llcharacter/llpose.cpp3
-rw-r--r--indra/llcharacter/llvisualparam.h1
-rw-r--r--indra/llcharacter/tests/lljoint_test.cpp2
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));