Merge branch 'master' into blender2.8
[blender.git] / source / blender / modifiers / intern / MOD_cast.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software  Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Daniel Dunbar
22  *                 Ton Roosendaal,
23  *                 Ben Batt,
24  *                 Brecht Van Lommel,
25  *                 Campbell Barton
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  *
29  */
30
31 /** \file blender/modifiers/intern/MOD_cast.c
32  *  \ingroup modifiers
33  */
34
35
36 #include "DNA_mesh_types.h"
37 #include "DNA_meshdata_types.h"
38 #include "DNA_object_types.h"
39
40 #include "BLI_math.h"
41 #include "BLI_utildefines.h"
42
43
44 #include "BKE_deform.h"
45 #include "BKE_editmesh.h"
46 #include "BKE_library.h"
47 #include "BKE_library_query.h"
48 #include "BKE_mesh.h"
49 #include "BKE_modifier.h"
50
51 #include "MOD_util.h"
52
53 static void initData(ModifierData *md)
54 {
55         CastModifierData *cmd = (CastModifierData *) md;
56
57         cmd->fac = 0.5f;
58         cmd->radius = 0.0f;
59         cmd->size = 0.0f;
60         cmd->flag = MOD_CAST_X | MOD_CAST_Y | MOD_CAST_Z | MOD_CAST_SIZE_FROM_RADIUS;
61         cmd->type = MOD_CAST_TYPE_SPHERE;
62         cmd->defgrp_name[0] = '\0';
63         cmd->object = NULL;
64 }
65
66 static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
67 {
68         CastModifierData *cmd = (CastModifierData *) md;
69         short flag;
70         
71         flag = cmd->flag & (MOD_CAST_X | MOD_CAST_Y | MOD_CAST_Z);
72
73         if ((cmd->fac == 0.0f) || flag == 0) return true;
74
75         return false;
76 }
77
78 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
79 {
80         CastModifierData *cmd = (CastModifierData *)md;
81         CustomDataMask dataMask = 0;
82
83         /* ask for vertexgroups if we need them */
84         if (cmd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT;
85
86         return dataMask;
87 }
88
89 static void foreachObjectLink(
90         ModifierData *md, Object *ob,
91         ObjectWalkFunc walk, void *userData)
92 {
93         CastModifierData *cmd = (CastModifierData *) md;
94
95         walk(userData, ob, &cmd->object, IDWALK_CB_NOP);
96 }
97
98 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
99 {
100         CastModifierData *cmd = (CastModifierData *)md;
101         if (cmd->object != NULL) {
102                 DEG_add_object_relation(ctx->node, cmd->object, DEG_OB_COMP_TRANSFORM, "Cast Modifier");
103                 DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Cast Modifier");
104         }
105 }
106
107 static void sphere_do(
108         CastModifierData *cmd, Object *ob, Mesh *mesh,
109         float (*vertexCos)[3], int numVerts)
110 {
111         MDeformVert *dvert = NULL;
112
113         Object *ctrl_ob = NULL;
114
115         int i, defgrp_index;
116         bool has_radius = false;
117         short flag, type;
118         float len = 0.0f;
119         float fac = cmd->fac;
120         float facm = 1.0f - fac;
121         const float fac_orig = fac;
122         float vec[3], center[3] = {0.0f, 0.0f, 0.0f};
123         float mat[4][4], imat[4][4];
124
125         flag = cmd->flag;
126         type = cmd->type; /* projection type: sphere or cylinder */
127
128         if (type == MOD_CAST_TYPE_CYLINDER) 
129                 flag &= ~MOD_CAST_Z;
130
131         ctrl_ob = cmd->object;
132
133         /* spherify's center is {0, 0, 0} (the ob's own center in its local
134          * space), by default, but if the user defined a control object,
135          * we use its location, transformed to ob's local space */
136         if (ctrl_ob) {
137                 if (flag & MOD_CAST_USE_OB_TRANSFORM) {
138                         invert_m4_m4(imat, ctrl_ob->obmat);
139                         mul_m4_m4m4(mat, imat, ob->obmat);
140                         invert_m4_m4(imat, mat);
141                 }
142
143                 invert_m4_m4(ob->imat, ob->obmat);
144                 mul_v3_m4v3(center, ob->imat, ctrl_ob->obmat[3]);
145         }
146
147         /* now we check which options the user wants */
148
149         /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
150         /* 2) cmd->radius > 0.0f: only the vertices within this radius from
151          * the center of the effect should be deformed */
152         if (cmd->radius > FLT_EPSILON) has_radius = 1;
153
154         /* 3) if we were given a vertex group name,
155          * only those vertices should be affected */
156         modifier_get_vgroup_mesh(ob, mesh, cmd->defgrp_name, &dvert, &defgrp_index);
157
158         if (flag & MOD_CAST_SIZE_FROM_RADIUS) {
159                 len = cmd->radius;
160         }
161         else {
162                 len = cmd->size;
163         }
164
165         if (len <= 0) {
166                 for (i = 0; i < numVerts; i++) {
167                         len += len_v3v3(center, vertexCos[i]);
168                 }
169                 len /= numVerts;
170
171                 if (len == 0.0f) len = 10.0f;
172         }
173
174         for (i = 0; i < numVerts; i++) {
175                 float tmp_co[3];
176
177                 copy_v3_v3(tmp_co, vertexCos[i]);
178                 if (ctrl_ob) {
179                         if (flag & MOD_CAST_USE_OB_TRANSFORM) {
180                                 mul_m4_v3(mat, tmp_co);
181                         }
182                         else {
183                                 sub_v3_v3(tmp_co, center);
184                         }
185                 }
186
187                 copy_v3_v3(vec, tmp_co);
188
189                 if (type == MOD_CAST_TYPE_CYLINDER)
190                         vec[2] = 0.0f;
191
192                 if (has_radius) {
193                         if (len_v3(vec) > cmd->radius) continue;
194                 }
195
196                 if (dvert) {
197                         const float weight = defvert_find_weight(&dvert[i], defgrp_index);
198                         if (weight == 0.0f) {
199                                 continue;
200                         }
201
202                         fac = fac_orig * weight;
203                         facm = 1.0f - fac;
204                 }
205
206                 normalize_v3(vec);
207
208                 if (flag & MOD_CAST_X)
209                         tmp_co[0] = fac * vec[0] * len + facm * tmp_co[0];
210                 if (flag & MOD_CAST_Y)
211                         tmp_co[1] = fac * vec[1] * len + facm * tmp_co[1];
212                 if (flag & MOD_CAST_Z)
213                         tmp_co[2] = fac * vec[2] * len + facm * tmp_co[2];
214
215                 if (ctrl_ob) {
216                         if (flag & MOD_CAST_USE_OB_TRANSFORM) {
217                                 mul_m4_v3(imat, tmp_co);
218                         }
219                         else {
220                                 add_v3_v3(tmp_co, center);
221                         }
222                 }
223
224                 copy_v3_v3(vertexCos[i], tmp_co);
225         }
226 }
227
228 static void cuboid_do(
229         CastModifierData *cmd, Object *ob, Mesh *mesh,
230         float (*vertexCos)[3], int numVerts)
231 {
232         MDeformVert *dvert = NULL;
233         Object *ctrl_ob = NULL;
234
235         int i, defgrp_index;
236         bool has_radius = false;
237         short flag;
238         float fac = cmd->fac;
239         float facm = 1.0f - fac;
240         const float fac_orig = fac;
241         float min[3], max[3], bb[8][3];
242         float center[3] = {0.0f, 0.0f, 0.0f};
243         float mat[4][4], imat[4][4];
244
245         flag = cmd->flag;
246
247         ctrl_ob = cmd->object;
248
249         /* now we check which options the user wants */
250
251         /* 1) (flag was checked in the "if (ctrl_ob)" block above) */
252         /* 2) cmd->radius > 0.0f: only the vertices within this radius from
253          * the center of the effect should be deformed */
254         if (cmd->radius > FLT_EPSILON) has_radius = 1;
255
256         /* 3) if we were given a vertex group name,
257          * only those vertices should be affected */
258         modifier_get_vgroup_mesh(ob, mesh, cmd->defgrp_name, &dvert, &defgrp_index);
259
260         if (ctrl_ob) {
261                 if (flag & MOD_CAST_USE_OB_TRANSFORM) {
262                         invert_m4_m4(imat, ctrl_ob->obmat);
263                         mul_m4_m4m4(mat, imat, ob->obmat);
264                         invert_m4_m4(imat, mat);
265                 }
266
267                 invert_m4_m4(ob->imat, ob->obmat);
268                 mul_v3_m4v3(center, ob->imat, ctrl_ob->obmat[3]);
269         }
270
271         if ((flag & MOD_CAST_SIZE_FROM_RADIUS) && has_radius) {
272                 for (i = 0; i < 3; i++) {
273                         min[i] = -cmd->radius;
274                         max[i] = cmd->radius;
275                 }
276         }
277         else if (!(flag & MOD_CAST_SIZE_FROM_RADIUS) && cmd->size > 0) {
278                 for (i = 0; i < 3; i++) {
279                         min[i] = -cmd->size;
280                         max[i] = cmd->size;
281                 }
282         }
283         else {
284                 /* get bound box */
285                 /* We can't use the object's bound box because other modifiers
286                  * may have changed the vertex data. */
287                 INIT_MINMAX(min, max);
288
289                 /* Cast's center is the ob's own center in its local space,
290                  * by default, but if the user defined a control object, we use
291                  * its location, transformed to ob's local space. */
292                 if (ctrl_ob) {
293                         float vec[3];
294
295                         /* let the center of the ctrl_ob be part of the bound box: */
296                         minmax_v3v3_v3(min, max, center);
297
298                         for (i = 0; i < numVerts; i++) {
299                                 sub_v3_v3v3(vec, vertexCos[i], center);
300                                 minmax_v3v3_v3(min, max, vec);
301                         }
302                 }
303                 else {
304                         for (i = 0; i < numVerts; i++) {
305                                 minmax_v3v3_v3(min, max, vertexCos[i]);
306                         }
307                 }
308
309                 /* we want a symmetric bound box around the origin */
310                 if (fabsf(min[0]) > fabsf(max[0])) max[0] = fabsf(min[0]);
311                 if (fabsf(min[1]) > fabsf(max[1])) max[1] = fabsf(min[1]);
312                 if (fabsf(min[2]) > fabsf(max[2])) max[2] = fabsf(min[2]);
313                 min[0] = -max[0];
314                 min[1] = -max[1];
315                 min[2] = -max[2];
316         }
317
318         /* building our custom bounding box */
319         bb[0][0] = bb[2][0] = bb[4][0] = bb[6][0] = min[0];
320         bb[1][0] = bb[3][0] = bb[5][0] = bb[7][0] = max[0];
321         bb[0][1] = bb[1][1] = bb[4][1] = bb[5][1] = min[1];
322         bb[2][1] = bb[3][1] = bb[6][1] = bb[7][1] = max[1];
323         bb[0][2] = bb[1][2] = bb[2][2] = bb[3][2] = min[2];
324         bb[4][2] = bb[5][2] = bb[6][2] = bb[7][2] = max[2];
325
326         /* ready to apply the effect, one vertex at a time */
327         for (i = 0; i < numVerts; i++) {
328                 int octant, coord;
329                 float d[3], dmax, apex[3], fbb;
330                 float tmp_co[3];
331
332                 copy_v3_v3(tmp_co, vertexCos[i]);
333                 if (ctrl_ob) {
334                         if (flag & MOD_CAST_USE_OB_TRANSFORM) {
335                                 mul_m4_v3(mat, tmp_co);
336                         }
337                         else {
338                                 sub_v3_v3(tmp_co, center);
339                         }
340                 }
341
342                 if (has_radius) {
343                         if (fabsf(tmp_co[0]) > cmd->radius ||
344                             fabsf(tmp_co[1]) > cmd->radius ||
345                             fabsf(tmp_co[2]) > cmd->radius)
346                         {
347                                 continue;
348                         }
349                 }
350
351                 if (dvert) {
352                         const float weight = defvert_find_weight(&dvert[i], defgrp_index);
353                         if (weight == 0.0f) {
354                                 continue;
355                         }
356
357                         fac = fac_orig * weight;
358                         facm = 1.0f - fac;
359                 }
360
361                 /* The algo used to project the vertices to their
362                  * bounding box (bb) is pretty simple:
363                  * for each vertex v:
364                  * 1) find in which octant v is in;
365                  * 2) find which outer "wall" of that octant is closer to v;
366                  * 3) calculate factor (var fbb) to project v to that wall;
367                  * 4) project. */
368
369                 /* find in which octant this vertex is in */
370                 octant = 0;
371                 if (tmp_co[0] > 0.0f) octant += 1;
372                 if (tmp_co[1] > 0.0f) octant += 2;
373                 if (tmp_co[2] > 0.0f) octant += 4;
374
375                 /* apex is the bb's vertex at the chosen octant */
376                 copy_v3_v3(apex, bb[octant]);
377
378                 /* find which bb plane is closest to this vertex ... */
379                 d[0] = tmp_co[0] / apex[0];
380                 d[1] = tmp_co[1] / apex[1];
381                 d[2] = tmp_co[2] / apex[2];
382
383                 /* ... (the closest has the higher (closer to 1) d value) */
384                 dmax = d[0];
385                 coord = 0;
386                 if (d[1] > dmax) {
387                         dmax = d[1];
388                         coord = 1;
389                 }
390                 if (d[2] > dmax) {
391                         /* dmax = d[2]; */ /* commented, we don't need it */
392                         coord = 2;
393                 }
394
395                 /* ok, now we know which coordinate of the vertex to use */
396
397                 if (fabsf(tmp_co[coord]) < FLT_EPSILON) /* avoid division by zero */
398                         continue;
399
400                 /* finally, this is the factor we wanted, to project the vertex
401                  * to its bounding box (bb) */
402                 fbb = apex[coord] / tmp_co[coord];
403
404                 /* calculate the new vertex position */
405                 if (flag & MOD_CAST_X)
406                         tmp_co[0] = facm * tmp_co[0] + fac * tmp_co[0] * fbb;
407                 if (flag & MOD_CAST_Y)
408                         tmp_co[1] = facm * tmp_co[1] + fac * tmp_co[1] * fbb;
409                 if (flag & MOD_CAST_Z)
410                         tmp_co[2] = facm * tmp_co[2] + fac * tmp_co[2] * fbb;
411
412                 if (ctrl_ob) {
413                         if (flag & MOD_CAST_USE_OB_TRANSFORM) {
414                                 mul_m4_v3(imat, tmp_co);
415                         }
416                         else {
417                                 add_v3_v3(tmp_co, center);
418                         }
419                 }
420
421                 copy_v3_v3(vertexCos[i], tmp_co);
422         }
423 }
424
425 static void deformVerts(
426         ModifierData *md, const ModifierEvalContext *ctx,
427         Mesh *mesh,
428         float (*vertexCos)[3],
429         int numVerts)
430 {
431         CastModifierData *cmd = (CastModifierData *)md;
432         Mesh *mesh_src = get_mesh(ctx->object, NULL, mesh, NULL, false, false);
433
434         BLI_assert(mesh_src->totvert == numVerts);
435
436         if (cmd->type == MOD_CAST_TYPE_CUBOID) {
437                 cuboid_do(cmd, ctx->object, mesh_src, vertexCos, numVerts);
438         }
439         else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
440                 sphere_do(cmd, ctx->object, mesh_src, vertexCos, numVerts);
441         }
442
443         if (mesh_src != mesh) {
444                 BKE_id_free(NULL, mesh_src);
445         }
446 }
447
448 static void deformVertsEM(
449         ModifierData *md, const ModifierEvalContext *ctx,
450         struct BMEditMesh *editData,
451         Mesh *mesh, float (*vertexCos)[3], int numVerts)
452 {
453         CastModifierData *cmd = (CastModifierData *)md;
454         Mesh *mesh_src = get_mesh(ctx->object, editData, mesh, NULL, false, false);
455
456         BLI_assert(mesh_src->totvert == numVerts);
457
458         if (cmd->type == MOD_CAST_TYPE_CUBOID) {
459                 cuboid_do(cmd, ctx->object, mesh_src, vertexCos, numVerts);
460         }
461         else { /* MOD_CAST_TYPE_SPHERE or MOD_CAST_TYPE_CYLINDER */
462                 sphere_do(cmd, ctx->object, mesh_src, vertexCos, numVerts);
463         }
464
465         if (mesh_src != mesh) {
466                 BKE_id_free(NULL, mesh_src);
467         }
468 }
469
470
471 ModifierTypeInfo modifierType_Cast = {
472         /* name */              "Cast",
473         /* structName */        "CastModifierData",
474         /* structSize */        sizeof(CastModifierData),
475         /* type */              eModifierTypeType_OnlyDeform,
476         /* flags */             eModifierTypeFlag_AcceptsCVs |
477                                 eModifierTypeFlag_AcceptsLattice |
478                                 eModifierTypeFlag_SupportsEditmode,
479
480         /* copyData */          modifier_copyData_generic,
481
482         /* deformVerts_DM */    NULL,
483         /* deformMatrices_DM */ NULL,
484         /* deformVertsEM_DM */  NULL,
485         /* deformMatricesEM_DM*/NULL,
486         /* applyModifier_DM */  NULL,
487         /* applyModifierEM_DM */NULL,
488
489         /* deformVerts */       deformVerts,
490         /* deformMatrices */    NULL,
491         /* deformVertsEM */     deformVertsEM,
492         /* deformMatricesEM */  NULL,
493         /* applyModifier */     NULL,
494         /* applyModifierEM */   NULL,
495
496         /* initData */          initData,
497         /* requiredDataMask */  requiredDataMask,
498         /* freeData */          NULL,
499         /* isDisabled */        isDisabled,
500         /* updateDepsgraph */   updateDepsgraph,
501         /* dependsOnTime */     NULL,
502         /* dependsOnNormals */  NULL,
503         /* foreachObjectLink */ foreachObjectLink,
504         /* foreachIDLink */     NULL,
505         /* foreachTexLink */    NULL,
506 };