Important information: this site is currently scheduled to go offline indefinitely by end of the year.

Maya py script

Read or post any tutorial related to file format analysis for modding purposes.
Post Reply
chrrox
Moderator
Posts: 2602
Joined: Sun May 18, 2008 3:01 pm
Has thanked: 57 times
Been thanked: 1422 times

Maya py script

Post by chrrox »

here is a sample maya py import script for hatsune miku for ipad.
its working great now including uv's
maya help
http://download.autodesk.com/us/maya/20 ... f40f22b125

Code: Select all

# Music Girl:Hatsune Miku
# Maya Python script

import maya.cmds as cmds
import maya.OpenMaya as om
import struct

def get_mobject(node):
	selectionList = om.MSelectionList()
	selectionList.add(node)
	oNode = om.MObject()
	selectionList.getDependNode(0, oNode)
	return oNode 

fname = cmds.fileDialog2(fm=1, ff='Music Girl:Hatsune Miku .mdl (*.mdl);;All Files (*.*)')[0]
f = open(fname, "rb")

magic = struct.unpack("4s",f.read(4))[0]
header = struct.unpack("4i",f.read(16))
f.seek(0x60, 0)
vertInfo = []
for i in range(0 ,header[3]):
	meshInfo = struct.unpack("4i",f.read(0x10))
	meshMatrix = struct.unpack("12f",f.read(0x30))
	meshInfo2 = struct.unpack("4i",f.read(0x10))
	vertInfo.append([meshInfo,meshMatrix,meshInfo2])
print(f.tell())
boneInfo = struct.unpack("4i",f.read(0x10))
texInfo = struct.unpack("4i",f.read(0x10))
matInfo = struct.unpack("4i",f.read(0x10))
vertOff = struct.unpack(str(header[3]) + "i",f.read(header[3] * 4))
faceOff = struct.unpack(str(header[3]) + "i",f.read(header[3] * 4))
weightOff = struct.unpack(str(header[3]) + "i",f.read(header[3] * 4))

for i in range(0 ,header[3]):
	vertexArray = om.MFloatPointArray()
	normalArray = om.MFloatPointArray()
	uArray = om.MFloatArray()
	vArray = om.MFloatArray()
	uvCounts = om.MIntArray()
	uvIds = om.MIntArray()
	f.seek(vertOff[i], 0)
	for a in range(0 ,vertInfo[i][0][1]):
		verts = struct.unpack("8f",f.read(32))
		pt = om.MFloatPoint(verts[0],verts[1], verts[2])
		vertexArray.append(pt)
		uArray.append(verts[6])
		vArray.append((verts[7] * -1) + 1)

	f.seek(faceOff[i], 0)
	pConnects = om.MIntArray()
	pCounts = om.MIntArray()
	for a in range(0 ,vertInfo[i][0][0]):
		faceCount = struct.unpack("H",f.read(2))[0]	
		matID = struct.unpack("H",f.read(2))[0]
		fstart = f.tell()
		StartDirection = -1
		f1 = struct.unpack("H",f.read(2))[0]
		f2 = struct.unpack("H",f.read(2))[0]
		FaceDirection = StartDirection
		while f.tell() < (fstart + (2 *faceCount )):
			f3 = struct.unpack("H",f.read(2))[0]
			if f3 == 0xFFFF:
				f1 = struct.unpack("H",f.read(2))[0]
				f2 = struct.unpack("H",f.read(2))[0]
				FaceDirection = StartDirection
			else:
				FaceDirection *= -1
				if (f1 != f2 and f1 != f3 and f3 != f2) : 
					if FaceDirection > 0:
						pConnects.append(f1)
						pConnects.append(f2)
						pConnects.append(f3)
					else:
						pConnects.append(f1)
						pConnects.append(f3)
						pConnects.append(f2)
					pCounts.append(3)
				f1 = f2
				f2 = f3

	f.seek(weightOff[i], 0)
	uvCounts = pCounts
	mesh = om.MFnMesh()
	ShapeMesh = cmds.group(em=True) # <-- we create an empty group/ trnasform node that will receive the mesh node as a sibling
	parentOwner = get_mobject( ShapeMesh )
	meshMObj = mesh.create(vertInfo[i][0][1], len(pCounts), vertexArray, pCounts, pConnects, uArray, vArray ,parentOwner ) #<-- don't forget to add a parent owner
	cmds.sets( 'null' + str(i + 1), e=True,forceElement='initialShadingGroup') # <--assign the defaut lambert shader
	defaultUVSetName = ''
	defaultUVSetName = mesh.currentUVSetName(-1)
	mesh.setUVs( uArray, vArray, defaultUVSetName )
        #if you want to manually set the uv's
	#for a in range(0 ,mesh.numPolygons()):
	#	for point in range(0 ,3):
	#		mesh.assignUV(a, point, pConnects[a*3+point] )
	mesh.assignUVs(pCounts,pConnects, defaultUVSetName)

