0333d52a464982759dfa677296fc64c694e4aff7
[blender.git] / source / blender / blenkernel / BKE_subdiv.h
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) 2018 by Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup bke
22  */
23
24 #ifndef __BKE_SUBDIV_H__
25 #define __BKE_SUBDIV_H__
26
27 #include "BLI_compiler_compat.h"
28 #include "BLI_sys_types.h"
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
34 struct Mesh;
35 struct MultiresModifierData;
36 struct OpenSubdiv_Converter;
37 struct OpenSubdiv_Evaluator;
38 struct OpenSubdiv_TopologyRefiner;
39 struct Subdiv;
40
41 typedef enum eSubdivVtxBoundaryInterpolation {
42   /* Do not interpolate boundaries. */
43   SUBDIV_VTX_BOUNDARY_NONE,
44   /* Sharpen edges. */
45   SUBDIV_VTX_BOUNDARY_EDGE_ONLY,
46   /* sharpen edges and corners, */
47   SUBDIV_VTX_BOUNDARY_EDGE_AND_CORNER,
48 } eSubdivVtxBoundaryInterpolation;
49
50 typedef enum eSubdivFVarLinearInterpolation {
51   SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE,
52   SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY,
53   SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_AND_JUNCTIONS,
54   SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_JUNCTIONS_AND_CONCAVE,
55   SUBDIV_FVAR_LINEAR_INTERPOLATION_BOUNDARIES,
56   SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL,
57 } eSubdivFVarLinearInterpolation;
58
59 typedef struct SubdivSettings {
60   /* Simple subdivision corresponds to "Simple" option in the interface. When its enabled the
61    * subdivided mesh is not "smoothed": new vertices are added uniformly on the existing surface.
62    *
63    * On an OpenSubdiv implementation level this translates to a subdivision scheme:
64    * when is_simple is true OSD_SCHEME_BILINEAR is used, otherwise OSD_SCHEME_CATMARK. */
65   bool is_simple;
66
67   /* This refers to an adaptive isolation when creating patches for the subdivided surface.
68    *
69    * When is set to false (aka uniform subdivision) fixed depth of isolation is used, which
70    * allows to iteratively add more subdivisions (uniform subdivision level 2 = uniform subdivision
71    * level 1 + uniform subdivision level 1). Uniform subdivisions will progressively go to a limit
72    * surface.
73    *
74    * Adaptive isolation generates patches at a limit surface (aka as if infinite number of uniform
75    * subdivisions have been applied). This setting allows to have matches normal and tangent space
76    * the same independent of number of subdivisions set in modifier settings. */
77   bool is_adaptive;
78
79   /* Corresponds to Quality option in modifier settings: higher values means the final surface
80    * will be more accurately represented by patches.
81    *
82    * On an OpenSubdiv implementation level this is an isolation level. */
83   int level;
84
85   bool use_creases;
86
87   eSubdivVtxBoundaryInterpolation vtx_boundary_interpolation;
88   eSubdivFVarLinearInterpolation fvar_linear_interpolation;
89 } SubdivSettings;
90
91 /* NOTE: Order of enumerators MUST match order of values in SubdivStats. */
92 typedef enum eSubdivStatsValue {
93   SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME = 0,
94   SUBDIV_STATS_SUBDIV_TO_MESH,
95   SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY,
96   SUBDIV_STATS_EVALUATOR_CREATE,
97   SUBDIV_STATS_EVALUATOR_REFINE,
98   SUBDIV_STATS_SUBDIV_TO_CCG,
99   SUBDIV_STATS_SUBDIV_TO_CCG_ELEMENTS,
100   SUBDIV_STATS_TOPOLOGY_COMPARE,
101
102   NUM_SUBDIV_STATS_VALUES,
103 } eSubdivStatsValue;
104
105 typedef struct SubdivStats {
106   union {
107     struct {
108       /* Time spend on creating topology refiner, which includes time
109        * spend on conversion from Blender data to OpenSubdiv data, and
110        * time spend on topology orientation on OpenSubdiv C-API side. */
111       double topology_refiner_creation_time;
112       /* Total time spent in BKE_subdiv_to_mesh(). */
113       double subdiv_to_mesh_time;
114       /* Geometry (MVert and co) creation time during SUBDIV_TYO_MESH. */
115       double subdiv_to_mesh_geometry_time;
116       /* Time spent on evaluator creation from topology refiner. */
117       double evaluator_creation_time;
118       /* Time spent on evaluator->refine(). */
119       double evaluator_refine_time;
120       /* Total time spent on whole CCG creation. */
121       double subdiv_to_ccg_time;
122       /* Time spent on CCG elements evaluation/initialization. */
123       double subdiv_to_ccg_elements_time;
124       /* Time spent on CCG elements evaluation/initialization. */
125       double topology_compare_time;
126     };
127     double values_[NUM_SUBDIV_STATS_VALUES];
128   };
129
130   /* Per-value timestamp on when corresponding BKE_subdiv_stats_begin() was
131    * called. */
132   double begin_timestamp_[NUM_SUBDIV_STATS_VALUES];
133 } SubdivStats;
134
135 /* Functor which evaluates displacement at a given (u, v) of given ptex face. */
136 typedef struct SubdivDisplacement {
137   /* Initialize displacement evaluator.
138    *
139    * Is called right before evaluation is actually needed. This allows to do
140    * some lazy initialization, like allocate evaluator from a main thread but
141    * then do actual evaluation from background job. */
142   void (*initialize)(struct SubdivDisplacement *displacement);
143
144   /* Return displacement which is to be added to the original coordinate.
145    *
146    * NOTE: This function is supposed to return "continuous" displacement for
147    * each pf PTex faces created for special (non-quad) polygon. This means,
148    * if displacement is stored on per-corner manner (like MDisps for multires)
149    * this is up the displacement implementation to average boundaries of the
150    * displacement grids if needed.
151    *
152    * Averaging of displacement for vertices created for over coarse vertices
153    * and edges is done by subdiv code. */
154   void (*eval_displacement)(struct SubdivDisplacement *displacement,
155                             const int ptex_face_index,
156                             const float u,
157                             const float v,
158                             const float dPdu[3],
159                             const float dPdv[3],
160                             float r_D[3]);
161
162   /* Free the data, not the evaluator itself. */
163   void (*free)(struct SubdivDisplacement *displacement);
164
165   void *user_data;
166 } SubdivDisplacement;
167
168 /* This structure contains everything needed to construct subdivided surface.
169  * It does not specify storage, memory layout or anything else.
170  * It is possible to create different storage's (like, grid based CPU side
171  * buffers, GPU subdivision mesh, CPU side fully qualified mesh) from the same
172  * Subdiv structure. */
173 typedef struct Subdiv {
174   /* Settings this subdivision surface is created for.
175    *
176    * It is read-only after assignment in BKE_subdiv_new_from_FOO(). */
177   SubdivSettings settings;
178   /* Topology refiner includes all the glue logic to feed Blender side
179    * topology to OpenSubdiv. It can be shared by both evaluator and GL mesh
180    * drawer. */
181   struct OpenSubdiv_TopologyRefiner *topology_refiner;
182   /* CPU side evaluator. */
183   struct OpenSubdiv_Evaluator *evaluator;
184   /* Optional displacement evaluator. */
185   struct SubdivDisplacement *displacement_evaluator;
186   /* Statistics for debugging. */
187   SubdivStats stats;
188
189   /* Cached values, are not supposed to be accessed directly. */
190   struct {
191     /* Indexed by base face index, element indicates total number of ptex
192      * faces created for preceding base faces. */
193     int *face_ptex_offset;
194   } cache_;
195 } Subdiv;
196
197 /* ========================== CONVERSION HELPERS ============================ */
198
199 /* NOTE: uv_smooth is eSubsurfUVSmooth. */
200 eSubdivFVarLinearInterpolation BKE_subdiv_fvar_interpolation_from_uv_smooth(int uv_smooth);
201
202 /* =============================== STATISTICS =============================== */
203
204 void BKE_subdiv_stats_init(SubdivStats *stats);
205
206 void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value);
207 void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value);
208
209 void BKE_subdiv_stats_reset(SubdivStats *stats, eSubdivStatsValue value);
210
211 void BKE_subdiv_stats_print(const SubdivStats *stats);
212
213 /* ================================ SETTINGS ================================ */
214
215 void BKE_subdiv_settings_validate_for_mesh(SubdivSettings *settings, const struct Mesh *mesh);
216
217 bool BKE_subdiv_settings_equal(const SubdivSettings *settings_a, const SubdivSettings *settings_b);
218
219 /* ============================== CONSTRUCTION ============================== */
220
221 /* Construct new subdivision surface descriptor, from scratch, using given
222  * settings and topology. */
223 Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
224                                       struct OpenSubdiv_Converter *converter);
225 Subdiv *BKE_subdiv_new_from_mesh(const SubdivSettings *settings, const struct Mesh *mesh);
226
227 /* Similar to above, but will not re-create descriptor if it was created for the
228  * same settings and topology.
229  * If settings or topology did change, the existing descriptor is freed and a
230  * new one is created from scratch.
231  *
232  * NOTE: It is allowed to pass NULL as an existing subdivision surface
233  * descriptor. This will create a new descriptor without any extra checks.
234  */
235 Subdiv *BKE_subdiv_update_from_converter(Subdiv *subdiv,
236                                          const SubdivSettings *settings,
237                                          struct OpenSubdiv_Converter *converter);
238 Subdiv *BKE_subdiv_update_from_mesh(Subdiv *subdiv,
239                                     const SubdivSettings *settings,
240                                     const struct Mesh *mesh);
241
242 void BKE_subdiv_free(Subdiv *subdiv);
243
244 /* ============================ DISPLACEMENT API ============================ */
245
246 void BKE_subdiv_displacement_attach_from_multires(Subdiv *subdiv,
247                                                   struct Mesh *mesh,
248                                                   const struct MultiresModifierData *mmd);
249
250 void BKE_subdiv_displacement_detach(Subdiv *subdiv);
251
252 /* ============================ TOPOLOGY HELPERS ============================ */
253
254 int *BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv);
255
256 /* =========================== PTEX FACES AND GRIDS ========================= */
257
258 /* For a given (ptex_u, ptex_v) within a ptex face get corresponding
259  * (grid_u, grid_v) within a grid. */
260 BLI_INLINE void BKE_subdiv_ptex_face_uv_to_grid_uv(const float ptex_u,
261                                                    const float ptex_v,
262                                                    float *r_grid_u,
263                                                    float *r_grid_v);
264
265 /* Inverse of above. */
266 BLI_INLINE void BKE_subdiv_grid_uv_to_ptex_face_uv(const float grid_u,
267                                                    const float grid_v,
268                                                    float *r_ptex_u,
269                                                    float *r_ptex_v);
270
271 /* For a given subdivision level (which is NOT refinement level) get size of
272  * CCG grid (number of grid points on a side).
273  */
274 BLI_INLINE int BKE_subdiv_grid_size_from_level(const int level);
275
276 /* Simplified version of mdisp_rot_face_to_crn, only handles quad and
277  * works in normalized coordinates.
278  *
279  * NOTE: Output coordinates are in ptex coordinates. */
280 BLI_INLINE int BKE_subdiv_rotate_quad_to_corner(const float quad_u,
281                                                 const float quad_v,
282                                                 float *r_corner_u,
283                                                 float *r_corner_v);
284
285 /* Converts (u, v) coordinate from within a grid to a quad coordinate in
286  * normalized ptex coordinates. */
287 BLI_INLINE void BKE_subdiv_rotate_grid_to_quad(
288     const int corner, const float grid_u, const float grid_v, float *r_quad_u, float *r_quad_v);
289
290 /* Convert Blender edge crease value to OpenSubdiv sharpness. */
291 BLI_INLINE float BKE_subdiv_edge_crease_to_sharpness_f(float edge_crease);
292 BLI_INLINE float BKE_subdiv_edge_crease_to_sharpness_char(char edge_crease);
293
294 #ifdef __cplusplus
295 }
296 #endif
297
298 #include "intern/subdiv_inline.h"
299
300 #endif /* __BKE_SUBDIV_H__ */