Same python code works differently on differently Maya (2012 - 2015)

513 views Asked by At

this simple code

import maya.cmds as cmd

circle1 = cmd.circle(nr=(0, 0, 1), c=(0, -1.1, 0), ch=1)
circle2 = cmd.duplicate(circle1[0], ic=1)
circle3 = cmd.duplicate(circle1[0], ic=1)
cmd.setAttr(circle2[0] + '.rotateZ', 120)
cmd.setAttr(circle3[0] + '.rotateZ', -120)

allCurves = circle1[0], circle2[0], circle3[0]
cmd.select(allCurves)
cmd.makeIdentity(apply=True, t=1, r=1, s=1, n=0)

works perfectly in Maya 2012, giving me this result:

enter image description here

Instead, in Maya 2015 the result of the same code is this:

enter image description here

All circles moves to the origin.

It seems the command cmd.makeIdentity work differently, but reading maya docs the command is the same. Also construction history settings are the same. I can't understand what Maya does behind the lines.

Why this lines of code works differently?

3

There are 3 answers

0
kartikg3 On BEST ANSWER

The real problem is because of a probable bug in the way the new Maya (2015) is performing preparations for makeIdentity when the nodes have shared history/connections/nodes (in this case the makeNurbCircle node). It seems to be creating interim transformGeometry nodes to compensate for the to-be frozen transforms in the wrong order in the chain. This wasn't the case in Maya 2012, when the order seems to be right. If you look at the comparison below, you'll see why.

2012 on the left; 2015 on the right: 2012 on the left; 2015 on the right

Either ways, if you want to preserve this shared history and do the freeze transform this way for whatever reason, you might have to manually do what makeIdentity attempts to, but in the cleaner way you want it to; i.e. connect up the transformGeometry nodes properly in the right order before manually freezing transformations on the transforms (using xform).

Here is something I just whipped up to do just that: (I will update the answer with comments and explanation when I find time later)

import maya.cmds as cmds


def makeIdentityCurvesWithSharedHistory(curves=[]):
    for curve in curves:
        curveShape = cmds.listRelatives(curve, shapes=True)[0]    
        makeCircle = cmds.listConnections(curveShape, type='makeNurbCircle')[0]
        transformation = cmds.xform(curve, q=True, matrix=True)    
        transformGeoNode = cmds.createNode('transformGeometry')
        cmds.setAttr('%s.transform' % transformGeoNode, transformation, type='matrix')
        cmds.connectAttr('%s.outputCurve' % makeCircle, '%s.inputGeometry' % transformGeoNode)
        cmds.connectAttr('%s.outputGeometry' % transformGeoNode, '%s.create' % curveShape, force=True)
        cmds.xform(curve, matrix=[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0])


circle1 = cmd.circle(nr=(0, 0, 1), c=(0, -1.1, 0), ch=1)
circle2 = cmd.duplicate(circle1[0], ic=1)
circle3 = cmd.duplicate(circle1[0], ic=1)
cmd.setAttr(circle2[0] + '.rotateZ', 120)
cmd.setAttr(circle3[0] + '.rotateZ', -120)

allCurves = circle1[0], circle2[0], circle3[0]
makeIdentityCurvesWithSharedHistory(allCurves)

If above code is used: enter image description here

Disclaimer: Theoretically, this should work in any version of Maya; But I have tested it only on Maya 2015.

1
SAF On

Problem in duplicate Input Connections. Previously, there was a bug. Probably... not sure.

Working code:

import maya.cmds as cmd

circle1 = cmd.circle(nr=(0, 0, 1), c=(0, -1.1, 0), ch=1)
circle2 = cmd.duplicate(circle1[0], ic=0) #InputConnections=0
circle3 = cmd.duplicate(circle1[0], ic=0) #InputConnections=0
cmd.setAttr(circle2[0] + '.rotateZ', 120)
cmd.setAttr(circle3[0] + '.rotateZ', -120)

allCurves = circle1[0], circle2[0], circle3[0]
cmd.select(allCurves)
cmd.makeIdentity(apply=True, t=1, r=1, s=1, n=0)
0
theodox On

If you move the makeIdentity up the chain it works visually:

circle1 = cmds.circle(nr=(0, 0, 1), c=(0, -1.1, 0), ch=1)
circle2 = cmds.duplicate(circle1[0], ic=1)
circle3 = cmds.duplicate(circle1[0], ic=1)
cmds.makeIdentity(apply=True, t=1, r=1, s=1, n=0)
cmds.setAttr(circle2[0] + '.rotateZ', 120)
cmds.setAttr(circle3[0] + '.rotateZ', -120)

The real problem is that MakeIdentity changes the geometry to allow the owning transform to be zeroed out while retaining the same appearance; if you're sharing shapes (ic=True) the results are kind of random when you call it on multiple objects. Check your history, you should see multiple 'transformGeometry' nodes on the circle shape which are each trying to affect the geometry.

If you want instances that are all zeroed out locally it's probably easier just to add another transform.