00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "SkinningPrimFunc.h"
00018 #include "Primitive.h"
00019 #include "SceneGraph.h"
00020
00021 using namespace Fluxus;
00022
00023 SkinningPrimFunc::SkinningPrimFunc()
00024 {
00025 }
00026
00027 SkinningPrimFunc::~SkinningPrimFunc()
00028 {
00029 }
00030
00031 void SkinningPrimFunc::Run(Primitive &prim, const SceneGraph &world)
00032 {
00033 int rootid = GetArg<int>("skeleton-root",0);
00034 int bindposerootid = GetArg<int>("bindpose-root",0);
00035 bool skinnormals = GetArg<int>("skin-normals",0);
00036 vector<dVector> *p = prim.GetDataVec<dVector>("p");
00037 vector<dVector> *pref = prim.GetDataVec<dVector>("pref");
00038 vector<dVector> *n = NULL;
00039 vector<dVector> *nref = NULL;
00040
00041 if (!pref)
00042 {
00044 Trace::Stream<<"SkinningPrimFunc::Run: aborting: primitive needs a pref (copy of p)"<<endl;
00045 return;
00046 }
00047
00048 if (skinnormals)
00049 {
00050 n = prim.GetDataVec<dVector>("n");
00051 nref = prim.GetDataVec<dVector>("nref");
00052 if (!nref)
00053 {
00054 Trace::Stream<<"SkinningPrimFunc::Run: aborting: primitive needs an nref (copy of n)"<<endl;
00055 return;
00056 }
00057 }
00058
00059 const SceneNode *root = static_cast<const SceneNode *>(world.FindNode(rootid));
00060 if (!root)
00061 {
00062 Trace::Stream<<"GenSkinWeightsPrimFunc::Run: couldn't find skeleton root node "<<rootid<<endl;
00063 return;
00064 }
00065
00066 const SceneNode *bindposeroot = static_cast<const SceneNode *>(world.FindNode(bindposerootid));
00067 if (!root)
00068 {
00069 Trace::Stream<<"GenSkinWeightsPrimFunc::Run: couldn't find bindopose skeleton root node "<<bindposerootid<<endl;
00070 return;
00071 }
00072
00073
00074 vector<const SceneNode*> skeleton;
00075 world.GetNodes(root, skeleton);
00076 vector<const SceneNode*> bindposeskeleton;
00077 world.GetNodes(bindposeroot, bindposeskeleton);
00078
00079 if (skeleton.size()!=bindposeskeleton.size())
00080 {
00081 Trace::Stream<<"SkinningPrimFunc::Run: aborting: skeleton sizes do not match! "<<
00082 skeleton.size()<<" vs "<<bindposeskeleton.size()<<endl;
00083 return;
00084 }
00085
00086
00087 vector<dMatrix> transforms;
00088 for (unsigned int i=0; i<skeleton.size(); i++)
00089 {
00090 transforms.push_back(world.GetGlobalTransform(skeleton[i])*
00091 world.GetGlobalTransform(bindposeskeleton[i]).inverse());
00092 }
00093
00094
00095 vector<vector<float>*> weights;
00096 for (unsigned int bone=0; bone<skeleton.size(); bone++)
00097 {
00098 char wname[235];
00099 snprintf(wname,256,"w%d",bone);
00100 vector<float> *w = prim.GetDataVec<float>(wname);
00101 if (w==NULL)
00102 {
00103 Trace::Stream<<"SkinningPrimFunc::Run: can't find weights, aborting"<<endl;
00104 return;
00105 }
00106 weights.push_back(w);
00107 }
00108
00109 for (unsigned int i=0; i<prim.Size(); i++)
00110 {
00111 dMatrix mat;
00112 mat.zero();
00113 for (unsigned int bone=0; bone<skeleton.size(); bone++)
00114 {
00115 mat+=(transforms[bone]*(*weights[bone])[i]);
00116 }
00117
00118 (*p)[i]=mat.transform((*pref)[i]);
00119
00120 if (skinnormals)
00121 {
00122 (*n)[i]=mat.transform_no_trans((*nref)[i]);
00123 }
00124 }
00125 }