Lux Render

March 6th, 2010
LuxRender using Mirror and Gold Metal Materials

LuxRender using Mirror and Gold Metal Materials

First LuxRender

I just tried out a FOSS renderer called LuxRender I recently got some new hardware and wanted to flex its cores and it seems that LuxRender is the perfect platform for it.

Here is the blurb from thier website:

LuxRender is based on PBRT, the unbiased raytracer developed by Matt Pharr and Greg Humphreys for academic use. Pharr and Humphreys were kind enough to provide the source code of their program under the terms of the GPL, thus making the program free software.

In 2007, a small group of programmers led by Terrence Vergauwen took on the challenge to modify the program and make it suitable for artistic use. Late 2007, the initial version of LuxRender was released. With the release of LuxRender 0.5 in June 2008, the program was considered to be usable enough for general use. Since then, the rendering speed and the number of features and available exporters has been growing steadily.

Hopefully I will get some time to make some shiny bling and look into an unbiased brutforce renderer.

In the meantime check out ioxu industries, Ben has done some sweet LuxRender renders over there and given he sits at the neighbouring desk at work, I can probably pick his brain for some ideas

Update: I made some shiny bling

Shiny Bling made in Lux Render after 60 minutes of playtime

Shiny Bling made in Lux Render after 60 minutes of playtime


More Lux Render Experiements

More Lux Render Experiements

Maya Python Script : Control Point and Vertex Colour and Massive confusion

January 16th, 2010

controlpoints1

I think I may have just found my answer that the control points are not points but face points

Like the difference between samples and points in Softimage.

I have never like the term texture verts or face normals, the term samples is a lot easier to swallow and less likely to confuse

But in the event I give up and ask for help on a forum but I will publish my foolish attempt below

  1. Created a grid
  2. Covered with locators
  3. Added a RGB map
  4. Linked the height of the locators to the RGB map R value
  5. Curse at the cruelty of the world
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
"""
 
import os,sys,maya
 
devFolder = "/home/samh/dev"
 
if devFolder not in sys.path:
	sys.path.insert(0,devFolder)
	print "Setting up dev environment for first time"
else:
	print "Dev environment setup"
 
import paintHeights
reload(paintHeights)
 
maya.cmds.file(new=True,force=True)
paintHeights.makePaintableLocators()
 
"""
import maya
 
def makePaintableLocators(numWidth=10,numBreadth=10,width=10,height=0.5,breadth=10):
	gridTrans= maya.cmds.polyPlane(constructionHistory=False,o=True,width=width,height=breadth,sw=numWidth,sh=numBreadth,cuv=2)
	gridShape = maya.cmds.listRelatives(shapes=True)[0]
 
 
	polyE = maya.cmds.polyEvaluate()
 
	#print "Mesh Details: ", polyE
 
	count = polyE["vertex"]
 
 
	#print "Hoopla",count
	#print maya.cmds.getAttr("%s.controlPoints" % gridShape)
 
 
 
	positions = [maya.cmds.getAttr("%s.vt[%d]" % (gridShape,i) )[0] for i in range(count)]
	#print "Positions: " , positions
	locators = ["%s" % maya.cmds.spaceLocator(position=(0,0,0))[0] for i in range(count)]
 
	[maya.cmds.setAttr("%s.translateX" % locators[i],positions[i][0]) for i in range(count)]
	[maya.cmds.setAttr("%s.translateY" % locators[i],positions[i][1]) for i in range(count)]
	[maya.cmds.setAttr("%s.translateZ" % locators[i],positions[i][2]) for i in range(count)]
	[maya.cmds.setAttr("%s.template"%i,True) for i in locators]
	maya.cmds.select(gridShape)
	colourSet = maya.cmds.polyColorSet(create=True,colorSet="heightField",newColorSet="heightField")[0]
	heights = [maya.cmds.getAttr("%s.colorSet[0].colorSetPoints[%s]" % (gridShape,i)) for i in range(count)]
	#print "Initial Heights: ", heights
 
	maya.cmds.polyColorPerVertex(rgb=(0.5,0.5,0.5),cdo=True)
	heightsNew = [maya.cmds.getAttr("%s.colorSet[0].colorSetPoints[%s]" % (gridShape,i)) for i in range(count)]
 
 
 
 
	#print "Heights New: ", heightsNew
	expressions = ["%s.translateY=(%s.colorSet[0].colorSetPoints[%s].colorSetPointsR - 0.5) * %f" % (locators[i], gridShape,i,height) for i in range(count)]
	#expressions = ["%s.translateY=(%s.colorPerVertex.vertexColor[%s].vertexColorRGB.vertexColorR) * %f" % (locators[i], gridShape,i,height) for i in range(count)]
 
	#values =[maya.cmds.getAttr("%s.colorPerVertex.vertexColor[%s].vertexColorRGB.vertexColorR" % (gridShape,i)) for i in range(count)]
 
 
	#print values
 
	[maya.cmds.expression(string = i) for i in expressions]
 
	return

