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