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