Update of /cvsroot/playerstage/code/stage/libstage
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16063

Added Files:
      Tag: opengl
        .cvsignore stage.cc 
Log Message:
added missing files

--- NEW FILE: .cvsignore ---
Makefile
Makefile.in
stest
ptest
.DS_Store

--- NEW FILE: stage.cc ---
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <assert.h>
#include <unistd.h>
#include <math.h>
#include <glib.h>
#include <locale.h>

#include <gdk-pixbuf/gdk-pixbuf.h>

//#define DEBUG

#include "stage.hh"
#include "config.h" // results of autoconf's system configuration tests

GHashTable* global_typetable = NULL;
GHashTable* stg_create_typetable( void );

//const char* stg_version

const char* stg_package_string( void )
{
  return PACKAGE_STRING;
}

const char* stg_version_string( void )
{
  return VERSION;
}

void stg_print_err( const char* err )
{
  printf( "Stage error: %s\n", err );
  //_stg_quit = TRUE;
}


/** Visit every voxel along a vector from (x,y,z) to (x+dx, y+dy, z+dz).
    Call the function for every voxel, passing in the current voxel
    coordinates followed by the two arguments. Adapted from Graphics
    Gems IV, algorithm by Cohen & Kaufman 1991 */
int stg_line_3d( int32_t x, int32_t y, int32_t z,
                 int32_t dx, int32_t dy, int32_t dz,
                 stg_line3d_func_t visit_voxel,
                 void* arg )
{
  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;
  while ( n-- ) {
    if((*visit_voxel)( x, y, z, arg ) )
      {
        return TRUE; // hit something!
      }

    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;
      }
    }
  }

  return FALSE; // hit nothing (leave vars not set)
}

int stg_polygon_3d( stg_point_int_t* pts, unsigned int pt_count,
                    stg_line3d_func_t visit_voxel,
                    void* arg )
{
  assert( pts );
  
  for( unsigned int p=0; p<pt_count; p++ )
    {
      int32_t x = pts[p].x; 
      int32_t y = pts[p].y; 
      
      int32_t dx = pts[(p+1)%pt_count].x - x;
      int32_t dy = pts[(p+1)%pt_count].y - y;
      
      if( stg_line_3d( x, y, 0,
                       dx, dy, 0,
                       visit_voxel, arg ) )
        return TRUE;
    }
  return FALSE;
}

void stg_print_geom( stg_geom_t* geom )
{
  printf( "geom pose: (%.2f,%.2f,%.2f) size: [%.2f,%.2f]\n",
          geom->pose.x,
          geom->pose.y,
          geom->pose.a,
          geom->size.x,
          geom->size.y );
}


void stg_print_pose( stg_pose_t* pose )
{
  printf( "pose [x:%.3f y:%.3f a:%.3f]\n",
          pose->x, pose->y, pose->a );
}

void stg_print_velocity( stg_velocity_t* vel )
{
  printf( "velocity [x:%.3f y:%.3f a:%.3f]\n",
          vel->x, vel->y, vel->a );
}

stg_msec_t stg_realtime( void )
{
  struct timeval tv;
  gettimeofday( &tv, NULL );  
  stg_msec_t timenow = (stg_msec_t)( tv.tv_sec*1e3 + tv.tv_usec/1e3 );
  return timenow;
}

stg_msec_t stg_realtime_since_start( void )
{
  static stg_msec_t starttime = 0;  
  stg_msec_t timenow = stg_realtime();
  
  if( starttime == 0 )
    starttime = timenow;
    
  return( timenow - starttime );
}


