Example #1
0
def multi_polyQuad():
    args,counter = pm.ls(sl=True),1
    w=400
    window = pm.window(w=w,h=40)
    pm.columnLayout()
    progressMessage=pm.text(l='Running through Objects...',w=w)
    argName=pm.text(l='',w=w)
    progressControl = pm.progressBar(isInterruptable=True, beginProgress=True, maxValue=len(args), width=w)
    window.show()
    for arg in args:
        if pm.progressBar(progressControl, query=True, isCancelled=True ) :
            break
        progressMessage.setLabel('Cleaning up then Quadding object '+str(counter)+'/'+str(len(args))+':')
        argName.setLabel(arg)
        pm.select(arg,r=True)
        #cleanup mesh
        mel.eval('polyCleanupArgList 3 { "0","1","0","0","0","0","0","0","0","1e-05","0","1e-05","0","1e-05","0","1","0" };')
        #quad all polies
        pm.polyQuad(arg, a=30, kgb=False, ktb=False,khe=False,ws=True,ch=False)
        #merge all verts
        pm.polyMergeVertex((arg+'.vtx[0:'+str(pm.polyEvaluate(arg,v=True))+']'), d=.001,am=True,ch=0)
        pm.polyNormalPerVertex(arg,ufn=True)
        pm.polySoftEdge(arg,angle=68, ch=0)
        pm.progressBar(progressControl, edit=True, step=1)
        counter+=1
    pm.progressBar(progressControl, edit=True, endProgress=True)
    pm.select(args, r=True)
    pm.selectMode(o=True)
    window.delete()
Example #2
0
    def unlock_normal(self, target, prefix=True, suffix=False):

        if suffix:
            prefix = False

        if prefix:
            prefix = 'unlockNorm_'
            suffix = ''
        elif suffix:
            prefix = ''
            suffix = '_unlockNorm'

        target_list = target
        if not isinstance(target_list, list):
            target_list = [target_list]

        for target in target_list:
            target = pm.PyNode(target)
            target_shape = self.get_visible_shape(target)
            old_unlockNorm_list = pm.listHistory(target_shape, type = 'polyNormalPerVertex')
            pm.polyNormalPerVertex(target, unFreezeNormal = True)
            new_unlockNorm_list = pm.listHistory(target_shape, type = 'polyNormalPerVertex')
            for unlockNorm in new_unlockNorm_list:
                if unlockNorm not in old_unlockNorm_list:
                    unlockNorm.rename(prefix + target.stripNamespace() + suffix)
Example #3
0
def bake_shape_to_vertex_normals(source_obj, dest_obj):
    '''
    Stores blend shape information into the vertex normals between 2 objects.
    Given 2 objects with the same topology, gather all vertex offsets and bake the vector into the vertex normal

    Args:
        source_obj (PyNode): Maya scene object that is the blend shape target
        dest_obj (PyNode): Original maya scene object
    '''
    source_vert_list = [
        Vector(pm.xform(x, q=True, t=True, ws=True)) for x in source_obj.vtx
    ]
    dest_vert_list = [
        Vector(pm.xform(x, q=True, t=True, ws=True)) for x in dest_obj.vtx
    ]

    rgb_vector_list, longest_length = v1_shared.shared_utils.bake_vertex_color_data(
        source_vert_list, dest_vert_list, False)

    for i, vtx in enumerate(dest_obj.vtx):
        r = Vector(list(rgb_vector_list[i])).length3D() / longest_length
        pm.polyColorPerVertex(vtx, rgb=[r, 0, 0])
        pm.polyNormalPerVertex(vtx, xyz=list(rgb_vector_list[i]))

    print(longest_length / 10)

    pm.polyOptions(dest_obj, cs=True)
Example #4
0
def unlockNormal():
    curr = time.time()
    mesh = pm.ls(sl=1,dag=1,ni=1,type="mesh")
    if not mesh:
        return
    
    mesh = mesh[0]
    smooth_list = []
    
    # NOTE OpenMaya 加速遍历过程 
    # NOTE Benchmark 选择400个面的基础球体
    # NOTE OpenMaya elapsed time : 0.010999917984 s
    # NOTE PyMel    elapsed time : 2.47600007057 s

    # NOTE OpenMaya 方案
    sel_list = om.MSelectionList()
    sel_list.add(mesh.fullPathName())
    dagPath = sel_list.getDagPath(0)

    edge_itr = om.MItMeshEdge(dagPath)
    vert_itr = om.MItMeshVertex(dagPath)
    
    while not edge_itr.isDone():
        flag = 0
        for i in range(2):
            vert_idx = edge_itr.vertexId(i)
            vert_itr.setIndex(vert_idx)
            for nor_1,nor_2 in combinations(vert_itr.getNormals(),2):
                if (nor_1 - nor_2).length() < 0.001:
                    flag += 1
                    break
            else:
                continue
        
        if flag == 2:
            edge = "%s.e[%s]" % (dagPath.fullPathName(),edge_itr.index())
            smooth_list.append(edge) 
        edge_itr.next()
    
    # NOTE PyMel 方案
    # for edge in mesh.edges:
    #     flag = 0
    #     for vtx in edge.connectedVertices():
    #         for nor_1,nor_2 in combinations(vtx.getNormals(),2):
    #             if (nor_1 - nor_2).length() < 0.001:
    #                 flag += 1
    #                 break
    #         else:
    #             continue

    #     if flag == 2:
    #         smooth_list.append(edge)

    pm.polyNormalPerVertex(mesh,ufn=1)
    pm.polySoftEdge(smooth_list,a=180,ch=0)
    # pm.select(smooth_list)

    print "elapsed time : %s s" % (time.time() - curr)
Example #5
0
 def cleanMe(self): 
     cmds.viewFit()
     object = pm.ls(tr=True)[0:6]
     for x in object:
         pm.select(x)
         pm.polyNormalPerVertex(x, ufn=True)
         pm.polySoftEdge(x, a=180, ch=1)
         pm.bakePartialHistory(x, ppt=True)
         pm.select(cl=True)
