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