WIP for SH-1281. Rigged assets are critiqued differently based upon whether they're avrigs w/wo joint offets and whether the asset contains a subset of the joints in the visual scene
parent
0398e611f2
commit
c494e5c0d5
|
|
@ -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,36 +1979,156 @@ void LLModelLoader::handlePivotPoint( daeElement* pRoot )
|
|||
}
|
||||
}
|
||||
|
||||
bool LLModelLoader::doesJointArrayContainACompleteRig( const std::vector<std::string> &jointListFromModel )
|
||||
//-----------------------------------------------------------------------------
|
||||
// critiqueRigForUploadApplicability()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLModelPreview::critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset )
|
||||
{
|
||||
std::deque<std::string> :: const_iterator masterJointIt = mMasterJointList.begin();
|
||||
std::deque<std::string> :: const_iterator masterJointEndIt = mMasterJointList.end();
|
||||
//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
|
||||
|
||||
std::vector<std::string> :: const_iterator modelJointIt = jointListFromModel.begin();
|
||||
std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromModel.end();
|
||||
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();
|
||||
|
||||
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;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 = 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;
|
||||
}
|
||||
|
||||
|
||||
//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() )
|
||||
{
|
||||
skinAndRigOk = false;
|
||||
}
|
||||
bool uploadingSkin = mFMP->childGetValue("upload_skin").asBoolean();
|
||||
bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean();
|
||||
|
||||
if ( uploadingSkin )
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue