Archive for January, 2010

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

Saturday, 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

Tuesday, January 12th, 2010

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

Sunday, 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