Blender V4.3
subdiv.cc
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#include "BKE_subdiv.hh"
10
11#include "DNA_mesh_types.h"
12#include "DNA_modifier_types.h"
13
14#include "BLI_utildefines.h"
15
17
18#include "MEM_guardedalloc.h"
19
20#include "subdiv_converter.hh"
21
22#include "opensubdiv_capi.hh"
25#ifdef WITH_OPENSUBDIV
27#endif
28
29namespace blender::bke::subdiv {
30
31/* --------------------------------------------------------------------
32 * Module.
33 */
34
35void init()
36{
38}
39
40void exit()
41{
43}
44
45/* --------------------------------------------------------------------
46 * Conversion helpers.
47 */
48
68
70{
71 switch (boundary_smooth) {
76 }
77 BLI_assert_msg(0, "Unknown boundary smooth flag");
79}
80
81/* --------------------------------------------------------------------
82 * Settings.
83 */
84
85bool settings_equal(const Settings *settings_a, const Settings *settings_b)
86{
87 return (settings_a->is_simple == settings_b->is_simple &&
88 settings_a->is_adaptive == settings_b->is_adaptive &&
89 settings_a->level == settings_b->level &&
90 settings_a->vtx_boundary_interpolation == settings_b->vtx_boundary_interpolation &&
91 settings_a->fvar_linear_interpolation == settings_b->fvar_linear_interpolation);
92}
93
94/* --------------------------------------------------------------------
95 * Construction.
96 */
97
98/* Creation from scratch. */
99
101{
102#ifdef WITH_OPENSUBDIV
103 SubdivStats stats;
104 stats_init(&stats);
106 OpenSubdiv_TopologyRefinerSettings topology_refiner_settings;
107 topology_refiner_settings.level = settings->level;
108 topology_refiner_settings.is_adaptive = settings->is_adaptive;
109 blender::opensubdiv::TopologyRefinerImpl *osd_topology_refiner = nullptr;
110 if (converter->getNumVertices(converter) != 0) {
112 converter, topology_refiner_settings);
113 }
114 else {
115 /* TODO(sergey): Check whether original geometry had any vertices.
116 * The thing here is: OpenSubdiv can only deal with faces, but our
117 * side of subdiv also deals with loose vertices and edges. */
118 }
119 Subdiv *subdiv = MEM_cnew<Subdiv>(__func__);
120 subdiv->settings = *settings;
121 subdiv->topology_refiner = osd_topology_refiner;
122 subdiv->evaluator = nullptr;
123 subdiv->displacement_evaluator = nullptr;
125 subdiv->stats = stats;
126 return subdiv;
127#else
128 UNUSED_VARS(settings, converter);
129 return nullptr;
130#endif
131}
132
133Subdiv *new_from_mesh(const Settings *settings, const Mesh *mesh)
134{
135 if (mesh->verts_num == 0) {
136 return nullptr;
137 }
138 OpenSubdiv_Converter converter;
139 converter_init_for_mesh(&converter, settings, mesh);
140 Subdiv *subdiv = new_from_converter(settings, &converter);
141 converter_free(&converter);
142 return subdiv;
143}
144
145/* Creation with cached-aware semantic. */
146
148 const Settings *settings,
149 OpenSubdiv_Converter *converter)
150{
151#ifdef WITH_OPENSUBDIV
152 /* Check if the existing descriptor can be re-used. */
153 bool can_reuse_subdiv = true;
154 if (subdiv != nullptr && subdiv->topology_refiner != nullptr) {
155 if (!settings_equal(&subdiv->settings, settings)) {
156 can_reuse_subdiv = false;
157 }
158 else {
160 can_reuse_subdiv = subdiv->topology_refiner->isEqualToConverter(converter);
162 }
163 }
164 else {
165 can_reuse_subdiv = false;
166 }
167 if (can_reuse_subdiv) {
168 return subdiv;
169 }
170 /* Create new subdiv. */
171 if (subdiv != nullptr) {
172 free(subdiv);
173 }
174 return new_from_converter(settings, converter);
175#else
176 UNUSED_VARS(subdiv, settings, converter);
177 return nullptr;
178#endif
179}
180
181Subdiv *update_from_mesh(Subdiv *subdiv, const Settings *settings, const Mesh *mesh)
182{
183 OpenSubdiv_Converter converter;
184 converter_init_for_mesh(&converter, settings, mesh);
185 subdiv = update_from_converter(subdiv, settings, &converter);
186 converter_free(&converter);
187 return subdiv;
188}
189
190/* Memory release. */
191
192void free(Subdiv *subdiv)
193{
194#ifdef WITH_OPENSUBDIV
195 if (subdiv->evaluator != nullptr) {
196 const eOpenSubdivEvaluator evaluator_type = subdiv->evaluator->type;
197 if (evaluator_type != OPENSUBDIV_EVALUATOR_CPU) {
198 /* Let the draw code do the freeing, to ensure that the OpenGL context is valid. */
200 return;
201 }
203 }
204 delete subdiv->topology_refiner;
205 displacement_detach(subdiv);
206 if (subdiv->cache_.face_ptex_offset != nullptr) {
208 }
209 MEM_freeN(subdiv);
210#else
211 UNUSED_VARS(subdiv);
212#endif
213}
214
215/* --------------------------------------------------------------------
216 * Topology helpers.
217 */
218
220{
221#ifdef WITH_OPENSUBDIV
222 if (subdiv->cache_.face_ptex_offset != nullptr) {
223 return subdiv->cache_.face_ptex_offset;
224 }
225 const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner;
226 if (topology_refiner == nullptr) {
227 return nullptr;
228 }
229 const int num_coarse_faces = topology_refiner->base_level().GetNumFaces();
230 subdiv->cache_.face_ptex_offset = static_cast<int *>(
231 MEM_malloc_arrayN(num_coarse_faces + 1, sizeof(int), __func__));
232 int ptex_offset = 0;
233 for (int face_index = 0; face_index < num_coarse_faces; face_index++) {
234 const int face_size = topology_refiner->base_level().GetFaceVertices(face_index).size();
235 const int num_ptex_faces = face_size == 4 ? 1 : face_size;
236 subdiv->cache_.face_ptex_offset[face_index] = ptex_offset;
237 ptex_offset += num_ptex_faces;
238 }
239 subdiv->cache_.face_ptex_offset[num_coarse_faces] = ptex_offset;
240 return subdiv->cache_.face_ptex_offset;
241#else
242 UNUSED_VARS(subdiv);
243 return nullptr;
244#endif
245}
246
247} // namespace blender::bke::subdiv
void(* BKE_subsurf_modifier_free_gpu_cache_cb)(blender::bke::subdiv::Subdiv *subdiv)
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define UNUSED_VARS(...)
@ 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.
const OpenSubdiv::Far::TopologyLevel & base_level() const
static TopologyRefinerImpl * createFromConverter(OpenSubdiv_Converter *converter, const OpenSubdiv_TopologyRefinerSettings &settings)
bool isEqualToConverter(const OpenSubdiv_Converter *converter) const
void openSubdiv_deleteEvaluator(OpenSubdiv_Evaluator *evaluator)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void free(Subdiv *subdiv)
Definition subdiv.cc:192
void converter_init_for_mesh(OpenSubdiv_Converter *converter, const Settings *settings, const Mesh *mesh)
@ 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
void stats_init(SubdivStats *stats)
void displacement_detach(Subdiv *subdiv)
FVarLinearInterpolation fvar_interpolation_from_uv_smooth(int uv_smooth)
Definition subdiv.cc:49
Subdiv * update_from_converter(Subdiv *subdiv, const Settings *settings, OpenSubdiv_Converter *converter)
Definition subdiv.cc:147
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)
void converter_free(OpenSubdiv_Converter *converter)
VtxBoundaryInterpolation vtx_boundary_interpolation_from_subsurf(int boundary_smooth)
Definition subdiv.cc:69
@ 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 openSubdiv_cleanup()
void openSubdiv_init()
eOpenSubdivEvaluator
@ OPENSUBDIV_EVALUATOR_CPU
int(* getNumVertices)(const OpenSubdiv_Converter *converter)
VtxBoundaryInterpolation vtx_boundary_interpolation
Definition BKE_subdiv.hh:70
FVarLinearInterpolation fvar_linear_interpolation
Definition BKE_subdiv.hh:71
Displacement * displacement_evaluator
struct blender::bke::subdiv::Subdiv::@63 cache_
OpenSubdiv_Evaluator * evaluator
blender::opensubdiv::TopologyRefinerImpl * topology_refiner