This must be a bug, here are the repro steps

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
"""
 
import os,sys,maya
 
devFolder = "/home/samh/dev"
 
if devFolder not in sys.path:
	sys.path.insert(0,devFolder)
	print "Setting up dev environment for first time"
else:
	print "Dev environment setup"
 
import paintHeights
reload(paintHeights)
 
maya.cmds.file(new=True,force=True)
paintHeights.makePaintableLocators()
 
"""
import maya
 
def makePaintableLocators(numWidth=10,numBreadth=10,width=10,height=10,breadth=10):
	gridTrans= maya.cmds.polyPlane(constructionHistory=False,o=2	,width=width,height=breadth,sw=numWidth,sh=numBreadth,cuv=2)
	gridShape = maya.cmds.listRelatives(shapes=True)[0]
	polyE = maya.cmds.polyEvaluate()
	count = polyE["vertex"]
	positions = [maya.cmds.getAttr("%s.vt[%d]" % (gridShape,i) )[0] for i in range(count)]
	locators = ["%s" % maya.cmds.spaceLocator(position=(0,0,0))[0] for i in range(count)]
	[maya.cmds.setAttr("%s.translateX" % locators[i],positions[i][0]) for i in range(count)]
	[maya.cmds.setAttr("%s.translateY" % locators[i],positions[i][1]) for i in range(count)]
	[maya.cmds.setAttr("%s.translateZ" % locators[i],positions[i][2]) for i in range(count)]
	[maya.cmds.setAttr("%s.template" % locators[i],1) for i in range(count)]
	maya.cmds.select(gridShape)
	colourSet = maya.cmds.polyColorSet(create=True,colorSet="heightField",newColorSet="heightField")[0]
	heights = [maya.cmds.getAttr("%s.colorSet[0].colorSetPoints[%s]" % (gridShape,i)) for i in range(count)]
	maya.cmds.polyColorPerVertex(rgb=(0.5,0.5,0.5),cdo=True)
	heightsNew = [maya.cmds.getAttr("%s.colorSet[0].colorSetPoints[%s]" % (gridShape,i)) for i in range(count)]
	a = [maya.cmds.setAttr("%s.colorSet[0].colorSetPoints[%s].colorSetPointsR" % (gridShape,i),0.5) for i in range(count*40)]
	expressions = ["%s.translateY=(%s.colorSet[0].colorSetPoints[%s].colorSetPointsR - 0.5) * %f" % (locators[i], gridShape,i,height) for i in range(count)]
	[maya.cmds.expression(string = i) for i in expressions]
	return

Maya Python, Toward a Feather system

January 12th, 2010
First instancing code as plugin

First instancing code as plugin

This takes the in mesh and duplicates it and shuffles it around.

Its just a glorified instancer at the moment

I am trying to get the seed and random attributes on the outside of the code rather than the inside, but they wont budge

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#Sam Hodge's Lame Scripted Plugin
 
