Merge branch 'blender2.7'
[blender.git] / source / blender / blenkernel / intern / subdiv_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 /** \file blender/blenkernel/intern/subdiv_mesh.c
27  *  \ingroup bke
28  */
29
30 #include "BKE_subdiv_mesh.h"
31
32 #include "atomic_ops.h"
33
34 #include "DNA_mesh_types.h"
35 #include "DNA_meshdata_types.h"
36 #include "DNA_key_types.h"
37
38 #include "BLI_alloca.h"
39 #include "BLI_math_vector.h"
40
41 #include "BKE_mesh.h"
42 #include "BKE_key.h"
43 #include "BKE_subdiv.h"
44 #include "BKE_subdiv_eval.h"
45 #include "BKE_subdiv_foreach.h"
46
47 #include "MEM_guardedalloc.h"
48
49 /* =============================================================================
50  * Subdivision context.
51  */
52
53 typedef struct SubdivMeshContext {
54         const SubdivToMeshSettings *settings;
55         const Mesh *coarse_mesh;
56         Subdiv *subdiv;
57         Mesh *subdiv_mesh;
58         /* Cached custom data arrays for fastter access. */
59         int *vert_origindex;
60         int *edge_origindex;
61         int *loop_origindex;
62         int *poly_origindex;
63         /* UV layers interpolation. */
64         int num_uv_layers;
65         MLoopUV *uv_layers[MAX_MTFACE];
66         /* Accumulated values.
67          *
68          * Averaging is happening for vertices along the coarse edges and corners.
69          * This is needed for both displacement and normals.
70          *
71          * Displacement is being accumulated to a verticies coordinates, since those
72          * are not needed during traversal of edge/corner vertices.
73          *
74          * For normals we are using dedicated array, since we can not use same
75          * vertices (normals are `short`, which will cause a lot of precision
76          * issues). */
77         float (*accumulated_normals)[3];
78         /* Per-subdivided vertex counter of averaged values. */
79         int *accumulated_counters;
80         /* Denotes whether normals can be evaluated from a limit surface. One case
81          * when it's not possible is when displacement is used. */
82         bool can_evaluate_normals;
83         bool have_displacement;
84 } SubdivMeshContext;
85
86 static void subdiv_mesh_ctx_cache_uv_layers(SubdivMeshContext *ctx)
87 {
88         Mesh *subdiv_mesh = ctx->subdiv_mesh;
89         ctx->num_uv_layers =
90                 CustomData_number_of_layers(&subdiv_mesh->ldata, CD_MLOOPUV);
91         for (int layer_index = 0; layer_index < ctx->num_uv_layers; ++layer_index) {
92                 ctx->uv_layers[layer_index] = CustomData_get_layer_n(
93                         &subdiv_mesh->ldata, CD_MLOOPUV, layer_index);
94         }
95 }
96
97 static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
98 {
99         Mesh *subdiv_mesh = ctx->subdiv_mesh;
100         /* Pointers to original indices layers. */
101         ctx->vert_origindex = CustomData_get_layer(
102                 &subdiv_mesh->vdata, CD_ORIGINDEX);
103         ctx->edge_origindex = CustomData_get_layer(
104                 &subdiv_mesh->edata, CD_ORIGINDEX);
105         ctx->loop_origindex = CustomData_get_layer(
106                 &subdiv_mesh->ldata, CD_ORIGINDEX);
107         ctx->poly_origindex = CustomData_get_layer(
108                 &subdiv_mesh->pdata, CD_ORIGINDEX);
109         /* UV layers interpolation. */
110         subdiv_mesh_ctx_cache_uv_layers(ctx);
111 }
112
113 static void subdiv_mesh_prepare_accumulator(
114         SubdivMeshContext *ctx, int num_vertices)
115 {
116         if (!ctx->can_evaluate_normals && !ctx->have_displacement) {
117                 return;
118         }
119         /* TODO(sergey): Technically, this is overallocating, we don't need memory
120          * for an inner subdivision vertices. */
121         ctx->accumulated_normals = MEM_calloc_arrayN(
122                 sizeof(*ctx->accumulated_normals),
123                 num_vertices,
124                 "subdiv accumulated normals");
125         ctx->accumulated_counters = MEM_calloc_arrayN(
126                 sizeof(*ctx->accumulated_counters),
127                 num_vertices,
128                 "subdiv accumulated counters");
129 }
130
131 static void subdiv_mesh_context_free(SubdivMeshContext *ctx)
132 {
133         MEM_SAFE_FREE(ctx->accumulated_normals);
134         MEM_SAFE_FREE(ctx->accumulated_counters);
135 }
136
137 /* =============================================================================
138  * Loop custom data copy helpers.
139  */
140
141 typedef struct LoopsOfPtex {
142         /* First loop of the ptex, starts at ptex (0, 0) and goes in u direction. */
143         const MLoop *first_loop;
144         /* Last loop of the ptex, starts at ptex (0, 0) and goes in v direction. */
145         const MLoop *last_loop;
146         /* For quad coarse faces only. */
147         const MLoop *second_loop;
148         const MLoop *third_loop;
149 } LoopsOfPtex;
150
151 static void loops_of_ptex_get(
152         const SubdivMeshContext *ctx,
153         LoopsOfPtex *loops_of_ptex,
154         const MPoly *coarse_poly,
155         const int ptex_of_poly_index)
156 {
157         const MLoop *coarse_mloop = ctx->coarse_mesh->mloop;
158         const int first_ptex_loop_index =
159                 coarse_poly->loopstart + ptex_of_poly_index;
160         /* Loop which look in the (opposite) V direction of the current
161          * ptex face.
162          *
163          * TODO(sergey): Get rid of using module on every iteration. */
164         const int last_ptex_loop_index =
165                 coarse_poly->loopstart +
166                 (ptex_of_poly_index + coarse_poly->totloop - 1) %
167                         coarse_poly->totloop;
168         loops_of_ptex->first_loop = &coarse_mloop[first_ptex_loop_index];
169         loops_of_ptex->last_loop = &coarse_mloop[last_ptex_loop_index];
170         if (coarse_poly->totloop == 4) {
171                 loops_of_ptex->second_loop = loops_of_ptex->first_loop + 1;
172                 loops_of_ptex->third_loop = loops_of_ptex->first_loop + 2;
173         }
174         else {
175                 loops_of_ptex->second_loop = NULL;
176                 loops_of_ptex->third_loop = NULL;
177         }
178 }
179
180 /* =============================================================================
181  * Vertex custom data interpolation helpers.
182  */
183
184 /* TODO(sergey): Somehow de-duplicate with loops storage, without too much
185  * exception cases all over the code. */
186
187 typedef struct VerticesForInterpolation {
188         /* This field points to a vertex data which is to be used for interpolation.
189          * The idea is to avoid unnecessary allocations for regular faces, where
190          * we can simply use corner verticies. */
191         const CustomData *vertex_data;
192         /* Vertices data calculated for ptex corners. There are always 4 elements
193          * in this custom data, aligned the following way:
194          *
195          *   index 0 -> uv (0, 0)
196          *   index 1 -> uv (0, 1)
197          *   index 2 -> uv (1, 1)
198          *   index 3 -> uv (1, 0)
199          *
200          * Is allocated for non-regular faces (triangles and n-gons). */
201         CustomData vertex_data_storage;
202         bool vertex_data_storage_allocated;
203         /* Infices within vertex_data to interpolate for. The indices are aligned
204          * with uv coordinates in a similar way as indices in loop_data_storage. */
205         int vertex_indices[4];
206 } VerticesForInterpolation;
207
208 static void vertex_interpolation_init(
209         const SubdivMeshContext *ctx,
210         VerticesForInterpolation *vertex_interpolation,
211         const MPoly *coarse_poly)
212 {
213         const Mesh *coarse_mesh = ctx->coarse_mesh;
214         const MLoop *coarse_mloop = coarse_mesh->mloop;
215         if (coarse_poly->totloop == 4) {
216                 vertex_interpolation->vertex_data = &coarse_mesh->vdata;
217                 vertex_interpolation->vertex_indices[0] =
218                         coarse_mloop[coarse_poly->loopstart + 0].v;
219                 vertex_interpolation->vertex_indices[1] =
220                         coarse_mloop[coarse_poly->loopstart + 1].v;
221                 vertex_interpolation->vertex_indices[2] =
222                         coarse_mloop[coarse_poly->loopstart + 2].v;
223                 vertex_interpolation->vertex_indices[3] =
224                         coarse_mloop[coarse_poly->loopstart + 3].v;
225                 vertex_interpolation->vertex_data_storage_allocated = false;
226         }
227         else {
228                 vertex_interpolation->vertex_data =
229                         &vertex_interpolation->vertex_data_storage;
230                 /* Allocate storage for loops corresponding to ptex corners. */
231                 CustomData_copy(&ctx->coarse_mesh->vdata,
232                                 &vertex_interpolation->vertex_data_storage,
233                                 CD_MASK_EVERYTHING,
234                                 CD_CALLOC,
235                                 4);
236                 /* Initialize indices. */
237                 vertex_interpolation->vertex_indices[0] = 0;
238                 vertex_interpolation->vertex_indices[1] = 1;
239                 vertex_interpolation->vertex_indices[2] = 2;
240                 vertex_interpolation->vertex_indices[3] = 3;
241                 vertex_interpolation->vertex_data_storage_allocated = true;
242                 /* Interpolate center of poly right away, it stays unchanged for all
243                  * ptex faces. */
244                 const float weight = 1.0f / (float)coarse_poly->totloop;
245                 float *weights = BLI_array_alloca(weights, coarse_poly->totloop);
246                 int *indices = BLI_array_alloca(indices, coarse_poly->totloop);
247                 for (int i = 0; i < coarse_poly->totloop; ++i) {
248                         weights[i] = weight;
249                         indices[i] = coarse_mloop[coarse_poly->loopstart + i].v;
250                 }
251                 CustomData_interp(&coarse_mesh->vdata,
252                                   &vertex_interpolation->vertex_data_storage,
253                                   indices,
254                                   weights, NULL,
255                                   coarse_poly->totloop,
256                                   2);
257         }
258 }
259
260 static void vertex_interpolation_from_corner(
261         const SubdivMeshContext *ctx,
262         VerticesForInterpolation *vertex_interpolation,
263         const MPoly *coarse_poly,
264         const int corner)
265 {
266         if (coarse_poly->totloop == 4) {
267                 /* Nothing to do, all indices and data is already assigned. */
268         }
269         else {
270                 const CustomData *vertex_data = &ctx->coarse_mesh->vdata;
271                 const Mesh *coarse_mesh = ctx->coarse_mesh;
272                 const MLoop *coarse_mloop = coarse_mesh->mloop;
273                 LoopsOfPtex loops_of_ptex;
274                 loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, corner);
275                 /* Ptex face corner corresponds to a poly loop with same index. */
276                 CustomData_copy_data(
277                         vertex_data,
278                         &vertex_interpolation->vertex_data_storage,
279                         coarse_mloop[coarse_poly->loopstart + corner].v,
280                         0,
281                         1);
282                 /* Interpolate remaining ptex face corners, which hits loops
283                  * middle points.
284                  *
285                  * TODO(sergey): Re-use one of interpolation results from previous
286                  * iteration. */
287                 const float weights[2] = {0.5f, 0.5f};
288                 const int first_loop_index = loops_of_ptex.first_loop - coarse_mloop;
289                 const int last_loop_index = loops_of_ptex.last_loop - coarse_mloop;
290                 const int first_indices[2] = {
291                         coarse_mloop[first_loop_index].v,
292                         coarse_mloop[coarse_poly->loopstart +
293                                 (first_loop_index - coarse_poly->loopstart + 1) %
294                                         coarse_poly->totloop].v};
295                 const int last_indices[2] = {coarse_mloop[first_loop_index].v,
296                                              coarse_mloop[last_loop_index].v};
297                 CustomData_interp(vertex_data,
298                                   &vertex_interpolation->vertex_data_storage,
299                                   first_indices,
300                                   weights, NULL,
301                                   2,
302                                   1);
303                 CustomData_interp(vertex_data,
304                                   &vertex_interpolation->vertex_data_storage,
305                                   last_indices,
306                                   weights, NULL,
307                                   2,
308                                   3);
309         }
310 }
311
312 static void vertex_interpolation_end(
313         VerticesForInterpolation *vertex_interpolation)
314 {
315         if (vertex_interpolation->vertex_data_storage_allocated) {
316                 CustomData_free(&vertex_interpolation->vertex_data_storage, 4);
317         }
318 }
319
320 /* =============================================================================
321  * Loop custom data interpolation helpers.
322  */
323
324 typedef struct LoopsForInterpolation {
325  /* This field points to a loop data which is to be used for interpolation.
326          * The idea is to avoid unnecessary allocations for regular faces, where
327          * we can simply interpolate corner verticies. */
328         const CustomData *loop_data;
329         /* Loops data calculated for ptex corners. There are always 4 elements
330          * in this custom data, aligned the following way:
331          *
332          *   index 0 -> uv (0, 0)
333          *   index 1 -> uv (0, 1)
334          *   index 2 -> uv (1, 1)
335          *   index 3 -> uv (1, 0)
336          *
337          * Is allocated for non-regular faces (triangles and n-gons). */
338         CustomData loop_data_storage;
339         bool loop_data_storage_allocated;
340         /* Infices within loop_data to interpolate for. The indices are aligned with
341          * uv coordinates in a similar way as indices in loop_data_storage. */
342         int loop_indices[4];
343 } LoopsForInterpolation;
344
345 static void loop_interpolation_init(
346         const SubdivMeshContext *ctx,
347         LoopsForInterpolation *loop_interpolation,
348         const MPoly *coarse_poly)
349 {
350         const Mesh *coarse_mesh = ctx->coarse_mesh;
351         if (coarse_poly->totloop == 4) {
352                 loop_interpolation->loop_data = &coarse_mesh->ldata;
353                 loop_interpolation->loop_indices[0] = coarse_poly->loopstart + 0;
354                 loop_interpolation->loop_indices[1] = coarse_poly->loopstart + 1;
355                 loop_interpolation->loop_indices[2] = coarse_poly->loopstart + 2;
356                 loop_interpolation->loop_indices[3] = coarse_poly->loopstart + 3;
357                 loop_interpolation->loop_data_storage_allocated = false;
358         }
359         else {
360                 loop_interpolation->loop_data = &loop_interpolation->loop_data_storage;
361                 /* Allocate storage for loops corresponding to ptex corners. */
362                 CustomData_copy(&ctx->coarse_mesh->ldata,
363                                 &loop_interpolation->loop_data_storage,
364                                 CD_MASK_EVERYTHING,
365                                 CD_CALLOC,
366                                 4);
367                 /* Initialize indices. */
368                 loop_interpolation->loop_indices[0] = 0;
369                 loop_interpolation->loop_indices[1] = 1;
370                 loop_interpolation->loop_indices[2] = 2;
371                 loop_interpolation->loop_indices[3] = 3;
372                 loop_interpolation->loop_data_storage_allocated = true;
373                 /* Interpolate center of poly right away, it stays unchanged for all
374                  * ptex faces. */
375                 const float weight = 1.0f / (float)coarse_poly->totloop;
376                 float *weights = BLI_array_alloca(weights, coarse_poly->totloop);
377                 int *indices = BLI_array_alloca(indices, coarse_poly->totloop);
378                 for (int i = 0; i < coarse_poly->totloop; ++i) {
379                         weights[i] = weight;
380                         indices[i] = coarse_poly->loopstart + i;
381                 }
382                 CustomData_interp(&coarse_mesh->ldata,
383                                   &loop_interpolation->loop_data_storage,
384                                   indices,
385                                   weights, NULL,
386                                   coarse_poly->totloop,
387                                   2);
388         }
389 }
390
391 static void loop_interpolation_from_corner(
392         const SubdivMeshContext *ctx,
393         LoopsForInterpolation *loop_interpolation,
394         const MPoly *coarse_poly,
395         const int corner)
396 {
397         if (coarse_poly->totloop == 4) {
398                 /* Nothing to do, all indices and data is already assigned. */
399         }
400         else {
401                 const CustomData *loop_data = &ctx->coarse_mesh->ldata;
402                 const Mesh *coarse_mesh = ctx->coarse_mesh;
403                 const MLoop *coarse_mloop = coarse_mesh->mloop;
404                 LoopsOfPtex loops_of_ptex;
405                 loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, corner);
406                 /* Ptex face corner corresponds to a poly loop with same index. */
407                 CustomData_free_elem(&loop_interpolation->loop_data_storage, 0, 1);
408                 CustomData_copy_data(loop_data,
409                                      &loop_interpolation->loop_data_storage,
410                                      coarse_poly->loopstart + corner,
411                                      0,
412                                      1);
413                 /* Interpolate remaining ptex face corners, which hits loops
414                  * middle points.
415                  *
416                  * TODO(sergey): Re-use one of interpolation results from previous
417                  * iteration. */
418                 const float weights[2] = {0.5f, 0.5f};
419                 const int base_loop_index = coarse_poly->loopstart;
420                 const int first_loop_index = loops_of_ptex.first_loop - coarse_mloop;
421                 const int second_loop_index =
422                         base_loop_index +
423                         (first_loop_index - base_loop_index + 1) % coarse_poly->totloop;
424                 const int first_indices[2] = {first_loop_index, second_loop_index};
425                 const int last_indices[2] = {
426                         loops_of_ptex.last_loop - coarse_mloop,
427                         loops_of_ptex.first_loop - coarse_mloop};
428                 CustomData_interp(loop_data,
429                                   &loop_interpolation->loop_data_storage,
430                                   first_indices,
431                                   weights, NULL,
432                                   2,
433                                   1);
434                 CustomData_interp(loop_data,
435                                   &loop_interpolation->loop_data_storage,
436                                   last_indices,
437                                   weights, NULL,
438                                   2,
439                                   3);
440         }
441 }
442
443 static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation)
444 {
445         if (loop_interpolation->loop_data_storage_allocated) {
446                 CustomData_free(&loop_interpolation->loop_data_storage, 4);
447         }
448 }
449
450 /* =============================================================================
451  * TLS.
452  */
453
454 typedef struct SubdivMeshTLS {
455         bool vertex_interpolation_initialized;
456         VerticesForInterpolation vertex_interpolation;
457         const MPoly *vertex_interpolation_coarse_poly;
458         int vertex_interpolation_coarse_corner;
459
460         bool loop_interpolation_initialized;
461         LoopsForInterpolation loop_interpolation;
462         const MPoly *loop_interpolation_coarse_poly;
463         int loop_interpolation_coarse_corner;
464 } SubdivMeshTLS;
465
466 static void subdiv_mesh_tls_free(void *tls_v)
467 {
468         SubdivMeshTLS *tls = tls_v;
469         if (tls->vertex_interpolation_initialized) {
470                 vertex_interpolation_end(&tls->vertex_interpolation);
471         }
472         if (tls->loop_interpolation_initialized) {
473                 loop_interpolation_end(&tls->loop_interpolation);
474         }
475 }
476
477 /* =============================================================================
478  * Evaluation helper functions.
479  */
480
481 static void eval_final_point_and_vertex_normal(
482         Subdiv *subdiv,
483         const int ptex_face_index,
484         const float u, const float v,
485         float r_P[3], short r_N[3])
486 {
487         if (subdiv->displacement_evaluator == NULL) {
488                 BKE_subdiv_eval_limit_point_and_short_normal(
489                         subdiv, ptex_face_index, u, v, r_P, r_N);
490         }
491         else {
492                 BKE_subdiv_eval_final_point(
493                         subdiv, ptex_face_index, u, v, r_P);
494         }
495 }
496
497 /* =============================================================================
498  * Accumulation helpers.
499  */
500
501 static void subdiv_accumulate_vertex_normal_and_displacement(
502         SubdivMeshContext *ctx,
503         const int ptex_face_index,
504         const float u, const float v,
505         MVert *subdiv_vert)
506 {
507         Subdiv *subdiv = ctx->subdiv;
508         const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
509         float dummy_P[3], dPdu[3], dPdv[3], D[3];
510         BKE_subdiv_eval_limit_point_and_derivatives(
511                 subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
512         /* Accumulate normal. */
513         if (ctx->can_evaluate_normals) {
514                 float N[3];
515                 cross_v3_v3v3(N, dPdu, dPdv);
516                 normalize_v3(N);
517                 add_v3_v3(ctx->accumulated_normals[subdiv_vertex_index], N);
518         }
519         /* Accumulate displacement if needed. */
520         if (ctx->have_displacement) {
521                 BKE_subdiv_eval_displacement(
522                         subdiv, ptex_face_index, u, v, dPdu, dPdv, D);
523                 add_v3_v3(subdiv_vert->co, D);
524         }
525         ++ctx->accumulated_counters[subdiv_vertex_index];
526 }
527
528 /* =============================================================================
529  * Callbacks.
530  */
531
532 static bool subdiv_mesh_topology_info(
533         const SubdivForeachContext *foreach_context,
534         const int num_vertices,
535         const int num_edges,
536         const int num_loops,
537         const int num_polygons)
538 {
539         SubdivMeshContext *subdiv_context = foreach_context->user_data;
540         subdiv_context->subdiv_mesh = BKE_mesh_new_nomain_from_template(
541                 subdiv_context->coarse_mesh,
542                 num_vertices,
543                 num_edges,
544                 0,
545                 num_loops,
546                 num_polygons);
547         subdiv_mesh_ctx_cache_custom_data_layers(subdiv_context);
548         subdiv_mesh_prepare_accumulator(subdiv_context, num_vertices);
549         return true;
550 }
551
552 /* =============================================================================
553  * Vertex subdivision process.
554  */
555
556 static void subdiv_vertex_data_copy(
557         const SubdivMeshContext *ctx,
558         const MVert *coarse_vertex,
559         MVert *subdiv_vertex)
560 {
561         const Mesh *coarse_mesh = ctx->coarse_mesh;
562         Mesh *subdiv_mesh = ctx->subdiv_mesh;
563         const int coarse_vertex_index = coarse_vertex - coarse_mesh->mvert;
564         const int subdiv_vertex_index = subdiv_vertex - subdiv_mesh->mvert;
565         CustomData_copy_data(&coarse_mesh->vdata,
566                              &ctx->subdiv_mesh->vdata,
567                              coarse_vertex_index,
568                              subdiv_vertex_index,
569                              1);
570 }
571
572 static void subdiv_vertex_data_interpolate(
573         const SubdivMeshContext *ctx,
574         MVert *subdiv_vertex,
575         const VerticesForInterpolation *vertex_interpolation,
576         const float u, const float v)
577 {
578         const int subdiv_vertex_index = subdiv_vertex - ctx->subdiv_mesh->mvert;
579         const float weights[4] = {(1.0f - u) * (1.0f - v),
580                                   u * (1.0f - v),
581                                   u * v,
582                                   (1.0f - u) * v};
583         CustomData_interp(vertex_interpolation->vertex_data,
584                           &ctx->subdiv_mesh->vdata,
585                           vertex_interpolation->vertex_indices,
586                           weights, NULL,
587                           4,
588                           subdiv_vertex_index);
589         if (ctx->vert_origindex != NULL) {
590                 ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE;
591         }
592 }
593
594 static void evaluate_vertex_and_apply_displacement_copy(
595         const SubdivMeshContext *ctx,
596         const int ptex_face_index,
597         const float u, const float v,
598         const MVert *coarse_vert,
599         MVert *subdiv_vert)
600 {
601         const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
602         const float inv_num_accumulated =
603                 1.0f / ctx->accumulated_counters[subdiv_vertex_index];
604         /* Displacement is accumulated in subdiv vertex position.
605          * Needs to to be backed up before copying data from original vertex. */
606         float D[3] = {0.0f, 0.0f, 0.0f};
607         if (ctx->have_displacement) {
608                 copy_v3_v3(D, subdiv_vert->co);
609                 mul_v3_fl(D, inv_num_accumulated);
610         }
611         /* Copy custom data and evaluate position. */
612         subdiv_vertex_data_copy(ctx, coarse_vert, subdiv_vert);
613         BKE_subdiv_eval_limit_point(
614                 ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
615         /* Apply displacement. */
616         add_v3_v3(subdiv_vert->co, D);
617         /* Copy normal from accumulated storage. */
618         if (ctx->can_evaluate_normals) {
619                 float N[3];
620                 copy_v3_v3(N, ctx->accumulated_normals[subdiv_vertex_index]);
621                 normalize_v3(N);
622                 normal_float_to_short_v3(subdiv_vert->no, N);
623         }
624 }
625
626 static void evaluate_vertex_and_apply_displacement_interpolate(
627         const SubdivMeshContext *ctx,
628         const int ptex_face_index,
629         const float u, const float v,
630         VerticesForInterpolation *vertex_interpolation,
631         MVert *subdiv_vert)
632 {
633         const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
634         const float inv_num_accumulated =
635                 1.0f / ctx->accumulated_counters[subdiv_vertex_index];
636         /* Displacement is accumulated in subdiv vertex position.
637          * Needs to to be backed up before copying data from original vertex. */
638         float D[3] = {0.0f, 0.0f, 0.0f};
639         if (ctx->have_displacement) {
640                 copy_v3_v3(D, subdiv_vert->co);
641                 mul_v3_fl(D, inv_num_accumulated);
642         }
643         /* Interpolate custom data and evaluate position. */
644         subdiv_vertex_data_interpolate(
645                 ctx, subdiv_vert, vertex_interpolation, u, v);
646         BKE_subdiv_eval_limit_point(
647                 ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
648         /* Apply displacement. */
649         add_v3_v3(subdiv_vert->co, D);
650         /* Copy normal from accumulated storage. */
651         if (ctx->can_evaluate_normals) {
652                 float N[3];
653                 copy_v3_v3(N, ctx->accumulated_normals[subdiv_vertex_index]);
654                 mul_v3_fl(N, inv_num_accumulated);
655                 normalize_v3(N);
656                 normal_float_to_short_v3(subdiv_vert->no, N);
657         }
658 }
659
660 static void subdiv_mesh_vertex_every_corner_or_edge(
661         const SubdivForeachContext *foreach_context,
662         void *UNUSED(tls),
663         const int ptex_face_index,
664         const float u, const float v,
665         const int subdiv_vertex_index)
666 {
667         SubdivMeshContext *ctx = foreach_context->user_data;
668         Mesh *subdiv_mesh = ctx->subdiv_mesh;
669         MVert *subdiv_mvert = subdiv_mesh->mvert;
670         MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
671         subdiv_accumulate_vertex_normal_and_displacement(
672                 ctx, ptex_face_index, u, v, subdiv_vert);
673 }
674
675 static void subdiv_mesh_vertex_every_corner(
676         const SubdivForeachContext *foreach_context,
677         void *tls,
678         const int ptex_face_index,
679         const float u, const float v,
680         const int UNUSED(coarse_vertex_index),
681         const int UNUSED(coarse_poly_index),
682         const int UNUSED(coarse_corner),
683         const int subdiv_vertex_index)
684 {
685         subdiv_mesh_vertex_every_corner_or_edge(
686                 foreach_context, tls, ptex_face_index, u, v, subdiv_vertex_index);
687 }
688
689 static void subdiv_mesh_vertex_every_edge(
690         const SubdivForeachContext *foreach_context,
691         void *tls,
692         const int ptex_face_index,
693         const float u, const float v,
694         const int UNUSED(coarse_edge_index),
695         const int UNUSED(coarse_poly_index),
696         const int UNUSED(coarse_corner),
697         const int subdiv_vertex_index)
698 {
699         subdiv_mesh_vertex_every_corner_or_edge(
700                 foreach_context, tls, ptex_face_index, u, v, subdiv_vertex_index);
701 }
702
703 static void subdiv_mesh_vertex_corner(
704         const SubdivForeachContext *foreach_context,
705         void *UNUSED(tls),
706         const int ptex_face_index,
707         const float u, const float v,
708         const int coarse_vertex_index,
709         const int UNUSED(coarse_poly_index),
710         const int UNUSED(coarse_corner),
711         const int subdiv_vertex_index)
712 {
713         BLI_assert(coarse_vertex_index != ORIGINDEX_NONE);
714         SubdivMeshContext *ctx = foreach_context->user_data;
715         const Mesh *coarse_mesh = ctx->coarse_mesh;
716         const MVert *coarse_mvert = coarse_mesh->mvert;
717         Mesh *subdiv_mesh = ctx->subdiv_mesh;
718         MVert *subdiv_mvert = subdiv_mesh->mvert;
719         const MVert *coarse_vert = &coarse_mvert[coarse_vertex_index];
720         MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
721         evaluate_vertex_and_apply_displacement_copy(
722                 ctx, ptex_face_index, u, v, coarse_vert, subdiv_vert);
723 }
724
725 static void subdiv_mesh_ensure_vertex_interpolation(
726         SubdivMeshContext *ctx,
727         SubdivMeshTLS *tls,
728         const MPoly *coarse_poly,
729         const int coarse_corner)
730 {
731         /* Check whether we've moved to another corner or polygon. */
732         if (tls->vertex_interpolation_initialized) {
733                 if (tls->vertex_interpolation_coarse_poly != coarse_poly ||
734                     tls->vertex_interpolation_coarse_corner != coarse_corner)
735                 {
736                         vertex_interpolation_end(&tls->vertex_interpolation);
737                         tls->vertex_interpolation_initialized = false;
738                 }
739         }
740         /* Initialize the interpolation. */
741         if (!tls->vertex_interpolation_initialized) {
742                 vertex_interpolation_init(ctx, &tls->vertex_interpolation, coarse_poly);
743         }
744         /* Update it for a new corner if needed. */
745         if (!tls->vertex_interpolation_initialized ||
746             tls->vertex_interpolation_coarse_corner != coarse_corner)
747         {
748                 vertex_interpolation_from_corner(
749                         ctx, &tls->vertex_interpolation, coarse_poly, coarse_corner);
750         }
751         /* Store settings used for the current state of interpolator. */
752         tls->vertex_interpolation_initialized = true;
753         tls->vertex_interpolation_coarse_poly = coarse_poly;
754         tls->vertex_interpolation_coarse_corner = coarse_corner;
755 }
756
757 static void subdiv_mesh_vertex_edge(
758         const SubdivForeachContext *foreach_context,
759         void *tls_v,
760         const int ptex_face_index,
761         const float u, const float v,
762         const int UNUSED(coarse_edge_index),
763         const int coarse_poly_index,
764         const int coarse_corner,
765         const int subdiv_vertex_index)
766 {
767         SubdivMeshContext *ctx = foreach_context->user_data;
768         SubdivMeshTLS *tls = tls_v;
769         const Mesh *coarse_mesh = ctx->coarse_mesh;
770         const MPoly *coarse_mpoly = coarse_mesh->mpoly;
771         const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
772         Mesh *subdiv_mesh = ctx->subdiv_mesh;
773         MVert *subdiv_mvert = subdiv_mesh->mvert;
774         MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
775         subdiv_mesh_ensure_vertex_interpolation(
776                 ctx, tls, coarse_poly, coarse_corner);
777         evaluate_vertex_and_apply_displacement_interpolate(
778                 ctx,
779                 ptex_face_index, u, v,
780                 &tls->vertex_interpolation,
781                 subdiv_vert);
782 }
783
784 static void subdiv_mesh_vertex_inner(
785         const SubdivForeachContext *foreach_context,
786         void *tls_v,
787         const int ptex_face_index,
788         const float u, const float v,
789         const int coarse_poly_index,
790         const int coarse_corner,
791         const int subdiv_vertex_index)
792 {
793         SubdivMeshContext *ctx = foreach_context->user_data;
794         SubdivMeshTLS *tls = tls_v;
795         Subdiv *subdiv = ctx->subdiv;
796         const Mesh *coarse_mesh = ctx->coarse_mesh;
797         const MPoly *coarse_mpoly = coarse_mesh->mpoly;
798         const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
799         Mesh *subdiv_mesh = ctx->subdiv_mesh;
800         MVert *subdiv_mvert = subdiv_mesh->mvert;
801         MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
802         subdiv_mesh_ensure_vertex_interpolation(
803                 ctx, tls, coarse_poly, coarse_corner);
804         subdiv_vertex_data_interpolate(
805                 ctx, subdiv_vert, &tls->vertex_interpolation, u, v);
806         eval_final_point_and_vertex_normal(
807                 subdiv, ptex_face_index, u, v, subdiv_vert->co, subdiv_vert->no);
808 }
809
810 /* =============================================================================
811  * Edge subdivision process.
812  */
813
814 static void subdiv_copy_edge_data(
815         SubdivMeshContext *ctx,
816         MEdge *subdiv_edge,
817         const MEdge *coarse_edge)
818 {
819         const int subdiv_edge_index = subdiv_edge - ctx->subdiv_mesh->medge;
820         if (coarse_edge == NULL) {
821                 subdiv_edge->crease = 0;
822                 subdiv_edge->bweight = 0;
823                 subdiv_edge->flag = 0;
824                 if (!ctx->settings->use_optimal_display) {
825                         subdiv_edge->flag |= ME_EDGERENDER;
826                 }
827                 if (ctx->edge_origindex != NULL) {
828                         ctx->edge_origindex[subdiv_edge_index] = ORIGINDEX_NONE;
829                 }
830                 return;
831         }
832         const int coarse_edge_index = coarse_edge - ctx->coarse_mesh->medge;
833         CustomData_copy_data(&ctx->coarse_mesh->edata,
834                              &ctx->subdiv_mesh->edata,
835                              coarse_edge_index,
836                              subdiv_edge_index,
837                              1);
838         subdiv_edge->flag |= ME_EDGERENDER;
839 }
840
841 static void subdiv_mesh_edge(
842         const SubdivForeachContext *foreach_context,
843         void *UNUSED(tls),
844         const int coarse_edge_index,
845         const int subdiv_edge_index,
846         const int subdiv_v1, const int subdiv_v2)
847 {
848         SubdivMeshContext *ctx = foreach_context->user_data;
849         Mesh *subdiv_mesh = ctx->subdiv_mesh;
850         MEdge *subdiv_medge = subdiv_mesh->medge;
851         MEdge *subdiv_edge = &subdiv_medge[subdiv_edge_index];
852         const MEdge *coarse_edge = NULL;
853         if (coarse_edge_index != ORIGINDEX_NONE) {
854                 const Mesh *coarse_mesh = ctx->coarse_mesh;
855                 const MEdge *coarse_medge = coarse_mesh->medge;
856                 coarse_edge = &coarse_medge[coarse_edge_index];
857         }
858         subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge);
859         subdiv_edge->v1 = subdiv_v1;
860         subdiv_edge->v2 = subdiv_v2;
861 }
862
863 /* =============================================================================
864  * Loops creation/interpolation.
865  */
866
867 static void subdiv_interpolate_loop_data(
868         const SubdivMeshContext *ctx,
869         MLoop *subdiv_loop,
870         const LoopsForInterpolation *loop_interpolation,
871         const float u, const float v)
872 {
873         const int subdiv_loop_index = subdiv_loop - ctx->subdiv_mesh->mloop;
874         const float weights[4] = {(1.0f - u) * (1.0f - v),
875                                   u * (1.0f - v),
876                                   u * v,
877                                   (1.0f - u) * v};
878         CustomData_interp(loop_interpolation->loop_data,
879                           &ctx->subdiv_mesh->ldata,
880                           loop_interpolation->loop_indices,
881                           weights, NULL,
882                           4,
883                           subdiv_loop_index);
884         /* TODO(sergey): Set ORIGINDEX. */
885 }
886
887 static void subdiv_eval_uv_layer(SubdivMeshContext *ctx,
888                                  MLoop *subdiv_loop,
889                                  const int ptex_face_index,
890                                  const float u, const float v)
891 {
892         if (ctx->num_uv_layers == 0) {
893                 return;
894         }
895         Subdiv *subdiv = ctx->subdiv;
896         const int mloop_index = subdiv_loop - ctx->subdiv_mesh->mloop;
897         for (int layer_index = 0; layer_index < ctx->num_uv_layers; layer_index++) {
898                 MLoopUV *subdiv_loopuv = &ctx->uv_layers[layer_index][mloop_index];
899                 BKE_subdiv_eval_face_varying(subdiv,
900                                              layer_index,
901                                              ptex_face_index,
902                                              u, v,
903                                              subdiv_loopuv->uv);
904         }
905 }
906
907 static void subdiv_mesh_ensure_loop_interpolation(
908         SubdivMeshContext *ctx,
909         SubdivMeshTLS *tls,
910         const MPoly *coarse_poly,
911         const int coarse_corner)
912 {
913         /* Check whether we've moved to another corner or polygon. */
914         if (tls->loop_interpolation_initialized) {
915                 if (tls->loop_interpolation_coarse_poly != coarse_poly ||
916                     tls->loop_interpolation_coarse_corner != coarse_corner)
917                 {
918                         loop_interpolation_end(&tls->loop_interpolation);
919                         tls->loop_interpolation_initialized = false;
920                 }
921         }
922         /* Initialize the interpolation. */
923         if (!tls->loop_interpolation_initialized) {
924                 loop_interpolation_init(ctx, &tls->loop_interpolation, coarse_poly);
925         }
926         /* Update it for a new corner if needed. */
927         if (!tls->loop_interpolation_initialized ||
928             tls->loop_interpolation_coarse_corner != coarse_corner)
929         {
930                 loop_interpolation_from_corner(
931                         ctx, &tls->loop_interpolation, coarse_poly, coarse_corner);
932         }
933         /* Store settings used for the current state of interpolator. */
934         tls->loop_interpolation_initialized = true;
935         tls->loop_interpolation_coarse_poly = coarse_poly;
936         tls->loop_interpolation_coarse_corner = coarse_corner;
937 }
938
939 static void subdiv_mesh_loop(
940         const SubdivForeachContext *foreach_context,
941         void *tls_v,
942         const int ptex_face_index,
943         const float u, const float v,
944         const int UNUSED(coarse_loop_index),
945         const int coarse_poly_index,
946         const int coarse_corner,
947         const int subdiv_loop_index,
948         const int subdiv_vertex_index, const int subdiv_edge_index)
949 {
950         SubdivMeshContext *ctx = foreach_context->user_data;
951         SubdivMeshTLS *tls = tls_v;
952         const Mesh *coarse_mesh = ctx->coarse_mesh;
953         const MPoly *coarse_mpoly = coarse_mesh->mpoly;
954         const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
955         Mesh *subdiv_mesh = ctx->subdiv_mesh;
956         MLoop *subdiv_mloop = subdiv_mesh->mloop;
957         MLoop *subdiv_loop = &subdiv_mloop[subdiv_loop_index];
958         subdiv_mesh_ensure_loop_interpolation(
959                 ctx, tls, coarse_poly, coarse_corner);
960         subdiv_interpolate_loop_data(
961                 ctx, subdiv_loop, &tls->loop_interpolation, u, v);
962         subdiv_eval_uv_layer(ctx, subdiv_loop, ptex_face_index, u, v);
963         subdiv_loop->v = subdiv_vertex_index;
964         subdiv_loop->e = subdiv_edge_index;
965 }
966
967 /* =============================================================================
968  * Polygons subdivision process.
969  */
970
971 static void subdiv_copy_poly_data(const SubdivMeshContext *ctx,
972                                   MPoly *subdiv_poly,
973                                   const MPoly *coarse_poly)
974 {
975         const int coarse_poly_index = coarse_poly - ctx->coarse_mesh->mpoly;
976         const int subdiv_poly_index = subdiv_poly - ctx->subdiv_mesh->mpoly;
977         CustomData_copy_data(&ctx->coarse_mesh->pdata,
978                              &ctx->subdiv_mesh->pdata,
979                              coarse_poly_index,
980                              subdiv_poly_index,
981                              1);
982 }
983
984 static void subdiv_mesh_poly(
985         const SubdivForeachContext *foreach_context,
986         void *UNUSED(tls),
987         const int coarse_poly_index,
988         const int subdiv_poly_index,
989         const int start_loop_index, const int num_loops)
990 {
991         BLI_assert(coarse_poly_index != ORIGINDEX_NONE);
992         SubdivMeshContext *ctx = foreach_context->user_data;
993         const Mesh *coarse_mesh = ctx->coarse_mesh;
994         const MPoly *coarse_mpoly = coarse_mesh->mpoly;
995         const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
996         Mesh *subdiv_mesh = ctx->subdiv_mesh;
997         MPoly *subdiv_mpoly = subdiv_mesh->mpoly;
998         MPoly *subdiv_poly = &subdiv_mpoly[subdiv_poly_index];
999         subdiv_copy_poly_data(ctx, subdiv_poly, coarse_poly);
1000         subdiv_poly->loopstart = start_loop_index;
1001         subdiv_poly->totloop = num_loops;
1002 }
1003
1004 /* =============================================================================
1005  * Loose elements subdivision process.
1006  */
1007
1008 static void subdiv_mesh_vertex_loose(
1009         const SubdivForeachContext *foreach_context,
1010         void *UNUSED(tls),
1011         const int coarse_vertex_index,
1012         const int subdiv_vertex_index)
1013 {
1014         SubdivMeshContext *ctx = foreach_context->user_data;
1015         const Mesh *coarse_mesh = ctx->coarse_mesh;
1016         const MVert *coarse_mvert = coarse_mesh->mvert;
1017         const MVert *coarse_vertex = &coarse_mvert[coarse_vertex_index];
1018         Mesh *subdiv_mesh = ctx->subdiv_mesh;
1019         MVert *subdiv_mvert = subdiv_mesh->mvert;
1020         MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index];
1021         subdiv_vertex_data_copy(ctx, coarse_vertex, subdiv_vertex);
1022 }
1023
1024 /* Get neighbor edges of the given one.
1025  * - neighbors[0] is an edge adjacent to edge->v1.
1026  * - neighbors[1] is an edge adjacent to edge->v2. */
1027 static void find_edge_neighbors(const SubdivMeshContext *ctx,
1028                                 const MEdge *edge,
1029                                 const MEdge *neighbors[2])
1030 {
1031         const Mesh *coarse_mesh = ctx->coarse_mesh;
1032         const MEdge *coarse_medge = coarse_mesh->medge;
1033         neighbors[0] = NULL;
1034         neighbors[1] = NULL;
1035         int neighbor_counters[2] = {0, 0};
1036         for (int edge_index = 0; edge_index < coarse_mesh->totedge; edge_index++) {
1037                 const MEdge *current_edge = &coarse_medge[edge_index];
1038                 if (current_edge == edge) {
1039                         continue;
1040                 }
1041                 if (ELEM(edge->v1, current_edge->v1, current_edge->v2)) {
1042                         neighbors[0] = current_edge;
1043                         ++neighbor_counters[0];
1044                 }
1045                 if (ELEM(edge->v2, current_edge->v1, current_edge->v2)) {
1046                         neighbors[1] = current_edge;
1047                         ++neighbor_counters[1];
1048                 }
1049         }
1050         /* Vertices which has more than one neighbor are considered infinitely
1051          * sharp. This is also how topology factory treats vertices of a surface
1052          * which are adjacent to a loose edge. */
1053         if (neighbor_counters[0] > 1) {
1054                 neighbors[0] = NULL;
1055         }
1056         if (neighbor_counters[1] > 1) {
1057                 neighbors[1] = NULL;
1058         }
1059 }
1060
1061 static void points_for_loose_edges_interpolation_get(
1062         SubdivMeshContext *ctx,
1063         const MEdge *coarse_edge,
1064         const MEdge *neighbors[2],
1065         float points_r[4][3])
1066 {
1067         const Mesh *coarse_mesh = ctx->coarse_mesh;
1068         const MVert *coarse_mvert = coarse_mesh->mvert;
1069         /* Middle points corresponds to the edge. */
1070         copy_v3_v3(points_r[1], coarse_mvert[coarse_edge->v1].co);
1071         copy_v3_v3(points_r[2], coarse_mvert[coarse_edge->v2].co);
1072         /* Start point, duplicate from edge start if no neighbor. */
1073         if (neighbors[0] != NULL) {
1074                 if (neighbors[0]->v1 == coarse_edge->v1) {
1075                         copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v2].co);
1076                 }
1077                 else {
1078                         copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v1].co);
1079                 }
1080         }
1081         else {
1082                 sub_v3_v3v3(points_r[0], points_r[1], points_r[2]);
1083                 add_v3_v3(points_r[0], points_r[1]);
1084         }
1085         /* End point, duplicate from edge end if no neighbor. */
1086         if (neighbors[1] != NULL) {
1087                 if (neighbors[1]->v1 == coarse_edge->v2) {
1088                         copy_v3_v3(points_r[3], coarse_mvert[neighbors[1]->v2].co);
1089                 }
1090                 else {
1091                         copy_v3_v3(points_r[3], coarse_mvert[neighbors[1]->v1].co);
1092                 }
1093         }
1094         else {
1095                 sub_v3_v3v3(points_r[3], points_r[2], points_r[1]);
1096                 add_v3_v3(points_r[3], points_r[2]);
1097         }
1098 }
1099
1100 static void subdiv_mesh_vertex_of_loose_edge_interpolate(
1101         SubdivMeshContext *ctx,
1102         const MEdge *coarse_edge,
1103         const float u,
1104         const int subdiv_vertex_index)
1105 {
1106         const Mesh *coarse_mesh = ctx->coarse_mesh;
1107         Mesh *subdiv_mesh = ctx->subdiv_mesh;
1108         if (u == 0.0f) {
1109                 CustomData_copy_data(&coarse_mesh->vdata,
1110                                      &subdiv_mesh->vdata,
1111                                      coarse_edge->v1,
1112                                      subdiv_vertex_index,
1113                                      1);
1114         }
1115         else if (u == 1.0f) {
1116                 CustomData_copy_data(&coarse_mesh->vdata,
1117                                      &subdiv_mesh->vdata,
1118                                      coarse_edge->v2,
1119                                      subdiv_vertex_index,
1120                                      1);
1121         }
1122         else {
1123                 BLI_assert(u > 0.0f);
1124                 BLI_assert(u < 1.0f);
1125                 const float interpolation_weights[2] = {1.0f - u, u};
1126                 const int coarse_vertex_indices[2] = {coarse_edge->v1, coarse_edge->v2};
1127                 CustomData_interp(&coarse_mesh->vdata,
1128                                   &subdiv_mesh->vdata,
1129                                   coarse_vertex_indices,
1130                                   interpolation_weights, NULL,
1131                                   2, subdiv_vertex_index);
1132                 if (ctx->vert_origindex != NULL) {
1133                         ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE;
1134                 }
1135         }
1136 }
1137
1138 static void subdiv_mesh_vertex_of_loose_edge(
1139         const struct SubdivForeachContext *foreach_context,
1140         void *UNUSED(tls),
1141         const int coarse_edge_index,
1142         const float u,
1143         const int subdiv_vertex_index)
1144 {
1145         SubdivMeshContext *ctx = foreach_context->user_data;
1146         const Mesh *coarse_mesh = ctx->coarse_mesh;
1147         const MEdge *coarse_edge = &coarse_mesh->medge[coarse_edge_index];
1148         Mesh *subdiv_mesh = ctx->subdiv_mesh;
1149         MVert *subdiv_mvert = subdiv_mesh->mvert;
1150         /* Find neighbors of the current loose edge. */
1151         const MEdge *neighbors[2];
1152         find_edge_neighbors(ctx, coarse_edge, neighbors);
1153         /* Get points for b-spline interpolation. */
1154         float points[4][3];
1155         points_for_loose_edges_interpolation_get(
1156                 ctx, coarse_edge, neighbors, points);
1157         /* Perform interpolation. */
1158         float weights[4];
1159         key_curve_position_weights(u, weights, KEY_BSPLINE);
1160         /* Interpolate custom data. */
1161         subdiv_mesh_vertex_of_loose_edge_interpolate(
1162                 ctx, coarse_edge, u, subdiv_vertex_index);
1163         /* Initialize  */
1164         MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index];
1165         interp_v3_v3v3v3v3(subdiv_vertex->co,
1166                            points[0],
1167                            points[1],
1168                            points[2],
1169                            points[3],
1170                            weights);
1171         /* Reset flags and such. */
1172         subdiv_vertex->flag = 0;
1173         /* TODO(sergey): This matches old behavior, but we can as well interpolate
1174          * it. Maybe even using vertex varying attributes. */
1175         subdiv_vertex->bweight = 0.0f;
1176         /* Reset normal, initialize it in a similar way as edit mode does for a
1177          * vertices adjacent to a loose edges. */
1178         normal_float_to_short_v3(subdiv_vertex->no, subdiv_vertex->co);
1179 }
1180
1181 /* =============================================================================
1182  * Initialization.
1183  */
1184
1185 static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context,
1186                                     SubdivForeachContext *foreach_context)
1187 {
1188         memset(foreach_context, 0, sizeof(*foreach_context));
1189         /* General information. */
1190         foreach_context->topology_info = subdiv_mesh_topology_info;
1191         /* Every boundary geometry. Used for dispalcement and normals averaging. */
1192         if (subdiv_context->can_evaluate_normals ||
1193             subdiv_context->have_displacement)
1194         {
1195                 foreach_context->vertex_every_corner = subdiv_mesh_vertex_every_corner;
1196                 foreach_context->vertex_every_edge = subdiv_mesh_vertex_every_edge;
1197         }
1198         else {
1199                 foreach_context->vertex_every_corner = NULL;
1200                 foreach_context->vertex_every_edge = NULL;
1201         }
1202         foreach_context->vertex_corner = subdiv_mesh_vertex_corner;
1203         foreach_context->vertex_edge = subdiv_mesh_vertex_edge;
1204         foreach_context->vertex_inner = subdiv_mesh_vertex_inner;
1205         foreach_context->edge = subdiv_mesh_edge;
1206         foreach_context->loop = subdiv_mesh_loop;
1207         foreach_context->poly = subdiv_mesh_poly;
1208         foreach_context->vertex_loose = subdiv_mesh_vertex_loose;
1209         foreach_context->vertex_of_loose_edge = subdiv_mesh_vertex_of_loose_edge;
1210         foreach_context->user_data_tls_free = subdiv_mesh_tls_free;
1211 }
1212
1213 /* =============================================================================
1214  * Public entry point.
1215  */
1216
1217 Mesh *BKE_subdiv_to_mesh(
1218         Subdiv *subdiv,
1219         const SubdivToMeshSettings *settings,
1220         const Mesh *coarse_mesh)
1221 {
1222         BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
1223         /* Make sure evaluator is up to date with possible new topology, and that
1224          * is is refined for the new positions of coarse vertices.
1225          */
1226         if (!BKE_subdiv_eval_update_from_mesh(subdiv, coarse_mesh)) {
1227                 /* This could happen in two situations:
1228                  * - OpenSubdiv is disabled.
1229                  * - Something totally bad happened, and OpenSubdiv rejected our
1230                  *   topology.
1231                  * In either way, we can't safely continue. */
1232                 if (coarse_mesh->totpoly) {
1233                         BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
1234                         return NULL;
1235                 }
1236         }
1237         /* Initialize subdivion mesh creation context/ */
1238         SubdivMeshContext subdiv_context = {0};
1239         subdiv_context.settings = settings;
1240         subdiv_context.coarse_mesh = coarse_mesh;
1241         subdiv_context.subdiv = subdiv;
1242         subdiv_context.have_displacement =
1243                 (subdiv->displacement_evaluator != NULL);
1244         subdiv_context.can_evaluate_normals = !subdiv_context.have_displacement;
1245         /* Multi-threaded traversal/evaluation. */
1246         BKE_subdiv_stats_begin(&subdiv->stats,
1247                                SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
1248         SubdivForeachContext foreach_context;
1249         setup_foreach_callbacks(&subdiv_context, &foreach_context);
1250         SubdivMeshTLS tls = {0};
1251         foreach_context.user_data = &subdiv_context;
1252         foreach_context.user_data_tls_size = sizeof(SubdivMeshTLS);
1253         foreach_context.user_data_tls = &tls;
1254         BKE_subdiv_foreach_subdiv_geometry(
1255                 subdiv, &foreach_context, settings, coarse_mesh);
1256         BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
1257         Mesh *result = subdiv_context.subdiv_mesh;
1258         // BKE_mesh_validate(result, true, true);
1259         BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
1260         if (!subdiv_context.can_evaluate_normals) {
1261                 result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
1262         }
1263         /* Free used memoty. */
1264         subdiv_mesh_context_free(&subdiv_context);
1265         return result;
1266 }