Exemple #1
0
def get_slow(mesh):
    '''
    Given a mesh, returns a list, one entry per vertex, with a list of (joint, value) pairs.
    ex:
        [0] = [ (ja, .5), (jb, .5) ]
        [1] = [ (ja, .5), (jb, .25), (jc, .25) ]
    '''

    skinClusterName = mel.findRelatedSkinCluster(mesh)
    
    joints = cmds.skinCluster(mesh.name(), q=True, inf=True)
    
    weights = []
    
    required = {}
    for j in joints:
        parent = cmds.listRelatives(j, p=True)
        required[j] = [parent[0] if parent else None] + cmds.xform(j, q=True, ws=True, t=True)
    
    info = {
        'joints': required,
        'weights': weights,
    }
    
    vtxStr = mesh.name() + '.vtx[%i]'
    for i in xrange(mesh.vtx.count()):
        weights.append( [(t, v) for t, v in zip(joints, cmds.skinPercent(skinClusterName, vtxStr % i, q=1, v=1)) if v > 0] )
    
    return info
Exemple #2
0
def getShapeInfo_DEPRECATED(name, controller):
    '''
    Returns a list of strings representing the shape of the given controller
    '''

    extraInfo = {'color': getShader(controller)}

    for shape in core.shape.getShapes(controller):
        extraInfo['curveColor'] = shape.overrideColor.get()

    if controller.hasAttr('shapeType'):
        extraInfo['shapeType'] = controller.shapeType.get()

    lines = [name + ':' + json.dumps(extraInfo)]
    for shape in core.shape.getShapes(controller):
        # pos = [xform(cv, q=True, os=True, t=True) for cv in shape.cv]
        # Iterating cvs in mel is 2-6x faster
        if shape.type() == 'nurbsCurve':
            cvStr = shape.name() + '.cv[%i]'
            localPos = [
                cmds.xform(cvStr % i, q=True, os=True, t=True)
                for i in xrange(shape.numCVs())
            ]
            worldPos = [
                cmds.xform(cvStr % i, q=True, ws=True, t=True)
                for i in xrange(shape.numCVs())
            ]
        else:
            cvStr = shape.name() + '.cv[%i][%i]'
            localPos = [
                cmds.xform(cvStr % (u, v), q=True, os=True, t=True)
                for u in xrange(shape.numCVsInU())
                for v in xrange(shape.numCVsInV())
            ]
            worldPos = [
                cmds.xform(cvStr % (u, v), q=True, ws=True, t=True)
                for u in xrange(shape.numCVsInU())
                for v in xrange(shape.numCVsInV())
            ]

        lines.append('    ' + shape.type() + '|os ' + str(localPos))
        lines.append('    ' + shape.type() + '|ws ' + str(worldPos))
    return lines
Exemple #3
0
def skeletonToJson(root):
    
    skel = {}
    
    for j in [root] + root.listRelatives(ad=True, type='joint'):
        parentName = j.getParent().shortName()
        
        skel[ j.shortName() ] = {
            'parent': parentName,
            'pos': cmds.xform(j.name(), q=True, ws=True, t=True),
            'jo': list(j.jointOrient.get())
        }
        
    return skel
Exemple #4
0
def orientJoint(jnt, target, upTarget=None, aim='x', up='y', upVector=None):
    '''
    Orient an object (doesn't have to be a joint) to the target.  Basically a
    code only aiming.
    
    :param PyNode jnt: The joint to orient
    :param PyNode target: The object to orient to.
    :param PyNode/upTarget pos: A PyNode or position [x,y,z] for the up vector
    :param upVector: If specified, upTarget is not needed
    :param chr aim:
    
    This works for aim=x, up=y and negative versions
    
    Things to investigate:
        * Sometimes the rotations are different but that turns out to be -0.0 in
        the matrix.  AFAIK, everything still ends up fine.
            # Adept ends up with the same JOs!
            # Minotaur is the same
        
        * It looks like rotate order doesn't matter
    
    It's (almost) an all code version of:

        if isinstance(pos, PyNode):
            upObj = pos
        else:
            upObj = spaceLocator()
            upObj.t.set( pos )
        
        aim = axisConvert(aim)
        up = axisConvert(up)
        
        # Temporarily unparent children and clear orientation.
        with lib.core.dagObj.Solo( jnt ):
            jnt.r.set(0, 0, 0)
            jnt.jo.set(0, 0, 0)
            
            const = aimConstraint( target, jnt, aim=aim, u=up, wut='object', wuo=upObj )
            jnt.jo.set( jnt.r.get() )
            delete( const )
            jnt.r.set(0, 0, 0)

        def axisConvert( axisChar ):
            """
            Turn a character representing an axis into 3 numbers, ex x = [1,0,0], -y = [0,-1,0]
            
            :param char axisChar: Either "x", "y" or "z", possibly negated, eg: "-x"
            """
            axis = [0, 0, 0]
            c = axisChar[-1]
            axis[ ord(c) - ord('x') ] = -1 if axisChar.startswith('-') else 1
            return axis
    '''

    #print jnt, target, pos, aim, up
    jPos = dt.Vector(cmds.xform(str(jnt), q=True, ws=True, t=True))

    if not isinstance(target, dt.Vector):
        tPos = dt.Vector(cmds.xform(str(target), q=True, ws=True, t=True))
    else:
        tPos = target

    if not upVector:
        if isinstance(upTarget, PyNode):
            uPos = dt.Vector(cmds.xform(str(upTarget), q=True, ws=True,
                                        t=True))
        else:
            uPos = dt.Vector(upTarget)

        upV = uPos - jPos
        if up[0] == '-':
            upV *= -1.0
        upV.normalize()
    else:
        upV = dt.Vector(upVector)
        upV.normalize()

    aimV = tPos - jPos
    if aim[0] == '-':
        aimV *= -1.0
    aimV.normalize()

    # The aim/up order determines if it's aim.cross(up) or up.cross(aim) for the final axis
    if aim[-1] == 'x' and up[-1] == 'y':
        mainCross = _forwardCross
        finalCross = _forwardCross
    elif aim[-1] == 'x' and up[-1] == 'z':
        mainCross = _reverseCross
        finalCross = _reverseCross

    elif aim[-1] == 'y' and up[-1] == 'z':
        mainCross = _forwardCross
        finalCross = _forwardCross
    elif aim[-1] == 'y' and up[-1] == 'x':
        mainCross = _reverseCross
        finalCross = _reverseCross

    elif aim[-1] == 'z' and up[-1] == 'x':
        mainCross = _forwardCross
        finalCross = _forwardCross
    elif aim[-1] == 'z' and up[-1] == 'y':
        mainCross = _reverseCross
        finalCross = _reverseCross

    finalAxis = mainCross(aimV, upV)
    finalAxis.normalize()

    # aimV and upV are probably not perpendicular, but finalAxis was built
    # perpendicular to both so rebuild upV from aimV and finalAxis
    #newUp = finalAxis.cross(aimV)
    newUp = finalCross(finalAxis, aimV)
    newUp.normalize()

    axes = [None, None, None]

    if aim[-1] == 'x':
        axes[0] = list(aimV) + [0.0]
    elif aim[-1] == 'y':
        axes[1] = list(aimV) + [0.0]
    else:
        axes[2] = list(aimV) + [0.0]

    if up[-1] == 'x':
        axes[0] = list(newUp) + [0.0]
    elif up[-1] == 'y':
        axes[1] = list(newUp) + [0.0]
    else:
        axes[2] = list(newUp) + [0.0]

    for i, v in enumerate(axes):
        if not v:
            axes[i] = list(finalAxis) + [0.0]

    axes.append(list(jnt.t.get()) + [1.0])

    r = core.math.eulerFromMatrix(axes, degrees=True)

    # Temporarily unparent children and clear orientation.
    with core.dagObj.TempWorld(jnt):
        with core.dagObj.Solo(jnt):
            if jnt.type() == 'joint':
                jnt.r.set(0, 0, 0)
                jnt.jo.set(r)
            else:
                jnt.r.set(r)