#struct.unpack(4*"i",f.read(struct.calcsize(4*"i")))[0] 
#f.seek(4, 0) absolute
#f.seek(4, 1) current pos
#f.seek(4, 2) end of file

f.close()
finale00
M-M-M-Monster veteran
M-M-M-Monster veteran
Posts: 2382
Joined: Sat Apr 09, 2011 1:22 am
Has thanked: 170 times
Been thanked: 307 times

Re: Maya py script

Post by finale00 »

How does the maya plugin interface work?
Do you just write your plugin and then say "load plugin" and then it will just execute your file? Since you specified a file open dialog.
chrrox
Moderator
Posts: 2602
Joined: Sun May 18, 2008 3:01 pm
Has thanked: 57 times
Been thanked: 1422 times

Re: Maya py script with uv's

Post by chrrox »

i am going to make a dock-able gui once i get the format strait but for now i just open the script editor and paste it in and hit run.
but you can setup python plugins to register at start-up just like noesis.
edit this is a good start
http://etoia.free.fr/?p=1771
User avatar
TheDude
mega-veteran
mega-veteran
Posts: 239
Joined: Sun Mar 20, 2011 7:35 pm
Has thanked: 29 times
Been thanked: 59 times
Contact:

Re: Maya py script

Post by TheDude »

Awesome work chrrox!
I used this along with your code over here: http://gameresearch.5d6d.net/archiver/tid-199.html to learn how to create importers for Maya.
Do you have any example skinning/skeleton code? For some reason I understand source code better than docs. :oops:
User avatar
Dinoguy1000
Site Admin
Posts: 786
Joined: Mon Sep 13, 2004 1:55 am
Has thanked: 154 times
Been thanked: 163 times

Re: Maya py script

Post by Dinoguy1000 »

TheDude wrote:For some reason I understand source code better than docs. :oops:
Because it's a damn sight harder to make docs worth anything than it is to simply make some illustrative source code (as I'm sure just about anyone who's done both will tell you). :wink:
Welcome to Xentax!

Rules | Requests | Wiki | Discord

If you run across a post that breaks the rules, please report the post - a mod or admin will handle it from there.
User avatar
TheDude
mega-veteran
mega-veteran
Posts: 239
Joined: Sun Mar 20, 2011 7:35 pm
Has thanked: 29 times
Been thanked: 59 times
Contact:

Re: Maya py script

Post by TheDude »

Dinoguy1000 wrote: Because it's a damn sight harder to make docs worth anything than it is to simply make some illustrative source code (as I'm sure just about anyone who's done both will tell you). :wink:
Image
chrrox
Moderator
Posts: 2602
Joined: Sun May 18, 2008 3:01 pm
Has thanked: 57 times
Been thanked: 1422 times

Re: Maya py script

Post by chrrox »

here is the sample weight importing.

Code: Select all

# Music Girl:Hatsune Miku
# Maya Python script

import maya.cmds as cmds
import pymel.core as pm
import maya.OpenMaya as om
import maya.OpenMayaAnim as oma
import os
import struct

def get_mobject(node):
	selectionList = om.MSelectionList()
	selectionList.add(node)
	oNode = om.MObject()
	selectionList.getDependNode(0, oNode)
	return oNode 

fname = cmds.fileDialog2(fm=1, ff='Music Girl:Hatsune Miku .mdl (*.mdl);;All Files (*.*)')[0]
f = open(fname, "rb")

base=os.path.basename(fname)
os.path.splitext(base)
base=os.path.splitext(base)[0]

magic = struct.unpack("4s",f.read(4))[0]
header = struct.unpack("4i",f.read(16))
f.seek(0x60, 0)
vertInfo = []
for i in range(0 ,header[3]):
	meshInfo = struct.unpack("4i",f.read(0x10))
	meshMatrix = struct.unpack("12f",f.read(0x30))
	meshInfo2 = struct.unpack("4i",f.read(0x10))
	vertInfo.append([meshInfo,meshMatrix,meshInfo2])
