create a grid of cubes

Grid of cubes in Maya.

# create a grid of cubes, their bottom plane set to zero y, and the center point at zero y.
x = -20
count = 0
cubes = []
while x <= 20:
	z = -20
	while z <= 20:
		cube = mc.polyCube( name = ('polyCube_' + str(count) + '_' + str(x) + str(z)) )
		count +=1
		cubeName=cube[0]
		cubes.append(cubeName)
		mc.setAttr((cubeName + '.translateY'), .5);
		mc.makeIdentity(apply=True, t =True, r=True, s=True, n= 0)
		mc.ResetTransformations()
		mc.move(x, 0, z)
		z += 1
	x +=1

Block of cubes

import maya.cmds as mc
# create a block grid of cubes
# change the mult number below to change the amount of cubes created.
mult =  3;
count = 0
cubes = []
y = mult - mult
while y <= mult *2:
    x = mult * -1
    while x <= mult:
	    z = mult * -1
	    while z <= mult:
		    cube = mc.polyCube( name = ('cube_' + str(count) ) )
		    count +=1
		    cubeName=cube[0]
		    cubes.append(cubeName)
		    mc.move(x, y, z)
		    z += 1
	    x +=1
    y +=1

Make a 3d cube grid, based on a selected object’s bounding box.

//MEL
proc makeCubeGrid(int $cubeGridDiv)
{
    string $cube[];
    string $cubes[] = {};
    string $sel[] = `ls -long -sl`;
    float $bBox[] = `polyEvaluate -b -ae $sel[0]`;

    float $w = ($bBox[1] - $bBox[0]) / $cubeGridDiv;
    float $h = ($bBox[3] - $bBox[2]) / $cubeGridDiv;
    float $d = ($bBox[5] - $bBox[4]) / $cubeGridDiv;

    float $p[3];
    for($i=0;$i<$cubeGridDiv;$i++)
    {
        $p[0] = $bBox[0] + (($bBox[1] - $bBox[0]) / $cubeGridDiv) * $i;
        for($k=0;$k<$cubeGridDiv;$k++)
        {
            $p[1] = $bBox[2] + (($bBox[3] - $bBox[2]) / $cubeGridDiv) * $k;
            for($n=0;$n<$cubeGridDiv;$n++)
            {
                $p[2] = $bBox[4] + (($bBox[5] - $bBox[4]) / $cubeGridDiv) * $n;
                $cube = `polyCube -w $w -h $h -d $d -sx 1 -sy 1 -sz 1 -ax 0 0 0 -ch 0`;
                move ($p[0] + $w / 2) ($p[1] + $h / 2) ($p[2] + $d / 2) $cube[0];
                makeIdentity -apply true -t 1 -r 1 -s 1 -n 0 $cube[0];
                $cubes[`size $cubes`] = $cube[0];
            };
        };
    };
    string $group = `group -em -n "cubes"`;
    parent $cubes $group;
};

makeCubeGrid(10);

Newline / convert newline shell script

When pasting data to a text file, for use with python and other data editing tools, it may be better to use a code text editor, like BB Edit or Text Wrangler. These apps can save your .txt files with UNIX line returns which is necessary to make some scripts work properly.

Technically the line breaks are invisible, but using the ‘tr’ command, in a UNIX shell, you could display them as any character you like, eg:

In the terminal type:

cat /path/some/file.txt | tr '\n' 'U'

In the above example, if the input file uses UNIX style line returns, \n ,each line will have a ‘U’ at the end, or nothing if the file is using another type of return.

To change line returns from Mac to Unix in a data file, try the shell script below.

#!/bin/sh

theFile="$1"

newFile=`basename -s ".txt" $theFile`.UnixLineReturns.txt

theDir=`dirname $theFile`

echo "theFile: $theFile"
echo "newFile: $newFile"
echo "theDir: $theDir"

cat "$theFile"  | tr '\r' '\n' > "$theDir/$newFile"

Create a Graphic EQ using SoundKeys and Maya

You can create this graphic equalizer with Trapcode Soundkeys and Maya. Use my Python script, below, to automatically import keyframe data and create the eq.

Trapcode Soundkeys, an Adobe After Effects plugin, breaks audio into into about 27 frequency blocks, “ranges”, and allows you to drive animation, set keyframes, or export keyframes. To export keys, copy the keyframes from the After Effects timeline, then paste into a text editor to create your data.txt files. Each frequency range should have it’s own text file, named sequentially. Use a code editor like BB Edit or Text Wrangler, as these apps will save your .txt files with UNIX line returns, which are necessary to make my Python script work properly.

Place all the data files in a directory, by themselves, and use the Python script below to automatically build the EQ in Maya.

