summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorprep linden <prep@lindenlab.com>2010-09-24 13:11:53 -0400
committerprep linden <prep@lindenlab.com>2010-09-24 13:11:53 -0400
commitc7f5a9419b4b93efdc04ebfbb8e05a2ef0e09142 (patch)
treed4bd4000daf955114e9dc1ed96a873b620115299
parente0588af08737177f8a1bc519376073e14b886434 (diff)
Added support for joint offsets
-rwxr-xr-xindra/llcharacter/lljoint.cpp15
-rwxr-xr-xindra/llcharacter/lljoint.h4
-rwxr-xr-xindra/llprimitive/llmodel.cpp15
-rwxr-xr-xindra/llprimitive/llmodel.h2
-rwxr-xr-xindra/newview/llfloatermodelpreview.cpp127
-rwxr-xr-xindra/newview/llmeshrepository.cpp17
-rwxr-xr-xindra/newview/llmeshrepository.h2
-rwxr-xr-xindra/newview/llviewerfoldertype.cpp3
-rwxr-xr-xindra/newview/llvoavatar.cpp10
-rwxr-xr-xindra/newview/llvoavatar.h4
-rwxr-xr-xindra/newview/llvovolume.cpp26
11 files changed, 222 insertions, 3 deletions
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index 5c49214051..2449b01e15 100755
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -239,6 +239,21 @@ void LLJoint::setPosition( const LLVector3& pos )
}
}
+//--------------------------------------------------------------------
+// storeCurrentXform()
+//--------------------------------------------------------------------
+void LLJoint::storeCurrentXform( const LLVector3& pos )
+{
+ mOldXform = mXform;
+ setPosition( pos );
+}
+//--------------------------------------------------------------------
+// restoreOldXform()
+//--------------------------------------------------------------------
+void LLJoint::restoreOldXform( void )
+{
+ mXform = mOldXform;
+}
//--------------------------------------------------------------------
// getWorldPosition()
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index 0473d1599a..cf644e899f 100755
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -86,6 +86,7 @@ protected:
// explicit transformation members
LLXformMatrix mXform;
+ LLXformMatrix mOldXform;
public:
U32 mDirtyFlags;
@@ -178,6 +179,9 @@ public:
S32 getJointNum() const { return mJointNum; }
void setJointNum(S32 joint_num) { mJointNum = joint_num; }
+
+ void restoreOldXform( void );
+ void storeCurrentXform( const LLVector3& pos );
};
#endif // LL_LLJOINT_H
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index 349c844470..f3f9c29157 100755
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -1342,6 +1342,21 @@ LLSD LLModel::writeModel(std::ostream& ostr, LLModel* physics, LLModel* high, LL
mdl["skin"]["bind_shape_matrix"][i*4+j] = high->mBindShapeMatrix.mMatrix[i][j];
}
}
+
+ if ( high->mAlternateBindMatrix.size() > 0 )
+ {
+ for (U32 i = 0; i < high->mJointList.size(); ++i)
+ {
+ for (U32 j = 0; j < 4; j++)
+ {
+ for (U32 k = 0; k < 4; k++)
+ {
+ mdl["skin"]["alt_inverse_bind_matrix"][i][j*4+k] = high->mAlternateBindMatrix[i].mMatrix[j][k];
+ }
+ }
+ }
+ }
+
}
if (!decomp.empty())
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index ea703d7228..ff22d39e60 100755
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -152,7 +152,7 @@ public:
LLMatrix4 mBindShapeMatrix;
std::vector<LLMatrix4> mInvBindMatrix;
-
+ std::vector<LLMatrix4> mAlternateBindMatrix;
std::string mLabel;
LLVector3 mNormalizedScale;
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 1796f76f03..3fe5d08bb3 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -318,6 +318,8 @@ LLFloaterModelPreview::~LLFloaterModelPreview()
{
sInstance = NULL;
+ gAgentAvatarp->resetJointPositions();
+
delete mModelPreview;
if (mGLName)
@@ -1304,6 +1306,106 @@ void LLModelLoader::run()
model->mBindShapeMatrix = rotation;
}*/
+ //The joint transfom map that we'll populate below
+ std::map<std::string,LLMatrix4> jointTransforms;
+ jointTransforms.clear();
+
+ //Some collada setup for accessing the skeleton
+ daeElement* pElement = 0;
+ dae.getDatabase()->getElement( &pElement, 0, 0, "skeleton" );
+ domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement );
+ if ( pSkeleton )
+ {
+ //Get the root node of the skeleton
+ daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
+ if ( pSkeletonRootNode )
+ {
+ //Once we have the root node - start acccessing it's joint components
+ static const int jointCnt = mJointMap.size();
+ std::map<std::string, std::string> :: const_iterator jointIt = mJointMap.begin();
+ bool missingID = false;
+ //Loop over all the possible joints within the .dae - using the allowed joint list in the ctor.
+ for ( int i=0; i<jointCnt; ++i, ++jointIt )
+ {
+ //Build a joint for the resolver to work with
+ char str[64]={0};
+ sprintf(str,"./%s",(*jointIt).second.c_str() );
+ //llwarns<<"Joint "<< str <<llendl;
+
+ //Setup the resolver
+ daeSIDResolver resolver( pSkeletonRootNode, str );
+
+ //Look for the joint
+ domNode* pJoint = daeSafeCast<domNode>(resolver.getElement());
+ if ( pJoint )
+ {
+ //Pull out the translate id and store it in the jointTranslations map
+ daeSIDResolver jointResolver( pJoint, "./translate" );
+ domTranslate* pTranslate = daeSafeCast<domTranslate>( jointResolver.getElement() );
+
+ LLMatrix4 workingTransform;
+
+ //Translation
+ if ( pTranslate )
+ {
+ domFloat3 jointTrans = pTranslate->getValue();
+ LLVector3 singleJointTranslation( jointTrans[0], jointTrans[1], jointTrans[2] );
+ workingTransform.setTranslation( singleJointTranslation );
+ }
+ else
+ {
+ missingID = true;
+ llwarns<< "No translation sid!" << llendl;
+ }
+ //Store the joint transform w/respect to it's name.
+ jointTransforms[(*jointIt).second.c_str()] = workingTransform;
+
+ }
+ else
+ {
+ missingID = true;
+ llwarns<< "Missing joint." << llendl;
+ }
+ }
+
+ //If anything failed in regards to extracting the skeleton, joints or translation id,
+ //mention it
+ if ( missingID )
+ {
+ llwarns<< "Partial jointmap found in asset - did you mean to just have a partial map?" << llendl;
+ }
+
+ //Set the joint translations on the avatar
+ //The joints are reset in the dtor
+ jointIt = mJointMap.begin();
+ for ( int i=0; i<jointCnt; ++i, ++jointIt )
+ {
+ std::string lookingForJoint = (*jointIt).first.c_str();
+ if ( jointTransforms.find( lookingForJoint ) != jointTransforms.end() )
+ {
+ LLMatrix4 jointTransform = jointTransforms[lookingForJoint];
+ LLJoint* pJoint = gAgentAvatarp->getJoint( lookingForJoint );
+ if ( pJoint )
+ {
+ pJoint->storeCurrentXform( jointTransform.getTranslation() );
+ }
+ else
+ {
+ //Most likely an error in the asset.
+ llwarns<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << llendl;
+ }
+ }
+ }
+ }
+ else
+ {
+ llwarns<<"No root node in this skeleton" << llendl;
+ }
+ }
+ else
+ {
+ llwarns<<"No skeleton in this asset" << llendl;
+ }
domSkin::domJoints* joints = skin->getJoints();
@@ -1391,6 +1493,29 @@ void LLModelLoader::run()
}
}
+ //We need to construct the alternate bind matrix (which contains the new joint positions)
+ //in the same order as they were stored in the joint buffer. The joints associated
+ //with the skeleton are not stored in the same order as they are in the exported joint buffer.
+ //This remaps the skeletal joints to be in the same order as the joints stored in the model.
+ std::vector<std::string> :: const_iterator jointIt = model->mJointList.begin();
+ static const int jointCnt = model->mJointList.size();
+ for ( int i=0; i<jointCnt; ++i, ++jointIt )
+ {
+ std::string lookingForJoint = (*jointIt).c_str();
+ //Look for the joint xform that we extracted from the skeleton, using the jointIt as the key
+ //and store it in the alternate bind matrix
+ if ( jointTransforms.find( lookingForJoint ) != jointTransforms.end() )
+ {
+ LLMatrix4 jointTransform = jointTransforms[lookingForJoint];
+ LLMatrix4 newInverse = model->mInvBindMatrix[i];
+ newInverse.setTranslation( jointTransforms[lookingForJoint].getTranslation() );
+ model->mAlternateBindMatrix.push_back( newInverse );
+ }
+ else
+ {
+ llwarns<<"Possibly misnamed/missing joint [" <<lookingForJoint.c_str()<<" ] "<<llendl;
+ }
+ }
//grab raw position array
@@ -2617,7 +2742,7 @@ void LLModelPreview::genLODs(S32 which_lod)
target_model->mJointList = base->mJointList;
target_model->mInvBindMatrix = base->mInvBindMatrix;
target_model->mBindShapeMatrix = base->mBindShapeMatrix;
-
+ target_model->mAlternateBindMatrix = base->mAlternateBindMatrix;
//copy material list
target_model->mMaterialList = base->mMaterialList;
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 8b14af009c..8381847842 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1016,6 +1016,23 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat
}
}
+ if (skin.has("alt_inverse_bind_matrix"))
+ {
+ for (U32 i = 0; i < skin["alt_inverse_bind_matrix"].size(); ++i)
+ {
+ LLMatrix4 mat;
+ for (U32 j = 0; j < 4; j++)
+ {
+ for (U32 k = 0; k < 4; k++)
+ {
+ mat.mMatrix[j][k] = skin["alt_inverse_bind_matrix"][i][j*4+k].asReal();
+ }
+ }
+
+ info.mAlternateBindMatrix.push_back(mat);
+ }
+ }
+
mSkinInfoQ.push(info);
}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index a2f403e214..7a65ea7a44 100755
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -132,6 +132,8 @@ public:
LLUUID mMeshID;
std::vector<std::string> mJointNames;
std::vector<LLMatrix4> mInvBindMatrix;
+ std::vector<LLMatrix4> mAlternateBindMatrix;
+
LLMatrix4 mBindShapeMatrix;
};
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index 3105a6ec43..1056db34ee 100755
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -132,6 +132,9 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
addEntry(LLFolderType::FT_CURRENT_OUTFIT, new ViewerFolderEntry("Current Outfit", "Inv_SysOpen", "Inv_SysClosed", TRUE));
addEntry(LLFolderType::FT_OUTFIT, new ViewerFolderEntry("New Outfit", "Inv_LookFolderOpen", "Inv_LookFolderClosed", TRUE));
addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "Inv_SysOpen", "Inv_SysClosed", TRUE));
+ addEntry(LLFolderType::FT_MESH, new ViewerFolderEntry("Mesh", "Inv_SysOpen", "Inv_SysClosed", FALSE));
+
+
addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "Inv_SysOpen", "Inv_SysClosed", FALSE));
addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, "default"));
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 54400c184b..1c65b18206 100755
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -4784,6 +4784,16 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )
}
//-----------------------------------------------------------------------------
+// resetJointPositions
+//-----------------------------------------------------------------------------
+void LLVOAvatar::resetJointPositions( void )
+{
+ for(S32 i = 0; i < (S32)mNumJoints; ++i)
+ {
+ mSkeleton[i].restoreOldXform();
+ }
+}
+//-----------------------------------------------------------------------------
// getCharacterPosition()
//-----------------------------------------------------------------------------
LLVector3 LLVOAvatar::getCharacterPosition()
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index 955deff1ea..af5cde7f46 100755
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -169,7 +169,9 @@ public:
virtual LLJoint* getJoint(const std::string &name);
virtual LLJoint* getRootJoint() { return &mRoot; }
-
+
+ void resetJointPositions( void );
+
virtual const char* getAnimationPrefix() { return "avatar"; }
virtual const LLUUID& getID();
virtual LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset);
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index d96b6eccb1..ed9ea2320e 100755
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4027,6 +4027,32 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
//get drawpool of avatar with rigged face
LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj);
+ //Determine if we've received skininfo that contains an
+ //alternate bind matrix - if it does then apply the translational component
+ //to the joints of the avatar.
+ const LLVOAvatar* pAvatarVO = vobj->getAvatar();
+ if ( pAvatarVO )
+ {
+ const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( vobj->getVolume()->getParams().getSculptID() );
+ if ( pSkinData )
+ {
+ static const int bindCnt = pSkinData->mAlternateBindMatrix.size();
+ if ( bindCnt > 0 )
+ {
+ static const int jointCnt = pSkinData->mJointNames.size();
+ for ( int i=0; i<jointCnt; ++i )
+ {
+ std::string lookingForJoint = pSkinData->mJointNames[i].c_str();
+ LLJoint* pJoint = vobj->getAvatar()->getJoint( lookingForJoint );
+ if ( pJoint )
+ {
+ pJoint->storeCurrentXform( pSkinData->mAlternateBindMatrix[i].getTranslation() );
+ }
+ }
+ }
+ }
+ }
+
if (pool)
{
const LLTextureEntry* te = facep->getTextureEntry();