Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages
kdtree.h
00001 /* 00002 Copyright (C) 2002 by Jorrit Tyberghein 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License as published by the Free Software Foundation; either 00007 version 2 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public 00015 License along with this library; if not, write to the Free 00016 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 */ 00018 00019 #ifndef __CS_KDTREE_H__ 00020 #define __CS_KDTREE_H__ 00021 00022 #include "csextern.h" 00023 00024 #include "csgeom/box.h" 00025 00026 #include "csutil/blockallocator.h" 00027 #include "csutil/ref.h" 00028 #include "csutil/scfstr.h" 00029 #include "csutil/scf_implementation.h" 00030 00031 #include "iutil/dbghelp.h" 00032 00033 struct iGraphics3D; 00034 class csKDTree; 00035 00058 typedef bool (csKDTreeVisitFunc)(csKDTree* treenode, void* userdata, 00059 uint32 timestamp, uint32& frustum_mask); 00060 00064 class CS_CRYSTALSPACE_EXPORT csKDTreeChild 00065 { 00066 private: 00067 friend class csKDTree; 00068 00069 csBox3 bbox; 00070 void* object; // Pointer back to the original object. 00071 csKDTree** leafs; // Leafs that contain this object. 00072 int num_leafs; 00073 int max_leafs; 00074 00075 public: 00076 uint32 timestamp; // Timestamp of last visit to this child. 00077 00078 public: 00079 csKDTreeChild (); 00080 ~csKDTreeChild (); 00081 00083 void AddLeaf (csKDTree* leaf); 00085 void RemoveLeaf (int idx); 00087 void RemoveLeaf (csKDTree* leaf); 00094 void ReplaceLeaf (csKDTree* old_leaf, csKDTree* new_leaf); 00095 00099 int FindLeaf (csKDTree* leaf); 00100 00104 inline const csBox3& GetBBox () const { return bbox; } 00105 00109 inline void* GetObject () const { return object; } 00110 }; 00111 00112 enum 00113 { 00114 CS_KDTREE_AXISINVALID = -1, 00115 CS_KDTREE_AXISX = 0, 00116 CS_KDTREE_AXISY = 1, 00117 CS_KDTREE_AXISZ = 2 00118 }; 00119 00136 class CS_CRYSTALSPACE_EXPORT csKDTree : 00137 public scfImplementation1<csKDTree, iDebugHelper> 00138 { 00139 private: 00140 static csBlockAllocator<csKDTree> tree_nodes; 00141 static csBlockAllocator<csKDTreeChild> tree_children; 00142 00143 csKDTree* child1; // If child1 is not 0 then child2 will 00144 csKDTree* child2; // also be not 0. 00145 csKDTree* parent; // 0 if this is the root. 00146 00147 csRef<iBase> userobject; // An optional user object for this node. 00148 00149 csBox3 node_bbox; // Bbox of the node itself. 00150 00151 int split_axis; // One of CS_KDTREE_AXIS? 00152 float split_location; // Where is the split? 00153 00154 // Objects in this node. If this node also has children (child1 00155 // and child2) then the objects here have to be moved to these 00156 // children. The 'Distribute()' function will do that. 00157 csKDTreeChild** objects; 00158 int num_objects; 00159 int max_objects; 00160 00161 // Estimate of the total number of objects in this tree including children. 00162 int estimate_total_objects; 00163 00164 // Disallow Distribute(). 00165 // If this flag is true it means that we cannot find a good split 00166 // location for the current list of objects. So in that case we don't 00167 // split at all and set this flag to true so that we will no longer 00168 // attempt to distribute. Whenever objects are added or removed to this 00169 // node this flag will be set to false again so that a new Distribute() 00170 // attempt can be made. This situation should be rare though. 00171 bool disallow_distribute; 00172 00173 // Current timestamp we are using for Front2Back(). Objects that 00174 // have the same timestamp are already visited during Front2Back(). 00175 static uint32 global_timestamp; 00176 00178 void AddObject (csKDTreeChild* obj); 00180 void RemoveObject (int idx); 00182 int FindObject (csKDTreeChild* obj); 00183 00187 void AddObject (const csBox3& bbox, csKDTreeChild* obj); 00188 00199 float FindBestSplitLocation (int axis, float& split_loc); 00200 00206 void DistributeLeafObjects (); 00207 00214 void Front2Back (const csVector3& pos, csKDTreeVisitFunc* func, 00215 void* userdata, uint32 cur_timestamp, uint32 frustum_mask); 00216 00223 void TraverseRandom (csKDTreeVisitFunc* func, 00224 void* userdata, uint32 cur_timestamp, uint32 frustum_mask); 00225 00229 void ResetTimestamps (); 00230 00234 void FlattenTo (csKDTree* node); 00235 00236 public: 00238 csKDTree (); 00240 virtual ~csKDTree (); 00242 void SetParent (csKDTree* p) { parent = p; } 00243 00245 void Clear (); 00246 00248 inline iBase* GetUserObject () const { return userobject; } 00249 00255 void SetUserObject (iBase* userobj); 00256 00264 csKDTreeChild* AddObject (const csBox3& bbox, void* object); 00265 00270 void UnlinkObject (csKDTreeChild* object); 00271 00276 void RemoveObject (csKDTreeChild* object); 00277 00281 void MoveObject (csKDTreeChild* object, const csBox3& new_bbox); 00282 00289 void Distribute (); 00290 00294 void FullDistribute (); 00295 00301 void Flatten (); 00302 00308 void TraverseRandom (csKDTreeVisitFunc* func, 00309 void* userdata, uint32 frustum_mask); 00310 00317 void Front2Back (const csVector3& pos, csKDTreeVisitFunc* func, 00318 void* userdata, uint32 frustum_mask); 00319 00327 uint32 NewTraversal (); 00328 00332 inline csKDTree* GetChild1 () const { return child1; } 00333 00337 inline csKDTree* GetChild2 () const { return child2; } 00338 00342 inline int GetObjectCount () const { return num_objects; } 00343 00350 inline int GetEstimatedObjectCount () { return estimate_total_objects; } 00351 00355 inline csKDTreeChild** GetObjects () const { return objects; } 00356 00361 inline const csBox3& GetNodeBBox () const { return node_bbox; } 00362 00363 // Debugging functions. 00364 bool Debug_CheckTree (csString& str); 00365 csPtr<iString> Debug_UnitTest (); 00366 void Debug_Dump (csString& str, int indent); 00367 void Debug_Statistics (int& tot_objects, 00368 int& tot_nodes, int& tot_leaves, int depth, int& max_depth, 00369 float& balance_quality); 00370 csPtr<iString> Debug_Statistics (); 00371 csTicks Debug_Benchmark (int num_iterations); 00372 00373 virtual int GetSupportedTests () const 00374 { 00375 return CS_DBGHELP_UNITTEST | CS_DBGHELP_STATETEST | 00376 CS_DBGHELP_TXTDUMP | CS_DBGHELP_BENCHMARK; 00377 } 00378 00379 virtual csPtr<iString> UnitTest () 00380 { 00381 return Debug_UnitTest (); 00382 } 00383 00384 virtual csPtr<iString> StateTest () 00385 { 00386 scfString* rc = new scfString (); 00387 if (!Debug_CheckTree (rc->GetCsString ())) 00388 return csPtr<iString> (rc); 00389 delete rc; 00390 return 0; 00391 } 00392 00393 virtual csTicks Benchmark (int num_iterations) 00394 { 00395 return Debug_Benchmark (num_iterations); 00396 } 00397 00398 virtual csPtr<iString> Dump () 00399 { 00400 scfString* rc = new scfString (); 00401 Debug_Dump (rc->GetCsString (), 0); 00402 return csPtr<iString> (rc); 00403 } 00404 00405 virtual void Dump (iGraphics3D* /*g3d*/) { } 00406 virtual bool DebugCommand (const char*) { return false; } 00407 }; 00408 00409 #endif // __CS_KDTREE_H__ 00410
Generated for Crystal Space by doxygen 1.4.4