00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #if !defined(_XRB_ENGINE2_QUADTREEBASE_HPP_)
00012 #define _XRB_ENGINE2_QUADTREEBASE_HPP_
00013
00014 #include "xrb.hpp"
00015
00016 #include <set>
00017
00018 #include "xrb_engine2_object.hpp"
00019 #include "xrb_engine2_enums.hpp"
00020 #include "xrb_vector.hpp"
00021
00022 namespace Xrb
00023 {
00024
00025 namespace Engine2
00026 {
00027
00028 class Object;
00029
00030
00031
00032
00033
00034
00035
00036 class QuadTree
00037 {
00038 public:
00039
00040 virtual ~QuadTree () = 0;
00041
00042 inline QuadTreeType GetQuadTreeType () const { return m_quad_tree_type; }
00043 inline QuadTree *Parent () const { return m_parent; }
00044 inline bool HasChildren () const { return m_child[0] != NULL; }
00045
00046 QuadTree const *RootNode () const;
00047 inline FloatVector2 const &Center () const { return m_center; }
00048 inline Float SideLength () const { return 2.0f * m_half_side_length; }
00049 inline Float HalfSideLength () const { return m_half_side_length; }
00050 inline Float Radius () const { return m_radius; }
00051 inline Uint32 SubordinateObjectCount () const { return m_subordinate_object_count; }
00052 inline Uint32 SubordinateStaticObjectCount () const { return m_subordinate_static_object_count; }
00053 Object *SmallestObjectTouchingPoint (FloatVector2 const &point);
00054
00055 inline bool IsAllowableObjectRadius (Object const *object) const { return object->Radius(GetQuadTreeType()) / m_radius > 0.5f; }
00056
00057 bool DoesAreaOverlapAnyObject (
00058 FloatVector2 const &area_center,
00059 Float area_radius) const;
00060 bool DoesAreaOverlapAnyObjectWrapped (
00061 FloatVector2 const &area_center,
00062 Float area_radius,
00063 Float object_layer_side_length,
00064 Float half_object_layer_side_length) const;
00065
00066
00067 void Clear ();
00068
00069
00070
00071
00072 bool AddObject (Object *object);
00073
00074 bool RemoveObject (Object *object);
00075
00076
00077 bool ReAddObject (Object *object);
00078
00079 protected:
00080
00081
00082 QuadTree (QuadTree *parent);
00083
00084 template <typename QuadTreeClass>
00085 inline QuadTreeClass const *Child (Uint32 const index) const
00086 {
00087 ASSERT2(index < 4);
00088 ASSERT2(m_child[index] != NULL);
00089 return DStaticCast<QuadTreeClass const *>(m_child[index]);
00090 }
00091 template <typename QuadTreeClass>
00092 inline QuadTreeClass *Child (Uint32 const index)
00093 {
00094 ASSERT2(index < 4);
00095 ASSERT2(m_child[index] != NULL);
00096 return DStaticCast<QuadTreeClass *>(m_child[index]);
00097 }
00098
00099 bool IsPointInsideQuad (FloatVector2 const &point) const;
00100
00101
00102
00103 inline bool DoesAreaOverlapQuadBounds (
00104 FloatVector2 const &area_center,
00105 Float const area_radius) const
00106 {
00107 ASSERT1(area_radius > 0.0f);
00108 Float radius_sum = area_radius + 2.0f * Radius();
00109 return (area_center - m_center).LengthSquared() < radius_sum*radius_sum;
00110 }
00111
00112
00113
00114 bool DoesAreaOverlapQuadBoundsWrapped (
00115 FloatVector2 area_center,
00116 Float area_radius,
00117 Float object_layer_side_length,
00118 Float half_object_layer_side_length) const;
00119
00120 void SetQuadTreeType (QuadTreeType quad_tree_type);
00121
00122
00123 void IncrementSubordinateObjectCount ();
00124
00125 void IncrementSubordinateStaticObjectCount ();
00126
00127 void DecrementSubordinateObjectCount ();
00128
00129 void DecrementSubordinateStaticObjectCount ();
00130
00131 template <typename QuadTreeClass>
00132 void Initialize (
00133 FloatVector2 const ¢er,
00134 Float const half_side_length,
00135 Uint8 const depth)
00136 {
00137 ASSERT1(half_side_length > 0.0f);
00138 ASSERT1(depth != 0);
00139
00140 m_parent = NULL;
00141 m_center = center;
00142 m_half_side_length = half_side_length;
00143 m_radius = Math::Sqrt(2.0f) * m_half_side_length;
00144 m_subordinate_object_count = 0;
00145 m_subordinate_static_object_count = 0;
00146 if (depth <= 1)
00147 {
00148 for (Uint8 i = 0; i < 4; ++i)
00149 m_child[i] = NULL;
00150 }
00151 else
00152 {
00153 Float child_half_side_length = 0.5f * m_half_side_length;
00154
00155 m_child[0] = new QuadTreeClass(
00156 center + child_half_side_length * FloatVector2( 1.0f, 1.0f),
00157 child_half_side_length,
00158 depth - 1);
00159 m_child[1] = new QuadTreeClass(
00160 center + child_half_side_length * FloatVector2(-1.0f, 1.0f),
00161 child_half_side_length,
00162 depth - 1);
00163 m_child[2] = new QuadTreeClass(
00164 center + child_half_side_length * FloatVector2(-1.0f, -1.0f),
00165 child_half_side_length,
00166 depth - 1);
00167 m_child[3] = new QuadTreeClass(
00168 center + child_half_side_length * FloatVector2( 1.0f, -1.0f),
00169 child_half_side_length,
00170 depth - 1);
00171
00172 for (Uint8 i = 0; i < 4; ++i)
00173 m_child[i]->m_parent = this;
00174 }
00175 }
00176
00177 typedef std::set<Object *> ObjectSet;
00178
00179
00180 ObjectSet m_object_set;
00181
00182
00183
00184
00185
00186 QuadTree *m_child[4];
00187
00188 QuadTree *m_parent;
00189
00190 FloatVector2 m_center;
00191
00192 Float m_half_side_length;
00193
00194 Float m_radius;
00195
00196 private:
00197
00198 void NonRecursiveAddObject (Object *object);
00199 void AddObjectIfNotAlreadyAdded (Object *object);
00200
00201
00202 Uint32 m_subordinate_object_count;
00203
00204 Uint32 m_subordinate_static_object_count;
00205
00206
00207
00208 QuadTreeType m_quad_tree_type;
00209 };
00210
00211 }
00212
00213 }
00214
00215 #endif // !defined(_XRB_ENGINE2_QUADTREEBASE_HPP_)