home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Zone / VRZONE.ISO / mac / PC / REND386 / JIREND / DEMO4.C < prev    next >
C/C++ Source or Header  |  1993-04-11  |  26KB  |  906 lines

  1. /* A simple user-interface demo -- Version 4 */
  2. /* Written by Bernie Roehl, February 1992 */
  3. /* Latest version (re)written June 1992 */
  4. /* Contact: broehl@sunee.waterloo.edu */
  5.   
  6. // revised by Jerry Isdale April 1993
  7. // define this to allow use of Global Devices Controller
  8. //#define GDC_AVAIL
  9.   
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <math.h>
  13. #include <ctype.h>   /* toupper() */
  14. #include <string.h>
  15. #include <mem.h>     /* memmove() */
  16. #include <dos.h>
  17. #include <signal.h>
  18. #include <bios.h>
  19.   
  20. #include "rend386.h"
  21. #include "userint.h"
  22. #include "intmath.h"
  23. #include "plg.h"
  24. #include "segio.h"
  25. #include "segasupp.h"
  26. #include "splits.h"
  27. #include "pointer.h"
  28. #include "tasks.h"
  29. #include "cursor.h"
  30. #include "f3dkitd.h"
  31. #include "eprint.h"
  32. #include "gdc.h"
  33.  
  34. //----------------------------------------------------  
  35. extern int read_world(FILE *in);
  36. void wrap(void); /* wrap-up function, shuts everything down */
  37. void polar_compute(void);
  38. void refresh_display(void);
  39. int load_logo(char *filename);
  40. void resize_viewport(void);
  41. void joystick_calibration(joystick_data *joy);
  42. void gather_data(OBJECT *obj);
  43. void prprint(int x,int y, int color, char *t);
  44. void status_on_screen(void);
  45.  
  46.  
  47. //----------------------------------------------------  
  48. extern unsigned _stklen = 10000;
  49.   
  50. #define XFSC 536870912   /* 2**29 for shifting xform coeffs to long */
  51.   
  52. /* default screen data setup */
  53.   
  54. STEREO default_stereo = {
  55. 600 , 240, 320, 50, 600, 1*65536L };
  56.   
  57. VIEW default_view = {
  58.    0,0,-8000, /* ex,ey,ez */
  59.    0,0,0, /* pan,tilt,roll */
  60.    4*65536L, /* zoom */
  61.    1000,15000,-5000, /* lx,ly,lz */
  62.    0,63, /* point, ambient */
  63.    0,319,0,200, /* left,right,top,bottom */
  64.    1,100000, /* hither, yon */
  65.    1/1.25*65536L, /* aspect ratio */
  66.    0, /* flags */
  67.    0,0, /* no offset */
  68.    0 /* no flip */
  69. }; /* don't init. matrix */
  70.   
  71. VIEW *current_view = &default_view;
  72.   
  73. VIEW orig_view; /* used for '*' key */
  74.   
  75. int v_page = 0; /* screen page swap variable */
  76.   
  77. OBJLIST *objlist; /* the linked list of objects in the scene */
  78.   
  79. int running = 1; /* non-zero until we're ready to exit */
  80. int redraw = 1; /* non-zero if we need a redraw */
  81. int review = 1; /* non-zero if we need to recompute current view */
  82. int reframe = 1; /* non-zero if we need to copy our frame back on-screen */
  83.   
  84. int do_horizon = 1;
  85.   
  86. int stereo_type = MONOSCOPIC;
  87.   
  88. extern int use_old_keys; /* NEED TO SET DISTANCE AS WELL ! */
  89.   
  90. int have_joystick = 0; /* non-zero if we have one or more joysticks */
  91. joystick_data joy;
  92.   
  93. long spacestep = 10L; /* "granularity" of motion */
  94.   
  95. unsigned lastkey = 0, nextolastkey = 0;
  96.   
  97. char *progname = "demo";
  98.   
  99. char vdname[40] = "vd256.rvd";
  100. int vdmode = 0x14;
  101.   
  102. char swdname[40] = "sega";
  103.   
  104. char mdname[40] = "mouse";
  105. PDRIVER *cursor_device = NULL; /* primary mouse device   */
  106. PDRIVER *menu_device = NULL; /* secondary mouse device */
  107. int manip_2D_avail = 0; /* can do mouse manipulation */
  108.   
  109. //----------------------------------------------------  
  110. // Extended Manipulation Device (Glove)
  111. char gpdname[40] = "pglove";
  112. char gpcursor[40] = "handsm.fig";
  113. float gpdo_x = 1, gpdo_y = 1, gpdo_z = 2;
  114. float gpdo_rx = 1, gpdo_ry = 1, gpdo_rz = 1;
  115. int have_glove = 0;
  116. int have_ptr = 0;
  117. PDRIVER *manip_device = NULL; // extended manip. device (glove or pointer)
  118.   
  119. //----------------------------------------------------  
  120. // Head Tracking Device
  121. char hdname[40] = "none";
  122. float hdo_x = 0, hdo_y = 0, hdo_z = 0; /* relative pos'n to neck */
  123. float hdo_rx = 0, hdo_ry = 0, hdo_rz = 0;
  124. PDRIVER *head_device = NULL; /* head tracking device   */
  125.   
  126. MATRIX head_tracker_map = {
  127. XFSC, 0, 0, 0, XFSC, 0, 0, 0, XFSC, 0, 0, 0 };
  128.   
  129. int sl_xflip = 0, sl_xoff = 0;
  130. long sl_left = -1, sl_top, sl_right, sl_bottom;
  131. int sr_xflip = 0, sr_xoff = 0;
  132. long sr_left = -1, sr_top, sr_right, sr_bottom;
  133. float sl_xrot = 0, sr_xrot = 0;
  134.   
  135. int use_glove = 0;
  136. int use_ht = 0;
  137. int use_wide = 0;
  138. int use_BW = 0;
  139. int swap_eyes = 0;
  140. int vd_loaded = 0;
  141.   
  142. //----------------------------------------------------  
  143. int fancy_background = 0; /* if set, we display a fancy background */
  144. int reflection_pool = 0; /* if set, draw a "reflecting pool" at the bottom of the screen */
  145. int have_logo = 0; /* if set, we have a logo */
  146. int show_logo = 0; /* if set, show the logo (if we have one) */
  147. int show_location = 1; /* if set, we display the current location on-screen */
  148. int show_compass = 1; /* if set, we display the 3-D compass on-screen */
  149. int show_framerate = 1; /* if set, we display the frames/second rate */
  150. int do_screen_clear = 1; /* by default, we clear the screen on each frame */
  151. int use_frame = 0; /* if set, draw a "frame" */
  152. int frame_x = 0, frame_y = 0; // frame origin
  153. int frame_w = 320, frame_h = 200; // frame size
  154.   
  155. //----------------------------------------------------  
  156. TASK *tasklist = NULL;
  157.   
  158. SPLIT *split_tree = NULL;
  159.   
  160. int npalette = 0; /* non-zero if we have a palette loaded */
  161. unsigned char palette[256*3];
  162.   
  163. char framefname[100];
  164.   
  165. extern struct Screeninfo *screeninfo;
  166. extern highest_color;
  167.   
  168. //----------------------------------------------------  
  169. char loadpath[100] = "";
  170. static char tempname[100];
  171.  
  172. char *fix_fname(char *name)
  173. {
  174.    if (loadpath[0] && !strchr(name, '\\') && !strchr(name, '/'))
  175.       sprintf(tempname, "%s\\%s", loadpath, name);
  176.    else
  177.       strcpy(tempname, name);
  178.    return tempname;
  179. }
  180.   
  181. //----------------------------------------------------  
  182. void *v_driver_pointer = NULL;
  183.   
  184. void load_video_driver(char *dfile)
  185. {
  186.    v_driver_pointer = load_driver(dfile);
  187.    if (v_driver_pointer == NULL)
  188.    {
  189.       fprintf(stderr,"Cannot read video driver %s\n", dfile);
  190.       exit(0);
  191.    }
  192. }
  193.   
  194. //----------------------------------------------------  
  195. void main(int argc, char *argv[])
  196. {
  197.    OBJECT *obj;
  198.    void joystick_calibration(), refresh_display();
  199.    unsigned getkey();
  200.    long x, y, z;
  201.    FILE *in;
  202.    int i;
  203.    PDRIVER *dm;
  204.    POINTER *p;
  205.    char *fname;
  206.   
  207.    if ((progname = strrchr(argv[0], '.')) != NULL) *progname = '\0';
  208.    progname = argv[0];
  209.   
  210.    if (getenv("REND386"))
  211.       strcpy(loadpath, getenv("REND386"));
  212.   
  213.    // Error Output File (eprintf)
  214.    // if not called, no output is done by eprintf calls
  215.    //eopenf("demo4.err");
  216.   
  217.    setup_render(40,800); /* # of K, # of polys */
  218.    atexit(wrap);
  219.    set_global_split_root(&split_tree);
  220.    initial_world_split(&split_tree);
  221.    set_move_handler(split_move_handler);
  222.    objlist = new_objlist();
  223.   
  224.    // Look for and load the config file
  225.    i = 1;
  226.    if(!stricmp(&(argv[1][0]), "/C"))
  227.    {
  228.       i = 2;
  229.       fname = &(argv[2][0]);
  230.    }
  231.    else fname = "rend386.cfg";
  232.   
  233.    if ((in = fopen(fname, "r")) == NULL)
  234.       fprintf(stderr, "Note -- config file '%s' not found; using defaults.\n", fname);
  235.    else
  236.    {
  237.       if (read_world(in))
  238.          fprintf(stderr, "Error reading config file '%s'\n", fname);
  239.       fclose(in);
  240.    }
  241.   
  242.    for (; i < argc; ++i)
  243.    {
  244.       if (argv[i][0] == '/' || argv[i][0] == '-')
  245.       {
  246.          switch(toupper(argv[i][1]))
  247.          {
  248.             case 'M':/* mirror stereo */
  249.                stereo_type = SPLITLR;
  250.             /* possibly problem here: assumes 320x200 mode before checking */
  251.                default_stereo.phys_screen_dist = 200;
  252.                default_stereo.phys_convergence = 700;
  253.                default_stereo.phys_screen_width = 120;
  254.                default_stereo.pixel_width = 160;
  255.                default_view.right = 159;
  256.                compute_stereo_data(&default_stereo, 0, 0, 0, 0, 0, 0, 159, 100);
  257.                compute_stereo_data(&default_stereo, 1, 1, 0, 0, 160, 0, 319, 100);
  258.                break;
  259.             case 'R':/* swap eyes on Sega driver */
  260.                swap_eyes = 1;
  261.                break;
  262.             case 'C':/* set conv. distance */
  263.                default_stereo.phys_screen_dist = atol(argv[++i]);
  264.                break;
  265.             case 'S':/* set world scale */
  266.                default_stereo.world_scaling = 65536.0*atof(argv[++i]);
  267.                break;
  268.             case 'E':/* set eye spacing */
  269.                default_stereo.phys_eye_spacing = atol(argv[++i]);
  270.                break;
  271.             case 'X':/* turn on stereo */
  272.                stereo_type = SWITCHED;
  273.                break;
  274.             case 'J':/* sort by object (default is polys) */
  275.                set_default_depth_sort(get_default_depth_sort() | BYOBJECT);
  276.                break;
  277.             case 'P':/* depth sort-- deepest */
  278.                set_default_depth_sort(get_default_depth_sort() & (~(BYOBJECT|AVERAGE|ATBACK)));
  279.                break;
  280.             case 'A':/* depth sort-- middle */
  281.                set_default_depth_sort(get_default_depth_sort() | AVERAGE);
  282.                break;
  283.             case '1':/* com 1 for SEGA */
  284.                select_sega_port(0x3FC);
  285.                break;
  286.             case '2':/* com 2 for SEGA */
  287.                select_sega_port(0x2FC);
  288.                break;
  289.             case 'G':/* enable glove */
  290.                use_glove = 1;
  291.                if(!have_ptr) have_glove = 1;
  292.                break;
  293.             case 'H':/* enable head tracker */
  294.                use_ht = 1;
  295.                break;
  296.             case 'W':/* enable wide-angle dual-VGA displays */
  297.                use_wide = 1;
  298.                stereo_type = SEPARATE;
  299.                default_stereo.phys_screen_dist = 50;
  300.                default_stereo.phys_convergence = 1200;
  301.                default_stereo.phys_screen_width = 115;
  302.                default_stereo.pixel_width = 320; /* hmm... may vary */
  303.                break;
  304.             case 'B':/* force all colors to monochrome */
  305.                use_BW = 1;
  306.                break;
  307.          }
  308.       }
  309.       else
  310.       {
  311.          char *in_filename;
  312.          in_filename = fix_fname(argv[i]);
  313.          if ((in = fopen(in_filename, "r")) == NULL)
  314.             fprintf(stderr, "Could not open '%s'\n", in_filename);
  315.          else
  316.             if (strstr(in_filename,".plg")) /* check if plg or fig file */
  317.             {
  318.                set_loadplg_offset(0,0,0);
  319.                set_loadplg_scale(1,1,1);
  320.                while ((obj = load_plg(in)) != NULL)
  321.                {
  322.                   SEGMENT *s;
  323.                   add_to_objlist(objlist, obj);
  324.                   if ((s = new_seg(NULL)) == NULL)
  325.                      fprintf(stderr, "Warning: out of memory while loading an object\n");
  326.                   else
  327.                   {
  328.                      seg_set_object(s, obj);
  329.                      set_object_owner(obj, s);
  330.                      update_segment(s);
  331.                   }
  332.                   if (spacestep < get_object_bounds(obj, &x, &y, &z)/5L)
  333.                      spacestep = get_object_bounds(obj, &x, &y, &z)/5L;
  334.                }
  335.                if (load_err)
  336.                {
  337.                   fprintf(stderr, "Load error: %d\n", load_err);
  338.                   getkey();
  339.                }
  340.             }
  341.             else if (strstr(in_filename,".fig")) /* check if plg or fig file */
  342.             {
  343.                SEGMENT *s;
  344.                int c;
  345.                set_readseg_objlist(objlist);
  346.                if ((s = readseg(in, NULL)) == NULL)
  347.                   fprintf(stderr, "Could not read '%s'\n", argv[i]);
  348.                else
  349.                   update_segment(s);
  350.             }
  351.             else {
  352.                if (read_world(in))
  353.                   fprintf(stderr, "Error reading world file\n");
  354.             }
  355.          fclose(in);
  356.       }
  357.    }
  358.   
  359.    have_joystick = joystick_check();
  360.   
  361.    load_video_driver(vdname);
  362.    screeninfo = screen_data();
  363.    highest_color = screeninfo->colors-1;
  364.    preset_default_colors();
  365.   
  366.    frame_x = screeninfo->xmin;
  367.    frame_y = screeninfo->ymin;
  368.    frame_w = screeninfo->xmax - screeninfo->xmin + 1;
  369.    frame_h = screeninfo->ymax - screeninfo->ymin + 1;
  370.   
  371.    /* Default view is full-screen: */
  372.    default_view.left = screeninfo->xmin;
  373.    default_view.top = screeninfo->ymin;
  374.    default_view.right = screeninfo->xmax;
  375.    default_view.bottom = screeninfo->ymax;
  376.    default_view.aspect = screeninfo->aspect;
  377.   
  378.    orig_view = default_view;
  379.   
  380.    if (enter_graphics())
  381.    {
  382.       fprintf(stderr, "Could not enter graphics mode\n");
  383.       exit(1);
  384.    }
  385.    vd_loaded++;
  386.   
  387.    frame_x = screeninfo->xmin;        /* reload in case driver changed it */
  388.    frame_y = screeninfo->ymin;
  389.    frame_w = screeninfo->xmax - screeninfo->xmin + 1;
  390.    frame_h = screeninfo->ymax - screeninfo->ymin + 1;
  391.   
  392.    /* Default view is full-screen: */
  393.    default_view.left = screeninfo->xmin;
  394.    default_view.top = screeninfo->ymin;
  395.    default_view.right = screeninfo->xmax;
  396.    default_view.bottom = screeninfo->ymax;
  397.    default_view.aspect = screeninfo->aspect;
  398.   
  399.   
  400.    signal(SIGABRT, wrap);
  401.    signal(SIGFPE, wrap);
  402.    signal(SIGILL, wrap);
  403.    signal(SIGINT, wrap);
  404.    signal(SIGSEGV, wrap);
  405.   
  406.    initialize_screen_factors(current_view);
  407.    fast_view_factors(current_view);
  408.   
  409.    if (npalette)
  410.       load_DAC_colors(palette, highest_color+1, use_BW);
  411.   
  412.    if (use_frame)
  413.    {
  414.       FILE *in;
  415.       use_frame = 0; /* we only set it back to 1 if we're successful */
  416.       if(stereo_type == MONOSCOPIC)
  417.          if ((in = fopen(fix_fname(framefname), "rb")) != NULL)
  418.          {
  419.             if (load_pcx(in, 3) == 0) use_frame = 1;
  420.             copy_block(3, 0, 0, 0, frame_x, frame_y, frame_w, frame_h);
  421.             copy_block(3, 0, 0, 1, frame_x, frame_y, frame_w, frame_h);
  422.             copy_block(3, 0, 0, 2, frame_x, frame_y, frame_w, frame_h);
  423.             fclose(in);
  424.          }
  425.    }
  426.   
  427.    init_body_links();
  428.   
  429.    if(stereo_type != MONOSCOPIC)
  430.    {
  431.       init_switch_driver(swdname);
  432.   
  433.       if(sl_left<0)
  434.       {
  435.          sl_left = default_view.left;
  436.          sl_right = default_view.right;
  437.          sl_top = default_view.top;
  438.          sl_bottom = default_view.bottom;
  439.       }
  440.       compute_stereo_data(&default_stereo, 0, sl_xflip, sl_xoff, 65536.0*sl_xrot,
  441.       sl_left, sl_top, sl_right, sl_bottom);
  442.   
  443.       if(sr_left<0)
  444.       {
  445.          sr_left = default_view.left;
  446.          sr_right = default_view.right;
  447.          sr_top = default_view.top;
  448.          sr_bottom = default_view.bottom;
  449.       }
  450.       compute_stereo_data(&default_stereo, 1, sr_xflip, sr_xoff, 65536.0*sr_xrot,
  451.       sr_left, sr_top, sr_right, sr_bottom);
  452.    }
  453.   
  454.    // Initialize Head Tracker
  455.    if(stricmp(hdname,"none") && use_ht)
  456.    {
  457.       extern PDRIVER *init_head_device(char *name, long x, long y, long z, long rx, long ry, long rz);
  458.       eprintf("Init Head Device: %s\n", hdname);
  459.       head_device = init_head_device(hdname, hdo_x, hdo_y, hdo_z,
  460.       hdo_rx*65536.0, hdo_ry*65536.0, hdo_rz*65536.0);
  461.    }
  462.    else eprintf("No Head Device: %s, use= %d\n", hdname, use_ht);
  463.   
  464.    // Initialize Mouse
  465.    if ((dm=mouseptr_init(mdname))!=NULL)
  466.    {
  467.       cursor_show(v_page);
  468.       manip_2D_avail++;
  469.    }
  470.    cursor_device = dm;
  471.    menu_device = dm;
  472.   
  473.    #ifdef GDC_AVAIL
  474.    // Initialize Global Devices Controller
  475.    if (use_gdc) gdc_init(use_gdc);
  476.    #endif // GDC_AVAIL
  477.   
  478.    // not going to be using powerglove
  479.    if ((!use_glove) || have_ptr || stricmp(gpdname,"pglove")) /* not going to be using powerglove */
  480.    {
  481.       if(stereo_type==SWITCHED)
  482.          init_SG_interrupt(switch_sega,NULL,6500);
  483.       else init_timer();
  484.    }
  485.   
  486.    // Using glove, initialize
  487.    if(use_glove && (!have_ptr))
  488.    {
  489.       extern SEGMENT *body_seg;
  490.       PDRIVER *gd;
  491.       extern PDRIVER *gloveptr_init(char *gname, long sx, long sy, long sz, long srx, long sry, long srz);
  492.   
  493.       gd = gloveptr_init(gpdname, gpdo_x*65536.0, gpdo_y*65536.0, gpdo_z*65536.0,
  494.       gpdo_rx*65536.0, gpdo_ry*65536.0, gpdo_rz*65536.0);
  495.       manip_device = menu_device = gd;
  496.       if(gd)
  497.          load_glove_cursor(body_seg, manip_device, gpcursor);
  498.       else have_glove = use_glove = 0;
  499.    }
  500.   
  501.    if(use_glove && have_ptr)
  502.    {
  503.       extern SEGMENT *body_seg;
  504.       PDRIVER *gd;
  505.       extern PDRIVER *gloveptr_init(char *gname, long sx, long sy, long sz, long srx, long sry, long srz);
  506.   
  507.       gd = gloveptr_init(gpdname, gpdo_x*65536.0, gpdo_y*65536.0, gpdo_z*65536.0,
  508.       gpdo_rx*65536.0, gpdo_ry*65536.0, gpdo_rz*65536.0);
  509.       manip_device = menu_device = gd;
  510.       if(gd)
  511.       {
  512.          set_loadplg_offset(0, 0, 0);
  513.          set_loadplg_scale(1, 1, 1);
  514.          load_3D_cursor(body_seg, manip_device, gpcursor);
  515.       }
  516.       else have_ptr = use_glove = 0;
  517.    }
  518.   
  519.    if ((have_joystick) != 0)
  520.    {
  521. #ifdef ASKUSER
  522.       popmsg("Joystick found -- use it?");
  523.       reframe = 1;
  524.       joystick_read(&joy);
  525.       while(!kbhit() && (joy.buttons==0)) joystick_read(&joy);
  526.       if(joy.buttons || toupper(getkey()) == 'Y')
  527.       {
  528.          refresh_display();
  529.          joystick_calibration(&joy);
  530.       }
  531.       else
  532.          have_joystick = 0;
  533.       refresh_display();
  534. #else
  535.       joystick_calibration(&joy);
  536. #endif
  537.    }
  538.   
  539.    while (running)
  540.    {
  541.       int x, y;
  542.       unsigned buttons;
  543.   
  544.       if (cursor_device) move_and_select_2D(cursor_device);
  545.   
  546.       if (have_joystick)
  547.          if (joystick_read(&joy))
  548.             do_joy(&joy);
  549.   
  550.       if (bioskey(1))
  551.       {
  552.          do_key(nextolastkey = getkey());
  553.          lastkey = nextolastkey;
  554.       }
  555.   
  556.    #ifdef GDC_AVAIL
  557.       if (use_gdc) gdc_UpdatePos();
  558.    #endif // GDC_AVAIL
  559.   
  560.   
  561.       if(head_device && use_ht) head_update(0);
  562.   
  563.       if (use_glove)
  564.       {
  565.          POINTER gp;
  566.          int g;
  567.   
  568.          if(!have_ptr)
  569.          {
  570.             glove_update(manip_device, &gp);
  571.             switch(gp.gesture)
  572.             {
  573.                case G_FIST :
  574.                   g = GRASP_DO;
  575.                   break;
  576.                case G_PINCH:
  577.                   g = ROTATE_DO;
  578.                   break;
  579.                case G_POINT:
  580.                   g = SELECT_DO;
  581.                   break;
  582.                default:
  583.                   g = FREE_DO;
  584.                   break;
  585.             }
  586.          }
  587.          else
  588.          {
  589.             cursor_update3D(manip_device, &gp);
  590.             switch(gp.buttons)
  591.             {
  592.                case 2:
  593.                   g = GRASP_DO;
  594.                   break;
  595.                case 3:
  596.                   g = ROTATE_DO;
  597.                   break;
  598.                case 1:
  599.                   g = SELECT_DO;
  600.                   break;
  601.                default:
  602.                   g = FREE_DO;
  603.                   break;
  604.             }
  605.          }
  606.   
  607.          manip_do(manip_device,g);
  608.       }
  609.   
  610.       run_tasks(tasklist);
  611.   
  612.       if (redraw) refresh_display();
  613.    }
  614. }
  615.  
  616. //----------------------------------------------------  
  617.   
  618. static char *closing_msg[] = {
  619.    "",
  620.    "The libraries used in this package are available on the Internet,",
  621.    "via anonymous ftp to sunee.uwaterloo.ca in pub/rend386.",
  622.    "",
  623.    "For more information, send e-mail to:",
  624.    "    Bernie Roehl  (broehl@sunee.uwaterloo.ca)",
  625.    "    Dave Stampe   (dstampe@sunee.uwaterloo.ca)",
  626.    "",
  627. NULL};
  628.   
  629. //----------------------------------------------------  
  630. void wrap(void) /* end program */
  631. {
  632.    int i;
  633.   
  634.    #ifdef GDC_AVAIL
  635.    if (use_gdc) gdc_remove();
  636.    #endif GDC_AVAIL
  637.   
  638.    if (have_joystick) joystick_quit();
  639.    if(vd_loaded) exit_graphics();
  640.    reset_render();
  641.    for (i = 0; closing_msg[i]; ++i)
  642.       fprintf(stderr, "%s\n", closing_msg[i]);
  643.    exit(0);
  644. }
  645.   
  646. //----------------------------------------------------  
  647. static l_x = 1000, l_y = 15000, l_z = -5000; /* light source */
  648.   
  649. long center_d = 10000;
  650. long center_x = 0;
  651. long center_y = 0;
  652. long center_z = 0;
  653. long latitude = 0;
  654. long longitude = 0;
  655. long center_roll = 0;
  656.   
  657. static long light_d = 1000000;
  658.   
  659. void polar_compute(void)
  660. {
  661.    MATRIX m,n;
  662.   
  663.    long x = 0;
  664.    long y = 0;
  665.    long z = -center_d;
  666.   
  667.    std_matrix(n,longitude,latitude,center_roll,0,0,0);
  668.   
  669.    matrix_point(n,&x,&y,&z);
  670.    current_view->ex = x + center_x;
  671.    current_view->ey = y + center_y;
  672.    current_view->ez = z + center_z;
  673.   
  674.    x = l_x;
  675.    y = l_y;
  676.    z = l_z;
  677.    matrix_point(n,&x,&y,&z);
  678.    current_view->lx = x;
  679.    current_view->ly = y;
  680.    current_view->lz = z;
  681.    current_view->pan = latitude;
  682.    current_view->tilt = longitude;
  683.    current_view->roll = center_roll;
  684. }
  685.   
  686. //----------------------------------------------------  
  687. void refresh_display(void)
  688. {
  689.    VIEW v;
  690.   
  691.    if (use_old_keys) polar_compute();
  692.    initialize_screen_factors(current_view);
  693.   
  694.    if(!(use_glove || head_device))
  695.    {
  696.       fast_view_factors(current_view);
  697.       screen_refresh(current_view);
  698.    }
  699.    else
  700.    {
  701.       body_centric_map(current_view, &v);
  702.       screen_refresh(&v);
  703.    }
  704.   
  705.    redraw = 0;
  706. }
  707.   
  708. //----------------------------------------------------  
  709. int load_logo(char *filename)
  710. {
  711.    char far *buffer;
  712.    FILE *in;
  713.    if ((in = fopen(fix_fname(filename), "rb")) == NULL) return 0;
  714.    if (load_pcx(in, 3)) { /* some sort of problem loading it in */
  715.       fclose(in);
  716.       return 0;
  717.    }
  718.    fclose(in);
  719.    return 1; /* all is well... we have a logo */
  720. }
  721.   
  722. //----------------------------------------------------  
  723. void resize_viewport(void)
  724. {
  725.    int top, left, bottom, right;
  726.    unsigned buttons;
  727.    cursor_hide();
  728.    clear_display(v_page);
  729.    cursor_show(v_page);
  730.    popmsg("Click top-left and drag");
  731.    do {
  732.       move_2D(cursor_device, &left, &top, &buttons);
  733.    }
  734.    while (buttons == 0);
  735.    while (buttons) {
  736.       while (!move_2D(cursor_device, &right, &bottom, &buttons));
  737.       clear_display(v_page);
  738.       vgabox(left, top, right, bottom, 15);
  739.    }
  740.    if (right - left > 10) {
  741.       current_view->left = left & (~0x0007); /* always on a 16-pixel boundary */
  742.       current_view->right = (right & (~0x0007)) + 7;
  743.    }
  744.    if (bottom - top > 10) {
  745.       current_view->top = top;
  746.       current_view->bottom = bottom;
  747.    }
  748.   
  749.    if(stereo_type == SWITCHED)  /* makes sense for Sega only (no shift) */
  750.    {
  751.       compute_stereo_data(&default_stereo, 0, sl_xflip, sl_xoff, 65536.0*sl_xrot,
  752.       current_view->left, current_view->top, current_view->right, current_view->bottom);
  753.       compute_stereo_data(&default_stereo, 1, sr_xflip, sr_xoff, 65536.0*sr_xrot,
  754.       current_view->left, current_view->top, current_view->right, current_view->bottom);
  755.    }
  756.   
  757.    /* Make sure all pages are refreshed: */
  758.    reset_screens();
  759.    refresh_display();
  760. }
  761.   
  762. /* Some support routines */
  763.   
  764. static void center(char *s, int w)
  765. {
  766.    int n;
  767.   
  768.    if (strlen(s) == 0) return;
  769.    n = (w - strlen(s)) /2;
  770.    memmove(&s[n], s, strlen(s)+1);
  771.    memset(s, ' ', n);
  772. }
  773.   
  774. //----------------------------------------------------  
  775. void joystick_calibration(joystick_data *joy)
  776. {
  777.    if (have_joystick == 0) return;
  778.    if (have_joystick & 1) joystick_init(joy, 0);
  779.    else if (have_joystick & 2) joystick_init(joy, 1);
  780.   
  781.    joystick_setscale(joy, 100);
  782.    reframe = 1;
  783. }
  784.   
  785. //----------------------------------------------------  
  786. void disp_status(VIEW *v)
  787. {
  788.    char *text[9], a[80], b[80], c[80], d[80], e[80], f[80], g[80];
  789.    int w, i;
  790.   
  791.    text[0] = a;
  792.    text[1] = "";
  793.    text[2] = b;
  794.    text[3] = c;
  795.    text[4] = d;
  796.    text[5] = e;
  797.    text[6] = f;
  798.    text[7] = g;
  799.    text[8] = NULL;
  800.    sprintf(a, "STATUS");
  801.   
  802.    sprintf(b, "X = %ld  Y = %ld  Z = %ld", v->ex, v->ey, v->ez);
  803.    w = strlen(b);
  804.    sprintf(c, "Pan = %ld   Tilt = %ld   Roll = %ld  ", v->pan/65536L, v->tilt/65536L, v->roll/65536L);
  805.    if (strlen(c) > w) w = strlen(c);
  806.    sprintf(d, "Zoom = %ld", v->zoom/65536L);
  807.    if (strlen(d) > w) w = strlen(d);
  808.    sprintf(e, "Hither = %ld  Yon = %ld", v->hither, v->yon);
  809.    if (strlen(e) > w) w = strlen(e);
  810.   
  811.    if (have_joystick)
  812.    {
  813.       joystick_read(&joy);
  814.       sprintf(f, "Joystick = %d,%d", joy.x, joy.y);
  815.       if (strlen(f) > w) w = strlen(f);
  816.    }
  817.    else
  818.       text[6] = NULL;
  819.    text[7] = NULL;
  820.   
  821.    for (i = 0; text[i]; ++i) center(text[i], w);
  822.    poptext(text);
  823.    reframe = 1;
  824.    getkey();
  825. }
  826.   
  827. //----------------------------------------------------  
  828. static int gnobjs, gnverts, gnpolys;
  829.   
  830. void gather_data(OBJECT *obj)
  831. {
  832.    int nv = 0, np = 0;
  833.    get_obj_info(obj, &nv, &np);
  834.    ++gnobjs;
  835.    gnverts += nv;
  836.    gnpolys += np;
  837. }
  838.   
  839. void disp_info(void)
  840. {
  841.    OBJECT *obj;
  842.    char buff[100];
  843.    gnobjs = 0, gnverts = 0, gnpolys = 0;
  844.   
  845.    walk_split_tree(split_tree, gather_data);
  846.    sprintf(buff, "%d object%s, %d vertice%s, %d polygon%s", gnobjs,
  847.       (gnobjs == 1) ? "" : "s", gnverts, (gnverts == 1) ? "" : "s",
  848.       gnpolys, (gnpolys == 1) ? "" : "s");
  849.    popmsg(buff);
  850.    reframe = 1;
  851.    getkey();
  852. }
  853.   
  854. // ---------------------------------------------------  
  855. extern AREA *areas;
  856.   
  857. extern POINTER gloveptr;
  858.   
  859. char *gest[] = {
  860.    "FLAT", "THUMB_IN", "INDEX_IN", "MIDDLE_IN",
  861.    "RING_IN", "PINCH", "FIST", "THUMB_OUT", "POINT",
  862. "BADFINGER", "RING_OUT", "??????" };
  863.   
  864. void prprint(int x,int y, int color, char *t)
  865. {
  866.    int bk = (color>8) ? 0 : 15;
  867.   
  868.    printxyr(x,y,bk,t,0);
  869.    printxyr(x+1,y+1,color,t,0);
  870. }
  871.   
  872. void status_on_screen(void)
  873. {
  874.    char buff[100];
  875.    AREA *a, *what_area();
  876.    long floor_at(), ceiling_at();
  877.   
  878.    if (show_location == 0) 
  879.       return;
  880.   
  881.    sprintf(buff, "Pos(x,z): %ld,%ld", current_view->ex, current_view->ez);
  882.    prprint(2,3,15,buff);
  883.    sprintf(buff, "Not in any area");
  884.    a = what_area(split_tree, current_view->ex, current_view->ey, current_view->ez);
  885.    if (a)
  886.    {
  887.       extern char *find_value();
  888.       char *p = find_value(areas, a);
  889.       if (p)
  890.          sprintf(buff, "Area: %s", p);
  891.    }
  892.    prprint(2,15,15,buff);
  893.   
  894.    if (use_glove)
  895.    {
  896.       int sl;
  897.       POINTER p;
  898.   
  899.       last_pointer(manip_device, &p);
  900.       sprintf(buff,"Glove: %s",gest[p.gesture]);
  901.       sl = strlen(buff)<<3;
  902.       prprint(300-sl,3,15,buff);
  903.    }
  904. }
  905.   
  906.