"""
#TEST turn a pipe into a cube
import os
import maya
 
 
devPath = "/home/samh/dev/scales/scratch"
 
maya.cmds.file(new=True,force=True)
 
for i in os.environ:
	if "MAYA" and "PLUG" in i:
		if devPath not in os.environ[i]:
			os.environ[i] =  "%s:%s" % (devPath ,os.environ[i])
			print "Setup Dev: %s : %s" % (i,os.environ[i])
		print "Settings: %s : %s" % (i,os.environ[i])
 
maya.cmds.unloadPlugin("duplicator.py")
maya.cmds.loadPlugin("duplicator.py")
 
 
 
cubeTrans = maya.cmds.polyCube(ch=0,o=1,w=0.1,h=0.1,d=0.1,sx=4,sy=4,sz=4,cuv=4)[0]
maya.cmds.createNode("shDuplicator")
pipeTrans = maya.cmds.polyPipe(ch=0,o=1,r=10.80581,h=22.165043)[0]
maya.cmds.connectAttr("pCubeShape1.outMesh","shDuplicator1.inputMesh",force=True)
maya.cmds.connectAttr("shDuplicator1.outputMesh","pPipeShape1.inMesh",force=True)
"""
 
 
import sys
import random
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
 
kPluginNodeName = "shDuplicator"
kPluginNodeId = OpenMaya.MTypeId(0x8700B)
 
class meshReplicator(OpenMayaMPx.MPxNode):
	inputMesh = OpenMaya.MObject()
	outputMesh = OpenMaya.MObject()
	seed = OpenMaya.MObject()
	count = OpenMaya.MObject()
 
	def __init__(self):
		OpenMayaMPx.MPxNode.__init__(self)
 
	def dupeMesh(self, inMesh, outData, count, seed):
 
 
		oldStuff = False
 
		meshFS = OpenMaya.MFnMesh()		
		if oldStuff:
			OpenMaya.MFnMesh().copy(inMesh,outData)		
		else:
			OpenMaya.MFnMesh().copy(inMesh,outData)		
 
			#transform = OpenMaya.
			meshFS = OpenMaya.MFnMesh(inMesh)
 
			oriVertCount = meshFS.numVertices()
 
			oriPolyCount = meshFS.numPolygons()
 
			oriPointArray = OpenMaya.MFloatPointArray()
 
			meshFS.getPoints(oriPointArray,OpenMaya.MSpace.kObject)
 
			oriPolyCounts = OpenMaya.MIntArray()
			oriPolyConnections = OpenMaya.MIntArray()
 
			meshFS.getVertices(oriPolyCounts, oriPolyConnections)
 
			outVertCount = oriVertCount * count
			outPolyCount = oriPolyCount * count
 
 
			oriPointArrayList = [OpenMaya.MPoint() for i in range(oriPointArray.length())]
 
			[meshFS.getPoint(i,oriPointArrayList[i],OpenMaya.MSpace.kObject) for i in range(oriPointArray.length())]
 
 
 
			locationArray = OpenMaya.MVectorArray()
			locationArray.setLength(count)
 
			random.seed(seed)
 
			#This will come from UV + N + mesh = Transform similar to a follicle
 
			[locationArray.set(OpenMaya.MVector(random.random(),random.random(),random.random()),i) for i in range(locationArray.length())]
 
			transOffset = OpenMaya.MTransformationMatrix()
 
 
			TransformArrayList = [OpenMaya.MTransformationMatrix() for i in range(locationArray.length())]
			[TransformArrayList[i].setTranslation(locationArray[i],OpenMaya.MSpace.kWorld) for i in range(locationArray.length())]
 
			MatrixList = [i.asMatrix() for i in TransformArrayList]
 
 
 
			FloatMatrixList = [OpenMaya.MFloatMatrix(i.matrix) for i in MatrixList]		
 
			transposeM = FloatMatrixList[0]
 
 
 
 
			outPointArray = OpenMaya.MFloatPointArray()
 
			oriFloatPointList = [oriPointArray[i] for i in range(oriPointArray.length())] #[OpenMaya.MFloatVector(i) for i in oriPointArrayList]			
 
 
 
			outPointArrayList = []
 
			[outPointArrayList.extend([ j*i for j in oriFloatPointList]) for i in FloatMatrixList]
 
 
			transVec = OpenMaya.MFloatVector(transposeM(3,0),transposeM(3,1),transposeM(3,2))			
 
			tmpTX = oriFloatPointList[0]*FloatMatrixList[0]
 
			outPointArrayList = [OpenMaya.MFloatPoint(i) for i in outPointArrayList]
 
			[outPointArray.append(outPointArrayList[i]) for i in range(len(outPointArrayList))]
 
 
			oriPolyCountsList = [oriPolyCounts[i] for i in range(oriPolyCounts.length())] * count
			outPolyCounts = OpenMaya.MIntArray()
			[outPolyCounts.append(i) for i in oriPolyCountsList]
 
			oriPolyConnectionsList = [oriPolyConnections[i] for i in range(oriPolyConnections.length())]
 
			outPolyConnectionsList = []
 
 
 
			[outPolyConnectionsList.extend([j + (i * oriVertCount) for j in oriPolyConnectionsList]) for i in range(count)]
			outPolyConnections=OpenMaya.MIntArray()
			[outPolyConnections.append(i) for i in outPolyConnectionsList]
			debug = False
			if debug:
				print ("Vert Count : %s"  % outVertCount)
				print ("Poly Count : %s"  % outVertCount)
				print ("PolyCounts : %s"  % outPolyCounts)
				print ("PointPosCounts : %s"  % ",".join(["%2.2e %2.2e %2.2e" % (outPointArray[i].x, outPointArray[i].y, outPointArray[i].z) for i in range(outPointArray.length())]))
				print ("PolyCounnection : %s"  % outPolyConnectionsList)
 
			meshFS2 = OpenMaya.MFnMesh()
 
 
 
 
			meshFS2.create(outVertCount, outPolyCount,outPointArray,outPolyCounts,outPolyConnections, outData)
 
		return meshFS
 
	def compute(self, plug, data):
		if plug == meshReplicator.outputMesh:
			inputData = data.inputValue(meshReplicator.inputMesh)
			inMesh = inputData.data()
 
			inputSeed = data.inputValue(meshReplicator.seed)
			inSeed = inputSeed.asInt()
 
			inputCount = data.inputValue(meshReplicator.count)
			inCount = inputCount.asInt()
 
			outputHandle = data.outputValue(meshReplicator.outputMesh)
 
			dataCreator = OpenMaya.MFnMeshData()
			newOutputData = dataCreator.create()
 
 
			self.dupeMesh(inMesh, newOutputData,5000,69)
			outputHandle.setMObject(newOutputData)
			data.setClean(plug)
		else:
			return OpenMaya.kUnknownParameter
 
