Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

simplified bitmap rendering (back to the old days) for speed and to a…

…llow garbage collection of unused cell arrays into a pool for reuse, thus keeping the memory footprint approximately constant over time - a serious improvement for large worlds.
  • Loading branch information...
commit 55b9c56897217966560659c1f54ab455dcb2d90d 1 parent 0a5ba1d
@rtv authored
View
2  CMakeLists.txt
@@ -43,7 +43,7 @@ ENDIF (NOT PROJECT_OS_WIN AND NOT PROJECT_OS_SOLARIS)
# Build type cflags
SET (OPTIMIZE "-O2")
SET (CMAKE_CXX_FLAGS_RELEASE " ${OPTIMIZE} -DNDEBUG ${WALL} " CACHE INTERNAL "C Flags for release" FORCE)
-SET (CMAKE_CXX_FLAGS_DEBUG " -ggdb ${WALL} " CACHE INTERNAL "C Flags for debug" FORCE)
+SET (CMAKE_CXX_FLAGS_DEBUG "-ggdb ${WALL} " CACHE INTERNAL "C Flags for debug" FORCE)
SET (CMAKE_CXX_FLAGS_PROFILE " -ggdb -pg ${WALL} " CACHE INTERNAL "C Flags for profile" FORCE)
#####################################
View
2  libstage/CMakeLists.txt
@@ -57,7 +57,7 @@ ENDIF (NOT(${FLTK_LDFLAGS} MATCHES "-lGL"))
# causes the shared library to have a version number
set_target_properties( stage PROPERTIES
VERSION ${VERSION}
- LINK_FLAGS "${FLTK_LDFLAGS}"
+ LINK_FLAGS "${FLTK_LDFLAGS}"
)
target_link_libraries( stage ${LTDL_LIB} )
View
209 libstage/block.cc
@@ -24,8 +24,7 @@ Block::Block( Model* mod,
color( color ),
inherit_color( inherit_color ),
wheel(wheel),
- rendered_cells( new CellPtrVec ),
- candidate_cells( new CellPtrVec ),
+ rendered_cells(),
gpts()
{
assert( mod );
@@ -39,10 +38,12 @@ Block::Block( Model* mod,
: mod( mod ),
mpts(),
pts(),
+ local_z(),
color(),
inherit_color(true),
- rendered_cells( new CellPtrVec ),
- candidate_cells( new CellPtrVec )
+ wheel(),
+ rendered_cells(),
+ gpts()
{
assert(mod);
assert(wf);
@@ -55,9 +56,6 @@ Block::Block( Model* mod,
Block::~Block()
{
if( mapped ) UnMap();
-
- delete rendered_cells;
- delete candidate_cells;
}
void Block::Translate( double x, double y )
@@ -139,9 +137,9 @@ const Color& Block::GetColor()
void Block::AppendTouchingModels( ModelPtrSet& touchers )
{
// for every cell we are rendered into
- FOR_EACH( cell_it, *rendered_cells )
- // for every block rendered into that cell
- FOR_EACH( block_it, (*cell_it)->blocks )
+ FOR_EACH( cell_it, rendered_cells )
+ // for every block rendered into that cell
+ FOR_EACH( block_it, (*cell_it)->GetBlocks() )
{
if( !mod->IsRelated( (*block_it)->mod ))
touchers.insert( (*block_it)->mod );
@@ -153,7 +151,7 @@ Model* Block::TestCollision()
//printf( "model %s block %p test collision...\n", mod->Token(), this );
// find the set of cells we would render into given the current global pose
- GenerateCandidateCells();
+ //GenerateCandidateCells();
if( mod->vis.obstacle_return )
{
@@ -161,10 +159,10 @@ Model* Block::TestCollision()
return this->mod->world->GetGround();
// for every cell we may be rendered into
- FOR_EACH( cell_it, *candidate_cells )
+ FOR_EACH( cell_it, rendered_cells )
{
// for every block rendered into that cell
- FOR_EACH( block_it, (*cell_it)->blocks )
+ FOR_EACH( block_it, (*cell_it)->GetBlocks() )
{
Block* testblock = *block_it;
Model* testmod = testblock->mod;
@@ -192,72 +190,64 @@ Model* Block::TestCollision()
void Block::Map()
{
- // TODO - if called often, we may not need to generate each time
- GenerateCandidateCells();
- SwitchToTestedCells();
- mapped = true;
+ // clear out of the old cells
+ RemoveFromCellArray( rendered_cells );
+
+ // now calculate the local coords of the block vertices
+ const unsigned int pt_count = pts.size();
+
+ if( mpts.size() == 0 )
+ {
+ // no valid cache of model coord points, so generate them
+ mpts.resize( pts.size() );
+
+ for( unsigned int i=0; i<pt_count; ++i )
+ mpts[i] = BlockPointToModelMeters( pts[i] );
+ }
+
+ // now calculate the global pixel coords of the block vertices
+ gpts.clear();
+ mod->LocalToPixels( mpts, gpts );
+
+ for( unsigned int i=0; i<pt_count; ++i )
+ MapLine( gpts[i],
+ gpts[(i+1)%pt_count] );
+
+ // update the block's absolute z bounds at this rendering
+ Pose gpose = mod->GetGlobalPose();
+ gpose.z += mod->geom.pose.z;
+ double scalez = mod->geom.size.z / mod->blockgroup.GetSize().z;
+ meters_t z = gpose.z - mod->blockgroup.GetOffset().z;
+ global_z.min = (scalez * local_z.min) + z;
+ global_z.max = (scalez * local_z.max) + z;
+
+ mapped = true;
}
void Block::UnMap()
{
RemoveFromCellArray( rendered_cells );
- rendered_cells->clear();
+ rendered_cells.clear();
mapped = false;
}
#include <algorithm>
#include <functional>
-inline void Block::RemoveFromCellArray( CellPtrVec *cells )
+inline void Block::RemoveFromCellArray( CellPtrVec& cells )
{
// FOR_EACH( it, *cells )
// (*it)->RemoveBlock(this);
// this is equivalent to the above commented code - experimenting
// with optimizations
- std::for_each( cells->begin(),
- cells->end(),
+ std::for_each( cells.begin(),
+ cells.end(),
std::bind2nd( std::mem_fun(&Cell::RemoveBlock), this));
-
- //printf( "%d %d %.2f\n", count1, countmore, ((float)count1)/float(countmore));
}
void Block::SwitchToTestedCells()
{
- // todo:
-
- // 1. find the set of cells in rendered but not candidate and remove
- // them
-
- // 2. find the set of cells in candidate but not rendered and insert
- // them
-
- // .. and see if that is faster than the current method
-
- //printf( "rendered_cells %lu\n", rendered_cells->size() );
- //printf( "candidate_cells %lu\n\n", candidate_cells->size() );
-
- RemoveFromCellArray( rendered_cells );
-
- // render the block into each of the candidate cells
- FOR_EACH( it, *candidate_cells )
- {
- Cell* cell = *it;
- // record that I am rendered in this cell
- rendered_cells->push_back( cell );
- // store me in the cell
- cell->blocks.push_back( this );
-
- ++cell->region->count;
- ++cell->region->superregion->count;
- }
-
- // switch current and candidate cell pointers
- CellPtrVec *tmp = rendered_cells;
- rendered_cells = candidate_cells;
- candidate_cells = tmp;
-
- mapped = true;
}
inline point_t Block::BlockPointToModelMeters( const point_t& bpt )
@@ -275,43 +265,6 @@ void Block::InvalidateModelPointCache()
mpts.clear();
}
-void Block::GenerateCandidateCells()
-{
- candidate_cells->clear();
-
- const unsigned int pt_count = pts.size();
-
- if( mpts.size() == 0 )
- {
- // no valid cache of model coord points, so generate them
- mpts.resize( pts.size() );
-
-
- for( unsigned int i=0; i<pt_count; ++i )
- mpts[i] = BlockPointToModelMeters( pts[i] );
- }
-
- gpts.clear();
- mod->LocalToPixels( mpts, gpts );
-
- for( unsigned int i=0; i<pt_count; ++i )
- mod->world->ForEachCellInLine( gpts[i],
- gpts[(i+1)%pt_count],
- *candidate_cells );
-
- // set global Z
- Pose gpose = mod->GetGlobalPose();
- gpose.z += mod->geom.pose.z;
- double scalez = mod->geom.size.z / mod->blockgroup.GetSize().z;
- meters_t z = gpose.z - mod->blockgroup.GetOffset().z;
-
- // store the block's absolute z bounds at this rendering
- global_z.min = (scalez * local_z.min) + z;
- global_z.max = (scalez * local_z.max) + z;
-
- mapped = true;
-}
-
void swap( int& a, int& b )
{
int tmp = a;
@@ -480,6 +433,74 @@ void Block::Load( Worldfile* wf, int entity )
wheel = wf->ReadInt( entity, "wheel", wheel );
}
+
+void Block::MapLine( const point_int_t& start,
+ const point_int_t& end )
+{
+ // line rasterization adapted from Cohen's 3D version in
+ // Graphics Gems II. Should be very fast.
+ const int32_t dx( end.x - start.x );
+ const int32_t dy( end.y - start.y );
+ const int32_t sx(sgn(dx));
+ const int32_t sy(sgn(dy));
+ const int32_t ax(abs(dx));
+ const int32_t ay(abs(dy));
+ const int32_t bx(2*ax);
+ const int32_t by(2*ay);
+ int32_t exy(ay-ax);
+ int32_t n(ax+ay);
+
+ int32_t globx(start.x);
+ int32_t globy(start.y);
+
+
+ World* w = mod->GetWorld();
+
+ while( n )
+ {
+ Region* reg( w->GetSuperRegion( GETSREG(globx), GETSREG(globy) )
+ ->GetRegion( GETREG(globx), GETREG(globy) ));
+
+ //printf( "REGION %p\n", reg );
+
+ // add all the required cells in this region before looking up
+ // another region
+ int32_t cx( GETCELL(globx) );
+ int32_t cy( GETCELL(globy) );
+
+ // need to call Region::GetCell() before using a Cell pointer
+ // directly, because the region allocates cells lazily, waiting
+ // for a call of this method
+ Cell* c( reg->GetCell( cx, cy ) );
+
+ // while inside the region, manipulate the Cell pointer directly
+ while( (cx>=0) && (cx<REGIONWIDTH) &&
+ (cy>=0) && (cy<REGIONWIDTH) &&
+ n > 0 )
+ {
+ c->AddBlock(this);
+
+ // cleverly skip to the next cell (now it's safe to
+ // manipulate the cell pointer)
+ if( exy < 0 )
+ {
+ globx += sx;
+ exy += by;
+ c += sx;
+ cx += sx;
+ }
+ else
+ {
+ globy += sy;
+ exy -= bx;
+ c += sy * REGIONWIDTH;
+ cy += sy;
+ }
+ --n;
+ }
+ }
+}
+
/////////////////////////////////////////////////////////////////////////////////////////
// utility functions to ensure block winding is consistent and matches OpenGL's default
View
4 libstage/canvas.cc
@@ -148,7 +148,9 @@ void Canvas::InitTextures()
{
PRINT_DEBUG( "Unable to load stall texture.\n" );
}
-
+
+ printf( "stall icon %s\n", fullpath.c_str() );
+
GLuint stall_id = TextureManager::getInstance().loadTexture( fullpath.c_str() );
TextureManager::getInstance()._stall_texture_id = stall_id;
View
3  libstage/file_manager.cc
@@ -33,7 +33,8 @@ namespace Stg
return std::string( stgPath );
}
- std::string FileManager::findFile( const std::string filename ) {
+ std::string FileManager::findFile( const std::string filename )
+ {
PRINT_DEBUG1("FileManager: trying %s\n", filename.c_str());
if ( readable( filename ) )
return filename;
View
85 libstage/model.cc
@@ -836,7 +836,7 @@ void Model::AddToPose( const Pose& pose )
void Model::PlaceInFreeSpace( meters_t xmin, meters_t xmax,
meters_t ymin, meters_t ymax )
{
- while( TestCollisionTree() )
+ while( TestCollision() )
SetPose( Pose::Random( xmin,xmax, ymin, ymax ));
}
@@ -845,22 +845,17 @@ void Model::AppendTouchingModels( ModelPtrSet& touchers )
blockgroup.AppendTouchingModels( touchers );
}
-Model* Model::TestCollision()
-{
- //printf( "mod %s test collision...\n", token );
- return( blockgroup.TestCollision() );
-}
-Model* Model::TestCollisionTree()
+Model* Model::TestCollision()
{
- Model* hitmod = TestCollision();
+ Model* hitmod = blockgroup.TestCollision();
if( hitmod == NULL )
FOR_EACH( it, children )
- {
- hitmod = (*it)->TestCollisionTree();
- if( hitmod )
- break;
+ {
+ hitmod = (*it)->TestCollision();
+ if( hitmod )
+ break;
}
//printf( "mod %s test collision done.\n", token );
@@ -918,56 +913,30 @@ void Model::UpdateCharge()
}
}
-void Model::CommitTestedPose()
-{
- FOR_EACH( it, children )
- (*it)->CommitTestedPose();
-
- blockgroup.SwitchToTestedCells();
-}
-
-Model* Model::ConditionalMove( const Pose& newpose )
+Model* Model::Move( const Pose& newpose )
{
- //assert( newpose.a >= -M_PI );
- //assert( newpose.a <= M_PI );
-
const Pose startpose( pose );
pose = newpose; // do the move provisionally - we might undo it below
-
- Model* hitmod( TestCollisionTree() );
-
- if( hitmod )
- {
- pose = startpose; // move failed - put me back where I started
- }
- else
- {
- CommitTestedPose(); //recursively commit to blocks to the new pose
- world->dirty = true; // need redraw
- }
- return hitmod;
-}
-
-void Model::ConditionalMove_calc( const Pose& newpose )
-{
- const Pose startpose( pose );
- pose = newpose; // do the move provisionally - we might undo it below
-
- this->hitmod = NULL;
- this->hitmod = TestCollisionTree();
-
- if( hitmod )
- pose = startpose; // move failed - put me back where I started
-}
-
-void Model::ConditionalMove_commit()
-{
- CommitTestedPose(); //recursively commit to blocks to the new pose
- world->dirty = true; // need redraw
+ UnMapWithChildren(); // remove from all blocks
+ MapWithChildren(); // render into blocks
+
+ Model* hitmod = TestCollision();
+
+ if( hitmod ) // crunch!
+ {
+ // put things back the way they were
+ // this is expensive, but it happens very rarely for most people
+ pose = startpose;
+ UnMapWithChildren();
+ MapWithChildren();
+ }
+ else
+ world->dirty = true; // need redraw
+
+ return hitmod;
}
-
void Model::UpdatePose( void )
{
if( velocity.IsZero() )
@@ -987,9 +956,9 @@ void Model::UpdatePose( void )
// attempts to move to the new pose. If the move fails because we'd
// hit another model, that model is returned.
- // ConditionalMove() returns a pointer to the model we hit, or
+ // Move() returns a pointer to the model we hit, or
// NULL. We use this as a boolean for SetStall()
- SetStall( ConditionalMove( pose + p ) );
+ SetStall( Move( pose + p ) );
}
View
8 libstage/option.cc
@@ -6,9 +6,9 @@
using namespace Stg;
-Option::Option( std::string n,
- std::string tok,
- std::string key,
+Option::Option( const std::string& n,
+ const std::string& tok,
+ const std::string& key,
bool v,
World* world ) :
optName( n ),
@@ -18,7 +18,7 @@ Option::Option( std::string n,
menu( NULL ),
menuCb( NULL ),
_world( world ),
- htname( strdup(n.c_str()) )
+ htname( n )
{
/* do nothing */
}
View
8 libstage/option.hh
@@ -32,7 +32,11 @@ namespace Stg {
World* _world;
public:
- Option( std::string n, std::string tok, std::string key, bool v, World *world );
+ Option( const std::string& n,
+ const std::string& tok,
+ const std::string& key,
+ bool v,
+ World *world );
const std::string name() const { return optName; }
inline bool isEnabled() const { return value; }
@@ -60,7 +64,7 @@ namespace Stg {
void Load( Worldfile* wf, int section );
void Save( Worldfile* wf, int section );
- const char* htname;
+ std::string htname;
};
}
View
156 libstage/region.cc
@@ -7,15 +7,49 @@
#include "region.hh"
using namespace Stg;
-Region::Region( SuperRegion* sr) :
+std::vector<Cell*> Region::dead_pool;
+
+Region::Region() :
cells(),
- superregion(sr),
- count(0)
-{
+ count(0),
+ superregion(NULL)
+{
}
Region::~Region()
{
+ if( cells )
+ delete[] cells;
+}
+
+void Region::AddBlock()
+{
+
+ ++count;
+ assert(count>0);
+ superregion->AddBlock();
+}
+
+void Region::RemoveBlock()
+{
+ --count;
+ assert(count>=0);
+ superregion->RemoveBlock();
+
+ // if there's nothing in this region, we can garbage collect the
+ // cells to keep memory usage under control
+ if( count == 0 )
+ {
+ if( cells )
+ {
+ // stash this on the pool for reuse
+ dead_pool.push_back(cells);
+ //printf( "retiring cells @ %p (pool %u)\n", cells, dead_pool.size() );
+ cells = NULL;
+ }
+ else
+ PRINT_ERR( "region.count == 0 but cells == NULL" );
+ }
}
SuperRegion::SuperRegion( World* world, point_int_t origin )
@@ -24,15 +58,29 @@ SuperRegion::SuperRegion( World* world, point_int_t origin )
world(world),
count(0)
{
- // populate the regions
- regions.insert( regions.begin(), SUPERREGIONSIZE, Region( this ) );
+ for( int32_t r=0; r<SUPERREGIONSIZE;r++)
+ regions[r].superregion = this;
}
SuperRegion::~SuperRegion()
{
}
-void SuperRegion::DrawOccupancy()
+
+void SuperRegion::AddBlock()
+{
+ ++count;
+ assert(count>0);
+}
+
+void SuperRegion::RemoveBlock()
+{
+ --count;
+ assert(count>=0);
+}
+
+
+void SuperRegion::DrawOccupancy() const
{
glPushMatrix();
GLfloat scale = 1.0/world->Resolution();
@@ -47,15 +95,15 @@ void SuperRegion::DrawOccupancy()
glRecti( 0,0, 1<<SRBITS, 1<<SRBITS );
// outline regions
- const Region* r = GetRegion(0,0);
+ const Region* r = &regions[0];
char buf[32];
glColor3f( 0,1,0 );
for( int y=0; y<SUPERREGIONWIDTH; ++y )
for( int x=0; x<SUPERREGIONWIDTH; ++x )
- {
- if( r->count ) // region contains some occupied cells
- {
+ {
+ if( r->count ) // region contains some occupied cells
+ {
// outline the region
glRecti( x<<RBITS, y<<RBITS,
(x+1)<<RBITS, (y+1)<<RBITS );
@@ -73,38 +121,38 @@ void SuperRegion::DrawOccupancy()
GLfloat yy = q+(y<<RBITS);
glRecti( xx, yy, xx+1, yy+1);
}
- }
- else if( ! r->cells.empty() ) // empty but used previously
- {
- double left = x << RBITS;
- double right = (x+1) << RBITS;
- double bottom = y << RBITS;
- double top = (y+1) << RBITS;
-
- double d = 3.0;
-
- // draw little corner markers for regions with memory
+ }
+ else if( r->cells ) // empty but used previously
+ {
+ double left = x << RBITS;
+ double right = (x+1) << RBITS;
+ double bottom = y << RBITS;
+ double top = (y+1) << RBITS;
+
+ double d = 3.0;
+
+ // draw little corner markers for regions with memory
// allocated but no contents
- glBegin( GL_LINES );
- glVertex2f( left, bottom );
- glVertex2f( left+d, bottom );
- glVertex2f( left, bottom );
- glVertex2f( left, bottom+d );
- glVertex2f( left, top );
- glVertex2f( left+d, top );
- glVertex2f( left, top );
- glVertex2f( left, top-d );
- glVertex2f( right, top );
- glVertex2f( right-d, top );
- glVertex2f( right, top );
- glVertex2f( right, top-d );
- glVertex2f( right, bottom );
- glVertex2f( right-d, bottom );
- glVertex2f( right, bottom );
- glVertex2f( right, bottom+d );
- glEnd();
- }
-
+ glBegin( GL_LINES );
+ glVertex2f( left, bottom );
+ glVertex2f( left+d, bottom );
+ glVertex2f( left, bottom );
+ glVertex2f( left, bottom+d );
+ glVertex2f( left, top );
+ glVertex2f( left+d, top );
+ glVertex2f( left, top );
+ glVertex2f( left, top-d );
+ glVertex2f( right, top );
+ glVertex2f( right-d, top );
+ glVertex2f( right, top );
+ glVertex2f( right, top-d );
+ glVertex2f( right, bottom );
+ glVertex2f( right-d, bottom );
+ glVertex2f( right, bottom );
+ glVertex2f( right, bottom+d );
+ glEnd();
+ }
+
++r; // next region quickly
}
@@ -115,7 +163,7 @@ void SuperRegion::DrawOccupancy()
}
-static void DrawBlock( GLfloat x, GLfloat y, GLfloat zmin, GLfloat zmax )
+static inline void DrawBlock( GLfloat x, GLfloat y, GLfloat zmin, GLfloat zmax )
{
glBegin( GL_QUADS );
@@ -149,7 +197,7 @@ static void DrawBlock( GLfloat x, GLfloat y, GLfloat zmin, GLfloat zmax )
glEnd();
}
-void SuperRegion::DrawVoxels()
+void SuperRegion::DrawVoxels() const
{
glPushMatrix();
GLfloat scale = 1.0/world->Resolution();
@@ -160,7 +208,7 @@ void SuperRegion::DrawVoxels()
glEnable( GL_DEPTH_TEST );
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
- Region* r = GetRegion( 0, 0);
+ const Region* r = &regions[0];//GetRegion( 0, 0);
for( int y=0; y<SUPERREGIONWIDTH; ++y )
for( int x=0; x<SUPERREGIONWIDTH; ++x )
@@ -205,8 +253,23 @@ void SuperRegion::DrawVoxels()
}
+//std::set<Block*> mapped_blocks;
+
+void Cell::AddBlock( Block* b )
+{
+ blocks.push_back( b );
+ b->rendered_cells.push_back(this);
+ region->AddBlock();
+
+ //mapped_blocks.insert(b);
+}
+
+
void Cell::RemoveBlock( Block* b )
{
+ //if( mapped_blocks.find(b) == mapped_blocks.end() )
+ //printf( "REMOVE BLOCK %p that was never mapped\n", b );
+
size_t len = blocks.size();
if( len )
{
@@ -243,6 +306,5 @@ void Cell::RemoveBlock( Block* b )
#endif
}
- --region->count;
- --region->superregion->count;
+ region->RemoveBlock();
}
View
137 libstage/region.hh
@@ -33,71 +33,114 @@ namespace Stg
// this is slightly faster than the inline method above, but not as safe
//#define GETREG(X) (( (static_cast<int32_t>(X)) & REGIONMASK ) >> RBITS)
+ // class Region;
+
class Cell
{
- friend class Region;
- friend class SuperRegion;
- friend class World;
- friend class Block;
+ //friend class Region;
+ friend class SuperRegion;
+ friend class World;
+ //friend class Block;
private:
- Region* region;
- std::vector<Block*> blocks;
-
+ std::vector<Block*> blocks;
+
public:
- Cell( Region* reg )
- : region( reg ),
- blocks()
- { /* nothing to do */ }
-
+ Cell()
+ : blocks(),
+ region(NULL)
+ { /* nothing to do */ }
+
void RemoveBlock( Block* b );
+ void AddBlock( Block* b );
+
+ const std::vector<Block*>& GetBlocks(){ return blocks; }
+ Region* region;
}; // class Cell
-
+
class Region
{
- public:
- std::vector<Cell> cells;
-
- SuperRegion* superregion;
- unsigned long count; // number of blocks rendered into this region
-
- Region( SuperRegion* sr );
- ~Region();
-
- Cell* GetCell( int32_t x, int32_t y )
- {
- if( cells.empty() ) // lazy population of cells
- cells.insert( cells.begin(), REGIONSIZE, Cell( this ) );
+ friend class SuperRegion;
+ friend class World; // for raytracing
+
+ private:
+ Cell* cells;
+
+ unsigned long count; // number of blocks rendered into this region
+
+ // vector of garbage collected cell arrays to reallocate before
+ // using new in GetCell()
+ static std::vector<Cell*> dead_pool;
- return( (Cell*)&cells[ x + y * REGIONWIDTH ] );
- }
+ public:
+ Region();
+ ~Region();
+
+ inline Cell* GetCell( int32_t x, int32_t y )
+ {
+ if( cells == NULL )
+ {
+ assert(count == 0 );
+
+ if( dead_pool.size() )
+ {
+ cells = dead_pool.back();
+ dead_pool.pop_back();
+
+ //printf( "reusing cells @ %p (pool %u)\n", cells, dead_pool.size() );
+ }
+ else
+ cells = new Cell[REGIONSIZE];
+
+ for( int32_t c=0; c<REGIONSIZE;++c)
+ cells[c].region = this;
+ }
+
+ return( &cells[ x + y * REGIONWIDTH ] );
+ }
+
+ inline void AddBlock();
+ inline void RemoveBlock();
- }; // class Region
+ SuperRegion* superregion;
+
+ //bool Occupied() const { return( count > 0 ); }
+ //bool Used() const { return( cells ? true : false ); }
+ }; // class Region
+
class SuperRegion
{
- friend class World;
- friend class Model;
-
+ // friend class World;
+ // friend class Model;
+
private:
-
- std::vector<Region> regions;
- point_int_t origin;
- World* world;
-
- public:
-
+ Region regions[SUPERREGIONSIZE];
+
+ point_int_t origin;
+ World* world;
+
+ unsigned long count; // number of blocks rendered into this superregion
+
+ public:
SuperRegion( World* world, point_int_t origin );
~SuperRegion();
-
- Region* GetRegion( int32_t x, int32_t y )
- { return( &regions[ x + y * SUPERREGIONWIDTH ] ); }
-
- void DrawOccupancy();
- void DrawVoxels();
-
- unsigned long count; // number of blocks rendered into this superregion
+
+ inline Region* GetRegion( int32_t x, int32_t y )
+ {
+ return( &regions[ x + y * SUPERREGIONWIDTH ]);
+ }
+
+ //inline const Region* GetRegionImmut( int32_t x, int32_t y ) const;
+
+ void DrawOccupancy() const;
+ void DrawVoxels() const;
+
+ inline void AddBlock();
+ inline void RemoveBlock();
+
+ const point_int_t& GetOrigin() const { return origin; }
}; // class SuperRegion;
}; // namespace Stg
View
57 libstage/stage.hh
@@ -608,7 +608,10 @@ namespace Stg
// STL container iterator macros - __typeof is a gcc extension, so
// this could be an issue one day.
#define VAR(V,init) __typeof(init) V=(init)
-//#define FOR_EACH(I,C) for(VAR(I,(C).begin());I!=(C).end();++I) NOTE:
+
+ //#define FOR_EACH(I,C) for(VAR(I,(C).begin());I!=(C).end();++I)
+
+// NOTE:
// this version assumes the container is not modified in the loop,
// which I think is true everywhere it is used in Stage
#define FOR_EACH(I,C) for(VAR(I,(C).begin()),ite=(C).end();(I)!=ite;++(I))
@@ -958,9 +961,9 @@ namespace Stg
/** add a Cell pointer to the vector for each cell on the line from
pt1 to pt2 inclusive */
- void ForEachCellInLine( const point_int_t& pt1,
- const point_int_t& pt2,
- CellPtrVec& cells );
+// void MapLine( const point_int_t& pt1,
+// const point_int_t& pt2,
+// Block* block );
/** convert a distance in meters to a distance in world occupancy
grid pixels */
@@ -1166,6 +1169,7 @@ namespace Stg
friend class SuperRegion;
friend class World;
friend class Canvas;
+ friend class Cell;
public:
/** Block Constructor. A model's body is a list of these
@@ -1217,13 +1221,14 @@ namespace Stg
/** Set the extent in Z of the block */
void SetZ( double min, double max );
- inline void RemoveFromCellArray( CellPtrVec* blocks );
- inline void GenerateCandidateCells();
+ inline void RemoveFromCellArray( CellPtrVec& blocks );
+ //inline void GenerateCandidateCells();
void AppendTouchingModels( ModelPtrSet& touchers );
/** Returns the first model that shares a bitmap cell with this model */
Model* TestCollision();
+
void SwitchToTestedCells();
void Load( Worldfile* wf, int entity );
Model* GetModel(){ return mod; };
@@ -1252,10 +1257,10 @@ namespace Stg
/** record the list entries for the cells where this block is rendered */
std::vector< std::list<Block*>::iterator > list_entries;
-
+
/** record the cells into which this block has been rendered to
- UnMapping them very quickly. */
- CellPtrVec * rendered_cells;
+ UnMapping them very quickly. */
+ CellPtrVec rendered_cells;
/** When moving a model, we test for collisions by generating, for
each block, a list of the cells in which it would be rendered if the
@@ -1263,7 +1268,7 @@ namespace Stg
allowed - the rendered cells are cleared, the potential cells are
written, and the pointers to the rendered and potential cells are
switched for next time (avoiding a memory copy).*/
- CellPtrVec * candidate_cells;
+ //CellPtrVec * candidate_cells;
PointIntVec gpts;
@@ -1273,6 +1278,11 @@ namespace Stg
/** invalidate the cache of points in model coordinates */
void InvalidateModelPointCache();
+
+ /** add a Cell pointer to the vector for each cell on the line from
+ pt1 to pt2 inclusive */
+ void MapLine( const point_int_t& pt1,
+ const point_int_t& pt2 );
};
@@ -2040,15 +2050,12 @@ namespace Stg
void RegisterOption( Option* opt );
void AppendTouchingModels( ModelPtrSet& touchers );
-
- /** Check to see if the current pose will yield a collision with
- obstacles. Returns a pointer to the first entity we are in
- collision with, or NULL if no collision exists. */
+
+ /** Check to see if the current pose will yield a collision with
+ obstacles. Returns a pointer to the first entity we are in
+ collision with, or NULL if no collision exists. Recursively
+ calls TestCollision() on all descendents. */
Model* TestCollision();
-
- /** Recursively call TestCollision() on this model and all its
- descendents */
- Model* TestCollisionTree();
void CommitTestedPose();
@@ -2108,11 +2115,11 @@ namespace Stg
virtual void UpdatePose();
virtual void UpdateCharge();
- Model* ConditionalMove( const Pose& newpose );
+ Model* Move( const Pose& newpose );
// EXP
- void ConditionalMove_calc( const Pose& newpose );
- void ConditionalMove_commit( void );
+ //void ConditionalMove_calc( const Pose& newpose );
+ //void ConditionalMove_commit( void );
meters_t ModelHeight() const;
@@ -2245,10 +2252,10 @@ namespace Stg
/** Add a block to this model centered at [x,y] with extent [dx, dy,
dz] */
- Block* AddBlockRect( meters_t x, meters_t y,
- meters_t dx, meters_t dy,
- meters_t dz );
-
+ Block* AddBlockRect( meters_t x, meters_t y,
+ meters_t dx, meters_t dy,
+ meters_t dz );
+
/** remove all blocks from this model, freeing their memory */
void ClearBlocks();
View
3  libstage/texture_manager.cc
@@ -23,10 +23,13 @@ Fl_Shared_Image* TextureManager::loadImage( const char* filename )
GLuint TextureManager::loadTexture( const char *filename )
{
+ printf( "attemopt to load texture %s\n", filename );
+
GLuint texName;
Fl_Shared_Image *img = loadImage( filename );
if( img == NULL ) {
fprintf( stderr, "unable to open image: %s\n", filename );
+ exit(-1);
return 0;
}
View
93 libstage/world.cc
@@ -196,14 +196,14 @@ World::~World( void )
SuperRegion* World::CreateSuperRegion( point_int_t origin )
{
SuperRegion* sr = new SuperRegion( this, origin );
- superregions[ sr->origin ] = sr;
+ superregions[ origin ] = sr;
dirty = true; // force redraw
return sr;
}
void World::DestroySuperRegion( SuperRegion* sr )
{
- superregions.erase( sr->origin );
+ superregions.erase( sr->GetOrigin() );
delete sr;
}
@@ -791,8 +791,11 @@ RaytraceResult World::Raytrace( const Ray& r )
Region* reg( GetSuperRegion( GETSREG(globx), GETSREG(globy) )
->GetRegion( GETREG(globx), GETREG(globy) ));
+
if( reg->count ) // if the region contains any objects
{
+ //assert( reg->cells.size() );
+
// invalidate the region crossing points used to jump over
// empty regions
calculatecrossings = true;
@@ -800,7 +803,8 @@ RaytraceResult World::Raytrace( const Ray& r )
// convert from global cell to local cell coords
int32_t cx( GETCELL(globx) );
int32_t cy( GETCELL(globy) );
-
+
+ //Cell* c = reg->GetCell(cx,cy);
Cell* c( &reg->cells[ cx + cy * REGIONWIDTH ] );
assert(c); // should be good: we know the region contains objects
@@ -998,88 +1002,27 @@ inline SuperRegion* World::GetSuperRegion( const int32_t x, const int32_t y )
{
// around 99% of the time the SR is the same as last
// lookup - cache gives a 4% overall speed up :)
-
- if( sr_cached && sr_cached->origin.x == x && sr_cached->origin.y == y )
- return sr_cached;
-
+
+ point_int_t org(x,y);
+
+ if( sr_cached && sr_cached->GetOrigin() == org )
+ return sr_cached;
+
// point_int_t pt(x,y);
- SuperRegion* sr = superregions[ point_int_t(x,y) ];
+ SuperRegion* sr = superregions[ org ];
if( sr == NULL ) // no superregion exists! make a new one
- sr = AddSuperRegion( point_int_t(x,y) );
-
+ sr = AddSuperRegion( org );
+
+ assert( sr );
+
// cache for next time around
sr_cached = sr;
- //assert( sr );
return sr;
}
-void World::ForEachCellInLine( const point_int_t& start,
- const point_int_t& end,
- CellPtrVec& cells )
-{
- // line rasterization adapted from Cohen's 3D version in
- // Graphics Gems II. Should be very fast.
- const int32_t dx( end.x - start.x );
- const int32_t dy( end.y - start.y );
- const int32_t sx(sgn(dx));
- const int32_t sy(sgn(dy));
- const int32_t ax(abs(dx));
- const int32_t ay(abs(dy));
- const int32_t bx(2*ax);
- const int32_t by(2*ay);
- int32_t exy(ay-ax);
- int32_t n(ax+ay);
-
- int32_t globx(start.x);
- int32_t globy(start.y);
-
- while( n )
- {
- Region* reg( GetSuperRegion( GETSREG(globx), GETSREG(globy) )
- ->GetRegion( GETREG(globx), GETREG(globy) ));
-
- // add all the required cells in this region before looking up
- // another region
- int32_t cx( GETCELL(globx) );
- int32_t cy( GETCELL(globy) );
-
- // need to call Region::GetCell() before using a Cell pointer
- // directly, because the region allocates cells lazily, waiting
- // for a call of this method
- Cell* c( reg->GetCell( cx, cy ) );
-
- // while inside the region, manipulate the Cell pointer directly
- while( (cx>=0) && (cx<REGIONWIDTH) &&
- (cy>=0) && (cy<REGIONWIDTH) &&
- n > 0 )
- {
- // find the cell at this location, then add it to the vector,
- cells.push_back( c );
-
- // cleverly skip to the next cell (now it's safe to
- // manipulate the cell pointer)
- if( exy < 0 )
- {
- globx += sx;
- exy += by;
- c += sx;
- cx += sx;
- }
- else
- {
- globy += sy;
- exy -= bx;
- c += sy * REGIONWIDTH;
- cy += sy;
- }
- --n;
- }
- }
-}
-
void World::Extend( point3_t pt )
{
extent.x.min = std::min( extent.x.min, pt.x );
Please sign in to comment.
Something went wrong with that request. Please try again.