Added support for joint offsets
parent
e0588af087
commit
c7f5a9419b
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ public:
|
|||
|
||||
LLMatrix4 mBindShapeMatrix;
|
||||
std::vector<LLMatrix4> mInvBindMatrix;
|
||||
|
||||
std::vector<LLMatrix4> mAlternateBindMatrix;
|
||||
std::string mLabel;
|
||||
|
||||
LLVector3 mNormalizedScale;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,6 +132,8 @@ public:
|
|||
LLUUID mMeshID;
|
||||
std::vector<std::string> mJointNames;
|
||||
std::vector<LLMatrix4> mInvBindMatrix;
|
||||
std::vector<LLMatrix4> mAlternateBindMatrix;
|
||||
|
||||
LLMatrix4 mBindShapeMatrix;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
|
|
@ -4783,6 +4783,16 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )
|
|||
return jointp;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// resetJointPositions
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLVOAvatar::resetJointPositions( void )
|
||||
{
|
||||
for(S32 i = 0; i < (S32)mNumJoints; ++i)
|
||||
{
|
||||
mSkeleton[i].restoreOldXform();
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// getCharacterPosition()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue