Advertisement
bradon

edge to joint flip V4

Feb 22nd, 2013
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.86 KB | None | 0 0
  1.  
  2. #===============================================================================
  3. # Create Joints on Edges
  4. # author: Bradon Webb
  5. # 02/17/13
  6. #
  7. #
  8. # To use script select edges from a polygon mesh in order that you want the joint chain
  9. # run script and it will make joints where each edge was.
  10. #
  11. # You need to manually do a rigid bind the joints to the mesh
  12. #===============================================================================
  13.  
  14. import maya.cmds as mc
  15. import maya.OpenMaya as om
  16. import pymel.core as pm
  17. import math
  18.  
  19. def getVertexNormal(edge):
  20.     '''
  21.    @summary:
  22.        gets the vertex normal given an edge
  23.    @arguments:
  24.        name of an edge
  25.    @returns:
  26.        the Y vertex normal of the first vertex attached to the edge
  27.    '''
  28.  
  29.     vtxfaces = mc.polyListComponentConversion(edge, fromEdge=True, toVertexFace=True)
  30.     flatnormals = mc.polyNormalPerVertex(vtxfaces, q=True, xyz=True)
  31.  
  32.     normals = []
  33.     normals = zip(*[iter(flatnormals)]*3)
  34.    
  35.     # get the Y component of the first vertx normal
  36.     vtxNormalYAxis = (normals[0])[1]
  37.    
  38.     print 'NormYComponent:', vtxNormalYAxis
  39.    
  40.     #print 'NORMAL:', normals
  41.     return vtxNormalYAxis
  42.  
  43.  
  44. def getDistance(vec1, vec2):
  45.     '''
  46.    @summary:
  47.        test two points in space gets the distance between the two
  48.    @arguments:
  49.        two point vectors
  50.    @returns:
  51.        the distance between the two points
  52.    '''
  53.    
  54.     dist = vec1 - vec2
  55.     #return dist
  56.     return math.sqrt(dist.x**2 + dist.y**2 + dist.z**2)
  57.  
  58.  
  59. def createHierarchy(nodeList=['object1,object2']):
  60.     '''
  61.    @summary:
  62.        will create a hierarchy chain, similar to a joint hierarchy out of a list of objects
  63.    @arguments:
  64.        list of object names
  65.    @returns:
  66.        nothing
  67.    '''
  68.     #reverse the list
  69.     nodeList.reverse()
  70.    
  71.     # get the length of the list
  72.     selectionLength = len(nodeList)
  73.    
  74.     # Loop through the selection list
  75.     for index, node in enumerate(nodeList):
  76.         # Check to make sure its not the last element in the list
  77.         if index < (selectionLength - 1):
  78.             # parent the node to the previously selected node
  79.             mc.parent(node, nodeList[index + 1])            
  80.             # Debuggin
  81.             #print "node", node
  82.             #print "child", nodeList[index + 1]
  83.             #print "index", index
  84.  
  85.  
  86. def calculateEdgeCenter(edge='polyObject.e[0]'):
  87.     '''
  88.    @summary:
  89.        gets the worldspace center given edge
  90.        libraries pymel, openMaya
  91.    @arguments:
  92.        edge = name of the edge as a string
  93.    @returns:
  94.        worldspace XYZ coordinates of the center of that edge
  95.   '''
  96.     edge = pm.MeshEdge(edge)
  97.    
  98.     # get the centerpoint of the edge
  99.     edgept = edge.__apimfn__().center(om.MSpace.kWorld)
  100.     edgecenterPoint = pm.datatypes.Point(edgept)
  101.    
  102.     print 'EDGECENTER:', edgecenterPoint
  103.     return edgecenterPoint
  104.  
  105. def createLineVector(point1 = om.MVector(0,0,0), point2 = om.MVector(1,1,0), name='vector'):
  106.     '''
  107.    @summary:
  108.        given two point MVectors create a line - good for visualizing normals and angles
  109.    @arguments:
  110.        Point1 = MVector
  111.        point2 = MVector
  112.        name = string, names the created line
  113.    @returns:
  114.        curve name
  115.    '''
  116.  
  117.     newCurve = mc.curve(name=name, worldSpace=True, degree=1,
  118.                         point=[(point1.x, point1.y, point1.z),
  119.                                (point2.x, point2.y, point2.z)])
  120.     return newCurve
  121.  
  122. def calculateRotations(pointOrigin=[0,0,0], pointX=[1,0,0], pointUP=[0,1,0]):
  123.     '''
  124.    @summary:
  125.        calculates Euler rotation values 3 point locations (mVectors)
  126.    @arguments:
  127.        pointOrigin = position of origin point (MVector)
  128.        pointX = position of x point (mVector)
  129.        pointUP = position of up point (mVector)
  130.    @returns:
  131.        Euler rotation to rotate the object back
  132.        [x,y,z]
  133.    '''
  134.     #rotOrder = mc.getAttr('%s.rotateOrder'%node)
  135.     # hard code rotation order to xyz
  136.     rotOrder = 0
  137.    
  138.     # Get Point Positions
  139.     originPosition = pointOrigin
  140.     XDirection = pointX
  141.     UPDirection = pointUP
  142.     worldOrigin = om.MVector(0,0,0)
  143.    
  144.     # Subtract Positions for Vector
  145.     UpVector = originPosition - UPDirection
  146.          
  147.     XAxis = XDirection - originPosition
  148.     ZAxis = UpVector^XAxis
  149.     YAxis = ZAxis^XAxis
  150.    
  151.     # Debugging
  152.     #print 'XAxis:', XAxis.x, XAxis.y, XAxis.z
  153.     #print 'UpVector:', UpVector.x, UpVector.y, UpVector.z
  154.     #print 'ZAxis:', ZAxis.x, ZAxis.y, ZAxis.z
  155.     #print 'YAxis:', YAxis.x, YAxis.y, YAxis.z
  156.  
  157.     XAxisNormalize = XAxis.normal()
  158.     YAxisNormalize = YAxis.normal()
  159.     ZAxisNormalize = ZAxis.normal()
  160.    
  161.     print 'ZAxisNORM:', ZAxisNormalize.x, ZAxisNormalize.y, ZAxisNormalize.z
  162.        
  163.     '''
  164.    uncomment code to create vector lines in space      
  165.    # Create lines in space for each axis: visual aid
  166.    xNormalCurve = createLineVector(point1=worldOrigin, point2=XAxisNormalize,  name='XAxisNormalize')
  167.    yNormalCurve = createLineVector(point1=worldOrigin, point2=YAxisNormalize,  name='YAxisNormalize')
  168.    zNormalCurve = createLineVector(point1=worldOrigin, point2=ZAxisNormalize,  name='ZAxisNormalize')
  169.    
  170.    # Create axis group and move to origin point: visual aid
  171.    #axisGroup = mc.group([xNormalCurve,yNormalCurve,zNormalCurve], name='{node}_axisGroup'.format(node=node))
  172.    
  173.    # Create axis group and move to origin point: visual aid
  174.    axisGroup = mc.group([xNormalCurve,yNormalCurve,zNormalCurve])
  175.    #mc.xform(axisGroup, worldSpace=True, translation=originPosition)
  176.    
  177.    # clear selection so the joints do not attach to one another
  178.    #mc.select(clear=True)
  179.    '''
  180.    
  181.     # Debugging            
  182.     #print 'XAxisNormalize:', XAxisNormalize.x, XAxisNormalize.y, XAxisNormalize.z
  183.     #print 'YAxisNormalize:', YAxisNormalize.x, YAxisNormalize.y, YAxisNormalize.z
  184.     #print 'ZAxisNormalize:', ZAxisNormalize.x, ZAxisNormalize.y, ZAxisNormalize.z
  185.        
  186.     # pack values into matrix      
  187.     matrix = om.MMatrix()
  188.        
  189.     om.MScriptUtil.setDoubleArray(matrix[0], 0, XAxisNormalize.x) # Sets the first row, first column
  190.     om.MScriptUtil.setDoubleArray(matrix[0], 1, XAxisNormalize.y) # Sets the first row, second column
  191.     om.MScriptUtil.setDoubleArray(matrix[0], 2, XAxisNormalize.z) # Sets the first row, third column
  192.        
  193.     om.MScriptUtil.setDoubleArray(matrix[1], 0, YAxisNormalize.x) # Sets the second row, first column
  194.     om.MScriptUtil.setDoubleArray(matrix[1], 1, YAxisNormalize.y) # Sets the second row, second column
  195.     om.MScriptUtil.setDoubleArray(matrix[1], 2, YAxisNormalize.z) # Sets the second row, third column
  196.        
  197.     om.MScriptUtil.setDoubleArray(matrix[2], 0, ZAxisNormalize.x) # Sets the third row, first column
  198.     om.MScriptUtil.setDoubleArray(matrix[2], 1, ZAxisNormalize.y) # Sets the third row, second column
  199.     om.MScriptUtil.setDoubleArray(matrix[2], 2, ZAxisNormalize.z) # Sets the third row, third column            
  200.        
  201.     # converts inverse matrix to center rotate points to 0
  202.     matrixInverse = matrix.inverse()
  203.        
  204.     # Convert to MTransformationMatrix to extract rotations
  205.     mTransformMtx = om.MTransformationMatrix(matrix)
  206.     mTransformMtxInverse = om.MTransformationMatrix(matrixInverse)
  207.                
  208.     # Get the euler rotations
  209.     eulerRot = mTransformMtx.eulerRotation()
  210.     eulerRotInverse = mTransformMtxInverse.eulerRotation()
  211.        
  212.     # sort to the proper rotate order
  213.     eulerRot.reorderIt(rotOrder)
  214.     eulerRotInverse.reorderIt(rotOrder)
  215.  
  216.     # convert radians to degrees
  217.     rotAngle = [math.degrees(angle) for angle in (eulerRot.x, eulerRot.y, eulerRot.z)]
  218.     rotAngleInverse = [math.degrees(angle) for angle in (eulerRotInverse.x, eulerRotInverse.y, eulerRotInverse.z)]
  219.    
  220.     # pack the rotation angle AND the ZAxis Y vector into a list
  221.     rotationResults = [rotAngle, ZAxisNormalize.y]
  222.        
  223.     print 'ANGLES: ', rotAngle
  224.     #print 'ANGLES INVERSE:', rotAngleInverse
  225.        
  226.     #return rotAngleInverse, rotAngle
  227.     #return rotAngle
  228.     return rotationResults
  229.  
  230. def createJointControls():
  231.     '''
  232.    @summary:
  233.        creates a joint at the center of every selected edge
  234.    @arguments:
  235.        needs a selection of edges
  236.    @returns:
  237.        JointChain
  238.    '''
  239.  
  240.     # This code works to retain the selected orderd
  241.     selectedEdgeList = mc.ls(orderedSelection=True, long=True)
  242.     #print 'EDGELIST:', selectedEdgeList
  243.    
  244.     # clear the selection
  245.     mc.select(clear=True)
  246.    
  247.     # create a list to store the joints
  248.     jointList = []
  249.    
  250.     numberOfEdges = len(selectedEdgeList)
  251.    
  252.     # for each edge in the list create a joint    
  253.     for index, selectedEdge in enumerate(selectedEdgeList):
  254.        
  255.         # test to make sure you are not on the last edge
  256.         if index < (numberOfEdges - 1):
  257.             # calculate the center of the next edge in the list
  258.             UPDirection = om.MVector(calculateEdgeCenter(selectedEdgeList[index+1]))
  259.         else:
  260.             print "YUP_ DEFAULT"
  261.             UPDirection = om.MVector(0,0,0)
  262.                    
  263.         # Main Function
  264.         # get the centerPoint
  265.         edgeCenter = calculateEdgeCenter(selectedEdge)
  266.        
  267.         # get the position of endpoints of the edge
  268.         edgeEndPoints = mc.xform(selectedEdge, query=True, worldSpace=True, translation=True)
  269.        
  270.         # get the xyz coordinates of both points on the edge
  271.         point1 = om.MVector(edgeEndPoints[0],edgeEndPoints[1],edgeEndPoints[2])
  272.         point2 = om.MVector(edgeEndPoints[3],edgeEndPoints[4],edgeEndPoints[5])
  273.    
  274.         # Main Rotation Calculation Function
  275.         # get the rotation of the edge based on three points
  276.         # use point 1 to test the rotations below in the IF Block
  277.         rotationResults = calculateRotations(pointOrigin=edgeCenter, pointX=point1, pointUP=UPDirection)
  278.         rotationVector = rotationResults[1]
  279.         rotationAngle = rotationResults[0]
  280.        
  281.                
  282.         # get the vertex normal of one of the points on the edge
  283.         # this will be used to compare the orientation of the rotation axis
  284.         vtxNormalYAxis = getVertexNormal(selectedEdge)
  285.        
  286.         # Debuggin
  287.         print 'vtxNormalYAxis: ', vtxNormalYAxis
  288.         print 'rotationVector_P1: ', rotationVector
  289.        
  290.         # Check to make sure the the rotation is oriented towards the vtxNormalYAxis
  291.         # if they are the same then point 1 is the correct orientation
  292.         # if they are not the same then point 2 is the correct orientation
  293.         if vtxNormalYAxis >= 0 and rotationVector >= 0:
  294.             print 'AXIS IS POSITIVE: Point 1 used'
  295.         elif vtxNormalYAxis < 0 and rotationVector < 0:
  296.             print 'AXIS IS NEGATIVE: point 1 used'
  297.         else:
  298.             print 'AXIS IS FLIPPED: point 2 used'
  299.             # Main Rotation Calculation Function
  300.             # get the rotation of the edge based on three points
  301.             rotationResults = calculateRotations(pointOrigin=edgeCenter, pointX=point2, pointUP=UPDirection)
  302.             rotationVector = rotationResults[1]
  303.             rotationAngle = rotationResults[0]            
  304.        
  305.        
  306.         # create Joint at the edge center and aligned to the edge
  307.         joint = mc.joint(position=edgeCenter, orientation=rotationAngle)
  308.        
  309.         # Display the joint orientation manipulator
  310.         mc.setAttr('{joint}.displayLocalAxis'.format(joint=joint), 1)
  311.        
  312.         # clear selection so the joints do not attach to one another
  313.         mc.select(clear=True)
  314.        
  315.         #append joint name to list
  316.         jointList.append(joint)
  317.    
  318.     # attach all the joints in a chain of hierarchy  
  319.     createHierarchy(nodeList=jointList)
  320.    
  321.     #newBindSkin " -byClosestPoint -toSkeleton";
  322.        
  323.  
  324. createJointControls()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement