Subsurf: Support subdivision of loose elements
[blender.git] / source / blender / blenkernel / intern / subdiv_converter_mesh.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2018 by Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Sergey Sharybin.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 #include "subdiv_converter.h"
27
28 #include <string.h>
29
30 #include "DNA_mesh_types.h"
31 #include "DNA_meshdata_types.h"
32
33 #include "BLI_utildefines.h"
34 #include "BLI_bitmap.h"
35 #include "BLI_math_vector.h"
36
37 #include "BKE_customdata.h"
38 #include "BKE_mesh_mapping.h"
39 #include "BKE_subdiv.h"
40
41 #include "MEM_guardedalloc.h"
42
43 #ifdef WITH_OPENSUBDIV
44 #  include "opensubdiv_capi.h"
45 #  include "opensubdiv_converter_capi.h"
46 #endif
47
48 /* Use mesh element mapping structures during conversion.
49  * Uses more memory but is much faster than naive algorithm.
50  */
51 #define USE_MESH_ELEMENT_MAPPING
52
53 #ifdef WITH_OPENSUBDIV
54 typedef struct ConverterStorage {
55         SubdivSettings settings;
56         const Mesh *mesh;
57
58 #ifdef USE_MESH_ELEMENT_MAPPING
59         MeshElemMap *vert_edge_map;
60         MeshElemMap *vert_poly_map;
61         MeshElemMap *edge_poly_map;
62         int *vert_edge_mem;
63         int *vert_poly_mem;
64         int *edge_poly_mem;
65 #endif
66
67         /* Indexed by loop index, value denotes index of face-varying vertex
68          * which corresponds to the UV coordinate.
69          */
70         int *loop_uv_indices;
71         int num_uv_coordinates;
72
73         /* Indexed by coarse mesh elements, gives index of corresponding element
74          * with ignoring all non-manifold entities.
75          *
76          * NOTE: This isn't strictly speaking manifold, this is more like non-loose
77          * geometry index. As in, index of element as if there were no loose edges
78          * or vertices in the mesh.
79          */
80         int *manifold_vertex_index;
81         int *manifold_edge_index;
82         /* Indexed by vertex index from mesh, corresponds to whether this vertex has
83          * infinite sharpness due to non-manifol topology.
84          */
85         BLI_bitmap *infinite_sharp_vertices_map;
86         /* Reverse mapping to above. */
87         int *manifold_vertex_index_reverse;
88         int *manifold_edge_index_reverse;
89         /* Number of non-loose elements. */
90         int num_manifold_vertices;
91         int num_manifold_edges;
92 } ConverterStorage;
93
94 static OpenSubdiv_SchemeType get_scheme_type(
95         const OpenSubdiv_Converter *converter)
96 {
97         ConverterStorage *storage = converter->user_data;
98         if (storage->settings.is_simple) {
99                 return OSD_SCHEME_BILINEAR;
100         }
101         else {
102                 return OSD_SCHEME_CATMARK;
103         }
104 }
105
106 static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(
107         const OpenSubdiv_Converter *converter)
108 {
109         ConverterStorage *storage = converter->user_data;
110         return BKE_subdiv_converter_fvar_linear_from_settings(&storage->settings);
111 }
112
113 static int get_num_faces(const OpenSubdiv_Converter *converter)
114 {
115         ConverterStorage *storage = converter->user_data;
116         return storage->mesh->totpoly;
117 }
118
119 static int get_num_edges(const OpenSubdiv_Converter *converter)
120 {
121         ConverterStorage *storage = converter->user_data;
122         return storage->num_manifold_edges;
123 }
124
125 static int get_num_vertices(const OpenSubdiv_Converter *converter)
126 {
127         ConverterStorage *storage = converter->user_data;
128         return storage->num_manifold_vertices;
129 }
130
131 static int get_num_face_vertices(const OpenSubdiv_Converter *converter,
132                                  int manifold_face_index)
133 {
134         ConverterStorage *storage = converter->user_data;
135         return storage->mesh->mpoly[manifold_face_index].totloop;
136 }
137
138 static void get_face_vertices(const OpenSubdiv_Converter *converter,
139                               int manifold_face_index,
140                               int *manifold_face_vertices)
141 {
142         ConverterStorage *storage = converter->user_data;
143         const MPoly *poly = &storage->mesh->mpoly[manifold_face_index];
144         const MLoop *mloop = storage->mesh->mloop;
145         for (int corner = 0; corner < poly->totloop; corner++) {
146                 manifold_face_vertices[corner] = storage->manifold_vertex_index[
147                         mloop[poly->loopstart + corner].v];
148         }
149 }
150
151 static void get_face_edges(const OpenSubdiv_Converter *converter,
152                            int manifold_face_index,
153                            int *manifold_face_edges)
154 {
155         ConverterStorage *storage = converter->user_data;
156         const MPoly *poly = &storage->mesh->mpoly[manifold_face_index];
157         const MLoop *mloop = storage->mesh->mloop;
158         for (int corner = 0; corner < poly->totloop; corner++) {
159                 manifold_face_edges[corner] =
160                         storage->manifold_edge_index[mloop[poly->loopstart + corner].e];
161         }
162 }
163
164 static void get_edge_vertices(const OpenSubdiv_Converter *converter,
165                               int manifold_edge_index,
166                               int *manifold_edge_vertices)
167 {
168         ConverterStorage *storage = converter->user_data;
169         const int edge_index =
170                 storage->manifold_edge_index_reverse[manifold_edge_index];
171         const MEdge *edge = &storage->mesh->medge[edge_index];
172         manifold_edge_vertices[0] = storage->manifold_vertex_index[edge->v1];
173         manifold_edge_vertices[1] = storage->manifold_vertex_index[edge->v2];
174 }
175
176 static int get_num_edge_faces(const OpenSubdiv_Converter *converter,
177                               int manifold_edge_index)
178 {
179         ConverterStorage *storage = converter->user_data;
180         const int edge_index =
181                 storage->manifold_edge_index_reverse[manifold_edge_index];
182 #ifdef USE_MESH_ELEMENT_MAPPING
183         return storage->edge_poly_map[edge_index].count;
184 #else
185         const Mesh *mesh = storage->mesh;
186         const MPoly *mpoly = mesh->mpoly;
187         const MLoop *mloop = mesh->mloop;
188         int num = 0;
189         for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
190                 const MPoly *poly = &mpoly[poly_index];
191                 for (int corner = 0; corner < poly->totloop; corner++) {
192                         const MLoop *loop = &mloop[poly->loopstart + corner];
193                         if (storage->manifold_edge_index[loop->e] == -1) {
194                                 continue;
195                         }
196                         if (loop->e == edge_index) {
197                                 ++num;
198                                 break;
199                         }
200                 }
201         }
202         return num;
203 #endif
204 }
205
206 static void get_edge_faces(const OpenSubdiv_Converter *converter,
207                            int manifold_edge_index,
208                            int *manifold_edge_faces)
209 {
210         ConverterStorage *storage = converter->user_data;
211         const int edge_index =
212                 storage->manifold_edge_index_reverse[manifold_edge_index];
213 #ifdef USE_MESH_ELEMENT_MAPPING
214         memcpy(manifold_edge_faces,
215                storage->edge_poly_map[edge_index].indices,
216                sizeof(int) * storage->edge_poly_map[edge_index].count);
217 #else
218         const Mesh *mesh = storage->mesh;
219         const MPoly *mpoly = mesh->mpoly;
220         const MLoop *mloop = mesh->mloop;
221         int num = 0;
222         for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
223                 const MPoly *poly = &mpoly[poly_index];
224                 for (int corner = 0; corner < mpoly->totloop; corner++) {
225                         const MLoop *loop = &mloop[poly->loopstart + corner];
226                         if (storage->manifold_edge_index[loop->e] == -1) {
227                                 continue;
228                         }
229                         if (loop->e == edge_index) {
230                                 manifold_edge_faces[num++] = poly_index;
231                                 break;
232                         }
233                 }
234         }
235 #endif
236 }
237
238 static float get_edge_sharpness(const OpenSubdiv_Converter *converter,
239                                 int manifold_edge_index)
240 {
241         ConverterStorage *storage = converter->user_data;
242         const int edge_index =
243                 storage->manifold_edge_index_reverse[manifold_edge_index];
244         const MEdge *medge = storage->mesh->medge;
245         const float edge_crease =  (float)medge[edge_index].crease / 255.0f;
246         return edge_crease * storage->settings.level;
247 }
248
249 static int get_num_vertex_edges(const OpenSubdiv_Converter *converter,
250                                 int manifold_vertex_index)
251 {
252         ConverterStorage *storage = converter->user_data;
253         const int vertex_index =
254                 storage->manifold_vertex_index_reverse[manifold_vertex_index];
255 #ifdef USE_MESH_ELEMENT_MAPPING
256         const int num_vertex_edges = storage->vert_edge_map[vertex_index].count;
257         int num_manifold_vertex_edges = 0;
258         for (int i = 0; i < num_vertex_edges; i++) {
259                 const int edge_index = storage->vert_edge_map[vertex_index].indices[i];
260                 const int manifold_edge_index =
261                         storage->manifold_edge_index[edge_index];
262                 if (manifold_edge_index == -1) {
263                         continue;
264                 }
265                 num_manifold_vertex_edges++;
266         }
267         return num_manifold_vertex_edges;
268 #else
269         const Mesh *mesh = storage->mesh;
270         const MEdge *medge = mesh->medge;
271         int num = 0;
272         for (int edge_index = 0; edge_index < mesh->totedge; edge_index++) {
273                 const MEdge *edge = &medge[edge_index];
274                 if (storage->manifold_edge_index[edge_index] == -1) {
275                         continue;
276                 }
277                 if (edge->v1 == vertex_index || edge->v2 == vertex_index) {
278                         ++num;
279                 }
280         }
281         return num;
282 #endif
283 }
284
285 static void get_vertex_edges(const OpenSubdiv_Converter *converter,
286                              int manifold_vertex_index,
287                              int *manifold_vertex_edges)
288 {
289         ConverterStorage *storage = converter->user_data;
290         const int vertex_index =
291                 storage->manifold_vertex_index_reverse[manifold_vertex_index];
292 #ifdef USE_MESH_ELEMENT_MAPPING
293         const int num_vertex_edges = storage->vert_edge_map[vertex_index].count;
294         int num_manifold_vertex_edges = 0;
295         for (int i = 0; i < num_vertex_edges; i++) {
296                 const int edge_index = storage->vert_edge_map[vertex_index].indices[i];
297                 const int manifold_edge_index =
298                         storage->manifold_edge_index[edge_index];
299                 if (manifold_edge_index == -1) {
300                         continue;
301                 }
302                 manifold_vertex_edges[num_manifold_vertex_edges] = manifold_edge_index;
303                 num_manifold_vertex_edges++;
304         }
305 #else
306         const Mesh *mesh = storage->mesh;
307         const MEdge *medge = mesh->medge;
308         int num = 0;
309         for (int edge_index = 0; edge_index < mesh->totedge; edge_index++) {
310                 const MEdge *edge = &medge[edge_index];
311                 if (storage->manifold_edge_index[edge_index] == -1) {
312                         continue;
313                 }
314                 if (edge->v1 == vertex_index || edge->v2 == vertex_index) {
315                         manifold_vertex_edges[num++] =
316                                 storage->manifold_edge_index[edge_index];
317                 }
318         }
319 #endif
320 }
321
322 static int get_num_vertex_faces(const OpenSubdiv_Converter *converter,
323                                 int manifold_vertex_index)
324 {
325         ConverterStorage *storage = converter->user_data;
326         const int vertex_index =
327                 storage->manifold_vertex_index_reverse[manifold_vertex_index];
328 #ifdef USE_MESH_ELEMENT_MAPPING
329         return storage->vert_poly_map[vertex_index].count;
330 #else
331         const Mesh *mesh = storage->mesh;
332         const MPoly *mpoly = mesh->mpoly;
333         const MLoop *mloop = mesh->mloop;
334         int num = 0;
335         for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
336                 const MPoly *poly = &mpoly[poly_index];
337                 for (int corner = 0; corner < mpoly->totloop; corner++) {
338                         const MLoop *loop = &mloop[poly->loopstart + corner];
339                         if (loop->v == vertex_index) {
340                                 ++num;
341                                 break;
342                         }
343                 }
344         }
345         return num;
346 #endif
347 }
348
349 static void get_vertex_faces(const OpenSubdiv_Converter *converter,
350                             int manifold_vertex_index,
351                             int *manifold_vertex_faces)
352 {
353         ConverterStorage *storage = converter->user_data;
354         const int vertex_index =
355                 storage->manifold_vertex_index_reverse[manifold_vertex_index];
356 #ifdef USE_MESH_ELEMENT_MAPPING
357         memcpy(manifold_vertex_faces,
358                storage->vert_poly_map[vertex_index].indices,
359                sizeof(int) * storage->vert_poly_map[vertex_index].count);
360 #else
361         const Mesh *mesh = storage->mesh;
362         const MPoly *mpoly = mesh->mpoly;
363         const MLoop *mloop = mesh->mloop;
364         int num = 0;
365         for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
366                 const MPoly *poly = &mpoly[poly_index];
367                 for (int corner = 0; corner < mpoly->totloop; corner++) {
368                         const MLoop *loop = &mloop[poly->loopstart + corner];
369                         if (loop->v == vertex_index) {
370                                 manifold_vertex_faces[num++] = poly_index;
371                                 break;
372                         }
373                 }
374         }
375 #endif
376 }
377
378 static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter,
379                                      int manifold_vertex_index)
380 {
381         ConverterStorage *storage = converter->user_data;
382         const int vertex_index =
383                 storage->manifold_vertex_index_reverse[manifold_vertex_index];
384         return BLI_BITMAP_TEST_BOOL(storage->infinite_sharp_vertices_map,
385                                     vertex_index);
386 }
387
388 static int get_num_uv_layers(const OpenSubdiv_Converter *converter)
389 {
390         ConverterStorage *storage = converter->user_data;
391         const Mesh *mesh = storage->mesh;
392         return CustomData_number_of_layers(&mesh->ldata, CD_MLOOPUV);
393 }
394
395 static void precalc_uv_layer(const OpenSubdiv_Converter *converter,
396                              const int layer_index)
397 {
398         ConverterStorage *storage = converter->user_data;
399         const Mesh *mesh = storage->mesh;
400         const MPoly *mpoly = mesh->mpoly;
401         const MLoop *mloop = mesh->mloop;
402         const MLoopUV *mloopuv = CustomData_get_layer_n(
403                 &mesh->ldata, CD_MLOOPUV, layer_index);
404         const int num_poly = mesh->totpoly;
405         const int num_vert = mesh->totvert;
406         const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
407         /* Initialize memory required for the operations. */
408         if (storage->loop_uv_indices == NULL) {
409                 storage->loop_uv_indices = MEM_malloc_arrayN(
410                         mesh->totloop, sizeof(int), "loop uv vertex index");
411         }
412         UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(
413                 mpoly, mloop, mloopuv,
414                 num_poly, num_vert,
415                 limit,
416                 false, true);
417         /* NOTE: First UV vertex is supposed to be always marked as separate. */
418         storage->num_uv_coordinates = -1;
419         for (int vertex_index = 0; vertex_index < num_vert; ++vertex_index) {
420                 const UvMapVert *uv_vert = BKE_mesh_uv_vert_map_get_vert(uv_vert_map,
421                                                                          vertex_index);
422                 while (uv_vert != NULL) {
423                         if (uv_vert->separate) {
424                                 storage->num_uv_coordinates++;
425                         }
426                         const MPoly *mp = &mpoly[uv_vert->poly_index];
427                         const int global_loop_index = mp->loopstart +
428                                                       uv_vert->loop_of_poly_index;
429                         storage->loop_uv_indices[global_loop_index] =
430                                 storage->num_uv_coordinates;
431                         uv_vert = uv_vert->next;
432                 }
433         }
434         /* So far this value was used as a 0-based index, actual number of UV
435          * vertices is 1 more.
436          */
437         storage->num_uv_coordinates += 1;
438         BKE_mesh_uv_vert_map_free(uv_vert_map);
439 }
440
441 static void finish_uv_layer(const OpenSubdiv_Converter *UNUSED(converter))
442 {
443 }
444
445 static int get_num_uvs(const OpenSubdiv_Converter *converter)
446 {
447         ConverterStorage *storage = converter->user_data;
448         return storage->num_uv_coordinates;
449 }
450
451 static int get_face_corner_uv_index(const OpenSubdiv_Converter *converter,
452                                     const int face_index,
453                                     const int corner)
454 {
455         ConverterStorage *storage = converter->user_data;
456         const MPoly *mp = &storage->mesh->mpoly[face_index];
457         return storage->loop_uv_indices[mp->loopstart + corner];
458 }
459
460 static void free_user_data(const OpenSubdiv_Converter *converter)
461 {
462         ConverterStorage *user_data = converter->user_data;
463         MEM_SAFE_FREE(user_data->loop_uv_indices);
464 #ifdef USE_MESH_ELEMENT_MAPPING
465         MEM_freeN(user_data->vert_edge_map);
466         MEM_freeN(user_data->vert_edge_mem);
467         MEM_freeN(user_data->vert_poly_map);
468         MEM_freeN(user_data->vert_poly_mem);
469         MEM_freeN(user_data->edge_poly_map);
470         MEM_freeN(user_data->edge_poly_mem);
471 #endif
472         MEM_freeN(user_data->manifold_vertex_index);
473         MEM_freeN(user_data->manifold_edge_index);
474         MEM_freeN(user_data->infinite_sharp_vertices_map);
475         MEM_freeN(user_data->manifold_vertex_index_reverse);
476         MEM_freeN(user_data->manifold_edge_index_reverse);
477         MEM_freeN(user_data);
478 }
479
480 static void init_functions(OpenSubdiv_Converter *converter)
481 {
482         converter->getSchemeType = get_scheme_type;
483
484         converter->getFVarLinearInterpolation = get_fvar_linear_interpolation;
485
486         converter->getNumFaces = get_num_faces;
487         converter->getNumEdges = get_num_edges;
488         converter->getNumVertices = get_num_vertices;
489
490         converter->getNumFaceVertices = get_num_face_vertices;
491         converter->getFaceVertices = get_face_vertices;
492         converter->getFaceEdges = get_face_edges;
493
494         converter->getEdgeVertices = get_edge_vertices;
495         converter->getNumEdgeFaces = get_num_edge_faces;
496         converter->getEdgeFaces = get_edge_faces;
497         converter->getEdgeSharpness = get_edge_sharpness;
498
499         converter->getNumVertexEdges = get_num_vertex_edges;
500         converter->getVertexEdges = get_vertex_edges;
501         converter->getNumVertexFaces = get_num_vertex_faces;
502         converter->getVertexFaces = get_vertex_faces;
503         converter->isInfiniteSharpVertex = is_infinite_sharp_vertex;
504
505         converter->getNumUVLayers = get_num_uv_layers;
506         converter->precalcUVLayer = precalc_uv_layer;
507         converter->finishUVLayer = finish_uv_layer;
508         converter->getNumUVCoordinates = get_num_uvs;
509         converter->getFaceCornerUVIndex = get_face_corner_uv_index;
510
511         converter->freeUserData = free_user_data;
512 }
513
514 static void create_element_maps_if_needed(ConverterStorage *storage)
515 {
516 #ifdef USE_MESH_ELEMENT_MAPPING
517         const Mesh *mesh = storage->mesh;
518         BKE_mesh_vert_edge_map_create(&storage->vert_edge_map,
519                                       &storage->vert_edge_mem,
520                                       mesh->medge,
521                                       mesh->totvert,
522                                       mesh->totedge);
523         BKE_mesh_vert_poly_map_create(&storage->vert_poly_map,
524                                       &storage->vert_poly_mem,
525                                       mesh->mpoly,
526                                       mesh->mloop,
527                                       mesh->totvert,
528                                       mesh->totpoly,
529                                       mesh->totloop);
530         BKE_mesh_edge_poly_map_create(&storage->edge_poly_map,
531                                       &storage->edge_poly_mem,
532                                       mesh->medge, mesh->totedge,
533                                       mesh->mpoly, mesh->totpoly,
534                                       mesh->mloop, mesh->totloop);
535 #else
536         (void) storage;  /* Ignored. */
537 #endif
538 }
539
540 static void initialize_manifold_index_array(const BLI_bitmap *used_map,
541                                             const int num_elements,
542                                             int **indices_r,
543                                             int **indices_reverse_r,
544                                             int *num_manifold_elements_r)
545 {
546         int *indices = MEM_malloc_arrayN(
547                 num_elements, sizeof(int), "manifold indices");
548         int *indices_reverse = MEM_malloc_arrayN(
549                 num_elements, sizeof(int), "manifold indices reverse");
550         int offset = 0;
551         for (int i = 0; i < num_elements; i++) {
552                 if (BLI_BITMAP_TEST_BOOL(used_map, i)) {
553                         indices[i] = i - offset;
554                         indices_reverse[i - offset] = i;
555                 }
556                 else {
557                         indices[i] = -1;
558                         offset++;
559                 }
560         }
561         *indices_r = indices;
562         *indices_reverse_r = indices_reverse;
563         *num_manifold_elements_r = num_elements - offset;
564 }
565
566 static void initialize_manifold_indices(ConverterStorage *storage)
567 {
568         const Mesh *mesh = storage->mesh;
569         const MEdge *medge = mesh->medge;
570         const MLoop *mloop = mesh->mloop;
571         const MPoly *mpoly = mesh->mpoly;
572         /* Set bits of elements which are not loose. */
573         BLI_bitmap *vert_used_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map");
574         BLI_bitmap *edge_used_map = BLI_BITMAP_NEW(mesh->totedge, "edge used map");
575         for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
576                 const MPoly *poly = &mpoly[poly_index];
577                 for (int corner = 0; corner < poly->totloop; corner++) {
578                         const MLoop *loop = &mloop[poly->loopstart + corner];
579                         BLI_BITMAP_ENABLE(vert_used_map, loop->v);
580                         BLI_BITMAP_ENABLE(edge_used_map, loop->e);
581                 }
582         }
583         initialize_manifold_index_array(vert_used_map,
584                                         mesh->totvert,
585                                         &storage->manifold_vertex_index,
586                                         &storage->manifold_vertex_index_reverse,
587                                         &storage->num_manifold_vertices);
588         initialize_manifold_index_array(edge_used_map,
589                                         mesh->totedge,
590                                         &storage->manifold_edge_index,
591                                         &storage->manifold_edge_index_reverse,
592                                         &storage->num_manifold_edges);
593         /* Initialize infinite sharp mapping. */
594         storage->infinite_sharp_vertices_map =
595                 BLI_BITMAP_NEW(mesh->totvert, "vert used map");
596         for (int edge_index = 0; edge_index < mesh->totedge; edge_index++) {
597                 if (!BLI_BITMAP_TEST_BOOL(edge_used_map, edge_index)) {
598                         const MEdge *edge = &medge[edge_index];
599                         BLI_BITMAP_ENABLE(storage->infinite_sharp_vertices_map, edge->v1);
600                         BLI_BITMAP_ENABLE(storage->infinite_sharp_vertices_map, edge->v2);
601                 }
602         }
603         /* Free working variables. */
604         MEM_freeN(vert_used_map);
605         MEM_freeN(edge_used_map);
606 }
607
608 static void init_user_data(OpenSubdiv_Converter *converter,
609                            const SubdivSettings *settings,
610                            const Mesh *mesh)
611 {
612         ConverterStorage *user_data =
613                  MEM_mallocN(sizeof(ConverterStorage), __func__);
614         user_data->settings = *settings;
615         user_data->mesh = mesh;
616         user_data->loop_uv_indices = NULL;
617         create_element_maps_if_needed(user_data);
618         initialize_manifold_indices(user_data);
619         converter->user_data = user_data;
620 }
621 #endif
622
623 void BKE_subdiv_converter_init_for_mesh(struct OpenSubdiv_Converter *converter,
624                                         const SubdivSettings *settings,
625                                         const Mesh *mesh)
626 {
627 #ifdef WITH_OPENSUBDIV
628         init_functions(converter);
629         init_user_data(converter, settings, mesh);
630 #else
631         UNUSED_VARS(converter, settings, mesh);
632 #endif
633 }