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