code cleanup: make bmesh operator names more consistant since python has access to...
[blender.git] / source / blender / modifiers / intern / MOD_remesh.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) 2011 by Nicholas Bishop.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/modifiers/intern/MOD_remesh.c
24  *  \ingroup modifiers
25  */
26
27 #include "MEM_guardedalloc.h"
28
29 #include "BLI_math_base.h"
30 #include "BLI_math_vector.h"
31 #include "BLI_utildefines.h"
32
33 #include "BKE_cdderivedmesh.h"
34 #include "BKE_DerivedMesh.h"
35 #include "BKE_mesh.h"
36
37 #include "DNA_meshdata_types.h"
38 #include "DNA_modifier_types.h"
39 #include "DNA_object_types.h"
40
41 #include "MOD_modifiertypes.h"
42
43 #include <assert.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 #ifdef WITH_MOD_REMESH
48 #  include "dualcon.h"
49 #endif
50
51 static void initData(ModifierData *md)
52 {
53         RemeshModifierData *rmd = (RemeshModifierData *) md;
54
55         rmd->scale = 0.9;
56         rmd->depth = 4;
57         rmd->hermite_num = 1;
58         rmd->flag = MOD_REMESH_FLOOD_FILL;
59         rmd->mode = MOD_REMESH_SHARP_FEATURES;
60         rmd->threshold = 1;
61 }
62
63 static void copyData(ModifierData *md, ModifierData *target)
64 {
65         RemeshModifierData *rmd = (RemeshModifierData *) md;
66         RemeshModifierData *trmd = (RemeshModifierData *) target;
67
68         trmd->threshold = rmd->threshold;
69         trmd->scale = rmd->scale;
70         trmd->hermite_num = rmd->hermite_num;
71         trmd->depth = rmd->depth;
72         trmd->flag = rmd->flag;
73         trmd->mode = rmd->mode;
74 }
75
76 #ifdef WITH_MOD_REMESH
77
78 static void init_dualcon_mesh(DualConInput *mesh, DerivedMesh *dm)
79 {
80         memset(mesh, 0, sizeof(DualConInput));
81
82         mesh->co = (void *)dm->getVertArray(dm);
83         mesh->co_stride = sizeof(MVert);
84         mesh->totco = dm->getNumVerts(dm);
85
86         mesh->faces = (void *)dm->getTessFaceArray(dm);
87         mesh->face_stride = sizeof(MFace);
88         mesh->totface = dm->getNumTessFaces(dm);
89
90         INIT_MINMAX(mesh->min, mesh->max);
91         dm->getMinMax(dm, mesh->min, mesh->max);
92 }
93
94 /* simple structure to hold the output: a CDDM and two counters to
95  * keep track of the current elements */
96 typedef struct {
97         DerivedMesh *dm;
98         int curvert, curface;
99 } DualConOutput;
100
101 /* allocate and initialize a DualConOutput */
102 static void *dualcon_alloc_output(int totvert, int totquad)
103 {
104         DualConOutput *output;
105
106         if (!(output = MEM_callocN(sizeof(DualConOutput),
107                                    "DualConOutput")))
108         {
109                 return NULL;
110         }
111         
112         output->dm = CDDM_new(totvert, 0, 0, 4 * totquad, totquad);
113         return output;
114 }
115
116 static void dualcon_add_vert(void *output_v, const float co[3])
117 {
118         DualConOutput *output = output_v;
119         DerivedMesh *dm = output->dm;
120         
121         assert(output->curvert < dm->getNumVerts(dm));
122         
123         copy_v3_v3(CDDM_get_verts(dm)[output->curvert].co, co);
124         output->curvert++;
125 }
126
127 static void dualcon_add_quad(void *output_v, const int vert_indices[4])
128 {
129         DualConOutput *output = output_v;
130         DerivedMesh *dm = output->dm;
131         MLoop *mloop;
132         MPoly *cur_poly;
133         int i;
134         
135         assert(output->curface < dm->getNumPolys(dm));
136
137         mloop = CDDM_get_loops(dm);
138         cur_poly = CDDM_get_poly(dm, output->curface);
139         
140         cur_poly->loopstart = output->curface * 4;
141         cur_poly->totloop = 4;
142         for (i = 0; i < 4; i++)
143                 mloop[output->curface * 4 + i].v = vert_indices[i];
144         
145         output->curface++;
146 }
147
148 static DerivedMesh *applyModifier(ModifierData *md,
149                                   Object *UNUSED(ob),
150                                   DerivedMesh *dm,
151                                   ModifierApplyFlag UNUSED(flag))
152 {
153         RemeshModifierData *rmd;
154         DualConOutput *output;
155         DualConInput input;
156         DerivedMesh *result;
157         DualConFlags flags = 0;
158         DualConMode mode = 0;
159
160         DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
161
162         rmd = (RemeshModifierData *)md;
163
164         init_dualcon_mesh(&input, dm);
165
166         if (rmd->flag & MOD_REMESH_FLOOD_FILL)
167                 flags |= DUALCON_FLOOD_FILL;
168
169         switch (rmd->mode) {
170                 case MOD_REMESH_CENTROID:
171                         mode = DUALCON_CENTROID;
172                         break;
173                 case MOD_REMESH_MASS_POINT:
174                         mode = DUALCON_MASS_POINT;
175                         break;
176                 case MOD_REMESH_SHARP_FEATURES:
177                         mode = DUALCON_SHARP_FEATURES;
178                         break;
179         }
180         
181         output = dualcon(&input,
182                          dualcon_alloc_output,
183                          dualcon_add_vert,
184                          dualcon_add_quad,
185                          flags,
186                          mode,
187                          rmd->threshold,
188                          rmd->hermite_num,
189                          rmd->scale,
190                          rmd->depth);
191         result = output->dm;
192         MEM_freeN(output);
193
194         if (rmd->flag & MOD_REMESH_SMOOTH_SHADING) {
195                 MPoly *mpoly = CDDM_get_polys(result);
196                 int i, totpoly = result->getNumPolys(result);
197                 
198                 /* Apply smooth shading to output faces */
199                 for (i = 0; i < totpoly; i++) {
200                         mpoly[i].flag |= ME_SMOOTH;
201                 }
202         }
203
204         CDDM_calc_edges(result);
205         CDDM_calc_normals(result);
206         return result;
207 }
208
209 #else /* !WITH_MOD_REMESH */
210
211 static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
212                                   DerivedMesh *derivedData,
213                                   ModifierApplyFlag UNUSED(flag))
214 {
215         return derivedData;
216 }
217
218 #endif /* !WITH_MOD_REMESH */
219
220 ModifierTypeInfo modifierType_Remesh = {
221         /* name */              "Remesh",
222         /* structName */        "RemeshModifierData",
223         /* structSize */        sizeof(RemeshModifierData),
224         /* type */              eModifierTypeType_Nonconstructive,
225         /* flags */             eModifierTypeFlag_AcceptsMesh |
226                                 eModifierTypeFlag_AcceptsCVs |
227                                 eModifierTypeFlag_SupportsEditmode,
228         /* copyData */          copyData,
229         /* deformVerts */       NULL,
230         /* deformMatrices */    NULL,
231         /* deformVertsEM */     NULL,
232         /* deformMatricesEM */  NULL,
233         /* applyModifier */     applyModifier,
234         /* applyModifierEM */   NULL,
235         /* initData */          initData,
236         /* requiredDataMask */  NULL,
237         /* freeData */          NULL,
238         /* isDisabled */        NULL,
239         /* updateDepgraph */    NULL,
240         /* dependsOnTime */     NULL,
241         /* dependsOnNormals */  NULL,
242         /* foreachObjectLink */ NULL,
243         /* foreachIDLink */     NULL,
244 };