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