diff options
Diffstat (limited to 'indra/llprimitive')
| -rw-r--r-- | indra/llprimitive/lldaeloader.cpp | 305 | ||||
| -rw-r--r-- | indra/llprimitive/lldaeloader.h | 14 | ||||
| -rw-r--r-- | indra/llprimitive/llmodel.cpp | 4 | ||||
| -rw-r--r-- | indra/llprimitive/llmodel.h | 2 | ||||
| -rw-r--r-- | indra/llprimitive/llmodelloader.cpp | 277 | ||||
| -rw-r--r-- | indra/llprimitive/llmodelloader.h | 34 | 
6 files changed, 238 insertions, 398 deletions
| diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 720986a411..38b061dd79 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -807,17 +807,19 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac  // LLDAELoader  //-----------------------------------------------------------------------------  LLDAELoader::LLDAELoader( -	std::string				filename, -	S32						lod, +	std::string			filename, +	S32					lod,  	load_callback_t		load_cb,  	joint_lookup_func_t	joint_lookup_func,  	texture_load_func_t	texture_load_func, -	state_callback_t		state_cb, -	void*						opaque_userdata, -	JointTransformMap&	jointMap, -	JointSet&				jointsFromNodes, +	state_callback_t	state_cb, +	void*				opaque_userdata, +	JointTransformMap&	jointTransformMap, +	JointNameSet&		jointsFromNodes, +    std::map<std::string, std::string>&		jointAliasMap, +    U32					maxJointsPerMesh,  	U32					modelLimit, -	bool					preprocess) +    bool				preprocess)  : LLModelLoader(  		filename,  		lod, @@ -826,10 +828,12 @@ LLDAELoader::LLDAELoader(  		texture_load_func,  		state_cb,  		opaque_userdata, -		jointMap, -		jointsFromNodes), -mGeneratedModelLimit(modelLimit), -mPreprocessDAE(preprocess) +		jointTransformMap, +		jointsFromNodes, +        jointAliasMap, +        maxJointsPerMesh), +  mGeneratedModelLimit(modelLimit), +  mPreprocessDAE(preprocess)  {  } @@ -1148,28 +1152,29 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do  		//Some collada setup for accessing the skeleton -		daeElement* pElement = 0; -		dae->getDatabase()->getElement( &pElement, 0, 0, "skeleton" ); - -		//Try to get at the skeletal instance controller -		domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement ); +        U32 skeleton_count = dae->getDatabase()->getElementCount( NULL, "skeleton" ); +        std::vector<domInstance_controller::domSkeleton*> skeletons; +        for (S32 i=0; i<skeleton_count; i++) +        { +            daeElement* pElement = 0; +            dae->getDatabase()->getElement( &pElement, i, 0, "skeleton" ); + +            //Try to get at the skeletal instance controller +            domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement ); +			daeElement* pSkeletonRootNode = NULL; +            if (pSkeleton) +            { +                pSkeletonRootNode = pSkeleton->getValue().getElement(); +            } +            if (pSkeleton && pSkeletonRootNode) +            { +                skeletons.push_back(pSkeleton); +            } +        }  		bool missingSkeletonOrScene = false;  		//If no skeleton, do a breadth-first search to get at specific joints -		bool rootNode = false; - -		//Need to test for a skeleton that does not have a root node -		//This occurs when your instance controller does not have an associated scene  -		if ( pSkeleton ) -		{ -			daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); -			if ( pSkeletonRootNode ) -			{ -				rootNode = true; -			} - -		} -		if ( !pSkeleton || !rootNode ) +		if ( skeletons.size() == 0 )  		{  			daeElement* pScene = root->getDescendant("visual_scene");  			if ( !pScene ) @@ -1184,7 +1189,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do  				S32 childCount = children.getCount();  				//Process any children that are joints -				//Not all children are joints, some code be ambient lights, cameras, geometry etc.. +				//Not all children are joints, some could be ambient lights, cameras, geometry etc..  				for (S32 i = 0; i < childCount; ++i)  				{  					domNode* pNode = daeSafeCast<domNode>(children[i]); @@ -1196,83 +1201,90 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do  			}  		}  		else -			//Has Skeleton -		{ -			//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 -				const int jointCnt = mJointMap.size(); -				JointMap :: const_iterator jointIt = mJointMap.begin(); - -				//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).first.c_str() ); -					//LL_WARNS()<<"Joint "<< str <<LL_ENDL; - -					//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 jointResolverA( pJoint, "./translate" ); -						domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() ); -						daeSIDResolver jointResolverB( pJoint, "./location" ); -						domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() ); - -						LLMatrix4 workingTransform; - -						//Translation via SID -						if ( pTranslateA ) -						{ -							extractTranslation( pTranslateA, workingTransform ); -						} -						else -							if ( pTranslateB ) -							{ -								extractTranslation( pTranslateB, workingTransform ); -							} -							else -							{ -								//Translation via child from element -								daeElement* pTranslateElement = getChildFromElement( pJoint, "translate" ); -								if ( pTranslateElement && pTranslateElement->typeID() != domTranslate::ID() ) -								{ -									LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL; -									missingSkeletonOrScene = true; -								} -								else -									if ( pTranslateElement ) -									{ -										extractTranslationViaElement( pTranslateElement, workingTransform ); -									} -									else -									{ -										extractTranslationViaSID( pJoint, workingTransform ); -									} - -							} - -							//Store the joint transform w/respect to it's name. -							mJointList[(*jointIt).second.c_str()] = workingTransform; -					} -				} - -				//If anything failed in regards to extracting the skeleton, joints or translation id, -				//mention it -				if ( missingSkeletonOrScene  ) -				{ -					LL_WARNS()<< "Partial jointmap found in asset - did you mean to just have a partial map?" << LL_ENDL; -				} -			}//got skeleton? -		} +			//Has one or more skeletons +            for (std::vector<domInstance_controller::domSkeleton*>::iterator skel_it = skeletons.begin(); +                 skel_it != skeletons.end(); ++skel_it) +            { +                domInstance_controller::domSkeleton* pSkeleton = *skel_it; +                //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 +                    const int jointCnt = mJointMap.size(); +                    JointMap :: const_iterator jointIt = mJointMap.begin(); + +                    //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).first.c_str() ); +                        //LL_WARNS()<<"Joint "<< str <<LL_ENDL; + +                        //Setup the resolver +                        daeSIDResolver resolver( pSkeletonRootNode, str ); + +                        //Look for the joint +                        domNode* pJoint = daeSafeCast<domNode>( resolver.getElement() ); +                        if ( pJoint ) +                        { +                            // FIXME this has a lot of overlap with processJointNode(), would be nice to refactor. + +                            //Pull out the translate id and store it in the jointTranslations map +                            daeSIDResolver jointResolverA( pJoint, "./translate" ); +                            domTranslate* pTranslateA = daeSafeCast<domTranslate>( jointResolverA.getElement() ); +                            daeSIDResolver jointResolverB( pJoint, "./location" ); +                            domTranslate* pTranslateB = daeSafeCast<domTranslate>( jointResolverB.getElement() ); + +                            LLMatrix4 workingTransform; + +                            //Translation via SID +                            if ( pTranslateA ) +                            { +                                extractTranslation( pTranslateA, workingTransform ); +                            } +                            else +                            { +                                if ( pTranslateB ) +                                { +                                    extractTranslation( pTranslateB, workingTransform ); +                                } +                                else +                                { +                                    //Translation via child from element +                                    daeElement* pTranslateElement = getChildFromElement( pJoint, "translate" ); +                                    if ( pTranslateElement && pTranslateElement->typeID() != domTranslate::ID() ) +                                    { +                                        LL_WARNS()<< "The found element is not a translate node" <<LL_ENDL; +                                        missingSkeletonOrScene = true; +                                    } +                                    else +                                        if ( pTranslateElement ) +                                        { +                                            extractTranslationViaElement( pTranslateElement, workingTransform ); +                                        } +                                        else +                                        { +                                            extractTranslationViaSID( pJoint, workingTransform ); +                                        } + +                                } +                            } + +                            //Store the joint transform w/respect to its name. +                            mJointList[(*jointIt).second.c_str()] = workingTransform; +                        } +                    } + +                    //If anything failed in regards to extracting the skeleton, joints or translation id, +                    //mention it +                    if ( missingSkeletonOrScene  ) +                    { +                        LL_WARNS()<< "Partial jointmap found in asset - did you mean to just have a partial map?" << LL_ENDL; +                    } +                }//got skeleton? +            }  		domSkin::domJoints* joints = skin->getJoints(); @@ -1307,7 +1319,6 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do  								name = mJointMap[name];  							}  							model->mSkinInfo.mJointNames.push_back(name); -							model->mSkinInfo.mJointMap[name] = j;  						}  					}  					else @@ -1325,7 +1336,6 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do  									name = mJointMap[name];  								}  								model->mSkinInfo.mJointNames.push_back(name); -								model->mSkinInfo.mJointMap[name] = j;  							}  						}  					} @@ -1353,8 +1363,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do  									mat.mMatrix[i][j] = transform[k*16 + i + j*4];  								}  							} - -							model->mSkinInfo.mInvBindMatrix.push_back(mat);											 +							model->mSkinInfo.mInvBindMatrix.push_back(mat);  						}  					}  				} @@ -1370,35 +1379,40 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do  		if ( !missingSkeletonOrScene )  		{ -			//Set the joint translations on the avatar - if it's a full mapping -			//The joints are reset in the dtor -			if ( getRigWithSceneParity() ) -			{	 -				JointMap :: const_iterator masterJointIt = mJointMap.begin(); -				JointMap :: const_iterator masterJointItEnd = mJointMap.end(); -				for (;masterJointIt!=masterJointItEnd;++masterJointIt ) -				{ -					std::string lookingForJoint = (*masterJointIt).first.c_str(); - -					if ( mJointList.find( lookingForJoint ) != mJointList.end() ) -					{ -						//LL_INFOS()<<"joint "<<lookingForJoint.c_str()<<LL_ENDL; -						LLMatrix4 jointTransform = mJointList[lookingForJoint]; -						LLJoint* pJoint = mJointLookupFunc(lookingForJoint,mOpaqueData); -						if ( pJoint ) -						{    -							LLUUID fake_mesh_id; -							fake_mesh_id.generate(); -							pJoint->addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, ""); -						} -						else -						{ -							//Most likely an error in the asset. -							LL_WARNS()<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL; -						} -					} -				} -			} +			//Set the joint translations on the avatar +            JointMap :: const_iterator masterJointIt = mJointMap.begin(); +            JointMap :: const_iterator masterJointItEnd = mJointMap.end(); +            for (;masterJointIt!=masterJointItEnd;++masterJointIt ) +            { +                std::string lookingForJoint = (*masterJointIt).first.c_str(); + +                if ( mJointList.find( lookingForJoint ) != mJointList.end() ) +                { +                    //LL_INFOS()<<"joint "<<lookingForJoint.c_str()<<LL_ENDL; +                    LLMatrix4 jointTransform = mJointList[lookingForJoint]; +                    LLJoint* pJoint = mJointLookupFunc(lookingForJoint,mOpaqueData); +                    if ( pJoint ) +                    {    +                        // FIXME: mesh_id is used to determine which +                        // mesh gets to set the joint offset, in the +                        // event of a conflict. Since we don't know +                        // the mesh id yet, we can't guarantee that +                        // joint offsets will be applied with the same +                        // priority as in the uploaded model. If the +                        // file contains multiple meshes with +                        // conflicting joint offsets, preview may be +                        // incorrect. +                        LLUUID fake_mesh_id; +                        fake_mesh_id.generate(); +                        pJoint->addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, ""); +                    } +                    else +                    { +                        //Most likely an error in the asset. +                        LL_WARNS()<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL; +                    } +                } +            }  		} //missingSkeletonOrScene  		//We need to construct the alternate bind matrix (which contains the new joint positions) @@ -1412,16 +1426,15 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do  			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 ( mJointList.find( lookingForJoint ) != mJointList.end() ) +			if ( mJointMap.find( lookingForJoint ) != mJointMap.end() )  			{ -				LLMatrix4 jointTransform = mJointList[lookingForJoint];  				LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i];  				newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() );  				model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse ); -			} +            }  			else  			{ -				LL_WARNS()<<"Possibly misnamed/missing joint [" <<lookingForJoint.c_str()<<" ] "<<LL_ENDL; +                LL_DEBUGS("Mesh")<<"Possibly misnamed/missing joint [" <<lookingForJoint.c_str()<<"] "<<LL_ENDL;  			}  		} @@ -1868,7 +1881,7 @@ daeElement* LLDAELoader::getChildFromElement( daeElement* pElement, std::string  	{  		return pChildOfElement;  	} -	LL_WARNS()<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL; +	LL_DEBUGS("Mesh")<< "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL;      return NULL;  } diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h index 27db5326d5..4e990dbe5e 100644 --- a/indra/llprimitive/lldaeloader.h +++ b/indra/llprimitive/lldaeloader.h @@ -47,17 +47,19 @@ public:  	dae_model_map	mModelsMap;  	LLDAELoader( -		std::string									filename, -		S32											lod,  +		std::string							filename, +		S32									lod,   		LLModelLoader::load_callback_t		load_cb,  		LLModelLoader::joint_lookup_func_t	joint_lookup_func,  		LLModelLoader::texture_load_func_t	texture_load_func,  		LLModelLoader::state_callback_t		state_cb, -		void*											opaque_userdata, -		JointTransformMap&						jointMap, -		JointSet&									jointsFromNodes, +		void*								opaque_userdata, +		JointTransformMap&					jointTransformMap, +		JointNameSet&						jointsFromNodes, +        std::map<std::string, std::string>& jointAliasMap, +        U32									maxJointsPerMesh,  		U32									modelLimit, -		bool									preprocess); +        bool								preprocess);  	virtual ~LLDAELoader() ;  	virtual bool OpenFile(const std::string& filename); diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index e494c55250..398f0997f3 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -867,6 +867,7 @@ LLSD LLModel::writeModel(  						S32 count = 0;  						for (weight_list::iterator iter = weights.begin(); iter != weights.end(); ++iter)  						{ +							// Note joint index cannot exceed 255.  							if (iter->mJointIdx < 255 && iter->mJointIdx >= 0)  							{  								U8 idx = (U8) iter->mJointIdx; @@ -1000,7 +1001,7 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BO  LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)  { -	//1. If a vertex has been weighted then we'll find it via pos and return it's weight list +	//1. If a vertex has been weighted then we'll find it via pos and return its weight list  	weight_map::iterator iterPos = mSkinWeights.begin();  	weight_map::iterator iterEnd = mSkinWeights.end(); @@ -1223,7 +1224,6 @@ bool LLModel::loadModel(std::istream& is)  	}  	return false; -  }  bool LLModel::isMaterialListSubset( LLModel* ref ) diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index ae602c09df..5f98942340 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -46,7 +46,7 @@ public:  	std::vector<std::string> mJointNames;  	std::vector<LLMatrix4> mInvBindMatrix;  	std::vector<LLMatrix4> mAlternateBindMatrix; -	std::map<std::string, U32> mJointMap; +    std::vector<U32> mJointRemap;  	LLMeshSkinInfo() { }  	LLMeshSkinInfo(LLSD& data); diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp index f86eceb98d..816ebc558a 100644 --- a/indra/llprimitive/llmodelloader.cpp +++ b/indra/llprimitive/llmodelloader.cpp @@ -102,16 +102,18 @@ void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3&  // LLModelLoader  //-----------------------------------------------------------------------------  LLModelLoader::LLModelLoader( -	std::string				filename, -	S32						lod, +	std::string			filename, +	S32					lod,  	load_callback_t		load_cb,  	joint_lookup_func_t	joint_lookup_func,  	texture_load_func_t	texture_load_func, -	state_callback_t		state_cb, -	void*						opaque_userdata, -	JointTransformMap&	jointMap, -	JointSet&				jointsFromNodes ) -: mJointList( jointMap ) +	state_callback_t	state_cb, +	void*				opaque_userdata, +	JointTransformMap&	jointTransformMap, +	JointNameSet&		jointsFromNodes, +    JointMap&           legalJointNamesMap, +    U32					maxJointsPerMesh) +: mJointList( jointTransformMap )  , mJointsFromNode( jointsFromNodes )  , LLThread("Model Loader")  , mFilename(filename) @@ -124,124 +126,14 @@ LLModelLoader::LLModelLoader(  , mTextureLoadFunc(texture_load_func)  , mStateCallback(state_cb)  , mOpaqueData(opaque_userdata) -, mRigParityWithScene(false) -, mRigValidJointUpload(false) -, mLegacyRigValid(false) +, mRigValidJointUpload(true) +, mLegacyRigValid(true)  , mNoNormalize(false)  , mNoOptimize(false)  , mCacheOnlyHitIfRigged(false) -{ -	mJointMap["mPelvis"] = "mPelvis"; -	mJointMap["mTorso"] = "mTorso"; -	mJointMap["mChest"] = "mChest"; -	mJointMap["mNeck"] = "mNeck"; -	mJointMap["mHead"] = "mHead"; -	mJointMap["mSkull"] = "mSkull"; -	mJointMap["mEyeRight"] = "mEyeRight"; -	mJointMap["mEyeLeft"] = "mEyeLeft"; -	mJointMap["mCollarLeft"] = "mCollarLeft"; -	mJointMap["mShoulderLeft"] = "mShoulderLeft"; -	mJointMap["mElbowLeft"] = "mElbowLeft"; -	mJointMap["mWristLeft"] = "mWristLeft"; -	mJointMap["mCollarRight"] = "mCollarRight"; -	mJointMap["mShoulderRight"] = "mShoulderRight"; -	mJointMap["mElbowRight"] = "mElbowRight"; -	mJointMap["mWristRight"] = "mWristRight"; -	mJointMap["mHipRight"] = "mHipRight"; -	mJointMap["mKneeRight"] = "mKneeRight"; -	mJointMap["mAnkleRight"] = "mAnkleRight"; -	mJointMap["mFootRight"] = "mFootRight"; -	mJointMap["mToeRight"] = "mToeRight"; -	mJointMap["mHipLeft"] = "mHipLeft"; -	mJointMap["mKneeLeft"] = "mKneeLeft"; -	mJointMap["mAnkleLeft"] = "mAnkleLeft"; -	mJointMap["mFootLeft"] = "mFootLeft"; -	mJointMap["mToeLeft"] = "mToeLeft"; - -	mJointMap["avatar_mPelvis"] = "mPelvis"; -	mJointMap["avatar_mTorso"] = "mTorso"; -	mJointMap["avatar_mChest"] = "mChest"; -	mJointMap["avatar_mNeck"] = "mNeck"; -	mJointMap["avatar_mHead"] = "mHead"; -	mJointMap["avatar_mSkull"] = "mSkull"; -	mJointMap["avatar_mEyeRight"] = "mEyeRight"; -	mJointMap["avatar_mEyeLeft"] = "mEyeLeft"; -	mJointMap["avatar_mCollarLeft"] = "mCollarLeft"; -	mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft"; -	mJointMap["avatar_mElbowLeft"] = "mElbowLeft"; -	mJointMap["avatar_mWristLeft"] = "mWristLeft"; -	mJointMap["avatar_mCollarRight"] = "mCollarRight"; -	mJointMap["avatar_mShoulderRight"] = "mShoulderRight"; -	mJointMap["avatar_mElbowRight"] = "mElbowRight"; -	mJointMap["avatar_mWristRight"] = "mWristRight"; -	mJointMap["avatar_mHipRight"] = "mHipRight"; -	mJointMap["avatar_mKneeRight"] = "mKneeRight"; -	mJointMap["avatar_mAnkleRight"] = "mAnkleRight"; -	mJointMap["avatar_mFootRight"] = "mFootRight"; -	mJointMap["avatar_mToeRight"] = "mToeRight"; -	mJointMap["avatar_mHipLeft"] = "mHipLeft"; -	mJointMap["avatar_mKneeLeft"] = "mKneeLeft"; -	mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft"; -	mJointMap["avatar_mFootLeft"] = "mFootLeft"; -	mJointMap["avatar_mToeLeft"] = "mToeLeft"; - - -	mJointMap["hip"] = "mPelvis"; -	mJointMap["abdomen"] = "mTorso"; -	mJointMap["chest"] = "mChest"; -	mJointMap["neck"] = "mNeck"; -	mJointMap["head"] = "mHead"; -	mJointMap["figureHair"] = "mSkull"; -	mJointMap["lCollar"] = "mCollarLeft"; -	mJointMap["lShldr"] = "mShoulderLeft"; -	mJointMap["lForeArm"] = "mElbowLeft"; -	mJointMap["lHand"] = "mWristLeft"; -	mJointMap["rCollar"] = "mCollarRight"; -	mJointMap["rShldr"] = "mShoulderRight"; -	mJointMap["rForeArm"] = "mElbowRight"; -	mJointMap["rHand"] = "mWristRight"; -	mJointMap["rThigh"] = "mHipRight"; -	mJointMap["rShin"] = "mKneeRight"; -	mJointMap["rFoot"] = "mFootRight"; -	mJointMap["lThigh"] = "mHipLeft"; -	mJointMap["lShin"] = "mKneeLeft"; -	mJointMap["lFoot"] = "mFootLeft"; - -	//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"); - +, mMaxJointsPerMesh(maxJointsPerMesh) +, mJointMap(legalJointNamesMap) +{      	assert_main_thread();  	sActiveLoaderList.push_back(this) ;  } @@ -476,8 +368,6 @@ void LLModelLoader::loadModelCallback()  //-----------------------------------------------------------------------------  void LLModelLoader::critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset )  { -	critiqueJointToNodeMappingFromScene(); -	  	//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 @@ -485,59 +375,27 @@ void LLModelLoader::critiqueRigForUploadApplicability( const std::vector<std::st  	bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset );  	bool isRigLegacyOK			 = isRigLegacy( jointListFromAsset ); -	//It's OK that both could end up being true, both default to false -	if ( isJointPositionUploadOK ) +	// It's OK that both could end up being true. + +    // Both start out as true and are forced to false if any mesh in +    // the model file is not vald by that criterion. Note that a file +    // can contain multiple meshes. +	if ( !isJointPositionUploadOK )  	{ -		setRigValidForJointPositionUpload( true ); +        // This starts out true, becomes false if false for any loaded +        // mesh.  +		setRigValidForJointPositionUpload( false );  	} -	if ( isRigLegacyOK)  +	if ( !isRigLegacyOK)   	{	 -		setLegacyRigValid( true ); +        // This starts out true, becomes false if false for any loaded +        // mesh.  +		setLegacyRigValid( false );  	}  } -//----------------------------------------------------------------------------- -// critiqueJointToNodeMappingFromScene() -//----------------------------------------------------------------------------- -void LLModelLoader::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 -	 -	JointSet::iterator jointsFromNodeIt = mJointsFromNode.begin(); -	JointSet::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 -			{ -				LL_INFOS() <<"critiqueJointToNodeMappingFromScene is missing a: " << name << LL_ENDL; -				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 ) -	{		 -		setRigWithSceneParity( true ); -	}	 -}  //-----------------------------------------------------------------------------  // isRigLegacy()  //----------------------------------------------------------------------------- @@ -549,68 +407,39 @@ bool LLModelLoader::isRigLegacy( const std::vector<std::string> &jointListFromAs  		return false;  	} -	bool result = false; - -	JointSet :: const_iterator masterJointIt = mMasterLegacyJointList.begin();	 -	JointSet :: 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(); +    // Too many joints in asset +    if (jointListFromAsset.size()>mMaxJointsPerMesh) +    { +        LL_WARNS() << "Rigged to " << jointListFromAsset.size() << " joints, max is " << mMaxJointsPerMesh << LL_ENDL; +        LL_WARNS() << "Skinning disabled due to too many joints" << LL_ENDL; +        return false; +    } + +    // Unknown joints in asset +    S32 unknown_joint_count = 0; +    for (std::vector<std::string>::const_iterator it = jointListFromAsset.begin(); +         it != jointListFromAsset.end(); ++it) +    { +        if (mJointMap.find(*it)==mJointMap.end()) +        { +            LL_WARNS() << "Rigged to unrecognized joint name " << *it << LL_ENDL; +            unknown_joint_count++; +        } +    } +    if (unknown_joint_count>0) +    { +        LL_WARNS() << "Skinning disabled due to unknown joints" << LL_ENDL; +        return false; +    } -		for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) -		{ -			if ( *masterJointIt == *modelJointIt ) -			{ -				result = true; -				break; -			}			 -		}		 -		if ( !result ) -		{ -			LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; -			break; -		} -	}	 -	return result; +	return true;  }  //-----------------------------------------------------------------------------  // isRigSuitableForJointPositionUpload()  //-----------------------------------------------------------------------------  bool LLModelLoader::isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset )  { -	bool result = false; - -	JointSet :: const_iterator masterJointIt = mMasterJointList.begin();	 -	JointSet :: 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 ) -		{ -			LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; -			break; -		} -	}	 -	return result; +    return true;  } diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h index bb4d06dca3..a902ca3404 100644 --- a/indra/llprimitive/llmodelloader.h +++ b/indra/llprimitive/llmodelloader.h @@ -34,10 +34,10 @@  class LLJoint; -typedef std::map<std::string, LLMatrix4>					JointTransformMap; -typedef std::map<std::string, LLMatrix4>:: iterator	JointTransformMapIt; -typedef std::map<std::string, std::string>				JointMap; -typedef std::deque<std::string>								JointSet; +typedef std::map<std::string, LLMatrix4>			JointTransformMap; +typedef std::map<std::string, LLMatrix4>::iterator	JointTransformMapIt; +typedef std::map<std::string, std::string>			JointMap; +typedef std::deque<std::string>						JointNameSet;  const S32 SLM_SUPPORTED_VERSION	= 3;  const S32 NUM_LOD						= 4; @@ -116,18 +116,21 @@ public:  	//map of avatar joints as named in COLLADA assets to internal joint names  	JointMap			mJointMap;  	JointTransformMap&	mJointList;	 -	JointSet&			mJointsFromNode; +	JointNameSet&		mJointsFromNode; +    U32					mMaxJointsPerMesh;  	LLModelLoader( -		std::string									filename, -		S32											lod,  +		std::string							filename, +		S32									lod,   		LLModelLoader::load_callback_t		load_cb,  		LLModelLoader::joint_lookup_func_t	joint_lookup_func,  		LLModelLoader::texture_load_func_t	texture_load_func,  		LLModelLoader::state_callback_t		state_cb, -		void*											opaque_userdata, -		JointTransformMap&						jointMap, -		JointSet&									jointsFromNodes); +		void*								opaque_userdata, +		JointTransformMap&					jointTransformMap, +		JointNameSet&						jointsFromNodes, +        JointMap&                           legalJointNamesMap, +        U32									maxJointsPerMesh);  	virtual ~LLModelLoader() ;  	virtual void setNoNormalize() { mNoNormalize = true; } @@ -158,7 +161,6 @@ public:  	//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  );  	//Determines if a rig is a legacy from the joint list  	bool isRigLegacy( const std::vector<std::string> &jointListFromAsset ); @@ -166,9 +168,6 @@ public:  	//Determines if a rig is suitable for upload  	bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset ); -	void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; } -	const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; } -  	const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }  	void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; } @@ -180,7 +179,7 @@ public:  	//-----------------------------------------------------------------------------  	bool isNodeAJoint(const char* name)  	{ -		return mJointMap.find(name) != mJointMap.end(); +		return name != NULL && mJointMap.find(name) != mJointMap.end();  	}  protected: @@ -189,17 +188,14 @@ protected:  	LLModelLoader::joint_lookup_func_t	mJointLookupFunc;  	LLModelLoader::texture_load_func_t	mTextureLoadFunc;  	LLModelLoader::state_callback_t		mStateCallback; -	void*											mOpaqueData; +	void*								mOpaqueData; -	bool		mRigParityWithScene;  	bool		mRigValidJointUpload;  	bool		mLegacyRigValid;  	bool		mNoNormalize;  	bool		mNoOptimize; -	JointSet				mMasterJointList; -	JointSet				mMasterLegacyJointList;  	JointTransformMap	mJointTransformMap;  	static std::list<LLModelLoader*> sActiveLoaderList; | 
