Extract common modifier parameters into ModifierEvalContext struct
[blender.git] / source / blender / modifiers / intern / MOD_mirror.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_mirror.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
42 #include "BKE_library_query.h"
43 #include "BKE_mesh.h"
44 #include "BKE_modifier.h"
45 #include "BKE_deform.h"
46
47 #include "MEM_guardedalloc.h"
48
49 #include "DEG_depsgraph_build.h"
50
51 #include "MOD_modifiertypes.h"
52
53 static void initData(ModifierData *md)
54 {
55         MirrorModifierData *mmd = (MirrorModifierData *) md;
56
57         mmd->flag |= (MOD_MIR_AXIS_X | MOD_MIR_VGROUP);
58         mmd->tolerance = 0.001;
59         mmd->mirror_ob = NULL;
60 }
61
62 static void copyData(ModifierData *md, ModifierData *target)
63 {
64 #if 0
65         MirrorModifierData *mmd = (MirrorModifierData *) md;
66         MirrorModifierData *tmmd = (MirrorModifierData *) target;
67 #endif
68         modifier_copyData_generic(md, target);
69 }
70
71 static void foreachObjectLink(
72         ModifierData *md, Object *ob,
73         ObjectWalkFunc walk, void *userData)
74 {
75         MirrorModifierData *mmd = (MirrorModifierData *) md;
76
77         walk(userData, ob, &mmd->mirror_ob, IDWALK_CB_NOP);
78 }
79
80 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
81 {
82         MirrorModifierData *mmd = (MirrorModifierData *)md;
83         if (mmd->mirror_ob != NULL) {
84                 DEG_add_object_relation(ctx->node, mmd->mirror_ob, DEG_OB_COMP_TRANSFORM, "Mirror Modifier");
85         }
86         DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Mirror Modifier");
87 }
88
89 static Mesh *doMirrorOnAxis(MirrorModifierData *mmd,
90                             Object *ob,
91                             const Mesh *mesh,
92                             int axis)
93 {
94         const float tolerance_sq = mmd->tolerance * mmd->tolerance;
95         const bool do_vtargetmap = (mmd->flag & MOD_MIR_NO_MERGE) == 0;
96         int tot_vtargetmap = 0;  /* total merge vertices */
97
98         Mesh *result;
99         const int maxVerts = mesh->totvert;
100         const int maxEdges = mesh->totedge;
101         const int maxLoops = mesh->totloop;
102         const int maxPolys = mesh->totpoly;
103         MVert *mv, *mv_prev;
104         MEdge *me;
105         MLoop *ml;
106         MPoly *mp;
107         float mtx[4][4];
108         int i;
109         int a, totshape;
110         int *vtargetmap = NULL, *vtmap_a = NULL, *vtmap_b = NULL;
111
112         /* mtx is the mirror transformation */
113         unit_m4(mtx);
114         mtx[axis][axis] = -1.0f;
115
116         if (mmd->mirror_ob) {
117                 float tmp[4][4];
118                 float itmp[4][4];
119
120                 /* tmp is a transform from coords relative to the object's own origin,
121                  * to coords relative to the mirror object origin */
122                 invert_m4_m4(tmp, mmd->mirror_ob->obmat);
123                 mul_m4_m4m4(tmp, tmp, ob->obmat);
124
125                 /* itmp is the reverse transform back to origin-relative coordinates */
126                 invert_m4_m4(itmp, tmp);
127
128                 /* combine matrices to get a single matrix that translates coordinates into
129                  * mirror-object-relative space, does the mirror, and translates back to
130                  * origin-relative space */
131                 mul_m4_m4m4(mtx, mtx, tmp);
132                 mul_m4_m4m4(mtx, itmp, mtx);
133         }
134
135         result = BKE_mesh_from_template(mesh, maxVerts * 2, maxEdges * 2, 0, maxLoops * 2, maxPolys * 2);
136
137         /*copy customdata to original geometry*/
138         CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, maxVerts);
139         CustomData_copy_data(&mesh->edata, &result->edata, 0, 0, maxEdges);
140         CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, maxLoops);
141         CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, maxPolys);
142
143         /* Subsurf for eg wont have mesh data in the custom data arrays.
144          * now add mvert/medge/mpoly layers. */
145         if (!CustomData_has_layer(&mesh->vdata, CD_MVERT)) {
146                 memcpy(result->mvert, mesh->mvert, sizeof(*result->mvert) * mesh->totvert);
147         }
148         if (!CustomData_has_layer(&mesh->edata, CD_MEDGE)) {
149                 memcpy(result->medge, mesh->medge, sizeof(*result->medge) * mesh->totedge);
150         }
151         if (!CustomData_has_layer(&mesh->pdata, CD_MPOLY)) {
152                 memcpy(result->mloop, mesh->mloop, sizeof(*result->mloop) * mesh->totloop);
153                 memcpy(result->mpoly, mesh->mpoly, sizeof(*result->mpoly) * mesh->totpoly);
154         }
155
156         /* copy customdata to new geometry,
157          * copy from its self because this data may have been created in the checks above */
158         CustomData_copy_data(&result->vdata, &result->vdata, 0, maxVerts, maxVerts);
159         CustomData_copy_data(&result->edata, &result->edata, 0, maxEdges, maxEdges);
160         /* loops are copied later */
161         CustomData_copy_data(&result->pdata, &result->pdata, 0, maxPolys, maxPolys);
162
163         if (do_vtargetmap) {
164                 /* second half is filled with -1 */
165                 vtargetmap = MEM_malloc_arrayN(maxVerts, 2 * sizeof(int), "MOD_mirror tarmap");
166
167                 vtmap_a = vtargetmap;
168                 vtmap_b = vtargetmap + maxVerts;
169         }
170
171         /* mirror vertex coordinates */
172         mv_prev = result->mvert;
173         mv = mv_prev + maxVerts;
174         for (i = 0; i < maxVerts; i++, mv++, mv_prev++) {
175                 mul_m4_v3(mtx, mv->co);
176
177                 if (do_vtargetmap) {
178                         /* compare location of the original and mirrored vertex, to see if they
179                          * should be mapped for merging */
180                         if (UNLIKELY(len_squared_v3v3(mv_prev->co, mv->co) < tolerance_sq)) {
181                                 *vtmap_a = maxVerts + i;
182                                 tot_vtargetmap++;
183
184                                 /* average location */
185                                 mid_v3_v3v3(mv->co, mv_prev->co, mv->co);
186                                 copy_v3_v3(mv_prev->co, mv->co);
187                         }
188                         else {
189                                 *vtmap_a = -1;
190                         }
191
192                         *vtmap_b = -1; /* fill here to avoid 2x loops */
193
194                         vtmap_a++;
195                         vtmap_b++;
196                 }
197         }
198         
199         /* handle shape keys */
200         totshape = CustomData_number_of_layers(&result->vdata, CD_SHAPEKEY);
201         for (a = 0; a < totshape; a++) {
202                 float (*cos)[3] = CustomData_get_layer_n(&result->vdata, CD_SHAPEKEY, a);
203                 for (i = maxVerts; i < result->totvert; i++) {
204                         mul_m4_v3(mtx, cos[i]);
205                 }
206         }
207         
208         /* adjust mirrored edge vertex indices */
209         me = result->medge + maxEdges;
210         for (i = 0; i < maxEdges; i++, me++) {
211                 me->v1 += maxVerts;
212                 me->v2 += maxVerts;
213         }
214         
215         /* adjust mirrored poly loopstart indices, and reverse loop order (normals) */
216         mp = result->mpoly + maxPolys;
217         ml = result->mloop;
218         for (i = 0; i < maxPolys; i++, mp++) {
219                 MLoop *ml2;
220                 int j, e;
221
222                 /* reverse the loop, but we keep the first vertex in the face the same,
223                  * to ensure that quads are split the same way as on the other side */
224                 CustomData_copy_data(&result->ldata, &result->ldata, mp->loopstart, mp->loopstart + maxLoops, 1);
225
226                 for (j = 1; j < mp->totloop; j++)
227                         CustomData_copy_data(&result->ldata, &result->ldata,
228                                              mp->loopstart + j,
229                                              mp->loopstart + maxLoops + mp->totloop - j,
230                                              1);
231
232                 ml2 = ml + mp->loopstart + maxLoops;
233                 e = ml2[0].e;
234                 for (j = 0; j < mp->totloop - 1; j++) {
235                         ml2[j].e = ml2[j + 1].e;
236                 }
237                 ml2[mp->totloop - 1].e = e;
238                 
239                 mp->loopstart += maxLoops;
240         }
241
242         /* adjust mirrored loop vertex and edge indices */
243         ml = result->mloop + maxLoops;
244         for (i = 0; i < maxLoops; i++, ml++) {
245                 ml->v += maxVerts;
246                 ml->e += maxEdges;
247         }
248
249         /* handle uvs,
250          * let tessface recalc handle updating the MTFace data */
251         if (mmd->flag & (MOD_MIR_MIRROR_U | MOD_MIR_MIRROR_V) || (is_zero_v2(mmd->uv_offset_copy) == false)) {
252                 const bool do_mirr_u = (mmd->flag & MOD_MIR_MIRROR_U) != 0;
253                 const bool do_mirr_v = (mmd->flag & MOD_MIR_MIRROR_V) != 0;
254
255                 const int totuv = CustomData_number_of_layers(&result->ldata, CD_MLOOPUV);
256
257                 for (a = 0; a < totuv; a++) {
258                         MLoopUV *dmloopuv = CustomData_get_layer_n(&result->ldata, CD_MLOOPUV, a);
259                         int j = maxLoops;
260                         dmloopuv += j; /* second set of loops only */
261                         for (; j-- > 0; dmloopuv++) {
262                                 if (do_mirr_u) dmloopuv->uv[0] = 1.0f - dmloopuv->uv[0] + mmd->uv_offset[0];
263                                 if (do_mirr_v) dmloopuv->uv[1] = 1.0f - dmloopuv->uv[1] + mmd->uv_offset[1];
264                                 dmloopuv->uv[0] += mmd->uv_offset_copy[0];
265                                 dmloopuv->uv[1] += mmd->uv_offset_copy[1];
266                         }
267                 }
268         }
269
270         /* handle vgroup stuff */
271         if ((mmd->flag & MOD_MIR_VGROUP) && CustomData_has_layer(&result->vdata, CD_MDEFORMVERT)) {
272                 MDeformVert *dvert = (MDeformVert *) CustomData_get_layer(&result->vdata, CD_MDEFORMVERT) + maxVerts;
273                 int *flip_map = NULL, flip_map_len = 0;
274
275                 flip_map = defgroup_flip_map(ob, &flip_map_len, false);
276                 
277                 if (flip_map) {
278                         for (i = 0; i < maxVerts; dvert++, i++) {
279                                 /* merged vertices get both groups, others get flipped */
280                                 if (do_vtargetmap && (vtargetmap[i] != -1))
281                                         defvert_flip_merged(dvert, flip_map, flip_map_len);
282                                 else
283                                         defvert_flip(dvert, flip_map, flip_map_len);
284                         }
285
286                         MEM_freeN(flip_map);
287                 }
288         }
289
290         if (do_vtargetmap) {
291                 /* slow - so only call if one or more merge verts are found,
292                  * users may leave this on and not realize there is nothing to merge - campbell */
293                 if (tot_vtargetmap) {
294                         result = BKE_mesh_merge_verts(result, vtargetmap, tot_vtargetmap, MESH_MERGE_VERTS_DUMP_IF_MAPPED);
295                 }
296                 MEM_freeN(vtargetmap);
297         }
298
299         return result;
300 }
301
302 static Mesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
303                                       Object *ob, Mesh *mesh)
304 {
305         Mesh *result = mesh;
306
307         /* check which axes have been toggled and mirror accordingly */
308         if (mmd->flag & MOD_MIR_AXIS_X) {
309                 result = doMirrorOnAxis(mmd, ob, result, 0);
310         }
311         if (mmd->flag & MOD_MIR_AXIS_Y) {
312                 Mesh *tmp = result;
313                 result = doMirrorOnAxis(mmd, ob, result, 1);
314                 if (tmp != mesh) {
315                         /* free intermediate results */
316                         BKE_mesh_free(tmp);
317                         MEM_freeN(tmp);
318                 }
319         }
320         if (mmd->flag & MOD_MIR_AXIS_Z) {
321                 Mesh *tmp = result;
322                 result = doMirrorOnAxis(mmd, ob, result, 2);
323                 if (tmp != mesh) {
324                         /* free intermediate results */
325                         BKE_mesh_free(tmp);
326                         MEM_freeN(tmp);
327                 }
328         }
329
330         return result;
331 }
332
333 static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx,
334                            Mesh *mesh)
335 {
336         Mesh *result;
337         MirrorModifierData *mmd = (MirrorModifierData *) md;
338
339         result = mirrorModifier__doMirror(mmd, ctx->object, mesh);
340         BKE_mesh_calc_normals(result);
341
342         return result;
343 }
344
345
346 ModifierTypeInfo modifierType_Mirror = {
347         /* name */              "Mirror",
348         /* structName */        "MirrorModifierData",
349         /* structSize */        sizeof(MirrorModifierData),
350         /* type */              eModifierTypeType_Constructive,
351         /* flags */             eModifierTypeFlag_AcceptsMesh |
352                                 eModifierTypeFlag_SupportsMapping |
353                                 eModifierTypeFlag_SupportsEditmode |
354                                 eModifierTypeFlag_EnableInEditmode |
355                                 eModifierTypeFlag_AcceptsCVs |
356                                 /* this is only the case when 'MOD_MIR_VGROUP' is used */
357                                 eModifierTypeFlag_UsesPreview,
358
359         /* copyData */          copyData,
360
361         /* deformVerts_DM */    NULL,
362         /* deformMatrices_DM */ NULL,
363         /* deformVertsEM_DM */  NULL,
364         /* deformMatricesEM_DM*/NULL,
365         /* applyModifier_DM */  NULL,
366         /* applyModifierEM_DM */NULL,
367
368         /* deformVerts */       NULL,
369         /* deformMatrices */    NULL,
370         /* deformVertsEM */     NULL,
371         /* deformMatricesEM */  NULL,
372         /* applyModifier */     applyModifier,
373         /* applyModifierEM */   NULL,
374
375         /* initData */          initData,
376         /* requiredDataMask */  NULL,
377         /* freeData */          NULL,
378         /* isDisabled */        NULL,
379         /* updateDepsgraph */   updateDepsgraph,
380         /* dependsOnTime */     NULL,
381         /* dependsOnNormals */  NULL,
382         /* foreachObjectLink */ foreachObjectLink,
383         /* foreachIDLink */     NULL,
384         /* foreachTexLink */    NULL,
385 };