remove unused vars
[blender.git] / source / blender / modifiers / intern / MOD_mirror.c
1 /*
2 * $Id$
3 *
4 * ***** BEGIN GPL LICENSE BLOCK *****
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software  Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *
20 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
21 * All rights reserved.
22 *
23 * Contributor(s): Daniel Dunbar
24 *                 Ton Roosendaal,
25 *                 Ben Batt,
26 *                 Brecht Van Lommel,
27 *                 Campbell Barton
28 *
29 * ***** END GPL LICENSE BLOCK *****
30 *
31 */
32
33 #include "DNA_meshdata_types.h"
34 #include "DNA_object_types.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 "MEM_guardedalloc.h"
48 #include "depsgraph_private.h"
49
50 static void initData(ModifierData *md)
51 {
52         MirrorModifierData *mmd = (MirrorModifierData*) md;
53
54         mmd->flag |= (MOD_MIR_AXIS_X | MOD_MIR_VGROUP);
55         mmd->tolerance = 0.001;
56         mmd->mirror_ob = NULL;
57 }
58
59 static void copyData(ModifierData *md, ModifierData *target)
60 {
61         MirrorModifierData *mmd = (MirrorModifierData*) md;
62         MirrorModifierData *tmmd = (MirrorModifierData*) target;
63
64         tmmd->axis = mmd->axis;
65         tmmd->flag = mmd->flag;
66         tmmd->tolerance = mmd->tolerance;
67         tmmd->mirror_ob = mmd->mirror_ob;;
68 }
69
70 static void foreachObjectLink(
71                                                  ModifierData *md, Object *ob,
72           void (*walk)(void *userData, Object *ob, Object **obpoin),
73                  void *userData)
74 {
75         MirrorModifierData *mmd = (MirrorModifierData*) md;
76         
77         if (mmd->mirror_ob)
78                 walk(userData, ob, &mmd->mirror_ob);
79 }
80
81 static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
82                                           Object *UNUSED(ob), 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,
90                                  DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mirror Modifier");
91         }
92 }
93
94
95 /* Mirror */
96 #define VERT_NEW        1
97
98 void vertgroup_flip_name (char *name, int strip_number);
99 DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
100                 Object *ob,
101                 DerivedMesh *dm,
102                 int UNUSED(initFlags),
103                 int axis)
104 {
105         float tolerance = mmd->tolerance;
106         DerivedMesh *cddm, *origdm;
107         bDeformGroup *def, *defb;
108         bDeformGroup **vector_def = NULL;
109         MVert *mv;
110         MEdge *me;
111         MLoop *ml;
112         MPoly *mp;
113         float mtx[4][4];
114         int i, j, *vtargetmap = NULL;
115         BLI_array_declare(vtargetmap);
116         int vector_size=0, a, b, totshape;
117         
118         origdm = dm;
119         if (!CDDM_Check(dm))
120                 dm = CDDM_copy(dm, 0);
121         
122         if (mmd->flag & MOD_MIR_VGROUP) {
123                 /* calculate the number of deformedGroups */
124                 for(vector_size = 0, def = ob->defbase.first; def;
125                         def = def->next, vector_size++);
126
127                 /* load the deformedGroups for fast access */
128                 vector_def =
129                         (bDeformGroup **)MEM_mallocN(sizeof(bDeformGroup*) * vector_size,
130                                                                                  "group_index");
131                 for(a = 0, def = ob->defbase.first; def; def = def->next, a++) {
132                         vector_def[a] = def;
133                 }
134         }
135
136         if (mmd->mirror_ob) {
137                 float mtx2[4][4];
138
139                 invert_m4_m4(mtx2, mmd->mirror_ob->obmat);
140                 mul_m4_m4m4(mtx, ob->obmat, mtx2);
141         } else {
142                 unit_m4(mtx);
143         }
144         
145         cddm = CDDM_from_template(dm, dm->numVertData*2, dm->numEdgeData*2, 0, dm->numLoopData*2, dm->numPolyData*2);
146         
147         /*copy customdata to original geometry*/
148         CustomData_copy_data(&dm->vertData, &cddm->vertData, 0, 0, dm->numVertData);
149         CustomData_copy_data(&dm->edgeData, &cddm->edgeData, 0, 0, dm->numEdgeData);
150         CustomData_copy_data(&dm->loopData, &cddm->loopData, 0, 0, dm->numLoopData);
151         CustomData_copy_data(&dm->polyData, &cddm->polyData, 0, 0, dm->numPolyData);
152
153         /*copy customdata to new geometry*/
154         CustomData_copy_data(&dm->vertData, &cddm->vertData, 0, dm->numVertData, dm->numVertData);
155         CustomData_copy_data(&dm->edgeData, &cddm->edgeData, 0, dm->numEdgeData, dm->numEdgeData);
156         CustomData_copy_data(&dm->polyData, &cddm->polyData, 0, dm->numPolyData, dm->numPolyData);
157         
158         /*mirror vertex coordinates*/
159         mv = CDDM_get_verts(cddm) + dm->numVertData;
160         for (i=0; i<dm->numVertData; i++, mv++) {
161                 mv->co[axis] = -mv->co[axis];
162                 if (fabs(mv->co[axis]) < tolerance) {
163                         BLI_array_append(vtargetmap, i+dm->numVertData);
164                 } else BLI_array_append(vtargetmap, -1);
165         }
166         
167         /*handle shape keys*/
168         totshape = CustomData_number_of_layers(&cddm->vertData, CD_SHAPEKEY);
169         for (a=0; a<totshape; a++) {
170                 float (*cos)[3] = CustomData_get_layer_n(&cddm->vertData, CD_SHAPEKEY, a);
171                 for (i=dm->numVertData; i<cddm->numVertData; i++) {
172                         cos[i][axis] = -cos[i][axis];
173                 }
174         }
175         
176         for (i=0; i<dm->numVertData; i++) {
177                 BLI_array_append(vtargetmap, -1);
178         }
179         
180         /*adjust mirrored edge vertex indices*/
181         me = CDDM_get_edges(cddm) + dm->numEdgeData;
182         for (i=0; i<dm->numEdgeData; i++, me++) {
183                 me->v1 += dm->numVertData;
184                 me->v2 += dm->numVertData;
185         }
186         
187         /*adjust mirrored poly loopstart indices, and reverse loop order (normals)*/    
188         mp = CDDM_get_polys(cddm) + dm->numPolyData;
189         ml = CDDM_get_loops(cddm);
190         for (i=0; i<dm->numPolyData; i++, mp++) {
191                 MLoop *ml2;
192                 int e;
193                 
194                 for (j=0; j<mp->totloop; j++) {
195                         CustomData_copy_data(&dm->loopData, &cddm->loopData, mp->loopstart+j,
196                                                                  mp->loopstart+dm->numLoopData+mp->totloop-j-1, 1);
197                 }
198                 
199                 ml2 = ml + mp->loopstart + dm->numLoopData;
200                 e = ml2[0].e;
201                 for (j=0; j<mp->totloop-1; j++) {
202                         ml2[j].e = ml2[j+1].e;
203                 }
204                 ml2[mp->totloop-1].e = e;
205                 
206                 mp->loopstart += dm->numLoopData;
207         }
208
209         /*adjust mirrored loop vertex and edge indices*/        
210         ml = CDDM_get_loops(cddm) + dm->numLoopData;
211         for (i=0; i<dm->numLoopData; i++, ml++) {
212                 ml->v += dm->numVertData;
213                 ml->e += dm->numEdgeData;
214         }
215
216         CDDM_recalc_tesselation(cddm, 1);
217         
218         /*handle vgroup stuff*/
219         if ((mmd->flag & MOD_MIR_VGROUP) && CustomData_has_layer(&cddm->vertData, CD_MDEFORMVERT)) {
220                 MDeformVert *dvert = CustomData_get_layer(&cddm->vertData, CD_MDEFORMVERT);
221                 
222                 for (i=0; i<dm->numVertData; i++, dvert++) {
223                         for(j = 0; j < dvert->totweight; ++j) {
224                                 char tmpname[32];
225
226                                 if(dvert->dw[j].def_nr < 0 ||
227                                    dvert->dw[j].def_nr >= vector_size)
228                                         continue;
229
230                                 def = vector_def[dvert->dw[j].def_nr];
231                                 strcpy(tmpname, def->name);
232                                 vertgroup_flip_name(tmpname,0);
233
234                                 for(b = 0, defb = ob->defbase.first; defb;
235                                         defb = defb->next, b++)
236                                 {
237                                         if(!strcmp(defb->name, tmpname))
238                                         {
239                                                 dvert->dw[j].def_nr = b;
240                                                 break;
241                                         }
242                                 }
243                         }
244                 }
245         }
246         
247         if (!(mmd->flag & MOD_MIR_NO_MERGE))
248                 cddm = CDDM_merge_verts(cddm, vtargetmap);
249         
250         BLI_array_free(vtargetmap);
251         
252         if (vector_def) MEM_freeN(vector_def);
253         
254         if (dm != origdm) {
255                 dm->needsFree = 1;
256                 dm->release(dm);
257         }
258         
259         return cddm;
260 }
261
262 static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
263                                                 Object *ob, DerivedMesh *dm,
264                                                 int initFlags)
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, initFlags, 0);
271         }
272         if(mmd->flag & MOD_MIR_AXIS_Y) {
273                 DerivedMesh *tmp = result;
274                 result = doMirrorOnAxis(mmd, ob, result, initFlags, 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, initFlags, 2);
280                 if(tmp != dm) tmp->release(tmp); /* free intermediate results */
281         }
282
283         return result;
284 }
285
286 static DerivedMesh *applyModifier(
287                 ModifierData *md, Object *ob, DerivedMesh *derivedData,
288   int UNUSED(useRenderParams), int UNUSED(isFinalCalc))
289 {
290         DerivedMesh *result;
291         MirrorModifierData *mmd = (MirrorModifierData*) md;
292
293         result = mirrorModifier__doMirror(mmd, ob, derivedData, 0);
294
295         if(result != derivedData)
296                 CDDM_calc_normals(result);
297         
298         return result;
299 }
300
301 static DerivedMesh *applyModifierEM(
302                 ModifierData *md, Object *ob, struct BMEditMesh *UNUSED(editData),
303   DerivedMesh *derivedData)
304 {
305         return applyModifier(md, ob, derivedData, 0, 1);
306 }
307
308
309 ModifierTypeInfo modifierType_Mirror = {
310         /* name */              "Mirror",
311         /* structName */        "MirrorModifierData",
312         /* structSize */        sizeof(MirrorModifierData),
313         /* type */              eModifierTypeType_Constructive,
314         /* flags */             eModifierTypeFlag_AcceptsMesh
315                                                         | eModifierTypeFlag_SupportsMapping
316                                                         | eModifierTypeFlag_SupportsEditmode
317                                                         | eModifierTypeFlag_EnableInEditmode
318                                                         | eModifierTypeFlag_AcceptsCVs,
319
320         /* copyData */          copyData,
321         /* deformVerts */       NULL,
322         /* deformMatrices */    NULL,
323         /* deformVertsEM */     NULL,
324         /* deformMatricesEM */  NULL,
325         /* applyModifier */     applyModifier,
326         /* applyModifierEM */   applyModifierEM,
327         /* initData */          initData,
328         /* requiredDataMask */  NULL,
329         /* freeData */          NULL,
330         /* isDisabled */        NULL,
331         /* updateDepgraph */    updateDepgraph,
332         /* dependsOnTime */     NULL,
333         /* dependsOnNormals */  NULL,
334         /* foreachObjectLink */ foreachObjectLink,
335         /* foreachIDLink */     NULL,
336 };