/* -------------------------------------------------------------
 * Designed by: Dr. Peter Hor-Ching Wang
 * Date: Sep. 10, 1995
 * Purpose: Attach VPL Dataglove to ching virtual reality system
 * Notes: This is a VR system based on sense8 WorldToolKit and
 *        DataGlove driver from Dr. Tomohiro Kuroda
 * ------------------------------------------------------------- */
#include "hand.c"
#include "handfont.c"
#include "datag.c"
/*
 * onlyhand.c:  attach DataGlove in com1 to hand object and move it
 *
 * (C) Tomohiro Kuroda June 1995
 */

/*
#define COM2 "/dev/ttyd2"
#define COM1 "/dev/ttyd1"
*/
/******* Port number *********/
#define GLOVEPORT COM1
#define BALLPORT  COM2
/******* Include Headers *******/

#include "wt.h"         /* Standard WTK header files */
#include "DataG.h"      /* Data Glove controlling functions */
#include "hand.h"       /* Hand object creating & dealing functions */

#define RIGHT   TRUE    /* TRUE in right hand */

/******* Global variables *******/
WTsensor        *mouse  = NULL;         /* a handle on the mouse */
WTviewpoint     *uview;                 /* universe's viewpoint */
WTsensor        *glove  = NULL;         /* Data Glove object */
WTsensor        *headpolh   = NULL;         /* Polhemous Fastrak */
WTsensor        *polh   = NULL;         /* Polhemous Fastrak */
WTsensor        *ball   = NULL;         /* Spaceball */

WtGloveHand     *hand;                  /* Hand object */

WTpq            InitialView;            /* Intiaial view point */


WTpq            InitialHand;            /* Initial hand position */

WTp3            light_pos = { 1200, -800, -1000 };      /* light position */
WTp3            light_dir = { -.68, .48, .58 };         /* light direction */

int             gb_calib_step = 0;      /* Calibration step of data glove
                                         * 0 : not in the calibration
                                         * 1 : calibrate fist
                                         * 2 : calibrate parm
                                         */

void LoadObjects (char *directory);
void LoadObjectsFile (char *directory);
void LoadUniverse (char *filename, float scale);
char fname[80];
/******* prototypes *******/
void actions(void);
void handle_key(int key);
void toggle_object(WTobject *obj);
void reset_view(void);
void reset_hand(void);
void rotate_fastrak(WTsensor *sensor);
void handle_spaceball(void);


/*************************/
/******* functions *******/
/*************************/

/******* main *******/
WTserial   *serial;
WTserial *WTserial_new();
int main(int argc, char *argv[])
{

  printf("WorldToolKit Data Glove simple demo\n");
  printf("Copyright 1995 Tomohiro Kuroda\n\n");
  
  printf ("Creating new universe\n");
  WTuniverse_new(WTDISPLAY_DEFAULT, WTWINDOW_DEFAULT);
  uview = WTuniverse_getviewpoint();
  
  WTlight_setambient(0.02);
  WTlight_new(light_pos, light_dir, 1.0);
  
  /* prepare to read keyboard */
  WTkeyboard_open();
  
  /* setup mouse sensor */
  mouse = WTsensor_new(WTmouse_open, WTmouse_close, WTmouse_moveview2,
                       NULL, 1, WTSENSOR_DEFAULT);
    WTsensor_setsensitivity (mouse,1000.0f);

  
  /* setup dataglove sensor */

  /*
  glove = WTdataglove_new(GLOVEPORT);
  */
  
  serial = WTserial_new("/dev/ttyd1"   ,9600) ;
  printf("Glove serial = %x\n",serial);
  WTserial_setsize(serial, 256);

  glove = WTsensor_new(WTdataglove_open, WTdataglove_close, WTdataglove_update,
          serial,1,WTSENSOR_DEFAULT);
  if(glove == NULL) printf("***************** glove not ready **************\n");

  /* setup polhemous sensor */

  while ( !headpolh ){
	printf("FastTrak_new\n");

  headpolh  = WTfastrak_new("/dev/ttyd2",1);
	}
  polh  = WTfastrak_new("/dev/ttyd2",2);
  printf("headpolh=%x, polh=%x\n",headpolh, polh);
  /* setup spaceball */
/*
  ball  = WTspaceball_new("/dev/ttyd2");
*/
  
  /* create hand object*/
	while( !hand) {
	printf("hand_new\n");

  hand = WtGloveHandInit(RIGHT, TRUE);
	}
  if(hand) WTobject_add(hand->parm);

  WTobject_getposition(hand->parm, InitialHand.p);
  WTobject_getorientation(hand->parm, InitialHand.q);
  
  
  /* attach polhemus */
 if(polh && hand){
    WTobject_addsensor(hand->parm, polh, WTFRAME_LOCAL);
    rotate_fastrak(polh);
  } 
  /* set universe action function */
  WTuniverse_setactions(actions);
  
  
  printf ("Universe ready\n");
  WTuniverse_ready();
  
  /* zoom until roughly all of universe is in view */
  WTviewpoint_zoomall(uview);
  /* save initial view point */
  WTviewpoint_getposition(uview, InitialView.p);
  WTviewpoint_getorientation(uview, InitialView.q);
  
  WTsensor_setsensitivity(mouse, 0.05 * WTuniverse_getradius());
  WTviewpoint_addsensor(uview, mouse);
  if(ball) WTviewpoint_addsensor(uview, ball);
  
  /* enter main loop */
  printf("Universe go\n");
  printf("(press ? for help)\n");
  WTuniverse_go();
  
  /* all done - clean up */
  WTuniverse_delete();
  return 0;
}               

