def trueZeroFloorPlane(rotationTarget, ctrl): trans = xform(rotationTarget, q=True, ws=True, t=True) # Make a unit X vector (assume left side is +x, right is -x) if trans[0] >= 0: tx = dt.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], [1.0, 0.0, 0.0, 1.0]]) else: tx = dt.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], [-1.0, 0.0, 0.0, 1.0]]) # Move out from the rotator by the unit X vector (in world space) altered = tx * rotationTarget.worldMatrix.get() # Get the X and Z world position of the new point alteredX = altered[3][0] alteredZ = altered[3][2] # Find the difference in X and Z world positions to calc Y deltaX = alteredX - trans[0] deltaZ = alteredZ - trans[2] rad = math.atan2(deltaX, deltaZ) degrees = math.degrees(rad) ctrl.ry.set(degrees) storeTrueZero(ctrl, [0, degrees, 0])
def useZ(matrix): return dt.Matrix([ matrix[0], matrix[1], matrix[2], [0, 0, matrix[3][2], matrix[3][3]] ])
def determineClosestWorldOrient(obj): ''' Given an object, returns the shortest rotation that aligns the object with the world. This is used to allow IK elements to have world alignment but easily return to the bind pose. ''' ''' # This is essentially a math version of the following: x = spaceLocator() y = spaceLocator() core.dagObj.moveTo( x, obj ) core.dagObj.moveTo( y, obj ) x.tx.set( 1 + x.tx.get() ) y.ty.set( 1 + y.ty.get() ) x.setParent(obj) y.setParent(obj) def zeroSmaller(loc): vals = [abs(v) for v in loc.t.get() ] largetVal = max(vals) index = vals.index(largetVal) for i, attr in enumerate('xyz'): if i == index: continue loc.attr( 't' + attr ).set(0) zeroSmaller( x ) zeroSmaller( y ) ref = spaceLocator() core.dagObj.moveTo( ref, obj ) aimConstraint( x, ref, wut='object', wuo=y ) rot = ref.r.get() delete( x, y, ref ) return rot ''' # Make 2 world spaced points one unit along x and y x = dt.Matrix([(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (1, 0, 0, 0)]) y = dt.Matrix([(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 1, 0, 0)]) #z = dt.Matrix( [ (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 1, 0,) ] ) world = obj.worldMatrix.get() inv = world.inverse() # Find the local matrices respective of the obj localX = x * inv localY = y * inv # For X, zero out the two smaller axes for each, ex t=.2, .3, .8 -> t=0, 0, .8 def useX(matrix): return dt.Matrix([ matrix[0], matrix[1], matrix[2], [matrix[3][0], 0, 0, matrix[3][3]] ]) def useY(matrix): return dt.Matrix([ matrix[0], matrix[1], matrix[2], [0, matrix[3][1], 0, matrix[3][3]] ]) def useZ(matrix): return dt.Matrix([ matrix[0], matrix[1], matrix[2], [0, 0, matrix[3][2], matrix[3][3]] ]) xUsed, yUsed, zUsed = [False] * 3 if abs(localX[3][0]) > abs(localX[3][1]) and abs(localX[3][0]) > abs( localX[3][2]): localX = useX(localX) xUsed = True elif abs(localX[3][1]) > abs(localX[3][0]) and abs(localX[3][1]) > abs( localX[3][2]): localX = useY(localX) yUsed = True else: localX = useZ(localX) zUsed = True # Do the same for Y if xUsed: if abs(localY[3][1]) > abs(localY[3][2]): localY = useY(localY) yUsed = True else: localY = useZ(localY) zUsed = True elif yUsed: if abs(localY[3][0]) > abs(localY[3][2]): localY = useX(localY) xUsed = True else: localY = useZ(localY) zUsed = True elif zUsed: if abs(localY[3][0]) > abs(localY[3][1]): localY = useX(localX) xUsed = True else: localY = useY(localY) yUsed = True # Find the 'world' (but treating the obj's pos as the origin) positions. worldX = localX * world worldY = localY * world # Convert this into a rotation matrix by mimicing an aim constraint x = dt.Vector(worldX[-1][:-1]) y = dt.Vector(worldY[-1][:-1]) x.normalize() y.normalize() z = x.cross(y) y = z.cross(x) msutil = maya.OpenMaya.MScriptUtil() mat = maya.OpenMaya.MMatrix() msutil.createMatrixFromList([ x[0], x[1], x[2], 0.0, y[0], y[1], y[2], 0.0, z[0], z[1], z[2], 0.0, 0.0, 0.0, 0.0, 1.0 ], mat) # noqa e123 rot = maya.OpenMaya.MEulerRotation.decompose( mat, maya.OpenMaya.MEulerRotation.kXYZ) return dt.Vector(math.degrees(rot.x), math.degrees(rot.y), math.degrees(rot.z))