diff options
author | prep linden <prep@lindenlab.com> | 2010-09-24 13:11:53 -0400 |
---|---|---|
committer | prep linden <prep@lindenlab.com> | 2010-09-24 13:11:53 -0400 |
commit | c7f5a9419b4b93efdc04ebfbb8e05a2ef0e09142 (patch) | |
tree | d4bd4000daf955114e9dc1ed96a873b620115299 | |
parent | e0588af08737177f8a1bc519376073e14b886434 (diff) |
Added support for joint offsets
-rwxr-xr-x | indra/llcharacter/lljoint.cpp | 15 | ||||
-rwxr-xr-x | indra/llcharacter/lljoint.h | 4 | ||||
-rwxr-xr-x | indra/llprimitive/llmodel.cpp | 15 | ||||
-rwxr-xr-x | indra/llprimitive/llmodel.h | 2 | ||||
-rwxr-xr-x | indra/newview/llfloatermodelpreview.cpp | 127 | ||||
-rwxr-xr-x | indra/newview/llmeshrepository.cpp | 17 | ||||
-rwxr-xr-x | indra/newview/llmeshrepository.h | 2 | ||||
-rwxr-xr-x | indra/newview/llviewerfoldertype.cpp | 3 | ||||
-rwxr-xr-x | indra/newview/llvoavatar.cpp | 10 | ||||
-rwxr-xr-x | indra/newview/llvoavatar.h | 4 | ||||
-rwxr-xr-x | indra/newview/llvovolume.cpp | 26 |
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(); |