Mayaからほしいデータを抽出してみる。

Dycoon2007-07-29

Maya5のOpen Mayaで私がほしいパラメーターを抽出するプログラムを書いてみました。
参考にしたのはここら辺
http://www.robthebloke.org/index.html
http://svn.hermitworksentertainment.com/maya2q3/browser/trunk/maya2q3/x42.cpp?rev=114

画像はテスト用に作ったものですが、あまりにも出来が悪いのでワイヤーフレームで。

抽出しているパラメータは
スキニングする前の頂点の座標、法線、uv座標、
マテリアル、テクスチャー、
階層、ボーン、頂点の重み、ボーンの割り当てられ方、
などです。
アニメーションもほしいですが今回は見送り。

#define _BOOL int

#include <stdlib.h>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#define REQUIRE_IOSTREAM

#include <maya/MStatus.h>
#include <maya/MObject.h>
#include <maya/MString.h> 
#include <maya/MArgList.h>
#include <maya/MGlobal.h>
#include <maya/MSelectionList.h>
#include <maya/MItSelectionList.h>
#include <maya/MItSurfaceCV.h>
#include <maya/MItMeshVertex.h>
#include <maya/MPoint.h>
#include <maya/MFnMesh.h>
#include <maya/MFnTransform.h>
#include <maya/MFnIkJoint.h>
#include <maya/MVector.h>
#include <maya/MMatrix.h>
#include <maya/MQuaternion.h>
#include <maya/MDagPath.h>
#include <maya/MFileIO.h>
#include <maya/MLibrary.h>
#include <maya/MIOStream.h>
#include <maya/MPointArray.h>
#include <maya/MFloatArray.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MItDependencyNodes.h>
#include <maya/MFnLambertShader.h>
#include <maya/MItMeshPolygon.h>
#include <maya/MFnSkinCluster.h>
#include <maya/MFnMatrixData.h>
#include <maya/MItGeometry.h>
#include <maya/MDagPathArray.h>
#include <math.h>

void PrintColor(MFnDependencyNode & node, const char * name, int depth)
{
	string space(depth, ' ');
	MPlug p;

	MString r = name;
	MString g = name;
	MString b = name;
	MString a = name;
	r += "R";
	g += "G";
	b += "B";
	a += "A";

	MColor color;
	p = node.findPlug(r.asChar());
	p.getValue(color.r);
	p = node.findPlug(g.asChar());
	p.getValue(color.g);
	p = node.findPlug(b.asChar());
	p.getValue(color.b);
	p = node.findPlug(a.asChar());
	p.getValue(color.a);
	p = node.findPlug(name);

	MString texname;

	MPlugArray plugs;
	p.connectedTo(plugs,true,false);

	for(int i=0;i!=plugs.length();++i)
	{
		if(plugs[i].node().apiType() == MFn::kFileTexture)
		{
			MFnDependencyNode fnDep(plugs[i].node());

			{
				MPlug mp;

				mp = fnDep.findPlug("fileTextureName");

				mp.getValue(texname);

			}
			break; 

		} 

	}
	
	if( name == string("color") && 
		color.r < 0.01f && 
		color.g < 0.01f && 
		color.b < 0.01f) 
	{
		color.r = color.g = color.b = 0.5f; 
	}

	cout << space << name << " "
		<< color.r << " " << color.g << " "
		<< color.b << " " << color.a << " "
		<< texname.asChar() << endl;
} 