// Look up the color in a database.  (i.e. transform color name to
// color value).  If the color is not found in the database, a bright
// red color will be returned instead.
stg_color_t stg_lookup_color(const char *name)
{
  if( name == NULL ) // no string?
    return 0; // black
  
  if( strcmp( name, "" ) == 0 ) // empty string?
    return 0; // black
  
  static FILE *file = NULL;
  static GHashTable* table = g_hash_table_new( g_str_hash, g_str_equal );
  
  if( file == NULL )
    {
      char* searchfiles[] = {
        "./rgb.txt",
#ifdef RGBFILE
        RGBFILE,
#endif
        "../rgb.txt",
        NULL };
      
      for( int i=0;
           searchfiles[i];
           i++ )
        {
          char* filename = searchfiles[i];
          PRINT_DEBUG1( "Attempting to open \"%s\"", filename );
          if( (file = fopen( filename, "r")) )
            break; // opened a file ok - jump out of for loop
        }
      
      if( file == NULL )
        {
          
          PRINT_ERR1("unable to open color database: %s",
                     strerror(errno));
          fclose(file);
          exit(0);
        }
      
      PRINT_DEBUG( "Success!" );

      // load the file into the hash table       
      while (TRUE)
        {
          char line[1024];
          if (!fgets(line, sizeof(line), file))
            break;
          
          // it's a macro or comment line - ignore the line
          if (line[0] == '!' || line[0] == '#' || line[0] == '%') 
            continue;

          // Trim the trailing space
          while (strchr(" \t\n", line[strlen(line)-1]))
            line[strlen(line)-1] = 0;
          
          // Read the color
          int r, g, b;
          int chars_matched = 0;
          sscanf( line, "%d %d %d %n", &r, &g, &b, &chars_matched );
          
          stg_color_t col = ( 0xFF000000 | (r << 16) | (g << 8) | b);

          // Read the name
          char* colorname = strdup( line + chars_matched );
          
          // map the name to the color in the table
          g_hash_table_insert( table, (gpointer)colorname, (gpointer)col );
          
        }

      fclose(file);
    }

  // look up the colorname in the database  
  return (stg_color_t)g_hash_table_lookup( table, name );
}

//////////////////////////////////////////////////////////////////////////
// scale an array of rectangles so they fit in a unit square
void stg_rotrects_normalize( stg_rotrect_t* rects, int num )
{
  // assuming the rectangles fit in a square +/- one billion units
  double minx, miny, maxx, maxy;
  minx = miny = BILLION;
  maxx = maxy = -BILLION;
  
  int r;
  for( r=0; r<num; r++ )
    {
      // test the origin of the rect
      if( rects[r].pose.x < minx ) minx = rects[r].pose.x;
      if( rects[r].pose.y < miny ) miny = rects[r].pose.y;      
      if( rects[r].pose.x > maxx ) maxx = rects[r].pose.x;      
      if( rects[r].pose.y > maxy ) maxy = rects[r].pose.y;

      // test the extremes of the rect
      if( (rects[r].pose.x+rects[r].size.x)  < minx ) 
        minx = (rects[r].pose.x+rects[r].size.x);
      
      if( (rects[r].pose.y+rects[r].size.y)  < miny ) 
        miny = (rects[r].pose.y+rects[r].size.y);
      
      if( (rects[r].pose.x+rects[r].size.x)  > maxx ) 
        maxx = (rects[r].pose.x+rects[r].size.x);
      
      if( (rects[r].pose.y+rects[r].size.y)  > maxy ) 
        maxy = (rects[r].pose.y+rects[r].size.y);
    }
  
  // now normalize all lengths so that the rects all fit inside
  // rectangle from 0,0 to 1,1
  double scalex = maxx - minx;
  double scaley = maxy - miny;

  for( r=0; r<num; r++ )
    { 
      rects[r].pose.x = (rects[r].pose.x - minx) / scalex;
      rects[r].pose.y = (rects[r].pose.y - miny) / scaley;
      rects[r].size.x = rects[r].size.x / scalex;
      rects[r].size.y = rects[r].size.y / scaley;
    }
}       

// sets [result] to the pose of [p2] in [p1]'s coordinate system
void stg_pose_sum( stg_pose_t* result, stg_pose_t* p1, stg_pose_t* p2 )
{
  double cosa = cos(p1->a);
  double sina = sin(p1->a);
  
  result->x = p1->x + p2->x * cosa - p2->y * sina;
  result->y = p1->y + p2->x * sina + p2->y * cosa;
  result->z = p1->z + p2->z;
  result->a = NORMALIZE(p1->a + p2->a);

  //  printf( "pose z %.2f\n", result->z );
}


// pb_* functions are only used inside this file

static guchar* pb_get_pixel( GdkPixbuf* pb, int x, int y )
{
  guchar* pixels = gdk_pixbuf_get_pixels(pb);
  int rs = gdk_pixbuf_get_rowstride(pb);
  int ch = gdk_pixbuf_get_n_channels(pb);
  return( pixels + y * rs + x * ch );
}

