region.hh
Go to the documentation of this file.
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( &regions[ 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