Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 0f72ec239f
Fetching contributors…

Cannot retrieve contributors at this time

384 lines (313 sloc) 9.859 kb
/*
region.cc
data structures supporting multi-resolution ray tracing in world class.
Copyright Richard Vaughan 2008
*/
#include <pthread.h>
#include "region.hh"
using namespace Stg;
Stg::Region::Region() :
cells(),
count(0),
superregion(NULL)
{
}
Stg::Region::~Region()
{
}
void Stg::Region::AddBlock()
{
++count;
assert(count>0);
superregion->AddBlock();
}
void Stg::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 )
cells.clear();
}
SuperRegion::SuperRegion( World* world, point_int_t origin )
: count(0),
origin(origin),
regions(),
world(world)
{
for( int32_t c=0; c<SUPERREGIONSIZE;++c)
regions[c].superregion = this;
}
SuperRegion::~SuperRegion()
{
}
void SuperRegion::AddBlock()
{
++count;
assert(count>0);
}
void SuperRegion::RemoveBlock()
{
--count;
assert(count>=0);
}
void SuperRegion::DrawOccupancy(void) const
{
//printf( "SR origin (%d,%d) this %p\n", origin.x, origin.y, this );
glPushMatrix();
GLfloat scale = 1.0/world->Resolution();
glScalef( scale, scale, 1.0 ); // XX TODO - this seems slightly
glTranslatef( origin.x<<SRBITS, origin.y<<SRBITS,0);
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
// outline superregion
glColor3f( 0,0,1 );
glRecti( 0,0, 1<<SRBITS, 1<<SRBITS );
// outline regions
if( regions )
{
const Region* r = &regions[0];
std::vector<GLfloat> rects(1000);
for( int y=0; y<SUPERREGIONWIDTH; ++y )
for( int x=0; x<SUPERREGIONWIDTH; ++x )
{
if( r->count ) // region contains some occupied cells
{
// outline the region
glColor3f(0,1,0);
glRecti( x<<RBITS, y<<RBITS,
(x+1)<<RBITS, (y+1)<<RBITS );
// show how many cells are occupied
//snprintf( buf, 15, "%lu", r->count );
//Gl::draw_string( x<<RBITS, y<<RBITS, 0, buf );
// draw a rectangle around each occupied cell
for( int p=0; p<REGIONWIDTH; ++p )
for( int q=0; q<REGIONWIDTH; ++q )
{
const Cell& c = r->cells[p+(q*REGIONWIDTH)];
if( c.blocks[0].size() ) // layer 0
{
const GLfloat xx = p+(x<<RBITS);
const GLfloat yy = q+(y<<RBITS);
rects.push_back( xx );
rects.push_back( yy );
rects.push_back( xx+1 );
rects.push_back( yy );
rects.push_back( xx+1 );
rects.push_back( yy+1 );
rects.push_back( xx );
rects.push_back( yy+1 );
}
if( c.blocks[1].size() ) // layer 1
{
const GLfloat xx = p+(x<<RBITS);
const GLfloat yy = q+(y<<RBITS);
const double dx = 0.1;
rects.push_back( xx+dx );
rects.push_back( yy+dx );
rects.push_back( xx+1-dx );
rects.push_back( yy+dx );
rects.push_back( xx+1-dx );
rects.push_back( yy+1-dx );
rects.push_back( xx+dx );
rects.push_back( yy+1-dx );
}
}
}
++r; // next region quickly
}
if( rects.size() )
{
assert( rects.size() % 8 == 0 ); // should be full of squares
glVertexPointer( 2, GL_FLOAT, 0, &rects[0] );
glDrawArrays( GL_QUADS, 0, rects.size()/2 );
}
}
else
{ // outline region-collected superregion
glColor3f( 1,1,0 );
glRecti( 0,0, (1<<SRBITS)-1, (1<<SRBITS)-1 );
glColor3f( 0,0,1 );
}
// char buf[32];
// snprintf( buf, 15, "%lu", count );
// Gl::draw_string( 1<<SBITS, 1<<SBITS, 0, buf );
glPopMatrix();
}
static inline const std::vector<GLfloat> DrawBlock( GLfloat x, GLfloat y, GLfloat zmin, GLfloat zmax )
{
std::vector<GLfloat> v(60);
// TOP
v[0]=x; v[1]=y; v[2]=zmax;
v[3]=1+x; v[4]=y; v[5]=zmax;
v[6]=1+x; v[7]=1+y; v[8]=zmax;
v[9]=x; v[10]=1+y; v[11]=zmax;
// sides
v[12]=x; v[13]=y; v[14]=zmax;
v[15]=x; v[16]=1+y; v[17]=zmax;
v[18]=x; v[19]=1+y; v[20]=zmin;
v[21]=x; v[22]=y; v[23]=zmin;
v[24]=1+x; v[25]=y; v[26]=zmax;
v[27]=x; v[28]=y; v[29]=zmax;
v[30]=x; v[31]=y; v[32]=zmin;
v[33]=1+x; v[34]=y; v[35]=zmin;
v[36]=1+x; v[37]=1+y; v[38]=zmax;
v[39]=1+x; v[40]=y; v[41]=zmax;
v[42]=1+x; v[43]=y; v[44]=zmin;
v[45]=1+x; v[46]=1+y; v[47]=zmin;
v[48]=x; v[49]=1+y; v[50]=zmax;
v[51]=1+x; v[52]=1+y; v[53]=zmax;
v[54]=1+x; v[55]=1+y; v[56]=zmin;
v[57]=x; v[58]=1+y; v[59]=zmin;
return v;
}
void SuperRegion::DrawVoxels(unsigned int layer) const
{
glPushMatrix();
GLfloat scale = 1.0/world->Resolution();
glScalef( scale, scale, 1.0 ); // XX TODO - this seems slightly
glTranslatef( origin.x<<SRBITS, origin.y<<SRBITS,0);
glEnable( GL_DEPTH_TEST );
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
std::vector<GLfloat> verts(1000);
std::vector<GLfloat> colors(1000);
const Region* r = &regions[0];
for( int y=0; y<SUPERREGIONWIDTH; ++y )
for( int x=0; x<SUPERREGIONWIDTH; ++x )
{
if( r->count ) // not an empty region
for( int p=0; p<REGIONWIDTH; ++p )
for( int q=0; q<REGIONWIDTH; ++q )
{
const std::vector<Block*>& blocks =
r->cells[p+(q*REGIONWIDTH)].blocks[layer];
if( blocks.size() ) // not an empty cell
{
const GLfloat xx(p+(x<<RBITS));
const GLfloat yy(q+(y<<RBITS));
FOR_EACH( it, blocks )
{
Block* block = *it;
Color c = block->group->mod.GetColor();
const std::vector<GLfloat> v = DrawBlock( xx, yy, block->global_z.min, block->global_z.max );
verts.insert( verts.end(), v.begin(), v.end() );
for( unsigned int i=0; i<20; i++ )
{
colors.push_back( c.r );
colors.push_back( c.g );
colors.push_back( c.b );
}
}
}
}
++r;
}
if( verts.size() )
{
assert( verts.size() % 60 == 0 ); // should be full of blocks, each with 20 3D vertices
glEnableClientState( GL_COLOR_ARRAY );
glVertexPointer( 3, GL_FLOAT, 0, &verts[0] );
glColorPointer( 3, GL_FLOAT, 0, &colors[0] );
glDrawArrays( GL_QUADS, 0, verts.size()/3 );
glDisableClientState( GL_COLOR_ARRAY );
}
glPopMatrix();
}
void Stg::Cell::AddBlock( Block* b, unsigned int layer )
{
assert( b );
assert( layer < 2 );
// printf( "cell %p add block %p vec %u\n", this, b, (unsigned int)blocks[layer].size() );
// printf( " before " );
// for( size_t i=0; i<CELLBLOCKRECORD_COUNT; i++ )
// printf("(%p,%d)",
// cbrecords[layer][i].block,
// //cbrecords[layer][i].block->group->mod.Token() : "NULL",
// (int)cbrecords[layer][i].used );
// puts("");
// CellBlockRecord* cbr = &cbrecords[layer][0];
// while( cbr->used ) ++cbr;
// // bounds check
// assert( &cbrecords[layer][0] - cbr < CELLBLOCKRECORD_COUNT * sizeof(CellBlockRecord*));
// // cbr now points to an unused record
// cbr->block = b;
// cbr->used = true;
// printf( " after " );
// for( size_t i=0; i<CELLBLOCKRECORD_COUNT; i++ )
// printf("(%p,%d)",
// cbrecords[layer][i].block,// ?
// // cbrecords[layer][i].block->group->mod.Token() : "NULL",
// (int)cbrecords[layer][i].used );
// puts("");
blocks[layer].push_back( b );
b->rendered_cells[layer].push_back(this);
region->AddBlock();
}
void Stg::Cell::RemoveBlock( Block* b, unsigned int layer )
{
assert( b );
assert( layer < 2 );
// printf( "cell %p remove block %p vec %u\n", this, b, (unsigned int)blocks[layer].size() );
// printf( " before " );
// for( size_t i=0; i<CELLBLOCKRECORD_COUNT; i++ )
// printf("(%p,%d)",
// cbrecords[layer][i].block,
// //cbrecords[layer][i].block->group->mod.Token() : "NULL",
// (int)cbrecords[layer][i].used );
// puts("");
// // zip along the cbrecords array until we find block b
// CellBlockRecord* cbr = &cbrecords[layer][0];
// while( cbr->block != b ) ++cbr;
// // found check
// assert( cbr->block == b );
// // bounds check
// assert( &cbrecords[layer][0] - cbr < CELLBLOCKRECORD_COUNT * sizeof(CellBlockRecord*));
// // cbr now points to the record for block b: invalidate the record
// assert( cbr->block == b );
// // mark the cbr as available for reuse
// cbr->used = false;
// printf( " after " );
// for( size_t i=0; i<CELLBLOCKRECORD_COUNT; i++ )
// printf("(%p,%d)",
// cbrecords[layer][i].block,// ?
// // cbrecords[layer][i].block->group->mod.Token() : "NULL",
// (int)cbrecords[layer][i].used );
// puts("");
std::vector<Block*>& blks( blocks[layer] );
const size_t len( blks.size() );
if( len )
{
#if 0
// Use conventional STL style
// this special-case test is faster for worlds with simple models,
// which are the ones we want to be really fast. It's a small
// extra cost for worlds with several models in each cell. It
// gives a 5% overall speed increase in fasr.world.
if( (blks.size() == 1) &&
(blks[0] == b) ) // special but common case
{
blks.clear(); // cheap
}
else // the general but relatively expensive case
{
EraseAll( b, blks );
}
#else
// attempt faster removal loop
// O(n) * low constant array element removal
// this C-style pointer work looks to be very slightly faster than the STL way
Block **start = &blks[0]; // start of array
Block **r = &blks[0]; // read from here
Block **w = &blks[0]; // write to here
while( r < start + len ) // scan down array, skipping 'this'
{
if( *r != b )
*w++ = *r;
++r;
}
blks.resize( w-start );
#endif
}
region->RemoveBlock();
}
Jump to Line
Something went wrong with that request. Please try again.