home *** CD-ROM | disk | FTP | other *** search
/ Mega Top 1 / os2_top1.zip / os2_top1 / APPS / RAYTRACE / RT / RT.C < prev    next >
C/C++ Source or Header  |  1994-06-24  |  63KB  |  2,679 lines

  1. /*
  2.  
  3. RT.C  CSG Ray Tracer
  4.  
  5. */
  6.  
  7. /*...sincludes:0:*/
  8. #include <stdio.h>
  9. #include <ctype.h>
  10. #include <stdlib.h>
  11. #include <stddef.h>
  12. #include <stdarg.h>
  13. #include <string.h>
  14. #include <memory.h>
  15. #include <malloc.h>
  16. #include <math.h>
  17. #include "standard.h"
  18. /*...e*/
  19.  
  20. static char progname[] = "rt";
  21. static char sccs_id[] = "@(#)CSG Ray Tracer  22/5/94";
  22.  
  23. /*...susefull:0:*/
  24. /*...sfatal:0:*/
  25. static void fatal(const char *fmt, ...)
  26.     {
  27.     va_list    vars;
  28.     char    s[256+1];
  29.  
  30.     va_start(vars, fmt);
  31.     vsprintf(s, fmt, vars);
  32.     va_end(vars);
  33.     fprintf(stderr, "%s: %s\n", progname, s);
  34.     exit(1);
  35.     }
  36. /*...e*/
  37. /*...smemcheck:0:*/
  38. static void *memcheck(void *p)
  39.     {
  40.     if ( p == NULL )
  41.         fatal("out of memory");
  42.     return p;
  43.     }
  44. /*...e*/
  45. /*...sstrsave:0:*/
  46. static char *strsave(char *s)
  47.     {
  48.     int    len = strlen(s);
  49.     char    *t = memcheck(malloc(len + 1));
  50.  
  51.     return strcpy(t, s);
  52.     }
  53. /*...e*/
  54. /*...e*/
  55. /*...smain:0:*/
  56. /*...sincludes:0:*/
  57. #include "rt.h"
  58. #include "fio.h"
  59. #include "tex.h"
  60. #include "vector.h"
  61. #include "rgbvec.h"
  62. #include "col.h"
  63. #include "surf.h"
  64. #include "sil.h"
  65. #include "plane.h"
  66. #include "biplane.h"
  67. #include "sphere.h"
  68. #include "quad.h"
  69. #include "shape.h"
  70.  
  71. /*...vrt\46\h:0:*/
  72. /*...vfio\46\h:0:*/
  73. /*...vtex\46\h:0:*/
  74. /*...vvector\46\h:0:*/
  75. /*...vrgbvec\46\h:0:*/
  76. /*...vcol\46\h:0:*/
  77. /*...vsurf\46\h:0:*/
  78. /*...vsil\46\h:0:*/
  79. /*...vplane\46\h:0:*/
  80. /*...vbiplane\46\h:0:*/
  81. /*...vsphere\46\h:0:*/
  82. /*...vquad\46\h:0:*/
  83. /*...vshape\46\h:0:*/
  84. /*...e*/
  85.  
  86. #ifdef OS2
  87. #include <float.h>
  88. #endif
  89.  
  90. /*...slighting:0:*/
  91. /*
  92. Surfaces do not emit light of their own. They only reflect and refract light
  93. from the light sources in the scene. The lighting/shading model used is the
  94. one defined in F,vD,F,H p734.
  95.  
  96. Global parameters :-
  97.     Ia = ambient intensity (rgb vector)
  98.  
  99. Parameters defined per surface :-
  100.     ka               = ambient-reflection-coefficient
  101.     kd               = diffuse coefficient, range 0.0 to 1.0
  102.     ks               = specular coefficient, range 0.0 to 1.0
  103.     kt               = transmission coefficent, range 0.0 to 1.0
  104.     od               = diffuse colour (rgb vector)
  105.     os               = specular colour (rgb vector)
  106.     phong_number     = Phong power
  107.     rinx = inside relative to outside of surface
  108.  
  109. Ambient contribution is :-
  110.     Ia * ka * od
  111.  
  112. Diffuse for light of intensity Ip, attenuated by distance by fatt, using
  113. Lamberts law gives :-
  114.     fatt * Ip * kd * od * cos_nl
  115.  
  116. Specular for light of intensity Ip, attenuated by distance by fatt, using
  117. the Phong shading model gives :-
  118.     fatt * Ip * ks * os * pow(cos_rv, phong_number)
  119.  
  120. Reflective component (specular only), using recursion (if depth not too deep) :-
  121.     intensity_from_looking_along_reflected_ray * ks * os
  122.  
  123. Refractive component (transmissive), given no total internal reflection,
  124. using recursion (if depth not too deep) :-
  125.     intensity_from_refractive_ray * kt
  126.  
  127. Before returning intensity, scale down by distance to origin of ray (eye).
  128. */
  129.  
  130. typedef struct { VECTOR posn; RGBVEC i; } LIGHT;
  131.  
  132. #define    N_LIGHTS    10
  133. static LIGHT lights[N_LIGHTS];
  134. static int n_lights = 0;
  135.  
  136. static RGBVEC i_background = { 0.0, 0.0, 0.0 };
  137. static RGBVEC i_ambient = { 0.0, 0.0, 0.0 };
  138. static double af1 = 1.0, af2 = 0.9;
  139.  
  140. /*...sscale_by_distance:0:*/
  141. /*
  142. The further light travels (from light source to surface, or from surface to
  143. eye etc.) the fainter it gets. Therefore as t increases, the amount intensity
  144. is reduced by should increase.
  145. */
  146.  
  147. static RGBVEC scale_by_distance(RGBVEC i, double t)
  148.     {
  149.     double    scalar = af1 * pow(af2, t);
  150.  
  151.     if ( scalar > 1.0 )
  152.         scalar = 1.0;
  153.  
  154.     i.r *= scalar;
  155.     i.g *= scalar;
  156.     i.b *= scalar;
  157.  
  158.     return i;
  159.     }
  160. /*...e*/
  161. /*...e*/
  162. /*...strace:0:*/
  163. #define    EPSILON        (1.0e-8)        /* A tiny number             */
  164.  
  165. /*...sshadow_calc:0:*/
  166. /*
  167.  
  168. In a CSG system without refraction, no rays can pass through any solid.
  169. Hence this code would return 1.0 or 0.0 depending on whether il is empty.
  170. Actually we are only interested in the range of t from 0 to dist_l being empty.
  171. This is because the light is dist_l away, things further don't cause shadows.
  172.  
  173. With refraction, things can be lit through glass-like solids.
  174. Let me admit, from the start, that refraction in a CSG system is a kludge!
  175. Glass-like solids transmit kt of the light coming from their other side.
  176. So we look along the intersections for transmissive surfaces and work out the
  177. combined transmissiveness.
  178.  
  179. We assume that pathalogical shapes (transmissive on one side, non-transmissive
  180. on the the other) do not exist. We also assume the kt coefficients match for
  181. a given shape on its entry and exit. We only use kt once (on entry) per shape.
  182.  
  183. Actually, to correctly handle illumination through refractive shapes is a
  184. nightmare, and requires that we calculate a full multi-part path back to the
  185. light. This is horrendous, and we will assume that refraction does not alter
  186. the path (much) back to the light.
  187.  
  188. In doing so, we will prevent glass causing shadows, which is the main goal.
  189.  
  190. */
  191.  
  192. static double shadow_calc(ISECTL *il, double dist_l)
  193.     {
  194.     int    j = 0;
  195.     double    kt_accum = 1.0;
  196.  
  197.     while ( j < il->n_isects && il->isects[j].t < dist_l )
  198.         {
  199.         double    kt = il->isects[j].shape->surf->kt;
  200.  
  201.         if ( kt == 0.0 )
  202.             return 0.0;
  203.         kt_accum *= kt;
  204.         j += 2;
  205.         }
  206.  
  207.     return kt_accum;
  208.     }
  209. /*...e*/
  210.  
  211. /*...sreflect:0:*/
  212. static VECTOR reflect(VECTOR unit_v, VECTOR unit_n, double cos_vn)
  213.     {
  214.     return vector_difference(scale_vector(vector_sum(unit_n, unit_n), cos_vn), unit_v);
  215.     }
  216. /*...e*/
  217. /*...srefract:0:*/
  218. /*
  219.           ^ N             Given an incident unit vector I, approaching a
  220.           | -             surface with unit normal vector N, compute the
  221.   \       |               transmitted ray T. This ray will not necessarily
  222.    \      |               be a unit vector.
  223.     \     |               
  224.      \  0 |               If the term under the square root is negative
  225.       \  i|               then this indicates total internal reflection.
  226.        \  |               
  227.      I  \||               n_it is the relative refractive index of the
  228.      -  -\|               incident medium relative the the transmissive
  229. ----------+----------> S  medium. Thus for air (1.0) entering crown glass
  230.           |\           -  (1.5) this number would be 1.0/1.5 = 0.66 approx.
  231.           | \             
  232.           |  \            We use the equation given in Byte Magazine Dec 90.
  233.           | 0 \           
  234.           |  t \          
  235.           |     \         
  236.           |   T  \|       
  237.           |   -  -\       
  238.           |               
  239. */
  240.  
  241. static BOOLEAN refract(
  242.     VECTOR unit_i,
  243.     VECTOR unit_n,
  244.     double n_it,
  245.     VECTOR *t
  246.     )
  247.     {
  248.     double    cos_ni = -scalar_product(unit_n, unit_i);
  249.     double    under_root = 1.0 + n_it*n_it * (cos_ni*cos_ni - 1.0);
  250.     double    n_comp;
  251.  
  252.     if ( under_root < 0.0 )
  253.         return FALSE; /* Total internal reflection */
  254.  
  255.     n_comp = n_it * cos_ni - sqrt(under_root);
  256.  
  257.     *t = unit_vector(vector_sum(scale_vector(unit_i, n_it),
  258.                         scale_vector(unit_n, n_comp)));
  259.  
  260.     return TRUE;
  261.     }
  262. /*...e*/
  263.  
  264. static RGBVEC trace(
  265.     SHAPE *root_shape,
  266.     VECTOR start, VECTOR direction,
  267.     int depth,
  268.     ISECTL *ils[]
  269.     )
  270.     {
  271.     ISECTL    *il = *ils;
  272.     double    t;
  273.     SHAPE    *shape;
  274.     SURF    *surf;
  275.     RGBVEC    i, od, os;
  276.     VECTOR    unit_direction, unit_v, isect_posn, unit_n;
  277.     int    j;
  278.  
  279.     unit_direction = unit_vector(direction);
  280.     unit_v = negate_vector(unit_direction);
  281.  
  282.     intersect_shape(root_shape, start, unit_direction, ils);
  283.     t_after_isectl(il, EPSILON);
  284.  
  285.     if ( is_empty_isectl(il) )
  286.         return i_background;
  287.  
  288.     /* Hit something */
  289.  
  290.     t          = il->isects[0].t;
  291.     shape      = il->isects[0].shape;
  292.     surf       = shape->surf;
  293.     isect_posn = t_along_pq(start, unit_direction, t);
  294.     unit_n     = unit_vector(normal_to_shape(shape, isect_posn));
  295.  
  296.     if ( il->isects[0].negate_normal )
  297.         unit_n = negate_vector(unit_n);
  298.  
  299.     /* Calculate colours at intersection position */
  300.  
  301.     od = evaluate_col(surf->od, isect_posn.x, isect_posn.y, isect_posn.z);
  302.     os = evaluate_col(surf->os, isect_posn.x, isect_posn.y, isect_posn.z);
  303.  
  304.     /* Ambient light */
  305.  
  306.     i.r = i_ambient.r * surf->ka * od.r;
  307.     i.g = i_ambient.g * surf->ka * od.g;
  308.     i.b = i_ambient.b * surf->ka * od.b;
  309.  
  310.     /* For each light source */
  311.  
  312.     for ( j = 0; j < n_lights; j++ )
  313. /*...shandle contribution of this light source:16:*/
  314. /*
  315. l is the vector from the intersection point to the light.
  316. dist_l is the distance to l.
  317. unit_l is a unit vector pointing to the light.
  318. We can reuse the intersection list used to hit the object for the shadow calc.
  319. */
  320.  
  321. {
  322. VECTOR    l, unit_l;
  323. double    dist_l, kt_accum;
  324.  
  325. l      = vector_difference(lights[j].posn, isect_posn);
  326. dist_l = magnitude(l);
  327. unit_l = inv_scale_vector(l, dist_l);
  328.  
  329. /* Can we see the light from the point of intersection */
  330.  
  331. intersect_shape(root_shape, isect_posn, unit_l, ils);
  332. t_after_isectl(il, EPSILON);
  333.  
  334. if ( (kt_accum = shadow_calc(il, dist_l)) > 0.0 )
  335.     {
  336.     RGBVEC    i_light;
  337.     VECTOR    unit_r;
  338.     double    cos_ln, cos_rv;
  339.  
  340.     i_light = scale_rgbvec(scale_by_distance(lights[j].i, dist_l), kt_accum);
  341.  
  342.     /* Diffuse lighting, using Lambert's law */
  343.  
  344.     if ( (cos_ln = scalar_product(unit_l, unit_n)) > 0.0 )
  345.         {
  346.         double    kd_cos_ln = surf->kd * cos_ln;
  347.  
  348.         i.r += i_light.r * od.r * kd_cos_ln;
  349.         i.g += i_light.g * od.g * kd_cos_ln;
  350.         i.b += i_light.b * od.b * kd_cos_ln;
  351.         }
  352.  
  353.     /* Specular lighting by light source, using Phong model */
  354.  
  355.     unit_r = reflect(unit_l, unit_n, cos_ln);
  356.  
  357.     if ( (cos_rv = scalar_product(unit_r, unit_v)) > 0.0 )
  358.         {
  359.         double    ks_cos_rv_n = surf->ks * pow(cos_rv, surf->phong);
  360.  
  361.         i.r += i_light.r * os.r * ks_cos_rv_n;
  362.         i.g += i_light.g * os.g * ks_cos_rv_n;
  363.         i.b += i_light.b * os.b * ks_cos_rv_n;
  364.         }
  365.     }
  366. }
  367. /*...e*/
  368.  
  369.     if ( depth > 0 )
  370.         {
  371.         if ( surf->ks > 0.0 )
  372. /*...sreflection:24:*/
  373. {
  374. double    cos_nv;
  375.  
  376. if ( (cos_nv = scalar_product(unit_n, unit_v)) > 0.0 )
  377.     {
  378.     VECTOR unit_r;
  379.     RGBVEC i_r;
  380.  
  381.     unit_r = reflect(unit_v, unit_n, cos_nv);
  382.     i_r    = trace(root_shape, isect_posn, unit_r, depth - 1, ils);
  383.  
  384.     i.r += surf->ks * os.r * i_r.r;
  385.     i.g += surf->ks * os.g * i_r.g;
  386.     i.b += surf->ks * os.b * i_r.b;
  387.     }
  388. }
  389. /*...e*/
  390.         if ( surf->kt > 0.0 )
  391. /*...srefraction:24:*/
  392. /*
  393. Refractive index of outside medium is assumed to be 1.0.
  394. Bend the ray into the medium, work out where it comes out, and bend it again.
  395. Then trace the emerging ray and accumulate its effect.
  396. If total internal reflection occurs, entering the shape, treat as reflection.
  397. If it occurs leaving, bounce the ray inside the shape and try to exit again.
  398. */
  399.  
  400. #define    MAX_BOUNCE    10
  401.  
  402. {
  403. VECTOR    unit_r;                /* Unit refracted ray at entry       */
  404.  
  405. if ( refract(unit_direction, unit_n, 1.0 / surf->rinx, &unit_r) )
  406.     /* Refraction has occurred */
  407.     {
  408.     double    t_out;            /* Value of t where leave solid      */
  409.     SHAPE    *shape_out;        /* Shape where leave solid           */
  410.     SURF    *surf_out;        /* Surface of shape where leave      */
  411.     VECTOR    isect_posn_out;        /* Place where leave solid           */
  412.     VECTOR    unit_n_out;        /* Unit inward pointing normal       */
  413.     VECTOR    unit_r_out;        /* Unit leaving refracted ray        */
  414.     double    kt_comp = surf->kt;    /* Composite scale down factor       */
  415.     double    t_comp = 0.0;        /* Composite/total distance inside   */
  416.     int    n_bounce = 0;        /* # of internal bounces             */
  417.  
  418.     isect_posn_out = isect_posn;
  419.     unit_r_out     = unit_r;
  420.     for ( ;; )
  421.         {
  422.         double    cos_rn;
  423.  
  424.         intersect_shape(root_shape, isect_posn_out, unit_r_out, ils);
  425.         t_after_isectl(il, EPSILON);
  426.  
  427.         t_out          = il->isects[1].t;
  428.         shape_out      = il->isects[1].shape;
  429.         surf_out       = shape_out->surf;
  430.         isect_posn_out = t_along_pq(isect_posn_out, unit_r_out, t_out);
  431.         unit_n_out     = unit_vector(normal_to_shape(shape_out, isect_posn_out));
  432.  
  433.         if ( !il->isects[1].negate_normal )
  434.             unit_n_out = negate_vector(unit_n_out);
  435.  
  436.         t_comp += t_out;
  437.  
  438.         if ( refract(unit_r_out, unit_n_out, surf_out->rinx, &unit_r_out) )
  439.             break; /* Refracted out of solid */
  440.  
  441.         /* Total internal reflection trying to leave solid */
  442.         /* This implies the solid has an index > 1.0 */
  443.  
  444.         if ( ++n_bounce == MAX_BOUNCE )
  445.             break; /* Reached our bounce limit, give up! */
  446.  
  447.         cos_rn = scalar_product(unit_r_out, unit_n_out);
  448.         unit_r_out = reflect(negate_vector(unit_r_out), unit_n_out, -cos_rn);
  449.         kt_comp *= surf_out->kt; /* Accumulate this as we effectively re-enter solid */
  450.         }
  451.  
  452.     if ( n_bounce < MAX_BOUNCE )
  453.         {
  454.         RGBVEC i_r;
  455.  
  456.         i_r = trace(root_shape, isect_posn_out, unit_r_out, depth - 1, ils);
  457.         i_r = scale_by_distance(i_r, t_comp);
  458.  
  459.         i.r += kt_comp * i_r.r;
  460.         i.g += kt_comp * i_r.g;
  461.         i.b += kt_comp * i_r.b;
  462.         }
  463.     }
  464. else
  465.     /* Total internal reflection trying to enter solid */
  466.     /* This implies the solid has an index < 1.0 */
  467.     /* This is not actually very likely (glass is 1.5, water 1.3 etc) */
  468.     {
  469.     double    cos_nv;
  470.  
  471.     if ( (cos_nv = scalar_product(unit_n, unit_v)) > 0.0 )
  472.         {
  473.         VECTOR u_r;
  474.         RGBVEC i_r;
  475.  
  476.         u_r = reflect(unit_v, unit_n, cos_nv);
  477.         i_r = trace(root_shape, isect_posn, u_r, depth - 1, ils);
  478.  
  479.         i.r += surf->kt * i_r.r;
  480.         i.g += surf->kt * i_r.g;
  481.         i.b += surf->kt * i_r.b;
  482.         }
  483.     }
  484. }
  485. /*...e*/
  486.         }
  487.  
  488.     return scale_by_distance(i, t);
  489.     }
  490. /*...e*/
  491. /*...slogging:0:*/
  492. #include <time.h>
  493.  
  494. static time_t t_start;
  495. static double m = 0.0; /* Maximum brightness so far */
  496.  
  497. static void bs(int n)
  498.     {
  499.     while ( n-- )
  500.         fputc('\b', stdout);
  501.     }
  502.  
  503. static char *str_of_time(time_t t)
  504.     {
  505.     static char buf[30+1];
  506.  
  507.     strcpy(buf, ctime(&t));
  508.     buf[19] = '\0';
  509.     return buf + 11;
  510.     }
  511.  
  512. static void log_init(char *fn)
  513.     {
  514.     t_start = time(NULL);
  515.  
  516.     printf("%s, started %8s,   0.0%% done, etc ________, max int 0.00 ", fn, str_of_time(t_start));
  517.     fflush(stdout);
  518.     m = 0.0;
  519.     }
  520.  
  521. static void log_bright(RGBVEC rgb)
  522.     {
  523.     if ( rgb.r > m ) m = rgb.r;
  524.     if ( rgb.g > m ) m = rgb.g;
  525.     if ( rgb.b > m ) m = rgb.b;
  526.     }
  527.  
  528. static void log_done_so_far(int done, int total)
  529.     {
  530.     double    percent = (100.0 * (double) done) / (double) total;
  531.     time_t    t_fin = t_start + (((time(NULL) - t_start) * total) / done);
  532.  
  533.     bs(40);
  534.     printf("%5.1lf%% done, etc %8s, max int %4.2lf ",
  535.         percent, str_of_time(t_fin), m);
  536.     fflush(stdout);
  537.     }
  538.  
  539. static void log_done(void)
  540.     {
  541.     time_t    t_now = time(NULL);
  542.  
  543.     bs(40);
  544.     printf("done %8s, took %ds, max int %4.2lf         \n",
  545.         str_of_time(t_now), t_now - t_start, m);
  546.     fflush(stdout);
  547.     }
  548. /*...e*/
  549. /*...smake_r_g_b:0:*/
  550. /*
  551. Given a RGBVEC value computed for a ray,
  552. work out a suitable set of 3 R,G and B bytes to write into the file.
  553. Mostly the RGBVEC should be supplied to us in a good range.
  554. Occasionally we must clamp the value.
  555. We ought to do something more clever here.
  556. */
  557.  
  558. static void make_r_g_b(RGBVEC rgb, byte *r, byte *g, byte *b)
  559.     {
  560.     if ( rgb.r <= 1.0 ) *r = (byte) (rgb.r * 255.0); else *r = 255;
  561.     if ( rgb.g <= 1.0 ) *g = (byte) (rgb.g * 255.0); else *g = 255;
  562.     if ( rgb.b <= 1.0 ) *b = (byte) (rgb.b * 255.0); else *b = 255;
  563.     }
  564. /*...e*/
  565. static double least_vis_diff = 1.0 / 255.0;
  566. /*...srender:0:*/
  567. typedef    VECTOR (*RAY_FUNC)(
  568.         int h, int v, int hpixels, int vpixels,
  569.         double hangle, double vangle,
  570.         VECTOR unit_forward, VECTOR unit_right, VECTOR unit_up
  571.         );
  572.  
  573. /*...scalc_normal_ray:0:*/
  574. /*
  575. Calculates a ray given usual perspective rules.
  576. Need to know which pixel of how many we are tracing.
  577. Need to know right and up vectors.
  578. */
  579.  
  580. static VECTOR calc_normal_ray(
  581.     int h, int v, int hpixels, int vpixels,
  582.     double hangle, double vangle,
  583.     VECTOR unit_forward, VECTOR unit_right, VECTOR unit_up
  584.     )
  585.     {
  586.     double hpixels2   = (double) (hpixels >> 1);
  587.     double vpixels2   = (double) (vpixels >> 1);
  588.     double vfactor    = (v - vpixels2) / vpixels2;
  589.     double hfactor    = (h - hpixels2) / hpixels2;
  590.     VECTOR vis_right  = scale_vector(unit_right, tan(hangle));
  591.     VECTOR vis_up     = scale_vector(unit_up   , tan(vangle));
  592.     VECTOR comp_up    = scale_vector(vis_up, vfactor);
  593.     VECTOR ray_plane  = vector_sum(unit_forward, comp_up);
  594.     VECTOR comp_right = scale_vector(vis_right, hfactor);
  595.     return vector_sum(ray_plane, comp_right);
  596.     }
  597. /*...e*/
  598. /*...scalc_escher_ray:0:*/
  599. /*
  600. Calculates a ray given using the twisted perspective Escher used in his
  601. "Above and Below" and "House of Stairs" works.
  602. */
  603.  
  604. static VECTOR calc_escher_ray(
  605.     int h, int v, int hpixels, int vpixels,
  606.     double hangle, double vangle,
  607.     VECTOR unit_forward, VECTOR unit_right, VECTOR unit_up
  608.     )
  609.     {
  610.     double hpixels2     = (double) (hpixels >> 1);
  611.     double vpixels2     = (double) (vpixels >> 1);
  612.     double vfactor      = (v - vpixels2) / vpixels2;
  613.     double hfactor      = (h - hpixels2) / hpixels2;
  614.     VECTOR vis_right    = scale_vector(unit_right, tan(hangle));
  615.     VECTOR comp_right   = scale_vector(vis_right, hfactor);
  616.     double va           = vangle * vfactor;
  617.     VECTOR comp_forward = scale_vector(unit_forward, cos(va));
  618.     VECTOR comp_up      = scale_vector(unit_up, sin(va));
  619.     return vector_sum(comp_forward, vector_sum(comp_right, comp_up));
  620.     }
  621. /*...e*/
  622. /*...sbasic_render:0:*/
  623. /*
  624. Traditional basic render operation.
  625. Send one ray for each pixel (excluding extras for reflection etc.).
  626. ie: Sample once for each pixel, do NOT supersample.
  627. Also, do not perform any 'jittering' of rays.
  628. */
  629.  
  630. static void basic_render(
  631.     char *fn,
  632.     BITMAP *bitmap,
  633.     ISECTL **ils,
  634.     SHAPE *shape,
  635.     VECTOR eye, VECTOR unit_forward, VECTOR unit_right, VECTOR unit_up,
  636.     int hpixels, int vpixels, double hangle, double vangle,
  637.     RAY_FUNC calc_ray,
  638.     int depth
  639.     )
  640.     {
  641.     int h, v;
  642.     log_init(fn);
  643.     for ( v = 0; v < vpixels; v++ )
  644.         {
  645.         for ( h = 0; h < hpixels; h++ )
  646.             {
  647.             VECTOR ray = (*calc_ray)(h, v, hpixels, vpixels, hangle, vangle, unit_forward, unit_right, unit_up);
  648.             RGBVEC rgb = trace(shape, eye, ray, depth, ils);
  649.             byte r, g, b;
  650.             log_bright(rgb);
  651.             make_r_g_b(rgb, &r, &g, &b);
  652.             fio_set_pixel(bitmap, h, v, r, g, b);
  653.             }
  654.         log_done_so_far(v + 1, vpixels);
  655.         }
  656.     log_done();
  657.     }
  658. /*...e*/
  659. /*...swhitted_render:0:*/
  660. /*
  661. Render using Whitted adaptive supersampling.
  662. Send rays at the 4 corners of a pixel.
  663. Ask function whitted for a combined pixel value.
  664. */
  665.  
  666. typedef struct { VECTOR ray; RGBVEC rgb; BOOLEAN traced; } SAMPLE;
  667.  
  668. #define    MAX_SS    4        /* Supersample by upto 4 each way */
  669.  
  670. static long normal = 0, extra = 0;
  671. /*...swhitted:0:*/
  672. /*
  673. Return a combined weighting of the 4 corner samples.
  674. If they differ 'notably', break the area into 4 sub-cells.
  675. Generate the 5 extra samples needed for 4 sub-cells.
  676. Then call ourself recursively to get colours for each cell, and return average.
  677. */
  678.  
  679. /*...saverage_of_4:0:*/
  680. static RGBVEC average_of_4(RGBVEC a, RGBVEC b, RGBVEC c, RGBVEC d)
  681.     {
  682.     RGBVEC av;
  683.     av.r = (a.r + b.r + c.r + d.r) * 0.25;
  684.     av.g = (a.g + b.g + c.g + d.g) * 0.25;
  685.     av.b = (a.b + b.b + c.b + d.b) * 0.25;
  686.     return av;
  687.     }
  688. /*...e*/
  689. /*...smidpoint_of_2:0:*/
  690. static VECTOR midpoint_of_2(VECTOR a, VECTOR b)
  691.     {
  692.     VECTOR mid;
  693.     mid.x = (a.x + b.x) * 0.5;
  694.     mid.y = (a.y + b.y) * 0.5;
  695.     mid.z = (a.z + b.z) * 0.5;
  696.     return mid;
  697.     }
  698. /*...e*/
  699. /*...smidpoint_of_4:0:*/
  700. static VECTOR midpoint_of_4(VECTOR a, VECTOR b, VECTOR c, VECTOR d)
  701.     {
  702.     VECTOR mid;
  703.     mid.x = (a.x + b.x + c.x + d.x) * 0.25;
  704.     mid.y = (a.y + b.y + c.y + d.y) * 0.25;
  705.     mid.z = (a.z + b.z + c.z + d.z) * 0.25;
  706.     return mid;
  707.     }
  708. /*...e*/
  709. /*...sis_close:0:*/
  710. /*
  711. 2 colours are not close when their red green and blue components differ
  712. more than the least visible difference.
  713. */
  714.  
  715. static BOOLEAN is_close(RGBVEC a, RGBVEC b)
  716.     {
  717.     return fabs(a.r - b.r) < least_vis_diff &&
  718.            fabs(a.g - b.g) < least_vis_diff &&
  719.            fabs(a.b - b.b) < least_vis_diff ;
  720.     }
  721. /*...e*/
  722.  
  723. static RGBVEC whitted(
  724.     SAMPLE *samples[MAX_SS+1],
  725.     int h,                /* Scaled by ss */
  726.     int ss,                /* Sample spacing */
  727.     SHAPE *shape,
  728.     VECTOR eye,
  729.     int depth,
  730.     ISECTL **ils
  731.     )
  732.     {
  733.     SAMPLE *sa = &(samples[ 0][h     ]);
  734.     SAMPLE *sb = &(samples[ 0][h + ss]);
  735.     SAMPLE *sc = &(samples[ss][h     ]);
  736.     SAMPLE *sd = &(samples[ss][h + ss]);
  737.     RGBVEC m_rgb = average_of_4(sa->rgb, sb->rgb, sc->rgb, sd->rgb);
  738.  
  739.     if ( ss == 1 )
  740.         return m_rgb;
  741.  
  742.     /* Are all 4 corners close to the middle */
  743.  
  744.     if ( is_close(m_rgb, sa->rgb) &&
  745.          is_close(m_rgb, sb->rgb) &&
  746.          is_close(m_rgb, sc->rgb) &&
  747.          is_close(m_rgb, sd->rgb) )
  748.         return m_rgb;
  749.     else
  750.         {
  751.         VECTOR a = sa->ray, b = sb->ray, c = sc->ray, d = sd->ray;
  752.         int ss2 = (ss >> 1);
  753.         SAMPLE *sab   = &(samples[0  ][h + ss2]);
  754.         SAMPLE *scd   = &(samples[ss ][h + ss2]);
  755.         SAMPLE *sac   = &(samples[ss2][h      ]);
  756.         SAMPLE *sbd   = &(samples[ss2][h + ss ]);
  757.         SAMPLE *sabcd = &(samples[ss2][h + ss2]);
  758.  
  759.         /* Trace any that are not already traced */
  760.  
  761.         if ( ! sab->traced )
  762.             {
  763.             sab->ray = midpoint_of_2(a, b);
  764.             sab->rgb = trace(shape, eye, sab->ray, depth, ils);
  765.             sab->traced = TRUE;
  766.             extra++;
  767.             }
  768.  
  769.         if ( ! scd->traced )
  770.             {
  771.             scd->ray = midpoint_of_2(c, d);
  772.             scd->rgb = trace(shape, eye, scd->ray, depth, ils);
  773.             scd->traced = TRUE;
  774.             extra++;
  775.             }
  776.  
  777.         if ( ! sac->traced )
  778.             {
  779.             sac->ray = midpoint_of_2(a, c);
  780.             sac->rgb = trace(shape, eye, sac->ray, depth, ils);
  781.             sac->traced = TRUE;
  782.             extra++;
  783.             }
  784.  
  785.         if ( ! sbd->traced )
  786.             {
  787.             sbd->ray = midpoint_of_2(b, d);
  788.             sbd->rgb = trace(shape, eye, sbd->ray, depth, ils);
  789.             sbd->traced = TRUE;
  790.             extra++;
  791.             }
  792.  
  793.         if ( ! sabcd->traced )
  794.             {
  795.             sabcd->ray = midpoint_of_4(a, b, c, d);
  796.             sabcd->rgb = trace(shape, eye, sabcd->ray, depth, ils);
  797.             sabcd->traced = TRUE;
  798.             extra++;
  799.             }
  800.  
  801.         /* Now obtain average of 4 nested whitted values */
  802.  
  803.         return average_of_4(
  804.             whitted(samples    , h    , ss2, shape, eye, depth, ils),
  805.             whitted(samples+ss2, h    , ss2, shape, eye, depth, ils),
  806.             whitted(samples    , h+ss2, ss2, shape, eye, depth, ils),
  807.             whitted(samples+ss2, h+ss2, ss2, shape, eye, depth, ils)
  808.             );
  809.         }
  810.     }
  811. /*...e*/
  812.  
  813. static void whitted_render(
  814.     char *fn,
  815.     BITMAP *bitmap,
  816.     ISECTL **ils,
  817.     SHAPE *shape,
  818.     VECTOR eye, VECTOR unit_forward, VECTOR unit_right, VECTOR unit_up,
  819.     int hpixels, int vpixels, double hangle, double vangle,
  820.     RAY_FUNC calc_ray,
  821.     int depth
  822.     )
  823.     {
  824.     int h, v, ssh, ssv;
  825.     int hsamples = (MAX_SS * hpixels) + 1;
  826.     SAMPLE *samples[MAX_SS+1], *t;
  827.  
  828.     for ( ssv = 0; ssv <= MAX_SS; ssv++ )
  829.         {
  830.         if ( (samples[ssv] = malloc(hsamples * sizeof(SAMPLE))) == NULL)
  831.             fatal("out of memory");
  832.         for ( ssh = 0; ssh < hsamples; ssh++ )
  833.             samples[ssv][ssh].traced = FALSE;
  834.         }
  835.  
  836.     log_init(fn);
  837.  
  838.     /* Work out the top row */
  839.     for ( h = 0; h <= hpixels; h++ )
  840.         {
  841.         VECTOR ray = (*calc_ray)(h, 0, hpixels, vpixels, hangle, vangle, unit_forward, unit_right, unit_up);
  842.         samples[0][h * MAX_SS].ray = ray;
  843.         samples[0][h * MAX_SS].rgb = trace(shape, eye, ray, depth, ils);
  844.         samples[0][h * MAX_SS].traced = TRUE;
  845.         normal++;
  846.         }
  847.  
  848.     log_done_so_far(1, vpixels+1);
  849.  
  850.     for ( v = 0; v < vpixels; v++ )
  851.         {
  852.         /* Work out bottom row (for this scan line of pixels) */
  853.         for ( h = 0; h <= hpixels; h++ )
  854.             {
  855.             VECTOR ray = (*calc_ray)(h, v+1, hpixels, vpixels, hangle, vangle, unit_forward, unit_right, unit_up);
  856.             samples[MAX_SS][h * MAX_SS].ray = ray;
  857.             samples[MAX_SS][h * MAX_SS].rgb = trace(shape, eye, ray, depth, ils);
  858.             samples[MAX_SS][h * MAX_SS].traced = TRUE;
  859.             normal++;
  860.             }
  861.         for ( h = 0; h < hpixels; h++ )
  862.             {
  863.             RGBVEC rgb = whitted(samples, h * MAX_SS, MAX_SS, shape, eye, depth, ils);
  864.             byte r, g, b;
  865.             log_bright(rgb);
  866.             make_r_g_b(rgb, &r, &g, &b);
  867.             fio_set_pixel(bitmap, h, v, r, g, b);
  868.             }
  869.         t = samples[0]; samples[0] = samples[MAX_SS]; samples[MAX_SS] = t;
  870.         for ( ssv = 1; ssv <= MAX_SS; ssv++ )
  871.             for ( ssh = 0; ssh < hsamples; ssh++ )
  872.                 samples[ssv][ssh].traced = FALSE;
  873.         log_done_so_far(v + 1, vpixels+1);
  874.         }
  875.     log_done();
  876.     printf("%ld normal rays, %ld extra rays\n", normal, extra);
  877.  
  878.     for ( ssv = 0; ssv <= MAX_SS; ssv++ )
  879.         free(samples[ssv]);
  880.     }
  881. /*...e*/
  882.  
  883. static void render(
  884.     SHAPE *shape,                /* Root of shape tree        */
  885.     VECTOR eye,                /* Eye position vector       */
  886.     VECTOR forward,                /* Forward vector            */
  887.     VECTOR up,                /* Up vector                 */
  888.     double hangle, double vangle,        /* Veiwing angles            */
  889.     int hpixels, int vpixels,        /* No of pixels to render    */
  890.     int depth,                /* Depth to recurse to       */
  891.     int render_type,            /* Rendering type            */
  892.     char *fn                /* Output filename           */
  893.     )
  894.     {
  895.     VECTOR unit_forward = unit_vector(forward);
  896.     VECTOR unit_up      = unit_vector(up);
  897.     VECTOR unit_right   = vector_product(unit_forward, unit_up);
  898.     BITMAP    *bitmap;
  899.     int    n_isectls, n_isects, i;
  900.     ISECTL    **ils;
  901.     RAY_FUNC calc_ray;
  902.  
  903.     if ( (bitmap = fio_create_bitmap(hpixels, vpixels)) == NULL )
  904.         fatal("out of memory for bitmap %dx%d", hpixels, vpixels);
  905.  
  906.     preprocess_shape(shape, &n_isectls, &n_isects);
  907.  
  908.     /* Now allocate intersection lists, for use in tracing */
  909.  
  910.     printf("Require %d intersection lists, each of %d intersections\n",
  911.         n_isectls, n_isects);
  912.     if ( (ils = malloc(n_isectls * sizeof(ISECTL *))) == NULL )
  913.         fatal("out of memory");
  914.     for ( i = 0; i < n_isectls; i++ )
  915.         if ( (ils[i] = create_isectl(n_isects)) == NULL )
  916.             fatal("out of memory");
  917.  
  918.     switch ( render_type / 10 )
  919.         {
  920.         case 0:
  921.             calc_ray = calc_normal_ray;
  922.             break;
  923.         case 1:
  924.             calc_ray = calc_escher_ray;
  925.             break;
  926.         default:
  927.             fatal("unknown projection");
  928.         }
  929.  
  930.     switch ( render_type % 10 )
  931.         {
  932.         case 0:
  933.             basic_render(fn, bitmap, ils, shape, eye, unit_forward, unit_right, unit_up, hpixels, vpixels, hangle, vangle, calc_ray, depth);
  934.             break;
  935.         case 1:
  936.             whitted_render(fn, bitmap, ils, shape, eye, unit_forward, unit_right, unit_up, hpixels, vpixels, hangle, vangle, calc_ray, depth);
  937.             break;
  938.         default:
  939.             fatal("unknown render type");
  940.         }
  941.  
  942.     for ( i = 0; i < n_isectls; i++ )
  943.         destroy_isectl(ils[i]);
  944.     free(ils);
  945.  
  946.     if ( !fio_write_bitmap(bitmap, fn) )
  947.         fatal("unable to write %s", fn);
  948.  
  949.     fio_destroy_bitmap(bitmap);
  950.     }
  951. /*...e*/
  952. /*...sread_data_file:0:*/
  953. /*...slexical stuff:0:*/
  954. #define    S_EOF        0
  955. #define    S_ID        1
  956. #define    S_VALUE        2
  957. #define    S_STRING    3
  958. #define    S_COMMA        4
  959. #define    S_LPAR        5
  960. #define    S_RPAR        6
  961. #define    S_RAD        7
  962. #define    S_VECTOR    8
  963. #define    S_RGBVEC    9
  964. #define    S_COL_CONST    10
  965. #define    S_COL_NO_MOVE    11
  966. #define    S_COL_INTERP0    12
  967. #define    S_COL_INTERP1    13
  968. #define    S_COL_INTERP2    14
  969. #define    S_COL_FIELD2D    15
  970. #define    S_COL_FIELD3D    16
  971. #define    S_COL_REMAP    17
  972. #define    S_COL_CYLPOLAR    18
  973. #define    S_COL_SPHPOLAR    19
  974. #define    S_COL_MATRIX2D    20
  975. #define    S_COL_MATRIX3D    21
  976. #define    S_SURF        22
  977. #define    S_RESURF    23
  978. #define    S_PLANE        24
  979. #define    S_X_LT        25
  980. #define    S_X_GT        26
  981. #define    S_Y_LT        27
  982. #define    S_Y_GT        28
  983. #define    S_Z_LT        29
  984. #define    S_Z_GT        30
  985. #define    S_BIPLANE    31
  986. #define    S_X_IN        32
  987. #define    S_Y_IN        33
  988. #define    S_Z_IN        34
  989. #define    S_QUAD        35
  990. #define    S_ELLIPSOID    36
  991. #define    S_SPHERE    37
  992. #define    S_X_ELL_CYL    38
  993. #define    S_Y_ELL_CYL    39
  994. #define    S_Z_ELL_CYL    40
  995. #define    S_X_CYL        41
  996. #define    S_Y_CYL        42
  997. #define    S_Z_CYL        43
  998. #define    S_X_ELL_CONE    44
  999. #define    S_Y_ELL_CONE    45
  1000. #define    S_Z_ELL_CONE    46
  1001. #define    S_X_CONE    47
  1002. #define    S_Y_CONE    48
  1003. #define    S_Z_CONE    49
  1004. #define    S_TRANS        50
  1005. #define    S_TRANS_X    51
  1006. #define    S_TRANS_Y    52
  1007. #define    S_TRANS_Z    53
  1008. #define    S_SCALE        54
  1009. #define    S_SCALE_X    55
  1010. #define    S_SCALE_Y    56
  1011. #define    S_SCALE_Z    57
  1012. #define    S_ROTATE_X    58
  1013. #define    S_ROTATE_Y    59
  1014. #define    S_ROTATE_Z    60
  1015. #define    S_UNION        61
  1016. #define    S_ISECT        62
  1017. #define    S_DIFF        63
  1018. #define    S_SDIFF        64
  1019. #define    S_EXTENT    65
  1020. #define    S_SET_VALUE    66
  1021. #define    S_SET_VECTOR    67
  1022. #define    S_SET_RGBVEC    68
  1023. #define    S_SET_COL    69
  1024. #define    S_SET_SURF    70
  1025. #define    S_SET_SHAPE    71
  1026. #define    S_SET_BKGND    72
  1027. #define    S_SET_AMBIENT    73
  1028. #define    S_SET_ATTEN    74
  1029. #define    S_ADD_LIGHT    75
  1030. #define    S_RENDER    76
  1031. #define    S_VISDIFF    77
  1032. #define    S_INCLUDE    78
  1033.  
  1034. typedef struct { char *id_name; int id; } RESERVED_WORD;
  1035.  
  1036. static RESERVED_WORD my_reserved_words[] =
  1037.     {
  1038.     "rad",        S_RAD,
  1039.     "xyz",        S_VECTOR,
  1040.     "rgb",        S_RGBVEC,
  1041.     "col",        S_COL_CONST,
  1042.     "col_nomove",    S_COL_NO_MOVE,
  1043.     "col_interp0",    S_COL_INTERP0,
  1044.     "col_interp1",    S_COL_INTERP1,
  1045.     "col_interp2",    S_COL_INTERP2,
  1046.     "col_field2d",    S_COL_FIELD2D,
  1047.     "col_field3d",    S_COL_FIELD3D,
  1048.     "col_remap",    S_COL_REMAP,
  1049.     "col_cyl",    S_COL_CYLPOLAR,
  1050.     "col_sph",    S_COL_SPHPOLAR,
  1051.     "col_mat2d",    S_COL_MATRIX2D,
  1052.     "col_mat3d",    S_COL_MATRIX3D,
  1053.     "surf",        S_SURF,
  1054.     "resurf",    S_RESURF,
  1055.     "plane",    S_PLANE,
  1056.     "x_lt",        S_X_LT,
  1057.     "x_gt",        S_X_GT,
  1058.     "y_lt",        S_Y_LT,
  1059.     "y_gt",        S_Y_GT,
  1060.     "z_lt",        S_Z_LT,
  1061.     "z_gt",        S_Z_GT,
  1062.     "biplane",    S_BIPLANE,
  1063.     "x_in",        S_X_IN,
  1064.     "y_in",        S_Y_IN,
  1065.     "z_in",        S_Z_IN,
  1066.     "quad",        S_QUAD,
  1067.     "ellipsoid",    S_ELLIPSOID,
  1068.     "sphere",    S_SPHERE,
  1069.     "x_ell_cyl",     S_X_ELL_CYL,
  1070.     "y_ell_cyl",     S_Y_ELL_CYL,
  1071.     "z_ell_cyl",     S_Z_ELL_CYL,
  1072.     "x_cyl",     S_X_CYL,
  1073.     "y_cyl",     S_Y_CYL,
  1074.     "z_cyl",     S_Z_CYL,
  1075.     "x_ell_cone",     S_X_ELL_CONE,
  1076.     "y_ell_cone",     S_Y_ELL_CONE,
  1077.     "z_ell_cone",     S_Z_ELL_CONE,
  1078.     "x_cone",     S_X_CONE,
  1079.     "y_cone",     S_Y_CONE,
  1080.     "z_cone",     S_Z_CONE,
  1081.     "trans",    S_TRANS,
  1082.     "trans_x",    S_TRANS_X,
  1083.     "trans_y",    S_TRANS_Y,
  1084.     "trans_z",    S_TRANS_Z,
  1085.     "scale",    S_SCALE,
  1086.     "scale_x",    S_SCALE_X,
  1087.     "scale_y",    S_SCALE_Y,
  1088.     "scale_z",    S_SCALE_Z,
  1089.     "rot_x",    S_ROTATE_X,
  1090.     "rot_y",    S_ROTATE_Y,
  1091.     "rot_z",    S_ROTATE_Z,
  1092.     "union",    S_UNION,
  1093.     "isect",    S_ISECT,
  1094.     "diff",        S_DIFF,
  1095.     "sdiff",    S_SDIFF,
  1096.     "extent",    S_EXTENT,
  1097.     "set_value",    S_SET_VALUE,
  1098.     "set_xyz",    S_SET_VECTOR,
  1099.     "set_rgb",    S_SET_RGBVEC,
  1100.     "set_col",    S_SET_COL,
  1101.     "set_surf",    S_SET_SURF,
  1102.     "set_shape",    S_SET_SHAPE,
  1103.     "set_background",S_SET_BKGND,
  1104.     "set_ambient",    S_SET_AMBIENT,
  1105.     "set_attenuation",S_SET_ATTEN,
  1106.     "add_light",    S_ADD_LIGHT,
  1107.     "render",    S_RENDER,
  1108.     "visdiff",    S_VISDIFF,
  1109.     "include",    S_INCLUDE,
  1110.     };
  1111.  
  1112. #define    N_RESERVED_WORDS (sizeof(my_reserved_words)/sizeof(my_reserved_words[0]))
  1113.  
  1114. typedef struct
  1115.     {
  1116.     FILE *fp;
  1117.     char fn[500+1];
  1118.     unsigned long line_num;
  1119.     int chr;
  1120.     char str[100+1];
  1121.     char id_name[100+1];
  1122.     double id_value;
  1123.     } F;
  1124.  
  1125. /*...sopen_stream:0:*/
  1126. static F *open_stream(FILE *fp, char *fn)
  1127.     {
  1128.     F *f = (F *) memcheck(malloc(sizeof(F)));
  1129.  
  1130.     f->fp = fp;
  1131.     f->line_num = 1UL;
  1132.     strcpy(f->fn, fn);
  1133.     f->chr = getc(f->fp);
  1134.     return f;
  1135.     }
  1136. /*...e*/
  1137. /*...sclose_stream:0:*/
  1138. static FILE *close_stream(F *f)
  1139.     {
  1140.     FILE    *fp = f->fp;
  1141.  
  1142.     free(f);
  1143.     return fp;
  1144.     }
  1145. /*...e*/
  1146. /*...sreaderr:0:*/
  1147. static void readerr(F *f, const char *fmt, ...)
  1148.     {
  1149.     va_list    vars;
  1150.     char    s[256+1];
  1151.  
  1152.     va_start(vars, fmt);
  1153.     vsprintf(s, fmt, vars);
  1154.     va_end(vars);
  1155.     fprintf(stderr, "%s(%lu): %s\n", f->fn, f->line_num, s);
  1156.     exit(1);
  1157.     }
  1158. /*...e*/
  1159. /*...sgetsym:0:*/
  1160. static int getsym(F *f)
  1161.     {
  1162.     int    i = 0;
  1163.  
  1164.     for ( ;; )
  1165.         {
  1166.         while ( f->chr != EOF && isspace(f->chr) )
  1167.             {
  1168.             if ( f->chr == '\n' )
  1169.                 f->line_num++;
  1170.             f->chr = getc(f->fp);
  1171.             }
  1172.  
  1173.         if ( f->chr == EOF )
  1174.             return S_EOF;
  1175.  
  1176.         if ( f->chr != ';' )
  1177.             break;
  1178.  
  1179.         while ( (f->chr = getc(f->fp)) != EOF && f->chr != '\n' )
  1180.             if ( f->chr == '\n' )
  1181.                 f->line_num++;
  1182.         }
  1183.  
  1184.     if ( f->chr == ',' )
  1185.         {
  1186.         f->chr = getc(f->fp);
  1187.         return S_COMMA;
  1188.         }
  1189.  
  1190.     if ( f->chr == '(' )
  1191.         {
  1192.         f->chr = getc(f->fp);
  1193.         return S_LPAR;
  1194.         }
  1195.  
  1196.     if ( f->chr == ')' )
  1197.         {
  1198.         f->chr = getc(f->fp);
  1199.         return S_RPAR;
  1200.         }
  1201.  
  1202.     if ( isdigit(f->chr) || f->chr == '+' || f->chr == '-' || f->chr == '.' )
  1203.         {
  1204.         char    num[50+1];
  1205.  
  1206.         do
  1207.             {
  1208.             num[i++] = (char) f->chr;
  1209.             f->chr = getc(f->fp);
  1210.             }
  1211.         while ( isdigit(f->chr) || f->chr == '+' || f->chr == '-' ||
  1212.             f->chr == '.' || f->chr == 'e' || f->chr == 'E' );
  1213.         num[i] = (char) '\0';
  1214.  
  1215.         sscanf(num, "%lf", &(f->id_value));
  1216.  
  1217.         return S_VALUE;
  1218.         }
  1219.  
  1220.     if ( f->chr == '"' )
  1221.         {
  1222.         int    j = 0;
  1223.  
  1224.         while ( (f->chr = getc(f->fp)) != EOF && f->chr != '"' )
  1225.             f->str[j++] = (char) f->chr;
  1226.         f->str[j] = '\0';
  1227.         if ( f->chr == '"' )
  1228.             f->chr = getc(f->fp);
  1229.         return S_STRING;
  1230.         }
  1231.  
  1232.     if ( !(isalnum(f->chr) || f->chr != '_') )
  1233.         readerr(f, "character 0x%02x not expected", f->chr);
  1234.  
  1235.     while ( f->chr != EOF && (isalnum(f->chr) || f->chr == '_') )
  1236.         {
  1237.         f->id_name[i++] = (char) f->chr;
  1238.         f->chr = getc(f->fp);
  1239.         }
  1240.     f->id_name[i] = '\0';
  1241.  
  1242.     for ( i = 0; i < N_RESERVED_WORDS; i++ )
  1243.         if ( !strcmp(f->id_name, my_reserved_words[i].id_name) )
  1244.             return my_reserved_words[i].id;
  1245.  
  1246.     return S_ID;
  1247.     }
  1248. /*...e*/
  1249. /*...sskip:0:*/
  1250. static void skip(F *f, int symbol, char *symbol_name)
  1251.     {
  1252.     if ( getsym(f) != symbol )
  1253.         readerr(f, "expected %s", symbol_name);
  1254.     }
  1255. /*...e*/
  1256. /*...e*/
  1257. /*...suser variables:0:*/
  1258. typedef byte VTYPE;
  1259. #define    VTYPE_VALUE    ((VTYPE) 0)
  1260. #define    VTYPE_VECTOR    ((VTYPE) 1)
  1261. #define    VTYPE_RGBVEC    ((VTYPE) 2)
  1262. #define    VTYPE_COL    ((VTYPE) 3)
  1263. #define    VTYPE_SURF    ((VTYPE) 4)
  1264. #define    VTYPE_SHAPE    ((VTYPE) 5)
  1265.  
  1266. static char *vtype_names[] =
  1267.     {
  1268.     "value",
  1269.     "xyz_vector",
  1270.     "rgb_vector",
  1271.     "colour",
  1272.     "surface",
  1273.     "shape",
  1274.     };
  1275.  
  1276. typedef struct
  1277.     {
  1278.     char    *name;
  1279.     VTYPE    vtype;
  1280.     union
  1281.         {
  1282.         double    value;
  1283.         VECTOR    vector;
  1284.         RGBVEC    rgb;
  1285.         COL    *col;
  1286.         SURF    *surf;
  1287.         SHAPE    *shape;
  1288.         } u;
  1289.     } VAR;
  1290.  
  1291. #define    N_VARS        500
  1292. static VAR vars[N_VARS];
  1293. static int n_vars = 0;
  1294.  
  1295. /*...slookup_var:0:*/
  1296. static int lookup_var(char *name)
  1297.     {
  1298.     int    i;
  1299.  
  1300.     for ( i = 0; i < n_vars; i++ )
  1301.         if ( !strcmp(name, vars[i].name) )
  1302.             return i;
  1303.     return -1;
  1304.     }
  1305. /*...e*/
  1306. /*...slookup_defined_var:0:*/
  1307. static int lookup_defined_var(F *f, char *name)
  1308.     {
  1309.     int    i;
  1310.  
  1311.     if ( (i = lookup_var(name)) == -1 )
  1312.         readerr(f, "undefined variable %s", name);
  1313.     return i;
  1314.     }
  1315. /*...e*/
  1316. /*...slookup_defined_var_vtype:0:*/
  1317. static int lookup_defined_var_vtype(F *f, char *name, VTYPE vtype)
  1318.     {
  1319.     int    i = lookup_defined_var(f, name);
  1320.  
  1321.     if ( vars[i].vtype != vtype )
  1322.         readerr(f, "expected %s variable", vtype_names[vtype]);
  1323.     return i;
  1324.     }
  1325. /*...e*/
  1326.  
  1327. /*...sadd_value_var:0:*/
  1328. static void add_value_var(F *f, char *name, double value)
  1329.     {
  1330.     if ( n_vars == N_VARS )
  1331.         readerr(f, "too many variables");
  1332.  
  1333.     vars[n_vars  ].name    = strsave(name);
  1334.     vars[n_vars  ].vtype   = VTYPE_VALUE;
  1335.     vars[n_vars++].u.value = value;
  1336.     }
  1337. /*...e*/
  1338. /*...sadd_vector_var:0:*/
  1339. static void add_vector_var(F *f, char *name, VECTOR vector)
  1340.     {
  1341.     if ( n_vars == N_VARS )
  1342.         readerr(f, "too many variables");
  1343.  
  1344.     vars[n_vars  ].name     = strsave(name);
  1345.     vars[n_vars  ].vtype    = VTYPE_VECTOR;
  1346.     vars[n_vars++].u.vector = vector;
  1347.     }
  1348. /*...e*/
  1349. /*...sadd_rgb_var:0:*/
  1350. static void add_rgb_var(F *f, char *name, RGBVEC rgb)
  1351.     {
  1352.     if ( n_vars == N_VARS )
  1353.         readerr(f, "too many variables");
  1354.  
  1355.     vars[n_vars  ].name  = strsave(name);
  1356.     vars[n_vars  ].vtype = VTYPE_RGBVEC;
  1357.     vars[n_vars++].u.rgb = rgb;
  1358.     }
  1359. /*...e*/
  1360. /*...sadd_col_var:0:*/
  1361. static void add_col_var(F *f, char *name, COL *col)
  1362.     {
  1363.     if ( n_vars == N_VARS )
  1364.         readerr(f, "too many variables");
  1365.  
  1366.     vars[n_vars  ].name  = strsave(name);
  1367.     vars[n_vars  ].vtype = VTYPE_COL;
  1368.     vars[n_vars++].u.col = col;
  1369.     }
  1370. /*...e*/
  1371. /*...sadd_surf_var:0:*/
  1372. static void add_surf_var(F *f, char *name, SURF *surf)
  1373.     {
  1374.     if ( n_vars == N_VARS )
  1375.         readerr(f, "too many variables");
  1376.  
  1377.     vars[n_vars  ].name   = strsave(name);
  1378.     vars[n_vars  ].vtype  = VTYPE_SURF;
  1379.     vars[n_vars++].u.surf = surf;
  1380.     }
  1381. /*...e*/
  1382. /*...sadd_shape_var:0:*/
  1383. static void add_shape_var(F *f, char *name, SHAPE *shape)
  1384.     {
  1385.     if ( n_vars == N_VARS )
  1386.         readerr(f, "too many variables");
  1387.  
  1388.     vars[n_vars  ].name    = strsave(name);
  1389.     vars[n_vars  ].vtype   = VTYPE_SHAPE;
  1390.     vars[n_vars++].u.shape = shape;
  1391.     }
  1392. /*...e*/
  1393. /*...e*/
  1394.  
  1395. static void read_data_file(char *fn);
  1396.  
  1397. /*...sget_file:0:*/
  1398. /*...sget_new_id:0:*/
  1399. static void get_new_id(F *f, char *name)
  1400.     {
  1401.     if ( getsym(f) != S_ID )
  1402.         readerr(f, "expected new identifier");
  1403.  
  1404.     strncpy(name, f->id_name, 30);
  1405.  
  1406.     if ( lookup_var(name) != -1 )
  1407.         readerr(f, "redefinition of identifier %s", name);
  1408.     }
  1409. /*...e*/
  1410. /*...sget_value:0:*/
  1411. static double get_value(F *f)
  1412.     {
  1413.     switch ( getsym(f) )
  1414.         {
  1415.         case S_VALUE:
  1416.             return f->id_value;
  1417.         case S_ID:
  1418.             return vars[lookup_defined_var_vtype(f, f->id_name, VTYPE_VALUE)].u.value;
  1419.         case S_RAD:
  1420.             {
  1421.             double    value;
  1422.  
  1423.             skip(f, S_LPAR, "(");
  1424.             value = get_value(f);
  1425.             skip(f, S_RPAR, ")");
  1426.             return value * PI / 180.0;
  1427.             }
  1428.         default:
  1429.             readerr(f, "number or numeric variable expected");
  1430.         }
  1431.     return 0.0; /* Keep fussy C compiler happy */
  1432.     }
  1433. /*...e*/
  1434. /*...sget_vector:0:*/
  1435. static VECTOR get_vector(F *f)
  1436.     {
  1437.     static VECTOR dummy_vector = { 0.0, 0.0, 0.0 };
  1438.  
  1439.     switch ( getsym(f) )
  1440.         {
  1441. /*...sS_VECTOR:16:*/
  1442. case S_VECTOR:
  1443.     {
  1444.     VECTOR    vector;
  1445.  
  1446.     skip(f, S_LPAR , "("); vector.x = get_value(f);
  1447.     skip(f, S_COMMA, ","); vector.y = get_value(f);
  1448.     skip(f, S_COMMA, ","); vector.z = get_value(f);
  1449.     skip(f, S_RPAR , ")");
  1450.     return vector;
  1451.     }
  1452. /*...e*/
  1453. /*...sS_TRANS:16:*/
  1454. case S_TRANS:
  1455.     {
  1456.     VECTOR v, t;
  1457.  
  1458.     skip(f, S_LPAR , "("); v = get_vector(f);
  1459.     skip(f, S_COMMA, ","); t = get_vector(f);
  1460.     skip(f, S_RPAR , ")");
  1461.     return vector_sum(v, t);
  1462.     }
  1463. /*...e*/
  1464. /*...sS_TRANS_X:16:*/
  1465. case S_TRANS_X:
  1466.     {
  1467.     VECTOR v;
  1468.     double t;
  1469.  
  1470.     skip(f, S_LPAR , "("); v = get_vector(f);
  1471.     skip(f, S_COMMA, ","); t = get_value(f);
  1472.     skip(f, S_RPAR , ")");
  1473.     v.x += t;
  1474.     return v;
  1475.     }
  1476. /*...e*/
  1477. /*...sS_TRANS_Y:16:*/
  1478. case S_TRANS_Y:
  1479.     {
  1480.     VECTOR v;
  1481.     double t;
  1482.  
  1483.     skip(f, S_LPAR , "("); v = get_vector(f);
  1484.     skip(f, S_COMMA, ","); t = get_value(f);
  1485.     skip(f, S_RPAR , ")");
  1486.     v.y += t;
  1487.     return v;
  1488.     }
  1489. /*...e*/
  1490. /*...sS_TRANS_Z:16:*/
  1491. case S_TRANS_Z:
  1492.     {
  1493.     VECTOR v;
  1494.     double t;
  1495.  
  1496.     skip(f, S_LPAR , "("); v = get_vector(f);
  1497.     skip(f, S_COMMA, ","); t = get_value(f);
  1498.     skip(f, S_RPAR , ")");
  1499.     v.z += t;
  1500.     return v;
  1501.     }
  1502. /*...e*/
  1503. /*...sS_SCALE:16:*/
  1504. case S_SCALE:
  1505.     {
  1506.     VECTOR v, factor;
  1507.  
  1508.     skip(f, S_LPAR , "("); v      = get_vector(f);
  1509.     skip(f, S_COMMA, ","); factor = get_vector(f);
  1510.     skip(f, S_RPAR , ")");
  1511.     v.x *= factor.x;
  1512.     v.y *= factor.y;
  1513.     v.z *= factor.z;
  1514.     return v;
  1515.     }
  1516. /*...e*/
  1517. /*...sS_SCALE_X:16:*/
  1518. case S_SCALE_X:
  1519.     {
  1520.     VECTOR v;
  1521.     double factor;
  1522.  
  1523.     skip(f, S_LPAR , "("); v      = get_vector(f);
  1524.     skip(f, S_COMMA, ","); factor = get_value(f);
  1525.     skip(f, S_RPAR , ")");
  1526.     v.x *= factor;
  1527.     return v;
  1528.     }
  1529. /*...e*/
  1530. /*...sS_SCALE_Y:16:*/
  1531. case S_SCALE_Y:
  1532.     {
  1533.     VECTOR v;
  1534.     double factor;
  1535.  
  1536.     skip(f, S_LPAR , "("); v      = get_vector(f);
  1537.     skip(f, S_COMMA, ","); factor = get_value(f);
  1538.     skip(f, S_RPAR , ")");
  1539.     v.y *= factor;
  1540.     return v;
  1541.     }
  1542. /*...e*/
  1543. /*...sS_SCALE_Z:16:*/
  1544. case S_SCALE_Z:
  1545.     {
  1546.     VECTOR v;
  1547.     double factor;
  1548.  
  1549.     skip(f, S_LPAR , "("); v      = get_vector(f);
  1550.     skip(f, S_COMMA, ","); factor = get_value(f);
  1551.     skip(f, S_RPAR , ")");
  1552.     v.z *= factor;
  1553.     return v;
  1554.     }
  1555. /*...e*/
  1556. /*...sS_ROTATE_X:16:*/
  1557. case S_ROTATE_X:
  1558.     {
  1559.     VECTOR v;
  1560.     double angle;
  1561.  
  1562.     skip(f, S_LPAR , "("); v = get_vector(f);
  1563.     skip(f, S_COMMA, ","); angle = get_value(f);
  1564.     skip(f, S_RPAR , ")");
  1565.     return rot_x_vector(v, angle);
  1566.     }
  1567. /*...e*/
  1568. /*...sS_ROTATE_Y:16:*/
  1569. case S_ROTATE_Y:
  1570.     {
  1571.     VECTOR v;
  1572.     double angle;
  1573.  
  1574.     skip(f, S_LPAR , "("); v = get_vector(f);
  1575.     skip(f, S_COMMA, ","); angle = get_value(f);
  1576.     skip(f, S_RPAR , ")");
  1577.     return rot_y_vector(v, angle);
  1578.     }
  1579. /*...e*/
  1580. /*...sS_ROTATE_Z:16:*/
  1581. case S_ROTATE_Z:
  1582.     {
  1583.     VECTOR v;
  1584.     double angle;
  1585.  
  1586.     skip(f, S_LPAR , "("); v = get_vector(f);
  1587.     skip(f, S_COMMA, ","); angle = get_value(f);
  1588.     skip(f, S_RPAR , ")");
  1589.     return rot_z_vector(v, angle);
  1590.     }
  1591. /*...e*/
  1592. /*...sS_ID:16:*/
  1593. case S_ID:
  1594.     return vars[lookup_defined_var_vtype(f, f->id_name, VTYPE_VECTOR)].u.vector;
  1595. /*...e*/
  1596. /*...sdefault:16:*/
  1597. default:
  1598.     readerr(f, "vector expected");
  1599. /*...e*/
  1600.         }
  1601.     return dummy_vector; /* Keep fussy C compiler happy */
  1602.     }
  1603. /*...e*/
  1604. /*...sget_rgb:0:*/
  1605. static RGBVEC get_rgb(F *f)
  1606.     {
  1607.     static RGBVEC dummy_rgbvec = { 0.0, 0.0, 0.0 };
  1608.  
  1609.     switch ( getsym(f) )
  1610.         {
  1611.         case S_RGBVEC:
  1612.             {
  1613.             RGBVEC    rgb;
  1614.  
  1615.             skip(f, S_LPAR , "("); rgb.r = get_value(f);
  1616.             skip(f, S_COMMA, ","); rgb.g = get_value(f);
  1617.             skip(f, S_COMMA, ","); rgb.b = get_value(f);
  1618.             skip(f, S_RPAR , ")");
  1619.             return rgb;
  1620.             }
  1621.         case S_ID:
  1622.             return vars[lookup_defined_var_vtype(f, f->id_name, VTYPE_RGBVEC)].u.rgb;
  1623.         default:
  1624.             readerr(f, "rgb colour vector expected");
  1625.         }
  1626.  
  1627.     return dummy_rgbvec; /* Keep fussy C compiler happy */
  1628.     }
  1629. /*...e*/
  1630. /*...sget_col:0:*/
  1631. /*
  1632. This returns a colour.
  1633. If it comes from a user variable, then a copy of the variable is returned.
  1634. If not, then the new datastructure is returned.
  1635. */
  1636.  
  1637. static COL *get_col(F *f)
  1638.     {
  1639.     switch ( getsym(f) )
  1640.         {
  1641. /*...sS_COL_CONST:16:*/
  1642. case S_COL_CONST:
  1643.     {
  1644.     RGBVEC rgbvec;
  1645.  
  1646.     skip(f, S_LPAR , "("); rgbvec = get_rgb(f);
  1647.     skip(f, S_RPAR , ")");
  1648.     return memcheck(create_const_col(rgbvec));
  1649.     }
  1650. /*...e*/
  1651. /*...sS_COL_NO_MOVE:16:*/
  1652. case S_COL_NO_MOVE:
  1653.     {
  1654.     COL *col;
  1655.  
  1656.     skip(f, S_LPAR , "("); col = get_col(f);
  1657.     skip(f, S_RPAR , ")");
  1658.  
  1659.     return memcheck(create_no_move_col(col));
  1660.     }
  1661. /*...e*/
  1662. /*...sS_COL_INTERP0:16:*/
  1663. case S_COL_INTERP0:
  1664.     {
  1665.     COL *col;
  1666.  
  1667.     skip(f, S_LPAR , "("); col = get_col(f);
  1668.     skip(f, S_RPAR , ")");
  1669.  
  1670.     return memcheck(create_interp0_col(col));
  1671.     }
  1672. /*...e*/
  1673. /*...sS_COL_INTERP1:16:*/
  1674. case S_COL_INTERP1:
  1675.     {
  1676.     COL *col;
  1677.  
  1678.     skip(f, S_LPAR , "("); col = get_col(f);
  1679.     skip(f, S_RPAR , ")");
  1680.  
  1681.     return memcheck(create_interp1_col(col));
  1682.     }
  1683. /*...e*/
  1684. /*...sS_COL_INTERP2:16:*/
  1685. case S_COL_INTERP2:
  1686.     {
  1687.     COL *col;
  1688.  
  1689.     skip(f, S_LPAR , "("); col = get_col(f);
  1690.     skip(f, S_RPAR , ")");
  1691.  
  1692.     return memcheck(create_interp2_col(col));
  1693.     }
  1694. /*...e*/
  1695. /*...sS_COL_FIELD2D:16:*/
  1696. case S_COL_FIELD2D:
  1697.     {
  1698.     double bx, by;
  1699.     BITMAP *bitmap;
  1700.  
  1701.     skip(f, S_LPAR , "("); bx = get_value(f);
  1702.     skip(f, S_COMMA, ","); by = get_value(f);
  1703.     skip(f, S_COMMA, ",");
  1704.  
  1705.     if ( getsym(f) != S_STRING )
  1706.         readerr(f, "expected input bitmap filename");
  1707.  
  1708.     if ( (bitmap = fio_read_bitmap(f->str)) == NULL )
  1709.         readerr(f, "unable to read bitmap %s", f->str);
  1710.  
  1711.     skip(f, S_RPAR , ")");
  1712.     return memcheck(create_2d_field_col(bx, by, bitmap));
  1713.     }
  1714. /*...e*/
  1715. /*...sS_COL_FIELD3D:16:*/
  1716. case S_COL_FIELD3D:
  1717.     {
  1718.     double bx, by, bz;
  1719.     TEX *tex;
  1720.  
  1721.     skip(f, S_LPAR , "("); bx = get_value(f);
  1722.     skip(f, S_COMMA, ","); by = get_value(f);
  1723.     skip(f, S_COMMA, ","); bz = get_value(f);
  1724.     skip(f, S_COMMA, ",");
  1725.  
  1726.     if ( getsym(f) != S_STRING )
  1727.         readerr(f, "expected input 3d texture-map filename");
  1728.  
  1729.     if ( (tex = read_tex(f->str)) == NULL )
  1730.         readerr(f, "unable to read 3d texture-map %s", f->str);
  1731.  
  1732.     skip(f, S_RPAR , ")");
  1733.     return memcheck(create_3d_field_col(bx, by, bz, tex));
  1734.     }
  1735. /*...e*/
  1736. /*...sS_COL_REMAP:16:*/
  1737. case S_COL_REMAP:
  1738.     {
  1739.     VECTOR base, v0, v1, v2;
  1740.     COL *col;
  1741.  
  1742.     skip(f, S_LPAR , "("); base = get_vector(f);
  1743.     skip(f, S_COMMA, ","); v0   = get_vector(f);
  1744.     skip(f, S_COMMA, ","); v1   = get_vector(f);
  1745.     skip(f, S_COMMA, ","); v2   = get_vector(f);
  1746.     skip(f, S_COMMA, ","); col  = get_col(f);
  1747.     skip(f, S_RPAR , ")");
  1748.     return memcheck(create_remap_col(base, v0, v1, v2, col));
  1749.     }
  1750. /*...e*/
  1751. /*...sS_COL_CYLPOLAR:16:*/
  1752. case S_COL_CYLPOLAR:
  1753.     {
  1754.     double lond, rd, hd;
  1755.     COL *col;
  1756.  
  1757.     skip(f, S_LPAR , "("); lond = get_value(f);
  1758.     skip(f, S_COMMA, ","); rd   = get_value(f);
  1759.     skip(f, S_COMMA, ","); hd   = get_value(f);
  1760.     skip(f, S_COMMA, ","); col  = get_col(f);
  1761.     skip(f, S_RPAR , ")");
  1762.  
  1763.     return memcheck(create_cyl_polar_col(lond, rd, hd, col));
  1764.     }
  1765. /*...e*/
  1766. /*...sS_COL_SPHPOLAR:16:*/
  1767. case S_COL_SPHPOLAR:
  1768.     {
  1769.     double lond, latd, rd;
  1770.     COL *col;
  1771.  
  1772.     skip(f, S_LPAR , "("); lond = get_value(f);
  1773.     skip(f, S_COMMA, ","); latd = get_value(f);
  1774.     skip(f, S_COMMA, ","); rd   = get_value(f);
  1775.     skip(f, S_COMMA, ","); col  = get_col(f);
  1776.     skip(f, S_RPAR , ")");
  1777.  
  1778.     return memcheck(create_sph_polar_col(lond, latd, rd, col));
  1779.     }
  1780. /*...e*/
  1781. /*...sS_COL_MATRIX2D:16:*/
  1782. case S_COL_MATRIX2D:
  1783.     {
  1784.     double mat[2][2];
  1785.     int i, j;
  1786.     COL *col;
  1787.  
  1788.     skip(f, S_LPAR , "(");
  1789.     for ( j = 0; j < 2; j++ )
  1790.         for ( i = 0; i < 2; i++ )
  1791.             {
  1792.             mat[j][i] = get_value(f);
  1793.             skip(f, S_COMMA, ",");
  1794.             }
  1795.     col = get_col(f);
  1796.     skip(f, S_RPAR , ")");
  1797.  
  1798.     return memcheck(create_2d_matrix_col(mat, col));
  1799.     }
  1800. /*...e*/
  1801. /*...sS_COL_MATRIX3D:16:*/
  1802. case S_COL_MATRIX3D:
  1803.     {
  1804.     double mat[3][3];
  1805.     int i, j;
  1806.     COL *col;
  1807.  
  1808.     skip(f, S_LPAR , "(");
  1809.     for ( j = 0; j < 3; j++ )
  1810.         for ( i = 0; i < 3; i++ )
  1811.             {
  1812.             mat[j][i] = get_value(f);
  1813.             skip(f, S_COMMA, ",");
  1814.             }
  1815.     col = get_col(f);
  1816.     skip(f, S_RPAR , ")");
  1817.  
  1818.     return memcheck(create_3d_matrix_col(mat, col));
  1819.     }
  1820. /*...e*/
  1821. /*...sS_ID:16:*/
  1822. case S_ID:
  1823.     {
  1824.     COL *col = vars[lookup_defined_var_vtype(f, f->id_name, VTYPE_COL)].u.col;
  1825.  
  1826.     return memcheck(copy_col(col));
  1827.     }
  1828. /*...e*/
  1829. /*...sdefault:16:*/
  1830. default:
  1831.     readerr(f, "colour definition or colour variable expected");
  1832. /*...e*/
  1833.         }
  1834.     return NULL; /* Keep fussy C compiler happy */
  1835.     }
  1836. /*...e*/
  1837. /*...sget_surf:0:*/
  1838. /*
  1839. This returns a surface.
  1840. If it comes from a user variable, then a copy of the variable is returned.
  1841. If not, then the new datastructure is returned.
  1842. */
  1843.  
  1844. static SURF *get_surf(F *f)
  1845.     {
  1846.     switch ( getsym(f) )
  1847.         {
  1848.         case S_SURF:
  1849.             {
  1850.             double    ka, kd, ks, kt;
  1851.             COL    *od, *os;
  1852.             double    phong, rinx;
  1853.  
  1854.             skip(f, S_LPAR , "("); ka    = get_value(f);
  1855.             skip(f, S_COMMA, ","); kd    = get_value(f);
  1856.             skip(f, S_COMMA, ","); ks    = get_value(f);
  1857.             skip(f, S_COMMA, ","); kt    = get_value(f);
  1858.             skip(f, S_COMMA, ","); od    = get_col(f);
  1859.             skip(f, S_COMMA, ","); os    = get_col(f);
  1860.             skip(f, S_COMMA, ","); phong = get_value(f);
  1861.             skip(f, S_COMMA, ","); rinx  = get_value(f);
  1862.             skip(f, S_RPAR , ")");
  1863.  
  1864.             return memcheck(create_surf(ka, kd, ks, kt, od, os, phong, rinx));
  1865.             }
  1866.         case S_ID:
  1867.             {
  1868.             SURF *surf = vars[lookup_defined_var_vtype(f, f->id_name, VTYPE_SURF)].u.surf;
  1869.  
  1870.             return memcheck(copy_surf(surf));
  1871.             }
  1872.         default:
  1873.             readerr(f, "surface definition or surface variable expected");
  1874.         }
  1875.     return NULL; /* Keep fussy C compiler happy */
  1876.     }
  1877. /*...e*/
  1878. /*...sget_opt_surf:0:*/
  1879. /*
  1880. Handle both the case that ", surface)" is supplied and that surface is
  1881. to be returned, and also the case ")" is supplied, and a default is to be used.
  1882. */
  1883.  
  1884. static SURF *get_opt_surf(F *f)
  1885.     {
  1886.     switch ( getsym(f) )
  1887.         {
  1888.         case S_COMMA:
  1889.             {
  1890.             SURF *surf = get_surf(f);
  1891.             skip(f, S_RPAR, ")");
  1892.             return surf;
  1893.             }
  1894.         case S_RPAR:
  1895.             {
  1896.             static RGBVEC rgbvec_g = { 0.5, 0.5, 0.5 };
  1897.             COL *col_g = memcheck(create_const_col(rgbvec_g));
  1898.             return memcheck(create_surf(0.8,0.8,0.8,0.0,col_g,col_g,100.0,1.0));
  1899.             }
  1900.         default:
  1901.             readerr(f, "surface definition, surface variable or ) expected");
  1902.         }
  1903.     return NULL; /* Keep fussy C compiler happy */
  1904.     }
  1905. /*...e*/
  1906. /*...sget_shape:0:*/
  1907. /*
  1908. This returns a shape.
  1909. If it comes from a user variable, then a copy of the variable is returned.
  1910. If not, then the new datastructure is returned.
  1911. */
  1912.  
  1913. static SHAPE *get_shape(F *f)
  1914.     {
  1915.     switch ( getsym(f) )
  1916.         {
  1917. /*...sS_PLANE:16:*/
  1918. case S_PLANE:
  1919.     {
  1920.     double    a, b, c, d;
  1921.     SURF    *surf;
  1922.  
  1923.     skip(f, S_LPAR , "("); a = get_value(f);
  1924.     skip(f, S_COMMA, ","); b = get_value(f);
  1925.     skip(f, S_COMMA, ","); c = get_value(f);
  1926.     skip(f, S_COMMA, ","); d = get_value(f);
  1927.     surf = get_opt_surf(f);
  1928.     return memcheck(create_plane_shape(memcheck(create_plane(a, b, c, d)), surf));
  1929.     }
  1930. /*...e*/
  1931. /*...sS_X_LT:16:*/
  1932. case S_X_LT:
  1933.     {
  1934.     double    x;
  1935.     SURF    *surf;
  1936.  
  1937.     skip(f, S_LPAR , "("); x = get_value(f);
  1938.     surf = get_opt_surf(f);
  1939.     return memcheck(create_plane_shape(memcheck(create_x_lt_plane(x)), surf));
  1940.     }
  1941. /*...e*/
  1942. /*...sS_X_GT:16:*/
  1943. case S_X_GT:
  1944.     {
  1945.     double    x;
  1946.     SURF    *surf;
  1947.  
  1948.     skip(f, S_LPAR , "("); x = get_value(f);
  1949.     surf = get_opt_surf(f);
  1950.     return memcheck(create_plane_shape(memcheck(create_x_gt_plane(x)), surf));
  1951.     }
  1952. /*...e*/
  1953. /*...sS_Y_LT:16:*/
  1954. case S_Y_LT:
  1955.     {
  1956.     double    y;
  1957.     SURF    *surf;
  1958.  
  1959.     skip(f, S_LPAR , "("); y = get_value(f);
  1960.     surf = get_opt_surf(f);
  1961.     return memcheck(create_plane_shape(memcheck(create_y_lt_plane(y)), surf));
  1962.     }
  1963. /*...e*/
  1964. /*...sS_Y_GT:16:*/
  1965. case S_Y_GT:
  1966.     {
  1967.     double    y;
  1968.     SURF    *surf;
  1969.  
  1970.     skip(f, S_LPAR , "("); y = get_value(f);
  1971.     surf = get_opt_surf(f);
  1972.     return memcheck(create_plane_shape(memcheck(create_y_gt_plane(y)), surf));
  1973.     }
  1974. /*...e*/
  1975. /*...sS_Z_LT:16:*/
  1976. case S_Z_LT:
  1977.     {
  1978.     double    z;
  1979.     SURF    *surf;
  1980.  
  1981.     skip(f, S_LPAR , "("); z = get_value(f);
  1982.     surf = get_opt_surf(f);
  1983.     return memcheck(create_plane_shape(memcheck(create_z_lt_plane(z)), surf));
  1984.     }
  1985. /*...e*/
  1986. /*...sS_Z_GT:16:*/
  1987. case S_Z_GT:
  1988.     {
  1989.     double    z;
  1990.     SURF    *surf;
  1991.  
  1992.     skip(f, S_LPAR , "("); z = get_value(f);
  1993.     surf = get_opt_surf(f);
  1994.     return memcheck(create_plane_shape(memcheck(create_z_gt_plane(z)), surf));
  1995.     }
  1996. /*...e*/
  1997. /*...sS_BIPLANE:16:*/
  1998. case S_BIPLANE:
  1999.     {
  2000.     double    a, b, c, d1, d2;
  2001.     SURF    *surf;
  2002.  
  2003.     skip(f, S_LPAR , "("); a  = get_value(f);
  2004.     skip(f, S_COMMA, ","); b  = get_value(f);
  2005.     skip(f, S_COMMA, ","); c  = get_value(f);
  2006.     skip(f, S_COMMA, ","); d1 = get_value(f);
  2007.     skip(f, S_COMMA, ","); d2 = get_value(f);
  2008.     surf = get_opt_surf(f);
  2009.     return memcheck(create_biplane_shape(memcheck(create_biplane(a, b, c, d1, d2)), surf));
  2010.     }
  2011. /*...e*/
  2012. /*...sS_X_IN:16:*/
  2013. case S_X_IN:
  2014.     {
  2015.     double    x1, x2;
  2016.     SURF    *surf;
  2017.  
  2018.     skip(f, S_LPAR , "("); x1 = get_value(f);
  2019.     skip(f, S_COMMA, ","); x2 = get_value(f);
  2020.     surf = get_opt_surf(f);
  2021.     return memcheck(create_biplane_shape(memcheck(create_x_in_biplane(x1, x2)), surf));
  2022.     }
  2023. /*...e*/
  2024. /*...sS_Y_IN:16:*/
  2025. case S_Y_IN:
  2026.     {
  2027.     double    yy1, yy2;
  2028.     SURF    *surf;
  2029.  
  2030.     skip(f, S_LPAR , "("); yy1 = get_value(f);
  2031.     skip(f, S_COMMA, ","); yy2 = get_value(f);
  2032.     surf = get_opt_surf(f);
  2033.     return memcheck(create_biplane_shape(memcheck(create_y_in_biplane(yy1, yy2)), surf));
  2034.     }
  2035. /*...e*/
  2036. /*...sS_Z_IN:16:*/
  2037. case S_Z_IN:
  2038.     {
  2039.     double    z1, z2;
  2040.     SURF    *surf;
  2041.  
  2042.     skip(f, S_LPAR , "("); z1 = get_value(f);
  2043.     skip(f, S_COMMA, ","); z2 = get_value(f);
  2044.     surf = get_opt_surf(f);
  2045.     return memcheck(create_biplane_shape(memcheck(create_z_in_biplane(z1, z2)), surf));
  2046.     }
  2047. /*...e*/
  2048. /*...sS_SPHERE:16:*/
  2049. case S_SPHERE:
  2050.     {
  2051.     double    r;
  2052.     SURF    *surf;
  2053.  
  2054.     skip(f, S_LPAR , "("); r = get_value(f);
  2055.     surf = get_opt_surf(f);
  2056.     return memcheck(create_sphere_shape(memcheck(create_sphere(r)), surf));
  2057.     }
  2058. /*...e*/
  2059. /*...sS_QUAD:16:*/
  2060. case S_QUAD:
  2061.     {
  2062.     double    a, b, c, d, e, ff, g, h, i, j;
  2063.     SURF    *surf;
  2064.  
  2065.     skip(f, S_LPAR , "("); a  = get_value(f);
  2066.     skip(f, S_COMMA, ","); b  = get_value(f);
  2067.     skip(f, S_COMMA, ","); c  = get_value(f);
  2068.     skip(f, S_COMMA, ","); d  = get_value(f);
  2069.     skip(f, S_COMMA, ","); e  = get_value(f);
  2070.     skip(f, S_COMMA, ","); ff = get_value(f);
  2071.     skip(f, S_COMMA, ","); g  = get_value(f);
  2072.     skip(f, S_COMMA, ","); h  = get_value(f);
  2073.     skip(f, S_COMMA, ","); i  = get_value(f);
  2074.     skip(f, S_COMMA, ","); j  = get_value(f);
  2075.     surf = get_opt_surf(f);
  2076.     return memcheck(create_quad_shape(memcheck(create_quad(a, b, c, d, e, ff, g, h, i, j)), surf));
  2077.     }
  2078. /*...e*/
  2079. /*...sS_ELLIPSOID:16:*/
  2080. case S_ELLIPSOID:
  2081.     {
  2082.     double    rx, ry, rz;
  2083.     SURF    *surf;
  2084.  
  2085.     skip(f, S_LPAR , "("); rx = get_value(f);
  2086.     skip(f, S_COMMA, ","); ry = get_value(f);
  2087.     skip(f, S_COMMA, ","); rz = get_value(f);
  2088.     surf = get_opt_surf(f);
  2089.     return memcheck(create_quad_shape(memcheck(create_ellipsoid(rx, ry, rz)), surf));
  2090.     }
  2091. /*...e*/
  2092. /*...sS_X_ELL_CYL:16:*/
  2093. case S_X_ELL_CYL:
  2094.     {
  2095.     double    ry, rz;
  2096.     SURF    *surf;
  2097.  
  2098.     skip(f, S_LPAR , "("); ry = get_value(f);
  2099.     skip(f, S_COMMA, ","); rz = get_value(f);
  2100.     surf = get_opt_surf(f);
  2101.     return memcheck(create_quad_shape(memcheck(create_x_ell_cyl(ry, rz)), surf));
  2102.     }
  2103. /*...e*/
  2104. /*...sS_Y_ELL_CYL:16:*/
  2105. case S_Y_ELL_CYL:
  2106.     {
  2107.     double    rx, rz;
  2108.     SURF    *surf;
  2109.  
  2110.     skip(f, S_LPAR , "("); rx = get_value(f);
  2111.     skip(f, S_COMMA, ","); rz = get_value(f);
  2112.     surf = get_opt_surf(f);
  2113.     return memcheck(create_quad_shape(memcheck(create_y_ell_cyl(rx, rz)), surf));
  2114.     }
  2115. /*...e*/
  2116. /*...sS_Z_ELL_CYL:16:*/
  2117. case S_Z_ELL_CYL:
  2118.     {
  2119.     double    rx, ry;
  2120.     SURF    *surf;
  2121.  
  2122.     skip(f, S_LPAR , "("); rx = get_value(f);
  2123.     skip(f, S_COMMA, ","); ry = get_value(f);
  2124.     surf = get_opt_surf(f);
  2125.     return memcheck(create_quad_shape(memcheck(create_z_ell_cyl(rx, ry)), surf));
  2126.     }
  2127. /*...e*/
  2128. /*...sS_X_CYL:16:*/
  2129. case S_X_CYL:
  2130.     {
  2131.     double    r;
  2132.     SURF    *surf;
  2133.  
  2134.     skip(f, S_LPAR , "("); r = get_value(f);
  2135.     surf = get_opt_surf(f);
  2136.     return memcheck(create_quad_shape(memcheck(create_x_cyl(r)), surf));
  2137.     }
  2138. /*...e*/
  2139. /*...sS_Y_CYL:16:*/
  2140. case S_Y_CYL:
  2141.     {
  2142.     double    r;
  2143.     SURF    *surf;
  2144.  
  2145.     skip(f, S_LPAR , "("); r = get_value(f);
  2146.     surf = get_opt_surf(f);
  2147.     return memcheck(create_quad_shape(memcheck(create_y_cyl(r)), surf));
  2148.     }
  2149. /*...e*/
  2150. /*...sS_Z_CYL:16:*/
  2151. case S_Z_CYL:
  2152.     {
  2153.     double    r;
  2154.     SURF    *surf;
  2155.  
  2156.     skip(f, S_LPAR , "("); r = get_value(f);
  2157.     surf = get_opt_surf(f);
  2158.     return memcheck(create_quad_shape(memcheck(create_z_cyl(r)), surf));
  2159.     }
  2160. /*...e*/
  2161. /*...sS_X_ELL_CONE:16:*/
  2162. case S_X_ELL_CONE:
  2163.     {
  2164.     double    ky, kz;
  2165.     SURF    *surf;
  2166.  
  2167.     skip(f, S_LPAR , "("); ky = get_value(f);
  2168.     skip(f, S_COMMA, ","); kz = get_value(f);
  2169.     surf = get_opt_surf(f);
  2170.     return memcheck(create_quad_shape(memcheck(create_x_ell_cone(ky, kz)), surf));
  2171.     }
  2172. /*...e*/
  2173. /*...sS_Y_ELL_CONE:16:*/
  2174. case S_Y_ELL_CONE:
  2175.     {
  2176.     double    kx, kz;
  2177.     SURF    *surf;
  2178.  
  2179.     skip(f, S_LPAR , "("); kx = get_value(f);
  2180.     skip(f, S_COMMA, ","); kz = get_value(f);
  2181.     surf = get_opt_surf(f);
  2182.     return memcheck(create_quad_shape(memcheck(create_y_ell_cone(kx, kz)), surf));
  2183.     }
  2184. /*...e*/
  2185. /*...sS_Z_ELL_CONE:16:*/
  2186. case S_Z_ELL_CONE:
  2187.     {
  2188.     double    kx, ky;
  2189.     SURF    *surf;
  2190.  
  2191.     skip(f, S_LPAR , "("); kx = get_value(f);
  2192.     skip(f, S_COMMA, ","); ky = get_value(f);
  2193.     surf = get_opt_surf(f);
  2194.     return memcheck(create_quad_shape(memcheck(create_z_ell_cone(kx, ky)), surf));
  2195.     }
  2196. /*...e*/
  2197. /*...sS_X_CONE:16:*/
  2198. case S_X_CONE:
  2199.     {
  2200.     double    k;
  2201.     SURF    *surf;
  2202.  
  2203.     skip(f, S_LPAR , "("); k = get_value(f);
  2204.     surf = get_opt_surf(f);
  2205.     return memcheck(create_quad_shape(memcheck(create_x_cone(k)), surf));
  2206.     }
  2207. /*...e*/
  2208. /*...sS_Y_CONE:16:*/
  2209. case S_Y_CONE:
  2210.     {
  2211.     double    k;
  2212.     SURF    *surf;
  2213.  
  2214.     skip(f, S_LPAR , "("); k = get_value(f);
  2215.     surf = get_opt_surf(f);
  2216.     return memcheck(create_quad_shape(memcheck(create_y_cone(k)), surf));
  2217.     }
  2218. /*...e*/
  2219. /*...sS_Z_CONE:16:*/
  2220. case S_Z_CONE:
  2221.     {
  2222.     double    k;
  2223.     SURF    *surf;
  2224.  
  2225.     skip(f, S_LPAR , "("); k = get_value(f);
  2226.     surf = get_opt_surf(f);
  2227.     return memcheck(create_quad_shape(memcheck(create_z_cone(k)), surf));
  2228.     }
  2229. /*...e*/
  2230. /*...sS_TRANS:16:*/
  2231. case S_TRANS:
  2232.     {
  2233.     SHAPE    *shape;
  2234.     VECTOR    t;
  2235.  
  2236.     skip(f, S_LPAR , "("); shape = get_shape(f);
  2237.     skip(f, S_COMMA, ","); t = get_vector(f);
  2238.     skip(f, S_RPAR , ")");
  2239.     trans(shape, t);
  2240.     return shape;
  2241.     }
  2242. /*...e*/
  2243. /*...sS_TRANS_X:16:*/
  2244. case S_TRANS_X:
  2245.     {
  2246.     SHAPE    *shape;
  2247.     double    t;
  2248.  
  2249.     skip(f, S_LPAR , "("); shape = get_shape(f);
  2250.     skip(f, S_COMMA, ","); t = get_value(f);
  2251.     skip(f, S_RPAR , ")");
  2252.     trans_x(shape, t);
  2253.     return shape;
  2254.     }
  2255. /*...e*/
  2256. /*...sS_TRANS_Y:16:*/
  2257. case S_TRANS_Y:
  2258.     {
  2259.     SHAPE    *shape;
  2260.     double    t;
  2261.  
  2262.     skip(f, S_LPAR , "("); shape = get_shape(f);
  2263.     skip(f, S_COMMA, ","); t = get_value(f);
  2264.     skip(f, S_RPAR , ")");
  2265.     trans_y(shape, t);
  2266.     return shape;
  2267.     }
  2268. /*...e*/
  2269. /*...sS_TRANS_Z:16:*/
  2270. case S_TRANS_Z:
  2271.     {
  2272.     SHAPE    *shape;
  2273.     double    t;
  2274.  
  2275.     skip(f, S_LPAR , "("); shape = get_shape(f);
  2276.     skip(f, S_COMMA, ","); t = get_value(f);
  2277.     skip(f, S_RPAR , ")");
  2278.     trans_z(shape, t);
  2279.     return shape;
  2280.     }
  2281. /*...e*/
  2282. /*...sS_SCALE:16:*/
  2283. case S_SCALE:
  2284.     {
  2285.     SHAPE    *shape;
  2286.     VECTOR    factor;
  2287.  
  2288.     skip(f, S_LPAR , "("); shape = get_shape(f);
  2289.     skip(f, S_COMMA, ","); factor = get_vector(f);
  2290.     if ( factor.x == 0.0 || factor.y == 0.0 || factor.z == 0 )
  2291.         readerr(f, "at least one component of factor is zero");
  2292.     skip(f, S_RPAR , ")");
  2293.     if ( !scale(shape, factor) )
  2294.         readerr(f, "can't scale shape");
  2295.     return shape;
  2296.     }
  2297. /*...e*/
  2298. /*...sS_SCALE_X:16:*/
  2299. case S_SCALE_X:
  2300.     {
  2301.     SHAPE    *shape;
  2302.     double    factor;
  2303.  
  2304.     skip(f, S_LPAR , "("); shape = get_shape(f);
  2305.     skip(f, S_COMMA, ","); factor = get_value(f);
  2306.     if ( factor == 0.0 )
  2307.         readerr(f, "factor is zero");
  2308.     skip(f, S_RPAR , ")");
  2309.     if ( !scale_x(shape, factor) )
  2310.         readerr(f, "can't scale_x shape");
  2311.     return shape;
  2312.     }
  2313. /*...e*/
  2314. /*...sS_SCALE_Y:16:*/
  2315. case S_SCALE_Y:
  2316.     {
  2317.     SHAPE    *shape;
  2318.     double    factor;
  2319.  
  2320.     skip(f, S_LPAR , "("); shape = get_shape(f);
  2321.     skip(f, S_COMMA, ","); factor = get_value(f);
  2322.     if ( factor == 0.0 )
  2323.         readerr(f, "factor is zero");
  2324.     skip(f, S_RPAR , ")");
  2325.     if ( !scale_y(shape, factor) )
  2326.         readerr(f, "can't scale_y shape");
  2327.     return shape;
  2328.     }
  2329. /*...e*/
  2330. /*...sS_SCALE_Z:16:*/
  2331. case S_SCALE_Z:
  2332.     {
  2333.     SHAPE    *shape;
  2334.     double    factor;
  2335.  
  2336.     skip(f, S_LPAR , "("); shape = get_shape(f);
  2337.     skip(f, S_COMMA, ","); factor = get_value(f);
  2338.     if ( factor == 0.0 )
  2339.         readerr(f, "factor is zero");
  2340.     skip(f, S_RPAR , ")");
  2341.     if ( !scale_z(shape, factor) )
  2342.         readerr(f, "can't scale_z shape");
  2343.     return shape;
  2344.     }
  2345. /*...e*/
  2346. /*...sS_ROTATE_X:16:*/
  2347. case S_ROTATE_X:
  2348.     {
  2349.     SHAPE    *shape;
  2350.     double    angle;
  2351.  
  2352.     skip(f, S_LPAR , "("); shape = get_shape(f);
  2353.     skip(f, S_COMMA, ","); angle = get_value(f);
  2354.     skip(f, S_RPAR , ")");
  2355.     rot_x(shape, angle);
  2356.     return shape;
  2357.     }
  2358. /*...e*/
  2359. /*...sS_ROTATE_Y:16:*/
  2360. case S_ROTATE_Y:
  2361.     {
  2362.     SHAPE    *shape;
  2363.     double    angle;
  2364.  
  2365.     skip(f, S_LPAR , "("); shape = get_shape(f);
  2366.     skip(f, S_COMMA, ","); angle = get_value(f);
  2367.     skip(f, S_RPAR , ")");
  2368.     rot_y(shape, angle);
  2369.     return shape;
  2370.     }
  2371. /*...e*/
  2372. /*...sS_ROTATE_Z:16:*/
  2373. case S_ROTATE_Z:
  2374.     {
  2375.     SHAPE    *shape;
  2376.     double    angle;
  2377.  
  2378.     skip(f, S_LPAR , "("); shape = get_shape(f);
  2379.     skip(f, S_COMMA, ","); angle = get_value(f);
  2380.     skip(f, S_RPAR , ")");
  2381.     rot_z(shape, angle);
  2382.     return shape;
  2383.     }
  2384. /*...e*/
  2385. /*...sS_UNION:16:*/
  2386. case S_UNION:
  2387.     {
  2388.     SHAPE    *shape;
  2389.     int    sym;
  2390.  
  2391.     skip(f, S_LPAR, "(");
  2392.     shape = get_shape(f);
  2393.     while ( (sym = getsym(f)) == S_COMMA )
  2394.         shape = memcheck(create_bin_shape(STYPE_UNION, shape, get_shape(f)));
  2395.     if ( sym != S_RPAR )
  2396.         readerr(f, "expected )");
  2397.  
  2398.     return shape;
  2399.     }
  2400. /*...e*/
  2401. /*...sS_ISECT:16:*/
  2402. case S_ISECT:
  2403.     {
  2404.     SHAPE    *shape;
  2405.     int    sym;
  2406.  
  2407.     skip(f, S_LPAR, "(");
  2408.     shape = get_shape(f);
  2409.     while ( (sym = getsym(f)) == S_COMMA )
  2410.         shape = memcheck(create_bin_shape(STYPE_ISECT, shape, get_shape(f)));
  2411.     if ( sym != S_RPAR )
  2412.         readerr(f, "expected )");
  2413.  
  2414.     return shape;
  2415.     }
  2416. /*...e*/
  2417. /*...sS_DIFF:16:*/
  2418. case S_DIFF:
  2419.     {
  2420.     SHAPE    *shape;
  2421.     int    sym;
  2422.  
  2423.     skip(f, S_LPAR, "(");
  2424.     shape = get_shape(f);
  2425.     while ( (sym = getsym(f)) == S_COMMA )
  2426.         shape = memcheck(create_bin_shape(STYPE_DIFF, shape, get_shape(f)));
  2427.     if ( sym != S_RPAR )
  2428.         readerr(f, "expected )");
  2429.  
  2430.     return shape;
  2431.     }
  2432. /*...e*/
  2433. /*...sS_SDIFF:16:*/
  2434. case S_SDIFF:
  2435.     {
  2436.     SHAPE    *shape;
  2437.     int    sym;
  2438.  
  2439.     skip(f, S_LPAR, "(");
  2440.     shape = get_shape(f);
  2441.     while ( (sym = getsym(f)) == S_COMMA )
  2442.         shape = memcheck(create_bin_shape(STYPE_SDIFF, shape, get_shape(f)));
  2443.     if ( sym != S_RPAR )
  2444.         readerr(f, "expected )");
  2445.  
  2446.     return shape;
  2447.     }
  2448. /*...e*/
  2449. /*...sS_EXTENT:16:*/
  2450. case S_EXTENT:
  2451.     {
  2452.     SHAPE    *shape;
  2453.     int    sym;
  2454.  
  2455.     skip(f, S_LPAR, "(");
  2456.     shape = get_shape(f);
  2457.     while ( (sym = getsym(f)) == S_COMMA )
  2458.         shape = memcheck(create_bin_shape(STYPE_EXTENT, shape, get_shape(f)));
  2459.     if ( sym != S_RPAR )
  2460.         readerr(f, "expected )");
  2461.  
  2462.     return shape;
  2463.     }
  2464. /*...e*/
  2465. /*...sS_RESURF:16:*/
  2466. case S_RESURF:
  2467.     {
  2468.     SHAPE    *shape;
  2469.     SURF    *surf;
  2470.  
  2471.     skip(f, S_LPAR , "("); shape = get_shape(f);
  2472.     surf = get_opt_surf(f);
  2473.  
  2474.     if ( !resurf(shape, surf) )
  2475.         readerr(f, "unable to resurface shape");
  2476.     destroy_surf(surf);
  2477.  
  2478.     return shape;
  2479.     }
  2480. /*...e*/
  2481. /*...sS_ID:16:*/
  2482. case S_ID:
  2483.     {
  2484.     SHAPE *shape = vars[lookup_defined_var_vtype(f, f->id_name, VTYPE_SHAPE)].u.shape;
  2485.  
  2486.     return memcheck(copy_shape(shape));
  2487.     }
  2488. /*...e*/
  2489. /*...sdefault:16:*/
  2490. default:
  2491.     readerr(f, "expected a shape specification");
  2492. /*...e*/
  2493.         }
  2494.     return NULL; /* Keep fussy C compiler happy */
  2495.     }
  2496. /*...e*/
  2497. /*...sget_set_value:0:*/
  2498. static void get_set_value(F *f)
  2499.     {
  2500.     char    name[30+1];
  2501.  
  2502.     get_new_id(f, name);
  2503.     add_value_var(f, name, get_value(f));
  2504.     }
  2505.  
  2506. /*...e*/
  2507. /*...sget_set_vector:0:*/
  2508. static void get_set_vector(F *f)
  2509.     {
  2510.     char    name[30+1];
  2511.  
  2512.     get_new_id(f, name);
  2513.     add_vector_var(f, name, get_vector(f));
  2514.     }
  2515. /*...e*/
  2516. /*...sget_set_rgb:0:*/
  2517. static void get_set_rgb(F *f)
  2518.     {
  2519.     char    name[30+1];
  2520.  
  2521.     get_new_id(f, name);
  2522.     add_rgb_var(f, name, get_rgb(f));
  2523.     }
  2524. /*...e*/
  2525. /*...sget_set_col:0:*/
  2526. static void get_set_col(F *f)
  2527.     {
  2528.     char    name[30+1];
  2529.  
  2530.     get_new_id(f, name);
  2531.     add_col_var(f, name, get_col(f));
  2532.     }
  2533. /*...e*/
  2534. /*...sget_set_surf:0:*/
  2535. static void get_set_surf(F *f)
  2536.     {
  2537.     char    name[30+1];
  2538.  
  2539.     get_new_id(f, name);
  2540.     add_surf_var(f, name, get_surf(f));
  2541.     }
  2542. /*...e*/
  2543. /*...sget_set_shape:0:*/
  2544. static void get_set_shape(F *f)
  2545.     {
  2546.     char    name[30+1];
  2547.  
  2548.     get_new_id(f, name);
  2549.     add_shape_var(f, name, get_shape(f));
  2550.     }
  2551. /*...e*/
  2552. /*...sget_set_background:0:*/
  2553. static void get_set_background(F *f)
  2554.     {
  2555.     i_background = get_rgb(f);
  2556.     }
  2557. /*...e*/
  2558. /*...sget_set_ambient:0:*/
  2559. static void get_set_ambient(F *f)
  2560.     {
  2561.     i_ambient = get_rgb(f);
  2562.     }
  2563. /*...e*/
  2564. /*...sget_set_atten:0:*/
  2565. static void get_set_atten(F *f)
  2566.     {
  2567.     af1 = get_value(f);
  2568.     af2 = get_value(f);
  2569.     }
  2570. /*...e*/
  2571. /*...sget_add_light:0:*/
  2572. static void get_add_light(F *f)
  2573.     {
  2574.     if ( n_lights == N_LIGHTS )
  2575.         readerr(f, "maximum of %d lights exceeded", N_LIGHTS);
  2576.  
  2577.     lights[n_lights  ].posn = get_vector(f);
  2578.     lights[n_lights++].i    = get_rgb(f);
  2579.     }
  2580. /*...e*/
  2581. /*...sget_render:0:*/
  2582. static void get_render(F *f)
  2583.     {
  2584.     SHAPE    *shape;
  2585.     VECTOR    eye, forward, up;
  2586.     double    hangle, vangle;
  2587.     int    hpixels, vpixels, depth, type;
  2588.  
  2589.     shape   = get_shape(f);
  2590.     eye     = get_vector(f);
  2591.     forward = get_vector(f);
  2592.     up      = get_vector(f);
  2593.     hangle  = get_value(f);
  2594.     vangle  = get_value(f);
  2595.     hpixels = (int) get_value(f);
  2596.     vpixels = (int) get_value(f);
  2597.     depth   = (int) get_value(f);
  2598.     type    = (int) get_value(f);
  2599.  
  2600.     if ( getsym(f) != S_STRING )
  2601.         readerr(f, "expected output filename");
  2602.  
  2603.     render(shape, eye, forward, up, hangle, vangle, hpixels, vpixels, depth, type, f->str);
  2604.  
  2605.     destroy_shape(shape);
  2606.     }
  2607. /*...e*/
  2608. /*...sget_visdiff:0:*/
  2609. static void get_visdiff(F *f)
  2610.     {
  2611.     least_vis_diff = get_value(f);
  2612.     }
  2613. /*...e*/
  2614. /*...sget_include:0:*/
  2615. static void get_include(F *f)
  2616.     {
  2617.     if ( getsym(f) != S_STRING )
  2618.         readerr(f, "expected filename");
  2619.  
  2620.     read_data_file(f->str);
  2621.     }
  2622. /*...e*/
  2623.  
  2624. static void get_file(F *f)
  2625.     {
  2626.     int    sym;
  2627.  
  2628.     while ( (sym = getsym(f)) != S_EOF )
  2629.         switch ( sym )
  2630.             {
  2631.             case S_SET_VALUE:    get_set_value(f);    break;
  2632.             case S_SET_VECTOR:    get_set_vector(f);    break;
  2633.             case S_SET_RGBVEC:    get_set_rgb(f);        break;
  2634.             case S_SET_COL:        get_set_col(f);        break;
  2635.             case S_SET_SURF:    get_set_surf(f);    break;
  2636.             case S_SET_SHAPE:    get_set_shape(f);    break;
  2637.             case S_SET_BKGND:    get_set_background(f);    break;
  2638.             case S_SET_AMBIENT:    get_set_ambient(f);    break;
  2639.             case S_SET_ATTEN:    get_set_atten(f);    break;
  2640.             case S_ADD_LIGHT:    get_add_light(f);    break;
  2641.             case S_RENDER:        get_render(f);        break;
  2642.             case S_VISDIFF:        get_visdiff(f);        break;
  2643.             case S_INCLUDE:        get_include(f);        break;
  2644.             default:        readerr(f, "expected assignment, set_ambient, set_attenuation, add_light, render or include statement");
  2645.             }
  2646.     }
  2647. /*...e*/
  2648.  
  2649. static void read_data_file(char *fn)
  2650.     {
  2651.     FILE    *fp;
  2652.     F    *f;
  2653.  
  2654.     if ( (fp = fopen(fn, "r")) == NULL )
  2655.         fatal("can't open %s", fn);
  2656.  
  2657.     f = open_stream(fp, fn);
  2658.     get_file(f);
  2659.     fp = close_stream(f);
  2660.     fclose(fp);
  2661.     }
  2662. /*...e*/
  2663.  
  2664. int main(int argc, char *argv[])
  2665.     {
  2666.     if ( argc != 2 )
  2667.         exit(1);
  2668.  
  2669. #ifdef OS2
  2670.     /* Prevent numeric exceptions from terminating this program */
  2671.     _control87(EM_UNDERFLOW|EM_DENORMAL, EM_UNDERFLOW|EM_DENORMAL);
  2672. #endif
  2673.  
  2674.     read_data_file(argv[1]);
  2675.  
  2676.     return 0;
  2677.     }
  2678. /*...e*/
  2679.