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 "BKE_subdiv_foreach.h"
25 
26 #include "atomic_ops.h"
27 
28 #include "DNA_key_types.h"
29 #include "DNA_mesh_types.h"
30 #include "DNA_meshdata_types.h"
31 
32 #include "BLI_bitmap.h"
33 #include "BLI_task.h"
34 
35 #include "BKE_customdata.h"
36 #include "BKE_key.h"
37 #include "BKE_mesh.h"
38 #include "BKE_subdiv.h"
39 #include "BKE_subdiv_mesh.h"
40 
41 #include "MEM_guardedalloc.h"
42 
43 /* -------------------------------------------------------------------- */
44 /** \name General helpers
45  * \{ */
46 
47 /* Number of ptex faces for a given polygon. */
num_ptex_faces_per_poly_get(const MPoly * poly)48 BLI_INLINE int num_ptex_faces_per_poly_get(const MPoly *poly)
49 {
50   return (poly->totloop == 4) ? 1 : poly->totloop;
51 }
52 
num_edges_per_ptex_face_get(const int resolution)53 BLI_INLINE int num_edges_per_ptex_face_get(const int resolution)
54 {
55   return 2 * (resolution - 1) * resolution;
56 }
57 
num_inner_edges_per_ptex_face_get(const int resolution)58 BLI_INLINE int num_inner_edges_per_ptex_face_get(const int resolution)
59 {
60   if (resolution < 2) {
61     return 0;
62   }
63   return (resolution - 2) * resolution + (resolution - 1) * (resolution - 1);
64 }
65 
66 /* Number of subdivision polygons per ptex face. */
num_polys_per_ptex_get(const int resolution)67 BLI_INLINE int num_polys_per_ptex_get(const int resolution)
68 {
69   return (resolution - 1) * (resolution - 1);
70 }
71 
72 /* Subdivision resolution per given polygon's ptex faces. */
ptex_face_resolution_get(const MPoly * poly,int resolution)73 BLI_INLINE int ptex_face_resolution_get(const MPoly *poly, int resolution)
74 {
75   return (poly->totloop == 4) ? (resolution) : ((resolution >> 1) + 1);
76 }
77 
78 /** \} */
79 
80 /* -------------------------------------------------------------------- */
81 /** \name Context which is passed to all threaded tasks
82  * \{ */
83 
84 typedef struct SubdivForeachTaskContext {
85   const Mesh *coarse_mesh;
86   const SubdivToMeshSettings *settings;
87   /* Callbacks. */
88   const SubdivForeachContext *foreach_context;
89   /* Counters of geometry in subdivided mesh, initialized as a part of
90    * offsets calculation.
91    */
92   int num_subdiv_vertices;
93   int num_subdiv_edges;
94   int num_subdiv_loops;
95   int num_subdiv_polygons;
96   /* Offsets of various geometry in the subdivision mesh arrays. */
97   int vertices_corner_offset;
98   int vertices_edge_offset;
99   int vertices_inner_offset;
100   int edge_boundary_offset;
101   int edge_inner_offset;
102   /* Indexed by coarse polygon index, indicates offset in subdivided mesh
103    * vertices, edges and polygons arrays, where first element of the poly
104    * begins.
105    */
106   int *subdiv_vertex_offset;
107   int *subdiv_edge_offset;
108   int *subdiv_polygon_offset;
109   /* Indexed by base face index, element indicates total number of ptex faces
110    * created for preceding base faces.
111    */
112   int *face_ptex_offset;
113   /* Bitmap indicating whether vertex was used already or not.
114    * - During patch evaluation indicates whether coarse vertex was already
115    *   evaluated and its position on limit is already known.
116    */
117   BLI_bitmap *coarse_vertices_used_map;
118   /* Bitmap indicating whether edge was used already or not. This includes:
119    * - During context initialization it indicates whether subdivided vertices
120    *   for corresponding edge were already calculated or not.
121    * - During patch evaluation it indicates whether vertices along this edge
122    *   were already evaluated.
123    */
124   BLI_bitmap *coarse_edges_used_map;
125 } SubdivForeachTaskContext;
126 
127 /** \} */
128 
129 /* -------------------------------------------------------------------- */
130 /** \name Threading helpers
131  * \{ */
132 
subdiv_foreach_tls_alloc(SubdivForeachTaskContext * ctx)133 static void *subdiv_foreach_tls_alloc(SubdivForeachTaskContext *ctx)
134 {
135   const SubdivForeachContext *foreach_context = ctx->foreach_context;
136   void *tls = NULL;
137   if (foreach_context->user_data_tls_size != 0) {
138     tls = MEM_mallocN(foreach_context->user_data_tls_size, "tls");
139     memcpy(tls, foreach_context->user_data_tls, foreach_context->user_data_tls_size);
140   }
141   return tls;
142 }
143 
subdiv_foreach_tls_free(SubdivForeachTaskContext * ctx,void * tls)144 static void subdiv_foreach_tls_free(SubdivForeachTaskContext *ctx, void *tls)
145 {
146   if (tls == NULL) {
147     return;
148   }
149   if (ctx->foreach_context != NULL) {
150     ctx->foreach_context->user_data_tls_free(tls);
151   }
152   MEM_freeN(tls);
153 }
154 
155 /** \} */
156 
157 /* -------------------------------------------------------------------- */
158 /** \name Initialization
159  * \{ */
160 
161 /* NOTE: Expects edge map to be zeroed. */
subdiv_foreach_ctx_count(SubdivForeachTaskContext * ctx)162 static void subdiv_foreach_ctx_count(SubdivForeachTaskContext *ctx)
163 {
164   /* Reset counters. */
165   ctx->num_subdiv_vertices = 0;
166   ctx->num_subdiv_edges = 0;
167   ctx->num_subdiv_loops = 0;
168   ctx->num_subdiv_polygons = 0;
169   /* Static geometry counters. */
170   const int resolution = ctx->settings->resolution;
171   const int no_quad_patch_resolution = ((resolution >> 1) + 1);
172   const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
173   const int num_inner_vertices_per_quad = (resolution - 2) * (resolution - 2);
174   const int num_inner_vertices_per_noquad_patch = (no_quad_patch_resolution - 2) *
175                                                   (no_quad_patch_resolution - 2);
176   const Mesh *coarse_mesh = ctx->coarse_mesh;
177   const MLoop *coarse_mloop = coarse_mesh->mloop;
178   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
179   ctx->num_subdiv_vertices = coarse_mesh->totvert;
180   ctx->num_subdiv_edges = coarse_mesh->totedge * (num_subdiv_vertices_per_coarse_edge + 1);
181   /* Calculate extra vertices and edges created by non-loose geometry. */
182   for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
183     const MPoly *coarse_poly = &coarse_mpoly[poly_index];
184     const int num_ptex_faces_per_poly = num_ptex_faces_per_poly_get(coarse_poly);
185     for (int corner = 0; corner < coarse_poly->totloop; corner++) {
186       const MLoop *loop = &coarse_mloop[coarse_poly->loopstart + corner];
187       const bool is_edge_used = BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, loop->e);
188       /* Edges which aren't counted yet. */
189       if (!is_edge_used) {
190         BLI_BITMAP_ENABLE(ctx->coarse_edges_used_map, loop->e);
191         ctx->num_subdiv_vertices += num_subdiv_vertices_per_coarse_edge;
192       }
193     }
194     /* Inner vertices of polygon. */
195     if (num_ptex_faces_per_poly == 1) {
196       ctx->num_subdiv_vertices += num_inner_vertices_per_quad;
197       ctx->num_subdiv_edges += num_edges_per_ptex_face_get(resolution - 2) +
198                                4 * num_subdiv_vertices_per_coarse_edge;
199       ctx->num_subdiv_polygons += num_polys_per_ptex_get(resolution);
200     }
201     else {
202       ctx->num_subdiv_vertices += 1 + num_ptex_faces_per_poly * (no_quad_patch_resolution - 2) +
203                                   num_ptex_faces_per_poly * num_inner_vertices_per_noquad_patch;
204       ctx->num_subdiv_edges += num_ptex_faces_per_poly *
205                                (num_inner_edges_per_ptex_face_get(no_quad_patch_resolution - 1) +
206                                 (no_quad_patch_resolution - 2) +
207                                 num_subdiv_vertices_per_coarse_edge);
208       if (no_quad_patch_resolution >= 3) {
209         ctx->num_subdiv_edges += coarse_poly->totloop;
210       }
211       ctx->num_subdiv_polygons += num_ptex_faces_per_poly *
212                                   num_polys_per_ptex_get(no_quad_patch_resolution);
213     }
214   }
215   /* Calculate extra vertices created by loose edges. */
216   for (int edge_index = 0; edge_index < coarse_mesh->totedge; edge_index++) {
217     if (!BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, edge_index)) {
218       ctx->num_subdiv_vertices += num_subdiv_vertices_per_coarse_edge;
219     }
220   }
221   ctx->num_subdiv_loops = ctx->num_subdiv_polygons * 4;
222 }
223 
subdiv_foreach_ctx_init_offsets(SubdivForeachTaskContext * ctx)224 static void subdiv_foreach_ctx_init_offsets(SubdivForeachTaskContext *ctx)
225 {
226   const Mesh *coarse_mesh = ctx->coarse_mesh;
227   const int resolution = ctx->settings->resolution;
228   const int resolution_2 = resolution - 2;
229   const int resolution_2_squared = resolution_2 * resolution_2;
230   const int no_quad_patch_resolution = ((resolution >> 1) + 1);
231   const int num_irregular_vertices_per_patch = (no_quad_patch_resolution - 2) *
232                                                (no_quad_patch_resolution - 1);
233   const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
234   const int num_subdiv_edges_per_coarse_edge = resolution - 1;
235   /* Constant offsets in arrays. */
236   ctx->vertices_corner_offset = 0;
237   ctx->vertices_edge_offset = coarse_mesh->totvert;
238   ctx->vertices_inner_offset = ctx->vertices_edge_offset +
239                                coarse_mesh->totedge * num_subdiv_vertices_per_coarse_edge;
240   ctx->edge_boundary_offset = 0;
241   ctx->edge_inner_offset = ctx->edge_boundary_offset +
242                            coarse_mesh->totedge * num_subdiv_edges_per_coarse_edge;
243   /* "Indexed" offsets. */
244   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
245   int vertex_offset = 0;
246   int edge_offset = 0;
247   int polygon_offset = 0;
248   for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
249     const MPoly *coarse_poly = &coarse_mpoly[poly_index];
250     const int num_ptex_faces_per_poly = num_ptex_faces_per_poly_get(coarse_poly);
251     ctx->subdiv_vertex_offset[poly_index] = vertex_offset;
252     ctx->subdiv_edge_offset[poly_index] = edge_offset;
253     ctx->subdiv_polygon_offset[poly_index] = polygon_offset;
254     if (num_ptex_faces_per_poly == 1) {
255       vertex_offset += resolution_2_squared;
256       edge_offset += num_edges_per_ptex_face_get(resolution - 2) +
257                      4 * num_subdiv_vertices_per_coarse_edge;
258       polygon_offset += num_polys_per_ptex_get(resolution);
259     }
260     else {
261       vertex_offset += 1 + num_ptex_faces_per_poly * num_irregular_vertices_per_patch;
262       edge_offset += num_ptex_faces_per_poly *
263                      (num_inner_edges_per_ptex_face_get(no_quad_patch_resolution - 1) +
264                       (no_quad_patch_resolution - 2) + num_subdiv_vertices_per_coarse_edge);
265       if (no_quad_patch_resolution >= 3) {
266         edge_offset += coarse_poly->totloop;
267       }
268       polygon_offset += num_ptex_faces_per_poly * num_polys_per_ptex_get(no_quad_patch_resolution);
269     }
270   }
271 }
272 
subdiv_foreach_ctx_init(Subdiv * subdiv,SubdivForeachTaskContext * ctx)273 static void subdiv_foreach_ctx_init(Subdiv *subdiv, SubdivForeachTaskContext *ctx)
274 {
275   const Mesh *coarse_mesh = ctx->coarse_mesh;
276   /* Allocate maps and offsets. */
277   ctx->coarse_vertices_used_map = BLI_BITMAP_NEW(coarse_mesh->totvert, "vertices used map");
278   ctx->coarse_edges_used_map = BLI_BITMAP_NEW(coarse_mesh->totedge, "edges used map");
279   ctx->subdiv_vertex_offset = MEM_malloc_arrayN(
280       coarse_mesh->totpoly, sizeof(*ctx->subdiv_vertex_offset), "vertex_offset");
281   ctx->subdiv_edge_offset = MEM_malloc_arrayN(
282       coarse_mesh->totpoly, sizeof(*ctx->subdiv_edge_offset), "subdiv_edge_offset");
283   ctx->subdiv_polygon_offset = MEM_malloc_arrayN(
284       coarse_mesh->totpoly, sizeof(*ctx->subdiv_polygon_offset), "subdiv_edge_offset");
285   /* Initialize all offsets. */
286   subdiv_foreach_ctx_init_offsets(ctx);
287   /* Calculate number of geometry in the result subdivision mesh. */
288   subdiv_foreach_ctx_count(ctx);
289   /* Re-set maps which were used at this step. */
290   BLI_bitmap_set_all(ctx->coarse_edges_used_map, false, coarse_mesh->totedge);
291   ctx->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
292 }
293 
subdiv_foreach_ctx_free(SubdivForeachTaskContext * ctx)294 static void subdiv_foreach_ctx_free(SubdivForeachTaskContext *ctx)
295 {
296   MEM_freeN(ctx->coarse_vertices_used_map);
297   MEM_freeN(ctx->coarse_edges_used_map);
298   MEM_freeN(ctx->subdiv_vertex_offset);
299   MEM_freeN(ctx->subdiv_edge_offset);
300   MEM_freeN(ctx->subdiv_polygon_offset);
301 }
302 
303 /** \} */
304 
305 /* -------------------------------------------------------------------- */
306 /** \name Vertex traversal process
307  * \{ */
308 
309 /* Traversal of corner vertices. They are coming from coarse vertices. */
310 
subdiv_foreach_corner_vertices_regular_do(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly,SubdivForeachVertexFromCornerCb vertex_corner,bool check_usage)311 static void subdiv_foreach_corner_vertices_regular_do(
312     SubdivForeachTaskContext *ctx,
313     void *tls,
314     const MPoly *coarse_poly,
315     SubdivForeachVertexFromCornerCb vertex_corner,
316     bool check_usage)
317 {
318   const float weights[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}};
319   const Mesh *coarse_mesh = ctx->coarse_mesh;
320   const MLoop *coarse_mloop = coarse_mesh->mloop;
321   const int coarse_poly_index = coarse_poly - coarse_mesh->mpoly;
322   const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
323   for (int corner = 0; corner < coarse_poly->totloop; corner++) {
324     const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
325     if (check_usage &&
326         BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_loop->v)) {
327       continue;
328     }
329     const int coarse_vertex_index = coarse_loop->v;
330     const int subdiv_vertex_index = ctx->vertices_corner_offset + coarse_vertex_index;
331     const float u = weights[corner][0];
332     const float v = weights[corner][1];
333     vertex_corner(ctx->foreach_context,
334                   tls,
335                   ptex_face_index,
336                   u,
337                   v,
338                   coarse_vertex_index,
339                   coarse_poly_index,
340                   0,
341                   subdiv_vertex_index);
342   }
343 }
344 
subdiv_foreach_corner_vertices_regular(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)345 static void subdiv_foreach_corner_vertices_regular(SubdivForeachTaskContext *ctx,
346                                                    void *tls,
347                                                    const MPoly *coarse_poly)
348 {
349   subdiv_foreach_corner_vertices_regular_do(
350       ctx, tls, coarse_poly, ctx->foreach_context->vertex_corner, true);
351 }
352 
subdiv_foreach_corner_vertices_special_do(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly,SubdivForeachVertexFromCornerCb vertex_corner,bool check_usage)353 static void subdiv_foreach_corner_vertices_special_do(
354     SubdivForeachTaskContext *ctx,
355     void *tls,
356     const MPoly *coarse_poly,
357     SubdivForeachVertexFromCornerCb vertex_corner,
358     bool check_usage)
359 {
360   const Mesh *coarse_mesh = ctx->coarse_mesh;
361   const MLoop *coarse_mloop = coarse_mesh->mloop;
362   const int coarse_poly_index = coarse_poly - coarse_mesh->mpoly;
363   int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
364   for (int corner = 0; corner < coarse_poly->totloop; corner++, ptex_face_index++) {
365     const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
366     if (check_usage &&
367         BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_vertices_used_map, coarse_loop->v)) {
368       continue;
369     }
370     const int coarse_vertex_index = coarse_loop->v;
371     const int subdiv_vertex_index = ctx->vertices_corner_offset + coarse_vertex_index;
372     vertex_corner(ctx->foreach_context,
373                   tls,
374                   ptex_face_index,
375                   0.0f,
376                   0.0f,
377                   coarse_vertex_index,
378                   coarse_poly_index,
379                   corner,
380                   subdiv_vertex_index);
381   }
382 }
383 
subdiv_foreach_corner_vertices_special(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)384 static void subdiv_foreach_corner_vertices_special(SubdivForeachTaskContext *ctx,
385                                                    void *tls,
386                                                    const MPoly *coarse_poly)
387 {
388   subdiv_foreach_corner_vertices_special_do(
389       ctx, tls, coarse_poly, ctx->foreach_context->vertex_corner, true);
390 }
391 
subdiv_foreach_corner_vertices(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)392 static void subdiv_foreach_corner_vertices(SubdivForeachTaskContext *ctx,
393                                            void *tls,
394                                            const MPoly *coarse_poly)
395 {
396   if (coarse_poly->totloop == 4) {
397     subdiv_foreach_corner_vertices_regular(ctx, tls, coarse_poly);
398   }
399   else {
400     subdiv_foreach_corner_vertices_special(ctx, tls, coarse_poly);
401   }
402 }
403 
subdiv_foreach_every_corner_vertices_regular(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)404 static void subdiv_foreach_every_corner_vertices_regular(SubdivForeachTaskContext *ctx,
405                                                          void *tls,
406                                                          const MPoly *coarse_poly)
407 {
408   subdiv_foreach_corner_vertices_regular_do(
409       ctx, tls, coarse_poly, ctx->foreach_context->vertex_every_corner, false);
410 }
411 
subdiv_foreach_every_corner_vertices_special(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)412 static void subdiv_foreach_every_corner_vertices_special(SubdivForeachTaskContext *ctx,
413                                                          void *tls,
414                                                          const MPoly *coarse_poly)
415 {
416   subdiv_foreach_corner_vertices_special_do(
417       ctx, tls, coarse_poly, ctx->foreach_context->vertex_every_corner, false);
418 }
419 
subdiv_foreach_every_corner_vertices(SubdivForeachTaskContext * ctx,void * tls)420 static void subdiv_foreach_every_corner_vertices(SubdivForeachTaskContext *ctx, void *tls)
421 {
422   if (ctx->foreach_context->vertex_every_corner == NULL) {
423     return;
424   }
425   const Mesh *coarse_mesh = ctx->coarse_mesh;
426   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
427   for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
428     const MPoly *coarse_poly = &coarse_mpoly[poly_index];
429     if (coarse_poly->totloop == 4) {
430       subdiv_foreach_every_corner_vertices_regular(ctx, tls, coarse_poly);
431     }
432     else {
433       subdiv_foreach_every_corner_vertices_special(ctx, tls, coarse_poly);
434     }
435   }
436 }
437 
438 /* Traverse of edge vertices. They are coming from coarse edges. */
439 
subdiv_foreach_edge_vertices_regular_do(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly,SubdivForeachVertexFromEdgeCb vertex_edge,bool check_usage)440 static void subdiv_foreach_edge_vertices_regular_do(SubdivForeachTaskContext *ctx,
441                                                     void *tls,
442                                                     const MPoly *coarse_poly,
443                                                     SubdivForeachVertexFromEdgeCb vertex_edge,
444                                                     bool check_usage)
445 {
446   const int resolution = ctx->settings->resolution;
447   const int resolution_1 = resolution - 1;
448   const float inv_resolution_1 = 1.0f / (float)resolution_1;
449   const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
450   const Mesh *coarse_mesh = ctx->coarse_mesh;
451   const MEdge *coarse_medge = coarse_mesh->medge;
452   const MLoop *coarse_mloop = coarse_mesh->mloop;
453   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
454   const int coarse_poly_index = coarse_poly - coarse_mpoly;
455   const int poly_index = coarse_poly - coarse_mesh->mpoly;
456   const int ptex_face_index = ctx->face_ptex_offset[poly_index];
457   for (int corner = 0; corner < coarse_poly->totloop; corner++) {
458     const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
459     const int coarse_edge_index = coarse_loop->e;
460     if (check_usage &&
461         BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map, coarse_edge_index)) {
462       continue;
463     }
464     const MEdge *coarse_edge = &coarse_medge[coarse_edge_index];
465     const bool flip = (coarse_edge->v2 == coarse_loop->v);
466     int subdiv_vertex_index = ctx->vertices_edge_offset +
467                               coarse_edge_index * num_subdiv_vertices_per_coarse_edge;
468     for (int vertex_index = 0; vertex_index < num_subdiv_vertices_per_coarse_edge;
469          vertex_index++, subdiv_vertex_index++) {
470       float fac = (vertex_index + 1) * inv_resolution_1;
471       if (flip) {
472         fac = 1.0f - fac;
473       }
474       if (corner >= 2) {
475         fac = 1.0f - fac;
476       }
477       float u, v;
478       if ((corner & 1) == 0) {
479         u = fac;
480         v = (corner == 2) ? 1.0f : 0.0f;
481       }
482       else {
483         u = (corner == 1) ? 1.0f : 0.0f;
484         v = fac;
485       }
486       vertex_edge(ctx->foreach_context,
487                   tls,
488                   ptex_face_index,
489                   u,
490                   v,
491                   coarse_edge_index,
492                   coarse_poly_index,
493                   0,
494                   subdiv_vertex_index);
495     }
496   }
497 }
498 
subdiv_foreach_edge_vertices_regular(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)499 static void subdiv_foreach_edge_vertices_regular(SubdivForeachTaskContext *ctx,
500                                                  void *tls,
501                                                  const MPoly *coarse_poly)
502 {
503   subdiv_foreach_edge_vertices_regular_do(
504       ctx, tls, coarse_poly, ctx->foreach_context->vertex_edge, true);
505 }
506 
subdiv_foreach_edge_vertices_special_do(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly,SubdivForeachVertexFromEdgeCb vertex_edge,bool check_usage)507 static void subdiv_foreach_edge_vertices_special_do(SubdivForeachTaskContext *ctx,
508                                                     void *tls,
509                                                     const MPoly *coarse_poly,
510                                                     SubdivForeachVertexFromEdgeCb vertex_edge,
511                                                     bool check_usage)
512 {
513   const int resolution = ctx->settings->resolution;
514   const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
515   const int num_vertices_per_ptex_edge = ((resolution >> 1) + 1);
516   const float inv_ptex_resolution_1 = 1.0f / (float)(num_vertices_per_ptex_edge - 1);
517   const Mesh *coarse_mesh = ctx->coarse_mesh;
518   const MEdge *coarse_medge = coarse_mesh->medge;
519   const MLoop *coarse_mloop = coarse_mesh->mloop;
520   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
521   const int coarse_poly_index = coarse_poly - coarse_mpoly;
522   const int poly_index = coarse_poly - coarse_mesh->mpoly;
523   const int ptex_face_start_index = ctx->face_ptex_offset[poly_index];
524   int ptex_face_index = ptex_face_start_index;
525   for (int corner = 0; corner < coarse_poly->totloop; corner++, ptex_face_index++) {
526     const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
527     const int coarse_edge_index = coarse_loop->e;
528     if (check_usage &&
529         BLI_BITMAP_TEST_AND_SET_ATOMIC(ctx->coarse_edges_used_map, coarse_edge_index)) {
530       continue;
531     }
532     const MEdge *coarse_edge = &coarse_medge[coarse_edge_index];
533     const bool flip = (coarse_edge->v2 == coarse_loop->v);
534     int subdiv_vertex_index = ctx->vertices_edge_offset +
535                               coarse_edge_index * num_subdiv_vertices_per_coarse_edge;
536     int vertex_delta = 1;
537     if (flip) {
538       subdiv_vertex_index += num_subdiv_vertices_per_coarse_edge - 1;
539       vertex_delta = -1;
540     }
541     for (int vertex_index = 1; vertex_index < num_vertices_per_ptex_edge;
542          vertex_index++, subdiv_vertex_index += vertex_delta) {
543       const float u = vertex_index * inv_ptex_resolution_1;
544       vertex_edge(ctx->foreach_context,
545                   tls,
546                   ptex_face_index,
547                   u,
548                   0.0f,
549                   coarse_edge_index,
550                   coarse_poly_index,
551                   corner,
552                   subdiv_vertex_index);
553     }
554     const int next_corner = (corner + 1) % coarse_poly->totloop;
555     const int next_ptex_face_index = ptex_face_start_index + next_corner;
556     for (int vertex_index = 1; vertex_index < num_vertices_per_ptex_edge - 1;
557          vertex_index++, subdiv_vertex_index += vertex_delta) {
558       const float v = 1.0f - vertex_index * inv_ptex_resolution_1;
559       vertex_edge(ctx->foreach_context,
560                   tls,
561                   next_ptex_face_index,
562                   0.0f,
563                   v,
564                   coarse_edge_index,
565                   coarse_poly_index,
566                   next_corner,
567                   subdiv_vertex_index);
568     }
569   }
570 }
571 
subdiv_foreach_edge_vertices_special(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)572 static void subdiv_foreach_edge_vertices_special(SubdivForeachTaskContext *ctx,
573                                                  void *tls,
574                                                  const MPoly *coarse_poly)
575 {
576   subdiv_foreach_edge_vertices_special_do(
577       ctx, tls, coarse_poly, ctx->foreach_context->vertex_edge, true);
578 }
579 
subdiv_foreach_edge_vertices(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)580 static void subdiv_foreach_edge_vertices(SubdivForeachTaskContext *ctx,
581                                          void *tls,
582                                          const MPoly *coarse_poly)
583 {
584   if (coarse_poly->totloop == 4) {
585     subdiv_foreach_edge_vertices_regular(ctx, tls, coarse_poly);
586   }
587   else {
588     subdiv_foreach_edge_vertices_special(ctx, tls, coarse_poly);
589   }
590 }
591 
subdiv_foreach_every_edge_vertices_regular(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)592 static void subdiv_foreach_every_edge_vertices_regular(SubdivForeachTaskContext *ctx,
593                                                        void *tls,
594                                                        const MPoly *coarse_poly)
595 {
596   subdiv_foreach_edge_vertices_regular_do(
597       ctx, tls, coarse_poly, ctx->foreach_context->vertex_every_edge, false);
598 }
599 
subdiv_foreach_every_edge_vertices_special(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)600 static void subdiv_foreach_every_edge_vertices_special(SubdivForeachTaskContext *ctx,
601                                                        void *tls,
602                                                        const MPoly *coarse_poly)
603 {
604   subdiv_foreach_edge_vertices_special_do(
605       ctx, tls, coarse_poly, ctx->foreach_context->vertex_every_edge, false);
606 }
607 
subdiv_foreach_every_edge_vertices(SubdivForeachTaskContext * ctx,void * tls)608 static void subdiv_foreach_every_edge_vertices(SubdivForeachTaskContext *ctx, void *tls)
609 {
610   if (ctx->foreach_context->vertex_every_edge == NULL) {
611     return;
612   }
613   const Mesh *coarse_mesh = ctx->coarse_mesh;
614   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
615   for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
616     const MPoly *coarse_poly = &coarse_mpoly[poly_index];
617     if (coarse_poly->totloop == 4) {
618       subdiv_foreach_every_edge_vertices_regular(ctx, tls, coarse_poly);
619     }
620     else {
621       subdiv_foreach_every_edge_vertices_special(ctx, tls, coarse_poly);
622     }
623   }
624 }
625 
626 /* Traversal of inner vertices, they are coming from ptex patches. */
627 
subdiv_foreach_inner_vertices_regular(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)628 static void subdiv_foreach_inner_vertices_regular(SubdivForeachTaskContext *ctx,
629                                                   void *tls,
630                                                   const MPoly *coarse_poly)
631 {
632   const int resolution = ctx->settings->resolution;
633   const float inv_resolution_1 = 1.0f / (float)(resolution - 1);
634   const Mesh *coarse_mesh = ctx->coarse_mesh;
635   const int coarse_poly_index = coarse_poly - coarse_mesh->mpoly;
636   const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
637   const int start_vertex_index = ctx->subdiv_vertex_offset[coarse_poly_index];
638   int subdiv_vertex_index = ctx->vertices_inner_offset + start_vertex_index;
639   for (int y = 1; y < resolution - 1; y++) {
640     const float v = y * inv_resolution_1;
641     for (int x = 1; x < resolution - 1; x++, subdiv_vertex_index++) {
642       const float u = x * inv_resolution_1;
643       ctx->foreach_context->vertex_inner(ctx->foreach_context,
644                                          tls,
645                                          ptex_face_index,
646                                          u,
647                                          v,
648                                          coarse_poly_index,
649                                          0,
650                                          subdiv_vertex_index);
651     }
652   }
653 }
654 
subdiv_foreach_inner_vertices_special(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)655 static void subdiv_foreach_inner_vertices_special(SubdivForeachTaskContext *ctx,
656                                                   void *tls,
657                                                   const MPoly *coarse_poly)
658 {
659   const int resolution = ctx->settings->resolution;
660   const int ptex_face_resolution = ptex_face_resolution_get(coarse_poly, resolution);
661   const float inv_ptex_face_resolution_1 = 1.0f / (float)(ptex_face_resolution - 1);
662   const Mesh *coarse_mesh = ctx->coarse_mesh;
663   const int coarse_poly_index = coarse_poly - coarse_mesh->mpoly;
664   int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
665   const int start_vertex_index = ctx->subdiv_vertex_offset[coarse_poly_index];
666   int subdiv_vertex_index = ctx->vertices_inner_offset + start_vertex_index;
667   ctx->foreach_context->vertex_inner(ctx->foreach_context,
668                                      tls,
669                                      ptex_face_index,
670                                      1.0f,
671                                      1.0f,
672                                      coarse_poly_index,
673                                      0,
674                                      subdiv_vertex_index);
675   subdiv_vertex_index++;
676   for (int corner = 0; corner < coarse_poly->totloop; corner++, ptex_face_index++) {
677     for (int y = 1; y < ptex_face_resolution - 1; y++) {
678       const float v = y * inv_ptex_face_resolution_1;
679       for (int x = 1; x < ptex_face_resolution; x++, subdiv_vertex_index++) {
680         const float u = x * inv_ptex_face_resolution_1;
681         ctx->foreach_context->vertex_inner(ctx->foreach_context,
682                                            tls,
683                                            ptex_face_index,
684                                            u,
685                                            v,
686                                            coarse_poly_index,
687                                            corner,
688                                            subdiv_vertex_index);
689       }
690     }
691   }
692 }
693 
subdiv_foreach_inner_vertices(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)694 static void subdiv_foreach_inner_vertices(SubdivForeachTaskContext *ctx,
695                                           void *tls,
696                                           const MPoly *coarse_poly)
697 {
698   if (coarse_poly->totloop == 4) {
699     subdiv_foreach_inner_vertices_regular(ctx, tls, coarse_poly);
700   }
701   else {
702     subdiv_foreach_inner_vertices_special(ctx, tls, coarse_poly);
703   }
704 }
705 
706 /* Traverse all vertices which are emitted from given coarse polygon. */
subdiv_foreach_vertices(SubdivForeachTaskContext * ctx,void * tls,const int poly_index)707 static void subdiv_foreach_vertices(SubdivForeachTaskContext *ctx, void *tls, const int poly_index)
708 {
709   const Mesh *coarse_mesh = ctx->coarse_mesh;
710   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
711   const MPoly *coarse_poly = &coarse_mpoly[poly_index];
712   if (ctx->foreach_context->vertex_inner != NULL) {
713     subdiv_foreach_inner_vertices(ctx, tls, coarse_poly);
714   }
715 }
716 
717 /** \} */
718 
719 /* -------------------------------------------------------------------- */
720 /** \name Edge traversal process
721  * \{ */
722 
723 /* TODO(sergey): Coarse edge are always NONE, consider getting rid of it. */
subdiv_foreach_edges_row(SubdivForeachTaskContext * ctx,void * tls,const int coarse_edge_index,const int start_subdiv_edge_index,const int start_vertex_index,const int num_edges_per_row)724 static int subdiv_foreach_edges_row(SubdivForeachTaskContext *ctx,
725                                     void *tls,
726                                     const int coarse_edge_index,
727                                     const int start_subdiv_edge_index,
728                                     const int start_vertex_index,
729                                     const int num_edges_per_row)
730 {
731   int subdiv_edge_index = start_subdiv_edge_index;
732   int vertex_index = start_vertex_index;
733   for (int edge_index = 0; edge_index < num_edges_per_row - 1; edge_index++, subdiv_edge_index++) {
734     const int v1 = vertex_index;
735     const int v2 = vertex_index + 1;
736     ctx->foreach_context->edge(
737         ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, v1, v2);
738     vertex_index += 1;
739   }
740   return subdiv_edge_index;
741 }
742 
743 /* TODO(sergey): Coarse edges are always NONE, consider getting rid of them. */
subdiv_foreach_edges_column(SubdivForeachTaskContext * ctx,void * tls,const int coarse_start_edge_index,const int coarse_end_edge_index,const int start_subdiv_edge_index,const int start_vertex_index,const int num_edges_per_row)744 static int subdiv_foreach_edges_column(SubdivForeachTaskContext *ctx,
745                                        void *tls,
746                                        const int coarse_start_edge_index,
747                                        const int coarse_end_edge_index,
748                                        const int start_subdiv_edge_index,
749                                        const int start_vertex_index,
750                                        const int num_edges_per_row)
751 {
752   int subdiv_edge_index = start_subdiv_edge_index;
753   int vertex_index = start_vertex_index;
754   for (int edge_index = 0; edge_index < num_edges_per_row; edge_index++, subdiv_edge_index++) {
755     int coarse_edge_index = ORIGINDEX_NONE;
756     if (edge_index == 0) {
757       coarse_edge_index = coarse_start_edge_index;
758     }
759     else if (edge_index == num_edges_per_row - 1) {
760       coarse_edge_index = coarse_end_edge_index;
761     }
762     const int v1 = vertex_index;
763     const int v2 = vertex_index + num_edges_per_row;
764     ctx->foreach_context->edge(
765         ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, v1, v2);
766     vertex_index += 1;
767   }
768   return subdiv_edge_index;
769 }
770 
771 /* Defines edges between inner vertices of patch, and also edges to the
772  * boundary.
773  */
774 
775 /* Consider a subdivision of base face at level 1:
776  *
777  *  y
778  *  ^
779  *  |   (6) ---- (7) ---- (8)
780  *  |    |        |        |
781  *  |   (3) ---- (4) ---- (5)
782  *  |    |        |        |
783  *  |   (0) ---- (1) ---- (2)
784  *  o---------------------------> x
785  *
786  * This is illustrate which parts of geometry is created by code below.
787  */
788 
subdiv_foreach_edges_all_patches_regular(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)789 static void subdiv_foreach_edges_all_patches_regular(SubdivForeachTaskContext *ctx,
790                                                      void *tls,
791                                                      const MPoly *coarse_poly)
792 {
793   const Mesh *coarse_mesh = ctx->coarse_mesh;
794   const MEdge *coarse_medge = coarse_mesh->medge;
795   const MLoop *coarse_mloop = coarse_mesh->mloop;
796   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
797   const int poly_index = coarse_poly - coarse_mpoly;
798   const int resolution = ctx->settings->resolution;
799   const int start_vertex_index = ctx->vertices_inner_offset +
800                                  ctx->subdiv_vertex_offset[poly_index];
801   const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
802   int subdiv_edge_index = ctx->edge_inner_offset + ctx->subdiv_edge_offset[poly_index];
803   /* Traverse bottom row of edges (0-1, 1-2). */
804   subdiv_edge_index = subdiv_foreach_edges_row(
805       ctx, tls, ORIGINDEX_NONE, subdiv_edge_index, start_vertex_index, resolution - 2);
806   /* Traverse remaining edges. */
807   for (int row = 0; row < resolution - 3; row++) {
808     const int start_row_vertex_index = start_vertex_index + row * (resolution - 2);
809     /* Traverse vertical columns.
810      *
811      * At first iteration it will be edges (0-3. 1-4, 2-5), then it
812      * will be (3-6, 4-7, 5-8) and so on.
813      */
814     subdiv_edge_index = subdiv_foreach_edges_column(ctx,
815                                                     tls,
816                                                     ORIGINDEX_NONE,
817                                                     ORIGINDEX_NONE,
818                                                     subdiv_edge_index,
819                                                     start_row_vertex_index,
820                                                     resolution - 2);
821     /* Create horizontal edge row.
822      *
823      * At first iteration it will be edges (3-4, 4-5), then it will be
824      * (6-7, 7-8) and so on.
825      */
826     subdiv_edge_index = subdiv_foreach_edges_row(ctx,
827                                                  tls,
828                                                  ORIGINDEX_NONE,
829                                                  subdiv_edge_index,
830                                                  start_row_vertex_index + resolution - 2,
831                                                  resolution - 2);
832   }
833   /* Connect inner part of patch to boundary. */
834   for (int corner = 0; corner < coarse_poly->totloop; corner++) {
835     const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
836     const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
837     const int start_edge_vertex = ctx->vertices_edge_offset +
838                                   coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
839     const bool flip = (coarse_edge->v2 == coarse_loop->v);
840     int side_start_index = start_vertex_index;
841     int side_stride = 0;
842     /* Calculate starting vertex of corresponding inner part of ptex. */
843     if (corner == 0) {
844       side_stride = 1;
845     }
846     else if (corner == 1) {
847       side_start_index += resolution - 3;
848       side_stride = resolution - 2;
849     }
850     else if (corner == 2) {
851       side_start_index += num_subdiv_vertices_per_coarse_edge *
852                               num_subdiv_vertices_per_coarse_edge -
853                           1;
854       side_stride = -1;
855     }
856     else if (corner == 3) {
857       side_start_index += num_subdiv_vertices_per_coarse_edge *
858                           (num_subdiv_vertices_per_coarse_edge - 1);
859       side_stride = -(resolution - 2);
860     }
861     for (int i = 0; i < resolution - 2; i++, subdiv_edge_index++) {
862       const int v1 = (flip) ? (start_edge_vertex + (resolution - i - 3)) : (start_edge_vertex + i);
863       const int v2 = side_start_index + side_stride * i;
864       ctx->foreach_context->edge(
865           ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, v1, v2);
866     }
867   }
868 }
869 
subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)870 static void subdiv_foreach_edges_all_patches_special(SubdivForeachTaskContext *ctx,
871                                                      void *tls,
872                                                      const MPoly *coarse_poly)
873 {
874   const Mesh *coarse_mesh = ctx->coarse_mesh;
875   const MEdge *coarse_medge = coarse_mesh->medge;
876   const MLoop *coarse_mloop = coarse_mesh->mloop;
877   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
878   const int poly_index = coarse_poly - coarse_mpoly;
879   const int resolution = ctx->settings->resolution;
880   const int ptex_face_resolution = ptex_face_resolution_get(coarse_poly, resolution);
881   const int ptex_face_inner_resolution = ptex_face_resolution - 2;
882   const int num_inner_vertices_per_ptex = (ptex_face_resolution - 1) * (ptex_face_resolution - 2);
883   const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
884   const int center_vertex_index = ctx->vertices_inner_offset +
885                                   ctx->subdiv_vertex_offset[poly_index];
886   const int start_vertex_index = center_vertex_index + 1;
887   int subdiv_edge_index = ctx->edge_inner_offset + ctx->subdiv_edge_offset[poly_index];
888   /* Traverse inner ptex edges. */
889   for (int corner = 0; corner < coarse_poly->totloop; corner++) {
890     const int start_ptex_face_vertex_index = start_vertex_index +
891                                              corner * num_inner_vertices_per_ptex;
892     /* Similar steps to regular patch case. */
893     subdiv_edge_index = subdiv_foreach_edges_row(ctx,
894                                                  tls,
895                                                  ORIGINDEX_NONE,
896                                                  subdiv_edge_index,
897                                                  start_ptex_face_vertex_index,
898                                                  ptex_face_inner_resolution + 1);
899     for (int row = 0; row < ptex_face_inner_resolution - 1; row++) {
900       const int start_row_vertex_index = start_ptex_face_vertex_index +
901                                          row * (ptex_face_inner_resolution + 1);
902       subdiv_edge_index = subdiv_foreach_edges_column(ctx,
903                                                       tls,
904                                                       ORIGINDEX_NONE,
905                                                       ORIGINDEX_NONE,
906                                                       subdiv_edge_index,
907                                                       start_row_vertex_index,
908                                                       ptex_face_inner_resolution + 1);
909       subdiv_edge_index = subdiv_foreach_edges_row(ctx,
910                                                    tls,
911                                                    ORIGINDEX_NONE,
912                                                    subdiv_edge_index,
913                                                    start_row_vertex_index +
914                                                        ptex_face_inner_resolution + 1,
915                                                    ptex_face_inner_resolution + 1);
916     }
917   }
918   /* Create connections between ptex faces. */
919   for (int corner = 0; corner < coarse_poly->totloop; corner++) {
920     const int next_corner = (corner + 1) % coarse_poly->totloop;
921     int current_patch_vertex_index = start_vertex_index + corner * num_inner_vertices_per_ptex +
922                                      ptex_face_inner_resolution;
923     int next_path_vertex_index = start_vertex_index + next_corner * num_inner_vertices_per_ptex +
924                                  num_inner_vertices_per_ptex - ptex_face_resolution + 1;
925     for (int row = 0; row < ptex_face_inner_resolution; row++, subdiv_edge_index++) {
926       const int v1 = current_patch_vertex_index;
927       const int v2 = next_path_vertex_index;
928       ctx->foreach_context->edge(
929           ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, v1, v2);
930       current_patch_vertex_index += ptex_face_inner_resolution + 1;
931       next_path_vertex_index += 1;
932     }
933   }
934   /* Create edges from center. */
935   if (ptex_face_resolution >= 3) {
936     for (int corner = 0; corner < coarse_poly->totloop; corner++, subdiv_edge_index++) {
937       const int current_patch_end_vertex_index = start_vertex_index +
938                                                  corner * num_inner_vertices_per_ptex +
939                                                  num_inner_vertices_per_ptex - 1;
940       const int v1 = center_vertex_index;
941       const int v2 = current_patch_end_vertex_index;
942       ctx->foreach_context->edge(
943           ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, v1, v2);
944     }
945   }
946   /* Connect inner path of patch to boundary. */
947   const MLoop *prev_coarse_loop = &coarse_mloop[coarse_poly->loopstart + coarse_poly->totloop - 1];
948   for (int corner = 0; corner < coarse_poly->totloop; corner++) {
949     const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
950     {
951       const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
952       const int start_edge_vertex = ctx->vertices_edge_offset +
953                                     coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
954       const bool flip = (coarse_edge->v2 == coarse_loop->v);
955       int side_start_index;
956       if (ptex_face_resolution >= 3) {
957         side_start_index = start_vertex_index + num_inner_vertices_per_ptex * corner;
958       }
959       else {
960         side_start_index = center_vertex_index;
961       }
962       for (int i = 0; i < ptex_face_resolution - 1; i++, subdiv_edge_index++) {
963         const int v1 = (flip) ? (start_edge_vertex + (resolution - i - 3)) :
964                                 (start_edge_vertex + i);
965         const int v2 = side_start_index + i;
966         ctx->foreach_context->edge(
967             ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, v1, v2);
968       }
969     }
970     if (ptex_face_resolution >= 3) {
971       const MEdge *coarse_edge = &coarse_medge[prev_coarse_loop->e];
972       const int start_edge_vertex = ctx->vertices_edge_offset +
973                                     prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
974       const bool flip = (coarse_edge->v2 == coarse_loop->v);
975       int side_start_index = start_vertex_index + num_inner_vertices_per_ptex * corner;
976       for (int i = 0; i < ptex_face_resolution - 2; i++, subdiv_edge_index++) {
977         const int v1 = (flip) ? (start_edge_vertex + (resolution - i - 3)) :
978                                 (start_edge_vertex + i);
979         const int v2 = side_start_index + (ptex_face_inner_resolution + 1) * i;
980         ctx->foreach_context->edge(
981             ctx->foreach_context, tls, ORIGINDEX_NONE, subdiv_edge_index, v1, v2);
982       }
983     }
984     prev_coarse_loop = coarse_loop;
985   }
986 }
987 
subdiv_foreach_edges_all_patches(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)988 static void subdiv_foreach_edges_all_patches(SubdivForeachTaskContext *ctx,
989                                              void *tls,
990                                              const MPoly *coarse_poly)
991 {
992   if (coarse_poly->totloop == 4) {
993     subdiv_foreach_edges_all_patches_regular(ctx, tls, coarse_poly);
994   }
995   else {
996     subdiv_foreach_edges_all_patches_special(ctx, tls, coarse_poly);
997   }
998 }
999 
subdiv_foreach_edges(SubdivForeachTaskContext * ctx,void * tls,int poly_index)1000 static void subdiv_foreach_edges(SubdivForeachTaskContext *ctx, void *tls, int poly_index)
1001 {
1002   const Mesh *coarse_mesh = ctx->coarse_mesh;
1003   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
1004   const MPoly *coarse_poly = &coarse_mpoly[poly_index];
1005   subdiv_foreach_edges_all_patches(ctx, tls, coarse_poly);
1006 }
1007 
subdiv_foreach_boundary_edges(SubdivForeachTaskContext * ctx,void * tls,int coarse_edge_index)1008 static void subdiv_foreach_boundary_edges(SubdivForeachTaskContext *ctx,
1009                                           void *tls,
1010                                           int coarse_edge_index)
1011 {
1012   const Mesh *coarse_mesh = ctx->coarse_mesh;
1013   const MEdge *coarse_medge = coarse_mesh->medge;
1014   const MEdge *coarse_edge = &coarse_medge[coarse_edge_index];
1015   const int resolution = ctx->settings->resolution;
1016   const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
1017   const int num_subdiv_edges_per_coarse_edge = resolution - 1;
1018   int subdiv_edge_index = ctx->edge_boundary_offset +
1019                           coarse_edge_index * num_subdiv_edges_per_coarse_edge;
1020   int last_vertex_index = ctx->vertices_corner_offset + coarse_edge->v1;
1021   for (int i = 0; i < num_subdiv_edges_per_coarse_edge - 1; i++, subdiv_edge_index++) {
1022     const int v1 = last_vertex_index;
1023     const int v2 = ctx->vertices_edge_offset +
1024                    coarse_edge_index * num_subdiv_vertices_per_coarse_edge + i;
1025     ctx->foreach_context->edge(
1026         ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, v1, v2);
1027     last_vertex_index = v2;
1028   }
1029   const int v1 = last_vertex_index;
1030   const int v2 = ctx->vertices_corner_offset + coarse_edge->v2;
1031   ctx->foreach_context->edge(
1032       ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, v1, v2);
1033 }
1034 
1035 /** \} */
1036 
1037 /* -------------------------------------------------------------------- */
1038 /** \name Loops traversal
1039  * \{ */
1040 
rotate_indices(const int rot,int * a,int * b,int * c,int * d)1041 static void rotate_indices(const int rot, int *a, int *b, int *c, int *d)
1042 {
1043   const int values[4] = {*a, *b, *c, *d};
1044   *a = values[(0 - rot + 4) % 4];
1045   *b = values[(1 - rot + 4) % 4];
1046   *c = values[(2 - rot + 4) % 4];
1047   *d = values[(3 - rot + 4) % 4];
1048 }
1049 
subdiv_foreach_loops_of_poly(SubdivForeachTaskContext * ctx,void * tls,int subdiv_loop_start_index,const int ptex_face_index,const int coarse_poly_index,const int coarse_corner_index,const int rotation,int v0,int e0,int v1,int e1,int v2,int e2,int v3,int e3,const float u,const float v,const float du,const float dv)1050 static void subdiv_foreach_loops_of_poly(SubdivForeachTaskContext *ctx,
1051                                          void *tls,
1052                                          int subdiv_loop_start_index,
1053                                          const int ptex_face_index,
1054                                          const int coarse_poly_index,
1055                                          const int coarse_corner_index,
1056                                          const int rotation,
1057                                          /*const*/ int v0,
1058                                          /*const*/ int e0,
1059                                          /*const*/ int v1,
1060                                          /*const*/ int e1,
1061                                          /*const*/ int v2,
1062                                          /*const*/ int e2,
1063                                          /*const*/ int v3,
1064                                          /*const*/ int e3,
1065                                          const float u,
1066                                          const float v,
1067                                          const float du,
1068                                          const float dv)
1069 {
1070   rotate_indices(rotation, &v0, &v1, &v2, &v3);
1071   rotate_indices(rotation, &e0, &e1, &e2, &e3);
1072   ctx->foreach_context->loop(ctx->foreach_context,
1073                              tls,
1074                              ptex_face_index,
1075                              u,
1076                              v,
1077                              ORIGINDEX_NONE,
1078                              coarse_poly_index,
1079                              coarse_corner_index,
1080                              subdiv_loop_start_index + 0,
1081                              v0,
1082                              e0);
1083   ctx->foreach_context->loop(ctx->foreach_context,
1084                              tls,
1085                              ptex_face_index,
1086                              u + du,
1087                              v,
1088                              ORIGINDEX_NONE,
1089                              coarse_poly_index,
1090                              coarse_corner_index,
1091                              subdiv_loop_start_index + 1,
1092                              v1,
1093                              e1);
1094   ctx->foreach_context->loop(ctx->foreach_context,
1095                              tls,
1096                              ptex_face_index,
1097                              u + du,
1098                              v + dv,
1099                              ORIGINDEX_NONE,
1100                              coarse_poly_index,
1101                              coarse_corner_index,
1102                              subdiv_loop_start_index + 2,
1103                              v2,
1104                              e2);
1105   ctx->foreach_context->loop(ctx->foreach_context,
1106                              tls,
1107                              ptex_face_index,
1108                              u,
1109                              v + dv,
1110                              ORIGINDEX_NONE,
1111                              coarse_poly_index,
1112                              coarse_corner_index,
1113                              subdiv_loop_start_index + 3,
1114                              v3,
1115                              e3);
1116 }
1117 
subdiv_foreach_loops_corner_index(const float u,const float v,const float du,const float dv)1118 static int subdiv_foreach_loops_corner_index(const float u,
1119                                              const float v,
1120                                              const float du,
1121                                              const float dv)
1122 {
1123   if (u + du <= 0.5f && v + dv <= 0.5f) {
1124     return 0;
1125   }
1126   if (u >= 0.5f && v + dv <= 0.5f) {
1127     return 1;
1128   }
1129   if (u >= 0.5f && v >= 0.5f) {
1130     return 2;
1131   }
1132   return 3;
1133 }
1134 
subdiv_foreach_loops_regular(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)1135 static void subdiv_foreach_loops_regular(SubdivForeachTaskContext *ctx,
1136                                          void *tls,
1137                                          const MPoly *coarse_poly)
1138 {
1139   const int resolution = ctx->settings->resolution;
1140   /* Base/coarse mesh information. */
1141   const Mesh *coarse_mesh = ctx->coarse_mesh;
1142   const MEdge *coarse_medge = coarse_mesh->medge;
1143   const MLoop *coarse_mloop = coarse_mesh->mloop;
1144   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
1145   const int coarse_poly_index = coarse_poly - coarse_mpoly;
1146   const int ptex_resolution = ptex_face_resolution_get(coarse_poly, resolution);
1147   const int ptex_inner_resolution = ptex_resolution - 2;
1148   const int num_subdiv_edges_per_coarse_edge = resolution - 1;
1149   const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
1150   const float inv_ptex_resolution_1 = 1.0f / (float)(ptex_resolution - 1);
1151   const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
1152   const int start_vertex_index = ctx->vertices_inner_offset +
1153                                  ctx->subdiv_vertex_offset[coarse_poly_index];
1154   const int start_edge_index = ctx->edge_inner_offset + ctx->subdiv_edge_offset[coarse_poly_index];
1155   const int start_poly_index = ctx->subdiv_polygon_offset[coarse_poly_index];
1156   const int start_loop_index = 4 * start_poly_index;
1157   const float du = inv_ptex_resolution_1;
1158   const float dv = inv_ptex_resolution_1;
1159   /* Hi-poly subdivided mesh. */
1160   int subdiv_loop_index = start_loop_index;
1161   /* Loops for inner part of ptex. */
1162   for (int y = 1; y < ptex_resolution - 2; y++) {
1163     const float v = y * inv_ptex_resolution_1;
1164     const int inner_y = y - 1;
1165     for (int x = 1; x < ptex_resolution - 2; x++, subdiv_loop_index += 4) {
1166       const int inner_x = x - 1;
1167       const float u = x * inv_ptex_resolution_1;
1168       /* Vertex indices ordered counter-clockwise. */
1169       const int v0 = start_vertex_index + (inner_y * ptex_inner_resolution + inner_x);
1170       const int v1 = v0 + 1;
1171       const int v2 = v0 + ptex_inner_resolution + 1;
1172       const int v3 = v0 + ptex_inner_resolution;
1173       /* Edge indices ordered counter-clockwise. */
1174       const int e0 = start_edge_index + (inner_y * (2 * ptex_inner_resolution - 1) + inner_x);
1175       const int e1 = e0 + ptex_inner_resolution;
1176       const int e2 = e0 + (2 * ptex_inner_resolution - 1);
1177       const int e3 = e0 + ptex_inner_resolution - 1;
1178 
1179       subdiv_foreach_loops_of_poly(ctx,
1180                                    tls,
1181                                    subdiv_loop_index,
1182                                    ptex_face_index,
1183                                    coarse_poly_index,
1184                                    subdiv_foreach_loops_corner_index(u, v, du, dv),
1185                                    0,
1186                                    v0,
1187                                    e0,
1188                                    v1,
1189                                    e1,
1190                                    v2,
1191                                    e2,
1192                                    v3,
1193                                    e3,
1194                                    u,
1195                                    v,
1196                                    du,
1197                                    dv);
1198     }
1199   }
1200   /* Loops for faces connecting inner ptex part with boundary. */
1201   const MLoop *prev_coarse_loop = &coarse_mloop[coarse_poly->loopstart + coarse_poly->totloop - 1];
1202   for (int corner = 0; corner < coarse_poly->totloop; corner++) {
1203     const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
1204     const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
1205     const MEdge *prev_coarse_edge = &coarse_medge[prev_coarse_loop->e];
1206     const int start_edge_vertex = ctx->vertices_edge_offset +
1207                                   coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
1208     const bool flip = (coarse_edge->v2 == coarse_loop->v);
1209     int side_start_index = start_vertex_index;
1210     int side_stride = 0;
1211     int v0 = ctx->vertices_corner_offset + coarse_loop->v;
1212     int v3, e3;
1213     int e2_offset, e2_stride;
1214     float u, v, delta_u, delta_v;
1215     if (prev_coarse_loop->v == prev_coarse_edge->v1) {
1216       v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge +
1217            num_subdiv_vertices_per_coarse_edge - 1;
1218       e3 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge +
1219            num_subdiv_edges_per_coarse_edge - 1;
1220     }
1221     else {
1222       v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
1223       e3 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge;
1224     }
1225     /* Calculate starting vertex of corresponding inner part of ptex. */
1226     if (corner == 0) {
1227       side_stride = 1;
1228       e2_offset = 0;
1229       e2_stride = 1;
1230       u = 0.0f;
1231       v = 0.0f;
1232       delta_u = du;
1233       delta_v = 0.0f;
1234     }
1235     else if (corner == 1) {
1236       side_start_index += resolution - 3;
1237       side_stride = resolution - 2;
1238       e2_offset = 2 * num_subdiv_edges_per_coarse_edge - 4;
1239       e2_stride = 2 * num_subdiv_edges_per_coarse_edge - 3;
1240       u = 1.0f - du;
1241       v = 0;
1242       delta_u = 0.0f;
1243       delta_v = dv;
1244     }
1245     else if (corner == 2) {
1246       side_start_index += num_subdiv_vertices_per_coarse_edge *
1247                               num_subdiv_vertices_per_coarse_edge -
1248                           1;
1249       side_stride = -1;
1250       e2_offset = num_edges_per_ptex_face_get(resolution - 2) - 1;
1251       e2_stride = -1;
1252       u = 1.0f - du;
1253       v = 1.0f - dv;
1254       delta_u = -du;
1255       delta_v = 0.0f;
1256     }
1257     else if (corner == 3) {
1258       side_start_index += num_subdiv_vertices_per_coarse_edge *
1259                           (num_subdiv_vertices_per_coarse_edge - 1);
1260       side_stride = -(resolution - 2);
1261       e2_offset = num_edges_per_ptex_face_get(resolution - 2) -
1262                   (2 * num_subdiv_edges_per_coarse_edge - 3);
1263       e2_stride = -(2 * num_subdiv_edges_per_coarse_edge - 3);
1264       u = 0.0f;
1265       v = 1.0f - dv;
1266       delta_u = 0.0f;
1267       delta_v = -dv;
1268     }
1269     for (int i = 0; i < resolution - 2; i++, subdiv_loop_index += 4) {
1270       int v1;
1271       if (flip) {
1272         v1 = start_edge_vertex + (resolution - i - 3);
1273       }
1274       else {
1275         v1 = start_edge_vertex + i;
1276       }
1277       const int v2 = side_start_index + side_stride * i;
1278       int e0;
1279       if (flip) {
1280         e0 = ctx->edge_boundary_offset + coarse_loop->e * num_subdiv_edges_per_coarse_edge +
1281              num_subdiv_edges_per_coarse_edge - i - 1;
1282       }
1283       else {
1284         e0 = ctx->edge_boundary_offset + coarse_loop->e * num_subdiv_edges_per_coarse_edge + i;
1285       }
1286       int e1 = start_edge_index + num_edges_per_ptex_face_get(resolution - 2) +
1287                corner * num_subdiv_vertices_per_coarse_edge + i;
1288       int e2;
1289       if (i == 0) {
1290         e2 = start_edge_index + num_edges_per_ptex_face_get(resolution - 2) +
1291              ((corner - 1 + coarse_poly->totloop) % coarse_poly->totloop) *
1292                  num_subdiv_vertices_per_coarse_edge +
1293              num_subdiv_vertices_per_coarse_edge - 1;
1294       }
1295       else {
1296         e2 = start_edge_index + e2_offset + e2_stride * (i - 1);
1297       }
1298 
1299       const float loop_u = u + delta_u * i;
1300       const float loop_v = v + delta_v * i;
1301 
1302       subdiv_foreach_loops_of_poly(ctx,
1303                                    tls,
1304                                    subdiv_loop_index,
1305                                    ptex_face_index,
1306                                    coarse_poly_index,
1307                                    subdiv_foreach_loops_corner_index(loop_u, loop_v, du, dv),
1308                                    corner,
1309                                    v0,
1310                                    e0,
1311                                    v1,
1312                                    e1,
1313                                    v2,
1314                                    e2,
1315                                    v3,
1316                                    e3,
1317                                    loop_u,
1318                                    loop_v,
1319                                    du,
1320                                    dv);
1321       v0 = v1;
1322       v3 = v2;
1323       e3 = e1;
1324     }
1325     prev_coarse_loop = coarse_loop;
1326   }
1327 }
1328 
subdiv_foreach_loops_special(SubdivForeachTaskContext * ctx,void * tls,const MPoly * coarse_poly)1329 static void subdiv_foreach_loops_special(SubdivForeachTaskContext *ctx,
1330                                          void *tls,
1331                                          const MPoly *coarse_poly)
1332 {
1333   const int resolution = ctx->settings->resolution;
1334   /* Base/coarse mesh information. */
1335   const Mesh *coarse_mesh = ctx->coarse_mesh;
1336   const MEdge *coarse_medge = coarse_mesh->medge;
1337   const MLoop *coarse_mloop = coarse_mesh->mloop;
1338   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
1339   const int coarse_poly_index = coarse_poly - coarse_mpoly;
1340   const int ptex_face_resolution = ptex_face_resolution_get(coarse_poly, resolution);
1341   const int ptex_face_inner_resolution = ptex_face_resolution - 2;
1342   const float inv_ptex_resolution_1 = 1.0f / (float)(ptex_face_resolution - 1);
1343   const int num_inner_vertices_per_ptex = (ptex_face_resolution - 1) * (ptex_face_resolution - 2);
1344   const int num_inner_edges_per_ptex_face = num_inner_edges_per_ptex_face_get(
1345       ptex_face_inner_resolution + 1);
1346   const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
1347   const int num_subdiv_edges_per_coarse_edge = resolution - 1;
1348   const int ptex_face_index = ctx->face_ptex_offset[coarse_poly_index];
1349   const int center_vertex_index = ctx->vertices_inner_offset +
1350                                   ctx->subdiv_vertex_offset[coarse_poly_index];
1351   const int start_vertex_index = center_vertex_index + 1;
1352   const int start_inner_vertex_index = center_vertex_index + 1;
1353   const int start_edge_index = ctx->edge_inner_offset + ctx->subdiv_edge_offset[coarse_poly_index];
1354   const int start_poly_index = ctx->subdiv_polygon_offset[coarse_poly_index];
1355   const int start_loop_index = 4 * start_poly_index;
1356   const float du = inv_ptex_resolution_1;
1357   const float dv = inv_ptex_resolution_1;
1358   /* Hi-poly subdivided mesh. */
1359   int subdiv_loop_index = start_loop_index;
1360   for (int corner = 0; corner < coarse_poly->totloop; corner++) {
1361     const int corner_vertex_index = start_vertex_index + corner * num_inner_vertices_per_ptex;
1362     const int corner_edge_index = start_edge_index + corner * num_inner_edges_per_ptex_face;
1363     for (int y = 1; y < ptex_face_inner_resolution; y++) {
1364       const float v = y * inv_ptex_resolution_1;
1365       const int inner_y = y - 1;
1366       for (int x = 1; x < ptex_face_inner_resolution + 1; x++, subdiv_loop_index += 4) {
1367         const int inner_x = x - 1;
1368         const float u = x * inv_ptex_resolution_1;
1369         /* Vertex indices ordered counter-clockwise. */
1370         const int v0 = corner_vertex_index +
1371                        (inner_y * (ptex_face_inner_resolution + 1) + inner_x);
1372         const int v1 = v0 + 1;
1373         const int v2 = v0 + ptex_face_inner_resolution + 2;
1374         const int v3 = v0 + ptex_face_inner_resolution + 1;
1375         /* Edge indices ordered counter-clockwise. */
1376         const int e0 = corner_edge_index +
1377                        (inner_y * (2 * ptex_face_inner_resolution + 1) + inner_x);
1378         const int e1 = e0 + ptex_face_inner_resolution + 1;
1379         const int e2 = e0 + (2 * ptex_face_inner_resolution + 1);
1380         const int e3 = e0 + ptex_face_inner_resolution;
1381         subdiv_foreach_loops_of_poly(ctx,
1382                                      tls,
1383                                      subdiv_loop_index,
1384                                      ptex_face_index + corner,
1385                                      coarse_poly_index,
1386                                      corner,
1387                                      0,
1388                                      v0,
1389                                      e0,
1390                                      v1,
1391                                      e1,
1392                                      v2,
1393                                      e2,
1394                                      v3,
1395                                      e3,
1396                                      u,
1397                                      v,
1398                                      du,
1399                                      dv);
1400       }
1401     }
1402   }
1403   /* Create connections between ptex faces. */
1404   for (int corner = 0; corner < coarse_poly->totloop; corner++) {
1405     const int next_corner = (corner + 1) % coarse_poly->totloop;
1406     const int corner_edge_index = start_edge_index + corner * num_inner_edges_per_ptex_face;
1407     const int next_corner_edge_index = start_edge_index +
1408                                        next_corner * num_inner_edges_per_ptex_face;
1409     int current_patch_vertex_index = start_inner_vertex_index +
1410                                      corner * num_inner_vertices_per_ptex +
1411                                      ptex_face_inner_resolution;
1412     int next_path_vertex_index = start_inner_vertex_index +
1413                                  next_corner * num_inner_vertices_per_ptex +
1414                                  num_inner_vertices_per_ptex - ptex_face_resolution + 1;
1415     int v0 = current_patch_vertex_index;
1416     int v1 = next_path_vertex_index;
1417     current_patch_vertex_index += ptex_face_inner_resolution + 1;
1418     next_path_vertex_index += 1;
1419     int e0 = start_edge_index + coarse_poly->totloop * num_inner_edges_per_ptex_face +
1420              corner * (ptex_face_resolution - 2);
1421     int e1 = next_corner_edge_index + num_inner_edges_per_ptex_face - ptex_face_resolution + 2;
1422     int e3 = corner_edge_index + 2 * ptex_face_resolution - 4;
1423     for (int row = 1; row < ptex_face_inner_resolution; row++, subdiv_loop_index += 4) {
1424       const int v2 = next_path_vertex_index;
1425       const int v3 = current_patch_vertex_index;
1426       const int e2 = e0 + 1;
1427       const float u = row * du;
1428       const float v = 1.0f - dv;
1429       subdiv_foreach_loops_of_poly(ctx,
1430                                    tls,
1431                                    subdiv_loop_index,
1432                                    ptex_face_index + next_corner,
1433                                    coarse_poly_index,
1434                                    next_corner,
1435                                    3,
1436                                    v0,
1437                                    e0,
1438                                    v1,
1439                                    e1,
1440                                    v2,
1441                                    e2,
1442                                    v3,
1443                                    e3,
1444                                    u,
1445                                    v,
1446                                    du,
1447                                    dv);
1448       current_patch_vertex_index += ptex_face_inner_resolution + 1;
1449       next_path_vertex_index += 1;
1450       v0 = v3;
1451       v1 = v2;
1452       e0 = e2;
1453       e1 += 1;
1454       e3 += 2 * ptex_face_resolution - 3;
1455     }
1456   }
1457   /* Create loops from center. */
1458   if (ptex_face_resolution >= 3) {
1459     const int start_center_edge_index = start_edge_index + (num_inner_edges_per_ptex_face +
1460                                                             ptex_face_inner_resolution) *
1461                                                                coarse_poly->totloop;
1462     const int start_boundary_edge = start_edge_index +
1463                                     coarse_poly->totloop * num_inner_edges_per_ptex_face +
1464                                     ptex_face_inner_resolution - 1;
1465     for (int corner = 0, prev_corner = coarse_poly->totloop - 1; corner < coarse_poly->totloop;
1466          prev_corner = corner, corner++, subdiv_loop_index += 4) {
1467       const int corner_edge_index = start_edge_index + corner * num_inner_edges_per_ptex_face;
1468       const int current_patch_end_vertex_index = start_vertex_index +
1469                                                  corner * num_inner_vertices_per_ptex +
1470                                                  num_inner_vertices_per_ptex - 1;
1471       const int prev_current_patch_end_vertex_index = start_vertex_index +
1472                                                       prev_corner * num_inner_vertices_per_ptex +
1473                                                       num_inner_vertices_per_ptex - 1;
1474       const int v0 = center_vertex_index;
1475       const int v1 = prev_current_patch_end_vertex_index;
1476       const int v2 = current_patch_end_vertex_index - 1;
1477       const int v3 = current_patch_end_vertex_index;
1478       const int e0 = start_center_edge_index + prev_corner;
1479       const int e1 = start_boundary_edge + prev_corner * (ptex_face_inner_resolution);
1480       const int e2 = corner_edge_index + num_inner_edges_per_ptex_face - 1;
1481       const int e3 = start_center_edge_index + corner;
1482       const float u = 1.0f - du;
1483       const float v = 1.0f - dv;
1484       subdiv_foreach_loops_of_poly(ctx,
1485                                    tls,
1486                                    subdiv_loop_index,
1487                                    ptex_face_index + corner,
1488                                    coarse_poly_index,
1489                                    corner,
1490                                    2,
1491                                    v0,
1492                                    e0,
1493                                    v1,
1494                                    e1,
1495                                    v2,
1496                                    e2,
1497                                    v3,
1498                                    e3,
1499                                    u,
1500                                    v,
1501                                    du,
1502                                    dv);
1503     }
1504   }
1505   /* Loops for faces connecting inner ptex part with boundary. */
1506   const MLoop *prev_coarse_loop = &coarse_mloop[coarse_poly->loopstart + coarse_poly->totloop - 1];
1507   for (int prev_corner = coarse_poly->totloop - 1, corner = 0; corner < coarse_poly->totloop;
1508        prev_corner = corner, corner++) {
1509     const MLoop *coarse_loop = &coarse_mloop[coarse_poly->loopstart + corner];
1510     const MEdge *coarse_edge = &coarse_medge[coarse_loop->e];
1511     const MEdge *prev_coarse_edge = &coarse_medge[prev_coarse_loop->e];
1512     const bool flip = (coarse_edge->v2 == coarse_loop->v);
1513     const int start_edge_vertex = ctx->vertices_edge_offset +
1514                                   coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
1515     const int corner_vertex_index = start_vertex_index + corner * num_inner_vertices_per_ptex;
1516     const int corner_edge_index = start_edge_index + corner * num_inner_edges_per_ptex_face;
1517     /* Create loops for polygons along U axis. */
1518     int v0 = ctx->vertices_corner_offset + coarse_loop->v;
1519     int v3, e3;
1520     if (prev_coarse_loop->v == prev_coarse_edge->v1) {
1521       v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge +
1522            num_subdiv_vertices_per_coarse_edge - 1;
1523       e3 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge +
1524            num_subdiv_edges_per_coarse_edge - 1;
1525     }
1526     else {
1527       v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
1528       e3 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge;
1529     }
1530     for (int i = 0; i <= ptex_face_inner_resolution; i++, subdiv_loop_index += 4) {
1531       int v1;
1532       if (flip) {
1533         v1 = start_edge_vertex + (resolution - i - 3);
1534       }
1535       else {
1536         v1 = start_edge_vertex + i;
1537       }
1538       int v2;
1539       if (ptex_face_inner_resolution >= 1) {
1540         v2 = corner_vertex_index + i;
1541       }
1542       else {
1543         v2 = center_vertex_index;
1544       }
1545       int e0;
1546       if (flip) {
1547         e0 = ctx->edge_boundary_offset + coarse_loop->e * num_subdiv_edges_per_coarse_edge +
1548              num_subdiv_edges_per_coarse_edge - i - 1;
1549       }
1550       else {
1551         e0 = ctx->edge_boundary_offset + coarse_loop->e * num_subdiv_edges_per_coarse_edge + i;
1552       }
1553       int e1 = start_edge_index + corner * (2 * ptex_face_inner_resolution + 1);
1554       if (ptex_face_resolution >= 3) {
1555         e1 += coarse_poly->totloop *
1556                   (num_inner_edges_per_ptex_face + ptex_face_inner_resolution + 1) +
1557               i;
1558       }
1559       int e2 = 0;
1560       if (i == 0 && ptex_face_resolution >= 3) {
1561         e2 = start_edge_index +
1562              coarse_poly->totloop *
1563                  (num_inner_edges_per_ptex_face + ptex_face_inner_resolution + 1) +
1564              corner * (2 * ptex_face_inner_resolution + 1) + ptex_face_inner_resolution + 1;
1565       }
1566       else if (i == 0 && ptex_face_resolution < 3) {
1567         e2 = start_edge_index + prev_corner * (2 * ptex_face_inner_resolution + 1);
1568       }
1569       else {
1570         e2 = corner_edge_index + i - 1;
1571       }
1572       const float u = du * i;
1573       const float v = 0.0f;
1574       subdiv_foreach_loops_of_poly(ctx,
1575                                    tls,
1576                                    subdiv_loop_index,
1577                                    ptex_face_index + corner,
1578                                    coarse_poly_index,
1579                                    corner,
1580                                    0,
1581                                    v0,
1582                                    e0,
1583                                    v1,
1584                                    e1,
1585                                    v2,
1586                                    e2,
1587                                    v3,
1588                                    e3,
1589                                    u,
1590                                    v,
1591                                    du,
1592                                    dv);
1593       v0 = v1;
1594       v3 = v2;
1595       e3 = e1;
1596     }
1597     /* Create loops for polygons along V axis. */
1598     const bool flip_prev = (prev_coarse_edge->v2 == coarse_loop->v);
1599     v0 = corner_vertex_index;
1600     if (prev_coarse_loop->v == prev_coarse_edge->v1) {
1601       v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge +
1602            num_subdiv_vertices_per_coarse_edge - 1;
1603     }
1604     else {
1605       v3 = ctx->vertices_edge_offset + prev_coarse_loop->e * num_subdiv_vertices_per_coarse_edge;
1606     }
1607     e3 = start_edge_index +
1608          coarse_poly->totloop * (num_inner_edges_per_ptex_face + ptex_face_inner_resolution + 1) +
1609          corner * (2 * ptex_face_inner_resolution + 1) + ptex_face_inner_resolution + 1;
1610     for (int i = 0; i <= ptex_face_inner_resolution - 1; i++, subdiv_loop_index += 4) {
1611       int v1;
1612       int e0, e1;
1613       if (i == ptex_face_inner_resolution - 1) {
1614         v1 = start_vertex_index + prev_corner * num_inner_vertices_per_ptex +
1615              ptex_face_inner_resolution;
1616         e1 = start_edge_index +
1617              coarse_poly->totloop *
1618                  (num_inner_edges_per_ptex_face + ptex_face_inner_resolution + 1) +
1619              prev_corner * (2 * ptex_face_inner_resolution + 1) + ptex_face_inner_resolution;
1620         e0 = start_edge_index + coarse_poly->totloop * num_inner_edges_per_ptex_face +
1621              prev_corner * ptex_face_inner_resolution;
1622       }
1623       else {
1624         v1 = v0 + ptex_face_inner_resolution + 1;
1625         e0 = corner_edge_index + ptex_face_inner_resolution +
1626              i * (2 * ptex_face_inner_resolution + 1);
1627         e1 = e3 + 1;
1628       }
1629       int v2 = flip_prev ? v3 - 1 : v3 + 1;
1630       int e2;
1631       if (flip_prev) {
1632         e2 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge +
1633              num_subdiv_edges_per_coarse_edge - 2 - i;
1634       }
1635       else {
1636         e2 = ctx->edge_boundary_offset + prev_coarse_loop->e * num_subdiv_edges_per_coarse_edge +
1637              1 + i;
1638       }
1639       const float u = 0.0f;
1640       const float v = du * (i + 1);
1641       subdiv_foreach_loops_of_poly(ctx,
1642                                    tls,
1643                                    subdiv_loop_index,
1644                                    ptex_face_index + corner,
1645                                    coarse_poly_index,
1646                                    corner,
1647                                    1,
1648                                    v0,
1649                                    e0,
1650                                    v1,
1651                                    e1,
1652                                    v2,
1653                                    e2,
1654                                    v3,
1655                                    e3,
1656                                    u,
1657                                    v,
1658                                    du,
1659                                    dv);
1660       v0 = v1;
1661       v3 = v2;
1662       e3 = e1;
1663     }
1664     prev_coarse_loop = coarse_loop;
1665   }
1666 }
1667 
subdiv_foreach_loops(SubdivForeachTaskContext * ctx,void * tls,int poly_index)1668 static void subdiv_foreach_loops(SubdivForeachTaskContext *ctx, void *tls, int poly_index)
1669 {
1670   const Mesh *coarse_mesh = ctx->coarse_mesh;
1671   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
1672   const MPoly *coarse_poly = &coarse_mpoly[poly_index];
1673   if (coarse_poly->totloop == 4) {
1674     subdiv_foreach_loops_regular(ctx, tls, coarse_poly);
1675   }
1676   else {
1677     subdiv_foreach_loops_special(ctx, tls, coarse_poly);
1678   }
1679 }
1680 
1681 /** \} */
1682 
1683 /* -------------------------------------------------------------------- */
1684 /** \name Polygons traverse process
1685  * \{ */
1686 
subdiv_foreach_polys(SubdivForeachTaskContext * ctx,void * tls,int poly_index)1687 static void subdiv_foreach_polys(SubdivForeachTaskContext *ctx, void *tls, int poly_index)
1688 {
1689   const int resolution = ctx->settings->resolution;
1690   const int start_poly_index = ctx->subdiv_polygon_offset[poly_index];
1691   /* Base/coarse mesh information. */
1692   const Mesh *coarse_mesh = ctx->coarse_mesh;
1693   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
1694   const MPoly *coarse_poly = &coarse_mpoly[poly_index];
1695   const int num_ptex_faces_per_poly = num_ptex_faces_per_poly_get(coarse_poly);
1696   const int ptex_resolution = ptex_face_resolution_get(coarse_poly, resolution);
1697   const int num_polys_per_ptex = num_polys_per_ptex_get(ptex_resolution);
1698   const int num_loops_per_ptex = 4 * num_polys_per_ptex;
1699   const int start_loop_index = 4 * start_poly_index;
1700   /* Hi-poly subdivided mesh. */
1701   int subdiv_polyon_index = start_poly_index;
1702   for (int ptex_of_poly_index = 0; ptex_of_poly_index < num_ptex_faces_per_poly;
1703        ptex_of_poly_index++) {
1704     for (int subdiv_poly_index = 0; subdiv_poly_index < num_polys_per_ptex;
1705          subdiv_poly_index++, subdiv_polyon_index++) {
1706       const int loopstart = start_loop_index + (ptex_of_poly_index * num_loops_per_ptex) +
1707                             (subdiv_poly_index * 4);
1708       ctx->foreach_context->poly(
1709           ctx->foreach_context, tls, poly_index, subdiv_polyon_index, loopstart, 4);
1710     }
1711   }
1712 }
1713 
1714 /** \} */
1715 
1716 /* -------------------------------------------------------------------- */
1717 /** \name Loose elements traverse process
1718  * \{ */
1719 
subdiv_foreach_loose_vertices_task(void * __restrict userdata,const int coarse_vertex_index,const TaskParallelTLS * __restrict tls)1720 static void subdiv_foreach_loose_vertices_task(void *__restrict userdata,
1721                                                const int coarse_vertex_index,
1722                                                const TaskParallelTLS *__restrict tls)
1723 {
1724   SubdivForeachTaskContext *ctx = userdata;
1725   if (BLI_BITMAP_TEST_BOOL(ctx->coarse_vertices_used_map, coarse_vertex_index)) {
1726     /* Vertex is not loose, was handled when handling polygons. */
1727     return;
1728   }
1729   const int subdiv_vertex_index = ctx->vertices_corner_offset + coarse_vertex_index;
1730   ctx->foreach_context->vertex_loose(
1731       ctx->foreach_context, tls->userdata_chunk, coarse_vertex_index, subdiv_vertex_index);
1732 }
1733 
subdiv_foreach_vertices_of_loose_edges_task(void * __restrict userdata,const int coarse_edge_index,const TaskParallelTLS * __restrict tls)1734 static void subdiv_foreach_vertices_of_loose_edges_task(void *__restrict userdata,
1735                                                         const int coarse_edge_index,
1736                                                         const TaskParallelTLS *__restrict tls)
1737 {
1738   SubdivForeachTaskContext *ctx = userdata;
1739   if (BLI_BITMAP_TEST_BOOL(ctx->coarse_edges_used_map, coarse_edge_index)) {
1740     /* Vertex is not loose, was handled when handling polygons. */
1741     return;
1742   }
1743   const int resolution = ctx->settings->resolution;
1744   const int resolution_1 = resolution - 1;
1745   const float inv_resolution_1 = 1.0f / (float)resolution_1;
1746   const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
1747   const Mesh *coarse_mesh = ctx->coarse_mesh;
1748   const MEdge *coarse_edge = &coarse_mesh->medge[coarse_edge_index];
1749   /* Subdivision vertices which corresponds to edge's v1 and v2. */
1750   const int subdiv_v1_index = ctx->vertices_corner_offset + coarse_edge->v1;
1751   const int subdiv_v2_index = ctx->vertices_corner_offset + coarse_edge->v2;
1752   /* First subdivided inner vertex of the edge.  */
1753   const int subdiv_start_vertex = ctx->vertices_edge_offset +
1754                                   coarse_edge_index * num_subdiv_vertices_per_coarse_edge;
1755   /* Perform interpolation. */
1756   for (int i = 0; i < resolution; i++) {
1757     const float u = i * inv_resolution_1;
1758     int subdiv_vertex_index;
1759     if (i == 0) {
1760       subdiv_vertex_index = subdiv_v1_index;
1761     }
1762     else if (i == resolution - 1) {
1763       subdiv_vertex_index = subdiv_v2_index;
1764     }
1765     else {
1766       subdiv_vertex_index = subdiv_start_vertex + (i - 1);
1767     }
1768     ctx->foreach_context->vertex_of_loose_edge(
1769         ctx->foreach_context, tls->userdata_chunk, coarse_edge_index, u, subdiv_vertex_index);
1770   }
1771 }
1772 
1773 /** \} */
1774 
1775 /* -------------------------------------------------------------------- */
1776 /** \name Subdivision process entry points
1777  * \{ */
1778 
subdiv_foreach_single_geometry_vertices(SubdivForeachTaskContext * ctx,void * tls)1779 static void subdiv_foreach_single_geometry_vertices(SubdivForeachTaskContext *ctx, void *tls)
1780 {
1781   if (ctx->foreach_context->vertex_corner == NULL) {
1782     return;
1783   }
1784   const Mesh *coarse_mesh = ctx->coarse_mesh;
1785   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
1786   for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
1787     const MPoly *coarse_poly = &coarse_mpoly[poly_index];
1788     subdiv_foreach_corner_vertices(ctx, tls, coarse_poly);
1789     subdiv_foreach_edge_vertices(ctx, tls, coarse_poly);
1790   }
1791 }
1792 
subdiv_foreach_mark_non_loose_geometry(SubdivForeachTaskContext * ctx)1793 static void subdiv_foreach_mark_non_loose_geometry(SubdivForeachTaskContext *ctx)
1794 {
1795   const Mesh *coarse_mesh = ctx->coarse_mesh;
1796   const MPoly *coarse_mpoly = coarse_mesh->mpoly;
1797   const MLoop *coarse_mloop = coarse_mesh->mloop;
1798   for (int poly_index = 0; poly_index < coarse_mesh->totpoly; poly_index++) {
1799     const MPoly *coarse_poly = &coarse_mpoly[poly_index];
1800     for (int corner = 0; corner < coarse_poly->totloop; corner++) {
1801       const MLoop *loop = &coarse_mloop[coarse_poly->loopstart + corner];
1802       BLI_BITMAP_ENABLE(ctx->coarse_edges_used_map, loop->e);
1803       BLI_BITMAP_ENABLE(ctx->coarse_vertices_used_map, loop->v);
1804     }
1805   }
1806 }
1807 
subdiv_foreach_single_thread_tasks(SubdivForeachTaskContext * ctx)1808 static void subdiv_foreach_single_thread_tasks(SubdivForeachTaskContext *ctx)
1809 {
1810   /* NOTE: In theory, we can try to skip allocation of TLS here, but in
1811    * practice if the callbacks used here are not specified then TLS will not
1812    * be requested anyway. */
1813   void *tls = subdiv_foreach_tls_alloc(ctx);
1814   /* Passes to average displacement on the corner vertices
1815    * and boundary edges. */
1816   subdiv_foreach_every_corner_vertices(ctx, tls);
1817   subdiv_foreach_every_edge_vertices(ctx, tls);
1818   /* Run callbacks which are supposed to be run once per shared geometry. */
1819   subdiv_foreach_single_geometry_vertices(ctx, tls);
1820   subdiv_foreach_tls_free(ctx, tls);
1821 
1822   const SubdivForeachContext *foreach_context = ctx->foreach_context;
1823   const bool is_loose_geometry_tagged = (foreach_context->vertex_every_edge != NULL &&
1824                                          foreach_context->vertex_every_corner != NULL);
1825   const bool is_loose_geometry_tags_needed = (foreach_context->vertex_loose != NULL ||
1826                                               foreach_context->vertex_of_loose_edge != NULL);
1827   if (is_loose_geometry_tagged && is_loose_geometry_tags_needed) {
1828     subdiv_foreach_mark_non_loose_geometry(ctx);
1829   }
1830 }
1831 
subdiv_foreach_task(void * __restrict userdata,const int poly_index,const TaskParallelTLS * __restrict tls)1832 static void subdiv_foreach_task(void *__restrict userdata,
1833                                 const int poly_index,
1834                                 const TaskParallelTLS *__restrict tls)
1835 {
1836   SubdivForeachTaskContext *ctx = userdata;
1837   /* Traverse hi-poly vertex coordinates and normals. */
1838   subdiv_foreach_vertices(ctx, tls->userdata_chunk, poly_index);
1839   /* Traverse mesh geometry for the given base poly index. */
1840   if (ctx->foreach_context->edge != NULL) {
1841     subdiv_foreach_edges(ctx, tls->userdata_chunk, poly_index);
1842   }
1843   if (ctx->foreach_context->loop != NULL) {
1844     subdiv_foreach_loops(ctx, tls->userdata_chunk, poly_index);
1845   }
1846   if (ctx->foreach_context->poly != NULL) {
1847     subdiv_foreach_polys(ctx, tls->userdata_chunk, poly_index);
1848   }
1849 }
1850 
subdiv_foreach_boundary_edges_task(void * __restrict userdata,const int edge_index,const TaskParallelTLS * __restrict tls)1851 static void subdiv_foreach_boundary_edges_task(void *__restrict userdata,
1852                                                const int edge_index,
1853                                                const TaskParallelTLS *__restrict tls)
1854 {
1855   SubdivForeachTaskContext *ctx = userdata;
1856   subdiv_foreach_boundary_edges(ctx, tls->userdata_chunk, edge_index);
1857 }
1858 
subdiv_foreach_free(const void * __restrict userdata,void * __restrict userdata_chunk)1859 static void subdiv_foreach_free(const void *__restrict userdata, void *__restrict userdata_chunk)
1860 {
1861   const SubdivForeachTaskContext *ctx = userdata;
1862   ctx->foreach_context->user_data_tls_free(userdata_chunk);
1863 }
1864 
BKE_subdiv_foreach_subdiv_geometry(Subdiv * subdiv,const SubdivForeachContext * context,const SubdivToMeshSettings * mesh_settings,const Mesh * coarse_mesh)1865 bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv,
1866                                         const SubdivForeachContext *context,
1867                                         const SubdivToMeshSettings *mesh_settings,
1868                                         const Mesh *coarse_mesh)
1869 {
1870   SubdivForeachTaskContext ctx = {0};
1871   ctx.coarse_mesh = coarse_mesh;
1872   ctx.settings = mesh_settings;
1873   ctx.foreach_context = context;
1874   subdiv_foreach_ctx_init(subdiv, &ctx);
1875   if (context->topology_info != NULL) {
1876     if (!context->topology_info(context,
1877                                 ctx.num_subdiv_vertices,
1878                                 ctx.num_subdiv_edges,
1879                                 ctx.num_subdiv_loops,
1880                                 ctx.num_subdiv_polygons)) {
1881       subdiv_foreach_ctx_free(&ctx);
1882       return false;
1883     }
1884   }
1885   /* Run all the code which is not supposed to be run from threads. */
1886   subdiv_foreach_single_thread_tasks(&ctx);
1887   /* Threaded traversal of the rest of topology. */
1888   TaskParallelSettings parallel_range_settings;
1889   BLI_parallel_range_settings_defaults(&parallel_range_settings);
1890   parallel_range_settings.userdata_chunk = context->user_data_tls;
1891   parallel_range_settings.userdata_chunk_size = context->user_data_tls_size;
1892   parallel_range_settings.min_iter_per_thread = 1;
1893   if (context->user_data_tls_free != NULL) {
1894     parallel_range_settings.func_free = subdiv_foreach_free;
1895   }
1896 
1897   /* TODO(sergey): Possible optimization is to have a single pool and push all
1898    * the tasks into it.
1899    * NOTE: Watch out for callbacks which needs to run for loose geometry as they
1900    * currently are relying on the fact that face/grid callbacks will tag non-
1901    * loose geometry. */
1902 
1903   BLI_task_parallel_range(
1904       0, coarse_mesh->totpoly, &ctx, subdiv_foreach_task, &parallel_range_settings);
1905   if (context->vertex_loose != NULL) {
1906     BLI_task_parallel_range(0,
1907                             coarse_mesh->totvert,
1908                             &ctx,
1909                             subdiv_foreach_loose_vertices_task,
1910                             &parallel_range_settings);
1911   }
1912   if (context->vertex_of_loose_edge != NULL) {
1913     BLI_task_parallel_range(0,
1914                             coarse_mesh->totedge,
1915                             &ctx,
1916                             subdiv_foreach_vertices_of_loose_edges_task,
1917                             &parallel_range_settings);
1918   }
1919   if (context->edge != NULL) {
1920     BLI_task_parallel_range(0,
1921                             coarse_mesh->totedge,
1922                             &ctx,
1923                             subdiv_foreach_boundary_edges_task,
1924                             &parallel_range_settings);
1925   }
1926   subdiv_foreach_ctx_free(&ctx);
1927   return true;
1928 }
1929 
1930 /** \} */
1931