Advertisement
Guest User

SAH kd tree construction CUDA

a guest
Feb 24th, 2020
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 67.65 KB | None | 0 0
  1. #pragma once
  2.  
  3. /* SAH kd-tree construction algorithm implementation
  4.  *
  5.  * Copyright (c) 2019-2020, Anatoliy V. Tomilov
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following condition is met:
  10.  * Redistributions of source code must retain the above copyright notice, this condition and the following disclaimer.
  11.  *
  12.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  13.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  15.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  16.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  17.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  18.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  19.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  20.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  21.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  22.  * POSSIBILITY OF SUCH DAMAGE.
  23.  */
  24.  
  25. #include "sah_kd_tree.h"
  26.  
  27. #include <thrust/tuple.h>
  28. #include <thrust/functional.h>
  29. #include <thrust/advance.h>
  30. #include <thrust/distance.h>
  31. #include <thrust/sequence.h>
  32. #include <thrust/fill.h>
  33. #include <thrust/copy.h>
  34. #include <thrust/partition.h>
  35. #include <thrust/remove.h>
  36. #include <thrust/gather.h>
  37. #include <thrust/scatter.h>
  38. #include <thrust/scan.h>
  39. #include <thrust/transform_scan.h>
  40. #include <thrust/transform.h>
  41. #include <thrust/transform_reduce.h>
  42. #include <thrust/reduce.h>
  43. #include <thrust/extrema.h>
  44. #include <thrust/count.h>
  45. #include <thrust/sort.h>
  46. #include <thrust/unique.h>
  47.  
  48. #include <thrust/iterator/counting_iterator.h>
  49. #include <thrust/iterator/discard_iterator.h>
  50. #include <thrust/iterator/permutation_iterator.h>
  51. #include <thrust/iterator/reverse_iterator.h>
  52. #include <thrust/iterator/transform_iterator.h>
  53. #include <thrust/iterator/transform_output_iterator.h>
  54. #include <thrust/iterator/zip_iterator.h>
  55.  
  56. #include <type_traits>
  57. #include <utility>
  58. #include <limits>
  59. #include <iterator>
  60.  
  61. #include <cassert>
  62.  
  63. //#ifdef DEBUG
  64. #include <thrust/equal.h>
  65. #include <thrust/logical.h>
  66.  
  67. #include <utility>
  68. #include <iostream>
  69. #include <iomanip>
  70. #include <cstdio>
  71. #include <chrono>
  72. #include <string>
  73.  
  74. struct timepoint
  75. {
  76.     std::string prefix = "time delta";
  77.     std::chrono::time_point< std::chrono::system_clock > start = std::chrono::system_clock::now();
  78.  
  79.     void reset()
  80.     {
  81.         start = std::chrono::system_clock::now();
  82.     }
  83.  
  84.     void print(std::string what)
  85.     {
  86.         auto stop = std::chrono::system_clock::now();
  87.         std::cout << prefix << ' ' << what << ' ' << std::chrono::duration_cast< std::chrono::milliseconds >(stop - std::exchange(start, stop)).count() << '\n';
  88.     }
  89. };
  90. //#endif
  91.  
  92. #ifndef __CUDACC_EXTENDED_LAMBDA__
  93. #error "nvcc --expt-extended-lambda"
  94. #endif
  95. #ifndef __CUDACC_RELAXED_CONSTEXPR__
  96. #error "nvcc --expt-relaxed-constexpr"
  97. #endif
  98.  
  99. namespace sah_kd_tree
  100. {
  101.  
  102. template< typename T >
  103. struct add_leaf_const_reference
  104. {
  105.     using type = const T &; // I, U, F
  106. };
  107.  
  108. template< typename T >
  109. using add_leaf_const_reference_t = typename add_leaf_const_reference< T >::type;
  110.  
  111. template<>
  112. struct add_leaf_const_reference< thrust::null_type >
  113. {
  114.     using type = thrust::null_type;
  115. };
  116.  
  117. template< typename ...Ts >
  118. struct add_leaf_const_reference< thrust::tuple< Ts... > >
  119. {
  120.     using type = thrust::tuple< add_leaf_const_reference_t< Ts >... >;
  121. };
  122.  
  123. template< typename iterator >
  124. using input_iterator_value_type = add_leaf_const_reference_t< typename iterator::value_type >;
  125.  
  126. template< typename iterator >
  127. using output_iterator_value_type = typename iterator::value_type;
  128.  
  129. template< typename policy, template< typename ... > class container >
  130. struct builder
  131. {
  132.  
  133.     policy p;
  134.  
  135.     template< I dimension >
  136.     struct projection
  137.     {
  138.  
  139.         policy p;
  140.  
  141.         struct
  142.         {
  143.             container< F > a, b, c;
  144.         } triangle;
  145.  
  146.         struct
  147.         {
  148.             container< F > split_cost;
  149.             container< U > split_event;
  150.             container< F > split_pos;
  151.             struct
  152.             {
  153.                 container< U > l, r;
  154.             } polygon_count;
  155.         } layer;
  156.  
  157.         struct
  158.         {
  159.             container< F > min, max;
  160.         } node;
  161.  
  162.         struct
  163.         {
  164.             container< F > min, max;
  165.         } polygon;
  166.  
  167.         struct
  168.         {
  169.             container< U > node;
  170.             container< F > pos;
  171.             container< I > kind;
  172.             container< U > polygon;
  173.  
  174.             container< U > l, r;
  175.         } event;
  176.  
  177.         template< typename a_iterator, typename b_iterator, typename c_iterator >
  178.         void set_triangle(a_iterator a_begin, a_iterator a_end,
  179.                           b_iterator b_begin, b_iterator b_end,
  180.                           c_iterator c_begin, c_iterator c_end)
  181.         {
  182.             auto triangle_count = U(thrust::distance(a_begin, a_end));
  183.             assert(triangle_count == U(thrust::distance(b_begin, b_end)));
  184.             assert(triangle_count == U(thrust::distance(c_begin, c_end)));
  185.  
  186.             triangle.a.assign(a_begin, a_end);
  187.             triangle.b.assign(b_begin, b_end);
  188.             triangle.c.assign(c_begin, c_end);
  189.         }
  190.  
  191.         void calculate_triangle_bbox()
  192.         {
  193.             auto triangle_count = U(triangle.a.size());
  194.             assert(triangle_count == U(triangle.b.size()));
  195.             assert(triangle_count == U(triangle.c.size()));
  196.  
  197.             std::cout << "triangle_count = " << triangle_count << "\n";
  198.  
  199.             polygon.min.resize(triangle_count);
  200.             polygon.max.resize(triangle_count);
  201.  
  202.             auto triangle_begin = thrust::make_zip_iterator(thrust::make_tuple(triangle.a.cbegin(), triangle.b.cbegin(), triangle.c.cbegin()));
  203.             using triangle_type = input_iterator_value_type< decltype(triangle_begin) >;
  204.             auto polygon_bbox_begin = thrust::make_zip_iterator(thrust::make_tuple(polygon.min.begin(), polygon.max.begin()));
  205.             using polygon_bbox_type = output_iterator_value_type< decltype(polygon_bbox_begin) >;
  206.             auto to_triangle_bbox = [] __host__ __device__ (triangle_type triangle) -> polygon_bbox_type
  207.             {
  208.                 F a = thrust::get< 0 >(triangle);
  209.                 F b = thrust::get< 1 >(triangle);
  210.                 F c = thrust::get< 2 >(triangle);
  211.                 return {thrust::min(a, thrust::min(b, c)), thrust::max(a, thrust::max(b, c))};
  212.             };
  213.             thrust::transform(p, triangle_begin, thrust::next(triangle_begin, triangle_count), polygon_bbox_begin, to_triangle_bbox);
  214.         }
  215.  
  216.         void caluculate_root_node_bbox()
  217.         {
  218.             auto root_bbox_min_begin = thrust::min_element(p, polygon.min.cbegin(), polygon.min.cend());
  219.             node.min.assign(root_bbox_min_begin, thrust::next(root_bbox_min_begin));
  220.  
  221.             auto root_bbox_max_begin = thrust::max_element(p, polygon.max.cbegin(), polygon.max.cend());
  222.             node.max.assign(root_bbox_max_begin, thrust::next(root_bbox_max_begin));
  223.         }
  224.  
  225.         template< typename type >
  226.         struct doubler
  227.         {
  228.             __host__ __device__ auto operator () (type value) -> thrust::tuple< type, type >
  229.             {
  230.                 return {value, value};
  231.             }
  232.         };
  233.  
  234.         void generate_initial_event()
  235.         {
  236.             auto triangle_count = U(triangle.a.size());
  237.  
  238.             auto triangle_bbox_begin = thrust::make_zip_iterator(thrust::make_tuple(polygon.min.cbegin(), polygon.max.cbegin()));
  239.             using bbox_type = input_iterator_value_type< decltype(triangle_bbox_begin) >;
  240.             auto is_planar_event = [] __host__ __device__ (bbox_type bbox) -> bool { return !(thrust::get< 0 >(bbox) < thrust::get< 1 >(bbox)); };
  241.             auto planar_event_count = U(thrust::count_if(p, triangle_bbox_begin, thrust::next(triangle_bbox_begin, triangle_count), is_planar_event));
  242.  
  243.             std::cout << "planar_event_count = " << planar_event_count << "\n";
  244.  
  245.             auto event_count = triangle_count - planar_event_count + triangle_count;
  246.  
  247.             event.pos.resize(event_count);
  248.             event.kind.resize(event_count, I(0));
  249.             event.polygon.resize(event_count);
  250.  
  251.             auto event_kind_lr_begin = thrust::make_zip_iterator(thrust::make_tuple(event.kind.begin(), event.kind.rbegin()));
  252.             auto planar_event_kind = thrust::fill_n(p, event_kind_lr_begin, triangle_count - planar_event_count, thrust::make_tuple< I, I >(+1, -1)); // right event sequenced before left event if positions are equal
  253.             //thrust::fill_n(p, thrust::get< 0 >(planar_event_kind.get_iterator_tuple()), planar_event_count, I(0));
  254.  
  255.             auto triangle_begin = thrust::make_counting_iterator< U >(0);
  256.             auto planar_event_begin = thrust::next(event.polygon.begin(), triangle_count - planar_event_count);
  257.             auto event_pair_begin = thrust::make_zip_iterator(thrust::make_tuple(event.polygon.begin(), event.polygon.rbegin()));
  258.             auto solid_event_begin = thrust::make_transform_output_iterator(event_pair_begin, doubler< U >{});
  259.             thrust::partition_copy(p, triangle_begin, thrust::next(triangle_begin, triangle_count), triangle_bbox_begin, planar_event_begin, solid_event_begin, is_planar_event);
  260.  
  261.             auto event_polygon_bbox_begin = thrust::make_permutation_iterator(triangle_bbox_begin, event.polygon.cbegin());
  262.             auto to_event_pos = [] __host__ __device__ (I event_kind, bbox_type bbox) -> F
  263.             {
  264.                 return (event_kind < 0) ? thrust::get< 1 >(bbox) : thrust::get< 0 >(bbox);
  265.             };
  266.             thrust::transform(p, event.kind.cbegin(), event.kind.cend(), event_polygon_bbox_begin, event.pos.begin(), to_event_pos);
  267.  
  268.             auto event_begin = thrust::make_zip_iterator(thrust::make_tuple(event.pos.begin(), event.kind.begin(), event.polygon.begin()));
  269.             thrust::sort(p, event_begin, thrust::next(event_begin, event_count));
  270.  
  271.             event.node.resize(event_count, U(0));
  272.         }
  273.  
  274.         using Y = projection< (dimension + 1) % 3 >;
  275.         using Z = projection< (dimension + 2) % 3 >;
  276.  
  277.         void find_perfect_split(const params & sah, U node_count, const container< U > & layer_node_offset, const Y & y, const Z & z)
  278.         {
  279.             auto event_count = U(event.kind.size());
  280.  
  281.             { // calculate l and r polygon count
  282.                 event.l.resize(event_count);
  283.                 event.r.resize(event_count);
  284.  
  285.                 auto l_triangle_count_begin = thrust::make_transform_iterator(event.kind.cbegin(), [] __host__ __device__ (I event_kind) -> U { return (event_kind < 0) ? 0 : 1; });
  286.                 thrust::exclusive_scan_by_key(p, event.node.cbegin(), event.node.cend(), l_triangle_count_begin, event.l.begin());
  287.  
  288.                 auto r_triangle_count_begin = thrust::make_transform_iterator(event.kind.crbegin(), [] __host__ __device__ (I event_kind) -> U { return (0 < event_kind) ? 0 : 1; });
  289.                 thrust::exclusive_scan_by_key(p, event.node.crbegin(), event.node.crend(), r_triangle_count_begin, event.r.rbegin());
  290.             }
  291.  
  292.             layer.split_cost.resize(node_count);
  293.             layer.split_event.resize(node_count);
  294.             layer.split_pos.resize(node_count);
  295.  
  296.             layer.polygon_count.l.resize(node_count);
  297.             layer.polygon_count.r.resize(node_count);
  298.  
  299.             auto node_limits_begin = thrust::make_zip_iterator(thrust::make_tuple(node.min.cbegin(), node.max.cbegin(), y.node.min.cbegin(), y.node.max.cbegin(), z.node.min.cbegin(), z.node.max.cbegin()));
  300.             auto node_bbox_begin = thrust::make_permutation_iterator(node_limits_begin, event.node.cbegin());
  301.             auto split_event_begin = thrust::make_counting_iterator< U >(0);
  302.             auto perfect_split_input_begin = thrust::make_zip_iterator(thrust::make_tuple(node_bbox_begin, event.pos.cbegin(), event.kind.cbegin(), split_event_begin, event.l.cbegin(), event.r.cbegin()));
  303.             using perfect_split_input_type = input_iterator_value_type< decltype(perfect_split_input_begin) >;
  304.             auto perfect_split_begin = thrust::make_zip_iterator(thrust::make_tuple(layer.split_cost.begin(), layer.split_event.begin(), layer.split_pos.begin(), layer.polygon_count.l.begin(), layer.polygon_count.r.begin()));
  305.             using perfect_split_type = output_iterator_value_type< decltype(perfect_split_begin) >;
  306.             auto to_split = [sah] __host__ __device__ (perfect_split_input_type perfect_split_value) -> perfect_split_type
  307.             {
  308.                 const auto & node_bbox = thrust::get< 0 >(perfect_split_value);
  309.                 F split_pos = thrust::get< 1 >(perfect_split_value);
  310.                 I event_kind = thrust::get< 2 >(perfect_split_value);
  311.                 U split_event = thrust::get< 3 >(perfect_split_value);
  312.                 U l = thrust::get< 4 >(perfect_split_value), r = thrust::get< 5 >(perfect_split_value);
  313.                 F min = thrust::get< 0 >(node_bbox), max = thrust::get< 1 >(node_bbox);
  314.                 F L = split_pos - min;
  315.                 F R = max - split_pos;
  316.                 if (event_kind < 0) {
  317.                     ++split_event;
  318.                 } else if (event_kind == 0) {
  319.                     if (L < R) {
  320.                         ++l;
  321.                         ++split_event;
  322.                     } else {
  323.                         ++r;
  324.                     }
  325.                 }
  326.                 F x = max - min;
  327.                 F y = thrust::get< 3 >(node_bbox) - thrust::get< 2 >(node_bbox);
  328.                 F z = thrust::get< 5 >(node_bbox) - thrust::get< 4 >(node_bbox);
  329.                 F perimeter = y + z;
  330.                 F square = y * z;
  331.                 F split_cost = (l * (square + perimeter * L) + r * (square + perimeter * R)) / (square + perimeter * x);
  332.                 split_cost *= sah.intersection_cost;
  333.                 split_cost += sah.traversal_cost;
  334.                 if ((l == 0) || (r == 0)) {
  335.                     split_cost *= sah.emptiness_factor;
  336.                 }
  337.                 return {split_cost, split_event, split_pos, l, r};
  338.             };
  339.             auto perfect_split_value_begin = thrust::make_transform_iterator(perfect_split_input_begin, to_split);
  340.             auto ends = thrust::reduce_by_key(p, event.node.cbegin(), event.node.cend(), perfect_split_value_begin, thrust::make_discard_iterator(), thrust::make_permutation_iterator(perfect_split_begin, layer_node_offset.cbegin()), thrust::equal_to< U >{}, thrust::minimum< perfect_split_type >{});
  341.             assert(ends.first == thrust::make_discard_iterator(layer_node_offset.size()));
  342.         }
  343.  
  344.         void calculate_polygon_side(const container< I > & node_split_dimension,
  345.                                     U base_node,
  346.                                     container< U > & polygon_event_l, container< U > & polygon_event_r,
  347.                                     container< I > & polygon_side)
  348.         {
  349.             auto event_count = U(event.kind.size());
  350.  
  351.             auto split_dimension_begin = thrust::make_permutation_iterator(node_split_dimension.cbegin(), event.node.cbegin());
  352.  
  353.             { // find event counterpart
  354.                 auto event_begin = thrust::make_counting_iterator< U >(0);
  355.                 auto event_end = thrust::next(event_begin, event_count);
  356.  
  357.                 auto event_side_begin = thrust::make_zip_iterator(thrust::make_tuple(split_dimension_begin, event.kind.cbegin()));
  358.                 using event_side_type = input_iterator_value_type< decltype(event_side_begin) >;
  359.  
  360.                 auto is_not_r_event = [] __host__ __device__ (event_side_type event_side) -> bool
  361.                 {
  362.                     U node_split_dimension = thrust::get< 0 >(event_side);
  363.                     if (node_split_dimension != dimension) {
  364.                         return false;
  365.                     }
  366.                     I event_kind = thrust::get< 1 >(event_side);
  367.                     return !(event_kind < 0);
  368.                 };
  369.                 thrust::scatter_if(p, event_begin, event_end, event.polygon.cbegin(), event_side_begin, polygon_event_l.begin(), is_not_r_event);
  370.  
  371.                 // TODO: optimize out one of (polygon_event_l, polygon_event_r)
  372.                 auto is_not_l_event = [] __host__ __device__ (event_side_type event_side) -> bool
  373.                 {
  374.                     U node_split_dimension = thrust::get< 0 >(event_side);
  375.                     if (node_split_dimension != dimension) {
  376.                         return false;
  377.                     }
  378.                     I event_kind = thrust::get< 1 >(event_side);
  379.                     return !(0 < event_kind);
  380.                 };
  381.                 thrust::scatter_if(p, event_begin, event_end, event.polygon.cbegin(), event_side_begin, polygon_event_r.begin(), is_not_l_event);
  382.             }
  383.  
  384.             //std::cout << "dimension " << dimension << ": event count " << event_count << std::endl;
  385.  
  386.             auto split_event_begin = thrust::make_permutation_iterator(thrust::prev(layer.split_event.cbegin(), base_node), event.node.cbegin());
  387.             auto polygon_event_lr_begin = thrust::make_zip_iterator(thrust::make_tuple(polygon_event_l.cbegin(), polygon_event_r.cbegin()));
  388.             auto event_lr_begin = thrust::make_permutation_iterator(polygon_event_lr_begin, event.polygon.cbegin());
  389.             using event_lr_type = input_iterator_value_type< decltype(event_lr_begin) >;
  390.             auto polygon_side_begin = thrust::make_permutation_iterator(polygon_side.begin(), event.polygon.cbegin());
  391.             auto to_polygon_side = [] __host__ __device__ (event_lr_type event_lr, U split_event) -> I
  392.             {
  393.                 U l = thrust::get< 0 >(event_lr);
  394.                 U r = thrust::get< 1 >(event_lr);
  395.                 assert(l != U(~0));
  396.                 assert(r != U(~0));
  397.                 if (r < l) {
  398.                     printf("event1: %u %u %u\n", l, r, split_event);
  399.                 }
  400.                 assert(!(r < l));
  401.                 if (r < split_event) {
  402.                     return -1; // goes to left node
  403.                 } else if (l < split_event) {
  404.                     return  0; // goes to both left child node and right child node (splitted), assert(event_kind != 0)
  405.                 } else {
  406.                     return +1; // goes to right node
  407.                 }
  408.             };
  409.             auto is_x = [] __host__ __device__ (I node_split_dimension) -> bool { return node_split_dimension == dimension; };
  410.             thrust::transform_if(p, event_lr_begin, thrust::next(event_lr_begin, event_count), split_event_begin, split_dimension_begin, polygon_side_begin, to_polygon_side, is_x);
  411.         }
  412.  
  413.         void decouple_lr_event(const container< I > & node_split_dimension, const container< I > & polygon_side)
  414.         {
  415.             auto event_count = U(event.kind.size());
  416.  
  417.             auto event_begin = thrust::make_counting_iterator< U >(0);
  418.  
  419.             auto split_dimension_begin = thrust::make_permutation_iterator(node_split_dimension.cbegin(), event.node.cbegin());
  420.             auto polygon_side_begin = thrust::make_permutation_iterator(polygon_side.cbegin(), event.polygon.cbegin());
  421.             auto polygon_stencil_begin = thrust::make_zip_iterator(thrust::make_tuple(split_dimension_begin, polygon_side_begin));
  422.             using polygon_stencil_type = input_iterator_value_type< decltype(polygon_stencil_begin) >;
  423.  
  424.             auto is_l_polygon = [] __host__ __device__ (polygon_stencil_type polygon_stencil) -> bool
  425.             {
  426.                 I split_dimension = thrust::get< 0 >(polygon_stencil);
  427.                 if (split_dimension < 0) {
  428.                     return false;
  429.                 }
  430.                 I polygon_side = thrust::get< 1 >(polygon_stencil);
  431.                 assert(polygon_side != 101325);
  432.                 return polygon_side < 0;
  433.             };
  434.             auto event_l_end = thrust::copy_if(p, event_begin, thrust::next(event_begin, event_count), polygon_stencil_begin, event.l.begin(), is_l_polygon);
  435.             event.l.erase(event_l_end, event.l.end());
  436.  
  437.             auto is_r_polygon = [] __host__ __device__ (polygon_stencil_type polygon_stencil) -> bool
  438.             {
  439.                 I split_dimension = thrust::get< 0 >(polygon_stencil);
  440.                 if (split_dimension < 0) {
  441.                     return false;
  442.                 }
  443.                 I polygon_side = thrust::get< 1 >(polygon_stencil);
  444.                 assert(polygon_side != 101325);
  445.                 return 0 < polygon_side;
  446.             };
  447.             auto event_r_end = thrust::copy_if(p, event_begin, thrust::next(event_begin, event_count), polygon_stencil_begin, event.r.begin(), is_r_polygon);
  448.             event.r.erase(event_r_end, event.r.end());
  449.         }
  450.  
  451.         void split_polygon(const container< I > & node_split_dimension, const container< F > & node_split_pos,
  452.                            const container< U > & polygon_triangle, const container< U > & polygon_node,
  453.                            U polygon_count, U splitted_polygon_count,
  454.                            const container< U > & splitted_polygon,
  455.                            const Y & y, const Z & z)
  456.         {
  457.             // node of right part of splitted polygon (starting from polygon_count) is still node from previous layer
  458.  
  459.             polygon.min.resize(polygon_count + splitted_polygon_count);
  460.             polygon.max.resize(polygon_count + splitted_polygon_count);
  461.  
  462.             auto polygon_bbox_begin = thrust::make_zip_iterator(thrust::make_tuple(polygon.min.begin(), polygon.max.begin()));
  463.             auto polygon_l_bbox_begin = thrust::make_permutation_iterator(polygon_bbox_begin, splitted_polygon.cbegin());
  464.             using polygon_bbox_input_type = input_iterator_value_type< decltype(polygon_l_bbox_begin) >;
  465.             auto node_begin = thrust::make_zip_iterator(thrust::make_tuple(node_split_dimension.cbegin(), node_split_pos.cbegin()));
  466.             auto polygon_node_begin = thrust::make_permutation_iterator(node_begin, polygon_node.cbegin());
  467.             auto triangle_begin = thrust::make_zip_iterator(thrust::make_tuple(triangle.a.cbegin(), triangle.b.cbegin(), triangle.c.cbegin(), y.triangle.a.cbegin(), y.triangle.b.cbegin(), y.triangle.c.cbegin(), z.triangle.a.cbegin(), z.triangle.b.cbegin(), z.triangle.c.cbegin()));
  468.             auto polygon_triangle_begin = thrust::make_permutation_iterator(triangle_begin, polygon_triangle.cbegin());
  469.             auto polygon_begin = thrust::make_zip_iterator(thrust::make_tuple(polygon_node_begin, polygon_triangle_begin));
  470.             using polygon_type = input_iterator_value_type< decltype(polygon_begin) >;
  471.             auto polygon_r_bbox_begin = thrust::next(polygon_bbox_begin, polygon_count);
  472.             auto splitted_polygon_bbox_begin = thrust::make_zip_iterator(thrust::make_tuple(polygon_l_bbox_begin, polygon_r_bbox_begin));
  473.             using splitted_polygon_bbox_type = output_iterator_value_type< decltype(splitted_polygon_bbox_begin) >;
  474.             auto to_splitted_polygon = [] __host__ __device__ (polygon_bbox_input_type bbox, polygon_type polygon) -> splitted_polygon_bbox_type
  475.             {
  476.                 F min = thrust::get< 0 >(bbox), max = thrust::get< 1 >(bbox);
  477.                 assert(!(max < min));
  478.                 const auto & polygon_node = thrust::get< 0 >(polygon);
  479.                 I node_split_dimension = thrust::get< 0 >(polygon_node);
  480.                 F node_split_pos = thrust::get< 1 >(polygon_node);
  481.                 if (node_split_dimension == dimension) {
  482.                     assert(!(node_split_pos < min) && !(max < node_split_pos));
  483.                     return {{min, node_split_pos}, {node_split_pos, max}};
  484.                 } else if (!(min < max)) {
  485.                     return {bbox, bbox};
  486.                 }
  487.  
  488.                 const auto & triangle = thrust::get< 1 >(polygon);
  489.                 F a, b, c;
  490.                 if (node_split_dimension == ((dimension + 1) % 3)) {
  491.                     a = thrust::get< 3 >(triangle);
  492.                     b = thrust::get< 4 >(triangle);
  493.                     c = thrust::get< 5 >(triangle);
  494.                 } else {
  495.                     assert(node_split_dimension == ((dimension + 2) % 3));
  496.                     a = thrust::get< 6 >(triangle);
  497.                     b = thrust::get< 7 >(triangle);
  498.                     c = thrust::get< 8 >(triangle);
  499.                 }
  500.  
  501.                 bool a_side = (a < node_split_pos);
  502.                 bool b_side = (b < node_split_pos);
  503.                 bool c_side = (c < node_split_pos);
  504.  
  505.                 F ax = thrust::get< 0 >(triangle);
  506.                 F bx = thrust::get< 1 >(triangle);
  507.                 F cx = thrust::get< 2 >(triangle);
  508.  
  509.                 if (a_side == b_side) {
  510.                     assert(a_side != c_side);
  511.                     thrust::swap(a_side, c_side);
  512.                     thrust::swap(ax, cx);
  513.                     thrust::swap(a, c);
  514.                 } else if (a_side == c_side) {
  515.                     assert(a_side != b_side);
  516.                     thrust::swap(a_side, b_side);
  517.                     thrust::swap(ax, bx);
  518.                     thrust::swap(a, b);
  519.                 }
  520.                 assert(b_side == c_side);
  521.  
  522.                 if (a_side != ((bx - ax) * (c - a) < (b - a) * (cx - ax))) {
  523.                     thrust::swap(bx, cx);
  524.                     thrust::swap(b, c);
  525.                 }
  526.  
  527.                 assert((b < a) || (a < b));
  528.                 F lpos = ax + (bx - ax) * (node_split_pos - a) / (b - a);
  529.                 assert((c < a) || (a < c));
  530.                 F rpos = ax + (cx - ax) * (node_split_pos - a) / (c - a);
  531.  
  532.                 if (std::is_floating_point_v< F >) {
  533.                     if (max < lpos) {
  534.                         lpos = max;
  535.                     }
  536.                     if (rpos < min) {
  537.                         rpos = min;
  538.                     }
  539.  
  540.                     if (rpos < lpos) {
  541.                         rpos = lpos = (lpos + rpos) / F(2);
  542.                     }
  543.                 }
  544.  
  545.                 assert(!(rpos < lpos));
  546.  
  547.                 F lmin, rmin;
  548.                 if (min < lpos) {
  549.                     if ((ax < bx) == (a < b)) {
  550.                         lmin = min;
  551.                         rmin = lpos;
  552.                     } else {
  553.                         lmin = lpos;
  554.                         rmin = min;
  555.                     }
  556.                 } else {
  557.                     lmin = min;
  558.                     rmin = min;
  559.                 }
  560.                 F lmax, rmax;
  561.                 if (rpos < max) {
  562.                     if ((ax < cx) == (a < c)) {
  563.                         lmax = rpos;
  564.                         rmax = max;
  565.                     } else {
  566.                         lmax = max;
  567.                         rmax = rpos;
  568.                     }
  569.                 } else {
  570.                     lmax = max;
  571.                     rmax = max;
  572.                 }
  573.                 assert(!(lmax < lmin));
  574.                 assert(!(rmax < rmin));
  575.                 return {{lmin, lmax}, {rmin, rmax}};
  576.             };
  577.             thrust::transform(p, polygon_l_bbox_begin, thrust::next(polygon_l_bbox_begin, splitted_polygon_count), thrust::next(polygon_begin, polygon_count), splitted_polygon_bbox_begin, to_splitted_polygon);
  578.         }
  579.  
  580.         void merge_event(U polygon_count, const container< U > & polygon_node, U splitted_polygon_count, const container< U > & splitted_polygon)
  581.         {
  582.             auto event_count = U(event.kind.size());
  583.  
  584.             auto polygon_bbox_begin = thrust::make_zip_iterator(thrust::make_tuple(polygon.min.cbegin(), polygon.max.cbegin()));
  585.             using bbox_type = input_iterator_value_type< decltype(polygon_bbox_begin) >;
  586.             auto is_planar_polygon = [] __host__ __device__ (bbox_type bbox) -> bool { return !(thrust::get< 0 >(bbox) < thrust::get< 1 >(bbox)); };
  587.  
  588.             auto polygon_l_bbox_begin = thrust::make_permutation_iterator(polygon_bbox_begin, splitted_polygon.cbegin());
  589.             auto polygon_r_bbox_begin = thrust::next(polygon_bbox_begin, polygon_count);
  590.  
  591.             auto planar_polygon_l_count = U(thrust::count_if(p, polygon_l_bbox_begin, thrust::next(polygon_l_bbox_begin, splitted_polygon_count), is_planar_polygon));
  592.             auto planar_polygon_r_count = U(thrust::count_if(p, polygon_r_bbox_begin, thrust::next(polygon_r_bbox_begin, splitted_polygon_count), is_planar_polygon));
  593.  
  594.             U splitted_event_l_count = splitted_polygon_count + splitted_polygon_count - planar_polygon_l_count;
  595.             U splitted_event_r_count = splitted_polygon_count + splitted_polygon_count - planar_polygon_r_count;
  596.  
  597.             //std::cout << "splitted_event_l_count = " << splitted_event_l_count << "\n";
  598.             //std::cout << "splitted_event_r_count = " << splitted_event_r_count << "\n";
  599.  
  600.             U splitted_event_count = splitted_event_l_count + splitted_event_r_count;
  601.  
  602.             auto l = U(event.l.size());
  603.             auto r = U(event.r.size());
  604.  
  605.             U event_storage_size = std::exchange(event_count, l + r + splitted_event_count);
  606.             if (event_storage_size < event_count) {
  607.                 event_storage_size = event_count;
  608.             }
  609.  
  610.             // grant additional storage for all merge operations
  611.             event.node.resize(event_storage_size + event_count, 101325u);
  612.             event.pos.resize(event_storage_size + event_count);
  613.             event.kind.resize(event_storage_size + event_count, I(0));
  614.             event.polygon.resize(event_storage_size + event_count);
  615.  
  616.             // merge l and r event
  617.             auto event_node_begin = thrust::make_permutation_iterator(polygon_node.cbegin(), event.polygon.cbegin());
  618.             auto event_value_begin = thrust::make_zip_iterator(thrust::make_tuple(event.pos.begin(), event.kind.begin(), event.polygon.begin()));
  619.  
  620.             auto event_key_l_begin = thrust::make_permutation_iterator(event_node_begin, event.l.cbegin());
  621.             auto event_value_l_begin = thrust::make_permutation_iterator(event_value_begin, event.l.cbegin());
  622.  
  623.             auto event_key_r_begin = thrust::make_permutation_iterator(event_node_begin, event.r.cbegin());
  624.             auto event_value_r_begin = thrust::make_permutation_iterator(event_value_begin, event.r.cbegin());
  625.  
  626.             if ((false)) {
  627.                 auto check_node = [] __host__ __device__ (U node)
  628.                 {
  629.                     if (node == 0 || node == ~0u) {
  630.                         printf("node node %u\n", node);
  631.                     }
  632.                 };
  633.                 thrust::for_each_n(p, event_key_l_begin, l, check_node);
  634.                 thrust::for_each_n(p, event_key_r_begin, r, check_node);
  635.             }
  636.  
  637.             auto event_lr_key_begin = thrust::next(event.node.begin(), event_storage_size);
  638.             auto event_lr_value_begin = thrust::next(event_value_begin, event_storage_size);
  639.             thrust::merge_by_key(p, event_key_l_begin, thrust::next(event_key_l_begin, l), event_key_r_begin, thrust::next(event_key_r_begin, r), event_value_l_begin, event_value_r_begin, event_lr_key_begin, event_lr_value_begin);
  640.  
  641.             auto splitted_event_offset = event_storage_size + l + r;
  642.  
  643.             // calculate event kind for event of splitted polygon
  644.             auto event_l_kind_l_begin = thrust::next(event.kind.begin(), splitted_event_offset);
  645.             auto event_r_kind_l_begin = thrust::next(event_l_kind_l_begin, splitted_event_l_count);
  646.             auto event_l_kind_r_begin = thrust::make_reverse_iterator(event_r_kind_l_begin);
  647.             auto event_r_kind_r_begin = thrust::prev(event_l_kind_r_begin, splitted_event_r_count);
  648.  
  649.             auto event_l_kind_lr_begin = thrust::make_zip_iterator(thrust::make_tuple(event_l_kind_l_begin, event_l_kind_r_begin));
  650.             auto event_r_kind_lr_begin = thrust::make_zip_iterator(thrust::make_tuple(event_r_kind_l_begin, event_r_kind_r_begin));
  651.  
  652.             auto kind_lr = thrust::make_tuple(+1, -1);
  653.             thrust::fill_n(p, event_l_kind_lr_begin, splitted_polygon_count - planar_polygon_l_count, kind_lr);
  654.             thrust::fill_n(p, event_r_kind_lr_begin, splitted_polygon_count - planar_polygon_r_count, kind_lr);
  655.  
  656.             // calculate l and r polygon for event of splitted polygon
  657.             auto event_l_polygon_l_begin = thrust::next(event.polygon.begin(), splitted_event_offset);
  658.             auto event_r_polygon_l_begin = thrust::next(event_l_polygon_l_begin, splitted_event_l_count);
  659.             auto event_l_polygon_r_begin = thrust::make_reverse_iterator(event_r_polygon_l_begin);
  660.             auto event_r_polygon_r_begin = thrust::prev(event_l_polygon_r_begin, splitted_event_r_count);
  661.  
  662.             auto event_l_polygon_lr_begin = thrust::make_zip_iterator(thrust::make_tuple(event_l_polygon_l_begin, event_l_polygon_r_begin));
  663.             auto event_r_polygon_lr_begin = thrust::make_zip_iterator(thrust::make_tuple(event_r_polygon_l_begin, event_r_polygon_r_begin));
  664.  
  665.             auto event_l_polygon_lr_output_begin = thrust::make_transform_output_iterator(event_l_polygon_lr_begin, doubler< U >{});
  666.             auto event_r_polygon_lr_output_begin = thrust::make_transform_output_iterator(event_r_polygon_lr_begin, doubler< U >{});
  667.  
  668.             auto event_l_polygon_planar_begin = thrust::next(event_l_polygon_l_begin, splitted_polygon_count - planar_polygon_l_count);
  669.             auto event_r_polygon_planar_begin = thrust::next(event_r_polygon_l_begin, splitted_polygon_count - planar_polygon_r_count);
  670.  
  671.             auto polygon_l_begin = splitted_polygon.cbegin();
  672.             auto polygon_r_begin = thrust::make_counting_iterator< U >(polygon_count);
  673.  
  674.             auto ends_l = thrust::partition_copy(p, polygon_l_begin, thrust::next(polygon_l_begin, splitted_polygon_count), polygon_l_bbox_begin, event_l_polygon_planar_begin, event_l_polygon_lr_output_begin, is_planar_polygon);
  675.             assert(thrust::next(event_l_polygon_planar_begin, planar_polygon_l_count) == ends_l.first);
  676.             auto ends_r = thrust::partition_copy(p, polygon_r_begin, thrust::next(polygon_r_begin, splitted_polygon_count), polygon_r_bbox_begin, event_r_polygon_planar_begin, event_r_polygon_lr_output_begin, is_planar_polygon);
  677.             assert(thrust::next(event_r_polygon_planar_begin, planar_polygon_r_count) == ends_r.first);
  678.  
  679.             // calculate event pos
  680. #if 1
  681.             auto event_polygon_begin = event_l_polygon_l_begin;
  682.             auto event_polygon_end = thrust::next(event_l_polygon_l_begin, splitted_polygon_count);
  683.             auto event_pos_begin = thrust::next(event.pos.begin(), splitted_event_offset);
  684.             event_pos_begin = thrust::gather(p, std::exchange(event_polygon_begin, event_polygon_end), event_polygon_end, polygon.min.cbegin(), event_pos_begin);
  685.             event_polygon_end = thrust::next(event_polygon_begin, splitted_polygon_count - planar_polygon_l_count);
  686.             event_pos_begin = thrust::gather(p, std::exchange(event_polygon_begin, event_polygon_end), event_polygon_end, polygon.max.cbegin(), event_pos_begin);
  687.             event_polygon_end = thrust::next(event_polygon_begin, splitted_polygon_count);
  688.             event_pos_begin = thrust::gather(p, std::exchange(event_polygon_begin, event_polygon_end), event_polygon_end, polygon.min.cbegin(), event_pos_begin);
  689.             assert(event.polygon.end() == thrust::next(event_polygon_begin, splitted_polygon_count - planar_polygon_r_count));
  690.             event_pos_begin = thrust::gather(p, event_polygon_begin, event.polygon.end(), polygon.max.cbegin(), event_pos_begin);
  691.             assert(event_pos_begin == event.pos.end());
  692. #else
  693.             auto event_polygon_bbox_begin = thrust::make_permutation_iterator(polygon_bbox_begin, event_l_polygon_l_begin);
  694.             auto to_event_pos = [] __host__ __device__ (I event_kind, bbox_type bbox) -> F
  695.             {
  696.                 return (event_kind < 0) ? thrust::get< 1 >(bbox) : thrust::get< 0 >(bbox);
  697.             };
  698.             thrust::transform(p, event_l_kind_l_begin, event.kind.end(), event_polygon_bbox_begin, thrust::next(event.pos.begin(), splitted_event_offset), to_event_pos);
  699. #endif
  700.  
  701.             // calculate event node
  702.             thrust::gather(p, event_l_polygon_l_begin, event.polygon.end(), polygon_node.cbegin(), thrust::next(event.node.begin(), splitted_event_offset));
  703.  
  704.             auto event_begin = thrust::make_zip_iterator(thrust::make_tuple(event.node.begin(), event.pos.begin(), event.kind.begin(), event.polygon.begin()));
  705.  
  706.             // sort splitted event
  707.             auto splitted_event_begin = thrust::next(event_begin, splitted_event_offset);
  708.             auto splitted_event_end = thrust::next(splitted_event_begin, splitted_event_count);
  709.             thrust::sort(p, splitted_event_begin, splitted_event_end);
  710.  
  711.             // cleanup repeating planar events
  712.             if (std::is_floating_point_v< F >) {
  713.                 auto clean_splitted_event_end = thrust::unique(p, splitted_event_begin, splitted_event_end);
  714.                 //std::cout << "CLEAN: " << thrust::distance(clean_splitted_event_end, splitted_event_end) << std::endl;
  715.                 event_count -= U(thrust::distance(clean_splitted_event_end, splitted_event_end));
  716.                 splitted_event_end = clean_splitted_event_end;
  717.             }
  718.  
  719.             if ((false)) {
  720.                 decltype(event.node) node{thrust::get< 0 >(splitted_event_begin.get_iterator_tuple()), thrust::get< 0 >(splitted_event_end.get_iterator_tuple())};
  721.                 decltype(event.polygon) polygon{thrust::get< 3 >(splitted_event_begin.get_iterator_tuple()), thrust::get< 3 >(splitted_event_end.get_iterator_tuple())};
  722.                 auto it = thrust::make_zip_iterator(thrust::make_tuple(polygon.begin(), node.begin()));
  723.                 thrust::sort_by_key(p, polygon.begin(), polygon.end(), node.begin());
  724.                 auto d = thrust::make_discard_iterator();
  725.                 using P = thrust::tuple< U, U, U >;
  726.                 container< P > uniq_nodes{node.size()};
  727.                 auto transform = [] __host__ __device__ (U node) -> P
  728.                 {
  729.                     return {node, 0, 1};
  730.                 };
  731.                 auto node_begin = thrust::make_transform_iterator(node.begin(), transform);
  732.                 auto sum = [] __host__ __device__ (const P & l, const P & r) -> P
  733.                 {
  734.                     U node_l = thrust::get< 0 >(l);
  735.                     U node_r = thrust::get< 0 >(r);
  736.                     bool b = node_l == node_r;
  737.                     if (!b) {
  738.                         printf("nodes1 %u %u\n", node_l, node_r);
  739.                     }
  740.                     U eq = thrust::get< 1 >(l) + thrust::get< 1 >(r) + (b ? 0 : 1);
  741.                     return {node_r, eq, thrust::get< 2 >(l) + thrust::get< 2 >(r)};
  742.                 };
  743.                 auto ends = thrust::reduce_by_key(p, polygon.begin(), polygon.end(), node_begin, d, uniq_nodes.begin(), thrust::equal_to< U >{}, sum);
  744.                 uniq_nodes.erase(ends.second, uniq_nodes.end());
  745.                 auto check = [] __host__ __device__ (const P & x)
  746.                 {
  747.                     if (!((thrust::get< 2 >(x) == 2) || (thrust::get< 2 >(x) == 1))) {
  748.                         printf("not two: %u %u\n", thrust::get< 2 >(x), thrust::get< 0 >(x));
  749.                     }
  750.                     assert(thrust::get< 1 >(x) == 0);
  751.                     assert((thrust::get< 2 >(x) == 2) || (thrust::get< 2 >(x) == 1));
  752.                 };
  753.                 thrust::for_each(p, uniq_nodes.begin(), uniq_nodes.end(), check);
  754.             }
  755.  
  756.             // merge splitted event w/ lr event
  757.             auto event_lr_begin = thrust::next(event_begin, event_storage_size);
  758.             auto event_end = thrust::merge(p, event_lr_begin, splitted_event_begin, splitted_event_begin, splitted_event_end, event_begin);
  759.             assert(thrust::next(event_begin, event_count) == event_end);
  760.  
  761.             assert(thrust::is_sorted(p, event_begin, event_end));
  762.  
  763.             if ((false)) {
  764.                 auto event_polygon_bbox_begin1 = thrust::make_zip_iterator(thrust::make_tuple(event.kind.cbegin(), thrust::make_permutation_iterator(polygon_bbox_begin, event.polygon.cbegin())));
  765.                 using event_polygon_bbox_type1 = input_iterator_value_type< decltype(event_polygon_bbox_begin1) >;
  766.                 auto to_event_pos1 = [] __host__ __device__ (event_polygon_bbox_type1 x) -> F
  767.                 {
  768.                     I event_kind = thrust::get< 0 >(x);
  769.                     const bbox_type & bbox = thrust::get< 1 >(x);
  770.                     return (event_kind < 0) ? thrust::get< 1 >(bbox) : thrust::get< 0 >(bbox);
  771.                 };
  772.                 assert(thrust::equal(p, event.pos.cbegin(), thrust::next(event.pos.cbegin(), event_count), thrust::make_transform_iterator(event_polygon_bbox_begin1, to_event_pos1)));
  773.             }
  774.  
  775.             // crop
  776.             event.node.resize(event_count);
  777.             event.pos.resize(event_count);
  778.             event.kind.resize(event_count);
  779.             event.polygon.resize(event_count);
  780.  
  781.             assert(thrust::equal(p, event.node.cbegin(), event.node.cend(), thrust::make_permutation_iterator(polygon_node.cbegin(), event.polygon.cbegin())));
  782.  
  783.             if ((false)) {
  784.                 auto node = event.node;
  785.                 auto polygon = event.polygon;
  786.                 auto it = thrust::make_zip_iterator(thrust::make_tuple(polygon.begin(), node.begin()));
  787.                 thrust::sort_by_key(p, polygon.begin(), polygon.end(), node.begin());
  788.                 auto d = thrust::make_discard_iterator();
  789.                 using P = thrust::tuple< U, U, U >;
  790.                 container< P > uniq_nodes{node.size()};
  791.                 auto transform = [] __host__ __device__ (U node) -> P
  792.                 {
  793.                     return {node, 0, 1};
  794.                 };
  795.                 auto node_begin = thrust::make_transform_iterator(node.begin(), transform);
  796.                 auto sum = [] __host__ __device__ (const P & l, const P & r) -> P
  797.                 {
  798.                     U node_l = thrust::get< 0 >(l);
  799.                     U node_r = thrust::get< 0 >(r);
  800.                     bool b = node_l == node_r;
  801.                     if (!b) {
  802.                         printf("nodes %u %u\n", node_l, node_r);
  803.                     }
  804.                     U eq = thrust::get< 1 >(l) + thrust::get< 1 >(r) + (b ? 0 : 1);
  805.                     return {node_r, eq, thrust::get< 2 >(l) + thrust::get< 2 >(r)};
  806.                 };
  807.                 auto ends = thrust::reduce_by_key(p, polygon.begin(), polygon.end(), node_begin, d, uniq_nodes.begin(), thrust::equal_to< U >{}, sum);
  808.                 uniq_nodes.erase(ends.second, uniq_nodes.end());
  809.                 auto check = [] __host__ __device__ (const P & x)
  810.                 {
  811.                     if (!((thrust::get< 2 >(x) == 2) || (thrust::get< 2 >(x) == 1))) {
  812.                         printf("not two: %u %u\n", thrust::get< 2 >(x), thrust::get< 0 >(x));
  813.                     }
  814.                     assert(thrust::get< 1 >(x) == 0);
  815.                     assert((thrust::get< 2 >(x) == 2) || (thrust::get< 2 >(x) == 1));
  816.                 };
  817.                 thrust::for_each(p, uniq_nodes.begin(), uniq_nodes.end(), check);
  818.             }
  819.         }
  820.  
  821.         void set_node_count(U node_count)
  822.         {
  823.             node.min.resize(node_count);
  824.             node.max.resize(node_count);
  825.         }
  826.  
  827.         void split_node(U prev_base_node, U base_node,
  828.                         const container< I > & node_split_dimension, const container< U > & node_split_pos,
  829.                         const container< U > & node_l, const container< U > & node_r)
  830.         {
  831.             auto node_split_pos_begin = thrust::next(node_split_pos.cbegin(), prev_base_node);
  832.             auto node_split_pos_end = thrust::next(node_split_pos.cbegin(), base_node);
  833.             auto node_split_dimension_begin = thrust::next(node_split_dimension.cbegin(), prev_base_node);
  834.             auto is_x = [] __host__ __device__ (I node_split_dimension) -> bool { return node_split_dimension == dimension; };
  835.             thrust::scatter_if(p, node_split_pos_begin, node_split_pos_end, thrust::next(node_l.cbegin(), prev_base_node), node_split_dimension_begin, node.max.begin(), is_x);
  836.             thrust::scatter_if(p, node_split_pos_begin, node_split_pos_end, thrust::next(node_r.cbegin(), prev_base_node), node_split_dimension_begin, node.min.begin(), is_x);
  837.         }
  838.  
  839.     };
  840.  
  841.     projection< 0 > x{p};
  842.     projection< 1 > y{p};
  843.     projection< 2 > z{p};
  844.  
  845.     struct
  846.     {
  847.         container< U > triangle;
  848.         container< U > node;
  849.         container< I > side;
  850.         struct
  851.         {
  852.             container< U > l, r; // corresponding left and right event in different best dimensions
  853.         } event;
  854.     } polygon;
  855.  
  856.     struct
  857.     {
  858.         container< I > split_dimension;
  859.         container< F > split_pos;
  860.         container< U > l, r; // left child node and right child node if not leaf, polygon range otherwise
  861.         struct
  862.         {
  863.             container< U > node, l, r; // unique polygon count in current node, its left child node and right child node
  864.         } polygon_count;
  865.     } node; // TODO: optimize out node.l
  866.  
  867.     container< U > layer_node_offset;
  868.  
  869.     container< U > splitted_polygon;
  870.  
  871.     void calculate_node_best_split(const params & sah, U base_node, U node_count)
  872.     {
  873.         auto node_split_cost_begin = thrust::make_zip_iterator(thrust::make_tuple(x.layer.split_cost.cbegin(), y.layer.split_cost.cbegin(), z.layer.split_cost.cbegin()));
  874.         auto node_split_pos_begin = thrust::make_zip_iterator(thrust::make_tuple(x.layer.split_pos.cbegin(), y.layer.split_pos.cbegin(), z.layer.split_pos.cbegin()));
  875.         auto node_l_polygon_count_begin = thrust::make_zip_iterator(thrust::make_tuple(x.layer.polygon_count.l.cbegin(), y.layer.polygon_count.l.cbegin(), z.layer.polygon_count.l.cbegin()));
  876.         auto node_r_polygon_count_begin = thrust::make_zip_iterator(thrust::make_tuple(x.layer.polygon_count.r.cbegin(), y.layer.polygon_count.r.cbegin(), z.layer.polygon_count.r.cbegin()));
  877.         auto node_split_begin = thrust::make_zip_iterator(thrust::make_tuple(node_split_cost_begin, node_split_pos_begin, node_l_polygon_count_begin, node_r_polygon_count_begin));
  878.         using node_split_type = input_iterator_value_type< decltype(node_split_begin) >;
  879.         auto node_polygon_count_begin = thrust::next(node.polygon_count.node.cbegin(), base_node);
  880.         auto node_best_split_begin = thrust::next(thrust::make_zip_iterator(thrust::make_tuple(node.split_dimension.begin(), node.split_pos.begin(), node.polygon_count.l.begin(), node.polygon_count.r.begin())), base_node);
  881.         using node_best_split_type = output_iterator_value_type< decltype(node_best_split_begin) >;
  882.         auto to_node_best_split = [sah] __host__ __device__ (node_split_type node_split, U node_polygon_count) -> node_best_split_type
  883.         {
  884.             assert(node_polygon_count != 0);
  885.             const auto & node_split_cost = thrust::get< 0 >(node_split);
  886.             const auto & node_split_pos = thrust::get< 1 >(node_split);
  887.             const auto & node_l_polygon_count = thrust::get< 2 >(node_split);
  888.             const auto & node_r_polygon_count = thrust::get< 3 >(node_split);
  889.             F x = thrust::get< 0 >(node_split_cost);
  890.             F y = thrust::get< 1 >(node_split_cost);
  891.             F z = thrust::get< 2 >(node_split_cost);
  892.             F best_node_split_cost = thrust::min(sah.intersection_cost * node_polygon_count, thrust::min(x, thrust::min(y, z)));
  893.             if (!(best_node_split_cost < x)) {
  894.                 return {0, thrust::get< 0 >(node_split_pos), thrust::get< 0 >(node_l_polygon_count), thrust::get< 0 >(node_r_polygon_count)};
  895.             } else if (!(best_node_split_cost < y)) {
  896.                 return {1, thrust::get< 1 >(node_split_pos), thrust::get< 1 >(node_l_polygon_count), thrust::get< 1 >(node_r_polygon_count)};
  897.             } else if (!(best_node_split_cost < z)) {
  898.                 return {2, thrust::get< 2 >(node_split_pos), thrust::get< 2 >(node_l_polygon_count), thrust::get< 2 >(node_r_polygon_count)};
  899.             } else {
  900.                 return {-1};
  901.             }
  902.         };
  903.         auto is_node_not_empty = [] __host__ __device__ (U node_polygon_count) -> bool { return node_polygon_count != 0; };
  904.         thrust::transform_if(p, node_split_begin, thrust::next(node_split_begin, node_count), node_polygon_count_begin, node_polygon_count_begin, node_best_split_begin, to_node_best_split, is_node_not_empty);
  905.     }
  906.  
  907.     template< typename iterator >
  908.     void print(iterator first, U count, const char * const what) const
  909.     {
  910.         std::copy(first, thrust::next(first, count), std::ostream_iterator< typename thrust::iterator_traits< iterator >::value_type >(std::cout << what, ", "));
  911.         std::cout << "\n";
  912.     }
  913.  
  914.     template< typename iterator >
  915.     void print(iterator first, iterator last, const char * const what) const
  916.     {
  917.         std::copy(first, last, std::ostream_iterator< typename thrust::iterator_traits< iterator >::value_type >(std::cout << what, ", "));
  918.         std::cout << "\n";
  919.     }
  920.  
  921.     U get_splitted_polygon_count(U base_node, U node_count) const
  922.     {
  923. #if 0
  924.         std::cout << "node_size " << node.split_pos.size() << "\n";
  925.         std::cout << "base_node " << base_node << "\n";
  926.         std::cout << "node_count " << node_count << "\n";
  927.         print(x.layer.polygon_count.l.cbegin(), x.layer.polygon_count.l.cend(), "x.layer.polygon_count.l: ");
  928.         print(x.layer.polygon_count.r.cbegin(), x.layer.polygon_count.r.cend(), "x.layer.polygon_count.r: ");
  929.         print(y.layer.polygon_count.l.cbegin(), y.layer.polygon_count.l.cend(), "y.layer.polygon_count.l: ");
  930.         print(y.layer.polygon_count.r.cbegin(), y.layer.polygon_count.r.cend(), "y.layer.polygon_count.r: ");
  931.         print(z.layer.polygon_count.l.cbegin(), z.layer.polygon_count.l.cend(), "z.layer.polygon_count.l: ");
  932.         print(z.layer.polygon_count.r.cbegin(), z.layer.polygon_count.r.cend(), "z.layer.polygon_count.r: ");
  933.         print(thrust::next(node.split_pos.cbegin(), base_node), node_count, "node.split_pos: ");
  934.         print(x.layer.split_pos.cbegin(), node_count, "x.layer.split_pos: ");
  935.         print(y.layer.split_pos.cbegin(), node_count, "y.layer.split_pos: ");
  936.         print(z.layer.split_pos.cbegin(), node_count, "z.layer.split_pos: ");
  937.         print(thrust::next(node.split_dimension.cbegin(), base_node), node_count, "node.split_dimension: ");
  938.         print(thrust::next(node.polygon_count.l.cbegin(), base_node), node_count, "node.polygon_count.l: ");
  939.         print(thrust::next(node.polygon_count.r.cbegin(), base_node), node_count, "node.polygon_count.r: ");
  940.         print(thrust::next(node.polygon_count.node.cbegin(), base_node), node_count, "node.polygon_count.node: ");
  941.         std::cout << std::endl;
  942. #endif
  943.  
  944.         auto node_polygon_count_begin = thrust::make_zip_iterator(thrust::make_tuple(node.split_dimension.cbegin(), node.polygon_count.l.cbegin(), node.polygon_count.r.cbegin(), node.polygon_count.node.cbegin()));
  945.         using node_polygon_count_type = input_iterator_value_type< decltype(node_polygon_count_begin) >;
  946.         auto to_splitted_polygon_count = [] __host__ __device__ (node_polygon_count_type node_polygon_count) -> U
  947.         {
  948.             I split_dimension = thrust::get< 0 >(node_polygon_count);
  949.             if (split_dimension < 0) {
  950.                 return 0;
  951.             }
  952.             U polygon_count_l = thrust::get< 1 >(node_polygon_count);
  953.             U polygon_count_r = thrust::get< 2 >(node_polygon_count);
  954.             U polygon_count = thrust::get< 3 >(node_polygon_count);
  955.             return polygon_count_l + polygon_count_r - polygon_count;
  956.         };
  957.         auto splitted_polygon_count_begin = thrust::next(node_polygon_count_begin, base_node);
  958.         return thrust::transform_reduce(p, splitted_polygon_count_begin, thrust::next(splitted_polygon_count_begin, node_count), to_splitted_polygon_count, U(0), thrust::plus< U >{});
  959.     }
  960.  
  961.     void separate_splitted_polygon(U base_node, U polygon_count, U splitted_polygon_count)
  962.     {
  963.         polygon.triangle.resize(polygon_count + splitted_polygon_count);
  964.         polygon.node.resize(polygon_count + splitted_polygon_count);
  965.         splitted_polygon.resize(splitted_polygon_count);
  966.  
  967.         auto polygon_begin = thrust::make_zip_iterator(thrust::make_tuple(polygon.triangle.begin(), polygon.node.begin()));
  968.         auto indexed_polygon_begin = thrust::make_zip_iterator(thrust::make_tuple(thrust::make_counting_iterator< U >(0), polygon_begin));
  969.         auto split_dimension_begin = thrust::make_permutation_iterator(node.split_dimension.cbegin(), polygon.node.cbegin());
  970.         auto splitted_polygon_stencil_begin = thrust::make_zip_iterator(thrust::make_tuple(polygon.node.cbegin(), split_dimension_begin, polygon.side.cbegin()));
  971.         using splitted_polygon_stencil_type = input_iterator_value_type< decltype(splitted_polygon_stencil_begin) >;
  972.         auto splitted_polygon_begin = thrust::make_zip_iterator(thrust::make_tuple(splitted_polygon.begin(), thrust::next(polygon_begin, polygon_count)));
  973.         auto is_splitted_polygon = [base_node] __host__ __device__ (splitted_polygon_stencil_type polygon_stencil) -> bool
  974.         {
  975.             U polygon_node = thrust::get< 0 >(polygon_stencil);
  976.             if (polygon_node < base_node) {
  977.                 return false;
  978.             }
  979.             I split_dimension = thrust::get< 1 >(polygon_stencil);
  980.             if (split_dimension < 0) {
  981.                 return false;
  982.             }
  983.             I polygon_side = thrust::get< 2 >(polygon_stencil);
  984.             assert(polygon_side != 101325);
  985.             if (polygon_side != 0) {
  986.                 return false;
  987.             }
  988.             return true;
  989.         };
  990.         auto splitted_polygon_end = thrust::copy_if(p, indexed_polygon_begin, thrust::next(indexed_polygon_begin, polygon_count), splitted_polygon_stencil_begin, splitted_polygon_begin, is_splitted_polygon);
  991.         //std::cout << "DIST: " << thrust::distance(splitted_polygon_begin, splitted_polygon_end) << std::endl;
  992.         assert(thrust::next(splitted_polygon_begin, splitted_polygon_count) == splitted_polygon_end);
  993.     }
  994.  
  995.     void update_polygon_node(U base_node, U polygon_count)
  996.     {
  997.         auto node_lr_begin = thrust::make_zip_iterator(thrust::make_tuple(node.l.cbegin(), node.r.cbegin()));
  998.         auto polygon_node_lr_begin = thrust::make_permutation_iterator(node_lr_begin, polygon.node.cbegin());
  999.         using polygon_node_lr_type = input_iterator_value_type< decltype(polygon_node_lr_begin) >;
  1000.         auto to_polygon_node = [] __host__ __device__ (I polygon_side, polygon_node_lr_type polygon_node_lr) -> U
  1001.         {
  1002.             return (0 < polygon_side) ? thrust::get< 1 >(polygon_node_lr) : thrust::get< 0 >(polygon_node_lr); // splitted event assigned to l node
  1003.         };
  1004.         auto split_dimension_begin = thrust::make_permutation_iterator(node.split_dimension.cbegin(), polygon.node.cbegin());
  1005.         auto node_stencil_begin = thrust::make_zip_iterator(thrust::make_tuple(polygon.node.cbegin(), split_dimension_begin));
  1006.         using node_stencil_type = input_iterator_value_type< decltype(node_stencil_begin) >;
  1007.         auto is_current_layer = [base_node] __host__ __device__ (node_stencil_type splitted_node_stencil) -> bool
  1008.         {
  1009.             U polygon_node = thrust::get< 0 >(splitted_node_stencil);
  1010.             if (polygon_node < base_node) {
  1011.                 return false;
  1012.             }
  1013.             I split_dimension = thrust::get< 1 >(splitted_node_stencil);
  1014.             if (split_dimension < 0) {
  1015.                 return false;
  1016.             }
  1017.             return true;
  1018.         };
  1019.         thrust::transform_if(p, polygon.side.cbegin(), thrust::next(polygon.side.cbegin(), polygon_count), polygon_node_lr_begin, node_stencil_begin, polygon.node.begin(), to_polygon_node, is_current_layer);
  1020.     }
  1021.  
  1022.     void update_splitted_polygon_node(U polygon_count, U splitted_polygon_count)
  1023.     {
  1024.         auto splitted_polygon_node_begin = thrust::next(polygon.node.begin(), polygon_count);
  1025.         thrust::gather(p, splitted_polygon_node_begin, thrust::next(splitted_polygon_node_begin, splitted_polygon_count), node.r.cbegin(), splitted_polygon_node_begin);
  1026.     }
  1027.  
  1028.     U d = 0;
  1029.  
  1030.     tree build(const params & sah)
  1031.     {
  1032.         auto triangle_count = U(x.triangle.a.size());
  1033.         assert(triangle_count > 0);
  1034.         assert(triangle_count == U(y.triangle.a.size()));
  1035.         assert(triangle_count == U(z.triangle.a.size()));
  1036.  
  1037.         polygon.triangle.resize(triangle_count);
  1038.         thrust::sequence(p, polygon.triangle.begin(), polygon.triangle.end());
  1039.  
  1040.         x.calculate_triangle_bbox();
  1041.         y.calculate_triangle_bbox();
  1042.         z.calculate_triangle_bbox();
  1043.  
  1044.         x.caluculate_root_node_bbox();
  1045.         y.caluculate_root_node_bbox();
  1046.         z.caluculate_root_node_bbox();
  1047.  
  1048.         polygon.node.assign(triangle_count, U(0));
  1049.  
  1050.         x.generate_initial_event();
  1051.         y.generate_initial_event();
  1052.         z.generate_initial_event();
  1053.  
  1054.         // layer
  1055.         U base_node = 0;
  1056.         U node_count = 1;
  1057.  
  1058.         node.split_dimension.resize(1);
  1059.         node.split_pos.resize(1);
  1060.         node.l.resize(1);
  1061.         node.r.resize(1);
  1062.         node.polygon_count.node.assign(1, triangle_count);
  1063.         node.polygon_count.l.resize(1);
  1064.         node.polygon_count.r.resize(1);
  1065.  
  1066.         for (U depth = 0; (sah.max_depth == 0) || (depth < sah.max_depth); ++depth) {
  1067.             d = depth;
  1068.             std::cout << "\n\n\ndepth = " << depth << "\n";
  1069.  
  1070.             assert(thrust::is_sorted(p, x.event.node.cbegin(), x.event.node.cend()));
  1071.             assert(thrust::is_sorted(p, y.event.node.cbegin(), y.event.node.cend()));
  1072.             assert(thrust::is_sorted(p, z.event.node.cbegin(), z.event.node.cend()));
  1073.  
  1074.             assert(thrust::none_of(p, x.event.node.cbegin(), x.event.node.cend(), thrust::placeholders::_1 < base_node));
  1075.             assert(thrust::none_of(p, y.event.node.cbegin(), y.event.node.cend(), thrust::placeholders::_1 < base_node));
  1076.             assert(thrust::none_of(p, z.event.node.cbegin(), z.event.node.cend(), thrust::placeholders::_1 < base_node));
  1077.  
  1078.             assert(thrust::equal(p, x.event.node.cbegin(), x.event.node.cend(), thrust::make_permutation_iterator(polygon.node.cbegin(), x.event.polygon.cbegin())));
  1079.             assert(thrust::equal(p, y.event.node.cbegin(), y.event.node.cend(), thrust::make_permutation_iterator(polygon.node.cbegin(), y.event.polygon.cbegin())));
  1080.             assert(thrust::equal(p, z.event.node.cbegin(), z.event.node.cend(), thrust::make_permutation_iterator(polygon.node.cbegin(), z.event.polygon.cbegin())));
  1081.  
  1082.             {
  1083.                 layer_node_offset.resize(node_count);
  1084.  
  1085.                 auto is_node_not_empty = [] __host__ __device__ (U node_polygon_count) -> bool { return node_polygon_count != 0; };
  1086.                 auto layer_node_begin = thrust::make_counting_iterator< U >(0);
  1087.                 auto layer_node_offset_end = thrust::copy_if(p, layer_node_begin, thrust::next(layer_node_begin, node_count), thrust::next(node.polygon_count.node.cbegin(), base_node), layer_node_offset.begin(), is_node_not_empty);
  1088.                 layer_node_offset.erase(layer_node_offset_end, layer_node_offset.end());
  1089.  
  1090.                 std::cout << "node_count = " << node_count << std::endl;
  1091.                 std::cout << "layer_node_offset_count = " << layer_node_offset.size() << std::endl;
  1092.             }
  1093. #if 0
  1094.             std::copy(x.event.node.cbegin(), x.event.node.cend(), std::ostream_iterator< U >(std::cout, ", "));
  1095.             std::cout << std::endl;
  1096.             std::copy(y.event.node.cbegin(), y.event.node.cend(), std::ostream_iterator< U >(std::cout, ", "));
  1097.             std::cout << std::endl;
  1098.             std::copy(z.event.node.cbegin(), z.event.node.cend(), std::ostream_iterator< U >(std::cout, ", "));
  1099.             std::cout << std::endl;
  1100.  
  1101.             std::copy(x.event.polygon.cbegin(), x.event.polygon.cend(), std::ostream_iterator< U >(std::cout, ", "));
  1102.             std::cout << std::endl;
  1103.             std::copy(y.event.polygon.cbegin(), y.event.polygon.cend(), std::ostream_iterator< U >(std::cout, ", "));
  1104.             std::cout << std::endl;
  1105.             std::copy(z.event.polygon.cbegin(), z.event.polygon.cend(), std::ostream_iterator< U >(std::cout, ", "));
  1106.             std::cout << std::endl;
  1107.  
  1108.             std::copy(polygon.node.cbegin(), polygon.node.cend(), std::ostream_iterator< U >(std::cout, ", "));
  1109.             std::cout << std::endl;
  1110.             std::copy(polygon.node.cbegin(), polygon.node.cend(), std::ostream_iterator< U >(std::cout, ", "));
  1111.             std::cout << std::endl;
  1112.             std::copy(polygon.node.cbegin(), polygon.node.cend(), std::ostream_iterator< U >(std::cout, ", "));
  1113.             std::cout << std::endl;
  1114. #endif
  1115.  
  1116.             x.find_perfect_split(sah, node_count, layer_node_offset, y, z);
  1117.             y.find_perfect_split(sah, node_count, layer_node_offset, z, x);
  1118.             z.find_perfect_split(sah, node_count, layer_node_offset, x, y);
  1119.  
  1120.             calculate_node_best_split(sah, base_node, node_count);
  1121.  
  1122.             auto node_split_dimension_begin = thrust::next(node.split_dimension.cbegin(), base_node);
  1123.             auto completed_node_count = U(thrust::count(p, node_split_dimension_begin, thrust::next(node_split_dimension_begin, node_count), I(-1)));
  1124.             std::cout << "completed node count " << completed_node_count << ' ' << node_count << std::endl;
  1125.             if (completed_node_count == node_count) {
  1126.                 break;
  1127.             }
  1128.  
  1129.             auto polygon_count = U(polygon.triangle.size());
  1130.  
  1131. #ifdef NDEBUG
  1132.             polygon.side.resize(polygon_count);
  1133.             polygon.event.l.resize(polygon_count);
  1134.             polygon.event.r.resize(polygon_count);
  1135. #else
  1136.             polygon.side.assign(polygon_count, I(101325));
  1137.             polygon.event.l.assign(polygon_count, U(~0u));
  1138.             polygon.event.r.resize(polygon_count, U(~0u));
  1139. #endif
  1140.  
  1141.             x.calculate_polygon_side(node.split_dimension, base_node, polygon.event.l, polygon.event.r, polygon.side);
  1142.             y.calculate_polygon_side(node.split_dimension, base_node, polygon.event.l, polygon.event.r, polygon.side);
  1143.             z.calculate_polygon_side(node.split_dimension, base_node, polygon.event.l, polygon.event.r, polygon.side);
  1144.  
  1145.             U splitted_polygon_count = get_splitted_polygon_count(base_node, node_count);
  1146.  
  1147.             std::cout << "splitted_polygon_count = " << splitted_polygon_count << "\n";
  1148.  
  1149.             { // generate index for child node
  1150.                 auto node_l_begin = thrust::next(node.l.begin(), base_node);
  1151.                 auto to_node_count = [] __host__ __device__ (I node_split_dimension) -> U { return (node_split_dimension < 0) ? 0 : 2; };
  1152.                 auto node_l_end = thrust::transform_exclusive_scan(p, node_split_dimension_begin, thrust::next(node_split_dimension_begin, node_count), node_l_begin, to_node_count, base_node + node_count, thrust::plus< U >{});
  1153.  
  1154.                 auto node_r_begin = thrust::next(node.r.begin(), base_node);
  1155.                 auto to_node_r = [] __host__ __device__ (U node_l) { return node_l + 1; };
  1156.                 thrust::transform(p, node_l_begin, node_l_end, node_r_begin, to_node_r);
  1157.             }
  1158.  
  1159.             separate_splitted_polygon(base_node, polygon_count, splitted_polygon_count);
  1160.             // filled polygon.triangle and polygon.node (copied) for splitted polygons
  1161.  
  1162.             x.decouple_lr_event(node.split_dimension, polygon.side);
  1163.             y.decouple_lr_event(node.split_dimension, polygon.side);
  1164.             z.decouple_lr_event(node.split_dimension, polygon.side);
  1165.             // l and r event indices are copied
  1166.  
  1167.             update_polygon_node(base_node, polygon_count);
  1168.             // l and r polygon nodes updated, splitted polygon node turned into corresponding l polygon node
  1169.  
  1170.             x.split_polygon(node.split_dimension, node.split_pos, polygon.triangle, polygon.node, polygon_count, splitted_polygon_count, splitted_polygon, y, z);
  1171.             y.split_polygon(node.split_dimension, node.split_pos, polygon.triangle, polygon.node, polygon_count, splitted_polygon_count, splitted_polygon, z, x);
  1172.             z.split_polygon(node.split_dimension, node.split_pos, polygon.triangle, polygon.node, polygon_count, splitted_polygon_count, splitted_polygon, x, y);
  1173.             // bboxes of polygones resulting after split are updated (unsing polygon.node from splitted polygones part)
  1174.  
  1175.             update_splitted_polygon_node(polygon_count, splitted_polygon_count);
  1176.  
  1177.             x.merge_event(polygon_count, polygon.node, splitted_polygon_count, splitted_polygon);
  1178.             y.merge_event(polygon_count, polygon.node, splitted_polygon_count, splitted_polygon);
  1179.             z.merge_event(polygon_count, polygon.node, splitted_polygon_count, splitted_polygon);
  1180.  
  1181.             U prev_base_node = base_node;
  1182.             base_node += node_count;
  1183.             node_count -= completed_node_count;
  1184.             node_count += node_count;
  1185.  
  1186.             node.polygon_count.node.resize(base_node + node_count);
  1187.  
  1188.             auto is_not_leaf = [] __host__ __device__ (I node_split_dimension) -> bool { return !(node_split_dimension < 0); };
  1189.  
  1190.             thrust::scatter_if(p, thrust::next(node.polygon_count.l.cbegin(), prev_base_node), thrust::next(node.polygon_count.l.cbegin(), base_node), thrust::next(node.l.cbegin(), prev_base_node), node_split_dimension_begin, node.polygon_count.node.begin(), is_not_leaf);
  1191.             thrust::scatter_if(p, thrust::next(node.polygon_count.r.cbegin(), prev_base_node), thrust::next(node.polygon_count.r.cbegin(), base_node), thrust::next(node.r.cbegin(), prev_base_node), node_split_dimension_begin, node.polygon_count.node.begin(), is_not_leaf);
  1192.  
  1193.             x.set_node_count(base_node + node_count);
  1194.             y.set_node_count(base_node + node_count);
  1195.             z.set_node_count(base_node + node_count);
  1196.  
  1197.             // at first copy parent bbox to children one
  1198.             auto node_bbox_begin = thrust::make_zip_iterator(thrust::make_tuple(x.node.min.begin(), x.node.max.begin(), y.node.min.begin(), y.node.max.begin(), z.node.min.begin(), z.node.max.begin()));
  1199.             auto layer_bbox_begin = thrust::next(node_bbox_begin, prev_base_node);
  1200.             auto layer_bbox_end = thrust::next(node_bbox_begin, base_node);
  1201.             thrust::scatter_if(p, layer_bbox_begin, layer_bbox_end, thrust::next(node.l.cbegin(), prev_base_node), node_split_dimension_begin, node_bbox_begin, is_not_leaf);
  1202.             thrust::scatter_if(p, layer_bbox_begin, layer_bbox_end, thrust::next(node.r.cbegin(), prev_base_node), node_split_dimension_begin, node_bbox_begin, is_not_leaf);
  1203.  
  1204.             // then move wall
  1205.             x.split_node(prev_base_node, base_node, node.split_dimension, node.split_pos, node.l, node.r);
  1206.             y.split_node(prev_base_node, base_node, node.split_dimension, node.split_pos, node.l, node.r);
  1207.             z.split_node(prev_base_node, base_node, node.split_dimension, node.split_pos, node.l, node.r);
  1208.  
  1209.             node.split_dimension.resize(base_node + node_count, I(-1));
  1210.             node.split_pos.resize(base_node + node_count);
  1211.             node.l.resize(base_node + node_count);
  1212.             node.r.resize(base_node + node_count);
  1213.             node.polygon_count.l.resize(base_node + node_count);
  1214.             node.polygon_count.r.resize(base_node + node_count);
  1215.         }
  1216.         // calculate node parent
  1217.         // sort value (polygon) by key (polygon.node)
  1218.         // reduce value (counter, 1) by operation (project1st, plus) and key (node) to (key (node), value (offset, count))
  1219.         // scatter value (offset, count) to (node.l, node.r) at key (node)
  1220.         return {};
  1221.     }
  1222.  
  1223. };
  1224.  
  1225. template< template< typename ... > class container, typename policy >
  1226. builder< policy, container > make_builder(const policy & p)
  1227. {
  1228.     return {p};
  1229. }
  1230.  
  1231. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement