Blender  V3.3
subdiv.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2018 Blender Foundation. All rights reserved. */
3 
8 #include "BKE_subdiv.h"
9 
10 #include "DNA_mesh_types.h"
11 #include "DNA_meshdata_types.h"
12 #include "DNA_modifier_types.h"
13 
14 #include "BLI_utildefines.h"
15 
16 #include "BKE_modifier.h"
17 #include "BKE_subdiv_modifier.h"
18 
19 #include "MEM_guardedalloc.h"
20 
21 #include "subdiv_converter.h"
22 
23 #include "opensubdiv_capi.h"
27 
28 /* --------------------------------------------------------------------
29  * Module.
30  */
31 
33 {
35 }
36 
38 {
40 }
41 
42 /* --------------------------------------------------------------------
43  * Conversion helpers.
44  */
45 
47 {
48  switch (uv_smooth) {
61  }
62  BLI_assert_msg(0, "Unknown uv smooth flag");
64 }
65 
67  int boundary_smooth)
68 {
69  switch (boundary_smooth) {
74  }
75  BLI_assert_msg(0, "Unknown boundary smooth flag");
77 }
78 
79 /* --------------------------------------------------------------------
80  * Settings.
81  */
82 
83 bool BKE_subdiv_settings_equal(const SubdivSettings *settings_a, const SubdivSettings *settings_b)
84 {
85  return (settings_a->is_simple == settings_b->is_simple &&
86  settings_a->is_adaptive == settings_b->is_adaptive &&
87  settings_a->level == settings_b->level &&
88  settings_a->vtx_boundary_interpolation == settings_b->vtx_boundary_interpolation &&
89  settings_a->fvar_linear_interpolation == settings_b->fvar_linear_interpolation);
90 }
91 
92 /* --------------------------------------------------------------------
93  * Construction.
94  */
95 
96 /* Creation from scratch. */
97 
99  struct OpenSubdiv_Converter *converter)
100 {
101  SubdivStats stats;
102  BKE_subdiv_stats_init(&stats);
104  OpenSubdiv_TopologyRefinerSettings topology_refiner_settings;
105  topology_refiner_settings.level = settings->level;
106  topology_refiner_settings.is_adaptive = settings->is_adaptive;
107  struct OpenSubdiv_TopologyRefiner *osd_topology_refiner = NULL;
108  if (converter->getNumVertices(converter) != 0) {
109  osd_topology_refiner = openSubdiv_createTopologyRefinerFromConverter(
110  converter, &topology_refiner_settings);
111  }
112  else {
113  /* TODO(sergey): Check whether original geometry had any vertices.
114  * The thing here is: OpenSubdiv can only deal with faces, but our
115  * side of subdiv also deals with loose vertices and edges. */
116  }
117  Subdiv *subdiv = MEM_callocN(sizeof(Subdiv), "subdiv from converter");
118  subdiv->settings = *settings;
119  subdiv->topology_refiner = osd_topology_refiner;
120  subdiv->evaluator = NULL;
121  subdiv->displacement_evaluator = NULL;
123  subdiv->stats = stats;
124  return subdiv;
125 }
126 
128 {
129  if (mesh->totvert == 0) {
130  return NULL;
131  }
132  OpenSubdiv_Converter converter;
133  BKE_subdiv_converter_init_for_mesh(&converter, settings, mesh);
134  Subdiv *subdiv = BKE_subdiv_new_from_converter(settings, &converter);
135  BKE_subdiv_converter_free(&converter);
136  return subdiv;
137 }
138 
139 /* Creation with cached-aware semantic. */
140 
142  const SubdivSettings *settings,
143  OpenSubdiv_Converter *converter)
144 {
145  /* Check if the existing descriptor can be re-used. */
146  bool can_reuse_subdiv = true;
147  if (subdiv != NULL && subdiv->topology_refiner != NULL) {
148  if (!BKE_subdiv_settings_equal(&subdiv->settings, settings)) {
149  can_reuse_subdiv = false;
150  }
151  else {
154  converter);
156  }
157  }
158  else {
159  can_reuse_subdiv = false;
160  }
161  if (can_reuse_subdiv) {
162  return subdiv;
163  }
164  /* Create new subdiv. */
165  if (subdiv != NULL) {
166  BKE_subdiv_free(subdiv);
167  }
168  return BKE_subdiv_new_from_converter(settings, converter);
169 }
170 
172  const SubdivSettings *settings,
173  const Mesh *mesh)
174 {
175  OpenSubdiv_Converter converter;
176  BKE_subdiv_converter_init_for_mesh(&converter, settings, mesh);
177  subdiv = BKE_subdiv_update_from_converter(subdiv, settings, &converter);
178  BKE_subdiv_converter_free(&converter);
179  return subdiv;
180 }
181 
182 /* Memory release. */
183 
184 void BKE_subdiv_free(Subdiv *subdiv)
185 {
186  if (subdiv->evaluator != NULL) {
187  const eOpenSubdivEvaluator evaluator_type = subdiv->evaluator->type;
188  if (evaluator_type != OPENSUBDIV_EVALUATOR_CPU) {
189  /* Let the draw code do the freeing, to ensure that the OpenGL context is valid. */
191  return;
192  }
194  }
195  if (subdiv->topology_refiner != NULL) {
197  }
199  if (subdiv->cache_.face_ptex_offset != NULL) {
201  }
202  MEM_freeN(subdiv);
203 }
204 
205 /* --------------------------------------------------------------------
206  * Topology helpers.
207  */
208 
210 {
211  if (subdiv->cache_.face_ptex_offset != NULL) {
212  return subdiv->cache_.face_ptex_offset;
213  }
214  OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
215  if (topology_refiner == NULL) {
216  return NULL;
217  }
218  const int num_coarse_faces = topology_refiner->getNumFaces(topology_refiner);
220  num_coarse_faces + 1, sizeof(int), "subdiv face_ptex_offset");
221  int ptex_offset = 0;
222  for (int face_index = 0; face_index < num_coarse_faces; face_index++) {
223  const int num_ptex_faces = topology_refiner->getNumFacePtexFaces(topology_refiner, face_index);
224  subdiv->cache_.face_ptex_offset[face_index] = ptex_offset;
225  ptex_offset += num_ptex_faces;
226  }
227  subdiv->cache_.face_ptex_offset[num_coarse_faces] = ptex_offset;
228  return subdiv->cache_.face_ptex_offset;
229 }
void BKE_subdiv_stats_init(SubdivStats *stats)
Definition: subdiv_stats.c:14
@ SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME
Definition: BKE_subdiv.h:76
@ SUBDIV_STATS_TOPOLOGY_COMPARE
Definition: BKE_subdiv.h:83
void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value)
Definition: subdiv_stats.c:31
void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value)
Definition: subdiv_stats.c:26
eSubdivFVarLinearInterpolation
Definition: BKE_subdiv.h:33
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL
Definition: BKE_subdiv.h:39
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY
Definition: BKE_subdiv.h:35
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_BOUNDARIES
Definition: BKE_subdiv.h:38
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE
Definition: BKE_subdiv.h:34
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_AND_JUNCTIONS
Definition: BKE_subdiv.h:36
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_JUNCTIONS_AND_CONCAVE
Definition: BKE_subdiv.h:37
eSubdivVtxBoundaryInterpolation
Definition: BKE_subdiv.h:24
@ SUBDIV_VTX_BOUNDARY_EDGE_AND_CORNER
Definition: BKE_subdiv.h:30
@ SUBDIV_VTX_BOUNDARY_EDGE_ONLY
Definition: BKE_subdiv.h:28
void BKE_subdiv_displacement_detach(Subdiv *subdiv)
void(* BKE_subsurf_modifier_free_gpu_cache_cb)(struct Subdiv *subdiv)
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
@ SUBSURF_BOUNDARY_SMOOTH_ALL
@ SUBSURF_BOUNDARY_SMOOTH_PRESERVE_CORNERS
@ SUBSURF_UV_SMOOTH_PRESERVE_CORNERS_AND_JUNCTIONS
@ SUBSURF_UV_SMOOTH_ALL
@ SUBSURF_UV_SMOOTH_PRESERVE_CORNERS
@ SUBSURF_UV_SMOOTH_NONE
@ SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES
@ SUBSURF_UV_SMOOTH_PRESERVE_CORNERS_JUNCTIONS_AND_CONCAVE
Read Guarded memory(de)allocation.
void openSubdiv_deleteEvaluator(OpenSubdiv_Evaluator *evaluator)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void openSubdiv_cleanup()
void openSubdiv_init()
eOpenSubdivEvaluator
@ OPENSUBDIV_EVALUATOR_CPU
int totvert
int(* getNumVertices)(const struct OpenSubdiv_Converter *converter)
int(* getNumFaces)(const struct OpenSubdiv_TopologyRefiner *topology_refiner)
int(* getNumFacePtexFaces)(const struct OpenSubdiv_TopologyRefiner *topology_refiner, const int face_index)
bool is_adaptive
Definition: BKE_subdiv.h:60
eSubdivFVarLinearInterpolation fvar_linear_interpolation
Definition: BKE_subdiv.h:71
eSubdivVtxBoundaryInterpolation vtx_boundary_interpolation
Definition: BKE_subdiv.h:70
SubdivSettings settings
Definition: BKE_subdiv.h:160
struct Subdiv::@68 cache_
SubdivStats stats
Definition: BKE_subdiv.h:170
struct SubdivDisplacement * displacement_evaluator
Definition: BKE_subdiv.h:168
struct OpenSubdiv_TopologyRefiner * topology_refiner
Definition: BKE_subdiv.h:164
struct OpenSubdiv_Evaluator * evaluator
Definition: BKE_subdiv.h:166
int * face_ptex_offset
Definition: BKE_subdiv.h:185
void BKE_subdiv_exit()
Definition: subdiv.c:37
bool BKE_subdiv_settings_equal(const SubdivSettings *settings_a, const SubdivSettings *settings_b)
Definition: subdiv.c:83
Subdiv * BKE_subdiv_update_from_converter(Subdiv *subdiv, const SubdivSettings *settings, OpenSubdiv_Converter *converter)
Definition: subdiv.c:141
eSubdivVtxBoundaryInterpolation BKE_subdiv_vtx_boundary_interpolation_from_subsurf(int boundary_smooth)
Definition: subdiv.c:66
void BKE_subdiv_free(Subdiv *subdiv)
Definition: subdiv.c:184
int * BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv)
Definition: subdiv.c:209
Subdiv * BKE_subdiv_update_from_mesh(Subdiv *subdiv, const SubdivSettings *settings, const Mesh *mesh)
Definition: subdiv.c:171
eSubdivFVarLinearInterpolation BKE_subdiv_fvar_interpolation_from_uv_smooth(int uv_smooth)
Definition: subdiv.c:46
Subdiv * BKE_subdiv_new_from_mesh(const SubdivSettings *settings, const Mesh *mesh)
Definition: subdiv.c:127
Subdiv * BKE_subdiv_new_from_converter(const SubdivSettings *settings, struct OpenSubdiv_Converter *converter)
Definition: subdiv.c:98
void BKE_subdiv_init()
Definition: subdiv.c:32
void BKE_subdiv_converter_free(struct OpenSubdiv_Converter *converter)
void BKE_subdiv_converter_init_for_mesh(struct OpenSubdiv_Converter *converter, const struct SubdivSettings *settings, const struct Mesh *mesh)
void openSubdiv_deleteTopologyRefiner(OpenSubdiv_TopologyRefiner *topology_refiner)
bool openSubdiv_topologyRefinerCompareWithConverter(const OpenSubdiv_TopologyRefiner *topology_refiner, const OpenSubdiv_Converter *converter)
OpenSubdiv_TopologyRefiner * openSubdiv_createTopologyRefinerFromConverter(OpenSubdiv_Converter *converter, const OpenSubdiv_TopologyRefinerSettings *settings)