void PrintMesh(MObject obj, int depth)
{
	MStatus	stat;
	string space(depth, ' ');

	MFnDependencyNode node(obj);

	MFnMesh mesh(obj);

	unsigned int i, isz;
	unsigned int j, jsz;
	unsigned int k, ksz;

	MObject vtxobj = obj;

	{
		MPlug mp;
		MPlugArray mpa;

		mp = node.findPlug("inMesh");
		mp.connectedTo(mpa, true, false);

		isz = mpa.length();

		for(i = 0 ; i < (1 < isz ? 1 : isz) ; i++)
		{
			MFnDependencyNode node(mpa[i].node());

			cout << space << " " << node.typeName().asChar() << " : "
					<< node.name().asChar() << endl;

			if(node.typeName() == "skinCluster")
			{
				MFnSkinCluster skinC(mpa[i].node());

				skinC.findPlug( "input" ).elementByLogicalIndex( skinC.indexForOutputShape( obj ) ) 
									.child( 0 ).getValue( vtxobj ); 


			}
		}
	}

	MFnMesh smesh(vtxobj);

	//
	MPointArray vertices;
	smesh.getPoints(vertices);
	cout << space << "vertex size = " << vertices.length() << endl;

	isz = vertices.length(); 
	//for(i = 0 ; i < isz ; i++)
	for(i = 0 ; i < 1 ; i++)
	{
		cout << space << " (" << 
			vertices[i].x << ", " <<
			vertices[i].y << ", " <<
			vertices[i].z << ", " <<
			vertices[i].w << ")" << endl;

		//cout << space << "  " << 
		//	vertices[i].x << "	" <<
		//	vertices[i].y << "	" <<
		//	vertices[i].z << "	" <<
		//	vertices[i].w << "" << endl;
	}

	//
	MFloatVectorArray normals;
	smesh.getNormals(normals);
	cout << space << "normal size = " << normals.length() << endl;

	isz = normals.length(); 
	//for(i = 0 ; i < isz ; i++)
	for(i = 0 ; i < 1 ; i++)
	{
		cout << space << " (" << 
			normals[i].x << ", " <<
			normals[i].y << ", " <<
			normals[i].z << ")" << endl;
	}

	//
	MStringArray uvsets;
	vector<MFloatArray> us;
	vector<MFloatArray> vs;
	smesh.getUVSetNames(uvsets);
	cout << space << "uvset size = " << uvsets.length() << endl;
	isz = uvsets.length();
	us.resize((size_t)isz);
	vs.resize((size_t)isz);
	for(i = 0 ; i < isz ; i++)
	{
		smesh.getUVs(us[i], vs[i], &uvsets[i]);

		jsz = us[i].length();
		cout << space << " " << uvsets[i].asChar() <<
			" size = " << jsz << endl;

		//for(j = 0 ; j < jsz ; j++)
		for(j = 0 ; j < 1 ; j++)
		{
			cout << space << "  (" << us[i][j] << ", " 
				<< vs[i][j] << ")" << endl;
		}
	}

	//
	MItMeshPolygon ipol(vtxobj);
	int uvindex;
	isz = uvsets.length();

	cout << space << "polygon size = " << mesh.numPolygons() << endl;

	while(!ipol.isDone())
	{
		jsz = (unsigned int)ipol.polygonVertexCount();

		cout << space << " polygon vertex size = " << jsz << endl;

		//for(j = 0 ; j < jsz ; j++)
		for(j = 0 ; j < 1 ; j++)
		{
			cout << space << "  vertex index = " << ipol.vertexIndex(j) <<
				" ,normal index = " << ipol.normalIndex(j);// << endl;

			for(i = 0 ; i < isz ; i++)
			{
				ipol.getUVIndex(j, uvindex, &uvsets[i]);
				cout << " ,uv index" << i << " = " << uvindex;
			}

			cout << endl;
		}

		//

		ipol.next();

		//一枚だけ表示
		break;
	}
	
	//

	isz = mesh.parentCount(); //isz = smesh.parentCount(); //間違っていたかな?

	cout << space << "parent count = " << isz << endl;

	for(i = 0 ; i < isz ; i++)
	{
		MObjectArray shaders;
		MIntArray indices;

		//smesh.getConnectedShaders(i,   //ここも間違っていた
		//						shaders, indices);
		mesh.getConnectedShaders(i,
								shaders, indices);

		jsz = shaders.length();

		cout << space << " shader size = " << jsz << endl;

		for(j = 0 ; j < jsz ; j++)
		{
			MPlug mp;
			MPlugArray mpa;
			MFnDependencyNode node(shaders[j]);

			mp = node.findPlug("surfaceShader");

			mp.connectedTo(mpa, true, false);

			ksz = mpa.length();
			for(k = 0 ; k < ksz ; k++)
			{
				MFnDependencyNode node(mpa[k].node());

				cout << space << "  Connections " 
					<< node.object().apiTypeStr() << " "
					<< node.typeName().asChar() << " "
					<< node.name().asChar() << endl;

				switch(node.object().apiType())
				{
					case MFn::kPhong:
						{
							MFnLambertShader node(node.object());

							PrintColor(node, "ambientColor", depth + 3);
							PrintColor(node, "color", depth + 3);
							PrintColor(node, "speqularColor", depth + 3);
							PrintColor(node, "incandescence", depth + 3);
							PrintColor(node, "transparency", depth + 3);
						}
						break;
					case MFn::kLambert:
						{
							MFnLambertShader node(node.object());

							PrintColor(node, "ambientColor", depth + 3);
							PrintColor(node, "color", depth + 3);
							PrintColor(node, "incandescence", depth + 3);
							PrintColor(node, "transparency", depth + 3);

						}
						break;
				}
			}
		}

		jsz = indices.length();

		cout << space << " indices size = " << jsz << endl;

		//for(j = 0 ; j < jsz ; j++)
		for(j = 0 ; j < 1 ; j++)
		{
			cout << space << "  index = " << indices[j] << endl;
		}


		
	}

	//
	{
		MPlug mp;
		MPlugArray mpa;

		mp = node.findPlug("inMesh");
		mp.connectedTo(mpa, true, false);

		isz = mpa.length();

		for(i = 0 ; i < isz ; i++)
		{
			MFnDependencyNode node(mpa[i].node());

			cout << space << " " << node.typeName().asChar() << " : "
					<< node.name().asChar() << endl;

			if(node.typeName() == "skinCluster")
			{
				MFnSkinCluster skinC(mpa[i].node());
				MDagPathArray dpa;

				//*
				{
					MPlugArray mpa;
					skinC.getConnections( mpa );

					unsigned int i, isz;

					isz = mpa.length();
					for(i = 0 ; i < isz ; i++)
					{
						cout << space << "  skinplug = " << mpa[i].name().asChar()
								<< endl;
					}
				}
				//*/

				jsz = skinC.influenceObjects(dpa, &stat);
				ksz = skinC.numOutputConnections();

				for(k = 0 ; k < ksz ; k++)
				{
					unsigned int index;
					index = skinC.indexForOutputConnection(k);

					MDagPath dp;
					skinC.getPathAtIndex(index, dp);

					MItGeometry gi(dp);

					cout << space << "  skin = " << dp.partialPathName().asChar()
						<< ", point size = " << gi.count()
						<< ", influence size = " << jsz << endl;

					for(j = 0 ; j < jsz ; j++)
					//for(j = 0 ; j < 1 ; j++)
					{
						cout << space << "   " << 
							dpa[j].partialPathName().asChar() << endl;
					}

					{
						//bindPreMatrix

						MObject objtobind;
						skinC.findPlug( "geomMatrix" ).getValue( objtobind );
						MFnMatrixData mat(objtobind);
						MMatrix ma = mat.matrix();

						MPlug mp = skinC.findPlug("bindPreMatrix", &stat);
						//MPlug mp = skinC.findPlug("matrix", &stat);
						cout << space << "   " << mp.name().asChar() << endl;

						//for(j = 0 ; j < jsz ; j++)
						for(j = 0 ; j < 1 ; j++)
						{
							MPlug mp2 =
									mp.elementByLogicalIndex(
										skinC.indexForInfluenceObject( dpa[j], NULL ), &stat);

							cout << space << "   " << mp2.name().asChar() << endl;

							MObject obj;
							mp2.getValue(obj);
							MFnMatrixData mat(obj);
							MMatrix m = ma * mat.matrix();
							m = m.inverse();

							cout << space << "    ("
								<< m[0][0] << " " << m[0][1] << " " << m[0][2] << " " << m[0][3] << endl
								<< space << "     "
								<< m[1][0] << " " << m[1][1] << " " << m[1][2] << " " << m[1][3] << endl
								<< space << "     "
								<< m[2][0] << " " << m[2][1] << " " << m[2][2] << " " << m[2][3] << endl
								<< space << "     "
								<< m[3][0] << " " << m[3][1] << " " << m[3][2] << " " << m[3][3] << ")" << endl;

							//cout << space << "    "
							//	<< m[3][0] << "\t" << m[3][1] << "\t" << m[3][2] << "\t" << m[3][3] << "" << endl;
						}

					}

					while(!gi.isDone())
					{
						MObject cp = gi.component();

						MFloatArray ws;
						unsigned int l, lsz;

						skinC.getWeights(dp, cp, ws, lsz);

						if(lsz != 0 &&
							//gi.index() == k &&
							!gi.isDone())
						{
							unsigned int wnum = 0;
							float outw[256] = {1.0f, 0.0f};
							unsigned int outinf[256] = {0};

							for(l = 0 ; l < lsz ; l++)
							{
								if(ws[l] > 0.001f )
								{
									if(wnum != 0)
									{
										outw[0] -= ws[l];
										outw[wnum] = ws[l];
									}
									outinf[wnum] = l;
									wnum++;
								}

							}

							cout << space << "   weight size = " <<
								wnum << " index = " << gi.index() << endl;
							for(l = 0 ; l < wnum ; l++)
							{
								cout << space << "    (" << outinf[l]
									<< ", " << outw[l] << ")" << endl;
							}

						}
					
						gi.next();
						//break;
					}

				}

				

			}
		
		}
	
	}



}

