home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / devel5 / hdmanip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-08  |  8.1 KB  |  369 lines

  1. /* Handles body/head/manipulator mappings */
  2.  
  3. /* Written by Dave Stampe, August 1992 */
  4.  
  5. /* Copyright 1992 by Dave Stampe and Bernie Roehl.
  6.    May be freely used to write software for release into the public domain;
  7.    all commercial endeavours MUST contact Bernie Roehl and Dave Stampe
  8.    for permission to incorporate any part of this software into their
  9.    products!
  10.  
  11.      ATTRIBUTION:  If you use any part of this source code or the libraries
  12.      in your projects, you must give attribution to REND386, Dave Stampe,
  13.      and Bernie Roehl in your documentation, source code, and at startup
  14.      of your program.  Let's keep the freeware ball rolling!
  15.  */
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>    /* atexit() */
  19. #include <mem.h>       /* memcpy() */
  20. #include <dos.h>
  21. #include "rend386.h"
  22. #include "intmath.h"
  23. #include "splits.h"
  24. #include "segasupp.h"
  25. #include "pointer.h"
  26. #include "cursor.h"
  27.  
  28. #ifdef VIDEO_TRACKER
  29. extern int start_video();
  30. extern int read_head_tracker(long *x, long *y, long *z, long *t, long *p, long *a);
  31. #endif
  32.  
  33. extern int use_glove;
  34.  
  35. extern int redraw;
  36.  
  37. static SEGMENT *rot_seg; /* used to rotate objects by center */
  38.  
  39. SEGMENT *body_seg = NULL; /* body-in-world base segment */
  40. SEGMENT *head_seg = NULL; /* head-on-body segment */
  41. SEGMENT *eye_seg; /* eyes-in-head segment */
  42.  
  43. extern PDRIVER *head_device;
  44.  
  45. MATRIX h_recenter, ht_offset, ht_ioffset;
  46.  
  47. int head_update(int recenter) /* repositions head based on tracker data */
  48. {
  49.     POINTER hp;
  50.     MATRIX m;
  51.     int c;
  52.  
  53.     if (!head_device) return 0;
  54.     c = pointer_read(head_device, &hp); /* read ht */
  55.  
  56.     if (recenter) /* use current pos'n as zero */
  57.     {
  58. #ifdef HD_CENTER
  59.         std_matrix(m, hp.rx, hp.ry, hp.rz, hp.x, hp.y, hp.z);
  60.         inverse_matrix(m, h_recenter);
  61.         matrix_product(ht_ioffset, h_recenter, h_recenter);
  62.         c = PNEW_POS;
  63. #endif
  64.     }
  65.  
  66.     if (c & (PNEW_POS | PNEW_ROT)) /* compute new hpos */
  67.     {
  68.         multi_matrix(m, hp.rx, hp.ry, hp.rz, hp.x, hp.y, hp.z, RYXZ);
  69. #ifdef HD_CENTER
  70.         matrix_product(h_recenter, m, m);
  71. #endif
  72.         matrix_product(m, ht_offset, m);
  73.         abs_mat_segment(head_seg, m);
  74.         redraw = 1;
  75.     }
  76.     return 0;
  77. }
  78.  
  79.  
  80.  
  81. void htrack_quit()
  82. {
  83.     pointer_quit(head_device);
  84. }
  85.  
  86.  
  87. PDRIVER *init_head_device(char *dfname, long x, long y, long z, long rx, long ry, long rz)
  88. {
  89.     MATRIX m;
  90.     PDRIVER *p;
  91.     POINTER pt;
  92.  
  93.     p = pointer_init(P_IS6H, dfname); /* setup glove device TEST */
  94.     if (p == NULL) return NULL;
  95.  
  96.     init_pointer(&pt); /* so that defaults are OK */
  97.     /* use abs. head motion */
  98.     pointer_abscale(p, 65536L, 65536L, 65536L, 65536L, 65536L, 65536L);
  99.     pointer_read(p, &pt);
  100.     pointer_read(p, &pt); /* save current position */
  101.  
  102.     head_device = p;
  103.     atexit(htrack_quit);
  104.  
  105.     identity_matrix(h_recenter);
  106.     std_matrix(m, rx, ry, rz ,x, y, z);
  107.  
  108.     matrix_copy(m, ht_offset);
  109.     /* matrix_copy(m, h_recenter); */
  110.  
  111.     inverse_matrix(m, ht_ioffset);
  112.     inverse_matrix(m, h_recenter);
  113.  
  114.     head_update(1);
  115.  
  116.     return p;
  117. }
  118.  
  119.  
  120. /* do BEFORE loading, initializing devices */
  121.  
  122. void init_body_links() /* setup body-glove-head system */
  123. {
  124.  extern int use_ht;
  125.  
  126.  if(!body_seg) body_seg = new_seg(NULL);
  127.  if(!head_seg) head_seg = new_seg(NULL);
  128.  attach_segment(head_seg, body_seg);
  129.  eye_seg = new_seg(head_seg);
  130.  rot_seg = new_seg(NULL); /* used by manipulation */
  131.  
  132.  abs_rot_segment(head_seg, 0*65536L, 0*65536L, 0, RYXZ);
  133.  if(use_ht)
  134.    abs_move_segment(eye_seg, 0,100,100); /* eyes in head pos'n */
  135. }
  136.  
  137. SEGMENT *connected = NULL;
  138.  
  139. void disconnect_body(VIEW *v)
  140. {
  141.  MATRIX m;
  142.  
  143.  if(!connected) return;
  144.  detach_segment (body_seg);
  145.  
  146.  seg_getposxyz(body_seg, &(v->ex), &(v->ey), &(v->ez) );
  147.  matrix_copy(get_seg_pmatrix(body_seg), m);
  148.  matrix_to_angle(m, &(v->tilt), &(v->pan), &(v->roll) );
  149.  
  150.  connected = NULL;
  151. }
  152.  
  153.  
  154. void connect_body(VIEW *v, SEGMENT *s)
  155. {
  156.  MATRIX m;
  157.  
  158.  if(!s) return;
  159.  if(connected)
  160.       disconnect_body(v);
  161.  fast_view_factors(v);
  162.  view_to_matrix(v,m);
  163.  abs_mat_segment(body_seg,m);
  164.  
  165.  attach_segment(body_seg, s);
  166.  seg_getjointxyz(body_seg, &(v->ex), &(v->ey), &(v->ez) );
  167.  matrix_copy(get_seg_jmatrix(body_seg), m);
  168.  matrix_to_angle(m, &(v->tilt), &(v->pan), &(v->roll) );
  169.  
  170.  connected = s;
  171. }
  172.  
  173.  
  174. /* takes "view" corresp. to body location,           */
  175. /* converts to centered eye view, updates cursors    */
  176. /* sequence: update cursor/glove, read head tracker, */
  177. /* body_centric_map(), manipulate object, and render */
  178.  
  179. void body_centric_map(VIEW *body, VIEW *v)
  180. {
  181.  MATRIX m;
  182.  
  183.  fast_view_factors(body);
  184.  *v = *body;
  185.  view_to_matrix(v,m);
  186.  abs_mat_segment(body_seg,m);
  187.  if (!connected) update_segment(body_seg);
  188.  else update_segment(connected);
  189.  memcpy(&m, get_seg_pmatrix(eye_seg),sizeof(MATRIX));
  190.  matrix_view_factors(v,m);
  191. }
  192.  
  193.  
  194. /************* SIMPLE 3D/6D OBJECT MANIPULATION *********/
  195.  
  196. static OBJECT *sel_obj;
  197. static SEGMENT *work_seg;
  198. static SEGMENT *old_parent;
  199.  
  200. extern SPLIT *split_tree;
  201.  
  202.  
  203. static void unhi_it(OBJECT *obj)
  204. {
  205.     set_obj_flags(obj, get_obj_flags(obj) & ~OBJ_HIGHLIGHTED);
  206.     unhighlight_obj(obj);
  207. }
  208.  
  209.  
  210. static MATRIX ogm;
  211. static long oxp, oyp, ozp;
  212. static long oxg, oyg, ozg;
  213.  
  214. #define FREE_DO   0
  215. #define GRASP_DO  1
  216. #define ROTATE_DO 2
  217. #define SELECT_DO 3
  218.  
  219. static gmode = FREE_DO;
  220.  
  221. void manip_do(PDRIVER *p, int command) /* glove execution loop element */
  222. {
  223.  OBJLIST *list;
  224.  OBJECT * obj;
  225.  int s;
  226.  long d,x,y,z;
  227.  MATRIX f;
  228.  MATRIX *m;
  229.  
  230.  POINTER pt;
  231.  SEGMENT *wrist_seg = manip_data(p, &x, &y, &z);
  232.  
  233.  if (p==NULL) return;
  234.  
  235.  s = last_pointer(p, &pt);
  236.  
  237. newmode:
  238.     switch(gmode)
  239.     {
  240.         case FREE_DO:
  241.             switch(command)
  242.             {
  243.                 case SELECT_DO:
  244.                     gmode = SELECT_DO;
  245.                     walk_split_tree(split_tree, unhi_it);
  246.                     sel_obj = NULL;
  247.                     redraw = 1;
  248.                     goto newmode;
  249.                 case GRASP_DO:
  250.                     if (sel_obj)
  251.                     {
  252.                         work_seg = get_object_owner(sel_obj);
  253.                         old_parent = parent_segment(work_seg);
  254.                         if (old_parent) detach_segment(work_seg);
  255.                         attach_segment(work_seg, wrist_seg);
  256.                         gmode = GRASP_DO;
  257.                         redraw = 1;
  258.                     }
  259.                     break;
  260.                 case ROTATE_DO:
  261.                     if (sel_obj)
  262.                     {
  263.                         work_seg = get_object_owner(sel_obj);
  264.                         if (work_seg == NULL) break;
  265.                         old_parent = parent_segment(work_seg);
  266.                         update_segment(work_seg);
  267.  
  268.                         if (old_parent == NULL)
  269.                             get_object_bounds(sel_obj, &oxp, &oyp, &ozp); /* center of obj */
  270.                         else
  271.                         {
  272.                             m = get_seg_pmatrix(work_seg); /* else by origin ("joint") */
  273.                             oxp = (*m)[3][0];
  274.                             oyp = (*m)[3][1];
  275.                             ozp = (*m)[3][2];
  276.                         }
  277.  
  278.                     abs_rot_segment(rot_seg, 0, 0, 0, RYXZ);
  279.                     abs_move_segment(rot_seg, oxp, oyp, ozp);
  280.                     update_segment(rot_seg);
  281.                     attach_segment(work_seg, rot_seg);
  282.  
  283.                     oxg = x-oxp;
  284.                     oyg = y-oyp;
  285.                     ozg = z-ozp;
  286.                     vector_to_matrix(f, oxg, oyg, ozg);
  287.                     inverse_matrix(f, ogm);
  288.                     gmode = ROTATE_DO;
  289.                     redraw = 1;
  290.                 }
  291.                 break;
  292.             default:
  293.                 break;
  294.             }
  295.             break;
  296.         case SELECT_DO:
  297.             switch(command)
  298.             {
  299.                 case SELECT_DO:
  300.                     list = which_area_objlist(split_tree, x, y, z);
  301.                     if (list != NULL)
  302.                     {
  303.                         obj = best_collision(list, x, y, z);
  304.                         if (obj == NULL)
  305.                         {
  306.                             unhighlight_obj(sel_obj);
  307.                             sel_obj = NULL;
  308.                         }
  309.                     else
  310.                     {
  311.                         if (sel_obj != obj) unhighlight_obj(sel_obj);
  312.                         highlight_obj(obj);
  313.                         sel_obj = obj;
  314.                     }
  315.                     redraw = 1;
  316.                 }
  317.             break;
  318.         default:
  319.             gmode = FREE_DO;
  320.             goto newmode;
  321.         }
  322.         break;
  323.     case GRASP_DO:
  324.         switch(command)
  325.         {
  326.         case GRASP_DO:
  327.             break; /* move is automatic */
  328.         default:
  329.             if (work_seg)
  330.             {
  331.                 detach_segment(work_seg);
  332.                 if (old_parent) attach_segment(work_seg, old_parent);
  333.                 redraw = 1;
  334.             }
  335.             gmode = FREE_DO;
  336.             goto newmode;
  337.         }
  338.         break;
  339.     case ROTATE_DO:
  340.         switch(command)
  341.         {
  342.         case ROTATE_DO:
  343.             if (sel_obj && (s & PNEW_POS))
  344.             {
  345.                 vector_to_matrix(f, x-oxp, y-oyp, z-ozp);
  346.                 matrix_product(f, ogm, f);
  347.                 f[3][0] = oxp;
  348.                 f[3][1] = oyp;
  349.                 f[3][2] = ozp;
  350.                 abs_mat_segment(rot_seg, f);
  351.                 update_segment(rot_seg);
  352.                 redraw = 1;
  353.             }
  354.             break;
  355.         default:
  356.             gmode = FREE_DO;
  357.             redraw = 1; /* convert to real pos'n */
  358.             detach_segment(work_seg);
  359.             if (old_parent) attach_segment(work_seg, old_parent);
  360.             goto newmode;
  361.         }
  362.         break;
  363.     default:
  364.         break;
  365.     }
  366. }
  367.  
  368.  
  369.