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