Blender  V2.93
subdiv_foreach.c
Go to the documentation of this file.
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 
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 /* -------------------------------------------------------------------- */
47 /* Number of ptex faces for a given polygon. */
49 {
50  return (poly->totloop == 4) ? 1 : poly->totloop;
51 }
52 
53 BLI_INLINE int num_edges_per_ptex_face_get(const int resolution)
54 {
55  return 2 * (resolution - 1) * resolution;
56 }
57 
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. */
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. */
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 
80 /* -------------------------------------------------------------------- */
84 typedef struct SubdivForeachTaskContext {
85  const Mesh *coarse_mesh;
87  /* Callbacks. */
89  /* Counters of geometry in subdivided mesh, initialized as a part of
90  * offsets calculation.
91  */
96  /* Offsets of various geometry in the subdivision mesh arrays. */
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  */
109  /* Indexed by base face index, element indicates total number of ptex faces
110  * created for preceding base faces.
111  */
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  */
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  */
126 
129 /* -------------------------------------------------------------------- */
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 
145 {
146  if (tls == NULL) {
147  return;
148  }
149  if (ctx->foreach_context != NULL) {
151  }
152  MEM_freeN(tls);
153 }
154 
157 /* -------------------------------------------------------------------- */
161 /* NOTE: Expects edge map to be zeroed. */
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) {
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 
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;
239  coarse_mesh->totedge * num_subdiv_vertices_per_coarse_edge;
240  ctx->edge_boundary_offset = 0;
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 
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");
280  coarse_mesh->totpoly, sizeof(*ctx->subdiv_vertex_offset), "vertex_offset");
282  coarse_mesh->totpoly, sizeof(*ctx->subdiv_edge_offset), "subdiv_edge_offset");
284  coarse_mesh->totpoly, sizeof(*ctx->subdiv_polygon_offset), "subdiv_edge_offset");
285  /* Initialize all offsets. */
287  /* Calculate number of geometry in the result subdivision mesh. */
289  /* Re-set maps which were used at this step. */
290  BLI_bitmap_set_all(ctx->coarse_edges_used_map, false, coarse_mesh->totedge);
292 }
293 
295 {
301 }
302 
305 /* -------------------------------------------------------------------- */
309 /* Traversal of corner vertices. They are coming from coarse vertices. */
310 
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 &&
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 
346  void *tls,
347  const MPoly *coarse_poly)
348 {
350  ctx, tls, coarse_poly, ctx->foreach_context->vertex_corner, true);
351 }
352 
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 &&
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 
385  void *tls,
386  const MPoly *coarse_poly)
387 {
389  ctx, tls, coarse_poly, ctx->foreach_context->vertex_corner, true);
390 }
391 
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 
405  void *tls,
406  const MPoly *coarse_poly)
407 {
409  ctx, tls, coarse_poly, ctx->foreach_context->vertex_every_corner, false);
410 }
411 
413  void *tls,
414  const MPoly *coarse_poly)
415 {
417  ctx, tls, coarse_poly, ctx->foreach_context->vertex_every_corner, false);
418 }
419 
421 {
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 
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 
500  void *tls,
501  const MPoly *coarse_poly)
502 {
504  ctx, tls, coarse_poly, ctx->foreach_context->vertex_edge, true);
505 }
506 
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 
573  void *tls,
574  const MPoly *coarse_poly)
575 {
577  ctx, tls, coarse_poly, ctx->foreach_context->vertex_edge, true);
578 }
579 
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 
593  void *tls,
594  const MPoly *coarse_poly)
595 {
597  ctx, tls, coarse_poly, ctx->foreach_context->vertex_every_edge, false);
598 }
599 
601  void *tls,
602  const MPoly *coarse_poly)
603 {
605  ctx, tls, coarse_poly, ctx->foreach_context->vertex_every_edge, false);
606 }
607 
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 
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;
644  tls,
645  ptex_face_index,
646  u,
647  v,
648  coarse_poly_index,
649  0,
650  subdiv_vertex_index);
651  }
652  }
653 }
654 
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;
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;
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 
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. */
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 
719 /* -------------------------------------------------------------------- */
723 /* TODO(sergey): Coarse edge are always NONE, consider getting rid of it. */
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. */
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 
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,
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,
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 
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,
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,
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,
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 
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 
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 
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 
1037 /* -------------------------------------------------------------------- */
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 
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);
1073  tls,
1074  ptex_face_index,
1075  u,
1076  v,
1078  coarse_poly_index,
1079  coarse_corner_index,
1080  subdiv_loop_start_index + 0,
1081  v0,
1082  e0);
1084  tls,
1085  ptex_face_index,
1086  u + du,
1087  v,
1089  coarse_poly_index,
1090  coarse_corner_index,
1091  subdiv_loop_start_index + 1,
1092  v1,
1093  e1);
1095  tls,
1096  ptex_face_index,
1097  u + du,
1098  v + dv,
1100  coarse_poly_index,
1101  coarse_corner_index,
1102  subdiv_loop_start_index + 2,
1103  v2,
1104  e2);
1106  tls,
1107  ptex_face_index,
1108  u,
1109  v + dv,
1111  coarse_poly_index,
1112  coarse_corner_index,
1113  subdiv_loop_start_index + 3,
1114  v3,
1115  e3);
1116 }
1117 
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 
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 
1180  tls,
1181  subdiv_loop_index,
1182  ptex_face_index,
1183  coarse_poly_index,
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 
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 
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;
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;
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;
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;
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);
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 
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 
1683 /* -------------------------------------------------------------------- */
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 
1716 /* -------------------------------------------------------------------- */
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;
1731  ctx->foreach_context, tls->userdata_chunk, coarse_vertex_index, subdiv_vertex_index);
1732 }
1733 
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  }
1769  ctx->foreach_context, tls->userdata_chunk, coarse_edge_index, u, subdiv_vertex_index);
1770  }
1771 }
1772 
1775 /* -------------------------------------------------------------------- */
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 
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];
1804  }
1805  }
1806 }
1807 
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. */
1818  /* Run callbacks which are supposed to be run once per shared geometry. */
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) {
1829  }
1830 }
1831 
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 
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 
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 
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)) {
1882  return false;
1883  }
1884  }
1885  /* Run all the code which is not supposed to be run from threads. */
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 
1904  0, coarse_mesh->totpoly, &ctx, subdiv_foreach_task, &parallel_range_settings);
1905  if (context->vertex_loose != NULL) {
1907  coarse_mesh->totvert,
1908  &ctx,
1910  &parallel_range_settings);
1911  }
1912  if (context->vertex_of_loose_edge != NULL) {
1914  coarse_mesh->totedge,
1915  &ctx,
1917  &parallel_range_settings);
1918  }
1919  if (context->edge != NULL) {
1921  coarse_mesh->totedge,
1922  &ctx,
1924  &parallel_range_settings);
1925  }
1927  return true;
1928 }
1929 
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:206
void(* SubdivForeachVertexFromEdgeCb)(const struct SubdivForeachContext *context, void *tls, const int ptex_face_index, const float u, const float v, const int coarse_edge_index, const int coarse_poly_index, const int coarse_corner, const int subdiv_vertex_index)
void(* SubdivForeachVertexFromCornerCb)(const struct SubdivForeachContext *context, void *tls, const int ptex_face_index, const float u, const float v, const int coarse_vertex_index, const int coarse_poly_index, const int coarse_corner, const int subdiv_vertex_index)
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_TEST_BOOL(_bitmap, _index)
Definition: BLI_bitmap.h:73
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
void BLI_bitmap_set_all(BLI_bitmap *bitmap, bool set, size_t bits)
Definition: bitmap.c:33
#define BLI_BITMAP_TEST_AND_SET_ATOMIC(_bitmap, _index)
Definition: BLI_bitmap.h:67
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
#define BLI_INLINE
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:231
_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:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
struct SELECTID_Context context
Definition: select_engine.c:47
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:160
size_t userdata_chunk_size
Definition: BLI_task.h:150
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)