def nodeCreator():
	return OpenMayaMPx.asMPxPtr( meshReplicator() )
 
def nodeInitializer():
	inTypedAttr = OpenMaya.MFnTypedAttribute()
	outTypedAttr = OpenMaya.MFnTypedAttribute()
 
	countNumericAttr = OpenMaya.MFnNumericAttribute()
 
	seedNumericAttr = OpenMaya.MFnNumericAttribute()
 
	meshReplicator.inputMesh = inTypedAttr.create("inputMesh", "in", OpenMaya.MFnData.kMesh)
	meshReplicator.outputMesh = outTypedAttr.create("outputMesh", "out", OpenMaya.MFnData.kMesh)
 
	meshReplicator.seed = seedNumericAttr.create("seedRand","seed",OpenMaya.MFnNumericData.kInt)
	seedNumericAttr.setDefault(1337)
	seedNumericAttr.setKeyable(True)
 
	meshReplicator.count = countNumericAttr.create("countInst","count",OpenMaya.MFnNumericData.kInt)
	countNumericAttr.setDefault(50)
	countNumericAttr.setKeyable(True)
 
 
	#seedNumericAttr.setWritable(True)
	#seedNumericAttr.setReadable(True)
    #seedNumericAttr.setKeyable(True)
	#countNumericAttr.setKeyable(True)
 
	meshReplicator.addAttribute(meshReplicator.inputMesh)
	meshReplicator.addAttribute(meshReplicator.outputMesh)
 
	meshReplicator.attributeAffects(meshReplicator.inputMesh, meshReplicator.outputMesh)
 
 
