40c9e5c3b1ba3b8f809d67c9472a22462ed92af3
[blender.git] / source / blender / modifiers / intern / MOD_subsurf.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) 2005 by the Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup modifiers
22  */
23
24
25 #include <stddef.h>
26
27 #include "MEM_guardedalloc.h"
28
29 #include "BLI_utildefines.h"
30
31 #include "DNA_object_types.h"
32 #include "DNA_scene_types.h"
33 #include "DNA_mesh_types.h"
34
35 #include "BKE_cdderivedmesh.h"
36 #include "BKE_scene.h"
37 #include "BKE_subdiv.h"
38 #include "BKE_subdiv_ccg.h"
39 #include "BKE_subdiv_mesh.h"
40 #include "BKE_subsurf.h"
41
42 #include "DEG_depsgraph.h"
43 #include "DEG_depsgraph_query.h"
44
45 #include "MOD_modifiertypes.h"
46
47 #include "intern/CCGSubSurf.h"
48
49 typedef struct SubsurfRuntimeData {
50         /* Cached subdivision surface descriptor, with topology and settings. */
51         struct Subdiv *subdiv;
52 } SubsurfRuntimeData;
53
54 static void initData(ModifierData *md)
55 {
56         SubsurfModifierData *smd = (SubsurfModifierData *) md;
57
58         smd->levels = 1;
59         smd->renderLevels = 2;
60         smd->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS;
61         smd->quality = 3;
62 }
63
64 static void copyData(const ModifierData *md, ModifierData *target, const int flag)
65 {
66 #if 0
67         const SubsurfModifierData *smd = (const SubsurfModifierData *) md;
68 #endif
69         SubsurfModifierData *tsmd = (SubsurfModifierData *) target;
70
71         modifier_copyData_generic(md, target, flag);
72
73         tsmd->emCache = tsmd->mCache = NULL;
74 }
75
76 static void freeRuntimeData(void *runtime_data_v)
77 {
78         if (runtime_data_v == NULL) {
79                 return;
80         }
81         SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)runtime_data_v;
82         if (runtime_data->subdiv != NULL) {
83                 BKE_subdiv_free(runtime_data->subdiv);
84         }
85         MEM_freeN(runtime_data);
86 }
87
88 static void freeData(ModifierData *md)
89 {
90         SubsurfModifierData *smd = (SubsurfModifierData *) md;
91
92         if (smd->mCache) {
93                 ccgSubSurf_free(smd->mCache);
94                 smd->mCache = NULL;
95         }
96         if (smd->emCache) {
97                 ccgSubSurf_free(smd->emCache);
98                 smd->emCache = NULL;
99         }
100         freeRuntimeData(smd->modifier.runtime);
101 }
102
103 static bool isDisabled(const Scene *scene, ModifierData *md, bool useRenderParams)
104 {
105         SubsurfModifierData *smd = (SubsurfModifierData *) md;
106         int levels = (useRenderParams) ? smd->renderLevels : smd->levels;
107
108         return get_render_subsurf_level(&scene->r, levels, useRenderParams != 0) == 0;
109 }
110
111 static int subdiv_levels_for_modifier_get(const SubsurfModifierData *smd,
112                                           const ModifierEvalContext *ctx)
113 {
114         Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
115         const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER);
116         const int requested_levels = (use_render_params) ? smd->renderLevels
117                                                          : smd->levels;
118         return get_render_subsurf_level(&scene->r,
119                                         requested_levels,
120                                         use_render_params);
121 }
122
123 static void subdiv_settings_init(SubdivSettings *settings,
124                                  const SubsurfModifierData *smd)
125 {
126         settings->is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE);
127         settings->is_adaptive = true;
128         settings->level = settings->is_simple ? 1 : smd->quality;
129         settings->vtx_boundary_interpolation = SUBDIV_VTX_BOUNDARY_EDGE_ONLY;
130         settings->fvar_linear_interpolation =
131                 BKE_subdiv_fvar_interpolation_from_uv_smooth(smd->uv_smooth);
132 }
133
134 /* Main goal of this function is to give usable subdivision surface descriptor
135  * which matches settings and topology. */
136 static Subdiv *subdiv_descriptor_ensure(SubsurfModifierData *smd,
137                                         const SubdivSettings *subdiv_settings,
138                                         const Mesh *mesh)
139 {
140         SubsurfRuntimeData *runtime_data =
141                 (SubsurfRuntimeData *)smd->modifier.runtime;
142         Subdiv *subdiv = BKE_subdiv_update_from_mesh(
143                 runtime_data->subdiv, subdiv_settings, mesh);
144         runtime_data->subdiv = subdiv;
145         return subdiv;
146 }
147
148 /* Subdivide into fully qualified mesh. */
149
150 static void subdiv_mesh_settings_init(SubdivToMeshSettings *settings,
151                                       const SubsurfModifierData *smd,
152                                       const ModifierEvalContext *ctx)
153 {
154         const int level = subdiv_levels_for_modifier_get(smd, ctx);
155         settings->resolution = (1 << level) + 1;
156         settings->use_optimal_display =
157                 (smd->flags & eSubsurfModifierFlag_ControlEdges);
158 }
159
160 static Mesh *subdiv_as_mesh(SubsurfModifierData *smd,
161                             const ModifierEvalContext *ctx,
162                             Mesh *mesh,
163                             Subdiv *subdiv)
164 {
165         Mesh *result = mesh;
166         SubdivToMeshSettings mesh_settings;
167         subdiv_mesh_settings_init(&mesh_settings, smd, ctx);
168         if (mesh_settings.resolution < 3) {
169                 return result;
170         }
171         result = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh);
172         return result;
173 }
174
175 /* Subdivide into CCG. */
176
177 static void subdiv_ccg_settings_init(SubdivToCCGSettings *settings,
178                                      const SubsurfModifierData *smd,
179                                      const ModifierEvalContext *ctx)
180 {
181         const int level = subdiv_levels_for_modifier_get(smd, ctx);
182         settings->resolution = (1 << level) + 1;
183         settings->need_normal = true;
184         settings->need_mask = false;
185 }
186
187 static Mesh *subdiv_as_ccg(SubsurfModifierData *smd,
188                             const ModifierEvalContext *ctx,
189                             Mesh *mesh,
190                             Subdiv *subdiv)
191 {
192         Mesh *result = mesh;
193         SubdivToCCGSettings ccg_settings;
194         subdiv_ccg_settings_init(&ccg_settings, smd, ctx);
195         if (ccg_settings.resolution < 3) {
196                 return result;
197         }
198         result = BKE_subdiv_to_ccg_mesh(subdiv, &ccg_settings, mesh);
199         return result;
200 }
201
202 static SubsurfRuntimeData *subsurf_ensure_runtime(SubsurfModifierData *smd)
203 {
204         SubsurfRuntimeData *runtime_data =
205                 (SubsurfRuntimeData *)smd->modifier.runtime;
206         if (runtime_data == NULL) {
207                 runtime_data = MEM_callocN(sizeof(*runtime_data), "subsurf runtime");
208                 smd->modifier.runtime = runtime_data;
209         }
210         return runtime_data;
211 }
212
213 /* Modifier itself. */
214
215 static Mesh *applyModifier(ModifierData *md,
216                            const ModifierEvalContext *ctx,
217                            Mesh *mesh)
218 {
219         Mesh *result = mesh;
220         SubsurfModifierData *smd = (SubsurfModifierData *) md;
221         SubdivSettings subdiv_settings;
222         subdiv_settings_init(&subdiv_settings, smd);
223         if (subdiv_settings.level == 0) {
224                 return result;
225         }
226         BKE_subdiv_settings_validate_for_mesh(&subdiv_settings, mesh);
227         SubsurfRuntimeData *runtime_data = subsurf_ensure_runtime(smd);
228         Subdiv *subdiv = subdiv_descriptor_ensure(smd, &subdiv_settings, mesh);
229         if (subdiv == NULL) {
230                 /* Happens on bad topology, but also on empty input mesh. */
231                 return result;
232         }
233         /* TODO(sergey): Decide whether we ever want to use CCG for subsurf,
234          * maybe when it is a last modifier in the stack? */
235         if (true) {
236                 result = subdiv_as_mesh(smd, ctx, mesh, subdiv);
237         }
238         else {
239                 result = subdiv_as_ccg(smd, ctx, mesh, subdiv);
240         }
241         // BKE_subdiv_stats_print(&subdiv->stats);
242         if (subdiv != runtime_data->subdiv) {
243                 BKE_subdiv_free(subdiv);
244         }
245         return result;
246 }
247
248 ModifierTypeInfo modifierType_Subsurf = {
249         /* name */              "Subdivision",
250         /* structName */        "SubsurfModifierData",
251         /* structSize */        sizeof(SubsurfModifierData),
252         /* type */              eModifierTypeType_Constructive,
253         /* flags */             eModifierTypeFlag_AcceptsMesh |
254                                 eModifierTypeFlag_SupportsMapping |
255                                 eModifierTypeFlag_SupportsEditmode |
256                                 eModifierTypeFlag_EnableInEditmode |
257                                 eModifierTypeFlag_AcceptsCVs,
258
259         /* copyData */          copyData,
260
261         /* deformVerts */       NULL,
262         /* deformMatrices */    NULL,
263         /* deformVertsEM */     NULL,
264         /* deformMatricesEM */  NULL,
265         /* applyModifier */     applyModifier,
266
267         /* initData */          initData,
268         /* requiredDataMask */  NULL,
269         /* freeData */          freeData,
270         /* isDisabled */        isDisabled,
271         /* updateDepsgraph */   NULL,
272         /* dependsOnTime */     NULL,
273         /* dependsOnNormals */  NULL,
274         /* foreachObjectLink */ NULL,
275         /* foreachIDLink */     NULL,
276         /* foreachTexLink */    NULL,
277         /* freeRuntimeData */   freeRuntimeData,
278 };