Merge branch 'blender2.7'
[blender.git] / source / blender / blenkernel / BKE_subdiv.h
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2018 by Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Sergey Sharybin.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file BKE_subdiv.h
27  *  \ingroup bke
28  *  \since July 2018
29  *  \author Sergey Sharybin
30  */
31
32 #ifndef __BKE_SUBDIV_H__
33 #define __BKE_SUBDIV_H__
34
35 #include "BLI_compiler_compat.h"
36 #include "BLI_sys_types.h"
37
38 struct Mesh;
39 struct MultiresModifierData;
40 struct Object;
41 struct OpenSubdiv_Converter;
42 struct OpenSubdiv_Evaluator;
43 struct OpenSubdiv_TopologyRefiner;
44 struct Subdiv;
45 struct SubdivToMeshSettings;
46
47 typedef enum eSubdivVtxBoundaryInterpolation {
48   /* Do not interpolate boundaries. */
49   SUBDIV_VTX_BOUNDARY_NONE,
50   /* Sharpen edges. */
51   SUBDIV_VTX_BOUNDARY_EDGE_ONLY,
52   /* sharpen edges and corners, */
53   SUBDIV_VTX_BOUNDARY_EDGE_AND_CORNER,
54 } eSubdivVtxBoundaryInterpolation;
55
56 typedef enum eSubdivFVarLinearInterpolation {
57         SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE,
58         SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY,
59         SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_AND_JUNCTIONS,
60         SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_JUNCTIONS_AND_CONCAVE,
61         SUBDIV_FVAR_LINEAR_INTERPOLATION_BOUNDARIES,
62         SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL,
63 } eSubdivFVarLinearInterpolation;
64
65 typedef struct SubdivSettings {
66         bool is_simple;
67         bool is_adaptive;
68         int level;
69         eSubdivVtxBoundaryInterpolation vtx_boundary_interpolation;
70         eSubdivFVarLinearInterpolation fvar_linear_interpolation;
71 } SubdivSettings;
72
73 /* NOTE: Order of enumerators MUST match order of values in SubdivStats. */
74 typedef enum eSubdivStatsValue {
75         SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME = 0,
76         SUBDIV_STATS_SUBDIV_TO_MESH,
77         SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY,
78         SUBDIV_STATS_EVALUATOR_CREATE,
79         SUBDIV_STATS_EVALUATOR_REFINE,
80         SUBDIV_STATS_SUBDIV_TO_CCG,
81         SUBDIV_STATS_SUBDIV_TO_CCG_ELEMENTS,
82         SUBDIV_STATS_TOPOLOGY_COMPARE,
83
84         NUM_SUBDIV_STATS_VALUES,
85 } eSubdivStatsValue;
86
87 typedef struct SubdivStats {
88         union {
89                 struct {
90                         /* Time spend on creating topology refiner, which includes time
91                          * spend on conversion from Blender data to OpenSubdiv data, and
92                          * time spend on topology orientation on OpenSubdiv C-API side. */
93                         double topology_refiner_creation_time;
94                         /* Total time spent in BKE_subdiv_to_mesh(). */
95                         double subdiv_to_mesh_time;
96                         /* Geometry (MVert and co) creation time during SUBDIV_TYO_MESH. */
97                         double subdiv_to_mesh_geometry_time;
98                         /* Time spent on evaluator creation from topology refiner. */
99                         double evaluator_creation_time;
100                         /* Time spent on evaluator->refine(). */
101                         double evaluator_refine_time;
102                         /* Total time spent on whole CCG creation. */
103                         double subdiv_to_ccg_time;
104                         /* Time spent on CCG elements evaluation/initialization. */
105                         double subdiv_to_ccg_elements_time;
106                         /* Time spent on CCG elements evaluation/initialization. */
107                         double topology_compare_time;
108                 };
109                 double values_[NUM_SUBDIV_STATS_VALUES];
110         };
111
112         /* Per-value timestamp on when corresponding BKE_subdiv_stats_begin() was
113          * called. */
114         double begin_timestamp_[NUM_SUBDIV_STATS_VALUES];
115 } SubdivStats;
116
117 /* Functor which evaluates dispalcement at a given (u, v) of given ptex face. */
118 typedef struct SubdivDisplacement {
119         /* Initialize displacement evaluator.
120          *
121          * Is called right before evaluation is actually needed. This allows to do
122          * some lazy initialization, like allocate evaluator from a main thread but
123          * then do actual evaluation from background job. */
124         void (*initialize)(struct SubdivDisplacement *displacement);
125
126         /* Return displacement which is to be added to the original coordinate.
127          *
128          * NOTE: This function is supposed to return "continuous" displacement for
129          * each pf PTex faces created for special (non-quad) polygon. This means,
130          * if displacement is stored on per-corner manner (like MDisps for multires)
131          * this is up the displacement implementation to average boundaries of the
132          * displacement grids if needed.
133          *
134          * Averaging of displacement for vertices created for over coarse vertices
135          * and edges is done by subdiv code. */
136         void (*eval_displacement)(struct SubdivDisplacement *displacement,
137                                   const int ptex_face_index,
138                                   const float u, const float v,
139                                   const float dPdu[3], const float dPdv[3],
140                                   float r_D[3]);
141
142         /* Free the data, not the evaluator itself. */
143         void (*free)(struct SubdivDisplacement *displacement);
144
145         void *user_data;
146 } SubdivDisplacement;
147
148 /* This structure contains everything needed to construct subdivided surface.
149  * It does not specify storage, memory layout or anything else.
150  * It is possible to create different storages (like, grid based CPU side
151  * buffers, GPU subdivision mesh, CPU side fully qualified mesh) from the same
152  * Subdiv structure. */
153 typedef struct Subdiv {
154         /* Settings this subdivision surface is created for.
155          *
156          * It is read-only after assignment in BKE_subdiv_new_from_FOO().
157          */
158         SubdivSettings settings;
159         /* Topology refiner includes all the glue logic to feed Blender side
160          * topology to OpenSubdiv. It can be shared by both evaluator and GL mesh
161          * drawer. */
162         struct OpenSubdiv_TopologyRefiner *topology_refiner;
163         /* CPU side evaluator. */
164         struct OpenSubdiv_Evaluator *evaluator;
165         /* Optional displacement evaluator. */
166         struct SubdivDisplacement *displacement_evaluator;
167         /* Statistics for debugging. */
168         SubdivStats stats;
169
170         /* Cached values, are not supposed to be accessed directly. */
171         struct {
172                 /* Indexed by base face index, element indicates total number of ptex
173                  *faces created for preceding base faces. */
174                 int *face_ptex_offset;
175         } cache_;
176 } Subdiv;
177
178 /* ========================== CONVERSION HELPERS ============================ */
179
180 /* NOTE: uv_smooth is eSubsurfUVSmooth. */
181 eSubdivFVarLinearInterpolation
182 BKE_subdiv_fvar_interpolation_from_uv_smooth(int uv_smooth);
183
184 /* =============================== STATISTICS =============================== */
185
186 void BKE_subdiv_stats_init(SubdivStats *stats);
187
188 void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value);
189 void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value);
190
191 void BKE_subdiv_stats_reset(SubdivStats *stats, eSubdivStatsValue value);
192
193 void BKE_subdiv_stats_print(const SubdivStats *stats);
194
195 /* ================================ SETTINGS ================================ */
196
197 bool BKE_subdiv_settings_equal(const SubdivSettings *settings_a,
198                                const SubdivSettings *settings_b);
199
200 /* ============================== CONSTRUCTION ============================== */
201
202 /* Construct new subdivision surface descriptor, from scratch, using given
203  * settings and topology. */
204 Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
205                                       struct OpenSubdiv_Converter *converter);
206 Subdiv *BKE_subdiv_new_from_mesh(const SubdivSettings *settings,
207                                  const struct Mesh *mesh);
208
209 /* Similar to above, but will not re-create descriptor if it was created for the
210  * same settings and topology.
211  * If settings or topology did change, the existing descriptor is freed and a
212  * new one is created from scratch.
213  *
214  * NOTE: It is allowed to pass NULL as an existing subdivision surface
215  * descriptor. This will create enw descriptor without any extra checks.
216  */
217 Subdiv *BKE_subdiv_update_from_converter(
218         Subdiv *subdiv,
219         const SubdivSettings *settings,
220         struct OpenSubdiv_Converter *converter);
221 Subdiv *BKE_subdiv_update_from_mesh(
222         Subdiv *subdiv,
223         const SubdivSettings *settings,
224         const struct Mesh *mesh);
225
226 void BKE_subdiv_free(Subdiv *subdiv);
227
228 /* ============================ DISPLACEMENT API ============================ */
229
230 void BKE_subdiv_displacement_attach_from_multires(
231         Subdiv *subdiv,
232         struct Mesh *mesh,
233         const struct MultiresModifierData *mmd);
234
235 void BKE_subdiv_displacement_detach(Subdiv *subdiv);
236
237 /* ============================ TOPOLOGY HELPERS ============================ */
238
239 int *BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv);
240
241 /* =========================== PTEX FACES AND GRIDS ========================= */
242
243 /* For a given (ptex_u, ptex_v) within a ptex face get corresponding
244  * (grid_u, grid_v) within a grid. */
245 BLI_INLINE void BKE_subdiv_ptex_face_uv_to_grid_uv(
246         const float ptex_u, const float ptex_v,
247         float *r_grid_u, float *r_grid_v);
248
249 /* For a given subdivision level (which is NOT refinement level) get size of
250  * CCG grid (number of grid points on a side).
251  */
252 BLI_INLINE int BKE_subdiv_grid_size_from_level(const int level);
253
254 /* Simplified version of mdisp_rot_face_to_crn, only handles quad and
255  * works in normalized coordinates.
256  *
257  * NOTE: Output coordinates are in ptex coordinates. */
258 BLI_INLINE int BKE_subdiv_rotate_quad_to_corner(
259         const float u, const float v,
260         float *r_u, float *r_v);
261
262 #include "intern/subdiv_inline.h"
263
264 #endif  /* __BKE_SUBDIV_H__ */