Example #6
0
def fixNormals(*args):
    geos = pm.ls(type='mesh')

    for geo in geos:
        if geo.isIntermediate():
            continue

        pm.polyNormalPerVertex(geo + '.vtx[*]', unFreezeNormal=True)

    return 'ok'
    def create_object_openmaya():
        global imported_object

        cmds.select(all=True, hierarchy=True)
        current_objs = cmds.ls(selection=True)

        new_mesh = om.MFnMesh()

        merge_vertices = True
        point_tolerance = 0.0001

        # create polys
        for p in range(0, len(imported_object.polys), 1):
            poly_list = []
            v_count = len(imported_object.polys[p])
            poly_list = om.MPointArray()
            poly_list.setLength(v_count)
            for i in range(v_count):
                poly_list.set(
                    imported_object.omVertices[int(
                        imported_object.polys[p][i])], i)
            new_mesh.addPolygon(poly_list, merge_vertices, point_tolerance)

        # create weightmaps
        if len(imported_object.weightMap) > 0:
            for v in range(0, imported_object.vertexCount, 1):
                c = imported_object.weightMap[v]
                vColor = om.MColor(c, c, c, c)
                new_mesh.setVertexColor(vColor, v)

        # Set mesh edits
        new_mesh.updateSurface()

        cmds.select(all=True, hierarchy=True)
        cmds.select(current_objs, deselect=True)
        mesh = pm.selected()[0]
        # create vertex normal map
        if len(imported_object.vertexNormals) > 0:
            for v in range(0, imported_object.vertexNormalsCount, 1):
                values = imported_object.vertexNormals[v]
                vertex_normal_vector = values[0]
                polygon_id = int(values[1])
                vert_id = int(values[2])
                try:
                    pm.select(mesh.vtxFace[vert_id][polygon_id])
                    pm.polyNormalPerVertex(xyz=vertex_normal_vector)
                except IndexError, e:
                    print e
Example #8
0
def apply_voxel_weighting(obj, voxel_data, max_iterations, min_distance):
    start_time = time.clock()

    main_progress_bar = pm.mel.eval('$tmp = $gMainProgressBar')
    pm.progressBar(main_progress_bar,
                   edit=True,
                   beginProgress=True,
                   isInterruptable=True,
                   status='Applying Skin Weights...',
                   maxValue=obj.vtx.count())

    voxel_size = voxel_data['voxel_size']
    joint_list = [
        pm.nt.Joint(obj.namespace() + x) for x in voxel_data['joint_list']
    ]

    skin_cluster = find_skin_cluster(obj) if find_skin_cluster(
        obj) else pm.skinCluster([obj] + joint_list, toSelectedBones=True)

    for index in xrange(0, obj.vtx.count()):
        if pm.progressBar(main_progress_bar, query=True, isCancelled=True):
            break
        pm.progressBar(main_progress_bar, edit=True, step=1)

        vertex_index_string = obj.name() + ".vtx[{0}]".format(index)

        vert_ws_vector = v1_math.vector.Vector(
            pm.xform(vertex_index_string, q=True, ws=True, t=True))
        voxel_vector, voxel_pos = v1_shared.skin_weight_utils.get_voxel_vector(
            vert_ws_vector, voxel_size)
        normal_vector = v1_math.vector.Vector(
            pm.polyNormalPerVertex(vertex_index_string,
                                   q=True,
                                   xyz=True,
                                   relative=True)[:3])

        voxel_list = [voxel_vector]
        voxel_list = v1_shared.skin_weight_utils.get_initial_search_voxels(
            voxel_list, voxel_vector, voxel_pos, voxel_size, normal_vector)
        weight_entry = v1_shared.skin_weight_utils.find_matching_point_from_voxels(
            vert_ws_vector, voxel_list, voxel_data, max_iterations,
            min_distance)

        if weight_entry:
            weighted_joint_list = [
                pm.nt.Joint(obj.namespace() + x) for x in weight_entry[2]
            ]
            pm.skinPercent(skin_cluster,
                           vertex_index_string,
                           normalize=False,
                           transformValue=zip(weighted_joint_list,
                                              weight_entry[1]))

    pm.select(obj)
    pm.mel.removeUnusedInfluences()

    pm.progressBar(main_progress_bar, edit=True, endProgress=True)

    print time.clock() - start_time
Example #9
0
def matchVertexNormals():
    """
    Match the 2 selected vertex normals of 2 different meshes.
    """

    try:
        src, tgt = pm.ls( hl=1 )
    except ValueError:
        assert False, "must have source and target meshes hilighted"


    sel_verts = lsSelectedVerts()
    if len( sel_verts ) != 2:
        assert False, "must have 2 verts selected"

    if sel_verts[0].node().getParent() == src:
        src_v = sel_verts[0]
    elif sel_verts[1].node().getParent() == src:
        src_v = sel_verts[1]
    else:
        assert False, "no vert selected from source mesh (%s)" % src

    if sel_verts[0].node().getParent() == tgt:
        tgt_v = sel_verts[0]
    elif sel_verts[1].node().getParent() == tgt:
        tgt_v = sel_verts[1]
    else:
        assert False, "no vert selected from target mesh (%s)" % tgt

    n = src_v.getNormals()[0]

    # if the transform is scaled in the x axis
    if bool( src.getScale()[0] < 0 ) is not bool( tgt.getScale()[0] < 0 ):
        n = n * [-1, 1, 1]

    pm.select( tgt_v, r=1 )
    pm.polyNormalPerVertex( xyz=n )

    pm.select( ( src_v, tgt_v ), r=1 )
Example #10
0
 def __getitem__(self,item):
     vtxFace = self.mesh.vtxFace[item]
     return {face_idx:pm.polyNormalPerVertex(vtxFace[face_idx],q=1,normalXYZ=1) for _,face_idx in vtxFace.indicesIter()}
Example #11
0
def exportSkin(meshes=None, path=None):
    """
    Exports the given mesh nodes as a skyrim skin fbx.
    If no meshes are given the current selected meshes will be used. If no meshes are selected all meshes skinned
    to the root skeleton will be used.
    
    Args:
        meshes(list): A list of meshes to export. 
        path(str): The destination fbx path. 

    Returns:
        str: The exported file path.
    """
    path = path or saveFbxDialog('Save Skin Dialog', dir=getSceneCharacterAssetDirectory())

    # Get the root skeleton
    root = getRootJoint()
    if root is None:
        raise RootJointException('Export rig failed, could not find a root joint in the scene.')
    rootSkeleton = [root] + root.listRelatives(ad=True, type='joint')

    def getSkinnedMeshes():
        clusters = set()
        for joint in rootSkeleton:
            for cluster in pmc.ls(pmc.listConnections(joint), type='skinCluster'):
                clusters.add(cluster)
        return [pmc.skinCluster(cluster, geometry=True, q=True)[0] for cluster in clusters]

    meshes = meshes or pmc.selected() or getSkinnedMeshes()
    meshes = getMeshes(meshes)

    if len(meshes) > 1:
        raise NotImplementedError('Multiple meshes selected for export. Currently we only support one mesh per skin.')

    # Check max influences
    for mesh in meshes:
        if not _checkMaxInfluences(mesh):
            raise MaxInfluenceException('Failed to export "%s". Skinning contains more than 4 influences.' % mesh)

    try:
        pmc.undoInfo(openChunk=True)

        # Set vertex colors to white
        for mesh in meshes:
            pmc.polyColorPerVertex(mesh, colorRGB=[1, 1, 1], a=1)

        # To fix certain issues with skinning we need to mess with the normals
        for mesh in meshes:
            pmc.bakePartialHistory(mesh, prePostDeformers=True)  # Delete Non-deformer history
            pmc.polyNormalPerVertex(mesh, unFreezeNormal=True)  # Unlock the normals
            pmc.polySoftEdge(mesh, a=180)  # Soften the normals
            pmc.bakePartialHistory(mesh, prePostDeformers=True)  # Delete Non-deformer history
            pmc.polyNormalPerVertex(mesh, freezeNormal=True)  # Lock the normals
            pmc.polySoftEdge(mesh, a=0)  # Harden the normals
            pmc.bakePartialHistory(mesh, prePostDeformers=True)  # Delete Non-deformer history

        # Remove all joint constraints
        constraints = root.listRelatives(ad=True, type='constraint')
        if len(constraints) > 0:
            pmc.delete(constraints)

        # Disconnect message connections
        for joint in rootSkeleton:
            joint.message.disconnect()
            if not joint.hasAttr(MATCH_ATTR_NAME):
                continue
            for input in joint.attr(MATCH_ATTR_NAME).inputs(plugs=True):
                input.disconnect(joint.attr(MATCH_ATTR_NAME))

        exportFbx(rootSkeleton + [mesh.getParent() for mesh in meshes], path=path)

    finally:
        pmc.undoInfo(closeChunk=True)
        pmc.undo()

    # Export nif
    ckcmd.importskin(path, os.path.dirname(path))
 def resetNormal(self):
     pm.polyNormalPerVertex(ufn=True)
