svn merge ^/trunk/blender -r42957:42967
[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 #include "BKE_utildefines.h"
47 #include "BKE_tessmesh.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(
72                                                  ModifierData *md, Object *ob,
73           void (*walk)(void *userData, Object *ob, Object **obpoin),
74                  void *userData)
75 {
76         MirrorModifierData *mmd = (MirrorModifierData*) md;
77
78         walk(userData, ob, &mmd->mirror_ob);
79 }
80
81 static void updateDepgraph(ModifierData *md, DagForest *forest,
82                                                 struct Scene *UNUSED(scene),
83                                                 Object *UNUSED(ob),
84                                                 DagNode *obNode)
85 {
86         MirrorModifierData *mmd = (MirrorModifierData*) md;
87
88         if(mmd->mirror_ob) {
89                 DagNode *latNode = dag_get_node(forest, mmd->mirror_ob);
90
91                 dag_add_relation(forest, latNode, obNode,
92                                  DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mirror Modifier");
93         }
94 }
95
96 static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
97                                    Object *ob,
98                                    DerivedMesh *dm,
99                                    int axis)
100 {
101         float tolerance_sq;
102         DerivedMesh *cddm, *origdm;
103         bDeformGroup *def;
104         bDeformGroup **vector_def = NULL;
105         MVert *mv, *ov;
106         MEdge *me;
107         MLoop *ml;
108         MPoly *mp;
109         float mtx[4][4];
110         int i, j, *vtargetmap = NULL;
111         BLI_array_declare(vtargetmap);
112         int vector_size=0, a, totshape;
113
114         tolerance_sq = mmd->tolerance * mmd->tolerance;
115         
116         origdm = dm;
117         if (!CDDM_Check(dm))
118                 dm = CDDM_copy(dm, 0);
119         
120         if (mmd->flag & MOD_MIR_VGROUP) {
121                 /* calculate the number of deformedGroups */
122                 for(vector_size = 0, def = ob->defbase.first; def;
123                         def = def->next, vector_size++);
124
125                 /* load the deformedGroups for fast access */
126                 vector_def =
127                         (bDeformGroup **)MEM_mallocN(sizeof(bDeformGroup*) * vector_size,
128                                                                                  "group_index");
129                 for(a = 0, def = ob->defbase.first; def; def = def->next, a++) {
130                         vector_def[a] = def;
131                 }
132         }
133
134         /*mtx is the mirror transformation*/
135         unit_m4(mtx);
136         mtx[axis][axis] = -1.0;
137
138         if (mmd->mirror_ob) {
139                 float tmp[4][4];
140                 float itmp[4][4];
141
142                 /*tmp is a transform from coords relative to the object's own origin, to
143                   coords relative to the mirror object origin*/
144                 invert_m4_m4(tmp, mmd->mirror_ob->obmat);
145                 mult_m4_m4m4(tmp, tmp, ob->obmat);
146
147                 /*itmp is the reverse transform back to origin-relative coordiantes*/
148                 invert_m4_m4(itmp, tmp);
149
150                 /*combine matrices to get a single matrix that translates coordinates into
151                   mirror-object-relative space, does the mirror, and translates back to
152                   origin-relative space*/
153                 mult_m4_m4m4(mtx, mtx, tmp);
154                 mult_m4_m4m4(mtx, itmp, mtx);
155         }
156         
157         cddm = CDDM_from_template(dm, dm->numVertData*2, dm->numEdgeData*2, 0, dm->numLoopData*2, dm->numPolyData*2);
158         
159         /*copy customdata to original geometry*/
160         CustomData_copy_data(&dm->vertData, &cddm->vertData, 0, 0, dm->numVertData);
161         CustomData_copy_data(&dm->edgeData, &cddm->edgeData, 0, 0, dm->numEdgeData);
162         CustomData_copy_data(&dm->loopData, &cddm->loopData, 0, 0, dm->numLoopData);
163         CustomData_copy_data(&dm->polyData, &cddm->polyData, 0, 0, dm->numPolyData);
164
165         /*copy customdata to new geometry*/
166         CustomData_copy_data(&dm->vertData, &cddm->vertData, 0, dm->numVertData, dm->numVertData);
167         CustomData_copy_data(&dm->edgeData, &cddm->edgeData, 0, dm->numEdgeData, dm->numEdgeData);
168         CustomData_copy_data(&dm->polyData, &cddm->polyData, 0, dm->numPolyData, dm->numPolyData);
169         
170         /*mirror vertex coordinates*/
171         ov = CDDM_get_verts(cddm);
172         mv = ov + dm->numVertData;
173         for (i=0; i<dm->numVertData; i++, mv++, ov++) {
174                 mul_m4_v3(mtx, mv->co);
175                 /*compare location of the original and mirrored vertex, to see if they
176                   should be mapped for merging*/
177                 if (len_squared_v3v3(ov->co, mv->co) < tolerance_sq) {
178                         BLI_array_append(vtargetmap, i+dm->numVertData);
179                 }
180                 else {
181                         BLI_array_append(vtargetmap, -1);
182                 }
183         }
184         
185         /*handle shape keys*/
186         totshape = CustomData_number_of_layers(&cddm->vertData, CD_SHAPEKEY);
187         for (a=0; a<totshape; a++) {
188                 float (*cos)[3] = CustomData_get_layer_n(&cddm->vertData, CD_SHAPEKEY, a);
189                 for (i=dm->numVertData; i<cddm->numVertData; i++) {
190                         mul_m4_v3(mtx, cos[i]);
191                 }
192         }
193         
194         for (i=0; i<dm->numVertData; i++) {
195                 BLI_array_append(vtargetmap, -1);
196         }
197         
198         /*adjust mirrored edge vertex indices*/
199         me = CDDM_get_edges(cddm) + dm->numEdgeData;
200         for (i=0; i<dm->numEdgeData; i++, me++) {
201                 me->v1 += dm->numVertData;
202                 me->v2 += dm->numVertData;
203         }
204         
205         /*adjust mirrored poly loopstart indices, and reverse loop order (normals)*/    
206         mp = CDDM_get_polys(cddm) + dm->numPolyData;
207         ml = CDDM_get_loops(cddm);
208         for (i=0; i<dm->numPolyData; i++, mp++) {
209                 MLoop *ml2;
210                 int e;
211                 
212                 for (j=0; j<mp->totloop; j++) {
213                         CustomData_copy_data(&dm->loopData, &cddm->loopData, mp->loopstart+j,
214                                                                  mp->loopstart+dm->numLoopData+mp->totloop-j-1, 1);
215                 }
216                 
217                 ml2 = ml + mp->loopstart + dm->numLoopData;
218                 e = ml2[0].e;
219                 for (j=0; j<mp->totloop-1; j++) {
220                         ml2[j].e = ml2[j+1].e;
221                 }
222                 ml2[mp->totloop-1].e = e;
223                 
224                 mp->loopstart += dm->numLoopData;
225         }
226
227         /*adjust mirrored loop vertex and edge indices*/        
228         ml = CDDM_get_loops(cddm) + dm->numLoopData;
229         for (i=0; i<dm->numLoopData; i++, ml++) {
230                 ml->v += dm->numVertData;
231                 ml->e += dm->numEdgeData;
232         }
233
234         CDDM_recalc_tesselation(cddm);
235         
236         /*handle vgroup stuff*/
237         if ((mmd->flag & MOD_MIR_VGROUP) && CustomData_has_layer(&cddm->vertData, CD_MDEFORMVERT)) {
238                 MDeformVert *dvert = CustomData_get_layer(&cddm->vertData, CD_MDEFORMVERT);
239                 int *flip_map= NULL, flip_map_len= 0;
240
241                 flip_map= defgroup_flip_map(ob, &flip_map_len, FALSE);
242                 
243                 for (i=0; i<dm->numVertData; i++, dvert++) {
244                         defvert_flip(dvert, flip_map, flip_map_len);
245                 }
246         }
247         
248         if (!(mmd->flag & MOD_MIR_NO_MERGE))
249                 cddm = CDDM_merge_verts(cddm, vtargetmap);
250         
251         BLI_array_free(vtargetmap);
252         
253         if (vector_def) MEM_freeN(vector_def);
254         
255         if (dm != origdm) {
256                 dm->needsFree = 1;
257                 dm->release(dm);
258         }
259         
260         return cddm;
261 }
262
263 static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
264                                                 Object *ob, DerivedMesh *dm)
265 {
266         DerivedMesh *result = dm;
267
268         /* check which axes have been toggled and mirror accordingly */
269         if(mmd->flag & MOD_MIR_AXIS_X) {
270                 result = doMirrorOnAxis(mmd, ob, result, 0);
271         }
272         if(mmd->flag & MOD_MIR_AXIS_Y) {
273                 DerivedMesh *tmp = result;
274                 result = doMirrorOnAxis(mmd, ob, result, 1);
275                 if(tmp != dm) tmp->release(tmp); /* free intermediate results */
276         }
277         if(mmd->flag & MOD_MIR_AXIS_Z) {
278                 DerivedMesh *tmp = result;
279                 result = doMirrorOnAxis(mmd, ob, result, 2);
280                 if(tmp != dm) tmp->release(tmp); /* free intermediate results */
281         }
282
283         return result;
284 }
285
286 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
287                                                 DerivedMesh *derivedData,
288                                                 int UNUSED(useRenderParams),
289                                                 int UNUSED(isFinalCalc))
290 {
291         DerivedMesh *result;
292         MirrorModifierData *mmd = (MirrorModifierData*) md;
293
294         result = mirrorModifier__doMirror(mmd, ob, derivedData);
295
296         if(result != derivedData)
297                 CDDM_calc_normals(result);
298         
299         return result;
300 }
301
302 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
303                                                 struct BMEditMesh *UNUSED(editData),
304                                                 DerivedMesh *derivedData)
305 {
306         return applyModifier(md, ob, derivedData, 0, 1);
307 }
308
309
310 ModifierTypeInfo modifierType_Mirror = {
311         /* name */              "Mirror",
312         /* structName */        "MirrorModifierData",
313         /* structSize */        sizeof(MirrorModifierData),
314         /* type */              eModifierTypeType_Constructive,
315         /* flags */             eModifierTypeFlag_AcceptsMesh
316                                                         | eModifierTypeFlag_SupportsMapping
317                                                         | eModifierTypeFlag_SupportsEditmode
318                                                         | eModifierTypeFlag_EnableInEditmode
319                                                         | eModifierTypeFlag_AcceptsCVs,
320
321         /* copyData */          copyData,
322         /* deformVerts */       NULL,
323         /* deformMatrices */    NULL,
324         /* deformVertsEM */     NULL,
325         /* deformMatricesEM */  NULL,
326         /* applyModifier */     applyModifier,
327         /* applyModifierEM */   applyModifierEM,
328         /* initData */          initData,
329         /* requiredDataMask */  NULL,
330         /* freeData */          NULL,
331         /* isDisabled */        NULL,
332         /* updateDepgraph */    updateDepgraph,
333         /* dependsOnTime */     NULL,
334         /* dependsOnNormals */  NULL,
335         /* foreachObjectLink */ foreachObjectLink,
336         /* foreachIDLink */     NULL,
337         /* foreachTexLink */    NULL,
338 };