00001
00008
00009
00010
00011
00012
00013 #ifndef ENG_WORLD_HH
00014 #define ENG_WORLD_HH 1
00015
00016 namespace eng {
00017
00018 class Object;
00019 #define QuadrantPtr SafePtr<World::Quadrant>
00020
00021
00022
00023
00024
00025
00026 enum { AXIS_LAT = AXIS_X, LAT = AXIS_LAT,
00027 AXIS_LON = AXIS_Y, LON = AXIS_LON,
00028 AXIS_ALT = AXIS_Z, ALT = AXIS_ALT };
00029 #define AXIS_LAT_ x
00030 #define AXIS_LON_ y
00031 #define AXIS_ALT_ z
00032 #define LAT_ AXIS_LAT_
00033 #define LON_ AXIS_LON_
00034 #define ALT_ AXIS_ALT_
00035
00036
00037
00038
00039 #define LAT_LON_ALT( LAT, LON, ALT ) (LAT), (LON), (ALT)
00040
00049 class World : public Threadable
00050 {
00051
00052 protected:
00053 class Quadrant;
00054 class Locus;
00055 friend class Locus;
00056 friend class Quadrant;
00057 friend void ThreadQuadrantPopulate( long quadrant );
00058
00059
00060 #define WORLD_AUTO_LOCK() THREAD_CODE( AutoLock<SlowLock> lock( &gWorld.mLock ); )
00061 #define LOCUS_AUTO_LOCK() THREAD_CODE( AutoLock<SlowLock> lock( &mLock ); )
00062 #define ASSERT_WORLD()
00063
00064 public:
00065 FN_MAIN_THREAD virtual void Make( void ) = 0;
00066 FN_REENTRANT virtual bool IfMade( void ) = 0;
00067 FN_REENTRANT eAttached Attach( SharedPtr<Object> object );
00068 FN_REENTRANT eAttached Detach( SharedPtr<Object> object );
00069 FN_REENTRANT WorldVertex CorrectPosition( const WorldVertex& pos );
00070 FN_MAIN_THREAD void Draw( void );
00071 FN_REENTRANT void EyePositionChanged( void );
00072 FN_REENTRANT uint GetObjectCnt( void );
00073 FN_REENTRANT const BoxVolume& GetBoxVolume( void ) { ASSERT(IfMade()); return mBoxVolume; }
00074 FN_REENTRANT fp GetLatWidth( void ) { ASSERT(IfMade()); return mBoxVolume.mMax.LAT_ - mBoxVolume.mMin.LAT_; }
00075 FN_REENTRANT fp GetLonWidth( void ) { ASSERT(IfMade()); return mBoxVolume.mMax.LON_ - mBoxVolume.mMin.LON_; }
00076 FN_REENTRANT fp GetAltWidth( void ) { ASSERT(IfMade()); return mBoxVolume.mMax.ALT_ - mBoxVolume.mMin.ALT_; }
00077 FN_REENTRANT WorldVertex GetCenter( void );
00078
00079
00080 FN_REENTRANT fp GetLocusEdge( uint dim );
00081 FN_LOCKED uint GetLocusObjectCnt( void );
00082
00083
00084 FN_REENTRANT fp GetQuadrantEdge( void ) { ASSERT(IfMade()); return mQuadrantEdge; }
00085 FN_REENTRANT uint GetQuadrantDim( uint dim ) { ASSERT(IfMade()); return mQuadrantDim[dim]; }
00086
00087 #if DEBUG
00088 void Check( void );
00089 #endif
00090
00091 protected:
00092 typedef uint Qidx;
00093 enum eSim { eSim_FLIGHT, eSim_SPACE };
00094 enum eOutsidePolicy { eOutsidePolicy_CLAMP, eOutsidePolicy_WRAP };
00095
00096 protected:
00097 World( void ) { }
00098 virtual ~World() { }
00099 void Make( const eSim sim, const Int3& quadrantDim, const fp quadrantEdge, const Int3& locusDim );
00100 FN_LOCKED virtual void Populate( QuadrantPtr quadrant ) = 0;
00101 FN_LOCKED QuadrantPtr GetQuadrant( const Int3& triplet );
00102 FN_REENTRANT QuadrantPtr GetQuadrant( const WorldVertex& pos );
00103 FN_REENTRANT Qidx GetQuadrantIdx( const Int3& triplet );
00104 FN_REENTRANT Qidx GetQuadrantIdx( const WorldVertex& pos );
00105 FN_REENTRANT Int3 GetQuadrantTriplet( const WorldVertex& pos );
00106 FN_REENTRANT Int3 WrapQuadrantTriplet( const Int3& triplet );
00107 FN_MAIN_THREAD void DeleteQuadrant( QuadrantPtr quadrant );
00108 FN_REENTRANT WorldVertex CorrectPositionClamp( const WorldVertex& pos );
00109 FN_REENTRANT WorldVertex CorrectPositionWrap( const WorldVertex& pos );
00110
00111
00112 protected:
00120 class Quadrant : public Threadable
00121 {
00122
00123 friend void ThreadQuadrantPopulate( long quadrant );
00124 public:
00125 enum eState { EMPTY, SHRUNK, POPULATING, POPULATED };
00126 Quadrant( const Int3& triplet, const fp edge, const uint seed );
00127 ~Quadrant();
00128 FN_LOCKED void Populate( void );
00129 FN_LOCKED uint Shrink( void );
00130 FN_LOCKED eAttached Attach( SharedPtr<Object> object );
00131 FN_LOCKED eAttached Detach( SharedPtr<Object> object );
00132 FN_REENTRANT void Draw( void );
00133 FN_LOCKED const BoxVolume& GetBoxVolume( void );
00134 FN_LOCKED WorldVertex GetCenter( void );
00135 FN_LOCKED Int3 GetTriplet( void );
00136 FN_REENTRANT eState GetState( void );
00137 FN_LOCKED void SetState( eState state );
00138 FN_LOCKED uint GetSeed( void );
00139 FN_REENTRANT uint GetObjectCnt( void );
00140
00141 private:
00142 BoxVolume ComputeBoxVolume( const Int3& triplet, const fp edge );
00143 class ShrinkEachObjectFunctor : public BSP::ForEachObjectFunctor
00144 {
00145 public:
00146 ShrinkEachObjectFunctor( void ) : mObjectCnt(0) { }
00147 void operator()( SharedPtr<Object> object );
00148 uint mObjectCnt;
00149 };
00150
00151 public:
00152 SlowLock mLock;
00153 private:
00154 Int3 mTriplet;
00155 eState mState;
00156 uint mSeed;
00157 BSP mBSP;
00158 int mObjectCnt;
00159 CLASS_VAR fp msEdge;
00160 public:
00161
00162 };
00163
00164
00165 protected:
00169 class Locus
00170 {
00171
00172 public:
00173 typedef World::Qidx Qidx;
00174 typedef vector<QuadrantPtr> PopulateQueue;
00175 Locus( void );
00176 ~Locus();
00177 FN_MAIN_THREAD void Init( const Int3& dim );
00178 FN_MAIN_THREAD void Update( void );
00179 FN_MAIN_THREAD void Draw( void );
00180 FN_LOCKED uint GetObjectCnt( void );
00181
00182 private:
00183 FN_MAIN_THREAD void Move( QuadrantPtr centerQuadrant );
00184 FN_MAIN_THREAD uint MakeQuadrant( const Int3 t, vector<PopulateQueue*>& populateQueues, uint populateQueueIdx );
00185 FN_MAIN_THREAD void DestroyZombieQuadrants( void );
00186 FN_MAIN_THREAD bool ShrinkQuadrant( QuadrantPtr quadrant );
00187 #if DEBUG
00188 FN_LOCKED QuadrantPtr GetCenterQuadrant( void );
00189 FN_LOCKED World::Qidx GetQuadrantIdx( const Int3& triplet );
00190 #endif
00191
00192 private:
00194 class LocusIdleFunctor : public Event<>::ListenerFunctor
00195 {
00196 public:
00197 LocusIdleFunctor( Locus& locus ) : mLocus(locus) { }
00198 void operator()( Void nothing );
00199 Locus& mLocus;
00200 };
00201 friend class LocusIdleFunctor;
00202
00203 private:
00204 typedef vector<Qidx> QuadrantContainer;
00205 typedef QuadrantContainer::iterator QuadrantIterator;
00206
00207 SlowLock mLock;
00208 QuadrantContainer mQuadrants;
00209 Int3 mDim;
00210 Int3 mDimHalf;
00211 Int3 mCenterTriplet;
00212 Int3 mPrevQuadrantTriplet;
00213 QuadrantContainer mPrevQuadrants;
00214 set<Qidx> mZombieQuadrants;
00215 };
00216
00217 private:
00219 struct QuadrantSeed
00220 {
00221 QuadrantSeed( Quadrant* q, uint seed ) : mQuadrant(q), mSeed(seed) { }
00222 Quadrant* mQuadrant;
00223 uint mSeed;
00224 };
00225
00226
00227 protected:
00228 SlowLock mLock;
00229 eSim mSim;
00230 eOutsidePolicy mOutsidePolicy;
00231 BoxVolume mBoxVolume;
00232 fp mQuadrantEdge;
00233 Int3 mQuadrantDim;
00234 Int3 mLocusDim;
00235 vector<QuadrantSeed> mQuadrants;
00236 Locus mLocus;
00237 fp mMargin;
00238 };
00239
00240 }
00241
00242 #endif // ENG_WORLD_HH