Cleanup: remove redundant, invalid info from headers
[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 BKE_subdiv.h
21  *  \ingroup bke
22  *  \since July 2018
23  *  \author Sergey Sharybin
24  */
25
26 #ifndef __BKE_SUBDIV_H__
27 #define __BKE_SUBDIV_H__
28
29 #include "BLI_compiler_compat.h"
30 #include "BLI_sys_types.h"
31
32 struct Mesh;
33 struct MultiresModifierData;
34 struct Object;
35 struct OpenSubdiv_Converter;
36 struct OpenSubdiv_Evaluator;
37 struct OpenSubdiv_TopologyRefiner;
38 struct Subdiv;
39 struct SubdivToMeshSettings;
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         bool is_simple;
61         bool is_adaptive;
62         int level;
63         eSubdivVtxBoundaryInterpolation vtx_boundary_interpolation;
64         eSubdivFVarLinearInterpolation fvar_linear_interpolation;
65 } SubdivSettings;
66
67 /* NOTE: Order of enumerators MUST match order of values in SubdivStats. */
68 typedef enum eSubdivStatsValue {
69         SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME = 0,
70         SUBDIV_STATS_SUBDIV_TO_MESH,
71         SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY,
72         SUBDIV_STATS_EVALUATOR_CREATE,
73         SUBDIV_STATS_EVALUATOR_REFINE,
74         SUBDIV_STATS_SUBDIV_TO_CCG,
75         SUBDIV_STATS_SUBDIV_TO_CCG_ELEMENTS,
76         SUBDIV_STATS_TOPOLOGY_COMPARE,
77
78         NUM_SUBDIV_STATS_VALUES,
79 } eSubdivStatsValue;
80
81 typedef struct SubdivStats {
82         union {
83                 struct {
84                         /* Time spend on creating topology refiner, which includes time
85                          * spend on conversion from Blender data to OpenSubdiv data, and
86                          * time spend on topology orientation on OpenSubdiv C-API side. */
87                         double topology_refiner_creation_time;
88                         /* Total time spent in BKE_subdiv_to_mesh(). */
89                         double subdiv_to_mesh_time;
90                         /* Geometry (MVert and co) creation time during SUBDIV_TYO_MESH. */
91                         double subdiv_to_mesh_geometry_time;
92                         /* Time spent on evaluator creation from topology refiner. */
93                         double evaluator_creation_time;
94                         /* Time spent on evaluator->refine(). */
95                         double evaluator_refine_time;
96                         /* Total time spent on whole CCG creation. */
97                         double subdiv_to_ccg_time;
98                         /* Time spent on CCG elements evaluation/initialization. */
99                         double subdiv_to_ccg_elements_time;
100                         /* Time spent on CCG elements evaluation/initialization. */
101                         double topology_compare_time;
102                 };
103                 double values_[NUM_SUBDIV_STATS_VALUES];
104         };
105
106         /* Per-value timestamp on when corresponding BKE_subdiv_stats_begin() was
107          * called. */
108         double begin_timestamp_[NUM_SUBDIV_STATS_VALUES];
109 } SubdivStats;
110
111 /* Functor which evaluates dispalcement at a given (u, v) of given ptex face. */
112 typedef struct SubdivDisplacement {
113         /* Initialize displacement evaluator.
114          *
115          * Is called right before evaluation is actually needed. This allows to do
116          * some lazy initialization, like allocate evaluator from a main thread but
117          * then do actual evaluation from background job. */
118         void (*initialize)(struct SubdivDisplacement *displacement);
119
120         /* Return displacement which is to be added to the original coordinate.
121          *
122          * NOTE: This function is supposed to return "continuous" displacement for
123          * each pf PTex faces created for special (non-quad) polygon. This means,
124          * if displacement is stored on per-corner manner (like MDisps for multires)
125          * this is up the displacement implementation to average boundaries of the
126          * displacement grids if needed.
127          *
128          * Averaging of displacement for vertices created for over coarse vertices
129          * and edges is done by subdiv code. */
130         void (*eval_displacement)(struct SubdivDisplacement *displacement,
131                                   const int ptex_face_index,
132                                   const float u, const float v,
133                                   const float dPdu[3], const float dPdv[3],
134                                   float r_D[3]);
135
136         /* Free the data, not the evaluator itself. */
137         void (*free)(struct SubdivDisplacement *displacement);
138
139         void *user_data;
140 } SubdivDisplacement;
141
142 /* This structure contains everything needed to construct subdivided surface.
143  * It does not specify storage, memory layout or anything else.
144  * It is possible to create different storages (like, grid based CPU side
145  * buffers, GPU subdivision mesh, CPU side fully qualified mesh) from the same
146  * Subdiv structure. */
147 typedef struct Subdiv {
148         /* Settings this subdivision surface is created for.
149          *
150          * It is read-only after assignment in BKE_subdiv_new_from_FOO().
151          */
152         SubdivSettings settings;
153         /* Topology refiner includes all the glue logic to feed Blender side
154          * topology to OpenSubdiv. It can be shared by both evaluator and GL mesh
155          * drawer. */
156         struct OpenSubdiv_TopologyRefiner *topology_refiner;
157         /* CPU side evaluator. */
158         struct OpenSubdiv_Evaluator *evaluator;
159         /* Optional displacement evaluator. */
160         struct SubdivDisplacement *displacement_evaluator;
161         /* Statistics for debugging. */
162         SubdivStats stats;
163
164         /* Cached values, are not supposed to be accessed directly. */
165         struct {
166                 /* Indexed by base face index, element indicates total number of ptex
167                  *faces created for preceding base faces. */
168                 int *face_ptex_offset;
169         } cache_;
170 } Subdiv;
171
172 /* ========================== CONVERSION HELPERS ============================ */
173
174 /* NOTE: uv_smooth is eSubsurfUVSmooth. */
175 eSubdivFVarLinearInterpolation
176 BKE_subdiv_fvar_interpolation_from_uv_smooth(int uv_smooth);
177
178 /* =============================== STATISTICS =============================== */
179
180 void BKE_subdiv_stats_init(SubdivStats *stats);
181
182 void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value);
183 void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value);
184
185 void BKE_subdiv_stats_reset(SubdivStats *stats, eSubdivStatsValue value);
186
187 void BKE_subdiv_stats_print(const SubdivStats *stats);
188
189 /* ================================ SETTINGS ================================ */
190
191 void BKE_subdiv_settings_validate_for_mesh(SubdivSettings *settings,
192                                            const struct Mesh *mesh);
193
194 bool BKE_subdiv_settings_equal(const SubdivSettings *settings_a,
195                                const SubdivSettings *settings_b);
196
197 /* ============================== CONSTRUCTION ============================== */
198
199 /* Construct new subdivision surface descriptor, from scratch, using given
200  * settings and topology. */
201 Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
202                                       struct OpenSubdiv_Converter *converter);
203 Subdiv *BKE_subdiv_new_from_mesh(const SubdivSettings *settings,
204                                  const struct Mesh *mesh);
205
206 /* Similar to above, but will not re-create descriptor if it was created for the
207  * same settings and topology.
208  * If settings or topology did change, the existing descriptor is freed and a
209  * new one is created from scratch.
210  *
211  * NOTE: It is allowed to pass NULL as an existing subdivision surface
212  * descriptor. This will create enw descriptor without any extra checks.
213  */
214 Subdiv *BKE_subdiv_update_from_converter(
215         Subdiv *subdiv,
216         const SubdivSettings *settings,
217         struct OpenSubdiv_Converter *converter);
218 Subdiv *BKE_subdiv_update_from_mesh(
219         Subdiv *subdiv,
220         const SubdivSettings *settings,
221         const struct Mesh *mesh);
222
223 void BKE_subdiv_free(Subdiv *subdiv);
224
225 /* ============================ DISPLACEMENT API ============================ */
226
227 void BKE_subdiv_displacement_attach_from_multires(
228         Subdiv *subdiv,
229         struct Mesh *mesh,
230         const struct MultiresModifierData *mmd);
231
232 void BKE_subdiv_displacement_detach(Subdiv *subdiv);
233
234 /* ============================ TOPOLOGY HELPERS ============================ */
235
236 int *BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv);
237
238 /* =========================== PTEX FACES AND GRIDS ========================= */
239
240 /* For a given (ptex_u, ptex_v) within a ptex face get corresponding
241  * (grid_u, grid_v) within a grid. */
242 BLI_INLINE void BKE_subdiv_ptex_face_uv_to_grid_uv(
243         const float ptex_u, const float ptex_v,
244         float *r_grid_u, float *r_grid_v);
245
246 /* Onverse of above. */
247 BLI_INLINE void BKE_subdiv_grid_uv_to_ptex_face_uv(
248         const float grid_u, const float grid_v,
249         float *r_ptex_u, float *r_ptex_v);
250
251 /* For a given subdivision level (which is NOT refinement level) get size of
252  * CCG grid (number of grid points on a side).
253  */
254 BLI_INLINE int BKE_subdiv_grid_size_from_level(const int level);
255
256 /* Simplified version of mdisp_rot_face_to_crn, only handles quad and
257  * works in normalized coordinates.
258  *
259  * NOTE: Output coordinates are in ptex coordinates. */
260 BLI_INLINE int BKE_subdiv_rotate_quad_to_corner(
261         const float quad_u, const float quad_v,
262         float *r_corner_u, float *r_corner_v);
263
264 /* Converts (u, v) coordinate from within a grid to a quad coordinate in
265  * normalized ptex coordinates. */
266 BLI_INLINE void BKE_subdiv_rotate_grid_to_quad(
267         const int corner,
268         const float grid_u, const float grid_v,
269         float *r_quad_u, float *r_quad_v);
270
271 #include "intern/subdiv_inline.h"
272
273 #endif  /* __BKE_SUBDIV_H__ */