Merge branch 'blender-v3.3-release'
[blender-addons.git] / io_mesh_stl / blender_utils.py
blobfdf353df2a1d32a68bf3cfb5bc235dcd1428efea
1 # SPDX-License-Identifier: GPL-2.0-or-later
4 def create_and_link_mesh(name, faces, face_nors, points, global_matrix):
5 """
6 Create a blender mesh and object called name from a list of
7 *points* and *faces* and link it in the current scene.
8 """
10 import array
11 from itertools import chain
12 import bpy
14 mesh = bpy.data.meshes.new(name)
15 mesh.from_pydata(points, [], faces)
17 if face_nors:
18 # Note: we store 'temp' normals in loops, since validate() may alter final mesh,
19 # we can only set custom lnors *after* calling it.
20 mesh.create_normals_split()
21 lnors = tuple(chain(*chain(*zip(face_nors, face_nors, face_nors))))
22 mesh.loops.foreach_set("normal", lnors)
24 mesh.transform(global_matrix)
26 # update mesh to allow proper display
27 mesh.validate(clean_customdata=False) # *Very* important to not remove lnors here!
29 if face_nors:
30 clnors = array.array('f', [0.0] * (len(mesh.loops) * 3))
31 mesh.loops.foreach_get("normal", clnors)
33 mesh.polygons.foreach_set("use_smooth", [True] * len(mesh.polygons))
35 mesh.normals_split_custom_set(tuple(zip(*(iter(clnors),) * 3)))
36 mesh.use_auto_smooth = True
37 mesh.free_normals_split()
39 mesh.update()
41 obj = bpy.data.objects.new(name, mesh)
42 bpy.context.collection.objects.link(obj)
43 bpy.context.view_layer.objects.active = obj
44 obj.select_set(True)
47 def faces_from_mesh(ob, global_matrix, use_mesh_modifiers=False):
48 """
49 From an object, return a generator over a list of faces.
51 Each faces is a list of his vertexes. Each vertex is a tuple of
52 his coordinate.
54 use_mesh_modifiers
55 Apply the preview modifier to the returned liste
57 triangulate
58 Split the quad into two triangles
59 """
61 import bpy
63 # get the editmode data
64 if ob.mode == "EDIT":
65 ob.update_from_editmode()
67 # get the modifiers
68 if use_mesh_modifiers:
69 depsgraph = bpy.context.evaluated_depsgraph_get()
70 mesh_owner = ob.evaluated_get(depsgraph)
71 else:
72 mesh_owner = ob
74 # Object.to_mesh() is not guaranteed to return a mesh.
75 try:
76 mesh = mesh_owner.to_mesh()
77 except RuntimeError:
78 return
80 if mesh is None:
81 return
83 mat = global_matrix @ ob.matrix_world
84 mesh.transform(mat)
85 if mat.is_negative:
86 mesh.flip_normals()
87 mesh.calc_loop_triangles()
89 vertices = mesh.vertices
91 for tri in mesh.loop_triangles:
92 yield [vertices[index].co.copy() for index in tri.vertices]
94 mesh_owner.to_mesh_clear()