License Headers: use SPDX-FileCopyrightText for mesh_tissue
[blender-addons.git] / mesh_tissue / uv_to_mesh.py
blob4acfe5840b761a19f72c25cc7ccbd25ab824d785
1 # SPDX-FileCopyrightText: 2017 Alessandro Zomparelli
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 # --------------------------------- UV to MESH ------------------------------- #
6 # -------------------------------- version 0.1.1 ----------------------------- #
7 # #
8 # Create a new Mesh based on active UV #
9 # #
10 # (c) Alessandro Zomparelli #
11 # (2017) #
12 # #
13 # http://www.co-de-it.com/ #
14 # #
15 # ############################################################################ #
17 import bpy, bmesh
18 import math
19 from bpy.types import Operator
20 from bpy.props import BoolProperty
21 from mathutils import Vector
22 from .utils import *
25 class uv_to_mesh(Operator):
26 bl_idname = "object.uv_to_mesh"
27 bl_label = "UV to Mesh"
28 bl_description = ("Create a new Mesh based on active UV")
29 bl_options = {'REGISTER', 'UNDO'}
31 apply_modifiers : BoolProperty(
32 name="Apply Modifiers",
33 default=True,
34 description="Apply object's modifiers"
36 vertex_groups : BoolProperty(
37 name="Keep Vertex Groups",
38 default=True,
39 description="Transfer all the Vertex Groups"
41 materials : BoolProperty(
42 name="Keep Materials",
43 default=True,
44 description="Transfer all the Materials"
46 auto_scale : BoolProperty(
47 name="Resize",
48 default=True,
49 description="Scale the new object in order to preserve the average surface area"
52 def execute(self, context):
53 if context.mode == 'EDIT_MESH': on_selection = True
54 else: on_selection = False
56 bpy.ops.object.mode_set(mode='OBJECT')
57 ob0 = context.object
58 for o in bpy.context.view_layer.objects: o.select_set(False)
59 ob0.select_set(True)
61 name0 = ob0.name
62 ob0 = convert_object_to_mesh(ob0, apply_modifiers=self.apply_modifiers, preserve_status=False)
63 me0 = ob0.data
64 area = 0
65 verts = []
66 faces = []
67 face_materials = []
68 if on_selection: polygons = [f for f in me0.polygons if f.select]
69 else: polygons = me0.polygons
70 bm = bmesh.new()
72 for face in polygons:
73 area += face.area
74 uv_face = []
75 store = False
76 if len(me0.uv_layers) > 0:
77 verts = []
78 for loop in face.loop_indices:
79 uv = me0.uv_layers.active.data[loop].uv
80 if uv.x != 0 and uv.y != 0:
81 store = True
82 new_vert = bm.verts.new((uv.x, uv.y, 0))
83 verts.append(new_vert)
84 if store:
85 new_face = bm.faces.new(verts)
86 new_face.material_index = face.material_index
87 else:
88 self.report({'ERROR'}, "Missing UV Map")
89 return {'CANCELLED'}
91 name = name0 + '_UV'
92 # Create mesh and object
93 me = bpy.data.meshes.new(name + 'Mesh')
94 ob = bpy.data.objects.new(name, me)
96 # Link object to scene and make active
97 scn = bpy.context.scene
98 bpy.context.collection.objects.link(ob)
99 bpy.context.view_layer.objects.active = ob
100 ob.select_set(True)
102 # Create mesh from given verts, faces.
103 bm.to_mesh(me)
104 # Update mesh with new data
105 me.update()
107 if self.auto_scale:
108 new_area = 0
109 for p in me.polygons:
110 new_area += p.area
111 if new_area == 0:
112 self.report({'ERROR'}, "Impossible to generate mesh from UV")
113 bpy.data.objects.remove(ob0)
114 return {'CANCELLED'}
116 # VERTEX GROUPS
117 if self.vertex_groups:
118 for group in ob0.vertex_groups:
119 index = group.index
120 ob.vertex_groups.new(name=group.name)
121 for p in polygons:
122 for vert, loop in zip(p.vertices, p.loop_indices):
123 try:
124 ob.vertex_groups[index].add([loop], group.weight(vert), 'REPLACE')
125 except:
126 pass
128 ob0.select_set(False)
129 if self.auto_scale:
130 scaleFactor = math.pow(area / new_area, 1 / 2)
131 ob.scale = Vector((scaleFactor, scaleFactor, scaleFactor))
133 bpy.ops.object.mode_set(mode='EDIT', toggle=False)
134 bpy.ops.mesh.remove_doubles(threshold=1e-06)
135 bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
136 bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
138 # MATERIALS
139 if self.materials:
140 if len(ob0.material_slots) > 0:
141 # assign old material
142 uv_materials = [slot.material for slot in ob0.material_slots]
143 for i in range(len(uv_materials)):
144 bpy.ops.object.material_slot_add()
145 bpy.context.object.material_slots[i].material = uv_materials[i]
147 bpy.data.objects.remove(ob0)
148 bpy.data.meshes.remove(me0)
149 return {'FINISHED'}