Blender  V3.3
subdiv_converter_mesh.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 "subdiv_converter.h"
9 
10 #include <string.h>
11 
12 #include "DNA_mesh_types.h"
13 #include "DNA_meshdata_types.h"
14 
15 #include "BLI_bitmap.h"
16 #include "BLI_utildefines.h"
17 
18 #include "BKE_customdata.h"
19 #include "BKE_mesh_mapping.h"
20 #include "BKE_subdiv.h"
21 
22 #include "MEM_guardedalloc.h"
23 
24 #include "opensubdiv_capi.h"
26 
27 #include "bmesh_class.h"
28 
29 /* Enable work-around for non-working CPU evaluator when using bilinear scheme.
30  * This forces Catmark scheme with all edges marked as infinitely sharp. */
31 #define BUGGY_SIMPLE_SCHEME_WORKAROUND 1
32 
33 typedef struct ConverterStorage {
35  const Mesh *mesh;
36  /* CustomData layer for vertex sharpnesses. */
37  const float *cd_vertex_crease;
38  /* Indexed by loop index, value denotes index of face-varying vertex
39  * which corresponds to the UV coordinate.
40  */
43  /* Indexed by coarse mesh elements, gives index of corresponding element
44  * with ignoring all non-manifold entities.
45  *
46  * NOTE: This isn't strictly speaking manifold, this is more like non-loose
47  * geometry index. As in, index of element as if there were no loose edges
48  * or vertices in the mesh.
49  */
51  /* Indexed by vertex index from mesh, corresponds to whether this vertex has
52  * infinite sharpness due to non-manifold topology.
53  */
55  /* Reverse mapping to above. */
58  /* Number of non-loose elements. */
62 
64 {
65 #if BUGGY_SIMPLE_SCHEME_WORKAROUND
66  (void)converter;
67  return OSD_SCHEME_CATMARK;
68 #else
69  ConverterStorage *storage = converter->user_data;
70  if (storage->settings.is_simple) {
71  return OSD_SCHEME_BILINEAR;
72  }
73  else {
74  return OSD_SCHEME_CATMARK;
75  }
76 #endif
77 }
78 
80  const struct OpenSubdiv_Converter *converter)
81 {
82  ConverterStorage *storage = converter->user_data;
84 }
85 
87  const OpenSubdiv_Converter *converter)
88 {
89  ConverterStorage *storage = converter->user_data;
91 }
92 
93 static bool specifies_full_topology(const OpenSubdiv_Converter *UNUSED(converter))
94 {
95  return false;
96 }
97 
98 static int get_num_faces(const OpenSubdiv_Converter *converter)
99 {
100  ConverterStorage *storage = converter->user_data;
101  return storage->mesh->totpoly;
102 }
103 
104 static int get_num_edges(const OpenSubdiv_Converter *converter)
105 {
106  ConverterStorage *storage = converter->user_data;
107  return storage->num_manifold_edges;
108 }
109 
110 static int get_num_vertices(const OpenSubdiv_Converter *converter)
111 {
112  ConverterStorage *storage = converter->user_data;
113  return storage->num_manifold_vertices;
114 }
115 
116 static int get_num_face_vertices(const OpenSubdiv_Converter *converter, int manifold_face_index)
117 {
118  ConverterStorage *storage = converter->user_data;
119  return storage->mesh->mpoly[manifold_face_index].totloop;
120 }
121 
122 static void get_face_vertices(const OpenSubdiv_Converter *converter,
123  int manifold_face_index,
124  int *manifold_face_vertices)
125 {
126  ConverterStorage *storage = converter->user_data;
127  const MPoly *poly = &storage->mesh->mpoly[manifold_face_index];
128  const MLoop *mloop = storage->mesh->mloop;
129  for (int corner = 0; corner < poly->totloop; corner++) {
130  manifold_face_vertices[corner] =
131  storage->manifold_vertex_index[mloop[poly->loopstart + corner].v];
132  }
133 }
134 
135 static void get_edge_vertices(const OpenSubdiv_Converter *converter,
136  int manifold_edge_index,
137  int *manifold_edge_vertices)
138 {
139  ConverterStorage *storage = converter->user_data;
140  const int edge_index = storage->manifold_edge_index_reverse[manifold_edge_index];
141  const MEdge *edge = &storage->mesh->medge[edge_index];
142  manifold_edge_vertices[0] = storage->manifold_vertex_index[edge->v1];
143  manifold_edge_vertices[1] = storage->manifold_vertex_index[edge->v2];
144 }
145 
146 static float get_edge_sharpness(const OpenSubdiv_Converter *converter, int manifold_edge_index)
147 {
148  ConverterStorage *storage = converter->user_data;
149 #if BUGGY_SIMPLE_SCHEME_WORKAROUND
150  if (storage->settings.is_simple) {
151  return 10.0f;
152  }
153 #endif
154  if (!storage->settings.use_creases) {
155  return 0.0f;
156  }
157  const int edge_index = storage->manifold_edge_index_reverse[manifold_edge_index];
158  const MEdge *medge = storage->mesh->medge;
159  return BKE_subdiv_crease_to_sharpness_char(medge[edge_index].crease);
160 }
161 
162 static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter,
163  int manifold_vertex_index)
164 {
165  ConverterStorage *storage = converter->user_data;
166 #if BUGGY_SIMPLE_SCHEME_WORKAROUND
167  if (storage->settings.is_simple) {
168  return true;
169  }
170 #endif
171  const int vertex_index = storage->manifold_vertex_index_reverse[manifold_vertex_index];
172  return BLI_BITMAP_TEST_BOOL(storage->infinite_sharp_vertices_map, vertex_index);
173 }
174 
175 static float get_vertex_sharpness(const OpenSubdiv_Converter *converter, int manifold_vertex_index)
176 {
177  ConverterStorage *storage = converter->user_data;
178  if (!storage->settings.use_creases || storage->cd_vertex_crease == NULL) {
179  return 0.0f;
180  }
181  const int vertex_index = storage->manifold_vertex_index_reverse[manifold_vertex_index];
182  return BKE_subdiv_crease_to_sharpness_f(storage->cd_vertex_crease[vertex_index]);
183 }
184 
185 static int get_num_uv_layers(const OpenSubdiv_Converter *converter)
186 {
187  ConverterStorage *storage = converter->user_data;
188  const Mesh *mesh = storage->mesh;
190 }
191 
192 static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int layer_index)
193 {
194  ConverterStorage *storage = converter->user_data;
195  const Mesh *mesh = storage->mesh;
196  const MPoly *mpoly = mesh->mpoly;
197  const MLoop *mloop = mesh->mloop;
198  const MLoopUV *mloopuv = CustomData_get_layer_n(&mesh->ldata, CD_MLOOPUV, layer_index);
199  const int num_poly = mesh->totpoly;
200  const int num_vert = mesh->totvert;
201  const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
202  /* Initialize memory required for the operations. */
203  if (storage->loop_uv_indices == NULL) {
205  mesh->totloop, sizeof(int), "loop uv vertex index");
206  }
207  UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(
208  mpoly, mloop, mloopuv, num_poly, num_vert, limit, false, true);
209  /* NOTE: First UV vertex is supposed to be always marked as separate. */
210  storage->num_uv_coordinates = -1;
211  for (int vertex_index = 0; vertex_index < num_vert; vertex_index++) {
212  const UvMapVert *uv_vert = BKE_mesh_uv_vert_map_get_vert(uv_vert_map, vertex_index);
213  while (uv_vert != NULL) {
214  if (uv_vert->separate) {
215  storage->num_uv_coordinates++;
216  }
217  const MPoly *mp = &mpoly[uv_vert->poly_index];
218  const int global_loop_index = mp->loopstart + uv_vert->loop_of_poly_index;
219  storage->loop_uv_indices[global_loop_index] = storage->num_uv_coordinates;
220  uv_vert = uv_vert->next;
221  }
222  }
223  /* So far this value was used as a 0-based index, actual number of UV
224  * vertices is 1 more.
225  */
226  storage->num_uv_coordinates += 1;
227  BKE_mesh_uv_vert_map_free(uv_vert_map);
228 }
229 
230 static void finish_uv_layer(const OpenSubdiv_Converter *UNUSED(converter))
231 {
232 }
233 
234 static int get_num_uvs(const OpenSubdiv_Converter *converter)
235 {
236  ConverterStorage *storage = converter->user_data;
237  return storage->num_uv_coordinates;
238 }
239 
240 static int get_face_corner_uv_index(const OpenSubdiv_Converter *converter,
241  const int face_index,
242  const int corner)
243 {
244  ConverterStorage *storage = converter->user_data;
245  const MPoly *mp = &storage->mesh->mpoly[face_index];
246  return storage->loop_uv_indices[mp->loopstart + corner];
247 }
248 
249 static void free_user_data(const OpenSubdiv_Converter *converter)
250 {
251  ConverterStorage *user_data = converter->user_data;
252  MEM_SAFE_FREE(user_data->loop_uv_indices);
253  MEM_freeN(user_data->manifold_vertex_index);
254  MEM_freeN(user_data->infinite_sharp_vertices_map);
255  MEM_freeN(user_data->manifold_vertex_index_reverse);
256  MEM_freeN(user_data->manifold_edge_index_reverse);
258 }
259 
260 static void init_functions(OpenSubdiv_Converter *converter)
261 {
262  converter->getSchemeType = get_scheme_type;
266 
267  converter->getNumFaces = get_num_faces;
268  converter->getNumEdges = get_num_edges;
269  converter->getNumVertices = get_num_vertices;
270 
272  converter->getFaceVertices = get_face_vertices;
273  converter->getFaceEdges = NULL;
274 
275  converter->getEdgeVertices = get_edge_vertices;
276  converter->getNumEdgeFaces = NULL;
277  converter->getEdgeFaces = NULL;
279 
280  converter->getNumVertexEdges = NULL;
281  converter->getVertexEdges = NULL;
282  converter->getNumVertexFaces = NULL;
283  converter->getVertexFaces = NULL;
286 
287  converter->getNumUVLayers = get_num_uv_layers;
288  converter->precalcUVLayer = precalc_uv_layer;
289  converter->finishUVLayer = finish_uv_layer;
290  converter->getNumUVCoordinates = get_num_uvs;
292 
293  converter->freeUserData = free_user_data;
294 }
295 
296 static void initialize_manifold_index_array(const BLI_bitmap *used_map,
297  const int num_elements,
298  int **r_indices,
299  int **r_indices_reverse,
300  int *r_num_manifold_elements)
301 {
302  int *indices = NULL;
303  if (r_indices != NULL) {
304  indices = MEM_malloc_arrayN(num_elements, sizeof(int), "manifold indices");
305  }
306  int *indices_reverse = NULL;
307  if (r_indices_reverse != NULL) {
308  indices_reverse = MEM_malloc_arrayN(num_elements, sizeof(int), "manifold indices reverse");
309  }
310  int offset = 0;
311  for (int i = 0; i < num_elements; i++) {
312  if (BLI_BITMAP_TEST_BOOL(used_map, i)) {
313  if (indices != NULL) {
314  indices[i] = i - offset;
315  }
316  if (indices_reverse != NULL) {
317  indices_reverse[i - offset] = i;
318  }
319  }
320  else {
321  if (indices != NULL) {
322  indices[i] = -1;
323  }
324  offset++;
325  }
326  }
327  if (r_indices != NULL) {
328  *r_indices = indices;
329  }
330  if (r_indices_reverse != NULL) {
331  *r_indices_reverse = indices_reverse;
332  }
333  *r_num_manifold_elements = num_elements - offset;
334 }
335 
337 {
338  const Mesh *mesh = storage->mesh;
339  const MEdge *medge = mesh->medge;
340  const MLoop *mloop = mesh->mloop;
341  const MPoly *mpoly = mesh->mpoly;
342  /* Set bits of elements which are not loose. */
343  BLI_bitmap *vert_used_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map");
344  BLI_bitmap *edge_used_map = BLI_BITMAP_NEW(mesh->totedge, "edge used map");
345  for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
346  const MPoly *poly = &mpoly[poly_index];
347  for (int corner = 0; corner < poly->totloop; corner++) {
348  const MLoop *loop = &mloop[poly->loopstart + corner];
349  BLI_BITMAP_ENABLE(vert_used_map, loop->v);
350  BLI_BITMAP_ENABLE(edge_used_map, loop->e);
351  }
352  }
353  initialize_manifold_index_array(vert_used_map,
354  mesh->totvert,
355  &storage->manifold_vertex_index,
357  &storage->num_manifold_vertices);
358  initialize_manifold_index_array(edge_used_map,
359  mesh->totedge,
360  NULL,
361  &storage->manifold_edge_index_reverse,
362  &storage->num_manifold_edges);
363  /* Initialize infinite sharp mapping. */
364  storage->infinite_sharp_vertices_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map");
365  for (int edge_index = 0; edge_index < mesh->totedge; edge_index++) {
366  if (!BLI_BITMAP_TEST_BOOL(edge_used_map, edge_index)) {
367  const MEdge *edge = &medge[edge_index];
370  }
371  }
372  /* Free working variables. */
373  MEM_freeN(vert_used_map);
374  MEM_freeN(edge_used_map);
375 }
376 
377 static void init_user_data(OpenSubdiv_Converter *converter,
378  const SubdivSettings *settings,
379  const Mesh *mesh)
380 {
382  user_data->settings = *settings;
383  user_data->mesh = mesh;
384  user_data->cd_vertex_crease = CustomData_get_layer(&mesh->vdata, CD_CREASE);
385  user_data->loop_uv_indices = NULL;
387  converter->user_data = user_data;
388 }
389 
391  const SubdivSettings *settings,
392  const Mesh *mesh)
393 {
394  init_functions(converter);
395  init_user_data(converter, settings, mesh);
396 }
CustomData interface, see also DNA_customdata_types.h.
int CustomData_number_of_layers(const struct CustomData *data, int type)
void * CustomData_get_layer_n(const struct CustomData *data, int type, int n)
void * CustomData_get_layer(const struct CustomData *data, int type)
UvMapVert * BKE_mesh_uv_vert_map_get_vert(UvVertMap *vmap, unsigned int v)
Definition: mesh_mapping.c:162
UvVertMap * BKE_mesh_uv_vert_map_create(const struct MPoly *mpoly, const struct MLoop *mloop, const struct MLoopUV *mloopuv, unsigned int totpoly, unsigned int totvert, const float limit[2], bool selected, bool use_winding)
void BKE_mesh_uv_vert_map_free(UvVertMap *vmap)
Definition: mesh_mapping.c:167
#define STD_UV_CONNECT_LIMIT
BLI_INLINE float BKE_subdiv_crease_to_sharpness_f(float edge_crease)
Definition: subdiv_inline.h:90
BLI_INLINE float BKE_subdiv_crease_to_sharpness_char(char edge_crease)
Definition: subdiv_inline.h:95
#define BLI_BITMAP_NEW(_num, _alloc_string)
Definition: BLI_bitmap.h:40
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:81
#define BLI_BITMAP_TEST_BOOL(_bitmap, _index)
Definition: BLI_bitmap.h:74
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:16
#define UNUSED(x)
@ CD_MLOOPUV
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
void * user_data
SyclQueue void void size_t num_bytes void
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
ccl_gpu_kernel_postfix int ccl_global int * indices
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_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
OpenSubdiv_FVarLinearInterpolation
OpenSubdiv_VtxBoundaryInterpolation
OpenSubdiv_SchemeType
@ OSD_SCHEME_CATMARK
@ OSD_SCHEME_BILINEAR
BLI_bitmap * infinite_sharp_vertices_map
SubdivSettings settings
const float * cd_vertex_crease
unsigned int e
unsigned int v
struct MEdge * medge
CustomData vdata
int totedge
int totvert
struct MLoop * mloop
int totpoly
int totloop
struct MPoly * mpoly
CustomData ldata
int(* getNumVertexFaces)(const struct OpenSubdiv_Converter *converter, const int vertex_index)
bool(* specifiesFullTopology)(const struct OpenSubdiv_Converter *converter)
void(* freeUserData)(const struct OpenSubdiv_Converter *converter)
void(* getFaceVertices)(const struct OpenSubdiv_Converter *converter, const int face_index, int *face_vertices)
float(* getVertexSharpness)(const struct OpenSubdiv_Converter *converter, const int vertex_index)
void(* getFaceEdges)(const struct OpenSubdiv_Converter *converter, const int face_index, int *face_edges)
int(* getNumUVLayers)(const struct OpenSubdiv_Converter *converter)
int(* getNumVertexEdges)(const struct OpenSubdiv_Converter *converter, const int vertex_index)
OpenSubdiv_FVarLinearInterpolation(* getFVarLinearInterpolation)(const struct OpenSubdiv_Converter *converter)
void(* getEdgeVertices)(const struct OpenSubdiv_Converter *converter, const int edge_index, int edge_vertices[2])
OpenSubdiv_SchemeType(* getSchemeType)(const struct OpenSubdiv_Converter *converter)
bool(* isInfiniteSharpVertex)(const struct OpenSubdiv_Converter *converter, const int vertex_index)
void(* getVertexFaces)(const struct OpenSubdiv_Converter *converter, const int vertex_index, int *vertex_faces)
int(* getNumVertices)(const struct OpenSubdiv_Converter *converter)
float(* getEdgeSharpness)(const struct OpenSubdiv_Converter *converter, const int edge_index)
int(* getNumEdges)(const struct OpenSubdiv_Converter *converter)
int(* getNumFaces)(const struct OpenSubdiv_Converter *converter)
int(* getNumEdgeFaces)(const struct OpenSubdiv_Converter *converter, const int edge_index)
int(* getNumUVCoordinates)(const struct OpenSubdiv_Converter *converter)
void(* getVertexEdges)(const struct OpenSubdiv_Converter *converter, const int vertex_index, int *vertex_edges)
void(* finishUVLayer)(const struct OpenSubdiv_Converter *converter)
void(* getEdgeFaces)(const struct OpenSubdiv_Converter *converter, const int edge, int *edge_faces)
OpenSubdiv_VtxBoundaryInterpolation(* getVtxBoundaryInterpolation)(const struct OpenSubdiv_Converter *converter)
void(* precalcUVLayer)(const struct OpenSubdiv_Converter *converter, const int layer_index)
int(* getFaceCornerUVIndex)(const struct OpenSubdiv_Converter *converter, const int face_index, const int corner_index)
int(* getNumFaceVertices)(const struct OpenSubdiv_Converter *converter, const int face_index)
bool use_creases
Definition: BKE_subdiv.h:68
struct UvMapVert * next
unsigned short loop_of_poly_index
unsigned int poly_index
int BKE_subdiv_converter_fvar_linear_from_settings(const SubdivSettings *settings)
int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(const SubdivSettings *settings)
static int get_face_corner_uv_index(const OpenSubdiv_Converter *converter, const int face_index, const int corner)
static void get_edge_vertices(const OpenSubdiv_Converter *converter, int manifold_edge_index, int *manifold_edge_vertices)
static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int layer_index)
static bool specifies_full_topology(const OpenSubdiv_Converter *UNUSED(converter))
static void get_face_vertices(const OpenSubdiv_Converter *converter, int manifold_face_index, int *manifold_face_vertices)
static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter, int manifold_vertex_index)
struct ConverterStorage ConverterStorage
static OpenSubdiv_VtxBoundaryInterpolation get_vtx_boundary_interpolation(const struct OpenSubdiv_Converter *converter)
static int get_num_faces(const OpenSubdiv_Converter *converter)
static void init_user_data(OpenSubdiv_Converter *converter, const SubdivSettings *settings, const Mesh *mesh)
static void finish_uv_layer(const OpenSubdiv_Converter *UNUSED(converter))
static int get_num_vertices(const OpenSubdiv_Converter *converter)
static void initialize_manifold_index_array(const BLI_bitmap *used_map, const int num_elements, int **r_indices, int **r_indices_reverse, int *r_num_manifold_elements)
static OpenSubdiv_SchemeType get_scheme_type(const OpenSubdiv_Converter *converter)
static int get_num_face_vertices(const OpenSubdiv_Converter *converter, int manifold_face_index)
void BKE_subdiv_converter_init_for_mesh(struct OpenSubdiv_Converter *converter, const SubdivSettings *settings, const Mesh *mesh)
static int get_num_edges(const OpenSubdiv_Converter *converter)
static void free_user_data(const OpenSubdiv_Converter *converter)
static float get_edge_sharpness(const OpenSubdiv_Converter *converter, int manifold_edge_index)
static float get_vertex_sharpness(const OpenSubdiv_Converter *converter, int manifold_vertex_index)
static int get_num_uvs(const OpenSubdiv_Converter *converter)
static void initialize_manifold_indices(ConverterStorage *storage)
static int get_num_uv_layers(const OpenSubdiv_Converter *converter)
static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(const OpenSubdiv_Converter *converter)
static void init_functions(OpenSubdiv_Converter *converter)