c4317f4d7409c9a5fd903ae082c88efabfbb3e73
[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 } ConvDMStorage;
66
67 static OpenSubdiv_SchemeType conv_dm_get_type(
68         const OpenSubdiv_Converter *converter)
69 {
70         ConvDMStorage *storage = converter->user_data;
71         if (storage->ss->meshIFC.simpleSubdiv)
72                 return OSD_SCHEME_BILINEAR;
73         else
74                 return OSD_SCHEME_CATMARK;
75 }
76
77 static int conv_dm_get_num_faces(const OpenSubdiv_Converter *converter)
78 {
79         ConvDMStorage *storage = converter->user_data;
80         DerivedMesh *dm = storage->dm;
81         return dm->getNumPolys(dm);
82 }
83
84 static int conv_dm_get_num_edges(const OpenSubdiv_Converter *converter)
85 {
86         ConvDMStorage *storage = converter->user_data;
87         DerivedMesh *dm = storage->dm;
88         return dm->getNumEdges(dm);
89 }
90
91 static int conv_dm_get_num_verts(const OpenSubdiv_Converter *converter)
92 {
93         ConvDMStorage *storage = converter->user_data;
94         DerivedMesh *dm = storage->dm;
95         return dm->getNumVerts(dm);
96 }
97
98 static int conv_dm_get_num_face_verts(const OpenSubdiv_Converter *converter,
99                                       int face)
100 {
101         ConvDMStorage *storage = converter->user_data;
102         DerivedMesh *dm = storage->dm;
103         const MPoly *mp = dm->getPolyArray(dm);
104         const MPoly *mpoly = &mp[face];
105         return mpoly->totloop;
106 }
107
108 static void conv_dm_get_face_verts(const OpenSubdiv_Converter *converter,
109                                    int face,
110                                    int *face_verts)
111 {
112         ConvDMStorage *storage = converter->user_data;
113         DerivedMesh *dm = storage->dm;
114         const MLoop *ml = dm->getLoopArray(dm);
115         const MPoly *mp = dm->getPolyArray(dm);
116         const MPoly *mpoly = &mp[face];
117         int loop;
118         for (loop = 0; loop < mpoly->totloop; loop++) {
119                 face_verts[loop] = ml[mpoly->loopstart + loop].v;
120         }
121 }
122
123 static void conv_dm_get_face_edges(const OpenSubdiv_Converter *converter,
124                                    int face,
125                                    int *face_edges)
126 {
127         ConvDMStorage *storage = converter->user_data;
128         DerivedMesh *dm = storage->dm;
129         const MLoop *ml = dm->getLoopArray(dm);
130         const MPoly *mp = dm->getPolyArray(dm);
131         const MPoly *mpoly = &mp[face];
132         int loop;
133         for (loop = 0; loop < mpoly->totloop; loop++) {
134                 face_edges[loop] = ml[mpoly->loopstart + loop].e;
135         }
136 }
137
138 static void conv_dm_get_edge_verts(const OpenSubdiv_Converter *converter,
139                                    int edge,
140                                    int *edge_verts)
141 {
142         ConvDMStorage *storage = converter->user_data;
143         DerivedMesh *dm = storage->dm;
144         const MEdge *me = dm->getEdgeArray(dm);
145         const MEdge *medge = &me[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         const MLoop *ml = dm->getLoopArray(dm);
157         const MPoly *mp = dm->getPolyArray(dm);
158         int num = 0, poly;
159         for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
160                 const MPoly *mpoly = &mp[poly];
161                 int loop;
162                 for (loop = 0; loop < mpoly->totloop; loop++) {
163                         const MLoop *mloop = &ml[mpoly->loopstart + loop];
164                         if (mloop->e == edge) {
165                                 ++num;
166                                 break;
167                         }
168                 }
169         }
170         return num;
171 #else
172         return storage->edge_poly_map[edge].count;
173 #endif
174 }
175
176 static void conv_dm_get_edge_faces(const OpenSubdiv_Converter *converter,
177                                    int edge,
178                                    int *edge_faces)
179 {
180         ConvDMStorage *storage = converter->user_data;
181 #ifndef USE_MESH_ELEMENT_MAPPING
182         DerivedMesh *dm = storage->dm;
183         const MLoop *ml = dm->getLoopArray(dm);
184         const MPoly *mp = dm->getPolyArray(dm);
185         int num = 0, poly;
186         for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
187                 const MPoly *mpoly = &mp[poly];
188                 int loop;
189                 for (loop = 0; loop < mpoly->totloop; loop++) {
190                         const MLoop *mloop = &ml[mpoly->loopstart + loop];
191                         if (mloop->e == edge) {
192                                 edge_faces[num++] = poly;
193                                 break;
194                         }
195                 }
196         }
197 #else
198         memcpy(edge_faces,
199                storage->edge_poly_map[edge].indices,
200                sizeof(int) * storage->edge_poly_map[edge].count);
201 #endif
202 }
203
204 static float conv_dm_get_edge_sharpness(const OpenSubdiv_Converter *converter,
205                                         int edge)
206 {
207         ConvDMStorage *storage = converter->user_data;
208         DerivedMesh *dm = storage->dm;
209         CCGSubSurf *ss = storage->ss;
210         const MEdge *medge = dm->getEdgeArray(dm);
211         return (float)medge[edge].crease / 255.0f * ss->subdivLevels;
212 }
213
214 static int conv_dm_get_num_vert_edges(const OpenSubdiv_Converter *converter,
215                                       int vert)
216 {
217         ConvDMStorage *storage = converter->user_data;
218 #ifndef USE_MESH_ELEMENT_MAPPING
219         DerivedMesh *dm = storage->dm;
220         const MEdge *me = dm->getEdgeArray(dm);
221         int num = 0, edge;
222         for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
223                 const MEdge *medge = &me[edge];
224                 if (medge->v1 == vert || medge->v2 == vert) {
225                         ++num;
226                 }
227         }
228         return num;
229 #else
230         return storage->vert_edge_map[vert].count;
231 #endif
232 }
233
234 static void conv_dm_get_vert_edges(const OpenSubdiv_Converter *converter,
235                                    int vert,
236                                    int *vert_edges)
237 {
238         ConvDMStorage *storage = converter->user_data;
239 #ifndef USE_MESH_ELEMENT_MAPPING
240         DerivedMesh *dm = storage->dm;
241         const MEdge *me = dm->getEdgeArray(dm);
242         int num = 0, edge;
243         for (edge = 0; edge < dm->getNumEdges(dm); edge++) {
244                 const MEdge *medge = &me[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         const MLoop *ml = dm->getLoopArray(dm);
263         const MPoly *mp = dm->getPolyArray(dm);
264         int num = 0, poly;
265         for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
266                 const MPoly *mpoly = &mp[poly];
267                 int loop;
268                 for (loop = 0; loop < mpoly->totloop; loop++) {
269                         const MLoop *mloop = &ml[mpoly->loopstart + loop];
270                         if (mloop->v == vert) {
271                                 ++num;
272                                 break;
273                         }
274                 }
275         }
276         return num;
277 #else
278         return storage->vert_poly_map[vert].count;
279 #endif
280 }
281
282 static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter,
283                                    int vert,
284                                    int *vert_faces)
285 {
286         ConvDMStorage *storage = converter->user_data;
287 #ifndef USE_MESH_ELEMENT_MAPPING
288         DerivedMesh *dm = storage->dm;
289         const MLoop *ml = dm->getLoopArray(dm);
290         const MPoly *mp = dm->getPolyArray(dm);
291         int num = 0, poly;
292         for (poly = 0; poly < dm->getNumPolys(dm); poly++) {
293                 const MPoly *mpoly = &mp[poly];
294                 int loop;
295                 for (loop = 0; loop < mpoly->totloop; loop++) {
296                         const MLoop *mloop = &ml[mpoly->loopstart + loop];
297                         if (mloop->v == vert) {
298                                 vert_faces[num++] = poly;
299                                 break;
300                         }
301                 }
302         }
303 #else
304         memcpy(vert_faces,
305                storage->vert_poly_map[vert].indices,
306                sizeof(int) * storage->vert_poly_map[vert].count);
307 #endif
308 }
309
310 static void conv_dm_free_user_data(const OpenSubdiv_Converter *converter)
311 {
312         ConvDMStorage *user_data = converter->user_data;
313 #ifdef USE_MESH_ELEMENT_MAPPING
314         MEM_freeN(user_data->vert_edge_map);
315         MEM_freeN(user_data->vert_edge_mem);
316         MEM_freeN(user_data->vert_poly_map);
317         MEM_freeN(user_data->vert_poly_mem);
318         MEM_freeN(user_data->edge_poly_map);
319         MEM_freeN(user_data->edge_poly_mem);
320 #endif
321         MEM_freeN(user_data);
322 }
323
324 void ccgSubSurf_converter_setup_from_derivedmesh(
325         CCGSubSurf *ss,
326         DerivedMesh *dm,
327         OpenSubdiv_Converter *converter)
328 {
329         ConvDMStorage *user_data;
330
331         converter->get_type = conv_dm_get_type;
332
333         converter->get_num_faces = conv_dm_get_num_faces;
334         converter->get_num_edges = conv_dm_get_num_edges;
335         converter->get_num_verts = conv_dm_get_num_verts;
336
337         converter->get_num_face_verts = conv_dm_get_num_face_verts;
338         converter->get_face_verts = conv_dm_get_face_verts;
339         converter->get_face_edges = conv_dm_get_face_edges;
340
341         converter->get_edge_verts = conv_dm_get_edge_verts;
342         converter->get_num_edge_faces = conv_dm_get_num_edge_faces;
343         converter->get_edge_faces = conv_dm_get_edge_faces;
344         converter->get_edge_sharpness = conv_dm_get_edge_sharpness;
345
346         converter->get_num_vert_edges = conv_dm_get_num_vert_edges;
347         converter->get_vert_edges = conv_dm_get_vert_edges;
348         converter->get_num_vert_faces = conv_dm_get_num_vert_faces;
349         converter->get_vert_faces = conv_dm_get_vert_faces;
350
351         user_data = MEM_mallocN(sizeof(ConvDMStorage), __func__);
352         user_data->ss = ss;
353         user_data->dm = dm;
354         converter->free_user_data = conv_dm_free_user_data;
355         converter->user_data = user_data;
356
357 #ifdef USE_MESH_ELEMENT_MAPPING
358         {
359                 const MEdge *medge = dm->getEdgeArray(dm);
360                 const MLoop *mloop = dm->getLoopArray(dm);
361                 const MPoly *mpoly = dm->getPolyArray(dm);
362                 const int num_vert = dm->getNumVerts(dm),
363                           num_edge = dm->getNumEdges(dm),
364                           num_loop = dm->getNumLoops(dm),
365                           num_poly = dm->getNumPolys(dm);
366                 BKE_mesh_vert_edge_map_create(&user_data->vert_edge_map,
367                                               &user_data->vert_edge_mem,
368                                               medge,
369                                               num_vert,
370                                               num_edge);
371
372                 BKE_mesh_vert_poly_map_create(&user_data->vert_poly_map,
373                                               &user_data->vert_poly_mem,
374                                               mpoly,
375                                               mloop,
376                                               num_vert,
377                                               num_poly,
378                                               num_loop);
379
380                 BKE_mesh_edge_poly_map_create(&user_data->edge_poly_map,
381                                               &user_data->edge_poly_mem,
382                                               medge,
383                                               num_edge,
384                                               mpoly,
385                                               num_poly,
386                                               mloop,
387                                               num_loop);
388         }
389 #endif  /* USE_MESH_ELEMENT_MAPPING */
390 }
391
392 /**
393  * Converter from CCGSubSurf
394  */
395
396 static OpenSubdiv_SchemeType conv_ccg_get_bilinear_type(
397         const OpenSubdiv_Converter *converter)
398 {
399         CCGSubSurf *ss = converter->user_data;
400         if (ss->meshIFC.simpleSubdiv) {
401                 return OSD_SCHEME_BILINEAR;
402         }
403         else {
404                 return OSD_SCHEME_CATMARK;
405         }
406 }
407
408 static int conv_ccg_get_num_faces(const OpenSubdiv_Converter *converter)
409 {
410         CCGSubSurf *ss = converter->user_data;
411         return ss->fMap->numEntries;
412 }
413
414 static int conv_ccg_get_num_edges(const OpenSubdiv_Converter *converter)
415 {
416         CCGSubSurf *ss = converter->user_data;
417         return ss->eMap->numEntries;
418 }
419
420 static int conv_ccg_get_num_verts(const OpenSubdiv_Converter *converter)
421 {
422         CCGSubSurf *ss = converter->user_data;
423         return ss->vMap->numEntries;
424 }
425
426 static int conv_ccg_get_num_face_verts(const OpenSubdiv_Converter *converter,
427                                        int face)
428 {
429         CCGSubSurf *ss = converter->user_data;
430         CCGFace *ccg_face = ccgSubSurf_getFace(ss, SET_INT_IN_POINTER(face));
431         return ccgSubSurf_getFaceNumVerts(ccg_face);
432 }
433
434 static void conv_ccg_get_face_verts(const OpenSubdiv_Converter *converter,
435                                     int face,
436                                     int *face_verts)
437 {
438         CCGSubSurf *ss = converter->user_data;
439         CCGFace *ccg_face = ccgSubSurf_getFace(ss, SET_INT_IN_POINTER(face));
440         int num_face_verts = ccgSubSurf_getFaceNumVerts(ccg_face);
441         int loop;
442         for (loop = 0; loop < num_face_verts; loop++) {
443                 CCGVert *ccg_vert = ccgSubSurf_getFaceVert(ccg_face, loop);
444                 face_verts[loop] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert));
445         }
446 }
447
448 static void conv_ccg_get_face_edges(const OpenSubdiv_Converter *converter,
449                                     int face,
450                                     int *face_edges)
451 {
452         CCGSubSurf *ss = converter->user_data;
453         CCGFace *ccg_face = ccgSubSurf_getFace(ss, SET_INT_IN_POINTER(face));
454         int num_face_verts = ccgSubSurf_getFaceNumVerts(ccg_face);
455         int loop;
456         for (loop = 0; loop < num_face_verts; loop++) {
457                 CCGEdge *ccg_edge = ccgSubSurf_getFaceEdge(ccg_face, loop);
458                 face_edges[loop] = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ccg_edge));
459         }
460 }
461
462 static void conv_ccg_get_edge_verts(const OpenSubdiv_Converter *converter,
463                                     int edge,
464                                     int *edge_verts)
465 {
466         CCGSubSurf *ss = converter->user_data;
467         CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, SET_INT_IN_POINTER(edge));
468         CCGVert *ccg_vert0 = ccgSubSurf_getEdgeVert0(ccg_edge);
469         CCGVert *ccg_vert1 = ccgSubSurf_getEdgeVert1(ccg_edge);
470         edge_verts[0] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert0));
471         edge_verts[1] = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(ccg_vert1));
472 }
473
474 static int conv_ccg_get_num_edge_faces(const OpenSubdiv_Converter *converter,
475                                        int edge)
476 {
477         CCGSubSurf *ss = converter->user_data;
478         CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, SET_INT_IN_POINTER(edge));
479         return ccgSubSurf_getEdgeNumFaces(ccg_edge);
480 }
481
482 static void conv_ccg_get_edge_faces(const OpenSubdiv_Converter *converter,
483                                     int edge,
484                                     int *edge_faces)
485 {
486         CCGSubSurf *ss = converter->user_data;
487         CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, SET_INT_IN_POINTER(edge));
488         int num_edge_faces = ccgSubSurf_getEdgeNumFaces(ccg_edge);
489         int face;
490         for (face = 0; face < num_edge_faces; face++) {
491                 CCGFace *ccg_face = ccgSubSurf_getEdgeFace(ccg_edge, face);
492                 edge_faces[face] = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ccg_face));
493         }
494 }
495
496 static float conv_ccg_get_edge_sharpness(const OpenSubdiv_Converter *converter,
497                                          int edge)
498 {
499         CCGSubSurf *ss = converter->user_data;
500         CCGEdge *ccg_edge = ccgSubSurf_getEdge(ss, SET_INT_IN_POINTER(edge));
501         /* TODO(sergey): Multiply by subdivision level once CPU evaluator
502          * is switched to uniform subdivision type.
503          */
504         return ccg_edge->crease;
505 }
506
507 static int conv_ccg_get_num_vert_edges(const OpenSubdiv_Converter *converter,
508                                        int vert)
509 {
510         CCGSubSurf *ss = converter->user_data;
511         CCGVert *ccg_vert = ccgSubSurf_getVert(ss, SET_INT_IN_POINTER(vert));
512         return ccgSubSurf_getVertNumEdges(ccg_vert);
513 }
514
515 static void conv_ccg_get_vert_edges(const OpenSubdiv_Converter *converter,
516                                     int vert,
517                                     int *vert_edges)
518 {
519         CCGSubSurf *ss = converter->user_data;
520         CCGVert *ccg_vert = ccgSubSurf_getVert(ss, SET_INT_IN_POINTER(vert));
521         int num_vert_edges = ccgSubSurf_getVertNumEdges(ccg_vert);
522         int edge;
523         for (edge = 0; edge < num_vert_edges; edge++) {
524                 CCGEdge *ccg_edge = ccgSubSurf_getVertEdge(ccg_vert, edge);
525                 vert_edges[edge] = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ccg_edge));
526         }
527 }
528
529 static int conv_ccg_get_num_vert_faces(const OpenSubdiv_Converter *converter,
530                                        int vert)
531 {
532         CCGSubSurf *ss = converter->user_data;
533         CCGVert *ccg_vert = ccgSubSurf_getVert(ss, SET_INT_IN_POINTER(vert));
534         return ccgSubSurf_getVertNumFaces(ccg_vert);
535 }
536
537 static void conv_ccg_get_vert_faces(const OpenSubdiv_Converter *converter,
538                                     int vert,
539                                     int *vert_faces)
540 {
541         CCGSubSurf *ss = converter->user_data;
542         CCGVert *ccg_vert = ccgSubSurf_getVert(ss, SET_INT_IN_POINTER(vert));
543         int num_vert_faces = ccgSubSurf_getVertNumFaces(ccg_vert);
544         int face;
545         for (face = 0; face < num_vert_faces; face++) {
546                 CCGFace *ccg_face = ccgSubSurf_getVertFace(ccg_vert, face);
547                 vert_faces[face] = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ccg_face));
548         }
549 }
550
551 void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss,
552                                          OpenSubdiv_Converter *converter)
553 {
554         converter->get_type = conv_ccg_get_bilinear_type;
555
556         converter->get_num_faces = conv_ccg_get_num_faces;
557         converter->get_num_edges = conv_ccg_get_num_edges;
558         converter->get_num_verts = conv_ccg_get_num_verts;
559
560         converter->get_num_face_verts = conv_ccg_get_num_face_verts;
561         converter->get_face_verts = conv_ccg_get_face_verts;
562         converter->get_face_edges = conv_ccg_get_face_edges;
563
564         converter->get_edge_verts = conv_ccg_get_edge_verts;
565         converter->get_num_edge_faces = conv_ccg_get_num_edge_faces;
566         converter->get_edge_faces = conv_ccg_get_edge_faces;
567         converter->get_edge_sharpness = conv_ccg_get_edge_sharpness;
568
569         converter->get_num_vert_edges = conv_ccg_get_num_vert_edges;
570         converter->get_vert_edges = conv_ccg_get_vert_edges;
571         converter->get_num_vert_faces = conv_ccg_get_num_vert_faces;
572         converter->get_vert_faces = conv_ccg_get_vert_faces;
573
574         converter->free_user_data = NULL;
575         converter->user_data = ss;
576 }
577
578 void ccgSubSurf_converter_free(
579         struct OpenSubdiv_Converter *converter)
580 {
581         if (converter->free_user_data) {
582                 converter->free_user_data(converter);
583         }
584 }
585
586 #endif  /* WITH_OPENSUBDIV */