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

  1. /* Read a World Description File */
  2.  
  3. /* Original read-world and format by Bernie Roehl, July 1992 */
  4. /* Rewritten for animation and configuration by Dave Stampe Oct. '92 */
  5.  
  6. // Massively rewritten to port to VR-386 API by Dave Stampe 9/1/94
  7. // The .WLD file format is for compatibility with REND386 V5.0,
  8. // and with "Virtual Reality Creations"
  9. // FUTURE WORLD LOADING MAY LOOK VERY DIFFERENT, AND BE MUCH BETTER
  10.  
  11.  
  12. /*
  13.  This code is part of the VR-386 project, created by Dave Stampe.
  14.  VR-386 is a desendent of REND386, created by Dave Stampe and
  15.  Bernie Roehl.  Almost all the code has been rewritten by Dave
  16.  Stampre for VR-386.
  17.  
  18.  Copyright (c) 1994 by Dave Stampe:
  19.  May be freely used to write software for release into the public domain
  20.  or for educational use; all commercial endeavours MUST contact Dave Stampe
  21.  (dstampe@psych.toronto.edu) for permission to incorporate any part of
  22.  this software or source code into their products!  Usually there is no
  23.  charge for under 50-100 items for low-cost or shareware products, and terms
  24.  are reasonable.  Any royalties are used for development, so equipment is
  25.  often acceptable payment.
  26.  
  27.  ATTRIBUTION:  If you use any part of this source code or the libraries
  28.  in your projects, you must give attribution to VR-386 and Dave Stampe,
  29.  and any other authors in your documentation, source code, and at startup
  30.  of your program.  Let's keep the freeware ball rolling!
  31.  
  32.  DEVELOPMENT: VR-386 is a effort to develop the process started by
  33.  REND386, improving programmer access by rewriting the code and supplying
  34.  a standard API.  If you write improvements, add new functions rather
  35.  than rewriting current functions.  This will make it possible to
  36.  include you improved code in the next API release.  YOU can help advance
  37.  VR-386.  Comments on the API are welcome.
  38.  
  39.  CONTACT: dstampe@psych.toronto.edu
  40. */
  41.  
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include <stdlib.h>
  45. #include <alloc.h>
  46. #include <dos.h>       /* delay() */
  47.  
  48. #include "config.h"
  49. #include "vr_api.h"
  50. #include "oldtasks.h"
  51. #include "intmath.h"
  52. #include "splits.h"
  53. #include "pcdevice.h"
  54. #include "segment.h"
  55.  
  56. int old_angle_order = 0;  /* if non-zero, camera angles are pan,tilt,roll */
  57.  
  58. extern int do_screen_clear;
  59. extern int flymode, floormode;
  60. extern unsigned char palette[];
  61. extern int npalette;
  62. extern TASK *tasklist;
  63.  
  64. extern char *fix_fname(char *fname);
  65.  
  66. static int keep_around = 0; /* if non-zero, don't use temp for names */
  67.  
  68.  
  69.  
  70. /**************** NAMED LIST SUPPORT **************/
  71.  
  72. typedef struct _name NAMEREF;
  73.  
  74. struct _name {
  75.         char *name;
  76.         void *value;
  77.         NAMEREF *next;
  78.          };
  79.  
  80. extern void *temp_mem;
  81. extern long temp_size;
  82.  
  83. NAMEREF *add_name(NAMEREF **list, char *name, void *value)
  84. {
  85.   NAMEREF *p;
  86.                 /* check if temp usable */
  87.   if (!keep_around && (temp_mem) &&
  88.     (temp_size>(sizeof(NAMEREF)+strlen(name)+1)))
  89.     {
  90.       p = temp_mem;
  91.       temp_mem = ((char *)temp_mem) + sizeof(NAMEREF);
  92.       p->name = temp_mem;
  93.       temp_mem = ((char *)temp_mem) + strlen(name) + 1;
  94.       strcpy(p->name, name);
  95.       temp_size -= sizeof(NAMEREF)+strlen(name)+1;
  96.     }
  97.   else                 /* use heap */
  98.     {
  99.       temp_mem = NULL;
  100.       if ((p = malloc(sizeof(NAMEREF))) == NULL) return NULL;
  101.       p->name = strdup(name);
  102.     }
  103.   p->value = value;
  104.   p->next = *list;
  105.   *list = p;
  106.   return *list;
  107. }
  108.  
  109.  
  110. void del_namelist(NAMEREF *list)
  111. {
  112.   if (keep_around) return;
  113.   if (temp_mem) return;
  114.   while (list)
  115.     {
  116.       if (list->name) free(list->name);
  117.       free(list);
  118.       list = list->next;
  119.     }
  120. }
  121.  
  122. void *find_name(NAMEREF *list, char *name)
  123. {
  124.   while (list)
  125.     {
  126.       if (!stricmp(list->name, name))
  127.       return list->value;
  128.       list = list->next;
  129.     }
  130.   return NULL;
  131. }
  132.  
  133. char *find_value(NAMEREF *list, void *value)
  134. {
  135.   while (list)
  136.     {
  137.       if (list->value == value)
  138.         return list->name;
  139.       list = list->next;
  140.     }
  141.   return NULL;
  142. }
  143.  
  144. unsigned int find_color(NAMEREF *list, char *name)
  145. {
  146.   if (isdigit(name[0])) /* handle dec/hex color */
  147.     return strtoul(name, NULL, 0);
  148.   if (name[0] == '&') return convert_color(&name[1], NULL);
  149.     return (unsigned)find_name(list, name);
  150. }
  151.  
  152.  
  153. /****************** TASK AND CONTROL SUPPORT *************/
  154.  
  155.  
  156. extern void spinner(), sculspin();
  157.  
  158. struct {
  159.     char *name;
  160.     void (*fn)();
  161.     } functions[] = { {"spinner", spinner},
  162.               {"sculspin", sculspin},
  163.               {NULL, NULL}         };
  164.  
  165.  
  166. /******************** POLYGON, PLANE NORMAL SUPPORT ***********/
  167.  
  168. #define LSCALE 536870912.0
  169.  
  170. void scale3(float a, float b, float c,
  171. long *ap, long *bp, long *cp)
  172. {
  173.   float maxim; /* integerize normal */
  174.  
  175.   maxim = (a > 0) ? a : -a; /* BUG IN BC 3.0 fabs()! */
  176.   maxim += (b > 0) ? b : -b;
  177.   maxim += (c > 0) ? c : -c;
  178.   if (maxim > 0.0001)
  179.     {
  180.       maxim /= LSCALE;
  181.       *ap = a/maxim;
  182.       *bp = b/maxim; /* normalize to <3.29> */
  183.       *cp = c/maxim;
  184.     }
  185. }
  186.  
  187. void scale4(float a, float b, float c, float d,
  188. long *ap, long *bp, long *cp, long *dp)
  189. {
  190.   float maxim; /* integerize normal */
  191.  
  192.   maxim = (a > 0) ? a : -a; /* BUG IN BC 3.0 fabs()! */
  193.   maxim += (b > 0) ? b : -b;
  194.   maxim += (c > 0) ? c : -c;
  195.   maxim += (d > 0) ? d : -d;
  196.   if (maxim > 0.0001)
  197.     {
  198.       maxim /= LSCALE;
  199.       *ap = a/maxim;
  200.       *bp = b/maxim; /* normalize to <3.29> */
  201.       *cp = c/maxim;
  202.       *dp = d/maxim;
  203.     }
  204. }
  205.  
  206.  
  207. /* facing normal, points should be in CW sequence */
  208. /* for axis aligned (+) split directions, use:    */
  209. /* x 0 0  x 100 0  x 0 100  for constant x */
  210. /* 0 y 0  0 y 100  100 y 0  for constant y */
  211. /* 0 0 z  100 0 z  0 100 z  for constant z */
  212.  
  213. void points_to_normal(  float x1, float y1, float z1,
  214.             float x2, float y2, float z2,
  215.             float x3, float y3, float z3,
  216.             long *ap, long *bp, long *cp  )
  217. {
  218.   float v1x, v1y, v1z, v2x, v2y, v2z;
  219.   float a, b, c; /* compute line equation */
  220.  
  221.   v1x = x2 - x1;
  222.   v1y = y2 - y1;
  223.   v1z = z2 - z1;
  224.   v2x = x3 - x1;
  225.   v2y = y3 - y1;
  226.   v2z = z3 - y1;
  227.   a = (v1y * v2z - v2y * v1z);
  228.   b = (v1x * v2z - v2x * v1z);
  229.   c = (v1x * v2y - v2x * v1y);
  230.   scale3(a, b, c, ap, bp, cp);
  231. }
  232.  
  233. void points_to_eqn(    float x1, float y1, float z1,
  234.             float x2, float y2, float z2,
  235.             float x3, float y3, float z3,
  236.             long *ap, long *bp, long *cp, long *dp)
  237. {
  238.   float v1x, v1y, v1z, v2x, v2y, v2z;
  239.   float a, b, c, d; /* compute line equation */
  240.  
  241.   v1x = x2 - x1;
  242.   v1y = y2 - y1;
  243.   v1z = z2 - z1;
  244.   v2x = x3 - x1;
  245.   v2y = y3 - y1;
  246.   v2z = z3 - y1;
  247.   a = (v1y * v2z - v2y * v1z);
  248.   b = (v1x * v2z - v2x * v1z);
  249.   c = (v1x * v2y - v2x * v1y);
  250.   d = -(a*x1 + b*y1 + c*z1); /* normalize to <3.29> */
  251.  
  252.   scale4(a, b, c, d, ap, bp, cp, dp);
  253. }
  254.  
  255. void normal_to_plane(    float x, float y, float z,
  256.             float nx, float ny, float nz,
  257.             long *ap, long *bp, long *cp, long *dp)
  258. {
  259.   float a, b, c, d; /* compute line equation  */
  260.     /* given normal and point */
  261.   a = nx;
  262.   b = -ny;
  263.   c = nz;
  264.   d = -(a*x + b*y + c*z);
  265.  
  266.   scale4(a, b, c, d, ap, bp, cp, dp);
  267. }
  268.  
  269.  
  270.  
  271. /************* WORLD AND CONFIG FILE LOADING **********/
  272.  
  273. NAMEREF *areas = NULL;
  274. NAMEREF *maps = NULL;
  275. NAMEREF *surfdefs = NULL;
  276. NAMEREF *objectlist = NULL;
  277. NAMEREF *fixedolist = NULL;
  278. NAMEREF *figurelist = NULL;
  279.  
  280. #ifdef ENABLE_STATEMACH
  281. extern NAMEREF *statelist;
  282. extern NAMEREF *varlist;
  283. #endif
  284.  
  285. void dump_lists(void)
  286. {
  287.   if(temp_mem) return; /* no need to delete if using temp. RAM */
  288.  
  289.   del_namelist(areas);
  290.   del_namelist(maps);
  291.   del_namelist(surfdefs);
  292.   del_namelist(objectlist);
  293.   del_namelist(fixedolist);
  294.   del_namelist(figurelist);
  295. #ifdef ENABLE_STATEMACH
  296.   del_namelist(statelist);
  297.   del_namelist(varlist);
  298. #endif
  299. }
  300.  
  301.  
  302. typedef struct _surface SURFACEX;
  303.  
  304. struct _surface {
  305.     unsigned color;
  306.     char *value;
  307.     SURFACEX *next;
  308.         };
  309.  
  310.  
  311. static SURFACEPAIR colormap[100];    // color pair table for mapping
  312.  
  313. int create_map_table(SURFACEX *map)  // creates color pair table for mapping
  314. {                                    // uses 0x80xx map flag for compatibility
  315.   int i = 0;
  316.   SURFACEX *p;
  317.   void *v;
  318.  
  319.   if (map)
  320.     {
  321.  
  322.       for (p = map; p; p = p->next)
  323.     {
  324.       colormap[i].old = p->color | 0x8000;
  325.       if ((v = find_name(surfdefs, p->value)) != NULL)
  326.          colormap[i].new = (unsigned) v;
  327.       else
  328.          colormap[i].new = 0;
  329.       i++;
  330.     }
  331.      }
  332.   return i;
  333. }
  334.  
  335.  
  336.  
  337.  
  338. extern char loadpath[];
  339.  
  340. #define match(a,b)  !strnicmp(a, b, strlen(b))
  341.  
  342.  
  343. OBJECT *find_seg(char *name)
  344. {
  345.   char *p = NULL;
  346.   OBJECT *obj;
  347.  
  348.   if (name[0]==0) return NULL;
  349.   if ((p = strchr(name, '.')) == NULL)
  350.     {
  351.       if ((obj = find_name(objectlist, name)) == NULL) goto try_seg;
  352.       return obj;
  353.     }
  354.   else
  355.     {                             // part of figure
  356.       *p++ = '\0';
  357. try_seg:
  358.       if ((obj = find_name(figurelist, name)) == NULL) return NULL; /* no such figure */
  359.       if (p==NULL) return obj; /* root of figure */
  360.       return find_segment_by_name(obj, p);
  361.     }
  362. }
  363.  
  364.  
  365.  
  366. void clean_equals(char *b)     // fixes up tokenization of string so
  367. {                              // word = word -> word=word
  368.   char *c=b, *d=b;             // so it's a hack!
  369.  
  370.   if(!strchr(b,'=')) return;
  371.  
  372.   while(*b) /* scan string: */
  373.     {
  374.        if(*b==' ' || *b=='\t') /* if whitespace: */
  375.      {
  376.        d = b; /* record start */
  377.        while (*b==' ' || *b=='\t') *c++ = *b++; /* copy till end of ws */
  378.        if(*b=='=')
  379.          {
  380.            c = d; /* roll back position */
  381.            *c++ = *b++; /* copy = */
  382.            while (*b==' ' || *b=='\t') b++; /* skip trailing ws */
  383.          }
  384.      }
  385.        else *c++ = *b++;
  386.      }
  387.   *c = 0;
  388. }
  389.  
  390.  
  391. // these scan a line for a token
  392. // but leave the dest unchanged if none found/error
  393.  
  394. void tokstr(char *c)        // return string from line
  395. {
  396.   char *s = strtok(NULL, " \t,\n#");
  397.   if(s) sscanf(s, "%s",c);
  398. }
  399.  
  400.  
  401. void tokstrn(char *c)        // return string or null string
  402. {
  403.   char *s = strtok(NULL, " \t,\n#");
  404.   if(s) sscanf(s, "%s",c);
  405.   else *c = 0;
  406. }
  407.  
  408. void tokint(int *i)        // return integer
  409. {
  410.   char *s = strtok(NULL, " \t,\n#");
  411.   if(s) sscanf(s, "%d",i);
  412. }
  413.  
  414. void tokhex(unsigned *i)
  415. {
  416.     char *s = strtok(NULL, " \t,\n#");
  417.     if(s) *i = (unsigned int)strtoul(s, NULL, 0);
  418. }
  419.  
  420. void toklong(long *i)
  421. {
  422.     char *s = strtok(NULL, " \t,\n#");
  423.     if(s) sscanf(s, "%ld",i);
  424. }
  425.  
  426. void tokfloat(float *i)
  427. {
  428.     char *s = strtok(NULL, " \t,\n#");
  429.     if(s) sscanf(s, "%f",i);
  430. }
  431.  
  432. void tokangle(long *i)
  433. {
  434.   float f;
  435.   char *s = strtok(NULL, " \t,\n#");
  436.   if(s)
  437.     {
  438.       sscanf(s, "%f", &f);
  439.       *i = 65536L * f;
  440.     }
  441. }
  442.  
  443. char *toks(void)
  444. {
  445.   char *s = strtok(NULL, " \t,\n#");
  446.   if (s) return "";
  447.   else return s;
  448. }
  449.  
  450. static int title_index = 0;        // WORLD TITLE goes here
  451. char *title[25] = { NULL };
  452.  
  453.  
  454. // LIST OF COMMANDS
  455.  
  456. static char *commands[] = {
  457.     "loadpath", "palette", "skycolor", "groundcolor", "screencolor",
  458.     "screenclear", "ambient", "worldscale", "flymode", "light",
  459.     "window", "key", "control", "viewframe", "start", "floormode",
  460.     "hither", "yon", "eyespacing", "screendist", "attachview",
  461.     "screenwidth", "convergence", "figure", "object", "stepsize",
  462.     "task", "position", "rotate", "camera", "options",
  463.     "include", "surfacemap", "surface", "surfacedef",
  464.     "split", "splitpt", "area", "floor", "floorpts",
  465.     "ceiling", "ceilingpts", "visfrom",
  466.     "endsplits", "polyobj", "polyobj2", "videodev",
  467.     "mousedev", "headdev", "glovedev", "ptrdev",
  468.     "switchdev", "glovecursor", "ptrcursor", "segaport", "switchport",
  469.     "pgloveport", "pglovetime", "stereoset", "stereotype",
  470.     "stereoleft", "stereoright", "depthtype", "attach", "detach",
  471.     "usemap", "fixedobj",
  472. #ifdef ENABLE_STATEMACH
  473.     "animation", "state", "if", "do",
  474. #endif
  475.     "title", "mlight", "segment", "addrep",
  476.     "anglestep",
  477.     "version",
  478.     NULL
  479. };
  480.  
  481. enum com_codes {
  482.     c_loadpath = 0, c_palette, c_skycolor, c_groundcolor, c_screencolor,
  483.     c_screenclear, c_ambient, c_worldscale, c_flymode, c_light,
  484.     c_window, c_key, c_control, c_viewframe, c_start, c_floormode,
  485.     c_hither, c_yon, c_eyespacing, c_screendist, c_attachview,
  486.     c_screenwidth, c_convergence, c_figure, c_object, c_stepsize,
  487.     c_task, c_position, c_rotate, c_camera, c_options,
  488.     c_include, c_surfacemap, c_surface, c_surfacedef,
  489.     c_split, c_splitpt, c_area, c_floor, c_floorpts,
  490.     c_ceiling, c_ceilingpts, c_visfrom,
  491.     c_endsplits, c_polyobj, c_polyobj2, c_videodev,
  492.     c_mousedev, c_headdev, c_glovedev, c_ptrdev,
  493.     c_switchdev, c_glovecursor, c_ptrcursor, c_segaport, c_switchport,
  494.     c_pgloveport, c_pglovetime, c_stereoset, c_stereotype,
  495.     c_stereoleft, c_stereoright, c_depthtype, c_attach, c_detach,
  496.     c_usemap, c_fixedobj,
  497. #ifdef ENABLE_STATEMACH
  498.     c_animation, c_state, c_if, c_do,
  499. #endif
  500.     c_title, c_mlight, c_segment, c_addrep,
  501.     c_anglestep,
  502.     c_version,
  503. };
  504.  
  505.  
  506.  
  507.  
  508. static SURFACEX *current_surface = NULL, *map;
  509. static SPLIT *current_split = NULL;
  510.  
  511. static char ps[] = " \t\n,#";
  512. static char st[] = "%s";
  513.  
  514. extern long spacestep, anglestep;
  515.  
  516. static char default_map[100] = "";
  517.  
  518. LIGHT *std_lights[3];  // default lights for the world
  519. LIGHT *amb_light;
  520. LIGHT * light1;
  521. LIGHT * light2;
  522.  
  523. void create_default_lights()
  524. {
  525.   POSE p = {1000, 15000, -5000, 0, 0, 0};
  526.   std_lights[0] = amb_light = create_light(NULL,AMBIENT_LIGHT,64);
  527.   std_lights[1] = light1 = create_light(NULL,POINT_LIGHT,64);
  528.   position_pointlight(light1,&p);
  529.   std_lights[2] = light2 = create_light(NULL,POINT_LIGHT,0);
  530.   p.x = -4000;
  531.   position_pointlight(light2,&p);
  532. }
  533.  
  534.  
  535. extern TELEPORT *fnkeyposn[10];
  536. extern TELEPORT *fnkeyhome[10];
  537.  
  538. extern OBJECT *body_vehicle_object;
  539.  
  540.  
  541. void read_world(FILE *in)
  542. {
  543.   char obuff[256];
  544.   char inbuff[256], *buff, fname[100];
  545.   char surfacemapname[100];
  546.   char *args;
  547.   char *pname;
  548.   int i,cmd;
  549.  
  550.   while (fgets(inbuff, sizeof(inbuff), in))
  551.     {
  552.       strcpy(obuff,inbuff);
  553.       buff = strtok(inbuff,"#");
  554.       for (buff = inbuff; isspace(*buff); ++buff);
  555.       if(buff[0]==0) continue;
  556.       clean_equals(buff);
  557.       for (args = buff+1; isalpha(*args); ++args);
  558.       args++;
  559.       buff = strtok(buff," \t\n");
  560.  
  561.       for (cmd = 0; commands[cmd]; cmd++)
  562.     if (!stricmp(commands[cmd], buff)) break;
  563.       if (commands[cmd] == NULL) continue;
  564.  
  565.       switch(cmd)
  566.     {
  567.       case c_palette:
  568.         {
  569.           FILE *in;
  570.           char *f;
  571.           tokstr(fname);
  572.           if ((in = fopen(f = fix_fname(fname), "rb")) != NULL)
  573.         {
  574.           npalette = fread(palette, 3, 256, in);
  575.           fclose(in);
  576.         }
  577.           else errprintf("Could not load palette '%s'", f);
  578.          }
  579.         break;
  580.  
  581.        case c_attach:
  582.          {
  583.            OBJECT *s, *par;
  584.  
  585.            if ((s = find_seg(strtok(NULL,ps))) == NULL) break;
  586.            if ((par = find_seg(strtok(NULL,ps))) == NULL) break;
  587.            attach_object(s, par, 0);
  588.            update_object(par);
  589.            break;
  590.          }
  591.  
  592.        case c_stepsize:
  593.            toklong(&spacestep);
  594.            break;
  595.  
  596.        case c_anglestep:
  597.            {
  598.         float a;
  599.         tokfloat(&a);
  600.         anglestep = a * 65536L;
  601.            }break;
  602.  
  603.        case c_loadpath:
  604.            tokstr(loadpath);
  605.            break;
  606.  
  607.        case c_skycolor:
  608.            tokhex(&sky_color);
  609.            set_skycolor(sky_color);
  610.            break;
  611.  
  612.        case c_groundcolor:
  613.            tokhex(&ground_color);
  614.            set_groundcolor(ground_color);
  615.            break;
  616.  
  617.        case c_screencolor:
  618.            tokhex(&screen_clear_color);
  619.            break;
  620.  
  621.        case c_screenclear:
  622.            tokint(&do_screen_clear);
  623.            break;
  624.  
  625.        case c_ambient:
  626.          {
  627.            int i;
  628.            tokint(&i);
  629.            set_light_intensity(amb_light,i);
  630.            break;
  631.          }
  632.  
  633.        case c_worldscale:
  634.            default_stereo.world_scaling = 65536.0 * atof(strtok(NULL,ps));
  635.            break;
  636.  
  637.        case c_light:
  638.            {
  639.          char *p;
  640.          POSE pose = DONTCARE_POSE;
  641.          int s;
  642.          COORD x,y,z;
  643.  
  644.          x = atol(strtok(NULL,ps));
  645.          y = atol(strtok(NULL,ps));
  646.          z = atol(strtok(NULL,ps));
  647.          p = strtok(NULL, ps);
  648.          if (isdigit(*p)) s = atoi(p);
  649.          else s = !stricmp(p, "spot");
  650.          if(!s)
  651.            {
  652.              pose.x = x;          // treat as location
  653.              pose.y = y;
  654.              pose.z = z;
  655.              position_pointlight(light1,&pose);
  656.            }
  657.          else
  658.            {
  659.              pose.rx = float2angle(x);  // treat as angles
  660.              pose.ry = float2angle(y);
  661.              pose.rz = float2angle(z);
  662.              rotate_spotlight(light1,&pose);
  663.            }
  664.            } break;
  665.  
  666.        case c_mlight:
  667.          {
  668.            char *p;
  669.            POSE pose = DONTCARE_POSE;
  670.            int s,i;
  671.            COORD x,y,z;
  672.            char parent[100];
  673.            char *m;
  674.            OBJECT *p_seg;
  675.  
  676.            x = atol(strtok(NULL,ps));
  677.            y = atol(strtok(NULL,ps));
  678.            z = atol(strtok(NULL,ps));
  679.            p = strtok(NULL, ps);
  680.            if (isdigit(*p)) s = atoi(p);
  681.            else s = !stricmp(p, "spot");
  682.            sscanf(strtok(NULL,ps), "%d", &i); /* intensity*128 */
  683.            set_light_intensity(light2,i);
  684.            if(!s)
  685.          {
  686.            pose.x = x;          // treat as location
  687.            pose.y = y;
  688.            pose.z = z;
  689.            position_pointlight(light2,&pose);
  690.          }
  691.            else
  692.          {
  693.            pose.rx = float2angle(x);  // treat as angles
  694.            pose.ry = float2angle(y);
  695.            pose.rz = float2angle(z);
  696.            rotate_spotlight(light2,&pose);
  697.          }
  698.  
  699.            tokstrn(parent);
  700.            if(parent[0]==0 || !stricmp(parent, "fixed")) break; /* not a moveable light */
  701.  
  702.            if ((m=strchr(parent, '='))!=NULL)
  703.          {
  704.            *m++ = 0;
  705.            add_name(&figurelist, parent, light2->seg); /* record name */
  706.          }
  707.            else m = parent;
  708.  
  709.            p_seg = find_seg(m);
  710.            if(p_seg)
  711.          {
  712.            attach_light(light2, p_seg, 0 );
  713.            update_object(p_seg);
  714.          }
  715.            break;
  716.          }
  717.  
  718.        case c_segment:
  719.          {
  720.            OBJECT *this_seg, *p_seg;
  721.            char parentname[60], *oname, *p;
  722.            long tx = 0, ty = 0, tz = 0, rx = 0, ry = 0, rz = 0;
  723.  
  724.            oname = NULL;
  725.            tokstrn(parentname);
  726.            tokangle(&rx);
  727.            tokangle(&ry);
  728.            tokangle(&rz);
  729.            toklong(&tx);
  730.            toklong(&ty);
  731.            toklong(&tz);
  732.  
  733.            if ((p = strchr(parentname, '=')) != NULL)
  734.          {
  735.            oname = parentname;
  736.            *p++ = '\0';
  737.          }
  738.            else  p = parentname;
  739.            p_seg = find_seg(p);
  740.            if ((this_seg = create_invisible_object()) != NULL)
  741.          {
  742.            POSE pose;
  743.            pose.x = tx;
  744.            pose.y = ty;
  745.            pose.z = tz;
  746.            pose.rx = rx;
  747.            pose.ry = ry;
  748.            pose.rz = rz;
  749.            attach_object(this_seg, p_seg, 0);
  750.            set_object_pose(this_seg, &pose);
  751.            update_object(this_seg);
  752.            if (oname) add_name(&figurelist, oname, this_seg);
  753.          }
  754.          }
  755.          break;
  756.  
  757.        case c_camera:
  758.          {
  759.            int n;
  760.            char *c;
  761.            POSE p = ZERO_POSE;
  762.  
  763.            tokint(&n);
  764.            if (n < 1 || n > 10) break;
  765.            if(n==1) goto set_start;
  766.            n--;
  767.            toklong(&(p.x));
  768.            toklong(&(p.y));
  769.            toklong(&(p.z));
  770.            if (old_angle_order)
  771.          {
  772.            tokangle(&(p.ry));
  773.            tokangle(&(p.rx));
  774.          }
  775.            else
  776.          {
  777.            tokangle(&(p.rx));
  778.            tokangle(&(p.ry));
  779.          }
  780.            tokangle(&(p.rz));
  781.  
  782.            if(!fnkeyposn[n])
  783.            fnkeyposn[n] = create_teleport();
  784.            teleport_set_here(fnkeyposn[n], &p);
  785.            teleport_set_vehicle(fnkeyposn[n],NULL,NULL);
  786.  
  787.            if(!fnkeyhome[n])
  788.            fnkeyhome[n] = create_teleport();
  789.            teleport_set_here(fnkeyhome[n], &p);
  790.            teleport_set_vehicle(fnkeyhome[n],NULL,NULL);
  791.  
  792.            // tokangle(&(v->zoom));        // ignore for now
  793.            // toklong(&(v->hither));
  794.            // toklong(&(v->yon));
  795.  
  796.           } break;
  797.  
  798.        case c_start:
  799.      set_start:
  800.          {
  801.            float zoom = 0.0;
  802.  
  803.            toklong(&initial_body_pose.x);
  804.            toklong(&initial_body_pose.y);
  805.            toklong(&initial_body_pose.z);
  806.            if(old_angle_order)
  807.          {
  808.            tokangle(&initial_body_pose.ry);
  809.            tokangle(&initial_body_pose.rx);
  810.          }
  811.            else
  812.          {
  813.            tokangle(&initial_body_pose.rx);
  814.            tokangle(&initial_body_pose.ry);
  815.          }
  816.            tokangle(&initial_body_pose.rz);
  817.  
  818.            tokfloat(&zoom);
  819.            if(zoom>16.0) zoom = 16.0;
  820.            if(zoom>0.5)
  821.            set_camera_zoom(default_camera, float2scale(zoom));
  822.  
  823.            *body_pose = initial_body_pose;
  824.            if(!fnkeyposn[0])
  825.            fnkeyposn[0] = create_teleport();
  826.            teleport_set_vehicle(fnkeyposn[0],body_vehicle_object,NULL);
  827.            teleport_set_here(fnkeyposn[0], &initial_body_pose);
  828.            if(!fnkeyhome[0])
  829.            fnkeyhome[0] = create_teleport();
  830.            teleport_set_here(fnkeyhome[0], &initial_body_pose);
  831.            teleport_set_vehicle(fnkeyhome[0],body_vehicle_object,NULL);
  832.            break;
  833.          }
  834.  
  835.        case c_attachview:
  836.          {
  837.            OBJECT *vehicle = NULL;
  838.            char parentname[60];
  839.            tokstrn(parentname);
  840.            vehicle = find_seg(parentname);
  841.            if(vehicle) connect_body(vehicle);
  842.  
  843.            if(!fnkeyposn[0])
  844.            fnkeyposn[0] = create_teleport();
  845.            teleport_set_here(fnkeyposn[0], &initial_body_pose);
  846.            teleport_set_vehicle(fnkeyposn[0],body_vehicle_object,NULL);
  847.  
  848.            if(!fnkeyhome[0])
  849.            fnkeyhome[0] = create_teleport();
  850.            teleport_set_here(fnkeyhome[0], &initial_body_pose);
  851.            teleport_set_vehicle(fnkeyhome[0],body_vehicle_object,NULL);
  852.          }
  853.           break;
  854.  
  855.        case c_hither:
  856.          {
  857.           COORD h = atol(strtok(NULL,ps));
  858.           if(h<1) h=1;
  859.           set_camera_hither(default_camera,h);
  860.           break;
  861.          }
  862.        case c_yon:
  863.          {
  864.           COORD y = atol(strtok(NULL,ps));
  865.           if(y>530000000L) y=530000000L;
  866.           set_camera_yon(default_camera,y);
  867.           break;
  868.          }
  869.  
  870.        case c_title:
  871.          if((args!=NULL)&&(args[0]!=0)&&(title_index<22))
  872.            {
  873.          char s[200];
  874.          sscanf(args, "%s", s);
  875.          if(strlen(args)>36) args[36] = 0;
  876.          if(!stricmp(s,"memory"))
  877.            {
  878.              sprintf(s, "Memory Left: %ld", coreleft());
  879.              args = s;
  880.            }
  881.          title[title_index++] = strdup(args);
  882.          title[title_index] = NULL;
  883.            }break;
  884.  
  885. #ifdef ENABLE_STATEMACH
  886.                /* ANIMATION PARSER */
  887.        case c_animation:
  888.          parse_ani();
  889.          break;
  890.        case c_state:
  891.          parse_state();
  892.          break;
  893.        case c_if:
  894.          parse_if();
  895.          break;
  896.        case c_do:
  897.          parse_do();
  898.          break;
  899. #endif
  900.       case c_figure:
  901.          {
  902.            char filename[60], parentname[60], *oname, *p;
  903.            float sx = 1, sy = 1, sz = 1;
  904.            FILE *fig;
  905.            POSE pose = ZERO_POSE;
  906.  
  907.            parentname[0] = '\0';
  908.            oname = NULL;
  909.            sscanf(strtok(NULL,ps), st, filename);
  910.            tokfloat(&sx);
  911.            tokfloat(&sy);
  912.            tokfloat(&sz);
  913.            tokangle(&pose.rx);
  914.            tokangle(&pose.ry);
  915.            tokangle(&pose.rz);
  916.            toklong(&pose.x);
  917.            toklong(&pose.y);
  918.            toklong(&pose.z);
  919.            tokstrn(parentname);
  920.            add_ext(filename, "fig");
  921.            if ((p = strchr(filename, '=')) != NULL)
  922.          {
  923.            oname = filename;
  924.            *p++ = '\0';
  925.          }
  926.            else
  927.          p = filename;
  928.            if ((fig = fopen(pname = fix_fname(p), "r")) != NULL)
  929.          {
  930.            SEGMENT *this_seg, *p_seg;
  931.            p_seg = find_seg(parentname);
  932.            this_seg = load_figure_as_object(fig, default_objlist, NULL, 0, sx, sy, sz);
  933.            if (this_seg != NULL)
  934.              {
  935.                add_objlist_to_world(default_objlist);
  936.                if(p_seg)attach_object(this_seg,p_seg,0);
  937.                set_object_pose(this_seg, &pose);
  938.                update_object(this_seg);
  939.              }
  940.            fclose(fig);
  941.            if (seg_error(NULL))
  942.              {
  943.               errprintf("%s in figure file '%s'\n", seg_error(NULL), pname);
  944.               break;
  945.              }
  946.            if (oname) add_name(&figurelist, oname, this_seg);
  947.          }
  948.            else
  949.            errprintf( "Could not open '%s'", pname);
  950.          }    break;
  951.  
  952.        case c_fixedobj:
  953.        case c_object:
  954.          {
  955.            char mappings[100], *p, filename[100], *oname, parentname[100];
  956.            float sx = 1, sy = 1, sz = 1;
  957.            ANGLE rx = 0, ry = 0, rz = 0;
  958.            COORD tx = 0, ty = 0, tz = 0;
  959.            int dt = 0, nmaps = 0;
  960.            int nobjs = 0;
  961.            FILE *plg;
  962.            OBJECT *obj;
  963.  
  964.            sscanf(strtok(NULL,ps), st, filename);
  965.            add_ext(filename, "plg");
  966.  
  967.            tokfloat(&sx);
  968.            tokfloat(&sy);
  969.            tokfloat(&sz);
  970.  
  971.            tokangle(&rx);
  972.            tokangle(&ry);
  973.            tokangle(&rz);
  974.            toklong(&tx);
  975.            toklong(&ty);
  976.            toklong(&tz);
  977.  
  978.            tokint(&dt);
  979.  
  980.            tokstrn(mappings);
  981.            map = find_name(maps, mappings);
  982.            if (!map)
  983.             map = find_name(maps, default_map);
  984.            nmaps = create_map_table(map);
  985.  
  986.            tokstrn(parentname);
  987.            if (cmd == c_fixedobj || (current_split) )  // on split: force to fixed!
  988.             strcpy(parentname, "fixed");
  989.  
  990.            if ((p = strchr(filename, '=')) != NULL)
  991.          {
  992.            oname = filename;
  993.            *p++ = '\0';
  994.          }
  995.            else
  996.          {
  997.            oname = NULL;
  998.            p = filename;
  999.          }
  1000.  
  1001.            if ((plg = fopen(pname = fix_fname(p), "r")) != NULL)
  1002.          {
  1003.            POSE pose;
  1004.            POSE zpose = ZERO_POSE;     // for load of moveable
  1005.                          // choose load offsets
  1006.            POSE *loadp = (!stricmp(parentname, "fixed")) ? &pose: &zpose ;
  1007.  
  1008.            pose.x=tx;  pose.y=ty;  pose.z=tz;
  1009.            pose.rx=rx;  pose.ry=ry; pose.rz=rz;
  1010.  
  1011.            nobjs = load_plg_to_objlist(plg, default_objlist, 100, loadp, sx, sy, sz, dt);
  1012.            if(nobjs)
  1013.              {
  1014.                if(nmaps&&nobjs)
  1015.               objlist_remap_surface(default_objlist, colormap, nmaps,
  1016.                       MAP_ALL_MASK, MAP_ALL_MASK);
  1017.  
  1018.                if (stricmp(parentname, "fixed"))
  1019.              {
  1020.                SEGMENT *s, *p = NULL;
  1021.  
  1022.                p = find_seg(parentname);
  1023.                obj = convert_objlist_to_moveable_object(default_objlist);
  1024.                if(obj && p) attach_object(obj, p, 0);
  1025.                set_object_pose(obj, &pose);
  1026.                update_object(obj);
  1027.              }
  1028.                else obj = first_in_objlist(default_objlist);
  1029.                add_objlist_to_world(default_objlist);
  1030.  
  1031.                if (oname)        // add name NOW in case file didn't load
  1032.              {
  1033.                if (stricmp(parentname, "fixed"))
  1034.                   add_name(&objectlist, oname, obj);
  1035.                else
  1036.                   add_name(&fixedolist, oname, obj);
  1037.               }
  1038.              }
  1039.            if (plg_error(NULL))
  1040.              {
  1041.                errprintf("%s in file %s\n", plg_error(NULL), pname);
  1042.                break;
  1043.              }
  1044.          }
  1045.            else
  1046.          {
  1047.            errprintf("Could not open '%s'", pname);
  1048.            break;
  1049.  
  1050.          }
  1051.            fclose(plg);
  1052.          }     break;
  1053.  
  1054.        case c_addrep:
  1055.          {
  1056.            char mappings[100], *p, filename[100], *oname;
  1057.            float sx = 1, sy = 1, sz = 1;
  1058.            int defsize = 0;
  1059.            FILE *plg;
  1060.            OBJECT *obj, sobj;
  1061.            POSE pose = ZERO_POSE;
  1062.            int nmaps = 0;
  1063.  
  1064.            sscanf(strtok(NULL,ps), st, filename);
  1065.            add_ext(filename, "plg");
  1066.  
  1067.            tokfloat(&sx);
  1068.            tokfloat(&sy);
  1069.            tokfloat(&sz);
  1070.            tokangle(&pose.rx);
  1071.            tokangle(&pose.ry);
  1072.            tokangle(&pose.rz);
  1073.            toklong(&pose.x);
  1074.            toklong(&pose.y);
  1075.            toklong(&pose.z);
  1076.            tokint(&defsize);
  1077.            tokstrn(mappings);
  1078.  
  1079.            map = find_name(maps, mappings);
  1080.            nmaps = create_map_table(map);
  1081.  
  1082.            if ((p = strchr(filename, '=')) == NULL) break;
  1083.            oname = filename;
  1084.            *p++ = '\0';
  1085.            if((obj = find_seg(oname))==NULL)
  1086.          {
  1087.            if(!(obj = find_name(fixedolist, oname))) break;
  1088.          }
  1089.           if ((plg = fopen(pname = fix_fname(p), "r")) != NULL)
  1090.         {
  1091.           while ((obj = load_extra_plg_representation(plg, obj, &pose, sx, sy, sz, defsize)) != NULL)
  1092.           if (obj)
  1093.              {
  1094.                if(nmaps)
  1095.             masked_remap_object_surface(obj, colormap, nmaps,
  1096.               MAP_ALL_MASK, MAP_ALL_MASK, FALSE);
  1097.                physical_update_object(obj);     /* update world coords, etc */
  1098.              }
  1099.            if (plg_error(NULL))
  1100.              {
  1101.                errprintf("%s in file %s\n", plg_error(NULL), pname);
  1102.                break;
  1103.              }
  1104.            }
  1105.          else
  1106.            {
  1107.          errprintf( "Could not open '%s'", pname);
  1108.          break;
  1109.            }
  1110.          fclose(plg);
  1111.          }    break;
  1112.  
  1113.        case c_task:
  1114.          {
  1115.            char taskname[100], param[100];
  1116.            long period;
  1117.            int i;
  1118.            void *data;
  1119.  
  1120.            sscanf(strtok(NULL,ps), st, taskname);
  1121.            period = atol(strtok(NULL,ps)) * 6L;  // FASTER CLK
  1122.            strcpy(param, strtok(NULL,"\n"));
  1123.            for (i = 0; functions[i].name; ++i)
  1124.          if (!stricmp(taskname, functions[i].name))
  1125.            {
  1126.              add_task(&tasklist, functions[i].fn, period, param);
  1127.              break;
  1128.            }
  1129.           }    break;
  1130.  
  1131.        case c_position:
  1132.          {
  1133.            OBJECT *obj;
  1134.            char oname[100];
  1135.            long x, y, z;
  1136.  
  1137.            strcpy(oname, strtok(NULL,ps));
  1138.            x = atol(strtok(NULL,ps));
  1139.            y = atol(strtok(NULL,ps));
  1140.            z = atol(strtok(NULL,ps));
  1141.            if ((obj = find_seg(oname)) != NULL)
  1142.          {
  1143.            POSE p = DONTCARE_POSE;
  1144.            p.x = x;
  1145.            p.y = y;
  1146.            p.z = z;
  1147.            set_object_pose(obj, &p);
  1148.            update_object(obj);
  1149.          }
  1150.          }break;
  1151.  
  1152.        case c_rotate:
  1153.           {
  1154.         OBJECT *obj;
  1155.         char oname[100];
  1156.         float rx, ry, rz;
  1157.  
  1158.         strcpy(oname,strtok(NULL,ps));
  1159.         rx = atof(strtok(NULL,ps));
  1160.         ry = atof(strtok(NULL,ps));
  1161.         rz = atof(strtok(NULL,ps));
  1162.         if ((obj = find_seg(oname)) != NULL)
  1163.           {
  1164.             POSE p = DONTCARE_POSE;
  1165.             p.rx = float2angle(rx);
  1166.             p.ry = float2angle(ry);
  1167.             p.rz = float2angle(rz);
  1168.             set_object_pose(obj, &p);
  1169.             update_object(obj);
  1170.           }
  1171.         }
  1172.         break;
  1173.  
  1174.        case c_include:
  1175.          {
  1176.            char fname[100];
  1177.            FILE *in;
  1178.            char *f;
  1179.            strcpy(fname,strtok(NULL,ps));
  1180.            if ((in = fopen(f = fix_fname(fname), "r")) != NULL)
  1181.          {
  1182.            read_world(in);
  1183.            fclose(in);
  1184.          }
  1185.            else
  1186.          errprintf("Could not open '%s'as include file", f);
  1187.          }break;
  1188.  
  1189.        case c_surfacemap:
  1190.          {
  1191.                 /* starts a new map of color numbers to surface names */
  1192.            strcpy(surfacemapname,strtok(NULL,ps));
  1193.            current_surface = NULL;
  1194.          }     break;
  1195.  
  1196.        case c_surface:
  1197.          {
  1198.            SURFACEX *p;
  1199.                 /* maps a color number to a surface name */
  1200.            if ((p = malloc(sizeof(SURFACEX))) != NULL)  // create list element
  1201.          {
  1202.            char buf2[40];
  1203.  
  1204.            if (current_surface == NULL)           // add name for color map (first)
  1205.             add_name(&maps, surfacemapname, p);
  1206.            else
  1207.             current_surface->next = p;       // or just add
  1208.            current_surface = p;
  1209.            p->next = NULL;
  1210.            p->color = strtoul(strtok(NULL,ps), NULL, 0);  // get value
  1211.            strcpy(buf2,strtok(NULL,ps));
  1212.            p->value = strdup(buf2);
  1213.          }
  1214.          }
  1215.          break;
  1216.  
  1217.        case c_surfacedef:
  1218.          {          /* maps a surface name to an internal color value */
  1219.            char sname[100], svalue[20];
  1220.  
  1221.            strcpy(sname,strtok(NULL,ps));   // add to list
  1222.            strcpy(svalue,strtok(NULL,ps));
  1223.            add_name(&surfdefs, sname, (void *) convert_color(svalue, NULL));
  1224.           } break;
  1225.  
  1226.        case c_split:
  1227.          {
  1228.            float x, y, z, nnx, nny, nnz;
  1229.            long nx, ny, nz;
  1230.            unsigned flags = 0;
  1231.  
  1232.            x = atof(strtok(NULL,ps));
  1233.            y = atof(strtok(NULL,ps));
  1234.            z = atof(strtok(NULL,ps));
  1235.            nnx = atof(strtok(NULL,ps));
  1236.            nny = atof(strtok(NULL,ps));
  1237.            nnz = atof(strtok(NULL,ps));
  1238.            tokhex(&flags);
  1239.            scale3(nnx, nny, nnz, &nx, &ny, &nz);
  1240.            add_split_to_world(x, y, z, nx, ny, nz, flags);
  1241.            }break;
  1242.  
  1243.        case c_splitpt:
  1244.          {
  1245.            float x1, x2, x3, y1, y2, y3, z1, z2, z3;
  1246.            long nx, ny, nz;
  1247.            unsigned flags = 0;
  1248.  
  1249.            x1 = atof(strtok(NULL,ps));
  1250.            y1 = atof(strtok(NULL,ps));
  1251.            z1 = atof(strtok(NULL,ps));
  1252.            x2 = atof(strtok(NULL,ps));
  1253.            y2 = atof(strtok(NULL,ps));
  1254.            z2 = atof(strtok(NULL,ps));
  1255.            x3 = atof(strtok(NULL,ps));
  1256.            y3 = atof(strtok(NULL,ps));
  1257.            z3 = atof(strtok(NULL,ps));
  1258.            flags = strtoul(strtok(NULL,ps), NULL, 0);
  1259.            points_to_normal(x1, y1, z1, x2, y2, z2, x3, y3, z3, &nx, &ny, &nz);
  1260.            add_split_to_world(x1, y1, z1, nx, ny, nz, flags);
  1261.         } break;
  1262.  
  1263.        case c_area:
  1264.          {
  1265.            long x, y, z;
  1266.            void *what_area();
  1267.            char areaname[100];
  1268.            AREA *a;
  1269.  
  1270.            x = atol(strtok(NULL,ps));
  1271.            y = atol(strtok(NULL,ps));
  1272.            z = atol(strtok(NULL,ps));
  1273.            sscanf(strtok(NULL,ps), st, areaname);
  1274.            add_name(&areas, areaname, a=what_area(global_world_root, x, y, z));
  1275.            set_area_name(a, areaname);
  1276.         }break;
  1277.  
  1278.        case c_endsplits:
  1279.            end_of_world_splits();
  1280.            break;
  1281.  
  1282.        case c_polyobj:
  1283.        case c_polyobj2:
  1284.          {
  1285.            char map[100], map2[100];
  1286.            OBJECT *obj;
  1287.            POLY *poly;
  1288.            unsigned color;
  1289.            int nv = 0;
  1290.            int i;
  1291.            long x[18], y[18], z[18];
  1292.  
  1293.            map[0] = '\0';
  1294.            nv = atoi(strtok(NULL,ps));
  1295.            tokstrn(map);
  1296.            if (cmd==c_polyobj2) tokstrn(map2);
  1297.  
  1298.            if (nv > 18) nv = 18;
  1299.            for(i=0;i<nv;i++)
  1300.          {
  1301.            x[i] = atol(strtok(NULL,ps));
  1302.            y[i] = atol(strtok(NULL,ps));
  1303.            z[i] = atol(strtok(NULL,ps));
  1304.          }
  1305.            i = (cmd==c_polyobj2) ? 2 : 1 ;
  1306.            obj = create_fixed_object(nv, i, nv*i);
  1307.            if (obj)
  1308.          {
  1309.            char *p;
  1310.            if ((p = strtok(NULL, ps)) != NULL)
  1311.                 set_object_sorting(obj, atoi(p));
  1312.            if (map)
  1313.             color = (unsigned) find_color(surfdefs, map);
  1314.            poly = add_poly(obj, color, nv);
  1315.            for (i = 0; i < nv; i++)
  1316.              {
  1317.                add_vertex(obj, x[i], y[i], z[i]);
  1318.                add_point(obj, poly, nv-i-1);
  1319.              }
  1320.            if (cmd == c_polyobj2)
  1321.              {
  1322.                if (map2)
  1323.                 color = (unsigned) find_color(surfdefs, map2);
  1324.                poly = add_poly(obj, color, nv);
  1325.                for (i = 0; i < nv; i++)
  1326.              {
  1327.                add_point(obj, poly, i);
  1328.              }
  1329.              }
  1330.            compute_object(obj);
  1331.            add_object_to_world(obj);
  1332.          }
  1333.            }break;
  1334.      }
  1335.      }
  1336.   return;
  1337. }
  1338.