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