Merge branch 'master' into blender2.8
[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_math_vector.h"
35
36 #include "BKE_customdata.h"
37 #include "BKE_mesh_mapping.h"
38 #include "BKE_subdiv.h"
39
40 #include "MEM_guardedalloc.h"
41
42 #ifdef WITH_OPENSUBDIV
43 #  include "opensubdiv_capi.h"
44 #  include "opensubdiv_converter_capi.h"
45 #endif
46
47 /* Use mesh element mapping structures during conversion.
48  * Uses more memory but is much faster than naive algorithm.
49  */
50 #define USE_MESH_ELEMENT_MAPPING
51
52 #ifdef WITH_OPENSUBDIV
53 typedef struct ConverterStorage {
54         SubdivSettings settings;
55         const Mesh *mesh;
56
57 #ifdef USE_MESH_ELEMENT_MAPPING
58         MeshElemMap *vert_edge_map;
59         MeshElemMap *vert_poly_map;
60         MeshElemMap *edge_poly_map;
61         int *vert_edge_mem;
62         int *vert_poly_mem;
63         int *edge_poly_mem;
64 #endif
65
66         /* Indexed by loop index, value denotes index of face-varying vertex
67          * which corresponds to the UV coordinate.
68          */
69         int *loop_uv_indices;
70         int num_uv_coordinates;
71 } ConverterStorage;
72
73 static OpenSubdiv_SchemeType get_scheme_type(
74         const OpenSubdiv_Converter *converter)
75 {
76         ConverterStorage *storage = converter->user_data;
77         if (storage->settings.is_simple) {
78                 return OSD_SCHEME_BILINEAR;
79         }
80         else {
81                 return OSD_SCHEME_CATMARK;
82         }
83 }
84
85 static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(
86         const OpenSubdiv_Converter *converter)
87 {
88         ConverterStorage *storage = converter->user_data;
89         return BKE_subdiv_converter_fvar_linear_from_settings(&storage->settings);
90 }
91
92 static int get_num_faces(const OpenSubdiv_Converter *converter)
93 {
94         ConverterStorage *storage = converter->user_data;
95         return storage->mesh->totpoly;
96 }
97
98 static int get_num_edges(const OpenSubdiv_Converter *converter)
99 {
100         ConverterStorage *storage = converter->user_data;
101         return storage->mesh->totedge;
102 }
103
104 static int get_num_verts(const OpenSubdiv_Converter *converter)
105 {
106         ConverterStorage *storage = converter->user_data;
107         return storage->mesh->totvert;
108 }
109
110 static int get_num_face_verts(const OpenSubdiv_Converter *converter, int face)
111 {
112         ConverterStorage *storage = converter->user_data;
113         return storage->mesh->mpoly[face].totloop;
114 }
115
116 static void get_face_verts(const OpenSubdiv_Converter *converter,
117                            int face,
118                            int *face_verts)
119 {
120         ConverterStorage *storage = converter->user_data;
121         const MPoly *mp = &storage->mesh->mpoly[face];
122         const MLoop *mloop = storage->mesh->mloop;
123         for (int loop = 0; loop < mp->totloop; loop++) {
124                 face_verts[loop] = mloop[mp->loopstart + loop].v;
125         }
126 }
127
128 static void get_face_edges(const OpenSubdiv_Converter *converter,
129                            int face,
130                            int *face_edges)
131 {
132         ConverterStorage *storage = converter->user_data;
133         const MPoly *mp = &storage->mesh->mpoly[face];
134         const MLoop *mloop = storage->mesh->mloop;
135         for (int loop = 0; loop < mp->totloop; loop++) {
136                 face_edges[loop] = mloop[mp->loopstart + loop].e;
137         }
138 }
139
140 static void get_edge_verts(const OpenSubdiv_Converter *converter,
141                            int edge,
142                            int *edge_verts)
143 {
144         ConverterStorage *storage = converter->user_data;
145         const MEdge *me = &storage->mesh->medge[edge];
146         edge_verts[0] = me->v1;
147         edge_verts[1] = me->v2;
148 }
149
150 static int get_num_edge_faces(const OpenSubdiv_Converter *converter, int edge)
151 {
152         ConverterStorage *storage = converter->user_data;
153 #ifdef USE_MESH_ELEMENT_MAPPING
154         return storage->edge_poly_map[edge].count;
155 #else
156         const Mesh *mesh = storage->mesh;
157         const MPoly *mpoly = mesh->mpoly;
158         const MLoop *mloop = mesh->mloop;
159         int num = 0;
160         for (int poly = 0; poly < mesh->totpoly; poly++) {
161                 const MPoly *mp = &mpoly[poly];
162                 for (int loop = 0; loop < mp->totloop; loop++) {
163                         const MLoop *ml = &mloop[mp->loopstart + loop];
164                         if (ml->e == edge) {
165                                 ++num;
166                                 break;
167                         }
168                 }
169         }
170         return num;
171 #endif
172 }
173
174 static void get_edge_faces(const OpenSubdiv_Converter *converter,
175                            int edge,
176                            int *edge_faces)
177 {
178         ConverterStorage *storage = converter->user_data;
179 #ifdef USE_MESH_ELEMENT_MAPPING
180         memcpy(edge_faces,
181                storage->edge_poly_map[edge].indices,
182                sizeof(int) * storage->edge_poly_map[edge].count);
183 #else
184         const Mesh *mesh = storage->mesh;
185         const MPoly *mpoly = mesh->mpoly;
186         const MLoop *mloop = mesh->mloop;
187         int num = 0;
188         for (int poly = 0; poly < mesh->totpoly; poly++) {
189                 const MPoly *mp = &mpoly[poly];
190                 for (int loop = 0; loop < mpoly->totloop; loop++) {
191                         const MLoop *ml = &mloop[mp->loopstart + loop];
192                         if (ml->e == edge) {
193                                 edge_faces[num++] = poly;
194                                 break;
195                         }
196                 }
197         }
198 #endif
199 }
200
201 static float get_edge_sharpness(const OpenSubdiv_Converter *converter, int edge)
202 {
203         ConverterStorage *storage = converter->user_data;
204         const MEdge *medge = storage->mesh->medge;
205         const float edge_crease =  (float)medge[edge].crease / 255.0f;
206         return edge_crease * storage->settings.level;
207 }
208
209 static int get_num_vert_edges(const OpenSubdiv_Converter *converter, int vert)
210 {
211         ConverterStorage *storage = converter->user_data;
212 #ifdef USE_MESH_ELEMENT_MAPPING
213         return storage->vert_edge_map[vert].count;
214 #else
215         const Mesh *mesh = storage->mesh;
216         const MEdge *medge = mesh->medge;
217         int num = 0;
218         for (int edge = 0; edge < mesh->totedge; edge++) {
219                 const MEdge *me = &medge[edge];
220                 if (me->v1 == vert || me->v2 == vert) {
221                         ++num;
222                 }
223         }
224         return num;
225 #endif
226 }
227
228 static void get_vert_edges(const OpenSubdiv_Converter *converter,
229                            int vert,
230                            int *vert_edges)
231 {
232         ConverterStorage *storage = converter->user_data;
233 #ifdef USE_MESH_ELEMENT_MAPPING
234         memcpy(vert_edges,
235                storage->vert_edge_map[vert].indices,
236                sizeof(int) * storage->vert_edge_map[vert].count);
237 #else
238         const Mesh *mesh = storage->mesh;
239         const MEdge *medge = mesh->medge;
240         int num = 0;
241         for (int edge = 0; edge < mesh->totedge; edge++) {
242                 const MEdge *me = &medge[edge];
243                 if (me->v1 == vert || me->v2 == vert) {
244                         vert_edges[num++] = edge;
245                 }
246         }
247 #endif
248 }
249
250 static int get_num_vert_faces(const OpenSubdiv_Converter *converter, int vert)
251 {
252         ConverterStorage *storage = converter->user_data;
253 #ifdef USE_MESH_ELEMENT_MAPPING
254         return storage->vert_poly_map[vert].count;
255 #else
256         const Mesh *mesh = storage->mesh;
257         const MPoly *mpoly = mesh->mpoly;
258         const MLoop *mloop = mesh->mloop;
259         int num = 0;
260         for (int poly = 0; poly < mesh->totpoly; poly++) {
261                 const MPoly *mp = &mpoly[poly];
262                 for (int loop = 0; loop < mpoly->totloop; loop++) {
263                         const MLoop *ml = &mloop[mp->loopstart + loop];
264                         if (ml->v == vert) {
265                                 ++num;
266                                 break;
267                         }
268                 }
269         }
270         return num;
271 #endif
272 }
273
274 static void get_vert_faces(const OpenSubdiv_Converter *converter,
275                            int vert,
276                            int *vert_faces)
277 {
278         ConverterStorage *storage = converter->user_data;
279 #ifdef USE_MESH_ELEMENT_MAPPING
280         memcpy(vert_faces,
281                storage->vert_poly_map[vert].indices,
282                sizeof(int) * storage->vert_poly_map[vert].count);
283 #else
284         const Mesh *mesh = storage->mesh;
285         const MPoly *mpoly = mesh->mpoly;
286         const MLoop *mloop = mesh->mloop;
287         int num = 0;
288         for (int poly = 0; poly < mesh->totpoly; poly++) {
289                 const MPoly *mp = &mpoly[poly];
290                 for (int loop = 0; loop < mpoly->totloop; loop++) {
291                         const MLoop *ml = &mloop[mp->loopstart + loop];
292                         if (ml->v == vert) {
293                                 vert_faces[num++] = poly;
294                                 break;
295                         }
296                 }
297         }
298 #endif
299 }
300
301 static int get_num_uv_layers(const OpenSubdiv_Converter *converter)
302 {
303         ConverterStorage *storage = converter->user_data;
304         const Mesh *mesh = storage->mesh;
305         return CustomData_number_of_layers(&mesh->ldata, CD_MLOOPUV);
306 }
307
308 static void precalc_uv_layer(const OpenSubdiv_Converter *converter,
309                              const int layer_index)
310 {
311         ConverterStorage *storage = converter->user_data;
312         const Mesh *mesh = storage->mesh;
313         const MPoly *mpoly = mesh->mpoly;
314         const MLoop *mloop = mesh->mloop;
315         const MLoopUV *mloopuv = CustomData_get_layer_n(
316                 &mesh->ldata, CD_MLOOPUV, layer_index);
317         const int num_poly = mesh->totpoly;
318         const int num_vert = mesh->totvert;
319         const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
320         /* Initialize memory required for the operations. */
321         if (storage->loop_uv_indices == NULL) {
322                 storage->loop_uv_indices = MEM_malloc_arrayN(
323                         mesh->totloop, sizeof(int), "loop uv vertex index");
324         }
325         UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(
326                 mpoly, mloop, mloopuv,
327                 num_poly, num_vert,
328                 limit,
329                 false, true);
330         /* NOTE: First UV vertex is supposed to be always marked as separate. */
331         storage->num_uv_coordinates = -1;
332         for (int vertex_index = 0; vertex_index < num_vert; ++vertex_index) {
333                 const UvMapVert *uv_vert = BKE_mesh_uv_vert_map_get_vert(uv_vert_map,
334                                                                          vertex_index);
335                 while (uv_vert != NULL) {
336                         if (uv_vert->separate) {
337                                 storage->num_uv_coordinates++;
338                         }
339                         const MPoly *mp = &mpoly[uv_vert->poly_index];
340                         const int global_loop_index = mp->loopstart +
341                                                       uv_vert->loop_of_poly_index;
342                         storage->loop_uv_indices[global_loop_index] =
343                                 storage->num_uv_coordinates;
344                         uv_vert = uv_vert->next;
345                 }
346         }
347         /* So far this value was used as a 0-based index, actual number of UV
348          * vertices is 1 more.
349          */
350         storage->num_uv_coordinates += 1;
351         BKE_mesh_uv_vert_map_free(uv_vert_map);
352 }
353
354 static void finish_uv_layer(const OpenSubdiv_Converter *UNUSED(converter))
355 {
356 }
357
358 static int get_num_uvs(const OpenSubdiv_Converter *converter)
359 {
360         ConverterStorage *storage = converter->user_data;
361         return storage->num_uv_coordinates;
362 }
363
364 static int get_face_corner_uv_index(const OpenSubdiv_Converter *converter,
365                                     const int face_index,
366                                     const int corner)
367 {
368         ConverterStorage *storage = converter->user_data;
369         const MPoly *mp = &storage->mesh->mpoly[face_index];
370         return storage->loop_uv_indices[mp->loopstart + corner];
371 }
372
373 static void free_user_data(const OpenSubdiv_Converter *converter)
374 {
375         ConverterStorage *user_data = converter->user_data;
376         MEM_SAFE_FREE(user_data->loop_uv_indices);
377 #ifdef USE_MESH_ELEMENT_MAPPING
378         MEM_freeN(user_data->vert_edge_map);
379         MEM_freeN(user_data->vert_edge_mem);
380         MEM_freeN(user_data->vert_poly_map);
381         MEM_freeN(user_data->vert_poly_mem);
382         MEM_freeN(user_data->edge_poly_map);
383         MEM_freeN(user_data->edge_poly_mem);
384 #endif
385         MEM_freeN(user_data);
386 }
387
388 static void init_functions(OpenSubdiv_Converter *converter)
389 {
390         converter->getSchemeType = get_scheme_type;
391
392         converter->getFVarLinearInterpolation = get_fvar_linear_interpolation;
393
394         converter->getNumFaces = get_num_faces;
395         converter->getNumEdges = get_num_edges;
396         converter->getNumVertices = get_num_verts;
397
398         converter->getNumFaceVertices = get_num_face_verts;
399         converter->getFaceVertices = get_face_verts;
400         converter->getFaceEdges = get_face_edges;
401
402         converter->getEdgeVertices = get_edge_verts;
403         converter->getNumEdgeFaces = get_num_edge_faces;
404         converter->getEdgeFaces = get_edge_faces;
405         converter->getEdgeSharpness = get_edge_sharpness;
406
407         converter->getNumVertexEdges = get_num_vert_edges;
408         converter->getVertexEdges = get_vert_edges;
409         converter->getNumVertexFaces = get_num_vert_faces;
410         converter->getVertexFaces = get_vert_faces;
411
412         converter->getNumUVLayers = get_num_uv_layers;
413         converter->precalcUVLayer = precalc_uv_layer;
414         converter->finishUVLayer = finish_uv_layer;
415         converter->getNumUVCoordinates = get_num_uvs;
416         converter->getFaceCornerUVIndex = get_face_corner_uv_index;
417
418         converter->freeUserData = free_user_data;
419 }
420
421 static void create_element_maps_if_needed(ConverterStorage *storage)
422 {
423 #ifdef USE_MESH_ELEMENT_MAPPING
424         const Mesh *mesh = storage->mesh;
425         BKE_mesh_vert_edge_map_create(&storage->vert_edge_map,
426                                       &storage->vert_edge_mem,
427                                       mesh->medge,
428                                       mesh->totvert,
429                                       mesh->totedge);
430         BKE_mesh_vert_poly_map_create(&storage->vert_poly_map,
431                                       &storage->vert_poly_mem,
432                                       mesh->mpoly,
433                                       mesh->mloop,
434                                       mesh->totvert,
435                                       mesh->totpoly,
436                                       mesh->totloop);
437         BKE_mesh_edge_poly_map_create(&storage->edge_poly_map,
438                                       &storage->edge_poly_mem,
439                                       mesh->medge, mesh->totedge,
440                                       mesh->mpoly, mesh->totpoly,
441                                       mesh->mloop, mesh->totloop);
442 #else
443         (void) storage;  /* Ignored. */
444 #endif
445 }
446
447 static void init_user_data(OpenSubdiv_Converter *converter,
448                            const SubdivSettings *settings,
449                            const Mesh *mesh)
450 {
451         ConverterStorage *user_data =
452                  MEM_mallocN(sizeof(ConverterStorage), __func__);
453         user_data->settings = *settings;
454         user_data->mesh = mesh;
455         user_data->loop_uv_indices = NULL;
456         create_element_maps_if_needed(user_data);
457         converter->user_data = user_data;
458 }
459 #endif
460
461 void BKE_subdiv_converter_init_for_mesh(struct OpenSubdiv_Converter *converter,
462                                         const SubdivSettings *settings,
463                                         const Mesh *mesh)
464 {
465 #ifdef WITH_OPENSUBDIV
466         init_functions(converter);
467         init_user_data(converter, settings, mesh);
468 #else
469         UNUSED_VARS(converter, settings, mesh);
470 #endif
471 }