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