def unlockNormal(thersold=0.05):

    curr = time.time()

    sel = pm.ls(sl=1, dag=1, ni=1, type="mesh")
    if not sel:
        return

    sel = sel[0]

    smooth_list = []
    hard_list = []
    sp_list = {}

    # pm.progressWindow()

    # NOTE OpenMaya 加速遍历过程
    sel_list = om.MSelectionList()
    sel_list.add(sel.fullPathName())
    dagPath = sel_list.getDagPath(0)

    # NOTE 获取 mesh 所有的法线信息
    mesh_normal = {}
    itr = om.MItMeshFaceVertex(dagPath)
    while not itr.isDone():
        face_id = itr.faceId()
        vert_id = itr.vertexId()
        normal = itr.getNormal()

        if not mesh_normal.has_key(vert_id):
            mesh_normal[vert_id] = {}
        mesh_normal[vert_id][face_id] = normal
        itr.next()

    face_itr = om.MItMeshPolygon(dagPath)
    edge_itr = om.MItMeshEdge(dagPath)
    vert_itr = om.MItMeshVertex(dagPath)
    while not edge_itr.isDone():

        if edge_itr.onBoundary():
            edge_itr.next()
            continue

        smooth_flag = 0
        hard_flag = 0
        for i in range(2):
            vert_idx = edge_itr.vertexId(i)

            face_list = edge_itr.getConnectedFaces()

            if len(face_list) != 2:
                print dagPath, edge_itr.index()
                raise RuntimeError(
                    u"model edge should not have 3 faces connected")

            face_1, face_2 = face_list

            normal_1 = mesh_normal[vert_idx][face_1]
            normal_2 = mesh_normal[vert_idx][face_2]

            # NOTE 法线分叉 说明是 硬边
            if normal_1 != normal_2:
                hard_flag += 1
                continue

            vert_itr.setIndex(vert_idx)

            vert_avg_normal = om.MVector(0.0, 0.0, 0.0)
            edge_avg_normal = om.MVector(0.0, 0.0, 0.0)
            face_list = vert_itr.getConnectedFaces()
            for face in face_list:
                face_itr.setIndex(face)
                normal = face_itr.getNormal()

                if face == face_1:
                    face_1_normal = normal
                    edge_avg_normal += normal
                elif face == face_2:
                    face_2_normal = normal
                    edge_avg_normal += normal

                vert_avg_normal += normal
            vert_avg_normal = vert_avg_normal / len(face_list)
            edge_avg_normal = edge_avg_normal / 2

            vert_avg_1 = (vert_avg_normal - normal_1).length()
            vert_avg_2 = (vert_avg_normal - normal_2).length()
            edge_avg_1 = (edge_avg_normal - normal_1).length()
            edge_avg_2 = (edge_avg_normal - normal_2).length()
            # NOTE 判断顶点是否近似 average
            if (vert_avg_1 < thersold and vert_avg_2 < thersold)\
            or (edge_avg_1 < thersold and edge_avg_2 < thersold):
                smooth_flag += 1
            else:
                # NOTE 过滤 非 hard
                _normal_1 = (face_1_normal - normal_1).length()
                _normal_2 = (face_2_normal - normal_2).length()
                if _normal_1 < thersold * 5 and _normal_2 < thersold * 5:
                    hard_flag += 1
                else:
                    vertex = "%s.vtx[%s]" % (dagPath.fullPathName(), vert_idx)
                    if vertex not in sp_list:
                        sp_list[vertex] = normal_1

        edge = "%s.e[%s]" % (dagPath.fullPathName(), edge_itr.index())
        # NOTE 两个点 smooth  (百分百smooth)
        if smooth_flag > 1:
            smooth_list.append(edge)
        if hard_flag > 0:
            hard_list.append(edge)

        edge_itr.next()

    if not hard_list:
        return

    # # NOTE 解锁法线
    # pm.polyNormalPerVertex(sel,ufn=1)

    # # NOTE 添加软边
    # pm.polySoftEdge(sel,a=180,ch=0)

    # # NOTE 添加硬边
    # pm.polySoftEdge(hard_list,a=0,ch=0)

    # # NOTE 添加硬边
    # pm.polySoftEdge(sel,a=0,ch=0)

    # NOTE 解锁法线
    pm.polyNormalPerVertex(sel, ufn=1)

    # NOTE 添加软边
    pm.polySoftEdge(smooth_list, a=180, ch=0)

    for vtx, normal in sp_list.items():
        pm.polyNormalPerVertex(vtx, xyz=list(normal))

    print "elapsed time : %s s" % (time.time() - curr)
getSel  = pm.ls(os=1)
vtxGrp = pm.ls(pm.polyListComponentConversion(getSel,fe=1,tv=1),fl=1)
vtxNum = len(vtxGrp)

vtxPosGrp = [pm.xform(vtx, q=True, ws=True, t=True)for vtx in vtxGrp]

tmpPoly = mc.polyCreateFacet(p=[tuple(vec) for vec in vtxPosGrp ])[0]
pm.xform(tmpPoly,cp=1)
centerPos = mc.xform(tmpPoly, q=True, ws=True, rp=True)
distGrp = [((vec[0] - centerPos[0]) ** 2 + (vec[1] - centerPos[1]) ** 2 + (vec[2] - centerPos[2]) ** 2) ** 0.5 for vec in vtxPosGrp]
dist = sum(distGrp)/vtxNum