# initialize the script plug-in
def initializePlugin(mobject):
	mplugin = OpenMayaMPx.MFnPlugin(mobject)
	try:
		mplugin.registerNode( kPluginNodeName, kPluginNodeId, nodeCreator, nodeInitializer)
	except:
		sys.stderr.write( "Failed to register node: %s" % kPluginNodeName )
		raise
 
# uninitialize the script plug-in
def uninitializePlugin(mobject):
	mplugin = OpenMayaMPx.MFnPlugin(mobject)
	try:
		mplugin.deregisterNode( kPluginNodeId )
	except:
		sys.stderr.write( "Failed to deregister node: %s" % kPluginNodeName )
		raise

Maya Python API Learning Example, inMesh -> outMesh

January 10th, 2010

I made my first attempt at playing with the Maya API using Python as my C++ is still too sketchy, and doing stuff in python is far quicker, no need to reload Maya.

Anyway the example is lifted from the animCubeNode.py from the maya dev kit

I just added a new input plug.

The intention is to add three mesh inputs, and output a final mesh using thier properties as a feather/scale system:

  1. feather/scale geo mesh, to define shape of scales geometry
  2. skin mesh, to define UV, P and N
  3. feather layout mesh, to define a vert for each quill, in proximity to the skin mesh

This way you can simply use mesh editing tools to determine a placement of feathers and scales. I am still n00bing it up for now, but the maths should be fairly straight forward, cross products and barycentric coordinates should be as hardcore as it gets for now.

Adding a few mappable inputs should get interesting to control: scale and rotation.

Anyway this is the first step, if I do it outside of working hours it will appear here.

here are some links that helped me out on the learning curve:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#Sam Hodge's Lame Scripted Plugin
 
"""
#TEST turn a pipe into a cube
import os
import maya
 
 
devPath = "/home/samh/dev"
 
maya.cmds.file(new=True,force=True)
 
for i in os.environ:
	if "MAYA" and "PLUG" in i:
		if devPath not in os.environ[i]:
			os.environ[i] =  "%s:%s" % (devPath ,os.environ[i])
			print "Setup Dev: %s : %s" % (i,os.environ[i])
		print "Settings: %s : %s" % (i,os.environ[i])
 
maya.cmds.unloadPlugin("duplicator.py")
maya.cmds.loadPlugin("duplicator.py")
 
 
 
cubeTrans = maya.cmds.polyCube(ch=0,o=1,w=12.380629,h=9.432578,d=7.009036,cuv=4)[0]
maya.cmds.createNode("shDuplicator")
pipeTrans = maya.cmds.polyPipe(ch=0,o=1,r=10.80581,h=22.165043)[0]
maya.cmds.connectAttr("pCubeShape1.outMesh","shDuplicator1.inputMesh",force=True)
maya.cmds.connectAttr("shDuplicator1.outputMesh","pPipeShape1.inMesh",force=True)
"""
 
 
import sys
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
 
kPluginNodeName = "shDuplicator"
kPluginNodeId = OpenMaya.MTypeId(0x8700B)
 
class meshReplicator(OpenMayaMPx.MPxNode):
	inputMesh = OpenMaya.MObject()
	outputMesh = OpenMaya.MObject()
 
	def __init__(self):
		OpenMayaMPx.MPxNode.__init__(self)
 
	def dupeMesh(self, inMesh, outData):
		OpenMaya.MFnMesh().copy(inMesh,outData)
		meshFS = OpenMaya.MFnMesh(inMesh)
		#Comment this out to hush the noise
		sys.stderr.write("Edge Count :" + repr(meshFS.numEdges())+"\n")
		sys.stderr.write("Vert Count :" + repr(meshFS.numVertices())+"\n")
		sys.stderr.write("Poly Count :" + repr(meshFS.numPolygons())+"\n")
		return meshFS
 
	def compute(self, plug, data):
		if plug == meshReplicator.outputMesh:
			inputData = data.inputValue(meshReplicator.inputMesh)
			inMesh = inputData.data()
 
 
			sys.stderr.write(inMesh.apiTypeStr() + "\n")
			outputHandle = data.outputValue(meshReplicator.outputMesh)
 
 
			dataCreator = OpenMaya.MFnMeshData()
			newOutputData = dataCreator.create()
 
			self.dupeMesh(inMesh, newOutputData)
			outputHandle.setMObject(newOutputData)
			data.setClean(plug)
		else:
			return OpenMaya.kUnknownParameter
 
