summaryrefslogtreecommitdiff
path: root/indra/newview/llfloatermodelpreview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llfloatermodelpreview.cpp')
-rwxr-xr-xindra/newview/llfloatermodelpreview.cpp297
1 files changed, 179 insertions, 118 deletions
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index f15d4def80..c0b5b7cfa6 100755
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -379,7 +379,7 @@ LLFloaterModelPreview::~LLFloaterModelPreview()
{
sInstance = NULL;
- if ( mModelPreview->containsRiggedAsset() )
+ if ( mModelPreview->mModelLoader->mResetJoints )
{
gAgentAvatarp->resetJointPositions();
}
@@ -959,7 +959,7 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl
// LLModelLoader
//-----------------------------------------------------------------------------
LLModelLoader::LLModelLoader(std::string filename, S32 lod, LLModelPreview* preview)
-: LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mState(STARTING), mFirstTransform(TRUE)
+: LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mState(STARTING), mFirstTransform(TRUE), mResetJoints( FALSE )
{
mJointMap["mPelvis"] = "mPelvis";
mJointMap["mTorso"] = "mTorso";
@@ -1036,6 +1036,28 @@ LLModelLoader::LLModelLoader(std::string filename, S32 lod, LLModelPreview* prev
mJointMap["lThigh"] = "mHipLeft";
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("mSkull");
+ 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");
}
void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform)
@@ -1105,32 +1127,32 @@ void LLModelLoader::run()
{
DAE dae;
domCOLLADA* dom = dae.open(mFilename);
-
+
if (dom)
{
daeDatabase* db = dae.getDatabase();
-
+
daeInt count = db->getElementCount(NULL, COLLADA_TYPE_MESH);
-
+
daeDocument* doc = dae.getDoc(mFilename);
if (!doc)
{
llwarns << "can't find internal doc" << llendl;
return;
}
-
+
daeElement* root = doc->getDomRoot();
if (!root)
{
llwarns << "document has no root" << llendl;
return;
}
-
+
//get unit scale
mTransform.setIdentity();
-
+
domAsset::domUnit* unit = daeSafeCast<domAsset::domUnit>(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID())));
-
+
if (unit)
{
F32 meter = unit->getMeter();
@@ -1138,19 +1160,19 @@ void LLModelLoader::run()
mTransform.mMatrix[1][1] = meter;
mTransform.mMatrix[2][2] = meter;
}
-
+
//get up axis rotation
LLMatrix4 rotation;
-
+
domUpAxisType up = UPAXISTYPE_Y_UP; // default is Y_UP
domAsset::domUp_axis* up_axis =
daeSafeCast<domAsset::domUp_axis>(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID())));
-
+
if (up_axis)
{
up = up_axis->getValue();
}
-
+
if (up == UPAXISTYPE_X_UP)
{
rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f);
@@ -1159,20 +1181,20 @@ void LLModelLoader::run()
{
rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f);
}
-
+
rotation *= mTransform;
mTransform = rotation;
-
-
+
+
for (daeInt idx = 0; idx < count; ++idx)
{ //build map of domEntities to LLModel
domMesh* mesh = NULL;
db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH);
-
+
if (mesh)
{
LLPointer<LLModel> model = LLModel::loadModelFromDomMesh(mesh);
-
+
if (model.notNull() && validate_model(model))
{
mModelList.push_back(model);
@@ -1180,17 +1202,17 @@ void LLModelLoader::run()
}
}
}
-
+
count = db->getElementCount(NULL, COLLADA_TYPE_SKIN);
for (daeInt idx = 0; idx < count; ++idx)
{ //add skinned meshes as instances
domSkin* skin = NULL;
db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN);
-
+
if (skin)
{
domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement());
-
+
if (geom)
{
domMesh* mesh = geom->getMesh();
@@ -1202,25 +1224,25 @@ void LLModelLoader::run()
LLVector3 mesh_scale_vector;
LLVector3 mesh_translation_vector;
model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector);
-
+
LLMatrix4 normalized_transformation;
normalized_transformation.setTranslation(mesh_translation_vector);
-
+
LLMatrix4 mesh_scale;
mesh_scale.initScale(mesh_scale_vector);
mesh_scale *= normalized_transformation;
normalized_transformation = mesh_scale;
-
+
glh::matrix4f inv_mat((F32*) normalized_transformation.mMatrix);
inv_mat = inv_mat.inverse();
LLMatrix4 inverse_normalized_transformation(inv_mat.m);
-
+
domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix();
-
+
if (bind_mat)
{ //get bind shape matrix
domFloat4x4& dom_value = bind_mat->getValue();
-
+
for (int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
@@ -1228,26 +1250,26 @@ void LLModelLoader::run()
model->mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4];
}
}
-
+
LLMatrix4 trans = normalized_transformation;
trans *= model->mBindShapeMatrix;
model->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" );
-
+
//Try to get at the skeletal instance controller
domInstance_controller::domSkeleton* pSkeleton = daeSafeCast<domInstance_controller::domSkeleton>( pElement );
bool missingSkeletonOrScene = false;
-
+
//If no skeleton, do a breadth-first search to get at specific joints
if ( !pSkeleton )
{
@@ -1262,7 +1284,7 @@ void LLModelLoader::run()
//Get the children at this level
daeTArray< daeSmartRef<daeElement> > children = pScene->getChildren();
S32 childCount = children.getCount();
-
+
//Process any children that are joints
//Not all children are joints, some code be ambient lights, cameras, geometry etc..
for (S32 i = 0; i < childCount; ++i)
@@ -1276,7 +1298,7 @@ void LLModelLoader::run()
}
}
else
- //Has Skeleton
+ //Has Skeleton
{
//Get the root node of the skeleton
daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement();
@@ -1285,7 +1307,7 @@ void LLModelLoader::run()
//Once we have the root node - start acccessing it's joint components
const int jointCnt = mJointMap.size();
std::map<std::string, std::string> :: 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 )
{
@@ -1293,10 +1315,10 @@ void LLModelLoader::run()
char str[64]={0};
sprintf(str,"./%s",(*jointIt).second.c_str() );
//llwarns<<"Joint "<< str <<llendl;
-
+
//Setup the resolver
daeSIDResolver resolver( pSkeletonRootNode, str );
-
+
//Look for the joint
domNode* pJoint = daeSafeCast<domNode>( resolver.getElement() );
if ( pJoint )
@@ -1304,9 +1326,9 @@ void LLModelLoader::run()
//Pull out the translate id and store it in the jointTranslations map
daeSIDResolver jointResolver( pJoint, "./translate" );
domTranslate* pTranslate = daeSafeCast<domTranslate>( jointResolver.getElement() );
-
+
LLMatrix4 workingTransform;
-
+
//Translation via SID
if ( pTranslate )
{
@@ -1326,12 +1348,12 @@ void LLModelLoader::run()
extractTranslationViaElement( pTranslateElement, workingTransform );
}
}
-
+
//Store the joint transform w/respect to it's name.
jointTransforms[(*jointIt).second.c_str()] = workingTransform;
}
}
-
+
//If anything failed in regards to extracting the skeleton, joints or translation id,
//mention it
if ( missingSkeletonOrScene )
@@ -1340,64 +1362,32 @@ void LLModelLoader::run()
}
}//got skeleton?
}
-
- if ( !missingSkeletonOrScene )
- {
- //Set the joint translations on the avatar
- //The joints are reset in the dtor
- const int jointCnt = mJointMap.size();
- std::map<std::string, std::string> :: const_iterator jointIt = mJointMap.begin();
- for ( int i=0; i<jointCnt; ++i, ++jointIt )
- {
- std::string lookingForJoint = (*jointIt).first.c_str();
- if ( jointTransforms.find( lookingForJoint ) != jointTransforms.end() )
- {
- LLMatrix4 jointTransform = jointTransforms[lookingForJoint];
- LLJoint* pJoint = gAgentAvatarp->getJoint( lookingForJoint );
- if ( pJoint )
- {
- pJoint->storeCurrentXform( jointTransform.getTranslation() );
- }
- else
- {
- //Most likely an error in the asset.
- llwarns<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << llendl;
- }
- //Reposition the avatars pelvis (avPos+offset)
- //if ( lookingForJoint == "mPelvis" )
- //{
- // const LLVector3& pos = gAgentAvatarp->getCharacterPosition();
- // gAgentAvatarp->setPelvisOffset( true, jointTransform.getTranslation() );
- // gAgentAvatarp->setPosition( pos + jointTransform.getTranslation() );
- //}
- }
- }
- } //missingSkeletonOrScene
-
+
+
domSkin::domJoints* joints = skin->getJoints();
-
+
domInputLocal_Array& joint_input = joints->getInput_array();
-
+
for (size_t i = 0; i < joint_input.getCount(); ++i)
{
domInputLocal* input = joint_input.get(i);
xsNMTOKEN semantic = input->getSemantic();
-
+
if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0)
{ //found joint source, fill model->mJointMap and model->mJointList
daeElement* elem = input->getSource().getElement();
-
+
domSource* source = daeSafeCast<domSource>(elem);
if (source)
{
-
-
+
+
domName_array* names_source = source->getName_array();
-
+
if (names_source)
{
domListOfNames &names = names_source->getValue();
-
+
for (size_t j = 0; j < names.getCount(); ++j)
{
std::string name(names.get(j));
@@ -1415,7 +1405,7 @@ void LLModelLoader::run()
if (names_source)
{
xsIDREFS& names = names_source->getValue();
-
+
for (size_t j = 0; j < names.getCount(); ++j)
{
std::string name(names.get(j).getID());
@@ -1440,11 +1430,11 @@ void LLModelLoader::run()
{
domListOfFloats& transform = t->getValue();
S32 count = transform.getCount()/16;
-
+
for (S32 k = 0; k < count; ++k)
{
LLMatrix4 mat;
-
+
for (int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
@@ -1452,14 +1442,55 @@ void LLModelLoader::run()
mat.mMatrix[i][j] = transform[k*16 + i + j*4];
}
}
-
+
model->mInvBindMatrix.push_back(mat);
}
}
}
}
}
-
+
+ //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).
+
+ if ( !model->mJointList.empty() && doesJointArrayContainACompleteRig( model->mJointList ) )
+ {
+ mResetJoints = true;
+ }
+
+ if ( !missingSkeletonOrScene )
+ {
+ //Set the joint translations on the avatar - if it's a full mapping
+ //The joints are reset in the dtor
+ if ( mResetJoints )
+ {
+ std::map<std::string, std::string> :: const_iterator masterJointIt = mJointMap.begin();
+ std::map<std::string, std::string> :: const_iterator masterJointItEnd = mJointMap.end();
+ for (;masterJointIt!=masterJointItEnd;++masterJointIt )
+ {
+ std::string lookingForJoint = (*masterJointIt).first.c_str();
+
+ if ( jointTransforms.find( lookingForJoint ) != jointTransforms.end() )
+ {
+ //llinfos<<"joint "<<lookingForJoint.c_str()<<llendl;
+ LLMatrix4 jointTransform = jointTransforms[lookingForJoint];
+ LLJoint* pJoint = gAgentAvatarp->getJoint( lookingForJoint );
+ if ( pJoint )
+ {
+ pJoint->storeCurrentXform( jointTransform.getTranslation() );
+ }
+ else
+ {
+ //Most likely an error in the asset.
+ llwarns<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << llendl;
+ }
+ }
+ }
+ }
+ } //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.
@@ -1483,9 +1514,9 @@ void LLModelLoader::run()
llwarns<<"Possibly misnamed/missing joint [" <<lookingForJoint.c_str()<<" ] "<<llendl;
}
}
-
+
//grab raw position array
-
+
domVertices* verts = mesh->getVertices();
if (verts)
{
@@ -1501,19 +1532,19 @@ void LLModelLoader::run()
if (pos_array)
{
domListOfFloats& pos = pos_array->getValue();
-
+
for (size_t j = 0; j < pos.getCount(); j += 3)
{
if (pos.getCount() <= j+2)
{
llerrs << "WTF?" << llendl;
}
-
+
LLVector3 v(pos[j], pos[j+1], pos[j+2]);
-
+
//transform from COLLADA space to volume space
v = v * inverse_normalized_transformation;
-
+
model->mPosition.push_back(v);
}
}
@@ -1521,7 +1552,7 @@ void LLModelLoader::run()
}
}
}
-
+
//grab skin weights array
domSkin::domVertex_weights* weights = skin->getVertex_weights();
if (weights)
@@ -1539,44 +1570,44 @@ void LLModelLoader::run()
}
}
}
-
+
if (vertex_weights)
{
domListOfFloats& w = vertex_weights->getValue();
domListOfUInts& vcount = weights->getVcount()->getValue();
domListOfInts& v = weights->getV()->getValue();
-
+
U32 c_idx = 0;
for (size_t vc_idx = 0; vc_idx < vcount.getCount(); ++vc_idx)
{ //for each vertex
daeUInt count = vcount[vc_idx];
-
+
//create list of weights that influence this vertex
LLModel::weight_list weight_list;
-
+
for (daeUInt i = 0; i < count; ++i)
{ //for each weight
daeInt joint_idx = v[c_idx++];
daeInt weight_idx = v[c_idx++];
-
+
if (joint_idx == -1)
{
//ignore bindings to bind_shape_matrix
continue;
}
-
+
F32 weight_value = w[weight_idx];
-
+
weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value));
}
-
+
//sort by joint weight
std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater());
-
+
std::vector<LLModel::JointWeight> wght;
-
+
F32 total = 0.f;
-
+
for (U32 i = 0; i < llmin((U32) 4, (U32) weight_list.size()); ++i)
{ //take up to 4 most significant weights
if (weight_list[i].mWeight > 0.f)
@@ -1585,7 +1616,7 @@ void LLModelLoader::run()
total += weight_list[i].mWeight;
}
}
-
+
F32 scale = 1.f/total;
if (scale != 1.f)
{ //normalize weights
@@ -1594,12 +1625,12 @@ void LLModelLoader::run()
wght[i].mWeight *= scale;
}
}
-
+
model->mSkinWeights[model->mPosition[vc_idx]] = wght;
}
-
+
//add instance to scene for this model
-
+
LLMatrix4 transformation = mTransform;
// adjust the transformation to compensate for mesh normalization
@@ -1607,12 +1638,12 @@ void LLModelLoader::run()
mesh_translation.setTranslation(mesh_translation_vector);
mesh_translation *= transformation;
transformation = mesh_translation;
-
+
LLMatrix4 mesh_scale;
mesh_scale.initScale(mesh_scale_vector);
mesh_scale *= transformation;
transformation = mesh_scale;
-
+
std::vector<LLImportMaterial> materials;
materials.resize(model->getNumVolumeFaces());
mScene[transformation].push_back(LLModelInstance(model, transformation, materials));
@@ -1624,22 +1655,52 @@ void LLModelLoader::run()
}
}
}
-
+
daeElement* scene = root->getDescendant("visual_scene");
-
+
if (!scene)
{
llwarns << "document has no visual_scene" << llendl;
setLoadState( ERROR_PARSING );
return;
}
-
processElement(scene);
-
+
doOnIdleOneTime(boost::bind(&LLModelPreview::loadModelCallback,mPreview,mLod));
}
}
+bool LLModelLoader::doesJointArrayContainACompleteRig( const std::vector<std::string> &jointListFromModel )
+{
+ 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();
+
+ bool found = false;
+ for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
+ {
+ found = false;
+ modelJointIt = jointListFromModel.begin();
+ for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
+ {
+ if ( *masterJointIt == *modelJointIt )
+ {
+ found = true;
+ break;
+ }
+ }
+ if ( !found )
+ {
+ llinfos<<" Asset did not contain the joint (if you're u/l a fully rigged asset - it is required)." << *masterJointIt<< llendl;
+ break;
+ }
+ }
+
+ return found;
+}
+
//called in the main thread
void LLModelLoader::loadTextures()
{