circle = pm.circle(s=vtxNum, r=dist, c=(0, 0, 0), d=3, ch=False)[0]
pm.xform(circle, ws=True, t=tuple(centerPos))

wu = (vtxPosGrp[0][0] - centerPos[0]),(vtxPosGrp[0][1] - centerPos[1]),(vtxPosGrp[0][2] - centerPos[2])

pm.normalConstraint(tmpPoly,circle,aim=[0,0,1],u=[0,1,0],wu=(0,1,0))

e2vInfos= pm.polyInfo(getSel,ev=1)
e2vDict = {}
for info in e2vInfos:
    evList = [ int(i) for i in re.findall('\\d+', info) ]
    e2vDict.update(dict([(evList[0], evList[1:])]))


# average normal
vtxGrp = pm.mel.eval("PolySelectConvert 3;")
avNmGrp = pm.polyNormalPerVertex(getSel,q=1,xyz=1)
Example #15
0
def unlockNormal(sel, thersold=0.05):

    smooth_list = set()
    edit_list = set()

    # # NOTE 执行一个 mesh 命令 - 更新模型数据 避免获取的法线数据不对
    # pm.polyConnectComponents(sel,ch=0)

    # NOTE OpenMaya 加速遍历过程
    sel_list = om.MSelectionList()
    sel_list.add(sel.fullPathName())
    dagPath = sel_list.getDagPath(0)

    # NOTE 获取 mesh 所有的法线信息
    mesh_normal = {}
    itr = om.MItMeshFaceVertex(dagPath)
    while not itr.isDone():
        face_id = itr.faceId()
        vert_id = itr.vertexId()
        normal = itr.getNormal()

        if not mesh_normal.has_key(vert_id):
            mesh_normal[vert_id] = {}
        mesh_normal[vert_id][face_id] = normal
        itr.next()

    pm.progressWindow(title='Unlock normal',
                      progress=0.0,
                      status='%s - colleting data...' % dagPath.fullPathName(),
                      isInterruptable=True)

    mesh = om.MFnMesh(dagPath)
    face_itr = om.MItMeshPolygon(dagPath)
    edge_itr = om.MItMeshEdge(dagPath)
    vert_itr = om.MItMeshVertex(dagPath)
    while not edge_itr.isDone():

        if edge_itr.onBoundary():
            edge_itr.next()
            continue

        edge_id = edge_itr.index()

        if pm.progressWindow(query=True, isCancelled=True):
            pm.progressWindow(endProgress=1)
            return
        amount = float(edge_id) / edge_itr.count() * 100
        pm.progressWindow(e=1, progress=amount)

        smooth_flag = 0
        for i in range(2):
            vert_id = edge_itr.vertexId(i)

            face_list = edge_itr.getConnectedFaces()

            if len(face_list) != 2:
                edge = "%s.e[%s]" % (dagPath.fullPathName(), edge_id)
                print edge
                msg = u"模型的边存在同时连接三个面\n边序号为 : %s" % edge
                QtWidgets.QMessageBox.warning(
                    QtWidgets.QApplication.activeWindow(), u"警告", msg)
                raise EdgeError(msg)

            face_1, face_2 = face_list

            normal_1 = mesh_normal[vert_id][face_1]
            normal_2 = mesh_normal[vert_id][face_2]

            # NOTE 法线不分叉 说明是 软边边
            if normal_1 == normal_2:
                vert_itr.setIndex(vert_id)

                vert_avg_normal = om.MVector(0.0, 0.0, 0.0)
                edge_avg_normal = om.MVector(0.0, 0.0, 0.0)
                vtx_face_list = vert_itr.getConnectedFaces()
                for face in vtx_face_list:
                    face_itr.setIndex(face)
                    normal = face_itr.getNormal()

                    if face in face_list:
                        edge_avg_normal += normal

                    vert_avg_normal += normal
                vert_avg_normal = vert_avg_normal / len(vtx_face_list)
                edge_avg_normal = edge_avg_normal / 2

                vert_avg_1 = (vert_avg_normal - normal_1).length()
                vert_avg_2 = (vert_avg_normal - normal_2).length()
                edge_avg_1 = (edge_avg_normal - normal_1).length()
                edge_avg_2 = (edge_avg_normal - normal_2).length()
                # NOTE 判断顶点是否近似 average
                if (vert_avg_1 < thersold and vert_avg_2 < thersold)\
                or (edge_avg_1 < thersold and edge_avg_2 < thersold):
                    smooth_flag += 1
                # NOTE 特殊调整的且统一的法线
                else:
                    edit_list.add(vert_id)
            else:
                # NOTE 硬边或特殊调整的法线
                edit_list.add(vert_id)
                break

        # NOTE smooth_flag 1 为 1个点 smooth
        # NOTE smooth_flag 2 为 2个点 smooth
        if smooth_flag >= 1:
            edge = "%s.e[%s]" % (dagPath.fullPathName(), edge_id)
            smooth_list.add(edge)

        edge_itr.next()

    # NOTE 获取特殊法线要修改的数据
    pm.progressWindow(e=1,
                      progress=0.0,
                      status='%s - get edited normal...' %
                      dagPath.fullPathName())
    normal_list = []
    face_list = []
    vtx_list = []
    print "edit_list", edit_list
    for i, vert_id in enumerate(edit_list):

        if pm.progressWindow(query=True, isCancelled=True):
            pm.progressWindow(endProgress=1)
            return
        amount = float(i) / len(edit_list) * 100
        pm.progressWindow(e=1, progress=amount)

        for face_id, normal in mesh_normal[vert_id].items():
            normal_list.append(normal)
            face_list.append(face_id)
            vtx_list.append(vert_id)

    pm.progressWindow(e=1,
                      progress=0.0,
                      status='%s - modify normal...' % dagPath.fullPathName())
    # NOTE 解锁法线
    pm.polyNormalPerVertex(sel, ufn=1)
    pm.progressWindow(e=1, progress=10)
    # NOTE 批量设置法线
    mesh.setFaceVertexNormals(normal_list, face_list, vtx_list)
    pm.progressWindow(e=1, progress=70)

    if smooth_list:
        pm.polySoftEdge(smooth_list, a=180, ch=0)

    pm.progressWindow(endProgress=1)
