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