def buildMesh() : numVertices=4 numFaces=1 outputMesh = OpenMaya.MObject() points = OpenMaya.MFloatPointArray() faceConnects = OpenMaya.MIntArray() faceCounts = OpenMaya.MIntArray() p = OpenMaya.MFloatPoint(-1.0,0.0,-1.0) points.append(p) p = OpenMaya.MFloatPoint(-1.0,0.0,1.0) points.append(p) p = OpenMaya.MFloatPoint(1.0,0.0,1.0) points.append(p) p = OpenMaya.MFloatPoint(1.0,0.0,-1.0) points.append(p) faceConnects.append(0) faceConnects.append(1) faceConnects.append(2) faceConnects.append(3) faceCounts.append(4) meshFN = OpenMaya.MFnMesh() meshFN.create(points, [4],faceConnects) nodeName = meshFN.name() print(nodeName) cmds.sets(nodeName, add='initialShadingGroup') cmds.select(nodeName) meshFN.updateSurface()
def drawBoundingBox(box, color): min = om.MFloatPoint(box.min) max = om.MFloatPoint(box.max) glPushAttrib(GL_ALL_ATTRIB_BITS) glDisable(GL_LIGHTING) glColor3f(color.r, color.g, color.b) glBegin(GL_LINE_STRIP) glVertex3f(min.x, min.y, min.z) glVertex3f(max.x, min.y, min.z) glVertex3f(max.x, max.y, min.z) glVertex3f(min.x, max.y, min.z) glVertex3f(min.x, min.y, min.z) glVertex3f(min.x, min.y, max.z) glVertex3f(min.x, max.y, max.z) glVertex3f(min.x, max.y, min.z) glVertex3f(max.x, max.y, min.z) glVertex3f(max.x, max.y, max.z) glVertex3f(max.x, min.y, max.z) glVertex3f(max.x, min.y, min.z) glVertex3f(max.x, min.y, max.z) glVertex3f(min.x, min.y, max.z) glVertex3f(min.x, max.y, max.z) glVertex3f(max.x, max.y, max.z) glEnd() glPopAttrib()
def intersect(mesh, point, ray): ''' This is probably some foundation for the yet-to-be surface follow stuff. ''' fnMesh = OpenMaya.MFnMesh(pdil.capi.asMObject(mesh.getShape()).object()) p = spaceLocator() p.t.set(point) p.setParent(mesh) objSpacePos = p.t.get() p.setTranslation(ray, space='world') objSpaceRay = p.t.get() - objSpacePos point = OpenMaya.MFloatPoint(objSpacePos) ray = OpenMaya.MFloatVector(objSpaceRay) res = fnMesh.allIntersections(point, ray, OpenMaya.MSpace.kObject, 50, False) # -> (hitPoints, hitRayParams, hitFaces, hitTriangles, hitBary1s, hitBary2s) if not len(res[0]): hits = [] else: hits = [] for hit in res[0]: p.t.set(hit.x, hit.y, hit.z) hits.append(p.getTranslation(space='world')) delete(p) return hits
def get_coord_on_drag(self, selected, ctx): vpX, vpY, _ = cmds.draggerContext(ctx, query=True, dragPoint=True) position = om.MPoint() # 3D point with double-precision coordinates direction = om.MVector() # 3D vector with double-precision coordinates omui.M3dView().active3dView().viewToWorld( int(vpX), int(vpY), position, # world point direction) # world vector for mesh in selected: selectionList = om.MSelectionList() selectionList.add(mesh) dagPath = selectionList.getDagPath(0) fnMesh = om.MFnMesh(dagPath) intersection = fnMesh.closestIntersection( om.MFloatPoint(position), # raySource om.MFloatVector(direction), # rayDirection om.MSpace.kWorld, # space 99999, # maxParam True) # testBothDirections hitPoint, hitRayParam, hitFace, hitTriangle, \ hitBary1, hitBary2 = intersection x, y, z, _ = hitPoint return x, y, z
def _closestIntersection(self, dagPath, worldPt, worldVector): """Return the closest intersection data for the given mesh with the given point and vector. :param dagPath: The MDagPath of the mesh object. :type dagPath: om2.MDagPath :param worldPt: The world point of the ray to test for intersection with. :type worldPt: om2.MPoint :param worldVector: The MVector of the intersection ray. :type worldVector: om2.MVector :return: The tuple with the intersection data: hitPoint: The intersection point. hitRayParam: The ray length to the intersection. hitFace: The face index of the intersection. hitTriangle: The relative index of the trangle. hitBary1: First barycentric coordinate. hitBary2: Second barycentric coordinate. :rtype: tuple(om2.MFloatPoint, float, int, int, float, float) """ meshFn = om2.MFnMesh(dagPath) accelParams = om2.MMeshIsectAccelParams() accelParams = meshFn.autoUniformGridParams() return meshFn.closestIntersection( om2.MFloatPoint(worldPt), om2.MFloatVector(worldVector), om2.MSpace.kWorld, 100000, # maxParam True)
def onPress(): vpX, vpY, _ = cmds.draggerContext(context, query=True, dragPoint=True) pos = om.MPoint() dir = om.MVector() omui.M3dView().active3dView().viewToWorld(int(vpX), int(vpY), pos, dir) for mesh in cmds.ls(type='mesh'): selectionList = om.MSelectionList() selectionList.add(mesh) dagPath = selectionList.getDagPath(0) fnMesh = om.MFnMesh(dagPath) hit = fnMesh.allIntersections(om.MFloatPoint(pos), om.MFloatVector(dir), om.MSpace.kWorld, 99999, False) if hit: try: hit1 = hit[0][0] hit2 = hit[0][1] mySel = cmds.ls(sl=True)[-1] pos = [(hit1[0] + hit2[0]) / 2, (hit1[1] + hit2[1]) / 2, (hit1[2] + hit2[2]) / 2] cmds.setAttr(mySel + '.translate', pos[0], pos[1], pos[2], type='double3') except: pass
def getPointer(s): """ Get intersection point on the mesh from the mouse click. """ if s.meshes: try: # Grab screen co-ords viewX, viewY, viewZ = cmds.draggerContext(s.tool, q=True, dp=True) # Set up empty vectors position = om.MPoint() direction = om.MVector() # Convert 2D positions into 3D positions omui.M3dView().active3dView().viewToWorld(int(viewX), int(viewY), position, direction) # Check our meshes for mesh in s.meshes: selection = om.MSelectionList() selection.add(mesh) dagPath = selection.getDagPath(0) fnMesh = om.MFnMesh(dagPath) # Shoot a ray and check for intersection intersection = fnMesh.closestIntersection(om.MFloatPoint(position), om.MFloatVector(direction), om.MSpace.kWorld, 99999, False) # hitPoint, hitRayParam, hitFace, hitTriangle, hitBary1, hitBary2 = intersection if intersection and intersection[3] != -1: return (mesh, intersection[2]) # hit mesh and face ID except RuntimeError: pass
def intersectionAPI2(): """ Select two objects. the second shot a ray at its X axis over the first. return: id face collision """ mSelList = OpenMaya.MGlobal.getActiveSelectionList() dagPath0 = mSelList.getDagPath(0) dagPath0.extendToShape() mfnMesh0 = OpenMaya.MFnMesh(dagPath0) dagPath1 = mSelList.getDagPath(1) mfnTransform = OpenMaya.MFnTransform(dagPath1) testBothDirections = False maxParamPtr = 9999999.0 space = OpenMaya.MSpace.kWorld spaceVector = OpenMaya.MSpace.kTransform raySource = OpenMaya.MFloatPoint(mfnTransform.rotatePivot(space)) # print raySource rayDirectionMatrix = mfnTransform.rotation(spaceVector).asMatrix() rayDirection = OpenMaya.MFloatVector(rayDirectionMatrix[0], rayDirectionMatrix[1], rayDirectionMatrix[2]) # http://zoomy.net/2009/07/31/fastidious-python-shrub/ hit = mfnMesh0.closestIntersection(raySource, rayDirection, space, maxParamPtr, testBothDirections) pm.select('%s.f[%s]' % (dagPath0, hit[2])) print(hit)
def getClosestHit(source, direction): nurbsHit = nurbsFn.intersect(om.MPoint(source), om.MVector(direction), om.MSpace.kWorld) if nurbsHit is None: return None return om.MFloatPoint(nurbsHit[0])
def meshIntersect(edgeVertsCoord=None, mesh2Intersect=None): '''see if a given edge(2 verts) interesects with mesh2Intersect ''' # see if given mesh or edgeVertsCoord intersects with target mesh or not mSelList = om.MSelectionList() mDagPath = om.MDagPath() targetMesh = "%s" % mesh2Intersect mSelList.add(targetMesh) targetDagP = mSelList.getDagPath(0) targetMfnSet = om.MFnMesh(targetDagP) edgeCount = len(edgeVertsCoord) hitCount = 0 for coord in edgeVertsCoord: rayStartPos = om.MFloatPoint(coord[0]) rayEndPos = om.MFloatPoint(coord[1]) rayVec = om.MFloatVector(rayEndPos - rayStartPos) rayLen = rayVec.length() infoList = targetMfnSet.closestIntersection(rayStartPos, rayVec, om.MSpace.kWorld, 999, False) hitPos = infoList[0] hitParem = infoList[1] hitLen = om.MVector(hitPos - rayStartPos).length() if hitParem == 0: # not even hit at all continue elif hitParem != 0: if hitLen <= rayLen: #print True return True # once a function does return, it ends the function else: # hit point is further than the length of the edge, not intersecting hitCount += 1 if hitCount == edgeCount: #print hitCount,edgeCount #print "inside geo or target too small" return False #print hitCount,edgeCount #print False return False
def utils_screenTo3dOffset(camMatrix, coords, ssOffset): coef = 0.1 vTargetCam = coords - ompy.MFloatPoint(matrix_getRow(3, camMatrix)) vOffset = matrix_getRow(0, camMatrix) * ssOffset.x * -1.0 + matrix_getRow( 1, camMatrix) * ssOffset.y * -1.0 vOffset *= vTargetCam.length() * -0.015 return vOffset
def dagPath_getAttrMFloatPointArray(objPath, Attr): out_value = [] node = objPath.node() plug = ompy.MPlug(node, Attr) if (plug.isNull == False): if (plug.isArray == True): for i in range(0, plug.numElements()): dHandle = plug.elementByLogicalIndex(i).asMDataHandle() out_value.append(ompy.MFloatPoint(dHandle.asFloatVector())) plug.destructHandle(dHandle) return out_value
def click(s): try: # Grab mouse co-ords on screen viewX, viewY, viewZ = cmds.draggerContext(s.myTool, q=True, ap=True) position = om.MPoint() direction = om.MVector() # Convert 2D screen positions into 3D world positions omui.M3dView().active3dView().viewToWorld(int(viewX), int(viewY), position, direction) sel = om.MSelectionList() sel.add(s.sel) dagPath = sel.getDagPath(0) fnMesh = om.MFnMesh(dagPath) intersection = fnMesh.closestIntersection( om.MFloatPoint(position), om.MFloatVector(direction), om.MSpace.kWorld, 99999, False) # Did our ray intersect with the object? if intersection: hitPoint, hitRayParam, hitFace, hitTriangle, hitBary1, hitBary2 = intersection if hitTriangle != -1: # Grab Skin Cluster skin = mel.eval("findRelatedSkinCluster %s" % s.sel) if skin: # Get Face points cmds.select("%s.f[%s]" % (s.sel, hitFace)) face = cmds.polyInfo(fv=True) # Get vertexes verts = [ "%s.vtx[%s]" % (s.sel, v) for v in findall(r"\s(\d+)\s", face[0]) ] # Get Joints cmds.select(verts, r=True) joints = cmds.skinPercent(skin, q=True, t=None) # Get weights weights = sorted( [(j, cmds.skinPercent(skin, t=j, q=True)) for j in joints], key=lambda x: x[1], reverse=True) cmds.select(weights[0][0], r=True) else: print "No skin found" # Return to previous tool cmds.setToolTo(s.tool) cmds.refresh() except RuntimeError: print "There was an issue selecting the object."
def inMesh(meshObj, positions, maxRes=100): '''{'del_path':'Polygons/QueryMesh/inMesh()ONLYSE', 'icon':':/polyMesh.png', 'usage':'\ meshObj = cmds.ls(sl=True)[-1]\\n\ objs = cmds.ls(sl=True)[:-1]\\n\ positions = []\\n\ for obj in objs:\\n\ positions.append( cmds.getAttr(obj+".t")[0] )\\n\\n\ inMeshData = $fun(meshObj, positions )\\n\ inMeshObjs=[]\\n\ for obj in objs:\\n\ if inMeshData[ objs.index(obj) ]:\\n\ inMeshObjs.append( obj )\\n\ if inMeshObjs:\\n\ cmds.select(inMeshObjs, r=True)\\n\ mel:\\n\ string $object = "pCube1";\\n\ vector $pos = <<0,0,0>>;\\n\ python("$fun(\""+$object+"\",["+$pos.x+"," +$pos.y+"," +$pos.z+"])");', } ''' meshs = newom.MSelectionList() meshs.add(meshObj) meshDagPath = meshs.getDagPath(0) meshFn = newom.MFnMesh(meshDagPath) divSize = emfx_getVoxelSize(meshObj, maxRes) bbox = cmds.exactWorldBoundingBox(meshObj, ignoreInvisible=False) xDiv = math.fabs(bbox[3] - bbox[0]) / divSize yDiv = math.fabs(bbox[4] - bbox[1]) / divSize zDiv = math.fabs(bbox[5] - bbox[2]) / divSize meshAcceleration = meshFn.uniformGridParams(int(xDiv), int(yDiv), int(zDiv)) whethers = [] rayDirection = newom.MFloatVector(0, -1, 0) for pos in positions: hitPoints = meshFn.allIntersections(newom.MFloatPoint(pos), rayDirection, newom.MSpace.kWorld, 9999.0, False, accelParams=meshAcceleration)[0] whethers.append(True if len(hitPoints) % 2 == 1 else False) meshFn.clearGlobalIntersectionAcceleratorInfo() return whethers
def get_ray_mesh_intersection(mesh, direction=[0,-1 ,0], origin=[0,1,0]): direction_v = om.MFloatVector(direction[0],direction[1],direction[2]) origin_p = om.MFloatPoint(origin[0],origin[1],origin[2]) # return om.MVector(pnt1-pnt2).length() selectionList = om.MSelectionList() selectionList.add(mesh) nodeDagPath = selectionList.getDagPath(0) mfn = om.MFnMesh(nodeDagPath) intersection = mfn.closestIntersection(origin_p, direction_v, om.MSpace.kWorld, 99999999, False) #return intersection#list(intersection[0])[:-1] vector = list(intersection[0])[:-1] distance = maths.distanceBetween(origin, vector) return {'vector':vector, 'distance':distance}
def rayMeshIntersect(mesh, pos, vector): ''' Example: mover = cmds.ls(sl=1)[0] mesh = 'steel' pos = cmds.xform(mover, q=1, rp=1, ws=1) newPos = rayMeshIntersect(mesh, pos, -utils.getAxisWorldVectors(mover)[1]) cmds.xform(mover, t=newPos, ws=1) ''' nodePos = om2.MPoint(pos[0], pos[1], pos[2], 1.0) vector = om2.MVector(vector) obj, dag, stringPath = dagPathFromName(mesh) meshFn = om2.MFnMesh(dag) selectionList = om2.MSelectionList() selectionList.add(mesh) dagPath = selectionList.getDagPath(0) fnMesh = om2.MFnMesh(dagPath) intersection = fnMesh.closestIntersection(om2.MFloatPoint(pos), om2.MFloatVector(vector), om2.MSpace.kWorld, 99999, False) if intersection: hitPoint, hitRayParam, hitFace, hitTriangle, hitBary1, hitBary2 = intersection x, y, z, _ = hitPoint return (x, y, z)
def checkHit(): sel = om.MGlobal.getActiveSelectionList() mesh_fn = loc_fn = None if sel.length(): mesh_dag = sel.getDagPath(0) if mesh_dag.hasFn(om.MFn.kMesh): mesh_fn = om.MFnMesh(mesh_dag) loc_dag = sel.getDagPath(1) if loc_dag.hasFn(om.MFn.kTransform): loc_fn = om.MFnTransform(loc_dag) print mesh_fn, loc_fn ray_src = om.MFloatPoint(loc_fn.translation(om.MSpace.kWorld)) ray_dir = om.MFloatVector(0,0,1) hit_points = mesh_fn.allIntersections(ray_src, ray_dir, om.MSpace.kObject, 9999, False ) for p in hit_points[0]: loc = pm.spaceLocator() pm.move(loc, [p[0], p[1], p[2]])
def inflateMesh(mesh, scale=1): sel_list = om.MSelectionList() sel_list.add(str(mesh)) DagPath, Obj = sel_list.getComponent(0) Mesh = om.MFnMesh(DagPath) MeshPoints = Mesh.getPoints(om.MSpace.kWorld) newMeshPoints = om.MFloatPointArray() for i in range(len(MeshPoints)): MeshPointNormal = Mesh.getVertexNormal(i, om.MSpace.kWorld) x = MeshPoints[i].x + MeshPointNormal.x * scale y = MeshPoints[i].y + MeshPointNormal.y * scale z = MeshPoints[i].z + MeshPointNormal.z * scale newMeshPoint = om.MFloatPoint(x, y, z) newMeshPoints.append(newMeshPoint) Mesh.setPoints(newMeshPoints, om.MSpace.kWorld)
def rayIntersect(pos, dir, mesh): pos2 = om.MFloatPoint(pos.x, pos.y, pos.z) dir = om.MFloatVector(dir.x, dir.y, dir.z) selectionList = om.MSelectionList() selectionList.add(mesh) dagPath = om.MDagPath() sel = selectionList.getDagPath(0) fnMesh = om.MFnMesh(sel) intersection = fnMesh.closestIntersection(pos2, dir, om.MSpace.kWorld, 9999, False) hitpoint = intersection[0] faceId = intersection[2] if intersection: x = hitpoint.x y = hitpoint.y z = hitpoint.z return x, y, z, faceId else: return None
def positionsOnMesh(meshObj, position, rayDirection=False): '''{'del_path':'Polygons/QueryMesh/positionsOnMesh()ONLYSE', 'usage':'\ meshObj = cmds.ls(sl=True)[-1]\\n\ objs = cmds.ls(sl=True)[:-1]\\n\ position = []\\n\ for obj in objs:\\n\ position.append( cmds.getAttr(obj+".t")[0] )\\n\ newPos = $fun(meshObj, position, rayDirection=(0,-1,0) )\\n\ for obj in objs:\\n\ pos = newPos[ objs.index(obj) ]\\n\ cmds.setAttr(obj+""t", pos[0], pos[1], pos[2], type="double3")', } ''' meshs = newom.MSelectionList() meshs.add(meshObj) meshDagPath = meshs.getDagPath(0) meshFn = newom.MFnMesh(meshDagPath) newPos = [] if rayDirection == False: print rayDirection for pos in position: newPos.append( tuple( meshFn.getClosestPoint(newom.MPoint(pos), newom.MSpace.kWorld)[0])) else: rayDirection = newom.MFloatVector(rayDirection) for pos in position: raySource = newom.MFloatPoint(pos) hitPoint = tuple( meshFn.closestIntersection(raySource, rayDirection, newom.MSpace.kWorld, 9999.0, False)[0]) hitPos = pos if hitPoint == (0, 0, 0, 1) else hitPoint newPos.append(hitPos) return newPos
def create(verts, faces, merge=True): ''' Given a list of vertices (iterables of floats) and a list of faces (iterable of integer vert indices), creates and returns a maya Mesh ''' cmds.select(cl=True) outputMesh = OpenMaya.MObject() # point array of mesh vertex local positions points = OpenMaya.MFloatPointArray() for eachVt in verts: p = OpenMaya.MFloatPoint(eachVt[0], eachVt[1], eachVt[2]) points.append(p) # vertex connections per poly face in one array of indexs into point array given above faceConnects = OpenMaya.MIntArray() for eachFace in faces: for eachCorner in eachFace: faceConnects.append(int(eachCorner)) # an array to hold the total number of vertices that each face has in this case quads so 4 faceCounts = OpenMaya.MIntArray() # python lists can be multiplied to duplicate faceCounts = [4] * len(faces) # get a mesh function set meshFN = OpenMaya.MFnMesh() # create mesh object using arrays above meshFN.create(points, faceCounts, faceConnects, parent=outputMesh) # now grab the name of the mesh nodeName = meshFN.name() cmds.sets(nodeName, add='initialShadingGroup') cmds.select(nodeName) meshFN.updateSurface() # this is useful because it deletes stray vertices (ie, those not used in any faces) cmds.polyMergeVertex(nodeName, ch=0) meshFN.updateSurface() return nodeName
def computeShapeOffset( rbT, bboxPos=[0.0,0.0,0.0], comPos=[0.0,0.0,0.0] ): # We want the implicit collision shapes (box etc) to # centered around the bounding box center so, we need to make # the collider shift offset relative to the center of mass rtn = (bboxPos[0]-comPos[0]), (bboxPos[1]-comPos[1]), (bboxPos[2]-comPos[2]) scl = maya.cmds.xform(rbT, q=True, relative=True, scale=True) # if scaling applied then remove if scl[0]!=1.0 or scl[1]!=1.0 or scl[2]!=1.0: m = [ scl[0], 0.0, 0.0, 0.0, 0.0, scl[1], 0.0, 0.0, 0.0, 0.0, scl[2], 0.0, 0.0, 0.0, 0.0, 1.0 ] pt = OpenMaya.MFloatPoint(rtn) sclMat = OpenMaya.MFloatMatrix(m) # return x,y,z rtn = list(pt * sclMat.inverse())[:-1] return rtn
def test_mesh_intersection(current_mesh, target_mesh): # get intersection bbox inter_bbox = get_inter_bbox(current_mesh.boundingBox(), target_mesh.boundingBox()) # check if edge of current mesh intersect to face of target mesh all_hit_faces = [] all_hit_points = [] for edge in target_mesh.edges: sour_point = om.MPoint(edge.getPoint(0, 'world')) end_point = om.MPoint(edge.getPoint(1, 'world')) # ignore edge not in inter bbox if not (inter_bbox.contains(sour_point) or inter_bbox.contains(end_point)): continue # do test current_mesh_om = om.MFnMesh(pynode_to_api2(current_mesh)) edge_vector = end_point - sour_point edge_len = edge_vector.length() edge_vector.normalize() speedup_param = current_mesh_om.autoUniformGridParams() hitPoints, _, hit_faces, _, _, _ = current_mesh_om.allIntersections( om.MFloatPoint(sour_point), # 射线起点 om.MFloatVector(edge_vector), # 射线方向 om.MSpace.kWorld, # 世界空间 edge_len, # 测试距离,超出此距离的命中不算 False, # 不进行双向测试 accelParams=speedup_param # 加速参数 ) all_hit_points.extend(hitPoints) all_hit_faces.extend( [current_mesh.f[face_id] for face_id in hit_faces]) # TODO locator 生成位置不对 # [pm.spaceLocator(p=(pt.x,pt.y,pt.z)) for pt in all_hit_points] return all_hit_faces
def _mesh_to_ray_intersection(ray, mesh, both_dirs=True, clean_up=True, above_only=True): """Calculate ray/mesh intersections. Args: ray (HVRay): ray object mesh (HFnMehs): mesh object both_dirs (bool): check intersections in both directions (ie. if this if false then intersections coming out of faces will not be flagged) clean_up (bool): remove duplicate points - these can occur if a ray intersects an the edge between two faces above_only (bool): remove points behind the ray's start point Returns: (HPoint list): list of points """ from maya_psyhive import open_maya as hom _ray_src = om.MFloatPoint(*ray.pnt.to_tuple()) _ray_dir = om.MFloatVector(*ray.vec.to_tuple()) _space = om.MSpace.kWorld _max_param = 999999 _result = mesh.allIntersections( _ray_src, _ray_dir, _space, _max_param, both_dirs, ) # Convert to HPoints _pts = [] for _item in _result[0]: _pt = hom.HPoint(_item) _pts.append(_pt) lprint('FOUND {:d} PTS'.format(len(_pts)), _pts, verbose=0) # Remove duplicate points if clean_up: _clean_pts = [] while _pts: _clean_pts.append(_pts.pop()) for _pt in copy.copy(_pts): for _clean_pt in _clean_pts: if not (_pt - _clean_pt).length(): _pts.remove(_pt) _pts = _clean_pts # Remove points behind the ray's start point if above_only: _above_pts = [] _plane = ray.to_plane() for _pt in _pts: _dist = _plane.distanceToPoint(hom.HVector(_pt), signed=True) if _dist > 0.0001: _above_pts.append(_pt) _pts = _above_pts return _pts
def curveEditPointsOnMesh(*args, **kwargs): '''{'path':'Dynamics/Particles/Crowd/curveEditPointsOnMesh( )', 'icon':':/curveCV.png', 'tip':'把曲线吸附到多边形上', 'usage':""" #选择曲线,再选择mesh;当closest=False,曲线按垂直方向投射到mesh上,为True,投射到最终的mesh的位置上 $fun( closest=False )""" } ''' if len(args) > 1: nurCurves = args[0] if type(nurCurves) == type(''): nurCurve = (nurCurves, ) mesh = args[1] else: sel = cmds.ls(sl=True) if len(sel) > 1: nurCurves, mesh = sel[:-1], sel[-1] else: print 'Select two objects or assign arguments to the function!' return False mesh = checkArg(mesh, nodeType='mesh') if not mesh: print 'Least object is not mesh' return False closest = kwargs.get('closest', False) for nurCurve in nurCurves: nurCurve = checkArg(nurCurve, nodeType='nurbsCurve') if not nurCurve: print '%s is not nurbsCurve object' % (nurCurve) continue curveNode = nameToNode(nurCurve, old=True) curFn = om.MFnNurbsCurve(curveNode) numEPs = curFn.numCVs() - curFn.degree() + 1 meshNode = nameToNode(mesh) meshFn = newom.MFnMesh(meshNode) #print closest for i in range(numEPs): ep = '%s.ep[%s]' % (nurCurve, i) pos = newom.MPoint(cmds.pointPosition(ep)) meshPoint = meshFn.closestIntersection(newom.MFloatPoint(pos), newom.MFloatVector(0, 1, 0), newom.MSpace.kWorld, 9999.0, True) if meshPoint[2] != -1: #print meshPoint dis = (meshPoint[0][0] - pos[0], meshPoint[0][1] - pos[1], meshPoint[0][2] - pos[2]) cmds.move(dis[0], dis[1], dis[2], ep, r=True) elif closest == True: closestPoint = meshFn.getClosestPoint(pos, newom.MSpace.kWorld) dis = (closestPoint[0][0] - pos[0], closestPoint[0][1] - pos[1], closestPoint[0][2] - pos[2]) cmds.move(dis[0], dis[1], dis[2], ep, r=True)
def getVoxels(self, pVoxelDistance, pMeshObj, pBoundingBox): ''' Obtain a list of voxels as a set of (x,y,z) coordinates in the mesh local space. We obtain these voxels by casting rays from points separated pVoxelDistance apart within the mesh bounding box, and test whether or not these points are contained within the mesh. A point is contained within a closed mesh if the ray shot from the point intersects an odd number of times with the surface of the mesh. ''' # Initialize a list of voxels contained within the mesh. voxels = [] # Get a reference to the MFnMesh function set, and use it on the given mesh object. meshFn = OpenMaya.MFnMesh(pMeshObj) # Compute an offset which we will apply to the min and max corners of the bounding box. halfVoxelDist = 0.5 * pVoxelDistance # Offset the position of the minimum point to account for the inter-voxel distance. minPoint = pBoundingBox.min minPoint.x += halfVoxelDist minPoint.y += halfVoxelDist minPoint.z += halfVoxelDist # Offset the position of the maximum point to account for the inter-voxel distance. maxPoint = pBoundingBox.max maxPoint.x += halfVoxelDist maxPoint.y += halfVoxelDist maxPoint.z += halfVoxelDist # Define an iterator which will allow us to step through the pVoxelDistance # point intervals contained within our bounding box. We use this iterator # in the for loops that follow to visit each voxel center in the bounding box. def floatIterator(start, stop, step): r = start while r < stop: yield r r += step # Iterate over every point in the bounding box, stepping by pVoxelDistance... for xCoord in floatIterator(minPoint.x, maxPoint.x, pVoxelDistance): for yCoord in floatIterator(minPoint.y, maxPoint.y, pVoxelDistance): for zCoord in floatIterator(minPoint.z, maxPoint.z, pVoxelDistance): # 2D representation of a ray cast from the point within the bounding box: # # (+) ^----------------- # | | # y | | - We are shooting the ray from the point: [*] # axis | <======[*] | - The direction of the ray is parallel to the -Z axis. # | | # | | # (-) ------------------> # (-) z axis (+) # # If the ray intersects with an odd number of points along the surface of the mesh, the # point is contained within the mesh (assuming a closed mesh). raySource = OpenMaya.MFloatPoint(xCoord, yCoord, zCoord) rayDirection = OpenMaya.MFloatVector(0, 0, -1) # intersectionPoints = OpenMaya.MFloatPointArray() tolerance = 0.0001 ret = meshFn.allIntersections( raySource, # raySource - where we are shooting the ray from. rayDirection, # rayDirection - the direction in which we are shooting the ray. OpenMaya.MSpace.kTransform, # coordinate space - the mesh's local coordinate space. float(9999), # maxParam - the range of the ray. False, # testBothDirections - we are not checking both directions from the raySource tolerance=tolerance, # tolerance - a numeric tolerance threshold which allow intersections to occur just outside the mesh. ) # Returns a tuple of: # -> (hitPoints, hitRayParams, hitFaces, hitTriangles, hitBary1s, hitBary2s) # If there is an odd number of intersection points, then the point lies within the mesh. Otherwise, # the point lies outside the mesh. We are only concerned with voxels whose centerpoint lies within the mesh if (len(ret[0]) % 2 == 1): voxels.append(raySource) # Return the list of voxel coordinates which lie within the mesh. return voxels
def setPointFromVolume(self, distance, surface=False, rand=False): """ mesh にポイントを散布し、そのポイントのポジション情報を取得 引数: distance(float) : ポイント間の距離。値が小さいほど密度が濃い surface(bool) : True の場合、メッシュの表面に散布 rand(float) : random に配置。数値がそのままランダム強度値となる """ # 境界ボックスの最小角と最大角に適用するオフセットを計算 self.halfVoxelDist = 0.5 * distance # バウンディングボックスの最小値を取得 self.minPoint = self.getBoundingBox().min self.minPoint.x += self.halfVoxelDist self.minPoint.y += self.halfVoxelDist self.minPoint.z += self.halfVoxelDist # バウンディングボックスの最大値を取得 self.maxPoint = self.getBoundingBox().max self.maxPoint.x += self.halfVoxelDist self.maxPoint.y += self.halfVoxelDist self.maxPoint.z += self.halfVoxelDist def floatIterator(start, stop, step): """ start ~ stop 範囲内の数値で step で指定した数分繰り返し、計算値を格納 例) バウンディングボックスの最小値(start) ~ 最大値(stop) の間で指定した数(step) の均等なポジション情報を取得。 """ r = start while r < stop: yield r r += step # 計算後のポジション情報を宣言 self.voxels = [] for xCoord in floatIterator(self.minPoint.x, self.maxPoint.x, distance): for yCoord in floatIterator(self.minPoint.y, self.maxPoint.y, distance): for zCoord in floatIterator(self.minPoint.z, self.maxPoint.z, distance): # 交差判定のパラメータ self.raySource = om.MFloatPoint(xCoord, yCoord, zCoord) self.maxParam = 9999.0 self.tolerance = 0.0001 randX = random.uniform(-1, 1) * rand randY = random.uniform(-1, 1) * rand randZ = random.uniform(-1, 1) * rand # 引数設定時の分岐 if surface == True: if rand != False: self.raySource += om.MFloatPoint( randX, randY, randZ) self.rayDirection = om.MFloatVector( randX, randY, randZ) elif rand == False: rand = 1 self.raySource += om.MFloatPoint( randX, randY, randZ) self.rayDirection = om.MFloatVector( randX, randY, randZ) elif surface == False: if rand != False: self.raySource += om.MFloatPoint( randX, randY, randZ) self.rayDirection = om.MFloatVector( randX, randY, randZ) elif rand == False: self.rayDirection = om.MFloatVector(0, 0, -1) # 交差判定 self.ret = self.meshFn.allIntersections( self.raySource, # raySource ---------- レイスタートポイント self.rayDirection, # rayDirection ------- レイの方向 om.MSpace. kWorld, # coordinate space --- ヒットポイントが指定されている座標空間 self.maxParam, # maxParam ----------- ヒットを考慮する最大半径 False, # testBothDirections - 負のrayDirectionのヒットも考慮する必要があるかどうか tolerance=self. tolerance, # tolerance ---------- 交差操作の数値許容差 ) # 引数設定時の戻り値の分岐 if surface == True: if (len(self.ret[0]) % 2 == 1): self.voxels.append( (self.ret[0][0][0], self.ret[0][0][1], self.ret[0][0][2])) elif len(self.ret[0]) % 2 == 0 and len( self.ret[0]) != 0: self.voxels.append( (self.ret[0][0][0], self.ret[0][0][1], self.ret[0][0][2])) elif surface == False: # 飛ばしたレイが1回のみ当たった場合はメッシュの中、それ以外はメッシュの外と判定 if (len(self.ret[0]) % 2 == 1): self.voxels.append(self.raySource) return self.voxels
import pymel.core as pmc import pymel.core.datatypes as pmdt import maya.api.OpenMaya as OpenMaya vertexArray = OpenMaya.MFloatPointArray() v = OpenMaya.MFloatPoint(0.0, 0.0, 0.0) vertexArray.append(v) v = OpenMaya.MFloatPoint(0.0, 1.0, 0.0) vertexArray.append(v) v = OpenMaya.MFloatPoint(1.0, 1.0, 0.0) vertexArray.append(v) v = OpenMaya.MFloatPoint(1.0, 0.0, 0.0) vertexArray.append(v) v = OpenMaya.MFloatPoint(2.0, 1.0, 0.0) vertexArray.append(v) v = OpenMaya.MFloatPoint(2.0, 0.0, 0.0) vertexArray.append(v) polygonCounts = OpenMaya.MIntArray() polygonCounts.append(3) polygonCounts.append(3) polygonCounts.append(3) polygonCounts.append(3) polygonConnects = OpenMaya.MIntArray() polygonConnects.append(0) polygonConnects.append(2) polygonConnects.append(1) polygonConnects.append(0) polygonConnects.append(3) polygonConnects.append(2)
def read_skc_file(scale_rate, skc_path, mesh_name): file = open(skc_path, "r") line = file.readline() vertexArray = OpenMaya.MFloatPointArray() uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() polygonCounts = OpenMaya.MIntArray() polygonConnects = OpenMaya.MIntArray() vertexWeights = [] material_num = 0 material_sets = [] while True: line = file.readline() if not line: break line = strip_space_line(line) if line.find("Materials") != -1: line = strip_space_line(line) material_num = int(line.split(":")[1]) for i in range(0, int(material_num)): material_sets.append(0) elif line.find("Vertices") != -1: print line elif line[0] == "v": vertex_data = parse_pos_uv_weight(line) pos = vertex_data[0] pos[0] *= scale_rate pos[1] *= scale_rate pos[2] *= scale_rate v = OpenMaya.MFloatPoint(pos[0], pos[1], pos[2]) vertexArray.append(v) uv = vertex_data[1] uArray.append(uv[0]) vArray.append(uv[1]) # bone weights skin_data = vertex_data[2] weight_num = skin_data[0] weights = [] for bi in range(0, int(weight_num)): tmp_bone_idx = skin_data[int(1 + 2 * bi)] tmp_bone_name = bone_name_list[int(tmp_bone_idx)] tmp_bone_weight = skin_data[int(2 + 2 * bi)] key_value = (tmp_bone_name, tmp_bone_weight) weights.append(key_value) vertexWeights.append(weights) elif line.find("Triangles") != -1: print line elif line[0] == "f": face_data = parse_face(line) polygonCounts.append(3) polygonConnects.append(int(face_data[2])) polygonConnects.append(int(face_data[3])) polygonConnects.append(int(face_data[4])) # assign material material_sets[int(face_data[1])] += 1 mFn_Mesh = OpenMaya.MFnMesh() m_DagMod = OpenMaya.MDagModifier() new_object = m_DagMod.createNode('transform') mFn_Mesh.create(vertexArray, polygonCounts, polygonConnects, uArray, vArray, new_object) mFn_Mesh.setName(mesh_name) m_DagMod.doIt() new_mesh = pmc.PyNode(mesh_name) new_transform = pmc.listRelatives(new_mesh, type='transform', parent=True)[0] mFn_Mesh.assignUVs(polygonCounts, polygonConnects, 'map1') node_name = mesh_name + "_mesh" pmc.select(new_transform) pmc.rename(new_transform, node_name) # skin cluster pmc.select(bone_name_list[0], add=True) skin_cluster = pmc.skinCluster(bindMethod=0, skinMethod=1, normalizeWeights=0, maximumInfluences=4, obeyMaxInfluences=True) pmc.select(node_name, r=True) pmc.skinPercent(skin_cluster, node_name, normalize=False, pruneWeights=100) for v in range(0, len(vertexWeights)): pmc.skinPercent(skin_cluster, "{0}.vtx[{1}]".format(node_name, v), transformValue=vertexWeights[v], normalize=True) #create material #pCylinder1.f[14:17] _mesh.f[{0}:{1}].format() material_starts = [] material_ends = [] mesh_selcte_sets = [] material_sets = filter(lambda x: x != 0, material_sets) print material_sets material_starts.append(0) material_ends.append(material_sets[0] - 1) mesh_selcte_sets.append( node_name + ".f[{0}:{1}]".format(int(material_starts[0]), int(material_ends[0]))) for i in range(1, len(material_sets)): material_starts.append(material_ends[int(i - 1)] + 1) material_ends.append(material_ends[int(i - 1)] + material_sets[i]) mesh_selcte_sets.append(node_name + ".f[{0}:{1}]".format( int(material_starts[i]), int(material_ends[i]))) print mesh_selcte_sets # 没有这一句会出错,必须将以前的选择清理掉 pmc.select(clear=True) for i in range(0, len(mesh_selcte_sets)): shader_name = "p_shader{0}".format(int(i)) new_shader = pmc.shadingNode("lambert", asShader=True, name=shader_name) new_shadinggroup = pmc.sets(renderable=True, noSurfaceShader=True, empty=True, name='{}_SG'.format(shader_name)) pmc.connectAttr(new_shader.outColor, new_shadinggroup.surfaceShader) pmc.select(mesh_selcte_sets[i]) pmc.hyperShade(assign=new_shadinggroup) pmc.select(clear=True)
def read_gmc_data(scale_rate, gmc_path, mesh_name): # first read, get object section file = open(gmc_path, "r") line_num = -1 line_nums = [] line = file.readline() line_num += 1 while True: line = file.readline() line_num += 1 if not line: break line = strip_space_line(line) if line.find("Object") == 0: line_nums.append(line_num) print line_nums file.close() # second read,read section 1 vertexArray = OpenMaya.MFloatPointArray() uArray = OpenMaya.MFloatArray() vArray = OpenMaya.MFloatArray() polygonCounts = OpenMaya.MIntArray() polygonConnects = OpenMaya.MIntArray() material_num = 0 material_sets = [] file = open(gmc_path, "r") line_num = -1 line = file.readline() line_num += 1 while True: line = file.readline() line_num += 1 if not line: break line = strip_space_line(line) if line_num >= line_nums[0] and line_num < line_nums[1]: if line.find("Vertices") == 0: print line elif line.find("v") == 0: vertex_line = re.split("v|n|c|t", line) vertex_data = [] vertex_data.append(parse_mesh_element(vertex_line[1])) vertex_data.append(parse_mesh_element(vertex_line[4])) pos = vertex_data[0] pos[0] *= scale_rate pos[1] *= scale_rate pos[2] *= scale_rate v = OpenMaya.MFloatPoint(pos[0], pos[1], pos[2]) vertexArray.append(v) uv = vertex_data[1] uArray.append(uv[0]) vArray.append(uv[1]) elif line.find("f") == 0: face_line = line[1:] face_data = [] face_data = parse_mesh_element(face_line) print face_data polygonCounts.append(3) polygonConnects.append(int(face_data[1])) polygonConnects.append(int(face_data[2])) polygonConnects.append(int(face_data[3])) mFn_Mesh = OpenMaya.MFnMesh() m_DagMod = OpenMaya.MDagModifier() new_object = m_DagMod.createNode('transform') mFn_Mesh.create(vertexArray, polygonCounts, polygonConnects, uArray, vArray, new_object) mFn_Mesh.setName(mesh_name) m_DagMod.doIt() new_mesh = pmc.PyNode(mesh_name) new_transform = pmc.listRelatives(new_mesh, type='transform', parent=True)[0] mFn_Mesh.assignUVs(polygonCounts, polygonConnects, 'map1') node_name = mesh_name + "_mesh" pmc.select(new_transform) pmc.rename(new_transform, node_name) file.close()