def unlockNormal(thersold=0.01):

    curr = time.time()

    sel = pm.ls(sl=1, dag=1, ni=1, type="mesh")
    if not sel:
        raise

    sel = sel[0]

    smooth_list = set()
    hard_list = set()

    edit_list = []
    # pm.progressWindow()

    # NOTE OpenMaya 加速遍历过程
    sel_list = om.MSelectionList()
    sel_list.add(sel.fullPathName())
    dagPath = sel_list.getDagPath(0)

    # NOTE 获取 mesh 所有的法线信息
    mesh_normal = {}
    itr = om.MItMeshFaceVertex(dagPath)
    while not itr.isDone():
        face_id = itr.faceId()
        vert_id = itr.vertexId()
        normal = itr.getNormal(space=om.MSpace.kWorld)

        if not mesh_normal.has_key(vert_id):
            mesh_normal[vert_id] = {}
        mesh_normal[vert_id][face_id] = normal
        itr.next()

    # NOTE 解锁法线 | 添加软边
    pm.polyNormalPerVertex(sel, ufn=1)
    pm.polySoftEdge(sel, a=180, ch=0)

    itr = om.MItMeshFaceVertex(dagPath)
    while not itr.isDone():
        face_id = itr.faceId()
        vert_id = itr.vertexId()
        normal = itr.getNormal(space=om.MSpace.kWorld)

        _normal = mesh_normal[vert_id][face_id]

        if (_normal - normal).length() > thersold:
            edit_list.append([_normal, face_id, vert_id])
        else:
            vertex = "%s.vtx[%s]" % (dagPath.fullPathName(), vert_id)
            smooth_list.add(vertex)

        itr.next()

    mesh = om.MFnMesh(dagPath)
    for data in edit_list:
        _normal, face_id, vert_id = data
        try:
            mesh.setFaceVertexNormal(_normal, face_id, vert_id)
        except:
            import traceback
            traceback.print_exc()
            print vert_id, face_id
            raise

    vtx_list = []
    for vtx in smooth_list:
        vtx = pm.PyNode(vtx)
        for nor_1, nor_2 in combinations(vtx.getNormals(), 2):
            if (nor_1 - nor_2).length() > 0.001:
                break
        else:
            continue

        vtx_list.append(vtx)

    pm.polySoftEdge(vtx_list, a=180, ch=0)

    # print edit_list
    print "elapsed time : %s s" % (time.time() - curr)