## make a graphic equalizer, based on keyframe data from After Effects and Sound Keys.
import os
import maya.cmds as mc
## add path to keyframe data files - just the source directory that contains them.
rootdir='/path/to/data/folder'
theAttribute = 'data'
count = 0
theCubes = []
for subdir, dirs, files in os.walk(rootdir):
	dataFiles = [each for each in files if each.endswith('.txt')]
	for thisFile in dataFiles:
		## create a cube for each data file, and distibute them across the  X axis
		mc.polyCube()
		cube = mc.ls(sl = True)
		cubeName=cube[0]
		theCubes.append(cubeName)
		mc.setAttr((cubeName + '.translateY'), .5);
		mc.makeIdentity(apply=True, t =True, r=True, s=True, n= 0)
		mc.ResetTransformations()
		mc.move( count -(len(dataFiles)/2), 0, 0)
		count +=1
count = 0
for subdir, dirs, files in os.walk(rootdir):
	dataFiles = [each for each in files if each.endswith('.txt')]
	for thisFile, o in zip(dataFiles, theCubes):
		## prepare each cube for animation by ading an attibute to accept the keys, and creating an expression
		theName = theCubes[count]
		mc.addAttr( theName, shortName='data', longName='data', defaultValue=1.0)
		mc.setAttr ( (theName + '.data'), e=True, keyable=True)
		mc.expression(o=theName, s = (theName + '.scaleY =' +  theName + '.data / 4'),  ae = True, uc = all)
		## make shader for each cube
		myBlinn = mc.shadingNode('blinn', asShader=True, name = ("myBlinn" + str(count)))
		myShader = mc.sets(renderable=True, noSurfaceShader=True, empty=True, name = ('myBlinn' + str(count) + 'SG'))
		mc.connectAttr( (myBlinn + ".outColor"), (myShader + ".surfaceShader"), f=True)
		mc.setAttr((myBlinn + ".color"), 0.1, 0.1, 0.1, type ='double3' )
		mySetRange =  mc.shadingNode('setRange', asUtility=True)
		mySetRange2 = mc.shadingNode('setRange', asUtility=True)
		mc.setAttr((mySetRange + ".minX"),230)
		mc.setAttr((mySetRange + ".maxX") ,240)
		mc.setAttr((mySetRange + ".oldMaxX") ,25)
		mc.setAttr((mySetRange2 + ".maxX") ,3)
		mc.setAttr((mySetRange2 + ".minX") ,.1)
		mc.setAttr((mySetRange2 + ".oldMaxX") ,25)
		myRamp = mc.shadingNode('ramp', asTexture=True)
		my2dPlace = mc.shadingNode('place2dTexture', asUtility=True)
		mc.connectAttr((my2dPlace + ".outUV"), (myRamp + ".uv"))
		mc.connectAttr((my2dPlace + ".outUvFilterSize"), (myRamp + ".uvFilterSize"))
		mc.setAttr((myRamp + ".colorEntryList[2].color"), 0, 0, 0 , type = 'double3')
		mc.removeMultiInstance((myRamp + ".colorEntryList[0]"), b=True )
		mc.removeMultiInstance(myRamp + ".colorEntryList[1]", b=True )
		mc.connectAttr( (theName + ".scaleY"), (mySetRange + ".valueX"), f=True)
		mc.connectAttr( (theName+ ".scaleY"), (mySetRange2 + ".valueX"), f=True)
		mc.connectAttr( (theName + ".scaleY"), (mySetRange2 + ".valueY"), f=True)
		mc.connectAttr( (theName + ".scaleY"), (mySetRange2 + ".valueZ"), f=True)
		myhsvToRgb = mc.createNode('hsvToRgb', ss=True)
		mc.setAttr((myhsvToRgb+".inHsv"), .75, .75, .75)
		mc.connectAttr( (mySetRange + ".outValueX"), (myhsvToRgb + ".inHsvR"), f=True )
		mc.connectAttr( (myRamp  + ".outColor"), (myBlinn + ".incandescence"), f=True )
		mc.connectAttr( (myhsvToRgb + ".outRgb"), (myRamp+ ".colorEntryList[2].color"), f=True )
		mc.connectAttr( (mySetRange2 + ".outValue"), (myRamp + ".colorGain"), f=True )
		mc.select(theName)
		mc.sets( e=True, forceElement= myShader)
		count +=1
		## read keyframe data and set keyframes
		dataFile = open((os.path.join(rootdir, thisFile)), 'r')
		lines = dataFile.readlines()
		dataFile.close()
		mylines = lines[10:-4]
		for eachLine in mylines:
			data = eachLine.split('\t')
			theFrame = data[1]
			theValue = data[2]
			mc.setKeyframe( o, v=float(theValue), at=theAttribute, t =float(theFrame))
