OpenSubdiv: Properly respect Subdivide UVs option
[blender.git] / source / blender / blenkernel / intern / CCGSubSurf_opensubdiv_converter.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  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c
22  *  \ingroup bke
23  */
24
25 #ifdef WITH_OPENSUBDIV
26
27 #include <stdlib.h>
28
29 #include "MEM_guardedalloc.h"
30 #include "BLI_sys_types.h" // for intptr_t support
31
32 #include "BLI_utildefines.h" /* for BLI_assert */
33 #include "BLI_math.h"
34
35 #include "CCGSubSurf.h"
36 #include "CCGSubSurf_intern.h"
37
38 #include "BKE_DerivedMesh.h"
39 #include "BKE_mesh_mapping.h"
40
41 #include "opensubdiv_capi.h"
42 #include "opensubdiv_converter_capi.h"
43
44 /* Use mesh element mapping structures during conversion.
45  * Uses more memory but is much faster than naive algorithm.
46  */
47 #define USE_MESH_ELEMENT_MAPPING
48
49 /**
50  * Converter from DerivedMesh.
51  */
52
53 typedef struct ConvDMStorage {
54         CCGSubSurf *ss;
55         DerivedMesh *dm;
56
57 #ifdef USE_MESH_ELEMENT_MAPPING
58         MeshElemMap *vert_edge_map,
59                     *vert_poly_map,
60                     *edge_poly_map;
61         int *vert_edge_mem,
62             *vert_poly_mem,
63             *edge_poly_mem;
64 #endif
65
66         MVert *mvert;
67         MEdge *medge;
68         MLoop *mloop;
69         MPoly *mpoly;
70
71         MeshIslandStore island_store;
72         int num_uvs;
73         float *uvs;
74         int *face_uvs;
75 } ConvDMStorage;
76
77 static OpenSubdiv_SchemeType conv_dm_get_type(
78         const OpenSubdiv_Converter *converter)
79 {
80         ConvDMStorage *storage = converter->user_data;
81         if (storage->ss->meshIFC.simpleSubdiv)
82                 return OSD_SCHEME_BILINEAR;
83         else
84                 return OSD_SCHEME_CATMARK;
85 }
86
87 static bool conv_dm_get_subdiv_uvs(
88         const OpenSubdiv_Converter *converter)
89 {
90         ConvDMStorage *storage = converter->user_data;
91         return (storage->ss->osd_subdiv_uvs);
92 }
93
94 static int conv_dm_get_num_faces(const OpenSubdiv_Converter *converter)
95 {
96         ConvDMStorage *storage = converter->user_data;
97         DerivedMesh *dm = storage->dm;
98         return dm->getNumPolys(dm);
99 }
100
101 static int conv_dm_get_num_edges(const OpenSubdiv_Converter *converter)
102 {
103         ConvDMStorage *storage = converter->user_data;
104         DerivedMesh *dm = storage->dm;
105         return dm->getNumEdges(dm);
106 }
107
108 static int conv_dm_get_num_verts(const OpenSubdiv_Converter *converter)
109 {
110         ConvDMStorage *storage = converter->user_data;
111         DerivedMesh *dm = storage->dm;
112         return dm->getNumVerts(dm);
113 }
114
115 static int conv_dm_get_num_face_verts(const OpenSubdiv_Converter *converter,
116                                       int face)
117 {
118         ConvDMStorage *storage = converter->user_data;
119         const MPoly *mpoly = &storage->mpoly[face];
120         return mpoly->totloop;
121 }
122
123 static void conv_dm_get_face_verts(const OpenSubdiv_Converter *converter,
124                                    int face,
125                                    int *face_verts)
126 {
127         ConvDMStorage *storage = converter->user_data;
128         const MPoly *mpoly = &storage->mpoly[face];
129         int loop;
130         for (loop = 0; loop < mpoly->totloop; loop++) {
131                 face_verts[loop] = storage->mloop[mpoly->loopstart + loop].v;
132         }
133 }
134
135 static void conv_dm_get_face_edges(const OpenSubdiv_Converter *converter,
136                                    int face,
137                                    int *face_edges)
138 {
139         ConvDMStorage *storage = converter->user_data;
140         const MPoly *mpoly = &storage->mpoly[face];
141         int loop;
142         for (loop = 0; loop < mpoly->totloop; loop++) {
143                 face_edges[loop] = storage->mloop[mpoly->loopstart + loop].e;
144         }
145 }
146
147 static void conv_dm_get_edge_verts(const OpenSubdiv_Converter *converter,
148                                    int edge,
149                                    int *edge_verts)
150 {
151         ConvDMStorage *storage = converter->user_data;
152         const MEdge *medge = &storage->medge[edge];
153         edge_verts[0] = medge->v1;
154         edge_verts[1] = medge->v2;
155 }
156
157 static int conv_dm_get_num_edge_faces(const OpenSubdiv_Converter *converter,
158                                       int edge)
159 {
160         ConvDMStorage *storage = converter->user_data;
161 #ifndef USE_MESH_ELEMENT_MAPPING
162         DerivedMesh *dm = storage->dm;
163         int num = 0, poly;
164         for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
165                 const MPoly *mpoly = &user_data->mpoly[poly];
166                 int loop;
167                 for (loop = 0; loop < mpoly->totloop; loop++) {
168                         const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
169                         if (mloop->e == edge) {
170                                 ++num;
171                                 break;
172                         }
173                 }
174         }
175         return num;
176 #else
177         return storage->edge_poly_map[edge].count;
178 #endif
179 }
180
181 static void conv_dm_get_edge_faces(const OpenSubdiv_Converter *converter,
182                                    int edge,
183                                    int *edge_faces)
184 {
185         ConvDMStorage *storage = converter->user_data;
186 #ifndef USE_MESH_ELEMENT_MAPPING
187         DerivedMesh *dm = storage->dm;
188         int num = 0, poly;
189         for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
190                 const MPoly *mpoly = &user_data->mpoly[poly];
191                 int loop;
192                 for (loop = 0; loop < mpoly->totloop; loop++) {
193                         const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
194                         if (mloop->e == edge) {
195                                 edge_faces[num++] = poly;
196                                 break;
197                         }
198                 }
199         }
200 #else
201         memcpy(edge_faces,
202                storage->edge_poly_map[edge].indices,
203                sizeof(int) * storage->edge_poly_map[edge].count);
204 #endif
205 }
206
207 static float conv_dm_get_edge_sharpness(const OpenSubdiv_Converter *converter,
208                                         int edge)
209 {
210         ConvDMStorage *storage = converter->user_data;
211         CCGSubSurf *ss = storage->ss;
212         const MEdge *medge = storage->medge;
213         return (float)medge[edge].crease / 255.0f * ss->subdivLevels;
214 }
215
216 static int conv_dm_get_num_vert_edges(const OpenSubdiv_Converter *converter,
217                                       int vert)
218 {
219         ConvDMStorage *storage = converter->user_data;
220 #ifndef USE_MESH_ELEMENT_MAPPING
221         DerivedMesh *dm = storage->dm;
222         int num = 0, edge;
223         for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
224                 const MEdge *medge = &user_data->medge[edge];
225                 if (medge->v1 == vert || medge->v2 == vert) {
226                         ++num;
227                 }
228         }
229         return num;
230 #else
231         return storage->vert_edge_map[vert].count;
232 #endif
233 }
234
235 static void conv_dm_get_vert_edges(const OpenSubdiv_Converter *converter,
236                                    int vert,
237                                    int *vert_edges)
238 {
239         ConvDMStorage *storage = converter->user_data;
240 #ifndef USE_MESH_ELEMENT_MAPPING
241         DerivedMesh *dm = storage->dm;
242         int num = 0, edge;
243         for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
244                 const MEdge *medge = &user_data->medge[edge];
245                 if (medge->v1 == vert || medge->v2 == vert) {
246                         vert_edges[num++] = edge;
247                 }
248         }
249 #else
250         memcpy(vert_edges,
251                storage->vert_edge_map[vert].indices,
252                sizeof(int) * storage->vert_edge_map[vert].count);
253 #endif
254 }
255
256 static int conv_dm_get_num_vert_faces(const OpenSubdiv_Converter *converter,
257                                       int vert)
258 {
259         ConvDMStorage *storage = converter->user_data;
260 #ifndef USE_MESH_ELEMENT_MAPPING
261         DerivedMesh *dm = storage->dm;
262         int num = 0, poly;
263         for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
264                 const MPoly *mpoly = &user_data->mpoly[poly];
265                 int loop;
266                 for (loop = 0; loop < mpoly->totloop; loop++) {
267                         const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
268                         if (mloop->v == vert) {
269                                 ++num;
270                                 break;
271                         }
272                 }
273         }
274         return num;
275 #else
276         return storage->vert_poly_map[vert].count;
277 #endif
278 }
279
280 static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter,
281                                    int vert,
282                                    int *vert_faces)
283 {
284         ConvDMStorage *storage = converter->user_data;
285 #ifndef USE_MESH_ELEMENT_MAPPING
286         DerivedMesh *dm = storage->dm;
287         int num = 0, poly;
288         for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
289                 const MPoly *mpoly = &storage->mpoly[poly];
290                 int loop;
291                 for (loop = 0; loop < mpoly->totloop; loop++) {
292                         const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop];
293                         if (mloop->v == vert) {
294                                 vert_faces[num++] = poly;
295                                 break;
296                         }
297                 }
298         }
299 #else
300         memcpy(vert_faces,
301                storage->vert_poly_map[vert].indices,
302                sizeof(int) * storage->vert_poly_map[vert].count);
303 #endif
304 }
305
306 static int conv_dm_get_num_uv_layers(const OpenSubdiv_Converter *converter)
307 {
308         ConvDMStorage *storage = converter->user_data;
309         DerivedMesh *dm = storage->dm;
310         int num_uv_layers = CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV);
311         return num_uv_layers;
312 }
313
314 static void conv_dm_precalc_uv_layer(const OpenSubdiv_Converter *converter,
315                                      int layer)
316 {
317         ConvDMStorage *storage = converter->user_data;
318         DerivedMesh *dm = storage->dm;
319
320         const MLoopUV *mloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer);
321         const int num_loops = dm->getNumLoops(dm);
322
323         /* Initialize memory required for the operations. */
324         if (storage->uvs == NULL) {
325                 storage->uvs = MEM_mallocN(sizeof(float) * 2 * num_loops, "osd uvs");
326         }
327         if (storage->face_uvs == NULL) {
328                 storage->face_uvs = MEM_mallocN(sizeof(int) * num_loops, "osd face uvs");
329         }
330
331         /* Calculate islands connectivity of the UVs. */
332         BKE_mesh_calc_islands_loop_poly_uvmap(
333                 storage->mvert, dm->getNumVerts(dm),
334                 storage->medge, dm->getNumEdges(dm),
335                 storage->mpoly, dm->getNumPolys(dm),
336                 storage->mloop, dm->getNumLoops(dm),
337                 mloopuv,
338                 &storage->island_store);
339
340         /* Here we "weld" duplicated vertices from island to the same UV value.
341          * The idea here is that we need to pass individual islands to OpenSubdiv.
342          */
343         storage->num_uvs = 0;
344         for (int island = 0; island < storage->island_store.islands_num; ++island) {
345                 MeshElemMap *island_poly_map = storage->island_store.islands[island];
346                 for (int poly = 0; poly < island_poly_map->count; ++poly) {
347                         int poly_index = island_poly_map->indices[poly];
348                         /* Within the same UV island we should share UV points across
349                          * loops. Otherwise each poly will be subdivided individually
350                          * which we don't really want.
351                          */
352                         const MPoly *mpoly = &storage->mpoly[poly_index];
353                         for (int loop = 0; loop < mpoly->totloop; ++loop) {
354                                 const MLoopUV *luv = &mloopuv[mpoly->loopstart + loop];
355                                 bool found = false;
356                                 /* TODO(sergey): Quite bad loop, which gives us O(N^2)
357                                  * complexity here. But how can we do it smarter, hopefully
358                                  * without requiring lots of additional memory.
359                                  */
360                                 for (int i = 0; i < storage->num_uvs; ++i) {
361                                         if (equals_v2v2(luv->uv, &storage->uvs[2 * i])) {
362                                                 storage->face_uvs[mpoly->loopstart + loop] = i;
363                                                 found = true;
364                                                 break;
365                                         }
366                                 }
367                                 if (!found) {
368                                         copy_v2_v2(&storage->uvs[2 * storage->num_uvs], luv->uv);
369                                         storage->face_uvs[mpoly->loopstart + loop] = storage->num_uvs;
370                                         ++storage->num_uvs;
371                                 }
372                         }
373                 }
374         }
375 }
376
377 static void conv_dm_finish_uv_layer(const OpenSubdiv_Converter *converter)
378 {
379         ConvDMStorage *storage = converter->user_data;
380         BKE_mesh_loop_islands_free(&storage->island_store);
381 }
382
383 static int conv_dm_get_num_uvs(const OpenSubdiv_Converter *converter)
384 {
385         ConvDMStorage *storage = converter->user_data;
386         return storage->num_uvs;
387 }
388
389 static void conv_dm_get_uvs(const OpenSubdiv_Converter *converter, float *uvs)
390 {
391         ConvDMStorage *storage = converter->user_data;
392         memcpy(uvs, storage->uvs, sizeof(float) * 2 * storage->num_uvs);
393 }
394
395 static int conv_dm_get_face_corner_uv_index(const OpenSubdiv_Converter *converter,
396                                             int face,
397                                             int corner)
398 {
399         ConvDMStorage *storage = converter->user_data;
400         const MPoly *mpoly = &storage->mpoly[face];
401         return storage->face_uvs[mpoly->loopstart + corner];
402 }
403
404 static void conv_dm_free_user_data(const OpenSubdiv_Converter *converter)
405 {
406         ConvDMStorage *user_data = converter->user_data;
407         if (user_data->uvs != NULL) {
408                 MEM_freeN(user_data->uvs);
409         }
410         if (user_data->face_uvs != NULL) {
411                 MEM_freeN(user_data->face_uvs);
412         }
413
414 #ifdef USE_MESH_ELEMENT_MAPPING
415         MEM_freeN(user_data->vert_edge_map);
416         MEM_freeN(user_data->vert_edge_mem);
417         MEM_freeN(user_data->vert_poly_map);
418         MEM_freeN(user_data->vert_poly_mem);
419         MEM_freeN(user_data->edge_poly_map);
420         MEM_freeN(user_data->edge_poly_mem);
421 #endif
422         MEM_freeN(user_data);
423 }
424
425 void ccgSubSurf_converter_setup_from_derivedmesh(
426         CCGSubSurf *ss,
427         DerivedMesh *dm,
428         OpenSubdiv_Converter *converter)
429 {
430         ConvDMStorage *user_data;
431
432         converter->get_type = conv_dm_get_type;
433
434         converter->get_subdiv_uvs = conv_dm_get_subdiv_uvs;
435
436         converter->get_num_faces = conv_dm_get_num_faces;
437         converter->get_num_edges = conv_dm_get_num_edges;
438         converter->get_num_verts = conv_dm_get_num_verts;
439
440         converter->get_num_face_verts = conv_dm_get_num_face_verts;
441         converter->get_face_verts = conv_dm_get_face_verts;
442         converter->get_face_edges = conv_dm_get_face_edges;
443
444         converter->get_edge_verts = conv_dm_get_edge_verts;
445         converter->get_num_edge_faces = conv_dm_get_num_edge_faces;
446         converter->get_edge_faces = conv_dm_get_edge_faces;
447         converter->get_edge_sharpness = conv_dm_get_edge_sharpness;
448
449         converter->get_num_vert_edges = conv_dm_get_num_vert_edges;
450         converter->get_vert_edges = conv_dm_get_vert_edges;
451         converter->get_num_vert_faces = conv_dm_get_num_vert_faces;
452         converter->get_vert_faces = conv_dm_get_vert_faces;
453
454         converter->get_num_uv_layers = conv_dm_get_num_uv_layers;
455         converter->precalc_uv_layer = conv_dm_precalc_uv_layer;
456         converter->finish_uv_layer = conv_dm_finish_uv_layer;
457         converter->get_num_uvs = conv_dm_get_num_uvs;
458         converter->get_uvs = conv_dm_get_uvs;
459         converter->get_face_corner_uv_index = conv_dm_get_face_corner_uv_index;
460
461         user_data = MEM_mallocN(sizeof(ConvDMStorage), __func__);
462         user_data->ss = ss;
463         user_data->dm = dm;
464
465         user_data->mvert = dm->getVertArray(dm);
466         user_data->medge = dm->getEdgeArray(dm);
467         user_data->mloop = dm->getLoopArray(dm);
468         user_data->mpoly = dm->getPolyArray(dm);
469
470         memset(&user_data->island_store, 0, sizeof(user_data->island_store));
471
472         user_data->uvs = NULL;
473         user_data->face_uvs = NULL;
474
475         converter->free_user_data = conv_dm_free_user_data;
476         converter->user_data = user_data;
477
478 #ifdef USE_MESH_ELEMENT_MAPPING
479         {
480                 const MEdge *medge = dm->getEdgeArray(dm);
481                 const MLoop *mloop = dm->getLoopArray(dm);
482                 const MPoly *mpoly = dm->getPolyArray(dm);
483                 const int num_vert = dm->getNumVerts(dm),
484                           num_edge = dm->getNumEdges(dm),
485                           num_loop = dm->getNumLoops(dm),
486                           num_poly = dm->getNumPolys(dm);
487                 BKE_mesh_vert_edge_map_create(&user_data->vert_edge_map,
488                                               &user_data->vert_edge_mem,
489                                               medge,
490                                               num_vert,
491                                               num_edge);
492
493                 BKE_mesh_vert_poly_map_create(&user_data->vert_poly_map,
494                                               &user_data->vert_poly_mem,
495                                               mpoly,
496                                               mloop,
497                                               num_vert,
498                                               num_poly,
499                                               num_loop);
500
501                 BKE_mesh_edge_poly_map_create(&user_data->edge_poly_map,
502                                               &user_data->edge_poly_mem,
503                                               medge,
504                                               num_edge,
505                                               mpoly,
506                                               num_poly,
507                                               mloop,
508                                               num_loop);
509         }
510 #endif  /* USE_MESH_ELEMENT_MAPPING */
511 }
512
513 /**
514  * Converter from CCGSubSurf
515  */
516
517 static OpenSubdiv_SchemeType conv_ccg_get_bilinear_type(
518         const OpenSubdiv_Converter *converter)
519 {
520         CCGSubSurf *ss = converter->user_data;
521         if (ss->meshIFC.simpleSubdiv) {
522                 return OSD_SCHEME_BILINEAR;
523         }
524         else {
525                 return OSD_SCHEME_CATMARK;
526         }
527 }
528
529 static bool conv_ccg_get_subdiv_uvs(
530         const OpenSubdiv_Converter *converter)
531 {
532         CCGSubSurf *ss = converter->user_data;
533         return (ss->osd_subdiv_uvs);
534 }
535
536 static int conv_ccg_get_num_faces(const OpenSubdiv_Converter *converter)
537 {
538         CCGSubSurf *ss = converter->user_data;
539         return ss->fMap->numEntries;
540 }
541
542 static int conv_ccg_get_num_edges(const OpenSubdiv_Converter *converter)
543 {
544         CCGSubSurf *ss = converter->user_data;
545         return ss->eMap->numEntries;
546 }
547
548 static int conv_ccg_get_num_verts(const OpenSubdiv_Converter *converter)
549 {
550         CCGSubSurf *ss = converter->user_data;
551         return ss->vMap->numEntries;
552 }
553
554 static int conv_ccg_get_num_face_verts(const OpenSubdiv_Converter *converter,
555                                        int face)
556 {
557         CCGSubSurf *ss = converter->user_data;
558         CCGFace *ccg_face = ccgSubSurf_getFace(ss, SET_INT_IN_POINTER(face));
559         return ccgSubSurf_getFaceNumVerts(ccg_face);
560 }
561
562 static void conv_ccg_get_face_verts(const OpenSubdiv_Converter *converter,
563                                     int face,
564                                     int *face_verts)
565 {
566         CCGSubSurf *ss = converter->user_data;
567         CCGFace *ccg_face = ccgSubSurf_getFace(ss, SET_INT_IN_POINTER(face));
568         int num_face_verts = ccgSubSurf_getFaceNumVerts(ccg_face);
569         int loop;
570         for (loop = 0; loop < num_face_verts; loop++) {
571                 CCGVert *ccg_vert = ccgSubSurf_getFaceVert(ccg_face, loop);
572                 face_verts[loop] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert));
573         }
574 }
575
576 static void conv_ccg_get_face_edges(const OpenSubdiv_Converter *converter,
577                                     int face,
578                                     int *face_edges)
579 {
580         CCGSubSurf *ss = converter->user_data;
581         CCGFace *ccg_face = ccgSubSurf_getFace(ss, SET_INT_IN_POINTER(face));
582         int num_face_verts = ccgSubSurf_getFaceNumVerts(ccg_face);
583         int loop;
584         for (loop = 0; loop < num_face_verts; loop++) {
585                 CCGEdge *ccg_edge = ccgSubSurf_getFaceEdge(ccg_face, loop);
586                 face_edges[loop] = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ccg_edge));
587         }
588 }
589
590 static void conv_ccg_get_edge_verts(const OpenSubdiv_Converter *converter,
591                                     int edge,
592                                     int *edge_verts)
593 {
594         CCGSubSurf *ss = converter->user_data;
595         CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, SET_INT_IN_POINTER(edge));
596         CCGVert *ccg_vert0 = ccgSubSurf_getEdgeVert0(ccg_edge);
597         CCGVert *ccg_vert1 = ccgSubSurf_getEdgeVert1(ccg_edge);
598         edge_verts[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert0));
599         edge_verts[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert1));
600 }
601
602 static int conv_ccg_get_num_edge_faces(const OpenSubdiv_Converter *converter,
603                                        int edge)
604 {
605         CCGSubSurf *ss = converter->user_data;
606         CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, SET_INT_IN_POINTER(edge));
607         return ccgSubSurf_getEdgeNumFaces(ccg_edge);
608 }
609
610 static void conv_ccg_get_edge_faces(const OpenSubdiv_Converter *converter,
611                                     int edge,
612                                     int *edge_faces)
613 {
614         CCGSubSurf *ss = converter->user_data;
615         CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, SET_INT_IN_POINTER(edge));
616         int num_edge_faces = ccgSubSurf_getEdgeNumFaces(ccg_edge);
617         int face;
618         for (face = 0; face < num_edge_faces; face++) {
619                 CCGFace *ccg_face = ccgSubSurf_getEdgeFace(ccg_edge, face);
620                 edge_faces[face] = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ccg_face));
621         }
622 }
623
624 static float conv_ccg_get_edge_sharpness(const OpenSubdiv_Converter *converter,
625                                          int edge)
626 {
627         CCGSubSurf *ss = converter->user_data;
628         CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, SET_INT_IN_POINTER(edge));
629         /* TODO(sergey): Multiply by subdivision level once CPU evaluator
630          * is switched to uniform subdivision type.
631          */
632         return ccg_edge->crease;
633 }
634
635 static int conv_ccg_get_num_vert_edges(const OpenSubdiv_Converter *converter,
636                                        int vert)
637 {
638         CCGSubSurf *ss = converter->user_data;
639         CCGVert *ccg_vert = ccgSubSurf_getVert(ss, SET_INT_IN_POINTER(vert));
640         return ccgSubSurf_getVertNumEdges(ccg_vert);
641 }
642
643 static void conv_ccg_get_vert_edges(const OpenSubdiv_Converter *converter,
644                                     int vert,
645                                     int *vert_edges)
646 {
647         CCGSubSurf *ss = converter->user_data;
648         CCGVert *ccg_vert = ccgSubSurf_getVert(ss, SET_INT_IN_POINTER(vert));
649         int num_vert_edges = ccgSubSurf_getVertNumEdges(ccg_vert);
650         int edge;
651         for (edge = 0; edge < num_vert_edges; edge++) {
652                 CCGEdge *ccg_edge = ccgSubSurf_getVertEdge(ccg_vert, edge);
653                 vert_edges[edge] = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ccg_edge));
654         }
655 }
656
657 static int conv_ccg_get_num_vert_faces(const OpenSubdiv_Converter *converter,
658                                        int vert)
659 {
660         CCGSubSurf *ss = converter->user_data;
661         CCGVert *ccg_vert = ccgSubSurf_getVert(ss, SET_INT_IN_POINTER(vert));
662         return ccgSubSurf_getVertNumFaces(ccg_vert);
663 }
664
665 static void conv_ccg_get_vert_faces(const OpenSubdiv_Converter *converter,
666                                     int vert,
667                                     int *vert_faces)
668 {
669         CCGSubSurf *ss = converter->user_data;
670         CCGVert *ccg_vert = ccgSubSurf_getVert(ss, SET_INT_IN_POINTER(vert));
671         int num_vert_faces = ccgSubSurf_getVertNumFaces(ccg_vert);
672         int face;
673         for (face = 0; face < num_vert_faces; face++) {
674                 CCGFace *ccg_face = ccgSubSurf_getVertFace(ccg_vert, face);
675                 vert_faces[face] = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ccg_face));
676         }
677 }
678
679 static int conv_ccg_get_num_uv_layers(const OpenSubdiv_Converter *UNUSED(converter))
680 {
681         return 0;
682 }
683
684 static void conv_ccg_precalc_uv_layer(const OpenSubdiv_Converter * UNUSED(converter),
685                                       int UNUSED(layer))
686 {
687 }
688
689 static void conv_ccg_finish_uv_layer(const OpenSubdiv_Converter *UNUSED(converter))
690 {
691 }
692
693 static int conv_ccg_get_num_uvs(const OpenSubdiv_Converter *UNUSED(converter))
694 {
695         return 0;
696 }
697
698 static void conv_ccg_get_uvs(const OpenSubdiv_Converter * UNUSED(converter),
699                       float *UNUSED(uvs))
700 {
701 }
702
703 static int conv_ccg_get_face_corner_uv_index(const OpenSubdiv_Converter *UNUSED(converter),
704                                              int UNUSED(face),
705                                              int UNUSED(corner_))
706 {
707         return 0;
708 }
709
710 void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
711                                          OpenSubdiv_Converter *converter)
712 {
713         converter->get_type = conv_ccg_get_bilinear_type;
714
715         converter->get_subdiv_uvs = conv_ccg_get_subdiv_uvs;
716
717         converter->get_num_faces = conv_ccg_get_num_faces;
718         converter->get_num_edges = conv_ccg_get_num_edges;
719         converter->get_num_verts = conv_ccg_get_num_verts;
720
721         converter->get_num_face_verts = conv_ccg_get_num_face_verts;
722         converter->get_face_verts = conv_ccg_get_face_verts;
723         converter->get_face_edges = conv_ccg_get_face_edges;
724
725         converter->get_edge_verts = conv_ccg_get_edge_verts;
726         converter->get_num_edge_faces = conv_ccg_get_num_edge_faces;
727         converter->get_edge_faces = conv_ccg_get_edge_faces;
728         converter->get_edge_sharpness = conv_ccg_get_edge_sharpness;
729
730         converter->get_num_vert_edges = conv_ccg_get_num_vert_edges;
731         converter->get_vert_edges = conv_ccg_get_vert_edges;
732         converter->get_num_vert_faces = conv_ccg_get_num_vert_faces;
733         converter->get_vert_faces = conv_ccg_get_vert_faces;
734
735         converter->get_num_uv_layers = conv_ccg_get_num_uv_layers;
736         converter->precalc_uv_layer = conv_ccg_precalc_uv_layer;
737         converter->finish_uv_layer = conv_ccg_finish_uv_layer;
738         converter->get_num_uvs = conv_ccg_get_num_uvs;
739         converter->get_uvs = conv_ccg_get_uvs;
740         converter->get_face_corner_uv_index = conv_ccg_get_face_corner_uv_index;
741
742         converter->free_user_data = NULL;
743         converter->user_data = ss;
744 }
745
746 void ccgSubSurf_converter_free(
747         struct OpenSubdiv_Converter *converter)
748 {
749         if (converter->free_user_data) {
750                 converter->free_user_data(converter);
751         }
752 }
753
754 #endif  /* WITH_OPENSUBDIV */