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 Playerstage-commit@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/playerstage-commit