Blender V4.3
BKE_subdiv.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2018 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#pragma once
10
11#include "BLI_compiler_compat.h"
12#include "BLI_sys_types.h"
13
14struct Mesh;
21
22namespace blender::bke::subdiv {
23
25 /* Do not interpolate boundaries. */
27 /* Sharpen edges. */
29 /* sharpen edges and corners, */
31};
32
41
42struct Settings {
43 /* Simple subdivision corresponds to "Simple" option in the interface. When it's enabled, the
44 * subdivided mesh is not "smoothed": new vertices are added uniformly on the existing surface.
45 *
46 * On an OpenSubdiv implementation level this translates to a subdivision scheme:
47 * when is_simple is true OSD_SCHEME_BILINEAR is used, otherwise OSD_SCHEME_CATMARK. */
49
50 /* This refers to an adaptive isolation when creating patches for the subdivided surface.
51 *
52 * When is set to false (aka uniform subdivision) fixed depth of isolation is used, which
53 * allows to iteratively add more subdivisions (uniform subdivision level 2 = uniform subdivision
54 * level 1 + uniform subdivision level 1). Uniform subdivisions will progressively go to a limit
55 * surface.
56 *
57 * Adaptive isolation generates patches at a limit surface (aka as if infinite number of uniform
58 * subdivisions have been applied). This setting allows to have matches normal and tangent space
59 * the same independent of number of subdivisions set in modifier settings. */
61
62 /* Corresponds to Quality option in modifier settings: higher values means the final surface
63 * will be more accurately represented by patches.
64 *
65 * On an OpenSubdiv implementation level this is an isolation level. */
66 int level;
67
69
72};
73
74/* NOTE: Order of enumerators MUST match order of values in SubdivStats. */
87
89 union {
90 struct {
91 /* Time spent on creating topology refiner, which includes time
92 * spend on conversion from Blender data to OpenSubdiv data, and
93 * time spent on topology orientation on OpenSubdiv C-API side. */
95 /* Total time spent in blender::bke::subdiv::subdiv_to_mesh(). */
97 /* Geometry (mesh vertices) creation time during SUBDIV_TYO_MESH. */
99 /* Time spent on evaluator creation from topology refiner. */
101 /* Time spent on evaluator->refine(). */
103 /* Total time spent on whole CCG creation. */
105 /* Time spent on CCG elements evaluation/initialization. */
107 /* Time spent on CCG elements evaluation/initialization. */
109 };
111 };
112
113 /* Per-value timestamp on when corresponding stats_begin() was
114 * called. */
116};
117
118/* Functor which evaluates displacement at a given (u, v) of given ptex face. */
120 /* Initialize displacement evaluator.
121 *
122 * Is called right before evaluation is actually needed. This allows to do
123 * some lazy initialization, like allocate evaluator from a main thread but
124 * then do actual evaluation from background job. */
125 void (*initialize)(Displacement *displacement);
126
127 /* Return displacement which is to be added to the original coordinate.
128 *
129 * NOTE: This function is supposed to return "continuous" displacement for
130 * each pf PTex faces created for special (non-quad) face. This means,
131 * if displacement is stored on per-corner manner (like MDisps for multires)
132 * this is up the displacement implementation to average boundaries of the
133 * displacement grids if needed.
134 *
135 * Averaging of displacement for vertices created for over coarse vertices
136 * and edges is done by subdiv code. */
137 void (*eval_displacement)(Displacement *displacement,
138 int ptex_face_index,
139 float u,
140 float v,
141 const float dPdu[3],
142 const float dPdv[3],
143 float r_D[3]);
144
145 /* Free the data, not the evaluator itself. */
146 void (*free)(Displacement *displacement);
147
149};
150
151/* This structure contains everything needed to construct subdivided surface.
152 * It does not specify storage, memory layout or anything else.
153 * It is possible to create different storage's (like, grid based CPU side
154 * buffers, GPU subdivision mesh, CPU side fully qualified mesh) from the same
155 * Subdiv structure. */
156struct Subdiv {
157 /* Settings this subdivision surface is created for.
158 *
159 * It is read-only after assignment in BKE_subdiv_new_from_FOO(). */
161 /* Topology refiner includes all the glue logic to feed Blender side
162 * topology to OpenSubdiv. It can be shared by both evaluator and GL mesh
163 * drawer. */
165 /* CPU side evaluator. */
167 /* Optional displacement evaluator. */
169 /* Statistics for debugging. */
171
172 /* Cached values, are not supposed to be accessed directly. */
173 struct {
174 /* Indexed by base face index, element indicates total number of ptex
175 * faces created for preceding base faces. This also stores the final
176 * ptex offset (the total number of PTex faces) at the end of the array
177 * so that algorithms can compute the number of ptex faces for a given
178 * face by computing the delta with the offset for the next face without
179 * using a separate data structure, e.g.:
180 *
181 * const int num_face_ptex_faces = face_ptex_offset[i + 1] - face_ptex_offset[i];
182 *
183 * In total this array has a size of `num base faces + 1`.
184 */
187};
188
189/* --------------------------------------------------------------------
190 * Module.
191 */
192
193/* (De)initialize the entire subdivision surface module. */
194void init();
195void exit();
196
197/* --------------------------------------------------------------------
198 * Conversion helpers.
199 */
200
201/* NOTE: uv_smooth is eSubsurfUVSmooth. */
203
205
206/* --------------------------------------------------------------------
207 * Statistics.
208 */
209
210void stats_init(SubdivStats *stats);
211
212void stats_begin(SubdivStats *stats, StatsValue value);
213void stats_end(SubdivStats *stats, StatsValue value);
214
215void stats_reset(SubdivStats *stats, StatsValue value);
216
217void stats_print(const SubdivStats *stats);
218
219/* --------------------------------------------------------------------
220 * Settings.
221 */
222
223bool settings_equal(const Settings *settings_a, const Settings *settings_b);
224
225/* --------------------------------------------------------------------
226 * Construction.
227 */
228
229/* Construct new subdivision surface descriptor, from scratch, using given
230 * settings and topology. */
231Subdiv *new_from_converter(const Settings *settings, OpenSubdiv_Converter *converter);
232Subdiv *new_from_mesh(const Settings *settings, const Mesh *mesh);
233
234/* Similar to above, but will not re-create descriptor if it was created for the
235 * same settings and topology.
236 * If settings or topology did change, the existing descriptor is freed and a
237 * new one is created from scratch.
238 *
239 * NOTE: It is allowed to pass NULL as an existing subdivision surface
240 * descriptor. This will create a new descriptor without any extra checks.
241 */
242Subdiv *update_from_converter(Subdiv *subdiv,
243 const Settings *settings,
244 OpenSubdiv_Converter *converter);
245Subdiv *update_from_mesh(Subdiv *subdiv, const Settings *settings, const Mesh *mesh);
246
247void free(Subdiv *subdiv);
248
249/* --------------------------------------------------------------------
250 * Displacement API.
251 */
252
253void displacement_attach_from_multires(Subdiv *subdiv,
254 Mesh *mesh,
255 const MultiresModifierData *mmd);
256
257void displacement_detach(Subdiv *subdiv);
258
259/* --------------------------------------------------------------------
260 * Topology helpers.
261 */
262
263/* For each element in the array, this stores the total number of ptex faces up to that element,
264 * with the total number of ptex faces being the last element in the array. The array is of length
265 * `base face count + 1`. */
266int *face_ptex_offset_get(Subdiv *subdiv);
267
268/* --------------------------------------------------------------------
269 * PTex faces and grids.
270 */
271
272/* For a given (ptex_u, ptex_v) within a ptex face get corresponding
273 * (grid_u, grid_v) within a grid. */
274BLI_INLINE void ptex_face_uv_to_grid_uv(float ptex_u,
275 float ptex_v,
276 float *r_grid_u,
277 float *r_grid_v);
278
279/* Inverse of above. */
280BLI_INLINE void grid_uv_to_ptex_face_uv(float grid_u,
281 float grid_v,
282 float *r_ptex_u,
283 float *r_ptex_v);
284
285/* For a given subdivision level (which is NOT refinement level) get size of
286 * CCG grid (number of grid points on a side).
287 */
288BLI_INLINE int grid_size_from_level(int level);
289
290/* Simplified version of mdisp_rot_face_to_crn, only handles quad and
291 * works in normalized coordinates.
292 *
293 * NOTE: Output coordinates are in ptex coordinates. */
294BLI_INLINE int rotate_quad_to_corner(float quad_u,
295 float quad_v,
296 float *r_corner_u,
297 float *r_corner_v);
298
299/* Converts (u, v) coordinate from within a grid to a quad coordinate in
300 * normalized ptex coordinates. */
302 int corner, float grid_u, float grid_v, float *r_quad_u, float *r_quad_v);
303
304/* Convert Blender edge crease value to OpenSubdiv sharpness. */
305BLI_INLINE float crease_to_sharpness(float edge_crease);
306
307} // namespace blender::bke::subdiv
308
#define BLI_INLINE
ATTR_WARN_UNUSED_RESULT const BMVert * v
void displacement_attach_from_multires(Subdiv *subdiv, Mesh *mesh, const MultiresModifierData *mmd)
void free(Subdiv *subdiv)
Definition subdiv.cc:192
BLI_INLINE void rotate_grid_to_quad(int corner, float grid_u, float grid_v, float *r_quad_u, float *r_quad_v)
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_AND_JUNCTIONS
Definition BKE_subdiv.hh:36
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_BOUNDARIES
Definition BKE_subdiv.hh:38
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE
Definition BKE_subdiv.hh:34
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY
Definition BKE_subdiv.hh:35
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_JUNCTIONS_AND_CONCAVE
Definition BKE_subdiv.hh:37
Subdiv * new_from_mesh(const Settings *settings, const Mesh *mesh)
Definition subdiv.cc:133
BLI_INLINE void grid_uv_to_ptex_face_uv(float grid_u, float grid_v, float *r_ptex_u, float *r_ptex_v)
void stats_init(SubdivStats *stats)
void displacement_detach(Subdiv *subdiv)
BLI_INLINE void ptex_face_uv_to_grid_uv(float ptex_u, float ptex_v, float *r_grid_u, float *r_grid_v)
BLI_INLINE int grid_size_from_level(int level)
BLI_INLINE int rotate_quad_to_corner(float quad_u, float quad_v, float *r_corner_u, float *r_corner_v)
FVarLinearInterpolation fvar_interpolation_from_uv_smooth(int uv_smooth)
Definition subdiv.cc:49
void stats_reset(SubdivStats *stats, StatsValue value)
Subdiv * update_from_converter(Subdiv *subdiv, const Settings *settings, OpenSubdiv_Converter *converter)
Definition subdiv.cc:147
BLI_INLINE float crease_to_sharpness(float edge_crease)
Subdiv * new_from_converter(const Settings *settings, OpenSubdiv_Converter *converter)
Definition subdiv.cc:100
void stats_begin(SubdivStats *stats, StatsValue value)
int * face_ptex_offset_get(Subdiv *subdiv)
Definition subdiv.cc:219
void stats_end(SubdivStats *stats, StatsValue value)
VtxBoundaryInterpolation vtx_boundary_interpolation_from_subsurf(int boundary_smooth)
Definition subdiv.cc:69
void stats_print(const SubdivStats *stats)
@ SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME
Definition BKE_subdiv.hh:76
Subdiv * update_from_mesh(Subdiv *subdiv, const Settings *settings, const Mesh *mesh)
Definition subdiv.cc:181
bool settings_equal(const Settings *settings_a, const Settings *settings_b)
Definition subdiv.cc:85
void(* free)(Displacement *displacement)
void(* eval_displacement)(Displacement *displacement, int ptex_face_index, float u, float v, const float dPdu[3], const float dPdv[3], float r_D[3])
void(* initialize)(Displacement *displacement)
VtxBoundaryInterpolation vtx_boundary_interpolation
Definition BKE_subdiv.hh:70
FVarLinearInterpolation fvar_linear_interpolation
Definition BKE_subdiv.hh:71
double values_[NUM_SUBDIV_STATS_VALUES]
double begin_timestamp_[NUM_SUBDIV_STATS_VALUES]
Displacement * displacement_evaluator
struct blender::bke::subdiv::Subdiv::@63 cache_
OpenSubdiv_Evaluator * evaluator
blender::opensubdiv::TopologyRefinerImpl * topology_refiner