Blender V5.0
subd/split.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "scene/camera.h"
6#include "scene/mesh.h"
7
8#include "subd/dice.h"
9#include "subd/patch.h"
10#include "subd/split.h"
11
12#include "subd/subpatch.h"
13#include "util/algorithm.h"
14
15#include "util/math.h"
16#include "util/types.h"
17
19
20/* DiagSplit */
21
22DiagSplit::DiagSplit(const SubdParams &params_) : params(params_) {}
23
24int DiagSplit::alloc_verts(int num)
25{
26 const int index = num_verts;
27 num_verts += num;
28 return index;
29}
30
31SubEdge *DiagSplit::alloc_edge(const int v0, const int v1, const int depth, bool &was_missing)
32{
33 const SubEdge edge(v0, v1, depth);
34 const auto it = edges.find(edge);
35 was_missing = (it == edges.end());
36 return const_cast<SubEdge *>(was_missing ? &*(edges.emplace(edge).first) : &*it);
37}
38
39void DiagSplit::alloc_edge(SubPatch::Edge *sub_edge,
40 const int v0,
41 const int v1,
42 const int depth,
43 const bool want_to_own_edge,
44 const bool want_to_own_vertex)
45{
46 bool was_missing;
47 sub_edge->edge = (v0 < v1) ? alloc_edge(v0, v1, depth, was_missing) :
48 alloc_edge(v1, v0, depth, was_missing);
49 sub_edge->own_vertex = false;
50 sub_edge->own_edge = was_missing && want_to_own_edge;
51 sub_edge->reversed = sub_edge->edge->start_vert_index != v0;
52
53 if (want_to_own_vertex) {
54 if (v0 < owned_verts.size()) {
55 /* Vertex in original mesh. */
56 if (!owned_verts[v0]) {
57 owned_verts[v0] = true;
58 sub_edge->own_vertex = true;
59 }
60 }
61 else {
62 /* Mid edge vertex. */
63 sub_edge->own_vertex = true;
64 }
65 }
66}
67
68void DiagSplit::alloc_subpatch(SubPatch &&sub)
69{
70 assert(sub.edges[0].edge->T >= 1);
71 assert(sub.edges[1].edge->T >= 1);
72 assert(sub.edges[2].edge->T >= 1);
73 if (sub.shape == SubPatch::QUAD) {
74 assert(sub.edges[3].edge->T >= 1);
75 }
76
77 sub.inner_grid_vert_offset = alloc_verts(sub.calc_num_inner_verts());
78 sub.triangles_offset = num_triangles;
79 num_triangles += sub.calc_num_triangles();
80
81 subpatches.push_back(std::move(sub));
82}
83
84float3 DiagSplit::to_world(const Patch *patch, const float2 uv)
85{
86 float3 P;
87
88 patch->eval(&P, nullptr, nullptr, nullptr, uv.x, uv.y);
89 if (params.camera) {
90 P = transform_point(&params.objecttoworld, P);
91 }
92
93 return P;
94}
95
96std::pair<int, float> DiagSplit::T(const Patch *patch,
97 float2 uv_start,
98 float2 uv_end,
99 const int depth,
100 const bool recursive_resolve)
101{
102 /* May not be necessary, but better to be safe. */
103 if (uv_end.x < uv_start.x || uv_end.y < uv_start.y) {
104 swap(uv_start, uv_end);
105 }
106
107 float Lsum = 0.0f;
108 float Lmax = 0.0f;
109 float Lsum_world = 0.0f;
110
111 float3 Plast = to_world(patch, uv_start);
112
113 for (int i = 1; i < params.test_steps; i++) {
114 const float t = i / (float)(params.test_steps - 1);
115
116 const float3 P = to_world(patch, uv_start + t * (uv_end - uv_start));
117
118 float L = len(P - Plast);
119 Lsum_world += L;
120
121 if (params.camera) {
122 Camera *cam = params.camera;
123
124 const float pixel_width = cam->world_to_raster_size((P + Plast) * 0.5f);
125 L /= pixel_width;
126 }
127
128 Lsum += L;
129 Lmax = max(L, Lmax);
130
131 Plast = P;
132 }
133
134 const int tmin = (int)ceilf(Lsum / params.dicing_rate);
135 const int tmax = (int)ceilf(
136 (params.test_steps - 1) * Lmax /
137 params.dicing_rate); // XXX paper says N instead of N-1, seems wrong?
138 int res = max(tmax, 1);
139
140 if (tmax - tmin > params.split_threshold) {
141 if (!recursive_resolve) {
142 res = DSPLIT_NON_UNIFORM;
143 }
144 else {
145 const float2 uv_mid = (uv_start + uv_end) * 0.5f;
146 const auto result_a = T(patch, uv_start, uv_mid, depth, true);
147 const auto result_b = T(patch, uv_mid, uv_end, depth, true);
148 res = result_a.first + result_b.first;
149 Lsum_world = result_a.second + result_b.second;
150 }
151 }
152
153 if (!recursive_resolve && res > DSPLIT_MAX_SEGMENTS) {
154 res = DSPLIT_NON_UNIFORM;
155 }
156
157 res = limit_edge_factor(patch, uv_start, uv_end, res);
158
159 /* Limit edge factor so we don't go beyond max depth. -3 is so that
160 * for triangle patches, all 3 edges get an opportunity to get split. */
161 if (depth >= DSPLIT_MAX_DEPTH - 3 && res == DSPLIT_NON_UNIFORM) {
163 }
164
165 return std::make_pair(res, Lsum_world);
166}
167
168int DiagSplit::limit_edge_factor(const Patch *patch,
169 const float2 uv_start,
170 const float2 uv_end,
171 const int T)
172{
173 const int max_t = 1 << params.max_level;
174 int max_t_for_edge = int(max_t * len(uv_start - uv_end));
175
176 if (patch->from_ngon) {
177 max_t_for_edge >>= 1; /* Initial split of ngon causes edges to extend half the distance. */
178 }
179
180 const int limit_T = (max_t_for_edge <= 1) ? 1 : min(T, max_t_for_edge);
181
182 assert(limit_T != 0);
183 return limit_T;
184}
185
186void DiagSplit::assign_edge_factor(SubEdge *edge,
187 const Patch *patch,
188 float2 uv_start,
189 float2 uv_end,
190 const bool recursive_resolve)
191{
192 assert(edge->T <= 0);
193
194 const auto result = T(patch, uv_start, uv_end, edge->depth, recursive_resolve);
195 edge->T = result.first;
196 edge->length = result.second;
197
198 /* Ensure we can always split at depth - 1. */
199 if (edge->depth == -1 && edge->T == 1) {
200 edge->T = 2;
201 }
202
203 if (edge->T > 0) {
204 edge->second_vert_index = alloc_verts(edge->T - 1);
205 }
206}
207
208void DiagSplit::resolve_edge_factors(const SubPatch &sub)
209{
210 SubEdge *edge0 = sub.edges[0].edge;
211 SubEdge *edge1 = sub.edges[1].edge;
212 SubEdge *edge2 = sub.edges[2].edge;
213
214 /* Compute edge factor if not already set. */
215 if (edge0->T == 0) {
216 assign_edge_factor(edge0, sub.patch, sub.uvs[0], sub.uvs[1], true);
217 }
218 if (edge1->T == 0) {
219 assign_edge_factor(edge1, sub.patch, sub.uvs[1], sub.uvs[2], true);
220 }
221
222 if (sub.shape == SubPatch::TRIANGLE) {
223 if (edge2->T == 0) {
224 assign_edge_factor(edge2, sub.patch, sub.uvs[2], sub.uvs[0], true);
225 }
226 }
227 else {
228 SubEdge *edge3 = sub.edges[3].edge;
229
230 if (edge2->T == 0) {
231 assign_edge_factor(edge2, sub.patch, sub.uvs[2], sub.uvs[3], true);
232 }
233 if (edge3->T == 0) {
234 assign_edge_factor(edge3, sub.patch, sub.uvs[3], sub.uvs[0], true);
235 }
236 }
237}
238
239float2 DiagSplit::split_edge(const Patch *patch,
240 SubPatch::Edge *subedge,
241 SubPatch::Edge *subedge_a,
242 SubPatch::Edge *subedge_b,
243 float2 uv_start,
244 float2 uv_end)
245{
246 /* This splits following the direction of the edge itself, not subpatch edge direction. */
247 if (subedge->reversed) {
248 swap(uv_start, uv_end);
249 }
250
251 SubEdge *edge = subedge->edge;
252
253 if (edge->must_split()) {
254 /* Split down the middle. */
255 const float2 P = 0.5f * (uv_start + uv_end);
256 if (edge->mid_vert_index == -1) {
257 /* Allocate mid vertex and edges. */
258 edge->mid_vert_index = alloc_verts(1);
259
260 bool unused;
261 SubEdge *edge_a = alloc_edge(
262 edge->start_vert_index, edge->mid_vert_index, edge->depth + 1, unused);
263 SubEdge *edge_b = alloc_edge(
264 edge->mid_vert_index, edge->end_vert_index, edge->depth + 1, unused);
265 assign_edge_factor(edge_a, patch, uv_start, P);
266 assign_edge_factor(edge_b, patch, P, uv_end);
267 }
268
269 /* Allocate sub edges and set ownership. */
270 alloc_edge(subedge_a,
271 subedge->start_vert_index(),
272 subedge->mid_vert_index(),
273 edge->depth + 1,
274 false,
275 false);
276 alloc_edge(subedge_b,
277 subedge->mid_vert_index(),
278 subedge->end_vert_index(),
279 edge->depth + 1,
280 false,
281 false);
282
283 subedge_a->own_edge = subedge->own_edge;
284 subedge_b->own_edge = subedge->own_edge;
285 subedge_a->own_vertex = subedge->own_vertex;
286 subedge_b->own_vertex = subedge->own_edge;
287
288 assert(P.x >= 0 && P.x <= 1.0f && P.y >= 0.0f && P.y <= 1.0f);
289 return P;
290 }
291
292 assert(edge->T >= 2);
293 const int mid = edge->T / 2;
294
295 /* T is final and edge vertices are already allocated. An adjacent subpatch may not
296 * split this edge. So we ensure T and vertex indices match up with the non-split edge. */
297 if (edge->mid_vert_index == -1) {
298 /* Allocate mid vertex and edges. */
299 edge->mid_vert_index = edge->second_vert_index - 1 + mid;
300
301 bool unused;
302 SubEdge *edge_a = alloc_edge(
303 edge->start_vert_index, edge->mid_vert_index, edge->depth + 1, unused);
304 SubEdge *edge_b = alloc_edge(
305 edge->mid_vert_index, edge->end_vert_index, edge->depth + 1, unused);
306 edge_a->T = mid;
307 edge_b->T = edge->T - mid;
308 edge_a->second_vert_index = edge->second_vert_index;
309 edge_b->second_vert_index = edge->second_vert_index + edge_a->T;
310 }
311
312 /* Allocate sub edges and set ownership. */
313 alloc_edge(subedge_a,
314 subedge->start_vert_index(),
315 subedge->mid_vert_index(),
316 edge->depth + 1,
317 false,
318 false);
319 alloc_edge(subedge_b,
320 subedge->mid_vert_index(),
321 subedge->end_vert_index(),
322 edge->depth + 1,
323 false,
324 false);
325
326 subedge_a->own_edge = subedge->own_edge;
327 subedge_b->own_edge = subedge->own_edge;
328 subedge_a->own_vertex = subedge->own_vertex;
329 subedge_b->own_vertex = subedge->own_edge;
330
331 const float2 P = interp(uv_start, uv_end, mid / (float)edge->T);
332 assert(P.x >= 0 && P.x <= 1.0f && P.y >= 0.0f && P.y <= 1.0f);
333
334 return P;
335}
336
337void DiagSplit::split_quad(SubPatch &&sub)
338{
339 /* Set edge factors if we haven't already. */
340 resolve_edge_factors(sub);
341
342 /* Split subpatch if edges are marked as must split,
343 * or if the following conditions are met:
344 * - Both edges have at least 2 segments.
345 * - Either edge has more than DSPLIT_MAX_SEGMENTS segments.
346 * - The ratio of segments for opposite edges doesn't exceed 1.5.
347 * This reduces over tessellation for some patches. */
348 const int min_T_u = min(sub.edges[0].edge->T, sub.edges[2].edge->T);
349 const int max_T_u = max(sub.edges[0].edge->T, sub.edges[2].edge->T);
350 const int min_T_v = min(sub.edges[3].edge->T, sub.edges[1].edge->T);
351 const int max_T_v = max(sub.edges[3].edge->T, sub.edges[1].edge->T);
352
353 bool split_u = sub.edges[0].edge->must_split() || sub.edges[2].edge->must_split() ||
354 (min_T_u >= 2 && min_T_v > DSPLIT_MAX_SEGMENTS && max_T_v / min_T_v > 1.5f);
355 bool split_v = sub.edges[3].edge->must_split() || sub.edges[1].edge->must_split() ||
356 (min_T_v >= 2 && min_T_u > DSPLIT_MAX_SEGMENTS && max_T_u / min_T_u > 1.5f);
357
358 /* If both need to split, pick longest axis. */
359 if (split_u && split_v) {
360 /* Slight bias so that for square quads, we get consistent results across
361 * platforms rather than choice being decided by precision. */
362 const float bias = 1.00012345f;
363 if ((sub.edges[0].edge->length + sub.edges[2].edge->length) * bias >=
364 sub.edges[1].edge->length + sub.edges[3].edge->length)
365 {
366 split_u = true;
367 split_v = false;
368 }
369 else {
370 split_u = false;
371 split_v = true;
372 }
373 }
374
375 if (!split_u && !split_v) {
376 /* Add the unsplit subpatch. */
377 alloc_subpatch(std::move(sub));
378 return;
379 }
380
381 /* Split into triangles if one side must the split, and the opposite side has
382 * only a single segment. Then we can't do an even split across the quad. */
383 if ((split_u && (sub.edges[0].edge->T == 1 || sub.edges[2].edge->T == 1)) ||
384 (!split_u && (sub.edges[1].edge->T == 1 || sub.edges[3].edge->T == 1)))
385 {
386 split_quad_into_triangles(std::move(sub));
387 return;
388 }
389
390 /* Copy into new subpatches. */
391 SubPatch sub_a(sub);
392 SubPatch sub_b(sub);
393
394 for (int i = 0; i < 4; i++) {
395 sub_a.edges[i].own_edge = false;
396 sub_a.edges[i].own_vertex = false;
397 sub_b.edges[i].own_edge = false;
398 sub_b.edges[i].own_vertex = false;
399 }
400
401 /* Pointers to various subpatch elements. */
402 SubPatch::Edge *sub_across_0;
403 SubPatch::Edge *sub_across_1;
404 SubPatch::Edge *sub_a_across_0;
405 SubPatch::Edge *sub_a_across_1;
406 SubPatch::Edge *sub_b_across_0;
407 SubPatch::Edge *sub_b_across_1;
408
409 SubPatch::Edge *sub_a_split;
410 SubPatch::Edge *sub_b_split;
411
412 float2 *uv_a;
413 float2 *uv_b;
414 float2 *uv_c;
415 float2 *uv_d;
416
417 /* Set pointers based on split axis. */
418 if (split_u) {
419 /*
420 * sub_across_1
421 * -------uv_a uv_c-------
422 * | | | |
423 * | A | | B |
424 * | | | |
425 * -------uv_b uv_d-------
426 * sub_across_0
427 */
428 sub_across_0 = &sub.edges[0];
429 sub_across_1 = &sub.edges[2];
430 sub_a_across_0 = &sub_a.edges[0];
431 sub_a_across_1 = &sub_a.edges[2];
432 sub_b_across_0 = &sub_b.edges[0];
433 sub_b_across_1 = &sub_b.edges[2];
434
435 sub_a.edges[3].own_edge = sub.edges[3].own_edge;
436 sub_a.edges[3].own_vertex = sub.edges[3].own_vertex;
437 sub_b.edges[1].own_edge = sub.edges[1].own_edge;
438 sub_b.edges[1].own_vertex = sub.edges[1].own_vertex;
439
440 sub_a_split = &sub_a.edges[1];
441 sub_b_split = &sub_b.edges[3];
442
443 uv_a = &sub_a.uvs[2];
444 uv_b = &sub_a.uvs[1];
445 uv_c = &sub_b.uvs[3];
446 uv_d = &sub_b.uvs[0];
447 }
448 else {
449 /*
450 * --------------------
451 * | A |
452 * uv_b------------uv_a
453 * sub_across_0 sub_across_1
454 * uv_d------------uv_c
455 * | B |
456 * --------------------
457 */
458 sub_across_0 = &sub.edges[3];
459 sub_across_1 = &sub.edges[1];
460 sub_a_across_0 = &sub_a.edges[3];
461 sub_a_across_1 = &sub_a.edges[1];
462 sub_b_across_0 = &sub_b.edges[3];
463 sub_b_across_1 = &sub_b.edges[1];
464
465 sub_a.edges[2].own_edge = sub.edges[2].own_edge;
466 sub_a.edges[2].own_vertex = sub.edges[2].own_vertex;
467 sub_b.edges[0].own_edge = sub.edges[0].own_edge;
468 sub_b.edges[0].own_vertex = sub.edges[0].own_vertex;
469
470 sub_a_split = &sub_a.edges[0];
471 sub_b_split = &sub_b.edges[2];
472
473 uv_a = &sub_a.uvs[1];
474 uv_b = &sub_a.uvs[0];
475 uv_c = &sub_b.uvs[2];
476 uv_d = &sub_b.uvs[3];
477 }
478
479 /* Allocate new edges and vertices. */
480 const float2 uv0 = split_edge(
481 sub.patch, sub_across_0, sub_a_across_0, sub_b_across_0, *uv_d, *uv_b);
482 const float2 uv1 = split_edge(
483 sub.patch, sub_across_1, sub_b_across_1, sub_a_across_1, *uv_a, *uv_c);
484
485 assert(sub_a_across_0->edge->T != 0);
486 assert(sub_b_across_0->edge->T != 0);
487 assert(sub_a_across_1->edge->T != 0);
488 assert(sub_b_across_1->edge->T != 0);
489
490 /* Split */
491 *uv_a = uv1;
492 *uv_b = uv0;
493
494 *uv_c = uv1;
495 *uv_d = uv0;
496
497 /* Create new edge */
498 const int split_edge_depth = (split_u) ?
499 max(sub.edges[1].edge->depth, sub.edges[3].edge->depth) :
500 max(sub.edges[0].edge->depth, sub.edges[2].edge->depth);
501 alloc_edge(sub_a_split,
502 sub_across_0->mid_vert_index(),
503 sub_across_1->mid_vert_index(),
504 split_edge_depth,
505 true,
506 false);
507 alloc_edge(sub_b_split,
508 sub_across_1->mid_vert_index(),
509 sub_across_0->mid_vert_index(),
510 split_edge_depth,
511 true,
512 false);
513
514 /* Set T for split edge. */
515 assign_edge_factor(sub_a_split->edge, sub.patch, uv0, uv1);
516
517 /* Recurse */
518 split_quad(std::move(sub_a));
519 split_quad(std::move(sub_b));
520}
521
522void DiagSplit::split_quad_into_triangles(SubPatch &&sub)
523{
525
526 /* Copy into new subpatches. */
527 SubPatch sub_a(sub);
528 SubPatch sub_b(sub);
529
530 sub_a.shape = SubPatch::TRIANGLE;
531 sub_b.shape = SubPatch::TRIANGLE;
532
533 for (int i = 0; i < 4; i++) {
534 sub_a.edges[i].own_edge = false;
535 sub_a.edges[i].own_vertex = false;
536 sub_b.edges[i].own_edge = false;
537 sub_b.edges[i].own_vertex = false;
538 }
539
540 const int split_edge_depth = std::max({sub.edges[0].edge->depth,
541 sub.edges[1].edge->depth,
542 sub.edges[2].edge->depth,
543 sub.edges[3].edge->depth});
544
545 sub_a.edges[0] = sub.edges[0];
546 sub_a.edges[1] = sub.edges[1];
547 sub_a.uvs[0] = sub.uvs[0];
548 sub_a.uvs[1] = sub.uvs[1];
549 sub_a.uvs[2] = sub.uvs[2];
550 alloc_edge(&sub_a.edges[2],
551 sub.edges[2].start_vert_index(),
552 sub.edges[0].start_vert_index(),
553 split_edge_depth,
554 true,
555 false);
556
557 sub_b.edges[1] = sub.edges[2];
558 sub_b.edges[2] = sub.edges[3];
559 sub_b.uvs[0] = sub.uvs[0];
560 sub_b.uvs[1] = sub.uvs[2];
561 sub_b.uvs[2] = sub.uvs[3];
562 alloc_edge(&sub_b.edges[0],
563 sub.edges[0].start_vert_index(),
564 sub.edges[2].start_vert_index(),
565 split_edge_depth,
566 true,
567 false);
568
569 /* Set T for new edge. */
570 assign_edge_factor(sub_b.edges[0].edge, sub.patch, sub.uvs[0], sub.uvs[2]);
571
572 /* Recurse */
573 split_triangle(std::move(sub_a));
574 split_triangle(std::move(sub_b));
575}
576
577void DiagSplit::split_triangle(SubPatch &&sub)
578{
580
581 /* Set edge factors if we haven't already. */
582 resolve_edge_factors(sub);
583
584 const bool do_split = sub.edges[0].edge->must_split() || sub.edges[1].edge->must_split() ||
585 sub.edges[2].edge->must_split();
586 if (!do_split) {
587 /* Add the unsplit subpatch. */
588 alloc_subpatch(std::move(sub));
589 return;
590 }
591
592 /* Slight bias so that for equal length edges, we get consistent results across
593 * platforms rather than choice being decided by precision. */
594 const float bias = 1.00012345f;
595
596 /* Pick longest edge that must be split. Note that in degenerate cases edges may have
597 * zero length but still requires splitting at depth 0. */
598 float max_length = 0.0f;
599 int split_index_0 = -1;
600 for (int i = 0; i < 3; i++) {
601 if (sub.edges[i].edge->must_split() &&
602 (split_index_0 == -1 || sub.edges[i].edge->length > max_length))
603 {
604 split_index_0 = i;
605 max_length = sub.edges[i].edge->length * bias;
606 }
607 }
608
609 /* Copy into new subpatches. */
610 SubPatch sub_a(sub);
611 SubPatch sub_b(sub);
612
613 for (int i = 0; i < 4; i++) {
614 sub_a.edges[i].own_edge = false;
615 sub_a.edges[i].own_vertex = false;
616 sub_b.edges[i].own_edge = false;
617 sub_b.edges[i].own_vertex = false;
618 }
619
620 const int split_index_1 = (split_index_0 + 1) % 3;
621 const int split_index_2 = (split_index_0 + 2) % 3;
622
623 sub_a.edges[2] = sub.edges[split_index_2];
624 sub_b.edges[1] = sub.edges[split_index_1];
625
626 /*
627 * uv_opposite
628 * 2 2
629 * / | | \
630 * / | | \
631 * / A | | B \
632 * / | | \
633 * 0 --- 1 0 --- 1
634 * uv_split
635 */
636
637 /* Allocate new edges and vertices. */
638 const float2 uv_split = split_edge(sub.patch,
639 &sub.edges[split_index_0],
640 &sub_a.edges[0],
641 &sub_b.edges[0],
642 sub.uvs[split_index_0],
643 sub.uvs[split_index_1]);
644
645 /* Set UVs. */
646 sub_a.uvs[0] = sub.uvs[split_index_0];
647 sub_a.uvs[1] = uv_split;
648 sub_a.uvs[2] = sub.uvs[split_index_2];
649 sub_b.uvs[0] = uv_split;
650 sub_b.uvs[1] = sub.uvs[split_index_1];
651 sub_b.uvs[2] = sub.uvs[split_index_2];
652
653 /* Create new edge */
654 const int vsplit = sub.edges[split_index_0].mid_vert_index();
655 const int vopposite = sub.edges[split_index_2].start_vert_index();
656
657 const int split_edge_depth = sub.edges[split_index_0].edge->depth + 1;
658
659 alloc_edge(&sub_a.edges[1], vsplit, vopposite, split_edge_depth, true, false);
660 alloc_edge(&sub_b.edges[2], vopposite, vsplit, split_edge_depth, true, false);
661
662 /* Set T for split edge. */
663 const float2 uv_opposite = sub.uvs[split_index_2];
664 assign_edge_factor(sub_a.edges[1].edge, sub.patch, uv_split, uv_opposite);
665
666 /* Recurse */
667 split_triangle(std::move(sub_a));
668 split_triangle(std::move(sub_b));
669}
670
671void DiagSplit::split_quad(const Mesh::SubdFace &face, const int face_index, const Patch *patch)
672{
673 const int *subd_face_corners = params.mesh->get_subd_face_corners().data();
674 const int v0 = subd_face_corners[face.start_corner + 0];
675 const int v1 = subd_face_corners[face.start_corner + 1];
676 const int v2 = subd_face_corners[face.start_corner + 2];
677 const int v3 = subd_face_corners[face.start_corner + 3];
678
679 const int depth = -1;
680
681 SubPatch subpatch(patch, face_index);
682 alloc_edge(&subpatch.edges[0], v0, v1, depth, true, true);
683 alloc_edge(&subpatch.edges[1], v1, v2, depth, true, true);
684 alloc_edge(&subpatch.edges[2], v2, v3, depth, true, true);
685 alloc_edge(&subpatch.edges[3], v3, v0, depth, true, true);
686
687 /* Forces a split in both axis for quads, needed to match split of ngons into quads. */
688 subpatch.edges[0].edge->T = DSPLIT_NON_UNIFORM;
689 subpatch.edges[3].edge->T = DSPLIT_NON_UNIFORM;
690 subpatch.edges[2].edge->T = DSPLIT_NON_UNIFORM;
691 subpatch.edges[1].edge->T = DSPLIT_NON_UNIFORM;
692
693 split_quad(std::move(subpatch));
694}
695
696void DiagSplit::split_ngon(const Mesh::SubdFace &face,
697 const int face_index,
698 const Patch *patches,
699 const size_t patches_byte_stride)
700{
701 const int *subd_face_corners = params.mesh->get_subd_face_corners().data();
702 const int v2 = alloc_verts(1);
703
704 const int depth = 0;
705
706 /* Allocate edges of n-gon. */
707 array<SubPatch::Edge> edges(face.num_corners);
708 for (int corner = 0; corner < face.num_corners; corner++) {
709 const int v = subd_face_corners[face.start_corner + corner];
710 const int vnext = subd_face_corners[face.start_corner + mod(corner + 1, face.num_corners)];
711
712 alloc_edge(&edges[corner], v, vnext, depth, true, true);
713 if (edges[corner].edge->mid_vert_index == -1) {
714 edges[corner].edge->mid_vert_index = alloc_verts(1);
715 }
716 }
717
718 /* Allocate patches. */
719 for (int corner = 0; corner < face.num_corners; corner++) {
720 const Patch *patch = (const Patch *)(((char *)patches) + (corner * patches_byte_stride));
721
722 /* v_prev .
723 * . .
724 * . edge2 .
725 * v3 ←------- v2 . . .
726 * | ↑
727 * edge3 | | edge1
728 * ↓ |
729 * v0 ------→ v1 . . v_next
730 * edge0
731 */
732 SubPatch::Edge &edge3 = edges[mod(corner + face.num_corners - 1, face.num_corners)];
733 SubPatch::Edge &edge0 = edges[corner];
734
735 /* Setup edges. */
736 const int v0 = edge0.start_vert_index();
737 const int v1 = edge0.mid_vert_index();
738 const int v3 = edge3.mid_vert_index();
739
740 SubPatch subpatch(patch, face_index, corner);
741 alloc_edge(&subpatch.edges[0], v0, v1, depth, false, false);
742 alloc_edge(&subpatch.edges[1], v1, v2, depth, true, false);
743 alloc_edge(&subpatch.edges[2], v2, v3, depth, true, corner == 0);
744 alloc_edge(&subpatch.edges[3], v3, v0, depth, false, false);
745
746 subpatch.edges[0].own_edge = edge0.own_edge;
747 subpatch.edges[0].own_vertex = edge0.own_vertex;
748 subpatch.edges[3].own_edge = edge3.own_edge;
749 subpatch.edges[3].own_vertex = edge3.own_edge;
750
751 /* Perform split. */
752 split_quad(std::move(subpatch));
753 }
754}
755
756void DiagSplit::split_patches(const Patch *patches, const size_t patches_byte_stride)
757{
758 /* TODO: reuse edge factor vertex position computations. */
759 /* TODO: support not splitting n-gons if not needed. */
760 /* TODO: multi-threading. */
761
762 /* Keep base mesh vertices, create new triangles. */
763 num_verts = params.mesh->get_num_subd_base_verts();
764 num_triangles = 0;
765
766 owned_verts.resize(num_verts, false);
767
768 /* Split all faces in the mesh. */
769 for (int f = 0; f < params.mesh->get_num_subd_faces(); f++) {
770 Mesh::SubdFace face = params.mesh->get_subd_face(f);
771 const Patch *patch = (const Patch *)(((char *)patches) +
772 (face.ptex_offset * patches_byte_stride));
773 if (face.is_quad()) {
774 split_quad(face, f, patch);
775 }
776 else {
777 split_ngon(face, f, patch, patches_byte_stride);
778 }
779 }
780}
781
ATTR_WARN_UNUSED_RESULT const size_t num
struct Camera Camera
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
DiagSplit(const SubdParams &params)
void split_patches(const Patch *patches, const size_t patches_byte_stride)
Definition patch.h:12
virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, const float u, float v) const =0
bool from_ngon
Definition patch.h:23
enum SubPatch::@271217051357320143155373165321151177022113114126 shape
float2 uvs[4]
Definition subpatch.h:162
@ TRIANGLE
Definition subpatch.h:99
const Patch * patch
Definition subpatch.h:94
Edge edges[4]
Definition subpatch.h:165
nullptr float
#define CCL_NAMESPACE_END
#define assert(assertion)
VecBase< float, D > constexpr mod(VecOp< float, D >, VecOp< float, D >) RET
VecBase< float, 2 > float2
VecBase< float, 3 > float3
ccl_device_inline float interp(const float a, const float b, const float t)
Definition math_base.h:502
#define T
#define L
#define ceilf
#define swap(a, b)
Definition sort.cc:59
#define min(a, b)
Definition sort.cc:36
float world_to_raster_size(const float3 P)
int mid_vert_index
Definition subpatch.h:33
int second_vert_index
Definition subpatch.h:42
int start_vert_index
Definition subpatch.h:29
int end_vert_index
Definition subpatch.h:30
float length
Definition subpatch.h:39
bool must_split() const
Definition subpatch.h:63
int depth
Definition subpatch.h:45
int T
Definition subpatch.h:36
int start_vert_index() const
Definition subpatch.h:119
SubEdge * edge
Definition subpatch.h:107
int mid_vert_index() const
Definition subpatch.h:123
int end_vert_index() const
Definition subpatch.h:127
float x
float y
@ DSPLIT_MAX_DEPTH
Definition subpatch.h:16
@ DSPLIT_NON_UNIFORM
Definition subpatch.h:15
@ DSPLIT_MAX_SEGMENTS
Definition subpatch.h:17
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
ccl_device_inline float3 transform_point(const ccl_private Transform *t, const float3 a)
Definition transform.h:56
uint len