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]);
		}
	}
}