def unlockNormal(thersold=0.05):

    curr = time.time()

    sel = pm.ls(sl=1, dag=1, ni=1, type="mesh")
    if not sel:
        return

    sel = sel[0]

    smooth_list = []
    hard_list = []
    smooth_vtx_list = set()
    edit_list = set()

    # NOTE OpenMaya 加速遍历过程
    sel_list = om.MSelectionList()
    sel_list.add(sel.fullPathName())
    dagPath = sel_list.getDagPath(0)

    # NOTE 获取 mesh 所有的法线信息
    mesh_normal = getMeshNormals(dagPath)

    # # NOTE 解锁法线
    # pm.polyNormalPerVertex(sel,ufn=1)
    # hard_vert_list = set()

    # itr = om.MItMeshFaceVertex(dagPath)
    # while not itr.isDone():
    #     face_id = itr.faceId()
    #     vert_id = itr.vertexId()
    #     normal  = itr.getNormal()

    #     if (normal - mesh_normal[vert_id][face_id]).length() < thersold:
    #         hard_vert_list.add("%s.vtx[%s]" % (dagPath.fullPathName(),vert_id))

    #     itr.next()

    # pm.polySoftEdge(sel,a=180,ch=0)
    # soft_vert_list = set()

    # itr = om.MItMeshFaceVertex(dagPath)
    # while not itr.isDone():
    #     face_id = itr.faceId()
    #     vert_id = itr.vertexId()
    #     normal  = itr.getNormal()

    #     if (normal - mesh_normal[vert_id][face_id]).length() < thersold:
    #         soft_vert_list.add("%s.vtx[%s]" % (dagPath.fullPathName(),vert_id))

    #     itr.next()

    # print list(hard_vert_list)
    # print list(soft_vert_list)

    # return
    # NOTE -----------------

    pm.progressWindow(title='Unlock model normal',
                      progress=0.0,
                      status='colleting data...',
                      isInterruptable=True)

    face_itr = om.MItMeshPolygon(dagPath)
    edge_itr = om.MItMeshEdge(dagPath)
    vert_itr = om.MItMeshVertex(dagPath)
    mesh = om.MFnMesh(dagPath)

    avg_vert_list = set()
    avg_edge_list = set()
    nonAvg_vert_list = set()
    modify_vert_list = set()
    edge_list = []
    while not vert_itr.isDone():
        vert_id = vert_itr.index()
        if pm.progressWindow(query=True, isCancelled=True):
            pm.progressWindow(endProgress=1)
            break
        amount = float(vert_id) / vert_itr.count() * 100
        pm.progressWindow(e=1, progress=amount)

        # normals = vert_itr.getNormals()
        normals = mesh_normal[vert_id].values()

        normals_set = set()

        [normals_set.add(nor.length()) for nor in normals]

        vtx = "%s.vtx[%s]" % (dagPath.fullPathName(), vert_id)
        if len(normals_set) != 1:
            for edge in vert_itr.getConnectedEdges():
                if edge not in edge_list:
                    edge_list.append("%s.e[%s]" %
                                     (dagPath.fullPathName(), edge))

            # nonAvg_vert_list.add("%s.vtx[%s]" % (dagPath.fullPathName(),vert_id))
            nonAvg_vert_list.add(vert_id)
        # else:
        #     normal = normals[0]
        #     face_list = vert_itr.getConnectedFaces()
        #     if (normal - getAvgVertNormal(face_list,face_itr)).length() > thersold:
        #         modify_vert_list.add(vtx)
        #     else:
        #         avg_vert_list.add(vtx)
        #         for edge in vert_itr.getConnectedEdges():
        #             avg_edge_list.add("%s.e[%s]" % (dagPath.fullPathName(),edge))

        vert_itr.next()

    # print nonAvg_vert_list
    # pm.select(nonAvg_vert_list)
    pm.polyNormalPerVertex(sel, ufn=1)
    pm.polySoftEdge(sel, a=180, ch=0)

    normal_list = []
    face_list = []
    vtx_list = []
    for i, vert_id in enumerate(nonAvg_vert_list):
        # if i > 20:
        #     break
        for face_id, normal in mesh_normal[vert_id].items():
            normal_list.append(normal)
            face_list.append(face_id)
            vtx_list.append(vert_id)
    # NOTE 多个设置比起单个法线设置要快很多
    mesh.setFaceVertexNormals(normal_list, face_list, vtx_list)

    # pm.select(avg_edge_list)
    # dul = pm.duplicate(sel,rr=1)[0]
    # # NOTE 解锁法线
    # pm.polyNormalPerVertex(sel,ufn=1)
    # # NOTE 添加软边
    # pm.polySoftEdge(sel,a=180,ch=0)

    # pm.select(dul,r=1)
    # pm.select(vert_list,r=1)
    # pm.transferAttributes(transferNormals=1 ,sampleSpace=4 ,searchMethod=3)

    # while not edge_itr.isDone():

    #     if edge_itr.onBoundary():
    #         edge_itr.next()
    #         continue

    #     edge_id = edge_itr.index()
    #     edge = "%s.e[%s]" % (dagPath.fullPathName(),edge_id)

    #     if pm.progressWindow( query=True, isCancelled=True ) :
    #         pm.progressWindow(endProgress=1)
    #         break
    #     amount = float(edge_id)/edge_itr.count()*100
    #     pm.progressWindow( e=1, progress=amount)

    #     smooth_flag = 0
    #     hard_flag = 0
    #     for i in range(2):
    #         vert_id = edge_itr.vertexId(i)

    #         face_list = edge_itr.getConnectedFaces()

    #         if len(face_list) != 2:
    #             print dagPath,edge_itr.index()
    #             raise RuntimeError(u"model edge should not have 3 faces connected")

    #         face_1,face_2 = face_list

    #         normal_1 = mesh_normal[vert_id][face_1]
    #         normal_2 = mesh_normal[vert_id][face_2]

    #         # vertex = "%s.vtx[%s]" % (dagPath.fullPathName(),vert_id)

    #         # NOTE 法线分叉 说明不是 软边边
    #         if normal_1 == normal_2:
    #             vert_itr.setIndex(vert_id)

    #             vert_avg_normal = om.MVector(0.0, 0.0, 0.0)
    #             edge_avg_normal = om.MVector(0.0, 0.0, 0.0)
    #             face_list = vert_itr.getConnectedFaces()
    #             for face in face_list:
    #                 face_itr.setIndex(face)
    #                 normal = face_itr.getNormal()

    #                 if face in [face_1,face_2]:
    #                     edge_avg_normal += normal

    #                 vert_avg_normal += normal
    #             vert_avg_normal = vert_avg_normal/len(face_list)
    #             edge_avg_normal = edge_avg_normal/2

    #             vert_avg_1 = (vert_avg_normal - normal_1).length()
    #             vert_avg_2 = (vert_avg_normal - normal_2).length()
    #             edge_avg_1 = (edge_avg_normal - normal_1).length()
    #             edge_avg_2 = (edge_avg_normal - normal_2).length()
    #             # NOTE 判断顶点是否近似 average
    #             if (vert_avg_1 < thersold and vert_avg_2 < thersold)\
    #             or (edge_avg_1 < thersold and edge_avg_2 < thersold):
    #                 smooth_flag += 1
    #                 smooth_vtx_list.add(vert_id)
    #             # NOTE 特殊调整的且统一的法线
    #             else:
    #                 edit_list.add(vert_id)
    #         else:
    #             # NOTE 硬边或特殊调整的法线
    #             edit_list.add(vert_id)
    #             break

    #     # NOTE 两个点 smooth  (百分百smooth)
    #     if smooth_flag > 1:
    #         smooth_list.append(edge)

    #     edge_itr.next()

    # # if not smooth_list:
    # #     return

    # pm.progressWindow( e=1,status='Unlocking...',progress=0)

    # # NOTE 解锁法线
    # pm.polyNormalPerVertex(sel,ufn=1)

    # # NOTE 添加软边
    # pm.polySoftEdge(smooth_list,a=180,ch=0)

    # mesh = om.MFnMesh(dagPath)
    # total = len(edit_list)
    # normal_list = []
    # face_list = []
    # vtx_list = []
    # for i,vert_id in enumerate(edit_list):
    #     if pm.progressWindow( query=True, isCancelled=True ) :
    #         pm.progressWindow(endProgress=1)
    #         break
    #     amount = float(i)/total * 100
    #     pm.progressWindow( e=1, progress=amount)
    #     for face_id,normal in mesh_normal[vert_id].items():
    #         normal_list.append(normal)
    #         face_list.append(face_id)
    #         vtx_list.append(vert_id)
    # # NOTE 多个设置比起单个法线设置要快很多
    # mesh.setFaceVertexNormals(normal_list,face_list,vtx_list)

    # pm.progressWindow( e=1,status='Fixing...',progress=0)

    # vtx_list = []
    # vert_itr = om.MItMeshVertex(dagPath)
    # for i,vert_id in enumerate(smooth_vtx_list):
    #     if vert_id in edit_list:
    #         continue
    #     if pm.progressWindow( query=True, isCancelled=True ) :
    #         pm.progressWindow(endProgress=1)
    #         break
    #     amount = float(i)/total * 100
    #     pm.progressWindow( e=1, progress=amount)

    #     vert_itr.setIndex(vert_id)
    #     for nor_1,nor_2 in combinations(vert_itr.getNormals(),2):
    #         if (nor_1 - nor_2).length() > thersold:
    #             break
    #     else:
    #         continue
    #     vertex = "%s.vtx[%s]" % (dagPath.fullPathName(),vert_id)
    #     vtx_list.append(vertex)

    # # pm.select(["%s.vtx[%s]" % (dagPath.fullPathName(),vert_id) for vert_id in edit_list])
    # pm.polySoftEdge(vtx_list,a=180,ch=0)

    # pm.flushUndo()
    pm.progressWindow(endProgress=1)

    print "elapsed time : %s s" % (time.time() - curr)