print(f.tell())
boneInfo = struct.unpack("4i",f.read(0x10))
texInfo = struct.unpack("4i",f.read(0x10))
matInfo = struct.unpack("4i",f.read(0x10))
vertOff = struct.unpack(str(header[3]) + "i",f.read(header[3] * 4))
faceOff = struct.unpack(str(header[3]) + "i",f.read(header[3] * 4))
weightOff = struct.unpack(str(header[3]) + "i",f.read(header[3] * 4))

f.seek(boneInfo[1], 0)
boneArray = []
for i in range(0 ,boneInfo[0]):
	boneMat = struct.unpack("16f",f.read(0x40))
	boneDat = struct.unpack("4I",f.read(0x10))
	bonePosition = om.MVector(boneMat[0], boneMat[1], boneMat[2])
	boneOritation = om.MQuaternion(boneMat[4], boneMat[5], boneMat[6], boneMat[7])
	#boneScale = om.MVector(boneMat[8], boneMat[9], boneMat[10])
	if boneDat[0] == 0xFFFFFFFF:
		cmds.select( clear=True)
	else:
		pm.select(boneArray[boneDat[0]])
	newBone = pm.joint( p=(0,0,0), name='joint' + str(i),radius= (0.1) )
	newBone.setTranslation(bonePosition)
	newBone.setOrientation(boneOritation)
	boneArray.append(newBone)
	cmds.objExists("joint' + str(i)")
if len(boneArray) != 0:
    cmds.setAttr (str(boneArray[0]) + ".overrideEnabled", 1)
    cmds.setAttr (str(boneArray[0]) + ".overrideColor", 16)