## the code below will set the playback range to equal the amount of the keyframe data in the files
fileData = open(rootdir + '/' + dataFiles[0])
lines= fileData.readlines()
fileData.close()
myLines = lines[10:-4]
countLines = len(myLines)
mc.playbackOptions( minTime='0sec', maxTime=countLines)

Sample keyframe data, exported from After Effects.

Apple Mac Pro Bluetooth issue solved

If you are using a Mac Pro with wireless Bluetooth devices, particularly a mouse, you may have noticed an annoying lag or stutter in the performance. I bought the Magic Mouse and a wireless keyboard to solve some ergonomic issues. Unfortunately, poor performance made the situation even worse. Now, after having fixed this problem, my wireless devices are working perfectly.

The problem seems to be poor reception from the Bluetooth unit that shipped with my Mac Pro. I solved this by installing a third party Bluetooth usb adapter. In order for the new usb Bluetooth to operate properly, I had to disable the original internal Bluetooth unit. The instructions to disable the Mac Pro’s Bluetooth are below:

Review the procedure for working on your Mac by downloading a manual here.

1. Turn off Mac Pro. Remove power cord. Remove case cover.
2. Remove the processor tray.

Mac Pro Processor Tray

3. Find the Bluetooth unit on the motherboard. It is located near the bottom, on the right hand side as you are looking into the case.

Mac Pro bluetooth unit

4. Remove the connector that connects the Bluetooth to the motherboard.

Mac Pro bluetooth connector

5. Replace processor tray, and close case.

bluetooth USB dongle

6. Install a usb Bluetooth adapter.

Above is the tiny IOGear USB 2.1 Bluetooth Micro Adapter GBU421, which seems to work well with my Mac.

Note: I am using an Intel based MacPro4,1, bought in 2009. If you are using an older Mac Pro, you may want to look at this article and this article, as I believe that the configuration is different.

Caveat: While I am fairly certain that the Mac Pro’s internal Bluetooth could use and antenna redesign, given that so many people are having this same issue, I was not able to completely resolve my issue until I moved the usb Bluetooth adapter up onto my Cinema display, which features usb ports, and is a bit closer to the wireless devices. When I placed the adapter on one of the Mac Pro’s USB ports, on the front of the tower, again the result was poor performance. This leads me to believe that there is some interference from my furniture as well.

Note: If you are using a Magic Mouse, Magic Prefs is a must. It greatly expands the functionality of the Magic Mouse.

Disclaimer

Python import/export Maya keyframes script

These are fairly rudimentary python scripts, to export keys from Maya and import them back into Maya. Creates a key at every frame. May be interesting to people learning Python.

Export Maya Keys

import maya.cmds as mc
# Select all nodes with keys to export
# Customize the path below so that it points to, or creates, the file where you want to store the keyframe data
myFileObject=open('/mydataDir/data.txt', 'w')
obs = mc.ls(sl=True)
theData = []
minTime = mc.playbackOptions(query=True, minTime=True)
maxTime = mc.playbackOptions(query=True, maxTime=True)
attributes = ['translateX', 'translateY', 'translateZ', 'rotateX', 'rotateY', 'rotateZ', 'scaleX', 'scaleY', 'scaleZ', 'visibility']
for time in range(minTime -1, maxTime +1):
	mc.currentTime(time)
	count = 0
	for selection in obs:
		name = obs[count]
		count +=1
		for theAttribute in attributes:
			myAtF = mc.getAttr(selection + '.' + theAttribute)
			myAt = str(myAtF)
			myTime = str(time)
			theData.append(myAt + ' ' + myTime + ' ' + theAttribute + ' ' + name + ' \n')
for lines in theData:
	myFileObject.writelines(lines)
myFileObject.close()

Import Maya Keys
This will import keys to nodes which are named identically to the nodes that were selected when the keys were exported.

import maya.cmds as mc
# Customize the path below so that it points to the file where you have exported the keyframe data
myFileObject=open('/mydataDir/data.txt', 'r')
theLines = myFileObject.readlines()
count = 0
for line in theLines:
	theLine = theLines[count]
	theSplit = str.split(theLine)
	theValue = theSplit[0]
	theFrame = theSplit[1]
	theAttribute = theSplit[2]
	theName = theSplit[3]
	mc.setKeyframe( theName, v=float(theValue), at=theAttribute, t =float(theFrame))
	count +=1
myFileObject.close()

Python – round, limit decimal places

pi = 3.14159265

print(pi)
# Result: 3.14159265 #

print("%.2f" % pi)
# Result: 3.14 #

round(pi,3)
# Result: 3.142 # 

print("%.1f" % round(pi,0))
# Result: 3.0 #