void PrintTransformMesh(MObject obj, int depth)
{
	string space(depth, ' ');

	MFnDependencyNode node(obj);

	cout << space << node.typeName().asChar() << " : "
		<< node.name().asChar() << endl;

	if(node.typeName() == MString("mesh"))
	{
		PrintMesh(obj, depth + 1);
	}
	if(node.typeName() == MString("transform") ||
		node.typeName() == MString("joint") )
	{
		MFnTransform trans(obj);

		MMatrix m = trans.transformation().asMatrix();

		cout << space << " ("
			<< m[0][0] << " " << m[0][1] << " " << m[0][2] << " " << m[0][3] << endl
			<< space << "  "
			<< m[1][0] << " " << m[1][1] << " " << m[1][2] << " " << m[1][3] << endl
			<< space << "  "
			<< m[2][0] << " " << m[2][1] << " " << m[2][2] << " " << m[2][3] << endl
			<< space << "  "
			<< m[3][0] << " " << m[3][1] << " " << m[3][2] << " " << m[3][3] << ")" << endl;

		{
			unsigned int i, isz;
			MObject obj;
			
			isz = trans.childCount();

			for(i = 0 ; i < isz ; i++)
			{
				obj = trans.child(i);
				MFnDependencyNode node(obj);

				PrintTransformMesh(obj, depth + 1);
			}
		}
		
	}

}

void MakeTestProc1(int argc, char **argv)
{
	MStatus	stat;

	{
		//MString fname("scenes/bamboogun_forx.mb");
		MString fname("scenes/mario4.mb");

		stat = MFileIO::open(fname, "mayaBinary", true);
		if(stat)
		{
		
		}
		else
		{
			cout << "failed in open." << endl;
			return;
		}
	}

	{
		MSelectionList selList;

		//selList.add("group5");
		selList.add("group6");

		unsigned int i, isz;

		isz = selList.length();

		for(i = 0 ; i < isz ; i++)
		{
			MObject obj;

			selList.getDependNode(i, obj);

			

			PrintTransformMesh(obj, 0);

		}

	}
}