def calc_vert_tangents(self): """self.loop_tris.bmのBORDERフラグが立っている頂点のtangentを計算。 :return: キーがBMVert, 値が[tangent, tangent(min), tangent(max)]の 辞書を返す。tangentはself.align_edgesが偽の場合に、tangent(min)と tangent(max)はself.align_edgesが真の場合に利用する。 fallbackはVector((0, 0, 0))とする。 :rtype: dict[BMVert, list[Vector]] """ WIRE = self.WIRE BORDER = self.BORDER loop_tris = self.loop_tris vert_dict = loop_tris.vert_dict() vert_tangents = {} # eve: Vector for eve in loop_tris.bm.verts: if not loop_tris.vflags[eve] & BORDER: continue # eveに接続する二頂点(vert_next, vert_prev)を求める eve_next, eve_prev = [eed.other_vert(eve) for eed in eve.link_edges if loop_tris.eflags[eed] & BORDER] # tangent (used when self.align_edges is False) tris = [] for tri in vert_dict[eve]: efa = tri[0].face if not efa.hide: # if not self.use_outside_calculation and efa.select or \ # self.use_outside_calculation and not efa.select: # tris.append(tri) if ( self.tangent_calculation in ("selected", "individual") and efa.select or self.tangent_calculation == "deselected" and not efa.select ): tris.append(tri) tangent = LoopTris.vert_tangent(eve, eve_prev, eve_next, tris, fallback=Vector((0, 0, 0))) # tangent_min, tangent_max (used when self.align_edges is True) edges = [] for eed in eve.link_edges: if eed.hide or loop_tris.eflags[eed] & (WIRE | BORDER): continue # if not self.use_outside_calculation and eed.select or \ # self.use_outside_calculation and not eed.select: # edges.append(eed) if ( self.tangent_calculation in ("selected", "individual") and eed.select or self.tangent_calculation == "deselected" and not eed.select ): edges.append(eed) tangent_min_max = [] if len(edges) == 1: eed = edges[0] vec = eed.other_vert(eve).co - eve.co if vec.length > 0: vec.normalize() vec1 = eve_prev.co - eve.co if vec1.length > 0: vec1.normalize() f1 = vec1.cross(vec).length if f1 > EPS: tangent_min_max.append(vec / f1) vec2 = eve_next.co - eve.co if vec2.length > 0: vec2.normalize() f2 = vec2.cross(vec).length if f2 > EPS: tangent_min_max.append(vec / f2) tangent_min_max.sort(key=lambda v: v.length) if len(tangent_min_max) == 0: tangents = [tangent] * 3 elif len(tangent_min_max) == 1: tangents = [tangent] + tangent_min_max * 2 else: tangents = [tangent] + tangent_min_max vert_tangents[eve] = tangents return vert_tangents
def init(self, context): if self.use_world_coords: if self.init_called[1]: return else: if self.init_called[0]: return bm = vabm.from_object( context.active_object, apply_modifiers=self.use_mirror_modifiers, settings="PREVIEW", modifier_types={"MIRROR"}, layer_name="original", add_faces_layers=True, ) vabm.LoopTris.index_update(bm) if self.use_world_coords: bm.transform(context.active_object.matrix_world) bm.normal_update() # 必要か? # LoopTris。要素の変更は無いのでキャッシュを有効にする loop_tris = LoopTris(bm) loop_tris.bm = bm loop_tris.vert_verts = vabm.vert_verts_dict(bm) memo = loop_tris.memoize memo.read = memo.write = True loop_tris.correct() # 編集中のbmeshの頂点インデックスから、modifier適用後のbmeshの頂点を # 参照する # vert用 loop_tris.derived_vert_from_original_index = d = {} layer = bm.verts.layers.int["original"] indices = set() for eve in bm.verts: i = eve[layer] if i != -1 and i not in indices: d[i] = eve indices.add(i) # face用 loop_tris.derived_face_from_original_index = d = {} layer = bm.faces.layers.int["original"] indices = set() for efa in bm.faces: i = efa[layer] if i != -1 and i not in indices: d[i] = efa indices.add(i) # --- Shift Outline --- loop_tris.eflags = eflags = {} for eed in bm.edges: flag = 0 selected = deselected = 0 for efa in eed.link_faces: if not efa.hide: if efa.select: selected += 1 else: deselected += 1 if eed.select and not eed.hide: if selected == 0 and deselected <= 2: flag = self.WIRE elif selected == 1 and deselected <= 1: flag = self.BORDER eflags[eed] = flag loop_tris.vflags = vflags = {} for eve in bm.verts: flag = 0 wire_num = border_num = 0 for eed in eve.link_edges: f = eflags[eed] if f & self.WIRE: wire_num += 1 elif f & self.BORDER: border_num += 1 if 1 <= wire_num <= 2 and border_num == 0: flag = self.WIRE elif wire_num == 0 and border_num == 2: flag = self.BORDER vflags[eve] = flag # --- Solidify --- # 頂点のhideとtriの面積により、法線計算に使えるか否かのフラグを付ける for eve in bm.verts: eve.tag = not eve.hide for tri in loop_tris: tri.tag = not tri[0].face.hide and tri.area > EPS if self.use_world_coords: self.init_called[1] = True self._loop_tris_world = loop_tris else: self._loop_tris = loop_tris self.init_called[0] = True