(0x40000000);
55 |
56 |
57 | /// standard object services ---------------------------------------------------
58 | OctreeDimensions::OctreeDimensions
59 | (
60 | const Vector3r& positionOfLowerCorner,
61 | const real size,
62 | const dword maxItemsPerCell,
63 | const dword maxLevelCount,
64 | const real minCellSize
65 | )
66 | : positionOfLowerCorner_m( positionOfLowerCorner )
67 | , size_m ( size >= 0.0f ? size : -size )
68 | , maxItemsPerCell_m ( maxItemsPerCell > 0 ? maxItemsPerCell : 1 )
69 | , maxLevel_m ( maxLevelCount > 0 ? maxLevelCount - 1 : 0 )
70 | , minSize_m ( minCellSize <= size_m ? minCellSize : size_m )
71 | {
72 | if( maxLevel_m > MAX_LEVEL )
73 | {
74 | maxLevel_m = MAX_LEVEL;
75 | }
76 | if( minSize_m < MIN_SIZE )
77 | {
78 | minSize_m = MIN_SIZE;
79 | }
80 | }
81 |
82 |
83 | OctreeDimensions::~OctreeDimensions()
84 | {
85 | }
86 |
87 |
88 | OctreeDimensions::OctreeDimensions
89 | (
90 | const OctreeDimensions& other
91 | )
92 | : positionOfLowerCorner_m( other.positionOfLowerCorner_m )
93 | , size_m ( other.size_m )
94 | , maxItemsPerCell_m ( other.maxItemsPerCell_m )
95 | , maxLevel_m ( other.maxLevel_m )
96 | , minSize_m ( other.minSize_m )
97 | {
98 | }
99 |
100 |
101 | OctreeDimensions& OctreeDimensions::operator=
102 | (
103 | const OctreeDimensions& other
104 | )
105 | {
106 | if( &other != this )
107 | {
108 | positionOfLowerCorner_m = other.positionOfLowerCorner_m;
109 | size_m = other.size_m;
110 | maxItemsPerCell_m = other.maxItemsPerCell_m;
111 | maxLevel_m = other.maxLevel_m;
112 | minSize_m = other.minSize_m;
113 | }
114 |
115 | return *this;
116 | }
117 |
118 |
119 |
120 |
121 | /// queries --------------------------------------------------------------------
122 | bool OctreeDimensions::isSubdivide
123 | (
124 | const dword itemCount,
125 | const dword level,
126 | const real size
127 | ) const
128 | {
129 | return (itemCount > maxItemsPerCell_m) &
130 | (level < maxLevel_m) & (size > (minSize_m * 2.0f));
131 | }
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 | /// OctreeBound ////////////////////////////////////////////////////////////////
141 |
142 |
143 | /// standard object services ---------------------------------------------------
144 | OctreeBound::OctreeBound()
145 | : positionOfLowerCorner_m( Vector3r::ZERO() )
146 | , positionOfUpperCorner_m( Vector3r::ONE() )
147 | , center_m ( Vector3r::HALF() )
148 | , circumSphereRadius_m ( Vector3r::HALF().length() )
149 | {
150 | }
151 |
152 |
153 | OctreeBound::OctreeBound
154 | (
155 | const Vector3r& positionOfLowerCorner,
156 | const real size
157 | )
158 | : positionOfLowerCorner_m( positionOfLowerCorner )
159 | , positionOfUpperCorner_m( positionOfLowerCorner + Vector3r(size, size, size) )
160 | , center_m ( (positionOfLowerCorner_m + positionOfUpperCorner_m)
161 | *= 0.5f )
162 | , circumSphereRadius_m ( (Vector3r::HALF() * size).length() )
163 | {
164 | }
165 |
166 |
167 | OctreeBound::OctreeBound
168 | (
169 | const OctreeBound& parentCellBound,
170 | const dword subCellIndex
171 | )
172 | {
173 | {
174 | const Vector3r* lowMidHigh[] =
175 | {
176 | &(parentCellBound.positionOfLowerCorner_m),
177 | &(parentCellBound.center_m),
178 | &(parentCellBound.positionOfUpperCorner_m)
179 | };
180 |
181 | positionOfLowerCorner_m.set(
182 | lowMidHigh[ subCellIndex & 1]->getX(),
183 | lowMidHigh[(subCellIndex >> 1) & 1]->getY(),
184 | lowMidHigh[(subCellIndex >> 2) & 1]->getZ() );
185 | positionOfUpperCorner_m.set(
186 | (lowMidHigh+1)[ subCellIndex & 1]->getX(),
187 | (lowMidHigh+1)[(subCellIndex >> 1) & 1]->getY(),
188 | (lowMidHigh+1)[(subCellIndex >> 2) & 1]->getZ() );
189 | }
190 |
191 | ((center_m = positionOfLowerCorner_m) += positionOfUpperCorner_m) *= 0.5f;
192 | circumSphereRadius_m = parentCellBound.circumSphereRadius_m * 0.5f;
193 | }
194 |
195 |
196 | OctreeBound::~OctreeBound()
197 | {
198 | }
199 |
200 |
201 | OctreeBound::OctreeBound
202 | (
203 | const OctreeBound& other
204 | )
205 | : positionOfLowerCorner_m( other.positionOfLowerCorner_m )
206 | , positionOfUpperCorner_m( other.positionOfUpperCorner_m )
207 | , center_m ( other.center_m )
208 | , circumSphereRadius_m ( other.circumSphereRadius_m )
209 | {
210 | }
211 |
212 |
213 | OctreeBound& OctreeBound::operator=
214 | (
215 | const OctreeBound& other
216 | )
217 | {
218 | if( &other != this )
219 | {
220 | positionOfLowerCorner_m = other.positionOfLowerCorner_m;
221 | positionOfUpperCorner_m = other.positionOfUpperCorner_m;
222 | center_m = other.center_m;
223 | circumSphereRadius_m = other.circumSphereRadius_m;
224 | }
225 |
226 | return *this;
227 | }
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 | /// OctreeData /////////////////////////////////////////////////////////////////
237 |
238 |
239 | /// standard object services ---------------------------------------------------
240 | OctreeData::OctreeData
241 | (
242 | const OctreeDimensions& dimensions
243 | )
244 | : bound_m ( dimensions.getPosition(), dimensions.getSize() )
245 | , level_m ( 0 )
246 | , pDimensions_m( &dimensions )
247 | {
248 | }
249 |
250 |
251 | OctreeData::OctreeData
252 | (
253 | const OctreeData& parentCellData,
254 | const dword subCellIndex
255 | )
256 | : bound_m ( parentCellData.bound_m, subCellIndex )
257 | , level_m ( parentCellData.level_m + 1 )
258 | , pDimensions_m( parentCellData.pDimensions_m )
259 | {
260 | }
261 |
262 |
263 | OctreeData::OctreeData
264 | (
265 | const OctreeData& other,
266 | const OctreeDimensions& dimensions
267 | )
268 | : bound_m ( other.bound_m )
269 | , level_m ( other.level_m )
270 | , pDimensions_m( &dimensions )
271 | {
272 | }
273 |
274 |
275 | OctreeData::~OctreeData()
276 | {
277 | }
278 |
279 |
280 | OctreeData::OctreeData
281 | (
282 | const OctreeData& other
283 | )
284 | : bound_m ( other.bound_m )
285 | , level_m ( other.level_m )
286 | , pDimensions_m( other.pDimensions_m )
287 | {
288 | }
289 |
290 |
291 | OctreeData& OctreeData::operator=
292 | (
293 | const OctreeData& other
294 | )
295 | {
296 | if( &other != this )
297 | {
298 | bound_m = other.bound_m;
299 | level_m = other.level_m;
300 | pDimensions_m = other.pDimensions_m;
301 | }
302 |
303 | return *this;
304 | }
305 |
--------------------------------------------------------------------------------
/component/OctreeAuxiliary.hpp:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------------------
2 |
3 | Octree Component, version 2.1
4 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
5 |
6 | http://www.hxa7241.org/
7 |
8 | ------------------------------------------------------------------------------*/
9 |
10 | /*------------------------------------------------------------------------------
11 |
12 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
13 |
14 | Redistribution and use in source and binary forms, with or without modification,
15 | are permitted provided that the following conditions are met:
16 |
17 | * Redistributions of source code must retain the above copyright notice, this
18 | list of conditions and the following disclaimer.
19 | * Redistributions in binary form must reproduce the above copyright notice, this
20 | list of conditions and the following disclaimer in the documentation and/or
21 | other materials provided with the distribution.
22 | * The name of the author may not be used to endorse or promote products derived
23 | from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
26 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28 | SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 | OF SUCH DAMAGE.
35 |
36 | ------------------------------------------------------------------------------*/
37 |
38 |
39 | #ifndef OctreeAuxiliary_h
40 | #define OctreeAuxiliary_h
41 |
42 |
43 | #include "Array.hpp"
44 | #include "Vector3r.hpp"
45 |
46 |
47 |
48 |
49 | namespace hxa7241_graphics
50 | {
51 | using namespace hxa7241;
52 | using hxa7241_general::Array;
53 | class OctreeCell;
54 |
55 |
56 | /**
57 | * Global octree data -- one instance for whole octree.
58 | *
59 | * Constant.
60 | *
61 | * @invariants
62 | * size_m >= 0
63 | * maxItemsPerCell_m >= 1
64 | * maxLevel_m >= 0 and <= MAX_LEVEL
65 | * minSize_m >= MIN_SIZE and <= size_m
66 | */
67 | class OctreeDimensions
68 | {
69 | /// standard object services ---------------------------------------------------
70 | public:
71 | OctreeDimensions( const Vector3r& positionOfLowerCorner,
72 | real size,
73 | dword maxItemCountPerCell,
74 | dword maxLevelCount,
75 | real minCellSize );
76 |
77 | ~OctreeDimensions();
78 | OctreeDimensions( const OctreeDimensions& );
79 | OctreeDimensions& operator=( const OctreeDimensions& );
80 |
81 |
82 | /// queries --------------------------------------------------------------------
83 | const Vector3r& getPosition() const;
84 | real getSize() const;
85 | dword getMaxItemCountPerCell() const;
86 | dword getMaxLevelCount() const;
87 | real getMinCellSize() const;
88 |
89 | bool isSubdivide( dword itemCount,
90 | dword level,
91 | real size ) const;
92 |
93 |
94 | /// fields ---------------------------------------------------------------------
95 | private:
96 | Vector3r positionOfLowerCorner_m;
97 | real size_m;
98 | dword maxItemsPerCell_m;
99 | dword maxLevel_m;
100 | real minSize_m;
101 |
102 | static const dword MAX_LEVEL;
103 | static const real MIN_SIZE;
104 | };
105 |
106 |
107 |
108 |
109 | /**
110 | * Geometric data for the bound of an octree cell.
111 | *
112 | * Constant.
113 | *
114 | * Radius is that of the circumsphere.
115 | *
116 | * Subcell numbering:
117 | *
118 | * y z 6 7
119 | * |/ 2 3 4 5
120 | * -x 0 1
121 | *
122 | * in binary:
123 | *
124 | * y z 110 111
125 | * |/ 010 011 100 101
126 | * -x 000 001
127 | *
128 | */
129 | class OctreeBound
130 | {
131 | /// standard object services ---------------------------------------------------
132 | public:
133 | OctreeBound();
134 | OctreeBound( const Vector3r& positionOfLowerCorner,
135 | real size );
136 | OctreeBound( const OctreeBound& parentCellBound,
137 | dword subCellIndex );
138 |
139 | ~OctreeBound();
140 | OctreeBound( const OctreeBound& );
141 | OctreeBound& operator=( const OctreeBound& );
142 |
143 |
144 | /// queries --------------------------------------------------------------------
145 | const Vector3r& getLowerCorner() const;
146 | const Vector3r& getUpperCorner() const;
147 | const Vector3r& getCenter() const;
148 | real getRadius() const;
149 | real getSize() const;
150 |
151 |
152 | /// fields ---------------------------------------------------------------------
153 | private:
154 | Vector3r positionOfLowerCorner_m;
155 | Vector3r positionOfUpperCorner_m;
156 | Vector3r center_m;
157 | real circumSphereRadius_m;
158 | };
159 |
160 |
161 |
162 |
163 | /**
164 | * Octree cell data during traversal.
165 | *
166 | * Constant.
167 | *
168 | * To be made during each level of tree descent, so storage is avoided, except
169 | * to hold one at the root.
170 | *
171 | * Subcell numbering:
172 | *
173 | * y z 6 7
174 | * |/ 2 3 4 5
175 | * -x 0 1
176 | *
177 | * in binary:
178 | *
179 | * y z 110 111
180 | * |/ 010 011 100 101
181 | * -x 000 001
182 | *
183 | *
184 | * @see OctreeBound
185 | * @see OctreeDimensions
186 | */
187 | class OctreeData
188 | {
189 | /// standard object services ---------------------------------------------------
190 | public:
191 | explicit OctreeData( const OctreeDimensions& dimensions );
192 | OctreeData( const OctreeData& parentCellData,
193 | dword subCellIndex );
194 | OctreeData( const OctreeData&,
195 | const OctreeDimensions& );
196 |
197 | ~OctreeData();
198 | OctreeData( const OctreeData& );
199 | OctreeData& operator=( const OctreeData& );
200 |
201 |
202 | /// queries --------------------------------------------------------------------
203 | const OctreeBound& getBound() const;
204 | dword getLevel() const;
205 | const OctreeDimensions& getDimensions() const;
206 |
207 | bool isSubdivide( dword itemCount ) const;
208 |
209 |
210 | /// fields ---------------------------------------------------------------------
211 | private:
212 | // local to cell
213 | OctreeBound bound_m;
214 | dword level_m;
215 |
216 | // global for octree
217 | const OctreeDimensions* pDimensions_m;
218 | };
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 | /**
228 | * Agent abstract base, for Octree implementation use.
229 | *
230 | * Return value of getSubcellOverlapsV is 8 bits, each bit is a bool
231 | * corresponding to a subcell, the high bit for subcell 7, the low bit for
232 | * subcell 0.
233 | *
234 | * Subcell numbering:
235 | *
236 | * y z 6 7
237 | * |/ 2 3 4 5
238 | * -x 0 1
239 | *
240 | * in binary:
241 | *
242 | * y z 110 111
243 | * |/ 010 011 100 101
244 | * -x 000 001
245 | *
246 | *
247 | * @see OctreeCell
248 | * @see OctreeBranch
249 | * @see OctreeLeaf
250 | */
251 | class OctreeAgentV
252 | {
253 | /// standard object services ---------------------------------------------------
254 | protected:
255 | OctreeAgentV() {}
256 | public:
257 | virtual ~OctreeAgentV() {}
258 | private:
259 | OctreeAgentV( const OctreeAgentV& );
260 | OctreeAgentV& operator=( const OctreeAgentV& );
261 | public:
262 |
263 |
264 | /// queries --------------------------------------------------------------------
265 | virtual bool isOverlappingCellV ( const void* pItem,
266 | const Vector3r& lowerCorner,
267 | const Vector3r& upperCorner ) const =0;
268 | virtual dword getSubcellOverlapsV( const void* pItem,
269 | const Vector3r& lower,
270 | const Vector3r& middle,
271 | const Vector3r& upper ) const =0;
272 |
273 |
274 | /// constants ------------------------------------------------------------------
275 | static const dword ALL_INSIDE = 0x0000FFFF;
276 | static const dword ALL_OUTSIDE = 0x00000000;
277 | };
278 |
279 |
280 |
281 |
282 | /**
283 | * Visitor abstract base, for Octree implementation use.
284 | *
285 | * Subcell numbering:
286 | *
287 | * y z 6 7
288 | * |/ 2 3 4 5
289 | * -x 0 1
290 | *
291 | * in binary:
292 | *
293 | * y z 110 111
294 | * |/ 010 011 100 101
295 | * -x 000 001
296 | *
297 | *
298 | * @see OctreeCell
299 | * @see OctreeBranch
300 | * @see OctreeLeaf
301 | */
302 | class OctreeVisitorV
303 | {
304 | /// standard object services ---------------------------------------------------
305 | protected:
306 | OctreeVisitorV() {}
307 | public:
308 | virtual ~OctreeVisitorV() {}
309 | private:
310 | OctreeVisitorV( const OctreeVisitorV& );
311 | OctreeVisitorV& operator=( const OctreeVisitorV& );
312 | public:
313 |
314 |
315 | /// commands -------------------------------------------------------------------
316 | virtual void visitRootV ( const OctreeCell* pRootCell,
317 | const OctreeData& octreeData ) =0;
318 | virtual void visitBranchV( const OctreeCell* subCells[8],
319 | const OctreeData& octreeData ) =0;
320 | virtual void visitLeafV ( const Array& items,
321 | const OctreeData& octreeData ) =0;
322 | };
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 | /// inlines ///
332 |
333 | /// OctreeDimensions -----------------------------------------------------------
334 | inline
335 | const Vector3r& OctreeDimensions::getPosition() const
336 | {
337 | return positionOfLowerCorner_m;
338 | }
339 |
340 |
341 | inline
342 | real OctreeDimensions::getSize() const
343 | {
344 | return size_m;
345 | }
346 |
347 |
348 | inline
349 | dword OctreeDimensions::getMaxItemCountPerCell() const
350 | {
351 | return maxItemsPerCell_m;
352 | }
353 |
354 |
355 | inline
356 | dword OctreeDimensions::getMaxLevelCount() const
357 | {
358 | return maxLevel_m + 1;
359 | }
360 |
361 |
362 | inline
363 | real OctreeDimensions::getMinCellSize() const
364 | {
365 | return minSize_m;
366 | }
367 |
368 |
369 |
370 |
371 | /// OctreeBound ----------------------------------------------------------------
372 | inline
373 | const Vector3r& OctreeBound::getLowerCorner() const
374 | {
375 | return positionOfLowerCorner_m;
376 | }
377 |
378 |
379 | inline
380 | const Vector3r& OctreeBound::getUpperCorner() const
381 | {
382 | return positionOfUpperCorner_m;
383 | }
384 |
385 |
386 | inline
387 | const Vector3r& OctreeBound::getCenter() const
388 | {
389 | return center_m;
390 | }
391 |
392 |
393 | inline
394 | real OctreeBound::getRadius() const
395 | {
396 | return circumSphereRadius_m;
397 | }
398 |
399 |
400 | inline
401 | real OctreeBound::getSize() const
402 | {
403 | return positionOfUpperCorner_m.getX() - positionOfLowerCorner_m.getX();
404 | }
405 |
406 |
407 |
408 |
409 | /// OctreeData -----------------------------------------------------------------
410 | inline
411 | const OctreeBound& OctreeData::getBound() const
412 | {
413 | return bound_m;
414 | }
415 |
416 |
417 | inline
418 | dword OctreeData::getLevel() const
419 | {
420 | return level_m;
421 | }
422 |
423 |
424 | inline
425 | const OctreeDimensions& OctreeData::getDimensions() const
426 | {
427 | return *pDimensions_m;
428 | }
429 |
430 |
431 | inline
432 | bool OctreeData::isSubdivide
433 | (
434 | const dword itemCount
435 | ) const
436 | {
437 | return pDimensions_m->isSubdivide( itemCount, level_m, bound_m.getSize() );
438 | }
439 |
440 |
441 | }//namespace
442 |
443 |
444 |
445 |
446 | #endif//OctreeAuxiliary_h
447 |
--------------------------------------------------------------------------------
/component/OctreeImplementation.cpp:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------------------
2 |
3 | Octree Component, version 2.1
4 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
5 |
6 | http://www.hxa7241.org/
7 |
8 | ------------------------------------------------------------------------------*/
9 |
10 | /*------------------------------------------------------------------------------
11 |
12 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
13 |
14 | Redistribution and use in source and binary forms, with or without modification,
15 | are permitted provided that the following conditions are met:
16 |
17 | * Redistributions of source code must retain the above copyright notice, this
18 | list of conditions and the following disclaimer.
19 | * Redistributions in binary form must reproduce the above copyright notice, this
20 | list of conditions and the following disclaimer in the documentation and/or
21 | other materials provided with the distribution.
22 | * The name of the author may not be used to endorse or promote products derived
23 | from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
26 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28 | SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 | OF SUCH DAMAGE.
35 |
36 | ------------------------------------------------------------------------------*/
37 |
38 |
39 | #include "OctreeImplementation.hpp"
40 |
41 |
42 | using namespace hxa7241_graphics;
43 |
44 |
45 |
46 |
47 | /// OctreeRoot /////////////////////////////////////////////////////////////////
48 |
49 |
50 | /// standard object services ---------------------------------------------------
51 | OctreeRoot::OctreeRoot
52 | (
53 | const Vector3r& position,
54 | const real sizeOfCube,
55 | const dword maxItemsPerCell,
56 | const dword maxLevelCount,
57 | const real minCellSize
58 | )
59 | : dimensions_m( position, sizeOfCube, maxItemsPerCell, maxLevelCount,
60 | minCellSize )
61 | , pRootCell_m ( 0 )
62 | {
63 | }
64 |
65 |
66 | OctreeRoot::~OctreeRoot()
67 | {
68 | delete pRootCell_m;
69 | }
70 |
71 |
72 | OctreeRoot::OctreeRoot
73 | (
74 | const OctreeRoot& other
75 | )
76 | : dimensions_m( other.dimensions_m )
77 | , pRootCell_m ( OctreeCell::cloneNonZero( other.pRootCell_m ) )
78 | {
79 | }
80 |
81 |
82 | OctreeRoot& OctreeRoot::operator=
83 | (
84 | const OctreeRoot& other
85 | )
86 | {
87 | if( &other != this )
88 | {
89 | // make new data before deleting old
90 | OctreeCell* pRootCell = OctreeCell::cloneNonZero( other.pRootCell_m );
91 | delete pRootCell_m;
92 | pRootCell_m = pRootCell;
93 |
94 | dimensions_m = other.dimensions_m;
95 | }
96 |
97 | return *this;
98 | }
99 |
100 |
101 |
102 |
103 | /// commands -------------------------------------------------------------------
104 | bool OctreeRoot::insert
105 | (
106 | const void* const pItem,
107 | const OctreeAgentV& agent
108 | )
109 | {
110 | bool isInserted = false;
111 |
112 | const OctreeData data( dimensions_m );
113 |
114 | // check if item overlaps root cell
115 | if( agent.isOverlappingCellV( pItem, data.getBound().getLowerCorner(),
116 | data.getBound().getUpperCorner() ) )
117 | {
118 | OctreeLeaf::insertMaybeCreate( data, pRootCell_m, pItem, agent );
119 |
120 | isInserted = true;
121 | }
122 |
123 | return isInserted;
124 | }
125 |
126 |
127 | bool OctreeRoot::remove
128 | (
129 | const void* const pItem,
130 | const OctreeAgentV& //agent
131 | )
132 | {
133 | bool isRemoved = false;
134 |
135 | if( pRootCell_m )
136 | {
137 | dword unusedBranchItemCount = 0;
138 | isRemoved = pRootCell_m->remove( pRootCell_m, pItem,
139 | dimensions_m.getMaxItemCountPerCell(), unusedBranchItemCount );
140 | }
141 |
142 | return isRemoved;
143 | }
144 |
145 |
146 |
147 |
148 | /// queries --------------------------------------------------------------------
149 | void OctreeRoot::visit
150 | (
151 | OctreeVisitorV& visitor
152 | ) const
153 | {
154 | const OctreeData data( dimensions_m );
155 |
156 | visitor.visitRootV( pRootCell_m, data );
157 | }
158 |
159 |
160 | bool OctreeRoot::isEmpty() const
161 | {
162 | return !pRootCell_m;
163 | }
164 |
165 |
166 | void OctreeRoot::getInfo
167 | (
168 | const dword rootWrapperByteSize,
169 | dword& byteSize,
170 | dword& leafCount,
171 | dword& itemCount,
172 | dword& maxDepth
173 | ) const
174 | {
175 | byteSize = 0;
176 | leafCount = 0;
177 | itemCount = 0;
178 | maxDepth = 0;
179 |
180 | if( pRootCell_m )
181 | {
182 | pRootCell_m->getInfo( byteSize, leafCount, itemCount, maxDepth );
183 | }
184 |
185 | byteSize += rootWrapperByteSize;
186 | }
187 |
188 |
189 | const Vector3r& OctreeRoot::getPosition() const
190 | {
191 | return dimensions_m.getPosition();
192 | }
193 |
194 |
195 | real OctreeRoot::getSize() const
196 | {
197 | return dimensions_m.getSize();
198 | }
199 |
200 |
201 | dword OctreeRoot::getMaxItemCountPerCell() const
202 | {
203 | return dimensions_m.getMaxItemCountPerCell();
204 | }
205 |
206 |
207 | dword OctreeRoot::getMaxLevelCount() const
208 | {
209 | return dimensions_m.getMaxLevelCount();
210 | }
211 |
212 |
213 | real OctreeRoot::getMinCellSize() const
214 | {
215 | return dimensions_m.getMinCellSize();
216 | }
217 |
218 |
219 |
220 |
221 | /// statics --------------------------------------------------------------------
222 | void OctreeRoot::continueVisit
223 | (
224 | const OctreeCell* pRootCell,
225 | const OctreeData& octreeData,
226 | OctreeVisitorV& visitor
227 | )
228 | {
229 | if( pRootCell )
230 | {
231 | pRootCell->visit( octreeData, visitor );
232 | }
233 | }
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 | /// OctreeCell /////////////////////////////////////////////////////////////////
243 |
244 |
245 | /// statics --------------------------------------------------------------------
246 | OctreeCell* OctreeCell::cloneNonZero
247 | (
248 | const OctreeCell* pOriginal
249 | )
250 | {
251 | return pOriginal ? pOriginal->clone() : 0;
252 | }
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 | /// OctreeBranch ///////////////////////////////////////////////////////////////
262 |
263 |
264 | /// standard object services ---------------------------------------------------
265 | OctreeBranch::OctreeBranch()
266 | {
267 | OctreeBranch::zeroSubCells();
268 | }
269 |
270 |
271 | OctreeBranch::OctreeBranch
272 | (
273 | const OctreeData& thisData,
274 | const Array& items,
275 | const void* const pItem,
276 | const OctreeAgentV& agent
277 | )
278 | {
279 | OctreeBranch::zeroSubCells();
280 |
281 | try
282 | {
283 | OctreeCell* pNotUsed = 0;
284 |
285 | // insert items
286 | for( int j = items.getLength(); j-- > 0; )
287 | {
288 | OctreeBranch::insert( thisData, pNotUsed, items[j], agent );
289 | }
290 |
291 | // insert last item
292 | OctreeBranch::insert( thisData, pNotUsed, pItem, agent );
293 | }
294 | catch( ... )
295 | {
296 | // delete any allocated cells
297 | this->~OctreeBranch();
298 |
299 | throw;
300 | }
301 | }
302 |
303 |
304 | OctreeBranch::~OctreeBranch()
305 | {
306 | for( int i = 8; i-- > 0; )
307 | {
308 | delete subCells_m[i];
309 | }
310 | }
311 |
312 |
313 | OctreeBranch::OctreeBranch
314 | (
315 | const OctreeBranch& other
316 | )
317 | {
318 | OctreeBranch::zeroSubCells();
319 |
320 | try
321 | {
322 | for( int i = 8; i-- > 0; )
323 | {
324 | subCells_m[i] = OctreeCell::cloneNonZero( other.subCells_m[i] );
325 | }
326 | }
327 | catch( ... )
328 | {
329 | // delete any allocated cells
330 | this->~OctreeBranch();
331 |
332 | throw;
333 | }
334 | }
335 |
336 |
337 | OctreeBranch& OctreeBranch::operator=
338 | (
339 | const OctreeBranch& other
340 | )
341 | {
342 | if( &other != this )
343 | {
344 | OctreeBranch copy( other );
345 |
346 | // 'move' subCells copies to this (leaving copy empty)
347 | for( int i = 8; i-- > 0; )
348 | {
349 | delete subCells_m[i];
350 | subCells_m[i] = copy.subCells_m[i];
351 |
352 | copy.subCells_m[i] = 0;
353 | }
354 | }
355 |
356 | return *this;
357 | }
358 |
359 |
360 |
361 |
362 | /// commands -------------------------------------------------------------------
363 | void OctreeBranch::insert
364 | (
365 | const OctreeData& thisData,
366 | OctreeCell*& ,//pThis,
367 | const void* const pItem,
368 | const OctreeAgentV& agent
369 | )
370 | {
371 | // get subcell-item overlaps flags
372 | const OctreeBound& bound = thisData.getBound();
373 | const dword overlaps = agent.getSubcellOverlapsV( pItem,
374 | bound.getLowerCorner(), bound.getCenter(), bound.getUpperCorner() );
375 |
376 | // loop through sub cells
377 | for( int i = 8; i-- > 0; )
378 | {
379 | // check if sub cell is overlapped by item
380 | if( (overlaps >> i) & 1 )
381 | {
382 | // make sub cell data
383 | const OctreeData subCellData( thisData, i );
384 |
385 | // add item to sub cell
386 | OctreeLeaf::insertMaybeCreate( subCellData, subCells_m[i],
387 | pItem, agent );
388 | }
389 | }
390 | }
391 |
392 |
393 | bool OctreeBranch::remove
394 | (
395 | OctreeCell*& pThis,
396 | const void* const pItem,
397 | const dword maxItemsPerCell,
398 | dword& itemCount
399 | )
400 | {
401 | bool isRemoved = false;
402 | dword branchItemCount = 0;
403 |
404 | // loop through sub cells
405 | for( int i = 8; i-- > 0; )
406 | {
407 | // remove item from non-null sub cell
408 | OctreeCell*& pSubCell = subCells_m[i];
409 | if( pSubCell )
410 | {
411 | isRemoved |= pSubCell->remove( pSubCell, pItem, maxItemsPerCell,
412 | branchItemCount );
413 | }
414 | }
415 |
416 | itemCount += branchItemCount;
417 |
418 | // decide whether to collapse this branch
419 | if( branchItemCount > 0 )
420 | {
421 | // collapse to leaf
422 | if( branchItemCount <= maxItemsPerCell )
423 | {
424 | // all subcells *will* be leafs!
425 | // because:
426 | // a) if a branch has below it less item refs than the threshold,
427 | // it collapses to a leaf (this function!)
428 | // b) the total of item refs below this branch in the tree is less
429 | // than the threshold
430 | // c) therefore the total of item refs in any branch below this
431 | // cell will be less than the threshold
432 | // d) branchs below this cell will be collapsed before this branch
433 | // (because the recursive 'remove' call is before the
434 | // collapsing code)
435 | // so: if this branch will collapse to a leaf, then all its sub
436 | // branchs (direct and indirect) will collapse to leafs, and that
437 | // will happen before this branch.
438 | OctreeCell*const pLeaf = new OctreeLeaf(
439 | reinterpret_cast( subCells_m ) );
440 |
441 | delete pThis;
442 | pThis = pLeaf;
443 | }
444 | }
445 | else
446 | {
447 | // delete this branch
448 | delete pThis;
449 | pThis = 0;
450 | }
451 |
452 | return isRemoved;
453 | }
454 |
455 |
456 |
457 |
458 | /// queries --------------------------------------------------------------------
459 | void OctreeBranch::visit
460 | (
461 | const OctreeData& thisData,
462 | OctreeVisitorV& visitor
463 | ) const
464 | {
465 | visitor.visitBranchV( const_cast(subCells_m), thisData );
466 | }
467 |
468 |
469 | OctreeCell* OctreeBranch::clone() const
470 | {
471 | return new OctreeBranch( *this );
472 | }
473 |
474 |
475 | void OctreeBranch::getInfo
476 | (
477 | dword& byteSize,
478 | dword& leafCount,
479 | dword& itemCount,
480 | dword& maxDepth
481 | ) const
482 | {
483 | byteSize += sizeof(*this);
484 |
485 | const dword thisDepth = maxDepth + 1;
486 |
487 | for( int i = 8; i-- > 0; )
488 | {
489 | const OctreeCell*const pSubCell = subCells_m[i];
490 | if( pSubCell )
491 | {
492 | dword depth = thisDepth;
493 | pSubCell->getInfo( byteSize, leafCount, itemCount, depth );
494 |
495 | if( maxDepth < depth )
496 | {
497 | maxDepth = depth;
498 | }
499 | }
500 | }
501 | }
502 |
503 |
504 |
505 |
506 | /// statics --------------------------------------------------------------------
507 | void OctreeBranch::continueVisit
508 | (
509 | const OctreeCell* subCells[8],
510 | const OctreeData& octreeData,
511 | const dword subCellIndex,
512 | OctreeVisitorV& visitor
513 | )
514 | {
515 | const OctreeCell*const pSubCell = subCells[ subCellIndex & 0x07 ];
516 | if( pSubCell )
517 | {
518 | const OctreeData subCellData( octreeData, subCellIndex );
519 | pSubCell->visit( subCellData, visitor );
520 | }
521 | }
522 |
523 |
524 |
525 |
526 | /// implementation -------------------------------------------------------------
527 | void OctreeBranch::zeroSubCells()
528 | {
529 | for( int i = 8; i-- > 0; )
530 | {
531 | subCells_m[i] = 0;
532 | }
533 | }
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 | /// OctreeLeaf /////////////////////////////////////////////////////////////////
543 |
544 |
545 | /// standard object services ---------------------------------------------------
546 | OctreeLeaf::OctreeLeaf()
547 | : items_m()
548 | {
549 | }
550 |
551 |
552 | OctreeLeaf::OctreeLeaf
553 | (
554 | const void* pItem
555 | )
556 | : items_m()
557 | {
558 | items_m.append( pItem );
559 | }
560 |
561 |
562 | OctreeLeaf::OctreeLeaf
563 | (
564 | const OctreeLeaf*const leafs[8]
565 | )
566 | : items_m()
567 | {
568 | // sum all items lengths
569 | dword totalLength = 0;
570 | for( int i = 8; i-- > 0; )
571 | {
572 | const OctreeLeaf*const pLeaf = leafs[i];
573 | if( pLeaf )
574 | {
575 | totalLength += pLeaf->items_m.getLength();
576 | }
577 | }
578 |
579 | // prepare items array to hold all other items
580 | items_m.setLength( totalLength );
581 |
582 | // copy items arrays
583 | const void** pElement = items_m.getStorage();
584 | for( int i = 0; i < 8; ++i )
585 | {
586 | const OctreeLeaf*const pLeaf = leafs[i];
587 | if( pLeaf )
588 | {
589 | const void* const* pOtherElement = pLeaf->items_m.getStorage();
590 | const void* const* pOtherEnd = pOtherElement +
591 | pLeaf->items_m.getLength();
592 | for( ; pOtherElement < pOtherEnd; ++pOtherElement, ++pElement )
593 | {
594 | *pElement = *pOtherElement;
595 | }
596 | }
597 | }
598 | }
599 |
600 |
601 | OctreeLeaf::~OctreeLeaf()
602 | {
603 | }
604 |
605 |
606 | OctreeLeaf::OctreeLeaf
607 | (
608 | const OctreeLeaf& other
609 | )
610 | : items_m( other.items_m )
611 | {
612 | }
613 |
614 |
615 | OctreeLeaf& OctreeLeaf::operator=
616 | (
617 | const OctreeLeaf& other
618 | )
619 | {
620 | items_m = other.items_m;
621 |
622 | return *this;
623 | }
624 |
625 |
626 |
627 |
628 | /// commands -------------------------------------------------------------------
629 | void OctreeLeaf::insert
630 | (
631 | const OctreeData& thisData,
632 | OctreeCell*& pThis,
633 | const void* const pItem,
634 | const OctreeAgentV& agent
635 | )
636 | {
637 | // check if item already present
638 | bool isAlreadyPresent = false;
639 | for( int i = items_m.getLength(); (i-- > 0) & !isAlreadyPresent; )
640 | {
641 | isAlreadyPresent |= (pItem == items_m[i]);
642 | }
643 |
644 | // only insert if item not already present
645 | if( !isAlreadyPresent )
646 | {
647 | // check if leaf should be subdivided
648 | if( !thisData.isSubdivide( items_m.getLength() + 1 ) )
649 | {
650 | // append item to collection
651 | items_m.append( pItem );
652 | }
653 | else
654 | {
655 | // subdivide by making branch and adding items to it
656 | OctreeCell*const pBranch = new OctreeBranch( thisData, items_m, pItem,
657 | agent );
658 |
659 | // replace this with branch
660 | delete pThis;
661 | pThis = pBranch;
662 | }
663 | }
664 | }
665 |
666 |
667 | bool OctreeLeaf::remove
668 | (
669 | OctreeCell*& pThis,
670 | const void* const pItem,
671 | const dword ,//maxItemsPerCell,
672 | dword& itemCount
673 | )
674 | {
675 | bool isRemoved = false;
676 |
677 | // loop through items
678 | for( int i = 0; i < items_m.getLength(); )
679 | {
680 | // check if item is present
681 | if( items_m[i] == pItem )
682 | {
683 | // remove item
684 | items_m.remove( i );
685 | isRemoved = true;
686 | }
687 | else
688 | {
689 | ++i;
690 | }
691 | }
692 |
693 | itemCount += items_m.getLength();
694 |
695 | // check if leaf is now empty
696 | if( items_m.isEmpty() )
697 | {
698 | // remove this leaf
699 | delete pThis;
700 | pThis = 0;
701 | }
702 |
703 | return isRemoved;
704 | }
705 |
706 |
707 |
708 |
709 | /// queries --------------------------------------------------------------------
710 | void OctreeLeaf::visit
711 | (
712 | const OctreeData& thisData,
713 | OctreeVisitorV& visitor
714 | ) const
715 | {
716 | visitor.visitLeafV( items_m, thisData );
717 | }
718 |
719 |
720 | OctreeCell* OctreeLeaf::clone() const
721 | {
722 | return new OctreeLeaf( *this );
723 | }
724 |
725 |
726 | void OctreeLeaf::getInfo
727 | (
728 | dword& byteSize,
729 | dword& leafCount,
730 | dword& itemCount,
731 | dword& maxDepth
732 | ) const
733 | {
734 | byteSize += sizeof(*this) + (items_m.getLength() * sizeof(void*));
735 | ++leafCount;
736 | itemCount += items_m.getLength();
737 | ++maxDepth;
738 | }
739 |
740 |
741 |
742 |
743 | /// statics --------------------------------------------------------------------
744 | void OctreeLeaf::insertMaybeCreate
745 | (
746 | const OctreeData& cellData,
747 | OctreeCell*& pCell,
748 | const void* const pItem,
749 | const OctreeAgentV& agent
750 | )
751 | {
752 | // check cell exists
753 | if( !pCell )
754 | {
755 | // make leaf, adding item
756 | OctreeCell*const pLeaf = new OctreeLeaf( pItem );
757 |
758 | // replace cell with leaf
759 | delete pCell;
760 | pCell = pLeaf;
761 | }
762 | else
763 | {
764 | // forward to existing cell
765 | pCell->insert( cellData, pCell, pItem, agent );
766 | }
767 | }
768 |
--------------------------------------------------------------------------------
/component/OctreeImplementation.hpp:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------------------
2 |
3 | Octree Component, version 2.1
4 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
5 |
6 | http://www.hxa7241.org/
7 |
8 | ------------------------------------------------------------------------------*/
9 |
10 | /*------------------------------------------------------------------------------
11 |
12 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
13 |
14 | Redistribution and use in source and binary forms, with or without modification,
15 | are permitted provided that the following conditions are met:
16 |
17 | * Redistributions of source code must retain the above copyright notice, this
18 | list of conditions and the following disclaimer.
19 | * Redistributions in binary form must reproduce the above copyright notice, this
20 | list of conditions and the following disclaimer in the documentation and/or
21 | other materials provided with the distribution.
22 | * The name of the author may not be used to endorse or promote products derived
23 | from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
26 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28 | SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 | OF SUCH DAMAGE.
35 |
36 | ------------------------------------------------------------------------------*/
37 |
38 |
39 | #ifndef OctreeImplementation_h
40 | #define OctreeImplementation_h
41 |
42 |
43 | #include "OctreeAuxiliary.hpp"
44 |
45 |
46 |
47 |
48 | namespace hxa7241_graphics
49 | {
50 |
51 |
52 | /**
53 | * Implementation class for the Octree template.
54 | *
55 | * @invariants
56 | * pRootCell_m can be null, or point to an OctreeCell instance.
57 | *
58 | * At construction, pRootCell_m is set to a legal value.
59 | * At destruction, pRootCell_m is deleted.
60 | * Whenever pRootCell_m is modified, it must be deleted then set to a legal
61 | * value.
62 | * A legal value is: either 0, or the value from invocation of 'new'.
63 | */
64 | class OctreeRoot
65 | {
66 | /// standard object services ---------------------------------------------------
67 | public:
68 | OctreeRoot( const Vector3r& position,
69 | real sizeOfCube,
70 | dword maxItemsPerCell,
71 | dword maxLevelCount,
72 | real minCellSize );
73 |
74 | ~OctreeRoot();
75 | OctreeRoot( const OctreeRoot& );
76 | OctreeRoot& operator=( const OctreeRoot& );
77 |
78 |
79 | /// commands -------------------------------------------------------------------
80 | bool insert( const void* pItem,
81 | const OctreeAgentV& agent );
82 | bool remove( const void* pItem,
83 | const OctreeAgentV& agent );
84 |
85 |
86 | /// queries --------------------------------------------------------------------
87 | void visit( OctreeVisitorV& visitor ) const;
88 |
89 | bool isEmpty() const;
90 | void getInfo( dword rootWrapperByteSize,
91 | dword& byteSize,
92 | dword& leafCount,
93 | dword& itemCount,
94 | dword& maxDepth ) const;
95 |
96 | const Vector3r& getPosition() const;
97 | real getSize() const;
98 | dword getMaxItemCountPerCell() const;
99 | dword getMaxLevelCount() const;
100 | real getMinCellSize() const;
101 |
102 |
103 | /// statics --------------------------------------------------------------------
104 | static void continueVisit( const OctreeCell* pRootCell,
105 | const OctreeData& octreeData,
106 | OctreeVisitorV& visitor );
107 |
108 |
109 | /// fields ---------------------------------------------------------------------
110 | private:
111 | OctreeDimensions dimensions_m;
112 | OctreeCell* pRootCell_m;
113 | };
114 |
115 |
116 |
117 |
118 | /**
119 | * Abstract base for Composite types, for implementing Octree nodes.
120 | *
121 | * @implementation
122 | * Subcell numbering:
123 | *
124 | * y z 6 7
125 | * |/ 2 3 4 5
126 | * -x 0 1
127 | *
128 | * in binary:
129 | *
130 | * y z 110 111
131 | * |/ 010 011 100 101
132 | * -x 000 001
133 | *
134 | */
135 | class OctreeCell
136 | {
137 | /// standard object services ---------------------------------------------------
138 | protected:
139 | OctreeCell() {}
140 | public:
141 | virtual ~OctreeCell() {}
142 | private:
143 | OctreeCell( const OctreeCell& );
144 | OctreeCell& operator=( const OctreeCell& );
145 | public:
146 |
147 |
148 | /// commands -------------------------------------------------------------------
149 | virtual void insert( const OctreeData& thisData,
150 | OctreeCell*& pThis,
151 | const void* pItem,
152 | const OctreeAgentV& agent ) =0;
153 | virtual bool remove( OctreeCell*& pThis,
154 | const void* pItem,
155 | const dword maxItemsPerCell,
156 | dword& itemCount ) =0;
157 |
158 |
159 | /// queries --------------------------------------------------------------------
160 | virtual void visit( const OctreeData& thisData,
161 | OctreeVisitorV& visitor ) const =0;
162 |
163 | virtual OctreeCell* clone() const =0;
164 |
165 | virtual void getInfo( dword& byteSize,
166 | dword& leafCount,
167 | dword& itemCount,
168 | dword& maxDepth ) const =0;
169 |
170 |
171 | /// statics --------------------------------------------------------------------
172 | static OctreeCell* cloneNonZero( const OctreeCell* );
173 | };
174 |
175 |
176 |
177 |
178 | /**
179 | * Inner node implementation of an octree cell.
180 | *
181 | * Stores pointers to eight (at most) child cells.
182 | *
183 | * @invariants
184 | * subCells_m elements can be null, or point to an OctreeCell instance.
185 | */
186 | class OctreeBranch
187 | : public OctreeCell
188 | {
189 | /// standard object services ---------------------------------------------------
190 | public:
191 | OctreeBranch();
192 | OctreeBranch( const OctreeData& thisData,
193 | const Array& items,
194 | const void* const pItem,
195 | const OctreeAgentV& agent );
196 |
197 | virtual ~OctreeBranch();
198 | OctreeBranch( const OctreeBranch& );
199 | OctreeBranch& operator=( const OctreeBranch& );
200 |
201 |
202 | /// commands -------------------------------------------------------------------
203 | virtual void insert( const OctreeData& thisData,
204 | OctreeCell*& pThis,
205 | const void* pItem,
206 | const OctreeAgentV& agent );
207 | virtual bool remove( OctreeCell*& pThis,
208 | const void* pItem,
209 | const dword maxItemsPerCell,
210 | dword& itemCount );
211 |
212 |
213 | /// queries --------------------------------------------------------------------
214 | virtual void visit( const OctreeData& thisData,
215 | OctreeVisitorV& visitor ) const;
216 |
217 | virtual OctreeCell* clone() const;
218 |
219 | virtual void getInfo( dword& byteSize,
220 | dword& leafCount,
221 | dword& itemCount,
222 | dword& maxDepth ) const;
223 |
224 |
225 | /// statics --------------------------------------------------------------------
226 | static void continueVisit( const OctreeCell* subCells[8],
227 | const OctreeData& octreeData,
228 | dword subCellIndex,
229 | OctreeVisitorV& visitor );
230 |
231 |
232 | /// implementation -------------------------------------------------------------
233 | protected:
234 | virtual void zeroSubCells();
235 |
236 |
237 | /// fields ---------------------------------------------------------------------
238 | private:
239 | OctreeCell* subCells_m[ 8 ];
240 | };
241 |
242 |
243 |
244 |
245 | /**
246 | * Outer node implementation of an octree cell.
247 | *
248 | * Stores pointers to items.
249 | */
250 | class OctreeLeaf
251 | : public OctreeCell
252 | {
253 | /// standard object services ---------------------------------------------------
254 | public:
255 | OctreeLeaf();
256 | OctreeLeaf( const OctreeLeaf*const leafs[8] );
257 | private:
258 | explicit OctreeLeaf( const void* pItem );
259 |
260 | public:
261 | virtual ~OctreeLeaf();
262 | OctreeLeaf( const OctreeLeaf& );
263 | OctreeLeaf& operator=( const OctreeLeaf& );
264 |
265 |
266 | /// commands -------------------------------------------------------------------
267 | virtual void insert( const OctreeData& thisData,
268 | OctreeCell*& pThis,
269 | const void* pItem,
270 | const OctreeAgentV& agent );
271 | virtual bool remove( OctreeCell*& pThis,
272 | const void* pItem,
273 | const dword maxItemsPerCell,
274 | dword& itemCount );
275 |
276 |
277 | /// queries --------------------------------------------------------------------
278 | virtual void visit( const OctreeData& thisData,
279 | OctreeVisitorV& visitor ) const;
280 |
281 | virtual OctreeCell* clone() const;
282 |
283 | virtual void getInfo( dword& byteSize,
284 | dword& leafCount,
285 | dword& itemCount,
286 | dword& maxDepth ) const;
287 |
288 |
289 | /// statics --------------------------------------------------------------------
290 | static void insertMaybeCreate( const OctreeData& cellData,
291 | OctreeCell*& pCell,
292 | const void* pItem,
293 | const OctreeAgentV& agent );
294 |
295 |
296 | /// fields ---------------------------------------------------------------------
297 | private:
298 | Array items_m;
299 | };
300 |
301 |
302 | }//namespace
303 |
304 |
305 |
306 |
307 | #endif//OctreeImplementation_h
308 |
--------------------------------------------------------------------------------
/component/Primitives.hpp:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------------------
2 |
3 | Octree Component, version 2.1
4 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
5 |
6 | http://www.hxa7241.org/
7 |
8 | ------------------------------------------------------------------------------*/
9 |
10 | /*------------------------------------------------------------------------------
11 |
12 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
13 |
14 | Redistribution and use in source and binary forms, with or without modification,
15 | are permitted provided that the following conditions are met:
16 |
17 | * Redistributions of source code must retain the above copyright notice, this
18 | list of conditions and the following disclaimer.
19 | * Redistributions in binary form must reproduce the above copyright notice, this
20 | list of conditions and the following disclaimer in the documentation and/or
21 | other materials provided with the distribution.
22 | * The name of the author may not be used to endorse or promote products derived
23 | from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
26 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28 | SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 | OF SUCH DAMAGE.
35 |
36 | ------------------------------------------------------------------------------*/
37 |
38 |
39 | #ifndef Primitives_h
40 | #define Primitives_h
41 |
42 |
43 | #include
44 | #include
45 |
46 |
47 |
48 |
49 | namespace hxa7241
50 | {
51 |
52 |
53 | /// types ----------------------------------------------------------------------
54 |
55 | // remove definition to set real to double
56 | #define REAL_IS_FLOAT
57 |
58 | typedef signed char byte;
59 | typedef unsigned char ubyte;
60 |
61 | typedef signed short word;
62 | typedef unsigned short uword;
63 |
64 | typedef signed int dword;
65 | typedef unsigned int udword;
66 |
67 | #ifdef REAL_IS_FLOAT
68 | typedef float real;
69 | #else
70 | typedef double real;
71 | #endif
72 |
73 |
74 | /// constants ------------------------------------------------------------------
75 |
76 | // limits.h version
77 |
78 | const byte BYTE_MIN = SCHAR_MIN;
79 | const byte BYTE_MAX = SCHAR_MAX;
80 | const int BYTE_BITS = 8;
81 |
82 | const ubyte UBYTE_MIN = 0;
83 | const ubyte UBYTE_MAX = UCHAR_MAX;
84 | const int UBYTE_BITS = 8;
85 |
86 |
87 | const word WORD_MIN = SHRT_MIN;
88 | const word WORD_MAX = SHRT_MAX;
89 | const int WORD_BITS = 16;
90 |
91 | const uword UWORD_MIN = 0;
92 | const uword UWORD_MAX = USHRT_MAX;
93 | const int UWORD_BITS = 16;
94 |
95 |
96 | const dword DWORD_MIN = INT_MIN;
97 | const dword DWORD_MAX = INT_MAX;
98 | const int DWORD_BITS = 32;
99 |
100 | const udword UDWORD_MIN = 0;
101 | const udword UDWORD_MAX = UINT_MAX;
102 | const int UDWORD_BITS = 32;
103 |
104 |
105 | const float FLOAT_MIN_POS = static_cast(FLT_MIN);
106 | const float FLOAT_MIN_NEG = static_cast(-FLT_MAX);
107 | const float FLOAT_MAX = static_cast(FLT_MAX);
108 | const float FLOAT_EPSILON = static_cast(FLT_EPSILON);
109 | const float FLOAT_ALMOST_ONE = static_cast(1.0f - FLT_EPSILON);
110 | const float FLOAT_SMALL = static_cast(1.0e-12f);
111 | const float FLOAT_LARGE = static_cast(1.0e+12f);
112 |
113 | const double DOUBLE_MIN_POS = static_cast(DBL_MIN);
114 | const double DOUBLE_MIN_NEG = static_cast(-DBL_MAX);
115 | const double DOUBLE_MAX = static_cast(DBL_MAX);
116 | const double DOUBLE_EPSILON = static_cast(DBL_EPSILON);
117 | const double DOUBLE_ALMOST_ONE = static_cast(1.0 - DBL_EPSILON);
118 | const double DOUBLE_SMALL = static_cast(1.0e-96);
119 | const double DOUBLE_LARGE = static_cast(1.0e+96);
120 |
121 | #ifdef REAL_IS_FLOAT
122 | const float REAL_MIN_POS = FLOAT_MIN_POS;
123 | const float REAL_MIN_NEG = FLOAT_MIN_NEG;
124 | const float REAL_MAX = FLOAT_MAX;
125 | const float REAL_EPSILON = FLOAT_EPSILON;
126 | const float REAL_ALMOST_ONE = FLOAT_ALMOST_ONE;
127 | const float REAL_SMALL = FLOAT_SMALL;
128 | const float REAL_LARGE = FLOAT_LARGE;
129 | #else
130 | const double REAL_MIN_POS = DOUBLE_MIN_POS;
131 | const double REAL_MIN_NEG = DOUBLE_MIN_NEG;
132 | const double REAL_MAX = DOUBLE_MAX;
133 | const double REAL_EPSILON = DOUBLE_EPSILON;
134 | const double REAL_ALMOST_ONE = DOUBLE_ALMOST_ONE;
135 | const double REAL_SMALL = DOUBLE_SMALL;
136 | const double REAL_LARGE = DOUBLE_LARGE;
137 | #endif
138 |
139 |
140 | // limits version
141 |
142 | /*
143 | const byte BYTE_MIN = std::numeric_limits::min();
144 | const byte BYTE_MAX = std::numeric_limits::max();
145 | const int BYTE_BITS = 8;
146 |
147 | const ubyte UBYTE_MIN = std::numeric_limits::min();
148 | const ubyte UBYTE_MAX = std::numeric_limits::max();
149 | const int UBYTE_BITS = 8;
150 |
151 |
152 | const word WORD_MIN = std::numeric_limits::min();
153 | const word WORD_MAX = std::numeric_limits::max();
154 | const int WORD_BITS = 16;
155 |
156 | const uword UWORD_MIN = std::numeric_limits::min();
157 | const uword UWORD_MAX = std::numeric_limits::max();
158 | const int UWORD_BITS = 16;
159 |
160 |
161 | const dword DWORD_MIN = std::numeric_limits::min();
162 | const dword DWORD_MAX = std::numeric_limits::max();
163 | const int DWORD_BITS = 32;
164 |
165 | const udword UDWORD_MIN = std::numeric_limits::min();
166 | const udword UDWORD_MAX = std::numeric_limits::max();
167 | const int UDWORD_BITS = 32;
168 |
169 |
170 | const float FLOAT_MIN_POS = std::numeric_limits::min();
171 | const float FLOAT_MIN_NEG =
172 | static_cast(-std::numeric_limits::max());
173 | const float FLOAT_MAX = std::numeric_limits::max();
174 | const float FLOAT_EPSILON = std::numeric_limits::epsilon();
175 | const float FLOAT_ALMOST_ONE =
176 | static_cast(1.0f - std::numeric_limits::epsilon());
177 | const float FLOAT_SMALL = static_cast(1.0e-12f);
178 | const float FLOAT_LARGE = static_cast(1.0e+12f);
179 |
180 | const double DOUBLE_MIN_POS = std::numeric_limits::min();
181 | const double DOUBLE_MIN_NEG =
182 | static_cast(-std::numeric_limits::max());
183 | const double DOUBLE_MAX = std::numeric_limits::max();
184 | const double DOUBLE_EPSILON = std::numeric_limits::epsilon();
185 | const double DOUBLE_ALMOST_ONE =
186 | static_cast(1.0 - std::numeric_limits::epsilon());
187 | const double DOUBLE_SMALL = static_cast(1.0e-96);
188 | const double DOUBLE_LARGE = static_cast(1.0e+96);
189 |
190 | #ifdef REAL_IS_FLOAT
191 | const float REAL_MIN_POS = FLOAT_MIN_POS;
192 | const float REAL_MIN_NEG = FLOAT_MIN_NEG;
193 | const float REAL_MAX = FLOAT_MAX;
194 | const float REAL_EPSILON = FLOAT_EPSILON;
195 | const float REAL_ALMOST_ONE = FLOAT_ALMOST_ONE;
196 | const float REAL_SMALL = FLOAT_SMALL;
197 | const float REAL_LARGE = FLOAT_LARGE;
198 | #else
199 | const double REAL_MIN_POS = DOUBLE_MIN_POS;
200 | const double REAL_MIN_NEG = DOUBLE_MIN_NEG;
201 | const double REAL_MAX = DOUBLE_MAX;
202 | const double REAL_EPSILON = DOUBLE_EPSILON;
203 | const double REAL_ALMOST_ONE = DOUBLE_ALMOST_ONE;
204 | const double REAL_SMALL = DOUBLE_SMALL;
205 | const double REAL_LARGE = DOUBLE_LARGE;
206 | #endif
207 | */
208 |
209 |
210 | }//namespace
211 |
212 |
213 |
214 |
215 | #endif//Primitives_h
216 |
--------------------------------------------------------------------------------
/component/Vector3r.cpp:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------------------
2 |
3 | Octree Component, version 2.1
4 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
5 |
6 | http://www.hxa7241.org/
7 |
8 | ------------------------------------------------------------------------------*/
9 |
10 | /*------------------------------------------------------------------------------
11 |
12 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
13 |
14 | Redistribution and use in source and binary forms, with or without modification,
15 | are permitted provided that the following conditions are met:
16 |
17 | * Redistributions of source code must retain the above copyright notice, this
18 | list of conditions and the following disclaimer.
19 | * Redistributions in binary form must reproduce the above copyright notice, this
20 | list of conditions and the following disclaimer in the documentation and/or
21 | other materials provided with the distribution.
22 | * The name of the author may not be used to endorse or promote products derived
23 | from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
26 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28 | SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 | OF SUCH DAMAGE.
35 |
36 | ------------------------------------------------------------------------------*/
37 |
38 |
39 | #include
40 |
41 | #include "Vector3r.hpp"
42 |
43 |
44 | using namespace hxa7241_graphics;
45 |
46 |
47 |
48 |
49 | /// standard object services ---------------------------------------------------
50 | Vector3r::Vector3r()
51 | {
52 | xyz_m[0] = real();
53 | xyz_m[1] = real();
54 | xyz_m[2] = real();
55 | }
56 |
57 |
58 | Vector3r::Vector3r
59 | (
60 | const real x,
61 | const real y,
62 | const real z
63 | )
64 | {
65 | xyz_m[0] = x;
66 | xyz_m[1] = y;
67 | xyz_m[2] = z;
68 | }
69 |
70 |
71 | //Vector3r::Vector3r
72 | //(
73 | // const real xyz[3]
74 | //)
75 | //{
76 | // xyz_m[0] = xyz[0];
77 | // xyz_m[1] = xyz[1];
78 | // xyz_m[2] = xyz[2];
79 | //}
80 | //
81 | //
82 | //Vector3r::~Vector3r()
83 | //{
84 | //}
85 | //
86 | //
87 | //Vector3r::Vector3r
88 | //(
89 | // const Vector3r& other
90 | //)
91 | //{
92 | // xyz_m[0] = other.xyz_m[0];
93 | // xyz_m[1] = other.xyz_m[1];
94 | // xyz_m[2] = other.xyz_m[2];
95 | //}
96 |
97 |
98 | Vector3r& Vector3r::operator=
99 | (
100 | const Vector3r& other
101 | )
102 | {
103 | if( &other != this )
104 | {
105 | xyz_m[0] = other.xyz_m[0];
106 | xyz_m[1] = other.xyz_m[1];
107 | xyz_m[2] = other.xyz_m[2];
108 | }
109 |
110 | return *this;
111 | }
112 |
113 |
114 |
115 |
116 | /// commands -------------------------------------------------------------------
117 | Vector3r& Vector3r::set
118 | (
119 | const real x,
120 | const real y,
121 | const real z
122 | )
123 | {
124 | xyz_m[0] = x;
125 | xyz_m[1] = y;
126 | xyz_m[2] = z;
127 |
128 | return *this;
129 | }
130 |
131 |
132 | /*Vector3r& Vector3r::set
133 | (
134 | const real xyz[3]
135 | )
136 | {
137 | xyz_m[0] = xyz[0];
138 | xyz_m[1] = xyz[1];
139 | xyz_m[2] = xyz[2];
140 |
141 | return *this;
142 | }
143 |
144 |
145 | Vector3r& Vector3r::setX
146 | (
147 | const real x
148 | )
149 | {
150 | xyz_m[0] = x;
151 |
152 | return *this;
153 | }
154 |
155 |
156 | Vector3r& Vector3r::setY
157 | (
158 | const real y
159 | )
160 | {
161 | xyz_m[1] = y;
162 |
163 | return *this;
164 | }
165 |
166 |
167 | Vector3r& Vector3r::setZ
168 | (
169 | const real z
170 | )
171 | {
172 | xyz_m[2] = z;
173 |
174 | return *this;
175 | }
176 |
177 |
178 | real& Vector3r::operator[]
179 | (
180 | const int i
181 | )
182 | {
183 | // careful !
184 | return xyz_m[i];
185 | }*/
186 |
187 |
188 | /*Vector3r& Vector3r::negateEq()
189 | {
190 | xyz_m[0] = -xyz_m[0];
191 | xyz_m[1] = -xyz_m[1];
192 | xyz_m[2] = -xyz_m[2];
193 |
194 | return *this;
195 | }
196 |
197 |
198 | Vector3r& Vector3r::absEq()
199 | {
200 | if( xyz_m[0] < real() )
201 | {
202 | xyz_m[0] = -xyz_m[0];
203 | }
204 | if( xyz_m[1] < real() )
205 | {
206 | xyz_m[1] = -xyz_m[1];
207 | }
208 | if( xyz_m[2] < real() )
209 | {
210 | xyz_m[2] = -xyz_m[2];
211 | }
212 |
213 | return *this;
214 | }
215 |
216 |
217 | Vector3r& Vector3r::unitizeEq()
218 | {
219 | const real length = sqrt(
220 | (xyz_m[0] * xyz_m[0]) +
221 | (xyz_m[1] * xyz_m[1]) +
222 | (xyz_m[2] * xyz_m[2]) );
223 | const real oneOverLength = (length != real()) ?
224 | real(1.0f) / length : real();
225 |
226 | xyz_m[0] *= oneOverLength;
227 | xyz_m[1] *= oneOverLength;
228 | xyz_m[2] *= oneOverLength;
229 |
230 | return *this;
231 | }
232 |
233 |
234 | Vector3r& Vector3r::crossEq
235 | (
236 | const Vector3r& v
237 | )
238 | {
239 | const real x = (xyz_m[1] * v.xyz_m[2]) - (xyz_m[2] * v.xyz_m[1]);
240 | const real y = (xyz_m[2] * v.xyz_m[0]) - (xyz_m[0] * v.xyz_m[2]);
241 | const real z = (xyz_m[0] * v.xyz_m[1]) - (xyz_m[1] * v.xyz_m[0]);
242 |
243 | xyz_m[0] = x;
244 | xyz_m[1] = y;
245 | xyz_m[2] = z;
246 |
247 | return *this;
248 | }*/
249 |
250 |
251 | Vector3r& Vector3r::operator+=
252 | (
253 | const Vector3r& v
254 | )
255 | {
256 | xyz_m[0] += v.xyz_m[0];
257 | xyz_m[1] += v.xyz_m[1];
258 | xyz_m[2] += v.xyz_m[2];
259 |
260 | return *this;
261 | }
262 |
263 |
264 | Vector3r& Vector3r::operator-=
265 | (
266 | const Vector3r& v
267 | )
268 | {
269 | xyz_m[0] -= v.xyz_m[0];
270 | xyz_m[1] -= v.xyz_m[1];
271 | xyz_m[2] -= v.xyz_m[2];
272 |
273 | return *this;
274 | }
275 |
276 |
277 | Vector3r& Vector3r::operator*=
278 | (
279 | const Vector3r& v
280 | )
281 | {
282 | xyz_m[0] *= v.xyz_m[0];
283 | xyz_m[1] *= v.xyz_m[1];
284 | xyz_m[2] *= v.xyz_m[2];
285 |
286 | return *this;
287 | }
288 |
289 |
290 | Vector3r& Vector3r::operator/=
291 | (
292 | const Vector3r& v
293 | )
294 | {
295 | xyz_m[0] /= v.xyz_m[0];
296 | xyz_m[1] /= v.xyz_m[1];
297 | xyz_m[2] /= v.xyz_m[2];
298 |
299 | return *this;
300 | }
301 |
302 |
303 | Vector3r& Vector3r::operator*=
304 | (
305 | const real r
306 | )
307 | {
308 | xyz_m[0] *= r;
309 | xyz_m[1] *= r;
310 | xyz_m[2] *= r;
311 |
312 | return *this;
313 | }
314 |
315 |
316 | Vector3r& Vector3r::operator/=
317 | (
318 | const real r
319 | )
320 | {
321 | // need to check if this is still faster
322 |
323 | const real oneOverR = real(1.0f) / r;
324 |
325 | xyz_m[0] *= oneOverR;
326 | xyz_m[1] *= oneOverR;
327 | xyz_m[2] *= oneOverR;
328 |
329 | return *this;
330 | }
331 |
332 |
333 | /*Vector3r& Vector3r::clampMinEq
334 | (
335 | const Vector3r& min
336 | )
337 | {
338 | if( xyz_m[0] < min.xyz_m[0] )
339 | {
340 | xyz_m[0] = min.xyz_m[0];
341 | }
342 | if( xyz_m[1] < min.xyz_m[1] )
343 | {
344 | xyz_m[1] = min.xyz_m[1];
345 | }
346 | if( xyz_m[2] < min.xyz_m[2] )
347 | {
348 | xyz_m[2] = min.xyz_m[2];
349 | }
350 |
351 | return *this;
352 | }
353 |
354 |
355 | Vector3r& Vector3r::clampMaxEq
356 | (
357 | const Vector3r& max
358 | )
359 | {
360 | if( xyz_m[0] > max.xyz_m[0] )
361 | {
362 | xyz_m[0] = max.xyz_m[0];
363 | }
364 | if( xyz_m[1] > max.xyz_m[1] )
365 | {
366 | xyz_m[1] = max.xyz_m[1];
367 | }
368 | if( xyz_m[2] > max.xyz_m[2] )
369 | {
370 | xyz_m[2] = max.xyz_m[2];
371 | }
372 |
373 | return *this;
374 | }
375 |
376 |
377 | Vector3r& Vector3r::clampEq
378 | (
379 | const Vector3r& min,
380 | const Vector3r& max
381 | )
382 | {
383 | if( xyz_m[0] < min.xyz_m[0] )
384 | xyz_m[0] = min.xyz_m[0];
385 | else
386 | if( xyz_m[0] > max.xyz_m[0] )
387 | xyz_m[0] = max.xyz_m[0];
388 |
389 | if( xyz_m[1] < min.xyz_m[1] )
390 | xyz_m[1] = min.xyz_m[1];
391 | else
392 | if( xyz_m[1] > max.xyz_m[1] )
393 | xyz_m[1] = max.xyz_m[1];
394 |
395 | if( xyz_m[2] < min.xyz_m[2] )
396 | xyz_m[2] = min.xyz_m[2];
397 | else
398 | if( xyz_m[2] > max.xyz_m[2] )
399 | xyz_m[2] = max.xyz_m[2];
400 |
401 | return *this;
402 | }
403 |
404 |
405 | Vector3r& Vector3r::clamp01Eq()
406 | {
407 | // [0,1) 0 to almost 1
408 |
409 | if( xyz_m[0] < real() )
410 | xyz_m[0] = real();
411 | else
412 | if( xyz_m[0] >= real(1.0f) )
413 | xyz_m[0] = REAL_ALMOST_ONE;
414 |
415 | if( xyz_m[1] < real() )
416 | xyz_m[1] = real();
417 | else
418 | if( xyz_m[1] >= real(1.0f) )
419 | xyz_m[1] = REAL_ALMOST_ONE;
420 |
421 | if( xyz_m[2] < real() )
422 | xyz_m[2] = real();
423 | else
424 | if( xyz_m[2] >= real(1.0f) )
425 | xyz_m[2] = REAL_ALMOST_ONE;
426 |
427 | return *this;
428 | }*/
429 |
430 |
431 |
432 |
433 | /// queries --------------------------------------------------------------------
434 | /*void Vector3r::get
435 | (
436 | real& x,
437 | real& y,
438 | real& z
439 | ) const
440 | {
441 | x = xyz_m[0];
442 | y = xyz_m[1];
443 | z = xyz_m[2];
444 | }
445 |
446 |
447 | void Vector3r::get
448 | (
449 | real xyz[3]
450 | ) const
451 | {
452 | xyz[0] = xyz_m[0];
453 | xyz[1] = xyz_m[1];
454 | xyz[2] = xyz_m[2];
455 | }*/
456 |
457 |
458 | /*real Vector3r::sum() const
459 | {
460 | return xyz_m[0] + xyz_m[1] + xyz_m[2];
461 | }
462 |
463 |
464 | real Vector3r::average() const
465 | {
466 | static const real ONE_OVER_3 = real(1.0f) / real(3.0f);
467 |
468 | return (xyz_m[0] + xyz_m[1] + xyz_m[2]) * ONE_OVER_3;
469 | }
470 |
471 |
472 | real Vector3r::smallest() const
473 | {
474 | real smallest = xyz_m[0] <= xyz_m[1] ? xyz_m[0] : xyz_m[1];
475 | smallest = smallest <= xyz_m[2] ? smallest : xyz_m[2];
476 |
477 | return smallest;
478 | }
479 |
480 |
481 | real Vector3r::largest() const
482 | {
483 | real largest = xyz_m[0] >= xyz_m[1] ? xyz_m[0] : xyz_m[1];
484 | largest = largest >= xyz_m[2] ? largest : xyz_m[2];
485 |
486 | return largest;
487 | }*/
488 |
489 |
490 | real Vector3r::length() const
491 | {
492 | return sqrt(
493 | (xyz_m[0] * xyz_m[0]) +
494 | (xyz_m[1] * xyz_m[1]) +
495 | (xyz_m[2] * xyz_m[2]) );
496 | }
497 |
498 |
499 | /*real Vector3r::dot
500 | (
501 | const Vector3r& v
502 | ) const
503 | {
504 | return
505 | (xyz_m[0] * v.xyz_m[0]) +
506 | (xyz_m[1] * v.xyz_m[1]) +
507 | (xyz_m[2] * v.xyz_m[2]);
508 | }
509 |
510 |
511 | real Vector3r::distance
512 | (
513 | const Vector3r& v
514 | ) const
515 | {
516 | const real xDif = xyz_m[0] - v.xyz_m[0];
517 | const real yDif = xyz_m[1] - v.xyz_m[1];
518 | const real zDif = xyz_m[2] - v.xyz_m[2];
519 |
520 | return sqrt( (xDif * xDif) + (yDif * yDif) + (zDif * zDif) );
521 | }
522 |
523 |
524 | real Vector3r::distance2
525 | (
526 | const Vector3r& v
527 | ) const
528 | {
529 | const real xDif = xyz_m[0] - v.xyz_m[0];
530 | const real yDif = xyz_m[1] - v.xyz_m[1];
531 | const real zDif = xyz_m[2] - v.xyz_m[2];
532 |
533 | return (xDif * xDif) + (yDif * yDif) + (zDif * zDif);
534 | }*/
535 |
536 |
537 | /*Vector3r Vector3r::operator-() const
538 | {
539 | return Vector3r( -xyz_m[0], -xyz_m[1], -xyz_m[2] );
540 | }
541 |
542 |
543 | Vector3r Vector3r::abs() const
544 | {
545 | return Vector3r(
546 | xyz_m[0] >= real() ? xyz_m[0] : -xyz_m[0],
547 | xyz_m[1] >= real() ? xyz_m[1] : -xyz_m[1],
548 | xyz_m[2] >= real() ? xyz_m[2] : -xyz_m[2] );
549 | }
550 |
551 |
552 | Vector3r Vector3r::unitized() const
553 | {
554 | const real length = sqrt(
555 | (xyz_m[0] * xyz_m[0]) +
556 | (xyz_m[1] * xyz_m[1]) +
557 | (xyz_m[2] * xyz_m[2]) );
558 | const real oneOverLength = (length != real()) ?
559 | real(1.0) / length : real();
560 |
561 | return Vector3r(
562 | xyz_m[0] * oneOverLength,
563 | xyz_m[1] * oneOverLength,
564 | xyz_m[2] * oneOverLength );
565 | }
566 |
567 |
568 | Vector3r Vector3r::cross
569 | (
570 | const Vector3r& v
571 | ) const
572 | {
573 | return Vector3r(
574 | (xyz_m[1] * v.xyz_m[2]) - (xyz_m[2] * v.xyz_m[1]),
575 | (xyz_m[2] * v.xyz_m[0]) - (xyz_m[0] * v.xyz_m[2]),
576 | (xyz_m[0] * v.xyz_m[1]) - (xyz_m[1] * v.xyz_m[0]) );
577 | }*/
578 |
579 |
580 | Vector3r Vector3r::operator+
581 | (
582 | const Vector3r& v
583 | ) const
584 | {
585 | return Vector3r(
586 | xyz_m[0] + v.xyz_m[0],
587 | xyz_m[1] + v.xyz_m[1],
588 | xyz_m[2] + v.xyz_m[2] );
589 | }
590 |
591 |
592 | Vector3r Vector3r::operator-
593 | (
594 | const Vector3r& v
595 | ) const
596 | {
597 | return Vector3r(
598 | xyz_m[0] - v.xyz_m[0],
599 | xyz_m[1] - v.xyz_m[1],
600 | xyz_m[2] - v.xyz_m[2] );
601 | }
602 |
603 |
604 | Vector3r Vector3r::operator*
605 | (
606 | const Vector3r& v
607 | ) const
608 | {
609 | return Vector3r(
610 | xyz_m[0] * v.xyz_m[0],
611 | xyz_m[1] * v.xyz_m[1],
612 | xyz_m[2] * v.xyz_m[2] );
613 | }
614 |
615 |
616 | Vector3r Vector3r::operator/
617 | (
618 | const Vector3r& v
619 | ) const
620 | {
621 | return Vector3r(
622 | xyz_m[0] / v.xyz_m[0],
623 | xyz_m[1] / v.xyz_m[1],
624 | xyz_m[2] / v.xyz_m[2] );
625 | }
626 |
627 |
628 | Vector3r Vector3r::operator*
629 | (
630 | const real r
631 | ) const
632 | {
633 | return Vector3r(
634 | xyz_m[0] * r,
635 | xyz_m[1] * r,
636 | xyz_m[2] * r );
637 | }
638 |
639 |
640 | Vector3r Vector3r::operator/
641 | (
642 | const real r
643 | ) const
644 | {
645 | const real oneOverR = real(1.0f) / r;
646 |
647 | return Vector3r(
648 | xyz_m[0] * oneOverR,
649 | xyz_m[1] * oneOverR,
650 | xyz_m[2] * oneOverR );
651 | }
652 |
653 |
654 | bool Vector3r::operator==
655 | (
656 | const Vector3r& v
657 | ) const
658 | {
659 | return
660 | (xyz_m[0] == v.xyz_m[0]) &
661 | (xyz_m[1] == v.xyz_m[1]) &
662 | (xyz_m[2] == v.xyz_m[2]);
663 | }
664 |
665 |
666 | bool Vector3r::operator!=
667 | (
668 | const Vector3r& v
669 | ) const
670 | {
671 | return
672 | (xyz_m[0] != v.xyz_m[0]) |
673 | (xyz_m[1] != v.xyz_m[1]) |
674 | (xyz_m[2] != v.xyz_m[2]);
675 | }
676 |
677 |
678 | bool Vector3r::isZero() const
679 | {
680 | return bool(
681 | (xyz_m[0] == real()) &
682 | (xyz_m[1] == real()) &
683 | (xyz_m[2] == real()) );
684 | }
685 |
686 |
687 | /*Vector3r Vector3r::sign() const
688 | {
689 | return compare( Vector3r::ZERO() );
690 | }
691 |
692 |
693 | Vector3r Vector3r::compare
694 | (
695 | const Vector3r& v
696 | ) const
697 | {
698 | return Vector3r(
699 | xyz_m[0] > v.xyz_m[0] ?
700 | real(+1.0f) : (xyz_m[0] == v.xyz_m[0] ? real() : real(-1.0f)),
701 | xyz_m[1] > v.xyz_m[1] ?
702 | real(+1.0f) : (xyz_m[1] == v.xyz_m[1] ? real() : real(-1.0f)),
703 | xyz_m[2] > v.xyz_m[2] ?
704 | real(+1.0f) : (xyz_m[2] == v.xyz_m[2] ? real() : real(-1.0f)) );
705 | }
706 |
707 |
708 | Vector3r Vector3r::equal
709 | (
710 | const Vector3r& v
711 | ) const
712 | {
713 | return Vector3r(
714 | static_cast( xyz_m[0] == v.xyz_m[0] ),
715 | static_cast( xyz_m[1] == v.xyz_m[1] ),
716 | static_cast( xyz_m[2] == v.xyz_m[2] ) );
717 | }
718 |
719 |
720 | Vector3r Vector3r::operator>
721 | (
722 | const Vector3r& v
723 | ) const
724 | {
725 | return Vector3r(
726 | static_cast( xyz_m[0] > v.xyz_m[0] ),
727 | static_cast( xyz_m[1] > v.xyz_m[1] ),
728 | static_cast( xyz_m[2] > v.xyz_m[2] ) );
729 | }
730 |
731 |
732 | Vector3r Vector3r::operator>=
733 | (
734 | const Vector3r& v
735 | ) const
736 | {
737 | return Vector3r(
738 | static_cast( xyz_m[0] >= v.xyz_m[0] ),
739 | static_cast( xyz_m[1] >= v.xyz_m[1] ),
740 | static_cast( xyz_m[2] >= v.xyz_m[2] ) );
741 | }
742 |
743 |
744 | Vector3r Vector3r::operator<
745 | (
746 | const Vector3r& v
747 | ) const
748 | {
749 | return Vector3r(
750 | static_cast( xyz_m[0] < v.xyz_m[0] ),
751 | static_cast( xyz_m[1] < v.xyz_m[1] ),
752 | static_cast( xyz_m[2] < v.xyz_m[2] ) );
753 | }
754 |
755 |
756 | Vector3r Vector3r::operator<=
757 | (
758 | const Vector3r& v
759 | ) const
760 | {
761 | return Vector3r(
762 | static_cast( xyz_m[0] <= v.xyz_m[0] ),
763 | static_cast( xyz_m[1] <= v.xyz_m[1] ),
764 | static_cast( xyz_m[2] <= v.xyz_m[2] ) );
765 | }*/
766 |
767 |
768 | /*Vector3r Vector3r::clampedMin
769 | (
770 | const Vector3r& min
771 | ) const
772 | {
773 | Vector3r v( *this );
774 |
775 | if( v.xyz_m[0] < min.xyz_m[0] )
776 | {
777 | v.xyz_m[0] = min.xyz_m[0];
778 | }
779 | if( v.xyz_m[1] < min.xyz_m[1] )
780 | {
781 | v.xyz_m[1] = min.xyz_m[1];
782 | }
783 | if( v.xyz_m[2] < min.xyz_m[2] )
784 | {
785 | v.xyz_m[2] = min.xyz_m[2];
786 | }
787 |
788 | return v;
789 | }
790 |
791 |
792 | Vector3r Vector3r::clampedMax
793 | (
794 | const Vector3r& max
795 | ) const
796 | {
797 | Vector3r v( *this );
798 |
799 | if( v.xyz_m[0] > max.xyz_m[0] )
800 | {
801 | v.xyz_m[0] = max.xyz_m[0];
802 | }
803 | if( v.xyz_m[1] > max.xyz_m[1] )
804 | {
805 | v.xyz_m[1] = max.xyz_m[1];
806 | }
807 | if( v.xyz_m[2] > max.xyz_m[2] )
808 | {
809 | v.xyz_m[2] = max.xyz_m[2];
810 | }
811 |
812 | return v;
813 | }
814 |
815 |
816 | Vector3r Vector3r::clamped
817 | (
818 | const Vector3r& min,
819 | const Vector3r& max
820 | ) const
821 | {
822 | Vector3r v( *this );
823 |
824 | if( v.xyz_m[0] < min.xyz_m[0] )
825 | v.xyz_m[0] = min.xyz_m[0];
826 | else
827 | if( v.xyz_m[0] > max.xyz_m[0] )
828 | v.xyz_m[0] = max.xyz_m[0];
829 |
830 | if( v.xyz_m[1] < min.xyz_m[1] )
831 | v.xyz_m[1] = min.xyz_m[1];
832 | else
833 | if( v.xyz_m[1] > max.xyz_m[1] )
834 | v.xyz_m[1] = max.xyz_m[1];
835 |
836 | if( v.xyz_m[2] < min.xyz_m[2] )
837 | v.xyz_m[2] = min.xyz_m[2];
838 | else
839 | if( v.xyz_m[2] > max.xyz_m[2] )
840 | v.xyz_m[2] = max.xyz_m[2];
841 |
842 | return v;
843 | }
844 |
845 |
846 | Vector3r Vector3r::clamped01() const
847 | {
848 | // [0,1) 0 to almost 1
849 |
850 | Vector3r v( *this );
851 |
852 | if( v.xyz_m[0] < real() )
853 | v.xyz_m[0] = real();
854 | else
855 | if( v.xyz_m[0] >= real(1.0f) )
856 | v.xyz_m[0] = REAL_ALMOST_ONE;
857 |
858 | if( v.xyz_m[1] < real() )
859 | v.xyz_m[1] = real();
860 | else
861 | if( v.xyz_m[1] >= real(1.0f) )
862 | v.xyz_m[1] = REAL_ALMOST_ONE;
863 |
864 | if( v.xyz_m[2] < real() )
865 | v.xyz_m[2] = real();
866 | else
867 | if( v.xyz_m[2] >= real(1.0f) )
868 | v.xyz_m[2] = REAL_ALMOST_ONE;
869 |
870 | return v;
871 | }*/
872 |
873 |
874 |
875 |
876 | /// constants ------------------------------------------------------------------
877 | const Vector3r& Vector3r::ZERO()
878 | {
879 | static const Vector3r k( real(0.0f), real(0.0f), real(0.0f) );
880 | return k;
881 | }
882 |
883 |
884 | const Vector3r& Vector3r::HALF()
885 | {
886 | static const Vector3r k( real(0.5f), real(0.5f), real(0.5f) );
887 | return k;
888 | }
889 |
890 |
891 | const Vector3r& Vector3r::ONE()
892 | {
893 | static const Vector3r k( real(1.0f), real(1.0f), real(1.0f) );
894 | return k;
895 | }
896 |
897 |
898 | /*const Vector3r& Vector3r::EPSILON()
899 | {
900 | static const Vector3r k( REAL_EPSILON, REAL_EPSILON, REAL_EPSILON );
901 | return k;
902 | }
903 |
904 |
905 | const Vector3r& Vector3r::ALMOST_ONE()
906 | {
907 | static const Vector3r k( REAL_ALMOST_ONE, REAL_ALMOST_ONE, REAL_ALMOST_ONE );
908 | return k;
909 | }
910 |
911 |
912 | const Vector3r& Vector3r::MIN()
913 | {
914 | static const Vector3r k( REAL_MIN_NEG, REAL_MIN_NEG, REAL_MIN_NEG );
915 | return k;
916 | }
917 |
918 |
919 | const Vector3r& Vector3r::MAX()
920 | {
921 | static const Vector3r k( REAL_MAX, REAL_MAX, REAL_MAX );
922 | return k;
923 | }
924 |
925 |
926 | const Vector3r& Vector3r::SMALL()
927 | {
928 | static const Vector3r k( REAL_SMALL, REAL_SMALL, REAL_SMALL );
929 | return k;
930 | }
931 |
932 |
933 | const Vector3r& Vector3r::LARGE()
934 | {
935 | static const Vector3r k( REAL_LARGE, REAL_LARGE, REAL_LARGE );
936 | return k;
937 | }
938 |
939 |
940 | const Vector3r& Vector3r::X()
941 | {
942 | static const Vector3r k( real(1.0f), real(0.0f), real(0.0f) );
943 | return k;
944 | }
945 |
946 |
947 | const Vector3r& Vector3r::Y()
948 | {
949 | static const Vector3r k( real(0.0f), real(1.0f), real(0.0f) );
950 | return k;
951 | }
952 |
953 |
954 | const Vector3r& Vector3r::Z()
955 | {
956 | static const Vector3r k( real(0.0f), real(0.0f), real(1.0f) );
957 | return k;
958 | }*/
959 |
960 |
961 |
962 |
963 | /// friends --------------------------------------------------------------------
964 | Vector3r hxa7241_graphics::operator*
965 | (
966 | const real r,
967 | const Vector3r& v
968 | )
969 | {
970 | return Vector3r(
971 | r * v.xyz_m[0],
972 | r * v.xyz_m[1],
973 | r * v.xyz_m[2] );
974 | }
975 |
976 |
977 | Vector3r hxa7241_graphics::operator/
978 | (
979 | const real r,
980 | const Vector3r& v
981 | )
982 | {
983 | return Vector3r(
984 | r / v.xyz_m[0],
985 | r / v.xyz_m[1],
986 | r / v.xyz_m[2] );
987 | }
988 |
--------------------------------------------------------------------------------
/component/Vector3r.hpp:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------------------
2 |
3 | Octree Component, version 2.1
4 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
5 |
6 | http://www.hxa7241.org/
7 |
8 | ------------------------------------------------------------------------------*/
9 |
10 | /*------------------------------------------------------------------------------
11 |
12 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
13 |
14 | Redistribution and use in source and binary forms, with or without modification,
15 | are permitted provided that the following conditions are met:
16 |
17 | * Redistributions of source code must retain the above copyright notice, this
18 | list of conditions and the following disclaimer.
19 | * Redistributions in binary form must reproduce the above copyright notice, this
20 | list of conditions and the following disclaimer in the documentation and/or
21 | other materials provided with the distribution.
22 | * The name of the author may not be used to endorse or promote products derived
23 | from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
26 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28 | SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 | OF SUCH DAMAGE.
35 |
36 | ------------------------------------------------------------------------------*/
37 |
38 |
39 | #ifndef Vector3r_h
40 | #define Vector3r_h
41 |
42 |
43 | #include "Primitives.hpp"
44 |
45 |
46 |
47 |
48 | namespace hxa7241_graphics
49 | {
50 | using namespace hxa7241;
51 |
52 |
53 | /**
54 | * Yes, its the 3D vector class!.
55 | *
56 | * If you write some 3D graphics software, then you MUST write your OWN vector
57 | * class -- it is the law. So here is mine.
58 | *
59 | * (Unused stuff commented-out)
60 | */
61 | class Vector3r
62 | {
63 | /// standard object services ---------------------------------------------------
64 | public:
65 | Vector3r();
66 | Vector3r( real x,
67 | real y,
68 | real z );
69 | // explicit Vector3r( const real xyz[3] );
70 |
71 | ~Vector3r();
72 | Vector3r( const Vector3r& );
73 | Vector3r& operator=( const Vector3r& );
74 |
75 |
76 | /// commands -------------------------------------------------------------------
77 | Vector3r& set( real x,
78 | real y,
79 | real z );
80 | // Vector3r& set( const real xyz[3] );
81 | //
82 | // Vector3r& setX( real );
83 | // Vector3r& setY( real );
84 | // Vector3r& setZ( real );
85 | // real& operator[]( int );
86 |
87 | // Vector3r& negateEq ();
88 | // Vector3r& absEq ();
89 | // Vector3r& unitizeEq();
90 | // Vector3r& crossEq ( const Vector3r& );
91 |
92 | Vector3r& operator+=( const Vector3r& );
93 | Vector3r& operator-=( const Vector3r& );
94 | Vector3r& operator*=( const Vector3r& );
95 | Vector3r& operator/=( const Vector3r& );
96 | Vector3r& operator*=( real );
97 | Vector3r& operator/=( real );
98 |
99 | // Vector3r& clampMinEq( const Vector3r& );
100 | // Vector3r& clampMaxEq( const Vector3r& );
101 | // Vector3r& clampEq ( const Vector3r& min,
102 | // const Vector3r& max );
103 | // Vector3r& clamp01Eq ();
104 |
105 |
106 | /// queries --------------------------------------------------------------------
107 | // void get( real& x,
108 | // real& y,
109 | // real& z ) const;
110 | // void get( real xyz[3] ) const;
111 |
112 | real getX() const;
113 | real getY() const;
114 | real getZ() const;
115 | real operator[]( int ) const;
116 |
117 | // real sum() const;
118 | // real average() const;
119 | // real smallest() const;
120 | // real largest() const;
121 |
122 | real length() const;
123 | // real dot( const Vector3r& ) const;
124 | // real distance ( const Vector3r& ) const;
125 | // real distance2( const Vector3r& ) const;
126 |
127 | // Vector3r operator-() const;
128 | // Vector3r abs() const;
129 | // Vector3r unitized() const;
130 | // Vector3r cross( const Vector3r& ) const;
131 |
132 | Vector3r operator+( const Vector3r& ) const;
133 | Vector3r operator-( const Vector3r& ) const;
134 | Vector3r operator*( const Vector3r& ) const;
135 | Vector3r operator/( const Vector3r& ) const;
136 | Vector3r operator*( real ) const;
137 | Vector3r operator/( real ) const;
138 |
139 | bool operator==( const Vector3r& ) const;
140 | bool operator!=( const Vector3r& ) const;
141 | bool isZero() const;
142 |
143 | // // returning vectors of -1.0 or 0.0 or +1.0
144 | // Vector3r sign () const;
145 | // Vector3r compare( const Vector3r& ) const;
146 | //
147 | // // returning vectors of static_cast(bool)
148 | // Vector3r equal ( const Vector3r& ) const;
149 | // Vector3r operator> ( const Vector3r& ) const;
150 | // Vector3r operator>=( const Vector3r& ) const;
151 | // Vector3r operator< ( const Vector3r& ) const;
152 | // Vector3r operator<=( const Vector3r& ) const;
153 |
154 | // Vector3r clampedMin( const Vector3r& ) const;
155 | // Vector3r clampedMax( const Vector3r& ) const;
156 | // Vector3r clamped ( const Vector3r& min,
157 | // const Vector3r& max ) const;
158 | // Vector3r clamped01 () const;
159 |
160 | friend Vector3r operator*( real, const Vector3r& );
161 | friend Vector3r operator/( real, const Vector3r& );
162 |
163 |
164 | /// constants ------------------------------------------------------------------
165 | static const Vector3r& ZERO();
166 | static const Vector3r& HALF();
167 | static const Vector3r& ONE();
168 | // static const Vector3r& EPSILON();
169 | // static const Vector3r& ALMOST_ONE();
170 | // static const Vector3r& MIN();
171 | // static const Vector3r& MAX();
172 | // static const Vector3r& SMALL();
173 | // static const Vector3r& LARGE();
174 | // static const Vector3r& X();
175 | // static const Vector3r& Y();
176 | // static const Vector3r& Z();
177 |
178 |
179 | /// fields ---------------------------------------------------------------------
180 | private:
181 | real xyz_m[3];
182 | };
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 | /// friends
192 | Vector3r operator*( real, const Vector3r& );
193 | Vector3r operator/( real, const Vector3r& );
194 |
195 |
196 |
197 |
198 | /// INLINES ///
199 | /*
200 | * These are certain. Leave others to the compiler.
201 | */
202 |
203 |
204 | /// standard object services ---------------------------------------------------
205 | /*inline
206 | Vector3r::Vector3r
207 | (
208 | const real xyz[3]
209 | )
210 | {
211 | Vector3r::set( xyz );
212 | }*/
213 |
214 |
215 | inline
216 | Vector3r::~Vector3r()
217 | {
218 | }
219 |
220 |
221 | inline
222 | Vector3r::Vector3r
223 | (
224 | const Vector3r& other
225 | )
226 | {
227 | Vector3r::operator=( other );
228 | }
229 |
230 |
231 |
232 |
233 | /// queries --------------------------------------------------------------------
234 | inline
235 | real Vector3r::getX() const
236 | {
237 | return xyz_m[0];
238 | }
239 |
240 |
241 | inline
242 | real Vector3r::getY() const
243 | {
244 | return xyz_m[1];
245 | }
246 |
247 |
248 | inline
249 | real Vector3r::getZ() const
250 | {
251 | return xyz_m[2];
252 | }
253 |
254 |
255 | inline
256 | real Vector3r::operator[]
257 | (
258 | const int i
259 | ) const
260 | {
261 | // careful !
262 | return xyz_m[i];
263 | }
264 |
265 |
266 | }//namespace
267 |
268 |
269 |
270 |
271 | #endif//Vector3r_h
272 |
--------------------------------------------------------------------------------
/docs/ogc-class-relations-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hxa7241/octree-cpp/a8e40b0d0a55bdc293a4848170f43daf42c926e3/docs/ogc-class-relations-diagram.png
--------------------------------------------------------------------------------
/docs/ogc-visit-sequence-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hxa7241/octree-cpp/a8e40b0d0a55bdc293a4848170f43daf42c926e3/docs/ogc-visit-sequence-diagram.png
--------------------------------------------------------------------------------
/samples/OctreeExample.cpp:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------------------
2 |
3 | Octree Component, version 2.1
4 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
5 |
6 | http://www.hxa7241.org/
7 |
8 | ------------------------------------------------------------------------------*/
9 |
10 | /*------------------------------------------------------------------------------
11 |
12 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
13 |
14 | Redistribution and use in source and binary forms, with or without modification,
15 | are permitted provided that the following conditions are met:
16 |
17 | * Redistributions of source code must retain the above copyright notice, this
18 | list of conditions and the following disclaimer.
19 | * Redistributions in binary form must reproduce the above copyright notice, this
20 | list of conditions and the following disclaimer in the documentation and/or
21 | other materials provided with the distribution.
22 | * The name of the author may not be used to endorse or promote products derived
23 | from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
26 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28 | SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 | OF SUCH DAMAGE.
35 |
36 | ------------------------------------------------------------------------------*/
37 |
38 |
39 | #include
40 | #include
41 |
42 | #include "Octree.hpp"
43 |
44 |
45 | using namespace hxa7241_graphics;
46 |
47 |
48 |
49 |
50 | /**
51 | * Step 1:
52 | * Check your item class provides access to its 3D properties.
53 | *
54 | * Step 2:
55 | * Implement a derivative of OctreeAgent, to calculate if an item
56 | * overlaps a cell, or subcells.
57 | *
58 | * Step 3:
59 | * Implement derivatives of OctreeVisitor, to perform operations
60 | * on an octree.
61 | *
62 | * Step 4:
63 | * Write code to create items, octrees, and visitors, add/remove items
64 | * to octrees, and execute operations on octrees.
65 | */
66 |
67 |
68 | /**
69 | * File contents:
70 |
71 | * Classes
72 | * * Block class: an example item
73 | * * OctreeAgentBlock class: an agent for the example item
74 | * * OctreeVisitorExample class: an example visitor using the item
75 | * Functions
76 | * * main function: code to make some items, make an octree, and use the
77 | * visitor.
78 | */
79 |
80 |
81 |
82 |
83 | /// Vector3r stream out
84 |
85 | std::ostream& operator<<( std::ostream&, const Vector3r& );
86 |
87 | std::ostream& operator<<
88 | (
89 | std::ostream& out,
90 | const Vector3r& obj
91 | )
92 | {
93 | return out << '(' << obj[0] << ' ' << obj[1] << ' ' << obj[2] << ')';
94 | }
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | /// Block //////////////////////////////////////////////////////////////////////
104 |
105 | /**
106 | * An example item: a minimal axis-aligned 3D block.
107 | *
108 | * You write this class, however you want. Though it will have some primitive
109 | * access to its 3D properties.
110 | */
111 | class Block
112 | {
113 | /// standard object services ---------------------------------------------------
114 | public:
115 | Block();
116 | Block( const Vector3r& position,
117 | const Vector3r& dimension );
118 |
119 | ~Block();
120 | Block( const Block& );
121 | Block& operator=( const Block& );
122 |
123 |
124 | /// queries --------------------------------------------------------------------
125 | const Vector3r& getPosition() const;
126 | const Vector3r& getDimensions() const;
127 |
128 |
129 | /// fields ---------------------------------------------------------------------
130 | private:
131 | Vector3r position_m;
132 | Vector3r dimensions_m;
133 | };
134 |
135 |
136 |
137 |
138 | /// standard object services ---------------------------------------------------
139 | Block::Block()
140 | : position_m ()
141 | , dimensions_m()
142 | {
143 | }
144 |
145 |
146 | Block::Block
147 | (
148 | const Vector3r& position,
149 | const Vector3r& dimensions
150 | )
151 | : position_m ( position )
152 | , dimensions_m( dimensions )
153 | {
154 | }
155 |
156 |
157 | Block::~Block()
158 | {
159 | }
160 |
161 |
162 | Block::Block
163 | (
164 | const Block& other
165 | )
166 | : position_m ( other.position_m )
167 | , dimensions_m( other.dimensions_m )
168 | {
169 | }
170 |
171 |
172 | Block& Block::operator=
173 | (
174 | const Block& other
175 | )
176 | {
177 | if( &other != this )
178 | {
179 | position_m = other.position_m;
180 | dimensions_m = other.dimensions_m;
181 | }
182 |
183 | return *this;
184 | }
185 |
186 |
187 | /// queries --------------------------------------------------------------------
188 | const Vector3r& Block::getPosition() const
189 | {
190 | return position_m;
191 | }
192 |
193 |
194 | const Vector3r& Block::getDimensions() const
195 | {
196 | return dimensions_m;
197 | }
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 | /// OctreeAgentBlock ///////////////////////////////////////////////////////////
207 |
208 | /**
209 | * An example Octree agent, for Block item class.
210 | *
211 | * You must write this class, as a concrete derivative of OctreeAgent<>. It
212 | * provides the Octree with a way to interact with your item class.
213 | */
214 | class OctreeAgentBlock
215 | : public OctreeAgent
216 | {
217 | /// standard object services ---------------------------------------------------
218 | public:
219 | OctreeAgentBlock() {};
220 |
221 | virtual ~OctreeAgentBlock() {};
222 | private:
223 | OctreeAgentBlock( const OctreeAgentBlock& );
224 | OctreeAgentBlock& operator=( const OctreeAgentBlock& );
225 |
226 |
227 | /// queries --------------------------------------------------------------------
228 | /// octree agent overrides
229 | protected:
230 | virtual bool isOverlappingCell ( const Block& item,
231 | const Vector3r& lowerCorner,
232 | const Vector3r& upperCorner ) const;
233 |
234 | // could also override getSubcellOverlaps to provide more efficent
235 | // calculation (boundary testing can be shared).
236 | };
237 |
238 |
239 |
240 |
241 | /// queries --------------------------------------------------------------------
242 | bool OctreeAgentBlock::isOverlappingCell
243 | (
244 | const Block& item,
245 | const Vector3r& lowerCorner,
246 | const Vector3r& upperCorner
247 | ) const
248 | {
249 | const Vector3r& itemLower( item.getPosition() );
250 | const Vector3r itemUpper = item.getPosition() + item.getDimensions();
251 |
252 | // check the two ranges overlap in every dimension
253 | bool isOverlap = true;
254 | for( int i = 3; i-- > 0; )
255 | {
256 | isOverlap &= (itemLower[i] < upperCorner[i]) &
257 | (itemUpper[i] > lowerCorner[i]);
258 | }
259 |
260 | return isOverlap;
261 | }
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 | /// OctreeVisitorExample ///////////////////////////////////////////////////////
271 |
272 | /**
273 | * An example Octree visitor, for writing out leaf content.
274 | *
275 | * You must write this class, as a concrete derivative of OctreeVisitor<>. It
276 | * defines an search/inspection operation on your items in an octree. Any number
277 | * of different ones can be written and used on the same octree.
278 | */
279 | class OctreeVisitorExample
280 | : public OctreeVisitor
281 | {
282 | /// standard object services ---------------------------------------------------
283 | public:
284 | OctreeVisitorExample();
285 |
286 | virtual ~OctreeVisitorExample();
287 | private:
288 | OctreeVisitorExample( const OctreeVisitorExample& );
289 | OctreeVisitorExample& operator=( const OctreeVisitorExample& );
290 |
291 |
292 | /// commands -------------------------------------------------------------------
293 | /// octree visitor overrides
294 | protected:
295 | virtual void visitRoot ( const OctreeCell* pRootCell,
296 | const OctreeData& octreeData );
297 | virtual void visitBranch( const OctreeCell* subCells[8],
298 | const OctreeData& octreeData );
299 | virtual void visitLeaf ( const Array& items,
300 | const OctreeData& octreeData );
301 |
302 | // any other commands ...
303 |
304 |
305 | /// queries --------------------------------------------------------------------
306 | // any queries ...
307 |
308 |
309 | /// fields ---------------------------------------------------------------------
310 | private:
311 | // any fields ...
312 | };
313 |
314 |
315 |
316 |
317 | /// standard object services ---------------------------------------------------
318 | OctreeVisitorExample::OctreeVisitorExample()
319 | {
320 | }
321 |
322 |
323 | OctreeVisitorExample::~OctreeVisitorExample()
324 | {
325 | }
326 |
327 |
328 | /// commands -------------------------------------------------------------------
329 | void OctreeVisitorExample::visitRoot
330 | (
331 | const OctreeCell* pRootCell,
332 | const OctreeData& octreeData
333 | )
334 | {
335 | // continue visit traversal
336 | OctreeRoot::continueVisit( pRootCell, octreeData, *this );
337 | }
338 |
339 |
340 | void OctreeVisitorExample::visitBranch
341 | (
342 | const OctreeCell* subCells[8],
343 | const OctreeData& octreeData
344 | )
345 | {
346 | // subcell numbering:
347 | // y z 6 7
348 | // |/ 2 3 4 5
349 | // -x 0 1
350 | //
351 | // (in binary:)
352 | // y z 110 111
353 | // |/ 010 011 100 101
354 | // -x 000 001
355 | //
356 |
357 | // step through subcells (can be in any order...)
358 | for( dword i = 0; i < 8; ++i )
359 | {
360 | // maybe do something here...
361 |
362 | // continue visit traversal
363 | OctreeBranch::continueVisit( subCells, octreeData, i, *this );
364 |
365 | // maybe do something here...
366 | }
367 | }
368 |
369 |
370 | void OctreeVisitorExample::visitLeaf
371 | (
372 | const Array& items,
373 | const OctreeData& octreeData
374 | )
375 | {
376 | // write out cell and items data:
377 |
378 | // make some short aliases
379 | const Vector3r& lower( octreeData.getBound().getLowerCorner() );
380 | const Vector3r& upper( octreeData.getBound().getUpperCorner() );
381 |
382 | // write leaf bound
383 | std::cout << "leaf: level(" << octreeData.getLevel() << ") ";
384 | std::cout << "lower" << lower << " " << "upper" << upper << "\n";
385 |
386 | // write items
387 | for( dword i = 0, end = items.getLength(); i < end; ++i )
388 | {
389 | // make some short aliases
390 | const Vector3r& lower( items[i]->getPosition() );
391 | const Vector3r upper( items[i]->getPosition() + items[i]->getDimensions()
392 | );
393 |
394 | // write item
395 | std::cout << " item: ";
396 | std::cout << "lower" << lower << " " << "upper" << upper << "\n";
397 | }
398 |
399 | std::cout << "\n";
400 | }
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 | /// main ///////////////////////////////////////////////////////////////////////
410 |
411 | /**
412 | * An example Octree usage, with the previously written classes.
413 | *
414 | * You must write some code to instantiate the items, octree, agent, and
415 | * visitors; and then add/remove items and visit the octree.
416 | */
417 | int main
418 | (
419 | int ,//argc,
420 | char*[] //argv[]
421 | )
422 | {
423 | // write banner
424 | std::cout << "\n HXA Octree Component v2.1 C++ *example*\n" <<
425 | " Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.\n"
426 | " http://www.hxa7241.org/\n\n";
427 |
428 |
429 | // make some items
430 | std::vector blocks;
431 | for( int i = 0; i < 8; ++i )
432 | {
433 | // one in the middle of each octant
434 | blocks.push_back( Block( Vector3r( real(i & 1) + 0.25f,
435 | real((i >> 1) & 1) + 0.25f,
436 | real((i >> 2) & 1) + 0.25f ),
437 | Vector3r(0.5f, 0.5f, 0.5f) ) );
438 | }
439 |
440 | // make an octree:
441 | // position (0,0,0), size 2m, max items per leaf 4, max depth 4,
442 | // min cell size 1mm
443 | Octree octree( Vector3r::ZERO(), 2.0f, 4, 4, 0.001f );
444 | std::cout << "Octree: position" << octree.getPosition() <<
445 | " size(" << octree.getSize() << ")" << "\n\n";
446 |
447 |
448 | // make an agent (probably a singleton)
449 | OctreeAgentBlock agent;
450 |
451 | // add items to octree, using agent
452 | for( int i = 0, end = blocks.size(); i < end; ++i )
453 | {
454 | octree.insert( blocks[i], agent );
455 | }
456 |
457 |
458 | // make a visitor (as many concrete variants and instances as wanted)
459 | OctreeVisitorExample visitor;
460 |
461 | // execute visitor
462 | octree.visit( visitor );
463 |
464 |
465 | return EXIT_SUCCESS;
466 | }
467 |
--------------------------------------------------------------------------------
/samples/OctreeStreamOut.cpp:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------------------
2 |
3 | Octree Component, version 2.1
4 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
5 |
6 | http://www.hxa7241.org/
7 |
8 | ------------------------------------------------------------------------------*/
9 |
10 | /*------------------------------------------------------------------------------
11 |
12 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
13 |
14 | Redistribution and use in source and binary forms, with or without modification,
15 | are permitted provided that the following conditions are met:
16 |
17 | * Redistributions of source code must retain the above copyright notice, this
18 | list of conditions and the following disclaimer.
19 | * Redistributions in binary form must reproduce the above copyright notice, this
20 | list of conditions and the following disclaimer in the documentation and/or
21 | other materials provided with the distribution.
22 | * The name of the author may not be used to endorse or promote products derived
23 | from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
26 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28 | SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 | OF SUCH DAMAGE.
35 |
36 | ------------------------------------------------------------------------------*/
37 |
38 |
39 | #include
40 |
41 | #include "OctreeStreamOut.hpp"
42 |
43 |
44 | using namespace hxa7241_graphics;
45 |
46 |
47 |
48 |
49 | /// other ----------------------------------------------------------------------
50 | static std::ostream& operator<<( std::ostream&, const Vector3r& );
51 |
52 | std::ostream& operator<<
53 | (
54 | std::ostream& out,
55 | const Vector3r& v
56 | )
57 | {
58 | return out << "(" << v.getX() << ", " << v.getY() << ", " << v.getZ() << ")";
59 | }
60 |
61 |
62 |
63 |
64 | /// standard object services ---------------------------------------------------
65 | OctreeStreamOutImplementation::OctreeStreamOutImplementation
66 | (
67 | std::ostream& outStream,
68 | const bool isLongFormat
69 | )
70 | : pOutStream_m ( &outStream )
71 | , isLongFormat_m( isLongFormat )
72 | , pCurrentCell_m( 0 )
73 | , indent_m ( 0 )
74 | {
75 | }
76 |
77 |
78 | OctreeStreamOutImplementation::~OctreeStreamOutImplementation()
79 | {
80 | }
81 |
82 |
83 | OctreeStreamOutImplementation::OctreeStreamOutImplementation
84 | (
85 | const OctreeStreamOutImplementation& other
86 | )
87 | : pOutStream_m ( other.pOutStream_m )
88 | , isLongFormat_m( other.isLongFormat_m )
89 | , pCurrentCell_m( 0 )
90 | , indent_m ( 0 )
91 | {
92 | }
93 |
94 |
95 | OctreeStreamOutImplementation& OctreeStreamOutImplementation::operator=
96 | (
97 | const OctreeStreamOutImplementation& other
98 | )
99 | {
100 | if( &other != this )
101 | {
102 | pOutStream_m = other.pOutStream_m;
103 | isLongFormat_m = other.isLongFormat_m;
104 |
105 | pCurrentCell_m = 0;
106 | indent_m = 0;
107 | }
108 |
109 | return *this;
110 | }
111 |
112 |
113 |
114 |
115 | /// commands -------------------------------------------------------------------
116 | void OctreeStreamOutImplementation::visitRoot
117 | (
118 | const OctreeCell* pRootCell,
119 | const OctreeData& octreeData,
120 | OctreeVisitorV& visitor
121 | )
122 | {
123 | dword byteSize = 0;
124 | dword leafCount = 0;
125 | dword itemCount = 0;
126 | dword maxDepth = 0;
127 |
128 | if( pRootCell )
129 | {
130 | pRootCell->getInfo( byteSize, leafCount, itemCount, maxDepth );
131 | }
132 |
133 | byteSize += sizeof(OctreeRoot);
134 |
135 | const OctreeDimensions& dimensions = octreeData.getDimensions();
136 | *pOutStream_m << "\nOctree " <<
137 | "\nposition: " << dimensions.getPosition() <<
138 | " size: " << dimensions.getSize() <<
139 | " maxItemsPerCell: " << dimensions.getMaxItemCountPerCell() <<
140 | " maxLevelCount: " << dimensions.getMaxLevelCount() <<
141 | "\n(bytes: " << byteSize <<
142 | ", leafs: " << leafCount <<
143 | ", items: " << itemCount <<
144 | ", depth: " << maxDepth <<
145 | ")\n{ ";
146 |
147 | if( pRootCell )
148 | {
149 | pCurrentCell_m = pRootCell;
150 | indent_m = 1;
151 |
152 | // continue visit traversal
153 | OctreeRoot::continueVisit( pRootCell, octreeData, visitor );
154 | }
155 | else
156 | {
157 | *pOutStream_m << "empty ";
158 | }
159 |
160 | *pOutStream_m << "}\n";
161 | }
162 |
163 |
164 | void OctreeStreamOutImplementation::visitBranch
165 | (
166 | const OctreeCell* subCells[8],
167 | const OctreeData& octreeData,
168 | OctreeVisitorV& visitor
169 | )
170 | {
171 | writeDataAndInfo( *pCurrentCell_m, octreeData, *pOutStream_m );
172 |
173 | // step through subcells
174 | for( int i = 0; i < 8; ++i )
175 | {
176 | *pOutStream_m << "\n";
177 | for( dword j = indent_m; j-- > 0; )
178 | {
179 | *pOutStream_m << "\t";
180 | }
181 | *pOutStream_m << "[" << i << " ";
182 |
183 | const OctreeCell*const pSubCell = subCells[i];
184 | if( pSubCell )
185 | {
186 | pCurrentCell_m = pSubCell;
187 | indent_m += 1;
188 |
189 | // continue visit traversal
190 | OctreeBranch::continueVisit( subCells, octreeData, i, visitor );
191 |
192 | indent_m -= 1;
193 | }
194 | else
195 | {
196 | *pOutStream_m << "empty ";
197 | }
198 |
199 | *pOutStream_m << "] ";
200 | }
201 |
202 | *pOutStream_m << "\n";
203 | for( dword i = indent_m - 1; i-- > 0; )
204 | {
205 | *pOutStream_m << "\t";
206 | }
207 | }
208 |
209 |
210 | void OctreeStreamOutImplementation::visitLeafBefore
211 | (
212 | const OctreeData& octreeData
213 | )
214 | {
215 | writeDataAndInfo( *pCurrentCell_m, octreeData, *pOutStream_m );
216 |
217 | indentNewline( 0 );
218 |
219 | if( isLongFormat_m )
220 | {
221 | *pOutStream_m << "<";
222 | }
223 | }
224 |
225 |
226 | void OctreeStreamOutImplementation::visitLeafAfter()
227 | {
228 | if( isLongFormat_m )
229 | {
230 | indentNewline( 0 );
231 | *pOutStream_m << ">";
232 | indentNewline( -1 );
233 | }
234 | }
235 |
236 |
237 | bool OctreeStreamOutImplementation::isLongFormat() const
238 | {
239 | return isLongFormat_m;
240 | }
241 |
242 |
243 | std::ostream& OctreeStreamOutImplementation::getOutStream() const
244 | {
245 | return *pOutStream_m;
246 | }
247 |
248 |
249 | std::ostream& OctreeStreamOutImplementation::indentNewline
250 | (
251 | const dword extraIndent
252 | ) const
253 | {
254 | *pOutStream_m << "\n";
255 | for( dword i = indent_m + extraIndent; i-- > 0; )
256 | {
257 | *pOutStream_m << "\t";
258 | }
259 |
260 | return *pOutStream_m;
261 | }
262 |
263 |
264 |
265 |
266 | /// implementation -------------------------------------------------------------
267 |
268 | void OctreeStreamOutImplementation::writeDataAndInfo
269 | (
270 | const OctreeCell& octreeCell,
271 | const OctreeData& octreeData,
272 | std::ostream& outStream
273 | )
274 | {
275 | // do octreeData
276 | outStream << "level(" <<
277 | octreeData.getLevel() << ") lo" <<
278 | octreeData.getBound().getLowerCorner() << " hi" <<
279 | octreeData.getBound().getUpperCorner() << " ctr" <<
280 | octreeData.getBound().getCenter() << " sph(" <<
281 | octreeData.getBound().getRadius() << ") ";
282 |
283 | // do info
284 | dword byteSize = 0;
285 | dword leafCount = 0;
286 | dword itemCount = 0;
287 | dword depthLargest = 0;
288 | octreeCell.getInfo( byteSize, leafCount, itemCount, depthLargest );
289 |
290 | outStream <<
291 | "(bytes: " << byteSize <<
292 | ", leafs: " << leafCount <<
293 | ", items: " << itemCount <<
294 | ", depth: " << depthLargest << ") ";
295 | }
296 |
--------------------------------------------------------------------------------
/samples/OctreeStreamOut.hpp:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------------------
2 |
3 | Octree Component, version 2.1
4 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
5 |
6 | http://www.hxa7241.org/
7 |
8 | ------------------------------------------------------------------------------*/
9 |
10 | /*------------------------------------------------------------------------------
11 |
12 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
13 |
14 | Redistribution and use in source and binary forms, with or without modification,
15 | are permitted provided that the following conditions are met:
16 |
17 | * Redistributions of source code must retain the above copyright notice, this
18 | list of conditions and the following disclaimer.
19 | * Redistributions in binary form must reproduce the above copyright notice, this
20 | list of conditions and the following disclaimer in the documentation and/or
21 | other materials provided with the distribution.
22 | * The name of the author may not be used to endorse or promote products derived
23 | from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
26 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28 | SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 | OF SUCH DAMAGE.
35 |
36 | ------------------------------------------------------------------------------*/
37 |
38 |
39 | #ifndef OctreeStreamOut_h
40 | #define OctreeStreamOut_h
41 |
42 |
43 | #include
44 |
45 | #include "Octree.hpp"
46 |
47 |
48 |
49 |
50 | namespace hxa7241_graphics
51 | {
52 |
53 |
54 | /**
55 | * Implementation for OctreeStreamOut template.
56 | *
57 | * @see OctreeStreamOut
58 | */
59 | class OctreeStreamOutImplementation
60 | {
61 | /// standard object services ---------------------------------------------------
62 | public:
63 | OctreeStreamOutImplementation( std::ostream& outStream,
64 | bool isLongFormat );
65 |
66 | ~OctreeStreamOutImplementation();
67 | OctreeStreamOutImplementation(
68 | const OctreeStreamOutImplementation& );
69 | OctreeStreamOutImplementation& operator=(
70 | const OctreeStreamOutImplementation& );
71 |
72 |
73 | /// commands -------------------------------------------------------------------
74 | void visitRoot ( const OctreeCell* pRootCell,
75 | const OctreeData& octreeData,
76 | OctreeVisitorV& visitor );
77 | void visitBranch( const OctreeCell* subCells[8],
78 | const OctreeData& octreeData,
79 | OctreeVisitorV& visitor );
80 | void visitLeafBefore( const OctreeData& octreeData );
81 | void visitLeafAfter ();
82 |
83 | bool isLongFormat() const;
84 | std::ostream& getOutStream() const;
85 | std::ostream& indentNewline( dword extraIndent ) const;
86 |
87 |
88 | /// implementation -------------------------------------------------------------
89 | protected:
90 | static void writeDataAndInfo( const OctreeCell& octreeCell,
91 | const OctreeData& octreeData,
92 | std::ostream& outStream );
93 |
94 |
95 | /// fields ---------------------------------------------------------------------
96 | private:
97 | std::ostream* pOutStream_m;
98 | bool isLongFormat_m;
99 |
100 | // visit state (only used during a visit)
101 | const OctreeCell* pCurrentCell_m;
102 | dword indent_m;
103 | };
104 |
105 |
106 |
107 |
108 |
109 | /**
110 | * An octree visitor for writing a text representation of an octree and its
111 | * contents.
112 | *
113 | * @see OctreeStreamOutImplementation
114 | */
115 | template
116 | class OctreeStreamOut
117 | : public OctreeVisitor
118 | {
119 | /// standard object services ---------------------------------------------------
120 | public:
121 | OctreeStreamOut( std::ostream& outStream,
122 | bool isLongFormat );
123 |
124 | virtual ~OctreeStreamOut();
125 | OctreeStreamOut( const OctreeStreamOut& );
126 | OctreeStreamOut& operator=( const OctreeStreamOut& );
127 |
128 |
129 | /// octree visitor overrides
130 | /// commands -------------------------------------------------------------------
131 | protected:
132 | virtual void visitRoot ( const OctreeCell* pRootCell,
133 | const OctreeData& octreeData );
134 | virtual void visitBranch( const OctreeCell* subCells[8],
135 | const OctreeData& octreeData );
136 | virtual void visitLeaf ( const Array& items,
137 | const OctreeData& octreeData );
138 |
139 |
140 | /// fields ---------------------------------------------------------------------
141 | private:
142 | OctreeStreamOutImplementation implementation_m;
143 | };
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 | /// TEMPLATES ///
153 |
154 | /// standard object services ---------------------------------------------------
155 | template
156 | inline
157 | OctreeStreamOut::OctreeStreamOut
158 | (
159 | std::ostream& outStream,
160 | const bool isLongFormat
161 | )
162 | : OctreeVisitor()
163 | , implementation_m ( outStream, isLongFormat )
164 | {
165 | }
166 |
167 |
168 | template
169 | inline
170 | OctreeStreamOut::~OctreeStreamOut()
171 | {
172 | }
173 |
174 |
175 | template
176 | inline
177 | OctreeStreamOut::OctreeStreamOut
178 | (
179 | const OctreeStreamOut& other
180 | )
181 | : OctreeVisitor()
182 | , implementation_m ( other.implementation_m )
183 | {
184 | }
185 |
186 |
187 | template
188 | inline
189 | OctreeStreamOut& OctreeStreamOut::operator=
190 | (
191 | const OctreeStreamOut& other
192 | )
193 | {
194 | if( &other != this )
195 | {
196 | implementation_m = other.implementation_m;
197 | }
198 |
199 | return *this;
200 | }
201 |
202 |
203 |
204 |
205 | /// commands -------------------------------------------------------------------
206 | template
207 | inline
208 | void OctreeStreamOut::visitRoot
209 | (
210 | const OctreeCell* pRootCell,
211 | const OctreeData& octreeData
212 | )
213 | {
214 | implementation_m.visitRoot( pRootCell, octreeData, *this );
215 | }
216 |
217 |
218 | template
219 | inline
220 | void OctreeStreamOut::visitBranch
221 | (
222 | const OctreeCell* subCells[8],
223 | const OctreeData& octreeData
224 | )
225 | {
226 | implementation_m.visitBranch( subCells, octreeData, *this );
227 | }
228 |
229 |
230 | template
231 | void OctreeStreamOut::visitLeaf
232 | (
233 | const Array& items,
234 | const OctreeData& octreeData
235 | )
236 | {
237 | implementation_m.visitLeafBefore( octreeData );
238 |
239 | const TYPE* const* ppItem = items.getStorage();
240 | const TYPE* const* ppEnd = ppItem + items.getLength();
241 |
242 | for( ; ppItem < ppEnd; ++ppItem )
243 | {
244 | if( implementation_m.isLongFormat() )
245 | {
246 | implementation_m.indentNewline( +1 );
247 | implementation_m.getOutStream() << "id:" << *ppItem << ": " <<
248 | **ppItem;
249 | }
250 | else
251 | {
252 | implementation_m.getOutStream() << "<" << "id:" << *ppItem <<
253 | ": " << **ppItem << "> ";
254 | }
255 | }
256 |
257 | implementation_m.visitLeafAfter();
258 | }
259 |
260 |
261 | }//namespace
262 |
263 |
264 |
265 |
266 | #endif//OctreeStreamOut_h
267 |
--------------------------------------------------------------------------------
/samples/OctreeTest.cpp:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------------------
2 |
3 | Octree Component, version 2.1
4 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
5 |
6 | http://www.hxa7241.org/
7 |
8 | ------------------------------------------------------------------------------*/
9 |
10 | /*------------------------------------------------------------------------------
11 |
12 | Copyright (c) 2004-2007, Harrison Ainsworth / HXA7241.
13 |
14 | Redistribution and use in source and binary forms, with or without modification,
15 | are permitted provided that the following conditions are met:
16 |
17 | * Redistributions of source code must retain the above copyright notice, this
18 | list of conditions and the following disclaimer.
19 | * Redistributions in binary form must reproduce the above copyright notice, this
20 | list of conditions and the following disclaimer in the documentation and/or
21 | other materials provided with the distribution.
22 | * The name of the author may not be used to endorse or promote products derived
23 | from this software without specific prior written permission.
24 |
25 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
26 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
28 | SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
30 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 | OF SUCH DAMAGE.
35 |
36 | ------------------------------------------------------------------------------*/
37 |
38 |
39 | #include
40 | #include
41 | #include
42 | #include
43 | #include
44 | #include
45 | #include
46 | #include
47 |
48 | #include "Octree.hpp"
49 |
50 | #include "OctreeStreamOut.hpp"
51 | #include "OctreeTest.hpp"
52 |
53 |
54 | using namespace hxa7241_graphics;
55 |
56 |
57 |
58 |
59 | std::ostream& operator<<( std::ostream&, const Vector3r& );
60 |
61 | std::ostream& operator<<
62 | (
63 | std::ostream& out,
64 | const Vector3r& v3f
65 | )
66 | {
67 | out << "(" << v3f.getX() << ", " << v3f.getY() << ", " << v3f.getZ() << ")";
68 |
69 | return out;
70 | }
71 |
72 |
73 |
74 |
75 | /// OctreeItemTest /////////////////////////////////////////////////////////////
76 |
77 | class OctreeItemTest
78 | {
79 | /// standard object services ---------------------------------------------------
80 | public:
81 | OctreeItemTest( const Vector3r& position = Vector3r::ZERO(),
82 | const Vector3r& dimension = Vector3r::ZERO(),
83 | dword payload = 0 );
84 |
85 | virtual ~OctreeItemTest();
86 | OctreeItemTest( const OctreeItemTest& );
87 | OctreeItemTest& operator=( const OctreeItemTest& );
88 |
89 |
90 | /// queries --------------------------------------------------------------------
91 | virtual const Vector3r& getPosition() const;
92 | virtual const Vector3r& getDimensions() const;
93 |
94 | virtual dword getPayload() const;
95 |
96 |
97 | /// fields ---------------------------------------------------------------------
98 | private:
99 | Vector3r position_m;
100 | Vector3r dimensions_m;
101 |
102 | dword payload_m;
103 | };
104 |
105 |
106 |
107 |
108 | /// standard object services ---------------------------------------------------
109 | OctreeItemTest::OctreeItemTest
110 | (
111 | const Vector3r& position,
112 | const Vector3r& dimensions,
113 | const dword payload
114 | )
115 | : position_m ( position )
116 | , dimensions_m( dimensions )
117 | , payload_m ( payload )
118 | {
119 | }
120 |
121 |
122 | OctreeItemTest::~OctreeItemTest()
123 | {
124 | }
125 |
126 |
127 | OctreeItemTest::OctreeItemTest
128 | (
129 | const OctreeItemTest& other
130 | )
131 | : position_m ( other.position_m )
132 | , dimensions_m( other.dimensions_m )
133 | , payload_m ( other.payload_m )
134 | {
135 | }
136 |
137 |
138 | OctreeItemTest& OctreeItemTest::operator=
139 | (
140 | const OctreeItemTest& other
141 | )
142 | {
143 | if( &other != this )
144 | {
145 | position_m = other.position_m;
146 | dimensions_m = other.dimensions_m;
147 | payload_m = other.payload_m;
148 | }
149 |
150 | return *this;
151 | }
152 |
153 |
154 | /// queries --------------------------------------------------------------------
155 | const Vector3r& OctreeItemTest::getPosition() const
156 | {
157 | return position_m;
158 | }
159 |
160 |
161 | const Vector3r& OctreeItemTest::getDimensions() const
162 | {
163 | return dimensions_m;
164 | }
165 |
166 |
167 | dword OctreeItemTest::getPayload() const
168 | {
169 | return payload_m;
170 | }
171 |
172 |
173 | std::ostream& operator<<( std::ostream&, const OctreeItemTest& );
174 |
175 | std::ostream& operator<<
176 | (
177 | std::ostream& out,
178 | const OctreeItemTest& item
179 | )
180 | {
181 | const Vector3r& position( item.getPosition() );
182 | const Vector3r& dimensions( item.getDimensions() );
183 |
184 | out << "{" << position << " " << dimensions << "}";
185 |
186 | return out;
187 | }
188 |
189 |
190 |
191 |
192 | /// OctreeAgentTest ////////////////////////////////////////////////////////////
193 |
194 | class OctreeAgentTest
195 | : public OctreeAgent
196 | {
197 | /// standard object services ---------------------------------------------------
198 | public:
199 | OctreeAgentTest() {};
200 |
201 | virtual ~OctreeAgentTest() {};
202 | private:
203 | OctreeAgentTest( const OctreeAgentTest& );
204 | OctreeAgentTest& operator=( const OctreeAgentTest& );
205 |
206 |
207 | /// queries --------------------------------------------------------------------
208 | /// octree agent overrides
209 | protected:
210 | virtual bool isOverlappingCell ( const OctreeItemTest& item,
211 | const Vector3r& lowerCorner,
212 | const Vector3r& upperCorner ) const;
213 |
214 |
215 | /// implementation -------------------------------------------------------------
216 | public:
217 | static bool isOverlapping( const Vector3r& itemLower,
218 | const Vector3r& itemUpper,
219 | const Vector3r& cellLower,
220 | const Vector3r& cellUpper );
221 | };
222 |
223 |
224 |
225 |
226 | /// queries --------------------------------------------------------------------
227 | /// octree agent overrides
228 | bool OctreeAgentTest::isOverlappingCell
229 | (
230 | const OctreeItemTest& item,
231 | const Vector3r& lowerCorner,
232 | const Vector3r& upperCorner
233 | ) const
234 | {
235 | return isOverlapping( item.getPosition(),
236 | item.getPosition() + item.getDimensions(), lowerCorner, upperCorner );
237 | }
238 |
239 |
240 | bool OctreeAgentTest::isOverlapping
241 | (
242 | const Vector3r& itemLower,
243 | const Vector3r& itemUpper,
244 | const Vector3r& cellLower,
245 | const Vector3r& cellUpper
246 | )
247 | {
248 | // check the two ranges overlap in every dimension
249 | bool isOverlap = true;
250 | for( int i = 3; i-- > 0; )
251 | {
252 | isOverlap &= (itemLower[i] < cellUpper[i]) &
253 | (itemUpper[i] > cellLower[i]);
254 | }
255 |
256 | return isOverlap;
257 | }
258 |
259 |
260 |
261 |
262 | /// OctreeVisitorTest //////////////////////////////////////////////////////////
263 |
264 | class OctreeVisitorTest
265 | : public OctreeVisitor
266 | {
267 | /// standard object services ---------------------------------------------------
268 | public:
269 | OctreeVisitorTest( const Octree& );
270 |
271 | virtual ~OctreeVisitorTest();
272 | private:
273 | OctreeVisitorTest( const OctreeVisitorTest& );
274 | OctreeVisitorTest& operator=( const OctreeVisitorTest& );
275 |
276 |
277 | /// commands -------------------------------------------------------------------
278 | protected:
279 | virtual void visitRoot ( const OctreeCell* pRootCell,
280 | const OctreeData& octreeData );
281 | virtual void visitBranch( const OctreeCell* subCells[8],
282 | const OctreeData& octreeData );
283 | virtual void visitLeaf ( const Array& items,
284 | const OctreeData& octreeData );
285 |
286 |
287 | /// queries --------------------------------------------------------------------
288 | public:
289 | typedef std::pair > LeafData;
290 |
291 | const std::vector& getIds() const;
292 | const std::vector& getLeafs() const;
293 |
294 |
295 | /// fields ---------------------------------------------------------------------
296 | private:
297 | std::vector ids_m;
298 | std::vector leafs_m;
299 | };
300 |
301 |
302 |
303 |
304 | /// standard object services ---------------------------------------------------
305 | OctreeVisitorTest::OctreeVisitorTest
306 | (
307 | const Octree& octree
308 | )
309 | : ids_m ()
310 | , leafs_m()
311 | {
312 | ids_m.push_back( static_cast(&octree) );
313 | }
314 |
315 |
316 | OctreeVisitorTest::~OctreeVisitorTest()
317 | {
318 | }
319 |
320 |
321 | OctreeVisitorTest::OctreeVisitorTest
322 | (
323 | const OctreeVisitorTest& other
324 | )
325 | : OctreeVisitor()
326 | , ids_m ( other.ids_m )
327 | , leafs_m( other.leafs_m )
328 | {
329 | }
330 |
331 |
332 | OctreeVisitorTest& OctreeVisitorTest::operator=
333 | (
334 | const OctreeVisitorTest& other
335 | )
336 | {
337 | if( &other != this )
338 | {
339 | ids_m = other.ids_m;
340 | leafs_m = other.leafs_m;
341 | }
342 |
343 | return *this;
344 | }
345 |
346 |
347 | /// commands -------------------------------------------------------------------
348 | void OctreeVisitorTest::visitRoot
349 | (
350 | const OctreeCell* pRootCell,
351 | const OctreeData& octreeData
352 | )
353 | {
354 | if( pRootCell )
355 | {
356 | ids_m.push_back( static_cast(pRootCell) );
357 |
358 | pRootCell->visit( octreeData, *this );
359 | }
360 | }
361 |
362 |
363 | void OctreeVisitorTest::visitBranch
364 | (
365 | const OctreeCell* subCells[8],
366 | const OctreeData& octreeData
367 | )
368 | {
369 | ids_m.push_back( subCells );
370 |
371 | // step through subcells
372 | for( dword i = 8; i-- > 0; )
373 | {
374 | const OctreeCell* pSubCell = subCells[i];
375 | if( pSubCell )
376 | {
377 | ids_m.push_back( static_cast(pSubCell) );
378 |
379 | // continue visit traversal
380 | OctreeBranch::continueVisit( subCells, octreeData, i, *this );
381 | }
382 | }
383 | }
384 |
385 |
386 | void OctreeVisitorTest::visitLeaf
387 | (
388 | const Array& items,
389 | const OctreeData& octreeData
390 | )
391 | {
392 | ids_m.push_back( static_cast(&items) );
393 |
394 | leafs_m.push_back( LeafData( octreeData, items ) );
395 | }
396 |
397 |
398 | /// queries --------------------------------------------------------------------
399 | const std::vector& OctreeVisitorTest::getIds() const
400 | {
401 | return ids_m;
402 | }
403 |
404 |
405 | const std::vector& OctreeVisitorTest::getLeafs()
406 | const
407 | {
408 | return leafs_m;
409 | }
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 | /// declarations ///////////////////////////////////////////////////////////////
419 |
420 | static bool testConstruction
421 | (
422 | std::ostream* out = 0,
423 | const bool isVerbose = false,
424 | const dword seed = 0
425 | );
426 | static bool testCommands
427 | (
428 | std::ostream* out = 0,
429 | const bool isVerbose = false,
430 | const dword seed = 0
431 | );
432 | static bool testCommands1
433 | (
434 | std::ostream* out = 0,
435 | const bool isVerbose = false,
436 | const dword seed = 0
437 | );
438 | static bool testCommands2
439 | (
440 | std::ostream* out = 0,
441 | const bool isVerbose = false,
442 | const dword seed = 0
443 | );
444 | static bool testCommands3
445 | (
446 | std::ostream* out = 0,
447 | const bool isVerbose = false,
448 | const dword seed = 0
449 | );
450 |
451 |
452 | class RandomFast
453 | {
454 | public:
455 | /// standard object services ---------------------------------------------------
456 | explicit RandomFast( const dword seed =0 )
457 | : random_m( seed )
458 | {
459 | }
460 |
461 | ~RandomFast()
462 | {
463 | }
464 |
465 | RandomFast( const RandomFast& other )
466 | : random_m( other.random_m )
467 | {
468 | }
469 |
470 | RandomFast& operator=( const RandomFast& other )
471 | {
472 | random_m = other.random_m;
473 |
474 | return *this;
475 | }
476 |
477 |
478 | /// commands -------------------------------------------------------------------
479 | RandomFast& setSeed( const dword seed )
480 | {
481 | random_m = seed;
482 |
483 | return *this;
484 | }
485 |
486 | RandomFast& next()
487 | {
488 | random_m = static_cast(1664525) * random_m +
489 | static_cast(1013904223);
490 |
491 | return *this;
492 | }
493 |
494 |
495 | /// queries --------------------------------------------------------------------
496 | dword getDword() const
497 | {
498 | return random_m;
499 | }
500 |
501 | udword getUdword() const
502 | {
503 | return static_cast(random_m);
504 | }
505 |
506 | float getFloat() const
507 | {
508 | dword itemp = static_cast(0x3F800000) |
509 | (static_cast(0x007FFFFF) & random_m);
510 | return *(reinterpret_cast(&itemp)) - 1.0f;
511 | }
512 |
513 | float getFloat( const float scale,
514 | const float displace = 0.0f ) const
515 | {
516 | return getFloat() * scale + displace;
517 | }
518 |
519 |
520 | /// fields ---------------------------------------------------------------------
521 | private:
522 | // current value of sequence and seed of the following part of the sequence
523 | dword random_m;
524 | };
525 |
526 |
527 | static void makeRandomFilledOctree
528 | (
529 | RandomFast& rand,
530 | const dword howManyItems,
531 | std::auto_ptr >& pOctree,
532 | std::vector& items
533 | );
534 | static void makeRandomOctree
535 | (
536 | RandomFast& rand,
537 | std::auto_ptr >& pOctree
538 | );
539 | static void makeRandomItems
540 | (
541 | RandomFast& rand,
542 | dword howMany,
543 | const Vector3r& position,
544 | real size,
545 | std::vector& items
546 | );
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 | /// test functions /////////////////////////////////////////////////////////////
556 |
557 | void hxa7241_graphics::preTest()
558 | {
559 | // make items
560 | OctreeItemTest item1( Vector3r( 1, 1, 1 ) );
561 | OctreeItemTest item2( Vector3r( 3, 3, 3 ) );
562 | OctreeItemTest item3( Vector3r( 4, 4, 4 ) );
563 |
564 | // make octree
565 | Vector3r position( 0, 0, 0 );
566 | real size = 5.0f;
567 | dword maxItems = 1;
568 | dword maxLevels = 4;
569 |
570 | Octree o1( position, size, maxItems, maxLevels, 0.001f );
571 |
572 | // insert items into octree
573 | OctreeAgentTest a;
574 | o1.insert( item1, a );
575 | o1.insert( item2, a );
576 | o1.insert( item3, a );
577 |
578 | // stream out octree
579 | OctreeStreamOut vso( std::cout, true );
580 | o1.visit( vso );
581 | }
582 |
583 |
584 |
585 |
586 | bool hxa7241_graphics::test_Octree
587 | (
588 | std::ostream* pOut,
589 | const bool isVerbose,
590 | dword seed
591 | )
592 | {
593 | if( 0 == seed )
594 | {
595 | seed = static_cast