def nodeCreator():
	return OpenMayaMPx.asMPxPtr( meshReplicator() )
 
def nodeInitializer():
	inTypedAttr = OpenMaya.MFnTypedAttribute()
	outTypedAttr = OpenMaya.MFnTypedAttribute()
 
	meshReplicator.inputMesh = inTypedAttr.create("inputMesh", "in", OpenMaya.MFnData.kMesh)
	meshReplicator.outputMesh = outTypedAttr.create("outputMesh", "out", OpenMaya.MFnData.kMesh)
 
	meshReplicator.addAttribute(meshReplicator.inputMesh)
	meshReplicator.addAttribute(meshReplicator.outputMesh)
 
	meshReplicator.attributeAffects(meshReplicator.inputMesh, meshReplicator.outputMesh)
 
 
# initialize the script plug-in
def initializePlugin(mobject):
	mplugin = OpenMayaMPx.MFnPlugin(mobject)
	try:
		mplugin.registerNode( kPluginNodeName, kPluginNodeId, nodeCreator, nodeInitializer)
	except:
		sys.stderr.write( "Failed to register node: %s" % kPluginNodeName )
		raise
 
# uninitialize the script plug-in
def uninitializePlugin(mobject):
	mplugin = OpenMayaMPx.MFnPlugin(mobject)
	try:
		mplugin.deregisterNode( kPluginNodeId )
	except:
		sys.stderr.write( "Failed to deregister node: %s" % kPluginNodeName )
		raise

Home Sweet Home : Back to Australia (soon) !!!

November 9th, 2009

nofrontfence

Well I have been here in Wellington since early July and its nearly time to go home. Just a couple of more weeks and the experience of working at Weta Digital will be behind me. There have been some highs and some lows. If I had my time over I would probably do it again. But right now I am happy to finish the chapter and come home and spend some time with my family, our pets in the family home.

I will be home on the 28th, which cooincidentally is the date of the wrap party, that was poorly planned but being back in my own bed after 5 months of absence will be the best wrap party of all for me.

Working Abroad

August 22nd, 2009

I just realised that I havent blogged in a while.

As a kid my Dad worked aboard in Algeria in a small community of Ksar Chellala


View Larger Map

And while he was away the only way could communicate was via a very expensive and unreliable telephone service.

Or via audio, with a 3 week latency.

We would record our voices onto an audio cassette, put it in the snail mail and send it to Algeria.

Most of the it would get there and our father would be able to hear his three kids’ voices.

I hope that dad treasured those tapes like gold, that would have been back in 1978 and 1979. It would be interesting to listen to them in retrospect.

We made the trip over and travelled around Europe and Northern Africa.

If you wind the clock forward a generation and about 30 years.

Now Maia my daughter can communicate via audio and video with a 200 millisecond latency, I call without fail and catch up on whats happening in Anna and Maia’s daily life back home.

Because of this technology I dont really feel so isolate from my roots in Adelaide, Anna and Maia have also made the trip across the ditch at roughly the same age, not the same as Europe, but still eye opening.

They will be back in four weeks and there is no substitute for holding the one you love in your arms and looking them in the eye.

Wellington is pretty nice and the work is good.

The whole Avatar day thing yesterday was a bit of a buzz and it was good to catchup with buddies in Wellington.

I caught up with Phil B, Heidi B, David A, Caroline A, Stevil, , Ben C, James F, Chloe, Daryl M at the Tasting Rooms on Courney Place. It was like an old school reunion

I better get back to work.

Wellington NZ

July 24th, 2009

We are here in Wellington, here are some photos that Anna put up of us around the place

http://picasaweb.google.com/pipika71

I am working at Weta until late November.

SALA work complete tonight!

June 30th, 2009

after weeks of cutting stencils with precision, a windy night and poor lighting and poor workmanship have left my artwork for SALA not quite matching my expectations in my mind

at least I can resuse the stencils and have another go

But not before I leave for New Zealand

Sam

length of a curve in Maya

