diff options
author | nutti <nutti.metro@gmail.com> | 2021-03-06 11:54:33 +0300 |
---|---|---|
committer | nutti <nutti.metro@gmail.com> | 2021-03-06 11:54:33 +0300 |
commit | 117faa96af35685d72e5e01f9a386d163d874133 (patch) | |
tree | b4378f8ca2e91c93ab035ab37b05e018f601ff54 /magic_uv/common.py | |
parent | c8752443311b133f8783a6b9b2152eb7c92d06a7 (diff) |
Magic UV: Release v6.5
Updated Features
* Texture Projection
* Add option "Scaling", "Rotation", "Translation"
* Select UV
* Add Zoom Selected UV feature
* Add option "Same Polygon Threshold"
* Add option "Selection Method"
* Add option "Sync Mesh Selection"
* UV Inspection
* Add option "Same Polygon Threshold"
* Add option "Display View3D"
* Mirror UV
* Add option "Origin"
* UVW
* Add option "Force Axis"
Other Updates
* Fix bugs
Diffstat (limited to 'magic_uv/common.py')
-rw-r--r-- | magic_uv/common.py | 112 |
1 files changed, 81 insertions, 31 deletions
diff --git a/magic_uv/common.py b/magic_uv/common.py index 3817486c..1d9d55cf 100644 --- a/magic_uv/common.py +++ b/magic_uv/common.py @@ -20,8 +20,8 @@ __author__ = "Nutti <nutti.metro@gmail.com>" __status__ = "production" -__version__ = "6.4" -__date__ = "23 Oct 2020" +__version__ = "6.5" +__date__ = "6 Mar 2021" from collections import defaultdict from pprint import pprint @@ -333,7 +333,7 @@ def get_uvimg_editor_board_size(area): return (255.0, 255.0) -def calc_polygon_2d_area(points): +def calc_tris_2d_area(points): area = 0.0 for i, p1 in enumerate(points): p2 = points[(i + 1) % len(points)] @@ -345,7 +345,7 @@ def calc_polygon_2d_area(points): return fabs(0.5 * area) -def calc_polygon_3d_area(points): +def calc_tris_3d_area(points): area = 0.0 for i, p1 in enumerate(points): p2 = points[(i + 1) % len(points)] @@ -395,6 +395,23 @@ def get_faces_list(bm, method, only_selected): return faces_list +def measure_all_faces_mesh_area(bm): + if compat.check_version(2, 80, 0) >= 0: + triangle_loops = bm.calc_loop_triangles() + else: + triangle_loops = bm.calc_tessface() + + areas = {face: 0.0 for face in bm.faces} + + for loops in triangle_loops: + face = loops[0].face + area = areas[face] + area += calc_tris_3d_area([l.vert.co for l in loops]) + areas[face] = area + + return areas + + def measure_mesh_area(obj, calc_method, only_selected): bm = bmesh.from_edit_mesh(obj.data) if check_version(2, 73, 0) >= 0: @@ -406,17 +423,18 @@ def measure_mesh_area(obj, calc_method, only_selected): areas = [] for faces in faces_list: - areas.append(measure_mesh_area_from_faces(faces)) + areas.append(measure_mesh_area_from_faces(bm, faces)) return areas -def measure_mesh_area_from_faces(faces): +def measure_mesh_area_from_faces(bm, faces): + face_areas = measure_all_faces_mesh_area(bm) + mesh_area = 0.0 for f in faces: - verts = [l.vert.co for l in f.loops] - f_mesh_area = calc_polygon_3d_area(verts) - mesh_area = mesh_area + f_mesh_area + if f in face_areas: + mesh_area += face_areas[f] return mesh_area @@ -486,12 +504,34 @@ def find_images(obj, face=None, tex_layer=None): return images -def measure_uv_area_from_faces(obj, faces, uv_layer, tex_layer, +def measure_all_faces_uv_area(bm, uv_layer): + if compat.check_version(2, 80, 0) >= 0: + triangle_loops = bm.calc_loop_triangles() + else: + triangle_loops = bm.calc_tessface() + + areas = {face: 0.0 for face in bm.faces} + + for loops in triangle_loops: + face = loops[0].face + area = areas[face] + area += calc_tris_2d_area([l[uv_layer].uv for l in loops]) + areas[face] = area + + return areas + + +def measure_uv_area_from_faces(obj, bm, faces, uv_layer, tex_layer, tex_selection_method, tex_size): + + face_areas = measure_all_faces_uv_area(bm, uv_layer) + uv_area = 0.0 for f in faces: - uvs = [l[uv_layer].uv for l in f.loops] - f_uv_area = calc_polygon_2d_area(uvs) + if f not in face_areas: + continue + + f_uv_area = face_areas[f] # user specified if tex_selection_method == 'USER_SPECIFIED' and tex_size is not None: @@ -547,8 +587,8 @@ def measure_uv_area_from_faces(obj, faces, uv_layer, tex_layer, return uv_area -def measure_uv_area(obj, calc_method, tex_selection_method, tex_size, - only_selected): +def measure_uv_area(obj, calc_method, tex_selection_method, + tex_size, only_selected): bm = bmesh.from_edit_mesh(obj.data) if check_version(2, 73, 0) >= 0: bm.verts.ensure_lookup_table() @@ -565,7 +605,8 @@ def measure_uv_area(obj, calc_method, tex_selection_method, tex_size, uv_areas = [] for faces in faces_list: uv_area = measure_uv_area_from_faces( - obj, faces, uv_layer, tex_layer, tex_selection_method, tex_size) + obj, bm, faces, uv_layer, tex_layer, + tex_selection_method, tex_size) if uv_area is None: return None uv_areas.append(uv_area) @@ -946,7 +987,8 @@ class RingBuffer: # clip: reference polygon # subject: tested polygon -def __do_weiler_atherton_cliping(clip_uvs, subject_uvs, mode): +def __do_weiler_atherton_cliping(clip_uvs, subject_uvs, mode, + same_polygon_threshold): clip_uvs = RingBuffer(clip_uvs) if __is_polygon_flipped(clip_uvs): @@ -961,7 +1003,7 @@ def __do_weiler_atherton_cliping(clip_uvs, subject_uvs, mode): debug_print(subject_uvs) # check if clip and subject is overlapped completely - if __is_polygon_same(clip_uvs, subject_uvs): + if __is_polygon_same(clip_uvs, subject_uvs, same_polygon_threshold): polygons = [subject_uvs.as_list()] debug_print("===== Polygons Overlapped Completely =====") debug_print(polygons) @@ -1193,26 +1235,31 @@ def get_uv_editable_objects(context): return objs -def get_overlapped_uv_info(bm_list, faces_list, uv_layer_list, mode): +def get_overlapped_uv_info(bm_list, faces_list, uv_layer_list, + mode, same_polygon_threshold=0.0000001): # at first, check island overlapped isl = [] for bm, uv_layer, faces in zip(bm_list, uv_layer_list, faces_list): info = get_island_info_from_faces(bm, faces, uv_layer) - isl.extend([(i, uv_layer) for i in info]) + isl.extend([(i, uv_layer, bm) for i in info]) overlapped_isl_pairs = [] overlapped_uv_layer_pairs = [] - for i, (i1, uv_layer_1) in enumerate(isl): - for i2, uv_layer_2 in isl[i + 1:]: + overlapped_bm_paris = [] + for i, (i1, uv_layer_1, bm_1) in enumerate(isl): + for i2, uv_layer_2, bm_2 in isl[i + 1:]: if (i1["max"].x < i2["min"].x) or (i2["max"].x < i1["min"].x) or \ (i1["max"].y < i2["min"].y) or (i2["max"].y < i1["min"].y): continue overlapped_isl_pairs.append([i1, i2]) overlapped_uv_layer_pairs.append([uv_layer_1, uv_layer_2]) + overlapped_bm_paris.append([bm_1, bm_2]) # next, check polygon overlapped overlapped_uvs = [] - for oip, uvlp in zip(overlapped_isl_pairs, overlapped_uv_layer_pairs): + for oip, uvlp, bmp in zip(overlapped_isl_pairs, + overlapped_uv_layer_pairs, + overlapped_bm_paris): for clip in oip[0]["faces"]: f_clip = clip["face"] clip_uvs = [l[uvlp[0]].uv.copy() for l in f_clip.loops] @@ -1228,11 +1275,13 @@ def get_overlapped_uv_info(bm_list, faces_list, uv_layer_list, mode): subject_uvs = [l[uvlp[1]].uv.copy() for l in f_subject.loops] # slow operation, apply Weiler-Atherton cliping algorithm - result, polygons = __do_weiler_atherton_cliping(clip_uvs, - subject_uvs, - mode) + result, polygons = \ + __do_weiler_atherton_cliping(clip_uvs, subject_uvs, + mode, same_polygon_threshold) if result: - overlapped_uvs.append({"clip_face": f_clip, + overlapped_uvs.append({"clip_bmesh": bmp[0], + "subject_bmesh": bmp[1], + "clip_face": f_clip, "subject_face": f_subject, "clip_uv_layer": uvlp[0], "subject_uv_layer": uvlp[1], @@ -1242,14 +1291,15 @@ def get_overlapped_uv_info(bm_list, faces_list, uv_layer_list, mode): return overlapped_uvs -def get_flipped_uv_info(faces_list, uv_layer_list): +def get_flipped_uv_info(bm_list, faces_list, uv_layer_list): flipped_uvs = [] - for faces, uv_layer in zip(faces_list, uv_layer_list): + for bm, faces, uv_layer in zip(bm_list, faces_list, uv_layer_list): for f in faces: polygon = RingBuffer([l[uv_layer].uv.copy() for l in f.loops]) if __is_polygon_flipped(polygon): uvs = [l[uv_layer].uv.copy() for l in f.loops] - flipped_uvs.append({"face": f, + flipped_uvs.append({"bmesh": bm, + "face": f, "uv_layer": uv_layer, "uvs": uvs, "polygons": [polygon.as_list()]}) @@ -1257,7 +1307,7 @@ def get_flipped_uv_info(faces_list, uv_layer_list): return flipped_uvs -def __is_polygon_same(points1, points2): +def __is_polygon_same(points1, points2, threshold): if len(points1) != len(points2): return False @@ -1267,7 +1317,7 @@ def __is_polygon_same(points1, points2): for p1 in pts1: for p2 in pts2: diff = p2 - p1 - if diff.length < 0.0000001: + if diff.length < threshold: pts2.remove(p2) break else: |