Fix T70013: slow OpenGL calls for every vertex and weight painting step
[blender.git] / source / blender / modifiers / intern / MOD_simpledeform.c
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) 2005 by the Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup modifiers
22  */
23
24 #include "BLI_utildefines.h"
25
26 #include "BLI_math.h"
27
28 #include "DNA_mesh_types.h"
29 #include "DNA_meshdata_types.h"
30 #include "DNA_object_types.h"
31
32 #include "BKE_editmesh.h"
33 #include "BKE_mesh.h"
34 #include "BKE_library.h"
35 #include "BKE_library_query.h"
36 #include "BKE_modifier.h"
37 #include "BKE_deform.h"
38
39 #include "DEG_depsgraph_query.h"
40
41 #include "MOD_util.h"
42
43 #include "bmesh.h"
44
45 #define BEND_EPS 0.000001f
46
47 /* Re-maps the indices for X Y Z by shifting them up and wrapping, such that
48  * X = Y, Y = Z, Z = X (for X axis), and X = Z, Y = X, Z = Y (for Y axis). This
49  * exists because the deformations (excluding bend) are based on the Z axis.
50  * Having this helps avoid long, drawn out switches. */
51 static const uint axis_map_table[3][3] = {
52     {1, 2, 0},
53     {2, 0, 1},
54     {0, 1, 2},
55 };
56
57 BLI_INLINE void copy_v3_v3_map(float a[3], const float b[3], const uint map[3])
58 {
59   a[0] = b[map[0]];
60   a[1] = b[map[1]];
61   a[2] = b[map[2]];
62 }
63
64 BLI_INLINE void copy_v3_v3_unmap(float a[3], const float b[3], const uint map[3])
65 {
66   a[map[0]] = b[0];
67   a[map[1]] = b[1];
68   a[map[2]] = b[2];
69 }
70
71 /* Clamps/Limits the given coordinate to:  limits[0] <= co[axis] <= limits[1]
72  * The amount of clamp is saved on dcut */
73 static void axis_limit(const int axis, const float limits[2], float co[3], float dcut[3])
74 {
75   float val = co[axis];
76   if (limits[0] > val) {
77     val = limits[0];
78   }
79   if (limits[1] < val) {
80     val = limits[1];
81   }
82
83   dcut[axis] = co[axis] - val;
84   co[axis] = val;
85 }
86
87 static void simpleDeform_taper(const float factor,
88                                const int UNUSED(axis),
89                                const float dcut[3],
90                                float r_co[3])
91 {
92   float x = r_co[0], y = r_co[1], z = r_co[2];
93   float scale = z * factor;
94
95   r_co[0] = x + x * scale;
96   r_co[1] = y + y * scale;
97   r_co[2] = z;
98
99   add_v3_v3(r_co, dcut);
100 }
101
102 static void simpleDeform_stretch(const float factor,
103                                  const int UNUSED(axis),
104                                  const float dcut[3],
105                                  float r_co[3])
106 {
107   float x = r_co[0], y = r_co[1], z = r_co[2];
108   float scale;
109
110   scale = (z * z * factor - factor + 1.0f);
111
112   r_co[0] = x * scale;
113   r_co[1] = y * scale;
114   r_co[2] = z * (1.0f + factor);
115
116   add_v3_v3(r_co, dcut);
117 }
118
119 static void simpleDeform_twist(const float factor,
120                                const int UNUSED(axis),
121                                const float *dcut,
122                                float r_co[3])
123 {
124   float x = r_co[0], y = r_co[1], z = r_co[2];
125   float theta, sint, cost;
126
127   theta = z * factor;
128   sint = sinf(theta);
129   cost = cosf(theta);
130
131   r_co[0] = x * cost - y * sint;
132   r_co[1] = x * sint + y * cost;
133   r_co[2] = z;
134
135   add_v3_v3(r_co, dcut);
136 }
137
138 static void simpleDeform_bend(const float factor,
139                               const int axis,
140                               const float dcut[3],
141                               float r_co[3])
142 {
143   float x = r_co[0], y = r_co[1], z = r_co[2];
144   float theta, sint, cost;
145
146   BLI_assert(!(fabsf(factor) < BEND_EPS));
147
148   switch (axis) {
149     case 0:
150       ATTR_FALLTHROUGH;
151     case 1:
152       theta = z * factor;
153       break;
154     default:
155       theta = x * factor;
156   }
157   sint = sinf(theta);
158   cost = cosf(theta);
159
160   switch (axis) {
161     case 0:
162       r_co[0] = x;
163       r_co[1] = (y - 1.0f / factor) * cost + 1.0f / factor;
164       r_co[2] = -(y - 1.0f / factor) * sint;
165       {
166         r_co[0] += dcut[0];
167         r_co[1] += sint * dcut[2];
168         r_co[2] += cost * dcut[2];
169       }
170       break;
171     case 1:
172       r_co[0] = (x - 1.0f / factor) * cost + 1.0f / factor;
173       r_co[1] = y;
174       r_co[2] = -(x - 1.0f / factor) * sint;
175       {
176         r_co[0] += sint * dcut[2];
177         r_co[1] += dcut[1];
178         r_co[2] += cost * dcut[2];
179       }
180       break;
181     default:
182       r_co[0] = -(y - 1.0f / factor) * sint;
183       r_co[1] = (y - 1.0f / factor) * cost + 1.0f / factor;
184       r_co[2] = z;
185       {
186         r_co[0] += cost * dcut[0];
187         r_co[1] += sint * dcut[0];
188         r_co[2] += dcut[2];
189       }
190   }
191 }
192
193 /* simple deform modifier */
194 static void SimpleDeformModifier_do(SimpleDeformModifierData *smd,
195                                     const ModifierEvalContext *UNUSED(ctx),
196                                     struct Object *ob,
197                                     struct Mesh *mesh,
198                                     float (*vertexCos)[3],
199                                     int numVerts)
200 {
201   const float base_limit[2] = {0.0f, 0.0f};
202   int i;
203   float smd_limit[2], smd_factor;
204   SpaceTransform *transf = NULL, tmp_transf;
205   void (*simpleDeform_callback)(const float factor,
206                                 const int axis,
207                                 const float dcut[3],
208                                 float co[3]) = NULL; /* Mode callback */
209   int vgroup;
210   MDeformVert *dvert;
211
212   /* This is historically the lock axis, _not_ the deform axis as the name would imply */
213   const int deform_axis = smd->deform_axis;
214   int lock_axis = smd->axis;
215   if (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) { /* Bend mode shouldn't have any lock axis */
216     lock_axis = 0;
217   }
218   else {
219     /* Don't lock axis if it is the chosen deform axis, as this flattens
220      * the geometry */
221     if (deform_axis == 0) {
222       lock_axis &= ~MOD_SIMPLEDEFORM_LOCK_AXIS_X;
223     }
224     if (deform_axis == 1) {
225       lock_axis &= ~MOD_SIMPLEDEFORM_LOCK_AXIS_Y;
226     }
227     if (deform_axis == 2) {
228       lock_axis &= ~MOD_SIMPLEDEFORM_LOCK_AXIS_Z;
229     }
230   }
231
232   /* Safe-check */
233   if (smd->origin == ob) {
234     smd->origin = NULL; /* No self references */
235   }
236
237   if (smd->limit[0] < 0.0f) {
238     smd->limit[0] = 0.0f;
239   }
240   if (smd->limit[0] > 1.0f) {
241     smd->limit[0] = 1.0f;
242   }
243
244   smd->limit[0] = min_ff(smd->limit[0], smd->limit[1]); /* Upper limit >= than lower limit */
245
246   /* Calculate matrixs do convert between coordinate spaces */
247   if (smd->origin != NULL) {
248     transf = &tmp_transf;
249     BLI_SPACE_TRANSFORM_SETUP(transf, ob, smd->origin);
250   }
251
252   /* Update limits if needed */
253   int limit_axis = deform_axis;
254   if (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) {
255     /* Bend is a special case. */
256     switch (deform_axis) {
257       case 0:
258         ATTR_FALLTHROUGH;
259       case 1:
260         limit_axis = 2;
261         break;
262       default:
263         limit_axis = 0;
264     }
265   }
266
267   {
268     float lower = FLT_MAX;
269     float upper = -FLT_MAX;
270
271     for (i = 0; i < numVerts; i++) {
272       float tmp[3];
273       copy_v3_v3(tmp, vertexCos[i]);
274
275       if (transf) {
276         BLI_space_transform_apply(transf, tmp);
277       }
278
279       lower = min_ff(lower, tmp[limit_axis]);
280       upper = max_ff(upper, tmp[limit_axis]);
281     }
282
283     /* SMD values are normalized to the BV, calculate the absolute values */
284     smd_limit[1] = lower + (upper - lower) * smd->limit[1];
285     smd_limit[0] = lower + (upper - lower) * smd->limit[0];
286
287     smd_factor = smd->factor / max_ff(FLT_EPSILON, smd_limit[1] - smd_limit[0]);
288   }
289
290   switch (smd->mode) {
291     case MOD_SIMPLEDEFORM_MODE_TWIST:
292       simpleDeform_callback = simpleDeform_twist;
293       break;
294     case MOD_SIMPLEDEFORM_MODE_BEND:
295       simpleDeform_callback = simpleDeform_bend;
296       break;
297     case MOD_SIMPLEDEFORM_MODE_TAPER:
298       simpleDeform_callback = simpleDeform_taper;
299       break;
300     case MOD_SIMPLEDEFORM_MODE_STRETCH:
301       simpleDeform_callback = simpleDeform_stretch;
302       break;
303     default:
304       return; /* No simpledeform mode? */
305   }
306
307   if (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) {
308     if (fabsf(smd_factor) < BEND_EPS) {
309       return;
310     }
311   }
312
313   MOD_get_vgroup(ob, mesh, smd->vgroup_name, &dvert, &vgroup);
314   const bool invert_vgroup = (smd->flag & MOD_SIMPLEDEFORM_FLAG_INVERT_VGROUP) != 0;
315   const uint *axis_map =
316       axis_map_table[(smd->mode != MOD_SIMPLEDEFORM_MODE_BEND) ? deform_axis : 2];
317
318   for (i = 0; i < numVerts; i++) {
319     float weight = defvert_array_find_weight_safe(dvert, i, vgroup);
320
321     if (invert_vgroup) {
322       weight = 1.0f - weight;
323     }
324
325     if (weight != 0.0f) {
326       float co[3], dcut[3] = {0.0f, 0.0f, 0.0f};
327
328       if (transf) {
329         BLI_space_transform_apply(transf, vertexCos[i]);
330       }
331
332       copy_v3_v3(co, vertexCos[i]);
333
334       /* Apply axis limits, and axis mappings */
335       if (lock_axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) {
336         axis_limit(0, base_limit, co, dcut);
337       }
338       if (lock_axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) {
339         axis_limit(1, base_limit, co, dcut);
340       }
341       if (lock_axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Z) {
342         axis_limit(2, base_limit, co, dcut);
343       }
344       axis_limit(limit_axis, smd_limit, co, dcut);
345
346       /* apply the deform to a mapped copy of the vertex, and then re-map it back. */
347       float co_remap[3];
348       float dcut_remap[3];
349       copy_v3_v3_map(co_remap, co, axis_map);
350       copy_v3_v3_map(dcut_remap, dcut, axis_map);
351       simpleDeform_callback(smd_factor, deform_axis, dcut_remap, co_remap); /* apply deform */
352       copy_v3_v3_unmap(co, co_remap, axis_map);
353
354       /* Use vertex weight has coef of linear interpolation */
355       interp_v3_v3v3(vertexCos[i], vertexCos[i], co, weight);
356
357       if (transf) {
358         BLI_space_transform_invert(transf, vertexCos[i]);
359       }
360     }
361   }
362 }
363
364 /* SimpleDeform */
365 static void initData(ModifierData *md)
366 {
367   SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
368
369   smd->mode = MOD_SIMPLEDEFORM_MODE_TWIST;
370   smd->axis = 0;
371   smd->deform_axis = 0;
372
373   smd->origin = NULL;
374   smd->factor = DEG2RADF(45.0f);
375   smd->limit[0] = 0.0f;
376   smd->limit[1] = 1.0f;
377 }
378
379 static void requiredDataMask(Object *UNUSED(ob),
380                              ModifierData *md,
381                              CustomData_MeshMasks *r_cddata_masks)
382 {
383   SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
384
385   /* ask for vertexgroups if we need them */
386   if (smd->vgroup_name[0] != '\0') {
387     r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
388   }
389 }
390
391 static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
392 {
393   SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
394   walk(userData, ob, &smd->origin, IDWALK_CB_NOP);
395 }
396
397 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
398 {
399   SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md;
400   if (smd->origin != NULL) {
401     DEG_add_object_relation(
402         ctx->node, smd->origin, DEG_OB_COMP_TRANSFORM, "SimpleDeform Modifier");
403     DEG_add_modifier_to_transform_relation(ctx->node, "SimpleDeform Modifier");
404   }
405 }
406
407 static void deformVerts(ModifierData *md,
408                         const ModifierEvalContext *ctx,
409                         struct Mesh *mesh,
410                         float (*vertexCos)[3],
411                         int numVerts)
412 {
413   SimpleDeformModifierData *sdmd = (SimpleDeformModifierData *)md;
414   Mesh *mesh_src = NULL;
415
416   if (ctx->object->type == OB_MESH && sdmd->vgroup_name[0] != '\0') {
417     /* mesh_src is only needed for vgroups. */
418     mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
419   }
420
421   SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
422
423   if (!ELEM(mesh_src, NULL, mesh)) {
424     BKE_id_free(NULL, mesh_src);
425   }
426 }
427
428 static void deformVertsEM(ModifierData *md,
429                           const ModifierEvalContext *ctx,
430                           struct BMEditMesh *editData,
431                           struct Mesh *mesh,
432                           float (*vertexCos)[3],
433                           int numVerts)
434 {
435   SimpleDeformModifierData *sdmd = (SimpleDeformModifierData *)md;
436   Mesh *mesh_src = NULL;
437
438   if (ctx->object->type == OB_MESH && sdmd->vgroup_name[0] != '\0') {
439     /* mesh_src is only needed for vgroups. */
440     mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false);
441   }
442
443   SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, numVerts);
444
445   if (!ELEM(mesh_src, NULL, mesh)) {
446     BKE_id_free(NULL, mesh_src);
447   }
448 }
449
450 ModifierTypeInfo modifierType_SimpleDeform = {
451     /* name */ "SimpleDeform",
452     /* structName */ "SimpleDeformModifierData",
453     /* structSize */ sizeof(SimpleDeformModifierData),
454     /* type */ eModifierTypeType_OnlyDeform,
455
456     /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs |
457         eModifierTypeFlag_AcceptsLattice | eModifierTypeFlag_SupportsEditmode |
458         eModifierTypeFlag_EnableInEditmode,
459
460     /* copyData */ modifier_copyData_generic,
461
462     /* deformVerts */ deformVerts,
463     /* deformMatrices */ NULL,
464     /* deformVertsEM */ deformVertsEM,
465     /* deformMatricesEM */ NULL,
466     /* applyModifier */ NULL,
467
468     /* initData */ initData,
469     /* requiredDataMask */ requiredDataMask,
470     /* freeData */ NULL,
471     /* isDisabled */ NULL,
472     /* updateDepsgraph */ updateDepsgraph,
473     /* dependsOnTime */ NULL,
474     /* dependsOnNormals */ NULL,
475     /* foreachObjectLink */ foreachObjectLink,
476     /* foreachIDLink */ NULL,
477     /* foreachTexLink */ NULL,
478     /* freeRuntimeData */ NULL,
479 };