home *** CD-ROM | disk | FTP | other *** search
- /*
-
- RT.C CSG Ray Tracer
-
- */
-
- /*...sincludes:0:*/
- #include <stdio.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <stddef.h>
- #include <stdarg.h>
- #include <string.h>
- #include <memory.h>
- #include <malloc.h>
- #include <math.h>
- #include "standard.h"
- /*...e*/
-
- static char progname [] = "rt";
- static char sccs_id [] = "@(#)CSG Ray Tracer 1/3/93";
-
- /*...susefull:0:*/
- /*...sfatal:0:*/
- static void fatal(const char *fmt, ...)
- {
- va_list vars;
- char s [256+1];
-
- va_start(vars, fmt);
- vsprintf(s, fmt, vars);
- va_end(vars);
- fprintf(stderr, "%s: %s\n", progname, s);
- exit(1);
- }
- /*...e*/
- /*...susage:0:*/
- static void usage(void)
- {
- fprintf(stderr, "usage: %s scriptfile\n", progname);
- fprintf(stderr, "flags: scriptfile contains scene and view definition\n");
- exit(1);
- }
- /*...e*/
- /*...sget_opt_value:0:*/
- static int get_opt_value(char *s, char *name)
- {
- int v;
-
- if ( s == NULL )
- fatal("missing %s argument", name);
- if ( !isdigit(s [0]) )
- fatal("bad %s argument", name);
- if ( s [0] == '0' && tolower(s [1]) == 'x' )
- sscanf(s + 2, "%x", &v);
- else
- v = atoi(s);
-
- return ( v );
- }
- /*...e*/
- /*...smemcheck:0:*/
- static void *memcheck(void *p)
- {
- if ( p == NULL )
- fatal("out of memory");
- return ( p );
- }
- /*...e*/
- /*...sstrsave:0:*/
- static char *strsave(char *s)
- {
- int len = strlen(s);
- char *t = memcheck(malloc(len + 1));
-
- return ( strcpy(t, s) );
- }
- /*...e*/
- /*...e*/
- /*...smain:0:*/
- /*...sincludes:0:*/
- #include "rt.h"
- #include "fio.h"
- #include "tex.h"
- #include "vector.h"
- #include "rgbvec.h"
- #include "col.h"
- #include "surf.h"
- #include "sil.h"
- #include "plane.h"
- #include "sphere.h"
- #include "quad.h"
- #include "shape.h"
-
- /*...vrt\46\h:0:*/
- /*...vfio\46\h:0:*/
- /*...vtex\46\h:0:*/
- /*...vvector\46\h:0:*/
- /*...vrgbvec\46\h:0:*/
- /*...vcol\46\h:0:*/
- /*...vsurf\46\h:0:*/
- /*...vsil\46\h:0:*/
- /*...vplane\46\h:0:*/
- /*...vsphere\46\h:0:*/
- /*...vquad\46\h:0:*/
- /*...vshape\46\h:0:*/
- /*...e*/
-
- #ifdef OS2_V2
- #include <signal.h>
- #include <float.h>
- /*...vd\58\\92\ibmc\92\include\92\signal\46\h:0:*/
- /*...vd\58\\92\ibmc\92\include\92\float\46\h:0:*/
- #endif
-
- /*...slighting:0:*/
- /*
- Surfaces do not emit light of their own. They only reflect and refract light
- from the light sources in the scene. The lighting/shading model used is the
- one defined in F,vD,F,H p734.
-
- Global parameters :-
- Ia = ambient intensity (rgb vector)
-
- Parameters defined per surface :-
- ka = ambient-reflection-coefficient
- kd = diffuse coefficient, range 0.0 to 1.0
- ks = specular coefficient, range 0.0 to 1.0
- kt = transmission coefficent, range 0.0 to 1.0
- od = diffuse colour (rgb vector)
- os = specular colour (rgb vector)
- phong_number = Phong power
- rinx = inside relative to outside of surface
-
- Ambient contribution is :-
- Ia * ka * od
-
- Diffuse for light of intensity Ip, attenuated by distance by fatt, using
- Lamberts law gives :-
- fatt * Ip * kd * od * cos_nl
-
- Specular for light of intensity Ip, attenuated by distance by fatt, using
- the Phong shading model gives :-
- fatt * Ip * ks * os * pow(cos_rv, phong_number)
-
- Reflective component (specular only), using recursion (if depth not too deep) :-
- intensity_from_looking_along_reflected_ray * ks * os
-
- Refractive component (transmissive), given no total internal reflection,
- using recursion (if depth not too deep) :-
- intensity_from_refractive_ray * kt
-
- Before returning intensity, scale down by distance to origin of ray (eye).
- */
-
- typedef struct { VECTOR posn; RGBVEC i; } LIGHT;
-
- #define N_LIGHTS 10
- static LIGHT lights [N_LIGHTS];
- static int n_lights = 0;
-
- static RGBVEC i_background = { 0.0, 0.0, 0.0 };
- static RGBVEC i_ambient = { 0.0, 0.0, 0.0 };
- static double af1 = 1.0, af2 = 0.9;
-
- /*...sscale_by_distance:0:*/
- /*
- The further light travels (from light source to surface, or from surface to
- eye etc.) the fainter it gets. Therefore as t increases, the amount intensity
- is reduced by should increase.
- */
-
- static RGBVEC scale_by_distance(RGBVEC i, double t)
- {
- double scalar = af1 * pow(af2, t);
-
- if ( scalar > 1.0 )
- scalar = 1.0;
-
- i.r *= scalar;
- i.g *= scalar;
- i.b *= scalar;
-
- return ( i );
- }
- /*...e*/
- /*...e*/
- /*...srender:0:*/
- /*...strace:0:*/
- #define EPSILON (1.0e-8) /* A tiny number */
-
- /*...sshadow_calc:0:*/
- /*
-
- In a CSG system without refraction, no rays can pass through any solid.
- Hence this code would return 1.0 or 0.0 depending on whether il is empty.
- Actually we are only interested in the range of t from 0 to dist_l being empty.
- This is because the light is dist_l away, things further don't cause shadows.
-
- With refraction, things can be lit through glass-like solids.
- Let me admit, from the start, that refraction in a CSG system is a kludge!
- Glass-like solids transmit kt of the light coming from their other side.
- So we look along the intersections for transmissive surfaces and work out the
- combined transmissiveness.
-
- We assume that pathalogical shapes (transmissive on one side, non-transmissive
- on the the other) do not exist. We also assume the kt coefficients match for
- a given shape on its entry and exit. We only use kt once (on entry) per shape.
-
- Actually, to correctly handle illumination through refractive shapes is a
- nightmare, and requires that we calculate a full multi-part path back to the
- light. This is horrendous, and we will assume that refraction does not alter
- the path (much) back to the light.
-
- In doing so, we will prevent glass causing shadows, which is the main goal.
-
- */
-
- static double shadow_calc(ISECTL *il, double dist_l)
- {
- int j = 0;
- double kt_accum = 1.0;
-
- while ( j < il -> n_isects && il -> isects [j].t < dist_l )
- {
- double kt = il -> isects [j].shape -> surf -> kt;
-
- if ( kt == 0.0 )
- return ( 0.0 );
- kt_accum *= kt;
- j += 2;
- }
-
- return ( kt_accum );
- }
- /*...e*/
-
- /*...sreflect:0:*/
- static VECTOR reflect(VECTOR unit_v, VECTOR unit_n, double cos_vn)
- {
- return ( vector_difference(scale_vector(vector_sum(unit_n, unit_n), cos_vn), unit_v) );
- }
- /*...e*/
- /*...srefract:0:*/
- /*
- ^ N Given an incident unit vector I, approaching a
- | - surface with unit normal vector N, compute the
- \ | transmitted ray T. This ray will not necessarily
- \ | be a unit vector.
- \ |
- \ 0 | If the term under the square root is negative
- \ i| then this indicates total internal reflection.
- \ |
- I \|| n_it is the relative refractive index of the
- - -\| incident medium relative the the transmissive
- ----------+----------> S medium. Thus for air (1.0) entering crown glass
- |\ - (1.5) this number would be 1.0/1.5 = 0.66 approx.
- | \
- | \ We use the equation given in Byte Magazine Dec 90.
- | 0 \
- | t \
- | \
- | T \|
- | - -\
- |
- */
-
- static BOOLEAN refract(
- VECTOR unit_i,
- VECTOR unit_n,
- double n_it,
- VECTOR *t
- )
- {
- double cos_ni = -scalar_product(unit_n, unit_i);
- double under_root = 1.0 + n_it*n_it * (cos_ni*cos_ni - 1.0);
- double n_comp;
-
- if ( under_root < 0.0 )
- return ( FALSE ); /* Total internal reflection */
-
- n_comp = n_it * cos_ni - sqrt(under_root);
-
- *t = unit_vector(vector_sum(scale_vector(unit_i, n_it),
- scale_vector(unit_n, n_comp)));
-
- return ( TRUE );
- }
- /*...e*/
-
- static RGBVEC trace(
- SHAPE *root_shape,
- VECTOR start, VECTOR direction,
- int depth,
- ISECTL *ils []
- )
- {
- ISECTL *il = *ils;
- double t;
- SHAPE *shape;
- SURF *surf;
- RGBVEC i, od, os;
- VECTOR unit_direction, unit_v, isect_posn, unit_n;
- int j;
-
- unit_direction = unit_vector(direction);
- unit_v = negate_vector(unit_direction);
-
- intersect_shape(root_shape, start, unit_direction, ils);
- t_after_isectl(il, EPSILON);
-
- if ( is_empty_isectl(il) )
- return ( i_background );
-
- /* Hit something */
-
- t = il -> isects [0].t;
- shape = il -> isects [0].shape;
- surf = shape -> surf;
- isect_posn = t_along_pq(start, unit_direction, t);
- unit_n = unit_vector(normal_to_shape(shape, isect_posn));
-
- if ( il -> isects [0].negate_normal )
- unit_n = negate_vector(unit_n);
-
- /* Calculate colours at intersection position */
-
- od = evaluate_col(surf -> od, isect_posn.x, isect_posn.y, isect_posn.z);
- os = evaluate_col(surf -> os, isect_posn.x, isect_posn.y, isect_posn.z);
-
- /* Ambient light */
-
- i.r = i_ambient.r * surf -> ka * od.r;
- i.g = i_ambient.g * surf -> ka * od.g;
- i.b = i_ambient.b * surf -> ka * od.b;
-
- /* For each light source */
-
- for ( j = 0; j < n_lights; j++ )
- /*...shandle contribution of this light source:16:*/
- /*
- l is the vector from the intersection point to the light.
- dist_l is the distance to l.
- unit_l is a unit vector pointing to the light.
- We can reuse the intersection list used to hit the object for the shadow calc.
- */
-
- {
- VECTOR l, unit_l;
- double dist_l, kt_accum;
-
- l = vector_difference(lights [j].posn, isect_posn);
- dist_l = magnitude(l);
- unit_l = inv_scale_vector(l, dist_l);
-
- /* Can we see the light from the point of intersection */
-
- intersect_shape(root_shape, isect_posn, unit_l, ils);
- t_after_isectl(il, EPSILON);
-
- if ( (kt_accum = shadow_calc(il, dist_l)) > 0.0 )
- {
- RGBVEC i_light;
- VECTOR unit_r;
- double cos_ln, cos_rv;
-
- i_light = scale_rgbvec(scale_by_distance(lights [j].i, dist_l), kt_accum);
-
- /* Diffuse lighting, using Lambert's law */
-
- if ( (cos_ln = scalar_product(unit_l, unit_n)) > 0.0 )
- {
- double kd_cos_ln = surf -> kd * cos_ln;
-
- i.r += i_light.r * od.r * kd_cos_ln;
- i.g += i_light.g * od.g * kd_cos_ln;
- i.b += i_light.b * od.b * kd_cos_ln;
- }
-
- /* Specular lighting by light source, using Phong model */
-
- unit_r = reflect(unit_l, unit_n, cos_ln);
-
- if ( (cos_rv = scalar_product(unit_r, unit_v)) > 0.0 )
- {
- double ks_cos_rv_n = surf -> ks * pow(cos_rv, surf -> phong);
-
- i.r += i_light.r * os.r * ks_cos_rv_n;
- i.g += i_light.g * os.g * ks_cos_rv_n;
- i.b += i_light.b * os.b * ks_cos_rv_n;
- }
- }
- }
- /*...e*/
-
- if ( depth > 0 )
- {
- if ( surf -> ks > 0.0 )
- /*...sreflection:24:*/
- {
- double cos_nv;
-
- if ( (cos_nv = scalar_product(unit_n, unit_v)) > 0.0 )
- {
- VECTOR unit_r;
- RGBVEC i_r;
-
- unit_r = reflect(unit_v, unit_n, cos_nv);
- i_r = trace(root_shape, isect_posn, unit_r, depth - 1, ils);
-
- i.r += surf -> ks * os.r * i_r.r;
- i.g += surf -> ks * os.g * i_r.g;
- i.b += surf -> ks * os.b * i_r.b;
- }
- }
- /*...e*/
- if ( surf -> kt > 0.0 )
- /*...srefraction:24:*/
- /*
- Refractive index of outside medium is assumed to be 1.0.
- Bend the ray into the medium, work out where it comes out, and bend it again.
- Then trace the emerging ray and accumulate its effect.
- If total internal reflection occurs, entering the shape, treat as reflection.
- If it occurs leaving, bounce the ray inside the shape and try to exit again.
- */
-
- #define MAX_BOUNCE 10
-
- {
- VECTOR unit_r; /* Unit refracted ray at entry */
-
- if ( refract(unit_direction, unit_n, 1.0 / surf -> rinx, &unit_r) )
- /* Refraction has occurred */
- {
- double t_out; /* Value of t where leave solid */
- SHAPE *shape_out; /* Shape where leave solid */
- SURF *surf_out; /* Surface of shape where leave */
- VECTOR isect_posn_out; /* Place where leave solid */
- VECTOR unit_n_out; /* Unit inward pointing normal */
- VECTOR unit_r_out; /* Unit leaving refracted ray */
- double kt_comp = surf -> kt; /* Composite scale down factor */
- double t_comp = 0.0; /* Composite/total distance inside */
- int n_bounce = 0; /* # of internal bounces */
-
- isect_posn_out = isect_posn;
- unit_r_out = unit_r;
- for ( ;; )
- {
- double cos_rn;
-
- intersect_shape(root_shape, isect_posn_out, unit_r_out, ils);
- t_after_isectl(il, EPSILON);
-
- t_out = il -> isects [1].t;
- shape_out = il -> isects [1].shape;
- surf_out = shape_out -> surf;
- isect_posn_out = t_along_pq(isect_posn_out, unit_r_out, t_out);
- unit_n_out = unit_vector(normal_to_shape(shape_out, isect_posn_out));
-
- if ( !il -> isects [1].negate_normal )
- unit_n_out = negate_vector(unit_n_out);
-
- t_comp += t_out;
-
- if ( refract(unit_r_out, unit_n_out, surf_out -> rinx, &unit_r_out) )
- break; /* Refracted out of solid */
-
- /* Total internal reflection trying to leave solid */
- /* This implies the solid has an index > 1.0 */
-
- if ( ++n_bounce == MAX_BOUNCE )
- break; /* Reached our bounce limit, give up! */
-
- cos_rn = scalar_product(unit_r_out, unit_n_out);
- unit_r_out = reflect(negate_vector(unit_r_out), unit_n_out, -cos_rn);
- kt_comp *= surf_out -> kt; /* Accumulate this as we effectively re-enter solid */
- }
-
- if ( n_bounce < MAX_BOUNCE )
- {
- RGBVEC i_r;
-
- i_r = trace(root_shape, isect_posn_out, unit_r_out, depth - 1, ils);
- i_r = scale_by_distance(i_r, t_comp);
-
- i.r += kt_comp * i_r.r;
- i.g += kt_comp * i_r.g;
- i.b += kt_comp * i_r.b;
- }
- }
- else
- /* Total internal reflection trying to enter solid */
- /* This implies the solid has an index < 1.0 */
- /* This is not actually very likely (glass is 1.5, water 1.3 etc) */
- {
- double cos_nv;
-
- if ( (cos_nv = scalar_product(unit_n, unit_v)) > 0.0 )
- {
- VECTOR u_r;
- RGBVEC i_r;
-
- u_r = reflect(unit_v, unit_n, cos_nv);
- i_r = trace(root_shape, isect_posn, u_r, depth - 1, ils);
-
- i.r += surf -> kt * i_r.r;
- i.g += surf -> kt * i_r.g;
- i.b += surf -> kt * i_r.b;
- }
- }
- }
- /*...e*/
- }
-
- return ( scale_by_distance(i, t) );
- }
- /*...e*/
- /*...slogging:0:*/
- #include <time.h>
-
- static time_t t_start;
-
- static void bs(int n)
- {
- while ( n-- )
- fputc('\b', stdout);
- }
-
- static char *str_of_time(time_t t)
- {
- static char buf [30+1];
-
- strcpy(buf, ctime(&t));
- buf [19] = '\0';
- return ( buf + 11 );
- }
-
- static void log_init(char *fn)
- {
- t_start = time(NULL);
-
- printf("%s, started %8s, 0.0%% done, etc ________, max int 0.00 ", fn, str_of_time(t_start));
- fflush(stdout);
- }
-
- static void log_done_so_far(int done, int total, double m)
- {
- double percent = (100.0 * (double) done) / (double) total;
- time_t t_fin = t_start + (((time(NULL) - t_start) * total) / done);
-
- bs(40);
- printf("%5.1lf%% done, etc %8s, max int %4.2lf ",
- percent, str_of_time(t_fin), m);
- fflush(stdout);
- }
-
- static void log_done(double m)
- {
- time_t t_now = time(NULL);
-
- bs(40);
- printf("done %8s, max int %4.2lf \n",
- str_of_time(t_now), m);
- fflush(stdout);
- }
- /*...e*/
-
- static void render(
- SHAPE *shape, /* Root of shape tree */
- VECTOR eye, /* Eye position vector */
- VECTOR forward, /* Forward vector */
- VECTOR up, /* Up vector */
- double hangle, double vangle, /* Veiwing angles */
- int hpixels, int vpixels, /* No of pixels to render */
- int depth, /* Depth to recurse to */
- char *fn /* Output filename */
- )
- {
- BITMAP *bitmap;
- VECTOR unit_forward, unit_up, unit_right, vis_up, vis_right;
- double hpixels2 = (double) (hpixels >> 1);
- double vpixels2 = (double) (vpixels >> 1);
- int h, v;
- double m = 0.0;
- int n_isectls, n_isects, i;
- ISECTL **ils;
-
- unit_forward = unit_vector(forward);
- unit_up = unit_vector(up);
- unit_right = vector_product(unit_forward, unit_up);
- vis_up = scale_vector(unit_up, tan(vangle));
- vis_right = scale_vector(unit_right, tan(hangle));
-
- if ( (bitmap = fio_create_bitmap(hpixels, vpixels)) == NULL )
- fatal("out of memory for bitmap %dx%d", hpixels, vpixels);
-
- preprocess_shape(shape, &n_isectls, &n_isects);
-
- /* Now allocate intersection lists, for use in tracing */
-
- printf("Require %d intersection lists, each of %d intersections\n",
- n_isectls, n_isects);
- if ( (ils = malloc(n_isectls * sizeof(ISECTL *))) == NULL )
- fatal("out of memory");
- for ( i = 0; i < n_isectls; i++ )
- if ( (ils [i] = create_isectl(n_isects)) == NULL )
- fatal("out of memory");
-
- log_init(fn);
-
- for ( v = 0; v < vpixels; v++ )
- {
- double vfactor = (v - vpixels2) / vpixels2;
- VECTOR comp_up, ray_plane;
-
- comp_up = scale_vector(vis_up, vfactor);
- ray_plane = vector_sum(unit_forward, comp_up);
-
- for ( h = 0; h < hpixels; h++ )
- {
- double hfactor = (h - hpixels2) / hpixels2;
- VECTOR comp_right, ray;
- RGBVEC rgb;
-
- comp_right = scale_vector(vis_right, hfactor);
- ray = vector_sum(ray_plane, comp_right);
- rgb = trace(shape, eye, ray, depth, ils);
-
- if ( rgb.r > m ) m = rgb.r;
- if ( rgb.g > m ) m = rgb.g;
- if ( rgb.b > m ) m = rgb.b;
-
- if ( rgb.r > 1.0 ) rgb.r = 1.0;
- if ( rgb.g > 1.0 ) rgb.g = 1.0;
- if ( rgb.b > 1.0 ) rgb.b = 1.0;
-
- fio_set_pixel(bitmap, h, v, (byte) (rgb.r * 255.0),
- (byte) (rgb.g * 255.0),
- (byte) (rgb.b * 255.0));
- }
-
- log_done_so_far(v + 1, vpixels, m);
- }
-
- log_done(m);
-
- for ( i = 0; i < n_isectls; i++ )
- destroy_isectl(ils [i]);
- free(ils);
-
- if ( !fio_write_bitmap(bitmap, fn) )
- fatal("unable to write %s", fn);
-
- fio_destroy_bitmap(bitmap);
- }
- /*...e*/
- /*...sread_data_file:0:*/
- /*...slexical stuff:0:*/
- #define S_EOF 0
- #define S_ID 1
- #define S_VALUE 2
- #define S_STRING 3
- #define S_COMMA 4
- #define S_LPAR 5
- #define S_RPAR 6
- #define S_RAD 7
- #define S_VECTOR 8
- #define S_RGBVEC 9
- #define S_COL_CONST 10
- #define S_COL_NO_MOVE 11
- #define S_COL_INTERP0 12
- #define S_COL_INTERP1 13
- #define S_COL_INTERP2 14
- #define S_COL_FIELD2D 15
- #define S_COL_FIELD3D 16
- #define S_COL_REMAP 17
- #define S_COL_CYLPOLAR 18
- #define S_COL_SPHPOLAR 19
- #define S_COL_MATRIX2D 20
- #define S_COL_MATRIX3D 21
- #define S_SURF 22
- #define S_RESURF 23
- #define S_PLANE 24
- #define S_X_LT 25
- #define S_X_GT 26
- #define S_Y_LT 27
- #define S_Y_GT 28
- #define S_Z_LT 29
- #define S_Z_GT 30
- #define S_QUAD 31
- #define S_ELLIPSOID 32
- #define S_SPHERE 33
- #define S_X_ELL_CYL 34
- #define S_Y_ELL_CYL 35
- #define S_Z_ELL_CYL 36
- #define S_X_CYL 37
- #define S_Y_CYL 38
- #define S_Z_CYL 39
- #define S_X_ELL_CONE 40
- #define S_Y_ELL_CONE 41
- #define S_Z_ELL_CONE 42
- #define S_X_CONE 43
- #define S_Y_CONE 44
- #define S_Z_CONE 45
- #define S_TRANS 46
- #define S_TRANS_X 47
- #define S_TRANS_Y 48
- #define S_TRANS_Z 49
- #define S_SCALE 50
- #define S_SCALE_X 51
- #define S_SCALE_Y 52
- #define S_SCALE_Z 53
- #define S_ROTATE_X 54
- #define S_ROTATE_Y 55
- #define S_ROTATE_Z 56
- #define S_UNION 57
- #define S_ISECT 58
- #define S_DIFF 59
- #define S_SDIFF 60
- #define S_EXTENT 61
- #define S_SET_VALUE 62
- #define S_SET_VECTOR 63
- #define S_SET_RGBVEC 64
- #define S_SET_COL 65
- #define S_SET_SURF 66
- #define S_SET_SHAPE 67
- #define S_SET_BKGND 68
- #define S_SET_AMBIENT 69
- #define S_SET_ATTEN 70
- #define S_ADD_LIGHT 71
- #define S_RENDER 72
- #define S_INCLUDE 73
-
- typedef struct { char *id_name; int id; } RESERVED_WORD;
-
- static RESERVED_WORD my_reserved_words [] =
- {
- "rad", S_RAD,
- "xyz", S_VECTOR,
- "rgb", S_RGBVEC,
- "col", S_COL_CONST,
- "col_nomove", S_COL_NO_MOVE,
- "col_interp0", S_COL_INTERP0,
- "col_interp1", S_COL_INTERP1,
- "col_interp2", S_COL_INTERP2,
- "col_field2d", S_COL_FIELD2D,
- "col_field3d", S_COL_FIELD3D,
- "col_remap", S_COL_REMAP,
- "col_cyl", S_COL_CYLPOLAR,
- "col_sph", S_COL_SPHPOLAR,
- "col_mat2d", S_COL_MATRIX2D,
- "col_mat3d", S_COL_MATRIX3D,
- "surf", S_SURF,
- "resurf", S_RESURF,
- "plane", S_PLANE,
- "x_lt", S_X_LT,
- "x_gt", S_X_GT,
- "y_lt", S_Y_LT,
- "y_gt", S_Y_GT,
- "z_lt", S_Z_LT,
- "z_gt", S_Z_GT,
- "quad", S_QUAD,
- "ellipsoid", S_ELLIPSOID,
- "sphere", S_SPHERE,
- "x_ell_cyl", S_X_ELL_CYL,
- "y_ell_cyl", S_Y_ELL_CYL,
- "z_ell_cyl", S_Z_ELL_CYL,
- "x_cyl", S_X_CYL,
- "y_cyl", S_Y_CYL,
- "z_cyl", S_Z_CYL,
- "x_ell_cone", S_X_ELL_CONE,
- "y_ell_cone", S_Y_ELL_CONE,
- "z_ell_cone", S_Z_ELL_CONE,
- "x_cone", S_X_CONE,
- "y_cone", S_Y_CONE,
- "z_cone", S_Z_CONE,
- "trans", S_TRANS,
- "trans_x", S_TRANS_X,
- "trans_y", S_TRANS_Y,
- "trans_z", S_TRANS_Z,
- "scale", S_SCALE,
- "scale_x", S_SCALE_X,
- "scale_y", S_SCALE_Y,
- "scale_z", S_SCALE_Z,
- "rot_x", S_ROTATE_X,
- "rot_y", S_ROTATE_Y,
- "rot_z", S_ROTATE_Z,
- "union", S_UNION,
- "isect", S_ISECT,
- "diff", S_DIFF,
- "sdiff", S_SDIFF,
- "extent", S_EXTENT,
- "set_value", S_SET_VALUE,
- "set_xyz", S_SET_VECTOR,
- "set_rgb", S_SET_RGBVEC,
- "set_col", S_SET_COL,
- "set_surf", S_SET_SURF,
- "set_shape", S_SET_SHAPE,
- "set_background",S_SET_BKGND,
- "set_ambient", S_SET_AMBIENT,
- "set_attenuation",S_SET_ATTEN,
- "add_light", S_ADD_LIGHT,
- "render", S_RENDER,
- "include", S_INCLUDE,
- };
-
- #define N_RESERVED_WORDS (sizeof(my_reserved_words)/sizeof(my_reserved_words [0]))
-
- typedef struct
- {
- FILE *fp;
- char fn [500+1];
- unsigned long line_num;
- int chr;
- char str [100+1];
- char id_name [100+1];
- double id_value;
- } F;
-
- /*...sopen_stream:0:*/
- static F *open_stream(FILE *fp, char *fn)
- {
- F *f = (F *) memcheck(malloc(sizeof(F)));
-
- f -> fp = fp;
- f -> line_num = 1UL;
- strcpy(f -> fn, fn);
- f -> chr = getc(f -> fp);
- return ( f );
- }
- /*...e*/
- /*...sclose_stream:0:*/
- static FILE *close_stream(F *f)
- {
- FILE *fp = f -> fp;
-
- free(f);
- return ( fp );
- }
- /*...e*/
- /*...sreaderr:0:*/
- static void readerr(F *f, const char *fmt, ...)
- {
- va_list vars;
- char s [256+1];
-
- va_start(vars, fmt);
- vsprintf(s, fmt, vars);
- va_end(vars);
- fprintf(stderr, "%s(%lu): %s\n", f -> fn, f -> line_num, s);
- exit(1);
- }
- /*...e*/
- /*...sgetsym:0:*/
- static int getsym(F *f)
- {
- int i = 0;
-
- for ( ;; )
- {
- while ( f -> chr != EOF && isspace(f -> chr) )
- {
- if ( f -> chr == '\n' )
- f -> line_num++;
- f -> chr = getc(f -> fp);
- }
-
- if ( f -> chr == EOF )
- return ( S_EOF );
-
- if ( f -> chr != ';' )
- break;
-
- while ( (f -> chr = getc(f -> fp)) != EOF && f -> chr != '\n' )
- if ( f -> chr == '\n' )
- f -> line_num++;
- }
-
- if ( f -> chr == ',' )
- {
- f -> chr = getc(f -> fp);
- return ( S_COMMA );
- }
-
- if ( f -> chr == '(' )
- {
- f -> chr = getc(f -> fp);
- return ( S_LPAR );
- }
-
- if ( f -> chr == ')' )
- {
- f -> chr = getc(f -> fp);
- return ( S_RPAR );
- }
-
- if ( isdigit(f -> chr) || f -> chr == '+' || f -> chr == '-' || f -> chr == '.' )
- {
- char num [50+1];
-
- do
- {
- num [i++] = (char) f -> chr;
- f -> chr = getc(f -> fp);
- }
- while ( isdigit(f -> chr) || f -> chr == '+' || f -> chr == '-' ||
- f -> chr == '.' || f -> chr == 'e' || f -> chr == 'E' );
- num [i] = (char) '\0';
-
- sscanf(num, "%lf", &(f -> id_value));
-
- return ( S_VALUE );
- }
-
- if ( f -> chr == '"' )
- {
- int j = 0;
-
- while ( (f -> chr = getc(f -> fp)) != EOF && f -> chr != '"' )
- f -> str [j++] = (char) f -> chr;
- f -> str [j] = '\0';
- if ( f -> chr == '"' )
- f -> chr = getc(f -> fp);
- return ( S_STRING );
- }
-
- if ( !(isalnum(f -> chr) || f -> chr != '_') )
- readerr(f, "character 0x%02x not expected", f -> chr);
-
- while ( f -> chr != EOF && (isalnum(f -> chr) || f -> chr == '_') )
- {
- f -> id_name [i++] = (char) f -> chr;
- f -> chr = getc(f -> fp);
- }
- f -> id_name [i] = '\0';
-
- for ( i = 0; i < N_RESERVED_WORDS; i++ )
- if ( !strcmp(f -> id_name, my_reserved_words [i].id_name) )
- return ( my_reserved_words [i].id );
-
- return ( S_ID );
- }
- /*...e*/
- /*...sskip:0:*/
- static void skip(F *f, int symbol, char *symbol_name)
- {
- if ( getsym(f) != symbol )
- readerr(f, "expected %s", symbol_name);
- }
- /*...e*/
- /*...e*/
- /*...suser variables:0:*/
- typedef byte VTYPE;
- #define VTYPE_VALUE ((VTYPE) 0)
- #define VTYPE_VECTOR ((VTYPE) 1)
- #define VTYPE_RGBVEC ((VTYPE) 2)
- #define VTYPE_COL ((VTYPE) 3)
- #define VTYPE_SURF ((VTYPE) 4)
- #define VTYPE_SHAPE ((VTYPE) 5)
-
- static char *vtype_names [] =
- {
- "value",
- "xyz_vector",
- "rgb_vector",
- "colour",
- "surface",
- "shape",
- };
-
- typedef struct
- {
- char *name;
- VTYPE vtype;
- union
- {
- double value;
- VECTOR vector;
- RGBVEC rgb;
- COL *col;
- SURF *surf;
- SHAPE *shape;
- } u;
- } VAR;
-
- #define N_VARS 500
- static VAR vars [N_VARS];
- static int n_vars = 0;
-
- /*...slookup_var:0:*/
- static int lookup_var(char *name)
- {
- int i;
-
- for ( i = 0; i < n_vars; i++ )
- if ( !strcmp(name, vars [i].name) )
- return ( i );
- return ( -1 );
- }
- /*...e*/
- /*...slookup_defined_var:0:*/
- static int lookup_defined_var(F *f, char *name)
- {
- int i;
-
- if ( (i = lookup_var(name)) == -1 )
- readerr(f, "undefined variable %s", name);
- return ( i );
- }
- /*...e*/
- /*...slookup_defined_var_vtype:0:*/
- static int lookup_defined_var_vtype(F *f, char *name, VTYPE vtype)
- {
- int i = lookup_defined_var(f, name);
-
- if ( vars [i].vtype != vtype )
- readerr(f, "expected %s variable", vtype_names [vtype]);
- return ( i );
- }
- /*...e*/
-
- /*...sadd_value_var:0:*/
- static void add_value_var(F *f, char *name, double value)
- {
- if ( n_vars == N_VARS )
- readerr(f, "too many variables");
-
- vars [n_vars ].name = strsave(name);
- vars [n_vars ].vtype = VTYPE_VALUE;
- vars [n_vars++].u.value = value;
- }
- /*...e*/
- /*...sadd_vector_var:0:*/
- static void add_vector_var(F *f, char *name, VECTOR vector)
- {
- if ( n_vars == N_VARS )
- readerr(f, "too many variables");
-
- vars [n_vars ].name = strsave(name);
- vars [n_vars ].vtype = VTYPE_VECTOR;
- vars [n_vars++].u.vector = vector;
- }
- /*...e*/
- /*...sadd_rgb_var:0:*/
- static void add_rgb_var(F *f, char *name, RGBVEC rgb)
- {
- if ( n_vars == N_VARS )
- readerr(f, "too many variables");
-
- vars [n_vars ].name = strsave(name);
- vars [n_vars ].vtype = VTYPE_RGBVEC;
- vars [n_vars++].u.rgb = rgb;
- }
- /*...e*/
- /*...sadd_col_var:0:*/
- static void add_col_var(F *f, char *name, COL *col)
- {
- if ( n_vars == N_VARS )
- readerr(f, "too many variables");
-
- vars [n_vars ].name = strsave(name);
- vars [n_vars ].vtype = VTYPE_COL;
- vars [n_vars++].u.col = col;
- }
- /*...e*/
- /*...sadd_surf_var:0:*/
- static void add_surf_var(F *f, char *name, SURF *surf)
- {
- if ( n_vars == N_VARS )
- readerr(f, "too many variables");
-
- vars [n_vars ].name = strsave(name);
- vars [n_vars ].vtype = VTYPE_SURF;
- vars [n_vars++].u.surf = surf;
- }
- /*...e*/
- /*...sadd_shape_var:0:*/
- static void add_shape_var(F *f, char *name, SHAPE *shape)
- {
- if ( n_vars == N_VARS )
- readerr(f, "too many variables");
-
- vars [n_vars ].name = strsave(name);
- vars [n_vars ].vtype = VTYPE_SHAPE;
- vars [n_vars++].u.shape = shape;
- }
- /*...e*/
- /*...e*/
-
- static void read_data_file(char *fn);
-
- /*...sget_file:0:*/
- /*...sget_new_id:0:*/
- static void get_new_id(F *f, char *name)
- {
- if ( getsym(f) != S_ID )
- readerr(f, "expected new identifier");
-
- strncpy(name, f -> id_name, 30);
-
- if ( lookup_var(name) != -1 )
- readerr(f, "redefinition of identifier %s", name);
- }
- /*...e*/
- /*...sget_value:0:*/
- static double get_value(F *f)
- {
- switch ( getsym(f) )
- {
- case S_VALUE:
- return ( f -> id_value );
- case S_ID:
- return ( vars [lookup_defined_var_vtype(f, f -> id_name, VTYPE_VALUE)].u.value );
- case S_RAD:
- {
- double value;
-
- skip(f, S_LPAR, "(");
- value = get_value(f);
- skip(f, S_RPAR, ")");
- return ( value * PI / 180.0 );
- }
- default:
- readerr(f, "number or numeric variable expected");
- }
- return ( 0.0 ); /* Keep fussy C compiler happy */
- }
- /*...e*/
- /*...sget_vector:0:*/
- static VECTOR get_vector(F *f)
- {
- static VECTOR dummy_vector = { 0.0, 0.0, 0.0 };
-
- switch ( getsym(f) )
- {
- /*...sS_VECTOR:16:*/
- case S_VECTOR:
- {
- VECTOR vector;
-
- skip(f, S_LPAR , "("); vector.x = get_value(f);
- skip(f, S_COMMA, ","); vector.y = get_value(f);
- skip(f, S_COMMA, ","); vector.z = get_value(f);
- skip(f, S_RPAR , ")");
- return ( vector );
- }
- /*...e*/
- /*...sS_TRANS:16:*/
- case S_TRANS:
- {
- VECTOR v, t;
-
- skip(f, S_LPAR , "("); v = get_vector(f);
- skip(f, S_COMMA, ","); t = get_vector(f);
- skip(f, S_RPAR , ")");
- return ( vector_sum(v, t) );
- }
- /*...e*/
- /*...sS_TRANS_X:16:*/
- case S_TRANS_X:
- {
- VECTOR v;
- double t;
-
- skip(f, S_LPAR , "("); v = get_vector(f);
- skip(f, S_COMMA, ","); t = get_value(f);
- skip(f, S_RPAR , ")");
- v.x += t;
- return ( v );
- }
- /*...e*/
- /*...sS_TRANS_Y:16:*/
- case S_TRANS_Y:
- {
- VECTOR v;
- double t;
-
- skip(f, S_LPAR , "("); v = get_vector(f);
- skip(f, S_COMMA, ","); t = get_value(f);
- skip(f, S_RPAR , ")");
- v.y += t;
- return ( v );
- }
- /*...e*/
- /*...sS_TRANS_Z:16:*/
- case S_TRANS_Z:
- {
- VECTOR v;
- double t;
-
- skip(f, S_LPAR , "("); v = get_vector(f);
- skip(f, S_COMMA, ","); t = get_value(f);
- skip(f, S_RPAR , ")");
- v.z += t;
- return ( v );
- }
- /*...e*/
- /*...sS_SCALE:16:*/
- case S_SCALE:
- {
- VECTOR v, factor;
-
- skip(f, S_LPAR , "("); v = get_vector(f);
- skip(f, S_COMMA, ","); factor = get_vector(f);
- skip(f, S_RPAR , ")");
- v.x *= factor.x;
- v.y *= factor.y;
- v.z *= factor.z;
- return ( v );
- }
- /*...e*/
- /*...sS_SCALE_X:16:*/
- case S_SCALE_X:
- {
- VECTOR v;
- double factor;
-
- skip(f, S_LPAR , "("); v = get_vector(f);
- skip(f, S_COMMA, ","); factor = get_value(f);
- skip(f, S_RPAR , ")");
- v.x *= factor;
- return ( v );
- }
- /*...e*/
- /*...sS_SCALE_Y:16:*/
- case S_SCALE_Y:
- {
- VECTOR v;
- double factor;
-
- skip(f, S_LPAR , "("); v = get_vector(f);
- skip(f, S_COMMA, ","); factor = get_value(f);
- skip(f, S_RPAR , ")");
- v.y *= factor;
- return ( v );
- }
- /*...e*/
- /*...sS_SCALE_Z:16:*/
- case S_SCALE_Z:
- {
- VECTOR v;
- double factor;
-
- skip(f, S_LPAR , "("); v = get_vector(f);
- skip(f, S_COMMA, ","); factor = get_value(f);
- skip(f, S_RPAR , ")");
- v.z *= factor;
- return ( v );
- }
- /*...e*/
- /*...sS_ROTATE_X:16:*/
- case S_ROTATE_X:
- {
- VECTOR v;
- double angle;
-
- skip(f, S_LPAR , "("); v = get_vector(f);
- skip(f, S_COMMA, ","); angle = get_value(f);
- skip(f, S_RPAR , ")");
- return ( rot_x_vector(v, angle) );
- }
- /*...e*/
- /*...sS_ROTATE_Y:16:*/
- case S_ROTATE_Y:
- {
- VECTOR v;
- double angle;
-
- skip(f, S_LPAR , "("); v = get_vector(f);
- skip(f, S_COMMA, ","); angle = get_value(f);
- skip(f, S_RPAR , ")");
- return ( rot_y_vector(v, angle) );
- }
- /*...e*/
- /*...sS_ROTATE_Z:16:*/
- case S_ROTATE_Z:
- {
- VECTOR v;
- double angle;
-
- skip(f, S_LPAR , "("); v = get_vector(f);
- skip(f, S_COMMA, ","); angle = get_value(f);
- skip(f, S_RPAR , ")");
- return ( rot_z_vector(v, angle) );
- }
- /*...e*/
- /*...sS_ID:16:*/
- case S_ID:
- return ( vars [lookup_defined_var_vtype(f, f -> id_name, VTYPE_VECTOR)].u.vector );
- /*...e*/
- /*...sdefault:16:*/
- default:
- readerr(f, "vector expected");
- /*...e*/
- }
- return ( dummy_vector ); /* Keep fussy C compiler happy */
- }
- /*...e*/
- /*...sget_rgb:0:*/
- static RGBVEC get_rgb(F *f)
- {
- static RGBVEC dummy_rgbvec = { 0.0, 0.0, 0.0 };
-
- switch ( getsym(f) )
- {
- case S_RGBVEC:
- {
- RGBVEC rgb;
-
- skip(f, S_LPAR , "("); rgb.r = get_value(f);
- skip(f, S_COMMA, ","); rgb.g = get_value(f);
- skip(f, S_COMMA, ","); rgb.b = get_value(f);
- skip(f, S_RPAR , ")");
- return ( rgb );
- }
- case S_ID:
- return ( vars [lookup_defined_var_vtype(f, f -> id_name, VTYPE_RGBVEC)].u.rgb );
- default:
- readerr(f, "rgb colour vector expected");
- }
-
- return ( dummy_rgbvec ); /* Keep fussy C compiler happy */
- }
- /*...e*/
- /*...sget_col:0:*/
- /*
- This returns a colour.
- If it comes from a user variable, then a copy of the variable is returned.
- If not, then the new datastructure is returned.
- */
-
- static COL *get_col(F *f)
- {
- switch ( getsym(f) )
- {
- /*...sS_COL_CONST:16:*/
- case S_COL_CONST:
- {
- RGBVEC rgbvec;
-
- skip(f, S_LPAR , "("); rgbvec = get_rgb(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_const_col(rgbvec)) );
- }
- /*...e*/
- /*...sS_COL_NO_MOVE:16:*/
- case S_COL_NO_MOVE:
- {
- COL *col;
-
- skip(f, S_LPAR , "("); col = get_col(f);
- skip(f, S_RPAR , ")");
-
- return ( memcheck(create_no_move_col(col)) );
- }
- /*...e*/
- /*...sS_COL_INTERP0:16:*/
- case S_COL_INTERP0:
- {
- COL *col;
-
- skip(f, S_LPAR , "("); col = get_col(f);
- skip(f, S_RPAR , ")");
-
- return ( memcheck(create_interp0_col(col)) );
- }
- /*...e*/
- /*...sS_COL_INTERP1:16:*/
- case S_COL_INTERP1:
- {
- COL *col;
-
- skip(f, S_LPAR , "("); col = get_col(f);
- skip(f, S_RPAR , ")");
-
- return ( memcheck(create_interp1_col(col)) );
- }
- /*...e*/
- /*...sS_COL_INTERP2:16:*/
- case S_COL_INTERP2:
- {
- COL *col;
-
- skip(f, S_LPAR , "("); col = get_col(f);
- skip(f, S_RPAR , ")");
-
- return ( memcheck(create_interp2_col(col)) );
- }
- /*...e*/
- /*...sS_COL_FIELD2D:16:*/
- case S_COL_FIELD2D:
- {
- double bx, by;
- BITMAP *bitmap;
-
- skip(f, S_LPAR , "("); bx = get_value(f);
- skip(f, S_COMMA, ","); by = get_value(f);
- skip(f, S_COMMA, ",");
-
- if ( getsym(f) != S_STRING )
- readerr(f, "expected input bitmap filename");
-
- if ( (bitmap = fio_read_bitmap(f -> str)) == NULL )
- readerr(f, "unable to read bitmap %s", f -> str);
-
- skip(f, S_RPAR , ")");
- return ( memcheck(create_2d_field_col(bx, by, bitmap)) );
- }
- /*...e*/
- /*...sS_COL_FIELD3D:16:*/
- case S_COL_FIELD3D:
- {
- double bx, by, bz;
- TEX *tex;
-
- skip(f, S_LPAR , "("); bx = get_value(f);
- skip(f, S_COMMA, ","); by = get_value(f);
- skip(f, S_COMMA, ","); bz = get_value(f);
- skip(f, S_COMMA, ",");
-
- if ( getsym(f) != S_STRING )
- readerr(f, "expected input 3d texture-map filename");
-
- if ( (tex = read_tex(f -> str)) == NULL )
- readerr(f, "unable to read 3d texture-map %s", f -> str);
-
- skip(f, S_RPAR , ")");
- return ( memcheck(create_3d_field_col(bx, by, bz, tex)) );
- }
- /*...e*/
- /*...sS_COL_REMAP:16:*/
- case S_COL_REMAP:
- {
- VECTOR base, v0, v1, v2;
- COL *col;
-
- skip(f, S_LPAR , "("); base = get_vector(f);
- skip(f, S_COMMA, ","); v0 = get_vector(f);
- skip(f, S_COMMA, ","); v1 = get_vector(f);
- skip(f, S_COMMA, ","); v2 = get_vector(f);
- skip(f, S_COMMA, ","); col = get_col(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_remap_col(base, v0, v1, v2, col)) );
- }
- /*...e*/
- /*...sS_COL_CYLPOLAR:16:*/
- case S_COL_CYLPOLAR:
- {
- double lond, rd, hd;
- COL *col;
-
- skip(f, S_LPAR , "("); lond = get_value(f);
- skip(f, S_COMMA, ","); rd = get_value(f);
- skip(f, S_COMMA, ","); hd = get_value(f);
- skip(f, S_COMMA, ","); col = get_col(f);
- skip(f, S_RPAR , ")");
-
- return ( memcheck(create_cyl_polar_col(lond, rd, hd, col)) );
- }
- /*...e*/
- /*...sS_COL_SPHPOLAR:16:*/
- case S_COL_SPHPOLAR:
- {
- double lond, latd, rd;
- COL *col;
-
- skip(f, S_LPAR , "("); lond = get_value(f);
- skip(f, S_COMMA, ","); latd = get_value(f);
- skip(f, S_COMMA, ","); rd = get_value(f);
- skip(f, S_COMMA, ","); col = get_col(f);
- skip(f, S_RPAR , ")");
-
- return ( memcheck(create_sph_polar_col(lond, latd, rd, col)) );
- }
- /*...e*/
- /*...sS_COL_MATRIX2D:16:*/
- case S_COL_MATRIX2D:
- {
- double m [2][2];
- int i, j;
- COL *col;
-
- skip(f, S_LPAR , "(");
- for ( j = 0; j < 2; j++ )
- for ( i = 0; i < 2; i++ )
- {
- m [j][i] = get_value(f);
- skip(f, S_COMMA, ",");
- }
- col = get_col(f);
- skip(f, S_RPAR , ")");
-
- return ( memcheck(create_2d_matrix_col(m, col)) );
- }
- /*...e*/
- /*...sS_COL_MATRIX3D:16:*/
- case S_COL_MATRIX3D:
- {
- double m [3][3];
- int i, j;
- COL *col;
-
- skip(f, S_LPAR , "(");
- for ( j = 0; j < 3; j++ )
- for ( i = 0; i < 3; i++ )
- {
- m [j][i] = get_value(f);
- skip(f, S_COMMA, ",");
- }
- col = get_col(f);
- skip(f, S_RPAR , ")");
-
- return ( memcheck(create_3d_matrix_col(m, col)) );
- }
- /*...e*/
- /*...sS_ID:16:*/
- case S_ID:
- {
- COL *col = vars [lookup_defined_var_vtype(f, f -> id_name, VTYPE_COL)].u.col;
-
- return ( memcheck(copy_col(col)) );
- }
- /*...e*/
- /*...sdefault:16:*/
- default:
- readerr(f, "colour definition or colour variable expected");
- /*...e*/
- }
- return ( NULL ); /* Keep fussy C compiler happy */
- }
- /*...e*/
- /*...sget_surf:0:*/
- /*
- This returns a surface.
- If it comes from a user variable, then a copy of the variable is returned.
- If not, then the new datastructure is returned.
- */
-
- static SURF *get_surf(F *f)
- {
- switch ( getsym(f) )
- {
- case S_SURF:
- {
- double ka, kd, ks, kt;
- COL *od, *os;
- double phong, rinx;
-
- skip(f, S_LPAR , "("); ka = get_value(f);
- skip(f, S_COMMA, ","); kd = get_value(f);
- skip(f, S_COMMA, ","); ks = get_value(f);
- skip(f, S_COMMA, ","); kt = get_value(f);
- skip(f, S_COMMA, ","); od = get_col(f);
- skip(f, S_COMMA, ","); os = get_col(f);
- skip(f, S_COMMA, ","); phong = get_value(f);
- skip(f, S_COMMA, ","); rinx = get_value(f);
- skip(f, S_RPAR , ")");
-
- return ( memcheck(create_surf(ka, kd, ks, kt, od, os, phong, rinx)) );
- }
- case S_ID:
- {
- SURF *surf = vars [lookup_defined_var_vtype(f, f -> id_name, VTYPE_SURF)].u.surf;
-
- return ( memcheck(copy_surf(surf)) );
- }
- default:
- readerr(f, "surface definition or surface variable expected");
- }
- return ( NULL ); /* Keep fussy C compiler happy */
- }
- /*...e*/
- /*...sget_shape:0:*/
- /*
- This returns a shape.
- If it comes from a user variable, then a copy of the variable is returned.
- If not, then the new datastructure is returned.
- */
-
- static SHAPE *get_shape(F *f)
- {
- switch ( getsym(f) )
- {
- /*...sS_PLANE:16:*/
- case S_PLANE:
- {
- double a, b, c, d;
- SURF *surf;
-
- skip(f, S_LPAR , "("); a = get_value(f);
- skip(f, S_COMMA, ","); b = get_value(f);
- skip(f, S_COMMA, ","); c = get_value(f);
- skip(f, S_COMMA, ","); d = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_plane_shape(memcheck(create_plane(a, b, c, d)), surf)) );
- }
- /*...e*/
- /*...sS_X_LT:16:*/
- case S_X_LT:
- {
- double x;
- SURF *surf;
-
- skip(f, S_LPAR , "("); x = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_plane_shape(memcheck(create_x_lt_plane(x)), surf)) );
- }
- /*...e*/
- /*...sS_X_GT:16:*/
- case S_X_GT:
- {
- double x;
- SURF *surf;
-
- skip(f, S_LPAR , "("); x = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_plane_shape(memcheck(create_x_gt_plane(x)), surf)) );
- }
- /*...e*/
- /*...sS_Y_LT:16:*/
- case S_Y_LT:
- {
- double y;
- SURF *surf;
-
- skip(f, S_LPAR , "("); y = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_plane_shape(memcheck(create_y_lt_plane(y)), surf)) );
- }
- /*...e*/
- /*...sS_Y_GT:16:*/
- case S_Y_GT:
- {
- double y;
- SURF *surf;
-
- skip(f, S_LPAR , "("); y = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_plane_shape(memcheck(create_y_gt_plane(y)), surf)) );
- }
- /*...e*/
- /*...sS_Z_LT:16:*/
- case S_Z_LT:
- {
- double z;
- SURF *surf;
-
- skip(f, S_LPAR , "("); z = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_plane_shape(memcheck(create_z_lt_plane(z)), surf)) );
- }
- /*...e*/
- /*...sS_Z_GT:16:*/
- case S_Z_GT:
- {
- double z;
- SURF *surf;
-
- skip(f, S_LPAR , "("); z = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_plane_shape(memcheck(create_z_gt_plane(z)), surf)) );
- }
- /*...e*/
- /*...sS_SPHERE:16:*/
- case S_SPHERE:
- {
- double r;
- SURF *surf;
-
- skip(f, S_LPAR , "("); r = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_sphere_shape(memcheck(create_sphere(r)), surf)) );
- }
- /*...e*/
- /*...sS_QUAD:16:*/
- case S_QUAD:
- {
- double a, b, c, d, e, ff, g, h, i, j;
- SURF *surf;
-
- skip(f, S_LPAR , "("); a = get_value(f);
- skip(f, S_COMMA, ","); b = get_value(f);
- skip(f, S_COMMA, ","); c = get_value(f);
- skip(f, S_COMMA, ","); d = get_value(f);
- skip(f, S_COMMA, ","); e = get_value(f);
- skip(f, S_COMMA, ","); ff = get_value(f);
- skip(f, S_COMMA, ","); g = get_value(f);
- skip(f, S_COMMA, ","); h = get_value(f);
- skip(f, S_COMMA, ","); i = get_value(f);
- skip(f, S_COMMA, ","); j = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_quad(a, b, c, d, e, ff, g, h, i, j)), surf)) );
- }
- /*...e*/
- /*...sS_ELLIPSOID:16:*/
- case S_ELLIPSOID:
- {
- double rx, ry, rz;
- SURF *surf;
-
- skip(f, S_LPAR , "("); rx = get_value(f);
- skip(f, S_COMMA, ","); ry = get_value(f);
- skip(f, S_COMMA, ","); rz = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_ellipsoid(rx, ry, rz)), surf)) );
- }
- /*...e*/
- /*...sS_X_ELL_CYL:16:*/
- case S_X_ELL_CYL:
- {
- double ry, rz;
- SURF *surf;
-
- skip(f, S_LPAR , "("); ry = get_value(f);
- skip(f, S_COMMA, ","); rz = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_x_ell_cyl(ry, rz)), surf)) );
- }
- /*...e*/
- /*...sS_Y_ELL_CYL:16:*/
- case S_Y_ELL_CYL:
- {
- double rx, rz;
- SURF *surf;
-
- skip(f, S_LPAR , "("); rx = get_value(f);
- skip(f, S_COMMA, ","); rz = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_y_ell_cyl(rx, rz)), surf)) );
- }
- /*...e*/
- /*...sS_Z_ELL_CYL:16:*/
- case S_Z_ELL_CYL:
- {
- double rx, ry;
- SURF *surf;
-
- skip(f, S_LPAR , "("); rx = get_value(f);
- skip(f, S_COMMA, ","); ry = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_z_ell_cyl(rx, ry)), surf)) );
- }
- /*...e*/
- /*...sS_X_CYL:16:*/
- case S_X_CYL:
- {
- double r;
- SURF *surf;
-
- skip(f, S_LPAR , "("); r = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_x_cyl(r)), surf)) );
- }
- /*...e*/
- /*...sS_Y_CYL:16:*/
- case S_Y_CYL:
- {
- double r;
- SURF *surf;
-
- skip(f, S_LPAR , "("); r = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_y_cyl(r)), surf)) );
- }
- /*...e*/
- /*...sS_Z_CYL:16:*/
- case S_Z_CYL:
- {
- double r;
- SURF *surf;
-
- skip(f, S_LPAR , "("); r = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_z_cyl(r)), surf)) );
- }
- /*...e*/
- /*...sS_X_ELL_CONE:16:*/
- case S_X_ELL_CONE:
- {
- double ky, kz;
- SURF *surf;
-
- skip(f, S_LPAR , "("); ky = get_value(f);
- skip(f, S_COMMA, ","); kz = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_x_ell_cone(ky, kz)), surf)) );
- }
- /*...e*/
- /*...sS_Y_ELL_CONE:16:*/
- case S_Y_ELL_CONE:
- {
- double kx, kz;
- SURF *surf;
-
- skip(f, S_LPAR , "("); kx = get_value(f);
- skip(f, S_COMMA, ","); kz = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_y_ell_cone(kx, kz)), surf)) );
- }
- /*...e*/
- /*...sS_Z_ELL_CONE:16:*/
- case S_Z_ELL_CONE:
- {
- double kx, ky;
- SURF *surf;
-
- skip(f, S_LPAR , "("); kx = get_value(f);
- skip(f, S_COMMA, ","); ky = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_z_ell_cone(kx, ky)), surf)) );
- }
- /*...e*/
- /*...sS_X_CONE:16:*/
- case S_X_CONE:
- {
- double k;
- SURF *surf;
-
- skip(f, S_LPAR , "("); k = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_x_cone(k)), surf)) );
- }
- /*...e*/
- /*...sS_Y_CONE:16:*/
- case S_Y_CONE:
- {
- double k;
- SURF *surf;
-
- skip(f, S_LPAR , "("); k = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_y_cone(k)), surf)) );
- }
- /*...e*/
- /*...sS_Z_CONE:16:*/
- case S_Z_CONE:
- {
- double k;
- SURF *surf;
-
- skip(f, S_LPAR , "("); k = get_value(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
- return ( memcheck(create_quad_shape(memcheck(create_z_cone(k)), surf)) );
- }
- /*...e*/
- /*...sS_TRANS:16:*/
- case S_TRANS:
- {
- SHAPE *shape;
- VECTOR t;
-
- skip(f, S_LPAR , "("); shape = get_shape(f);
- skip(f, S_COMMA, ","); t = get_vector(f);
- skip(f, S_RPAR , ")");
- trans(shape, t);
- return ( shape );
- }
- /*...e*/
- /*...sS_TRANS_X:16:*/
- case S_TRANS_X:
- {
- SHAPE *shape;
- double t;
-
- skip(f, S_LPAR , "("); shape = get_shape(f);
- skip(f, S_COMMA, ","); t = get_value(f);
- skip(f, S_RPAR , ")");
- trans_x(shape, t);
- return ( shape );
- }
- /*...e*/
- /*...sS_TRANS_Y:16:*/
- case S_TRANS_Y:
- {
- SHAPE *shape;
- double t;
-
- skip(f, S_LPAR , "("); shape = get_shape(f);
- skip(f, S_COMMA, ","); t = get_value(f);
- skip(f, S_RPAR , ")");
- trans_y(shape, t);
- return ( shape );
- }
- /*...e*/
- /*...sS_TRANS_Z:16:*/
- case S_TRANS_Z:
- {
- SHAPE *shape;
- double t;
-
- skip(f, S_LPAR , "("); shape = get_shape(f);
- skip(f, S_COMMA, ","); t = get_value(f);
- skip(f, S_RPAR , ")");
- trans_z(shape, t);
- return ( shape );
- }
- /*...e*/
- /*...sS_SCALE:16:*/
- case S_SCALE:
- {
- SHAPE *shape;
- VECTOR factor;
-
- skip(f, S_LPAR , "("); shape = get_shape(f);
- skip(f, S_COMMA, ","); factor = get_vector(f);
- if ( factor.x == 0.0 || factor.y == 0.0 || factor.z == 0 )
- readerr(f, "at least one component of factor is zero");
- skip(f, S_RPAR , ")");
- if ( !scale(shape, factor) )
- readerr(f, "can't scale shape");
- return ( shape );
- }
- /*...e*/
- /*...sS_SCALE_X:16:*/
- case S_SCALE_X:
- {
- SHAPE *shape;
- double factor;
-
- skip(f, S_LPAR , "("); shape = get_shape(f);
- skip(f, S_COMMA, ","); factor = get_value(f);
- if ( factor == 0.0 )
- readerr(f, "factor is zero");
- skip(f, S_RPAR , ")");
- if ( !scale_x(shape, factor) )
- readerr(f, "can't scale_x shape");
- return ( shape );
- }
- /*...e*/
- /*...sS_SCALE_Y:16:*/
- case S_SCALE_Y:
- {
- SHAPE *shape;
- double factor;
-
- skip(f, S_LPAR , "("); shape = get_shape(f);
- skip(f, S_COMMA, ","); factor = get_value(f);
- if ( factor == 0.0 )
- readerr(f, "factor is zero");
- skip(f, S_RPAR , ")");
- if ( !scale_y(shape, factor) )
- readerr(f, "can't scale_y shape");
- return ( shape );
- }
- /*...e*/
- /*...sS_SCALE_Z:16:*/
- case S_SCALE_Z:
- {
- SHAPE *shape;
- double factor;
-
- skip(f, S_LPAR , "("); shape = get_shape(f);
- skip(f, S_COMMA, ","); factor = get_value(f);
- if ( factor == 0.0 )
- readerr(f, "factor is zero");
- skip(f, S_RPAR , ")");
- if ( !scale_z(shape, factor) )
- readerr(f, "can't scale_z shape");
- return ( shape );
- }
- /*...e*/
- /*...sS_ROTATE_X:16:*/
- case S_ROTATE_X:
- {
- SHAPE *shape;
- double angle;
-
- skip(f, S_LPAR , "("); shape = get_shape(f);
- skip(f, S_COMMA, ","); angle = get_value(f);
- skip(f, S_RPAR , ")");
- rot_x(shape, angle);
- return ( shape );
- }
- /*...e*/
- /*...sS_ROTATE_Y:16:*/
- case S_ROTATE_Y:
- {
- SHAPE *shape;
- double angle;
-
- skip(f, S_LPAR , "("); shape = get_shape(f);
- skip(f, S_COMMA, ","); angle = get_value(f);
- skip(f, S_RPAR , ")");
- rot_y(shape, angle);
- return ( shape );
- }
- /*...e*/
- /*...sS_ROTATE_Z:16:*/
- case S_ROTATE_Z:
- {
- SHAPE *shape;
- double angle;
-
- skip(f, S_LPAR , "("); shape = get_shape(f);
- skip(f, S_COMMA, ","); angle = get_value(f);
- skip(f, S_RPAR , ")");
- rot_z(shape, angle);
- return ( shape );
- }
- /*...e*/
- /*...sS_UNION:16:*/
- case S_UNION:
- {
- SHAPE *shape;
- int sym;
-
- skip(f, S_LPAR, "(");
- shape = get_shape(f);
- while ( (sym = getsym(f)) == S_COMMA )
- shape = memcheck(create_bin_shape(STYPE_UNION, shape, get_shape(f)));
- if ( sym != S_RPAR )
- readerr(f, "expected )");
-
- return ( shape );
- }
- /*...e*/
- /*...sS_ISECT:16:*/
- case S_ISECT:
- {
- SHAPE *shape;
- int sym;
-
- skip(f, S_LPAR, "(");
- shape = get_shape(f);
- while ( (sym = getsym(f)) == S_COMMA )
- shape = memcheck(create_bin_shape(STYPE_ISECT, shape, get_shape(f)));
- if ( sym != S_RPAR )
- readerr(f, "expected )");
-
- return ( shape );
- }
- /*...e*/
- /*...sS_DIFF:16:*/
- case S_DIFF:
- {
- SHAPE *shape;
- int sym;
-
- skip(f, S_LPAR, "(");
- shape = get_shape(f);
- while ( (sym = getsym(f)) == S_COMMA )
- shape = memcheck(create_bin_shape(STYPE_DIFF, shape, get_shape(f)));
- if ( sym != S_RPAR )
- readerr(f, "expected )");
-
- return ( shape );
- }
- /*...e*/
- /*...sS_SDIFF:16:*/
- case S_SDIFF:
- {
- SHAPE *shape;
- int sym;
-
- skip(f, S_LPAR, "(");
- shape = get_shape(f);
- while ( (sym = getsym(f)) == S_COMMA )
- shape = memcheck(create_bin_shape(STYPE_SDIFF, shape, get_shape(f)));
- if ( sym != S_RPAR )
- readerr(f, "expected )");
-
- return ( shape );
- }
- /*...e*/
- /*...sS_EXTENT:16:*/
- case S_EXTENT:
- {
- SHAPE *shape;
- int sym;
-
- skip(f, S_LPAR, "(");
- shape = get_shape(f);
- while ( (sym = getsym(f)) == S_COMMA )
- shape = memcheck(create_bin_shape(STYPE_EXTENT, shape, get_shape(f)));
- if ( sym != S_RPAR )
- readerr(f, "expected )");
-
- return ( shape );
- }
- /*...e*/
- /*...sS_RESURF:16:*/
- case S_RESURF:
- {
- SHAPE *shape;
- SURF *surf;
-
- skip(f, S_LPAR , "("); shape = get_shape(f);
- skip(f, S_COMMA, ","); surf = get_surf(f);
- skip(f, S_RPAR , ")");
-
- if ( !resurf(shape, surf) )
- readerr(f, "unable to resurface shape");
- destroy_surf(surf);
-
- return ( shape );
- }
- /*...e*/
- /*...sS_ID:16:*/
- case S_ID:
- {
- SHAPE *shape = vars [lookup_defined_var_vtype(f, f -> id_name, VTYPE_SHAPE)].u.shape;
-
- return ( memcheck(copy_shape(shape)) );
- }
- /*...e*/
- /*...sdefault:16:*/
- default:
- readerr(f, "expected a shape specification");
- /*...e*/
- }
- return ( NULL ); /* Keep fussy C compiler happy */
- }
- /*...e*/
- /*...sget_set_value:0:*/
- static void get_set_value(F *f)
- {
- char name [30+1];
-
- get_new_id(f, name);
- add_value_var(f, name, get_value(f));
- }
-
- /*...e*/
- /*...sget_set_vector:0:*/
- static void get_set_vector(F *f)
- {
- char name [30+1];
-
- get_new_id(f, name);
- add_vector_var(f, name, get_vector(f));
- }
- /*...e*/
- /*...sget_set_rgb:0:*/
- static void get_set_rgb(F *f)
- {
- char name [30+1];
-
- get_new_id(f, name);
- add_rgb_var(f, name, get_rgb(f));
- }
- /*...e*/
- /*...sget_set_col:0:*/
- static void get_set_col(F *f)
- {
- char name [30+1];
-
- get_new_id(f, name);
- add_col_var(f, name, get_col(f));
- }
- /*...e*/
- /*...sget_set_surf:0:*/
- static void get_set_surf(F *f)
- {
- char name [30+1];
-
- get_new_id(f, name);
- add_surf_var(f, name, get_surf(f));
- }
- /*...e*/
- /*...sget_set_shape:0:*/
- static void get_set_shape(F *f)
- {
- char name [30+1];
-
- get_new_id(f, name);
- add_shape_var(f, name, get_shape(f));
- }
- /*...e*/
- /*...sget_set_background:0:*/
- static void get_set_background(F *f)
- {
- i_background = get_rgb(f);
- }
- /*...e*/
- /*...sget_set_ambient:0:*/
- static void get_set_ambient(F *f)
- {
- i_ambient = get_rgb(f);
- }
- /*...e*/
- /*...sget_set_atten:0:*/
- static void get_set_atten(F *f)
- {
- af1 = get_value(f);
- af2 = get_value(f);
- }
- /*...e*/
- /*...sget_add_light:0:*/
- static void get_add_light(F *f)
- {
- if ( n_lights == N_LIGHTS )
- readerr(f, "maximum of %d lights exceeded", N_LIGHTS);
-
- lights [n_lights ].posn = get_vector(f);
- lights [n_lights++].i = get_rgb(f);
- }
- /*...e*/
- /*...sget_render:0:*/
- static void get_render(F *f)
- {
- SHAPE *shape;
- VECTOR eye, forward, up;
- double hangle, vangle;
- int hpixels, vpixels, depth;
-
- shape = get_shape(f);
- eye = get_vector(f);
- forward = get_vector(f);
- up = get_vector(f);
- hangle = get_value(f);
- vangle = get_value(f);
- hpixels = (int) get_value(f);
- vpixels = (int) get_value(f);
- depth = (int) get_value(f);
-
- if ( getsym(f) != S_STRING )
- readerr(f, "expected output filename");
-
- render(shape, eye, forward, up, hangle, vangle, hpixels, vpixels, depth, f -> str);
-
- destroy_shape(shape);
- }
- /*...e*/
- /*...sget_include:0:*/
- static void get_include(F *f)
- {
- if ( getsym(f) != S_STRING )
- readerr(f, "expected filename");
-
- read_data_file(f -> str);
- }
- /*...e*/
-
- static void get_file(F *f)
- {
- int sym;
-
- while ( (sym = getsym(f)) != S_EOF )
- switch ( sym )
- {
- case S_SET_VALUE: get_set_value(f); break;
- case S_SET_VECTOR: get_set_vector(f); break;
- case S_SET_RGBVEC: get_set_rgb(f); break;
- case S_SET_COL: get_set_col(f); break;
- case S_SET_SURF: get_set_surf(f); break;
- case S_SET_SHAPE: get_set_shape(f); break;
- case S_SET_BKGND: get_set_background(f); break;
- case S_SET_AMBIENT: get_set_ambient(f); break;
- case S_SET_ATTEN: get_set_atten(f); break;
- case S_ADD_LIGHT: get_add_light(f); break;
- case S_RENDER: get_render(f); break;
- case S_INCLUDE: get_include(f); break;
- default: readerr(f, "expected assignment, set_ambient, set_attenuation, add_light, render or include statement");
- }
- }
- /*...e*/
-
- static void read_data_file(char *fn)
- {
- FILE *fp;
- F *f;
-
- if ( (fp = fopen(fn, "r")) == NULL )
- fatal("can't open %s", fn);
-
- f = open_stream(fp, fn);
- get_file(f);
- fp = close_stream(f);
- fclose(fp);
- }
- /*...e*/
-
- int main(int argc, char *argv [])
- {
- if ( argc != 2 )
- exit(1);
-
- #ifdef OS2_V2
- /* Prevent numeric exceptions from terminating this program */
- _control87(EM_UNDERFLOW|EM_DENORMAL, EM_UNDERFLOW|EM_DENORMAL);
- #endif
-
- read_data_file(argv [1]);
-
- return ( 0 );
- }
- /*...e*/
-