Example #18
0
def unlockNormal(thersold=0.05):

    curr = time.time()

    sel = pm.ls(sl=1, dag=1, ni=1, type="mesh")
    if not sel:
        return

    sel = sel[0]

    smooth_list = []
    hard_list = []
    smooth_vtx_list = set()
    edit_list = set()

    # NOTE OpenMaya 加速遍历过程
    sel_list = om.MSelectionList()
    sel_list.add(sel.fullPathName())
    dagPath = sel_list.getDagPath(0)

    # NOTE 获取 mesh 所有的法线信息
    mesh_normal = {}
    itr = om.MItMeshFaceVertex(dagPath)
    while not itr.isDone():
        face_id = itr.faceId()
        vert_id = itr.vertexId()
        normal = itr.getNormal()

        if not mesh_normal.has_key(vert_id):
            mesh_normal[vert_id] = {}
        # mesh_normal[vert_id][face_id] = [round(data,2) for data in normal]
        mesh_normal[vert_id][face_id] = normal
        itr.next()

    # output = r"F:\MayaTecent\MayaScript\model\unlockNormal\data.json"
    # with open(output,'w') as f:
    #     json.dump(mesh_normal,f,indent=4)
    # return

    pm.progressWindow(title='Unlock model normal',
                      progress=0.0,
                      status='colleting data...',
                      isInterruptable=True)

    face_itr = om.MItMeshPolygon(dagPath)
    edge_itr = om.MItMeshEdge(dagPath)
    vert_itr = om.MItMeshVertex(dagPath)
    while not edge_itr.isDone():

        if edge_itr.onBoundary():
            edge_itr.next()
            continue

        edge_id = edge_itr.index()
        edge = "%s.e[%s]" % (dagPath.fullPathName(), edge_id)

        if pm.progressWindow(query=True, isCancelled=True):
            pm.progressWindow(endProgress=1)
            break
        amount = float(edge_id) / edge_itr.count() * 100
        pm.progressWindow(e=1, progress=amount)

        smooth_flag = 0
        hard_flag = 0
        for i in range(2):
            vert_id = edge_itr.vertexId(i)

            face_list = edge_itr.getConnectedFaces()

            if len(face_list) != 2:
                print dagPath, edge_itr.index()
                raise RuntimeError(
                    u"model edge should not have 3 faces connected")

            face_1, face_2 = face_list

            normal_1 = mesh_normal[vert_id][face_1]
            normal_2 = mesh_normal[vert_id][face_2]

            # vertex = "%s.vtx[%s]" % (dagPath.fullPathName(),vert_id)

            # NOTE 法线分叉 说明不是 软边边
            if normal_1 == normal_2:
                vert_itr.setIndex(vert_id)

                vert_avg_normal = om.MVector(0.0, 0.0, 0.0)
                edge_avg_normal = om.MVector(0.0, 0.0, 0.0)
                face_list = vert_itr.getConnectedFaces()
                for face in face_list:
                    face_itr.setIndex(face)
                    normal = face_itr.getNormal()

                    if face in [face_1, face_2]:
                        edge_avg_normal += normal

                    vert_avg_normal += normal
                vert_avg_normal = vert_avg_normal / len(face_list)
                edge_avg_normal = edge_avg_normal / 2

                vert_avg_1 = (vert_avg_normal - normal_1).length()
                vert_avg_2 = (vert_avg_normal - normal_2).length()
                edge_avg_1 = (edge_avg_normal - normal_1).length()
                edge_avg_2 = (edge_avg_normal - normal_2).length()
                # NOTE 判断顶点是否近似 average
                if (vert_avg_1 < thersold and vert_avg_2 < thersold)\
                or (edge_avg_1 < thersold and edge_avg_2 < thersold):
                    smooth_flag += 1
                    smooth_vtx_list.add(vert_id)
                # NOTE 特殊调整的且统一的法线
                else:
                    edit_list.add(vert_id)
            else:
                # NOTE 硬边或特殊调整的法线
                edit_list.add(vert_id)
                break

        # NOTE 两个点 smooth  (百分百smooth)
        if smooth_flag > 1:
            smooth_list.append(edge)

        edge_itr.next()

    # if not smooth_list:
    #     return

    pm.progressWindow(e=1, status='Unlocking...', progress=0)

    # NOTE 解锁法线
    pm.polyNormalPerVertex(sel, ufn=1)

    # NOTE 添加软边
    pm.polySoftEdge(smooth_list, a=180, ch=0)

    mesh = om.MFnMesh(dagPath)
    total = len(edit_list)
    normal_list = []
    face_list = []
    vtx_list = []
    for i, vert_id in enumerate(edit_list):
        if pm.progressWindow(query=True, isCancelled=True):
            pm.progressWindow(endProgress=1)
            break
        amount = float(i) / total * 100
        pm.progressWindow(e=1, progress=amount)
        for face_id, normal in mesh_normal[vert_id].items():
            normal_list.append(normal)
            face_list.append(face_id)
            vtx_list.append(vert_id)
    # NOTE 多个设置比起单个法线设置要快很多
    mesh.setFaceVertexNormals(normal_list, face_list, vtx_list)

    pm.progressWindow(e=1, status='Fixing...', progress=0)

    vtx_list = []
    vert_itr = om.MItMeshVertex(dagPath)
    for i, vert_id in enumerate(smooth_vtx_list):
        if vert_id in edit_list:
            continue
        if pm.progressWindow(query=True, isCancelled=True):
            pm.progressWindow(endProgress=1)
            break
        amount = float(i) / total * 100
        pm.progressWindow(e=1, progress=amount)

        vert_itr.setIndex(vert_id)
        for nor_1, nor_2 in combinations(vert_itr.getNormals(), 2):
            if (nor_1 - nor_2).length() > thersold:
                break
        else:
            continue
        vertex = "%s.vtx[%s]" % (dagPath.fullPathName(), vert_id)
        vtx_list.append(vertex)

    # pm.select(["%s.vtx[%s]" % (dagPath.fullPathName(),vert_id) for vert_id in edit_list])
    pm.polySoftEdge(vtx_list, a=180, ch=0)

    pm.flushUndo()
    pm.progressWindow(endProgress=1)

    print "elapsed time : %s s" % (time.time() - curr)
Example #19
0
#
#    A tool to copy and paste normal data via the polyNormalPerVertex command and exporting that data out
#    to a text file and pasting it somewhere else.
#
##############################################################################################################################

import pymel.core as pm
import maya.OpenMayaAnim as animAPI
import maya.mel as mel

pm.ls(sl = True)
175, 350 159 149 340
pm.select(ball.f[159])
pm.select(ball.f[350])
pm.polyInfo(pm.ls(sl = True).f[350], vf = True)
pm.polyNormalPerVertex(ball.vtxFace[175][159], q = True, xyz = True)
pm.polyNormalPerVertex(ball.vtxFace[175][350], xyz = pm.polyNormalPerVertex(ball.vtxFace[175][159], q = True, xyz = True))
pm.polyNormalPerVertex(ball.vtxFace[175][340], xyz = pm.polyNormalPerVertex(ball.vtxFace[175][159], q = True, xyz = True))



def moriToolUI(mayaFalse = False):
    windowID = 'moritool'#checking if window already exists
    if pm.window(windowID, exists = True):
        pm.deleteUI(windowID)
        pm.windowPref( 'moritool', remove=True )
    pm.window(windowID, title = u'Prism 森ツール')
    
    moriToolLayout = pm.columnLayout( 'moriToolLayout', width = 400)
    vertexFrame = pm.frameLayout(label = u'頂点関連', labelIndent = 5, marginHeight = 5, parent = moriToolLayout, nch = 5)
    vertexRow = pm.rowLayout( 'vertexRow', nc = 5, width = 600)
Example #20
0
# coding:utf-8
from __future__ import unicode_literals, division, print_function

__author__ = 'timmyliang'
__email__ = '*****@*****.**'
__date__ = '2020-05-22 12:29:35'
"""

"""

import sys
import pymel.core as pm
from collections import defaultdict

sel_list = pm.ls(pm.pickWalk(d="down"), type="mesh")
sel = sel_list[0] if sel_list else sys.exit(0)

mesh_normal = defaultdict(dict)
for vtxFace in sel.vtxFace:
    vert_id, face_id = vtxFace.currentItemIndex()
    mesh_normal[vert_id][face_id] = pm.polyNormalPerVertex(vtxFace,
                                                           q=1,
                                                           normalXYZ=1)

