Voxel
 All Classes Namespaces Files Functions Typedefs Enumerations Enumerator Macros Pages
synchronized_detail_octree.h
1 #pragma once
2 
3 #ifndef SYNCHRONIZED_TEXTURE_HEAP_DETAIL_OCTREE_H
4 #define SYNCHRONIZED_TEXTURE_HEAP_DETAIL_OCTREE_H
5 
6 
7 
8 
9 #include "vector.h"
10 
11 #include <memory>
12 
13 
14 
15 
16 namespace Synchronized {
17 
18 
19 namespace detail {
20 
21 
22 
23 
24 /*==============================================================================
25  Octree class
26 ==============================================================================*/
27 
28 
29 struct Octree {
30 
31  inline Octree( unsigned int const height = 0 );
32 
33 
34  inline unsigned int const Height() const;
35 
36 
37  inline Vector< size_t, 3 > Fill( unsigned int const logSize );
38 
39 
40  inline unsigned int const CountLeaves() const;
41 
42  template< typename t_Iterator > // points to std::pair< Vector< unsigned int, 3 >, unsigned int >, which is a coordinate,logSize pair
43  inline void Leaves( t_Iterator const& destination ) const;
44 
45 
46  // logSize is the height at which to insert the node
47  void Insert( Vector< unsigned int, 3 > const& coordinates, unsigned int const logSize );
48 
49  // logSize is the height from which to erase the node. return value is the coordinates from which it was erased. throws on failure
50  Vector< unsigned int, 3 > const Erase( unsigned int const logSize );
51 
52 
53 private:
54 
55  struct Node {
56 
57  inline Node();
58  inline Node( unsigned int const splits );
59 
60 
61  unsigned int const CountLeaves() const;
62 
63  template< typename t_Iterator >
64  void Leaves(
65  t_Iterator& destination,
66  Vector< unsigned int, 3 >& coordinates,
67  unsigned int const height
68  ) const;
69 
70 
71  bool const FindInsert( // returns true if this node was previously not filled, but now is
72  Vector< unsigned int, 3 > const& coordinates,
73  unsigned int const logSize,
74  unsigned int const height
75  );
76 
77  bool const Insert( // returns true if this node was previously not filled, but now is
78  Vector< unsigned int, 3 > const& coordinates,
79  unsigned int const logSize,
80  unsigned int const height
81  );
82 
83 
84  bool const Erase(
85  Vector< unsigned int, 3 >& coordinates,
86  std::unique_ptr< Node >& owner,
87  unsigned int const logSize,
88  unsigned int const height
89  );
90 
91 
92  private:
93 
94  std::unique_ptr< Node > m_children[ 8 ];
95  };
96 
97 
98  std::unique_ptr< Node > m_root;
99  unsigned int m_height;
100 };
101 
102 
103 
104 
105 /*==============================================================================
106  Octree methods
107 ==============================================================================*/
108 
109 
110 Octree::Octree( unsigned int const height ) : m_height( height ) {
111 }
112 
113 
114 unsigned int const Octree::Height() const {
115 
116  return m_height;
117 }
118 
119 
120 Vector< size_t, 3 > Octree::Fill( unsigned int const logSize ) {
121 
122  Vector< unsigned int, 3 > logSizes;
123  logSizes[ 2 ] = logSize / 3;
124  logSizes[ 1 ] = ( logSize - logSizes[ 2 ] ) / 2;
125  logSizes[ 0 ] = logSize - logSizes[ 1 ] - logSizes[ 2 ];
126  assert( ( logSizes[ 0 ] >= logSizes[ 1 ] ) && ( logSizes[ 1 ] >= logSizes[ 2 ] ) );
127  assert( logSizes[ 2 ] + 1 >= logSizes[ 0 ] );
128 
129  unsigned int splits = 0;
130  if ( logSizes[ 1 ] < logSizes[ 0 ] )
131  ++splits;
132  if ( logSizes[ 2 ] < logSizes[ 0 ] )
133  ++splits;
134 
135  m_root.reset( new Node( splits ) );
136  m_height = logSizes[ 0 ];
137 
138  Vector< size_t, 3 > size = { { 1, 1, 1 } };
139  size <<= logSizes;
140  return size;
141 }
142 
143 
144 unsigned int const Octree::CountLeaves() const {
145 
146  unsigned int result = 0;
147  if ( m_root )
148  result = m_root->CountLeaves();
149  return result;
150 }
151 
152 
153 template< typename t_Iterator >
154 void Octree::Leaves( t_Iterator const& destination ) const {
155 
156  if ( m_root ) {
157 
158  t_Iterator destinationCopy = destination;
159  Vector< unsigned int, 3 > coordinates = { { 0, 0, 0 } };
160  m_root->Leaves( destinationCopy, coordinates, m_height );
161  }
162 }
163 
164 
165 
166 
167 /*==============================================================================
168  Octree::Node methods
169 ==============================================================================*/
170 
171 
172 Octree::Node::Node() {
173 }
174 
175 
176 Octree::Node::Node( unsigned int const splits ) {
177 
178  assert( ( splits >= 0 ) && ( splits < 3 ) );
179 
180  if ( splits > 0 ) {
181 
182  unsigned int const children = ( 1u << ( 3 - splits ) );
183  for ( unsigned int ii = 0; ii < children; ++ii )
184  m_children[ ii ].reset( new Node );
185  }
186 }
187 
188 
189 template< typename t_Iterator >
190 void Octree::Node::Leaves( t_Iterator& destination, Vector< unsigned int, 3 >& coordinates, unsigned int const height ) const {
191 
192  unsigned int children = 0;
193 
194  for ( unsigned int ii = 0; ii < 8; ++ii ) {
195 
196  if ( m_children[ ii ] ) {
197 
198  coordinates &= ~( ( 1u << height ) - 1 );
199  if ( ii & 1 )
200  coordinates[ 0 ] |= ( 1u << ( height - 1 ) );
201  if ( ii & 2 )
202  coordinates[ 1 ] |= ( 1u << ( height - 1 ) );
203  if ( ii & 4 )
204  coordinates[ 2 ] |= ( 1u << ( height - 1 ) );
205 
206  m_children[ ii ]->Leaves( destination, coordinates, height - 1 );
207  ++children;
208  }
209  }
210 
211  if ( children == 0 ) {
212 
213  *destination = std::pair< Vector< unsigned int, 3 >, unsigned int >( coordinates, height );
214  ++destination;
215  }
216 }
217 
218 
219 
220 
221 } // namespace detail
222 
223 
224 } // namespace Synchronized
225 
226 
227 
228 
229 #endif // SYNCHRONIZED_TEXTURE_HEAP_DETAIL_OCTREE_H