Hi all
Really should get a bit more active on here! Figure I’m going to start putting more stuff up for open critique so I can get better. My knowledge is pretty functional, and I’m now getting pretty comfortable with python but I wonder if I’m picking up a lot of bad habits and I’m sure I can be so much more efficient!
So here’s a starter.
One of our lighting guys wanted to be able to generate Area Lights per polygon of his selected object, and have the area lights match up the size of the polygon.
Here’s a quick vid of it working
Cheers
Luke
from maya import cmds
import math
#CREATES AREA LIGHTS THAT MATCHES POLYGONS
#GET FACES
def areaLightFaceMatch( sel = cmds.ls(selection = True) ):
for face in sel: #If faces are in slice we'll iterate through those
if ':' in face:
faceShape = face.split('.f')[0] #Get object shape name
faceNums = face.split( '[' )[-1]
faceNums = faceNums.split( ']' )[0]
sRange = int(faceNums.split(':')[0]) # Start Range
eRange = int(faceNums.split(':')[-1]) # end Range
i = sRange
while i <= eRange:
faceAreaLight('{0}.f[{1}]'.format(faceShape, i))
i += 1
else:
faceAreaLight( face )
def faceAreaLight( inFace = '' ):
#Query face positions
faceLocation = cmds.xform(inFace, query = True, translation = True, worldSpace = True)
#Calculate centre point of face
avX = 0
avY = 0
avZ = 0
numVerts = 0
i = 0
while i < len(faceLocation):
avX += faceLocation[i]
avY += faceLocation[i+1]
avZ += faceLocation[i+2]
i += 3
numVerts += 1
avX /= numVerts
avY /= numVerts
avZ /= numVerts
faceCentre = [avX, avY, avZ]
#Query face normal
faceNormalQuery = cmds.polyInfo( inFace, faceNormals = True )
faceNormal = faceNormalQuery[0].split()[2:]
#Place locators for aim constraint (angle of Light)
#We want it to face outwards (normal based) so we create a Target locator off the face's normal
#and an Up Vector locator at the averate point of one of the edges
locTarget = cmds.createNode( 'locator' )
cmds.move( faceCentre[0] + float(faceNormal[0]),
faceCentre[1] + float(faceNormal[1]),
faceCentre[2] + float(faceNormal[2]),
cmds.listRelatives(locTarget, parent = True)[0] )
locUpVector = cmds.createNode( 'locator' )
cmds.move( (faceLocation[0] + faceLocation[3]) / 2,
(faceLocation[1] + faceLocation[4]) / 2,
(faceLocation[2] + faceLocation[5]) / 2,
cmds.listRelatives(locUpVector, parent=True)[0] )
newLight = cmds.createNode( 'areaLight' )
newLightTransform = cmds.listRelatives(newLight, parent = True)[0]
cmds.move( faceCentre[0], faceCentre[1], faceCentre[2], newLightTransform )
#Create the aim constraint to angle the light, ensuring that maintain offset is turned off (we want it to rotate)
aimConstraint = cmds.aimConstraint( cmds.listRelatives(locTarget, parent = True)[0],
newLightTransform,
aimVector = ( 0, 0, -1.0 ),
upVector = ( 0, -1.0, 0 ),
worldUpType = 'object',
worldUpObject = cmds.listRelatives(locUpVector, parent = True)[0],
mo = False )
#SCALE CALCULATIONS
#We need to scale the light so it matches the polygon.
#To do this I'm calculating the length of two vectors, from vert 0 to vert 1, and vert 0 to vert 2 (across and up the face)
vX = (faceLocation[0] - faceLocation[3], faceLocation[1] - faceLocation[4], faceLocation[2] - faceLocation[5])
magnitudeX = math.sqrt( (vX[0] * vX[0]) + (vX[1] * vX[1]) + (vX[2] * vX[2]) )
vY = (faceLocation[0] - faceLocation[6], faceLocation[1] - faceLocation[7], faceLocation[2] - faceLocation[8])
magnitudeY = math.sqrt( (vY[0] * vY[0]) + (vY[1] * vY[1]) + (vY[2] * vY[2]) )
#I then plug in the vector's magnitudes into the scale attribute directly
#(but by half as the area light is already in the centre of the face)
cmds.setAttr( '{0}.scaleX'.format(newLightTransform), magnitudeX * 0.5 )
cmds.setAttr( '{0}.scaleY'.format(newLightTransform), magnitudeY * 0.5 )
cmds.setAttr( '{0}.scaleZ'.format(newLightTransform), 30 )
#Then we can remove the locators and aim constraint
cmds.delete( aimConstraint )
cmds.delete( cmds.listRelatives(locTarget, parent = True)[0] )
cmds.delete( cmds.listRelatives(locUpVector, parent = True)[0] )