00a2436098e1580f07cd91038eae17203ebda8eb
[blender.git] / source / blender / blenkernel / intern / subdiv_converter_mesh.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2018 by Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup bke
22  */
23
24 #include "subdiv_converter.h"
25
26 #include <string.h>
27
28 #include "DNA_mesh_types.h"
29 #include "DNA_meshdata_types.h"
30
31 #include "BLI_utildefines.h"
32 #include "BLI_bitmap.h"
33
34 #include "BKE_customdata.h"
35 #include "BKE_mesh_mapping.h"
36 #include "BKE_subdiv.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "opensubdiv_capi.h"
41 #include "opensubdiv_converter_capi.h"
42
43 /* Enable work-around for non-working CPU evaluator when using bilinear scheme.
44  * This forces Catmark scheme with all edges marked as infinitely sharp. */
45 #define BUGGY_SIMPLE_SCHEME_WORKAROUND 1
46
47 typedef struct ConverterStorage {
48         SubdivSettings settings;
49         const Mesh *mesh;
50         /* Indexed by loop index, value denotes index of face-varying vertex
51          * which corresponds to the UV coordinate.
52          */
53         int *loop_uv_indices;
54         int num_uv_coordinates;
55         /* Indexed by coarse mesh elements, gives index of corresponding element
56          * with ignoring all non-manifold entities.
57          *
58          * NOTE: This isn't strictly speaking manifold, this is more like non-loose
59          * geometry index. As in, index of element as if there were no loose edges
60          * or vertices in the mesh.
61          */
62         int *manifold_vertex_index;
63         /* Indexed by vertex index from mesh, corresponds to whether this vertex has
64          * infinite sharpness due to non-manifol topology.
65          */
66         BLI_bitmap *infinite_sharp_vertices_map;
67         /* Reverse mapping to above. */
68         int *manifold_vertex_index_reverse;
69         int *manifold_edge_index_reverse;
70         /* Number of non-loose elements. */
71         int num_manifold_vertices;
72         int num_manifold_edges;
73 } ConverterStorage;
74
75 static OpenSubdiv_SchemeType get_scheme_type(
76         const OpenSubdiv_Converter *converter)
77 {
78 #if BUGGY_SIMPLE_SCHEME_WORKAROUND
79         (void) converter;
80         return OSD_SCHEME_CATMARK;
81 #else
82         ConverterStorage *storage = converter->user_data;
83         if (storage->settings.is_simple) {
84                 return OSD_SCHEME_BILINEAR;
85         }
86         else {
87                 return OSD_SCHEME_CATMARK;
88         }
89 #endif
90 }
91
92 static OpenSubdiv_VtxBoundaryInterpolation get_vtx_boundary_interpolation(
93         const struct OpenSubdiv_Converter *converter) {
94         ConverterStorage *storage = converter->user_data;
95         return BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(
96                 &storage->settings);
97 }
98
99 static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(
100         const OpenSubdiv_Converter *converter)
101 {
102         ConverterStorage *storage = converter->user_data;
103         return BKE_subdiv_converter_fvar_linear_from_settings(&storage->settings);
104 }
105
106 static bool specifies_full_topology(
107         const OpenSubdiv_Converter *UNUSED(converter))
108 {
109         return false;
110 }
111
112 static int get_num_faces(const OpenSubdiv_Converter *converter)
113 {
114         ConverterStorage *storage = converter->user_data;
115         return storage->mesh->totpoly;
116 }
117
118 static int get_num_edges(const OpenSubdiv_Converter *converter)
119 {
120         ConverterStorage *storage = converter->user_data;
121         return storage->num_manifold_edges;
122 }
123
124 static int get_num_vertices(const OpenSubdiv_Converter *converter)
125 {
126         ConverterStorage *storage = converter->user_data;
127         return storage->num_manifold_vertices;
128 }
129
130 static int get_num_face_vertices(const OpenSubdiv_Converter *converter,
131                                  int manifold_face_index)
132 {
133         ConverterStorage *storage = converter->user_data;
134         return storage->mesh->mpoly[manifold_face_index].totloop;
135 }
136
137 static void get_face_vertices(const OpenSubdiv_Converter *converter,
138                               int manifold_face_index,
139                               int *manifold_face_vertices)
140 {
141         ConverterStorage *storage = converter->user_data;
142         const MPoly *poly = &storage->mesh->mpoly[manifold_face_index];
143         const MLoop *mloop = storage->mesh->mloop;
144         for (int corner = 0; corner < poly->totloop; corner++) {
145                 manifold_face_vertices[corner] = storage->manifold_vertex_index[
146                         mloop[poly->loopstart + corner].v];
147         }
148 }
149
150 static void get_edge_vertices(const OpenSubdiv_Converter *converter,
151                               int manifold_edge_index,
152                               int *manifold_edge_vertices)
153 {
154         ConverterStorage *storage = converter->user_data;
155         const int edge_index =
156                 storage->manifold_edge_index_reverse[manifold_edge_index];
157         const MEdge *edge = &storage->mesh->medge[edge_index];
158         manifold_edge_vertices[0] = storage->manifold_vertex_index[edge->v1];
159         manifold_edge_vertices[1] = storage->manifold_vertex_index[edge->v2];
160 }
161
162 static float get_edge_sharpness(const OpenSubdiv_Converter *converter,
163                                 int manifold_edge_index)
164 {
165         ConverterStorage *storage = converter->user_data;
166 #if BUGGY_SIMPLE_SCHEME_WORKAROUND
167         if (storage->settings.is_simple) {
168                 return 10.0f;
169         }
170 #endif
171         const int edge_index =
172                 storage->manifold_edge_index_reverse[manifold_edge_index];
173         const MEdge *medge = storage->mesh->medge;
174         const float edge_crease =  (float)medge[edge_index].crease / 255.0f;
175         return edge_crease * edge_crease * 10.0f;
176 }
177
178 static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter,
179                                      int manifold_vertex_index)
180 {
181         ConverterStorage *storage = converter->user_data;
182 #if BUGGY_SIMPLE_SCHEME_WORKAROUND
183         if (storage->settings.is_simple) {
184                 return true;
185         }
186 #endif
187         const int vertex_index =
188                 storage->manifold_vertex_index_reverse[manifold_vertex_index];
189         return BLI_BITMAP_TEST_BOOL(storage->infinite_sharp_vertices_map,
190                                     vertex_index);
191 }
192
193 static float get_vertex_sharpness(const OpenSubdiv_Converter *UNUSED(converter),
194                                   int UNUSED(manifold_vertex_index))
195 {
196         return 0.0f;
197 }
198
199 static int get_num_uv_layers(const OpenSubdiv_Converter *converter)
200 {
201         ConverterStorage *storage = converter->user_data;
202         const Mesh *mesh = storage->mesh;
203         return CustomData_number_of_layers(&mesh->ldata, CD_MLOOPUV);
204 }
205
206 static void precalc_uv_layer(const OpenSubdiv_Converter *converter,
207                              const int layer_index)
208 {
209         ConverterStorage *storage = converter->user_data;
210         const Mesh *mesh = storage->mesh;
211         const MPoly *mpoly = mesh->mpoly;
212         const MLoop *mloop = mesh->mloop;
213         const MLoopUV *mloopuv = CustomData_get_layer_n(
214                 &mesh->ldata, CD_MLOOPUV, layer_index);
215         const int num_poly = mesh->totpoly;
216         const int num_vert = mesh->totvert;
217         const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
218         /* Initialize memory required for the operations. */
219         if (storage->loop_uv_indices == NULL) {
220                 storage->loop_uv_indices = MEM_malloc_arrayN(
221                         mesh->totloop, sizeof(int), "loop uv vertex index");
222         }
223         UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(
224                 mpoly, mloop, mloopuv,
225                 num_poly, num_vert,
226                 limit,
227                 false, true);
228         /* NOTE: First UV vertex is supposed to be always marked as separate. */
229         storage->num_uv_coordinates = -1;
230         for (int vertex_index = 0; vertex_index < num_vert; ++vertex_index) {
231                 const UvMapVert *uv_vert = BKE_mesh_uv_vert_map_get_vert(uv_vert_map,
232                                                                          vertex_index);
233                 while (uv_vert != NULL) {
234                         if (uv_vert->separate) {
235                                 storage->num_uv_coordinates++;
236                         }
237                         const MPoly *mp = &mpoly[uv_vert->poly_index];
238                         const int global_loop_index = mp->loopstart +
239                                                       uv_vert->loop_of_poly_index;
240                         storage->loop_uv_indices[global_loop_index] =
241                                 storage->num_uv_coordinates;
242                         uv_vert = uv_vert->next;
243                 }
244         }
245         /* So far this value was used as a 0-based index, actual number of UV
246          * vertices is 1 more.
247          */
248         storage->num_uv_coordinates += 1;
249         BKE_mesh_uv_vert_map_free(uv_vert_map);
250 }
251
252 static void finish_uv_layer(const OpenSubdiv_Converter *UNUSED(converter))
253 {
254 }
255
256 static int get_num_uvs(const OpenSubdiv_Converter *converter)
257 {
258         ConverterStorage *storage = converter->user_data;
259         return storage->num_uv_coordinates;
260 }
261
262 static int get_face_corner_uv_index(const OpenSubdiv_Converter *converter,
263                                     const int face_index,
264                                     const int corner)
265 {
266         ConverterStorage *storage = converter->user_data;
267         const MPoly *mp = &storage->mesh->mpoly[face_index];
268         return storage->loop_uv_indices[mp->loopstart + corner];
269 }
270
271 static void free_user_data(const OpenSubdiv_Converter *converter)
272 {
273         ConverterStorage *user_data = converter->user_data;
274         MEM_SAFE_FREE(user_data->loop_uv_indices);
275         MEM_freeN(user_data->manifold_vertex_index);
276         MEM_freeN(user_data->infinite_sharp_vertices_map);
277         MEM_freeN(user_data->manifold_vertex_index_reverse);
278         MEM_freeN(user_data->manifold_edge_index_reverse);
279         MEM_freeN(user_data);
280 }
281
282 static void init_functions(OpenSubdiv_Converter *converter)
283 {
284         converter->getSchemeType = get_scheme_type;
285         converter->getVtxBoundaryInterpolation = get_vtx_boundary_interpolation;
286         converter->getFVarLinearInterpolation = get_fvar_linear_interpolation;
287         converter->specifiesFullTopology = specifies_full_topology;
288
289         converter->getNumFaces = get_num_faces;
290         converter->getNumEdges = get_num_edges;
291         converter->getNumVertices = get_num_vertices;
292
293         converter->getNumFaceVertices = get_num_face_vertices;
294         converter->getFaceVertices = get_face_vertices;
295         converter->getFaceEdges = NULL;
296
297         converter->getEdgeVertices = get_edge_vertices;
298         converter->getNumEdgeFaces = NULL;
299         converter->getEdgeFaces = NULL;
300         converter->getEdgeSharpness = get_edge_sharpness;
301
302         converter->getNumVertexEdges = NULL;
303         converter->getVertexEdges = NULL;
304         converter->getNumVertexFaces = NULL;
305         converter->getVertexFaces = NULL;
306         converter->isInfiniteSharpVertex = is_infinite_sharp_vertex;
307         converter->getVertexSharpness = get_vertex_sharpness;
308
309         converter->getNumUVLayers = get_num_uv_layers;
310         converter->precalcUVLayer = precalc_uv_layer;
311         converter->finishUVLayer = finish_uv_layer;
312         converter->getNumUVCoordinates = get_num_uvs;
313         converter->getFaceCornerUVIndex = get_face_corner_uv_index;
314
315         converter->freeUserData = free_user_data;
316 }
317
318 static void initialize_manifold_index_array(const BLI_bitmap *used_map,
319                                             const int num_elements,
320                                             int **indices_r,
321                                             int **indices_reverse_r,
322                                             int *num_manifold_elements_r)
323 {
324         int *indices = NULL;
325         if (indices_r != NULL) {
326                 indices = MEM_malloc_arrayN(
327                         num_elements, sizeof(int), "manifold indices");
328         }
329         int *indices_reverse = NULL;
330         if (indices_reverse_r != NULL) {
331                 indices_reverse = MEM_malloc_arrayN(
332                         num_elements, sizeof(int), "manifold indices reverse");
333         }
334         int offset = 0;
335         for (int i = 0; i < num_elements; i++) {
336                 if (BLI_BITMAP_TEST_BOOL(used_map, i)) {
337                         if (indices != NULL) {
338                                 indices[i] = i - offset;
339                         }
340                         if (indices_reverse != NULL) {
341                                 indices_reverse[i - offset] = i;
342                         }
343                 }
344                 else {
345                         if (indices != NULL) {
346                                 indices[i] = -1;
347                         }
348                         offset++;
349                 }
350         }
351         if (indices_r != NULL) {
352                 *indices_r = indices;
353         }
354         if (indices_reverse_r != NULL) {
355                 *indices_reverse_r = indices_reverse;
356         }
357         *num_manifold_elements_r = num_elements - offset;
358 }
359
360 static void initialize_manifold_indices(ConverterStorage *storage)
361 {
362         const Mesh *mesh = storage->mesh;
363         const MEdge *medge = mesh->medge;
364         const MLoop *mloop = mesh->mloop;
365         const MPoly *mpoly = mesh->mpoly;
366         /* Set bits of elements which are not loose. */
367         BLI_bitmap *vert_used_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map");
368         BLI_bitmap *edge_used_map = BLI_BITMAP_NEW(mesh->totedge, "edge used map");
369         for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
370                 const MPoly *poly = &mpoly[poly_index];
371                 for (int corner = 0; corner < poly->totloop; corner++) {
372                         const MLoop *loop = &mloop[poly->loopstart + corner];
373                         BLI_BITMAP_ENABLE(vert_used_map, loop->v);
374                         BLI_BITMAP_ENABLE(edge_used_map, loop->e);
375                 }
376         }
377         initialize_manifold_index_array(vert_used_map,
378                                         mesh->totvert,
379                                         &storage->manifold_vertex_index,
380                                         &storage->manifold_vertex_index_reverse,
381                                         &storage->num_manifold_vertices);
382         initialize_manifold_index_array(edge_used_map,
383                                         mesh->totedge,
384                                         NULL,
385                                         &storage->manifold_edge_index_reverse,
386                                         &storage->num_manifold_edges);
387         /* Initialize infinite sharp mapping. */
388         storage->infinite_sharp_vertices_map =
389                 BLI_BITMAP_NEW(mesh->totvert, "vert used map");
390         for (int edge_index = 0; edge_index < mesh->totedge; edge_index++) {
391                 if (!BLI_BITMAP_TEST_BOOL(edge_used_map, edge_index)) {
392                         const MEdge *edge = &medge[edge_index];
393                         BLI_BITMAP_ENABLE(storage->infinite_sharp_vertices_map, edge->v1);
394                         BLI_BITMAP_ENABLE(storage->infinite_sharp_vertices_map, edge->v2);
395                 }
396         }
397         /* Free working variables. */
398         MEM_freeN(vert_used_map);
399         MEM_freeN(edge_used_map);
400 }
401
402 static void init_user_data(OpenSubdiv_Converter *converter,
403                            const SubdivSettings *settings,
404                            const Mesh *mesh)
405 {
406         ConverterStorage *user_data =
407                  MEM_mallocN(sizeof(ConverterStorage), __func__);
408         user_data->settings = *settings;
409         user_data->mesh = mesh;
410         user_data->loop_uv_indices = NULL;
411         initialize_manifold_indices(user_data);
412         converter->user_data = user_data;
413 }
414
415 void BKE_subdiv_converter_init_for_mesh(struct OpenSubdiv_Converter *converter,
416                                         const SubdivSettings *settings,
417                                         const Mesh *mesh)
418 {
419         init_functions(converter);
420         init_user_data(converter, settings, mesh);
421 }