Music Videos produced in Bangkok

Posted by on Jun 21, 2014 in animation, modeling, photography, Video | No Comments

A couple of music videos produced with EPYX Productions. I did the photography and VFX.

Music videos produced in Bangkok, Thailand. Hong Hoon was created to support the feature horror film Hong Hoon starring Ananda Everingham. Alone was a music video for an up and coming Thai hard rock band called System Sucker.

Opening a newer version Maya file in an older version of Maya

Posted by on Jan 9, 2013 in animation, Maya | No Comments

A common issue when using AW Maya is trying to open a file that was created in a newer version of Maya than your installed version. Maya files are not backwards compatible, in my experience. There are two ways that I know of to deal with this. One is to simply select “Ignore Version” in the File->Open dialog. I tried this today and it failed, Maya crashed. Another option, which did work for me, is to save the newer version file as an ASCII file (, and edit the file’s data manually. This is very simple to do. You will need to have access to the newer version of Maya to accomplish this though, or have your collaborator deliver an ASCII version of the file. Once you have the ASCII file, do the following things:

1) Save a dummy ASCII file from your older version of Maya (ex: so that you can see the older format file’s data. For safety, make a copy of your “Newer Version” file, as you will be editing the code directly.

2) open both files side by side examine the “headers”, the top portion of each file. You will note a similarity in the first 10 – 15 lines of data. I am using a Mac, so examining the files, the last line I see in what I would call header information is: fileInfo "osv" "Mac OS X 10.8.2";. After this there is a “createNode” Maya command, that I don’t want to disturb. It’s slightly different from one file to another and one version to another, but only slightly. You will have no trouble figuring out where to copy and where to paste. Copy this header data from the older version file and paste to the newer version file, overwriting the relevant code.

2) The file should now open in the older version of Maya. Of course any features of the newer version of Maya that are not available in the older version of Maya will not work in this opened scene (actually I’m not certain what happens in this scenario).

There may be other methods, but I am not aware.

colorAtPoint Maya command

Posted by on Apr 8, 2012 in animation, MEL | No Comments

Expressions for transforming nodes via pixel values.

string $cubes2[] = `ls -type transform "newCube*"`;
for( $each in $cubes2) {
float $u = `getAttr($each + ".translateX")`;
float $v = `getAttr($each + ".translateZ")`;
float $capValueF[] = `colorAtPoint -o RGB -u (($u+40)/80) -v (($v+40)/80) file1`;
setAttr ($each + ".scaleY") (($capValueF[0]+$capValueF[1]+$capValueF[2])*10);
setAttr ($each + "Lam.incandescenceR") $capValueF[0];
setAttr ($each + "Lam.incandescenceG") $capValueF[1];
setAttr ($each + "Lam.incandescenceB") $capValueF[2];

Maya Particle Instancing Experiment

Posted by on Oct 25, 2011 in animation, dynamics, Maya | No Comments

Maya Python script:

#Audio Driven Particle System 2011.10.27 A1
#Python for Maya
#Code By: Oliver Wolfson -
#You will need keyframes formatted in text files in an exclusive directory to make this work. See: 
# for more details

import os
import maya.cmds as mc

Light = mc.spotLight(ca=120, n="mySpotLight")
mc.setAttr( ("mySpotLightShape.useDepthMapShadows"), 1)
mc.setAttr( ("mySpotLightShape.dmapResolution"), 2048)
mc.setAttr( ("mySpotLightShape.dmapFilterSize"), 6)
mc.setAttr( ("mySpotLightShape.penumbraAngle"), 10)
mc.setAttr( ("mySpotLightShape.dropoff"), 1)
mc.setAttr( ("mySpotLight.translateX"), 125)
mc.setAttr( ("mySpotLight.translateY"), 100)
mc.setAttr( ("mySpotLight.translateZ"), 20)
mc.setAttr( ("mySpotLight.rotateX"), -33)
mc.setAttr( ("mySpotLight.rotateY"), 10)
mc.setAttr( ("mySpotLight.rotateZ"), -45)
mc.setAttr( ("mySpotLight.scaleX"), 30)
mc.setAttr( ("mySpotLight.scaleY"), 30)
mc.setAttr( ("mySpotLight.scaleZ"), 30)

num = 0
for p in range(0, 64, 2):
    print("this is the " + str(num) + " num:" + str(p))
    num += 1
    Locator = mc.spaceLocator(n=("myLocator"+ str(num)))
    Shader = mc.shadingNode('blinn', asShader = True)
    mc.setAttr ((Shader+ ".glowIntensity"), .1)
    SG = mc.sets (renderable=True, noSurfaceShader=True, empty=True)
    mc.connectAttr((Shader +".outColor"), (SG + ".surfaceShader"))
    mc.setAttr((Shader + ".color"),0.203189, 0.252033, 0.57554)
    Plane = mc.polyPlane(h = 10, sw = 1, sh = 15, cuv = 2)
    mc.setAttr(str(Plane[0]) + ".rotateX", 90)
    mc.setAttr(str(Plane[0]) + ".scaleX", .25)
    mc.makeIdentity( apply=True )
    mc.hyperShade(assign = Shader)
    Emitter = mc.emitter (type = 'omni')
    Particles = mc.particle()
    mc.connectDynamic(Particles, em= Emitter )
    mc.setAttr((Particles[1] + ".lifespanMode"), 1)[0])

    Wave = mc.nonLinear( type= 'wave' )
    mc.setAttr((Wave[0] + ".wavelength"), .4)
    mc.setAttr((Wave[0] + "Handle.rotateZ"), 90)
    mc.setAttr((Wave[0] + "Handle.rotateY"), 50)
    mc.setAttr((Wave[0] + "Handle.translateY"), -7)
    mc.setAttr((Wave[0] + "Handle.translateZ"), 11)
    mc.makeIdentity( apply=True )
    mc.particleInstancer( Particles[1], addObject = True, object = Plane[0], cycle='None', cycleStep=1, cycleStepUnits='Frames', levelOfDetail='Geometry', rotationUnits='Degrees', rotationOrder='XYZ', position='worldPosition', age='age')

    mc.expression ( s = Wave[0] + ".offset = " + Locator[0] + ".translateY/10;\n" + Wave[0] + ".amplitude = " + Locator[0] + ".translateY/10;\n" + Wave[0] + "Handle.rotateX = frame;\n" + Wave[0] + "Handle.rotateZ = " + Locator[0] +  ".translateY*0;\n" + Wave[0] + "Handle.scaleX =" + Locator[0] + ".translateY;\n"  + Wave[0] + "Handle.scaleY = " + Locator[0] + ".translateY;\n" + Wave[0] + "Handle.scaleZ = " +  Locator[0] + ".translateY;\n")
    mc.expression ( s = Emitter[0] + ".translateY = " + Locator[0] + ".translateY;\n" + Emitter[0] + ".rate = " + Locator[0] + ".translateY*20;\n" + Emitter[0] + ".speed = " + Locator[0] + ".translateY;\n")
    mc.expression ( s = Plane[0] + ".rotateY = " + Locator[0] + ".translateY*60;\n" + Plane[0] + ".translateY = " + Locator[0] + ".translateY;\n" + Plane[0] + ".scaleY = " + Locator[0] + ".translateY/;\n" + Plane[0] + ".rotateX = " + Locator[0] + ".translateY;\n")
    mc.expression ( s = Shader + ".incandescenceR =" + Locator[0] + ".translateY/200;\n" + Shader + ".incandescenceG = " + Locator[0] + ".translateY/200;\n" + Shader + ".incandescenceB = " + Locator[0] + ".translateY/100;"), add=True), add=True) , add=True) ("myGroup" + str(num)) )
    mc.setAttr("myGroup" + str(num) + ".translateZ", p*-10)