// static void pb_set_pixel( GdkPixbuf* pb, int x, int y, uint8_t val )
// {
//   // bounds checking
//   int width = gdk_pixbuf_get_width(pb);
//   int height = gdk_pixbuf_get_height(pb);
//   if( x >=0 && x < width && y >= 0 && y < height )
//     {
//       // zeroing
//       guchar* pix = pb_get_pixel( pb, x, y );
//       int bytes_per_sample = gdk_pixbuf_get_bits_per_sample (pb) / 8;
//       int num_samples = gdk_pixbuf_get_n_channels(pb);
//       memset( pix, val, num_samples * bytes_per_sample );
//     }
//   else
//     PRINT_WARN4( "pb_set_pixel coordinate %d,%d out of range (image 
dimensions %d by %d)", x, y, width, height );
// }

// set all the pixels in a rectangle 
static void pb_set_rect( GdkPixbuf* pb, int x, int y, int width, int height, 
uint8_t val )
{
  int bytes_per_sample = gdk_pixbuf_get_bits_per_sample (pb) / 8;
  int num_samples = gdk_pixbuf_get_n_channels(pb);

  int a, b;
  for( a = y; a < y+height; a++ )
    for( b = x; b < x+width; b++ )
      { 
        // zeroing
        guchar* pix = pb_get_pixel( pb, b, a );
        memset( pix, val, num_samples * bytes_per_sample );
      }
}  

// returns TRUE if any channel in the pixel is non-zero
static gboolean pb_pixel_is_set( GdkPixbuf* pb, int x, int y, int threshold )
{
  guchar* pixel = pb_get_pixel( pb,x,y );
  //int channels = gdk_pixbuf_get_n_channels(pb);
  //int i;
  //for( i=0; i<channels; i++ )
  //if( pixel[i] ) return TRUE;
  if( pixel[0] > threshold ) return TRUE; // just use the red channel for now

  return FALSE;
}




int stg_rotrects_from_image_file( const char* filename, 
                                         stg_rotrect_t** rects, 
                                         unsigned int* rect_count,
                                         unsigned int* widthp, 
                                         unsigned int* heightp )
{
  // TODO: make this a parameter
  const int threshold = 127;

  GError* err = NULL;
  GdkPixbuf* pb = gdk_pixbuf_new_from_file( filename, &err );

  if( err )
    {
      fprintf( stderr, "\nError loading bitmap: %s\n", err->message );
      return 1; // error
    }
  
  // this should be ok as no error was reported
  assert( pb );
  
  
#ifdef DEBUG
  printf( "debug: Loaded image \"%s\" \n\tchannels:%d bits:%d alpha:%d "
          "width:%d height:%d rowstride:%d pixels:%p (%s %s)\n",          
          filename,
          gdk_pixbuf_get_n_channels(pb),
          gdk_pixbuf_get_bits_per_sample(pb),
          gdk_pixbuf_get_has_alpha(pb),       
          gdk_pixbuf_get_width(pb),
          gdk_pixbuf_get_height(pb),
          gdk_pixbuf_get_rowstride(pb),
          gdk_pixbuf_get_pixels(pb),
          __FILE__, __FUNCTION__ );
#endif

  
  *rect_count = 0;
  size_t allocation_unit = 1000;
  size_t rects_allocated = allocation_unit;
  *rects = (stg_rotrect_t*)g_new( stg_rotrect_t, rects_allocated );
  
  int img_width = gdk_pixbuf_get_width(pb);
  int img_height = gdk_pixbuf_get_height(pb);
  
  // if the caller wanted to know the dimensions
  if( widthp ) *widthp = img_width;
  if( heightp ) *heightp = img_height;
  
  int y, x;
  for(y = 0; y < img_height; y++)
    {
      for(x = 0; x < img_width; x++)
        {
          // skip blank (white) pixels
          if(  pb_pixel_is_set( pb,x,y, threshold) )
            continue;
          
          // a rectangle starts from this point
          int startx = x;
          int starty = y;
          int height = img_height; // assume full height for starters
          
          // grow the width - scan along the line until we hit an empty (white) 
pixel
          for( ; x < img_width &&  ! pb_pixel_is_set(pb,x,y,threshold); x++ )
            {
              // handle horizontal cropping
              //double ppx = x * sx; 
              //if (ppx < this->crop_ax || ppx > this->crop_bx)
              //continue;
              
              // look down to see how large a rectangle below we can make
              int yy  = y;
              while( ! pb_pixel_is_set(pb,x,yy,threshold) && (yy < 
img_height-1) )
                { 
                  // handle vertical cropping
                  //double ppy = (this->image->height - yy) * sy;
                  //if (ppy < this->crop_ay || ppy > this->crop_by)
                  //continue;
                  
                  yy++; 
                }             

              // now yy is the depth of a line of non-zero pixels
              // downward we store the smallest depth - that'll be the
              // height of the rectangle
              if( yy-y < height ) height = yy-y; // shrink the height to fit
            } 
          
          // whiten the pixels we have used in this rect
          pb_set_rect( pb, startx, starty, x-startx, height, 0xFF );
          
          // add this rectangle to the array
          (*rect_count)++;
          
          if( (*rect_count) > rects_allocated )
            {
              rects_allocated = (*rect_count) + allocation_unit;
              
              *rects = (stg_rotrect_t*)
                realloc( *rects, rects_allocated * sizeof(stg_rotrect_t) );
            }

          //  y-invert all the rectangles because we're using conventional
          // rather than graphics coordinates. this is much faster than
          // inverting the original image.
          stg_rotrect_t *latest = &(*rects)[(*rect_count)-1];
          latest->pose.x = startx;
          latest->pose.y = img_height - (starty + height);
          latest->pose.a = 0.0;
          latest->size.x = x - startx;
          latest->size.y = height;
          
          //printf( "rect %d (%.2f %.2f %.2f %.2f %.2f\n", 
          //  *rect_count, 
          //  latest->x, latest->y, latest->a, latest->w, latest->h ); 
          
        }
    }
  
  // free the image data
  gdk_pixbuf_unref( pb );
  return 0; // ok
}

