
bool FindFirstSkinCluster (MObject objShape, MFnSkinCluster& skinClusterFn, MStatus* stat)
{
	MItDependencyGraph itDep (objShape, MFn::kSkinClusterFilter, MItDependencyGraph::kUpstream, MItDependencyGraph::kBreadthFirst, MItDependencyGraph::kNodeLevel, stat);
	if (stat->error())
	{
		Log ("    error while trying to iterate dependency graph %s", stat->errorString().asChar());
		return false;
	}

	bool bSkinClusterFound = false;

	while (!itDep.isDone())
	{
		MObject objSkinCluster = itDep.thisNode (stat);
		if (stat->error())
		{
			Log ("    error while iterating dependency graph %s", stat->errorString().asChar());
			return false;
		}

		if (objSkinCluster.hasFn(MFn::kSkinClusterFilter))
		{
			skinClusterFn.setObject(objSkinCluster);
			if (bSkinClusterFound)
				*stat = MS::kFailure;
			else
			{
				*stat = MS::kSuccess;
				bSkinClusterFound = true;
			}
			Log ("Skin cluster %s found", skinClusterFn.name().asChar());
		}

		if (itDep.next().error())
			break;
	}
	return bSkinClusterFound;
}


MStatus CBVSkinExport::exportJoints()
{
	// get the list of influence objects
	//
	MDagPathArray infs;
	MStatus stat;
	unsigned int nInfs = m_fnSkinCluster.influenceObjects(infs, &stat);
	if (stat.error())
	{
		Log ("Error getting influence objects %s", stat.errorString().asChar());
		return stat;
	}

	if (0 == nInfs)
	{
		stat = MS::kFailure;
		Log("*ERROR* No influence objects found.");
		return stat;
	}

	fprintf (m_fOutFile, "<skeleton> <!-- count=\"%u\" -->\n", nInfs);
	for (unsigned int kk = 0; kk < nInfs; ++kk)
	{
		fprintf (m_fOutFile, "<joint jointId=\"%u\">\n<name>%s</name>\n", kk, infs[kk].fullPathName().asChar()+1);
		MMatrix mxJoint = infs[kk].inclusiveMatrix ();
		fprintf (m_fOutFile, "<transformMatrix>\n");
		for (int nRow = 0; nRow < 4; ++nRow)
		{
			for (int nCol = 0; nCol < 4; ++nCol)
				fprintf (m_fOutFile, "\t%.16g", mxJoint[nRow][nCol]);
			fprintf (m_fOutFile, "\n");
		}
		fprintf (m_fOutFile, "</transformMatrix>\n");
		fprintf (m_fOutFile, "</joint>\n");
	}
	fprintf (m_fOutFile, "</skeleton>\n");

	// loop through the geometries affected by this cluster
	//
	unsigned int nGeoms = m_fnSkinCluster.numOutputConnections();
	unsigned int ii;
	for (ii = 0; ii < nGeoms; ++ii)
	{
		unsigned int index = m_fnSkinCluster.indexForOutputConnection (ii, &stat);
		if(!stat)
		{
			Log("Error getting geometry index %s", stat.errorString().asChar());
			return stat;
		}

		// get the dag path of the ii'th geometry
		//
		MDagPath skinPath;
		stat = m_fnSkinCluster.getPathAtIndex(index,skinPath);
		if(!stat)
		{
			Log ("Error getting geometry path %s", stat.errorString().asChar());
			return stat;
		}

		// iterate through the components of this geometry
		//
		MFnMesh meshFn (skinPath, &stat);
		if (stat)
		{
			MItGeometry gIter(skinPath);

			// print out the path name of the skin, vertexCount & influenceCount
			//
			fprintf(m_fOutFile, "<geometry> <!-- %d control vertices, %d influences -->\n", gIter.count(), nInfs);
			fprintf (m_fOutFile, "<name>%s</name>\n", skinPath.partialPathName().asChar());
			exportMesh (meshFn);

			fprintf (m_fOutFile, "<cvWeights> <!-- control vertex count=\"%u\" --> \n", gIter.count());
		
			for ( /* nothing */ ; !gIter.isDone(); gIter.next() )
			{
				MObject comp = gIter.component (&stat);
				if(!stat)
				{
					Log ("Error getting component %s", stat.errorString().asChar());
					return stat;
				}

				// Get the weights for this vertex (one per influence object)
				//
				MFloatArray wts;
				unsigned int infCount;
				stat = m_fnSkinCluster.getWeights (skinPath,comp,wts,infCount);
				if(!stat)
				{
					Log ("Error getting weights %s", stat.errorString().asChar());
					return stat;
				}
				
				if (0 == infCount)
				{
					stat = MS::kFailure;
					Log ("Error: 0 influence objects.");
					return stat;
				}

				fprintf (m_fOutFile, "<cv> <!-- control vertex %u of %u --> ", gIter.index(), gIter.count());
				// Output the weight data for this vertex
				//
				for (unsigned int jj = 0; jj < infCount ; ++jj )
				{
					float fWeight = wts[jj];
					if (fWeight > 1e-4 || fWeight < -1e-4)
						fprintf (m_fOutFile,"<weight jointId=\"%u\">%.16g</weight>", jj, fWeight);
				}
				fprintf (m_fOutFile,"</cv>\n",gIter.index());
			}
			fprintf (m_fOutFile, "</cvWeights>\n");
			fprintf (m_fOutFile, "</geometry>\n");
		}
	}
	return stat;
}

