Fix crash when snapping ruler
[blender.git] / source / blender / modifiers / intern / MOD_remesh.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2011 by Nicholas Bishop.
17  */
18
19 /** \file
20  * \ingroup modifiers
21  */
22
23 #include "MEM_guardedalloc.h"
24
25 #include "BLI_utildefines.h"
26
27 #include "BLI_math_base.h"
28
29 #include "DNA_meshdata_types.h"
30 #include "DNA_modifier_types.h"
31 #include "DNA_object_types.h"
32 #include "DNA_mesh_types.h"
33
34 #include "MOD_modifiertypes.h"
35
36 #include "BKE_mesh.h"
37 #include "BKE_mesh_runtime.h"
38
39 #include <assert.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #ifdef WITH_MOD_REMESH
44 #  include "BLI_math_vector.h"
45
46 #  include "dualcon.h"
47 #endif
48
49 static void initData(ModifierData *md)
50 {
51   RemeshModifierData *rmd = (RemeshModifierData *)md;
52
53   rmd->scale = 0.9;
54   rmd->depth = 4;
55   rmd->hermite_num = 1;
56   rmd->flag = MOD_REMESH_FLOOD_FILL;
57   rmd->mode = MOD_REMESH_SHARP_FEATURES;
58   rmd->threshold = 1;
59 }
60
61 #ifdef WITH_MOD_REMESH
62
63 static void init_dualcon_mesh(DualConInput *input, Mesh *mesh)
64 {
65   memset(input, 0, sizeof(DualConInput));
66
67   input->co = (void *)mesh->mvert;
68   input->co_stride = sizeof(MVert);
69   input->totco = mesh->totvert;
70
71   input->mloop = (void *)mesh->mloop;
72   input->loop_stride = sizeof(MLoop);
73
74   BKE_mesh_runtime_looptri_ensure(mesh);
75   input->looptri = (void *)mesh->runtime.looptris.array;
76   input->tri_stride = sizeof(MLoopTri);
77   input->tottri = mesh->runtime.looptris.len;
78
79   INIT_MINMAX(input->min, input->max);
80   BKE_mesh_minmax(mesh, input->min, input->max);
81 }
82
83 /* simple structure to hold the output: a CDDM and two counters to
84  * keep track of the current elements */
85 typedef struct {
86   Mesh *mesh;
87   int curvert, curface;
88 } DualConOutput;
89
90 /* allocate and initialize a DualConOutput */
91 static void *dualcon_alloc_output(int totvert, int totquad)
92 {
93   DualConOutput *output;
94
95   if (!(output = MEM_callocN(sizeof(DualConOutput), "DualConOutput"))) {
96     return NULL;
97   }
98
99   output->mesh = BKE_mesh_new_nomain(totvert, 0, 0, 4 * totquad, totquad);
100   return output;
101 }
102
103 static void dualcon_add_vert(void *output_v, const float co[3])
104 {
105   DualConOutput *output = output_v;
106   Mesh *mesh = output->mesh;
107
108   assert(output->curvert < mesh->totvert);
109
110   copy_v3_v3(mesh->mvert[output->curvert].co, co);
111   output->curvert++;
112 }
113
114 static void dualcon_add_quad(void *output_v, const int vert_indices[4])
115 {
116   DualConOutput *output = output_v;
117   Mesh *mesh = output->mesh;
118   MLoop *mloop;
119   MPoly *cur_poly;
120   int i;
121
122   assert(output->curface < mesh->totpoly);
123
124   mloop = mesh->mloop;
125   cur_poly = &mesh->mpoly[output->curface];
126
127   cur_poly->loopstart = output->curface * 4;
128   cur_poly->totloop = 4;
129   for (i = 0; i < 4; i++) {
130     mloop[output->curface * 4 + i].v = vert_indices[i];
131   }
132
133   output->curface++;
134 }
135
136 static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh)
137 {
138   RemeshModifierData *rmd;
139   DualConOutput *output;
140   DualConInput input;
141   Mesh *result;
142   DualConFlags flags = 0;
143   DualConMode mode = 0;
144
145   rmd = (RemeshModifierData *)md;
146
147   init_dualcon_mesh(&input, mesh);
148
149   if (rmd->flag & MOD_REMESH_FLOOD_FILL) {
150     flags |= DUALCON_FLOOD_FILL;
151   }
152
153   switch (rmd->mode) {
154     case MOD_REMESH_CENTROID:
155       mode = DUALCON_CENTROID;
156       break;
157     case MOD_REMESH_MASS_POINT:
158       mode = DUALCON_MASS_POINT;
159       break;
160     case MOD_REMESH_SHARP_FEATURES:
161       mode = DUALCON_SHARP_FEATURES;
162       break;
163   }
164
165   output = dualcon(&input,
166                    dualcon_alloc_output,
167                    dualcon_add_vert,
168                    dualcon_add_quad,
169                    flags,
170                    mode,
171                    rmd->threshold,
172                    rmd->hermite_num,
173                    rmd->scale,
174                    rmd->depth);
175   result = output->mesh;
176   MEM_freeN(output);
177
178   if (rmd->flag & MOD_REMESH_SMOOTH_SHADING) {
179     MPoly *mpoly = result->mpoly;
180     int i, totpoly = result->totpoly;
181
182     /* Apply smooth shading to output faces */
183     for (i = 0; i < totpoly; i++) {
184       mpoly[i].flag |= ME_SMOOTH;
185     }
186   }
187
188   BKE_mesh_calc_edges(result, true, false);
189   result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
190   return result;
191 }
192
193 #else /* !WITH_MOD_REMESH */
194
195 static Mesh *applyModifier(ModifierData *UNUSED(md),
196                            const ModifierEvalContext *UNUSED(ctx),
197                            Mesh *mesh)
198 {
199   return mesh;
200 }
201
202 #endif /* !WITH_MOD_REMESH */
203
204 ModifierTypeInfo modifierType_Remesh = {
205     /* name */ "Remesh",
206     /* structName */ "RemeshModifierData",
207     /* structSize */ sizeof(RemeshModifierData),
208     /* type */ eModifierTypeType_Nonconstructive,
209     /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs |
210         eModifierTypeFlag_SupportsEditmode,
211
212     /* copyData */ modifier_copyData_generic,
213
214     /* deformVerts */ NULL,
215     /* deformMatrices */ NULL,
216     /* deformVertsEM */ NULL,
217     /* deformMatricesEM */ NULL,
218     /* applyModifier */ applyModifier,
219
220     /* initData */ initData,
221     /* requiredDataMask */ NULL,
222     /* freeData */ NULL,
223     /* isDisabled */ NULL,
224     /* updateDepsgraph */ NULL,
225     /* dependsOnTime */ NULL,
226     /* dependsOnNormals */ NULL,
227     /* foreachObjectLink */ NULL,
228     /* foreachIDLink */ NULL,
229     /* freeRuntimeData */ NULL,
230 };