Voxel
 All Classes Namespaces Files Functions Typedefs Enumerations Enumerator Macros Pages
synchronized_detail_octree.cpp
1 #include "synchronized_detail_octree.h"
2 #include "exception.h"
3 
4 #include <assert.h>
5 
6 
7 
8 
9 namespace Synchronized {
10 
11 
12 namespace detail {
13 
14 
15 
16 
17 /*==============================================================================
18  Octree methods
19 ==============================================================================*/
20 
21 
22 void Octree::Insert( Vector< unsigned int, 3 > const& coordinates, unsigned int const logSize ) {
23 
24  assert( logSize <= m_height );
25 
26  assert( ( coordinates[ 0 ] & ( ( 1u << logSize ) - 1 ) ) == 0 );
27  assert( ( coordinates[ 1 ] & ( ( 1u << logSize ) - 1 ) ) == 0 );
28  assert( ( coordinates[ 2 ] & ( ( 1u << logSize ) - 1 ) ) == 0 );
29 
30  assert( ( coordinates[ 0 ] & ~( ( 1u << m_height ) - 1 ) ) == 0 );
31  assert( ( coordinates[ 1 ] & ~( ( 1u << m_height ) - 1 ) ) == 0 );
32  assert( ( coordinates[ 2 ] & ~( ( 1u << m_height ) - 1 ) ) == 0 );
33 
34  if ( m_root )
35  m_root->FindInsert( coordinates, logSize, m_height );
36  else {
37 
38  m_root.reset( new Node );
39  m_root->Insert( coordinates, logSize, m_height );
40  }
41 }
42 
43 
44 Vector< unsigned int, 3 > const Octree::Erase( unsigned int const logSize ) {
45 
46  Vector< unsigned int, 3 > coordinates = { { 0, 0, 0 } };
47  bool success = false;
48  if ( m_root && ( logSize <= m_height ) )
49  success = m_root->Erase( coordinates, m_root, logSize, m_height );
50 
51  if ( ! success )
52  THROW_EXCEPTION( "out of texture heap space!" );
53 
54  return coordinates;
55 }
56 
57 
58 
59 
60 /*==============================================================================
61  Octree::Node methods
62 ==============================================================================*/
63 
64 
65 unsigned int const Octree::Node::CountLeaves() const {
66 
67  unsigned int result = 0;
68  for ( unsigned int ii = 0; ii < 8; ++ii )
69  if ( m_children[ ii ] )
70  result += m_children[ ii ]->CountLeaves();
71 
72  // if no children, then this is a leaf
73  if ( result == 0 )
74  ++result;
75 
76  return result;
77 }
78 
79 
80 bool const Octree::Node::FindInsert(
81  Vector< unsigned int, 3 > const& coordinates,
82  unsigned int const logSize,
83  unsigned int const height
84 )
85 {
86  bool result = false;
87 
88  assert( logSize <= height );
89  unsigned int children = 0;
90  for ( unsigned int ii = 0; ii < 8; ++ii )
91  if ( m_children[ ii ] )
92  ++children;
93 
94  if ( children > 0 ) {
95 
96  if ( logSize == height ) {
97 
98  for ( unsigned int ii = 0; ii < 8; ++ii )
99  if ( m_children[ ii ] )
100  m_children[ ii ].reset();
101 
102  result = true;
103  }
104  else if ( logSize < height ) {
105 
106  unsigned int index = 0;
107  if ( coordinates[ 0 ] & ( 1u << ( height - 1 ) ) )
108  index += 1;
109  if ( coordinates[ 1 ] & ( 1u << ( height - 1 ) ) )
110  index += 2;
111  if ( coordinates[ 2 ] & ( 1u << ( height - 1 ) ) )
112  index += 4;
113 
114  bool filled = false;
115  if ( ! m_children[ index ] ) {
116 
117  m_children[ index ].reset( new Node );
118  filled = m_children[ index ]->Insert( coordinates, logSize, height - 1 );
119  ++children;
120  }
121  else
122  filled = m_children[ index ]->FindInsert( coordinates, logSize, height - 1 );
123 
124  if ( filled && ( children == 8 ) ) {
125 
126  bool grandchildren = false;
127  for ( unsigned int ii = 0; ( ! grandchildren ) && ( ii < 8 ); ++ii )
128  if ( ii != index )
129  for ( unsigned int jj = 0; ( ! grandchildren ) && ( jj < 8 ); ++jj )
130  grandchildren |= static_cast< bool >( m_children[ ii ]->m_children[ jj ] );
131 
132  if ( ! grandchildren ) {
133 
134  for ( unsigned int ii = 0; ii < 8; ++ii )
135  m_children[ ii ].reset();
136 
137  result = true;
138  }
139  }
140  }
141  }
142 
143  return result;
144 }
145 
146 
147 bool const Octree::Node::Insert(
148  Vector< unsigned int, 3 > const& coordinates,
149  unsigned int const logSize,
150  unsigned int const height
151 )
152 {
153  bool result = true;
154 
155  assert( logSize <= height );
156  if ( logSize < height ) {
157 
158  unsigned int index = 0;
159  if ( coordinates[ 0 ] & ( 1u << ( height - 1 ) ) )
160  index += 1;
161  if ( coordinates[ 1 ] & ( 1u << ( height - 1 ) ) )
162  index += 2;
163  if ( coordinates[ 2 ] & ( 1u << ( height - 1 ) ) )
164  index += 4;
165 
166  assert( ! m_children[ index ] );
167  m_children[ index ].reset( new Node );
168  m_children[ index ]->Insert( coordinates, logSize, height - 1 );
169 
170  result = false;
171  }
172 
173  return result;
174 }
175 
176 
177 bool const Octree::Node::Erase(
178  Vector< unsigned int, 3 >& coordinates,
179  std::unique_ptr< Node >& owner,
180  unsigned int const logSize,
181  unsigned int const height
182 )
183 {
184  bool result = false;
185 
186  assert( logSize <= height );
187  unsigned int children = 0;
188  for ( unsigned int ii = 0; ii < 8; ++ii )
189  if ( m_children[ ii ] )
190  ++children;
191 
192  if ( logSize == height ) {
193 
194  if ( children == 0 ) {
195 
196  owner.reset();
197  result = true;
198  }
199  }
200  else if ( logSize < height ) {
201 
202  if ( children == 0 ) {
203 
204  if ( logSize + 1 == height ) {
205 
206  for ( unsigned int ii = 1; ii < 8; ++ii )
207  m_children[ ii ].reset( new Node );
208  }
209  else {
210 
211  for ( unsigned int ii = 0; ii < 8; ++ii )
212  m_children[ ii ].reset( new Node );
213 
214  result = m_children[ 0 ]->Erase( coordinates, m_children[ 0 ], logSize, height - 1 );
215  assert( result );
216  }
217 
218  result = true;
219  }
220  else {
221 
222  for ( unsigned int ii = 0; ii < 8; ++ii ) {
223 
224  if ( m_children[ ii ] ) {
225 
226  if ( m_children[ ii ]->Erase( coordinates, m_children[ ii ], logSize, height - 1 ) ) {
227 
228  if ( ! m_children[ ii ] )
229  --children;
230 
231  if ( ii & 1 )
232  coordinates[ 0 ] |= ( 1u << ( height - 1 ) );
233  if ( ii & 2 )
234  coordinates[ 1 ] |= ( 1u << ( height - 1 ) );
235  if ( ii & 4 )
236  coordinates[ 2 ] |= ( 1u << ( height - 1 ) );
237 
238  result = true;
239  break;
240  }
241  }
242  }
243 
244  if ( children == 0 )
245  owner.reset();
246  }
247  }
248 
249  return result;
250 }
251 
252 
253 
254 
255 } // namespace detail
256 
257 
258 } // namespace Synchronized