Blender V4.5
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
8
9#pragma once
10
11#include "BLI_compiler_compat.h"
12
13struct Mesh;
20
21namespace blender::bke::subdiv {
22
24 /* Do not interpolate boundaries. */
26 /* Sharpen edges. */
28 /* sharpen edges and corners, */
30};
31
40
41struct Settings {
42 /* Simple subdivision corresponds to "Simple" option in the interface. When it's enabled, the
43 * subdivided mesh is not "smoothed": new vertices are added uniformly on the existing surface.
44 *
45 * On an OpenSubdiv implementation level this translates to a subdivision scheme:
46 * when is_simple is true OSD_SCHEME_BILINEAR is used, otherwise OSD_SCHEME_CATMARK. */
48
49 /* This refers to an adaptive isolation when creating patches for the subdivided surface.
50 *
51 * When is set to false (aka uniform subdivision) fixed depth of isolation is used, which
52 * allows to iteratively add more subdivisions (uniform subdivision level 2 = uniform subdivision
53 * level 1 + uniform subdivision level 1). Uniform subdivisions will progressively go to a limit
54 * surface.
55 *
56 * Adaptive isolation generates patches at a limit surface (aka as if infinite number of uniform
57 * subdivisions have been applied). This setting allows to have matches normal and tangent space
58 * the same independent of number of subdivisions set in modifier settings. */
60
61 /* Corresponds to Quality option in modifier settings: higher values means the final surface
62 * will be more accurately represented by patches.
63 *
64 * On an OpenSubdiv implementation level this is an isolation level. */
65 int level;
66
68
71};
72
73/* NOTE: Order of enumerators MUST match order of values in SubdivStats. */
86
88 union {
89 struct {
90 /* Time spent on creating topology refiner, which includes time
91 * spend on conversion from Blender data to OpenSubdiv data, and
92 * time spent on topology orientation on OpenSubdiv C-API side. */
94 /* Total time spent in blender::bke::subdiv::subdiv_to_mesh(). */
96 /* Geometry (mesh vertices) creation time during SUBDIV_TO_MESH. */
98 /* Time spent on evaluator creation from topology refiner. */
100 /* Time spent on evaluator->refine(). */
102 /* Total time spent on whole CCG creation. */
104 /* Time spent on CCG elements evaluation/initialization. */
106 /* Time spent on CCG elements evaluation/initialization. */
108 };
110 };
111
112 /* Per-value timestamp on when corresponding stats_begin() was
113 * called. */
115};
116
117/* Functor which evaluates displacement at a given (u, v) of given ptex face. */
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)(Displacement *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) face. 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)(Displacement *displacement,
137 int ptex_face_index,
138 float u,
139 float v,
140 const float dPdu[3],
141 const float dPdv[3],
142 float r_D[3]);
143
144 /* Free the data, not the evaluator itself. */
145 void (*free)(Displacement *displacement);
146
148};
149
150/* This structure contains everything needed to construct subdivided surface.
151 * It does not specify storage, memory layout or anything else.
152 * It is possible to create different storage's (like, grid based CPU side
153 * buffers, GPU subdivision mesh, CPU side fully qualified mesh) from the same
154 * Subdiv structure. */
155struct Subdiv {
156 /* Settings this subdivision surface is created for.
157 *
158 * It is read-only after assignment in BKE_subdiv_new_from_FOO(). */
160 /* Topology refiner includes all the glue logic to feed Blender side
161 * topology to OpenSubdiv. It can be shared by both evaluator and GL mesh
162 * drawer. */
164 /* CPU side evaluator. */
166 /* Optional displacement evaluator. */
168 /* Statistics for debugging. */
170
171 /* Cached values, are not supposed to be accessed directly. */
172 struct {
173 /* Indexed by base face index, element indicates total number of ptex
174 * faces created for preceding base faces. This also stores the final
175 * ptex offset (the total number of PTex faces) at the end of the array
176 * so that algorithms can compute the number of ptex faces for a given
177 * face by computing the delta with the offset for the next face without
178 * using a separate data structure, e.g.:
179 *
180 * const int num_face_ptex_faces = face_ptex_offset[i + 1] - face_ptex_offset[i];
181 *
182 * In total this array has a size of `num base faces + 1`.
183 */
186};
187
188/* --------------------------------------------------------------------
189 * Module.
190 */
191
192/* (De)initialize the entire subdivision surface module. */
193void init();
194void exit();
195
196/* --------------------------------------------------------------------
197 * Conversion helpers.
198 */
199
200/* NOTE: uv_smooth is eSubsurfUVSmooth. */
202
204
205/* --------------------------------------------------------------------
206 * Statistics.
207 */
208
209void stats_init(SubdivStats *stats);
210
211void stats_begin(SubdivStats *stats, StatsValue value);
212void stats_end(SubdivStats *stats, StatsValue value);
213
214void stats_reset(SubdivStats *stats, StatsValue value);
215
216void stats_print(const SubdivStats *stats);
217
218/* --------------------------------------------------------------------
219 * Settings.
220 */
221
222bool settings_equal(const Settings *settings_a, const Settings *settings_b);
223
224/* --------------------------------------------------------------------
225 * Construction.
226 */
227
228/* Construct new subdivision surface descriptor, from scratch, using given
229 * settings and topology. */
230Subdiv *new_from_converter(const Settings *settings, OpenSubdiv_Converter *converter);
231Subdiv *new_from_mesh(const Settings *settings, const Mesh *mesh);
232
233/* Similar to above, but will not re-create descriptor if it was created for the
234 * same settings and topology.
235 * If settings or topology did change, the existing descriptor is freed and a
236 * new one is created from scratch.
237 *
238 * NOTE: It is allowed to pass NULL as an existing subdivision surface
239 * descriptor. This will create a new descriptor without any extra checks.
240 */
241Subdiv *update_from_converter(Subdiv *subdiv,
242 const Settings *settings,
243 OpenSubdiv_Converter *converter);
244Subdiv *update_from_mesh(Subdiv *subdiv, const Settings *settings, const Mesh *mesh);
245
246void free(Subdiv *subdiv);
247
248/* --------------------------------------------------------------------
249 * Displacement API.
250 */
251
253 Mesh *mesh,
254 const MultiresModifierData *mmd);
255
256void displacement_detach(Subdiv *subdiv);
257
258/* --------------------------------------------------------------------
259 * Topology helpers.
260 */
261
262/* For each element in the array, this stores the total number of ptex faces up to that element,
263 * with the total number of ptex faces being the last element in the array. The array is of length
264 * `base face count + 1`. */
265int *face_ptex_offset_get(Subdiv *subdiv);
266
267/* --------------------------------------------------------------------
268 * PTex faces and grids.
269 */
270
271/* For a given (ptex_u, ptex_v) within a ptex face get corresponding
272 * (grid_u, grid_v) within a grid. */
273BLI_INLINE void ptex_face_uv_to_grid_uv(float ptex_u,
274 float ptex_v,
275 float *r_grid_u,
276 float *r_grid_v);
277
278/* Inverse of above. */
279BLI_INLINE void grid_uv_to_ptex_face_uv(float grid_u,
280 float grid_v,
281 float *r_ptex_u,
282 float *r_ptex_v);
283
284/* For a given subdivision level (which is NOT refinement level) get size of
285 * CCG grid (number of grid points on a side).
286 */
287BLI_INLINE int grid_size_from_level(int level);
288
289/* Simplified version of mdisp_rot_face_to_crn, only handles quad and
290 * works in normalized coordinates.
291 *
292 * NOTE: Output coordinates are in ptex coordinates. */
293BLI_INLINE int rotate_quad_to_corner(float quad_u,
294 float quad_v,
295 float *r_corner_u,
296 float *r_corner_v);
297
298/* Converts (u, v) coordinate from within a grid to a quad coordinate in
299 * normalized ptex coordinates. */
301 int corner, float grid_u, float grid_v, float *r_quad_u, float *r_quad_v);
302
303/* Convert Blender edge crease value to OpenSubdiv sharpness. */
304BLI_INLINE float crease_to_sharpness(float crease);
305BLI_INLINE float sharpness_to_crease(float sharpness);
306
307} // namespace blender::bke::subdiv
308
309#include "intern/subdiv_inline.hh" // IWYU pragma: export
#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:190
BLI_INLINE float crease_to_sharpness(float crease)
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:35
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_BOUNDARIES
Definition BKE_subdiv.hh:37
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE
Definition BKE_subdiv.hh:33
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY
Definition BKE_subdiv.hh:34
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_JUNCTIONS_AND_CONCAVE
Definition BKE_subdiv.hh:36
Subdiv * new_from_mesh(const Settings *settings, const Mesh *mesh)
Definition subdiv.cc:131
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 float sharpness_to_crease(float sharpness)
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:47
void stats_reset(SubdivStats *stats, StatsValue value)
Subdiv * update_from_converter(Subdiv *subdiv, const Settings *settings, OpenSubdiv_Converter *converter)
Definition subdiv.cc:145
Subdiv * new_from_converter(const Settings *settings, OpenSubdiv_Converter *converter)
Definition subdiv.cc:98
void stats_begin(SubdivStats *stats, StatsValue value)
int * face_ptex_offset_get(Subdiv *subdiv)
Definition subdiv.cc:217
void stats_end(SubdivStats *stats, StatsValue value)
VtxBoundaryInterpolation vtx_boundary_interpolation_from_subsurf(int boundary_smooth)
Definition subdiv.cc:67
void stats_print(const SubdivStats *stats)
@ SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME
Definition BKE_subdiv.hh:75
Subdiv * update_from_mesh(Subdiv *subdiv, const Settings *settings, const Mesh *mesh)
Definition subdiv.cc:179
bool settings_equal(const Settings *settings_a, const Settings *settings_b)
Definition subdiv.cc:83
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:69
FVarLinearInterpolation fvar_linear_interpolation
Definition BKE_subdiv.hh:70
double values_[NUM_SUBDIV_STATS_VALUES]
double begin_timestamp_[NUM_SUBDIV_STATS_VALUES]
struct blender::bke::subdiv::Subdiv::@141333164245306152254011066224135037245225347145 cache_
Displacement * displacement_evaluator
OpenSubdiv_Evaluator * evaluator
blender::opensubdiv::TopologyRefinerImpl * topology_refiner