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