summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xindra/newview/llfloatermodelpreview.cpp447
-rw-r--r--indra/newview/llfloatermodelpreview.h52
2 files changed, 410 insertions, 89 deletions
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index a808cc47a2..cdd2bcf8e3 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -340,7 +340,7 @@ BOOL LLFloaterModelPreview::postBuild()
mPreviewRect = preview_panel->getRect();
- mModelPreview = new LLModelPreview(512, 512, this);
+ mModelPreview = new LLModelPreview(512, 512, this );
mModelPreview->setPreviewTarget(16.f);
mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5));
@@ -383,7 +383,7 @@ LLFloaterModelPreview::~LLFloaterModelPreview()
sInstance = NULL;
if ( mModelPreview && mModelPreview->getResetJointFlag() )
- {
+ {
gAgentAvatarp->resetJointPositions();
}
@@ -994,8 +994,11 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl
//-----------------------------------------------------------------------------
// LLModelLoader
//-----------------------------------------------------------------------------
-LLModelLoader::LLModelLoader(std::string filename, S32 lod, LLModelPreview* preview)
-: LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE)
+LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap,
+ std::deque<std::string>& jointsFromNodes )
+: mJointList( jointMap )
+, mJointsFromNode( jointsFromNodes )
+, LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE)
{
mJointMap["mPelvis"] = "mPelvis";
mJointMap["mTorso"] = "mTorso";
@@ -1073,27 +1076,6 @@ LLModelLoader::LLModelLoader(std::string filename, S32 lod, LLModelPreview* prev
mJointMap["lShin"] = "mKneeLeft";
mJointMap["lFoot"] = "mFootLeft";
- //move into joint mapper class
- mMasterJointList.push_front("mPelvis");
- mMasterJointList.push_front("mTorso");
- mMasterJointList.push_front("mChest");
- mMasterJointList.push_front("mNeck");
- mMasterJointList.push_front("mHead");
- mMasterJointList.push_front("mCollarLeft");
- mMasterJointList.push_front("mShoulderLeft");
- mMasterJointList.push_front("mElbowLeft");
- mMasterJointList.push_front("mWristLeft");
- mMasterJointList.push_front("mCollarRight");
- mMasterJointList.push_front("mShoulderRight");
- mMasterJointList.push_front("mElbowRight");
- mMasterJointList.push_front("mWristRight");
- mMasterJointList.push_front("mHipRight");
- mMasterJointList.push_front("mKneeRight");
- mMasterJointList.push_front("mFootRight");
- mMasterJointList.push_front("mHipLeft");
- mMasterJointList.push_front("mKneeLeft");
- mMasterJointList.push_front("mFootLeft");
-
if (mPreview)
{
//only try to load from slm if viewer is configured to do so and this is the
@@ -1356,12 +1338,8 @@ bool LLModelLoader::doLoadModel()
skin_info.mBindShapeMatrix = trans;
}
-
-
- //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" );
@@ -1410,7 +1388,7 @@ bool LLModelLoader::doLoadModel()
domNode* pNode = daeSafeCast<domNode>(children[i]);
if ( isNodeAJoint( pNode ) )
{
- processJointNode( pNode, jointTransforms );
+ processJointNode( pNode, mJointList );
}
}
}
@@ -1468,7 +1446,7 @@ bool LLModelLoader::doLoadModel()
}
//Store the joint transform w/respect to it's name.
- jointTransforms[(*jointIt).second.c_str()] = workingTransform;
+ mJointList[(*jointIt).second.c_str()] = workingTransform;
}
}
@@ -1571,13 +1549,10 @@ bool LLModelLoader::doLoadModel()
//Now that we've parsed the joint array, let's determine if we have a full rig
//(which means we have all the joints that are required for an avatar versus
//a skinned asset attached to a node in a file that contains an entire skeleton,
- //but does not use the skeleton).
- mPreview->setRigValid( doesJointArrayContainACompleteRig( model->mSkinInfo.mJointNames ) );
- if ( !skeletonWithNoRootNode && !model->mSkinInfo.mJointNames.empty() && mPreview->isRigValid() )
- {
- mPreview->setResetJointFlag( true );
- }
+ //but does not use the skeleton).
+ mPreview->critiqueRigForUploadApplicability( model->mSkinInfo.mJointNames );
+
if ( !missingSkeletonOrScene )
{
//Set the joint translations on the avatar - if it's a full mapping
@@ -1590,10 +1565,10 @@ bool LLModelLoader::doLoadModel()
{
std::string lookingForJoint = (*masterJointIt).first.c_str();
- if ( jointTransforms.find( lookingForJoint ) != jointTransforms.end() )
+ if ( mJointList.find( lookingForJoint ) != mJointList.end() )
{
//llinfos<<"joint "<<lookingForJoint.c_str()<<llendl;
- LLMatrix4 jointTransform = jointTransforms[lookingForJoint];
+ LLMatrix4 jointTransform = mJointList[lookingForJoint];
LLJoint* pJoint = gAgentAvatarp->getJoint( lookingForJoint );
if ( pJoint )
{
@@ -1609,6 +1584,7 @@ bool LLModelLoader::doLoadModel()
}
} //missingSkeletonOrScene
+
//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.
@@ -1620,11 +1596,11 @@ bool LLModelLoader::doLoadModel()
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() )
+ if ( mJointList.find( lookingForJoint ) != mJointList.end() )
{
- LLMatrix4 jointTransform = jointTransforms[lookingForJoint];
+ LLMatrix4 jointTransform = mJointList[lookingForJoint];
LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i];
- newInverse.setTranslation( jointTransforms[lookingForJoint].getTranslation() );
+ newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() );
model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse );
}
else
@@ -1787,7 +1763,11 @@ bool LLModelLoader::doLoadModel()
processElement(scene);
handlePivotPoint( root );
+
+ buildJointToNodeMappingFromScene( root );
+ mPreview->critiqueJointToNodeMappingFromScene();
+
return true;
}
@@ -1836,8 +1816,9 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
model[lod].push_back(loaded_model);
if (lod == LLModel::LOD_HIGH && !loaded_model->mSkinInfo.mJointNames.empty())
- { //check to see if rig is valid
- mPreview->setRigValid( doesJointArrayContainACompleteRig( loaded_model->mSkinInfo.mJointNames ) );
+ {
+ //check to see if rig is valid
+ mPreview->critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames );
}
}
else
@@ -1911,7 +1892,52 @@ void LLModelLoader::loadModelCallback()
delete this;
}
-
+//-----------------------------------------------------------------------------
+// buildJointToNodeMappingFromScene()
+//-----------------------------------------------------------------------------
+void LLModelLoader::buildJointToNodeMappingFromScene( daeElement* pRoot )
+{
+ daeElement* pScene = pRoot->getDescendant("visual_scene");
+ if ( pScene )
+ {
+ daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren();
+ S32 childCount = children.getCount();
+ for (S32 i = 0; i < childCount; ++i)
+ {
+ domNode* pNode = daeSafeCast<domNode>(children[i]);
+ processJointToNodeMapping( pNode );
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+// processJointToNodeMapping()
+//-----------------------------------------------------------------------------
+void LLModelLoader::processJointToNodeMapping( domNode* pNode )
+{
+ if ( isNodeAJoint( pNode ) )
+ {
+ //1.Store the parent
+ std::string nodeName = pNode->getName();
+ if ( !nodeName.empty() )
+ {
+ mJointsFromNode.push_front( pNode->getName() );
+ }
+ //2. Handle the kiddo's
+ daeTArray< daeSmartRef<daeElement> > childOfChild = pNode->getChildren();
+ S32 childOfChildCount = childOfChild.getCount();
+ for (S32 i = 0; i < childOfChildCount; ++i)
+ {
+ domNode* pChildNode = daeSafeCast<domNode>( childOfChild[i] );
+ if ( pChildNode )
+ {
+ processJointToNodeMapping( pChildNode );
+ }
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+// handlePivotPoint()
+//-----------------------------------------------------------------------------
void LLModelLoader::handlePivotPoint( daeElement* pRoot )
{
//Import an optional pivot point - a pivot point is just a node in the visual scene named "AssetPivot"
@@ -1953,37 +1979,157 @@ void LLModelLoader::handlePivotPoint( daeElement* pRoot )
}
}
-bool LLModelLoader::doesJointArrayContainACompleteRig( const std::vector<std::string> &jointListFromModel )
+//-----------------------------------------------------------------------------
+// critiqueRigForUploadApplicability()
+//-----------------------------------------------------------------------------
+void LLModelPreview::critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset )
+{
+ //Determines the following use cases for a rig:
+ //1. It is suitable for upload with skin weights & joint positions, or
+ //2. It is suitable for upload as standard av with just skin weights
+
+ bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset );
+ bool isRigLegacyOK = isRigLegacy( jointListFromAsset );
+
+ //It's OK that both could end up being true, both default to false
+ if ( isJointPositionUploadOK )
+ {
+ setRigValidForJointPositionUpload( true );
+ }
+
+ if ( isRigLegacyOK )
+ {
+ setLegacyRigValid( true );
+ }
+
+ if ( isJointPositionUploadOK )
+ {
+ setResetJointFlag( true );
+ }
+}
+//-----------------------------------------------------------------------------
+// critiqueJointToNodeMappingFromScene()
+//-----------------------------------------------------------------------------
+void LLModelPreview::critiqueJointToNodeMappingFromScene( void )
+{
+ //Do the actual nodes back the joint listing from the dae?
+ //if yes then this is a fully rigged asset, otherwise it's just a partial rig
+
+ std::deque<std::string>::iterator jointsFromNodeIt = mJointsFromNode.begin();
+ std::deque<std::string>::iterator jointsFromNodeEndIt = mJointsFromNode.end();
+ bool result = true;
+
+ if ( !mJointsFromNode.empty() )
+ {
+ for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt )
+ {
+ std::string name = *jointsFromNodeIt;
+ if ( mJointTransformMap.find( name ) != mJointTransformMap.end() )
+ {
+ continue;
+ }
+ else
+ {
+ llinfos<<"critiqueJointToNodeMappingFromScene is missing a: "<<name<<llendl;
+ result = false;
+ }
+ }
+ }
+ else
+ {
+ result = false;
+ }
+
+ //Determines the following use cases for a rig:
+ //1. Full av rig w/1-1 mapping from the scene and joint array
+ //2. Partial rig but w/o parity between the scene and joint array
+ if ( result )
+ {
+ setResetJointFlag( true );
+ //llinfos<<"Full"<<llendl;
+ }
+ else
+ {
+ setResetJointFlag( false );
+ //llinfos<<"Partial"<<llendl;
+ }
+}
+//-----------------------------------------------------------------------------
+// isRigLegacy()
+//-----------------------------------------------------------------------------
+bool LLModelPreview::isRigLegacy( const std::vector<std::string> &jointListFromAsset )
+{
+ //No joints in asset
+ if ( jointListFromAsset.size() == 0 )
+ {
+ return false;
+ }
+
+ bool result = false;
+
+ std::deque<std::string> :: const_iterator masterJointIt = mMasterLegacyJointList.begin();
+ std::deque<std::string> :: const_iterator masterJointEndIt = mMasterLegacyJointList.end();
+
+ std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();
+ std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
+
+ for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
+ {
+ result = false;
+ modelJointIt = jointListFromAsset.begin();
+
+ for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
+ {
+ if ( *masterJointIt == *modelJointIt )
+ {
+ result = true;
+ break;
+ }
+ }
+ if ( !result )
+ {
+ llinfos<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< llendl;
+ break;
+ }
+ }
+ return result;
+}
+//-----------------------------------------------------------------------------
+// isRigSuitableForJointPositionUpload()
+//-----------------------------------------------------------------------------
+bool LLModelPreview::isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset )
{
+ bool result = false;
+
std::deque<std::string> :: const_iterator masterJointIt = mMasterJointList.begin();
std::deque<std::string> :: const_iterator masterJointEndIt = mMasterJointList.end();
- std::vector<std::string> :: const_iterator modelJointIt = jointListFromModel.begin();
- std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromModel.end();
+ std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();
+ std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
- bool found = false;
for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
{
- found = false;
- modelJointIt = jointListFromModel.begin();
+ result = false;
+ modelJointIt = jointListFromAsset.begin();
+
for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
{
if ( *masterJointIt == *modelJointIt )
{
- found = true;
+ result = true;
break;
}
}
- if ( !found )
+ if ( !result )
{
- llinfos<<" Asset did not contain the joint (if you're u/l a fully rigged asset - it is required)." << *masterJointIt<< llendl;
+ llinfos<<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< llendl;
break;
}
- }
-
- return found;
+ }
+ return result;
}
+
//called in the main thread
void LLModelLoader::loadTextures()
{
@@ -2013,6 +2159,9 @@ void LLModelLoader::loadTextures()
}
}
+//-----------------------------------------------------------------------------
+// isNodeAJoint()
+//-----------------------------------------------------------------------------
bool LLModelLoader::isNodeAJoint( domNode* pNode )
{
if ( pNode->getName() == NULL)
@@ -2027,7 +2176,9 @@ bool LLModelLoader::isNodeAJoint( domNode* pNode )
return false;
}
-
+//-----------------------------------------------------------------------------
+// isNodeAPivotPoint()
+//-----------------------------------------------------------------------------
bool LLModelLoader::isNodeAPivotPoint( domNode* pNode )
{
bool result = false;
@@ -2046,14 +2197,18 @@ bool LLModelLoader::isNodeAPivotPoint( domNode* pNode )
}
return result;
}
-
+//-----------------------------------------------------------------------------
+// extractTranslation()
+//-----------------------------------------------------------------------------
void LLModelLoader::extractTranslation( domTranslate* pTranslate, LLMatrix4& transform )
{
domFloat3 jointTrans = pTranslate->getValue();
LLVector3 singleJointTranslation( jointTrans[0], jointTrans[1], jointTrans[2] );
transform.setTranslation( singleJointTranslation );
}
-
+//-----------------------------------------------------------------------------
+// extractTranslationViaElement()
+//-----------------------------------------------------------------------------
void LLModelLoader::extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform )
{
domTranslate* pTranslateChild = dynamic_cast<domTranslate*>( pTranslateElement );
@@ -2061,8 +2216,10 @@ void LLModelLoader::extractTranslationViaElement( daeElement* pTranslateElement,
LLVector3 singleJointTranslation( translateChild[0], translateChild[1], translateChild[2] );
transform.setTranslation( singleJointTranslation );
}
-
-void LLModelLoader::processJointNode( domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms )
+//-----------------------------------------------------------------------------
+// processJointNode()
+//-----------------------------------------------------------------------------
+void LLModelLoader::processJointNode( domNode* pNode, JointTransformMap& jointTransforms )
{
if (pNode->getName() == NULL)
{
@@ -2135,7 +2292,9 @@ void LLModelLoader::processJointNode( domNode* pNode, std::map<std::string,LLMat
}
}
}
-
+//-----------------------------------------------------------------------------
+// getChildFromElement()
+//-----------------------------------------------------------------------------
daeElement* LLModelLoader::getChildFromElement( daeElement* pElement, std::string const & name )
{
daeElement* pChildOfElement = pElement->getChild( name.c_str() );
@@ -2456,8 +2615,10 @@ LLColor4 LLModelLoader::getDaeColor(daeElement* element)
LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex(NULL)
, mPelvisZOffset( 0.0f )
-, mRigValid( false )
+, mLegacyRigValid( false )
+, mRigValidJointUpload( false )
, mResetJoints( false )
+, mLastJointUpdate( false )
{
mNeedsUpdate = TRUE;
mCameraDistance = 0.f;
@@ -2491,6 +2652,40 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
mModelPivot = LLVector3( 0.0f, 0.0f, 0.0f );
glodInit();
+
+ //move into joint mapper class
+ //1. joints for joint offset verification
+ mMasterJointList.push_front("mPelvis");
+ mMasterJointList.push_front("mTorso");
+ mMasterJointList.push_front("mChest");
+ mMasterJointList.push_front("mNeck");
+ mMasterJointList.push_front("mHead");
+ mMasterJointList.push_front("mCollarLeft");
+ mMasterJointList.push_front("mShoulderLeft");
+ mMasterJointList.push_front("mElbowLeft");
+ mMasterJointList.push_front("mWristLeft");
+ mMasterJointList.push_front("mCollarRight");
+ mMasterJointList.push_front("mShoulderRight");
+ mMasterJointList.push_front("mElbowRight");
+ mMasterJointList.push_front("mWristRight");
+ mMasterJointList.push_front("mHipRight");
+ mMasterJointList.push_front("mKneeRight");
+ mMasterJointList.push_front("mFootRight");
+ mMasterJointList.push_front("mHipLeft");
+ mMasterJointList.push_front("mKneeLeft");
+ mMasterJointList.push_front("mFootLeft");
+ //2. legacy joint list - used to verify rigs that will not be using joint offsets
+ mMasterLegacyJointList.push_front("mPelvis");
+ mMasterLegacyJointList.push_front("mTorso");
+ mMasterLegacyJointList.push_front("mChest");
+ mMasterLegacyJointList.push_front("mNeck");
+ mMasterLegacyJointList.push_front("mHead");
+ mMasterLegacyJointList.push_front("mHipRight");
+ mMasterLegacyJointList.push_front("mKneeRight");
+ mMasterLegacyJointList.push_front("mFootRight");
+ mMasterLegacyJointList.push_front("mHipLeft");
+ mMasterLegacyJointList.push_front("mKneeLeft");
+ mMasterLegacyJointList.push_front("mFootLeft");
}
LLModelPreview::~LLModelPreview()
@@ -2518,14 +2713,20 @@ U32 LLModelPreview::calcResourceCost()
}
}
- //Upload skin is selected BUT the joints coming in from the asset
- //were malformed.
+ //Upload skin is selected BUT check to see if the joints coming in from the asset were malformed.
if ( mFMP && mFMP->childGetValue("upload_skin").asBoolean() )
{
- if ( !isRigValid() )
+ bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
+ if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
+ {
+ mFMP->childDisable("ok_btn");
+ }
+ else
+ if ( !isLegacyRigValid() )
{
mFMP->childDisable("ok_btn");
}
+ //ok_btn should not have been changed unless something was wrong with joint list
}
U32 cost = 0;
@@ -2858,7 +3059,7 @@ void LLModelPreview::loadModel(std::string filename, S32 lod)
clearGLODGroup();
}
- mModelLoader = new LLModelLoader(filename, lod, this);
+ mModelLoader = new LLModelLoader(filename, lod, this, mJointTransformMap, mJointsFromNode );
mModelLoader->start();
@@ -3694,12 +3895,22 @@ void LLModelPreview::updateStatusMessages()
bool errorStateFromLoader = getLoadState() >= LLModelLoader::ERROR_PARSING ? true : false;
bool skinAndRigOk = true;
- bool uploadingSkin = mFMP->childGetValue("upload_skin").asBoolean();
- if ( uploadingSkin && !isRigValid() )
+ bool uploadingSkin = mFMP->childGetValue("upload_skin").asBoolean();
+ bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
+
+ if ( uploadingSkin )
{
- skinAndRigOk = false;
+ if ( uploadingJointPositions && !isRigValidForJointPositionUpload() )
+ {
+ skinAndRigOk = false;
+ }
+ else
+ if ( !isLegacyRigValid() )
+ {
+ skinAndRigOk = false;
+ }
}
-
+
if ( upload_ok && !errorStateFromLoader && skinAndRigOk )
{
mFMP->childEnable("ok_btn");
@@ -4089,7 +4300,55 @@ void LLModelPreview::update()
}
}
+//-----------------------------------------------------------------------------
+// changeAvatarsJointPositions()
+//-----------------------------------------------------------------------------
+void LLModelPreview::changeAvatarsJointPositions( LLModel* pModel )
+{
+ if ( mMasterJointList.empty() )
+ {
+ return;
+ }
+
+ std::vector<std::string> :: const_iterator jointListItBegin = pModel->mSkinInfo.mJointNames.begin();
+ std::vector<std::string> :: const_iterator jointListItEnd = pModel->mSkinInfo.mJointNames.end();
+
+ S32 index = 0;
+ for ( ; jointListItBegin!=jointListItEnd; ++jointListItBegin, ++index )
+ {
+ std::string elem = *jointListItBegin;
+ //llinfos<<"joint "<<elem<<llendl;
+
+ S32 matrixCnt = pModel->mSkinInfo.mAlternateBindMatrix.size();
+ if ( matrixCnt < 1 )
+ {
+ llinfos<<"Total WTF moment :"<<matrixCnt<<llendl;
+ }
+ else
+ {
+ LLMatrix4 jointTransform = pModel->mSkinInfo.mAlternateBindMatrix[index];
+ LLJoint* pJoint = gAgentAvatarp->getJoint( elem );
+ if ( pJoint )
+ {
+ pJoint->storeCurrentXform( jointTransform.getTranslation() );
+ }
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+// getTranslationForJointOffset()
+//-----------------------------------------------------------------------------
+LLVector3 LLModelPreview::getTranslationForJointOffset( std::string joint )
+{
+ LLMatrix4 jointTransform;
+ if ( mJointTransformMap.find( joint ) != mJointTransformMap.end() )
+ {
+ jointTransform = mJointTransformMap[joint];
+ return jointTransform.getTranslation();
+ }
+ return LLVector3(0.0f,0.0f,0.0f);
+}
//-----------------------------------------------------------------------------
// render()
//-----------------------------------------------------------------------------
@@ -4140,9 +4399,21 @@ BOOL LLModelPreview::render()
LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance;
bool has_skin_weights = false;
- bool upload_skin = mFMP->childGetValue("upload_skin").asBoolean();
+ bool upload_skin = mFMP->childGetValue("upload_skin").asBoolean();
bool upload_joints = mFMP->childGetValue("upload_joints").asBoolean();
+ bool resetJoints = false;
+ if ( upload_joints != mLastJointUpdate )
+ {
+ if ( mLastJointUpdate )
+ {
+ resetJoints = true;
+ }
+
+ mLastJointUpdate = upload_joints;
+
+ }
+
for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)
{
for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
@@ -4187,11 +4458,30 @@ BOOL LLModelPreview::render()
if (!upload_skin && upload_joints)
{ //can't upload joints if not uploading skin weights
mFMP->childSetValue("upload_joints", false);
- upload_joints = false;
- }
-
+ upload_joints = false;
+ }
+
mFMP->childSetEnabled("upload_joints", upload_skin);
+ //poke at avatar when we upload custom joints
+ /*
+ if ( upload_joints )
+ {
+ for (LLModelLoader::scene::iterator iter = mScene[mPreviewLOD].begin(); iter != mScene[mPreviewLOD].end(); ++iter)
+ {
+ for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
+ {
+ LLModelInstance& instance = *model_iter;
+ LLModel* model = instance.mModel;
+ if ( !model->mSkinWeights.empty() )
+ {
+ changeAvatarsJointPositions( model );
+ }
+ }
+ }
+ }
+ */
+
F32 explode = mFMP->childGetValue("physics_explode").asReal();
glClear(GL_DEPTH_BUFFER_BIT);
@@ -4468,6 +4758,7 @@ BOOL LLModelPreview::render()
//quick 'n dirty software vertex skinning
//build matrix palette
+
LLMatrix4 mat[64];
for (U32 j = 0; j < model->mSkinInfo.mJointNames.size(); ++j)
{
diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h
index dc6a33d0ab..186bf114d1 100644
--- a/indra/newview/llfloatermodelpreview.h
+++ b/indra/newview/llfloatermodelpreview.h
@@ -53,6 +53,9 @@ class domTranslate;
class LLMenuButton;
class LLToggleableMenu;
+typedef std::map<std::string, LLMatrix4> JointTransformMap;
+typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt;
+
const S32 NUM_LOD = 4;
class LLModelLoader : public LLThread
@@ -94,8 +97,8 @@ public:
//queue of models that need a physics rep
model_queue mPhysicsQ;
- LLModelLoader(std::string filename, S32 lod, LLModelPreview* preview);
-
+ LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap,
+ std::deque<std::string>& jointsFromNodes );
virtual void run();
bool doLoadModel();
bool loadFromSLM(const std::string& filename);
@@ -115,17 +118,19 @@ public:
void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform );
void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform );
- bool doesJointArrayContainACompleteRig( const std::vector<std::string> &modelJointList );
- bool checkForCompleteRig( const std::vector<std::string> &jointListFromModel );
-
void handlePivotPoint( daeElement* pRoot );
bool isNodeAPivotPoint( domNode* pNode );
void setLoadState(U32 state);
+ void buildJointToNodeMappingFromScene( daeElement* pRoot );
+ void processJointToNodeMapping( domNode* pNode );
+
+
//map of avatar joints as named in COLLADA assets to internal joint names
std::map<std::string, std::string> mJointMap;
- std::deque<std::string> mMasterJointList;
+ JointTransformMap& mJointList;
+ std::deque<std::string>& mJointsFromNode;
};
class LLFloaterModelPreview : public LLFloater
@@ -297,12 +302,28 @@ public:
void updateStatusMessages();
void clearGLODGroup();
void onLODParamCommit(bool enforce_tri_limit);
+
const bool getModelPivot( void ) const { return mHasPivot; }
void setHasPivot( bool val ) { mHasPivot = val; }
void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; }
- const bool isRigValid( void ) const { return mRigValid; }
- void setRigValid( bool rigValid ) { mRigValid = rigValid; }
-
+
+ //Sets the current avatars joints to new positions
+ //Makes in world go to shit, however
+ void changeAvatarsJointPositions( LLModel* pModel );
+ //Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
+ void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset );
+ void critiqueJointToNodeMappingFromScene( void );
+ //Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions
+ //Accessors for joint position upload friendly rigs
+ const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
+ void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
+ bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset );
+ //Determines if a rig is a legacy from the joint list
+ bool isRigLegacy( const std::vector<std::string> &jointListFromAsset );
+ //Accessors for the legacy rigs
+ const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
+ void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }
+
static void textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
boost::signals2::connection setDetailsCallback( const details_signal_t::slot_type& cb ){ return mDetailsSignal.connect(cb); }
@@ -314,6 +335,8 @@ public:
void setResetJointFlag( bool state ) { mResetJoints = state; }
bool getResetJointFlag( void ) { return mResetJoints; }
+ LLVector3 getTranslationForJointOffset( std::string joint );
+
protected:
friend class LLModelLoader;
friend class LLFloaterModelPreview;
@@ -377,8 +400,15 @@ public:
float mPelvisZOffset;
- bool mRigValid;
-};
+ bool mRigValidJointUpload;
+ bool mLegacyRigValid;
+ bool mLastJointUpdate;
+
+ std::deque<std::string> mMasterJointList;
+ std::deque<std::string> mMasterLegacyJointList;
+ std::deque<std::string> mJointsFromNode;
+ JointTransformMap mJointTransformMap;
+};
#endif // LL_LLFLOATERMODELPREVIEW_H