This is a snippet from my low poly tree generator written in python for Maya. The script generates, scatters, rigs, and animates a low poly scene.
import maya.cmds as cmds
import maya.mel as mel
import random
import math
import functools
import mtoa.utils as mutils
class WorldGen:
def __init__(self, pfx, iter):
self.pfx = pfx
self.iter = iter
def show(self):
self.createMyLayout()
def createMyLayout(self):
self.pfxUI = self.pfx[:-1]
if cmds.window("testUI", exists = True):
cmds.deleteUI("testUI")
self.window = cmds.window(title= "testUI", iconName = 'testUI', widthHeight = (500, 500))
cmds.columnLayout(adjustableColumn = True, columnAlign = "left", rowSpacing = 20)
self.clearScene = cmds.button(l = 'World_Clear', w = 300, h = 25, c = self.pfxUI + '.worldClear()')
self.terrain(None)
self.terrainSlider = cmds.intSliderGrp(l = 'Terrain_Seed', w = 300, h = 25,min = -50, max = 50, v = 0, s = 1, dc = 'empty')
cmds.intSliderGrp(self.terrainSlider, e = True, dc = functools.partial(self.terrain, self.terrainSlider))
self.genFunction = cmds.optionMenu(l = 'Select_Scattered_Obj')
cmds.menuItem(l = 'Trees')
cmds.menuItem(l = 'Reeds')
cmds.menuItem(l = 'Rocks')
self.scatterGenNum = cmds.intFieldGrp(l = 'Amount')
self.scatterZoneMin = cmds.floatFieldGrp(l = 'Scatter_Min', pre = 3)
self.scatterZoneMax = cmds.floatFieldGrp(l = 'Scatter_Max', pre = 3)
self.scatterButton = cmds.button(l = 'Scatter', w = 300, h = 25, c = self.scatter)
self.buildLights = cmds.button(l = 'Scene_Lights', w = 300, h = 25, c = self.buildLights)
cmds.showWindow(self.window)
def worldClear(self):
''' clears the scene '''
if cmds.objExists(self.pfx + '*'):
cmds.delete(self.pfx + '*')
mel.eval('hyperShadePanelMenuCommand("hyperShadePanel1", "deleteUnusedNodes");')
def getSliderValue(self,ctrlName):
value = cmds.intSliderGrp(ctrlName, q = 1, value = 1)
return value
def clamp(self, num, min, max): return min if num < min else max if num > max else num
def buildLights(self, *args):
''' builds an hdri dome '''
mutils.createLocator("aiSkyDomeLight", asLight = True)
cmds.rename('aiSkyDomeLight1', self.pfx + 'skyDome')
exr = cmds.shadingNode('file', asTexture = 1, isColorManaged = 1, n = self.pfx + 'skyDomeHDRI')
placeHDRI = cmds.shadingNode('place2dTexture', asUtility = 1)
self.project = cmds.workspace(q = 1, rd = 1)
self.hdriPath = cmds.fileDialog2(fileFilter = '*.exr', dir = self.project, cap = 'Select_HDRI')[0]
cmds.setAttr(exr + '.fileTextureName', self.hdriPath, type = 'string')
cmds.connectAttr(placeHDRI + '.outUV', exr + '.uvCoord', force = 1)
cmds.connectAttr(exr + '.outColor', self.pfx + 'skyDome.color')
def bottomPivot(self, object):
''' bottoms the pivot and snaps object to the origin '''
cmds.xform(object, cp=1)
boundingBox = cmds.xform(object, q = 1, bb = 1, ws = 1)
xMin, yMin, zMin, xMax, yMax, zMax = boundingBox
cmds.move(yMin, [object + '.scalePivot', object + '.rotatePivot'], y = 1, absolute = 1)
cmds.move(yMin*-1, object, r = 1, y = 1)
def squashDeform(self, object, sqMultiplier):
''' deforms an object'''
sqFactor = round(random.random()/sqMultiplier, 2)
sqFactor = sqFactor * -1
flFactorX = 1 + random.random()
flFactorZ = 1 + random.random()
cmds.select(object)
cmds.nonLinear(typ = 'squash', factor = sqFactor)
cmds.select(object)
cmds.nonLinear(typ = 'flare', startFlareX = flFactorX, startFlareZ = flFactorZ)
def unwrap(self, object):
cmds.select(object)
cmds.polyPlanarProjection(object + '.f[:]', md = 'x')
def shadeObj(self, object, name, rgb, randomArg, rampArg):
'''Assign shaders to object'''
if not cmds.objExists(name + '_SN*'):
shader = self.createShader(name + '_SN', rgb, randomArg, rampArg)
if randomArg:
pick = random.randint(0,4)
assignSurface = shader[pick]
else:
assignSurface = shader
else:
if randomArg:
pick = random.randint(0,4)
shader = name + '_SN_' + str(pick)
assignSurface = shader
else:
shader = name + '_SN'
assignSurface = shader
cmds.select(object)
cmds.hyperShade(a = assignSurface)
return assignSurface
def createShader(self, shaderName, rgb, randomArg, rampArg):
''' creates an Arnold shader'''
if randomArg:
shaderOptionsList = []
for i in range(0, 5):
surfaceNode = cmds.shadingNode('aiStandardSurface', asShader = 1, n = shaderName + '_' + str(i))
offsetRGB = random.uniform(-.010, .010)
rgb = [value + offsetRGB for value in rgb]
if rampArg:
ramp = cmds.shadingNode('ramp', asTexture = 1, n = shaderName + '_rampTx_' + str(i))
cmds.setAttr(ramp + '.colorEntryList[0].color', rgb[0], rgb[1], rgb[2])
cmds.setAttr(ramp + '.colorEntryList[1].color', self.clamp(rgb[0] - .150, 0.000, 1.000), self.clamp(rgb[1] - .150, 0.000, 1.000), self.clamp(rgb[2] - .150, 0.000, 1.000))
cmds.setAttr(ramp + '.colorEntryList[1].position', 1)
cmds.connectAttr(ramp + '.outColor', surfaceNode + '.baseColor')
else:
constantNode = cmds.shadingNode('colorConstant', asUtility = 1, n = shaderName + '_constant_' + str(i))
cmds.setAttr(constantNode + '.inColor', rgb[0], rgb[1], rgb[2])
cmds.connectAttr(constantNode + '.outColor', surfaceNode + '.baseColor')
cmds.setAttr(surfaceNode + '.specularRoughness', .65)
shaderOptionsList.append(surfaceNode)
return shaderOptionsList
else:
surfaceNode = cmds.shadingNode('aiStandardSurface', asShader = 1, n = shaderName)
if rampArg:
ramp = cmds.shadingNode('ramp', asTexture = 1, n = shaderName + '_rampTx')
cmds.setAttr(ramp + '.colorEntryList[0].color', rgb[0], rgb[1], rgb[2])
cmds.setAttr(ramp + '.colorEntryList[1].color', self.clamp(rgb[0] - .150, 0.000, 1.000), self.clamp(rgb[1] - .150, 0.000, 1.000), self.clamp(rgb[2] - .150, 0.000, 1.000))
cmds.setAttr(ramp + '.colorEntryList[1].position', 1)
cmds.connectAttr(ramp + '.outColor', surfaceNode + '.baseColor')
else:
constantNode = cmds.shadingNode('colorConstant', asUtility = 1, n = shaderName + '_constant')
cmds.setAttr(constantNode + '.inColor', rgb[0], rgb[1], rgb[2])
cmds.connectAttr(constantNode + '.outColor', surfaceNode + '.baseColor')
cmds.setAttr(surfaceNode + '.specularRoughness', .65)
return surfaceNode
def average(self, list):
sum = 0.000
for i in list:
sum += i
avg = round(sum / len(list), 3)
return avg
#---------------------------------------------------------------------------------------------------------
def leafGen(self, res, gName, pre):
'''generates a leaf clump'''
var = random.randint(10,15)
storeVar = var
rInnit = random.uniform(6.01, 7.01)
primaryClump = cmds.polySphere(n = pre + 'outLeaf_0', r = rInnit, sx = res, sy = res)
self.squashDeform(primaryClump, 2)
for i in range(0, storeVar):
radius = random.uniform(5.01, 6.50)
secClump = cmds.polySphere(n = 'leafClump {}'.format(i), r = radius, sx = res, sy = res)
boundingBox = cmds.xform(primaryClump, q =1, bb = 1, ws = 1)
boundingBox = [round(value, 2) for value in boundingBox]
xMinNew = boundingBox[0] / 1.25
xMinNew = boundingBox[3] / 1.25
yMinNew = boundingBox[1] * .5
yMaxNew = boundingBox[4] * .5
zMinNew = boundingBox[2] / 1.25
zMaxNew = boundingBox[5] / 1.25
posX = random.uniform(xMinNew, yMinNew)
posY = random.uniform(yMinNew, yMaxNew)
posZ = random.uniform(zMinNew, zMaxNew)
cmds.move(posX,posY,posZ)
self.squashDeform(secClump, 3)
cmds.select('leaf*')
cmds.rename(pre + 'outLeaf_1')
cmds.select(pre + 'outLeaf_*')
cmds.DeleteHistory()
cmds.select(pre + 'outLeaf_*')
group = cmds.group(n = gName)
return group
....