Depsgraph: New dependency graph integration commit
[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->faces = (void *)dm->getTessFaceArray(dm);
82         mesh->face_stride = sizeof(MFace);
83         mesh->totface = dm->getNumTessFaces(dm);
84
85         INIT_MINMAX(mesh->min, mesh->max);
86         dm->getMinMax(dm, mesh->min, mesh->max);
87 }
88
89 /* simple structure to hold the output: a CDDM and two counters to
90  * keep track of the current elements */
91 typedef struct {
92         DerivedMesh *dm;
93         int curvert, curface;
94 } DualConOutput;
95
96 /* allocate and initialize a DualConOutput */
97 static void *dualcon_alloc_output(int totvert, int totquad)
98 {
99         DualConOutput *output;
100
101         if (!(output = MEM_callocN(sizeof(DualConOutput),
102                                    "DualConOutput")))
103         {
104                 return NULL;
105         }
106         
107         output->dm = CDDM_new(totvert, 0, 0, 4 * totquad, totquad);
108         return output;
109 }
110
111 static void dualcon_add_vert(void *output_v, const float co[3])
112 {
113         DualConOutput *output = output_v;
114         DerivedMesh *dm = output->dm;
115         
116         assert(output->curvert < dm->getNumVerts(dm));
117         
118         copy_v3_v3(CDDM_get_verts(dm)[output->curvert].co, co);
119         output->curvert++;
120 }
121
122 static void dualcon_add_quad(void *output_v, const int vert_indices[4])
123 {
124         DualConOutput *output = output_v;
125         DerivedMesh *dm = output->dm;
126         MLoop *mloop;
127         MPoly *cur_poly;
128         int i;
129         
130         assert(output->curface < dm->getNumPolys(dm));
131
132         mloop = CDDM_get_loops(dm);
133         cur_poly = CDDM_get_poly(dm, output->curface);
134         
135         cur_poly->loopstart = output->curface * 4;
136         cur_poly->totloop = 4;
137         for (i = 0; i < 4; i++)
138                 mloop[output->curface * 4 + i].v = vert_indices[i];
139         
140         output->curface++;
141 }
142
143 static DerivedMesh *applyModifier(ModifierData *md,
144                                   Object *UNUSED(ob),
145                                   DerivedMesh *dm,
146                                   ModifierApplyFlag UNUSED(flag))
147 {
148         RemeshModifierData *rmd;
149         DualConOutput *output;
150         DualConInput input;
151         DerivedMesh *result;
152         DualConFlags flags = 0;
153         DualConMode mode = 0;
154
155         DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
156
157         rmd = (RemeshModifierData *)md;
158
159         init_dualcon_mesh(&input, dm);
160
161         if (rmd->flag & MOD_REMESH_FLOOD_FILL)
162                 flags |= DUALCON_FLOOD_FILL;
163
164         switch (rmd->mode) {
165                 case MOD_REMESH_CENTROID:
166                         mode = DUALCON_CENTROID;
167                         break;
168                 case MOD_REMESH_MASS_POINT:
169                         mode = DUALCON_MASS_POINT;
170                         break;
171                 case MOD_REMESH_SHARP_FEATURES:
172                         mode = DUALCON_SHARP_FEATURES;
173                         break;
174         }
175         
176         output = dualcon(&input,
177                          dualcon_alloc_output,
178                          dualcon_add_vert,
179                          dualcon_add_quad,
180                          flags,
181                          mode,
182                          rmd->threshold,
183                          rmd->hermite_num,
184                          rmd->scale,
185                          rmd->depth);
186         result = output->dm;
187         MEM_freeN(output);
188
189         if (rmd->flag & MOD_REMESH_SMOOTH_SHADING) {
190                 MPoly *mpoly = CDDM_get_polys(result);
191                 int i, totpoly = result->getNumPolys(result);
192                 
193                 /* Apply smooth shading to output faces */
194                 for (i = 0; i < totpoly; i++) {
195                         mpoly[i].flag |= ME_SMOOTH;
196                 }
197         }
198
199         CDDM_calc_edges(result);
200         result->dirty |= DM_DIRTY_NORMALS;
201         return result;
202 }
203
204 #else /* !WITH_MOD_REMESH */
205
206 static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
207                                   DerivedMesh *derivedData,
208                                   ModifierApplyFlag UNUSED(flag))
209 {
210         return derivedData;
211 }
212
213 #endif /* !WITH_MOD_REMESH */
214
215 ModifierTypeInfo modifierType_Remesh = {
216         /* name */              "Remesh",
217         /* structName */        "RemeshModifierData",
218         /* structSize */        sizeof(RemeshModifierData),
219         /* type */              eModifierTypeType_Nonconstructive,
220         /* flags */             eModifierTypeFlag_AcceptsMesh |
221                                 eModifierTypeFlag_AcceptsCVs |
222                                 eModifierTypeFlag_SupportsEditmode,
223         /* copyData */          copyData,
224         /* deformVerts */       NULL,
225         /* deformMatrices */    NULL,
226         /* deformVertsEM */     NULL,
227         /* deformMatricesEM */  NULL,
228         /* applyModifier */     applyModifier,
229         /* applyModifierEM */   NULL,
230         /* initData */          initData,
231         /* requiredDataMask */  NULL,
232         /* freeData */          NULL,
233         /* isDisabled */        NULL,
234         /* updateDepgraph */    NULL,
235         /* updateDepsgraph */   NULL,
236         /* dependsOnTime */     NULL,
237         /* dependsOnNormals */  NULL,
238         /* foreachObjectLink */ NULL,
239         /* foreachIDLink */     NULL,
240 };