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

  1. // new CAMERA and STEREO support routines
  2. // 29/12/93 by Dave Stampe
  3.  
  4.  
  5.  
  6. /*
  7.  This code is part of the VR-386 project, created by Dave Stampe.
  8.  VR-386 is a desendent of REND386, created by Dave Stampe and
  9.  Bernie Roehl.  Almost all the code has been rewritten by Dave
  10.  Stampre for VR-386.
  11.  
  12.  Copyright (c) 1994 by Dave Stampe:
  13.  May be freely used to write software for release into the public domain
  14.  or for educational use; all commercial endeavours MUST contact Dave Stampe
  15.  (dstampe@psych.toronto.edu) for permission to incorporate any part of
  16.  this software or source code into their products!  Usually there is no
  17.  charge for under 50-100 items for low-cost or shareware products, and terms
  18.  are reasonable.  Any royalties are used for development, so equipment is
  19.  often acceptable payment.
  20.  
  21.  ATTRIBUTION:  If you use any part of this source code or the libraries
  22.  in your projects, you must give attribution to VR-386 and Dave Stampe,
  23.  and any other authors in your documentation, source code, and at startup
  24.  of your program.  Let's keep the freeware ball rolling!
  25.  
  26.  DEVELOPMENT: VR-386 is a effort to develop the process started by
  27.  REND386, improving programmer access by rewriting the code and supplying
  28.  a standard API.  If you write improvements, add new functions rather
  29.  than rewriting current functions.  This will make it possible to
  30.  include you improved code in the next API release.  YOU can help advance
  31.  VR-386.  Comments on the API are welcome.
  32.  
  33.  CONTACT: dstampe@psych.toronto.edu
  34. */
  35.  
  36.  
  37. #include <stdio.h>
  38. #include <stdlib.h>  /* for atol(), only for debugging! */
  39. #include <dos.h>
  40. #include <alloc.h>
  41.  
  42. #include "vr_api.h"
  43. #include "intmath.h"
  44. #include "segment.h"
  45.  
  46.  
  47. #include "pcdevice.h"    // last_render_time()
  48.  
  49.  
  50. /* default screen data setup */
  51.  
  52. STEREO default_stereo = {
  53.     600 , 240, 320, 50, 600, 1*65536L ,     // stereo setup
  54.      0, 0, 319, 200, 0, 0, 0, 0, 0, 0 ,     // left window
  55.      0,0,0,0,0,0,0,0,0,0,0,0,
  56.      0, 0, 319, 200, 0, 0, 0, 0, 0, 0 ,     // right window
  57.      0,0,0,0,0,0,0,0,0,0,0,0 };
  58.  
  59. WORD stereo_type = MONOSCOPIC;
  60.  
  61.     // computes the static stereo factors for camera, caches
  62. void compute_camera_factors(CAMERA *c)
  63. {
  64.   STEREO *s = c->stereo;
  65.   STWINDOW *sw;
  66.   DWORD x_fixup;
  67.   DWORD world_iod;
  68.  
  69.   initialize_screen_factors(c->mono);
  70.  
  71.   if(!c->is_stereo) return;
  72.  
  73.   sw = &(s->window[0]);
  74.   c->left->x_offset = sw->xoff;
  75.   c->left->y_offset = sw->yoff;
  76.   c->left->orientation = sw->orientation;
  77.  
  78.   sw = &(s->window[1]);
  79.   c->right->x_offset = sw->xoff;
  80.   c->right->y_offset = sw->yoff;
  81.   c->right->orientation = sw->orientation;
  82.  
  83.   c->left->zoom = c->right->zoom =
  84.        (2*65536L * s->phys_screen_dist) / s->phys_screen_width;
  85.  
  86.   x_fixup = (s->phys_eye_spacing * s->phys_screen_dist * s->pixel_width ) /
  87.     (s->phys_convergence * 2 * s->phys_screen_width);
  88.  
  89.   world_iod = (s->phys_eye_spacing * s->world_scaling) >> 17;
  90.  
  91.   sw = &(s->window[0]);
  92.   c->left->x_offset = -sw->xoff - ((sw->orientation&XFLIP) ? -x_fixup : x_fixup) ;
  93.   std_matrix(sw->mat, sw->rx, -sw->ry, sw->rz, -world_iod, 0, 0);
  94.   c->left->left   = sw->l;
  95.   c->left->right  = sw->r;
  96.   c->left->top    = sw->t;
  97.   c->left->bottom = sw->b;
  98.   c->left->orientation = sw->orientation;
  99.   initialize_screen_factors(c->left);
  100.  
  101.   sw = &(s->window[1]);
  102.   c->right->x_offset = -sw->xoff - ((sw->orientation&XFLIP) ? x_fixup : -x_fixup) ;
  103.   std_matrix(sw->mat, sw->rx, sw->ry, sw->rz, world_iod, 0, 0);
  104.   c->right->left   = sw->l;
  105.   c->right->right  = sw->r;
  106.   c->right->top    = sw->t;
  107.   c->right->bottom = sw->b;
  108.   c->right->orientation = sw->orientation;
  109.   initialize_screen_factors(c->right);
  110. }
  111.  
  112.  
  113.  
  114.     // sets renderer to draw a view, mono or stereo view
  115.     // also copies segment position
  116. VIEW *select_camera_view(CAMERA *c, WORD which_eye)
  117. {
  118.   STEREO *s = c->stereo;
  119.   MATRIX e;
  120.   MATRIX *m = get_seg_pmatrix(c->seg);
  121.   VIEW *v = c->mono;
  122.  
  123.   matrix_view_factors(c->mono, *m);
  124.  
  125.   if(c->is_stereo)
  126.     {
  127.       if(which_eye==LEFT_EYE)
  128.     {
  129.       matrix_product(*m,s->window[0].mat,e);
  130.       matrix_view_factors(c->left,e);
  131.       v = c->left;
  132.     }
  133.       else
  134.     {
  135.       matrix_product(*m,s->window[1].mat,e);
  136.       matrix_view_factors(c->right,e);
  137.       v = c->right;
  138.     }
  139.     }
  140.   render_set_view(v);
  141.   return v;
  142. }
  143.  
  144.  
  145.  
  146. static VIEW *create_view()
  147. {
  148.  VIEW *v = calloc(sizeof(VIEW),1);
  149.  if(!v) return NULL;
  150.  v->zoom   = float2scale(2.0);
  151.  v->left   = screeninfo->xmin;
  152.  v->right  = screeninfo->xmax;
  153.  v->top    = screeninfo->ymin;
  154.  v->bottom = screeninfo->ymax;
  155.  v->aspect = screeninfo->aspect;
  156.  v->hither = 10L;
  157.  v->yon    = 134217728L;
  158.  return v;
  159. }
  160.  
  161.  
  162. STEREO *create_new_stereo(CAMERA *c, CAMERA *template)
  163. {
  164.   STEREO *sd = calloc(sizeof(STEREO),1);
  165.   STEREO *s = &default_stereo;
  166.  
  167.   if(!sd) return NULL;
  168.   if(template)
  169.     if(template->is_stereo)
  170.       s = template->stereo;
  171.   *sd = *s;
  172.   return sd;
  173. }
  174.  
  175.  
  176. STEREO *get_camera_stereo(CAMERA *c)
  177. {
  178.   return c->stereo;
  179. }
  180.  
  181.  
  182. STEREO *set_camera_stereo(CAMERA *c, STEREO *s)
  183. {
  184.   c->stereo = s;
  185.   compute_camera_factors(c);
  186. }
  187.  
  188.  
  189. CAMERA *create_camera(BOOL is_stereo, CAMERA *template)
  190. {
  191.  CAMERA *c = calloc(sizeof(CAMERA),1);
  192.  VIEW *v = NULL;
  193.  VIEW *vl=NULL, *vr=NULL;
  194.  
  195.  if(!c) return NULL;
  196.  if(!(v=create_view())) goto free_all;
  197.  if(template)
  198.    {
  199.      memcpy(c,template,sizeof(CAMERA));
  200.      is_stereo = template->is_stereo;
  201.    }
  202.  
  203.  c->is_stereo = is_stereo;
  204.  
  205.  if(is_stereo)
  206.    {
  207.      vl = create_view();
  208.      if(!vl) goto free_all;
  209.      vr = create_view();
  210.      if(!vr) goto free_all;
  211.      if(template)
  212.        {
  213.      memcpy(vl,&(template->left),sizeof(VIEW));
  214.      memcpy(vr,&(template->right),sizeof(VIEW));
  215.        }
  216.      else
  217.        {
  218.      c->stereo = &default_stereo;
  219.        }
  220.      c->left  = vl;
  221.      c->right = vr;
  222.    }
  223.  
  224.  c->mono = v;
  225.  c->seg = new_seg(NULL);
  226.  
  227.  if(c->seg)
  228.    {
  229.      register_system_segment(c->seg);
  230.      initialize_screen_factors(c->mono);
  231.      if(c->is_stereo) compute_camera_factors(c);
  232.    }
  233.   return c;
  234.  
  235. free_all:            // fail: dump memory
  236.   if(vl) free(vl);
  237.   if(vr) free(vr);
  238.   if(v)  free(v);
  239.   if(c)  free(c);
  240.  
  241.   return NULL;
  242. }
  243.  
  244.  
  245. void destroy_camera(CAMERA *c)
  246. {
  247.   if(c->is_stereo)
  248.     {
  249.       free(c->left);
  250.       free(c->right);
  251.     }
  252.   free(c->mono);
  253.   destroy_segment(c->seg);
  254.   free(c);
  255. }
  256.  
  257.     // attach camera to moveable object
  258. void attach_camera(CAMERA *c, OBJECT *obj)
  259. {
  260.   if(!is_object_moveable(obj)) return;
  261.   attach_object(c->seg, obj, 0);
  262.   update_object(obj);
  263. }
  264.  
  265.  
  266.     // detach camera
  267. void detach_camera(CAMERA *c)
  268. {
  269.   detach_object(c->seg, 1);
  270.   update_object(c->seg);
  271. }
  272.  
  273.  
  274. void set_camera_pose(CAMERA *c, POSE *p)
  275. {
  276.   seg_setpose(c->seg, p);
  277.   full_update_segment(c->seg);
  278. }
  279.  
  280.  
  281. void get_camera_localpose(CAMERA *c, POSE *p)
  282. {
  283.   seg_getpose(c->seg, p);
  284. }
  285.  
  286. void get_camera_worldpose(CAMERA *c, POSE *p)
  287. {
  288.   seg_getworldpose(c->seg, p);
  289. }
  290.  
  291. void get_camera_matrix(CAMERA *c, MATRIX m)
  292. {
  293.   matrix_copy(*get_seg_pmatrix(c->seg), m);
  294. }
  295.  
  296.     // computes coords of point in front of MONOSCOPIC camera
  297. void camera_point_ahead(CAMERA *c, COORD distance,
  298.             COORD *xp, COORD *yp, COORD *zp)
  299. {
  300.   MATRIX n;
  301.  
  302.   matrix_copy(*get_seg_pmatrix(c->seg), n);
  303.   *xp = 0;
  304.   *yp = 0;
  305.   *zp = distance;
  306.  
  307.   matrix_point(n, xp, yp, zp);
  308. }
  309.  
  310.  
  311.  
  312. void set_camera_zoom(CAMERA *c, SCALE zoom)
  313. {
  314.   c->mono->zoom = zoom;
  315. }
  316.  
  317. SCALE get_camera_zoom(CAMERA *c)
  318. {
  319.   return c->mono->zoom;
  320. }
  321.  
  322. void set_camera_window(CAMERA *c, WORD l, WORD t, WORD r, WORD b)
  323. {
  324.   c->mono->left   = l;
  325.   c->mono->top    = t;
  326.   c->mono->right  = r;
  327.   c->mono->bottom = b;
  328. }
  329.  
  330. void set_camera_hither(CAMERA *c, COORD h)
  331. {
  332.   if(h<1) return;
  333.   c->mono->hither = h;
  334.   if(c->is_stereo)
  335.     {
  336.       c->left->hither = h;
  337.       c->right->hither = h;
  338.     }
  339. }
  340.  
  341. COORD get_camera_hither(CAMERA *c)
  342. {
  343.   return c->mono->hither;
  344. }
  345.  
  346. void set_camera_yon(CAMERA *c, COORD y)
  347. {
  348.   if(y<1 || y>530000000L) return;
  349.   c->mono->yon = y;
  350.   if(c->is_stereo)
  351.     {
  352.       c->left->yon = y;
  353.       c->right->yon = y;
  354.     }
  355. }
  356.  
  357. COORD get_camera_yon(CAMERA *c)
  358. {
  359.   return c->mono->yon;
  360. }
  361.  
  362.  
  363.  
  364.