1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2020 Blender Foundation.
17  * All rights reserved.
18  */
19 
20 /** \file
21  * \ingroup edsculpt
22  */
23 
24 #include "MEM_guardedalloc.h"
25 
26 #include "BLI_blenlib.h"
27 #include "BLI_dial_2d.h"
28 #include "BLI_edgehash.h"
29 #include "BLI_gsqueue.h"
30 #include "BLI_hash.h"
31 #include "BLI_math.h"
32 #include "BLI_task.h"
33 #include "BLI_utildefines.h"
34 
35 #include "BLT_translation.h"
36 
37 #include "DNA_brush_types.h"
38 #include "DNA_customdata_types.h"
39 #include "DNA_mesh_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_node_types.h"
42 #include "DNA_object_types.h"
43 #include "DNA_scene_types.h"
44 
45 #include "BKE_brush.h"
46 #include "BKE_bvhutils.h"
47 #include "BKE_ccg.h"
48 #include "BKE_collision.h"
49 #include "BKE_colortools.h"
50 #include "BKE_context.h"
51 #include "BKE_image.h"
52 #include "BKE_kelvinlet.h"
53 #include "BKE_key.h"
54 #include "BKE_lib_id.h"
55 #include "BKE_main.h"
56 #include "BKE_mesh.h"
57 #include "BKE_mesh_mapping.h"
58 #include "BKE_mesh_mirror.h"
59 #include "BKE_modifier.h"
60 #include "BKE_multires.h"
61 #include "BKE_node.h"
62 #include "BKE_object.h"
63 #include "BKE_paint.h"
64 #include "BKE_particle.h"
65 #include "BKE_pbvh.h"
66 #include "BKE_pointcache.h"
67 #include "BKE_report.h"
68 #include "BKE_scene.h"
69 #include "BKE_screen.h"
70 #include "BKE_subdiv_ccg.h"
71 #include "BKE_subsurf.h"
72 
73 #include "DEG_depsgraph.h"
74 #include "DEG_depsgraph_query.h"
75 
76 #include "WM_api.h"
77 #include "WM_message.h"
78 #include "WM_toolsystem.h"
79 #include "WM_types.h"
80 
81 #include "ED_object.h"
82 #include "ED_screen.h"
83 #include "ED_sculpt.h"
84 #include "ED_view3d.h"
85 #include "paint_intern.h"
86 #include "sculpt_intern.h"
87 
88 #include "RNA_access.h"
89 #include "RNA_define.h"
90 
91 #include "GPU_immediate.h"
92 #include "GPU_immediate_util.h"
93 #include "GPU_matrix.h"
94 #include "GPU_state.h"
95 
96 #include "UI_interface.h"
97 #include "UI_resources.h"
98 
99 #include "bmesh.h"
100 #include "bmesh_tools.h"
101 
102 #include <math.h>
103 #include <stdlib.h>
104 #include <string.h>
105 
cloth_brush_simulation_location_get(SculptSession * ss,const Brush * brush,float r_location[3])106 static void cloth_brush_simulation_location_get(SculptSession *ss,
107                                                 const Brush *brush,
108                                                 float r_location[3])
109 {
110   if (!ss->cache || !brush) {
111     zero_v3(r_location);
112     return;
113   }
114 
115   if (brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL) {
116     copy_v3_v3(r_location, ss->cache->initial_location);
117     return;
118   }
119   copy_v3_v3(r_location, ss->cache->location);
120 }
121 
cloth_brush_simulation_falloff_get(const Brush * brush,const float radius,const float location[3],const float co[3])122 static float cloth_brush_simulation_falloff_get(const Brush *brush,
123                                                 const float radius,
124                                                 const float location[3],
125                                                 const float co[3])
126 {
127   if (brush->sculpt_tool != SCULPT_TOOL_CLOTH) {
128     /* All brushes that are not the cloth brush do not use simulation areas. */
129     return 1.0f;
130   }
131 
132   /* Global simulation does not have any falloff as the entire mesh is being simulated. */
133   if (brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_GLOBAL) {
134     return 1.0f;
135   }
136 
137   const float distance = len_v3v3(location, co);
138   const float limit = radius + (radius * brush->cloth_sim_limit);
139   const float falloff = radius + (radius * brush->cloth_sim_limit * brush->cloth_sim_falloff);
140 
141   if (distance > limit) {
142     /* Outiside the limits. */
143     return 0.0f;
144   }
145   if (distance < falloff) {
146     /* Before the falloff area. */
147     return 1.0f;
148   }
149   /* Do a smoothstep transition inside the falloff area. */
150   float p = 1.0f - ((distance - falloff) / (limit - falloff));
151   return 3.0f * p * p - 2.0f * p * p * p;
152 }
153 
154 #define CLOTH_LENGTH_CONSTRAINTS_BLOCK 100000
155 #define CLOTH_SIMULATION_ITERATIONS 5
156 
157 #define CLOTH_SOLVER_DISPLACEMENT_FACTOR 0.6f
158 #define CLOTH_MAX_CONSTRAINTS_PER_VERTEX 1024
159 #define CLOTH_SIMULATION_TIME_STEP 0.01f
160 #define CLOTH_DEFORMATION_SNAKEHOOK_STRENGTH 0.35f
161 #define CLOTH_DEFORMATION_TARGET_STRENGTH 0.01f
162 #define CLOTH_DEFORMATION_GRAB_STRENGTH 0.1f
163 
cloth_brush_sim_has_length_constraint(SculptClothSimulation * cloth_sim,const int v1,const int v2)164 static bool cloth_brush_sim_has_length_constraint(SculptClothSimulation *cloth_sim,
165                                                   const int v1,
166                                                   const int v2)
167 {
168   return BLI_edgeset_haskey(cloth_sim->created_length_constraints, v1, v2);
169 }
170 
cloth_brush_reallocate_constraints(SculptClothSimulation * cloth_sim)171 static void cloth_brush_reallocate_constraints(SculptClothSimulation *cloth_sim)
172 {
173   if (cloth_sim->tot_length_constraints >= cloth_sim->capacity_length_constraints) {
174     cloth_sim->capacity_length_constraints += CLOTH_LENGTH_CONSTRAINTS_BLOCK;
175     cloth_sim->length_constraints = MEM_reallocN_id(cloth_sim->length_constraints,
176                                                     cloth_sim->capacity_length_constraints *
177                                                         sizeof(SculptClothLengthConstraint),
178                                                     "length constraints");
179   }
180 }
181 
cloth_brush_add_length_constraint(SculptSession * ss,SculptClothSimulation * cloth_sim,const int node_index,const int v1,const int v2,const bool use_persistent)182 static void cloth_brush_add_length_constraint(SculptSession *ss,
183                                               SculptClothSimulation *cloth_sim,
184                                               const int node_index,
185                                               const int v1,
186                                               const int v2,
187                                               const bool use_persistent)
188 {
189   SculptClothLengthConstraint *length_constraint =
190       &cloth_sim->length_constraints[cloth_sim->tot_length_constraints];
191 
192   length_constraint->elem_index_a = v1;
193   length_constraint->elem_index_b = v2;
194 
195   length_constraint->node = node_index;
196 
197   length_constraint->elem_position_a = cloth_sim->pos[v1];
198   length_constraint->elem_position_b = cloth_sim->pos[v2];
199 
200   length_constraint->type = SCULPT_CLOTH_CONSTRAINT_STRUCTURAL;
201 
202   if (use_persistent) {
203     length_constraint->length = len_v3v3(SCULPT_vertex_persistent_co_get(ss, v1),
204                                          SCULPT_vertex_persistent_co_get(ss, v2));
205   }
206   else {
207     length_constraint->length = len_v3v3(SCULPT_vertex_co_get(ss, v1),
208                                          SCULPT_vertex_co_get(ss, v2));
209   }
210   length_constraint->strength = 1.0f;
211 
212   cloth_sim->tot_length_constraints++;
213 
214   /* Reallocation if the array capacity is exceeded. */
215   cloth_brush_reallocate_constraints(cloth_sim);
216 
217   /* Add the constraint to the GSet to avoid creating it again. */
218   BLI_edgeset_add(cloth_sim->created_length_constraints, v1, v2);
219 }
220 
cloth_brush_add_softbody_constraint(SculptClothSimulation * cloth_sim,const int node_index,const int v,const float strength)221 static void cloth_brush_add_softbody_constraint(SculptClothSimulation *cloth_sim,
222                                                 const int node_index,
223                                                 const int v,
224                                                 const float strength)
225 {
226   SculptClothLengthConstraint *length_constraint =
227       &cloth_sim->length_constraints[cloth_sim->tot_length_constraints];
228 
229   length_constraint->elem_index_a = v;
230   length_constraint->elem_index_b = v;
231 
232   length_constraint->node = node_index;
233 
234   length_constraint->elem_position_a = cloth_sim->pos[v];
235   length_constraint->elem_position_b = cloth_sim->softbody_pos[v];
236 
237   length_constraint->type = SCULPT_CLOTH_CONSTRAINT_SOFTBODY;
238 
239   length_constraint->length = 0.0f;
240   length_constraint->strength = strength;
241 
242   cloth_sim->tot_length_constraints++;
243 
244   /* Reallocation if the array capacity is exceeded. */
245   cloth_brush_reallocate_constraints(cloth_sim);
246 }
247 
cloth_brush_add_pin_constraint(SculptClothSimulation * cloth_sim,const int node_index,const int v,const float strength)248 static void cloth_brush_add_pin_constraint(SculptClothSimulation *cloth_sim,
249                                            const int node_index,
250                                            const int v,
251                                            const float strength)
252 {
253   SculptClothLengthConstraint *length_constraint =
254       &cloth_sim->length_constraints[cloth_sim->tot_length_constraints];
255 
256   length_constraint->elem_index_a = v;
257   length_constraint->elem_index_b = v;
258 
259   length_constraint->node = node_index;
260 
261   length_constraint->elem_position_a = cloth_sim->pos[v];
262   length_constraint->elem_position_b = cloth_sim->init_pos[v];
263 
264   length_constraint->type = SCULPT_CLOTH_CONSTRAINT_PIN;
265 
266   length_constraint->length = 0.0f;
267   length_constraint->strength = strength;
268 
269   cloth_sim->tot_length_constraints++;
270 
271   /* Reallocation if the array capacity is exceeded. */
272   cloth_brush_reallocate_constraints(cloth_sim);
273 }
274 
cloth_brush_add_deformation_constraint(SculptClothSimulation * cloth_sim,const int node_index,const int v,const float strength)275 static void cloth_brush_add_deformation_constraint(SculptClothSimulation *cloth_sim,
276                                                    const int node_index,
277                                                    const int v,
278                                                    const float strength)
279 {
280   SculptClothLengthConstraint *length_constraint =
281       &cloth_sim->length_constraints[cloth_sim->tot_length_constraints];
282 
283   length_constraint->elem_index_a = v;
284   length_constraint->elem_index_b = v;
285 
286   length_constraint->node = node_index;
287 
288   length_constraint->type = SCULPT_CLOTH_CONSTRAINT_DEFORMATION;
289 
290   length_constraint->elem_position_a = cloth_sim->pos[v];
291   length_constraint->elem_position_b = cloth_sim->deformation_pos[v];
292 
293   length_constraint->length = 0.0f;
294   length_constraint->strength = strength;
295 
296   cloth_sim->tot_length_constraints++;
297 
298   /* Reallocation if the array capacity is exceeded. */
299   cloth_brush_reallocate_constraints(cloth_sim);
300 }
301 
do_cloth_brush_build_constraints_task_cb_ex(void * __restrict userdata,const int n,const TaskParallelTLS * __restrict UNUSED (tls))302 static void do_cloth_brush_build_constraints_task_cb_ex(
303     void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
304 {
305   SculptThreadedTaskData *data = userdata;
306   SculptSession *ss = data->ob->sculpt;
307   const Brush *brush = data->brush;
308   PBVHNode *node = data->nodes[n];
309 
310   const int node_index = POINTER_AS_INT(BLI_ghash_lookup(data->cloth_sim->node_state_index, node));
311   if (data->cloth_sim->node_state[node_index] != SCULPT_CLOTH_NODE_UNINITIALIZED) {
312     /* The simulation already contains constraints for this node. */
313     return;
314   }
315 
316   PBVHVertexIter vd;
317 
318   const bool pin_simulation_boundary = ss->cache != NULL && brush != NULL &&
319                                        brush->flag2 & BRUSH_CLOTH_PIN_SIMULATION_BOUNDARY &&
320                                        brush->cloth_simulation_area_type !=
321                                            BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC;
322 
323   const bool use_persistent = brush != NULL && brush->flag & BRUSH_PERSISTENT;
324 
325   /* Brush can be NULL in tools that use the solver without relying of constraints with deformation
326    * positions. */
327   const bool cloth_is_deform_brush = ss->cache != NULL && brush != NULL &&
328                                      SCULPT_is_cloth_deform_brush(brush);
329   float radius_squared = 0.0f;
330   if (cloth_is_deform_brush) {
331     radius_squared = ss->cache->initial_radius * ss->cache->initial_radius;
332   }
333 
334   /* Only limit the contraint creation to a radius when the simulation is local. */
335   const float cloth_sim_radius_squared = brush->cloth_simulation_area_type ==
336                                                  BRUSH_CLOTH_SIMULATION_AREA_LOCAL ?
337                                              data->cloth_sim_radius * data->cloth_sim_radius :
338                                              FLT_MAX;
339 
340   BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
341   {
342     const float len_squared = len_squared_v3v3(vd.co, data->cloth_sim_initial_location);
343     if (len_squared < cloth_sim_radius_squared) {
344 
345       SculptVertexNeighborIter ni;
346       int build_indices[CLOTH_MAX_CONSTRAINTS_PER_VERTEX];
347       int tot_indices = 0;
348       build_indices[tot_indices] = vd.index;
349       tot_indices++;
350       SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) {
351         build_indices[tot_indices] = ni.index;
352         tot_indices++;
353       }
354       SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
355 
356       if (data->cloth_sim->softbody_strength > 0.0f) {
357         cloth_brush_add_softbody_constraint(data->cloth_sim, node_index, vd.index, 1.0f);
358       }
359 
360       /* As we don't know the order of the neighbor vertices, we create all possible combinations
361        * between the neighbor and the original vertex as length constraints. */
362       /* This results on a pattern that contains structural, shear and bending constraints for all
363        * vertices, but constraints are repeated taking more memory than necessary. */
364 
365       for (int c_i = 0; c_i < tot_indices; c_i++) {
366         for (int c_j = 0; c_j < tot_indices; c_j++) {
367           if (c_i != c_j && !cloth_brush_sim_has_length_constraint(
368                                 data->cloth_sim, build_indices[c_i], build_indices[c_j])) {
369             cloth_brush_add_length_constraint(ss,
370                                               data->cloth_sim,
371                                               node_index,
372                                               build_indices[c_i],
373                                               build_indices[c_j],
374                                               use_persistent);
375           }
376         }
377       }
378     }
379 
380     if (brush && brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
381       /* The cloth brush works by applying forces in most of its modes, but some of them require
382        * deformation coordinates to make the simulation stable. */
383       if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB && len_squared < radius_squared) {
384         /* When the grab brush brush is used as part of the cloth brush, deformation constraints
385          * are created with different strengths and only inside the radius of the brush. */
386         const float fade = BKE_brush_curve_strength(brush, sqrtf(len_squared), ss->cache->radius);
387         cloth_brush_add_deformation_constraint(
388             data->cloth_sim, node_index, vd.index, fade * CLOTH_DEFORMATION_GRAB_STRENGTH);
389       }
390       else if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK) {
391         /* Cloth Snake Hook creates deformation constraint with fixed strength because the strength
392          * is controlled per iteration using cloth_sim->deformation_strength. */
393         cloth_brush_add_deformation_constraint(
394             data->cloth_sim, node_index, vd.index, CLOTH_DEFORMATION_SNAKEHOOK_STRENGTH);
395       }
396     }
397     else if (data->cloth_sim->deformation_pos) {
398       /* Any other tool that target the cloth simulation handle the falloff in
399        * their own code when modifying the deformation coordinates of the simulation, so
400        * deformation constraints are created with a fixed strength for all vertices. */
401       cloth_brush_add_deformation_constraint(
402           data->cloth_sim, node_index, vd.index, CLOTH_DEFORMATION_TARGET_STRENGTH);
403     }
404 
405     if (pin_simulation_boundary) {
406       const float sim_falloff = cloth_brush_simulation_falloff_get(
407           brush, ss->cache->initial_radius, ss->cache->location, vd.co);
408       /* Vertex is inside the area of the simulation without any falloff applied. */
409       if (sim_falloff < 1.0f) {
410         /* Create constraints with more strength the closer the vertex is to the simulation
411          * boundary. */
412         cloth_brush_add_pin_constraint(data->cloth_sim, node_index, vd.index, 1.0f - sim_falloff);
413       }
414     }
415   }
416   BKE_pbvh_vertex_iter_end;
417 }
418 
cloth_brush_apply_force_to_vertex(SculptSession * UNUSED (ss),SculptClothSimulation * cloth_sim,const float force[3],const int vertex_index)419 static void cloth_brush_apply_force_to_vertex(SculptSession *UNUSED(ss),
420                                               SculptClothSimulation *cloth_sim,
421                                               const float force[3],
422                                               const int vertex_index)
423 {
424   madd_v3_v3fl(cloth_sim->acceleration[vertex_index], force, 1.0f / cloth_sim->mass);
425 }
426 
do_cloth_brush_apply_forces_task_cb_ex(void * __restrict userdata,const int n,const TaskParallelTLS * __restrict tls)427 static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
428                                                    const int n,
429                                                    const TaskParallelTLS *__restrict tls)
430 {
431   SculptThreadedTaskData *data = userdata;
432   SculptSession *ss = data->ob->sculpt;
433   const Brush *brush = data->brush;
434   SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
435   const float *offset = data->offset;
436   const float *grab_delta = data->grab_delta;
437   float(*imat)[4] = data->mat;
438 
439   const bool use_falloff_plane = !SCULPT_is_cloth_deform_brush(brush) &&
440                                  brush->cloth_force_falloff_type ==
441                                      BRUSH_CLOTH_FORCE_FALLOFF_PLANE;
442 
443   PBVHVertexIter vd;
444   const float bstrength = ss->cache->bstrength;
445 
446   SculptBrushTest test;
447   SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
448       ss, &test, data->brush->falloff_shape);
449   const int thread_id = BLI_task_parallel_thread_id(tls);
450 
451   /* For Pich Perpendicular Deform Type. */
452   float x_object_space[3];
453   float z_object_space[3];
454   if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR) {
455     normalize_v3_v3(x_object_space, imat[0]);
456     normalize_v3_v3(z_object_space, imat[2]);
457   }
458 
459   /* For Plane Force Falloff. */
460   float deform_plane[4];
461   float plane_normal[3];
462   if (use_falloff_plane) {
463     normalize_v3_v3(plane_normal, grab_delta);
464     plane_from_point_normal_v3(deform_plane, data->area_co, plane_normal);
465   }
466 
467   /* Gravity */
468   float gravity[3] = {0.0f};
469   if (ss->cache->supports_gravity) {
470     madd_v3_v3fl(gravity, ss->cache->gravity_direction, -data->sd->gravity_factor);
471   }
472 
473   /* Original data for deform brushes. */
474   SculptOrigVertData orig_data;
475   if (SCULPT_is_cloth_deform_brush(brush)) {
476     SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
477   }
478 
479   BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
480   {
481     float force[3];
482     float sim_location[3];
483     cloth_brush_simulation_location_get(ss, brush, sim_location);
484     const float sim_factor = cloth_brush_simulation_falloff_get(
485         brush, ss->cache->radius, sim_location, cloth_sim->init_pos[vd.index]);
486 
487     float current_vertex_location[3];
488     if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
489       SCULPT_orig_vert_data_update(&orig_data, &vd);
490       copy_v3_v3(current_vertex_location, orig_data.co);
491     }
492     else {
493       copy_v3_v3(current_vertex_location, vd.co);
494     }
495 
496     /* Apply gravity in the entire simulation area. */
497     float vertex_gravity[3];
498     mul_v3_v3fl(vertex_gravity, gravity, sim_factor);
499     cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, vertex_gravity, vd.index);
500 
501     /* When using the plane falloff mode the falloff is not constrained by the brush radius. */
502     if (sculpt_brush_test_sq_fn(&test, current_vertex_location) || use_falloff_plane) {
503 
504       float dist = sqrtf(test.dist);
505 
506       if (use_falloff_plane) {
507         dist = dist_to_plane_v3(vd.co, deform_plane);
508       }
509 
510       const float fade = sim_factor * bstrength *
511                          SCULPT_brush_strength_factor(ss,
512                                                       brush,
513                                                       current_vertex_location,
514                                                       dist,
515                                                       vd.no,
516                                                       vd.fno,
517                                                       vd.mask ? *vd.mask : 0.0f,
518                                                       vd.index,
519                                                       thread_id);
520 
521       float brush_disp[3];
522       float normal[3];
523       if (vd.no) {
524         normal_short_to_float_v3(normal, vd.no);
525       }
526       else {
527         copy_v3_v3(normal, vd.fno);
528       }
529 
530       switch (brush->cloth_deform_type) {
531         case BRUSH_CLOTH_DEFORM_DRAG:
532           sub_v3_v3v3(brush_disp, ss->cache->location, ss->cache->last_location);
533           normalize_v3(brush_disp);
534           mul_v3_v3fl(force, brush_disp, fade);
535           break;
536         case BRUSH_CLOTH_DEFORM_PUSH:
537           /* Invert the fade to push inwards. */
538           mul_v3_v3fl(force, offset, -fade);
539           break;
540         case BRUSH_CLOTH_DEFORM_GRAB:
541           madd_v3_v3v3fl(cloth_sim->deformation_pos[vd.index],
542                          orig_data.co,
543                          ss->cache->grab_delta_symmetry,
544                          fade);
545           zero_v3(force);
546           break;
547         case BRUSH_CLOTH_DEFORM_SNAKE_HOOK:
548           copy_v3_v3(cloth_sim->deformation_pos[vd.index], cloth_sim->pos[vd.index]);
549           madd_v3_v3fl(cloth_sim->deformation_pos[vd.index], ss->cache->grab_delta_symmetry, fade);
550           cloth_sim->deformation_strength[vd.index] = fade;
551           zero_v3(force);
552           break;
553         case BRUSH_CLOTH_DEFORM_PINCH_POINT:
554           if (use_falloff_plane) {
555             float distance = dist_signed_to_plane_v3(vd.co, deform_plane);
556             copy_v3_v3(brush_disp, plane_normal);
557             mul_v3_fl(brush_disp, -distance);
558           }
559           else {
560             sub_v3_v3v3(brush_disp, ss->cache->location, vd.co);
561           }
562           normalize_v3(brush_disp);
563           mul_v3_v3fl(force, brush_disp, fade);
564           break;
565         case BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR: {
566           float disp_center[3];
567           float x_disp[3];
568           float z_disp[3];
569           sub_v3_v3v3(disp_center, ss->cache->location, vd.co);
570           normalize_v3(disp_center);
571           mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space));
572           mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space));
573           add_v3_v3v3(disp_center, x_disp, z_disp);
574           mul_v3_v3fl(force, disp_center, fade);
575         } break;
576         case BRUSH_CLOTH_DEFORM_INFLATE:
577           mul_v3_v3fl(force, normal, fade);
578           break;
579         case BRUSH_CLOTH_DEFORM_EXPAND:
580           cloth_sim->length_constraint_tweak[vd.index] += fade * 0.1f;
581           zero_v3(force);
582           break;
583       }
584 
585       cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, force, vd.index);
586     }
587   }
588   BKE_pbvh_vertex_iter_end;
589 }
590 
cloth_brush_collider_cache_create(Depsgraph * depsgraph)591 static ListBase *cloth_brush_collider_cache_create(Depsgraph *depsgraph)
592 {
593   ListBase *cache = NULL;
594   DEG_OBJECT_ITER_BEGIN (depsgraph,
595                          ob,
596                          DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE |
597                              DEG_ITER_OBJECT_FLAG_DUPLI) {
598     CollisionModifierData *cmd = (CollisionModifierData *)BKE_modifiers_findby_type(
599         ob, eModifierType_Collision);
600     if (cmd && cmd->bvhtree) {
601       if (cache == NULL) {
602         cache = MEM_callocN(sizeof(ListBase), "ColliderCache array");
603       }
604 
605       ColliderCache *col = MEM_callocN(sizeof(ColliderCache), "ColliderCache");
606       col->ob = ob;
607       col->collmd = cmd;
608       collision_move_object(cmd, 1.0, 0.0, true);
609       BLI_addtail(cache, col);
610     }
611   }
612   DEG_OBJECT_ITER_END;
613   return cache;
614 }
615 
616 typedef struct ClothBrushCollision {
617   CollisionModifierData *col_data;
618   struct IsectRayPrecalc isect_precalc;
619 } ClothBrushCollision;
620 
cloth_brush_collision_cb(void * userdata,int index,const BVHTreeRay * ray,BVHTreeRayHit * hit)621 static void cloth_brush_collision_cb(void *userdata,
622                                      int index,
623                                      const BVHTreeRay *ray,
624                                      BVHTreeRayHit *hit)
625 {
626   ClothBrushCollision *col = (ClothBrushCollision *)userdata;
627   CollisionModifierData *col_data = col->col_data;
628   MVertTri *verttri = &col_data->tri[index];
629   MVert *mverts = col_data->x;
630   float *tri[3], no[3], co[3];
631 
632   tri[0] = mverts[verttri->tri[0]].co;
633   tri[1] = mverts[verttri->tri[1]].co;
634   tri[2] = mverts[verttri->tri[2]].co;
635   float dist = 0.0f;
636 
637   bool tri_hit = isect_ray_tri_watertight_v3(
638       ray->origin, &col->isect_precalc, UNPACK3(tri), &dist, NULL);
639   normal_tri_v3(no, UNPACK3(tri));
640   madd_v3_v3v3fl(co, ray->origin, ray->direction, dist);
641 
642   if (tri_hit && dist < hit->dist) {
643     hit->index = index;
644     hit->dist = dist;
645 
646     copy_v3_v3(hit->co, co);
647     copy_v3_v3(hit->no, no);
648   }
649 }
650 
cloth_brush_solve_collision(Object * object,SculptClothSimulation * cloth_sim,const int i)651 static void cloth_brush_solve_collision(Object *object,
652                                         SculptClothSimulation *cloth_sim,
653                                         const int i)
654 {
655   const int raycast_flag = BVH_RAYCAST_DEFAULT & ~(BVH_RAYCAST_WATERTIGHT);
656 
657   ColliderCache *collider_cache;
658   BVHTreeRayHit hit;
659 
660   float obmat_inv[4][4];
661   invert_m4_m4(obmat_inv, object->obmat);
662 
663   for (collider_cache = cloth_sim->collider_list->first; collider_cache;
664        collider_cache = collider_cache->next) {
665     float ray_start[3], ray_normal[3];
666     float pos_world_space[3], prev_pos_world_space[3];
667 
668     mul_v3_m4v3(pos_world_space, object->obmat, cloth_sim->pos[i]);
669     mul_v3_m4v3(prev_pos_world_space, object->obmat, cloth_sim->last_iteration_pos[i]);
670     sub_v3_v3v3(ray_normal, pos_world_space, prev_pos_world_space);
671     copy_v3_v3(ray_start, prev_pos_world_space);
672     hit.index = -1;
673     hit.dist = len_v3(ray_normal);
674     normalize_v3(ray_normal);
675 
676     ClothBrushCollision col;
677     CollisionModifierData *collmd = collider_cache->collmd;
678     col.col_data = collmd;
679     isect_ray_tri_watertight_v3_precalc(&col.isect_precalc, ray_normal);
680 
681     BLI_bvhtree_ray_cast_ex(collmd->bvhtree,
682                             ray_start,
683                             ray_normal,
684                             0.3f,
685                             &hit,
686                             cloth_brush_collision_cb,
687                             &col,
688                             raycast_flag);
689 
690     if (hit.index != -1) {
691 
692       float collision_disp[3];
693       float movement_disp[3];
694       mul_v3_v3fl(collision_disp, hit.no, 0.005f);
695       sub_v3_v3v3(movement_disp, pos_world_space, prev_pos_world_space);
696       float friction_plane[4];
697       float pos_on_friction_plane[3];
698       plane_from_point_normal_v3(friction_plane, hit.co, hit.no);
699       closest_to_plane_v3(pos_on_friction_plane, friction_plane, pos_world_space);
700       sub_v3_v3v3(movement_disp, pos_on_friction_plane, hit.co);
701 
702       /* TODO(pablodp606): This can be exposed in a brush/filter property as friction. */
703       mul_v3_fl(movement_disp, 0.35f);
704 
705       copy_v3_v3(cloth_sim->pos[i], hit.co);
706       add_v3_v3(cloth_sim->pos[i], movement_disp);
707       add_v3_v3(cloth_sim->pos[i], collision_disp);
708       mul_v3_m4v3(cloth_sim->pos[i], obmat_inv, cloth_sim->pos[i]);
709     }
710   }
711 }
712 
do_cloth_brush_solve_simulation_task_cb_ex(void * __restrict userdata,const int n,const TaskParallelTLS * __restrict UNUSED (tls))713 static void do_cloth_brush_solve_simulation_task_cb_ex(
714     void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
715 {
716   SculptThreadedTaskData *data = userdata;
717   SculptSession *ss = data->ob->sculpt;
718   const Brush *brush = data->brush;
719 
720   PBVHNode *node = data->nodes[n];
721   PBVHVertexIter vd;
722   SculptClothSimulation *cloth_sim = data->cloth_sim;
723   const float time_step = data->cloth_time_step;
724 
725   const int node_index = POINTER_AS_INT(BLI_ghash_lookup(data->cloth_sim->node_state_index, node));
726   if (data->cloth_sim->node_state[node_index] != SCULPT_CLOTH_NODE_ACTIVE) {
727     return;
728   }
729 
730   AutomaskingCache *automasking = SCULPT_automasking_active_cache_get(ss);
731 
732   BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
733   {
734     float sim_location[3];
735     cloth_brush_simulation_location_get(ss, brush, sim_location);
736     const float sim_factor =
737         ss->cache ? cloth_brush_simulation_falloff_get(
738                         brush, ss->cache->radius, sim_location, cloth_sim->init_pos[vd.index]) :
739                     1.0f;
740     if (sim_factor > 0.0f) {
741       int i = vd.index;
742       float temp[3];
743       copy_v3_v3(temp, cloth_sim->pos[i]);
744 
745       mul_v3_fl(cloth_sim->acceleration[i], time_step);
746 
747       float pos_diff[3];
748       sub_v3_v3v3(pos_diff, cloth_sim->pos[i], cloth_sim->prev_pos[i]);
749       mul_v3_fl(pos_diff, (1.0f - cloth_sim->damping) * sim_factor);
750 
751       const float mask_v = (1.0f - (vd.mask ? *vd.mask : 0.0f)) *
752                            SCULPT_automasking_factor_get(automasking, ss, vd.index);
753 
754       madd_v3_v3fl(cloth_sim->pos[i], pos_diff, mask_v);
755       madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v);
756 
757       if (cloth_sim->collider_list != NULL) {
758         cloth_brush_solve_collision(data->ob, cloth_sim, i);
759       }
760 
761       copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]);
762 
763       copy_v3_v3(cloth_sim->prev_pos[i], temp);
764       copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]);
765       copy_v3_fl(cloth_sim->acceleration[i], 0.0f);
766 
767       copy_v3_v3(vd.co, cloth_sim->pos[vd.index]);
768 
769       if (vd.mvert) {
770         vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
771       }
772     }
773   }
774   BKE_pbvh_vertex_iter_end;
775 
776   /* Disable the simulation on this node, it needs to be enabled again to continue. */
777   cloth_sim->node_state[node_index] = SCULPT_CLOTH_NODE_INACTIVE;
778 }
779 
cloth_brush_satisfy_constraints(SculptSession * ss,Brush * brush,SculptClothSimulation * cloth_sim)780 static void cloth_brush_satisfy_constraints(SculptSession *ss,
781                                             Brush *brush,
782                                             SculptClothSimulation *cloth_sim)
783 {
784 
785   AutomaskingCache *automasking = SCULPT_automasking_active_cache_get(ss);
786 
787   for (int constraint_it = 0; constraint_it < CLOTH_SIMULATION_ITERATIONS; constraint_it++) {
788     for (int i = 0; i < cloth_sim->tot_length_constraints; i++) {
789       const SculptClothLengthConstraint *constraint = &cloth_sim->length_constraints[i];
790 
791       if (cloth_sim->node_state[constraint->node] != SCULPT_CLOTH_NODE_ACTIVE) {
792         /* Skip all constraints that were created for inactive nodes. */
793         continue;
794       }
795 
796       const int v1 = constraint->elem_index_a;
797       const int v2 = constraint->elem_index_b;
798 
799       float v1_to_v2[3];
800       sub_v3_v3v3(v1_to_v2, constraint->elem_position_b, constraint->elem_position_a);
801       const float current_distance = len_v3(v1_to_v2);
802       float correction_vector[3];
803       float correction_vector_half[3];
804 
805       const float constraint_distance = constraint->length +
806                                         (cloth_sim->length_constraint_tweak[v1] * 0.5f) +
807                                         (cloth_sim->length_constraint_tweak[v2] * 0.5f);
808 
809       if (current_distance > 0.0f) {
810         mul_v3_v3fl(correction_vector,
811                     v1_to_v2,
812                     CLOTH_SOLVER_DISPLACEMENT_FACTOR *
813                         (1.0f - (constraint_distance / current_distance)));
814       }
815       else {
816         mul_v3_v3fl(correction_vector, v1_to_v2, CLOTH_SOLVER_DISPLACEMENT_FACTOR);
817       }
818 
819       mul_v3_v3fl(correction_vector_half, correction_vector, 0.5f);
820 
821       const float mask_v1 = (1.0f - SCULPT_vertex_mask_get(ss, v1)) *
822                             SCULPT_automasking_factor_get(automasking, ss, v1);
823       const float mask_v2 = (1.0f - SCULPT_vertex_mask_get(ss, v2)) *
824                             SCULPT_automasking_factor_get(automasking, ss, v2);
825 
826       float sim_location[3];
827       cloth_brush_simulation_location_get(ss, brush, sim_location);
828 
829       const float sim_factor_v1 = ss->cache ?
830                                       cloth_brush_simulation_falloff_get(brush,
831                                                                          ss->cache->radius,
832                                                                          sim_location,
833                                                                          cloth_sim->init_pos[v1]) :
834                                       1.0f;
835       const float sim_factor_v2 = ss->cache ?
836                                       cloth_brush_simulation_falloff_get(brush,
837                                                                          ss->cache->radius,
838                                                                          sim_location,
839                                                                          cloth_sim->init_pos[v2]) :
840                                       1.0f;
841 
842       float deformation_strength = 1.0f;
843       if (constraint->type == SCULPT_CLOTH_CONSTRAINT_DEFORMATION) {
844         deformation_strength = (cloth_sim->deformation_strength[v1] +
845                                 cloth_sim->deformation_strength[v2]) *
846                                0.5f;
847       }
848 
849       if (constraint->type == SCULPT_CLOTH_CONSTRAINT_SOFTBODY) {
850         const float softbody_plasticity = brush ? brush->cloth_constraint_softbody_strength : 0.0f;
851         madd_v3_v3fl(cloth_sim->pos[v1],
852                      correction_vector_half,
853                      1.0f * mask_v1 * sim_factor_v1 * constraint->strength * softbody_plasticity);
854         madd_v3_v3fl(cloth_sim->softbody_pos[v1],
855                      correction_vector_half,
856                      -1.0f * mask_v1 * sim_factor_v1 * constraint->strength *
857                          (1.0f - softbody_plasticity));
858       }
859       else {
860         madd_v3_v3fl(cloth_sim->pos[v1],
861                      correction_vector_half,
862                      1.0f * mask_v1 * sim_factor_v1 * constraint->strength * deformation_strength);
863         if (v1 != v2) {
864           madd_v3_v3fl(cloth_sim->pos[v2],
865                        correction_vector_half,
866                        -1.0f * mask_v2 * sim_factor_v2 * constraint->strength *
867                            deformation_strength);
868         }
869       }
870     }
871   }
872 }
873 
SCULPT_cloth_brush_do_simulation_step(Sculpt * sd,Object * ob,SculptClothSimulation * cloth_sim,PBVHNode ** nodes,int totnode)874 void SCULPT_cloth_brush_do_simulation_step(
875     Sculpt *sd, Object *ob, SculptClothSimulation *cloth_sim, PBVHNode **nodes, int totnode)
876 {
877   SculptSession *ss = ob->sculpt;
878   Brush *brush = BKE_paint_brush(&sd->paint);
879 
880   /* Update the constraints. */
881   cloth_brush_satisfy_constraints(ss, brush, cloth_sim);
882 
883   /* Solve the simulation and write the final step to the mesh. */
884   SculptThreadedTaskData solve_simulation_data = {
885       .sd = sd,
886       .ob = ob,
887       .brush = brush,
888       .nodes = nodes,
889       .cloth_time_step = CLOTH_SIMULATION_TIME_STEP,
890       .cloth_sim = cloth_sim,
891   };
892 
893   TaskParallelSettings settings;
894   BKE_pbvh_parallel_range_settings(&settings, true, totnode);
895   BLI_task_parallel_range(
896       0, totnode, &solve_simulation_data, do_cloth_brush_solve_simulation_task_cb_ex, &settings);
897 }
898 
cloth_brush_apply_brush_foces(Sculpt * sd,Object * ob,PBVHNode ** nodes,int totnode)899 static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
900 {
901   SculptSession *ss = ob->sculpt;
902   Brush *brush = BKE_paint_brush(&sd->paint);
903 
904   float grab_delta[3];
905   float mat[4][4];
906   float area_no[3];
907   float area_co[3];
908   float imat[4][4];
909   float offset[3];
910 
911   SculptThreadedTaskData apply_forces_data = {
912       .sd = sd,
913       .ob = ob,
914       .brush = brush,
915       .nodes = nodes,
916       .area_no = area_no,
917       .area_co = area_co,
918       .mat = imat,
919   };
920 
921   BKE_curvemapping_init(brush->curve);
922 
923   /* Init the grab delta. */
924   copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
925   normalize_v3(grab_delta);
926 
927   apply_forces_data.grab_delta = grab_delta;
928 
929   if (is_zero_v3(ss->cache->grab_delta_symmetry)) {
930     return;
931   }
932 
933   /* Calcuate push offset. */
934 
935   if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_PUSH) {
936     mul_v3_v3fl(offset, ss->cache->sculpt_normal_symm, ss->cache->radius);
937     mul_v3_v3(offset, ss->cache->scale);
938     mul_v3_fl(offset, 2.0f);
939 
940     apply_forces_data.offset = offset;
941   }
942 
943   if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR ||
944       brush->cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_PLANE) {
945     SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no, area_co);
946 
947     /* Init stroke local space matrix. */
948     cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry);
949     mat[0][3] = 0.0f;
950     cross_v3_v3v3(mat[1], area_no, mat[0]);
951     mat[1][3] = 0.0f;
952     copy_v3_v3(mat[2], area_no);
953     mat[2][3] = 0.0f;
954     copy_v3_v3(mat[3], ss->cache->location);
955     mat[3][3] = 1.0f;
956     normalize_m4(mat);
957 
958     apply_forces_data.area_co = area_co;
959     apply_forces_data.area_no = area_no;
960     apply_forces_data.mat = mat;
961 
962     /* Update matrix for the cursor preview. */
963     if (ss->cache->mirror_symmetry_pass == 0) {
964       copy_m4_m4(ss->cache->stroke_local_mat, mat);
965     }
966   }
967 
968   if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK) {
969     /* Set the deformation strength to 0. Snake hook will initialize the strength in the required
970      * area. */
971     const int totverts = SCULPT_vertex_count_get(ss);
972     for (int i = 0; i < totverts; i++) {
973       ss->cache->cloth_sim->deformation_strength[i] = 0.0f;
974     }
975   }
976 
977   TaskParallelSettings settings;
978   BKE_pbvh_parallel_range_settings(&settings, true, totnode);
979   BLI_task_parallel_range(
980       0, totnode, &apply_forces_data, do_cloth_brush_apply_forces_task_cb_ex, &settings);
981 }
982 
983 /* Allocates nodes state and initializes them to Uninitialized, so constraints can be created for
984  * them. */
cloth_sim_initialize_default_node_state(SculptSession * ss,SculptClothSimulation * cloth_sim)985 static void cloth_sim_initialize_default_node_state(SculptSession *ss,
986                                                     SculptClothSimulation *cloth_sim)
987 {
988   PBVHNode **nodes;
989   int totnode;
990   BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
991 
992   cloth_sim->node_state = MEM_malloc_arrayN(
993       totnode, sizeof(eSculptClothNodeSimState), "node sim state");
994   cloth_sim->node_state_index = BLI_ghash_ptr_new("node sim state indices");
995   for (int i = 0; i < totnode; i++) {
996     cloth_sim->node_state[i] = SCULPT_CLOTH_NODE_UNINITIALIZED;
997     BLI_ghash_insert(cloth_sim->node_state_index, nodes[i], POINTER_FROM_INT(i));
998   }
999   MEM_SAFE_FREE(nodes);
1000 }
1001 
1002 /* Public functions. */
SCULPT_cloth_brush_simulation_create(SculptSession * ss,const float cloth_mass,const float cloth_damping,const float cloth_softbody_strength,const bool use_collisions,const bool needs_deform_coords)1003 SculptClothSimulation *SCULPT_cloth_brush_simulation_create(SculptSession *ss,
1004                                                             const float cloth_mass,
1005                                                             const float cloth_damping,
1006                                                             const float cloth_softbody_strength,
1007                                                             const bool use_collisions,
1008                                                             const bool needs_deform_coords)
1009 {
1010   const int totverts = SCULPT_vertex_count_get(ss);
1011   SculptClothSimulation *cloth_sim;
1012 
1013   cloth_sim = MEM_callocN(sizeof(SculptClothSimulation), "cloth constraints");
1014 
1015   cloth_sim->length_constraints = MEM_callocN(sizeof(SculptClothLengthConstraint) *
1016                                                   CLOTH_LENGTH_CONSTRAINTS_BLOCK,
1017                                               "cloth length constraints");
1018   cloth_sim->capacity_length_constraints = CLOTH_LENGTH_CONSTRAINTS_BLOCK;
1019 
1020   cloth_sim->acceleration = MEM_calloc_arrayN(
1021       totverts, sizeof(float[3]), "cloth sim acceleration");
1022   cloth_sim->pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim pos");
1023   cloth_sim->prev_pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim prev pos");
1024   cloth_sim->last_iteration_pos = MEM_calloc_arrayN(
1025       totverts, sizeof(float[3]), "cloth sim last iteration pos");
1026   cloth_sim->init_pos = MEM_calloc_arrayN(totverts, sizeof(float[3]), "cloth sim init pos");
1027   cloth_sim->length_constraint_tweak = MEM_calloc_arrayN(
1028       totverts, sizeof(float), "cloth sim length tweak");
1029 
1030   if (needs_deform_coords) {
1031     cloth_sim->deformation_pos = MEM_calloc_arrayN(
1032         totverts, sizeof(float[3]), "cloth sim deformation positions");
1033     cloth_sim->deformation_strength = MEM_calloc_arrayN(
1034         totverts, sizeof(float), "cloth sim deformation strength");
1035   }
1036 
1037   if (cloth_softbody_strength > 0.0f) {
1038     cloth_sim->softbody_pos = MEM_calloc_arrayN(
1039         totverts, sizeof(float[3]), "cloth sim softbody pos");
1040   }
1041 
1042   cloth_sim->mass = cloth_mass;
1043   cloth_sim->damping = cloth_damping;
1044   cloth_sim->softbody_strength = cloth_softbody_strength;
1045 
1046   if (use_collisions) {
1047     cloth_sim->collider_list = cloth_brush_collider_cache_create(ss->depsgraph);
1048   }
1049 
1050   cloth_sim_initialize_default_node_state(ss, cloth_sim);
1051 
1052   return cloth_sim;
1053 }
1054 
SCULPT_cloth_brush_ensure_nodes_constraints(Sculpt * sd,Object * ob,PBVHNode ** nodes,int totnode,SculptClothSimulation * cloth_sim,float initial_location[3],const float radius)1055 void SCULPT_cloth_brush_ensure_nodes_constraints(
1056     Sculpt *sd,
1057     Object *ob,
1058     PBVHNode **nodes,
1059     int totnode,
1060     SculptClothSimulation *cloth_sim,
1061     /* Cannot be const, because it is assigned to a non-const variable.
1062      * NOLINTNEXTLINE: readability-non-const-parameter. */
1063     float initial_location[3],
1064     const float radius)
1065 {
1066   Brush *brush = BKE_paint_brush(&sd->paint);
1067 
1068   /* TODO: Multi-threaded needs to be disabled for this task until implementing the optimization of
1069    * storing the constraints per node. */
1070   /* Currently all constrains are added to the same global array which can't be accessed from
1071    * different threads. */
1072   TaskParallelSettings settings;
1073   BKE_pbvh_parallel_range_settings(&settings, false, totnode);
1074 
1075   cloth_sim->created_length_constraints = BLI_edgeset_new("created length constraints");
1076 
1077   SculptThreadedTaskData build_constraints_data = {
1078       .sd = sd,
1079       .ob = ob,
1080       .brush = brush,
1081       .nodes = nodes,
1082       .cloth_sim = cloth_sim,
1083       .cloth_sim_initial_location = initial_location,
1084       .cloth_sim_radius = radius,
1085   };
1086   BLI_task_parallel_range(
1087       0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings);
1088 
1089   BLI_edgeset_free(cloth_sim->created_length_constraints);
1090 }
1091 
SCULPT_cloth_brush_simulation_init(SculptSession * ss,SculptClothSimulation * cloth_sim)1092 void SCULPT_cloth_brush_simulation_init(SculptSession *ss, SculptClothSimulation *cloth_sim)
1093 {
1094   const int totverts = SCULPT_vertex_count_get(ss);
1095   const bool has_deformation_pos = cloth_sim->deformation_pos != NULL;
1096   const bool has_softbody_pos = cloth_sim->softbody_pos != NULL;
1097   for (int i = 0; i < totverts; i++) {
1098     copy_v3_v3(cloth_sim->last_iteration_pos[i], SCULPT_vertex_co_get(ss, i));
1099     copy_v3_v3(cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
1100     copy_v3_v3(cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
1101     if (has_deformation_pos) {
1102       copy_v3_v3(cloth_sim->deformation_pos[i], SCULPT_vertex_co_get(ss, i));
1103       cloth_sim->deformation_strength[i] = 1.0f;
1104     }
1105     if (has_softbody_pos) {
1106       copy_v3_v3(cloth_sim->softbody_pos[i], SCULPT_vertex_co_get(ss, i));
1107     }
1108   }
1109 }
1110 
SCULPT_cloth_brush_store_simulation_state(SculptSession * ss,SculptClothSimulation * cloth_sim)1111 void SCULPT_cloth_brush_store_simulation_state(SculptSession *ss, SculptClothSimulation *cloth_sim)
1112 {
1113   const int totverts = SCULPT_vertex_count_get(ss);
1114   for (int i = 0; i < totverts; i++) {
1115     copy_v3_v3(cloth_sim->pos[i], SCULPT_vertex_co_get(ss, i));
1116   }
1117 }
1118 
SCULPT_cloth_sim_activate_nodes(SculptClothSimulation * cloth_sim,PBVHNode ** nodes,int totnode)1119 void SCULPT_cloth_sim_activate_nodes(SculptClothSimulation *cloth_sim,
1120                                      PBVHNode **nodes,
1121                                      int totnode)
1122 {
1123   /* Activate the nodes inside the simulation area. */
1124   for (int n = 0; n < totnode; n++) {
1125     const int node_index = POINTER_AS_INT(BLI_ghash_lookup(cloth_sim->node_state_index, nodes[n]));
1126     cloth_sim->node_state[node_index] = SCULPT_CLOTH_NODE_ACTIVE;
1127   }
1128 }
1129 
sculpt_cloth_ensure_constraints_in_simulation_area(Sculpt * sd,Object * ob,PBVHNode ** nodes,int totnode)1130 static void sculpt_cloth_ensure_constraints_in_simulation_area(Sculpt *sd,
1131                                                                Object *ob,
1132                                                                PBVHNode **nodes,
1133                                                                int totnode)
1134 {
1135   SculptSession *ss = ob->sculpt;
1136   Brush *brush = BKE_paint_brush(&sd->paint);
1137   const float radius = ss->cache->initial_radius;
1138   const float limit = radius + (radius * brush->cloth_sim_limit);
1139   float sim_location[3];
1140   cloth_brush_simulation_location_get(ss, brush, sim_location);
1141   SCULPT_cloth_brush_ensure_nodes_constraints(
1142       sd, ob, nodes, totnode, ss->cache->cloth_sim, sim_location, limit);
1143 }
1144 
1145 /* Main Brush Function. */
SCULPT_do_cloth_brush(Sculpt * sd,Object * ob,PBVHNode ** nodes,int totnode)1146 void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
1147 {
1148   SculptSession *ss = ob->sculpt;
1149   Brush *brush = BKE_paint_brush(&sd->paint);
1150 
1151   /* Brushes that use anchored strokes and restore the mesh can't rely on symmetry passes and steps
1152    * count as it is always the first step, so the simulation needs to be created when it does not
1153    * exist for this stroke. */
1154   if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache) || !ss->cache->cloth_sim) {
1155 
1156     /* The simulation structure only needs to be created on the first symmetry pass. */
1157     if (SCULPT_stroke_is_first_brush_step(ss->cache) || !ss->cache->cloth_sim) {
1158       ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create(
1159           ss,
1160           brush->cloth_mass,
1161           brush->cloth_damping,
1162           brush->cloth_constraint_softbody_strength,
1163           (brush->flag2 & BRUSH_CLOTH_USE_COLLISION),
1164           SCULPT_is_cloth_deform_brush(brush));
1165       SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim);
1166     }
1167 
1168     if (brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL) {
1169       /* When using simulation a fixed local simulation area, constraints are created only using
1170        * the initial stroke position and initial radius (per symmetry pass) instead of per node.
1171        * This allows to skip unnecessary constraints that will never be simulated, making the
1172        * solver faster. When the simulation starts for a node, the node gets activated and all its
1173        * constraints are considered final. As the same node can be included inside the brush radius
1174        * from multiple symmetry passes, the cloth brush can't activate the node for simulation yet
1175        * as this will cause the ensure constraints function to skip the node in the next symmetry
1176        * passes. It needs to build the constraints here and skip simulating the first step, so all
1177        * passes can add their constraints to all affected nodes. */
1178       sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes, totnode);
1179     }
1180     /* The first step of a symmetry pass is never simulated as deformation modes need valid delta
1181      * for brush tip alignement. */
1182     return;
1183   }
1184 
1185   /* Ensure the constraints for the nodes. */
1186   sculpt_cloth_ensure_constraints_in_simulation_area(sd, ob, nodes, totnode);
1187 
1188   /* Store the initial state in the simulation. */
1189   SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim);
1190 
1191   /* Enable the nodes that should be simulated. */
1192   SCULPT_cloth_sim_activate_nodes(ss->cache->cloth_sim, nodes, totnode);
1193 
1194   /* Apply forces to the vertices. */
1195   cloth_brush_apply_brush_foces(sd, ob, nodes, totnode);
1196 
1197   /* Update and write the simulation to the nodes. */
1198   SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode);
1199 }
1200 
SCULPT_cloth_simulation_free(struct SculptClothSimulation * cloth_sim)1201 void SCULPT_cloth_simulation_free(struct SculptClothSimulation *cloth_sim)
1202 {
1203   MEM_SAFE_FREE(cloth_sim->pos);
1204   MEM_SAFE_FREE(cloth_sim->last_iteration_pos);
1205   MEM_SAFE_FREE(cloth_sim->prev_pos);
1206   MEM_SAFE_FREE(cloth_sim->acceleration);
1207   MEM_SAFE_FREE(cloth_sim->length_constraints);
1208   MEM_SAFE_FREE(cloth_sim->length_constraint_tweak);
1209   MEM_SAFE_FREE(cloth_sim->deformation_pos);
1210   MEM_SAFE_FREE(cloth_sim->softbody_pos);
1211   MEM_SAFE_FREE(cloth_sim->init_pos);
1212   MEM_SAFE_FREE(cloth_sim->deformation_strength);
1213   MEM_SAFE_FREE(cloth_sim->node_state);
1214   BLI_ghash_free(cloth_sim->node_state_index, NULL, NULL);
1215   if (cloth_sim->collider_list) {
1216     BKE_collider_cache_free(&cloth_sim->collider_list);
1217   }
1218   MEM_SAFE_FREE(cloth_sim);
1219 }
1220 
1221 /* Cursor drawing function. */
SCULPT_cloth_simulation_limits_draw(const uint gpuattr,const Brush * brush,const float location[3],const float normal[3],const float rds,const float line_width,const float outline_col[3],const float alpha)1222 void SCULPT_cloth_simulation_limits_draw(const uint gpuattr,
1223                                          const Brush *brush,
1224                                          const float location[3],
1225                                          const float normal[3],
1226                                          const float rds,
1227                                          const float line_width,
1228                                          const float outline_col[3],
1229                                          const float alpha)
1230 {
1231   float cursor_trans[4][4], cursor_rot[4][4];
1232   const float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f};
1233   float quat[4];
1234   unit_m4(cursor_trans);
1235   translate_m4(cursor_trans, location[0], location[1], location[2]);
1236   rotation_between_vecs_to_quat(quat, z_axis, normal);
1237   quat_to_mat4(cursor_rot, quat);
1238   GPU_matrix_push();
1239   GPU_matrix_mul(cursor_trans);
1240   GPU_matrix_mul(cursor_rot);
1241 
1242   GPU_line_width(line_width);
1243   immUniformColor3fvAlpha(outline_col, alpha * 0.5f);
1244   imm_draw_circle_dashed_3d(
1245       gpuattr, 0, 0, rds + (rds * brush->cloth_sim_limit * brush->cloth_sim_falloff), 320);
1246   immUniformColor3fvAlpha(outline_col, alpha * 0.7f);
1247   imm_draw_circle_wire_3d(gpuattr, 0, 0, rds + rds * brush->cloth_sim_limit, 80);
1248   GPU_matrix_pop();
1249 }
1250 
SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr,SculptSession * ss,const float outline_col[3],float outline_alpha)1251 void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr,
1252                                              SculptSession *ss,
1253                                              const float outline_col[3],
1254                                              float outline_alpha)
1255 {
1256   float local_mat_inv[4][4];
1257   invert_m4_m4(local_mat_inv, ss->cache->stroke_local_mat);
1258   GPU_matrix_mul(ss->cache->stroke_local_mat);
1259 
1260   const float dist = ss->cache->radius;
1261   const float arrow_x = ss->cache->radius * 0.2f;
1262   const float arrow_y = ss->cache->radius * 0.1f;
1263 
1264   immUniformColor3fvAlpha(outline_col, outline_alpha);
1265   GPU_line_width(2.0f);
1266   immBegin(GPU_PRIM_LINES, 2);
1267   immVertex3f(gpuattr, dist, 0.0f, 0.0f);
1268   immVertex3f(gpuattr, -dist, 0.0f, 0.0f);
1269   immEnd();
1270 
1271   immBegin(GPU_PRIM_TRIS, 6);
1272   immVertex3f(gpuattr, dist, 0.0f, 0.0f);
1273   immVertex3f(gpuattr, dist - arrow_x, arrow_y, 0.0f);
1274   immVertex3f(gpuattr, dist - arrow_x, -arrow_y, 0.0f);
1275 
1276   immVertex3f(gpuattr, -dist, 0.0f, 0.0f);
1277   immVertex3f(gpuattr, -dist + arrow_x, arrow_y, 0.0f);
1278   immVertex3f(gpuattr, -dist + arrow_x, -arrow_y, 0.0f);
1279 
1280   immEnd();
1281 }
1282 
1283 /* Cloth Filter. */
1284 
1285 typedef enum eSculpClothFilterType {
1286   CLOTH_FILTER_GRAVITY,
1287   CLOTH_FILTER_INFLATE,
1288   CLOTH_FILTER_EXPAND,
1289   CLOTH_FILTER_PINCH,
1290   CLOTH_FILTER_SCALE,
1291 } eSculptClothFilterType;
1292 
1293 static EnumPropertyItem prop_cloth_filter_type[] = {
1294     {CLOTH_FILTER_GRAVITY, "GRAVITY", 0, "Gravity", "Applies gravity to the simulation"},
1295     {CLOTH_FILTER_INFLATE, "INFLATE", 0, "Inflate", "Inflates the cloth"},
1296     {CLOTH_FILTER_EXPAND, "EXPAND", 0, "Expand", "Expands the cloth's dimensions"},
1297     {CLOTH_FILTER_PINCH, "PINCH", 0, "Pinch", "Pulls the cloth to the cursor's start position"},
1298     {CLOTH_FILTER_SCALE,
1299      "SCALE",
1300      0,
1301      "Scale",
1302      "Scales the mesh as a softbody using the origin of the object as scale"},
1303     {0, NULL, 0, NULL, NULL},
1304 };
1305 
1306 static EnumPropertyItem prop_cloth_filter_orientation_items[] = {
1307     {SCULPT_FILTER_ORIENTATION_LOCAL,
1308      "LOCAL",
1309      0,
1310      "Local",
1311      "Use the local axis to limit the force and set the gravity direction"},
1312     {SCULPT_FILTER_ORIENTATION_WORLD,
1313      "WORLD",
1314      0,
1315      "World",
1316      "Use the global axis to limit the force and set the gravity direction"},
1317     {SCULPT_FILTER_ORIENTATION_VIEW,
1318      "VIEW",
1319      0,
1320      "View",
1321      "Use the view axis to limit the force and set the gravity direction"},
1322     {0, NULL, 0, NULL, NULL},
1323 };
1324 
1325 typedef enum eClothFilterForceAxis {
1326   CLOTH_FILTER_FORCE_X = 1 << 0,
1327   CLOTH_FILTER_FORCE_Y = 1 << 1,
1328   CLOTH_FILTER_FORCE_Z = 1 << 2,
1329 } eClothFilterForceAxis;
1330 
1331 static EnumPropertyItem prop_cloth_filter_force_axis_items[] = {
1332     {CLOTH_FILTER_FORCE_X, "X", 0, "X", "Apply force in the X axis"},
1333     {CLOTH_FILTER_FORCE_Y, "Y", 0, "Y", "Apply force in the Y axis"},
1334     {CLOTH_FILTER_FORCE_Z, "Z", 0, "Z", "Apply force in the Z axis"},
1335     {0, NULL, 0, NULL, NULL},
1336 };
1337 
cloth_filter_is_deformation_filter(eSculptClothFilterType filter_type)1338 static bool cloth_filter_is_deformation_filter(eSculptClothFilterType filter_type)
1339 {
1340   return ELEM(filter_type, CLOTH_FILTER_SCALE);
1341 }
1342 
cloth_filter_apply_displacement_to_deform_co(const int v_index,const float disp[3],FilterCache * filter_cache)1343 static void cloth_filter_apply_displacement_to_deform_co(const int v_index,
1344                                                          const float disp[3],
1345                                                          FilterCache *filter_cache)
1346 {
1347   float final_disp[3];
1348   copy_v3_v3(final_disp, disp);
1349   SCULPT_filter_zero_disabled_axis_components(final_disp, filter_cache);
1350   add_v3_v3v3(filter_cache->cloth_sim->deformation_pos[v_index],
1351               filter_cache->cloth_sim->init_pos[v_index],
1352               final_disp);
1353 }
1354 
cloth_filter_apply_forces_to_vertices(const int v_index,const float force[3],const float gravity[3],FilterCache * filter_cache)1355 static void cloth_filter_apply_forces_to_vertices(const int v_index,
1356                                                   const float force[3],
1357                                                   const float gravity[3],
1358                                                   FilterCache *filter_cache)
1359 {
1360   float final_force[3];
1361   copy_v3_v3(final_force, force);
1362   SCULPT_filter_zero_disabled_axis_components(final_force, filter_cache);
1363   add_v3_v3(final_force, gravity);
1364   cloth_brush_apply_force_to_vertex(NULL, filter_cache->cloth_sim, final_force, v_index);
1365 }
1366 
cloth_filter_apply_forces_task_cb(void * __restrict userdata,const int i,const TaskParallelTLS * __restrict UNUSED (tls))1367 static void cloth_filter_apply_forces_task_cb(void *__restrict userdata,
1368                                               const int i,
1369                                               const TaskParallelTLS *__restrict UNUSED(tls))
1370 {
1371   SculptThreadedTaskData *data = userdata;
1372   Sculpt *sd = data->sd;
1373   SculptSession *ss = data->ob->sculpt;
1374   PBVHNode *node = data->nodes[i];
1375 
1376   SculptClothSimulation *cloth_sim = ss->filter_cache->cloth_sim;
1377 
1378   const eSculptClothFilterType filter_type = data->filter_type;
1379   const bool is_deformation_filter = cloth_filter_is_deformation_filter(filter_type);
1380 
1381   float sculpt_gravity[3] = {0.0f};
1382   if (sd->gravity_object) {
1383     copy_v3_v3(sculpt_gravity, sd->gravity_object->obmat[2]);
1384   }
1385   else {
1386     sculpt_gravity[2] = -1.0f;
1387   }
1388   mul_v3_fl(sculpt_gravity, sd->gravity_factor * data->filter_strength);
1389 
1390   PBVHVertexIter vd;
1391   BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
1392   {
1393     float fade = vd.mask ? *vd.mask : 0.0f;
1394     fade *= SCULPT_automasking_factor_get(ss->filter_cache->automasking, ss, vd.index);
1395     fade = 1.0f - fade;
1396     float force[3] = {0.0f, 0.0f, 0.0f};
1397     float disp[3], temp[3], transform[3][3];
1398 
1399     if (ss->filter_cache->active_face_set != SCULPT_FACE_SET_NONE) {
1400       if (!SCULPT_vertex_has_face_set(ss, vd.index, ss->filter_cache->active_face_set)) {
1401         continue;
1402       }
1403     }
1404 
1405     switch (filter_type) {
1406       case CLOTH_FILTER_GRAVITY:
1407         if (ss->filter_cache->orientation == SCULPT_FILTER_ORIENTATION_VIEW) {
1408           /* When using the view orientation apply gravity in the -Y axis, this way objects will
1409            * fall down instead of backwards. */
1410           force[1] = -data->filter_strength * fade;
1411         }
1412         else {
1413           force[2] = -data->filter_strength * fade;
1414         }
1415         SCULPT_filter_to_object_space(force, ss->filter_cache);
1416         break;
1417       case CLOTH_FILTER_INFLATE: {
1418         float normal[3];
1419         SCULPT_vertex_normal_get(ss, vd.index, normal);
1420         mul_v3_v3fl(force, normal, fade * data->filter_strength);
1421       } break;
1422       case CLOTH_FILTER_EXPAND:
1423         cloth_sim->length_constraint_tweak[vd.index] += fade * data->filter_strength * 0.01f;
1424         zero_v3(force);
1425         break;
1426       case CLOTH_FILTER_PINCH:
1427         sub_v3_v3v3(force, ss->filter_cache->cloth_sim_pinch_point, vd.co);
1428         normalize_v3(force);
1429         mul_v3_fl(force, fade * data->filter_strength);
1430         break;
1431       case CLOTH_FILTER_SCALE:
1432         unit_m3(transform);
1433         scale_m3_fl(transform, 1.0f + (fade * data->filter_strength));
1434         copy_v3_v3(temp, cloth_sim->init_pos[vd.index]);
1435         mul_m3_v3(transform, temp);
1436         sub_v3_v3v3(disp, temp, cloth_sim->init_pos[vd.index]);
1437         zero_v3(force);
1438 
1439         break;
1440     }
1441 
1442     if (is_deformation_filter) {
1443       cloth_filter_apply_displacement_to_deform_co(vd.index, disp, ss->filter_cache);
1444     }
1445     else {
1446       cloth_filter_apply_forces_to_vertices(vd.index, force, sculpt_gravity, ss->filter_cache);
1447     }
1448   }
1449   BKE_pbvh_vertex_iter_end;
1450 
1451   BKE_pbvh_node_mark_update(node);
1452 }
1453 
sculpt_cloth_filter_modal(bContext * C,wmOperator * op,const wmEvent * event)1454 static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
1455 {
1456   Object *ob = CTX_data_active_object(C);
1457   Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
1458   SculptSession *ss = ob->sculpt;
1459   Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
1460   int filter_type = RNA_enum_get(op->ptr, "type");
1461   float filter_strength = RNA_float_get(op->ptr, "strength");
1462 
1463   if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
1464     SCULPT_filter_cache_free(ss);
1465     SCULPT_undo_push_end();
1466     SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
1467     return OPERATOR_FINISHED;
1468   }
1469 
1470   if (event->type != MOUSEMOVE) {
1471     return OPERATOR_RUNNING_MODAL;
1472   }
1473 
1474   const float len = event->prevclickx - event->x;
1475   filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC;
1476 
1477   SCULPT_vertex_random_access_ensure(ss);
1478 
1479   BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
1480 
1481   const int totverts = SCULPT_vertex_count_get(ss);
1482 
1483   for (int i = 0; i < totverts; i++) {
1484     copy_v3_v3(ss->filter_cache->cloth_sim->pos[i], SCULPT_vertex_co_get(ss, i));
1485   }
1486 
1487   SculptThreadedTaskData data = {
1488       .sd = sd,
1489       .ob = ob,
1490       .nodes = ss->filter_cache->nodes,
1491       .filter_type = filter_type,
1492       .filter_strength = filter_strength,
1493   };
1494 
1495   TaskParallelSettings settings;
1496   BKE_pbvh_parallel_range_settings(&settings, true, ss->filter_cache->totnode);
1497   BLI_task_parallel_range(
1498       0, ss->filter_cache->totnode, &data, cloth_filter_apply_forces_task_cb, &settings);
1499 
1500   /* Activate all nodes. */
1501   SCULPT_cloth_sim_activate_nodes(
1502       ss->filter_cache->cloth_sim, ss->filter_cache->nodes, ss->filter_cache->totnode);
1503 
1504   /* Update and write the simulation to the nodes. */
1505   SCULPT_cloth_brush_do_simulation_step(
1506       sd, ob, ss->filter_cache->cloth_sim, ss->filter_cache->nodes, ss->filter_cache->totnode);
1507 
1508   if (ss->deform_modifiers_active || ss->shapekey_active) {
1509     SCULPT_flush_stroke_deform(sd, ob, true);
1510   }
1511   SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS);
1512   return OPERATOR_RUNNING_MODAL;
1513 }
1514 
sculpt_cloth_filter_invoke(bContext * C,wmOperator * op,const wmEvent * event)1515 static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1516 {
1517   Object *ob = CTX_data_active_object(C);
1518   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
1519   Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
1520   SculptSession *ss = ob->sculpt;
1521 
1522   const eSculptClothFilterType filter_type = RNA_enum_get(op->ptr, "type");
1523 
1524   /* Update the active vertex */
1525   float mouse[2];
1526   SculptCursorGeometryInfo sgi;
1527   mouse[0] = event->mval[0];
1528   mouse[1] = event->mval[1];
1529   SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
1530 
1531   SCULPT_vertex_random_access_ensure(ss);
1532 
1533   /* Needs mask data to be available as it is used when solving the constraints. */
1534   BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
1535 
1536   SCULPT_undo_push_begin("Cloth filter");
1537   SCULPT_filter_cache_init(C, ob, sd, SCULPT_UNDO_COORDS);
1538 
1539   ss->filter_cache->automasking = SCULPT_automasking_cache_init(sd, NULL, ob);
1540 
1541   const float cloth_mass = RNA_float_get(op->ptr, "cloth_mass");
1542   const float cloth_damping = RNA_float_get(op->ptr, "cloth_damping");
1543   const bool use_collisions = RNA_boolean_get(op->ptr, "use_collisions");
1544   ss->filter_cache->cloth_sim = SCULPT_cloth_brush_simulation_create(
1545       ss,
1546       cloth_mass,
1547       cloth_damping,
1548       0.0f,
1549       use_collisions,
1550       cloth_filter_is_deformation_filter(filter_type));
1551 
1552   copy_v3_v3(ss->filter_cache->cloth_sim_pinch_point, SCULPT_active_vertex_co_get(ss));
1553 
1554   SCULPT_cloth_brush_simulation_init(ss, ss->filter_cache->cloth_sim);
1555 
1556   float origin[3] = {0.0f, 0.0f, 0.0f};
1557   SCULPT_cloth_brush_ensure_nodes_constraints(sd,
1558                                               ob,
1559                                               ss->filter_cache->nodes,
1560                                               ss->filter_cache->totnode,
1561                                               ss->filter_cache->cloth_sim,
1562                                               origin,
1563                                               FLT_MAX);
1564 
1565   const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets");
1566   if (use_face_sets) {
1567     ss->filter_cache->active_face_set = SCULPT_active_face_set_get(ss);
1568   }
1569   else {
1570     ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
1571   }
1572 
1573   const int force_axis = RNA_enum_get(op->ptr, "force_axis");
1574   ss->filter_cache->enabled_force_axis[0] = force_axis & CLOTH_FILTER_FORCE_X;
1575   ss->filter_cache->enabled_force_axis[1] = force_axis & CLOTH_FILTER_FORCE_Y;
1576   ss->filter_cache->enabled_force_axis[2] = force_axis & CLOTH_FILTER_FORCE_Z;
1577 
1578   SculptFilterOrientation orientation = RNA_enum_get(op->ptr, "orientation");
1579   ss->filter_cache->orientation = orientation;
1580 
1581   WM_event_add_modal_handler(C, op);
1582   return OPERATOR_RUNNING_MODAL;
1583 }
1584 
SCULPT_OT_cloth_filter(struct wmOperatorType * ot)1585 void SCULPT_OT_cloth_filter(struct wmOperatorType *ot)
1586 {
1587   /* Identifiers. */
1588   ot->name = "Filter Cloth";
1589   ot->idname = "SCULPT_OT_cloth_filter";
1590   ot->description = "Applies a cloth simulation deformation to the entire mesh";
1591 
1592   /* API callbacks. */
1593   ot->invoke = sculpt_cloth_filter_invoke;
1594   ot->modal = sculpt_cloth_filter_modal;
1595   ot->poll = SCULPT_mode_poll;
1596 
1597   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1598 
1599   /* RNA. */
1600   RNA_def_enum(ot->srna,
1601                "type",
1602                prop_cloth_filter_type,
1603                CLOTH_FILTER_GRAVITY,
1604                "Filter type",
1605                "Operation that is going to be applied to the mesh");
1606   RNA_def_float(
1607       ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f);
1608   RNA_def_enum_flag(ot->srna,
1609                     "force_axis",
1610                     prop_cloth_filter_force_axis_items,
1611                     CLOTH_FILTER_FORCE_X | CLOTH_FILTER_FORCE_Y | CLOTH_FILTER_FORCE_Z,
1612                     "Force axis",
1613                     "Apply the force in the selected axis");
1614   RNA_def_enum(ot->srna,
1615                "orientation",
1616                prop_cloth_filter_orientation_items,
1617                SCULPT_FILTER_ORIENTATION_LOCAL,
1618                "Orientation",
1619                "Orientation of the axis to limit the filter force");
1620   RNA_def_float(ot->srna,
1621                 "cloth_mass",
1622                 1.0f,
1623                 0.0f,
1624                 2.0f,
1625                 "Cloth Mass",
1626                 "Mass of each simulation particle",
1627                 0.0f,
1628                 1.0f);
1629   RNA_def_float(ot->srna,
1630                 "cloth_damping",
1631                 0.0f,
1632                 0.0f,
1633                 1.0f,
1634                 "Cloth Damping",
1635                 "How much the applied forces are propagated through the cloth",
1636                 0.0f,
1637                 1.0f);
1638   ot->prop = RNA_def_boolean(ot->srna,
1639                              "use_face_sets",
1640                              false,
1641                              "Use Face Sets",
1642                              "Apply the filter only to the Face Set under the cursor");
1643   ot->prop = RNA_def_boolean(ot->srna,
1644                              "use_collisions",
1645                              false,
1646                              "Use Collisions",
1647                              "Collide with other collider objects in the scene");
1648 }
1649