void print_pointer( void* p, char* separator )
{
  printf( "%p%s", p, separator) ;
}


// POINTS -----------------------------------------------------------

stg_point_t* stg_points_create( size_t count )
{
  return( (stg_point_t*)g_new( stg_point_t, count ));
}

void stg_points_destroy( stg_point_t* pts )
{
  g_free( pts );
}


stg_point_t* stg_unit_square_points_create( void )
{
  stg_point_t * pts = stg_points_create( 4 );
  
  pts[0].x = 0;
  pts[0].y = 0;
  pts[1].x = 1;
  pts[1].y = 0;
  pts[2].x = 1;
  pts[2].y = 1;
  pts[3].x = 0;
  pts[3].y = 1;  
  
  return pts;
}


// CALLBACKS -------------------------------------------------------

stg_cb_t* cb_create( stg_model_callback_t callback, void* arg )
{
  stg_cb_t* cb = (stg_cb_t*)g_new( stg_cb_t, 1 );
  cb->callback = callback;
  cb->arg = arg;
  return cb;
}

void cb_destroy( stg_cb_t* cb )
{
  free( cb );
}

// return a value based on val, but limited minval <= val >= maxval  
double constrain( double val, double minval, double maxval )
{
  if( val < minval )
    return minval;

  if( val > maxval )
    return maxval;
  
  return val;
}


stg_color_t stg_color_pack( double r, double g, double b, double a )
{
  stg_color_t col=0;
  col += (stg_color_t)((1.0-a)*256.0)<<24;
  col += (stg_color_t)(r*256.0)<<16;
  col += (stg_color_t)(g*256.0)<<8;
  col += (stg_color_t)(b*256.0);

  return col;
}

void stg_color_unpack( stg_color_t col, 
                       double* r, double* g, double* b, double* a )
{
  if(a) *a = 1.0 - (((col & 0xFF000000) >> 24) / 256.0);
  if(r) *r = ((col & 0x00FF0000) >> 16) / 256.0;
  if(g) *g = ((col & 0x0000FF00) >> 8)  / 256.0;
  if(b) *b = ((col & 0x000000FF) >> 0)  / 256.0;
}




-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit

Reply via email to