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

  1. /* Handles body/head/manipulator mappings */
  2.  
  3. /* Written by Dave Stampe, August 1992 */
  4.  
  5. // modified for VRC for better viewpoint control
  6. // and default body ssegment access
  7.  
  8. // Split up, rearranged, parially ported to VR-3866 API
  9.  
  10. /*
  11.  This code is part of the VR-386 project, created by Dave Stampe.
  12.  VR-386 is a desendent of REND386, created by Dave Stampe and
  13.  Bernie Roehl.  Almost all the code has been rewritten by Dave
  14.  Stampre for VR-386.
  15.  
  16.  Copyright (c) 1994 by Dave Stampe:
  17.  May be freely used to write software for release into the public domain
  18.  or for educational use; all commercial endeavours MUST contact Dave Stampe
  19.  (dstampe@psych.toronto.edu) for permission to incorporate any part of
  20.  this software or source code into their products!  Usually there is no
  21.  charge for under 50-100 items for low-cost or shareware products, and terms
  22.  are reasonable.  Any royalties are used for development, so equipment is
  23.  often acceptable payment.
  24.  
  25.  ATTRIBUTION:  If you use any part of this source code or the libraries
  26.  in your projects, you must give attribution to VR-386 and Dave Stampe,
  27.  and any other authors in your documentation, source code, and at startup
  28.  of your program.  Let's keep the freeware ball rolling!
  29.  
  30.  DEVELOPMENT: VR-386 is a effort to develop the process started by
  31.  REND386, improving programmer access by rewriting the code and supplying
  32.  a standard API.  If you write improvements, add new functions rather
  33.  than rewriting current functions.  This will make it possible to
  34.  include you improved code in the next API release.  YOU can help advance
  35.  VR-386.  Comments on the API are welcome.
  36.  
  37.  CONTACT: dstampe@psych.toronto.edu
  38. */
  39.  
  40.  
  41. #include <stdio.h>
  42. #include <stdlib.h>    /* atexit() */
  43. #include <mem.h>       /* memcpy() */
  44. #include <dos.h>
  45.  
  46. #include "pointer.h"
  47. #include "vr_api.h"
  48. #include "segment.h"
  49. #include "intmath.h"
  50. #include "splits.h"
  51. #include "pcdevice.h"
  52.  
  53.  
  54.  
  55. /************* SIMPLE 3D/6D OBJECT MANIPULATION *********/
  56.  
  57. static OBJECT *sel_obj;
  58. static SEGMENT *work_seg;
  59. static SEGMENT *old_parent;
  60.  
  61. static SEGMENT *rot_seg = NULL; /* used to rotate objects by center */
  62.  
  63. static MATRIX ogm;
  64. static long oxp, oyp, ozp;
  65. static long oxg, oyg, ozg;
  66.  
  67. #define FREE_DO   0        // released
  68. #define GRASP_DO  1        // holding
  69. #define ROTATE_DO 2        // "pinch" rotation emulation for 3D dev.
  70. #define SELECT_DO 3        // looking for an object to grasp...
  71.  
  72. static gmode = FREE_DO;    // current grasping mode
  73.  
  74.  
  75. //// STILL USES SEGMENT CALLS FOR NOW
  76.  
  77. static PDRIVER *manip_pdriver = NULL;
  78. static SEGMENT *manip_segment = NULL;
  79. static SEGMENT *manip_sel_seg = NULL;
  80. static POSE manip_sel_offset = ZERO_POSE;
  81.  
  82.  
  83.     // sets up the 3D/6D manip system
  84. void set_3D_manip_data(PDRIVER *ptr, SEGMENT *move, SEGMENT *sel, POSE *seloffset)
  85. {
  86.   manip_pdriver = ptr;
  87.   manip_segment = move;
  88.   manip_sel_seg = sel;
  89.   manip_sel_offset = *seloffset;
  90. }
  91.  
  92.  
  93. static SEGMENT *manip_data(long *x, long *y, long *z)
  94. {
  95.   *x = manip_sel_offset.x;
  96.   *y = manip_sel_offset.y;
  97.   *z = manip_sel_offset.z;
  98.   matrix_point(*get_seg_pmatrix(manip_sel_seg), x, y, z);
  99.  
  100.   return manip_segment;
  101. }
  102.  
  103.  
  104.  
  105. void do_3D_manip(WORD command) /* glove execution loop element */
  106. {
  107.  OBJLIST *list;
  108.  OBJECT * obj;
  109.  int s;
  110.  long d,x,y,z;
  111.  MATRIX f;
  112.  MATRIX *m;
  113.  
  114.  POINTER pt;
  115.  SEGMENT *wrist_seg = manip_data(&x, &y, &z);  // local manipulation
  116.                           // very general call
  117.  if (manip_pdriver==NULL) return;
  118.  if (!rot_seg) rot_seg = new_seg(NULL); // initialize if needed
  119.  
  120.  s = last_pointer(manip_pdriver, &pt);
  121.  
  122. newmode:
  123.  switch(gmode)
  124.    {
  125.      case FREE_DO:
  126.        switch(command)
  127.      {
  128.        case SELECT_DO:
  129.          gmode = SELECT_DO;
  130.          do_for_all_selected(unhighlight_object);
  131.          sel_obj = NULL;
  132.          world_changed++;
  133.          goto newmode;
  134.        case GRASP_DO:
  135.          if (sel_obj)
  136.            {
  137.          work_seg = object2segment(sel_obj);
  138.          old_parent = parent_segment(work_seg);
  139.          if (old_parent) detach_segment(work_seg,1);
  140.          attach_segment(work_seg, wrist_seg,1);
  141.          gmode = GRASP_DO;
  142.          world_changed++;
  143.            }
  144.          break;
  145.        case ROTATE_DO:
  146.          if (sel_obj)
  147.            {
  148.          work_seg = object2segment(sel_obj);
  149.          if (work_seg == NULL) break;
  150.          old_parent = parent_segment(work_seg);
  151.          update_segment(work_seg);
  152.          if (old_parent == NULL)
  153.             get_object_bounds(sel_obj, &oxp, &oyp, &ozp); /* center of obj */
  154.          else
  155.            {
  156.              m = get_seg_pmatrix(work_seg); /* else by origin ("joint") */
  157.              oxp = (*m)[3][0];
  158.              oyp = (*m)[3][1];
  159.              ozp = (*m)[3][2];
  160.            }
  161.          abs_rot_segment(rot_seg, 0, 0, 0, RYXZ);
  162.          abs_move_segment(rot_seg, oxp, oyp, ozp);
  163.          update_segment(rot_seg);
  164.          attach_segment(work_seg, rot_seg,1);
  165.          oxg = x-oxp;
  166.          oyg = y-oyp;
  167.          ozg = z-ozp;
  168.          vector_to_matrix(f, oxg, oyg, ozg);
  169.          inverse_matrix(f, ogm);
  170.          gmode = ROTATE_DO;
  171.          world_changed++;
  172.            }
  173.          break;
  174.        default:
  175.          break;
  176.      }
  177.        break;
  178.      case SELECT_DO:
  179.        switch(command)
  180.      {
  181.        case SELECT_DO:
  182.          list = which_area_objlist(global_world_root, x, y, z);
  183.          if (list != NULL)
  184.            {
  185.          obj = best_collision(list, x, y, z);
  186.          if (obj == NULL)
  187.            {
  188.              unhighlight_object(sel_obj);
  189.              sel_obj = NULL;
  190.            }
  191.          else
  192.            {
  193.              if (sel_obj != obj) unhighlight_object(sel_obj);
  194.              highlight_object(obj);
  195.              sel_obj = obj;
  196.            }
  197.          world_changed++;
  198.            }
  199.          break;
  200.        default:
  201.          gmode = FREE_DO;
  202.          goto newmode;
  203.      }
  204.        break;
  205.      case GRASP_DO:
  206.        switch(command)
  207.      {
  208.        case GRASP_DO:
  209.          break; /* move is automatic */
  210.        default:
  211.          if (work_seg)
  212.            {
  213.          detach_segment(work_seg,1);
  214.          if (old_parent) attach_segment(work_seg, old_parent,1);
  215.          world_changed++;
  216.            }
  217.          gmode = FREE_DO;
  218.          goto newmode;
  219.      }
  220.        break;
  221.      case ROTATE_DO:
  222.        switch(command)
  223.      {
  224.        case ROTATE_DO:
  225.          if (sel_obj && (s & PNEW_POS))
  226.            {
  227.          vector_to_matrix(f, x-oxp, y-oyp, z-ozp);
  228.          matrix_product(f, ogm, f);
  229.          f[3][0] = oxp;
  230.          f[3][1] = oyp;
  231.          f[3][2] = ozp;
  232.          abs_mat_segment(rot_seg, f);
  233.          update_segment(rot_seg);
  234.          world_changed++;
  235.            }
  236.          break;
  237.        default:
  238.          gmode = FREE_DO;
  239.          world_changed++;
  240.          detach_segment(work_seg,1);
  241.          if (old_parent) attach_segment(work_seg, old_parent,1);
  242.          goto newmode;
  243.      }
  244.        break;
  245.      default:
  246.        break;
  247.    }
  248. }
  249.  
  250.  
  251.