Merge branch 'blender-v2.92-release'
[blender-addons.git] / mesh_tissue / utils.py
blob8e343feaffd4a2d1d89e80dbe97392983a2833fe
1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
19 import bpy
20 import threading
21 import numpy as np
22 import multiprocessing
23 from multiprocessing import Process, Pool
25 weight = []
26 n_threads = multiprocessing.cpu_count()
28 class ThreadVertexGroup(threading.Thread):
29 def __init__ ( self, id, vertex_group, n_verts):
30 self.id = id
31 self.vertex_group = vertex_group
32 self.n_verts = n_verts
33 threading.Thread.__init__ ( self )
35 def run (self):
36 global weight
37 global n_threads
38 verts = np.arange(int(self.n_verts/8))*8 + self.id
39 for v in verts:
40 try:
41 weight[v] = self.vertex_group.weight(v)
42 except:
43 pass
45 def thread_read_weight(_weight, vertex_group):
46 global weight
47 global n_threads
48 print(n_threads)
49 weight = _weight
50 n_verts = len(weight)
51 threads = [ThreadVertexGroup(i, vertex_group, n_verts) for i in range(n_threads)]
52 for t in threads: t.start()
53 for t in threads: t.join()
54 return weight
56 def process_read_weight(id, vertex_group, n_verts):
57 global weight
58 global n_threads
59 verts = np.arange(int(self.n_verts/8))*8 + self.id
60 for v in verts:
61 try:
62 weight[v] = self.vertex_group.weight(v)
63 except:
64 pass
67 def read_weight(_weight, vertex_group):
68 global weight
69 global n_threads
70 print(n_threads)
71 weight = _weight
72 n_verts = len(weight)
73 n_cores = multiprocessing.cpu_count()
74 pool = Pool(processes=n_cores)
75 multiple_results = [pool.apply_async(process_read_weight, (i, vertex_group, n_verts)) for i in range(n_cores)]
76 #processes = [Process(target=process_read_weight, args=(i, vertex_group, n_verts)) for i in range(n_threads)]
77 #for t in processes: t.start()
78 #for t in processes: t.join()
79 return weight
81 #Recursively transverse layer_collection for a particular name
82 def recurLayerCollection(layerColl, collName):
83 found = None
84 if (layerColl.name == collName):
85 return layerColl
86 for layer in layerColl.children:
87 found = recurLayerCollection(layer, collName)
88 if found:
89 return found
91 def auto_layer_collection():
92 # automatically change active layer collection
93 layer = bpy.context.view_layer.active_layer_collection
94 layer_collection = bpy.context.view_layer.layer_collection
95 if layer.hide_viewport or layer.collection.hide_viewport:
96 collections = bpy.context.object.users_collection
97 for c in collections:
98 lc = recurLayerCollection(layer_collection, c.name)
99 if not c.hide_viewport and not lc.hide_viewport:
100 bpy.context.view_layer.active_layer_collection = lc
102 def lerp(a, b, t):
103 return a + (b - a) * t
105 def _lerp2(v1, v2, v3, v4, v):
106 v12 = v1.lerp(v2,v.x) # + (v2 - v1) * v.x
107 v34 = v3.lerp(v4,v.x) # + (v4 - v3) * v.x
108 return v12.lerp(v34, v.y)# + (v34 - v12) * v.y
110 def lerp2(v1, v2, v3, v4, v):
111 v12 = v1 + (v2 - v1) * v.x
112 v34 = v3 + (v4 - v3) * v.x
113 return v12 + (v34 - v12) * v.y
115 def lerp3(v1, v2, v3, v4, v):
116 loc = lerp2(v1.co, v2.co, v3.co, v4.co, v)
117 nor = lerp2(v1.normal, v2.normal, v3.normal, v4.normal, v)
118 nor.normalize()
119 return loc + nor * v.z
121 def _convert_object_to_mesh(ob, apply_modifiers=True, preserve_status=True):
122 if not apply_modifiers:
123 mod_visibility = [m.show_viewport for m in ob.modifiers]
124 for m in ob.modifiers:
125 m.show_viewport = False
126 if preserve_status:
127 # store status
128 mode = bpy.context.object.mode
129 selected = bpy.context.selected_objects
130 active = bpy.context.object
131 # change status
132 bpy.ops.object.mode_set(mode='OBJECT')
133 bpy.ops.object.select_all(action='DESELECT')
134 new_ob = ob.copy()
135 new_ob.data = ob.data.copy()
136 bpy.context.collection.objects.link(new_ob)
137 bpy.context.view_layer.objects.active = new_ob
138 new_ob.select_set(True)
139 bpy.ops.object.convert(target='MESH')
140 if preserve_status:
141 # restore status
142 bpy.ops.object.select_all(action='DESELECT')
143 for o in selected: o.select_set(True)
144 bpy.context.view_layer.objects.active = active
145 bpy.ops.object.mode_set(mode=mode)
146 if not apply_modifiers:
147 for m,vis in zip(ob.modifiers,mod_visibility):
148 m.show_viewport = vis
149 return new_ob
151 def convert_object_to_mesh(ob, apply_modifiers=True, preserve_status=True):
152 if not ob.name: return None
153 if ob.type != 'MESH':
154 if not apply_modifiers:
155 mod_visibility = [m.show_viewport for m in ob.modifiers]
156 for m in ob.modifiers: m.show_viewport = False
157 #ob.modifiers.update()
158 #dg = bpy.context.evaluated_depsgraph_get()
159 #ob_eval = ob.evaluated_get(dg)
160 #me = bpy.data.meshes.new_from_object(ob_eval, preserve_all_data_layers=True, depsgraph=dg)
161 me = simple_to_mesh(ob)
162 new_ob = bpy.data.objects.new(ob.data.name, me)
163 new_ob.location, new_ob.matrix_world = ob.location, ob.matrix_world
164 if not apply_modifiers:
165 for m,vis in zip(ob.modifiers,mod_visibility): m.show_viewport = vis
166 else:
167 if apply_modifiers:
168 new_ob = ob.copy()
169 new_ob.data = simple_to_mesh(ob)
170 else:
171 new_ob = ob.copy()
172 new_ob.data = ob.data.copy()
173 new_ob.modifiers.clear()
174 bpy.context.collection.objects.link(new_ob)
175 if preserve_status:
176 new_ob.select_set(False)
177 else:
178 for o in bpy.context.view_layer.objects: o.select_set(False)
179 new_ob.select_set(True)
180 bpy.context.view_layer.objects.active = new_ob
181 return new_ob
183 def simple_to_mesh(ob):
184 dg = bpy.context.evaluated_depsgraph_get()
185 ob_eval = ob.evaluated_get(dg)
186 me = bpy.data.meshes.new_from_object(ob_eval, preserve_all_data_layers=True, depsgraph=dg)
187 me.calc_normals()
188 return me
190 # Prevent Blender Crashes with handlers
191 def set_animatable_fix_handler(self, context):
192 old_handlers = []
193 blender_handlers = bpy.app.handlers.render_init
194 for h in blender_handlers:
195 if "turn_off_animatable" in str(h):
196 old_handlers.append(h)
197 for h in old_handlers: blender_handlers.remove(h)
198 blender_handlers.append(turn_off_animatable)
199 return
201 def turn_off_animatable(scene):
202 for o in bpy.data.objects:
203 o.tissue_tessellate.bool_run = False
204 o.reaction_diffusion_settings.run = False
205 #except: pass
206 return