I woke up this morning with a major efficiency improvement in my head... I really need a break from this. Here's the updated script:
http://zoomy.net/pub/voxelize_meshes_v.3.py Okay, I'm done. Peter On Feb 27, 12:24 am, Chad Dombrova <[email protected]> wrote: > actually, speaking of pymel, pymel nodes sport many methods derived from api > mfn classes, so this script would be a nice test of many of these methods. i > may take a crack at it. would be nice for a speed comparison as well. pymel > would of course be a bit slower because of the wrapping mechanisms, but the > code required on the end-user's part would be much, much less. that's the > inevitable trade-off. > > -chad > > On Feb 26, 2010, at 5:49 PM, pjrich wrote: > > > > > You know, I don't think I actually checked to see if it was using > > pymel or not, I've been using pymel so often I've begun to just assume > > that's how python in maya ought to work, and of course between script > > runs it stays in session, so to speak... so in my eagerness to get > > this out I got sloppy. Thanks for the cleanup Richard, if you don't > > mind I'm going to repost this at my site -- > > Cheers, > > Peter > > > On Feb 26, 3:59 pm, Richard Kazuo <[email protected]> wrote: > >> Sure, I hope the author doesn't mind as I modified to make it work without > >> pyMel... I did it in a rush and didn't test it too much, but seems to work > >> with simple spheres. > > >> ### start: voxelize meshes v.2 > >> ### this script turns the selected meshes into cubes > >> ### over the current timeline range. > >> #cmds.progressBar(endProgress=1) > >> import maya.OpenMaya as om > >> import maya.cmds as cmds > >> import maya.mel as mel > > >> # shoot a ray from point in direction and return all hits with mesh > >> def rayIntersect(mesh, point, direction=(0.0, 0.0, -1.0)): > >> # get dag path of mesh - so obnoxious > >> om.MGlobal.clearSelectionList() > >> om.MGlobal.selectByName(mesh) > >> sList = om.MSelectionList() > >> om.MGlobal.getActiveSelectionList(sList) > >> item = om.MDagPath() > >> sList.getDagPath(0, item) > >> item.extendToShape() > >> fnMesh = om.MFnMesh(item) > > >> raySource = om.MFloatPoint(point[0], point[1], point[2], 1.0) > >> rayDir = om.MFloatVector(direction[0], direction[1], direction[2]) > >> faceIds = None > >> triIds = None > >> idsSorted = False > >> worldSpace = om.MSpace.kWorld > >> maxParam = 99999999 > >> testBothDirections = False > >> accelParams = None > >> sortHits = True > >> hitPoints = om.MFloatPointArray() > >> hitRayParams = om.MFloatArray() > >> hitFaces = om.MIntArray() > >> hitTris = None > >> hitBarys1 = None > >> hitBarys2 = None > >> tolerance = 0.0001 > > >> hit = fnMesh.allIntersections(raySource, rayDir, faceIds, triIds, > >> idsSorted, worldSpace, maxParam, testBothDirections, accelParams, sortHits, > >> hitPoints, hitRayParams, hitFaces, hitTris, hitBarys1, hitBarys2, > >> tolerance) > > >> # clear selection as may cause problems if called repeatedly > >> om.MGlobal.clearSelectionList() > >> result = [] > >> for x in range(hitPoints.length()): > >> result.append((hitPoints[x][0], hitPoints[x][1], hitPoints[x][2])) > >> return result > > >> # round to nearest fraction in decimal form: 1, .5, .25 > >> def roundToFraction(input, fraction): > >> factor = 1/fraction > >> return round(input*factor)/factor > > >> # progress bar, enabling "Esc" > >> def makeProgBar(length): > >> global gMainProgressBar > >> gMainProgressBar = mel.eval('$tmp = $gMainProgressBar'); > >> cmds.progressBar( gMainProgressBar, > >> edit=True, > >> beginProgress=True, > >> isInterruptable=True, > >> maxValue=length > >> ) > > >> def promptNumber(): > >> result = cmds.promptDialog( > >> title='Grow Shrub', > >> message='Block size:', > >> text="1", > >> button=['OK', 'Cancel'], > >> defaultButton='OK', > >> cancelButton='Cancel', > >> dismissString='Cancel') > >> if result == 'OK': > >> return float(cmds.promptDialog(query=True, text=True)) > >> else: return 0 > > >> def init(cubeSize): > >> global cubeDict, xLocs, yLocs, zLocs > >> cubeDict = {} > >> xLocs = [] > >> yLocs = [] > >> zLocs = [] > > >> # make 3 arrays of ray start points, one for each axis > >> # this is necessary because rays aren't likely to catch surfaces > >> # which are edge-on... so to make sure to catch all faces, > >> # we shoot rays along each axis > >> fac = 1/cubeSize > >> for y in range(ymin*fac, ymax*fac+1): > >> for z in range(zmin*fac, zmax*fac+1): > >> loc = (xmax, y*cubeSize, z*cubeSize) > >> xLocs.append(loc) > >> for z in range(zmin*fac, zmax*fac+1): > >> for x in range(xmin*fac, xmax*fac+1): > >> loc = (x*cubeSize, ymax, z*cubeSize) > >> yLocs.append(loc) > >> for x in range(xmin*fac, xmax*fac+1): > >> for y in range(ymin*fac, ymax*fac+1): > >> loc = (x*cubeSize, y*cubeSize, zmax) > >> zLocs.append(loc) > > >> # start the action > >> *#EDIT: I dont have pyMel to test this, but commented this line because I > >> think this is only checking for the first > >> # selected object. If you select a mesh and then a nurbs, it still > >> runs > >> and raises an exception... > >> # at least thats whats happening in Maya's native python* > >> if len(cmds.ls(sl=1)) == 0: #or > >> cmds.objectType(cmds.listRelatives(cmds.ls(sl=1)[0], > >> s=1, ni=1)) != "mesh": > >> result = cmds.confirmDialog( title='Mesh selection', message='Please > >> select a mesh.', button=['OK']) > >> else: > >> startTime= cmds.timerX() > >> cubeSize = promptNumber() > > >> # set selected objects to be the shape targets, aka controls > >> ctrl = cmds.ls(sl=1) > > >> firstFrame = int(cmds.playbackOptions(query=1, min=1)) > >> lastFrame = int(cmds.playbackOptions(query=1, max=1)) > >> duration = int(lastFrame-firstFrame) > > >> makeProgBar(duration*len(ctrl)) > >> cmds.progressBar(gMainProgressBar, edit=True, beginProgress=1) > > >> bb = cmds.exactWorldBoundingBox(ctrl[0]) > >> xmin = bb[0] > >> xmax = bb[3] > >> xdist = abs(xmin)+abs(xmax) > >> ymin = bb[1] > >> ymax = bb[4] > >> ydist = abs(ymin)+abs(ymax) > >> zmin = bb[2] > >> zmax = bb[5] > > >> print "Finding bounding box of animation..." > >> print "Press ESC to cancel" > >> # find outer boundaries of animation > >> for f in range(firstFrame,lastFrame): > >> for c in ctrl: > >> if cmds.progressBar(gMainProgressBar, query=1, isCancelled=1 ): > >> break > >> cmds.currentTime(f) > >> cmds.progressBar(gMainProgressBar, edit=1, step=1) > > >> bb = cmds.exactWorldBoundingBox(c) > >> xmin = min(xmin, bb[0]) > >> xmax = max(xmax, bb[3]) > >> ymin = min(ymin, bb[1]) > >> ymax = max(ymax, bb[4]) > >> zmin = min(zmin, bb[2]) > >> zmax = max(zmax, bb[5]) > > >> cmds.progressBar(gMainProgressBar, edit=1, endProgress=1) > > >> init(cubeSize) > > >> cmds.progressBar(gMainProgressBar, edit=1, endProgress=1) > >> makeProgBar(duration*len(ctrl)) > >> cmds.progressBar(gMainProgressBar, edit=1, beginProgress=1) > > >> print "Animating visibility over", duration, "frames..." > >> print "Press ESC to cancel" > > >> # animate cube visibility > >> resetList = [] > >> #EDIT: incremented by one because it was not calculating the last frame > >> for f in range(firstFrame,lastFrame+1): # for each frame > >> cmds.currentTime(f, edit=1, update=1) > >> # if the cube was visible last frame, hide it > >> for x in resetList: > >> cmds.setKeyframe(x, at="scale", v=0, t=f) > >> resetList = [] > >> locArrays = [xLocs, yLocs, zLocs] > >> directions = [(-1.0, 0.0, 0,0), (0.0, -1.0, 0,0), (0.0, 0.0, -1.0)] > >> # for every target control object: > >> for c in ctrl: > >> if cmds.progressBar(gMainProgressBar, query=1, isCancelled=1 ): > >> break > >> cmds.progressBar(gMainProgressBar, edit=1, step=1) > >> # for each axis: > >> for i in range(3): > >> cmds.flushUndo() > >> # for every gridpoint orthagonal to the animation: > >> for loc in locArrays[i]: > >> hits = [] > >> # zap a ray thrugh the object > >> hits = rayIntersect(c, loc, directions[i]) > >> for x in hits: > >> # snap hit locations to cubegrid > >> x = (roundToFraction(x[0], cubeSize), roundToFraction(x[1], > >> cubeSize), roundToFraction(x[2], cubeSize) ) > >> # if location isn't in cubeDict, add it and a new cube > >> if x not in cubeDict: > >> cubeDict[x] = cmds.polyCube(sz=1, sy=1, sx=1, cuv=4, > >> d=cubeSize, h=cubeSize, w=cubeSize, ch=1)[0] > >> # move cube to quantized location > >> cmds.xform(cubeDict[x], t=x) > >> # set a scale key > >> cmds.setKeyframe(cubeDict[x], at="scale", v=1, t=f) > >> # if previous frame didn't have a scale key, set it to 0 > >> tempCurTime = cmds.currentTime(q=1)-1 > >> lastKey = cmds.keyframe(cubeDict[x], at="scale", q=1, > >> t=(tempCurTime,tempCurTime), valueChange=1) > >> if lastKey == None or lastKey[0] != 1.0: > >> cmds.setKeyframe(cubeDict[x], at="scale", v=0, t=(f-1)) > >> # add cube to resetList > >> resetList.append(cubeDict[x]) > >> cmds.currentTime(f, edit=1, update=1) > > >> cmds.progressBar(gMainProgressBar, edit=1, endProgress=1) > >> totalTime = cmds.timerX(startTime=startTime) > >> print("Total Time: "+str(totalTime)) > > >> ### end voxelize meshes v.2 > > >> Really nice effect! Works like a charm. :) > > >> On Fri, Feb 26, 2010 at 4:29 PM, Chris G <[email protected]> wrote: > > >>> I'm doing some modifications to be able to run the script without PyMel > >>> and > >>>> found out some things: > > >>> Can you post that? I'd like to try it out. > > >>>> You're not importing "maya.mel as mel" nor "maya.cmds as cmds" at the > >>>> beggining of the code, is this something that PyMel installation does > >>>> automatically? > > >>> from pymel.core import * > >>> will give you cmds and mel names, but mel corresponds to pymel's > >>> pymel.core.language.Mel > > >>> - Chris > > >>> -- > >>>http://groups.google.com/group/python_inside_maya > > > -- > >http://groups.google.com/group/python_inside_maya -- http://groups.google.com/group/python_inside_maya
