home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Zone / VRZONE.ISO / mac / PC / PCGLOVE / RACBALL / RB.C < prev    next >
C/C++ Source or Header  |  1992-10-17  |  23KB  |  879 lines

  1. /* This program requires Release 4.01 of Rend386 to compile */
  2.  
  3.  
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <dos.h>
  7. #include <math.h>
  8. #include "rend386.h"
  9. #include "userint.h"
  10. #include "plg.h"
  11. #include "splits.h"
  12. #include "tasks.h"
  13. #include "pointer.h"
  14. #include "cursor.h"
  15. #include "segasupp.h"
  16. #include "segio.h"
  17. #include "intmath.h"
  18.  
  19. #define to_rad(a) ((a) * 3.14159262 / 180.0)
  20. #define sine(x)   sin(to_rad(x/65536L))
  21. #define cosine(x) cos(to_rad(x/65536L))
  22.  
  23. #define CEILING    2400
  24. #define FLOOR         0
  25. #define LEFT_WALL   500
  26. #define RIGHT_WALL 3650
  27. #define BACK_WALL     0
  28. #define FRONT_WALL 4000
  29.  
  30.  
  31. /* Global variables */
  32. /* This is our main object list.
  33.    Files used:  keyboard, world, cursors
  34. */
  35. OBJLIST      *objlist;
  36.  
  37. /* This is the default values for stereo viewing.
  38.    Files used:  keyboard, world, render
  39. */
  40. STEREO         default_stereo = {600,240,320,50,600, 1*65536L};
  41.  
  42. /* This variable indicates the type of viewing.
  43.    Declared in file: render.c
  44.    Files used: keyboard, gloveptr, world, render
  45. */
  46. int         stereo_type = MONOSCOPIC;
  47.  
  48. /* This variable declares the default startup view of the program.
  49.    Files used: keyboard, world
  50. */
  51. VIEW         default_view =  {
  52.                 0,0,-1000,
  53.                 0,0,0,
  54.                 9*65536L,
  55.                 1000,15000,-5000,
  56.                 0,319,0,199,
  57.                 1,100000,
  58.                 1/1.25*65535L,
  59.                 0
  60.                 };
  61.  
  62. /* This pointer points to the location of the default view
  63.    Files used: keyboard, world, render
  64. */
  65. VIEW         *current_view = &default_view;
  66.  
  67. /* This pointer in the beginning of the split tree for the program.  We
  68.    will only one however, that is not a requirement.
  69.    Files used: keyboard, world, render, cursors, hdmanip
  70. */
  71. SPLIT           *split_tree = NULL;
  72.  
  73. /* This variable holds a palette.
  74.    Files used: world
  75. */
  76. unsigned char     palette[256*3];
  77.  
  78. /* This pointer is the start of a set of tasks.
  79.    Files used: world
  80. */
  81. TASK         *tasklist = NULL;
  82.  
  83. /* This pointer holds a handle to the current video driver installed.
  84.    Files used: main program
  85. */
  86. void        *v_driver_pointer = NULL;
  87.  
  88. /* This variable holds a loadpath specified in the configuration file or
  89.    in a world file.
  90.    Files used: world
  91. */
  92. char         loadpath[100] = "";
  93.  
  94. /* This variable holds a temporary filename including a loadpath.
  95.    Files used: main program
  96. */
  97. static char     tempname[100];
  98.  
  99.  
  100. char         framefname[100];
  101.  
  102. /* Delcares an extern function. */
  103. extern void     *screen_data();
  104.  
  105. /* This variable is used to hold information about the current screen setup.
  106.    File used: gloveptr, mouseptr, render, userint
  107. */
  108. extern struct     Screeninfo *screeninfo;
  109.  
  110. /* This variable is used in the userint file.  Purpose ?
  111. */
  112. PDRIVER     *menu_device = NULL;
  113. PDRIVER        *manip_device = NULL;
  114.  
  115. /* These variable are used as the configuration settings for the glove
  116.    pointer device, translation and rotation.
  117.    Files used: world
  118. */
  119. float         gpdo_x = 2, gpdo_y = 2, gpdo_z = 2,
  120.         gpdo_rx = 1, gpdo_ry = 1, gpdo_rz = 1;
  121.  
  122. /* These varaiables are used as the configuration settings for the head
  123.    tracker device, relative position to neck, and rotation. */
  124. float         hdo_x = 0, hdo_y = 0, hdo_z = 0; /* relative pos'n to neck */
  125. float         hdo_rx = 0, hdo_ry = 0, hdo_rz = 0;
  126.  
  127. /* These variables are used as the configuration settings for the STEREOLEFT
  128.    command in a world file.  Check world.doc for description.
  129.    Files used: world keyboard
  130. */
  131. int         sl_xflip = 0, sl_xoff = 0;
  132. long         sl_left = -1, sl_top, sl_right, sl_bottom;
  133.  
  134. /* These variables are used as the configuration settings for the
  135.    STEREORIGHT command in a world file.  Check world.doc for description.
  136.    Files used: world keyboard
  137. */
  138. int         sr_xflip = 0, sr_xoff = 0;
  139. long         sr_left = -1, sr_top, sr_right, sr_bottom;
  140.  
  141. /* These variables are used as the configuration settings for the rotation
  142.    of the STEREORIGHT and STEREOLEFT commands in the world file.  Check
  143.    world.doc for description.
  144.    Files used: world keyboard.
  145. */
  146. float         sl_xrot = 0, sr_xrot = 0;
  147.  
  148. /* This variable indicates whether or not a glove is being used.
  149.    0 = false.
  150.    Files used: cursors hdmanip
  151. */
  152. int         use_glove = 1;
  153.  
  154. /* This variable indicates whether or not a head tracker is being used.
  155.    0 = false.
  156.    Files used: render
  157. */
  158. int         use_ht = 0;
  159.  
  160. /* This variable indicates whether or not a wide-angle dual VGA
  161.    head mounted display system is being used.
  162.    0 = false.
  163.    Files used: render
  164. */
  165. int         use_wide = 0;
  166.  
  167. /* This variable indicates whether or not a monochrome system is being used.
  168.    0 = false.
  169.    Files used: render
  170. */
  171. int         use_BW = 0;
  172.  
  173. /* This variable is set to 1 if the eyes are to be switched when using
  174.    the Sega 3D glasses.
  175.    Files used: render
  176. */
  177. int         swap_eyes = 0;
  178.  
  179. /* This variable is set to display a fancy background
  180.    Files used: keyboard render
  181. */
  182. int         fancy_background = 0;
  183.  
  184. /* This variable is set to draw a reflection pool at the bottom of the
  185.    screen.
  186.    Files used: keybaord render
  187. */
  188. int         reflection_pool = 0;
  189.  
  190. /* This variable is set to indicate we have a logo to display.
  191.    Files used: render
  192. */
  193. int         have_logo = 0;
  194.  
  195. /* This variable is set to show our logo, if we have one.
  196.    Files used: render keyboard
  197. */
  198. int         show_logo = 0;
  199.  
  200. /* This variable is set to show the current location on-screen.
  201.    Files used: render keyboard
  202. */
  203. int         show_location = 0;
  204.  
  205. /* This variable is set to show the 3D compass on-screen.
  206.    Files used: render keyboard
  207. */
  208. int         show_compass = 0;
  209.  
  210. /* This variable is set to display the frames/second rate on-screen.
  211.    Files used: render keyboard
  212. */
  213. int         show_framerate = 0;
  214.  
  215. /* This variable is set to clear the screen on each frame.
  216.    Files used: render world keyboard
  217. */
  218. int         do_screen_clear = 1;
  219.  
  220. /* This variable is set to draw a "frame".
  221.    Files used: world render
  222. */
  223. int         use_frame = 0;
  224.  
  225. /* These variabels define the location of a "frame".
  226.    Files used: world render
  227. */
  228. int         frame_x = 0, frame_y = 0, frame_w = 320, frame_h = 200;
  229.  
  230. /* This variable is set to the current display mode to use.
  231.    Files used: render world
  232. */
  233. int        vdmode = 0x14;
  234.  
  235. /* This variable is set to 1 if we need to recompute the current view.
  236.    Files used: world keyboard
  237. */
  238. int         review = 1;
  239.  
  240. /* This variable is set to 1 if we need to copy our gram back on-screen.
  241.    Files used: keyboard world colormap render rendrep
  242. */
  243. int         reframe = 0;
  244.  
  245.  
  246. /* This variable is set if the shift key is used by the user.
  247.    Files used: main program keyboard
  248. */
  249. int         shifted = 0;
  250.  
  251. /* This variable is used to hold the current visual page being used.
  252.    Files used: render userint
  253. */
  254. int        v_page = 0;
  255.  
  256. /* This variable is set if a glove is available.
  257.    Files used: world cursors
  258. */
  259. int         have_glove = 1;
  260.  
  261. /* This variable is set if a pointer device is available.
  262.    Files used: world cursors
  263. */
  264. int         have_ptr = 0;
  265.  
  266. /* This variable is set if we can do mouse manipulations.
  267.    Files used: keyboard
  268. */
  269. int         manip_2D_avail = 0;
  270.  
  271. /* This variable is set to run the main execution loop.
  272.    Files used: main
  273. */
  274. int             execution = 1;
  275.  
  276. /* This variable is set to indicate a screen redraw is necessary.
  277.    Files used: keyboard anim world cursors render hdmanip
  278. */
  279. int        redraw = 1;
  280.  
  281. /* This variable is set if a horizon should be drawn.
  282.    Files used: keyboard render colormap
  283. */
  284. int        do_horizon = 1;
  285.  
  286. /* This variable is not necessary because it is define elsewhere and can
  287.    be set with a world file.  It is the color the system paints the top
  288.    half of the screen after it is cleared; if the do_horizon variable is
  289.    set to 1.
  290.    Files used: world render colormap
  291. */
  292. extern         sky_color;
  293.  
  294. /* This variable is not necessary because it is define elsewhere and can
  295.    be set with a world file.  It is the color the system paints the bottom
  296.    half of the screen after it is cleared; if the do_horizon variable is
  297.    set to 1.
  298.    Files used: world render colormap
  299. */
  300. extern        ground_color;
  301.  
  302. /* This variable is not necessary because it is define elsewhere and can
  303.    be set with a world file.  It is the color the system paints the screen
  304.    after it is cleared; if the do_horizon variable is set to 0.
  305.    Files used: world render colormap
  306. */
  307. extern int      screen_clear_color;
  308.  
  309.  
  310. /* This variable holds the highest possible color value.
  311.    Files used: render colormap
  312. */
  313. extern         highest_color;
  314.  
  315. /* This variable is set to 0 if no palette is loaded and
  316.    non-zero if a palette is loaded
  317.    Files used: world
  318. */
  319. int         npalette = 0;
  320.  
  321. /* This variable holds the name of the current switcher driver.
  322.    Files used: world
  323. */
  324. char         swdname[40] = "sega";
  325.  
  326. /* This variable holds the name of the current glove pointer driver.
  327.    Files used: world
  328. */
  329. char         gpdname[40] = "pglove";
  330.  
  331. /* This variable holds the name of the current head tracker driver.
  332.    Files used: world
  333. */
  334. char         hdname[40] = "none";
  335.  
  336. /* This variable holds the name of the glove pointer driver cursor figure.
  337.    Files used: world
  338. */
  339. char         gpcursor[40] = "handsm.fig";
  340.  
  341. /* This variable holds the name of the current video driver.
  342.    Files used: main program and world
  343. */
  344. char            vdname[40] = "vd256.rvd";
  345.  
  346. /* This variable holds the name of the current mouse driver.
  347.    Files used: world
  348. */
  349. char            mdname[40] = "none";
  350.  
  351. int head_device = 0;
  352. int BALL_SPEED = 10;
  353. extern SEGMENT *body_seg;
  354.  
  355.  
  356. /**************************************************************************
  357.    This function is used by the file render.c to display various things
  358.    on the screen to the user.  This is not needed by any program just
  359.    an option.  However, render.c needs access to this function
  360. ***************************************************************************/
  361. void status_on_screen()
  362. {
  363. }
  364.  
  365.  
  366. /**************************************************************************
  367.    This function concatenates the loadpath to the string name IF
  368.    name is not "\\" and not "/" and loadpath is not empty.  It is used by
  369.    the files: world.c.
  370. **************************************************************************/
  371. char *fix_fname(char *name)
  372. {
  373.  
  374.     if (loadpath[0] && !strchr(name, '\\') && !strchr(name, '/'))
  375.         sprintf(tempname, "%s\\%s", loadpath, name);
  376.     else
  377.         strcpy(tempname, name);
  378.     return tempname;
  379. }
  380.  
  381.  
  382. /**************************************************************************
  383.   This function is called when the user ends the graphics program.  It
  384.   shuts done the graphics system and exits the renders and finally exits
  385.   the progam.
  386. **************************************************************************/
  387. void closeall(){
  388.   exit_graphics();
  389.   reset_render();
  390.   exit(0);
  391. }
  392.  
  393.  
  394.  
  395. /**************************************************************************
  396.    This function is from Rend386 demo2.c program and is used to get
  397.    keyboard input from the user.
  398. ***************************************************************************/
  399. unsigned getkey(){
  400.   unsigned c;
  401.   union REGS regs;
  402.  
  403.   regs.h.ah = 2;
  404.   int86(0x16, ®s,®s );
  405.   shifted = (regs.h.al & 3);
  406.   if ((c=bioskey(0)) & 0xff) c &= 0xff;
  407.   else if ( shifted ) c |= 1;
  408.   return c;
  409. }
  410.  
  411.  
  412.  
  413. /**************************************************************************
  414.    This function handles keys pressed by the user.Handle any user keys.
  415. **************************************************************************/
  416. void handle_key ( unsigned int c ){
  417. FILE *infile;
  418.  
  419.   switch ( c ) {
  420.     case 'q':
  421.     case 'Q':popmsg ( "Do you wish to quit? (y/n)" );
  422.          if ( toupper(getkey())== 'Y' ) execution = 0;
  423.          else redraw = 1;
  424.          break;
  425.  
  426.     /* Look up. Step by 1 angle value */
  427.     case 0x4800: current_view->tilt += 65536L;
  428.          redraw = 1;
  429.          break;
  430.  
  431.     /* Look down. Step by 1 angle value */
  432.     case 0x5000: current_view->tilt -= 65536L;
  433.          redraw = 1;
  434.          break;
  435.  
  436.     /* Look to the left.  Step by 1 angle value */
  437.     case 0x4B00: current_view->pan -= 65536L;
  438.          redraw = 1;
  439.          break;
  440.  
  441.     /* Look to the right.  Step by 1 angle value */
  442.     case 0x4D00: current_view->pan += 65536L;
  443.          redraw = 1;
  444.          break;
  445.  
  446.  
  447.     case 'Y':
  448.     case 'y': rel_rot_segment ( body_seg, 0L, 90*65536L, 0L, RYXZ );
  449.           update_segment ( body_seg );
  450. /*          current_view->pan += 90*65536L;  */
  451.           redraw = 1;
  452.           break;
  453.  
  454.     case 'b':
  455.     case 'B': current_view->ex -= 50L * sine(current_view->pan);
  456.           current_view->ez -= 50L * cosine(current_view->pan);
  457.           rel_move_segment ( body_seg, -50L*sine(current_view->pan),
  458.                        0,
  459.                        -50L*cosine(current_view->pan));
  460.           update_segment ( body_seg );
  461.  
  462.           redraw = 1;
  463.           break;
  464.  
  465.     case 'f':
  466.     case 'F': current_view->ex += 50L * sine(current_view->pan);
  467.           current_view->ez += 50L * cosine(current_view->pan);
  468.  
  469.           rel_move_segment ( body_seg, 50L*sine(current_view->pan),
  470.                        0,
  471.                        50L*cosine(current_view->pan));
  472.           update_segment ( body_seg );
  473.           redraw = 1;
  474.           break;
  475.  
  476.     case 'r':
  477.     case 'R': current_view->ex += 50L * cosine(current_view->pan);
  478.           current_view->ez -= 50L * sine(current_view->pan);
  479.           rel_move_segment ( body_seg, +50L*cosine(current_view->pan),
  480.                        0,
  481.                        -50L*sine(current_view->pan));
  482.           update_segment ( body_seg );
  483.           redraw = 1;
  484.           break;
  485.  
  486.     case 'l':
  487.     case 'L': current_view->ex -= 50L * cosine(current_view->pan);
  488.           current_view->ez += 50L * sine(current_view->pan);
  489.           rel_move_segment ( body_seg, -50L*cosine(current_view->pan),
  490.                        0,
  491.                        +50L*sine(current_view->pan));
  492.           update_segment ( body_seg );
  493.           redraw = 1;
  494.           break;
  495.  
  496.  
  497.   }
  498. }
  499.  
  500.  
  501.  
  502. /**************************************************************************
  503.   This function performs the updating of the screen after any object or
  504.   perspective movements.  The majority of the work is done in the
  505.   function screen_refresh in the file render.c
  506. **************************************************************************/
  507. void refresh_display(){
  508.  
  509.   initialize_screen_factors ( current_view );
  510.   fast_view_factors ( current_view );
  511.   screen_refresh ( current_view );
  512.  
  513. }
  514.  
  515.  
  516.  
  517. int    x_position,
  518.     y_position,
  519.     z_position,
  520.     inc_val_x,
  521.     inc_val_y,
  522.     inc_val_z;
  523. /**************************************************************************
  524.   This function moves the ball according to the racquet hit and the
  525.   boundaries of the court.
  526. **************************************************************************/
  527. void move_ball(SEGMENT *BALL)
  528. {
  529.   y_position+=inc_val_y;
  530.   if ( y_position > CEILING )
  531.     {
  532.       inc_val_y = -BALL_SPEED; /* (rand() % 50);*/
  533.       y_position+=inc_val_y;
  534.     }
  535.   else if ( y_position <= FLOOR )
  536.     {
  537.       inc_val_y = BALL_SPEED; /* (rand() %50); */
  538.       y_position+=inc_val_y;
  539.     }
  540.  
  541.  
  542.   x_position+=inc_val_x;
  543.   if ( x_position > RIGHT_WALL )
  544.     {
  545.       inc_val_x = -BALL_SPEED; /*(rand() %50);*/
  546.       x_position+=inc_val_x;
  547.     }
  548.   else if (x_position < LEFT_WALL )
  549.     {
  550.       inc_val_x = BALL_SPEED; /*(rand() % 50);*/
  551.       x_position+=inc_val_x;
  552.     }
  553.  
  554.  
  555.   if ( inc_val_z > BALL_SPEED ) inc_val_z -= 1;
  556.   if ( inc_val_z < -BALL_SPEED ) inc_val_z += 1;
  557.   z_position+=inc_val_z;
  558.   if ( z_position > FRONT_WALL )
  559.     {
  560.       inc_val_z = -BALL_SPEED; /*(rand() % 50); */
  561.       z_position+=inc_val_z;
  562.     }
  563.   else if ( z_position <= BACK_WALL )
  564.     {
  565.       inc_val_z = BALL_SPEED; /* (rand() % 50);*/
  566.       z_position+=inc_val_z;
  567.     }
  568.  
  569.   abs_move_segment ( BALL, x_position, y_position, z_position );
  570.   update_segment ( BALL );
  571.  
  572. }
  573.  
  574.  
  575. void prprint(int x,int y, int color, char *t)
  576. {
  577.     int bk = (color>8) ? 0 : 15;
  578.  
  579.     printxyr(x,y,bk,t,0);
  580.     printxyr(x+1,y+1,color,t,0);
  581. }
  582.  
  583.  
  584. SEGMENT *palm;
  585. OBJECT  *palm_object;
  586. OBJECT  *handle;
  587. /**************************************************************************
  588.   This function performs the functions of the program.  The loop terminates
  589.   when execution = 1.
  590. **************************************************************************/
  591. void main_loop(SEGMENT *BALL, SEGMENT *RACQUET){
  592.   POINTER gp;
  593.   OBJECT *racquet_object;
  594.   OBJECT *ball_object;
  595.   long x,y,z,rad;
  596.  
  597.   int NO_RACQUET = 1;
  598.   char buf[100];
  599.   long dist;
  600.  
  601.   racquet_object = seg_get_object(find_segment_by_name(RACQUET, "racquet"));
  602.   ball_object = seg_get_object (BALL);
  603.   rad = get_object_bounds ( handle, &x, &y, &z );
  604.  
  605.   while ( execution )
  606.     {
  607.       if (bioskey(1))     handle_key (getkey());
  608.       if (redraw)     refresh_display();
  609.       move_ball(BALL);
  610.  
  611.       glove_update( manip_device, &gp );
  612.       update_segment ( body_seg );
  613.  
  614.  
  615.       if ( NO_RACQUET )
  616.     {
  617.       dist = sphere_pretest (palm_object,x,y,z);
  618.       sprintf(buf, "Racquet dist: %ld", dist);
  619.       prprint(2,3,15,buf);
  620.       if (( dist < 100 ) && (gp.gesture == G_FIST ))
  621.         {
  622.           attach_segment ( RACQUET, palm );
  623.           NO_RACQUET = 0;
  624.         }
  625.  
  626.     }
  627.  
  628.       if (!NO_RACQUET)
  629.       {
  630.      rad = get_object_bounds ( ball_object, &x, &y, &z );
  631.      dist = sphere_pretest ( racquet_object, x, y, z );
  632.      sprintf(buf, "Ball dist: %ld", dist );
  633.      prprint ( 2, 3, 15, buf );
  634.      if (dist<300)
  635.        {
  636.          if ( inc_val_z < 0 )
  637.            inc_val_z = BALL_SPEED*5;
  638.          else
  639.            inc_val_z = -BALL_SPEED*5;
  640.          z_position += inc_val_z;
  641.        }
  642.       }
  643.  
  644.     }
  645. }
  646.  
  647.  
  648.  
  649. /**************************************************************************
  650.   This function is called to load video drivers.  The pointer
  651.   v_driver_pointer is set to a handle representing the video driver.
  652.   The variable v_driver_pointer is used by the files: main only.
  653. **************************************************************************/
  654. void load_video_driver ( char *dfile )
  655. {
  656.   v_driver_pointer = load_driver ( dfile );
  657.   if ( v_driver_pointer == NULL )
  658.   {
  659.     fprintf ( stderr, "Bad video driver/n" );
  660.     exit ( 1 );
  661.   }
  662. }
  663.  
  664.  
  665.  
  666. /**************************************************************************
  667.   This function is used to read the racquetball used in the game and
  668.   assign it to a segment called ball_seg which is returned to the caller.
  669. **************************************************************************/
  670. SEGMENT * read_ball()
  671. {
  672.   FILE *in;
  673.   OBJECT *ball;
  674.   SEGMENT *ball_seg;
  675.  
  676.   if ((in = fopen ( "ball.plg", "r" )) == NULL )
  677.     {
  678.       fprintf ( stderr, "Unable to open ball file.\n" );
  679.       exit(1);
  680.     }
  681.  
  682.   set_loadplg_offset ( 0, 0, 0 );
  683.   set_loadplg_scale ( 5, 5, 5 );
  684.   ball = load_plg ( in );
  685.   if ( load_err != 0 )
  686.     {
  687.       fprintf ( stderr, "Error loading ball.plg file.\n" );
  688.       exit(1);
  689.     }
  690.  
  691.   add_to_objlist ( objlist, ball );
  692.   ball_seg = new_seg ( NULL );
  693.   seg_set_object ( ball_seg, ball );
  694.  
  695.   update_segment ( ball_seg );
  696.  
  697.   x_position = 1000;
  698.   y_position = 500;
  699.   z_position = 2000;
  700.   inc_val_x = 50;
  701.   inc_val_y = 40;
  702.   inc_val_z = 40;
  703.  
  704.   return ball_seg;
  705. }
  706.  
  707.  
  708. /**************************************************************************
  709.   This function is used to read the racquet used in the game and
  710.   assign it to a segment called racquet_seg which is returned to the caller.
  711. **************************************************************************/
  712. SEGMENT * read_racquet()
  713. {
  714.   FILE *in;
  715.   SEGMENT *racquet_seg;
  716.  
  717.   if ((in = fopen ( "racquet.fig", "r" )) == NULL )
  718.     {
  719.       fprintf ( stderr, "Unable to open racquet file.\n" );
  720.       exit(1);
  721.     }
  722.  
  723. /*  set_loadplg_offset (1000, 500, 2000);
  724.   set_loadplg_scale (3, 3, 3);  */
  725.  
  726.   set_readseg_objlist ( objlist );
  727.   set_readseg_scale ( 3, 3, 3 );
  728.   racquet_seg = readseg (in, NULL);
  729.   if ( readseg_err != 0 )
  730.     {
  731.       fprintf ( stderr, "Error loading racquet.plg file.\n" );
  732.       exit(1);
  733.     }
  734.  
  735.   /*add_to_objlist ( objlist, racquet );
  736.   racquet_seg = new_seg ( NULL );
  737.   seg_set_object ( racquet_seg, racquet );  */
  738.  
  739.   abs_move_segment ( racquet_seg, 1500, 500, 2000 );
  740.   abs_rot_segment ( racquet_seg, 0L, 90*65536L, 0L, RXYZ );
  741.   update_segment ( racquet_seg );
  742.  
  743.   handle = seg_get_object (find_segment_by_name(racquet_seg, "handle" ));
  744.   if ( handle == NULL )
  745.     {
  746.        fprintf ( stderr, "Cannot find handle segment.\n" );
  747.        exit(1);
  748.     }
  749.  
  750.   return racquet_seg;
  751. }
  752.  
  753.  
  754.  
  755. void get_glove()
  756. {
  757.   PDRIVER *gd;
  758.   extern PDRIVER *gloveptr_init(char *gname, long sx, long sy,
  759.          long sz, long srx, long sry, long srz );
  760.  
  761.   gd = gloveptr_init ( gpdname, gpdo_x*65536.0, gpdo_y*65536.0, gpdo_z*65536.0,
  762.                gpdo_rx*65536.0, gpdo_ry*65536.0, gpdo_rz*65536.0 );
  763.  
  764.   manip_device = menu_device = gd;
  765.   if(gd)
  766.     load_glove_cursor ( body_seg, manip_device, gpcursor );
  767. }
  768.  
  769.  
  770.  
  771.  
  772. void main(int argc, char *argv[]){
  773.   char *fname, *in_filename;
  774.   FILE *in;
  775.   SEGMENT *BALL, *RACQUET;
  776.  
  777.   setup_render(40,800);
  778.   atexit(closeall);
  779.   set_global_split_root ( &split_tree );
  780.   initial_world_split ( &split_tree );
  781.   set_move_handler ( split_move_handler );
  782.   objlist = new_objlist();
  783.  
  784.  
  785.   fname = "rend386.cfg";
  786.   if ((in = fopen ( fname, "r" )) == NULL )
  787.     {
  788.       fprintf ( stderr, "Configuration file not found!" );
  789.       exit(1);
  790.     }
  791.   else
  792.     {
  793.       if ( read_world(in))
  794.     {
  795.         fprintf ( stderr, "Error reading configuration file!" );
  796.         exit(1);
  797.     }
  798.       fclose ( in );
  799.     }
  800.  
  801.   in_filename = fix_fname(argv[1] );
  802.   if ( strstr (in_filename, ".wld"))
  803.     {
  804.       if ((in = fopen ( in_filename, "r" )) == NULL )
  805.     {
  806.       fprintf ( stderr, "Error opening world file.\n" );
  807.       exit(1);
  808.     }
  809.       if (read_world(in))
  810.     {
  811.       fprintf ( stderr, "Error reading world file.\n");
  812.       exit(1);
  813.     }
  814.       fclose(in);
  815.     }
  816.  
  817.  
  818.  
  819.  
  820.  
  821.   load_video_driver ( vdname );
  822.   screeninfo = screen_data();
  823.   highest_color = screeninfo->colors-1;
  824.   preset_default_colors();
  825.  
  826.   frame_x = screeninfo->xmin;
  827.   frame_y = screeninfo->ymin;
  828.   frame_w = screeninfo->xmax - screeninfo->xmin+1;
  829.   frame_h = screeninfo->ymax - screeninfo->ymin+1;
  830.  
  831.   default_view.left = screeninfo->xmin;
  832.   default_view.top = screeninfo->ymin;
  833.   default_view.right = screeninfo->xmax;
  834.   default_view.bottom = screeninfo->ymax;
  835.   default_view.aspect = screeninfo->aspect;
  836.  
  837.  
  838.   if (enter_graphics()) {
  839.     fprintf ( stderr, "could not enter graphics mode\n\n");
  840.     exit(1);
  841.     }
  842.  
  843.   screen_clear_color = 0;
  844.  
  845.   sky_color  = 1; ground_color = 2;
  846.  
  847.  
  848.   initialize_screen_factors ( current_view );
  849.   fast_view_factors ( current_view );
  850.  
  851.  
  852.   BALL = read_ball();
  853.   RACQUET = read_racquet();
  854.  
  855.   body_seg = new_seg(NULL);
  856.   set_readseg_scale ( 1,1,1 ); /* Must do or will get previous readseg scale */
  857.   get_glove();
  858.  
  859.  
  860.   abs_move_segment ( body_seg, 2250, 800, -300 );
  861.   update_segment ( body_seg );
  862.  
  863.  
  864.  
  865.  
  866.   palm = find_segment_by_name (body_seg, "palm" );
  867.   rel_rot_segment ( palm, 0L,0L, -45*65536L, RZXY );
  868.   update_segment ( palm );
  869.   if ( palm == NULL )
  870.     {
  871.        fprintf ( stderr, "Cannot find palm segment.\n" );
  872.        exit(1);
  873.     }
  874.   palm_object = seg_get_object ( palm );
  875.  
  876.   main_loop(BALL, RACQUET);   /* start us off */
  877.  
  878. }
  879.