Fermat
bintree_visitor.h
Go to the documentation of this file.
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 
32 #pragma once
33 
34 #include <cugar/basic/types.h>
35 
36 namespace cugar {
37 
40 
44 template <typename node_type, typename leaf_type = typename node_type::node_tag>
45 struct Bintree_visitor {};
46 
50 template <typename Node_type>
51 struct Bintree_visitor<Node_type, leaf_index_tag>
52 {
53  typedef Node_type node_type;
54 
58  m_num_nodes(0), m_num_leaves(0), m_nodes(NULL), m_node_sizes(NULL), m_leaf_pointers(NULL), m_leaf_ranges(NULL), m_parents(NULL), m_skip_nodes(NULL) {}
59 
60  void set_node_count(const uint32 num_nodes) { m_num_nodes = num_nodes; }
61  void set_leaf_count(const uint32 num_leaves) { m_num_leaves = num_leaves; }
62 
63  void set_nodes(const node_type* nodes) { m_nodes = nodes; }
64  void set_parents(const uint32* parents) { m_parents = parents; }
65  void set_skip_nodes(const uint32* skip_nodes) { m_skip_nodes = skip_nodes; }
66  void set_leaf_pointers(const uint32* leaf_pointers) { m_leaf_pointers = leaf_pointers; }
67  void set_leaf_ranges(const uint2* leaf_ranges) { m_leaf_ranges = leaf_ranges; }
68 
71  CUGAR_HOST_DEVICE uint32 get_node_count() const { return m_num_nodes; }
72 
75  CUGAR_HOST_DEVICE uint32 get_leaf_count() const { return m_num_leaves; }
76 
80  CUGAR_HOST_DEVICE uint32 get_child_count(const uint32 node) const
81  {
82  return m_nodes[node].get_child_count();
83  }
84 
88  CUGAR_HOST_DEVICE bool is_leaf(const uint32 node) const
89  {
90  return m_nodes[node].is_leaf();
91  }
92 
97  CUGAR_HOST_DEVICE uint32 get_child(const uint32 node, const uint32 i) const
98  {
99  return m_nodes[node].get_child(i);
100  }
101 
105  CUGAR_HOST_DEVICE uint32 get_parent(const uint32 node) const
106  {
107  return m_parents[node];
108  }
109 
113  CUGAR_HOST_DEVICE uint32 get_skip_node(const uint32 node) const
114  {
115  return m_skip_nodes[node];
116  }
117 
121  CUGAR_HOST_DEVICE uint2 get_leaf_range(const uint32 node) const
122  {
123  const uint32 leaf_index = m_nodes[node].get_leaf_index();
124  return m_leaf_ranges ?
125  m_leaf_ranges[leaf_index] :
126  make_uint2(leaf_index,leaf_index+1);
127  }
128 
132  CUGAR_HOST_DEVICE uint32 get_range_size(const uint32 node) const
133  {
134  return m_node_sizes[node];
135  }
136 
139  CUGAR_HOST_DEVICE bool has_leaf_pointers() const { return m_leaf_pointers != NULL; }
140 
143  CUGAR_HOST_DEVICE uint32 get_leaf_node(const uint32 i) const
144  {
145  return m_leaf_pointers[i];
146  }
147 
148  uint32 m_num_nodes;
149  uint32 m_num_leaves;
150  const node_type* m_nodes;
151  const uint32* m_node_sizes;
152  const uint32* m_leaf_pointers;
153  const uint2* m_leaf_ranges;
154  const uint32* m_parents;
155  const uint32* m_skip_nodes;
156 };
157 
161 template <typename Node_type>
162 struct Bintree_visitor<Node_type, leaf_range_tag>
163 {
164  typedef Node_type node_type;
165 
169  m_num_nodes(0), m_num_leaves(0), m_nodes(NULL), m_leaf_pointers(NULL), m_parents(NULL), m_skip_nodes(NULL) {}
170 
171  void set_node_count(const uint32 num_nodes) { m_num_nodes = num_nodes; }
172  void set_leaf_count(const uint32 num_leaves) { m_num_leaves = num_leaves; }
173 
174  void set_nodes(const node_type* nodes) { m_nodes = nodes; }
175  void set_parents(const uint32* parents) { m_parents = parents; }
176  void set_skip_nodes(const uint32* skip_nodes) { m_skip_nodes = skip_nodes; }
177  void set_leaf_pointers(const uint32* leaf_pointers) { m_leaf_pointers = leaf_pointers; }
178 
181  CUGAR_HOST_DEVICE uint32 get_node_count() const { return m_num_nodes; }
182 
185  CUGAR_HOST_DEVICE uint32 get_leaf_count() const { return m_num_leaves; }
186 
190  CUGAR_HOST_DEVICE bool is_leaf(const uint32 node) const
191  {
192  return m_nodes[node].is_leaf() ? true : false;
193  }
194 
198  CUGAR_HOST_DEVICE uint32 get_child_count(const uint32 node) const
199  {
200  return m_nodes[node].get_child_count();
201  }
202 
207  CUGAR_HOST_DEVICE uint32 get_child(const uint32 node, const uint32 i) const
208  {
209  return m_nodes[node].get_child(i);
210  }
211 
215  CUGAR_HOST_DEVICE uint32 get_parent(const uint32 node) const
216  {
217  return m_parents[node];
218  }
219 
223  CUGAR_HOST_DEVICE uint32 get_skip_node(const uint32 node) const
224  {
225  return m_skip_nodes[node];
226  }
227 
231  CUGAR_HOST_DEVICE uint2 get_leaf_range(const uint32 node) const
232  {
233  return m_nodes[node].get_leaf_range();
234  }
235 
239  CUGAR_HOST_DEVICE uint32 get_range_size(const uint32 node) const
240  {
241  return m_nodes[node].get_range_size();
242  }
243 
246  CUGAR_HOST_DEVICE bool has_leaf_pointers() const { return m_leaf_pointers != NULL; }
247 
250  CUGAR_HOST_DEVICE uint32 get_leaf_node(const uint32 i) const
251  {
252  return m_leaf_pointers[i];
253  }
254 
255  uint32 m_num_nodes;
256  uint32 m_num_leaves;
257  const node_type* m_nodes;
258  const uint32* m_leaf_pointers;
259  const uint32* m_parents;
260  const uint32* m_skip_nodes;
261 };
262 
263 template <typename bvh_visitor_type>
264 void check_tree_rec(const uint32 node_id, const uint32 parent_id, const bvh_visitor_type& visitor, const uint32 n_prims, const uint32 max_leaf_size)
265 {
266  // check the parent pointer
267  if (parent_id != visitor.get_parent( node_id ))
268  throw cugar::logic_error("node[%u] has wrong parent: %u != %u", node_id, parent_id, visitor.get_parent( node_id ));
269 
270  if (visitor.is_leaf( node_id ) == false)
271  {
272  // check the number of children
273  const uint32 child_count = visitor.get_child_count( node_id );
274  if (child_count == 0 || child_count > 2)
275  throw cugar::logic_error("node[%u] has %u children", node_id, child_count);
276 
277  // check the children
278  for (uint32 i = 0; i < 2; ++i)
279  {
280  const uint32 child_id = visitor.get_child( node_id, i );
281  if (child_id >= visitor.get_node_count())
282  throw cugar::logic_error("node[%u].child(%u) out of bounds : %u / %u", node_id, i, child_id, visitor.get_node_count());
283 
284  check_tree_rec( child_id, node_id, visitor, n_prims, max_leaf_size );
285  }
286  }
287  else
288  {
289  // check the leaf range
290  const uint2 leaf_range = visitor.get_leaf_range( node_id );
291 
292  // check for malformed ranges
293  if (leaf_range.x > leaf_range.y)
294  throw cugar::logic_error("leaf[%u] : malformed range (%u, %u)", node_id, leaf_range.x, leaf_range.y);
295 
296  // check for out-of-bounds primitive indices
297  if (leaf_range.y > n_prims)
298  throw cugar::logic_error("leaf[%u] : range out of bounds (%u, %u) / %u", node_id, leaf_range.x, leaf_range.y, n_prims);
299 
300  // check for out-of-bounds primitive indices
301  if (leaf_range.y - leaf_range.x > max_leaf_size)
302  throw cugar::logic_error("leaf[%u] : maximum size overflow (%u, %u) / %u", node_id, leaf_range.x, leaf_range.y, max_leaf_size);
303  }
304 }
305 
308 template <typename node_type, typename leaf_type>
309 void check_tree(const Bintree_visitor<node_type,leaf_type>& visitor, const uint32 n_prims, const uint32 max_leaf_size = uint32(-1))
310 {
311  check_tree_rec( 0u, uint32(-1), visitor, n_prims, max_leaf_size );
312 }
313 
315 
316 } // namespace cugar
CUGAR_HOST_DEVICE uint32 get_leaf_node(const uint32 i) const
Definition: bintree_visitor.h:250
Bintree_visitor()
Definition: bintree_visitor.h:168
Definition: exceptions.h:72
CUGAR_HOST_DEVICE uint32 get_leaf_count() const
Definition: bintree_visitor.h:185
CUGAR_HOST_DEVICE uint32 get_range_size(const uint32 node) const
Definition: bintree_visitor.h:132
Definition: bintree_node.h:56
CUGAR_HOST_DEVICE uint32 get_skip_node(const uint32 node) const
Definition: bintree_visitor.h:113
CUGAR_HOST_DEVICE bool is_leaf(const uint32 node) const
Definition: bintree_visitor.h:88
CUGAR_HOST_DEVICE uint32 get_child(const uint32 node, const uint32 i) const
Definition: bintree_visitor.h:97
CUGAR_HOST_DEVICE uint2 get_leaf_range(const uint32 node) const
Definition: bintree_visitor.h:231
CUGAR_HOST_DEVICE uint32 get_parent(const uint32 node) const
Definition: bintree_visitor.h:215
CUGAR_HOST_DEVICE bool has_leaf_pointers() const
Definition: bintree_visitor.h:139
CUGAR_HOST_DEVICE uint32 get_range_size(const uint32 node) const
Definition: bintree_visitor.h:239
Bintree_visitor()
Definition: bintree_visitor.h:57
void check_tree(const Bintree_visitor< node_type, leaf_type > &visitor, const uint32 n_prims, const uint32 max_leaf_size=uint32(-1))
Definition: bintree_visitor.h:309
CUGAR_HOST_DEVICE uint32 get_skip_node(const uint32 node) const
Definition: bintree_visitor.h:223
CUGAR_HOST_DEVICE uint32 get_parent(const uint32 node) const
Definition: bintree_visitor.h:105
CUGAR_HOST_DEVICE uint32 get_node_count() const
Definition: bintree_visitor.h:71
Define a vector_view POD type and plain_view() for std::vector.
Definition: diff.h:38
Definition: bintree_visitor.h:45
Definition: bintree_node.h:60
CUGAR_HOST_DEVICE uint32 get_child_count(const uint32 node) const
Definition: bintree_visitor.h:80
CUGAR_HOST_DEVICE uint32 get_leaf_node(const uint32 i) const
Definition: bintree_visitor.h:143
CUGAR_HOST_DEVICE bool has_leaf_pointers() const
Definition: bintree_visitor.h:246
CUGAR_HOST_DEVICE uint32 get_node_count() const
Definition: bintree_visitor.h:181
CUGAR_HOST_DEVICE uint32 get_leaf_count() const
Definition: bintree_visitor.h:75
CUGAR_HOST_DEVICE uint32 get_child_count(const uint32 node) const
Definition: bintree_visitor.h:198
CUGAR_HOST_DEVICE uint2 get_leaf_range(const uint32 node) const
Definition: bintree_visitor.h:121
CUGAR_HOST_DEVICE bool is_leaf(const uint32 node) const
Definition: bintree_visitor.h:190
CUGAR_HOST_DEVICE uint32 get_child(const uint32 node, const uint32 i) const
Definition: bintree_visitor.h:207