NavHeader
journalHeader
Showing posts with label Python. Show all posts
Showing posts with label Python. Show all posts

Tuesday, July 3, 2012

Happy Independence Day!

If you're not from the US, you can celebrate independence from Maya's frustrating attribute editing tools with our latest tool! Hope you enjoy and if you play with pop bottle rockets, after you light them remember to let go (as my grandfather laughingly told me after I neglected to do so)


In other news, I'm looking for some potential collaborators going forward on some of the cgMonks stuff. I'm fixing to start pushing through the modular rigger and there are some opportunities to make some new characters while we're at it. For example, a fish of some sort for the fish module, bird for the wing module, etc. etc. If you're interested, can model or are a talented designer who wants to get some free publicity, lemme know.

Saturday, July 23, 2011

Basic problem solving - Scripting for a monotonous task....

So, I've been working a gig for a couple of weeks now and ran into an issue that Maya's base tools seemed to provide no good solutions. When I find myself in such a predicament I invariably find myself going down a path. Before I begin, a caveat - I'm an intermediate scripter and I'm sure there's much more efficient coding methods. However, functioning inefficient tools are better than no tools:) Hope this is helpful to anyone who happens to peruse these ramblings....

  1. Identify the need - In this case I need to ensure that a skinned mesh didn't have any vert with more than two influences. The annoying thing with maya is that even if you tell the skin to only have 2 influences and to maintain it it does the job about 98% of the time and just doesn't seem to care about that other 2%. Faced with the prospect of individually checking every vertex via the component editor for more that two skins, any other option is much more attractive.

  2. See if Maya has any tools to fix the problem - Messed with skin settings and the various mirroring, hammering and skin options to see if native maya can fix it. Sometimes this work, in this case it didn't

  3. To the internets! - Google and CreativeCrash check for a script or solution. If someone else has solved it and been kind enough to post the answer no reason to reinvent the wheel.

  4. Write a tool - Think through the requirements and results you need from a specific function or functions and beg, borrow and steal (while providing credit) the pieces to make it work.
For this little conundrum,  I wanted Maya to tell me if I had any vertices that had an influence above x influences and get that information in a usable format. Here was the particular flow on this problem.

  • For this script, I started with writing a function to return any vertices over 2 influences. 
  • As a part of that, I found the functions I needed to use need to know the skin cluster name which I remembered having wrote a function for a while back so I grabbed that.
  • Then, I thought it silly to cap it at 2 influences and allowed the user to specify the number of influences the user chose
  • Finally, worked on the workflow so that the user didn't have to type commands into the script editor as I wanted to be able to give my client a buttonable script for their artists. In the end it made sense to me to have it both report the bad verts as well as select the first in that list to easily get to work. If I was in a fuller production environment it might make sense to make a gui or modify the function to be able to select through the bad vertices list rather than a one off end function here.
In the end, spending an hour or two making a simple tool both enables a montonous task prone to user error doable as well as provides a tool for other artists to be able to do the same which is always a boon in production.


import maya.cmds as mc
import maya.mel as mel

maxInfluences = 2

def returnExcessInfluenceVerts(mesh, maxInfluences):
    skinCluster = querySkinCluster(mesh)

    badVertices = []
    
    vertexList = (mc.ls ([mesh+'.vtx[*]'],flatten=True))
    #Find the bad verts
    for v in vertexList:
        influenceList = mc.skinPercent(skinCluster, v, query=True, transform=None) 
        if len(influenceList) > maxInfluences:
            badVertices.append(v)
    return badVertices


def querySkinCluster(obj):
    mel.eval ('$mesh = "%s";' % (obj))
    skin = mel.eval('findRelatedSkinCluster($mesh);')
    return skin
   
mesh = (mc.ls (sl=True))
if len(mesh)<1:
    print ('Please select a mesh')

