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 inline const std::vector<Block*>& GetBlocks( unsigned int index ) 00052 { return blocks[index]; } 00053 00054 Region* region; 00055 }; // class Cell 00056 00057 class Region 00058 { 00059 friend class SuperRegion; 00060 friend class World; // for raytracing 00061 00062 private: 00063 std::vector<Cell> cells; 00064 unsigned long count; // number of blocks rendered into this region 00065 00066 public: 00067 Region(); 00068 ~Region(); 00069 00070 inline Cell* GetCell( int32_t x, int32_t y ) 00071 { 00072 if( cells.size() == 0 ) 00073 { 00074 assert(count == 0 ); 00075 00076 cells.resize( REGIONSIZE ); 00077 00078 for( int32_t c=0; c<REGIONSIZE;++c) 00079 cells[c].region = this; 00080 } 00081 00082 return( &cells[ x + y * REGIONWIDTH ] ); 00083 } 00084 00085 inline void AddBlock(); 00086 inline void RemoveBlock(); 00087 00088 SuperRegion* superregion; 00089 00090 }; // class Region 00091 00092 class SuperRegion 00093 { 00094 private: 00095 unsigned long count; // number of blocks rendered into this superregion 00096 point_int_t origin; 00097 Region regions[SUPERREGIONSIZE]; 00098 World* world; 00099 00100 public: 00101 SuperRegion( World* world, point_int_t origin ); 00102 ~SuperRegion(); 00103 00104 inline Region* GetRegion( int32_t x, int32_t y ) 00105 { 00106 return( ®ions[ x + y * SUPERREGIONWIDTH ]); 00107 } 00108 00109 void DrawOccupancy(void) const; 00110 void DrawVoxels(unsigned int layer) const; 00111 00112 inline void AddBlock(); 00113 inline void RemoveBlock(); 00114 00115 const point_int_t& GetOrigin() const { return origin; } 00116 }; // class SuperRegion; 00117 00118 00119 }; // namespace Stg