ClangFormat: apply to source, most of intern
[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(const OpenSubdiv_Converter *converter)
76 {
77 #if BUGGY_SIMPLE_SCHEME_WORKAROUND
78   (void)converter;
79   return OSD_SCHEME_CATMARK;
80 #else
81   ConverterStorage *storage = converter->user_data;
82   if (storage->settings.is_simple) {
83     return OSD_SCHEME_BILINEAR;
84   }
85   else {
86     return OSD_SCHEME_CATMARK;
87   }
88 #endif
89 }
90
91 static OpenSubdiv_VtxBoundaryInterpolation get_vtx_boundary_interpolation(
92     const struct OpenSubdiv_Converter *converter)
93 {
94   ConverterStorage *storage = converter->user_data;
95   return BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(&storage->settings);
96 }
97
98 static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(
99     const OpenSubdiv_Converter *converter)
100 {
101   ConverterStorage *storage = converter->user_data;
102   return BKE_subdiv_converter_fvar_linear_from_settings(&storage->settings);
103 }
104
105 static bool specifies_full_topology(const OpenSubdiv_Converter *UNUSED(converter))
106 {
107   return false;
108 }
109
110 static int get_num_faces(const OpenSubdiv_Converter *converter)
111 {
112   ConverterStorage *storage = converter->user_data;
113   return storage->mesh->totpoly;
114 }
115
116 static int get_num_edges(const OpenSubdiv_Converter *converter)
117 {
118   ConverterStorage *storage = converter->user_data;
119   return storage->num_manifold_edges;
120 }
121
122 static int get_num_vertices(const OpenSubdiv_Converter *converter)
123 {
124   ConverterStorage *storage = converter->user_data;
125   return storage->num_manifold_vertices;
126 }
127
128 static int get_num_face_vertices(const OpenSubdiv_Converter *converter, int manifold_face_index)
129 {
130   ConverterStorage *storage = converter->user_data;
131   return storage->mesh->mpoly[manifold_face_index].totloop;
132 }
133
134 static void get_face_vertices(const OpenSubdiv_Converter *converter,
135                               int manifold_face_index,
136                               int *manifold_face_vertices)
137 {
138   ConverterStorage *storage = converter->user_data;
139   const MPoly *poly = &storage->mesh->mpoly[manifold_face_index];
140   const MLoop *mloop = storage->mesh->mloop;
141   for (int corner = 0; corner < poly->totloop; corner++) {
142     manifold_face_vertices[corner] =
143         storage->manifold_vertex_index[mloop[poly->loopstart + corner].v];
144   }
145 }
146
147 static void get_edge_vertices(const OpenSubdiv_Converter *converter,
148                               int manifold_edge_index,
149                               int *manifold_edge_vertices)
150 {
151   ConverterStorage *storage = converter->user_data;
152   const int edge_index = storage->manifold_edge_index_reverse[manifold_edge_index];
153   const MEdge *edge = &storage->mesh->medge[edge_index];
154   manifold_edge_vertices[0] = storage->manifold_vertex_index[edge->v1];
155   manifold_edge_vertices[1] = storage->manifold_vertex_index[edge->v2];
156 }
157
158 static float get_edge_sharpness(const OpenSubdiv_Converter *converter, int manifold_edge_index)
159 {
160   ConverterStorage *storage = converter->user_data;
161 #if BUGGY_SIMPLE_SCHEME_WORKAROUND
162   if (storage->settings.is_simple) {
163     return 10.0f;
164   }
165 #endif
166   if (!storage->settings.use_creases) {
167     return 0.0f;
168   }
169   const int edge_index = storage->manifold_edge_index_reverse[manifold_edge_index];
170   const MEdge *medge = storage->mesh->medge;
171   const float edge_crease = (float)medge[edge_index].crease / 255.0f;
172   return edge_crease * edge_crease * 10.0f;
173 }
174
175 static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter,
176                                      int manifold_vertex_index)
177 {
178   ConverterStorage *storage = converter->user_data;
179 #if BUGGY_SIMPLE_SCHEME_WORKAROUND
180   if (storage->settings.is_simple) {
181     return true;
182   }
183 #endif
184   const int vertex_index = storage->manifold_vertex_index_reverse[manifold_vertex_index];
185   return BLI_BITMAP_TEST_BOOL(storage->infinite_sharp_vertices_map, vertex_index);
186 }
187
188 static float get_vertex_sharpness(const OpenSubdiv_Converter *converter,
189                                   int UNUSED(manifold_vertex_index))
190 {
191   ConverterStorage *storage = converter->user_data;
192   if (!storage->settings.use_creases) {
193     return 0.0f;
194   }
195   return 0.0f;
196 }
197
198 static int get_num_uv_layers(const OpenSubdiv_Converter *converter)
199 {
200   ConverterStorage *storage = converter->user_data;
201   const Mesh *mesh = storage->mesh;
202   return CustomData_number_of_layers(&mesh->ldata, CD_MLOOPUV);
203 }
204
205 static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int layer_index)
206 {
207   ConverterStorage *storage = converter->user_data;
208   const Mesh *mesh = storage->mesh;
209   const MPoly *mpoly = mesh->mpoly;
210   const MLoop *mloop = mesh->mloop;
211   const MLoopUV *mloopuv = CustomData_get_layer_n(&mesh->ldata, CD_MLOOPUV, layer_index);
212   const int num_poly = mesh->totpoly;
213   const int num_vert = mesh->totvert;
214   const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
215   /* Initialize memory required for the operations. */
216   if (storage->loop_uv_indices == NULL) {
217     storage->loop_uv_indices = MEM_malloc_arrayN(
218         mesh->totloop, sizeof(int), "loop uv vertex index");
219   }
220   UvVertMap *uv_vert_map = BKE_mesh_uv_vert_map_create(
221       mpoly, mloop, mloopuv, num_poly, num_vert, limit, false, true);
222   /* NOTE: First UV vertex is supposed to be always marked as separate. */
223   storage->num_uv_coordinates = -1;
224   for (int vertex_index = 0; vertex_index < num_vert; ++vertex_index) {
225     const UvMapVert *uv_vert = BKE_mesh_uv_vert_map_get_vert(uv_vert_map, vertex_index);
226     while (uv_vert != NULL) {
227       if (uv_vert->separate) {
228         storage->num_uv_coordinates++;
229       }
230       const MPoly *mp = &mpoly[uv_vert->poly_index];
231       const int global_loop_index = mp->loopstart + uv_vert->loop_of_poly_index;
232       storage->loop_uv_indices[global_loop_index] = storage->num_uv_coordinates;
233       uv_vert = uv_vert->next;
234     }
235   }
236   /* So far this value was used as a 0-based index, actual number of UV
237    * vertices is 1 more.
238    */
239   storage->num_uv_coordinates += 1;
240   BKE_mesh_uv_vert_map_free(uv_vert_map);
241 }
242
243 static void finish_uv_layer(const OpenSubdiv_Converter *UNUSED(converter))
244 {
245 }
246
247 static int get_num_uvs(const OpenSubdiv_Converter *converter)
248 {
249   ConverterStorage *storage = converter->user_data;
250   return storage->num_uv_coordinates;
251 }
252
253 static int get_face_corner_uv_index(const OpenSubdiv_Converter *converter,
254                                     const int face_index,
255                                     const int corner)
256 {
257   ConverterStorage *storage = converter->user_data;
258   const MPoly *mp = &storage->mesh->mpoly[face_index];
259   return storage->loop_uv_indices[mp->loopstart + corner];
260 }
261
262 static void free_user_data(const OpenSubdiv_Converter *converter)
263 {
264   ConverterStorage *user_data = converter->user_data;
265   MEM_SAFE_FREE(user_data->loop_uv_indices);
266   MEM_freeN(user_data->manifold_vertex_index);
267   MEM_freeN(user_data->infinite_sharp_vertices_map);
268   MEM_freeN(user_data->manifold_vertex_index_reverse);
269   MEM_freeN(user_data->manifold_edge_index_reverse);
270   MEM_freeN(user_data);
271 }
272
273 static void init_functions(OpenSubdiv_Converter *converter)
274 {
275   converter->getSchemeType = get_scheme_type;
276   converter->getVtxBoundaryInterpolation = get_vtx_boundary_interpolation;
277   converter->getFVarLinearInterpolation = get_fvar_linear_interpolation;
278   converter->specifiesFullTopology = specifies_full_topology;
279
280   converter->getNumFaces = get_num_faces;
281   converter->getNumEdges = get_num_edges;
282   converter->getNumVertices = get_num_vertices;
283
284   converter->getNumFaceVertices = get_num_face_vertices;
285   converter->getFaceVertices = get_face_vertices;
286   converter->getFaceEdges = NULL;
287
288   converter->getEdgeVertices = get_edge_vertices;
289   converter->getNumEdgeFaces = NULL;
290   converter->getEdgeFaces = NULL;
291   converter->getEdgeSharpness = get_edge_sharpness;
292
293   converter->getNumVertexEdges = NULL;
294   converter->getVertexEdges = NULL;
295   converter->getNumVertexFaces = NULL;
296   converter->getVertexFaces = NULL;
297   converter->isInfiniteSharpVertex = is_infinite_sharp_vertex;
298   converter->getVertexSharpness = get_vertex_sharpness;
299
300   converter->getNumUVLayers = get_num_uv_layers;
301   converter->precalcUVLayer = precalc_uv_layer;
302   converter->finishUVLayer = finish_uv_layer;
303   converter->getNumUVCoordinates = get_num_uvs;
304   converter->getFaceCornerUVIndex = get_face_corner_uv_index;
305
306   converter->freeUserData = free_user_data;
307 }
308
309 static void initialize_manifold_index_array(const BLI_bitmap *used_map,
310                                             const int num_elements,
311                                             int **indices_r,
312                                             int **indices_reverse_r,
313                                             int *num_manifold_elements_r)
314 {
315   int *indices = NULL;
316   if (indices_r != NULL) {
317     indices = MEM_malloc_arrayN(num_elements, sizeof(int), "manifold indices");
318   }
319   int *indices_reverse = NULL;
320   if (indices_reverse_r != NULL) {
321     indices_reverse = MEM_malloc_arrayN(num_elements, sizeof(int), "manifold indices reverse");
322   }
323   int offset = 0;
324   for (int i = 0; i < num_elements; i++) {
325     if (BLI_BITMAP_TEST_BOOL(used_map, i)) {
326       if (indices != NULL) {
327         indices[i] = i - offset;
328       }
329       if (indices_reverse != NULL) {
330         indices_reverse[i - offset] = i;
331       }
332     }
333     else {
334       if (indices != NULL) {
335         indices[i] = -1;
336       }
337       offset++;
338     }
339   }
340   if (indices_r != NULL) {
341     *indices_r = indices;
342   }
343   if (indices_reverse_r != NULL) {
344     *indices_reverse_r = indices_reverse;
345   }
346   *num_manifold_elements_r = num_elements - offset;
347 }
348
349 static void initialize_manifold_indices(ConverterStorage *storage)
350 {
351   const Mesh *mesh = storage->mesh;
352   const MEdge *medge = mesh->medge;
353   const MLoop *mloop = mesh->mloop;
354   const MPoly *mpoly = mesh->mpoly;
355   /* Set bits of elements which are not loose. */
356   BLI_bitmap *vert_used_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map");
357   BLI_bitmap *edge_used_map = BLI_BITMAP_NEW(mesh->totedge, "edge used map");
358   for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
359     const MPoly *poly = &mpoly[poly_index];
360     for (int corner = 0; corner < poly->totloop; corner++) {
361       const MLoop *loop = &mloop[poly->loopstart + corner];
362       BLI_BITMAP_ENABLE(vert_used_map, loop->v);
363       BLI_BITMAP_ENABLE(edge_used_map, loop->e);
364     }
365   }
366   initialize_manifold_index_array(vert_used_map,
367                                   mesh->totvert,
368                                   &storage->manifold_vertex_index,
369                                   &storage->manifold_vertex_index_reverse,
370                                   &storage->num_manifold_vertices);
371   initialize_manifold_index_array(edge_used_map,
372                                   mesh->totedge,
373                                   NULL,
374                                   &storage->manifold_edge_index_reverse,
375                                   &storage->num_manifold_edges);
376   /* Initialize infinite sharp mapping. */
377   storage->infinite_sharp_vertices_map = BLI_BITMAP_NEW(mesh->totvert, "vert used map");
378   for (int edge_index = 0; edge_index < mesh->totedge; edge_index++) {
379     if (!BLI_BITMAP_TEST_BOOL(edge_used_map, edge_index)) {
380       const MEdge *edge = &medge[edge_index];
381       BLI_BITMAP_ENABLE(storage->infinite_sharp_vertices_map, edge->v1);
382       BLI_BITMAP_ENABLE(storage->infinite_sharp_vertices_map, edge->v2);
383     }
384   }
385   /* Free working variables. */
386   MEM_freeN(vert_used_map);
387   MEM_freeN(edge_used_map);
388 }
389
390 static void init_user_data(OpenSubdiv_Converter *converter,
391                            const SubdivSettings *settings,
392                            const Mesh *mesh)
393 {
394   ConverterStorage *user_data = MEM_mallocN(sizeof(ConverterStorage), __func__);
395   user_data->settings = *settings;
396   user_data->mesh = mesh;
397   user_data->loop_uv_indices = NULL;
398   initialize_manifold_indices(user_data);
399   converter->user_data = user_data;
400 }
401
402 void BKE_subdiv_converter_init_for_mesh(struct OpenSubdiv_Converter *converter,
403                                         const SubdivSettings *settings,
404                                         const Mesh *mesh)
405 {
406   init_functions(converter);
407   init_user_data(converter, settings, mesh);
408 }