Revision: 6898
http://playerstage.svn.sourceforge.net/playerstage/?rev=6898&view=rev
Author: alexcb
Date: 2008-07-21 23:21:42 +0000 (Mon, 21 Jul 2008)
Log Message:
-----------
optimized raytracing code
Modified Paths:
--------------
code/stage/trunk/libstage/block.cc
code/stage/trunk/libstage/region.hh
code/stage/trunk/libstage/world.cc
Modified: code/stage/trunk/libstage/block.cc
===================================================================
--- code/stage/trunk/libstage/block.cc 2008-07-21 18:27:33 UTC (rev 6897)
+++ code/stage/trunk/libstage/block.cc 2008-07-21 23:21:42 UTC (rev 6898)
@@ -67,6 +67,7 @@
glPopMatrix();
}
+//TODO FIXME - this is really SLOW
void StgBlock::DrawSides()
{
// construct a strip that wraps around the polygon
Modified: code/stage/trunk/libstage/region.hh
===================================================================
--- code/stage/trunk/libstage/region.hh 2008-07-21 18:27:33 UTC (rev 6897)
+++ code/stage/trunk/libstage/region.hh 2008-07-21 23:21:42 UTC (rev 6898)
@@ -35,8 +35,10 @@
stg_cell_t* GetCell( int32_t x, int32_t y )
{
uint32_t index = x + (y*REGIONWIDTH);
+#ifdef DEBUG
assert( index >=0 );
- assert( index < REGIONSIZE );
+ assert( index < REGIONSIZE );
+#endif
return &cells[index];
}
Modified: code/stage/trunk/libstage/world.cc
===================================================================
--- code/stage/trunk/libstage/world.cc 2008-07-21 18:27:33 UTC (rev 6897)
+++ code/stage/trunk/libstage/world.cc 2008-07-21 23:21:42 UTC (rev 6898)
@@ -448,152 +448,172 @@
stg_raytrace_sample_t* sample,
bool ztest )
{
- // printf( "raytracing at [ %.2f %.2f %.2f %.2f ] for %.2f \n",
-// pose.x,
-// pose.y,
-// pose.z,
-// pose.a,
-// range );
+ // printf( "raytracing at [ %.2f %.2f %.2f %.2f ] for %.2f \n",
+ // pose.x,
+ // pose.y,
+ // pose.z,
+ // pose.a,
+ // range );
+
+ // initialize the sample
+ sample->pose = pose;
+ sample->range = range; // we might change this below
+ sample->block = NULL; // we might change this below
+
+ // find the global integer bitmap address of the ray
+ int32_t x = (int32_t)(pose.x*ppm);
+ int32_t y = (int32_t)(pose.y*ppm);
+ int32_t z = 0;
+
+ int32_t xstart = x;
+ int32_t ystart = y;
+
+ // and the x and y offsets of the ray
+ int32_t dx = (int32_t)(ppm*range * cos(pose.a));
+ int32_t dy = (int32_t)(ppm*range * sin(pose.a));
+ int32_t dz = 0;
+
+ // if( finder->debug )
+ // RecordRay( pose.x,
+ // pose.y,
+ // pose.x + range.max * cos(pose.a),
+ // pose.y + range.max * sin(pose.a) );
+
+ // fast integer line 3d algorithm adapted from Cohen's code from
+ // Graphics Gems IV
+ int n, sx, sy, sz, exy, exz, ezy, ax, ay, az, bx, by, bz;
+ sx = sgn(dx); sy = sgn(dy); sz = sgn(dz);
+ ax = abs(dx); ay = abs(dy); az = abs(dz);
+ bx = 2*ax; by = 2*ay; bz = 2*az;
+ exy = ay-ax; exz = az-ax; ezy = ay-az;
+ n = ax+ay+az;
+
+ // printf( "Raytracing from (%d,%d,%d) steps (%d,%d,%d) %d\n",
+ // x,y,z, dx,dy,dz, n );
+
+ // superregion coords
+ stg_point_int_t lastsup;
+ lastsup.x = INT_MAX; // an unlikely first raytrace
+ lastsup.y = INT_MAX;
+
+ stg_point_int_t lastreg = {0,0};
+ lastsup.x = INT_MAX; // an unlikely first raytrace
+ lastsup.y = INT_MAX;
+
+ SuperRegion* sr = NULL;
+ Region* r = NULL;
+ bool nonempty_region = false;
+
+ //puts( "RAYTRACE" );
+
+ //bitmasks to calculate region, and cell values
+ static int32_t reg_coord_mask = ~ ( ( ~ 0x00 ) << SRBITS ); //this then
needs to be shifted >>
+ static int32_t cell_coord_mask = ~ ( ( ~ 0x00 ) << RBITS );
- // initialize the sample
- sample->pose = pose;
- sample->range = range; // we might change this below
- sample->block = NULL; // we might change this below
-
- // find the global integer bitmap address of the ray
- int32_t x = (int32_t)(pose.x*ppm);
- int32_t y = (int32_t)(pose.y*ppm);
- int32_t z = 0;
-
- int32_t xstart = x;
- int32_t ystart = y;
-
- // and the x and y offsets of the ray
- int32_t dx = (int32_t)(ppm*range * cos(pose.a));
- int32_t dy = (int32_t)(ppm*range * sin(pose.a));
- int32_t dz = 0;
-
- // if( finder->debug )
- // RecordRay( pose.x,
- // pose.y,
- // pose.x + range.max * cos(pose.a),
- // pose.y + range.max * sin(pose.a) );
-
- // fast integer line 3d algorithm adapted from Cohen's code from
- // Graphics Gems IV
- int n, sx, sy, sz, exy, exz, ezy, ax, ay, az, bx, by, bz;
- sx = sgn(dx); sy = sgn(dy); sz = sgn(dz);
- ax = abs(dx); ay = abs(dy); az = abs(dz);
- bx = 2*ax; by = 2*ay; bz = 2*az;
- exy = ay-ax; exz = az-ax; ezy = ay-az;
- n = ax+ay+az;
-
- // printf( "Raytracing from (%d,%d,%d) steps (%d,%d,%d) %d\n",
- // x,y,z, dx,dy,dz, n );
-
- // superregion coords
- stg_point_int_t lastsup;
- lastsup.x = INT_MAX; // an unlikely first raytrace
- lastsup.y = INT_MAX;
-
- stg_point_int_t lastreg = {0,0};
- lastsup.x = INT_MAX; // an unlikely first raytrace
- lastsup.y = INT_MAX;
-
- SuperRegion* sr = NULL;
- Region* r = NULL;
-
- //puts( "RAYTRACE" );
-
- while ( n-- )
+ // superregion coords (must be updated every time x or y changes
+ // but only one variable changes at a time in the loop, so its
+ // more efficient to compute at the end of the loop, when we know
what's changed)
+ stg_point_int_t sup;
+ sup.x = x >> SRBITS;
+ sup.y = y >> SRBITS;
+
+ // find the region coords inside this superregion (again: only updated
when x or y changes)
+ stg_point_int_t reg;
+ reg.x = ( x & reg_coord_mask ) >> RBITS;
+ reg.y = ( y & reg_coord_mask ) >> RBITS;
+
+ // compute the pixel offset inside this region (again: only updated
when x or y changes)
+ stg_point_int_t cell;
+ cell.x = x & cell_coord_mask;
+ cell.y = y & cell_coord_mask;
+
+
+ while ( n-- )
{
- // superregion coords
- stg_point_int_t sup;
- sup.x = x >> SRBITS;
- sup.y = y >> SRBITS;
-
- // printf( "pixel [%d %d]\tS[ %d %d ]\t",
- // x, y, sup.x, sup.y );
+
+ // printf( "pixel [%d %d]\tS[ %d %d ]\t",
+ // x, y, sup.x, sup.y );
- if( ! (sup.x == lastsup.x && sup.y == lastsup.y ))
- {
- sr = (SuperRegion*)g_hash_table_lookup( superregions, (void*)&sup );
- lastsup = sup; // remember these coords
- }
+ if( sr )
+ {
+ // printf( "R[ %d %d ]\t", reg.x, reg.y );
+
+ if( reg.x != lastreg.x || reg.y != lastreg.y )
+ {
+ r = sr->GetRegion( reg.x, reg.y );
+ lastreg = reg;
+ nonempty_region = ( r && r->count );
+ }
+
+ if( nonempty_region )
+ {
+ // printf( "C[ %d %d ]\t", cell.x, cell.y );
+
+ for( GSList* list = r->GetCell( cell.x, cell.y
)->list;
+ list;
+ list = list->next )
+ {
+ StgBlock* block = (StgBlock*)list->data;
+ //assert( block );
+
+ // if this block does not belong to the
searching model and it
+ // matches the predicate and it's in
the right z range
+ if( //block && (block->Model() !=
finder) &&
+ (ztest ? block->IntersectGlobalZ(
pose.z ) : true) &&
+ (*func)( block, mod, arg ) )
+ {
+ // a hit!
+ sample->block = block;
+ sample->range = hypot(
(x-xstart)/ppm, (y-ystart)/ppm );
+ return;
+ }
+ }
+ }
+ }
+
+ // printf( "\t step %d n %d pixel [ %d, %d ] block [ %d
%d ] index [ %d %d ] \n",
+ // //coarse [ %d %d ]\n",
+ // count++, n, x, y, blockx, blocky, b_dx, b_dy );
+
+ // increment our pixel in the correct direction
+ if ( exy < 0 ) {
+ x += sx; exy += by; //exz += bz;
+
+ //update super region
+ sup.x = x >> SRBITS;
+ if( sup.x != lastsup.x ) {
+ sr = (SuperRegion*)g_hash_table_lookup(
superregions, (void*)&sup );
+ lastsup = sup; // remember these coords
+ }
- if( sr )
- {
- // find the region coords inside this superregion
- stg_point_int_t reg;
- reg.x = (x - ( sup.x << SRBITS)) >> RBITS;
- reg.y = (y - ( sup.y << SRBITS)) >> RBITS;
-
- // printf( "R[ %d %d ]\t", reg.x, reg.y );
-
- if( ! (reg.x == lastreg.x && reg.y == lastreg.y ))
- {
- r = sr->GetRegion( reg.x, reg.y );
- lastreg = reg;
- }
-
- if( r && r->count )
- {
- // compute the pixel offset inside this region
- stg_point_int_t cell;
- cell.x = x - ((sup.x << SRBITS) + (reg.x << RBITS));
- cell.y = y - ((sup.y << SRBITS) + (reg.y << RBITS));
-
- // printf( "C[ %d %d ]\t", cell.x, cell.y );
-
- for( GSList* list = r->GetCell( cell.x, cell.y )->list;
- list;
- list = list->next )
- {
- StgBlock* block = (StgBlock*)list->data;
- assert( block );
-
- // if this block does not belong to the searching model and it
- // matches the predicate and it's in the right z range
- if( //block && (block->Model() != finder) &&
- (ztest ? block->IntersectGlobalZ( pose.z ) : true) &&
- (*func)( block, mod, arg ) )
- {
- // a hit!
- sample->block = block;
- sample->range = hypot( (x-xstart)/ppm, (y-ystart)/ppm );
- return;
- }
+ //the next two computations are only needed when sr is
valid;
+ //however, profiling shows it is faster without the
if-branch
+ //recompute region x value - this can be skipped if sr
== NULL, but might be cheaper without the if() cond
+ reg.x = ( x & reg_coord_mask ) >> RBITS;
+
+ //recompute cell x value - can be skipped if sr == NULL
+ cell.x = x & cell_coord_mask;
}
- }
- }
-
- // printf( "\t step %d n %d pixel [ %d, %d ] block [ %d %d ]
index [ %d %d ] \n",
- // //coarse [ %d %d ]\n",
- // count++, n, x, y, blockx, blocky, b_dx, b_dy );
-
- // increment our pixel in the correct direction
- if ( exy < 0 ) {
- if ( exz < 0 ) {
- x += sx; exy += by; exz += bz;
- }
- else {
- z += sz; exz -= bx; ezy += by;
- }
- }
- else {
- if ( ezy < 0 ) {
- z += sz;
- exz -= bx; ezy += by;
- }
- else {
- y += sy; exy -= bx; ezy -= bz;
- }
- }
- // puts("");
+ else {
+ y += sy; exy -= bx; //ezy -= bz;
+ //update super region
+ sup.y = y >> SRBITS;
+ if( sup.y != lastsup.y ) {
+ sr = (SuperRegion*)g_hash_table_lookup(
superregions, (void*)&sup );
+ lastsup = sup; // remember these coords
+ }
+
+ //same deal with profiling - it is faster without the
if() cond
+ //recompute region y value - this can be skipped if sr
== NULL
+ reg.y = ( y & reg_coord_mask ) >> RBITS;
+
+ //recompute cell y value - can be skipped if sr == NULL
+ cell.y = y & cell_coord_mask;
+ }
}
-
- // hit nothing
- return;
+
+ // hit nothing
+ return;
}
static void _save_cb( gpointer key, gpointer data, gpointer user )
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit