def inset_faces_individual_multiple_values(verts, faces, thicknesses, depths, edges=None, face_mask=None, props=None): # It generate Bmesh per one face, inset face into it and merge the Bmesh to output Bmesh if props is None: props = set('use_even_offset') if not face_mask: iter_face_mask = cycle([True]) else: iter_face_mask = chain(face_mask, cycle([face_mask[-1]])) verts_number = 0 iter_thick = chain(thicknesses, cycle([thicknesses[-1]])) iter_depth = chain(depths, cycle([depths[-1]])) bm_out = bmesh.new() sv = bm_out.faces.layers.int.new('sv') mask = bm_out.faces.layers.int.new('mask') for i, (f, m, t, d) in enumerate(zip(faces, iter_face_mask, iter_thick, iter_depth)): # each instance of bmesh get a lot of operative memory, they should be illuminated as fast as possible bm = bmesh_from_sv([verts[i] for i in f], [list(range(len(f)))], face_int_layers={'sv': [i], 'mask': None}) mask = bm.faces.layers.int.get('mask') if m and (t or d): res = inset_individual(bm, faces=list(bm.faces), thickness=t, depth=d, use_even_offset='use_even_offset' in props, use_interpolate=True, use_relative_offset='use_relative_offset' in props) for rf in res['faces']: rf[mask] = 1 else: for face in bm.faces: face[mask] = 2 verts_number += merge_bmeshes(bm_out, verts_number, bm) bm.free() remove_doubles(bm_out, verts=bm_out.verts, dist=1e-6) return bm_out
def inset_faces_region_multiple_values(verts, faces, thicknesses, depths, edges=None, face_mask=None, props=None): # It split mesh into islands, calculate average value of thickness and depth per island, # inserts faces into island and merge mesh into output mesh if props is None: props = {'use_even_offset', 'use_boundary'} if not face_mask: iter_face_mask = cycle([True]) else: iter_face_mask = chain(face_mask, cycle([face_mask[-1]])) face_mask = [m for _, m in zip(range(len(faces)), iter_face_mask)] thicknesses = [ t for _, t in zip(range(len(faces)), chain(thicknesses, cycle([thicknesses[-1]]))) ] depths = [ d for _, d in zip(range(len(faces)), chain(depths, cycle([depths[-1]]))) ] bm = bmesh_from_sv(verts, faces, edges, face_int_layers={ 'sv': list(range(len(faces))), 'mask': None }) sv = bm.faces.layers.int.get('sv') mask = bm.faces.layers.int.get('mask') # Split mesh to islands islands = [] ignored_faces = [] used = set() for face in bm.faces: if face in used: continue if not face_mask[face[sv]]: ignored_faces.append(face) used.add(face) continue elif not any([thicknesses[face[sv]], depths[face[sv]]]): ignored_faces.append(face) used.add(face) continue island = [] next_faces = [face] while next_faces: nf = next_faces.pop() if nf in used: continue island.append(nf) used.add(nf) for edge in nf.edges: for twin_face in edge.link_faces: if twin_face not in used: if not face_mask[twin_face[sv]]: ignored_faces.append(twin_face) used.add(twin_face) elif not any([ thicknesses[twin_face[sv]], depths[twin_face[sv]] ]): ignored_faces.append(twin_face) used.add(twin_face) else: next_faces.append(twin_face) islands.append(island) # Regenerate mesh from islands verts_number = 0 bm_out = bmesh.new() sv_out = bm_out.faces.layers.int.new('sv') mask_out = bm_out.faces.layers.int.new('mask') for island_faces in islands: # each instance of bmesh get a lot of operative memory, they should be illuminated as fast as possible bm_isl = bmesh.new() sv_isl = bm_isl.faces.layers.int.new('sv') mask_isl = bm_isl.faces.layers.int.new('mask') used_verts = dict() for face in island_faces: face_verts = [] for v in face.verts: if v not in used_verts: v_new = bm_isl.verts.new(v.co) used_verts[v] = v_new face_verts.append(v_new) else: face_verts.append(used_verts[v]) face_new = bm_isl.faces.new(face_verts) face_new[sv_isl] = face[sv] face_new[mask_isl] = face[mask] bm_isl.normal_update() thick_isl = sum([thicknesses[f[sv_isl]] for f in bm_isl.faces]) / len(island_faces) depth_isl = sum([depths[f[sv_isl]] for f in bm_isl.faces]) / len(island_faces) res = inset_region(bm_isl, faces=bm_isl.faces, thickness=thick_isl, depth=depth_isl, use_interpolate=True, **{k: True for k in props}) for rf in res['faces']: rf[mask_isl] = 1 verts_number += merge_bmeshes(bm_out, verts_number, bm_isl) bm_isl.free() for face in ignored_faces: v_news = [] for v in face.verts: v_news.append(bm_out.verts.new(v.co)) f = bm_out.faces.new(v_news) f[sv_out] = face[sv] f[mask_out] = 2 bm.free() remove_doubles(bm_out, verts=bm_out.verts, dist=1e-6) return bm_out