June 9th, 2009

I found a reasonable solutionhere:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//=================================
// curveLength v1.0 (08/2004)
// by Edvard Toth
// 
// The script is freeware. Non-commercial redistribution is permitted as long as this header remains included and unmodified.
// Your feedback is always appreciated - if you find the script useful or if you have questions, comments, suggestions, requests, 
// bug-reports, if you created an updated version, to check for updates or to make a donation please contact me at:
//
// http://www.edvardtoth.com
// 
//==================================
// INSTALLATION: Copy the script into your Maya script-directory and start it with the curveLength; command.
//
// COMPATIBILITY NOTE: Tested with Maya 4.0 - 4.5 - 5.0 - 6.0 - 7.0
//
// DESCRIPTION:
// This tiny but very straightforward utility measures the length of a curve without all the hassle that comes with 
// using Maya's implementation of the "Arc Length Tool".
//
 
global proc curveLength ()
{
 
string $CL_curve[] = `ls -sl`;
 
	if (size($CL_curve[0]) == 0)
    {
	confirmDialog -t "Oops..." -m "Please select a valid curve." -b Continue;
	return;
	}
 
	string $CL_curvea[] = `ls -l $CL_curve[0]`;
	string $CL_curveb[] = `listRelatives -f -ni -s $CL_curvea[0]`;
 
	if (nodeType($CL_curveb[0])!="nurbsCurve")
    {
	confirmDialog -t "Oops..." -m "Please select a valid curve." -b Continue;
	return;
	}    
 
        int $CL_spans = `getAttr ($CL_curve[0] + ".spans")`;
 
        string $CL_arclengthnode = `arcLengthDimension ($CL_curve[0] + ".u[" + $CL_spans + "]")`;
        string $CL_nodeparent[] = `listRelatives -p $CL_arclengthnode`;
 
        float $CL_curvelength = `getAttr ($CL_arclengthnode + ".al")`;
 
        delete $CL_nodeparent;
 
        confirmDialog -t $CL_curve[0] -m ("curvelength:  " + $CL_curvelength) -b OK;    
}

but since I hate Mel I have ported it to python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
def lengthOfCurve(dagPathToCurve):
	"""
	Assume that the Shape path is given, error checking is for upstream
	"""
	import maya
	numSpans = maya.cmds.getAttr("%s.spans" % dagPathToCurve)
	arcLengthTemp= maya.cmds.arcLengthDimension("%s.u[%s]" % (dagPathToCurve,numSpans))
 
	nodeParent = maya.cmds.listRelatives(arcLengthTemp,parent=True)
	curveLength = maya.cmds.getAttr ("%s.al" % arcLengthTemp)
	maya.cmds.delete(nodeParent)
	return curveLength
 
 
for i in maya.cmds.ls(selection=True):
	shapeNodes = maya.cmds.listRelatives(i,shapes=True)
	for shape in shapeNodes:
		if maya.cmds.nodeType(shape) == "nurbsCurve":
			print "Curve: %s is %s units long" % (shape, lengthOfCurve(shape))
		else:
			print "Wrong: %s is a %s" % (shape, maya.cmds.nodeType(shape))

As Nick so rightly pointed out the following makes a lot more sense

sometimes rtfm > google

arclen docs

1
2
3
4
5
6
7
8
9
import maya
 
for i in maya.cmds.ls(selection=True):
	shapeNodes = maya.cmds.listRelatives(i,shapes=True)
	for shape in shapeNodes:
		if maya.cmds.nodeType(shape) == "nurbsCurve":
			print "Curve: %s is %s units long" % (shape, arcLen(shape,constuctionHistory=False))
		else:
			print "Wrong: %s is a %s" % (shape, maya.cmds.nodeType(shape))

RSP Talks at Conjecture 2009 (previously known as Phantom)

June 8th, 2009

On Sunday, at 11:30 in the morning I presented to a group of about 30 hardcore sci fi fans about the visual effect production process.

It was basically a matter of telling the audience what goes into making visual effects, from the business, direction and technical.

They seemed to be fairly interested.

Overall I could have paced myself a bit better, but I probably could have played the reel for an hour and they would have been happy with that too