/******* actions *******/

void actions(void)
{
  int   key;
  
  /* Move Hand object along Data Glove input */
  if(!gb_calib_step) WtGloveHand_update(hand, glove, 0, FALSE);
  
  /* handle spaceball */
  if(ball) handle_spaceball();
  
  /* get key and do key functions */
  key = WTkeyboard_getlastkey();
  if (key) handle_key(key);     /* interpret keypress */
}


void handle_key(int key)
{
  int ren;
  WTpq l6d;
  
  switch (key) {
  case 'q':
    printf("Quitting.\n");
    WTuniverse_stop();
    break;
  case 'm':
                      printf("Load objects from a Master File: ");
                      gets(fname);
                      LoadObjectsFile(fname);
                      break;
  case 'd':
                      printf("Load objects from a directory: ");
                      gets(fname);
                      LoadObjects(fname);
                      break;
  case 'h':
   WTobject_addsensor (hand->parm, mouse, WTFRAME_VPOINT);

    break;
  case 'u':
    LoadUniverse (NULL, 0.0f);
    break;
  case 'w':
    ren = WTuniverse_getrendering();
    if ( ren & WTRENDER_WIREFRAME )
      WTuniverse_setrendering(WTRENDER_GOURAUD);
    else
      WTuniverse_setrendering(WTRENDER_WIREFRAME);
    break;
  case '!':
    /* displays state information */
    /* frame rate and total polygons */
    printf("\nPolygons: %6d, Frame rate: %8.2f fps\n",
           WTuniverse_npolygons(), WTuniverse_framerate());
    
    /* current viewpoint */
    WTviewpoint_getposition(uview, l6d.p);
    WTviewpoint_getorientation(uview, l6d.q);
    printf("View: x=%8.3f, y=%8.3f, z=%8.3f\n", l6d.p[X],
           l6d.p[Y], l6d.p[Z]);
    printf("      qx=%8.4f, qy=%8.4f, qz=%8.4f, qw=%8.4f\n", l6d.q[X],
           l6d.q[Y], l6d.q[Z], l6d.q[W]);
    
    break;
    
  
  case 'c':
    if(!gb_calib_step){
/*      if(polh) WTobject_removesensor(hand->parm, polh); */
      reset_hand();
      reset_view();
    }
    if(!WTglove_calibrate(glove, gb_calib_step))
      gb_calib_step = 2;
    gb_calib_step = (gb_calib_step == 2 ? 0 : gb_calib_step + 1);
    WtGloveHand_update(hand, glove, gb_calib_step, FALSE);
    if(!gb_calib_step){
/*      if(polh){
        WTobject_addsensor(hand->parm, polh, WTFRAME_LOCAL);
        rotate_fastrak(polh);
      } */
    }
    break;
  case 'i':
    reset_view();
        break;
  case '?':
    printf("\nYou can use the mouse to fly around\n");
     printf(" and you can use Dataglove to move fingers ( Not hand itself)\n");
  default:
    printf("\n");
    printf(" 'w'  Toggles wireframe\n");
    printf(" '!'  Get informations\n");
    printf(" 'c'  Calibrate Data Glove\n");
    printf(" 'i'  Initialize viewing point\n");
    printf(" 'm'  Load objects from a master file\n");
    printf(" 'd'  Load objects from a directory\n");
    printf(" 'u'  Load Universe\n");
    printf(" 'q'  Quits\n");
    break;
  }
}       


void reset_view()
{
   WTviewpoint_setposition(uview, InitialView.p);
   WTviewpoint_setorientation(uview, InitialView.q);
}

void reset_hand()
{
  WTobject_setposition(hand->parm, InitialHand.p);
  WTobject_setorientation(hand->parm, InitialHand.q);
}


void rotate_fastrak(WTsensor *polh)
{
  WTq q;
        
  /* rotate -90 degree about X */
  WTeuler_2q(-0.5*PI, 0.0, 0.0, q);
  
  WTsensor_rotate(polh, q);
}

