Maya + MEL/Python

This exercise was an exploration of combining Maya and Python using motion capture data.

As a re-introduction to Maya Expression Language, we wrote some procedures to query the coordinates of an object's vertices, then draw a curve through them.

The "getVertices" Procedure

global proc getVertices(string \$tnode, vector \$data[]) {
int \$count = size(\$data);
int \$num[] = `polyEvaluate -v \$tnode`;
string \$shp[] = `listRelatives -shapes \$tnode`;
string \$shape = \$shp[0];
float \$pos[];
for(\$n = 0; \$n < \$num[0]; \$n++) {
\$vert = \$shape + ".vtx[" + \$n + "]";
\$pos = `pointPosition -world \$vert`;
\$data[\$count] = <<\$pos[0],\$pos[1],\$pos[2]>>;
\$count++;
}
}

Utilizing the Data: "makeCurve"

The "getVertices" procedure stores the XYZ data in a global variable, "\$data[]". The next procedure compiles the data into a Maya curve command, then runs it.

global proc makeCurve(vector \$data[]) {
string \$cmd = "curve -d 3";
for(\$n = 0; \$n < size(\$data); \$n++{
vector \$vertex = \$data[\$n];
\$cmd = \$cmd + "-p " + \$vertex.x + " " + \$vertex.y + " " + \$vertex.z + " ";         }
print \$cmd;
eval (\$cmd);
}

Examples of using the scripts to convert primitives to curves.

Conversion to Python

Next, Malcolm asked us to convert the code from MEL to Python. This was fairly simple using the knowledge from the previous projects.

import maya.cmds as cmds
import maya.mel as mel

def getVertices(tnode):
data = []
num = cmds.polyEvaluate(tnode, v = True)
shp = cmds.listRelatives(tnode, shapes = True)
shape = shp[0]
pos = []

for n in range(num):
vert = "%s.vtx[%d]" % (shape, n)
pos = cmds.pointPosition(vert, world = True)
data.append(pos[0:3])
send = makeCurve(data,num)

def makeCurve(data, num):
cmd = "curve -d 3 "
for n in range(num):
vertex = data[n]
cmd = cmd + ("-p %s %s %s ") % (vertex[0], vertex[1], vertex[2])
mel.eval(cmd)

Using this method, I hand animated some mocap information to render as curves.

Animation by Sorya Serei

Interpreting Motion Capture Data

Once in Maya, I interpreted .txt mocap data using Malcolm's script "MoCapDB", which can be used to query and gather various types of information from within a mocap file.

This script can be easily utilized to generate markers for a given frame number, but the challenge was to have it generate ALL markers for ALL frames, in a way that we could scrub through on the timeline.

My solution was to use MoCapDB to reference the data file, and for every marker, create a NURBS sphere, then:

1. Store the created sphere in a variable, curSph.
2. Call the position of that marker for the given frame using MoCapDB, then store the XYZ coordinates into variables.
3. Use this information to create keyframes in the translate X, Y, and Z channels.

import maya.cmds as cmd
import maya.mel as mel
from MoCapDB import MoCapDB

db = MoCapDB('/home/cfetze20/mount/stuhome/mocap/dogwalk.txt', 0.02)

def mocapScrub(step):
# Run for loop for every mocap marker
for m in range(db.nummarkers()):
sph = cmd.sphere(r=0.2)
# Run subsequent loop for each frame
for n in range(0, db.numframes(), step):
curSph = cmd.ls(selection=True)
markers = db.getMarkerData(m, n, n, 1)
# Take the XYZ marker data, and store it in these three variables
if len(markers) == 3:
x = markers[0]
y = markers[1]
z = markers[2]
# Use the stored XYZ data to set keyframes.
cmd.setKeyframe(curSph[0] + ".tx", time=n, value=x)
cmd.setKeyframe(curSph[0] + ".ty", time=n, value=y)
cmd.setKeyframe(curSph[0] + ".tz", time=n, value=z)
# Clear variable data in preparation for the next loop
del(markers, x, y, z, curSph)