Blender  V2.93
subdiv.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2018 by Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "BKE_subdiv.h"
25 
26 #include "DNA_mesh_types.h"
27 #include "DNA_meshdata_types.h"
28 #include "DNA_modifier_types.h"
29 
30 #include "BLI_utildefines.h"
31 
32 #include "MEM_guardedalloc.h"
33 
34 #include "subdiv_converter.h"
35 
36 #include "opensubdiv_capi.h"
40 
41 /* =================----====--===== MODULE ==========================------== */
42 
44 {
46 }
47 
49 {
51 }
52 
53 /* ========================== CONVERSION HELPERS ============================ */
54 
56 {
57  switch (uv_smooth) {
70  }
71  BLI_assert(!"Unknown uv smooth flag");
73 }
74 
76  int boundary_smooth)
77 {
78  switch (boundary_smooth) {
83  }
84  BLI_assert(!"Unknown boundary smooth flag");
86 }
87 
88 /* ================================ SETTINGS ================================ */
89 
90 bool BKE_subdiv_settings_equal(const SubdivSettings *settings_a, const SubdivSettings *settings_b)
91 {
92  return (settings_a->is_simple == settings_b->is_simple &&
93  settings_a->is_adaptive == settings_b->is_adaptive &&
94  settings_a->level == settings_b->level &&
95  settings_a->vtx_boundary_interpolation == settings_b->vtx_boundary_interpolation &&
96  settings_a->fvar_linear_interpolation == settings_b->fvar_linear_interpolation);
97 }
98 
99 /* ============================== CONSTRUCTION ============================== */
100 
101 /* Creation from scratch. */
102 
104  struct OpenSubdiv_Converter *converter)
105 {
106  SubdivStats stats;
107  BKE_subdiv_stats_init(&stats);
109  OpenSubdiv_TopologyRefinerSettings topology_refiner_settings;
110  topology_refiner_settings.level = settings->level;
111  topology_refiner_settings.is_adaptive = settings->is_adaptive;
112  struct OpenSubdiv_TopologyRefiner *osd_topology_refiner = NULL;
113  if (converter->getNumVertices(converter) != 0) {
114  osd_topology_refiner = openSubdiv_createTopologyRefinerFromConverter(
115  converter, &topology_refiner_settings);
116  }
117  else {
118  /* TODO(sergey): Check whether original geometry had any vertices.
119  * The thing here is: OpenSubdiv can only deal with faces, but our
120  * side of subdiv also deals with loose vertices and edges. */
121  }
122  Subdiv *subdiv = MEM_callocN(sizeof(Subdiv), "subdiv from converetr");
123  subdiv->settings = *settings;
124  subdiv->topology_refiner = osd_topology_refiner;
125  subdiv->evaluator = NULL;
126  subdiv->displacement_evaluator = NULL;
128  subdiv->stats = stats;
129  return subdiv;
130 }
131 
133 {
134  if (mesh->totvert == 0) {
135  return NULL;
136  }
137  OpenSubdiv_Converter converter;
138  BKE_subdiv_converter_init_for_mesh(&converter, settings, mesh);
139  Subdiv *subdiv = BKE_subdiv_new_from_converter(settings, &converter);
140  BKE_subdiv_converter_free(&converter);
141  return subdiv;
142 }
143 
144 /* Creation with cached-aware semantic. */
145 
147  const SubdivSettings *settings,
148  OpenSubdiv_Converter *converter)
149 {
150  /* Check if the existing descriptor can be re-used. */
151  bool can_reuse_subdiv = true;
152  if (subdiv != NULL && subdiv->topology_refiner != NULL) {
153  if (!BKE_subdiv_settings_equal(&subdiv->settings, settings)) {
154  can_reuse_subdiv = false;
155  }
156  else {
159  converter);
161  }
162  }
163  else {
164  can_reuse_subdiv = false;
165  }
166  if (can_reuse_subdiv) {
167  return subdiv;
168  }
169  /* Create new subdiv. */
170  if (subdiv != NULL) {
171  BKE_subdiv_free(subdiv);
172  }
173  return BKE_subdiv_new_from_converter(settings, converter);
174 }
175 
177  const SubdivSettings *settings,
178  const Mesh *mesh)
179 {
180  OpenSubdiv_Converter converter;
181  BKE_subdiv_converter_init_for_mesh(&converter, settings, mesh);
182  subdiv = BKE_subdiv_update_from_converter(subdiv, settings, &converter);
183  BKE_subdiv_converter_free(&converter);
184  return subdiv;
185 }
186 
187 /* Memory release. */
188 
189 void BKE_subdiv_free(Subdiv *subdiv)
190 {
191  if (subdiv->evaluator != NULL) {
193  }
194  if (subdiv->topology_refiner != NULL) {
196  }
198  if (subdiv->cache_.face_ptex_offset != NULL) {
200  }
201  MEM_freeN(subdiv);
202 }
203 
204 /* =========================== PTEX FACES AND GRIDS ========================= */
205 
207 {
208  if (subdiv->cache_.face_ptex_offset != NULL) {
209  return subdiv->cache_.face_ptex_offset;
210  }
211  OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
212  if (topology_refiner == NULL) {
213  return NULL;
214  }
215  const int num_coarse_faces = topology_refiner->getNumFaces(topology_refiner);
217  num_coarse_faces, sizeof(int), "subdiv face_ptex_offset");
218  int ptex_offset = 0;
219  for (int face_index = 0; face_index < num_coarse_faces; face_index++) {
220  const int num_ptex_faces = topology_refiner->getNumFacePtexFaces(topology_refiner, face_index);
221  subdiv->cache_.face_ptex_offset[face_index] = ptex_offset;
222  ptex_offset += num_ptex_faces;
223  }
224  return subdiv->cache_.face_ptex_offset;
225 }
void BKE_subdiv_stats_init(SubdivStats *stats)
Definition: subdiv_stats.c:30
@ SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME
Definition: BKE_subdiv.h:92
@ SUBDIV_STATS_TOPOLOGY_COMPARE
Definition: BKE_subdiv.h:99
void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value)
Definition: subdiv_stats.c:47
void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value)
Definition: subdiv_stats.c:42
eSubdivFVarLinearInterpolation
Definition: BKE_subdiv.h:49
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL
Definition: BKE_subdiv.h:55
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY
Definition: BKE_subdiv.h:51
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_BOUNDARIES
Definition: BKE_subdiv.h:54
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE
Definition: BKE_subdiv.h:50
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_AND_JUNCTIONS
Definition: BKE_subdiv.h:52
@ SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_JUNCTIONS_AND_CONCAVE
Definition: BKE_subdiv.h:53
eSubdivVtxBoundaryInterpolation
Definition: BKE_subdiv.h:40
@ SUBDIV_VTX_BOUNDARY_EDGE_AND_CORNER
Definition: BKE_subdiv.h:46
@ SUBDIV_VTX_BOUNDARY_EDGE_ONLY
Definition: BKE_subdiv.h:44
void BKE_subdiv_displacement_detach(Subdiv *subdiv)
#define BLI_assert(a)
Definition: BLI_assert.h:58
@ 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:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void openSubdiv_init(void)
void openSubdiv_cleanup(void)
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:76
eSubdivFVarLinearInterpolation fvar_linear_interpolation
Definition: BKE_subdiv.h:87
eSubdivVtxBoundaryInterpolation vtx_boundary_interpolation
Definition: BKE_subdiv.h:86
struct Subdiv::@67 cache_
SubdivSettings settings
Definition: BKE_subdiv.h:176
SubdivStats stats
Definition: BKE_subdiv.h:186
struct SubdivDisplacement * displacement_evaluator
Definition: BKE_subdiv.h:184
struct OpenSubdiv_TopologyRefiner * topology_refiner
Definition: BKE_subdiv.h:180
struct OpenSubdiv_Evaluator * evaluator
Definition: BKE_subdiv.h:182
int * face_ptex_offset
Definition: BKE_subdiv.h:192
void BKE_subdiv_exit()
Definition: subdiv.c:48
bool BKE_subdiv_settings_equal(const SubdivSettings *settings_a, const SubdivSettings *settings_b)
Definition: subdiv.c:90
Subdiv * BKE_subdiv_update_from_converter(Subdiv *subdiv, const SubdivSettings *settings, OpenSubdiv_Converter *converter)
Definition: subdiv.c:146
eSubdivVtxBoundaryInterpolation BKE_subdiv_vtx_boundary_interpolation_from_subsurf(int boundary_smooth)
Definition: subdiv.c:75
void BKE_subdiv_free(Subdiv *subdiv)
Definition: subdiv.c:189
int * BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv)
Definition: subdiv.c:206
Subdiv * BKE_subdiv_update_from_mesh(Subdiv *subdiv, const SubdivSettings *settings, const Mesh *mesh)
Definition: subdiv.c:176
eSubdivFVarLinearInterpolation BKE_subdiv_fvar_interpolation_from_uv_smooth(int uv_smooth)
Definition: subdiv.c:55
Subdiv * BKE_subdiv_new_from_mesh(const SubdivSettings *settings, const Mesh *mesh)
Definition: subdiv.c:132
Subdiv * BKE_subdiv_new_from_converter(const SubdivSettings *settings, struct OpenSubdiv_Converter *converter)
Definition: subdiv.c:103
void BKE_subdiv_init()
Definition: subdiv.c:43
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)