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