Fix T63283: Second subdivision modifier does not ignore crease
[blender.git] / source / blender / modifiers / intern / MOD_multires.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_mesh_types.h"
32 #include "DNA_object_types.h"
33 #include "DNA_scene_types.h"
34
35 #include "BKE_cdderivedmesh.h"
36 #include "BKE_mesh.h"
37 #include "BKE_multires.h"
38 #include "BKE_modifier.h"
39 #include "BKE_paint.h"
40 #include "BKE_subdiv.h"
41 #include "BKE_subdiv_ccg.h"
42 #include "BKE_subdiv_mesh.h"
43 #include "BKE_subsurf.h"
44
45 #include "DEG_depsgraph_query.h"
46
47 #include "MOD_modifiertypes.h"
48
49 typedef struct MultiresRuntimeData {
50         /* Cached subdivision surface descriptor, with topology and settings. */
51         struct Subdiv *subdiv;
52 } MultiresRuntimeData;
53
54 static void initData(ModifierData *md)
55 {
56         MultiresModifierData *mmd = (MultiresModifierData *)md;
57
58         mmd->lvl = 0;
59         mmd->sculptlvl = 0;
60         mmd->renderlvl = 0;
61         mmd->totlvl = 0;
62         mmd->uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS;
63         mmd->quality = 3;
64         mmd->flags |= eMultiresModifierFlag_UseCrease;
65 }
66
67 static void copyData(const ModifierData *md_src, ModifierData *md_dst, const int flag)
68 {
69         modifier_copyData_generic(md_src, md_dst, flag);
70 }
71
72 static void freeRuntimeData(void *runtime_data_v)
73 {
74         if (runtime_data_v == NULL) {
75                 return;
76         }
77         MultiresRuntimeData *runtime_data = (MultiresRuntimeData *)runtime_data_v;
78         if (runtime_data->subdiv != NULL) {
79                 BKE_subdiv_free(runtime_data->subdiv);
80         }
81         MEM_freeN(runtime_data);
82 }
83
84 static void freeData(ModifierData *md)
85 {
86         MultiresModifierData *mmd = (MultiresModifierData *) md;
87         freeRuntimeData(mmd->modifier.runtime);
88 }
89
90 static MultiresRuntimeData *multires_ensure_runtime(MultiresModifierData *mmd)
91 {
92         MultiresRuntimeData *runtime_data =
93                 (MultiresRuntimeData *)mmd->modifier.runtime;
94         if (runtime_data == NULL) {
95                 runtime_data = MEM_callocN(sizeof(*runtime_data), "subsurf runtime");
96                 mmd->modifier.runtime = runtime_data;
97         }
98         return runtime_data;
99 }
100
101 /* Main goal of this function is to give usable subdivision surface descriptor
102  * which matches settings and topology. */
103 static Subdiv *subdiv_descriptor_ensure(MultiresModifierData *mmd,
104                                         const SubdivSettings *subdiv_settings,
105                                         const Mesh *mesh)
106 {
107         MultiresRuntimeData *runtime_data =
108                 (MultiresRuntimeData *)mmd->modifier.runtime;
109         Subdiv *subdiv = BKE_subdiv_update_from_mesh(
110                 runtime_data->subdiv, subdiv_settings, mesh);
111         runtime_data->subdiv = subdiv;
112         return subdiv;
113 }
114
115 /* Subdivide into fully qualified mesh. */
116
117 static Mesh *multires_as_mesh(MultiresModifierData *mmd,
118                               const ModifierEvalContext *ctx,
119                               Mesh *mesh,
120                               Subdiv *subdiv)
121 {
122         Mesh *result = mesh;
123         const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER);
124         const bool ignore_simplify = (ctx->flag & MOD_APPLY_IGNORE_SIMPLIFY);
125         const Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
126         Object *object = ctx->object;
127         SubdivToMeshSettings mesh_settings;
128         BKE_multires_subdiv_mesh_settings_init(
129                 &mesh_settings, scene, object, mmd, use_render_params, ignore_simplify);
130         if (mesh_settings.resolution < 3) {
131                 return result;
132         }
133         BKE_subdiv_displacement_attach_from_multires(subdiv, mesh, mmd);
134         result = BKE_subdiv_to_mesh(subdiv, &mesh_settings, mesh);
135         return result;
136 }
137
138 /* Subdivide into CCG. */
139
140 static void multires_ccg_settings_init(SubdivToCCGSettings *settings,
141                                        const MultiresModifierData *mmd,
142                                        const ModifierEvalContext *ctx,
143                                        Mesh *mesh)
144 {
145         const bool has_mask =
146                 CustomData_has_layer(&mesh->ldata, CD_GRID_PAINT_MASK);
147         const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER);
148         const bool ignore_simplify = (ctx->flag & MOD_APPLY_IGNORE_SIMPLIFY);
149         const Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
150         Object *object = ctx->object;
151         const int level = multires_get_level(
152                 scene, object, mmd, use_render_params, ignore_simplify);
153         settings->resolution = (1 << level) + 1;
154         settings->need_normal = true;
155         settings->need_mask = has_mask;
156 }
157
158 static Mesh *multires_as_ccg(MultiresModifierData *mmd,
159                              const ModifierEvalContext *ctx,
160                              Mesh *mesh,
161                              Subdiv *subdiv)
162 {
163         Mesh *result = mesh;
164         SubdivToCCGSettings ccg_settings;
165         multires_ccg_settings_init(&ccg_settings, mmd, ctx, mesh);
166         if (ccg_settings.resolution < 3) {
167                 return result;
168         }
169         BKE_subdiv_displacement_attach_from_multires(subdiv, mesh, mmd);
170         result = BKE_subdiv_to_ccg_mesh(subdiv, &ccg_settings, mesh);
171         return result;
172 }
173
174 static Mesh *applyModifier(ModifierData *md,
175                            const ModifierEvalContext *ctx,
176                            Mesh *mesh)
177 {
178         Mesh *result = mesh;
179         MultiresModifierData *mmd = (MultiresModifierData *)md;
180         SubdivSettings subdiv_settings;
181         BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
182         if (subdiv_settings.level == 0) {
183                 return result;
184         }
185         BKE_subdiv_settings_validate_for_mesh(&subdiv_settings, mesh);
186         MultiresRuntimeData *runtime_data = multires_ensure_runtime(mmd);
187         Subdiv *subdiv = subdiv_descriptor_ensure(mmd, &subdiv_settings, mesh);
188         if (subdiv == NULL) {
189                 /* Happens on bad topology, ut also on empty input mesh. */
190                 return result;
191         }
192         /* NOTE: Orco needs final coordinates on CPU side, which are expected to be
193          * accessible via MVert. For this reason we do not evaluate multires to
194          * grids when orco is requested. */
195         const bool for_orco = (ctx->flag & MOD_APPLY_ORCO) != 0;
196         if ((ctx->object->mode & OB_MODE_SCULPT) && !for_orco) {
197                 /* NOTE: CCG takes ownership over Subdiv. */
198                 result = multires_as_ccg(mmd, ctx, mesh, subdiv);
199                 result->runtime.subdiv_ccg_tot_level = mmd->totlvl;
200                 /* TODO(sergey): Usually it is sculpt stroke's update variants which
201                  * takes care of this, but is possible that we need this before the
202                  * stroke: i.e. when exiting blender right after stroke is done.
203                  * Annoying and not so much black-boxed as far as sculpting goes, and
204                  * surely there is a better way of solving this. */
205                 if (ctx->object->sculpt != NULL) {
206                         ctx->object->sculpt->subdiv_ccg = result->runtime.subdiv_ccg;
207                 }
208                 /* NOTE: CCG becomes an owner of Subdiv descriptor, so can not share
209                  * this pointer. Not sure if it's needed, but might have a second look
210                  * on the ownership model here. */
211                 runtime_data->subdiv = NULL;
212                 // BKE_subdiv_stats_print(&subdiv->stats);
213         }
214         else {
215                 result = multires_as_mesh(mmd, ctx, mesh, subdiv);
216                 // BKE_subdiv_stats_print(&subdiv->stats);
217                 if (subdiv != runtime_data->subdiv) {
218                         BKE_subdiv_free(subdiv);
219                 }
220         }
221         return result;
222 }
223
224 ModifierTypeInfo modifierType_Multires = {
225         /* name */              "Multires",
226         /* structName */        "MultiresModifierData",
227         /* structSize */        sizeof(MultiresModifierData),
228         /* type */              eModifierTypeType_Constructive,
229         /* flags */             eModifierTypeFlag_AcceptsMesh |
230                                 eModifierTypeFlag_SupportsMapping |
231                                 eModifierTypeFlag_RequiresOriginalData,
232
233         /* copyData */          copyData,
234
235         /* deformVerts */       NULL,
236         /* deformMatrices */    NULL,
237         /* deformVertsEM */     NULL,
238         /* deformMatricesEM */  NULL,
239         /* applyModifier */     applyModifier,
240
241         /* initData */          initData,
242         /* requiredDataMask */  NULL,
243         /* freeData */          freeData,
244         /* isDisabled */        NULL,
245         /* updateDepsgraph */   NULL,
246         /* dependsOnTime */     NULL,
247         /* dependsOnNormals */  NULL,
248         /* foreachObjectLink */ NULL,
249         /* foreachIDLink */     NULL,
250         /* foreachTexLink */    NULL,
251         /* freeRuntimeData */   freeRuntimeData,
252 };