for i in range(0 ,header[3]):
	vertexArray = om.MFloatPointArray()
	normalArray = om.MFloatPointArray()
	uArray = om.MFloatArray()
	vArray = om.MFloatArray()
	uvCounts = om.MIntArray()
	uvIds = om.MIntArray()
	f.seek(vertOff[i], 0)
	for a in range(0 ,vertInfo[i][0][1]):
		verts = struct.unpack("8f",f.read(32))
		pt = om.MFloatPoint(verts[0],verts[1], verts[2])
		vertexArray.append(pt)
		uArray.append(verts[6])
		vArray.append((verts[7] * -1) + 1)

	f.seek(faceOff[i], 0)
	pConnects = om.MIntArray()
	pCounts = om.MIntArray()
	for a in range(0 ,vertInfo[i][0][0]):
		faceCount = struct.unpack("H",f.read(2))[0]	
		matID = struct.unpack("H",f.read(2))[0]
		fstart = f.tell()
		StartDirection = -1
		f1 = struct.unpack("H",f.read(2))[0]
		f2 = struct.unpack("H",f.read(2))[0]
		FaceDirection = StartDirection
		while f.tell() < (fstart + (2 *faceCount )):
			f3 = struct.unpack("H",f.read(2))[0]
			if f3 == 0xFFFF:
				f1 = struct.unpack("H",f.read(2))[0]
				f2 = struct.unpack("H",f.read(2))[0]
				FaceDirection = StartDirection
			else:
				FaceDirection *= -1
				if (f1 != f2 and f1 != f3 and f3 != f2) : 
					if FaceDirection > 0:
						pConnects.append(f1)
						pConnects.append(f2)
						pConnects.append(f3)
					else:
						pConnects.append(f1)
						pConnects.append(f3)
						pConnects.append(f2)
					pCounts.append(3)
				f1 = f2
				f2 = f3

	f.seek(weightOff[i], 0)
	weights = {}
	for a in range(0 ,vertInfo[i][0][1]):
		vWeights = {}
		wCount = struct.unpack("I",f.read(4))[0]
		for b in range(0 ,wCount):
			boneId = struct.unpack("I",f.read(4))[0]
			weight = struct.unpack("f",f.read(4))[0]
			vWeights[boneId] = weight
		weights[a] = vWeights
	uvCounts = pCounts
	mesh = om.MFnMesh()
	ShapeMesh = cmds.group( em=True, name='null_' + base + str(i) )  # <-- we create an empty group/ trnasform node that will receive the mesh node as a sibling
	parentOwner = get_mobject( ShapeMesh )
	meshMObj = mesh.create(vertInfo[i][0][1], len(pCounts), vertexArray, pCounts, pConnects, uArray, vArray ,parentOwner ) #<-- don't forget to add a parent owner
	cmds.sets( 'null_' + base + str(i), e=True,forceElement='initialShadingGroup') # <--assign the defaut lambert shader
	defaultUVSetName = ''
	defaultUVSetName = mesh.currentUVSetName(-1)
	mesh.setUVs( uArray, vArray, defaultUVSetName )
	#for a in range(0 ,mesh.numPolygons()):
	#	for point in range(0 ,3):
	#		mesh.assignUV(a, point, pConnects[a*3+point] )
	mesh.assignUVs(pCounts,pConnects, defaultUVSetName)
	mesh.setName('mesh_' + base + str(i))
	if len(boneArray) != 0:
	    pm.skinCluster( str(boneArray[0]), 'mesh_' + base + str(i),sm=2,mi=4,omi=1,n='skinCluster_' + base + str(i))
	#pm.rename( 'skinCluster' + str(i + 1), 'miku_Skin' + str(i))

	# poly mesh and skinCluster name
	shapeName = 'mesh_' + base + str(i)
	clusterName = 'skinCluster_' + base + str(i)

	# get the MFnSkinCluster for clusterName
	selList = om.MSelectionList()
	selList.add(clusterName)
	clusterNode = om.MObject()
	selList.getDependNode(0, clusterNode)
	skinFn = oma.MFnSkinCluster(clusterNode)

	# get the MDagPath for all influence
	infDags = om.MDagPathArray()
	skinFn.influenceObjects(infDags)

	# create a dictionary whose key is the MPlug indice id and 
	# whose value is the influence list id
	infIds = {}
	infs = []
	for x in xrange(infDags.length()):
		infPath = infDags[x].fullPathName()
		infId = int(skinFn.indexForInfluenceObject(infDags[x]))
		infIds[infId] = x
		infs.append(infPath)

	# get the MPlug for the weightList and weights attributes
	wlPlug = skinFn.findPlug('weightList')
	wPlug = skinFn.findPlug('weights')
	wlAttr = wlPlug.attribute()
	wAttr = wPlug.attribute()
	wInfIds = om.MIntArray()

	# unlock influences used by skincluster
	for inf in infs:
		cmds.setAttr('%s.liw' % inf)

	# normalize needs turned off for the prune to work
	skinNorm = cmds.getAttr('%s.normalizeWeights' % clusterName)
	if skinNorm != 0:
		cmds.setAttr('%s.normalizeWeights' % clusterName, 0)
	cmds.skinPercent(clusterName, shapeName, nrm=False, prw=100)

	# restore normalize setting
	if skinNorm != 0:
		cmds.setAttr('%s.normalizeWeights' % clusterName, skinNorm)

	for vertId, weightData in weights.items():
		wlAttr = '%s.weightList[%s]' % (clusterName, vertId)
		for infId, infValue in weightData.items():
			wAttr = '.weights[%s]' % infId
			cmds.setAttr(wlAttr + wAttr, infValue)


#struct.unpack(4*"i",f.read(struct.calcsize(4*"i")))[0] 
#f.seek(4, 0) absolute
#f.seek(4, 1) current pos
#f.seek(4, 2) end of file

f.close()
User avatar
TheDude
mega-veteran
mega-veteran
Posts: 239
Joined: Sun Mar 20, 2011 7:35 pm
Has thanked: 29 times
Been thanked: 59 times
Contact:

Re: Maya py script

Post by TheDude »

Thanks chrrox!

Image
User avatar
Dinoguy1000
Site Admin
Posts: 786
Joined: Mon Sep 13, 2004 1:55 am
Has thanked: 154 times
Been thanked: 163 times

Re: Maya py script

Post by Dinoguy1000 »

You could also thank him for his post (the little yellow thumbs-up button at the bottom of his post). ;)
Welcome to Xentax!

Rules | Requests | Wiki | Discord

If you run across a post that breaks the rules, please report the post - a mod or admin will handle it from there.
User avatar
TheDude
mega-veteran
mega-veteran
Posts: 239
Joined: Sun Mar 20, 2011 7:35 pm
Has thanked: 29 times
Been thanked: 59 times
Contact:

Re: Maya py script

Post by TheDude »

It's a sad day when digital cookies aren't enough. :D
Ugh, forums are too complicated - Python is easier. (:
Post Reply