print(mesh_normal)
Example #21
0
def unlockNormal():

    curr = time.time()

    sel = pm.ls(sl=1, dag=1, ni=1, type="mesh")
    if not sel:
        return

    sel = sel[0]
    smooth_list = []

    # pm.progressWindow()

    # NOTE OpenMaya 加速遍历过程
    sel_list = om.MSelectionList()
    sel_list.add(sel.fullPathName())
    dagPath = sel_list.getDagPath(0)

    edge_itr = om.MItMeshEdge(dagPath)
    vert_itr = om.MItMeshVertex(dagPath)

    exclude_list = []
    normal_data = {}
    while not edge_itr.isDone():
        idx = edge_itr.index()

        normal_list = []
        flag = 0
        for i in range(2):
            vert_idx = edge_itr.vertexId(i)
            vert_itr.setIndex(vert_idx)
            normals = vert_itr.getNormals()
            value = sum([round(val, 2) for vec in normals for val in vec])
            normal_list.append(value)

            # NOTE 检查列表元素是否全部相等来判断是否是完全平滑的点
            # NOTE http://www.voidcn.com/article/p-oqthigpz-bsh.html
            if normals[1:] != normals[:-1]:
                flag += 1

        if flag == 2:
            pass

        normal_data[idx] = normal_list

        edge_itr.next()

    # NOTE 解锁法线
    pm.polyNormalPerVertex(sel, ufn=1)
    # NOTE 整体添加硬边
    pm.polySoftEdge(sel, a=0)

    edge_itr = om.MItMeshEdge(dagPath)
    vert_itr = om.MItMeshVertex(dagPath)
    while not edge_itr.isDone():
        flag = 0
        idx = edge_itr.index()
        normal_list = normal_data[idx]
        for i in range(2):
            vert_idx = edge_itr.vertexId(i)
            vert_itr.setIndex(vert_idx)
            normals = vert_itr.getNormals()
            value = sum([round(val, 2) for vec in normals for val in vec])

            if value not in normal_list:
                flag += 1

        if flag == 2:
            edge = "%s.e[%s]" % (dagPath.fullPathName(), edge_itr.index())
            smooth_list.append(edge)
        edge_itr.next()

    pm.polySoftEdge(smooth_list, a=180, ch=0)
    pm.select(smooth_list)

    print "elapsed time : %s s" % (time.time() - curr)
Example #22
0
def unlockNormal():
    
    curr = time.time()

    sel = pm.ls(sl=1,dag=1,ni=1,type="mesh")
    if not sel:
        return
    
    sel = sel[0]

    smooth_list = []
    
    # pm.progressWindow()

    # NOTE OpenMaya 加速遍历过程 
    sel_list = om.MSelectionList()
    sel_list.add(sel.fullPathName())
    dagPath = sel_list.getDagPath(0)

    # NOTE 获取 mesh 所有的法线信息
    itr = om.MItMeshFaceVertex(dagPath)
    mesh_normal = {}
    while not itr.isDone():
        face_id = itr.faceId()
        vert_id = itr.vertexId()
        normal  = itr.getNormal()

        if not mesh_normal.has_key(vert_id):
            mesh_normal[vert_id] = {}
        mesh_normal[vert_id][face_id] = normal
        itr.next()

    edge_itr = om.MItMeshEdge(dagPath)
    vert_itr = om.MItMeshVertex(dagPath)
    while not edge_itr.isDone():
        
        # NOTE 测试
        # if edge_itr.index() != 43:
        #     edge_itr.next()
        #     continue

        if edge_itr.onBoundary():
            edge_itr.next()
            continue

        for i in range(2):
            vert_idx = edge_itr.vertexId(i)
            vert_itr.setIndex(vert_idx)
            try:
                face_1,face_2 = edge_itr.getConnectedFaces()
            except:
                print dagPath,edge_itr.index()
                import traceback
                traceback.print_exc()
                raise
            normal_1 = mesh_normal[vert_idx][face_1]
            normal_2 = mesh_normal[vert_idx][face_2]
            if normal_1 != normal_2:
                break
        else:
            edge = "%s.e[%s]" % (dagPath.fullPathName(),edge_itr.index())
            smooth_list.append(edge) 
            
        edge_itr.next()

        

    # NOTE 解锁法线
    pm.polyNormalPerVertex(sel,ufn=1)
    # NOTE 添加软边边
    pm.polySoftEdge(smooth_list,a=180,ch=0)

    # pm.select(smooth_list)

    print "elapsed time : %s s" % (time.time() - curr)
def unlockNormal():
    curr = time.time()
    mesh = pm.ls(sl=1, dag=1, ni=1, type="mesh")
    if not mesh:
        return

    mesh = mesh[0]
    smooth_list = []

    # pm.progressWindow()

    # NOTE OpenMaya 加速遍历过程
    sel_list = om.MSelectionList()
    sel_list.add(mesh.fullPathName())
    dagPath = sel_list.getDagPath(0)

    edge_itr = om.MItMeshEdge(dagPath)
    vert_itr = om.MItMeshVertex(dagPath)

    normal_data = {}
    while not edge_itr.isDone():
        for i in range(2):
            vert_idx = edge_itr.vertexId(i)
            vert_itr.setIndex(vert_idx)
            normals = vert_itr.getNormals()
            edges = vert_itr.getConnectedEdges()

            for nor, edge in zip(normals, edges):
                if edge == edge_itr.index():
                    if i == 0:
                        normal_list = [nor]
                    else:
                        normal_list.append(nor)
                        normal_data[edge_itr.index()] = normal_list
                    break

        # if length > 0.0001:
        #     edge = "%s.e[%s]" % (dagPath.fullPathName(),edge_itr.index())
        #     smooth_list.append(edge)
        edge_itr.next()

    # print normal_data
    # NOTE 解锁法线
    pm.polyNormalPerVertex(mesh, ufn=1)
    # NOTE 整体添加硬边
    pm.polySoftEdge(mesh, a=0, ch=0)

    edge_itr = om.MItMeshEdge(dagPath)
    while not edge_itr.isDone():
        flag = 0
        for i in range(2):
            vert_idx = edge_itr.vertexId(i)
            vert_itr.setIndex(vert_idx)
            normals = vert_itr.getNormals()
            edges = vert_itr.getConnectedEdges()

            for nor, edge in zip(normals, edges):
                if edge == edge_itr.index():
                    _nor = normal_data[edge_itr.index()][i]
                    if (nor - _nor).length() < 0.01:
                        flag += 1
                        break

        if flag == 2:
            edge = "%s.e[%s]" % (dagPath.fullPathName(), edge_itr.index())
            smooth_list.append(edge)
        edge_itr.next()

    # pm.polySoftEdge(smooth_list,a=180,ch=0)
    pm.select(smooth_list)

    print "elapsed time : %s s" % (time.time() - curr)