void handle_spaceball(void)
{
  int           data;
  static FLAG           button_up = TRUE;

  data = WTsensor_getmiscdata(ball);
  
  /* teleport to initial view with BUTTON1 */
  if(button_up){
    if ( data & WTSPACEBALL_BUTTON1_DOWN ){
      button_up = FALSE;
      reset_view();
    }
  
    /* Data Glove calibration with button 7 */
    else if( data & WTSPACEBALL_BUTTON7_DOWN ){
      button_up = FALSE;
      if(!gb_calib_step){
/*        if(polh) WTobject_removesensor(hand->parm, polh); */
        reset_hand();
        reset_view();
      }
      if(!WTglove_calibrate(glove, gb_calib_step))
        gb_calib_step = 2;
      gb_calib_step = (gb_calib_step == 2 ? 0 : gb_calib_step + 1);
      WtGloveHand_update(hand, glove, gb_calib_step, FALSE);
      if(!gb_calib_step){
/*        if(polh){
          WTobject_addsensor(hand->parm, polh, WTFRAME_LOCAL);
          rotate_fastrak(polh);
        } */
      }
    }
  }
  else if(data & WTSPACEBALL_BUTTONS_UP)
    button_up = TRUE;
}


/* ------------------------------------------------------- */
/*
 * loads a new universe from filename and scale passed
 * into the function.  If either of the arguments
 * is null, prompts the user
 */
void LoadUniverse (char *filename, float scale)
{
        char buf[WTPATHLEN];
        WTpq initView;

        /* if no filename ask for one */
        if (filename == NULL) {
                filename = malloc (WTPATHLEN);
                printf ("Enter filename to load as new universe: ");
                gets (filename);
        }

        /* if scale is 0.0 ask for one */
        if (scale == 0.0f) {
                printf ("Enter scale for new universe: ");
                gets (buf);
                if (!buf[0])
                        scale = 1.0f;
                else
                        scale = (float) atof (buf);
        }


        /* load universe geometry */
	scale=1.0;
        printf ("Loading new universe '%s' at scale '%.2f'\n",filename,scale);
        if (WTuniverse_load (filename, &initView, scale) ) {
        /* move the viewpoint to the position and orientation read
                from the model */
        WTviewpoint_moveto (uview, &initView);


        /* scale mouse sensitivity with the size of the universe */
/*
        printf("universe getradius=%f\n",WTuniverse_getradius);
        WTsensor_setsensitivity (mouse, 0.03f*WTuniverse_getradius ());
*/
        WTsensor_setsensitivity (mouse,1000.0f);
        WTsensor_setsensitivity (ball, 1000.0f);
                printf ("done.\n");
        }
        else
                printf ("error.\n");


        /* show text menu */
} /* END LoadUniverse */



/* ------------------------------------------------------- */
/*
 * load a master file
 * of dynamic objects
 */
void LoadObjectsFile (char *directory)
{
        FILE *fp;
        WTpq pq;
        char fname[80];
        WTobject *obj = NULL;
        char *newline;
        /* if no directory ask for one */
        if (directory == NULL) {
                directory = malloc (WTPATHLEN);
                printf ("Enter directory to load objects from: ");
                gets (directory);
        }

        /* open directory */
        printf ("Loading dynamic objects from master file : '%s'\n", directory);        fp = fopen(directory,"r");
        if (!fp) {
                WTwarning ("Couldn't open file : '%s'!\n", directory);
                return;
        }

        /* load objects from specified master file*/
        while ( fgets(fname, 80, fp) != NULL ) {
                /* check the file extension to see if we recognize it. */
                newline = strchr(fname,'\n');
                *newline = '\0';
                printf ("Loading: '%s'...", fname);
                obj = WTobject_new (fname, &pq, 1.0f, FALSE, FALSE);
                if (obj)
                        printf("done.\n");
                else
                        printf("error.\n");
        }

        fclose(fp);
} /* END LoadObjects */



/* ------------------------------------------------------- */
/*
 * load an entire directory
 * of dynamic objects
 */
void LoadObjects (char *directory)
{
        WTpq pq;
        char path[WTPATHLEN], *fname;
        WTobject *obj = NULL;
        WTdirectory *dir;
        char *period;

        /* if no directory ask for one */
        if (directory == NULL) {
                directory = malloc (WTPATHLEN);
                printf ("Enter directory to load objects from: ");
                gets (directory);
        }

        /* open directory */
        printf ("Loading dynamic objects from directory: '%s'\n", directory);
        dir = WTdirectory_open(directory);
        if (!dir) {
                WTwarning ("Couldn't open directory: '%s'!\n", directory);
                return;
        }

        /* load objects from specified directory */
        while ( (fname = WTdirectory_getentry (dir)) != NULL ) {
                /* check the file extension to see if we recognize it. */
                strlwr (fname);
                period = strchr (fname, '.');
                if (!period) continue;
if (strcmp(period, ".nff") && strcmp(period, ".dxf") && strcmp (period, ".3ds")
                        && strcmp(period,".stl") && strcmp (period, ".obj")
                )
                        continue;

                /* make up path and load object */
                strcpy (path, directory);
                strcat (path, WTFILE_DELIM);
                strcat (path, fname);
                printf ("Loading: '%s'...", path);
                obj = WTobject_new (path, &pq, 1.0f, FALSE, FALSE);
                if (obj)
                        printf("done.\n");
                else
                        printf("error.\n");
        }

        /* done loading close directory */
        WTdirectory_close (dir);
} /* END LoadObjects */

    Source: geocities.com/hsvfapa