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