This entry was posted on Wednesday, April 20th, 2016 at 2:33.pm and is filed under Problem Solving. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.
Getting geo data from intersections on the road to making cleaner wraps…
So the rabbit trail from over the weekend proved to not be the answer to my original problem as hoped. Namely I was still getting geo movement from far off regions when baking blendshapes to non-similar geo (think a sphere placed on a body).
As such, my next plan to resolve this was to create a specific conforming geo piece to wrap to then wrap my nonconforming object to. To do this, I need a way to find the geo closest to my geo I wanted to transfer the blendshapes too and so wrote a new function for this that would:
- Search target geo against a source geo piece to find geo from each target within the source by two methods:
- boundingBox.contains – by vert
- rayCasting – by the compass vectors to make sure it is completely within the sourceObject
- Translate that data to verts,edges, faces
- Have a method to expand that data:
- selection traversing
- softSelection radius
Lessons learned:
- bounding box checking is much much faster so use that mode unless you just have to have a more precise idea of what verts are inside the mesh.
- Not a lot of specific info I could find on some of these concepts and so wanted to share to save someone else time and deadends
Here’s part one of this issue which is housed at cgm.core.lib.geo_Utils.get_contained. There are too many dependencies to include them all but you can get this gist from the code.
def get_contained(sourceObj= None, targets = None, mode = 0, returnMode = 0, selectReturn = True, expandBy = None, expandAmount = 0): """ Method for checking targets componeents or entirty are within a source object. :parameters: sourceObj(str): Object to check against targets(list): list of objects to check mode(int):search by 0: rayCast interior 1: bounding box -- THIS IS MUCH FASTER returnMode(int):Data to return 0:obj 1:face 2:edge 3:verts/cv selectReturn(bool): whether to select the return or not expandBy(str): None expandSelection: uses polyTraverse to grow selection softSelect: use softSelection with linear falloff by the expandAmount Distance expandAmount(float/int): amount to expand :returns list items matching conditions :acknowledgements http://forums.cgsociety.org/archive/index.php?t-904223.html http://maya-tricks.blogspot.com/2009/04/python.html -- idea of raycasting to resolve if in interior of object http://forums.cgsociety.org/archive/index.php?t-1065459.html :TODO Only works with mesh currently """ __l_returnModes = ['obj/transform','face','edge/span','vert/cv'] __l_modes = ['raycast interior','bounding box'] __l_expandBy = [None, 'expandSelection','softSelect'] result = [] _mode = cgmValid.valueArg(mode, inRange=[0,1], noneValid=False, calledFrom = 'get_contained') log.info("mode: {0}".format(_mode)) _returnMode = cgmValid.valueArg(returnMode, inRange=[0,3], noneValid=False, calledFrom = 'get_contained') log.info("returnMode: {0}".format(_returnMode)) _selectReturn = cgmValid.boolArg(selectReturn, calledFrom='get_contained') _expandBy = None if expandBy is not None: if expandBy in __l_expandBy: _expandBy = expandBy else: raise ValueError,"'{0}' expandBy arg not found in : {1}".format(expandBy, __l_expandBy) #Get our objects if we don't have them if sourceObj is None and targets is None: _sel = mc.ls(sl=True) sourceObj = _sel[0] targets = _sel[1:] targets = cgmValid.listArg(targets)#...Validate our targets as a list l_targetCounts = [] for o in targets: _d = cgmValid.MeshDict(o) l_targetCounts.append(_d['pointCountPerShape'][0]) sel = OM.MSelectionList()#..make selection list for i,o in enumerate([sourceObj] + targets): try: sel.add(o)#...add objs except Exception,err: raise Exception,"{0} fail. {1}".format(o,err) _dagPath = OM.MDagPath()#...mesh path holder matching = []#...our match holder _l_found = OM.MSelectionList()#...new list for found matches guiFactory.doProgressWindow(winName='get_contained', statusMessage='Progress...', startingProgress=1, interruptableState=True) if _mode is 1: log.info('bounding box mode...') try:#Get our source bb info sel.getDagPath(0,_dagPath) fnMesh_source = OM.MFnMesh(_dagPath) matrix_source = OM.MMatrix(_dagPath.inclusiveMatrix()) bb_source = fnMesh_source.boundingBox() bb_source.transformUsing(matrix_source) sel.remove(0)#...remove the source except Exception,err: raise Exception,"Source validation fail | {0}".format(err) for i in xrange(sel.length()): _tar = targets[i] _vtxCount = l_targetCounts[i] log.info("Checking '{0}'".format(_tar)) guiFactory.doUpdateProgressWindow("Checking {0}".format(_tar), i, sel.length(), reportItem=False) sel.getDagPath(i, _dagPath)#...get the target fnMesh_target = OM.MFnMesh(_dagPath)#...get the FnMesh for the target fnMesh_target.setObject(_dagPath) pArray_target = OM.MPointArray()#...data array fnMesh_target.getPoints(pArray_target)#...get comparing data matrix_target = OM.MMatrix(_dagPath.inclusiveMatrix()) fnMesh_target = OM.MFnMesh(_dagPath) bb_target = fnMesh_source.boundingBox() bb_target.transformUsing(matrix_target) if bb_source.contains( cgmOM.Point(mc.xform(_tar, q=True, ws=True, t=True))) or bb_source.intersects(bb_target): if _returnMode is 0:#...object _l_found.add(_dagPath) continue iter = OM.MItGeometry(_dagPath) while not iter.isDone(): vert = iter.position(OM.MSpace.kWorld) if bb_source.contains(vert): _l_found.add(_dagPath, iter.currentItem()) iter.next() elif _mode is 0: log.info('Ray cast Mode...') sel.remove(0)#...remove the source for i in xrange(sel.length()): _tar = targets[i] _vtxCount = l_targetCounts[i] log.info("Checking '{0}'".format(_tar)) sel.getDagPath(i, _dagPath)#...get the target fnMesh_target = OM.MFnMesh(_dagPath)#...get the FnMesh for the target fnMesh_target.setObject(_dagPath) guiFactory.doUpdateProgressWindow("Checking {0}".format(_tar), i, sel.length(), reportItem=False) iter = OM.MItGeometry(_dagPath) _cnt = 0 if _returnMode is 0:#...if the object intersects _found = False while not iter.isDone(): guiFactory.doUpdateProgressWindow("Checking vtx[{0}]".format(_cnt), _cnt, _vtxCount, reportItem=False) _cnt +=1 vert = iter.position(OM.MSpace.kWorld) _inside = True for v in cgmValid.d_stringToVector.itervalues(): d_return = cgmRAYS.findMeshIntersection(sourceObj, vert, v, maxDistance=10000, tolerance=.1) if not d_return.get('hit'):#...if we miss once, it's not inside _inside = False if _inside: _l_found.add(_dagPath) _found = True iter.next() else:#...vert/edge/face mode... while not iter.isDone(): guiFactory.doUpdateProgressWindow("Checking vtx[{0}]".format(_cnt), _cnt, _vtxCount, reportItem=False) _cnt +=1 vert = iter.position(OM.MSpace.kWorld) _good = True p = cgmOM.Point(vert) for v in cgmValid.d_stringToVector.itervalues(): d_return = cgmRAYS.findMeshIntersection(sourceObj, vert, v, maxDistance=10000, tolerance=.1) if not d_return.get('hit'):#...if we miss once, it's not inside _good = False if _good: _l_found.add(_dagPath, iter.currentItem()) iter.next() guiFactory.doCloseProgressWindow() #Post processing ============================================================================= _l_found.getSelectionStrings(matching)#...push data to strings log.info("Found {0} vers contained...".format(len(matching))) #Expand ======================================================================================== if _expandBy is not None and returnMode > 0: log.info("Expanding result by '{0}'...".format(_expandBy)) _sel = mc.ls(sl=True) or [] _expandFactor = int(expandAmount) mc.select(matching) if _expandBy is 'expandSelection': for i in range(_expandFactor): mel.eval("PolySelectTraverse 1;") matching = mc.ls(sl = True) if _expandBy is 'softSelect': mc.softSelect(softSelectEnabled=True,ssc='1,0,0,0,1,2', softSelectFalloff = 1, softSelectDistance = _expandFactor) matching = cgmSELECT.get_softSelectionItems() mc.softSelect(softSelectEnabled=False) #if _sel:mc.select(_sel) if _returnMode > 0 and _returnMode is not 3 and matching:#...need to convert log.info("Return conversion necessary") if _returnMode is 1:#...face matching = mc.polyListComponentConversion(matching, fv=True, tf=True, internal = True) elif _returnMode is 2:#...edge matching = mc.polyListComponentConversion(matching, fv=True, te=True, internal = True ) if _selectReturn and matching: mc.select(matching) return matching
Up next is setting up a new wrap setup with this data. Will post when that’s done.

