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