Blender V5.0
dice.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"
10#include "subd/patch.h"
11#include "subd/split.h"
12
13#include "util/tbb.h"
14
16
18 const int num_verts,
19 const int num_triangles,
22{
23 Mesh *mesh = params.mesh;
24
25 mesh->num_subd_added_verts = num_verts - mesh->get_verts().size();
26 mesh->resize_mesh(num_verts, num_triangles);
27
29
30 mesh_triangles = mesh->triangles.data();
31 mesh_shader = mesh->shader.data();
32 mesh_smooth = mesh->smooth.data();
33 mesh_P = mesh->verts.data();
34 mesh_N = attr_vN->data_float3();
35
36 if (params.ptex) {
37 Attribute *attr_ptex_face_id = params.mesh->attributes.add(ATTR_STD_PTEX_FACE_ID);
38 Attribute *attr_ptex_uv = params.mesh->attributes.add(ATTR_STD_PTEX_UV);
39
40 mesh_ptex_face_id = attr_ptex_face_id->data_float();
41 mesh_ptex_uv = attr_ptex_uv->data_float2();
42 }
43
44 interpolation.setup();
45}
46
48{
49 float3 P;
50
51 sub.patch->eval(&P, nullptr, nullptr, nullptr, uv.x, uv.y);
52 if (params.camera) {
53 P = transform_perspective(&params.camera->worldtoraster, P);
54 }
55
56 return P;
57}
58
59float EdgeDice::quad_area(const float3 &a, const float3 &b, const float3 &c, const float3 &d)
60{
61 return triangle_area(a, b, d) + triangle_area(a, d, c);
62}
63
64float EdgeDice::scale_factor(const SubPatch &sub, const int Mu, const int Mv)
65{
66 /* estimate area as 4x largest of 4 quads */
67 float3 P[3][3];
68
69 for (int i = 0; i < 3; i++) {
70 for (int j = 0; j < 3; j++) {
71 P[i][j] = eval_projected(sub, sub.map_uv(make_float2(i * 0.5f, j * 0.5f)));
72 }
73 }
74
75 const float A1 = quad_area(P[0][0], P[1][0], P[0][1], P[1][1]);
76 const float A2 = quad_area(P[1][0], P[2][0], P[1][1], P[2][1]);
77 const float A3 = quad_area(P[0][1], P[1][1], P[0][2], P[1][2]);
78 const float A4 = quad_area(P[1][1], P[2][1], P[1][2], P[2][2]);
79 const float Apatch = max(A1, max(A2, max(A3, A4))) * 4.0f;
80
81 /* solve for scaling factor */
82 const float Atri = params.dicing_rate * params.dicing_rate * 0.5f;
83 const float Ntris = Apatch / Atri;
84
85 // XXX does the -sqrt solution matter
86 // XXX max(D, 0.0) is highly suspicious, need to test cases
87 // where D goes negative
88 const float N = 0.5f * (Ntris - (sub.edges[0].edge->T + sub.edges[2].edge->T +
89 sub.edges[3].edge->T + sub.edges[1].edge->T));
90 const float D = (4.0f * N * Mu * Mv) + ((Mu + Mv) * (Mu + Mv));
91 const float S = (Mu + Mv + sqrtf(max(D, 0.0f))) / (2 * Mu * Mv);
92
93 return S;
94}
95
96void EdgeDice::set_vertex(const SubPatch &sub, const int index, const float2 uv)
97{
98 assert(index < params.mesh->verts.size());
99
100 float3 P;
101 float3 N;
102
103 sub.patch->eval(&P, nullptr, nullptr, &N, uv.x, uv.y);
104
105 mesh_P[index] = P;
106 mesh_N[index] = N;
107
108 for (const SubdAttribute &attr : interpolation.vertex_attributes) {
109 attr.interp(sub.patch->patch_index, sub.face_index, sub.corner, &index, &uv, 1);
110 }
111}
112
114 const int triangle_index,
115 const int v0,
116 const int v1,
117 const int v2,
118 const float2 uv0,
119 const float2 uv1,
120 const float2 uv2)
121{
122 assert(triangle_index * 3 < params.mesh->triangles.size());
123
124 const Patch *patch = sub.patch;
125
126 mesh_triangles[triangle_index * 3 + 0] = v0;
127 mesh_triangles[triangle_index * 3 + 1] = v1;
128 mesh_triangles[triangle_index * 3 + 2] = v2;
129 mesh_shader[triangle_index] = patch->shader;
130 mesh_smooth[triangle_index] = patch->smooth;
131
132 if (mesh_ptex_face_id) {
133 mesh_ptex_face_id[triangle_index] = patch->patch_index;
134 }
135 if (mesh_ptex_uv) {
136 mesh_ptex_uv[triangle_index * 3 + 0] = uv0;
137 mesh_ptex_uv[triangle_index * 3 + 0] = uv1;
138 mesh_ptex_uv[triangle_index * 3 + 0] = uv2;
139 }
140
141 /* TODO: batch together multiple triangles. */
142 float2 uv[3] = {uv0, uv1, uv2};
143 for (const SubdAttribute &attr : interpolation.triangle_attributes) {
144 attr.interp(sub.patch->patch_index, sub.face_index, sub.corner, &triangle_index, uv, 1);
145 }
146}
147
148void EdgeDice::add_grid_triangles_and_stitch(const SubPatch &sub, const int Mu, const int Mv)
149{
150 const float du = 1.0f / (float)Mu;
151 const float dv = 1.0f / (float)Mv;
152 const int grid_vertex_offset = sub.inner_grid_vert_offset;
153 int triangle_index = sub.triangles_offset;
154
155 /* Create inner grid. */
156 for (int j = 1; j < Mv; j++) {
157 for (int i = 1; i < Mu; i++) {
158 const float u = i * du;
159 const float v = j * dv;
160 const int center_i = grid_vertex_offset + (i - 1) + (j - 1) * (Mu - 1);
161
162 set_vertex(sub, center_i, sub.map_uv(make_float2(u, v)));
163
164 if (i < Mu - 1 && j < Mv - 1) {
165 const int i1 = grid_vertex_offset + (i - 1) + (j - 1) * (Mu - 1);
166 const int i2 = grid_vertex_offset + i + (j - 1) * (Mu - 1);
167 const int i3 = grid_vertex_offset + i + j * (Mu - 1);
168 const int i4 = grid_vertex_offset + (i - 1) + j * (Mu - 1);
169
170 const float2 uv1 = sub.map_uv(make_float2(u, v));
171 const float2 uv2 = sub.map_uv(make_float2(u + du, v));
172 const float2 uv3 = sub.map_uv(make_float2(u + du, v + dv));
173 const float2 uv4 = sub.map_uv(make_float2(u, v + dv));
174
175 set_triangle(sub, triangle_index++, i1, i2, i3, uv1, uv2, uv3);
176 set_triangle(sub, triangle_index++, i1, i3, i4, uv1, uv3, uv4);
177 }
178 }
179 }
180
181 /* Stitch inner grid to edges. */
182 for (int edge = 0; edge < 4; edge++) {
183 const int outer_T = sub.edges[edge].edge->T;
184 const int inner_T = ((edge % 2) == 0) ? Mu - 2 : Mv - 2;
185
186 float2 inner_uv, outer_uv, inner_uv_step, outer_uv_step;
187 switch (edge) {
188 case 0:
189 inner_uv = make_float2(du, dv);
190 outer_uv = make_float2(0.0f, 0.0f);
191 inner_uv_step = make_float2(du, 0.0f);
192 outer_uv_step = make_float2(1.0f / (float)outer_T, 0.0f);
193 break;
194 case 1:
195 inner_uv = make_float2(1.0f - du, dv);
196 outer_uv = make_float2(1.0f, 0.0f);
197 inner_uv_step = make_float2(0.0f, dv);
198 outer_uv_step = make_float2(0.0f, 1.0f / (float)outer_T);
199 break;
200 case 2:
201 inner_uv = make_float2(1.0f - du, 1.0f - dv);
202 outer_uv = make_float2(1.0f, 1.0f);
203 inner_uv_step = make_float2(-du, 0.0f);
204 outer_uv_step = make_float2(-1.0f / (float)outer_T, 0.0f);
205 break;
206 case 3:
207 default:
208 inner_uv = make_float2(du, 1.0f - dv);
209 outer_uv = make_float2(0.0f, 1.0f);
210 inner_uv_step = make_float2(0.0f, -dv);
211 outer_uv_step = make_float2(0.0f, -1.0f / (float)outer_T);
212 break;
213 }
214
215 /* Stitch together two arrays of verts with triangles. At each step, we compare using
216 * the next verts on both sides, to find the split direction with the smallest
217 * diagonal, and use that in order to keep the triangle shape reasonable. */
218 for (size_t i = 0, j = 0; i < inner_T || j < outer_T;) {
219 const int v0 = sub.get_vert_along_grid_edge(edge, i);
220 const int v1 = sub.get_vert_along_edge(edge, j);
221 int v2;
222
223 const float2 uv0 = sub.map_uv(inner_uv);
224 const float2 uv1 = sub.map_uv(outer_uv);
225 float2 uv2;
226
227 if (j == outer_T) {
228 v2 = sub.get_vert_along_grid_edge(edge, ++i);
229 inner_uv += inner_uv_step;
230 uv2 = sub.map_uv(inner_uv);
231 }
232 else if (i == inner_T) {
233 v2 = sub.get_vert_along_edge(edge, ++j);
234 outer_uv += outer_uv_step;
235 uv2 = sub.map_uv(outer_uv);
236 }
237 else {
238 /* Length of diagonals. */
239 const int v2_a = sub.get_vert_along_edge(edge, j + 1);
240 const int v2_b = sub.get_vert_along_grid_edge(edge, i + 1);
241
242 const float len_a = len_squared(mesh_P[v0] - mesh_P[v2_a]);
243 const float len_b = len_squared(mesh_P[v1] - mesh_P[v2_b]);
244
245 /* Use smallest diagonal. */
246 if (len_a < len_b) {
247 v2 = v2_a;
248 outer_uv += outer_uv_step;
249 uv2 = sub.map_uv(outer_uv);
250 j++;
251 }
252 else {
253 v2 = v2_b;
254 inner_uv += inner_uv_step;
255 uv2 = sub.map_uv(inner_uv);
256 i++;
257 }
258 }
259
260 set_triangle(sub, triangle_index++, v0, v1, v2, uv0, uv1, uv2);
261 }
262 }
263}
264
265void EdgeDice::add_triangle_strip(const SubPatch &sub, const int left_edge, const int right_edge)
266{
267 /* Stitch triangles from side to side, edge in the other direction has T = 1. */
268 const int left_T = sub.edges[left_edge].edge->T;
269 const int right_T = sub.edges[right_edge].edge->T;
270
271 float2 left_uv, right_uv, left_uv_step, right_uv_step;
272 if (right_edge == 0) {
273 left_uv = make_float2(0.0f, 1.0f);
274 right_uv = make_float2(0.0f, 0.0f);
275 left_uv_step = make_float2(1.0f / (float)left_T, 0.0f);
276 right_uv_step = make_float2(1.0f / (float)right_T, 0.0f);
277 }
278 else {
279 left_uv = make_float2(0.0f, 0.0f);
280 right_uv = make_float2(1.0f, 0.0f);
281 left_uv_step = make_float2(0.0f, 1.0f / (float)left_T);
282 right_uv_step = make_float2(0.0f, 1.0f / (float)right_T);
283 }
284
285 /* Stitch together two arrays of verts with triangles. at each step, we compare using the next
286 * verts on both sides, to find the split direction with the smallest diagonal, and use that
287 * in order to keep the triangle shape reasonable. */
288 int triangle_index = sub.triangles_offset;
289
290 for (size_t i = 0, j = 0; i < left_T || j < right_T;) {
291 const int v0 = sub.get_vert_along_edge_reverse(left_edge, i);
292 const int v1 = sub.get_vert_along_edge(right_edge, j);
293 int v2;
294
295 const float2 uv0 = sub.map_uv(left_uv);
296 const float2 uv1 = sub.map_uv(right_uv);
297 float2 uv2;
298
299 if (j == right_T) {
300 v2 = sub.get_vert_along_edge_reverse(left_edge, ++i);
301 left_uv += left_uv_step;
302 uv2 = sub.map_uv(left_uv);
303 }
304 else if (i == left_T) {
305 v2 = sub.get_vert_along_edge(right_edge, ++j);
306 right_uv += right_uv_step;
307 uv2 = sub.map_uv(right_uv);
308 }
309 else {
310 /* Length of diagonals. */
311 const int v2_a = sub.get_vert_along_edge(right_edge, j + 1);
312 const int v2_b = sub.get_vert_along_edge_reverse(left_edge, i + 1);
313
314 const float len_a = len_squared(mesh_P[v0] - mesh_P[v2_a]);
315 const float len_b = len_squared(mesh_P[v1] - mesh_P[v2_b]);
316
317 /* Use smallest diagonal. */
318 if (len_a < len_b) {
319 v2 = v2_a;
320 right_uv += right_uv_step;
321 uv2 = sub.map_uv(right_uv);
322 j++;
323 }
324 else {
325 v2 = v2_b;
326 left_uv += left_uv_step;
327 uv2 = sub.map_uv(left_uv);
328 i++;
329 }
330 }
331
332 set_triangle(sub, triangle_index++, v0, v1, v2, uv0, uv1, uv2);
333 }
334}
335
337{
338 for (int edge = 0; edge < 4; edge++) {
339 const int t = sub.edges[edge].edge->T;
340 const int i_start = (sub.edges[edge].own_vertex) ? 0 : 1;
341 const int i_end = (sub.edges[edge].own_edge) ? t : 1;
342
343 /* set verts on the edge of the patch */
344 for (int i = i_start; i < i_end; i++) {
345 const float f = i / (float)t;
346
347 float2 uv;
348 switch (edge) {
349 case 0:
350 uv = make_float2(f, 0.0f);
351 break;
352 case 1:
353 uv = make_float2(1.0f, f);
354 break;
355 case 2:
356 uv = make_float2(1.0f - f, 1.0f);
357 break;
358 case 3:
359 default:
360 uv = make_float2(0.0f, 1.0f - f);
361 break;
362 }
363
364 const int vert_index = sub.get_vert_along_edge(edge, i);
365 set_vertex(sub, vert_index, sub.map_uv(uv));
366 }
367 }
368}
369
371{
372 /* Compute inner grid size with scale factor. */
373 const int Mu = max(sub.edges[0].edge->T, sub.edges[2].edge->T);
374 const int Mv = max(sub.edges[3].edge->T, sub.edges[1].edge->T);
375
376 if (Mv == 1) {
377 /* No inner grid, stitch triangles from side to side. */
378 add_triangle_strip(sub, 2, 0);
379 }
380 else if (Mu == 1) {
381 /* No inner grid, stitch triangles from side to side. */
382 add_triangle_strip(sub, 3, 1);
383 }
384 else {
385#if 0
386 /* Doesn't work very well, especially at grazing angles. */
387 const float S = scale_factor(sub, ef, Mu, Mv);
388 const int grid_Mu = max((int)ceilf(S * Mu), 1); // XXX handle 0 & 1?
389 const int grid_Mv = max((int)ceilf(S * Mv), 1); // XXX handle 0 & 1?
390 add_grid_triangles_and_stitch(sub, grid_Mu, grid_Mv);
391#else
393#endif
394 }
395}
396
398{
399 for (int edge = 0; edge < 3; edge++) {
400 const int t = sub.edges[edge].edge->T;
401 const int i_start = (sub.edges[edge].own_vertex) ? 0 : 1;
402 const int i_end = (sub.edges[edge].own_edge) ? t : 1;
403
404 /* set verts on the edge of the patch */
405 for (int i = i_start; i < i_end; i++) {
406 const float f = i / (float)t;
407
408 float2 uv;
409 switch (edge) {
410 case 0:
411 uv = make_float2(f, 0.0f);
412 break;
413 case 1:
414 uv = make_float2(1.0f - f, f);
415 break;
416 case 2:
417 default:
418 uv = make_float2(0.0f, 1.0f - f);
419 break;
420 }
421
422 const int vert_index = sub.get_vert_along_edge(edge, i);
423 set_vertex(sub, vert_index, sub.map_uv(uv));
424 }
425 }
426}
427
429{
430 const int M = max(max(sub.edges[0].edge->T, sub.edges[1].edge->T), sub.edges[2].edge->T);
431 const float d = 1.0f / (float)(M + 1);
432
433 int triangle_index = sub.triangles_offset;
434
435 if (M == 1) {
436 /* Single triangle. */
437 set_triangle(sub,
438 triangle_index++,
439 sub.edges[0].start_vert_index(),
440 sub.edges[1].start_vert_index(),
441 sub.edges[2].start_vert_index(),
442 sub.map_uv(make_float2(0.0f, 0.0f)),
443 sub.map_uv(make_float2(1.0f, 0.0f)),
444 sub.map_uv(make_float2(0.0f, 1.0f)));
445 assert(triangle_index == sub.triangles_offset + sub.calc_num_triangles());
446 return;
447 }
448 if (M == 2) {
449 /* Edges have 2 segments or less. */
450 int num_split = 0;
451 int split_0 = -1;
452 for (int i = 0; i < 3; i++) {
453 if (sub.edges[i].edge->T == 2) {
454 num_split++;
455 if (split_0 == -1) {
456 split_0 = i;
457 }
458 }
459 }
460 /* When two edges have 2 segments, we assume split_0 is the first of two consecutive edges. */
461 if (split_0 == 0 && sub.edges[2].edge->T == 2) {
462 split_0 = 2;
463 }
464
465 const int split_1 = (split_0 + 1) % 3;
466 const int split_2 = (split_0 + 2) % 3;
467
468 const int v[3] = {sub.edges[0].start_vert_index(),
469 sub.edges[1].start_vert_index(),
470 sub.edges[2].start_vert_index()};
471 const int mid_v[3] = {sub.get_vert_along_edge(0, 1),
472 sub.get_vert_along_edge(1, 1),
473 sub.get_vert_along_edge(2, 1)};
474 const float2 uv[3] = {sub.map_uv(make_float2(0.0f, 0.0f)),
475 sub.map_uv(make_float2(1.0f, 0.0f)),
476 sub.map_uv(make_float2(0.0f, 1.0f))};
477 const float2 mid_uv[3] = {sub.map_uv(make_float2(0.5f, 0.0f)),
478 sub.map_uv(make_float2(0.5f, 0.5f)),
479 sub.map_uv(make_float2(0.0f, 0.5f))};
480
481 if (num_split == 3) {
482 /* All edges have two segments
483 * /\
484 * /--\
485 * / \/ \
486 * ------- */
487 set_triangle(sub, triangle_index++, v[0], mid_v[0], mid_v[2], uv[0], mid_uv[0], mid_uv[2]);
488 set_triangle(sub, triangle_index++, v[1], mid_v[1], mid_v[0], uv[1], mid_uv[1], mid_uv[0]);
489 set_triangle(sub, triangle_index++, v[2], mid_v[2], mid_v[1], uv[2], mid_uv[2], mid_uv[1]);
491 sub, triangle_index++, mid_v[0], mid_v[1], mid_v[2], mid_uv[0], mid_uv[1], mid_uv[2]);
492 }
493 else {
494 /* One edge has two segments.
495 * / \
496 * / | \
497 * / | \
498 * ------- */
499 set_triangle(sub,
500 triangle_index++,
501 v[split_0],
502 mid_v[split_0],
503 v[split_2],
504 uv[split_0],
505 mid_uv[split_0],
506 uv[split_2]);
507 if (num_split == 1) {
508 set_triangle(sub,
509 triangle_index++,
510 mid_v[split_0],
511 v[split_1],
512 v[split_2],
513 mid_uv[split_0],
514 uv[split_1],
515 uv[split_2]);
516 }
517 else {
518 /* Two edges have two segments.
519 * /|\
520 * / | \
521 * / |/ \
522 * ------- */
523 set_triangle(sub,
524 triangle_index++,
525 mid_v[split_0],
526 v[split_1],
527 mid_v[split_1],
528 mid_uv[split_0],
529 uv[split_1],
530 mid_uv[split_1]);
531 set_triangle(sub,
532 triangle_index++,
533 mid_v[split_0],
534 mid_v[split_1],
535 v[split_2],
536 mid_uv[split_0],
537 mid_uv[split_1],
538 uv[split_2]);
539 }
540 }
541 assert(triangle_index == sub.triangles_offset + sub.calc_num_triangles());
542 return;
543 }
544
545 const int inner_M = M - 2;
546
547 for (int j = 0; j < inner_M; j++) {
548 for (int i = 0; i < j + 1; i++) {
549 const int i_next = i + 1;
550 const int j_next = j + 1;
551
552 const float2 inner_uv = make_float2(d, d);
553
554 const int v0 = sub.get_inner_grid_vert_triangle(i, j);
555 const int v1 = sub.get_inner_grid_vert_triangle(i_next, j_next);
556 const int v2 = sub.get_inner_grid_vert_triangle(i, j_next);
557
558 const float2 uv0 = sub.map_uv(inner_uv + make_float2(i, j - i) * d);
559 const float2 uv1 = sub.map_uv(inner_uv + make_float2(i_next, j - i) * d);
560 const float2 uv2 = sub.map_uv(inner_uv + make_float2(i, j_next - i) * d);
561
562 set_vertex(sub, v0, uv0);
563 if (j == inner_M - 1) {
564 set_vertex(sub, v1, uv1);
565 set_vertex(sub, v2, uv2);
566 }
567
568 set_triangle(sub, triangle_index++, v0, v1, v2, uv0, uv1, uv2);
569
570 if (i < j) {
571 const int v3 = sub.get_inner_grid_vert_triangle(i_next, j);
572 const float2 uv3 = sub.map_uv(inner_uv + make_float2(i_next, j - i_next) * d);
573
574 set_vertex(sub, v3, uv3);
575
576 set_triangle(sub, triangle_index++, v0, v3, v1, uv0, uv3, uv1);
577 }
578 }
579 }
580
581 assert(triangle_index == sub.triangles_offset + inner_M * inner_M);
582
583 /* Stitch inner grid to edges. */
584 for (int edge = 0; edge < 3; edge++) {
585 const int outer_T = sub.edges[edge].edge->T;
586 const int inner_T = inner_M;
587
588 float2 inner_uv, outer_uv, inner_uv_step, outer_uv_step;
589 switch (edge) {
590 case 0:
591 inner_uv = make_float2(d, d);
592 outer_uv = make_float2(0.0f, 0.0f);
593 inner_uv_step = make_float2(d, 0.0f);
594 outer_uv_step = make_float2(1.0f / (float)outer_T, 0.0f);
595 break;
596 case 1:
597 inner_uv = make_float2(1.0f - 2.0f * d, d);
598 outer_uv = make_float2(1.0f, 0.0f);
599 inner_uv_step = make_float2(-d, d);
600 outer_uv_step = make_float2(-1.0f / (float)outer_T, 1.0f / (float)outer_T);
601 break;
602 case 2:
603 default:
604 inner_uv = make_float2(d, 1.0f - 2.0f * d);
605 outer_uv = make_float2(0.0f, 1.0f);
606 inner_uv_step = make_float2(0.0f, -d);
607 outer_uv_step = make_float2(0.0f, -1.0f / (float)outer_T);
608 break;
609 }
610
611 /* Stitch together two arrays of verts with triangles. At each step, we compare using
612 * the next verts on both sides, to find the split direction with the smallest
613 * diagonal, and use that in order to keep the triangle shape reasonable. */
614 for (size_t i = 0, j = 0; i < inner_T || j < outer_T;) {
615 const int v0 = sub.get_vert_along_grid_edge(edge, i);
616 const int v1 = sub.get_vert_along_edge(edge, j);
617 int v2;
618
619 const float2 uv0 = sub.map_uv(inner_uv);
620 const float2 uv1 = sub.map_uv(outer_uv);
621 float2 uv2;
622
623 if (j == outer_T) {
624 v2 = sub.get_vert_along_grid_edge(edge, ++i);
625 inner_uv += inner_uv_step;
626 uv2 = sub.map_uv(inner_uv);
627 }
628 else if (i == inner_T) {
629 v2 = sub.get_vert_along_edge(edge, ++j);
630 outer_uv += outer_uv_step;
631 uv2 = sub.map_uv(outer_uv);
632 }
633 else {
634 /* Length of diagonals. */
635 const int v2_a = sub.get_vert_along_edge(edge, j + 1);
636 const int v2_b = sub.get_vert_along_grid_edge(edge, i + 1);
637
638 const float len_a = len_squared(mesh_P[v0] - mesh_P[v2_a]);
639 const float len_b = len_squared(mesh_P[v1] - mesh_P[v2_b]);
640
641 /* Use smallest diagonal. */
642 if (len_a < len_b) {
643 v2 = v2_a;
644 outer_uv += outer_uv_step;
645 uv2 = sub.map_uv(outer_uv);
646 j++;
647 }
648 else {
649 v2 = v2_b;
650 inner_uv += inner_uv_step;
651 uv2 = sub.map_uv(inner_uv);
652 i++;
653 }
654 }
655
656 set_triangle(sub, triangle_index++, v0, v1, v2, uv0, uv1, uv2);
657 }
658 }
659
660 assert(triangle_index == sub.triangles_offset + sub.calc_num_triangles());
661}
662
664{
665 const size_t num_subpatches = split.get_num_subpatches();
666
667 /* Vertex coordinates for sides. Needs to be done first because tessellation depends
668 * on these coordinates and they are unique assigned to a subpatch for determinism. */
669 parallel_for(blocked_range<size_t>(0, num_subpatches, 8), [&](const blocked_range<size_t> &r) {
670 for (size_t i = r.begin(); i != r.end(); i++) {
671 const SubPatch &subpatch = split.get_subpatch(i);
672 if (subpatch.shape == SubPatch::TRIANGLE) {
673 tri_set_sides(subpatch);
674 }
675 else {
676 quad_set_sides(subpatch);
677 }
678 }
679 });
680
681 /* Inner vertex coordinates and triangles. */
682 parallel_for(blocked_range<size_t>(0, num_subpatches, 8), [&](const blocked_range<size_t> &r) {
683 for (size_t i = r.begin(); i != r.end(); i++) {
684 const SubPatch &subpatch = split.get_subpatch(i);
685 if (subpatch.shape == SubPatch::TRIANGLE) {
686 tri_dice(subpatch);
687 }
688 else {
689 quad_dice(subpatch);
690 }
691 }
692 });
693}
694
#define D
static void split(const char *text, const char *seps, char ***str, int *count)
#define A2
Definition RandGen.cpp:28
#define A1
Definition RandGen.cpp:27
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
Attribute * add(ustring name, const TypeDesc type, AttributeElement element)
void tri_set_sides(const SubPatch &sub)
Definition dice.cpp:397
void set_vertex(const SubPatch &sub, const int index, const float2 uv)
Definition dice.cpp:96
void quad_dice(const SubPatch &sub)
Definition dice.cpp:370
void add_triangle_strip(const SubPatch &sub, const int left_edge, const int right_edge)
Definition dice.cpp:265
float3 * mesh_N
Definition dice.h:47
float quad_area(const float3 &a, const float3 &b, const float3 &c, const float3 &d)
Definition dice.cpp:59
bool * mesh_smooth
Definition dice.h:45
int * mesh_triangles
Definition dice.h:43
float2 * mesh_ptex_uv
Definition dice.h:49
float * mesh_ptex_face_id
Definition dice.h:48
int * mesh_shader
Definition dice.h:44
float3 eval_projected(const SubPatch &sub, const float2 uv)
Definition dice.cpp:47
float scale_factor(const SubPatch &sub, const int Mu, const int Mv)
Definition dice.cpp:64
void tri_dice(const SubPatch &sub)
Definition dice.cpp:428
SubdAttributeInterpolation & interpolation
Definition dice.h:42
void add_grid_triangles_and_stitch(const SubPatch &sub, const int Mu, const int Mv)
Definition dice.cpp:148
EdgeDice(const SubdParams &params, const int num_verts, const int num_triangles, SubdAttributeInterpolation &interpolation)
Definition dice.cpp:17
void quad_set_sides(const SubPatch &sub)
Definition dice.cpp:336
void set_triangle(const SubPatch &sub, const int triangle_index, const int v0, const int v1, const int v2, const float2 uv0, const float2 uv1, const float2 uv2)
Definition dice.cpp:113
float3 * mesh_P
Definition dice.h:46
SubdParams params
Definition dice.h:41
void dice(const DiagSplit &split)
Definition dice.cpp:663
AttributeSet attributes
Definition patch.h:12
virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, const float u, float v) const =0
int shader
Definition patch.h:21
bool smooth
Definition patch.h:22
int patch_index
Definition patch.h:20
int get_inner_grid_vert_triangle(int i, int j) const
Definition subpatch.h:234
enum SubPatch::@271217051357320143155373165321151177022113114126 shape
int get_vert_along_edge_reverse(const int edge, const int n) const
Definition subpatch.h:229
int get_vert_along_edge(const int edge, const int n) const
Definition subpatch.h:224
int inner_grid_vert_offset
Definition subpatch.h:101
@ TRIANGLE
Definition subpatch.h:99
int calc_num_triangles() const
Definition subpatch.h:189
const Patch * patch
Definition subpatch.h:94
int face_index
Definition subpatch.h:96
int get_vert_along_grid_edge(const int edge, const int n) const
Definition subpatch.h:242
Edge edges[4]
Definition subpatch.h:165
float2 map_uv(float2 uv) const
Definition subpatch.h:295
int corner
Definition subpatch.h:97
int triangles_offset
Definition subpatch.h:103
nullptr float
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float3 transform_perspective(const ccl_private ProjectionTransform *t, const float3 a)
#define CCL_NAMESPACE_END
static float verts[][3]
#define assert(assertion)
@ ATTR_STD_VERTEX_NORMAL
ccl_device_inline float len_squared(const float2 a)
ccl_device_inline float triangle_area(const ccl_private float3 &v1, const ccl_private float3 &v2, const ccl_private float3 &v3)
#define M
#define N
#define sqrtf
#define make_float2
#define ceilf
float3 * data_float3()
void resize_mesh(const int numverts, const int numtris)
int T
Definition subpatch.h:36
int start_vert_index() const
Definition subpatch.h:119
SubEdge * edge
Definition subpatch.h:107
std::function< void(const int, const int, const int, const int *, const float2 *, const int)> interp
float x
float y
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251