home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Homebrewer's Handbook / vr.iso / vr386 / pointer.c < prev    next >
C/C++ Source or Header  |  1996-03-19  |  12KB  |  413 lines

  1. /* Pointer device driver interface routines */
  2.  
  3. /* Written by Dave Stampe, Aug. 1992 */
  4.  
  5. // Pointers are an attempt to integrate device support across
  6. // REND386.  Why isn't anyone using them?
  7.  
  8. // this code allows loading of pointer driver (or ones built in to
  9. // the program) with a standardized interface.  No one has to worry
  10. // about any of the code HERE: look at mouseptr.c and stop worrying
  11. // about it!  All you need to do is support initiial, quit, and
  12. // read calls, and fill in a few fields for device resolution
  13. // and range.  Rest of the stuff is for future expansion
  14.  
  15. /*
  16.  This code is part of the VR-386 project, created by Dave Stampe.
  17.  VR-386 is a desendent of REND386, created by Dave Stampe and
  18.  Bernie Roehl.  Almost all the code has been rewritten by Dave
  19.  Stampre for VR-386.
  20.  
  21.  Copyright (c) 1994 by Dave Stampe:
  22.  May be freely used to write software for release into the public domain
  23.  or for educational use; all commercial endeavours MUST contact Dave Stampe
  24.  (dstampe@psych.toronto.edu) for permission to incorporate any part of
  25.  this software or source code into their products!  Usually there is no
  26.  charge for under 50-100 items for low-cost or shareware products, and terms
  27.  are reasonable.  Any royalties are used for development, so equipment is
  28.  often acceptable payment.
  29.  
  30.  ATTRIBUTION:  If you use any part of this source code or the libraries
  31.  in your projects, you must give attribution to VR-386 and Dave Stampe,
  32.  and any other authors in your documentation, source code, and at startup
  33.  of your program.  Let's keep the freeware ball rolling!
  34.  
  35.  DEVELOPMENT: VR-386 is a effort to develop the process started by
  36.  REND386, improving programmer access by rewriting the code and supplying
  37.  a standard API.  If you write improvements, add new functions rather
  38.  than rewriting current functions.  This will make it possible to
  39.  include you improved code in the next API release.  YOU can help advance
  40.  VR-386.  Comments on the API are welcome.
  41.  
  42.  CONTACT: dstampe@psych.toronto.edu
  43. */
  44.  
  45.  
  46.  
  47. #include <stdio.h>
  48. #include <dos.h>
  49. #include <alloc.h>
  50. #include <mem.h>
  51. #include <string.h>
  52.  
  53. #include "pointint.h"
  54. #include "vr_api.h"
  55. #include "intmath.h"
  56.  
  57. extern long scale_16(long s, long a, long x); /* used to do scaling */
  58.                                               /* (x+a)*s            */
  59.  
  60. extern long calc_scale_16(long a, long b, long s); /* computes scaling factor */
  61.                                                    /* (a+b)/2/s          */
  62.  
  63. extern pconfig *mouse_driver(int op, POINTER *p, int mode);
  64. extern pconfig *glove_driver(int op, POINTER *p, int mode);
  65. extern pconfig *logitech_driver(int op, POINTER *p, int mode);
  66. extern pconfig *joy_driver(int op, POINTER *p, int mode);
  67. extern pconfig *mjoy_driver(int op, POINTER *p, int mode);
  68. extern pconfig *keymon_driver(int op, POINTER *p, int mode);
  69. extern pconfig *key_driver(int op, POINTER *p, int mode);
  70.  
  71. //extern pconfig *pot_driver(int op, POINTER *p, int mode);
  72. extern void *load_driver(char *m);
  73.  
  74. static struct INTDRIVER {
  75.             void *driver;
  76.             char *name;
  77.             } intdrivers[10] = {
  78.                 { mouse_driver,    "mouse" },
  79.                 { glove_driver,    "pglove" },
  80.                 { logitech_driver, "logitech" },
  81.                 { joy_driver,      "joystick" },
  82.                 { mjoy_driver,     "mjoy" },
  83.                 { keymon_driver,   "keymon" },
  84.                 { key_driver,      "keys" },
  85.                 { NULL, NULL }
  86.                        };
  87.  
  88.  
  89. extern int logitech_port;  /* used to pass logitech port */
  90.  
  91. PDRIVER *pointer_init(int type, char *drfile)
  92. {
  93.  int i;
  94.     pconfig *(*pd)(int op, POINTER *p, int mode);
  95.     pdrblock *p;
  96.     pconfig *d;
  97.     if (drfile == NULL) return NULL;
  98.  
  99.     for(i=0;intdrivers[i].name;i++)
  100.       {
  101.         if(!stricmp(drfile,intdrivers[i].name))
  102.           {
  103.         p = malloc(sizeof(pdrblock));
  104.         if (p == NULL) return NULL;
  105.         p->driver_pointer = intdrivers[i].driver;
  106.         d = p->driver_pointer(DRIVER_INIT, (POINTER *) type, 0);
  107.         if (d == NULL) return NULL;
  108.         goto got_a_driver;
  109.           }
  110.       }
  111.     if (!strnicmp(drfile, "logitech", 8))
  112.         {                                 /* select com2 based on trailing char. */
  113.         logitech_port = (drfile[8]=='2') ? 1 : 0;
  114.         p = malloc(sizeof(pdrblock));
  115.         if (p == NULL) return NULL;
  116.         d = logitech_driver(DRIVER_INIT, (POINTER *) type, 0);
  117.         p->driver_pointer = logitech_driver;
  118.         }
  119. //    else if (!strnicmp(drfile, "pots", 8))
  120. //        {                                 /* select com2 based on trailing char. */
  121. //        p = malloc(sizeof(pdrblock));
  122. //        if (p == NULL) return NULL;
  123. //        d = pot_driver(DRIVER_INIT, (POINTER *) type, 0);
  124. ///        p->driver_pointer = pot_driver;
  125. //        }
  126.     else
  127.         {
  128.         pd = load_driver(drfile);
  129.         if (pd == NULL) return NULL;
  130.         p = malloc(sizeof(pdrblock));
  131.         if (p == NULL) return NULL;
  132.         p->driver_pointer = pd =
  133.             MK_FP(FP_SEG(pd), 16+FP_OFF(pd)); /* entry point */
  134.         d = pd(DRIVER_INIT, (POINTER *) type, 0);
  135.         if (d == NULL) return NULL;
  136.     }
  137. got_a_driver:
  138.     p->pdata = d;
  139.     p->xmult = p->ymult = p->zmult = 65536L;
  140.     p->xadd = p->yadd = p->zadd = 0;
  141.     p->xrmult = p->yrmult = p->zrmult = 65536L;
  142.     p->xradd = p->yradd = p->zradd = 0;
  143.     return p;
  144. }
  145.  
  146. /* makes sure device is available, OK */
  147. /* returns *pconfig or NULL           */
  148.  
  149. pconfig *pointer_check(PDRIVER *p)
  150. {
  151.     if (p)
  152.         return (((pdrblock *)p)->driver_pointer) (DRIVER_CHECK, NULL, 0);
  153.     else
  154.         return NULL;
  155. }
  156.  
  157. /* recenters, recalibrates, etc */
  158. void pointer_reset(PDRIVER *p)
  159. {
  160.     if (p == NULL) return;
  161.     (((pdrblock *)p)->driver_pointer) (DRIVER_RESET, NULL, 0);
  162. }
  163.  
  164. /* reads pointer, scales data and        */
  165. /* returns bitwise OR of the following:  */
  166. int pointer_read(PDRIVER *p, POINTER *pt)
  167. {
  168.     POINTER *op = &((pdrblock *)p)->oldp;
  169.     pdrblock *pd = (pdrblock *)p;
  170.     int has = pd->pdata->databits;
  171.     int changed = 0;
  172.     int sx, sy;
  173.  
  174.     if (p == NULL || pt == NULL) return 0;
  175.     if ((p->driver_pointer) (DRIVER_READ, pt, P_POINTER) == NULL)
  176.     {
  177.         memcpy( pt, op, sizeof(POINTER) ); /* handle no new data */
  178.         pt->wpos_valid = 0;
  179.         pt->changed = 0;
  180.         op->changed = 0;
  181.         return 0;
  182.     }
  183.  
  184.     if (has & P_HASX)
  185.     {
  186.         pt->x = scale_16(pd->xmult, pd->xadd, pt->x);
  187.         if ((pt->dx = pt->x - op->x) != 0) changed |= PNEW_POS;
  188.     }
  189.     else pt->x = 0;
  190.     if (has & P_HASY)
  191.     {
  192.         pt->y = scale_16(pd->ymult, pd->yadd, pt->y);
  193.         if ((pt->dy = pt->y - op->y) != 0) changed |= PNEW_POS;
  194.     }
  195.     else pt->y = 0;
  196.     if (has & P_HASZ)
  197.     {
  198.         pt->z = scale_16(pd->zmult, pd->zadd, pt->z);
  199.         if ((pt->dz = pt->z - op->z) != 0) changed |= PNEW_POS;
  200.     }
  201.     else pt->z = 0;
  202.  
  203.     if (has & P_HASRX)
  204.     {
  205.         pt->rx = scale_16(pd->xrmult, pd->xradd, pt->rx);
  206.         if ((pt->drx = pt->rx - op->rx) != 0) changed |= PNEW_ROT;
  207.     }
  208.     else pt->rx = 0;
  209.     if (has & P_HASRY)
  210.     {
  211.         pt->ry = scale_16(pd->yrmult, pd->yradd, pt->ry);
  212.         if ((pt->dry = pt->ry - op->ry) != 0) changed |= PNEW_ROT;
  213.     }
  214.     else pt->ry = 0;
  215.     if (has & P_HASRZ)
  216.     {
  217.         pt->rz = scale_16(pd->zrmult, pd->zradd, pt->rz);
  218.         if ((pt->drz = pt->rz - op->rz) != 0) changed |= PNEW_ROT;
  219.     }
  220.     else pt->rz = 0;
  221.  
  222.     pt->buttons &= has&0x0007 ;
  223.     if ((has&0x0007) && pt->buttons != op->buttons) changed |= PNEW_BUT;
  224.  
  225.     if ((has&P_HASGEST) && pt->gesture != op->gesture) changed |= PNEW_GEST;
  226.  
  227.     if ((has&P_HASKEYS) && pt->keys != op->keys) changed |= PNEW_KEY;
  228.  
  229.     if (has & P_HASFLEX)
  230.     {
  231.         int i;
  232.         int n = pd->pdata->flexnum;
  233.  
  234.         for (i = 0; i < n; i++)
  235.             if (pt->flex[i] != op->flex[i])
  236.             {
  237.                 changed |= PNEW_FLEX;
  238.                 break;
  239.             }
  240.     }
  241.     if (changed)
  242.     {
  243.         memcpy(op, pt, sizeof(POINTER));
  244.         pt->wpos_valid = 0;
  245.     }
  246.     pt->changed = changed;
  247.     op->changed = changed;
  248.     return changed;
  249. }
  250.  
  251.  
  252. int mouse_read(PDRIVER *p, int *xp, int *yp, unsigned *bp)
  253. {
  254.   POINTER pt;
  255.   POINTER *opt = &(p->oldp);
  256.   int c = 0;
  257.  
  258.   if (p == NULL) return 0;
  259.   if (!(p->pdata->databits & P_HASSCR)) return 0;
  260.  
  261.   (p->driver_pointer) (DRIVER_READ, &pt, P_SCREEN);
  262.  
  263.   if (p->oldsx != pt.x || p->oldsy != pt.y)
  264.     c |= PNEW_POS;
  265.   if (opt->buttons != pt.buttons)
  266.     c |= PNEW_BUT;
  267.  
  268.   p->oldsx = pt.x;
  269.   p->oldsy = pt.y;
  270.   opt->buttons = pt.buttons ;
  271.  
  272.   if (xp) *xp = pt.x;
  273.   if (yp) *yp = pt.y;
  274.   if (bp) *bp = pt.buttons;
  275.  
  276.   opt->changed = c;
  277.  
  278.   return c;
  279. }
  280.  
  281.  
  282. int mouse_last(PDRIVER *p, int *xp, int *yp, int *bp)
  283. {
  284.     if (p == NULL) return 0;
  285.  
  286.     if (xp) *xp = p->oldsx;
  287.     if (yp) *yp = p->oldsy;
  288.     if (bp) *bp = (&(p->oldp))->buttons;
  289.     return (&(p->oldp))->changed;
  290. }
  291.  
  292. void set_mouse_limits(PDRIVER *p, int maxx, int maxy)
  293. {
  294.     if (p == NULL) return; /* NOTE: MODIFIES DRIVER */
  295.     p->pdata->maxsx = maxx;
  296.     p->pdata->maxsy = maxy;
  297.     (p->driver_pointer) (DRIVER_CMD, (POINTER *) (P_SCREEN | P_CENTER), 0);
  298.     mouse_read(p, NULL, NULL, NULL);
  299. }
  300.  
  301. /* disconnects driver */
  302. void pointer_quit(PDRIVER *p)
  303. {
  304.     if (p == NULL) return;
  305.     (((pdrblock *)p)->driver_pointer) (DRIVER_QUIT, NULL, 0);
  306. }
  307.  
  308. /* changes device mode */
  309. pconfig *device_command(PDRIVER *p, int command)
  310. {
  311.     pconfig *pc;
  312.  
  313.     if (p == NULL) return NULL;
  314.     pc = (((pdrblock *)p)->driver_pointer) (DRIVER_CMD, (POINTER *) command, 0);
  315.     p->pdata = pc;
  316.     return pc;
  317. }
  318.  
  319. /* sets scaling (+/- given value, centered at 0) */
  320.  
  321. void pointer_tscale(PDRIVER *p, long x, long y, long z)
  322. {
  323.     long mx = p->pdata->maxx;
  324.     long mn = p->pdata->minx;
  325.     p->xmult = calc_scale_16(mx, mn, x);
  326.     p->xadd = (mn+mx)/2;
  327.  
  328.     mx = p->pdata->maxy;
  329.     mn = p->pdata->miny;
  330.     p->ymult = calc_scale_16(mx, mn, y);
  331.     p->yadd = (mn+mx)/2;
  332.  
  333.     if (p->pdata->type != P_IS2DP) /* use y scaling for pseudo-z axis */
  334.     {
  335.         mx = p->pdata->maxz;
  336.         mn = p->pdata->minz;
  337.     }
  338.     p->zmult = calc_scale_16(mx, mn, z);
  339.     p->zadd = (mn+mx)/2;
  340. }
  341.  
  342.  
  343. void pointer_rscale(PDRIVER *p, long rx, long ry, long rz)
  344. {
  345.     long mx = p->pdata->maxxr;
  346.     long mn = p->pdata->minxr;
  347.     p->xrmult = calc_scale_16(mx, mn, rx);
  348.     p->xradd = (mn-mx)/2;
  349.  
  350.     mx = p->pdata->maxyr;
  351.     mn = p->pdata->minyr;
  352.     p->yrmult = calc_scale_16(mx, mn, ry);
  353.     p->yradd = (mn-mx)/2;
  354.  
  355.     mx = p->pdata->maxzr;
  356.     mn = p->pdata->minzr;
  357.     p->zrmult = calc_scale_16(mx, mn, rz);
  358.     p->zradd = (mn-mx)/2;
  359. }
  360.  
  361. void pointer_abscale(PDRIVER *p, long xs, long ys, long zs,
  362.     long xrs, long yrs, long zrs)
  363. {
  364.     p->xmult = scale_16(xs, 0, p->pdata->xres); /* set up to scale tick resolution */
  365.     p->ymult = scale_16(ys, 0, p->pdata->yres);
  366.     p->zmult = scale_16(zs, 0, p->pdata->zres);
  367.     p->xrmult = scale_16(xrs, 0, p->pdata->xrres); /* some weirdness with rot. scaling */
  368.     p->yrmult = scale_16(yrs, 0, p->pdata->yrres); /* as tick res. not really expressible */
  369.     p->zrmult = scale_16(zrs, 0, p->pdata->zrres); /* in <16.16>: so set tickres>>16 or so */
  370.     p->xadd = p->yadd = p->zadd = 0; /* look at PG y-rot for example */
  371.     p->xradd = p->yradd = p->zradd = 0;
  372. }
  373.  
  374.  
  375. void init_pointer(POINTER *p) /* initialize pointer structure */
  376. {
  377.     memset( p, 0, sizeof(POINTER));
  378.     p->wpos[0][0] = p->wpos[1][1] = p->wpos[2][2] = 536870912L;
  379. }
  380.  
  381. int last_pointer(PDRIVER *d, POINTER *p) /* copy of last read value */
  382. {
  383.     memcpy(p, &(d->oldp), sizeof(POINTER));
  384.     return(p->changed);
  385. }
  386.  
  387. /* find world coordinates of pointer based on given view */
  388.  
  389. void pointer_to_world(POINTER *p, CAMERA *c, long *x, long *y, long *z)
  390. {
  391.   MATRIX n;
  392.   *x = p->x;
  393.   *y = p->y;
  394.   *z = p->z;
  395.   get_camera_matrix(c, n);
  396.   matrix_point(n,x,y,z);
  397.   p->wpos[3][0] = *x;
  398.   p->wpos[3][1] = *y;
  399.   p->wpos[3][2] = *z;
  400.   p->wpos_valid = 1;
  401. }
  402.  
  403.  
  404. /* rotate data to view alignment */
  405.  
  406. void rotate_to_view( CAMERA *c, long *x, long *y, long *z)
  407. {
  408.   MATRIX n;
  409.   get_camera_matrix(c, n);
  410.   matrix_rotate(n,x,y,z);
  411. }
  412.  
  413.