00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef _OCTREE_H_
00013 #define _OCTREE_H_
00014
00015 #include <vector>
00016 #include <celmath/quaternion.h>
00017 #include <celmath/plane.h>
00018 #include <celengine/observer.h>
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 template <class OBJ, class PREC> class OctreeProcessor
00030 {
00031 public:
00032 OctreeProcessor() {};
00033 virtual ~OctreeProcessor() {};
00034
00035 virtual void process(const OBJ& obj, PREC distance, float appMag) = 0;
00036 };
00037
00038
00039
00040
00041
00042 template <class OBJ, class PREC> class StaticOctree;
00043 template <class OBJ, class PREC> class DynamicOctree
00044 {
00045 typedef std::vector<const OBJ*> ObjectList;
00046
00047 typedef bool (LimitingFactorPredicate) (const OBJ&, const float);
00048 typedef bool (StraddlingPredicate) (const Point3<PREC>&, const OBJ&, const float);
00049 typedef PREC (ExclusionFactorDecayFunction)(const PREC);
00050
00051 public:
00052 DynamicOctree(const Point3<PREC>& cellCenterPos,
00053 const float exclusionFactor);
00054 ~DynamicOctree();
00055
00056 void insertObject (const OBJ&, const PREC);
00057 void rebuildAndSort(StaticOctree<OBJ, PREC>*&, OBJ*&);
00058
00059 private:
00060 static unsigned int SPLIT_THRESHOLD;
00061
00062 static LimitingFactorPredicate* limitingFactorPredicate;
00063 static StraddlingPredicate* straddlingPredicate;
00064 static ExclusionFactorDecayFunction* decayFunction;
00065
00066 private:
00067 void add (const OBJ&);
00068 void split(const PREC);
00069 void sortIntoChildNodes();
00070 DynamicOctree* getChild(const OBJ&, const Point3<PREC>&);
00071
00072 DynamicOctree** _children;
00073 Point3<PREC> cellCenterPos;
00074 PREC exclusionFactor;
00075 ObjectList* _objects;
00076 };
00077
00078
00079
00080
00081
00082 template <class OBJ, class PREC> class StaticOctree
00083 {
00084 friend class DynamicOctree<OBJ, PREC>;
00085
00086 public:
00087 StaticOctree(const Point3<PREC>& cellCenterPos,
00088 const float exclusionFactor,
00089 OBJ* _firstObject,
00090 unsigned int nObjects);
00091 ~StaticOctree();
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 void processVisibleObjects(OctreeProcessor<OBJ, PREC>& processor,
00105 const Point3<PREC>& obsPosition,
00106 const Plane<float>* frustumPlanes,
00107 float limitingFactor,
00108 PREC scale) const;
00109
00110 void processCloseObjects(OctreeProcessor<OBJ, PREC>& processor,
00111 const Point3<PREC>& obsPosition,
00112 PREC boundingRadius,
00113 PREC scale) const;
00114
00115 int countChildren() const;
00116 int countObjects() const;
00117
00118 private:
00119 static const PREC SQRT3;
00120
00121 private:
00122 StaticOctree** _children;
00123 Point3<PREC> cellCenterPos;
00124 float exclusionFactor;
00125 OBJ* _firstObject;
00126 unsigned int nObjects;
00127 };
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 enum
00144 {
00145 XPos = 1,
00146 YPos = 2,
00147 ZPos = 4,
00148 };
00149
00150
00151
00152
00153
00154 template <class OBJ, class PREC>
00155 inline DynamicOctree<OBJ, PREC>::DynamicOctree(const Point3<PREC>& cellCenterPos,
00156 const float exclusionFactor):
00157 _children (NULL),
00158 cellCenterPos (cellCenterPos),
00159 exclusionFactor(exclusionFactor),
00160 _objects (NULL)
00161 {
00162 }
00163
00164
00165 template <class OBJ, class PREC>
00166 inline DynamicOctree<OBJ, PREC>::~DynamicOctree()
00167 {
00168 if (_children != NULL)
00169 {
00170 for (int i=0; i<8; ++i)
00171 {
00172 delete _children[i];
00173 }
00174
00175 delete[] _children;
00176 }
00177 }
00178
00179
00180 template <class OBJ, class PREC>
00181 inline void DynamicOctree<OBJ, PREC>::insertObject(const OBJ& obj, const PREC scale)
00182 {
00183
00184 if (limitingFactorPredicate(obj, exclusionFactor) || straddlingPredicate(cellCenterPos, obj, exclusionFactor) )
00185 add(obj);
00186 else
00187 {
00188
00189
00190
00191
00192
00193
00194
00195 if (_children == NULL)
00196 {
00197
00198 if (_objects != NULL && _objects->size() >= DynamicOctree<OBJ, PREC>::SPLIT_THRESHOLD)
00199 split(scale * 0.5f);
00200 add(obj);
00201 }
00202 else
00203
00204
00205 this->getChild(obj, cellCenterPos)->insertObject(obj, scale * (PREC) 0.5);
00206 }
00207 }
00208
00209
00210 template <class OBJ, class PREC>
00211 inline void DynamicOctree<OBJ, PREC>::add(const OBJ& obj)
00212 {
00213 if (_objects == NULL)
00214 _objects = new ObjectList;
00215
00216 _objects->push_back(&obj);
00217 }
00218
00219
00220 template <class OBJ, class PREC>
00221 inline void DynamicOctree<OBJ, PREC>::split(const PREC scale)
00222 {
00223 _children = new DynamicOctree*[8];
00224
00225 for (int i=0; i<8; ++i)
00226 {
00227 Point3<PREC> centerPos = cellCenterPos;
00228
00229 centerPos.x += ((i & XPos) != 0) ? scale : -scale;
00230 centerPos.y += ((i & YPos) != 0) ? scale : -scale;
00231 centerPos.z += ((i & ZPos) != 0) ? scale : -scale;
00232
00233 _children[i] = new DynamicOctree(centerPos,
00234 decayFunction(exclusionFactor));
00235 }
00236 sortIntoChildNodes();
00237 }
00238
00239
00240
00241
00242
00243 template <class OBJ, class PREC>
00244 inline void DynamicOctree<OBJ, PREC>::sortIntoChildNodes()
00245 {
00246 unsigned int nKeptInParent = 0;
00247
00248 for (unsigned int i=0; i<_objects->size(); ++i)
00249 {
00250 const OBJ& obj = *(*_objects)[i];
00251
00252 if (straddlingPredicate(cellCenterPos, obj, exclusionFactor) )
00253 (*_objects)[nKeptInParent++] = (*_objects)[i];
00254 else
00255 this->getChild(obj, cellCenterPos)->add(obj);
00256 }
00257
00258 _objects->resize(nKeptInParent);
00259 }
00260
00261
00262 template <class OBJ, class PREC>
00263 inline void DynamicOctree<OBJ, PREC>::rebuildAndSort(StaticOctree<OBJ, PREC>*& _staticNode, OBJ*& _sortedObjects)
00264 {
00265 OBJ* _firstObject = _sortedObjects;
00266
00267 if (_objects != NULL)
00268 for (typename ObjectList::const_iterator iter = _objects->begin(); iter != _objects->end(); ++iter)
00269 {
00270 *_sortedObjects++ = **iter;
00271 }
00272
00273 unsigned int nObjects = (unsigned int) (_sortedObjects - _firstObject);
00274 _staticNode = new StaticOctree<OBJ, PREC>(cellCenterPos, exclusionFactor, _firstObject, nObjects);
00275
00276 if (_children != NULL)
00277 {
00278 _staticNode->_children = new StaticOctree<OBJ, PREC>*[8];
00279
00280 for (int i=0; i<8; ++i)
00281 _children[i]->rebuildAndSort(_staticNode->_children[i], _sortedObjects);
00282 }
00283 }
00284
00285
00286
00287 template <class OBJ, class PREC>
00288 const PREC StaticOctree<OBJ, PREC>::SQRT3 = (PREC) 1.732050807568877;
00289
00290
00291 template <class OBJ, class PREC>
00292 inline StaticOctree<OBJ, PREC>::StaticOctree(const Point3<PREC>& cellCenterPos,
00293 const float exclusionFactor,
00294 OBJ* _firstObject,
00295 unsigned int nObjects):
00296 _children (NULL),
00297 cellCenterPos (cellCenterPos),
00298 exclusionFactor(exclusionFactor),
00299 _firstObject (_firstObject),
00300 nObjects (nObjects)
00301 {
00302 }
00303
00304
00305 template <class OBJ, class PREC>
00306 inline StaticOctree<OBJ, PREC>::~StaticOctree()
00307 {
00308 if (_children != NULL)
00309 {
00310 for (int i=0; i<8; ++i)
00311 delete _children[i];
00312
00313 delete[] _children;
00314 }
00315 }
00316
00317
00318 template <class OBJ, class PREC>
00319 inline int StaticOctree<OBJ, PREC>::countChildren() const
00320 {
00321 int count = 0;
00322
00323 for (int i=0; i<8; ++i)
00324 count += _children != NULL ? 1 + _children[i]->countChildren() : 0;
00325
00326 return count;
00327 }
00328
00329
00330 template <class OBJ, class PREC>
00331 inline int StaticOctree<OBJ, PREC>::countObjects() const
00332 {
00333 int count = nObjects;
00334
00335 if (_children != NULL)
00336 for (int i=0; i<8; ++i)
00337 count += _children[i]->countObjects();
00338
00339 return count;
00340 }
00341
00342 #endif // _OCTREE_H_