def triangulateMesh(isObj, simplify, smoothe): if isObj and not cmds.objExists('triObj'): cmds.select(baseObject) cmds.duplicate(baseObject, name = "triObj") cmds.select('triObj') if smoothe: cmds.polySmooth('triObj', c=smoothe) cmds.polyReduce(ver = 1) cmds.polyReduce(ver = 1) if simplify > 0: cmds.polyReduce(ver = 1, p = simplify) num_faces = cmds.polyEvaluate('triObj', f=True) print "Triangulating faces..." #iterate over faces face_i = 0 while face_i < num_faces: if ((num_faces - face_i) % 5 == 0): print "Triangulate check: Approximately " + str(num_faces - face_i) + " faces remaining...." face = cmds.select('triObj.f['+ str(face_i)+']') verts = getCorners(isObj,face_i) if not isCoplanar(verts): cmds.polyTriangulate('triObj.f['+ str(face_i)+']') num_faces = cmds.polyEvaluate('triObj', f=True) face_i +=1
def CER_TestCreateMultipleRandom(): for i in range(0, 30): cmds.polySphere(name='Object' + str(i)) cmds.move(random.randint(-4, 4), random.randint(-3, 3), random.randint(-2, 2), 'Object' + str(i)) CER_MergeAllMeshes() cmds.polyTriangulate('FinalModel', ch=True)
def CL_Displace(height, iUseSoftSel=0, ssRadius=0): """ Main function to perform ContourLines Displace. Keep all curves in the scene and displace the selected plane depends on the shape of that curves. Curves must be drawn from bigger to smaller (lower displace to higher) :param height: height of displacement :param iUseSoftSel: use soft selection 0 False 1 True :param ssRadius: soft selection radius :return: None """ curves = cmd.ls(type='nurbsCurve') checkClosed(curves) checkPlanar(curves) checkIntersection(curves) sel = cmd.ls(sl=True) if len(sel) == 0: raise Exception("Selezionare il piano!") print '--------- Selection is: ' + sel[0] + ' ---------' i = 1 for c in curves: shape = createShapeFromCurve(height*i, c) displacePointsInsideMesh(sel[0], shape, height, iUseSoftSel, ssRadius) cmd.delete(shape) print "Terminato displacement livello " + str(i) i += 1 cmd.polyTriangulate(sel[0])
def CL_Displace_SM(height, fRadius=5): """ Same function as CL_Displace, but use displacePointsInsideMeshSM instead of displacePointsInsideMesh :param height: height of displacement :param fRadius: soft modification radius :return: None """ curves = cmd.ls(type='nurbsCurve') checkClosed(curves) checkPlanar(curves) checkIntersection(curves) sel = cmd.ls(sl=True) if len(sel) == 0: raise Exception("Selezionare il piano!") print '--------- Selection is: ' + sel[0] + ' ---------' i = 1 for c in curves: shape = createShapeFromCurve(height*i, c) displacePointsInsideMeshSM(sel[0], shape, height, fRadius) cmd.delete(shape) print "Terminato displacement livello " + str(i) i += 1 cmd.polyTriangulate(sel[0])
def getMeshVertexData( mesh ): returnData = [] exportObject = 'bwExportObject' cmds.duplicate( mesh, n=exportObject ) cmds.polyTriangulate(exportObject) numOfFaces = cmds.polyEvaluate(exportObject, f=True ) for i in xrange(0, numOfFaces): faceSelect = exportObject + '.f[' + str(i) + ']' fVertices = [] fVertices = cmds.polyListComponentConversion(faceSelect, ff = True, tvf = True) fVertices = cmds.filterExpand(fVertices, sm = 70, ex = True) print fVertices for vertex in fVertices: faceDict = {} vName = cmds.polyListComponentConversion(vertex, fvf = True, tv = True) xyz = [] xyz = cmds.xform(vName, q = True, os = True, t = True) faceDict['x'] = round(xyz[0], 2) faceDict['y'] = round(xyz[1], 2) faceDict['z'] = round(xyz[2], 2) normal = [] normal = cmds.polyNormalPerVertex(vertex, q = True, xyz = True) faceDict['xN'] = round(normal[0], 2) faceDict['yN'] = round(normal[1], 2) faceDict['zN'] = round(normal[2], 2) # vuv = [] # vuv = cmds.polyListComponentConversion(vertex, fvf = True, tuv = True) # uvCoords = [] # uvCoords = cmds.polyEditUV(vuv[0], q = True, u = True, v = True) # faceDict['u'] = round(uvCoords[0], 2) # faceDict['v'] = round(uvCoords[0], 2) returnData.append(faceDict) cmds.delete(exportObject) return json.dumps(returnData)
def CL_Displace_noShape(height, sse=0, ssd=0): curves = cmd.ls(type='nurbsCurve') checkClosed(curves) checkPlanar(curves) checkIntersection(curves) sel = cmd.ls(sl=True) if len(sel) == 0: raise Exception("Selezionare il piano!") print '--------- Selection is: ' + sel[0] + ' ---------' cmd.selectMode(component=True) cmd.softSelect(sse=sse, ssd=ssd) count = 1 for c in curves: vtxNumber = len(cmd.getAttr(sel[0]+'.vtx[:]')) for i in range(0, vtxNumber): v = sel[0]+'.vtx[%d]' % i vPosition = cmd.xform(v, query=True, translation=True, worldSpace=True) if testIfInsideCurve(vPosition, c, (1, 0, 0)): cmd.move(height, v, y=True, r=True) print "Terminato displacement livello " + str(count) count += 1 cmd.softSelect(sse=0) cmd.selectMode(o=True) cmd.polyTriangulate(sel[0])
def TriangulateAllSkinnedMeshes(): with mayaUtils.DebugTimer('TriangulateAllSkinnedMeshes'): cmds.select(clear=True) skinList = cmds.ls(type='skinCluster') or [] for s in skinList: mesh = mayaUtils.GetMeshFromSkinCluster(s) cmds.polyTriangulate(mesh) cmds.bakePartialHistory(mesh, prePostDeformers=True) cmds.select(clear=True)
def smooth_copy(mesh, progressBar, progressStep): # 331 orig_name = self.static_base_meshes[0] # modified by Hiura self.original_mesh = snapshot(mesh, 0) # modified by Hiura self.original_mesh = cm.rename(self.original_mesh, orig_name + "_MorphExport") cm.polySoftEdge(self.original_mesh, a=180, ch=0) cm.polyTriangulate(self.original_mesh, ch=0) # added by Hiura self.vert_count = get_vert_count(self.original_mesh) store_original_vert_positions(progressBar, progressStep)
def hexalate(): list = cmds.ls(sl=1, fl=1) for i in range(len(list)): cmds.polyTriangulate(list[i], ch=True) edgeCount = cmds.polyEvaluate(e=1) cmds.select((list[i] + '.e[0:' + str(edgeCount) + ']'), r=True) hexEdgeSet = cmds.sets(name='edgeSetHex') cmds.polySubdivideFacet(list[i], dv=1, m=0, ch=1) cmds.select(hexEdgeSet, r=1) cmds.polyDelEdge(cv=1, ch=1) cmds.select(hexEdgeSet, r=1, ne=1) cmds.delete() cmds.select(list)
def generate(pts): """Takes in a list of tuples (set of 3D points) and generates a polygon model""" cmds.polyCreateFacet(name="shirt", p=points) cmds.polyTriangulate() cmds.polyQuad(angle=90) cmds.polySubdivideFacet(dv=SUBDIVISIONS) cmds.polyTriangulate() # Center shirt on origin centerX = cmds.objectCenter("shirt", x=True, gl=True) centerY = cmds.objectCenter("shirt", y=True, gl=True) centerZ = cmds.objectCenter("shirt", z=True, gl=True) cmds.move(-centerX, -centerY, -centerZ, "shirt", absolute=True)
def hexalate(): list=cmds.ls(sl=1,fl=1) for i in range (len(list)): cmds.polyTriangulate(list[i], ch = True) edgeCount = cmds.polyEvaluate( e=1) cmds.select( (list[i] + '.e[0:' + str(edgeCount) + ']'), r=True) hexEdgeSet = cmds.sets(name = 'edgeSetHex') cmds.polySubdivideFacet( list[i], dv = 1, m=0, ch=1) cmds.select(hexEdgeSet, r=1) cmds.polyDelEdge(cv=1, ch=1) cmds.select(hexEdgeSet, r = 1, ne = 1) cmds.delete() cmds.select(list)
def generate(pts): """Takes in a list of tuples (set of 3D points) and generates a polygon model""" cmds.polyCreateFacet(name="shirt", p=points) cmds.polyTriangulate() cmds.polyQuad(angle=90) cmds.polySubdivideFacet(dv=SUBDIVISIONS) cmds.polyTriangulate() # Center shirt on origin centerX = cmds.objectCenter("shirt", x = True, gl = True) centerY = cmds.objectCenter("shirt", y = True, gl = True) centerZ = cmds.objectCenter("shirt", z = True, gl = True) cmds.move(-centerX, -centerY, -centerZ, "shirt", absolute=True)
def getMeshVolume(node): selection = cmds.ls(selection=True) # based on http://www.vfxoverflow.com/questions/getting-the-volume-of-an-arbitrary-closed-mesh duplicate = cmds.duplicate(node, rr=True, inputConnections=False, upstreamNodes=False) children = cmds.listRelatives(duplicate, type='transform', fullPath=True) if not children is None: for child in children: print("Delete " + child) cmds.delete(child) cmds.makeIdentity(duplicate, apply=True, t=True, r=True, s=True, n=False) cmds.polyTriangulate(duplicate) triangles = cmds.ls(duplicate[0] + '.f[*]', flatten=True) volume = 0 for triangle in triangles: triVolume = 0 triVertices = cmds.polyListComponentConversion(triangle, tv=True) triVertices = cmds.ls(triVertices, flatten=True) if len(triVertices) != 3: cmds.error(triangle + " is not a triangle") v1 = cmds.pointPosition(triVertices[0], w=True) v2 = cmds.pointPosition(triVertices[1], w=True) v3 = cmds.pointPosition(triVertices[2], w=True) res = cmds.polyInfo(triangle, fn=True) buff = res[0].split(":") buff = buff[1].split(" ") vector = [float(buff[1]), float(buff[2]), float(buff[3])] faceNormal = vectorNorm(vector) area = abs(((v1[0]) * ((v3[1]) - (v2[1]))) + ((v2[0]) * ((v1[1]) - (v3[1]))) + ((v3[0]) * ((v2[1]) - (v1[1])))) * 0.5 triVolume = 0 triVolume = ((v1[2] + v2[2] + v3[2]) / 3.0) * area if ((faceNormal[2]) < 0): triVolume = -triVolume volume = volume + triVolume cmds.delete(duplicate) cmds.select(selection) return volume
def bbExport(): cbVal = cmds.checkBox("cb1", q=True, v=True) rbVal = cmds.radioButtonGrp("rb1", q=True, sl=True) if rbVal == 1: if cbVal: print("Triangulating Mesh") cmds.polyTriangulate() cmds.loadPlugin("ModelExporter.mll") else: print("Not Triangulating Mesh") cmds.loadPlugin("ModelExporter.mll") elif rbVal == 2: cmds.loadPlugin("SmoothSkinAnimExporter.mll") else: cmds.loadPlugin("SmoothSkinBindposeRigExporter.mll")
def parToLocMesh(mesh, particles): trinode = mc.polyTriangulate(mesh, ch=True) #count the particles count = mc.getAttr(particles + '.count') #create a group for the locators locGroup = mc.group(em=True) newCount = 0 for p in range(count): pos = mc.getParticleAttr(('%s.pt[%d]' % (particles, p)), at='worldPosition') point = (pos[0], pos[1], pos[2]) direction = (0.0, 1.0, 0.0) if rayIntersect(mesh, point, direction): loc = mc.spaceLocator() mc.move(pos[0], pos[1], pos[2], loc, a=True) mc.scale(0.1, 0.1, 0.1, loc, a=True, p=(pos[0], pos[1], pos[2])) mc.parent(loc, locGroup) newCount = newCount + 1 locGroup = mc.rename(locGroup, 'loc_%d_GRP' % (newCount)) mc.delete(trinode) return locGroup
def cutMeshBool(mesh,boundingObject): ''' Cut a specified mesh by applying a boolean intersect operation. @param mesh: The mesh to cut based on a bounding geometry @type mesh: str @param boundingObject: The object to intersect @type boundingObject: str ''' # ========== # - Checks - # ========== # Check Mesh if not mc.objExists(mesh): raise Exception('Mesh "'+mesh+'" does not exist!') if not glTools.utils.mesh.isMesh(mesh): raise Exception('Object "'+mesh+'" is not a valid mesh!') # Check Bounding Mesh if not mc.objExists(boundingObject): raise Exception('Bounding object "'+boundingObject+'" does not exist!') if not glTools.utils.mesh.isMesh(boundingObject): raise Exception('Bounding object "'+boundingObject+'" is not a valid mesh!') # ============ # - Cut Mesh - # ============ # Get Prefix prefix = glTools.utils.stringUtils.stripSuffix(boundingObject) # Triangulate Bounding Mesh mc.polyTriangulate(boundingObject,ch=False) # Cut Mesh cutMesh = mc.polyBoolOp(mesh,boundingObject,op=3,n=prefix+'Cut') if not cutMesh: raise Exception('Boolean intersection failed!') cutMesh = mc.rename(cutMesh[0],prefix+'Geo') # Cleanup mc.polyCloseBorder(cutMesh,ch=False) # ================= # - Return Result - # ================= return cutMesh
def _exportMeshes(self): # export all if self.accessMode == MPxFileTranslator.kExportAccessMode: mc.select(self._getMeshes(mc.ls(typ='mesh'))) # export selection elif self.accessMode == MPxFileTranslator.kExportActiveAccessMode: mc.select(self._getMeshes(mc.ls(sl=1))) else: raise ThreeJsError('Unsupported access mode: {0}'.format(self.accessMode)) dups = [mc.duplicate(mesh)[0] for mesh in mc.ls(sl=1)] combined = mc.polyUnite(dups, mergeUVSets=1, ch=0) if len(dups) > 1 else dups[0] mc.polyTriangulate(combined) mc.select(combined) sel = MSelectionList() MGlobal.getActiveSelectionList(sel) mDag = MDagPath() mComp = MObject() sel.getDagPath(0, mDag, mComp) self._exportMesh(mDag, mComp) mc.delete(combined)
def _exportMeshes(self): # export all if self.accessMode == MPxFileTranslator.kExportAccessMode: mc.select(self._getMeshes(mc.ls(typ="mesh"))) # export selection elif self.accessMode == MPxFileTranslator.kExportActiveAccessMode: mc.select(self._getMeshes(mc.ls(sl=1))) else: raise ThreeJsError("Unsupported access mode: {0}".format(self.accessMode)) dups = [mc.duplicate(mesh)[0] for mesh in mc.ls(sl=1)] combined = mc.polyUnite(dups, mergeUVSets=1, ch=0) if len(dups) > 1 else dups[0] mc.polyTriangulate(combined) mc.select(combined) sel = MSelectionList() MGlobal.getActiveSelectionList(sel) mDag = MDagPath() mComp = MObject() sel.getDagPath(0, mDag, mComp) self._exportMesh(mDag, mComp) mc.delete(combined)
def makeFaceWithHole(): points = [] # Create the initial square points.append((-5, -5, 0)) points.append((5, -5, 0)) points.append((5, 5, 0)) points.append((-5, 5, 0)) # Add empty point to start a hole points.append(()) for i in range(32): theta = (math.pi * 2) / 32 * i x = math.cos(theta) y = math.sin(theta) points.append((2 * x, 2 * y, 0)) newFace = cmds.polyCreateFacet(p=points) cmds.polyTriangulate() cmds.polyQuad() # Generally doesn't hurt anything
def exportAllModels(destinationFolder): ''' Export all models in the model group as OBJ's ''' createFolderStructure(destinationFolder) if not cmds.objExists('model'): print 'Expecting a group called model which contains the models to export.' return for item in cmds.listRelatives('model', c=True): print '\texporting ' + str(item) cmds.delete(item, ch=True) cmds.polyTriangulate(item, ch=False) cmds.select(item, r=True) mel.eval('polySoftEdge -a 180 -ch 0 ' + str(item)) exportCmd = 'file -force -options "groups=0;ptgroups=0;materials=0;smoothing=1;normals=1" ' exportCmd += '-typ "OBJexport" -pr -es ' exportCmd += '"' + str(os.path.join(destinationFolder, item)) + '"' mel.eval(exportCmd)
def pack_vert_uvs(mesh, progressBar, progressStep): # 151 cm.polyTriangulate(mesh, ch=0) anim_uvs = cm.polyUVSet(mesh, create=1, uvSet="anim_map") cm.polyUVSet(mesh, currentUVSet=1, uvSet=anim_uvs[0]) cm.polyAutoProjection(mesh, lm=0, pb=0, ibd=1, cm=0, l=2, sc=1, o=1, p=6, ps=0.2, ws=0, ch=0) cm.polyMapSewMove(mesh) lastProgress = 0 # added by Hiura for i in range(self.vert_count): current_position = (float(i) + 0.5) / self.vert_count # cm.polyColorPerVertex(mesh, rgb=[current_position, .5, 0]) # deleted by Hiura # >>>> modified by Hiura ( based on bryan_smyth'post ) # cm.polyEditUV(mesh + ".map[" + str(i) + "]", u=current_position, v=.501961, r=0) cm.polyEditUV(mesh + ".map[" + cm.polyListComponentConversion( mesh + ".vtx[%d]" % i, fv=True, tuv=True)[0].split("[")[-1][:-1] + "]", u=current_position, v=.501961, r=0) # <<<< modified by Hiura self.vertex_uv_position.append(current_position) # >>>> added by Hiura nowProgress = int( float(progressStep) * float(i) / float(self.vert_count)) if nowProgress > lastProgress: cm.progressBar(progressBar, edit=True, step=int(nowProgress - lastProgress)) lastProgress = nowProgress
def pinocchioObjExport(mesh, objFilePath): loadObjPlugin() savedSel = cmds.ls(sl=1) try: if not isATypeOf(mesh, 'geometryShape'): subShape = getShape(mesh) if subShape: mesh = subShape if not isATypeOf(mesh, 'geometryShape'): raise TypeError('cannot find a geometry shape for %s' % mesh) meshDup = addShape(mesh) cmds.polyCloseBorder(meshDup, ch=0) cmds.polyTriangulate(meshDup, ch=0) cmds.select(meshDup, r=1) cmds.file(objFilePath, op="groups=0;ptgroups=0;materials=0;smoothing=0;normals=0", typ="OBJexport", es=True, f=1) cmds.delete(meshDup) finally: cmds.select(savedSel) return objFilePath
def makeSeamless(meshName): """Makes a supplied mesh "seamless" in Unity by deleting its UV coordinates, smoothing normals, triangulating, and clearing material assignments""" # clear uvs so there are no seams or tangents uvs = cmds.polyUVSet(meshName, q=True, auv=True) for uv in uvs: try: cmds.polyUVSet(meshName, e=True, uvSet=uv, delete=True) except: pass uvSet = cmds.polyUVSet(meshName, q=True, auv=True)[0] sel = om.MSelectionList() sel.add(meshName) dagPath = om.MDagPath() sel.getDagPath(0, dagPath) fn = om.MFnMesh(dagPath) fn.clearUVs(uvSet) # smooth normals so there are no normal separations cmds.polySoftEdge(meshName, a=180, ch=True) # triangulate geometry cmds.polyTriangulate(meshName) # apply a single material so there are no submesh separations cmds.sets(meshName, e=True, forceElement='initialShadingGroup') # delete all history cmds.delete(meshName, ch=True) cmds.select(clear=True)
def triangulateAll(): """Triangulates all meshes in the scene and deletes non-deformer history. This method is provided since Maya's triangulation preserves mesh volume, while Unity's is intended to optimally strip a mesh. In most cases, this function will reduce vertex count but also prevent a model from being optimized for stripping.""" sel = om.MSelectionList() for x in cmds.ls(type='transform'): sel.add(x) models = [] iter = om.MItSelectionList(sel) while not iter.isDone(): path = om.MDagPath() iter.getDagPath(path) objectName = path.fullPathName() path.extendToShape() fn = om.MFnDagNode(path) if fn.typeName() == 'mesh': models.append(objectName) iter.next() for model in models: cmds.polyTriangulate(model) deleteNonDeformerHistory()
def parToLocMesh(mesh, particles): trinode = mc.polyTriangulate(mesh, ch = True) #count the particles count = mc.getAttr( particles + '.count' ) #create a group for the locators locGroup = mc.group( em=True ) newCount = 0 for p in range(count): pos = mc.getParticleAttr( ('%s.pt[%d]'%(particles, p)), at='worldPosition' ) point = (pos[0] , pos[1] , pos[2]) direction=(0.0, 1.0, 0.0) if rayIntersect(mesh, point , direction): loc = mc.spaceLocator( ) mc.move( pos[0] , pos[1] , pos[2], loc, a = True ) mc.scale( 0.1, 0.1, 0.1, loc, a = True, p = ( pos[0] , pos[1] , pos[2] )) mc.parent(loc, locGroup) newCount = newCount + 1 locGroup = mc.rename(locGroup , 'loc_%d_GRP' % (newCount) ) mc.delete (trinode) return locGroup
def _fix(self, faces): """ :param list faces: """ cmds.polyTriangulate(faces, ch=False)
return vtxList def initMeshFromMayaMesh(self, meshName): _vs = [] _faces = [] numV = mc.polyEvaluate(meshName, v=True) numF = mc.polyEvaluate(meshName, f=True) for i in range(numV): _vs.append(mc.pointPosition(meshName+".vtx["+str(i)+"]")) for i in range(numF): _faces.append(self.faceVtxList(meshName+".f["+str(i)+"]")) self.vs = _vs self.faces = _faces #TestCode### mayaMesh = Mesh() mc.polyTriangulate("man") mayaMesh.initMeshFromMayaMesh("man") myMesh = TriMesh() myMesh.append(mayaMesh) #myMesh.write_OBJ("C:/Users/cimple/Documents/maya/projects/autoRig/scenes/testSphere.obj") for i in range(len(myMesh.vs)): sphere = mc.polySphere(r=0.1*myMesh.vtxDistDic[i]) vtxPos = myMesh.vs[i] mc.move(vtxPos[0], vtxPos[1], vtxPos[2], absolute=True)
def _exportMeshes(self): selectedMesh = [] # First: Duplicate and combine all of the selected meshes. This is done to create a temporary # object that can be used if self.accessMode == MPxFileTranslator.kExportAccessMode: selectedMesh = mc.ls(typ='mesh') # export selection elif self.accessMode == MPxFileTranslator.kExportActiveAccessMode: selectedMesh = mc.ls(sl=1) else: raise ThreeJsError('Unsupported access mode: {0}'.format(self.accessMode)) if(len(selectedMesh) == 0): print "*** No mesh selected. Quitting export." return print "Selected Items:" for mesh in selectedMesh: print " - " + mesh # If the model is animated, then set the frame to the starting frame. if self.options['animation']: # Make sure the animation is set to it's starting frame startTime = MAnimControl.animationStartTime() animationFrame = MTime(startTime) MAnimControl.setCurrentTime(animationFrame) # If we are exporting animations or weights generate the bone hierarchy. if self.options['animation'] or self.options['skinWeights']: self._generateBoneHierarchy(); # duplicate the mesh and convert all faces to triangles. duplicatedMesh = mc.duplicate(selectedMesh) for mesh in duplicatedMesh: mc.polyTriangulate(mesh) # Select the duplicate as the active mesh mc.select(mesh) sel = MSelectionList() MGlobal.getActiveSelectionList(sel) mDag = MDagPath() mObj = MObject() sel.getDagPath(0, mDag, mObj) self._exportGeometryData(mDag, mObj) # Delete the duplicate since we are done with it. mc.delete(mesh) # Select the original mesh and get a DAG for animation processing. if self.options['animation'] or self.options['skinWeights']: for mesh in selectedMesh: relatives= mc.listRelatives(mesh, shapes=True) if(len(relatives) == 0): print "*** Could not find mesh for selection [" + mesh + "]" continue print "Found Mesh in Selection: " + relatives[0] mc.select(relatives[0]); sel = MSelectionList() MGlobal.getActiveSelectionList(sel) mDag = MDagPath() mObj = MObject() sel.getDependNode(0, mObj) sel.getDagPath(0, mDag) self._exportSkinData(mDag, mObj) if self.options['animation']: self._exportAnimationData();
def drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length,old_circle,ShereBool): if(iteration < branches): iteration = iteration + 1 print("iteration= "+str(iteration)) #Draw circle and extrude based on parameters R=radius*math.fabs(math.sin(iteration)) R=radius+iteration-math.fabs(iteration) R=10-iteration circle( nr=(nrX, nrY, nrZ), c=(cX, cY, cZ), r=radius) shape = cmds.ls(sl=True)[0] circleReffArr.append(shape) cmds.select( clear=True ) cmds.select( old_circle, add=True ) cmds.select( shape, add=True ) cmds.loft( c=0, ch=1, d=3, ss=1, rsn=True, ar=1, u=1, rn=0, po=0) extrudedSurface = cmds.ls(sl=True)[0] print("nrX= "+str(nrX)+" nrY= "+str(nrY)+" nrZ= "+str(nrZ)) if(0==True): cmds.polySphere(createUVs=2, sy=20, ch=1, sx=20, r=radius*10) SpherePoly = cmds.ls(sl=True)[0] cmds.move( cX, cY, cZ, SpherePoly, absolute=True ) #extrudedSurface=extrude (shape, et=0, d= (nrX, nrY, nrZ), l= length) #extrudedSurface=extrude (shape, extrudeType=0, d= (nrX, nrY, nrZ), l= length,polygon=1) #extrudedSurface=extrude (shape, extrudeType=0, d= (nrX, nrY, nrZ), l= length) cmds.nurbsToPoly(extrudedSurface, uss=1, ch=1, ft=0.01, d=0.1, pt=0, f=0, mrt=0, mel=0.001, ntr=0, vn=3, pc=1000, chr=0.9, un=3, vt=1, ut=1, ucr=0, cht=0.01, mnd=1, es=0, uch=0) delete(extrudedSurface) #print("extrudedSurface= "+str(extrudedSurface)) extrudedPoly = cmds.ls(sl=True)[0] print("extrudedPoly= "+str(extrudedPoly)) cmds.polyCloseBorder(extrudedPoly, ch=1)# Close Holl hollface = cmds.ls(sl=True)[0] print("hollface= "+str(hollface)) cmds.polyTriangulate(hollface, ch=1) cmds.select(extrudedPoly) #cmds.polyClean(extrudedPoly) #cmds.eval('polyCleanupArgList 4 { "0","1","1","1","1","1","1","1","0","1e-05","0","1e-05","0","1e-05","0","1","1","0" };') #Delete the base circle, keep the cylinder #delete(shape) #Define direction vector and normalize vector = MVector(nrX, nrY, nrZ) vector.normalize() cX = cX + (length*vector.x) cY = cY + (length*vector.y) cZ = cZ + (length*vector.z) randX = random.randint(0, 1)*2 -1 randY = random.randint(0, 1)*2 -1 randZ = random.randint(0, 1)*2 -1 #Random direction vector #For X, Y, Z, ( -1 or 1 )*angle + (randint from -angleVariance to +angleVariance) nrX = nrX + ((angle*randX) + random.randint(0, angleVariance*2) - angleVariance)/100.0 nrY = nrY + ((angle*randY) + random.randint(0, angleVariance*2) - angleVariance)/100.0 nrZ = nrZ + ((angle*randZ) + random.randint(0, angleVariance*2) - angleVariance)/100.0 #Length and Radius based on factor + (randint from -variance to +variance) length = length * (lengthFactor + (random.randint(0, lengthVariance*2*100)/100.0) - lengthVariance) radius = radius * (radiusFactor + (random.randint(0, radiusVariance*2*100)/100.0) - radiusVariance) #Draw first branch drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length,shape,False) #drawBranch(iteration, cX, cY, cZ, 0, 1, 0, radius, length,shape,False) #-------------------- #Use opposite base angle from previous branch nrX = nrX + ((angle*randX*-1) + random.randint(0, angleVariance*2) - angleVariance)/100.0 nrY = nrY + ((angle*randY*-1) + random.randint(0, angleVariance*2) - angleVariance)/100.0 nrZ = nrZ + ((angle*randZ*-1) + random.randint(0, angleVariance*2) - angleVariance)/100.0 length = length * (lengthFactor + (random.randint(0, lengthVariance*2*100)/100.0) - lengthVariance) radius = radius * (radiusFactor + (random.randint(0, radiusVariance*2*100)/100.0) - radiusVariance) #Draw second branch drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length,shape,True)
def autoQuad(): cmds.polyTriangulate() cmds.polyQuad()
def triangulate(): mc.polyTriangulate()
def splitMesh(mesh, assetName): """ Take the given mesh and break it into chunks based on the influence weights of each bone. For example, if the mesh was a leg that was skinned to a thigh bone, a calf bone, and a foot bone, this function will split the leg mesh into three new meshes, one for each major influence. This is sometimes known as an "anim mesh" :param mesh: name of mesh to split up :param assetName: name of character or rig (the name given on publish) :return: a list of the newly created meshes """ # get mesh's skinCluster skinCluster = riggingUtils.findRelatedSkinCluster(mesh) # get the influences in that skinCluster influences = cmds.skinCluster(skinCluster, q=True, inf=True) # create a group if it doesn't exist if not cmds.objExists(assetName + "_animMeshGrp"): cmds.group(empty=True, name=assetName + "_animMeshGrp") newMeshes = [] # loop through each influence, creating a mesh for that influnece is applicable for influence in influences: # create a new mesh if cmds.objExists(mesh + "_" + influence): cmds.warning("Mesh with name: " + mesh + "_" + influence + " already exists. Skipping.") else: newMesh = cmds.duplicate(mesh, name=mesh + "_" + influence)[0] # unlock attrs so we can add a constraint later for attr in [".tx", ".ty", ".tz", ".rx", ".ry", ".rz"]: cmds.setAttr(newMesh + attr, lock=False) # if there is only 1 influence, constrain the entire mesh as is if len(influences) <= 1: cmds.parentConstraint(influence, newMesh, mo=True) # otherwise, loop through each influence getting the components affected by that influence else: verts = [] notWeighted = [] for i in range(cmds.polyEvaluate(mesh, v=True)): value = cmds.skinPercent(skinCluster, mesh + ".vtx[" + str(i) + "]", transform=influence, q=True) if value > 0.5: verts.append(newMesh + ".vtx[" + str(i) + "]") else: notWeighted.append(newMesh + ".vtx[" + str(i) + "]") # if the amount of non-weighted verts is the same as the number of verts in the mesh, delete the mesh. if len(notWeighted) == cmds.polyEvaluate(mesh, v=True): cmds.delete(newMesh) if verts: # select all verts cmds.select(newMesh + ".vtx[*]") # Convert the selection to contained faces if len(verts) != cmds.polyEvaluate(mesh, v=True): # unselect the verts we want to keep, convert remaining to faces and delete cmds.select(verts, tgl=True) cmds.select( cmds.polyListComponentConversion(fv=True, tf=True, internal=False)) cmds.delete() # constrain mesh to influence, parent mesh to group cmds.parentConstraint(influence, newMesh, mo=True) cmds.parent(newMesh, assetName + "_animMeshGrp") # fill holes, triangulate, and smooth normals cmds.polyCloseBorder(newMesh, ch=False) cmds.polyTriangulate(newMesh, ch=False) cmds.polySoftEdge(newMesh, a=90, ch=False) newMeshes.append(newMesh) return (newMeshes)
def voxelize(mesh_name, division_level): """ Voxelize the given mesh. mesh_name: the name of the mesh division_level: the number of times to subdivide the initial bounding box. """ # Get the bouding box for the mesh min_x, min_y, min_z, max_x, max_y, max_z =\ cmds.exactWorldBoundingBox(mesh_name) cx = (max_x + min_x)/2.0 cy = (max_y + min_y)/2.0 cz = (max_z + min_z)/2.0 hx = (max_x - min_x)/2.0 hy = (max_y - min_y)/2.0 hz = (max_z - min_z)/2.0 hl = max([hx, hy, hz]) # Subdivide the bounding boxes until we've reached the desired subdiv level root_aabb = satTest.AABB(cx,cy,cz,hl,hl,hl) voxel_lattice = [root_aabb] while voxel_lattice: current_voxel = voxel_lattice.pop(0) if current_voxel.subdivs < division_level: voxel_lattice.extend(current_voxel.subdivide()) continue voxel_lattice.append(current_voxel) break # Triangluate the mesh. #@TODO: probably best to implment this without modifying the original mesh, # but then we need to implement our own polygon --> triangle subdivison. cmds.polyTriangulate(mesh_name, ch=1) # Loop over each face in the mesh, and find which boxes it intersects. vox_map = {} faces = cmds.ls('%s.f[*]'%mesh_name, fl=True) i = 0 initializeProgressWindow("Voxelizing Mesh", len(faces)) for face in faces: if not updateProgressWindow(i, len(faces)): break verts = cmds.ls(cmds.polyListComponentConversion(face, tv=True), fl=True) v0 = cmds.xform(verts[0], t=True, q=True) v1 = cmds.xform(verts[1], t=True, q=True) v2 = cmds.xform(verts[2], t=True, q=True) tri_verts = v0+v1+v2 tri = satTest.Triangle(*tri_verts) for voxel in voxel_lattice: try: is_filled = vox_map[voxel.center] continue except KeyError: pass if tri.intersects(voxel): vox_map[voxel.center] = voxel.half_vector i += 1 # Fill in the voxels voxel_group = '%s_vox_group'%mesh_name cmds.group(name=voxel_group, em=True) for i, ((lx, ly, lz), (sx, sy, sz)) in enumerate(vox_map.items()): scale_factor = sx/hx cname = '%s_vox_%d'%(mesh_name, i) cmds.polyCube(name=cname) cmds.xform(cname, translation=[lx,ly,lz]) cmds.parent(cname, voxel_group) killProgressWindow()
def generate(pts): """Takes in a list of tuples (set of 3D points) and generates a polygon model""" cmds.polyCreateFacet(name="shirt", p=points) cmds.polyTriangulate() cmds.polySubdivideFacet(dv=SUBDIVISIONS) cmds.polyTriangulate()
def polyTriangulate(*args, **kwargs): res = cmds.polyTriangulate(*args, **kwargs) if not kwargs.get('query', kwargs.get('q', False)): res = _factories.maybeConvert(res, _general.PyNode) return res
def triangulate_surface(): mc.polyTriangulate(ch=True) mc.select("Landscape_0") return True
def CER_TestCreate(): cmds.polySphere(name='Object001') cmds.polyTriangulate('Object001', ch=True)
def CER_TestCreateMultiple(): cmds.polySphere(name='Object001') cmds.move(-0.5, -1, -0.5, 'Object001') cmds.polySphere(name='Object002') CER_MergeAllMeshes() cmds.polyTriangulate('FinalModel', ch=True)
def finalize(): cmds.polyTriangulate(cch=True, nds=0) cmds.xform(p=True, ztp=True) cmds.makeIdentity(apply=True, t=1, r=1, s=1, n=0) cmds.delete(ch=True)
def process_keyframe_animation_btn(*args): # 377 reinit_vars() # with Undo(): for selected in cm.ls(sl=1): if check_model(selected): self.static_base_meshes.append(selected) # >>>> added by Hiura bCanceled = False if len(self.static_base_meshes) > 0: for one_mesh in self.static_base_meshes: time = 0 tmp_node = cm.snapshot(one_mesh, st=time, et=time, ch=0) tmp_snap = cm.listRelatives(tmp_node, c=1)[0] tmp_snap = cm.parent(tmp_snap, w=1) cm.polySoftEdge(tmp_snap, a=180, ch=0) cm.polyTriangulate(tmp_snap, ch=0) org_num = get_vert_count(one_mesh) new_num = get_vert_count(tmp_snap) if org_num != new_num: buf = 'Warning! Vertex Number Change.\n original=' + str( org_num ) + ' new=' + str( new_num ) + '\n\nMaybe not working properly.\nContinue?' ret = cm.confirmDialog(title='Confirm', message=buf, button=['Yes', 'No'], defaultButton='Yes', cancelButton='No', dismissString='No') if ret != 'Yes': bCanceled = True cm.delete(tmp_snap) cm.delete(tmp_node) # <<<< added by Hiura if not bCanceled: if len(self.static_base_meshes) > 0: # >>>> added by Hiura gMainProgressBar = mel.eval('$tmp = $gMainProgressBar') cm.progressBar(gMainProgressBar, edit=True, beginProgress=True, isInterruptable=False, status='"VAT Converting ...', minValue=0, maxValue=100) # <<<< added by Hiura make_merge_snapshots(self.static_base_meshes) cm.progressBar(gMainProgressBar, edit=True, step=5) # added by Hiura # smooth_copy(self.morph_array[0][0], gMainProgressBar, 15) smooth_copy(self.morph_array[0], gMainProgressBar, 15) # modified by Hiura pack_vert_uvs(self.original_mesh, gMainProgressBar, 30) populate_morph_arrays(gMainProgressBar, 50) remove_meshes() cm.progressBar(gMainProgressBar, edit=True, endProgress=True) # added by Hiura render_out_textures() #.. else: cm.warning("No applicable meshes selected")
def triangulate(self): """Triangulate this mesh.""" cmds.polyTriangulate(self, constructionHistory=False)
def exportSTL(): #grab the selected object(s) selected = cmds.ls(sl=True) #only do this if there's something selected if(selected > 0): #bring up the file dialog so the user can tell you where to save this filename = cmds.fileDialog2(caption='Export selected as STL') #find the asterik in the name (stl isn't a file type in maya) extensionIndex = str(filename[0]).find("*") #append the stl extension to the filename filename = str(filename[0][0: extensionIndex]) + "STL" #open a file at the filename specified f = open(str(filename), 'w') #use this for the progress bar totalFaces = 0 #progress bar max value currentFace = 0 # progress bar current value #get total number of faces for k in range(0, len(selected)): cmds.select(selected[k]) #Convert that object to faces and select them cmds.ConvertSelectionToFaces() #get the number of faces for that object totalFaces += int(cmds.polyEvaluate(f=True)) if(cmds.window("ExportSTL", ex = True)): cmds.deleteUI("ExportSTL") window = cmds.window("ExportSTL", title="ExportSTL", width=100, height=130, s = False) cmds.columnLayout( columnAttach=('both', 5), rowSpacing=10, columnWidth=250 ) #create progress bar progressControl = cmds.progressBar(maxValue=100, width=100, vis = False) #show window cmds.showWindow(window) #for each object for k in range(0, len(selected)): #opening line for each object f.write("solid " + str(selected[k]) + "\n") #duplicate the current mesh item newObj = cmds.duplicate(selected[k]) cmds.select(newObj) #stl requires objects to be triangulated (why we duplicated the original) triangulated = cmds.polyTriangulate(newObj) #Convert that object to faces and select them cmds.ConvertSelectionToFaces() #get the number of faces selected numFaces = cmds.polyEvaluate( f=True ) for i in range(0, numFaces): #increment how much progress has been made currentFace += 1 #update the progress bar progressInc = cmds.progressBar(progressControl, edit=True, maxValue = totalFaces, pr = currentFace, vis = True) #get the normal vector of the current face normals = cmds.polyInfo(str(newObj[0])+".f[" + str(i) + "]", fn = True) normalString = normals[0][20: len(normals[0])] normalVector = normalString.split(" ") #write the normal vector values f.write("\t facet normal " + str(normalVector[0]) + " " + str(normalVector[1]) + " " + str(normalVector[2]) + "\n") f.write("\t \t outer loop \n") vertices = cmds.polyListComponentConversion(str(newObj[0]) + ".f[" + str(i) + "]", ff = True, tv = True) cmds.select(vertices) #store the vertices in an array vertices = cmds.ls(sl = True, fl = True) #for every vertex selected, write that to the file for j in range(0, len(vertices)): pp = cmds.pointPosition(vertices[j], w = True) f.write("\t \t \t vertex " + str(pp[0]) + " " + str(pp[1]) + " " + str(pp[2]) + "\n") #close the current face in the file f.write("\t \t endloop \n") f.write("\t endfacet \n") #close the current mesh in the file f.write("endsolid") #delete the duplicated object cmds.delete(newObj) #close the file f.close() #remove the progress window cmds.deleteUI("ExportSTL") #let the user know it's done cmds.headsUpMessage(str(filename) + " created.") #clear the selection cmds.select(cl=True)
import maya.cmds as cmds import json with open( "C:/Users/Michael/PycharmProjects/FacialRetargeting/configs/David_to_Louise_v2.json" ) as f: config = json.load(f) # triangulate base mesh cmds.polyTriangulate(config['maya_base_mesh_name']) # get all blendshapes' meshes mesh_list = cmds.ls(config['maya_bs_group'], dag=1, type="mesh") # get all blenshapes from blenshape group # triangualte each blendshape mesh for mesh in mesh_list: remove_letters = 5 # somehow maya adds "Shape" at the end of the mesh if 'ShapeOrig' in mesh: # ... and sometimes "ShapeOrig" remove_letters = 9 mesh_name = str(mesh[:-remove_letters]) # triangulate mesh cmds.polyTriangulate(mesh_name) # delete history cmds.delete(mesh_name, ch=True)
def FaceCapExport(*args): faceCapAvatarVersion = "0.1" faceCapAvatarScale = cmds.floatField("scaleField", q=True, v=True) faceCapBlendShapeNames = [ 'browInnerUp', 'browDown_L', 'browDown_R', 'browOuterUp_L', 'browOuterUp_R', 'eyeLookUp_L', 'eyeLookUp_R', 'eyeLookDown_L', 'eyeLookDown_R', 'eyeLookIn_L', 'eyeLookIn_R', 'eyeLookOut_L', 'eyeLookOut_R', 'eyeBlink_L', 'eyeBlink_R', 'eyeSquint_L', 'eyeSquint_R', 'eyeWide_L', 'eyeWide_R', 'cheekPuff', 'cheekSquint_L', 'cheekSquint_R', 'noseSneer_L', 'noseSneer_R', 'jawOpen', 'jawForward', 'jawLeft', 'jawRight', 'mouthFunnel', 'mouthPucker', 'mouthLeft', 'mouthRight', 'mouthRollUpper', 'mouthRollLower', 'mouthShrugUpper', 'mouthShrugLower', 'mouthClose', 'mouthSmile_L', 'mouthSmile_R', 'mouthFrown_L', 'mouthFrown_R', 'mouthDimple_L', 'mouthDimple_R', 'mouthUpperUp_L', 'mouthUpperUp_R', 'mouthLowerDown_L', 'mouthLowerDown_R', 'mouthPress_L', 'mouthPress_R', 'mouthStretch_L', 'mouthStretch_R', 'tongueOut' ] polywinkBlendShapeNames = [ 'browInnerUp', 'browDownLeft', 'browDownRight', 'browOuterUpLeft', 'browOuterUpRight', 'eyeLookUpLeft', 'eyeLookUpRight', 'eyeLookDownLeft', 'eyeLookDownRight', 'eyeLookInLeft', 'eyeLookInRight', 'eyeLookOutLeft', 'eyeLookOutRight', 'eyeBlinkLeft', 'eyeBlinkRight', 'eyeSquintLeft', 'eyeSquintRight', 'eyeWideLeft', 'eyeWideRight', 'cheekPuff', 'cheekSquintLeft', 'cheekSquintRight', 'noseSneerLeft', 'noseSneerRight', 'jawOpen', 'jawForward', 'jawLeft', 'jawRight', 'mouthFunnel', 'mouthPucker', 'mouthLeft', 'mouthRight', 'mouthRollUpper', 'mouthRollLower', 'mouthShrugUpper', 'mouthShrugLower', 'mouthClose', 'mouthSmileLeft', 'mouthSmileRight', 'mouthFrownLeft', 'mouthFrownRight', 'mouthDimpleLeft', 'mouthDimpleRight', 'mouthUpperUpLeft', 'mouthUpperUpRight', 'mouthLowerDownLeft', 'mouthLowerDownRight', 'mouthPressLeft', 'mouthPressRight', 'mouthStretchLeft', 'mouthStretchRight', 'tongueOut' ] exportLog = '' selection = cmds.ls(sl=True) # Check sceme units currentUnit = cmds.currentUnit(q=True, linear=True) if currentUnit == 'm': exportLog = UpdateExportLog( exportLog + 'Info: Scene is set to meters.\nInfo: Scale should be set to 100.0 approximately.\n' ) elif currentUnit == 'cm': exportLog = UpdateExportLog( exportLog + 'Info: Scene is set to centimeters.\nInfo: Scale should be set to 1.0 approximately.\n' ) else: exportLog = UpdateExportLog( exportLog + 'Warning: Scene units not set to meters or centimeters.\nWarning: Adjust scale to match default Avatar.\n' ) # Check if selection is a single mesh. if (len(selection) != 1): exportLog = UpdateExportLog(exportLog + 'Error: Please select the root object.\n') return # Check if selection is mesh my_shapes = cmds.listRelatives(shapes=True) if not my_shapes: exportLog = UpdateExportLog( exportLog + 'Error: Selection does not contain a mesh.\n') return # Check if the mesh has a parent. parentNode = cmds.listRelatives(selection[0], p=True) if (parentNode): exportLog = UpdateExportLog( exportLog + 'Error: Object must not have a parent. Did you select the root?\n') return # Check if the selected mesh has only one blendShape node. my_history = cmds.listHistory(selection[0]) my_blendShape_nodes = cmds.ls(my_history, type='blendShape') if len(my_blendShape_nodes) != 1: exportLog = UpdateExportLog( exportLog + 'Error: Root object needs one blendshape node.\n') return # List all children. my_children = cmds.listRelatives(selection[0], children=True, type='transform') # If children have rotation, free it. if my_children: for child in my_children: cmds.makeIdentity(child, apply=True, translate=False, rotate=True, scale=True) # Check if mesh has a single material. cmds.select(selection[0]) pm.hyperShade(shaderNetworksSelectMaterialNodes=True) my_materials = cmds.ls(sl=True) if len(my_materials) != 1: exportLog = UpdateExportLog( exportLog + 'Warning: FaceCap Custom avatar can have only 1 material.\n') # Check for compatible blendshape naming and reset all blendshape nodes to 0. my_blendShape_names = cmds.listAttr(my_blendShape_nodes[0] + '.w', m=True) compatibleBlendShapeNames = [] for shapeName in my_blendShape_names: cmds.setAttr(my_blendShape_nodes[0] + "." + shapeName, 0) if shapeName in faceCapBlendShapeNames or shapeName in polywinkBlendShapeNames: compatibleBlendShapeNames.append(shapeName) else: exportLog = UpdateExportLog(exportLog + ('Warning: the name for blendshape ' + shapeName + ' is not compatible with FaceCap.\n')) if (len(compatibleBlendShapeNames) == 0): exportLog = UpdateExportLog( exportLog + 'Error: No blendshapes with compatible naming found.\n') return else: exportLog = UpdateExportLog(exportLog + ('Info: Found ' + str(len(compatibleBlendShapeNames)) + ' blendshapes with compatible naming.\n')) # Get the output file faceCapFilter = "*.FCA" exportPath = cmds.fileDialog2(fileFilter=faceCapFilter, caption='Pick export file *.FCA', fileMode=0) if not exportPath: exportLog = UpdateExportLog(exportLog + 'Export canceled.\n') return # Create list of objects containing meshes to export exportList = [] exportListLog = str(selection[0]) exportList.append(selection[0]) if my_children: for child in my_children: my_shapes = cmds.listRelatives(child, shapes=True) if len(my_shapes) != 0: exportListLog += ',' + str(child) exportList.append(child) exportLog = UpdateExportLog(exportLog + ('Exporting: ' + exportListLog + '.\n')) # Open a file file1 = open(exportPath[0], "w") # Write file header and version file1.write("FaceCapAvatarVersion," + faceCapAvatarVersion + "\n") # Write amount of objects file1.write("Objects," + str(len(exportList)) + "\n") # Tell user to wait exportLog = UpdateExportLog(exportLog + '\nPlease wait') cmds.refresh() # Get frozen pivot offset for the root. rootOffset = cmds.xform(selection[0], sp=True, q=True, ws=True) # Export objects for objectIndex in range(0, len(exportList)): # Get local translation for object tx = Rnd((cmds.getAttr(str(exportList[objectIndex]) + '.tx') - rootOffset[0]) * faceCapAvatarScale) ty = Rnd((cmds.getAttr(str(exportList[objectIndex]) + '.ty') - rootOffset[1]) * faceCapAvatarScale) tz = Rnd((cmds.getAttr(str(exportList[objectIndex]) + '.tz') - rootOffset[2]) * faceCapAvatarScale) # Write object header and position if objectIndex == 0: file1.write('Object,BlendshapeObject,0,0,0\n') else: file1.write('Object,' + str(exportList[objectIndex]).strip() + ',' + str(tx) + ',' + str(ty) + ',' + str(tz) + '\n') # Triangulate mesh cmds.select(exportList[objectIndex]) triangulationNode = cmds.polyTriangulate() # Store mesh details cmds.select(exportList[objectIndex]) vtxCount = cmds.polyEvaluate(v=True) uvCount = cmds.polyEvaluate(uv=True) faceCount = cmds.polyEvaluate(f=True) shapeCount = len(compatibleBlendShapeNames) # Get frozen pivot offset vtxOffset = cmds.xform(exportList[objectIndex], sp=True, q=True, ws=True) # Write vertex data file1.write("Vtx," + str(vtxCount) + "\n") for i in range(0, vtxCount): position = cmds.xform(exportList[objectIndex] + ".vtx[" + str(i) + "]", q=True, objectSpace=True, t=True) if objectIndex == 0: position[0] -= vtxOffset[0] position[1] -= vtxOffset[1] position[2] -= vtxOffset[2] file1.write( str(Rnd(faceCapAvatarScale * position[0])) + "," + str(Rnd(faceCapAvatarScale * position[1])) + "," + str(Rnd(faceCapAvatarScale * position[2])) + "\n") exportLog = UpdateExportLog(exportLog + '.') # Write normal data file1.write("Normals," + str(vtxCount) + "\n") for i in range(0, vtxCount): normalsX = cmds.polyNormalPerVertex(exportList[objectIndex] + ".vtx[" + str(i) + "]", q=True, x=True) normalsY = cmds.polyNormalPerVertex(exportList[objectIndex] + ".vtx[" + str(i) + "]", q=True, y=True) normalsZ = cmds.polyNormalPerVertex(exportList[objectIndex] + ".vtx[" + str(i) + "]", q=True, z=True) if normalsX and normalsY and normalsZ: normalX = sum(normalsX) / len(normalsX) normalY = sum(normalsY) / len(normalsY) normalZ = sum(normalsZ) / len(normalsZ) file1.write( str(Rnd(normalX)) + "," + str(Rnd(normalY)) + "," + str(Rnd(normalZ)) + "\n") else: normalX = 0 normalY = 1 normalZ = 0 file1.write( str(Rnd(normalX)) + "," + str(Rnd(normalY)) + "," + str(Rnd(normalZ)) + "\n") exportLog = UpdateExportLog(exportLog + '.') # Write uv data file1.write("Uvs," + str(uvCount) + "\n") for i in range(0, uvCount): cmds.select(exportList[objectIndex] + ".map[" + str(i) + "]") uvs = cmds.polyEditUV(q=True) file1.write(str(Rnd(uvs[0])) + "," + str(Rnd(uvs[1])) + "\n") exportLog = UpdateExportLog(exportLog + '.') # Write face data, uv indices need to be re-ordered. file1.write("Faces," + str(faceCount) + "\n") for f in range(0, faceCount): orderedVtxIndices = cmds.polyInfo( (exportList[objectIndex] + ".f[" + str(f) + "]"), fv=True)[0] orderedVtxIndices = orderedVtxIndices.split() orderedVtxIndices = [int(i) for i in orderedVtxIndices[2:]] uvIndices = maya.cmds.polyListComponentConversion( (exportList[objectIndex] + ".f[" + str(f) + "]"), fromFace=True, toUV=True) if uvIndices: uvIndices = maya.cmds.filterExpand(uvIndices, sm=35, ex=True) uvIndices = [ int(i.split("map")[-1].strip("[]")) for i in uvIndices ] else: exportLog = UpdateExportLog( exportLog + '\nError: Model needs to have 1 uv channel.' + exportPath[0] + '\n') exportLog = UpdateExportLog( exportLog + '\nError: output file is incomplete.' + exportPath[0] + '\n\n') sys.exit() tmpDict = {} for t in uvIndices: vtxFromUv = maya.cmds.polyListComponentConversion( (exportList[objectIndex] + ".map[" + str(t) + "]"), fromUV=True, toVertex=True) index = int(vtxFromUv[0].split("[")[-1].split("]")[0]) tmpDict[index] = t orderedPolyUvs = [] for vtx in orderedVtxIndices: orderedPolyUvs.append(tmpDict[vtx]) file1.write( str(orderedVtxIndices[0]) + ":" + str(orderedVtxIndices[1]) + ":" + str(orderedVtxIndices[2]) + "," + str(orderedPolyUvs[0]) + ":" + str(orderedPolyUvs[1]) + ":" + str(orderedPolyUvs[2])) file1.write("\n") exportLog = UpdateExportLog(exportLog + '.') # Write shape data if objectIndex == 0: file1.write("Shapes," + str(shapeCount) + "\n") for i in range(0, shapeCount): # Change polywink blendshape naming to FaceCap naming outputShapeName = compatibleBlendShapeNames[i] if 'Left' in outputShapeName: outputShapeName = outputShapeName.replace('Left', '_L') elif 'Right' in outputShapeName: outputShapeName = outputShapeName.replace('Right', '_R') file1.write("ShapeName," + outputShapeName + "\n") cmds.setAttr( my_blendShape_nodes[0] + "." + compatibleBlendShapeNames[i], 1) for j in range(0, vtxCount): position = cmds.xform(exportList[objectIndex] + ".vtx[" + str(j) + "]", q=True, objectSpace=True, t=True) position[0] -= vtxOffset[0] position[1] -= vtxOffset[1] position[2] -= vtxOffset[2] file1.write( str(Rnd(faceCapAvatarScale * position[0])) + "," + str(Rnd(faceCapAvatarScale * position[1])) + "," + str(Rnd(faceCapAvatarScale * position[2])) + "\n") cmds.setAttr( my_blendShape_nodes[0] + "." + compatibleBlendShapeNames[i], 0) exportLog = UpdateExportLog(exportLog + '.') # Remove triangulation mode cmds.delete(triangulationNode) # Close file file1.close() cmds.select(selection[0]) exportLog = UpdateExportLog(exportLog + '\nResult: ' + exportPath[0] + '\n') exportLog = UpdateExportLog(exportLog + 'Finished.\n')