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