Fermat
bvh_inline.h
1 /*
2  * Copyright (c) 2010-2018, NVIDIA Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of NVIDIA Corporation nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 namespace cugar{
29 
30 template <uint32 DIM>
32 {
33  // constructor
34  Bvh_partitioner(const uint32 split_dim, const float split_plane) :
35  m_split_dim( split_dim ),
36  m_split_plane( split_plane )
37  {}
38 
39  // partitioner functor
40  bool operator()(
41  const typename Bvh_builder<DIM>::Point& v) const { return v.center(m_split_dim) < m_split_plane; }
42 
43  uint32 m_split_dim;
44  float m_split_plane;
45 };
46 
47 template <uint32 DIM>
48 uint32 largest_dim(const Vector<float,DIM>& v)
49 {
50  return uint32( std::max_element( &v[0], &v[0] + DIM ) - &v[0] );
51 }
52 
53 inline void build_skip_nodes(const Bvh_node* nodes, uint32* skip_nodes)
54 {
55  std::stack< std::pair<uint32,uint32> > node_stack;
56 
57  node_stack.push( std::make_pair(0u,Bvh_node::kInvalid) );
58 
59  while (!node_stack.empty())
60  {
61  const uint32 node_id = node_stack.top().first;
62  const uint32 skip_node = node_stack.top().second;
63  node_stack.pop();
64 
65  skip_nodes[node_id] = skip_node;
66 
67  if (!nodes[node_id].is_leaf())
68  {
69  node_stack.push( std::make_pair(nodes[node_id].get_child(0u), nodes[node_id].get_child(1u)) );
70  node_stack.push( std::make_pair(nodes[node_id].get_child(1u), skip_node) );
71  }
72  }
73 }
74 
75 template <uint32 DIM>
76 template <typename Iterator>
78  const Iterator begin,
79  const Iterator end,
80  Bvh<DIM>* bvh)
81 {
82  m_points.resize( end - begin );
83 
84  uint32 i = 0;
85  for (Iterator it = begin; it != end; ++it, ++i)
86  {
87  m_points[i].m_bbox = *it;
88  m_points[i].m_index = i;
89  }
90 
91  Node node;
92  node.m_begin = 0u;
93  node.m_end = uint32(end - begin);
94  node.m_depth = 0u;
95  node.m_node = 0u;
96 
97  Node_stack node_stack;
98  node_stack.push( node );
99 
100  Bvh_node root( Bvh_node::kLeaf, node.m_begin, node.m_end );
101  bvh->m_nodes.erase( bvh->m_nodes.begin(), bvh->m_nodes.end() );
102  bvh->m_nodes.push_back( root );
103  bvh->m_bboxes.resize( 1u );
104 
105  while (node_stack.empty() == false)
106  {
107  const Node node = node_stack.top();
108  node_stack.pop();
109 
110  const uint32 node_index = node.m_node;
111 
112  bbox_type bbox;
113  compute_bbox( node.m_begin, node.m_end, bbox );
114 
115  bvh->m_bboxes[ node_index ] = bbox;
116 
117  if (node.m_end - node.m_begin < m_max_leaf_size)
118  {
119  //
120  // Make a leaf node
121  //
122  Bvh_node& bvh_node = bvh->m_nodes[ node_index ];
123  bvh_node = Bvh_node( Bvh_node::kLeaf, node.m_begin, node.m_end );
124  }
125  else
126  {
127  //
128  // Make a split node
129  //
130 
131  // alloc space for children
132  const uint32 left_node_index = uint32( bvh->m_nodes.size() );
133  bvh->m_nodes.resize( left_node_index + 2 );
134  bvh->m_bboxes.resize( left_node_index + 2 );
135 
136  Bvh_node& bvh_node = bvh->m_nodes[ node_index ];
137  bvh_node = Bvh_node( Bvh_node::kInternal, left_node_index, node.m_end - node.m_begin );
138 
139  // find split plane
140  const uint32 split_dim = largest_dim( bbox[1] - bbox[0] );
141  const float split_plane = (bbox[1][split_dim] + bbox[0][split_dim]) * 0.5f;
142 
143  // partition the points
144  Bvh_partitioner partitioner( split_dim, split_plane );
145  uint32 middle = uint32(
146  std::partition( &m_points[0] + node.m_begin, &m_points[0] + node.m_end, partitioner ) -
147  &m_points[0] );
148 
149  // unsuccessful split: split in two equally sized subsets
150  if (middle == node.m_begin ||
151  middle == node.m_end)
152  middle = (node.m_begin + node.m_end) / 2;
153 
154  // push left and right children in processing queue
155  Node right_node;
156  right_node.m_begin = middle;
157  right_node.m_end = node.m_end;
158  right_node.m_depth = node.m_depth + 1u;
159  right_node.m_node = left_node_index + 1u;
160  node_stack.push( right_node );
161 
162  Node left_node;
163  left_node.m_begin = node.m_begin;
164  left_node.m_end = middle;
165  left_node.m_depth = node.m_depth + 1u;
166  left_node.m_node = left_node_index;
167  node_stack.push( left_node );
168  }
169  }
170 }
171 
172 template <uint32 DIM>
174  const uint32 begin,
175  const uint32 end,
176  bbox_type& bbox)
177 {
178  bbox.clear();
179  for (uint32 i = begin; i < end; i++)
180  bbox.insert( m_points[i].m_bbox );
181 }
182 
183 // compute SAH cost of a subtree
184 inline float compute_sah_cost(const Bvh<3>& bvh, uint32 node_index)
185 {
186  const Bvh_node node = bvh.m_nodes[ node_index ];
187 
188  if (node.is_leaf())
189  {
190  return float( node.get_leaf_size() );
191  }
192  else
193  {
194  const float cost1 = compute_sah_cost( bvh, node.get_child(0) );
195  const float cost2 = compute_sah_cost( bvh, node.get_child(1) );
196 
197  const Bbox3f bbox1 = bvh.m_bboxes[ node.get_child(0) ];
198  const Bbox3f bbox2 = bvh.m_bboxes[ node.get_child(1) ];
199 
200  const Bbox3f bbox = bvh.m_bboxes[ node_index ];
201 
202  return 2.0f + (area( bbox1 ) * cost1 + area( bbox2 ) * cost2) / std::max( area( bbox ), 1.0e-6f );
203  }
204 }
205 
206 } // namespace cugar
CUGAR_HOST CUGAR_DEVICE void clear()
Definition: bbox_inline.h:85
thrust::device_vector< T >::iterator begin(thrust::device_vector< T > &vec)
Definition: thrust_view.h:89
Definition: bvh_node.h:45
void build_skip_nodes(const Bvh_node *nodes, uint32 *skip_nodes)
build skip nodes for a tree
Definition: bvh_inline.h:53
Definition: bvh.h:84
Definition: vector.h:54
Define a vector_view POD type and plain_view() for std::vector.
Definition: diff.h:38
Definition: bvh_inline.h:31
void build(const Iterator begin, const Iterator end, Bvh< DIM > *bvh)
Definition: bvh_inline.h:77
CUGAR_HOST_DEVICE float area(const Bbox2f &bbox)
Definition: bbox_inline.h:134
Definition: bvh.h:99
CUGAR_HOST CUGAR_DEVICE void insert(const Vector_t &v)
Definition: bbox_inline.h:65
float compute_sah_cost(const Bvh< 3 > &bvh, uint32 node_index=0)
compute SAH cost of a subtree
Definition: bvh_inline.h:184