Exemple #5
0
 def check(cls, jnt):
     if cls.zero < abs(cmds.xform(str(jnt), q=True, ws=True, t=True)[0]) < cls.tolerance:
         cls.offcenter.append(jnt)
Exemple #6
0
def get_old(mesh):
    '''
    Creates as dictionary that looks like the following:
    
    {
        'weights': [   ], # index is vertex index, value is list of bone, weight pairs
        [0] = [ ('j1', .75), ('j2', .25) ]...
        
        'joints': {
            'j1': [parent, global_x, global_y, global_z]
            ...
        }
    }
    '''
    
    ''' DEBUG
    from pdil.core import capi
    from maya.api.OpenMayaAnim import MFnSkinCluster
    '''
    
    
    skinClusterName = mel.findRelatedSkinCluster(mesh)
    
    skinClusterMObj = capi.asMObject( skinClusterName )
    skinFn = MFnSkinCluster( skinClusterMObj.object() )
    
    #construct a dict mapping joint names to joint indices
    jointApiIndices = {}
    
    for jointDagMObj in skinFn.influenceObjects():
        jointApiIndices[ skinFn.indexForInfluenceObject( jointDagMObj ) ] = jointDagMObj.partialPathName()
        
    weightListPlug = skinFn.findPlug( 'weightList', True )
    weightListObj = weightListPlug.attribute()
    weightsPlug = skinFn.findPlug( 'weights', True )
    
    weights = [None] * mesh.vtx.count() # Prebuilding the whole range is nearly instant, appending is probably slower
    # since it will trigger resizing.
    
    for vertIdx in xrange(mesh.vtx.count()):  # noqa
        # We need to use the api to query the physical indices used
        weightsPlug.selectAncestorLogicalIndex( vertIdx, weightListObj )
        activeJointIndices = weightsPlug.getExistingArrayAttributeIndices()
        
        # Values = cmds_getAttr( baseFmtStr % vertIdx + '.weights' )[0] # api 2.0 is 0.09 instead of  0.25
        values = [weightsPlug.elementByLogicalIndex(i).asDouble() for i in activeJointIndices]
        
        try:
            # If `i` isn't in jointApiIndices, that value is skipped.  Not sure why these garbage values are just left behind...
            weights[vertIdx] = [ (jointApiIndices[idx], v) for idx, v in zip( activeJointIndices, values ) if idx in jointApiIndices]
        except Exception:
            raise
            '''
            weights[vertIdx] = []
            # This gets hit when an influence object has been removed
            for i, v in zip(activeJointIndices, values):
                if v > 0.000001:
                    weights[vertIdx].append( (jointApiIndices[i], v) )
            '''
    
    # Prune out the unused joints (Maybe make an option?)
    joints = {}
    requiredJoints = set()
    for wgt in weights:
        for j, v in wgt:
            requiredJoints.add(j)
    
    # Save the joint's parent and worldspace position, for possible future use/issue detection.
    for j in requiredJoints:
        parent = cmds.listRelatives(j, p=True)
        joints[j] = [parent[0] if parent else None] + cmds.xform(j, q=True, ws=True, t=True)
    
    
    return {'weights': weights, 'joints': joints}