touchTest/gestureSDLTest.c
author Jim Grandpre <jim.tla@gmail.com>
Fri, 16 Jul 2010 20:48:43 -0400
changeset 4664 317a151b79ad
parent 4662 3c4e0130c9b1
child 4676 99b4560b7aa1
permissions -rw-r--r--
Bug fixes, now using RWops instead of File pointers.
     1 #include <stdio.h>
     2 #include <SDL.h>
     3 #include <math.h>
     4 #include <SDL_touch.h>
     5 #include <SDL_gesture.h>
     6 
     7 #define PI 3.1415926535897
     8 #define PHI ((sqrt(5)-1)/2)
     9 #define WIDTH 640
    10 #define HEIGHT 480
    11 #define BPP 4
    12 #define DEPTH 32
    13 
    14 #define MAXFINGERS 5
    15 
    16 #define DOLLARNPOINTS 64
    17 #define DOLLARSIZE 256
    18 
    19 //MUST BE A POWER OF 2!
    20 #define EVENT_BUF_SIZE 256
    21 
    22 SDL_Event events[EVENT_BUF_SIZE];
    23 int eventWrite;
    24 
    25 int mousx,mousy;
    26 int keystat[512];
    27 int bstatus;
    28 
    29 int colors[7] = {0xFF,0xFF00,0xFF0000,0xFFFF00,0x00FFFF,0xFF00FF,0xFFFFFF};
    30 
    31 int index2fingerid[MAXFINGERS];
    32 int fingersDown;
    33 
    34 typedef struct {
    35   float x,y;
    36 } Point;
    37 
    38 typedef struct {
    39   Point p;
    40   float pressure;
    41   int id;
    42 } Finger;
    43 
    44 typedef struct {
    45   Finger f;
    46   Point cv;
    47   float dtheta,dDist;
    48 } TouchPoint;
    49 
    50  
    51 typedef struct { //dt + s
    52   Point d,s; //direction, start
    53   int points;
    54 } Line;
    55 
    56 
    57 typedef struct {
    58   float length;
    59   
    60   int numPoints;
    61   Point p[EVENT_BUF_SIZE]; //To be safe
    62 } DollarPath;
    63 
    64 typedef struct {
    65   float ang,r;
    66   Point p;
    67 } Knob;
    68 
    69 Knob knob;
    70 
    71 Finger finger[MAXFINGERS];
    72 
    73 
    74 DollarPath dollarPath[MAXFINGERS];
    75 
    76 #define MAXTEMPLATES 4
    77 
    78 Point dollarTemplate[MAXTEMPLATES][DOLLARNPOINTS];
    79 int numDollarTemplates = 0;
    80 #ifdef DRAW_VECTOR_EST
    81 Line gestureLine[MAXFINGERS];
    82 #endif
    83 
    84 void handler (int sig)
    85 {
    86   printf ("\exiting...(%d)\n", sig);
    87   exit (0);
    88 }
    89 
    90 void perror_exit (char *error)
    91 {
    92   perror (error);
    93   handler (9);
    94 }
    95 
    96 
    97 void setpix(SDL_Surface *screen, int x, int y, unsigned int col)
    98 {
    99   Uint32 *pixmem32;
   100   Uint32 colour;
   101   
   102   if((unsigned)x > screen->w) return;
   103   if((unsigned)y > screen->h) return;
   104 
   105   pixmem32 = (Uint32*) screen->pixels  + y*screen->pitch/BPP + x;
   106   
   107   Uint8 r,g,b;
   108   float a;
   109   
   110   memcpy(&colour,pixmem32,screen->format->BytesPerPixel);
   111 
   112   SDL_GetRGB(colour,screen->format,&r,&g,&b); //Always returns 0xFFFFFF?
   113   //r = 0;g = 0; b = 0;
   114   a = (col>>24)&0xFF;
   115   if(a == 0) a = 0xFF; //Hack, to make things easier.
   116   a /= 0xFF;
   117   r = r*(1-a) + ((col>>16)&0xFF)*(a);
   118   g = g*(1-a) + ((col>> 8)&0xFF)*(a);
   119   b = b*(1-a) + ((col>> 0)&0xFF)*(a);
   120   colour = SDL_MapRGB( screen->format,r, g, b);
   121   
   122 
   123   *pixmem32 = colour;
   124 }
   125 
   126 void drawLine(SDL_Surface *screen,int x0,int y0,int x1,int y1,unsigned int col) {
   127   float t;
   128   for(t=0;t<1;t+=1.f/SDL_max(abs(x0-x1),abs(y0-y1)))
   129     setpix(screen,x1+t*(x0-x1),y1+t*(y0-y1),col);
   130 }
   131 void drawCircle(SDL_Surface* screen,int x,int y,int r,unsigned int c)
   132 {
   133 
   134   float a;
   135   int tx;
   136   
   137   int ty;
   138   float xr;
   139   for(ty = -abs(r);ty <= abs(r);ty++) {
   140     xr = sqrt(r*r - ty*ty);
   141     if(r > 0) { //r > 0 ==> filled circle
   142       for(tx=-xr+.5;tx<=xr-.5;tx++) {
   143 	setpix(screen,x+tx,y+ty,c);
   144       }
   145     }
   146     else {
   147       setpix(screen,x-xr+.5,y+ty,c);
   148       setpix(screen,x+xr-.5,y+ty,c);
   149     }
   150   }
   151 }
   152 
   153 void drawKnob(SDL_Surface* screen,Knob k) {
   154   //printf("Knob: x = %f, y = %f, r = %f, a = %f\n",k.p.x,k.p.y,k.r,k.ang);
   155  
   156   drawCircle(screen,k.p.x*screen->w,k.p.y*screen->h,k.r*screen->w,0xFFFFFF);
   157   
   158   drawCircle(screen,(k.p.x+k.r/2*cos(k.ang))*screen->w,
   159   	            (k.p.y+k.r/2*sin(k.ang))*screen->h,k.r/4*screen->w,0);
   160   
   161 }
   162 
   163 void DrawScreen(SDL_Surface* screen, int h)
   164 {
   165   int x, y, xm,ym,c;
   166   if(SDL_MUSTLOCK(screen))
   167     {                                              
   168       if(SDL_LockSurface(screen) < 0) return;
   169     }
   170   for(y = 0; y < screen->h; y++ )
   171     {
   172       for( x = 0; x < screen->w; x++ )
   173         {
   174 	  //setpixel(screen, x, y, (x*x)/256+3*y+h, (y*y)/256+x+h, h);
   175 	  //xm = (x+h)%screen->w;
   176 	  //ym = (y+h)%screen->w;
   177 	  //c = sin(h/256*2*PI)*x*y/screen->w/screen->h;
   178 	  //setpix(screen,x,y,255*sin(xm/screen->w*2*PI),sin(h/255*2*PI)*255*y/screen->h,c);
   179 	  setpix(screen,x,y,((x%255)<<16) + ((y%255)<<8) + (x+y)%255);
   180 	  //setpix(screen,x,y,0); //Inefficient, but that's okay...
   181         }
   182     }
   183   drawCircle(screen,mousx,mousy,-30,0xFFFFFF);
   184   drawLine(screen,0,0,screen->w,screen->h,0xFFFFFF);
   185 
   186   int i;
   187 //draw Touch History
   188   TouchPoint gestureLast[MAXFINGERS];
   189   //printf("------------------Start History------------------\n");
   190   for(i = 0;i < MAXFINGERS;i++) {
   191     gestureLast[i].f.id = -1;
   192   }
   193   int numDownFingers = 0;
   194   Point centroid;
   195   float gdtheta,gdDist;
   196 
   197 
   198   for(i = SDL_max(0,eventWrite - EVENT_BUF_SIZE);i < eventWrite;i++) {
   199     SDL_Event event = events[i&(EVENT_BUF_SIZE-1)];
   200     int age = eventWrite - i - 1;
   201     if(event.type == SDL_FINGERMOTION || 
   202        event.type == SDL_FINGERDOWN ||
   203        event.type == SDL_FINGERUP) {
   204       SDL_Touch* inTouch = SDL_GetTouch(event.tfinger.touchId);
   205       //SDL_Finger* inFinger = SDL_GetFinger(inTouch,event.tfinger.fingerId);
   206 	    
   207       float x = ((float)event.tfinger.x)/inTouch->xres;
   208       float y = ((float)event.tfinger.y)/inTouch->yres;      
   209       
   210       //draw the touch:
   211       
   212       unsigned int c = colors[event.tfinger.touchId%7]; 
   213       unsigned int col = 
   214 	((unsigned int)(c*(.1+.85))) |
   215 	((unsigned int)((0xFF*(1-((float)age)/EVENT_BUF_SIZE))) & 0xFF)<<24;
   216 
   217       if(event.type == SDL_FINGERMOTION)
   218 	drawCircle(screen,x*screen->w,y*screen->h,5,col);
   219       else if(event.type == SDL_FINGERDOWN)
   220 	drawCircle(screen,x*screen->w,y*screen->h,-10,col);     
   221       /*      
   222       //if there is a centroid, draw it
   223       if(numDownFingers > 1) {
   224 	unsigned int col = 
   225 	  ((unsigned int)(0xFFFFFF)) |
   226 	  ((unsigned int)((0xFF*(1-((float)age)/EVENT_BUF_SIZE))) & 0xFF)<<24;
   227 	drawCircle(screen,centroid.x*screen->w,centroid.y*screen->h,5,col);
   228       }
   229       */
   230     }
   231   }
   232   
   233 
   234   for(i=0;i<MAXFINGERS;i++)
   235     if(finger[i].p.x >= 0 && finger[i].p.y >= 0)
   236       if(finger[i].pressure > 0)
   237 	drawCircle(screen,finger[i].p.x*screen->w,finger[i].p.y*screen->h
   238 		   ,20,0xFF*finger[i].pressure);
   239       else
   240 	drawCircle(screen,finger[i].p.x*screen->w,finger[i].p.y*screen->h
   241 		   ,20,0xFF);
   242 
   243 
   244   
   245   keystat[32] = 0;
   246   
   247   if(knob.p.x > 0)
   248     drawKnob(screen,knob);
   249   
   250   if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen);
   251   
   252   SDL_Flip(screen);
   253 }
   254 
   255 SDL_Surface* initScreen(int width,int height)
   256 {
   257   return SDL_SetVideoMode(width, height, DEPTH,
   258 			  SDL_HWSURFACE | SDL_RESIZABLE);
   259 }
   260 
   261 int main(int argc, char* argv[])
   262 {  
   263   SDL_Surface *screen;
   264   SDL_Event event;
   265   
   266   int keypress = 0;
   267   int h=0,s=1,i,j;
   268 
   269   //gesture variables
   270   int numDownFingers = 0;
   271   float gdtheta = 0,gdDist = 0;
   272   Point centroid;
   273   knob.r = .1;
   274   knob.ang = 0;
   275   TouchPoint gestureLast[MAXFINGERS];
   276   
   277 
   278 
   279   memset(keystat,0,512*sizeof(keystat[0]));
   280   if (SDL_Init(SDL_INIT_VIDEO) < 0 ) return 1;
   281   
   282   if (!(screen = initScreen(WIDTH,HEIGHT)))
   283     {
   284       SDL_Quit();
   285       return 1;
   286     }
   287 
   288   while(!keystat[27]) {
   289     //Poll SDL
   290     while(SDL_PollEvent(&event)) 
   291       {
   292 	//Record _all_ events
   293 	events[eventWrite & (EVENT_BUF_SIZE-1)] = event;
   294 	eventWrite++;
   295 	
   296 	switch (event.type) 
   297 	  {
   298 	  case SDL_QUIT:
   299 	    keystat[27] = 1;
   300 	    break;
   301 	  case SDL_KEYDOWN:
   302 	    //printf("%i\n",event.key.keysym.sym);
   303 	    keystat[event.key.keysym.sym] = 1;
   304 	    if(event.key.keysym.sym == 32) {
   305 	      SDL_RecordGesture(-1);
   306 	    }
   307 	    else if(event.key.keysym.sym == 115) {
   308 	      SDL_RWops *src;
   309 	      //fp = fopen("gestureSave","w");
   310 	      src = SDL_RWFromFile("gestureSave","w");
   311 	      
   312 	      printf("Wrote %i templates\n",SDL_SaveAllDollarTemplates(src));
   313 	      //fclose(fp);
   314 	      SDL_RWclose(src);
   315 	    }
   316 	    else if(event.key.keysym.sym == 108) {
   317 	      SDL_RWops *src;
   318 	      //fp = fopen("gestureSave","r");
   319 	      src = SDL_RWFromFile("gestureSave","r");
   320 	      printf("Loaded: %i\n",SDL_LoadDollarTemplates(-1,src));
   321 	      //fclose(fp);
   322 	      SDL_RWclose(src);
   323 	    }
   324 	    
   325 	    //keypress = 1;
   326 	    break;
   327 	  case SDL_KEYUP:
   328 	      //printf("%i\n",event.key.keysym.sym);
   329 	    keystat[event.key.keysym.sym] = 0;
   330 	    //keypress = 1;
   331 	    break;
   332 	  case SDL_VIDEORESIZE:
   333 	    if (!(screen = initScreen(event.resize.w,
   334 				      event.resize.h)))
   335 	      {
   336 		SDL_Quit();
   337 		return 1;
   338 	      }
   339 	    break;
   340 	  case SDL_MOUSEMOTION:
   341 	    mousx = event.motion.x;
   342 	    mousy = event.motion.y; 
   343 	    break;
   344 	  case SDL_MOUSEBUTTONDOWN:
   345 	    bstatus |=  (1<<(event.button.button-1));
   346 	    break;
   347 	  case SDL_MOUSEBUTTONUP:
   348 	    bstatus &= ~(1<<(event.button.button-1));
   349 	    break;
   350 	  case SDL_FINGERMOTION:    
   351 	    ;
   352 	    //printf("Finger: %i,x: %i, y: %i\n",event.tfinger.fingerId,
   353 	    //	   event.tfinger.x,event.tfinger.y);
   354 	    SDL_Touch* inTouch = SDL_GetTouch(event.tfinger.touchId);
   355 	    SDL_Finger* inFinger = SDL_GetFinger(inTouch,event.tfinger.fingerId);
   356 
   357 	    for(i = 0;i<MAXFINGERS;i++) 
   358 	      if(index2fingerid[i] == event.tfinger.fingerId) 	      
   359 		break;
   360 	    if(i == MAXFINGERS) break;  
   361 	    if(inTouch > 0) {
   362 	      finger[i].p.x = ((float)event.tfinger.x)/
   363 		inTouch->xres;
   364 	      finger[i].p.y = ((float)event.tfinger.y)/
   365 		inTouch->yres;
   366 	      
   367 	      finger[i].pressure = 
   368 		((float)event.tfinger.pressure)/inTouch->pressureres;
   369 	      /*
   370 	      printf("Finger: %i, Pressure: %f Pressureres: %i\n",
   371 		     event.tfinger.fingerId,
   372 		     finger[i].pressure,
   373 		     inTouch->pressureres);
   374 	      */
   375 	      //printf("Finger: %i, pressure: %f\n",event.tfinger.fingerId,
   376 	      //   finger[event.tfinger.fingerId].pressure);
   377 	    }
   378 	    
   379 	    break;	    
   380 	  case SDL_FINGERDOWN:
   381 	    printf("Finger: %i down - x: %i, y: %i\n",event.tfinger.fingerId,
   382 		   event.tfinger.x,event.tfinger.y);
   383 
   384 	    for(i = 0;i<MAXFINGERS;i++) 
   385 	      if(index2fingerid[i] == -1) {
   386 		index2fingerid[i] = event.tfinger.fingerId;
   387 		break;
   388 	      }
   389 	    finger[i].p.x = event.tfinger.x;
   390 	    finger[i].p.y = event.tfinger.y;
   391 	    break;
   392 	  case SDL_FINGERUP:
   393 	    printf("Figner: %i up - x: %i, y: %i\n",event.tfinger.fingerId,
   394 	           event.tfinger.x,event.tfinger.y);
   395 	    for(i = 0;i<MAXFINGERS;i++) 
   396 	      if(index2fingerid[i] == event.tfinger.fingerId) {
   397 		index2fingerid[i] = -1;
   398 		break;
   399 	      }
   400 	    finger[i].p.x = -1;
   401 	    finger[i].p.y = -1;
   402 	    break;
   403 	  case SDL_MULTIGESTURE:
   404 	    knob.p.x = event.mgesture.x;
   405 	    knob.p.y = event.mgesture.y;
   406 	    knob.ang += event.mgesture.dTheta;
   407 	    knob.r += event.mgesture.dDist;
   408 	    break;
   409 	  case SDL_DOLLARGESTURE:
   410 	    printf("Gesture %lu performed, error: %f\n",
   411 		   event.dgesture.gestureId,
   412 		   event.dgesture.error);
   413 	    break;
   414 	  case SDL_DOLLARRECORD:
   415 	    printf("Recorded gesture: %lu\n",event.dgesture.gestureId);
   416 	    break;
   417 	  }
   418       }
   419     DrawScreen(screen,h);    
   420     for(i = 0; i < 256; i++) 
   421       if(keystat[i]) 
   422 	printf("Key %i down\n",i);
   423   }  
   424   SDL_Quit();
   425   
   426   return 0;
   427 }
   428