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