else:
    badVertices = returnExcessInfluenceVerts(mesh[0],maxInfluences)
    
    if len(badVertices)>0:
        mc.select(badVertices[0], replace=True)
        print ('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
        print ('%s%i%s' % ('There are ',(len(badVertices)),' verts are over the max influence:'))    
        print badVertices
    else:
        print ('No verts over max influence')

Wednesday, January 12, 2011

distanceTools.py is kinda workin okay...

Color me surprised. Been workin on this the last two days. Some of the foundation stuff for the project. Still getting used to syntax changes but really enjoying the flexibility python affords.

Also found a better way to display code in posts, woot woot!


"""
distanceTools.py
Josh Burton
www.joshburton.com
1/12/2011

Collection of functions for measuring stuff!

Function Key:
1) distanceBetweenPoints (point1, point2)
    return - distance
    
2) distanceBetweenObjects (obj1, obj2)
    return - distance
    
3) getWSPos (obj)
    return - world space position in array format
    
4) distanceBetweenObjectsArray (objArray)
    return - array of distances between each object in the input array

5) averageDistanceBetweenObjects (objArray)
    return - average of the distancees between the objects in the input array
    
6) measureDistanceBetweenObjs (objArray)
    creates - measure nodes between all ojects in the list,names them,  
              checks for a 'measure_grp' and if it finds none, creates it, parents distance nodes under that 


"""


""" returns the distance between two points in space """
def distanceBetweenPoints (point1, point2):
    from math import sqrt,pow
    distance = sqrt( pow(point1[0]-point2[0], 2) + pow(point1[1]-point2[1], 2) + pow(point1[2]-point2[2], 2) )
    return distance




""" returns the distance between two object's pivots """
def distanceBetweenObjects (obj1, obj2):
    from math import sqrt,pow
    point1 = getWSPos (obj1)
    point2 = getWSPos (obj2)
    distance = sqrt( pow(point1[0]-point2[0], 2) + pow(point1[1]-point2[1], 2) + pow(point1[2]-point2[2], 2) )
    return distance




""" simple worldspace position query """
def getWSPos (obj):
    pos = cmds.xform (obj,q=True, ws=True, rp=True)
    return pos




""" Pass an array of objects into it and get an array of distances """
def distanceBetweenObjectsArray (objArray):
    from math import sqrt,pow
    cnt = 0
    objPositionArray = []
    distancesArray = []
    cnt = (len(objArray) - 1)
    firstTermCnt = 0
    seoncTermCnt = 1

    for obj in objArray:                    
        """get its positional data"""
        tempPos = getWSPos (obj)
        objPositionArray.append (tempPos)
    
    while cnt > 0:
        point1 = objPositionArray[firstTermCnt]
        point2 = objPositionArray[seoncTermCnt]
        distance = sqrt( pow(point1[0]-point2[0], 2) + pow(point1[1]-point2[1], 2) + pow(point1[2]-point2[2], 2) )        
        distancesArray.append (distance)
        firstTermCnt +=1
        seoncTermCnt +=1
        cnt -= 1
  
        if (cnt == 0):
            break
    
    return distancesArray




""" averages the distance between objects in an array"""
def averageDistanceBetweenObjects (objArray):
    distanceArray = distanceBetweenObjectsArray (objArray)
    average = float(sum(distanceArray)) / len(distanceArray)
    return average 



""" Makes measure nodes between every object in the array """
def measureDistanceBetweenObjs (objArray):
    """need to add grouping and naming if I wanna use this"""
    cnt = 0
    locatorPositionArray = []
    cnt = (len(locArray) - 1)
    firstTermCnt = 0
    seoncTermCnt =1
    distanceObjArray = []
    coreNameArray = []
       
    if objExists ('measure_grp'):
        pass    
        
    else:
        tmp = cmds.group (empty=True, name='measure_grp')
        cmds.xform (tmp, os=True, piv= (0,0,0))
    
    for obj in objArray:                    
        """get its positional data"""
        tempPos = cmds.xform (obj,q=True, ws=True, rp=True)
        locatorPositionArray.append (tempPos)
        
        tmp = obj.split('_')
        coreNameArray.append (tmp[0])      
    
    while cnt > 0:
        distanceObj = cmds.distanceDimension( sp=locatorPositionArray[firstTermCnt], ep=locatorPositionArray[seoncTermCnt] )
        tmp = cmds.listRelatives ( [distanceObj], p=True)
        tmp = cmds.rename (tmp, (coreNameArray[firstTermCnt]+'_to_'+coreNameArray[seoncTermCnt]+'_distMeas') )
        distanceObjArray.append (distanceObj)
        firstTermCnt +=1
        seoncTermCnt +=1
        cnt -= 1
            
        cmds.parent (tmp,'measure_grp')

        if (cnt == 0):
            break        

Thursday, January 6, 2011

Python Baby!

Digging in to Python on the tutelage of my good friend and Python Master Bokser. I have to say I have a lot of fun doing scripting and td stuff - it's so immediate in it's objectivity. It works or it doesn't. Me likee.


We're getting underway with what I am temporarily calling 'bbThingamarig'. At this point we're working on low level function building blocks.

Here's a snippit:
def setRotationOrderOnJoint (jnt, ro):
    #Checks for valid rotation order
    validRO = 'True'
    rotationOrderOptions = ['xyz','yzx','zxy','xzy','yxz','zyx']
    if not ro in rotationOrderOptions:
        print (ro + ' is not a valid rotation order. Skipping')
        validRO = 'False'
    else:
        cmds.joint (jnt, e=True, rotationOrder= ro)
    return validRO
I hope to share some fun news about Morphy in the next few days that should prove to provide even more goodies for the community. Good stuff.

What else is going on...ice proofing exterior pipes, training Atticus the super dog on a wireless fence and becoming more convinced that there is a national conspiracy that all barbers have to scalp me every time I grace a barber shop. Good times.

Hope everyone made some good resolutions that last longer than the month:) 

All the stuff on this site is 2000 - by Josh Burton...unless otherwise noted. All rights reserved.