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