for l in range(1, 33, 1):"myLocator" + str(l)), add=True)

## add path to keyframe data files - just the source directory that contains them.
## "ty", in line 13, refers to the Maya attribute channel of the selected objects. Modify this attribute as necessary.
for subdir, dirs, files in os.walk(rootdir):
    for thisFile, o in zip(files, objs):
        file = open((os.path.join(rootdir, thisFile)), 'r')
        lines = file.readlines()
        for i in range(len(lines)):
            mc.setKeyframe(o, at='ty', v=float(lines[i]), t=i, itt='linear', ott='linear')

Use this information to build key data for this script

CG Rain Drops

Posted by on Dec 23, 2010 in animation, code, dynamics, Maya | No Comments

Splashes created in Real Flow, and instanced to Maya Particles.

Ripples created with a dynamic fluid texture.

float $colU = particleShape1.collisionU;
float $colV = particleShape1.collisionV;

if ($colU > 0) {
int $xpos = fluidTexture2DShape1.resolutionW * $colU;
int $ypos = fluidTexture2DShape1.resolutionH * $colV;
setFluidAttr -xi $xpos -yi $ypos -at density -ad -fv 0.6 fluidTexture2DShape1;

Create a Graphic EQ using SoundKeys and Maya

Posted by on Sep 26, 2010 in animation, code, Maya, MEL, python | 10 Comments

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.
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
		cube = = True)
		mc.setAttr((cubeName + '.translateY'), .5);
		mc.makeIdentity(apply=True, t =True, r=True, s=True, n= 0)
		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.sets( e=True, forceElement= myShader)
		count +=1
		## read keyframe data and set keyframes
		dataFile = open((os.path.join(rootdir, thisFile)), 'r')
		lines = dataFile.readlines()
		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()
myLines = lines[10:-4]
countLines = len(myLines)
mc.playbackOptions( minTime='0sec', maxTime=countLines)

Sample keyframe data, exported from After Effects.

White Light Group web teaser

Posted by on Aug 18, 2010 in animation, graphics, motion graphics | One Comment

Web teaser for White Light Group media company.

Red and Blue Chair

Posted by on Jun 13, 2010 in animation, Maya, modeling, rendering | No Comments
The Red Blue Chair was a chair designed in 1917 by Gerrit Rietveld. It represents one of the first explorations by the De Stijl art movement in three dimensions.


Maya and Mental Ray.

Model based on several models found on the 3D warehouse. Download an obj of the Red and Blue Chair.

More info from Wikipedia.

Shattering Glass Dynamic Simulation

Posted by on May 22, 2010 in animation, dynamics, Maya | No Comments

Maya rigid bodies and Mental Ray.

Load More