code cleanup: make bmesh operator names more consistant since python has access to...
[blender.git] / source / blender / modifiers / intern / MOD_decimate.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_decimate.c
32  *  \ingroup modifiers
33  */
34
35 #include "DNA_object_types.h"
36
37 #include "BLI_math.h"
38 #include "BLI_string.h"
39 #include "BLI_utildefines.h"
40
41 #include "BLF_translation.h"
42
43 #include "MEM_guardedalloc.h"
44
45 #include "BKE_mesh.h"
46 #include "BKE_modifier.h"
47 #include "BKE_deform.h"
48 #include "BKE_particle.h"
49 #include "BKE_cdderivedmesh.h"
50
51 #include "bmesh.h"
52
53 // #define USE_TIMEIT
54
55 #ifdef USE_TIMEIT
56 #  include "PIL_time.h"
57 #endif
58
59 #include "MOD_util.h"
60
61 static void initData(ModifierData *md)
62 {
63         DecimateModifierData *dmd = (DecimateModifierData *) md;
64
65         dmd->percent = 1.0;
66         dmd->angle   = DEG2RADF(15.0f);
67 }
68
69 static void copyData(ModifierData *md, ModifierData *target)
70 {
71         DecimateModifierData *dmd = (DecimateModifierData *) md;
72         DecimateModifierData *tdmd = (DecimateModifierData *) target;
73
74         tdmd->percent = dmd->percent;
75         tdmd->iter = dmd->iter;
76         tdmd->angle = dmd->angle;
77         BLI_strncpy(tdmd->defgrp_name, dmd->defgrp_name, sizeof(tdmd->defgrp_name));
78         tdmd->flag = dmd->flag;
79         tdmd->mode = dmd->mode;
80 }
81
82 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
83 {
84         DecimateModifierData *dmd = (DecimateModifierData *) md;
85         CustomDataMask dataMask = 0;
86
87         /* ask for vertexgroups if we need them */
88         if (dmd->defgrp_name[0]) dataMask |= CD_MASK_MDEFORMVERT;
89
90         return dataMask;
91 }
92
93 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
94                                   DerivedMesh *derivedData,
95                                   ModifierApplyFlag UNUSED(flag))
96 {
97         DecimateModifierData *dmd = (DecimateModifierData *) md;
98         DerivedMesh *dm = derivedData, *result = NULL;
99         BMesh *bm;
100
101         float *vweights = NULL;
102
103 #ifdef USE_TIMEIT
104         TIMEIT_START(decim);
105 #endif
106
107         /* set up front so we dont show invalid info in the UI */
108         dmd->face_count = dm->getNumPolys(dm);
109
110         switch (dmd->mode) {
111                 case MOD_DECIM_MODE_COLLAPSE:
112                         if (dmd->percent == 1.0f) {
113                                 return dm;
114                         }
115                         break;
116                 case MOD_DECIM_MODE_UNSUBDIV:
117                         if (dmd->iter == 0) {
118                                 return dm;
119                         }
120                         break;
121                 case MOD_DECIM_MODE_DISSOLVE:
122                         if (dmd->angle == 0.0f) {
123                                 return dm;
124                         }
125                         break;
126         }
127
128         if (dmd->face_count <= 3) {
129                 modifier_setError(md, "Modifier requires more than 3 input faces");
130                 return dm;
131         }
132
133         if (dmd->mode == MOD_DECIM_MODE_COLLAPSE) {
134                 if (dmd->defgrp_name[0]) {
135                         MDeformVert *dvert;
136                         int defgrp_index;
137
138                         modifier_get_vgroup(ob, dm, dmd->defgrp_name, &dvert, &defgrp_index);
139
140                         if (dvert) {
141                                 const unsigned int vert_tot = dm->getNumVerts(dm);
142                                 unsigned int i;
143
144                                 vweights = MEM_mallocN(vert_tot * sizeof(float), __func__);
145
146                                 if (dmd->flag & MOD_DECIM_FLAG_INVERT_VGROUP) {
147                                         for (i = 0; i < vert_tot; i++) {
148                                                 vweights[i] = 1.0f - defvert_find_weight(&dvert[i], defgrp_index);
149                                         }
150                                 }
151                                 else {
152                                         for (i = 0; i < vert_tot; i++) {
153                                                 vweights[i] = defvert_find_weight(&dvert[i], defgrp_index);
154                                         }
155                                 }
156                         }
157                 }
158         }
159
160         bm = DM_to_bmesh(dm);
161
162         switch (dmd->mode) {
163                 case MOD_DECIM_MODE_COLLAPSE:
164                 {
165                         const int do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0;
166                         BM_mesh_decimate_collapse(bm, dmd->percent, vweights, do_triangulate);
167                         break;
168                 }
169                 case MOD_DECIM_MODE_UNSUBDIV:
170                 {
171                         BM_mesh_decimate_unsubdivide(bm, dmd->iter);
172                         break;
173                 }
174                 case MOD_DECIM_MODE_DISSOLVE:
175                 {
176                         const int do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0;
177                         BM_mesh_decimate_dissolve(bm, dmd->angle, do_dissolve_boundaries);
178                         break;
179                 }
180         }
181
182         if (vweights) {
183                 MEM_freeN(vweights);
184         }
185
186         /* update for display only */
187         dmd->face_count = bm->totface;
188         result = CDDM_from_bmesh(bm, FALSE);
189         BLI_assert(bm->toolflagpool == NULL);  /* make sure we never alloc'd this */
190         BM_mesh_free(bm);
191
192 #ifdef USE_TIMEIT
193         TIMEIT_END(decim);
194 #endif
195
196         return result;
197 }
198
199 ModifierTypeInfo modifierType_Decimate = {
200         /* name */              "Decimate",
201         /* structName */        "DecimateModifierData",
202         /* structSize */        sizeof(DecimateModifierData),
203         /* type */              eModifierTypeType_Nonconstructive,
204         /* flags */             eModifierTypeFlag_AcceptsMesh |
205                                 eModifierTypeFlag_AcceptsCVs,
206         /* copyData */          copyData,
207         /* deformVerts */       NULL,
208         /* deformMatrices */    NULL,
209         /* deformVertsEM */     NULL,
210         /* deformMatricesEM */  NULL,
211         /* applyModifier */     applyModifier,
212         /* applyModifierEM */   NULL,
213         /* initData */          initData,
214         /* requiredDataMask */  requiredDataMask,
215         /* freeData */          NULL,
216         /* isDisabled */        NULL,
217         /* updateDepgraph */    NULL,
218         /* dependsOnTime */     NULL,
219         /* dependsOnNormals */  NULL,
220         /* foreachObjectLink */ NULL,
221         /* foreachIDLink */     NULL,
222         /* foreachTexLink */    NULL,
223 };