void SkinningPrimFunc::Run(Primitive &prim, const SceneGraph &world) { int rootid = GetArg<int>("skeleton-root",0); int bindposerootid = GetArg<int>("bindpose-root",0); bool skinnormals = GetArg<int>("skin-normals",0); vector<dVector, FLX_ALLOC(dVector) > *p = prim.GetDataVec<dVector>("p"); vector<dVector, FLX_ALLOC(dVector) > *pref = prim.GetDataVec<dVector>("pref"); vector<dVector, FLX_ALLOC(dVector) > *n = NULL; vector<dVector, FLX_ALLOC(dVector) > *nref = NULL; if (!pref) { ///\todo sort out a proper error messaging thing Trace::Stream<<"SkinningPrimFunc::Run: aborting: primitive needs a pref (copy of p)"<<endl; return; } if (skinnormals) { n = prim.GetDataVec<dVector>("n"); nref = prim.GetDataVec<dVector>("nref"); if (!nref) { Trace::Stream<<"SkinningPrimFunc::Run: aborting: primitive needs an nref (copy of n)"<<endl; return; } } const SceneNode *root = static_cast<const SceneNode *>(world.FindNode(rootid)); if (!root) { Trace::Stream<<"GenSkinWeightsPrimFunc::Run: couldn't find skeleton root node "<<rootid<<endl; return; } const SceneNode *bindposeroot = static_cast<const SceneNode *>(world.FindNode(bindposerootid)); if (!root) { Trace::Stream<<"GenSkinWeightsPrimFunc::Run: couldn't find bindopose skeleton root node "<<bindposerootid<<endl; return; } // get the nodes as flat lists vector<const SceneNode*> skeleton; world.GetNodes(root, skeleton); vector<const SceneNode*> bindposeskeleton; world.GetNodes(bindposeroot, bindposeskeleton); if (skeleton.size()!=bindposeskeleton.size()) { Trace::Stream<<"SkinningPrimFunc::Run: aborting: skeleton sizes do not match! "<< skeleton.size()<<" vs "<<bindposeskeleton.size()<<endl; return; } // make a vector of all the transforms vector<dMatrix> transforms; for (unsigned int i=0; i<skeleton.size(); i++) { transforms.push_back(world.GetGlobalTransform(skeleton[i])* world.GetGlobalTransform(bindposeskeleton[i]).inverse()); } // get pointers to all the weights vector<vector<float, FLX_ALLOC(float) >*> weights; for (unsigned int bone=0; bone<skeleton.size(); bone++) { char wname[256]; snprintf(wname,256,"w%d",bone); vector<float, FLX_ALLOC(float) > *w = prim.GetDataVec<float>(wname); if (w==NULL) { Trace::Stream<<"SkinningPrimFunc::Run: can't find weights, aborting"<<endl; return; } weights.push_back(w); } for (unsigned int i=0; i<prim.Size(); i++) { dMatrix mat; mat.zero(); for (unsigned int bone=0; bone<skeleton.size(); bone++) { mat+=(transforms[bone]*(*weights[bone])[i]); } (*p)[i]=mat.transform((*pref)[i]); if (skinnormals) { (*n)[i]=mat.transform_no_trans((*nref)[i]); } } }