Delete DUAL_MESH.PY
This commit is contained in:
		| @@ -1,345 +0,0 @@ | |||||||
| # ##### BEGIN GPL LICENSE BLOCK ##### |  | ||||||
| # |  | ||||||
| #  This program is free software; you can redistribute it and/or |  | ||||||
| #  modify it under the terms of the GNU General Public License |  | ||||||
| #  as published by the Free Software Foundation; either version 2 |  | ||||||
| #  of the License, or (at your option) any later version. |  | ||||||
| # |  | ||||||
| #  This program is distributed in the hope that it will be useful, |  | ||||||
| #  but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
| #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
| #  GNU General Public License for more details. |  | ||||||
| # |  | ||||||
| #  You should have received a copy of the GNU General Public License |  | ||||||
| #  along with this program; if not, write to the Free Software Foundation, |  | ||||||
| #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |  | ||||||
| # |  | ||||||
| # ##### END GPL LICENSE BLOCK ##### |  | ||||||
|  |  | ||||||
| # --------------------------------- DUAL MESH -------------------------------- # |  | ||||||
| # -------------------------------- version 0.3 ------------------------------- # |  | ||||||
| #                                                                              # |  | ||||||
| # Convert a generic mesh to its dual. With open meshes it can get some wired   # |  | ||||||
| # effect on the borders.                                                       # |  | ||||||
| #                                                                              # |  | ||||||
| #                        (c)   Alessandro Zomparelli                           # |  | ||||||
| #                                    (2017)                                    # |  | ||||||
| #                                                                              # |  | ||||||
| # http://www.co-de-it.com/                                                     # |  | ||||||
| #                                                                              # |  | ||||||
| # ############################################################################ # |  | ||||||
|  |  | ||||||
|  |  | ||||||
| import bpy |  | ||||||
| from bpy.types import Operator |  | ||||||
| from bpy.props import ( |  | ||||||
|         BoolProperty, |  | ||||||
|         EnumProperty, |  | ||||||
|         ) |  | ||||||
| import bmesh |  | ||||||
| from .utils import * |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class dual_mesh_tessellated(Operator): |  | ||||||
|     bl_idname = "object.dual_mesh_tessellated" |  | ||||||
|     bl_label = "Dual Mesh" |  | ||||||
|     bl_description = ("Generate a polygonal mesh using Tessellate. (Non-destructive)") |  | ||||||
|     bl_options = {'REGISTER', 'UNDO'} |  | ||||||
|  |  | ||||||
|     apply_modifiers : BoolProperty( |  | ||||||
|         name="Apply Modifiers", |  | ||||||
|         default=True, |  | ||||||
|         description="Apply object's modifiers" |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     source_faces : EnumProperty( |  | ||||||
|             items=[ |  | ||||||
|                 ('QUAD', 'Quad Faces', ''), |  | ||||||
|                 ('TRI', 'Triangles', '')], |  | ||||||
|             name="Source Faces", |  | ||||||
|             description="Source polygons", |  | ||||||
|             default="QUAD", |  | ||||||
|             options={'LIBRARY_EDITABLE'} |  | ||||||
|             ) |  | ||||||
|  |  | ||||||
|     def execute(self, context): |  | ||||||
|         auto_layer_collection() |  | ||||||
|         ob0 = context.object |  | ||||||
|         name1 = "DualMesh_{}_Component".format(self.source_faces) |  | ||||||
|         # Generate component |  | ||||||
|         if self.source_faces == 'QUAD': |  | ||||||
|             verts = [(0.0, 0.0, 0.0), (0.0, 0.5, 0.0), |  | ||||||
|                     (0.0, 1.0, 0.0), (0.5, 1.0, 0.0), |  | ||||||
|                     (1.0, 1.0, 0.0), (1.0, 0.5, 0.0), |  | ||||||
|                     (1.0, 0.0, 0.0), (0.5, 0.0, 0.0), |  | ||||||
|                     (1/3, 1/3, 0.0), (2/3, 2/3, 0.0)] |  | ||||||
|             edges = [(0,1), (1,2), (2,3), (3,4), (4,5), (5,6), (6,7), |  | ||||||
|                         (7,0), (1,8), (8,7), (3,9), (9,5), (8,9)] |  | ||||||
|             faces = [(7,8,1,0), (8,9,3,2,1), (9,5,4,3), (9,8,7,6,5)] |  | ||||||
|         else: |  | ||||||
|             verts = [(0.0,0.0,0.0), (0.5,0.0,0.0), (1.0,0.0,0.0), (0.0,1.0,0.0), (0.5,1.0,0.0), (1.0,1.0,0.0)] |  | ||||||
|             edges = [(0,1), (1,2), (2,5), (5,4), (4,3), (3,0), (1,4)] |  | ||||||
|             faces = [(0,1,4,3), (1,2,5,4)] |  | ||||||
|  |  | ||||||
|         # check pre-existing component |  | ||||||
|         try: |  | ||||||
|             _verts = [0]*len(verts)*3 |  | ||||||
|             __verts = [c for co in verts for c in co] |  | ||||||
|             ob1 = bpy.data.objects[name1] |  | ||||||
|             ob1.data.vertices.foreach_get("co",_verts) |  | ||||||
|             for a, b in zip(_verts, __verts): |  | ||||||
|                 if abs(a-b) > 0.0001: |  | ||||||
|                     raise ValueError |  | ||||||
|         except: |  | ||||||
|             me = bpy.data.meshes.new("Dual-Mesh")  # add a new mesh |  | ||||||
|             me.from_pydata(verts, edges, faces) |  | ||||||
|             me.update(calc_edges=True, calc_edges_loose=True) |  | ||||||
|             if self.source_faces == 'QUAD': n_seams = 8 |  | ||||||
|             else: n_seams = 6 |  | ||||||
|             for i in range(n_seams): me.edges[i].use_seam = True |  | ||||||
|             ob1 = bpy.data.objects.new(name1, me) |  | ||||||
|             context.collection.objects.link(ob1) |  | ||||||
|             # fix visualization issue |  | ||||||
|             context.view_layer.objects.active = ob1 |  | ||||||
|             ob1.select_set(True) |  | ||||||
|             bpy.ops.object.editmode_toggle() |  | ||||||
|             bpy.ops.object.editmode_toggle() |  | ||||||
|             ob1.select_set(False) |  | ||||||
|             # hide component |  | ||||||
|             ob1.hide_select = True |  | ||||||
|             ob1.hide_render = True |  | ||||||
|             ob1.hide_viewport = True |  | ||||||
|         ob = convert_object_to_mesh(ob0,False,False) |  | ||||||
|         ob.name = 'DualMesh' |  | ||||||
|         #ob = bpy.data.objects.new("DualMesh", convert_object_to_mesh(ob0,False,False)) |  | ||||||
|         #context.collection.objects.link(ob) |  | ||||||
|         #context.view_layer.objects.active = ob |  | ||||||
|         #ob.select_set(True) |  | ||||||
|         ob.tissue_tessellate.component = ob1 |  | ||||||
|         ob.tissue_tessellate.generator = ob0 |  | ||||||
|         ob.tissue_tessellate.gen_modifiers = self.apply_modifiers |  | ||||||
|         ob.tissue_tessellate.merge = True |  | ||||||
|         ob.tissue_tessellate.bool_dissolve_seams = True |  | ||||||
|         if self.source_faces == 'TRI': ob.tissue_tessellate.fill_mode = 'FAN' |  | ||||||
|         bpy.ops.object.update_tessellate() |  | ||||||
|         ob.location = ob0.location |  | ||||||
|         ob.matrix_world = ob0.matrix_world |  | ||||||
|         return {'FINISHED'} |  | ||||||
|  |  | ||||||
|     def invoke(self, context, event): |  | ||||||
|         return context.window_manager.invoke_props_dialog(self) |  | ||||||
|  |  | ||||||
| class dual_mesh(Operator): |  | ||||||
|     bl_idname = "object.dual_mesh" |  | ||||||
|     bl_label = "Convert to Dual Mesh" |  | ||||||
|     bl_description = ("Convert a generic mesh into a polygonal mesh. (Destructive)") |  | ||||||
|     bl_options = {'REGISTER', 'UNDO'} |  | ||||||
|  |  | ||||||
|     quad_method : EnumProperty( |  | ||||||
|             items=[('BEAUTY', 'Beauty', |  | ||||||
|                     'Split the quads in nice triangles, slower method'), |  | ||||||
|                     ('FIXED', 'Fixed', |  | ||||||
|                     'Split the quads on the 1st and 3rd vertices'), |  | ||||||
|                     ('FIXED_ALTERNATE', 'Fixed Alternate', |  | ||||||
|                     'Split the quads on the 2nd and 4th vertices'), |  | ||||||
|                     ('SHORTEST_DIAGONAL', 'Shortest Diagonal', |  | ||||||
|                     'Split the quads based on the distance between the vertices') |  | ||||||
|                     ], |  | ||||||
|             name="Quad Method", |  | ||||||
|             description="Method for splitting the quads into triangles", |  | ||||||
|             default="FIXED", |  | ||||||
|             options={'LIBRARY_EDITABLE'} |  | ||||||
|             ) |  | ||||||
|     polygon_method : EnumProperty( |  | ||||||
|             items=[ |  | ||||||
|                 ('BEAUTY', 'Beauty', 'Arrange the new triangles evenly'), |  | ||||||
|                 ('CLIP', 'Clip', |  | ||||||
|                  'Split the polygons with an ear clipping algorithm')], |  | ||||||
|             name="Polygon Method", |  | ||||||
|             description="Method for splitting the polygons into triangles", |  | ||||||
|             default="BEAUTY", |  | ||||||
|             options={'LIBRARY_EDITABLE'} |  | ||||||
|             ) |  | ||||||
|     preserve_borders : BoolProperty( |  | ||||||
|             name="Preserve Borders", |  | ||||||
|             default=True, |  | ||||||
|             description="Preserve original borders" |  | ||||||
|             ) |  | ||||||
|     apply_modifiers : BoolProperty( |  | ||||||
|             name="Apply Modifiers", |  | ||||||
|             default=True, |  | ||||||
|             description="Apply object's modifiers" |  | ||||||
|             ) |  | ||||||
|  |  | ||||||
|     def execute(self, context): |  | ||||||
|         mode = context.mode |  | ||||||
|         if mode == 'EDIT_MESH': |  | ||||||
|             mode = 'EDIT' |  | ||||||
|         act = context.active_object |  | ||||||
|         if mode != 'OBJECT': |  | ||||||
|             sel = [act] |  | ||||||
|             bpy.ops.object.mode_set(mode='OBJECT') |  | ||||||
|         else: |  | ||||||
|             sel = context.selected_objects |  | ||||||
|         doneMeshes = [] |  | ||||||
|  |  | ||||||
|         for ob0 in sel: |  | ||||||
|             if ob0.type != 'MESH': |  | ||||||
|                 continue |  | ||||||
|             if ob0.data.name in doneMeshes: |  | ||||||
|                 continue |  | ||||||
|             ob = ob0 |  | ||||||
|             mesh_name = ob0.data.name |  | ||||||
|  |  | ||||||
|             # store linked objects |  | ||||||
|             clones = [] |  | ||||||
|             n_users = ob0.data.users |  | ||||||
|             count = 0 |  | ||||||
|             for o in bpy.data.objects: |  | ||||||
|                 if o.type != 'MESH': |  | ||||||
|                     continue |  | ||||||
|                 if o.data.name == mesh_name: |  | ||||||
|                     count += 1 |  | ||||||
|                     clones.append(o) |  | ||||||
|                 if count == n_users: |  | ||||||
|                     break |  | ||||||
|  |  | ||||||
|             if self.apply_modifiers: |  | ||||||
|                 bpy.ops.object.convert(target='MESH') |  | ||||||
|             ob.data = ob.data.copy() |  | ||||||
|             bpy.ops.object.select_all(action='DESELECT') |  | ||||||
|             ob.select_set(True) |  | ||||||
|             context.view_layer.objects.active = ob0 |  | ||||||
|             bpy.ops.object.mode_set(mode='EDIT') |  | ||||||
|  |  | ||||||
|             # prevent borders erosion |  | ||||||
|             bpy.ops.mesh.select_mode( |  | ||||||
|                     use_extend=False, use_expand=False, type='EDGE' |  | ||||||
|                     ) |  | ||||||
|             bpy.ops.mesh.select_non_manifold( |  | ||||||
|                     extend=False, use_wire=False, use_boundary=True, |  | ||||||
|                     use_multi_face=False, use_non_contiguous=False, |  | ||||||
|                     use_verts=False |  | ||||||
|                     ) |  | ||||||
|             bpy.ops.mesh.extrude_region_move( |  | ||||||
|                     MESH_OT_extrude_region={"mirror": False}, |  | ||||||
|                     TRANSFORM_OT_translate={"value": (0, 0, 0)} |  | ||||||
|                     ) |  | ||||||
|  |  | ||||||
|             bpy.ops.mesh.select_mode( |  | ||||||
|                     use_extend=False, use_expand=False, type='VERT', |  | ||||||
|                     action='TOGGLE' |  | ||||||
|                     ) |  | ||||||
|             bpy.ops.mesh.select_all(action='SELECT') |  | ||||||
|             bpy.ops.mesh.quads_convert_to_tris( |  | ||||||
|                     quad_method=self.quad_method, ngon_method=self.polygon_method |  | ||||||
|                     ) |  | ||||||
|             bpy.ops.mesh.select_all(action='DESELECT') |  | ||||||
|             bpy.ops.object.mode_set(mode='OBJECT') |  | ||||||
|             bpy.ops.object.modifier_add(type='SUBSURF') |  | ||||||
|             ob.modifiers[-1].name = "dual_mesh_subsurf" |  | ||||||
|             while True: |  | ||||||
|                 bpy.ops.object.modifier_move_up(modifier="dual_mesh_subsurf") |  | ||||||
|                 if ob.modifiers[0].name == "dual_mesh_subsurf": |  | ||||||
|                     break |  | ||||||
|  |  | ||||||
|             bpy.ops.object.modifier_apply( |  | ||||||
|                     apply_as='DATA', modifier='dual_mesh_subsurf' |  | ||||||
|                     ) |  | ||||||
|  |  | ||||||
|             bpy.ops.object.mode_set(mode='EDIT') |  | ||||||
|             bpy.ops.mesh.select_all(action='DESELECT') |  | ||||||
|  |  | ||||||
|             verts = ob.data.vertices |  | ||||||
|  |  | ||||||
|             bpy.ops.object.mode_set(mode='OBJECT') |  | ||||||
|             verts[-1].select = True |  | ||||||
|             bpy.ops.object.mode_set(mode='EDIT') |  | ||||||
|             bpy.ops.mesh.select_more(use_face_step=False) |  | ||||||
|  |  | ||||||
|             bpy.ops.mesh.select_similar( |  | ||||||
|                 type='EDGE', compare='EQUAL', threshold=0.01) |  | ||||||
|             bpy.ops.mesh.select_all(action='INVERT') |  | ||||||
|  |  | ||||||
|             bpy.ops.mesh.dissolve_verts() |  | ||||||
|             bpy.ops.mesh.select_all(action='DESELECT') |  | ||||||
|  |  | ||||||
|             bpy.ops.mesh.select_non_manifold( |  | ||||||
|                 extend=False, use_wire=False, use_boundary=True, |  | ||||||
|                 use_multi_face=False, use_non_contiguous=False, use_verts=False) |  | ||||||
|             bpy.ops.mesh.select_more() |  | ||||||
|  |  | ||||||
|             # find boundaries |  | ||||||
|             bpy.ops.object.mode_set(mode='OBJECT') |  | ||||||
|             bound_v = [v.index for v in ob.data.vertices if v.select] |  | ||||||
|             bound_e = [e.index for e in ob.data.edges if e.select] |  | ||||||
|             bound_p = [p.index for p in ob.data.polygons if p.select] |  | ||||||
|             bpy.ops.object.mode_set(mode='EDIT') |  | ||||||
|  |  | ||||||
|             # select quad faces |  | ||||||
|             context.tool_settings.mesh_select_mode = (False, False, True) |  | ||||||
|             bpy.ops.mesh.select_face_by_sides(number=4, extend=False) |  | ||||||
|  |  | ||||||
|             # deselect boundaries |  | ||||||
|             bpy.ops.object.mode_set(mode='OBJECT') |  | ||||||
|             for i in bound_v: |  | ||||||
|                 context.active_object.data.vertices[i].select = False |  | ||||||
|             for i in bound_e: |  | ||||||
|                 context.active_object.data.edges[i].select = False |  | ||||||
|             for i in bound_p: |  | ||||||
|                 context.active_object.data.polygons[i].select = False |  | ||||||
|  |  | ||||||
|             bpy.ops.object.mode_set(mode='EDIT') |  | ||||||
|  |  | ||||||
|             context.tool_settings.mesh_select_mode = (False, False, True) |  | ||||||
|             bpy.ops.mesh.edge_face_add() |  | ||||||
|             context.tool_settings.mesh_select_mode = (True, False, False) |  | ||||||
|             bpy.ops.mesh.select_all(action='DESELECT') |  | ||||||
|  |  | ||||||
|             # delete boundaries |  | ||||||
|             bpy.ops.mesh.select_non_manifold( |  | ||||||
|                     extend=False, use_wire=True, use_boundary=True, |  | ||||||
|                     use_multi_face=False, use_non_contiguous=False, use_verts=True |  | ||||||
|                     ) |  | ||||||
|             bpy.ops.mesh.delete(type='VERT') |  | ||||||
|  |  | ||||||
|             # remove middle vertices |  | ||||||
|             bm = bmesh.from_edit_mesh(ob.data) |  | ||||||
|             for v in bm.verts: |  | ||||||
|                 if len(v.link_edges) == 2 and len(v.link_faces) < 3: |  | ||||||
|                     v.select = True |  | ||||||
|  |  | ||||||
|             # dissolve |  | ||||||
|             bpy.ops.mesh.dissolve_verts() |  | ||||||
|             bpy.ops.mesh.select_all(action='DESELECT') |  | ||||||
|  |  | ||||||
|             # remove border faces |  | ||||||
|             if not self.preserve_borders: |  | ||||||
|                 bpy.ops.mesh.select_non_manifold( |  | ||||||
|                     extend=False, use_wire=False, use_boundary=True, |  | ||||||
|                     use_multi_face=False, use_non_contiguous=False, use_verts=False |  | ||||||
|                     ) |  | ||||||
|                 bpy.ops.mesh.select_more() |  | ||||||
|                 bpy.ops.mesh.delete(type='FACE') |  | ||||||
|  |  | ||||||
|             # clean wires |  | ||||||
|             bpy.ops.mesh.select_non_manifold( |  | ||||||
|                     extend=False, use_wire=True, use_boundary=False, |  | ||||||
|                     use_multi_face=False, use_non_contiguous=False, use_verts=False |  | ||||||
|                     ) |  | ||||||
|             bpy.ops.mesh.delete(type='EDGE') |  | ||||||
|  |  | ||||||
|             bpy.ops.object.mode_set(mode='OBJECT') |  | ||||||
|             ob0.data.name = mesh_name |  | ||||||
|             doneMeshes.append(mesh_name) |  | ||||||
|  |  | ||||||
|             for o in clones: |  | ||||||
|                 o.data = ob.data |  | ||||||
|  |  | ||||||
|         for o in sel: |  | ||||||
|             o.select_set(True) |  | ||||||
|  |  | ||||||
|         context.view_layer.objects.active = act |  | ||||||
|         bpy.ops.object.mode_set(mode=mode) |  | ||||||
|  |  | ||||||
|         return {'FINISHED'} |  | ||||||
		Reference in New Issue
	
	Block a user
	 0000OOOO0000
					0000OOOO0000