00001 #pragma once 00002 /* 00003 region.hh 00004 data structures supporting multi-resolution ray tracing in world class. 00005 Copyright Richard Vaughan 2008 00006 */ 00007 00008 #include "stage.hh" 00009 00010 namespace Stg 00011 { 00012 00013 // a bit of experimenting suggests that these values are fast. YMMV. 00014 const int32_t RBITS( 5 ); // regions contain (2^RBITS)^2 pixels 00015 const int32_t SBITS( 5 );// superregions contain (2^SBITS)^2 regions 00016 const int32_t SRBITS( RBITS+SBITS ); 00017 00018 const int32_t REGIONWIDTH( 1<<RBITS ); 00019 const int32_t REGIONSIZE( REGIONWIDTH*REGIONWIDTH ); 00020 00021 const int32_t SUPERREGIONWIDTH( 1<<SBITS ); 00022 const int32_t SUPERREGIONSIZE( SUPERREGIONWIDTH*SUPERREGIONWIDTH ); 00023 00024 const int32_t CELLMASK( ~((~0x00)<< RBITS )); 00025 const int32_t REGIONMASK( ~((~0x00)<< SRBITS )); 00026 00027 inline int32_t GETCELL( const int32_t x ) { return( x & CELLMASK); } 00028 inline int32_t GETREG( const int32_t x ) { return( ( x & REGIONMASK ) >> RBITS); } 00029 inline int32_t GETSREG( const int32_t x ) { return( x >> SRBITS); } 00030 00031 // this is slightly faster than the inline method above, but not as safe 00032 //#define GETREG(X) (( (static_cast<int32_t>(X)) & REGIONMASK ) >> RBITS) 00033 00034 class Cell 00035 { 00036 friend class SuperRegion; 00037 friend class World; 00038 00039 private: 00040 std::vector<Block*> blocks[2]; 00041 00042 public: 00043 Cell() 00044 : blocks(), 00045 region(NULL) 00046 { /* nothing to do */ } 00047 00048 void RemoveBlock( Block* b, unsigned int index ); 00049 void AddBlock( Block* b, unsigned int index ); 00050 00051 const std::vector<Block*>& GetBlocks( unsigned int index ){ return blocks[index]; } 00052 00053 Region* region; 00054 }; // class Cell 00055 00056 class Region 00057 { 00058 friend class SuperRegion; 00059 friend class World; // for raytracing 00060 00061 private: 00062 Cell* cells; 00063 unsigned long count; // number of blocks rendered into this region 00064 00065 // vector of garbage collected cell arrays to reallocate before 00066 // using new in GetCell() 00067 static std::vector<Cell*> dead_pool; 00068 00069 public: 00070 Region(); 00071 ~Region(); 00072 00073 inline Cell* GetCell( int32_t x, int32_t y ) 00074 { 00075 if( cells == NULL ) 00076 { 00077 assert(count == 0 ); 00078 00079 if( dead_pool.size() ) 00080 { 00081 cells = dead_pool.back(); 00082 dead_pool.pop_back(); 00083 //printf( "reusing cells @ %p (pool %u)\n", cells, dead_pool.size() ); 00084 } 00085 else 00086 cells = new Cell[REGIONSIZE]; 00087 00088 for( int32_t c=0; c<REGIONSIZE;++c) 00089 cells[c].region = this; 00090 } 00091 return( &cells[ x + y * REGIONWIDTH ] ); 00092 } 00093 00094 inline void AddBlock(); 00095 inline void RemoveBlock(); 00096 00097 SuperRegion* superregion; 00098 00099 }; // class Region 00100 00101 class SuperRegion 00102 { 00103 private: 00104 unsigned long count; // number of blocks rendered into this superregion 00105 pthread_rwlock_t rwlock; 00106 point_int_t origin; 00107 Region regions[SUPERREGIONSIZE]; 00108 World* world; 00109 00110 public: 00111 SuperRegion( World* world, point_int_t origin ); 00112 ~SuperRegion(); 00113 00114 inline Region* GetRegion( int32_t x, int32_t y ) 00115 { 00116 return( ®ions[ x + y * SUPERREGIONWIDTH ]); 00117 } 00118 00119 void DrawOccupancy(unsigned int layer) const; 00120 void DrawVoxels(unsigned int layer) const; 00121 00122 inline void ReadLock(){ pthread_rwlock_rdlock( &rwlock); } 00123 inline void WriteLock(){ pthread_rwlock_wrlock( &rwlock); } 00124 inline void Unlock(){ pthread_rwlock_unlock( &rwlock); } 00125 00126 inline void AddBlock(); 00127 inline void RemoveBlock(); 00128 00129 const point_int_t& GetOrigin() const { return origin; } 00130 }; // class SuperRegion; 00131 00132 }; // namespace Stg