Blender  V2.93
subd_split.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "render/camera.h"
18 #include "render/mesh.h"
19 
20 #include "subd/subd_dice.h"
21 #include "subd/subd_patch.h"
22 #include "subd/subd_split.h"
23 
24 #include "util/util_algorithm.h"
25 #include "util/util_foreach.h"
26 #include "util/util_hash.h"
27 #include "util/util_math.h"
28 #include "util/util_types.h"
29 
31 
32 /* DiagSplit */
33 
34 #define DSPLIT_NON_UNIFORM -1
35 #define STITCH_NGON_CENTER_VERT_INDEX_OFFSET 0x60000000
36 #define STITCH_NGON_SPLIT_EDGE_CENTER_VERT_TAG (0x60000000 - 1)
37 
38 DiagSplit::DiagSplit(const SubdParams &params_) : params(params_)
39 {
40 }
41 
42 float3 DiagSplit::to_world(Patch *patch, float2 uv)
43 {
44  float3 P;
45 
46  patch->eval(&P, NULL, NULL, NULL, uv.x, uv.y);
47  if (params.camera)
48  P = transform_point(&params.objecttoworld, P);
49 
50  return P;
51 }
52 
53 static void order_float2(float2 &a, float2 &b)
54 {
55  if (b.x < a.x || b.y < a.y) {
56  swap(a, b);
57  }
58 }
59 
60 int DiagSplit::T(Patch *patch, float2 Pstart, float2 Pend, bool recursive_resolve)
61 {
62  order_float2(Pstart, Pend); /* May not be necessary, but better to be safe. */
63 
64  float Lsum = 0.0f;
65  float Lmax = 0.0f;
66 
67  float3 Plast = to_world(patch, Pstart);
68 
69  for (int i = 1; i < params.test_steps; i++) {
70  float t = i / (float)(params.test_steps - 1);
71 
72  float3 P = to_world(patch, Pstart + t * (Pend - Pstart));
73 
74  float L;
75 
76  if (!params.camera) {
77  L = len(P - Plast);
78  }
79  else {
80  Camera *cam = params.camera;
81 
82  float pixel_width = cam->world_to_raster_size((P + Plast) * 0.5f);
83  L = len(P - Plast) / pixel_width;
84  }
85 
86  Lsum += L;
87  Lmax = max(L, Lmax);
88 
89  Plast = P;
90  }
91 
92  int tmin = (int)ceilf(Lsum / params.dicing_rate);
93  int tmax = (int)ceilf((params.test_steps - 1) * Lmax /
94  params.dicing_rate); // XXX paper says N instead of N-1, seems wrong?
95  int res = max(tmax, 1);
96 
97  if (tmax - tmin > params.split_threshold) {
98  if (!recursive_resolve) {
99  res = DSPLIT_NON_UNIFORM;
100  }
101  else {
102  float2 P = (Pstart + Pend) * 0.5f;
103  res = T(patch, Pstart, P, true) + T(patch, P, Pend, true);
104  }
105  }
106 
107  limit_edge_factor(res, patch, Pstart, Pend);
108  return res;
109 }
110 
111 void DiagSplit::partition_edge(
112  Patch *patch, float2 *P, int *t0, int *t1, float2 Pstart, float2 Pend, int t)
113 {
114  if (t == DSPLIT_NON_UNIFORM) {
115  *P = (Pstart + Pend) * 0.5f;
116  *t0 = T(patch, Pstart, *P);
117  *t1 = T(patch, *P, Pend);
118  }
119  else {
120  assert(t >= 2); /* Need at least two segments to partition into. */
121 
122  int I = (int)floorf((float)t * 0.5f);
123  *P = interp(Pstart, Pend, I / (float)t);
124  *t0 = I;
125  *t1 = t - I;
126  }
127 }
128 
129 void DiagSplit::limit_edge_factor(int &T, Patch *patch, float2 Pstart, float2 Pend)
130 {
131  int max_t = 1 << params.max_level;
132  int max_t_for_edge = int(max_t * len(Pstart - Pend));
133 
134  if (patch->from_ngon) {
135  max_t_for_edge >>= 1; /* Initial split of ngon causes edges to extend half the distance. */
136  }
137 
138  T = (max_t_for_edge <= 1) ? 1 : min(T, max_t_for_edge);
139 
140  assert(T >= 1 || T == DSPLIT_NON_UNIFORM);
141 }
142 
143 void DiagSplit::resolve_edge_factors(Subpatch &sub)
144 {
145  /* Resolve DSPLIT_NON_UNIFORM to actual T value if splitting is no longer possible. */
146  if (sub.edge_u0.T == 1 && sub.edge_u1.T == DSPLIT_NON_UNIFORM) {
147  sub.edge_u1.T = T(sub.patch, sub.c01, sub.c11, true);
148  }
149  if (sub.edge_u1.T == 1 && sub.edge_u0.T == DSPLIT_NON_UNIFORM) {
150  sub.edge_u0.T = T(sub.patch, sub.c00, sub.c10, true);
151  }
152  if (sub.edge_v0.T == 1 && sub.edge_v1.T == DSPLIT_NON_UNIFORM) {
153  sub.edge_v1.T = T(sub.patch, sub.c11, sub.c10, true);
154  }
155  if (sub.edge_v1.T == 1 && sub.edge_v0.T == DSPLIT_NON_UNIFORM) {
156  sub.edge_v0.T = T(sub.patch, sub.c01, sub.c00, true);
157  }
158 }
159 
160 void DiagSplit::split(Subpatch &sub, int depth)
161 {
162  if (depth > 32) {
163  /* We should never get here, but just in case end recursion safely. */
164  assert(!"diagsplit recursion limit reached");
165 
166  sub.edge_u0.T = 1;
167  sub.edge_u1.T = 1;
168  sub.edge_v0.T = 1;
169  sub.edge_v1.T = 1;
170 
171  subpatches.push_back(sub);
172  return;
173  }
174 
175  bool split_u = (sub.edge_u0.T == DSPLIT_NON_UNIFORM || sub.edge_u1.T == DSPLIT_NON_UNIFORM);
176  bool split_v = (sub.edge_v0.T == DSPLIT_NON_UNIFORM || sub.edge_v1.T == DSPLIT_NON_UNIFORM);
177 
178  /* Split subpatches such that the ratio of T for opposite edges doesn't
179  * exceed 1.5, this reduces over tessellation for some patches
180  */
181  /* clang-format off */
182  if (min(sub.edge_u0.T, sub.edge_u1.T) > 8 && /* Must be uniform and preferably greater than 8 to split. */
183  min(sub.edge_v0.T, sub.edge_v1.T) >= 2 && /* Must be uniform and at least 2 to split. */
184  max(sub.edge_u0.T, sub.edge_u1.T) / min(sub.edge_u0.T, sub.edge_u1.T) > 1.5f)
185  {
186  split_v = true;
187  }
188  if (min(sub.edge_v0.T, sub.edge_v1.T) > 8 &&
189  min(sub.edge_u0.T, sub.edge_u1.T) >= 2 &&
190  max(sub.edge_v0.T, sub.edge_v1.T) / min(sub.edge_v0.T, sub.edge_v1.T) > 1.5f)
191  {
192  split_u = true;
193  }
194  /* clang-format on */
195 
196  /* Alternate axis. */
197  if (split_u && split_v) {
198  split_u = depth % 2;
199  }
200 
201  if (!split_u && !split_v) {
202  /* Add the unsplit subpatch. */
203  subpatches.push_back(sub);
204  Subpatch &subpatch = subpatches[subpatches.size() - 1];
205 
206  /* Update T values and offsets. */
207  for (int i = 0; i < 4; i++) {
208  Subpatch::edge_t &edge = subpatch.edges[i];
209 
210  edge.offset = edge.edge->T;
211  edge.edge->T += edge.T;
212  }
213  }
214  else {
215  /* Copy into new subpatches. */
216  Subpatch sub_a = sub;
217  Subpatch sub_b = sub;
218 
219  /* Pointers to various subpatch elements. */
220  Subpatch::edge_t *sub_across_0, *sub_across_1;
221  Subpatch::edge_t *sub_a_across_0, *sub_a_across_1;
222  Subpatch::edge_t *sub_b_across_0, *sub_b_across_1;
223 
224  Subpatch::edge_t *sub_a_split, *sub_b_split;
225 
226  float2 *Pa, *Pb, *Pc, *Pd;
227 
228  /* Set pointers based on split axis. */
229  if (split_u) {
230  sub_across_0 = &sub.edge_u0;
231  sub_across_1 = &sub.edge_u1;
232  sub_a_across_0 = &sub_a.edge_u0;
233  sub_a_across_1 = &sub_a.edge_u1;
234  sub_b_across_0 = &sub_b.edge_u0;
235  sub_b_across_1 = &sub_b.edge_u1;
236 
237  sub_a_split = &sub_a.edge_v1;
238  sub_b_split = &sub_b.edge_v0;
239 
240  Pa = &sub_a.c11;
241  Pb = &sub_a.c10;
242  Pc = &sub_b.c01;
243  Pd = &sub_b.c00;
244  }
245  else {
246  sub_across_0 = &sub.edge_v0;
247  sub_across_1 = &sub.edge_v1;
248  sub_a_across_0 = &sub_a.edge_v0;
249  sub_a_across_1 = &sub_a.edge_v1;
250  sub_b_across_0 = &sub_b.edge_v0;
251  sub_b_across_1 = &sub_b.edge_v1;
252 
253  sub_a_split = &sub_a.edge_u0;
254  sub_b_split = &sub_b.edge_u1;
255 
256  Pa = &sub_a.c10;
257  Pb = &sub_a.c00;
258  Pc = &sub_b.c11;
259  Pd = &sub_b.c01;
260  }
261 
262  /* Partition edges */
263  float2 P0, P1;
264 
265  partition_edge(
266  sub.patch, &P0, &sub_a_across_0->T, &sub_b_across_0->T, *Pd, *Pb, sub_across_0->T);
267  partition_edge(
268  sub.patch, &P1, &sub_a_across_1->T, &sub_b_across_1->T, *Pc, *Pa, sub_across_1->T);
269 
270  /* Split */
271  *Pa = P1;
272  *Pb = P0;
273 
274  *Pc = P1;
275  *Pd = P0;
276 
277  int tsplit = T(sub.patch, P0, P1);
278 
279  if (depth == -2 && tsplit == 1) {
280  tsplit = 2; /* Ensure we can always split at depth -1. */
281  }
282 
283  sub_a_split->T = tsplit;
284  sub_b_split->T = tsplit;
285 
286  resolve_edge_factors(sub_a);
287  resolve_edge_factors(sub_b);
288 
289  /* Create new edge */
290  Edge &edge = *alloc_edge();
291 
292  sub_a_split->edge = &edge;
293  sub_b_split->edge = &edge;
294 
295  sub_a_split->offset = 0;
296  sub_b_split->offset = 0;
297 
298  sub_a_split->indices_decrease_along_edge = false;
299  sub_b_split->indices_decrease_along_edge = true;
300 
301  sub_a_split->sub_edges_created_in_reverse_order = !split_u;
302  sub_b_split->sub_edges_created_in_reverse_order = !split_u;
303 
306 
307  /* Recurse */
308  edge.T = 0;
309  split(sub_a, depth + 1);
310 
311  int edge_t = edge.T;
312  (void)edge_t;
313 
314  edge.top_offset = sub_across_1->edge->T;
315  edge.bottom_offset = sub_across_0->edge->T;
316 
317  edge.T = 0; /* We calculate T twice along each edge. :/ */
318  split(sub_b, depth + 1);
319 
320  assert(edge.T == edge_t); /* If this fails we will crash at some later point! */
321 
322  edge.top = sub_across_1->edge;
323  edge.bottom = sub_across_0->edge;
324  }
325 }
326 
327 int DiagSplit::alloc_verts(int n)
328 {
329  int a = num_alloced_verts;
330  num_alloced_verts += n;
331  return a;
332 }
333 
335 {
336  edges.emplace_back();
337  return &edges.back();
338 }
339 
340 void DiagSplit::split_patches(Patch *patches, size_t patches_byte_stride)
341 {
342  int patch_index = 0;
343 
344  for (int f = 0; f < params.mesh->get_num_subd_faces(); f++) {
345  Mesh::SubdFace face = params.mesh->get_subd_face(f);
346 
347  Patch *patch = (Patch *)(((char *)patches) + patch_index * patches_byte_stride);
348 
349  if (face.is_quad()) {
350  patch_index++;
351 
352  split_quad(face, patch);
353  }
354  else {
355  patch_index += face.num_corners;
356 
357  split_ngon(face, patch, patches_byte_stride);
358  }
359  }
360 
361  params.mesh->vert_to_stitching_key_map.clear();
362  params.mesh->vert_stitching_map.clear();
363 
364  post_split();
365 }
366 
368  const Mesh *mesh,
369  const Mesh::SubdFace &face,
370  int corner,
371  bool &reversed,
372  int v0,
373  int v1)
374 {
375  int a = mesh->get_subd_face_corners()[face.start_corner + mod(corner + 0, face.num_corners)];
376  int b = mesh->get_subd_face_corners()[face.start_corner + mod(corner + 1, face.num_corners)];
377 
378  reversed = !(b < a);
379 
380  if (b < a) {
381  swap(a, b);
382  swap(v0, v1);
383  }
384 
385  Edge *edge = split->alloc_edge();
386 
387  edge->is_stitch_edge = true;
388  edge->stitch_start_vert_index = a;
389  edge->stitch_end_vert_index = b;
390 
391  edge->start_vert_index = v0;
392  edge->end_vert_index = v1;
393 
394  edge->stitch_edge_key = {a, b};
395 
396  return edge;
397 }
398 
399 void DiagSplit::split_quad(const Mesh::SubdFace &face, Patch *patch)
400 {
401  Subpatch subpatch(patch);
402 
403  int v = alloc_verts(4);
404 
405  bool v0_reversed, u1_reversed, v1_reversed, u0_reversed;
407  this, params.mesh, face, 3, v0_reversed, v + 3, v + 0);
409  this, params.mesh, face, 2, u1_reversed, v + 2, v + 3);
411  this, params.mesh, face, 1, v1_reversed, v + 1, v + 2);
413  this, params.mesh, face, 0, u0_reversed, v + 0, v + 1);
414 
415  subpatch.edge_v0.sub_edges_created_in_reverse_order = !v0_reversed;
416  subpatch.edge_u1.sub_edges_created_in_reverse_order = u1_reversed;
417  subpatch.edge_v1.sub_edges_created_in_reverse_order = v1_reversed;
418  subpatch.edge_u0.sub_edges_created_in_reverse_order = !u0_reversed;
419 
420  subpatch.edge_v0.indices_decrease_along_edge = v0_reversed;
421  subpatch.edge_u1.indices_decrease_along_edge = u1_reversed;
422  subpatch.edge_v1.indices_decrease_along_edge = v1_reversed;
423  subpatch.edge_u0.indices_decrease_along_edge = u0_reversed;
424 
425  /* Forces a split in both axis for quads, needed to match split of ngons into quads. */
426  subpatch.edge_u0.T = DSPLIT_NON_UNIFORM;
427  subpatch.edge_u1.T = DSPLIT_NON_UNIFORM;
428  subpatch.edge_v0.T = DSPLIT_NON_UNIFORM;
429  subpatch.edge_v1.T = DSPLIT_NON_UNIFORM;
430 
431  split(subpatch, -2);
432 }
433 
435  const Mesh *mesh,
436  const Mesh::SubdFace &face,
437  int corner,
438  int side,
439  bool &reversed,
440  int v0,
441  int v1,
442  int vc)
443 {
444  Edge *edge = split->alloc_edge();
445 
446  int a = mesh->get_subd_face_corners()[face.start_corner + mod(corner + 0, face.num_corners)];
447  int b = mesh->get_subd_face_corners()[face.start_corner + mod(corner + 1, face.num_corners)];
448 
449  if (b < a) {
450  edge->stitch_edge_key = {b, a};
451  }
452  else {
453  edge->stitch_edge_key = {a, b};
454  }
455 
456  reversed = !(b < a);
457 
458  if (side == 0) {
459  a = vc;
460  }
461  else {
462  b = vc;
463  }
464 
465  if (!reversed) {
466  swap(a, b);
467  swap(v0, v1);
468  }
469 
470  edge->is_stitch_edge = true;
471  edge->stitch_start_vert_index = a;
472  edge->stitch_end_vert_index = b;
473 
474  edge->start_vert_index = v0;
475  edge->end_vert_index = v1;
476 
477  return edge;
478 }
479 
480 void DiagSplit::split_ngon(const Mesh::SubdFace &face, Patch *patches, size_t patches_byte_stride)
481 {
482  Edge *prev_edge_u0 = nullptr;
483  Edge *first_edge_v0 = nullptr;
484 
485  for (int corner = 0; corner < face.num_corners; corner++) {
486  Patch *patch = (Patch *)(((char *)patches) + corner * patches_byte_stride);
487 
488  Subpatch subpatch(patch);
489 
490  int v = alloc_verts(4);
491 
492  /* Setup edges. */
493  Edge *edge_u1 = alloc_edge();
494  Edge *edge_v1 = alloc_edge();
495 
496  edge_v1->is_stitch_edge = true;
497  edge_u1->is_stitch_edge = true;
498 
499  edge_u1->stitch_start_vert_index = -(face.start_corner + mod(corner + 0, face.num_corners)) -
500  1;
502 
503  edge_u1->start_vert_index = v + 3;
504  edge_u1->end_vert_index = v + 2;
505 
506  edge_u1->stitch_edge_key = {edge_u1->stitch_start_vert_index, edge_u1->stitch_end_vert_index};
507 
508  edge_v1->stitch_start_vert_index = -(face.start_corner + mod(corner + 1, face.num_corners)) -
509  1;
511 
512  edge_v1->start_vert_index = v + 1;
513  edge_v1->end_vert_index = v + 2;
514 
515  edge_v1->stitch_edge_key = {edge_v1->stitch_start_vert_index, edge_v1->stitch_end_vert_index};
516 
517  bool v0_reversed, u0_reversed;
518 
520  params.mesh,
521  face,
522  corner - 1,
523  0,
524  v0_reversed,
525  v + 3,
526  v + 0,
528 
529  subpatch.edge_u1.edge = edge_u1;
530  subpatch.edge_v1.edge = edge_v1;
531 
533  params.mesh,
534  face,
535  corner + 0,
536  1,
537  u0_reversed,
538  v + 0,
539  v + 1,
541 
542  subpatch.edge_v0.sub_edges_created_in_reverse_order = !v0_reversed;
545  subpatch.edge_u0.sub_edges_created_in_reverse_order = !u0_reversed;
546 
547  subpatch.edge_v0.indices_decrease_along_edge = v0_reversed;
548  subpatch.edge_u1.indices_decrease_along_edge = false;
549  subpatch.edge_v1.indices_decrease_along_edge = true;
550  subpatch.edge_u0.indices_decrease_along_edge = u0_reversed;
551 
552  /* Perform split. */
553  {
554  subpatch.edge_u0.T = T(subpatch.patch, subpatch.c00, subpatch.c10);
555  subpatch.edge_u1.T = T(subpatch.patch, subpatch.c01, subpatch.c11);
556  subpatch.edge_v0.T = T(subpatch.patch, subpatch.c00, subpatch.c01);
557  subpatch.edge_v1.T = T(subpatch.patch, subpatch.c10, subpatch.c11);
558 
559  resolve_edge_factors(subpatch);
560 
561  split(subpatch, 0);
562  }
563 
564  /* Update offsets after T is known from split. */
565  edge_u1->top = subpatch.edge_v0.edge;
566  edge_u1->stitch_top_offset = edge_u1->top->T * (v0_reversed ? -1 : 1);
567  edge_v1->top = subpatch.edge_u0.edge;
568  edge_v1->stitch_top_offset = edge_v1->top->T * (!u0_reversed ? -1 : 1);
569 
570  if (corner == 0) {
571  first_edge_v0 = subpatch.edge_v0.edge;
572  }
573 
574  if (prev_edge_u0) {
575  if (v0_reversed) {
576  subpatch.edge_v0.edge->stitch_offset = prev_edge_u0->T;
577  }
578  else {
579  prev_edge_u0->stitch_offset = subpatch.edge_v0.edge->T;
580  }
581 
582  int T = subpatch.edge_v0.edge->T + prev_edge_u0->T;
583  subpatch.edge_v0.edge->stitch_edge_T = T;
584  prev_edge_u0->stitch_edge_T = T;
585  }
586 
587  if (corner == face.num_corners - 1) {
588  if (v0_reversed) {
589  subpatch.edge_u0.edge->stitch_offset = first_edge_v0->T;
590  }
591  else {
592  first_edge_v0->stitch_offset = subpatch.edge_u0.edge->T;
593  }
594 
595  int T = first_edge_v0->T + subpatch.edge_u0.edge->T;
596  first_edge_v0->stitch_edge_T = T;
597  subpatch.edge_u0.edge->stitch_edge_T = T;
598  }
599 
600  prev_edge_u0 = subpatch.edge_u0.edge;
601  }
602 }
603 
605 {
606  int num_stitch_verts = 0;
607 
608  /* All patches are now split, and all T values known. */
609 
610  foreach (Edge &edge, edges) {
611  if (edge.second_vert_index < 0) {
612  edge.second_vert_index = alloc_verts(edge.T - 1);
613  }
614 
615  if (edge.is_stitch_edge) {
616  num_stitch_verts = max(num_stitch_verts,
618  }
619  }
620 
621  num_stitch_verts += 1;
622 
623  /* Map of edge key to edge stitching vert offset. */
624  struct pair_hasher {
625  size_t operator()(const pair<int, int> &k) const
626  {
627  return hash_uint2(k.first, k.second);
628  }
629  };
630  typedef unordered_map<pair<int, int>, int, pair_hasher> edge_stitch_verts_map_t;
631  edge_stitch_verts_map_t edge_stitch_verts_map;
632 
633  foreach (Edge &edge, edges) {
634  if (edge.is_stitch_edge) {
635  if (edge.stitch_edge_T == 0) {
636  edge.stitch_edge_T = edge.T;
637  }
638 
639  if (edge_stitch_verts_map.find(edge.stitch_edge_key) == edge_stitch_verts_map.end()) {
640  edge_stitch_verts_map[edge.stitch_edge_key] = num_stitch_verts;
641  num_stitch_verts += edge.stitch_edge_T - 1;
642  }
643  }
644  }
645 
646  /* Set start and end indices for edges generated from a split. */
647  foreach (Edge &edge, edges) {
648  if (edge.start_vert_index < 0) {
649  /* Fix up offsets. */
650  if (edge.top_indices_decrease) {
651  edge.top_offset = edge.top->T - edge.top_offset;
652  }
653 
655  }
656 
657  if (edge.end_vert_index < 0) {
658  if (edge.bottom_indices_decrease) {
659  edge.bottom_offset = edge.bottom->T - edge.bottom_offset;
660  }
661 
663  }
664  }
665 
666  int vert_offset = params.mesh->verts.size();
667 
668  /* Add verts to stitching map. */
669  foreach (const Edge &edge, edges) {
670  if (edge.is_stitch_edge) {
671  int second_stitch_vert_index = edge_stitch_verts_map[edge.stitch_edge_key];
672 
673  for (int i = 0; i <= edge.T; i++) {
674  /* Get proper stitching key. */
675  int key;
676 
677  if (i == 0) {
678  key = edge.stitch_start_vert_index;
679  }
680  else if (i == edge.T) {
681  key = edge.stitch_end_vert_index;
682  }
683  else {
684  key = second_stitch_vert_index + i - 1 + edge.stitch_offset;
685  }
686 
688  if (i == 0) {
689  key = second_stitch_vert_index - 1 + edge.stitch_offset;
690  }
691  else if (i == edge.T) {
692  key = second_stitch_vert_index - 1 + edge.T;
693  }
694  }
695  else if (key < 0 && edge.top) { /* ngon spoke edge */
696  int s = edge_stitch_verts_map[edge.top->stitch_edge_key];
697  if (edge.stitch_top_offset >= 0) {
698  key = s - 1 + edge.stitch_top_offset;
699  }
700  else {
701  key = s - 1 + edge.top->stitch_edge_T + edge.stitch_top_offset;
702  }
703  }
704 
705  /* Get real vert index. */
706  int vert = edge.get_vert_along_edge(i) + vert_offset;
707 
708  /* Add to map */
709  if (params.mesh->vert_to_stitching_key_map.find(vert) ==
710  params.mesh->vert_to_stitching_key_map.end()) {
711  params.mesh->vert_to_stitching_key_map[vert] = key;
712  params.mesh->vert_stitching_map.insert({key, vert});
713  }
714  }
715  }
716  }
717 
718  /* Dice; TODO(mai): Move this out of split. */
719  QuadDice dice(params);
720 
721  int num_verts = num_alloced_verts;
722  int num_triangles = 0;
723 
724  for (size_t i = 0; i < subpatches.size(); i++) {
725  subpatches[i].inner_grid_vert_offset = num_verts;
726  num_verts += subpatches[i].calc_num_inner_verts();
727  num_triangles += subpatches[i].calc_num_triangles();
728  }
729 
730  dice.reserve(num_verts, num_triangles);
731 
732  for (size_t i = 0; i < subpatches.size(); i++) {
733  Subpatch &sub = subpatches[i];
734 
735  sub.edge_u0.T = max(sub.edge_u0.T, 1);
736  sub.edge_u1.T = max(sub.edge_u1.T, 1);
737  sub.edge_v0.T = max(sub.edge_v0.T, 1);
738  sub.edge_v1.T = max(sub.edge_v1.T, 1);
739 
740  dice.dice(sub);
741  }
742 
743  /* Cleanup */
744  subpatches.clear();
745  edges.clear();
746 }
747 
typedef float(TangentPoint)[2]
void swap(T &a, T &b)
Definition: Common.h:33
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btVector3 operator()(const btVector3 &x) const
Return the transform of the vector.
Definition: btTransform.h:90
void post_split()
Definition: subd_split.cpp:604
void split_patches(Patch *patches, size_t patches_byte_stride)
Definition: subd_split.cpp:340
void split_quad(const Mesh::SubdFace &face, Patch *patch)
Definition: subd_split.cpp:399
void split_ngon(const Mesh::SubdFace &face, Patch *patches, size_t patches_byte_stride)
Definition: subd_split.cpp:480
DiagSplit(const SubdParams &params)
Definition: subd_split.cpp:38
Edge * alloc_edge()
Definition: subd_split.cpp:334
void reserve(int num_verts, int num_triangles)
Definition: subd_dice.cpp:41
bool from_ngon
Definition: subd_patch.h:37
virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)=0
void dice(Subpatch &sub)
Definition: subd_dice.cpp:253
edge_t edges[4]
Definition: subd_subpatch.h:63
float2 c11
Definition: subd_subpatch.h:57
edge_t edge_v1
Definition: subd_subpatch.h:65
edge_t edge_u0
Definition: subd_subpatch.h:65
float2 c01
Definition: subd_subpatch.h:57
class Patch * patch
Definition: subd_subpatch.h:29
edge_t edge_u1
Definition: subd_subpatch.h:65
edge_t edge_v0
Definition: subd_subpatch.h:65
float2 c10
Definition: subd_subpatch.h:57
float2 c00
Definition: subd_subpatch.h:57
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define CCL_NAMESPACE_END
#define ceilf(x)
#define floorf(x)
static float P(float k)
Definition: math_interp.c:41
#define T
#define L
static unsigned a[3]
Definition: RandGen.cpp:92
void split(const std::string &s, const char delim, std::vector< std::string > &tokens)
Definition: abc_util.cc:115
#define I
#define min(a, b)
Definition: sort.c:51
float world_to_raster_size(float3 P)
Definition: camera.cpp:635
int stitch_offset
bool bottom_indices_decrease
int second_vert_index
Edge * bottom
int stitch_end_vert_index
int start_vert_index
int bottom_offset
Edge * top
int stitch_top_offset
pair< int, int > stitch_edge_key
bool is_stitch_edge
bool top_indices_decrease
int get_vert_along_edge(int n) const
int stitch_edge_T
int top_offset
int stitch_start_vert_index
int end_vert_index
int ptex_offset
Definition: mesh.h:103
int start_corner
Definition: mesh.h:99
int num_corners
Definition: mesh.h:100
bool is_quad()
Definition: mesh.h:105
size_t get_num_subd_faces() const
Definition: mesh.h:246
float size[3]
SubdFace get_subd_face(size_t index) const
Definition: mesh.cpp:400
int max_level
Definition: subd_dice.h:43
Mesh * mesh
Definition: subd_dice.h:37
Camera * camera
Definition: subd_dice.h:44
Transform objecttoworld
Definition: subd_dice.h:45
int split_threshold
Definition: subd_dice.h:41
float dicing_rate
Definition: subd_dice.h:42
int test_steps
Definition: subd_dice.h:40
bool sub_edges_created_in_reverse_order
Definition: subd_subpatch.h:37
struct Edge * edge
Definition: subd_subpatch.h:39
bool indices_decrease_along_edge
Definition: subd_subpatch.h:36
#define DSPLIT_NON_UNIFORM
Definition: subd_split.cpp:34
static Edge * create_split_edge_from_corner(DiagSplit *split, const Mesh *mesh, const Mesh::SubdFace &face, int corner, int side, bool &reversed, int v0, int v1, int vc)
Definition: subd_split.cpp:434
#define STITCH_NGON_CENTER_VERT_INDEX_OFFSET
Definition: subd_split.cpp:35
static Edge * create_edge_from_corner(DiagSplit *split, const Mesh *mesh, const Mesh::SubdFace &face, int corner, bool &reversed, int v0, int v1)
Definition: subd_split.cpp:367
static void order_float2(float2 &a, float2 &b)
Definition: subd_split.cpp:53
#define STITCH_NGON_SPLIT_EDGE_CENTER_VERT_TAG
Definition: subd_split.cpp:36
float max
ccl_device_inline uint hash_uint2(uint kx, uint ky)
Definition: util_hash.h:83
ccl_device_inline int mod(int x, int m)
Definition: util_math.h:405
ccl_device_inline float2 interp(const float2 &a, const float2 &b, float t)
ccl_device_inline float3 transform_point(const Transform *t, const float3 a)
uint len