Fast algorithms for 3D-graphics (program code)

Embed Size (px)

Citation preview

Glaeser-graphics/CODE/read.c#include "3d_std.h"

void face_defaults();

void help(prog_name) char *prog_name;{ fprintf(Output, "usage %s [ options ]\n", prog_name); fprintf(Output, " or %s [ demo option ]\n", prog_name); fprintf(Output, "\nvalid options are:\ \n\t-s\t\t(silent: log-file %s.log created)\ \n\t-a < name of anim script >\t(read from an animation script)\ \n\t-v < name of video file >\t(write to a video file)\ \n\t-gouraud\t(apply Gouraud shading)\ \n\t-dump\t\t(dump data into a data file)\ \n\t-section\t(intersect objects under certain conditions)\n", prog_name); fprintf(Output, "valid demo options (no data file!) are:\ \n\t%s -splines\t(shows various splines)\ \n\t%s -surfs\t(shows spline surfaces)\ \n\t%s -contour\t(shows contour lines and isophotes)\ \n", prog_name, prog_name, prog_name); safe_exit("\nPlease start again");}

void open_datafile(argc, argv) int argc; char **argv;{ char *full_path; extern Bool Cut; short i;

if (argc < 2) help(argv[0]); Alloc_string(Name_of_logfile, strlen(argv[0]) + 4); strcpy(Name_of_logfile, argv[0]); strcat(Name_of_logfile, ".log"); for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { Alloc_string(Name_of_file, strlen(argv[1])); strcpy(Name_of_file, argv[i]); Input = prep_datafile(argv[i], NULL); } else if (!strcmp(argv[i],"-s")) { /* silent */ if (argc == 2) safe_exit("data file missing"); if (Output == stdout) safe_open(&Output, Name_of_logfile, "w", ""); } else if (!strcmp(argv[i],"-v")) { /* from first picture */ if (++i < argc) { Alloc_string(Name_of_video, strlen(argv[i]) + 4); Name_of_video = argv[i]; Prepare_video = TRUE; Store_image = TRUE; } else safe_exit("-v without a file name"); } else if (!strcmp(argv[i],"-a")) { if (++i < argc) { Alloc_string(Name_of_anim_file, strlen(argv[i])); strcpy(Name_of_anim_file, argv[i]); fprintf(Output, "animfile is %s\n", Name_of_anim_file); Anim_script = TRUE; } else safe_exit("-a without a file name"); } else if (!strcmp(argv[i],"-split")) { Split_up = TRUE; } else if (!strcmp(argv[i],"-dump")) { Dump = TRUE; } else if (!strcmp(argv[i],"-section")) { Cut = TRUE; } else if (!strcmp(argv[i],"-gouraud")) { Smooth_shading = TRUE; } else if (!strcmp(argv[i],"-sun")) { Sun = TRUE; } else if (!strcmp(argv[i], "-contour")) { test_contours_and_sections(); safe_exit("contour testing ready"); } else if (!strcmp(argv[i], "-surfs")){ test_spline_surfaces(atoi(&argv[1][6])); safe_exit("splines surfs ready"); } else if (!strcmp(argv[i], "-splines")){ test_spline(B_SPLINE); safe_exit("spline curves ready"); } else { fprintf(Output, "unknown option %s\n", argv[i]), help(argv[0]); } } /* for */ if (Smooth_shading) init_smooth_shading(); get_pal_size();}

Bool Cut = FALSE;extern short More_memory;

void assign_functions(){ register Polyhedron *obj = Object_pool, *hi_obj; extern void optimize_normals(), fill_normal_pool(), plot_solid(), plot_hollow(), plot_function_graph(), plot_revolution(), plot_helical(), z_buffer_obj();

hi_obj = obj + (1 + Reflections) * Total_objects; for (; obj < hi_obj; obj++) if (obj->type != MATH_SURF) { obj->func->normals = optimize_normals; if (Z_buffer.on) obj->func->plot = z_buffer_obj; else { if (obj->geom_property == CONVEX) obj->func->plot = plot_solid; else if (obj->geom_property == HOLLOW) obj->func->plot = plot_hollow; else if (obj->type == CURVE) ; else safe_exit("no valid geom_prop"); } } else { obj->func->normals = fill_normal_pool; if (obj->subtype == REVOLUTION) obj->func->plot = plot_revolution; else if (obj->subtype == HELICAL) obj->func->plot = plot_helical; else if (obj->subtype == FUNCTION_GRAPH) obj->func->plot = plot_function_graph; else if (obj->subtype == GENERAL_MATH_SURF) obj->func->plot = z_buffer_obj; else safe_exit("no valid subtype of math_surface"); }}

void read_data(argc, argv) short argc; char **argv;{ Vector trans; short i;

open_datafile(argc, argv); read_perspective(argc); read_objects();#ifdef GEOM if (!strcmp(Object_pool->name, "Aufwickeln")) { Polyhedron *o, *hi_o; hi_o = (o = Object_pool) + Total_objects; while (o < hi_o) bend_letter(o++); }#endif allocate_rest_of_pools(); if (Cut) More_memory = 500; if (Anim_script) read_anim_script(); bary_centers(Object_pool); if (Reflections) prepare_mirror(); if (Reflections) bary_centers(Mirror_pool); if (Move_origin && !Anim_script) { Turn_vec(trans, Target); translate_whole_scene(trans); translate_proj(trans, 0); } check_if_eye_is_not_too_close(); if (Cut) More_memory = 500; assign_functions();}

halt(n)short n;{ char c[10];

fprintf(Output, "checkpoint %d (b for break) ",n); scanf("%s", c); if (!strcmp(c, "b")) safe_exit("Abort by user");}

Bool ax_through_origin;Vector ax_dir, ax_point;float rot_angle;

Bool Group_copy;

read_objects(){

allocate_pools(); No_of_groups = -1; Cur_group = group_pool - 1; Hi_object = (Cur_object = Object_pool) + Total_objects; for (; ; Cur_object++) { if (Cur_object >= Hi_object) error_msg(3); alloc_object(Cur_object); read_properties(Cur_object); if (No_more_data) break; if (!Group_copy) { read_lists(Cur_object); if (No_more_data) break; manipulate_object(Cur_object); if (Split_up) check_split(Cur_object); } face_defaults(Cur_object); Cur_object->index = Cur_object - Object_pool; if (end_of_input()) break; }#ifdef FIG_2_7 apply_collineation();#endif Total_objects = Cur_object - Object_pool + 1; Hi_object = Object_pool + Total_objects; print_groups(); fclose(Input);}

#ifdef FIG_2_7apply_collineation(){}#endif

void adapt_face_colors(obj1, obj2) Polyhedron *obj1, *obj2;{ register Face *f1 = obj1->faces[0], *f2 = obj2->faces[0], *hi_f2 = f2 + obj2->no_of_faces;

for (; f2 < hi_f2; f1++, f2++) f1->color = f2->color, f1->phys_property = f2->phys_property;}

void face_defaults(obj) Polyhedron *obj;{ register Face *f = obj->faces[0], *hi_f = f + obj->no_of_faces; register Ubyte default_color = obj->color_index; register Ubyte default_phys_property = obj->phys_property;

for (; f < hi_f; f++) { if (f->color == IMPOSSIBLE_COLOR) f->color = default_color; if (f->phys_property == IMPOSSIBLE_PHYS_PROPERTY) f->phys_property = default_phys_property; }}

read_properties(obj) Polyhedron *obj;{

Group_copy = FALSE; check_group(); if (Group_copy || end_of_input()) return; obj->parent_group_index = No_of_groups; Cur_group->primitives[Cur_group->no_of_primitives++]= obj; if (end_of_input()) return; Alloc_string(obj->name, strlen(Comment)); strcpy((char *)obj->name,Comment); Get_comment(); fprintf (Output,"%s %s ",obj->name, Comment); obj->color_index = color_index(Comment); obj->phys_property = Phys_property; Get_comment(); obj->type = type_index(); if (!Identical_object) { Fprint_comment(); if (obj->type == SPHERE || obj->type == LINE) obj->geom_property = CONVEX; else if (obj->type == POLYGON) obj->geom_property = HOLLOW; else { Get_comment(); Fprint_comment(); if (obj->type!= CURVE) { obj->geom_property = geom_property_index(); } else obj->subtype = curve_subtype(); } }

switch (obj->type) { extern void read_polygon(), read_revolution(), read_translation(), read_cylindrical_surface(), read_line(), read_curve(), read_math_surface(), read_general_convex_polyhedron(), read_stich(); case POLYGON: obj->func->read = read_polygon; break; case POLY_OF_REV: case SPHERE: case OUTER_TORUS: case SMOOTH_BOX: case SMOOTH_CYL: case OVAL: case ELL_CYL: obj->func->read = read_revolution; break; case BOX: case ROUNDED: case POLY_OF_TRANSL: obj->func->read = read_translation; break; case GENERAL_POLY: obj->func->read = read_general_convex_polyhedron; break; case CYLINDER: obj->func->read = read_cylindrical_surface; break; case LINE: obj->func->read = read_line; break; case MATH_SURF: obj->func->read = read_math_surface; break; case CURVE: obj->func->read = read_curve; break; default: fprintf(Output, "type %d not defined\n", obj->type); break; }}

void copy_vec_array(new, old, n) register Vector new[], old[]; short n;{ register Vector *hi_new = new + n;

for (; new < hi_new; new++, old++) Copy_vec(*new, *old);}

read_lists(obj) Polyhedron *obj;{ if (Identical_object && obj->type != PROJECTION) { adapt_all_info_to_new_object(Cur_object,Identical_object); return; } obj->func->read(obj); if (Cut) Cur_edge += 10 * obj->no_of_edges; if (obj->type != CURVE) { if (!Chess_pattern) face_defaults(obj); read_patterns(); check_neighbors(obj); }}

get_trans(v)Vector v;{ Get_comment(); Zero_vec(v); if (!strcmp(Comment, "x")) { /* translation along x - axis expected */ v[X] = read_float(); } else if (!strcmp(Comment, "y")) { /* translation along y - axis expected */ v[Y] = read_float(); } else if (!strcmp(Comment, "z")) { /* translation along z - axis expected */ v[Z] = read_float(); } else { /* full translation vector expected */ v[X] = atof(Comment); v[Y] = read_float(); v[Z] = read_float(); } }

get_euler(angle)float angle[3];{ ax_through_origin = TRUE; Get_comment(); if (!strcmp(Comment, "x")) { /* rotation about x - axis expected */ angle[0] = angle[2] = 0; angle[1] = read_float(); } else if (!strcmp(Comment, "y")) { /* rotation about y - axis expected */ angle[0] = -90; angle[2] = 90; angle[1] = read_float(); } else if (!strcmp(Comment, "z")) { /* rotation about z - axis expected */ angle[0] = angle[1] = 0; angle[2] = read_float(); } else if (!strcmp(Comment, "euler")) { /* euler rotation expected */ angle[0] = read_float(); angle[1] = read_float(); angle[2] = read_float(); } else if (is_keyword(61)) { /* axpoint */ ax_through_origin = FALSE; Fread_vec(ax_point); Get_comment(); must_be_keyword(62); /* axdirection */ Get_comment(); Zero_vec(angle); if (!strcmp(Comment, "x")) { Get_comment(); must_be_keyword(49); /* angle */ angle[1] = read_float(); } else if (!strcmp(Comment, "y")) { Get_comment(); must_be_keyword(49); /* angle */ angle[0] = -90; angle[2] = 90; angle[1] = read_float(); } else if (!strcmp(Comment, "z")) { Get_comment(); must_be_keyword(49); /* angle */ angle[2] = read_float(); } else { ax_dir[X] = atof(Comment); ax_dir[Y] = read_float(); ax_dir[Z] = read_float(); Get_comment(); must_be_keyword(49); /* angle */ rot_angle = read_float(); } }}

short curve_subtype(){ if (is_keyword(113)) return AKIMA_SPLINE; else if (is_keyword(114)) return CUBIC_SPLINE; else if (is_keyword(115)) return B_SPLINE; else safe_exit("unknown type of spline");}

short type_index(){ register Polyhedron *obj = Object_pool;

Identical_object = NULL; if (is_keyword(112)) { Cur_object->receives_shadow = FALSE; Get_comment(); } else Cur_object->receives_shadow = TRUE; if (is_keyword(10)) return POLY_OF_REV; if (is_keyword(7)) return POLY_OF_TRANSL; if (is_keyword(89)) return ELL_CYL; if (is_keyword(104)) return OVAL; if (is_keyword(105)) return ROUNDED; if (is_keyword(107)) return OUTER_TORUS; if (is_keyword(108)) return SMOOTH_BOX; if (is_keyword(109)) return SMOOTH_CYL; if (is_keyword(9)) return BOX; if (is_keyword(11)) return GENERAL_POLY; if (is_keyword(12)) return MATH_SURF; if (is_keyword(25)) return CURVE; if (is_keyword(19)) return CYLINDER; if (is_keyword(26)) return SPHERE; if (is_keyword(85)) { Identical_object = Cur_object; return PROJECTION;} if (is_keyword(36)) { Cur_object->subtype = POLYGON; return POLYGON; } if (is_keyword(65)) { Cur_object->subtype = RECTANGLE; return POLYGON; } if (is_keyword(66)) { Cur_object->subtype = SQUARE; return POLYGON; } if (is_keyword(35)) { Cur_object->subtype = LINE; return LINE; } /* return POT_PLANT; return TREE; */

/* It is still possible that the type of the object is given indirectly by the name of a previous object */

if (is_keyword(24)) { /* like */ Get_comment(); for (; obj < Cur_object; obj++) if (!strcmp(Comment,obj->name)) { Identical_object = obj; return PREVIOUS_OBJECT; } } error_msg(20);}

short geom_property_index(){ if (is_keyword(39)) return CONVEX; if (is_keyword(40)) return HOLLOW; if (is_keyword(41)) return CONCAVE; error_msg(21);}

short phys_property_index(){ if (is_keyword(90)) { Get_comment(); return NORMAL; } if (is_keyword(91)) { Get_comment(); return SHINY; } if (is_keyword(92)) { Get_comment(); return REFLECTING; } if (is_keyword(93)) { Get_comment(); return MAT; } return NORMAL; /* default */}

Glaeser-graphics/DATA/read.meMany of the data files in this directory have been createdbefore writing the book "Fast Algorithms for 3D-Graphics".At that time, the pseudo language to describe spatial objectswas mainly German. Thus, you will find a lot of German wordsin the files which will not tell you anything. Please excuse this fact.

To get into the writing of data files, please have a look atthe file `demo.1' and try to modify it.

After that, have a look at `demo.2'. This file shows how youcan work with `include files'.

Glaeser-graphics/CODE/3d_std.h#include #include #include "Types.h"#include "Macros.h"#include "G_macros.h" #include "Proto.h"#include "Globals.h"

Glaeser-graphics/CODE/G_macros.h/* System dependent macros for Silicon Graphics Workstations (SG35 with power graphics, Indigo2 */

#define IRIS#define SLASH '/'

#include "gl.h"#include "device.h"#include "get.h"

/* window on the screen */#define XMIN 0 #define XMAX 1280#define YMIN 0#define YMAX 1024

/* Now some system-dependent constants. */

#define PALETTE_SIZE (2*32) #define RGB_RANGE 256#define MAX_COLORS (2*256)#define COLOR_OFFSET 256

#define UPKEY (unsigned short) UPARROWKEY#define DOWNKEY (unsigned short) DOWNARROWKEY#define LEFTKEY (unsigned short) LEFTARROWKEY#define RIGHTKEY (unsigned short) RIGHTARROWKEY#define CENTERKEY (unsigned short) 65450

#define Esc_pressed() (getbutton(LEFTALTKEY) && getbutton(QKEY))

/* And now graphics macros... */

#define G_open_graphics() iris_open_graphics()#define G_close_graphics() gexit()#define G_set_RGB(n, R, G, B) mapcolor((Colorindex) n,\ (short) R, (short) G,(short) B)#define G_linewidth(n) (void) linewidth((short) n)#define G_set_color(a) color((Colorindex) a)/*#define G_set_pixel(x, y) rectfs((short) x, (short) y,\ (short) x+1, (short) y+1) */#define G_set_pixel(x, y) iris_set_pixel((float) x, (float) y)#define G_move(v) move2((v)[0], (v)[1])#define G_draw(v) draw2((v)[0], (v)[1])#define G_move_int(x, y) move2s((short) x, (short) y)#define G_draw_int(x, y) draw2s((short) x, (short) y)#define G_area_move(v) pmv2((v)[0], (v)[1])#define G_area_draw(v) pdr2((v)[0], (v)[1])#define G_area_close() pclos()#define G_set_hue(h) setshade((Colorindex) (h))#define G_close_smooth_poly() spclos()#define G_fill_short_poly(n, poly) polf2s(n, poly) #define G_area_move_int(x, y) pmv2s((short) x, (short) y)#define G_area_draw_int(x, y) pdr2s((short) x, (short) y)

#define G_clear_screen(col)\ (Line_graphics ? \ color(BLACK) : color(col)), clear()#define G_close_line()#define G_ratio() (float) 1.0#define G_rect_filled(x1, y1, x2, y2)\ rectf((float) x1, (float) y1, (float) x2, (float) y2)#define G_window_width() iris_xwidth() #define G_window_height() iris_ywidth() #define G_key_pressed() (Ushort) iris_keypressed() #define G_available_colors() 4096#define G_xor_line(p, q) xor_line(p, q)#define G_xor_mode_possible() TRUE#define G_arrows_possible() TRUE#define G_clipping() FALSE#define G_beep() ringbell()#define G_swap_screens() swapbuffers()#define G_draw_on_backscreen() frontbuffer(FALSE), backbuffer(TRUE)#define G_draw_on_frontscreen() frontbuffer(TRUE), backbuffer(FALSE)#define G_explain_keyboard() iris_explain_keyboard()

char *malloc(), *realloc();

#define Malloc(no_of_bytes) malloc(no_of_bytes)#define Ralloc(ptr, no_of_bytes) realloc(ptr, no_of_bytes)#define Free_array(ptr,str) free_mem(ptr, str)#define Free(ptr) free((char *) ptr)

#define ftoa(fl,st,a,b) sprintf(st,"%.3f",fl)

#define READ_BINARY "r"#define WRITE_BINARY "w"/*#define HARDWARE_DEPTHCUING

#define G_depthcuing(on_off)\ IRIS_depthcuing(on_off)

#define G_depths_for_depthcuing(min_z, max_z)\ switch_to_3d_hardware(min_z, max_z)

#define G_colors_for_depthcuing(min_color, max_color)\ shaderange((Colorindex) min_color, (Colorindex) max_color, -1, 1),\ setdepth(0, 0xfff)

#define IRIS_Z(v) (v)[Z] #define G_move3(v)\ move((Coord) (v)[X], (Coord) (v)[Y], (Coord) IRIS_Z(v))#define G_draw3(v)\ draw((v)[X], (v)[Y], IRIS_Z(v))*/#define G_move3d(v) move((v)[X], (v)[Y], (v)[Z])#define G_draw3d(v) draw((v)[X], (v)[Y], (v)[Z])

#define G_area_move3d(v) pmv((v)[X], (v)[Y], (v)[Z])#define G_area_draw3d(v) pdr((v)[X], (v)[Y], (v)[Z])

Glaeser-graphics/SYSTDEPS/G_macros.h/* System dependent macros for Silicon Graphics Workstations (SG35 with power graphics, Indigo2 */

#define IRIS#define SLASH '/'

#include "gl.h"#include "device.h"#include "get.h"

/* window on the screen */#define XMIN 0 #define XMAX 1280#define YMIN 0#define YMAX 1024

/* Now some system-dependent constants. */

#define PALETTE_SIZE (2*32) #define RGB_RANGE 256#define MAX_COLORS (2*256)#define COLOR_OFFSET 256

#define UPKEY (unsigned short) UPARROWKEY#define DOWNKEY (unsigned short) DOWNARROWKEY#define LEFTKEY (unsigned short) LEFTARROWKEY#define RIGHTKEY (unsigned short) RIGHTARROWKEY#define CENTERKEY (unsigned short) 65450

#define Esc_pressed() (getbutton(LEFTALTKEY) && getbutton(QKEY))

/* And now graphics macros... */

#define G_open_graphics() iris_open_graphics()#define G_close_graphics() gexit()#define G_set_RGB(n, R, G, B) mapcolor((Colorindex) n,\ (short) R, (short) G,(short) B)#define G_linewidth(n) (void) linewidth((short) n)#define G_set_color(a) color((Colorindex) a)/*#define G_set_pixel(x, y) rectfs((short) x, (short) y,\ (short) x+1, (short) y+1) */#define G_set_pixel(x, y) iris_set_pixel((float) x, (float) y)#define G_move(v) move2((v)[0], (v)[1])#define G_draw(v) draw2((v)[0], (v)[1])#define G_move_int(x, y) move2s((short) x, (short) y)#define G_draw_int(x, y) draw2s((short) x, (short) y)#define G_area_move(v) pmv2((v)[0], (v)[1])#define G_area_draw(v) pdr2((v)[0], (v)[1])#define G_area_close() pclos()#define G_set_hue(h) setshade((Colorindex) (h))#define G_close_smooth_poly() spclos()#define G_fill_short_poly(n, poly) polf2s(n, poly) #define G_area_move_int(x, y) pmv2s((short) x, (short) y)#define G_area_draw_int(x, y) pdr2s((short) x, (short) y)

#define G_clear_screen(col)\ (Line_graphics ? \ color(BLACK) : color(col)), clear()#define G_close_line()#define G_ratio() (float) 1.0#define G_rect_filled(x1, y1, x2, y2)\ rectf((float) x1, (float) y1, (float) x2, (float) y2)#define G_window_width() iris_xwidth() #define G_window_height() iris_ywidth() #define G_key_pressed() (Ushort) iris_keypressed() #define G_available_colors() 4096#define G_xor_line(p, q) xor_line(p, q)#define G_xor_mode_possible() TRUE#define G_arrows_possible() TRUE#define G_clipping() FALSE#define G_beep() ringbell()#define G_swap_screens() swapbuffers()#define G_draw_on_backscreen() frontbuffer(FALSE), backbuffer(TRUE)#define G_draw_on_frontscreen() frontbuffer(TRUE), backbuffer(FALSE)#define G_explain_keyboard() iris_explain_keyboard()

char *malloc(), *realloc();

#define Malloc(no_of_bytes) malloc(no_of_bytes)#define Ralloc(ptr, no_of_bytes) realloc(ptr, no_of_bytes)#define Free_array(ptr,str) free_mem(ptr, str)#define Free(ptr) free((char *) ptr)

#define ftoa(fl,st,a,b) sprintf(st,"%.3f",fl)

#define READ_BINARY "r"#define WRITE_BINARY "w"/*#define HARDWARE_DEPTHCUING

#define G_depthcuing(on_off)\ IRIS_depthcuing(on_off)

#define G_depths_for_depthcuing(min_z, max_z)\ switch_to_3d_hardware(min_z, max_z)

#define G_colors_for_depthcuing(min_color, max_color)\ shaderange((Colorindex) min_color, (Colorindex) max_color, -1, 1),\ setdepth(0, 0xfff)

#define IRIS_Z(v) (v)[Z] #define G_move3(v)\ move((Coord) (v)[X], (Coord) (v)[Y], (Coord) IRIS_Z(v))#define G_draw3(v)\ draw((v)[X], (v)[Y], IRIS_Z(v))*/#define G_move3d(v) move((v)[X], (v)[Y], (v)[Z])#define G_draw3d(v) draw((v)[X], (v)[Y], (v)[Z])

#define G_area_move3d(v) pmv((v)[X], (v)[Y], (v)[Z])#define G_area_draw3d(v) pdr((v)[X], (v)[Y], (v)[Z])

Glaeser-graphics/CODE/Globals.h#ifdef MAIN Global Buffer Z_buffer = { NULL, 0, 0, 65000, FALSE }; Global Vector Target = { 0, 0, 0 }; Global Vector Null_vec = { 0, 0, 0 }; Global Palette Parent_palette[] = { 0, TRUE , 0,0,"gray", "grau", 0.05, 0.05, 0.05, 1.00, 1.00, 1.00, 1, TRUE , 0,0,"green", "gruen", 0.00, 0.30, 0.00, 0.80, 1.00, 0.80, 2, TRUE , 0,0,"yellow", "gelb", 0.50, 0.30, 0.00, 1.00, 1.00, 0.50, 3, FALSE, 0,0,"blue", "blau", 0.00, 0.25, 0.45, 0.70, 0.70, 1.00, 4, FALSE, 0,0,"pink", "rosa", 0.50, 0.00, 0.25, 1.00, 0.85, 0.80, 5, FALSE, 0,0,"cyan", "tuerkis", 0.00, 0.25, 0.25, 0.50, 1.00, 1.00, 6, FALSE, 0,0,"magenta", "violett", 0.20, 0.20, 0.20, 1.00, 0.50, 1.00, 7, FALSE ,0,0,"orange", "orange", 0.50, 0.15, 0.00, 1.00, 0.60, 0.40, 8, FALSE, 0,0,"brickcolor", "ziegel",0.35, 0.05, 0.05, 1.00, 0.75, 0.75, 9, FALSE, 0,0,"brownish","gelbbraun",0.30, 0.17, 0.00, 0.70, 0.70, 0.35, 10, FALSE, 0,0,"red", "rot", 0.60, 0.00, 0.00, 1.00, 0.70, 0.70, 11, FALSE, 0,0,"glass", "glas ", 0.05, 0.25, 0.45, 0.85, 0.85, 1.00, 12, FALSE, 0,0,"whitegray","weissgrau",0.35, 0.35, 0.35, 0.95, 0.95, 0.95, 13, FALSE, 0,0,"greenblue","gruenblau",0.00, 0.40, 0.33, 0.12, 1.00, 0.78, 14, FALSE, 0,0,"brown","braun", 0.20, 0.15, 0.05, 1.0, 0.70, 0.70, 15, FALSE, 0,0,"Xxxxx","Xxxxx", 0.05, 0.25, 0.45, 0.85, 0.85, 1.00 }; Global PostScript_file PScript = { "image.eps", /* Name of file. */ NULL, /* File not opened yet. */ /* Init function pointers: */ initPostScript, closePostScript, transform_to_PostScript, write_PostScript_macros, pscript_line, pscript_fill_poly, pscript_outline_poly };#else Global Buffer Z_buffer; Global Vector Target; Global Vector Null_vec; Global Palette Parent_palette[15]; Global PostScript_file PScript;#endifGlobal double Azim[MAX_SYSTS], Elev[MAX_SYSTS], Init(Twist, 0), Init(Fovy, PI/6);Global Bool Init(Prepare_video, FALSE), Init(Store_image, FALSE), Quicksort, Init(Options, FALSE), Init(Showmap, FALSE), Init(Depth_cueing, TRUE), Init(save_frontscreen, FALSE), Init(Special_view, FALSE), Init(Intersections, FALSE), Init(Auto_rot, TRUE), Init(hardcopy, FALSE), Init(Show_axes, FALSE), Init(Show_boxes, FALSE), Init(Show_normals, FALSE), Init(Show_groups, FALSE), Init(All_in_shadow, FALSE), Init(Revolution, FALSE), Init(Heliocentric, TRUE), Init(Show_silhouette, FALSE), Init(Silhouette, FALSE), Init(New_eye, TRUE), Init(New_light, TRUE), Init(Xor_mode, FALSE), Init(Anim_script, FALSE), Init(Move_origin, FALSE), Init(Split_up, FALSE), Init(Reflections, FALSE), Init(Clip_with_mirror, FALSE), Init(Perforation, 0), Init(Chess_pattern, FALSE), Init(Face_consts_done, FALSE), Init(Clip_on, G_clipping()), *Outside_mirror, Init(Sort_mirror, FALSE), Init(No_more_data, FALSE), Init(Action, FALSE), Init(Dump, FALSE), Init(Replay_only, FALSE), Is_a_shadow_poly, Painting, Xy_clip, Init(Z_clip, TRUE), Save_color_ranges, Quick_redraw, Calc_shade_ranges, Init(Fast_hidden_lines, FALSE), Init(bug_is_possible, FALSE), Init(Window_opened, FALSE), Init(Smooth_shading, FALSE), Init(Read_comment, TRUE), Init(Sun, FALSE), Init(Mirror_integrated, FALSE), Init(Hard_zbuffer, FALSE), Backface_test, Init(Line_graphics, TRUE); Global Ushort Init(*Hue_of_vertex, NULL), Palette_size, Shift_color;Global float Init(Delta_azim, -(PI/180)), Init(Delta_elev, 0), Init(Delta_twist, 0), Init(Delta_dist, 0.999), Dist[MAX_SYSTS], Min_dist, Max_dist, Init(Enlarge_world, 1.0), Dist_light, Pixel_ratio, X_mid, Y_mid, Init(X_lookat, 0.0), Init(Y_lookat, 0.0), Scale_factor, Min_scale_factor, Max_scale_factor, Inclination_angle, Z_CLIP[MAX_SYSTS], Z0[MAX_SYSTS], Full_width[MAX_SYSTS], Half_width[MAX_SYSTS], Shadow_intensity[MAX_SYSTS], Total_depth, Min_depth, Max_depth, Total_diameter, Max_min_xyz[6];#define MAX_VERTICES 8000Global long Init(Total_vertices, MAX_VERTICES), /* We start with this value because we do not want to allocate too much RAM. If we need more space, we can allocate it in the data file. */ Init(Total_edges, 0), Init(Total_faces, 0), Total_sections; Global short Cur_poly_color, Bgr_color, Init(Bgr_palette, 0), Init(Color_of_base_plane, -1), Init(Draw_mode, WIRE_FRAME), Init(Prev_draw_mode, WIRE_FRAME), Init(Screen_mode, 0), /* AMIGA - specific */ **Map_color, Cur_palette, Brightness_of_face, *Order, *Last_order, *Last_mirror_order, *order_of_group, Init(Curve_type, 0), *Script_drawmode, *Script_option, Init(Total_objects, 50), Init(No_of_mirrors, 0), Init(No_of_lights, 0), Init(Total_systems, 1), Active_systems, No_of_section_planes, No_of_curves, Used_palettes, Possible_palettes, Init(Frame, 0), Init(Hi_frame, 15000), Init(Total_groups, 0), No_of_groups, Window_width, Window_height;Global Vector Proj_center[MAX_SYSTS], pseudo_proj_center, mirror_normal, *Script_eye, *Script_light[MAX_LIGHTS], *Script_other, *Script_target, Init(*Coord_pool, NULL), *Screen_pool, *Light_pool[MAX_SYSTS], *Normal_pool, **Edge_pool, **Contour_pool, **Hi_contour, Init(*Cur_vec, NULL), **Cur_edge, *Cur_edge_in_mirror, *Hi_edge_in_mirror;Global Vector2 *Poly_pool, *Poly1_, *Poly2_, *Poly3_, *Poly4_, Drawing_window[4];Global Polyhedron *Object_pool, *Cur_object, *Hi_object, *Identical_object, *Mirror_pool, *Hi_mirror;Global char Comment[260], *Name_of_file, *Name_of_logfile, Init(*Name_of_video, NULL), Init(*Name_of_picture, NULL), Init(*Name_of_colormap, NULL), *Coded_formula, Init(*Name_of_anim_file, NULL);Global FILE Init(*Output, stdout);Global FILE *Input, *Video_file, *Video_file2, Init(*datafile, NULL), *List;Global Face *Cur_face, *Hi_face;Global Halfspace *Sep_pool;Global Slice *Cur_slice, *Hi_slice;Global Ring *Cur_ring, *Hi_ring;#ifdef MAIN Global Complex I = { 0, 1 }, One = { 1, 0 }, Zero = { 0, 0 };#else Global Complex I, One, Zero;#endif

Global Obj_group *group_pool, *Cur_group, *Hi_group;Global Ubyte Cur_hue, *Color_pool, Init(Phys_property, NORMAL);Global Rot_matrix Rot[MAX_SYSTS], InvRot[MAX_SYSTS];Global short Min_x, Min_y, Max_x, Max_y;Global float Min_z, Max_z;Global float Clip_vol[6];Global float Near, Far;Global Bool Init(Is_a_reflection, FALSE);

#define SCREEN_SYST 0#define LIGHT_SYST1 1#define SAME_SYST -1

#define ONLY_NEIGHBORS 1#define OWN_FACES_AND_NEIGHBORS 2#define NEIGHBORS_AND_RESIDUAL_PATTERNS 3

#define DISJOINT 0#define INTERSECTION 1#define POLY1_INSIDE_POLY2 2 #define POLY2_INSIDE_POLY1 3

#define MAX_8_BIT 0xff #define END_MOVIE MAX_8_BIT #define NEW_FRAME (MAX_8_BIT - 1) #define IMPOSSIBLE_COLOR 126 #define NO_COLOR 127#define IMPOSSIBLE_PHYS_PROPERTY IMPOSSIBLE_COLOR

#define MAX_HUE MAX_8_BIT #define BGR_LIGHT (MAX_8_BIT / 7)

Global float Init(Ambient, BGR_LIGHT);

#define MAX_POLY_SIZE 400

Glaeser-graphics/CODE/Macros.h#ifdef TRUE# undef TRUE#endif#ifdef FALSE# undef FALSE#endif#define TRUE (Bool) 1#define FALSE (Bool) 0

#define X 0 #define Y 1#define Z 2

#define PI 3.141592654#define EPS 1e-7#define INFINITE 1e20

#define MAX_LIGHTS 4 #define MAX_SYSTS (MAX_LIGHTS + 1)

/* Some useful comparisons */#define Minimum(x, y) ( (x) < (y) ? (x) : (y) ) #define Maximum(x, y) ( (x) > (y) ? (x) : (y) )#define Sign(x) ( (x) < 0 ? (-1) : (1) )

/* Some macro functions for (2d and 3d) vectors. */

#define Print(str) fprintf(Output,"%s\n",str)#define Print_vec(a) fprintf(Output,"%.2f,%.2f,%.2f\n",(a)[X], (a)[Y],(a)[Z])#define Print_vec2(a) fprintf(Output,"%.2f,%.2f\n",(a)[X],(a)[Y])#define Fread_vec(v) fscanf(Input,"%f%f%f",&((v)[X]),&((v)[Y]),&((v)[Z]))#define Fread_vec2(v) fscanf(Input,"%f%f",&((v)[X]),&((v)[Y]))#define Get_comment() fscanf(Input, "%s", Comment)#define Fprint_comment() fprintf(Output, "%s ", Comment)#define Copy_vec(a,b) (a)[X]=(b)[X], (a)[Y]=(b)[Y],(a)[Z]=(b)[Z]#define Copy_vec2(a,b) (a)[X]=(b)[X], (a)[Y]=(b)[Y]#define Round_vec(a, b)\ (a)[X] = (b)[X] + 0.5, (a)[Y] = (b)[Y] + 0.5, (a)[Z] = (b)[Z] + 0.5#define Stretch_vec(new,v,k)\ (new)[X]=k*(v)[X],(new)[Y]=k*(v)[Y],(new)[Z]=k*(v)[Z]#define Stretch_vec2(new,v,k) (new)[X]=k*(v)[X],(new)[Y]=k*(v)[Y]#define Point_on_line(result, p, q, lambda)\ ((result)[X] = (p)[X] + lambda * ((q)[X] - (p)[X]),\ (result)[Y] = (p)[Y] + lambda * ((q)[Y] - (p)[Y]),\ (result)[Z] = (p)[Z] + lambda * ((q)[Z] - (p)[Z]))#define Linear_comb(result, p, pq, lambda)\ ((result)[X] = (p)[X] + lambda * (pq)[X],\ (result)[Y] = (p)[Y] + lambda * (pq)[Y],\ (result)[Z] = (p)[Z] + lambda * (pq)[Z])#define Linear_comb2(result, p, pq, lambda)\ ((result)[X] = (p)[X] + lambda * (pq)[X],\ (result)[Y] = (p)[Y] + lambda * (pq)[Y])#define Scale_vec(new, v, k)\ (new)[X]=k*(v)[X],(new)[Y]=k*(v)[Y],(new)[Z]=k*(v)[Z]#define Scale_vec2(new, v, k) (new)[X]=k*(v)[X],(new)[Y]=k*(v)[Y]#define Swap(a, b) (temp = a, a = b, b = temp )#define Subt_vec(AB, a, b) \ ((AB)[X] = (b)[X] - (a)[X],\ (AB)[Y] = (b)[Y] - (a)[Y],\ (AB)[Z] = (b)[Z] - (a)[Z])#define Subt_vec2(ab, a, b)\ ((ab)[X] = (b)[X] - (a)[X],\ (ab)[Y] = (b)[Y] - (a)[Y])#define Add_vec(result, a, b)\ ((result)[X] = (a)[X] + (b)[X],\ (result)[Y] = (a)[Y] + (b)[Y],\ (result)[Z] = (a)[Z] + (b)[Z])#define Add_vec2(result, a, b)\ ((result)[X] = (a)[X] + (b)[X],\ (result)[Y] = (a)[Y] + (b)[Y]) #define Middle_point(m,a,b) (m)[X] = ((a)[X]+(b)[X])/2,\ (m)[Y] = ((a)[Y]+(b)[Y])/2, (m)[Z] = ((a)[Z]+(b)[Z])/2#define Turn_vec(t, v) (t)[X] = -(v)[X], (t)[Y] = -(v)[Y], (t)[Z] = -(v)[Z]#define Turn_vec2(t, v) (t)[X] = -(v)[X], (t)[Y] = -(v)[Y]#define Square(v) ((v)[X]*(v)[X]+(v)[Y]*(v)[Y]+(v)[Z]*(v)[Z])#define Sqr(x) (x)*(x)#define Length(v) sqrt((double) Dot_product(v, v))#define Square2(v) ((v)[X]*(v)[X]+(v)[Y]*(v)[Y])#define Length2(v) sqrt((double) Square2(v))#define Dot_product(a, b)\ ((a)[X] * (b)[X] + (a)[Y] * (b)[Y] + (a)[Z] * (b)[Z])#define Dot_product2(a, b) ((a)[X] * (b)[X] + (a)[Y] * (b)[Y])#define Cross_product(n, a, b)\ ((n)[X] = (a)[Y] * (b)[Z] - (a)[Z] * (b)[Y],\ (n)[Y] = (a)[Z] * (b)[X] - (a)[X] * (b)[Z],\ (n)[Z] = (a)[X] * (b)[Y] - (a)[Y] * (b)[X])#define Cross_product2(a, b) ((a)[X] * (b)[Y] - (a)[Y] * (b)[X])#define Normal_vec2(n,v) ((n)[X] = -(v)[Y], (n)[Y] = (v)[X])#define Zero_vec(v) (v)[X] = (v)[Y] = (v)[Z] = 0#define Init_vec(v, vx, vy, vz) (v)[X] = vx, (v)[Y] = vy, (v)[Z] = vz#define Area(a,b,c)\ ((a)[X]*(b)[Y]-(a)[Y]*(b)[X]\ +(b)[X]*(c)[Y]-(b)[Y]*(c)[X]\ +(c)[X]*(a)[Y]-(c)[Y]*(a)[X])

#define Vec_dot_matrix(c, a, b)\ (c)[X] = (a)[X] * *(b) + (a)[Y] * *(b+3) + (a)[Z] * *(b+6),\ (c)[Y] = (a)[X] * *(b+1) + (a)[Y] * *(b+4) + (a)[Z] * *(b+7),\ (c)[Z] = (a)[X] * *(b+2) + (a)[Y] * *(b+5) + (a)[Z] * *(b+8)

#define Rotate_and_project(proj, wld)\ (Vec_dot_matrix(*proj, *wld, rot),\ lambda = Scale_factor / (*Dist - (*proj)[Z]),\ (*proj)[X] = X_mid + lambda * (*proj)[X],\ (*proj)[Y] = Y_mid + Pixel_ratio * lambda * (*proj)[Y])

#define Rotate_and_illuminate(shadow, wld, n)\ Vec_dot_matrix(*shadow, *wld, rot),\ lambda = Dist[n] / (Dist[n] - (*shadow)[Z]),\ (*shadow)[X] *= lambda, (*shadow)[Y] *= lambda

#define Screen_to_world(v) (Coord_pool + (v - Screen_pool))#define Light_to_world(v, n) (Coord_pool + (v - Light_pool[n]))#define Screen_to_light(v, n) (Light_pool[n] + (v - Screen_pool))#define Screen_coords(v) (Screen_pool + (v-Coord_pool))#define Light_coords(v, n) (Light_pool[n] + (v-Coord_pool))#define Corresponding_coords(v, n) (Light_pool[n] + (v-Coord_pool))#define Corr_coords(ptr, syst) \ ((syst < 0) ? (ptr) : (Corresponding_coords(ptr, syst)))

#define Next_div_by_4(y, x) (y = 4 * ((x + 3) / 4))

#define Set_map_color(palette, hue)\ Cur_hue = hue,\ Cur_poly_color = Map_color[palette][Scale_hue(hue)],\ G_set_color(Cur_poly_color)

/* Dynamical arrays */

#define Alloc_array(type, array, n, string)\ array = (type *) alloc_mem((long) (n), (long) sizeof(type), string)

#define Alloc_ptr_array(type, array, n, string)\ array = (type **) alloc_mem((long) (n), (long) sizeof(type *), string)

#define Alloc_2d_array(type, array, n, m) {\ int i;\ Alloc_ptr_array(type, array, (long) n, "A");\ array[0] = (type *) alloc_mem((long) n, (long) (m) * sizeof(type), "A[0]");\ for (i = 1; i < n; i++)\ array[i] = array[i-1] + m;\}

#define Alloc_huge_2d_array(type, array, n, m) {\ Alloc_ptr_array(type, array, (long) n, "A");\ for (i = 0; i < n; i++) \ array[i] = (type *) alloc_mem((long) m, (long) sizeof(type), "A[0]");\}

#define Alloc_2d_ptr_array(type, array, n, m) {\ array = (type ***) alloc_mem((long) n, (long) sizeof(type **), "P");\ array[0] = (type **) alloc_mem((long) n, (long) m * sizeof(type *),"P[0]");\ for (i = 1; i < n; i++)\ array[i] = array[i-1] + m;\}

#define Free_2d_array(array) Free_array(array[0], "2d"), Free_array(array, "2d")

#define Free_huge_2d_array(array, n) {\ for (i = 0; i < n; i++)\ Free_array(array[i], "2d");\ Free_array(array, "2d");\}

#define Alloc_3d_array(type, array, n1, n2, n3) {\ array = (type ***) alloc_mem((long) (n1), (long) sizeof(type **), "A");\ for (i = 0; i < n1; i++) {\ array[i] = (type **) alloc_mem((long)(n2), (long) sizeof(type *), "B");\ for (j = 0; j < n2; j++) {\ array[i][j]= (type *) alloc_mem((long)(n3), (long) sizeof(type), "C");\ }\ }\}

#define VOID void

#define Alloc_string(array, n)\ Alloc_array(char, array, (n + 1), "string")

#define Is_zero(x) (fabs(x) < EPS)

#define Ident2(a, b) \ (Is_zero((a)[X]-(b)[X]) && Is_zero((a)[Y]-(b)[Y]))

#define Min_max(min, max, x)\ if ((x) < (min)) (min) = (x);\ else if ((x) > (max)) (max) = (x);

#define Min_max_vec(min_v, max_v, v) {\ Min_max((min_v)[X], (max_v)[X], (v)[X]);\ Min_max((min_v)[Y], (max_v)[Y], (v)[Y]);\ Min_max((min_v)[Z], (max_v)[Z], (v)[Z]);\}

#define Is_convex(obj)\ ((obj->geom_property == CONVEX) ? TRUE : FALSE)

#define Backface(f)\ (f->dark_face[SCREEN_SYST])

#define Is_dark(f, syst)\ (f->dark_face[(short) syst])

#define Hue(f)\ (f->color_range[SCREEN_SYST])

#define Shadow_color_range(f, syst)\ (f->color_range[syst])

#define Color_of_mult_shadow(f, degree)\ (f->others[degree])

#define refl_edge_pool Light_pool[1]

#define Is_a_reflected_object(obj)\ (obj >= Mirror_pool && obj < Mirror_pool + Total_objects)

#define Which_side(point, plane)\ Sign(Dot_product((plane).normal, (point)) - (plane).cnst)

#define Check_escape() {\ if (Esc_pressed()) error_msg(1000);\}#define ESCAPE (unsigned char) 27#define Scale_hue(h) ((h) >> Shift_color)#define TWIST 0 #define ENLARGE 1 #define FOVY 2 #define NOT_CLOSED FALSE#define ALREADY_CLOSED TRUE#define mem_alloc(n, m, s) alloc_mem((long) n, (long) m, s)#define BACKGROUND() G_set_color(Bgr_color)#define T2(w, z) ((w) = (z) / (Dist[0] - (z)))#define UndoT2(z, w) ((z) = (w) * Dist[0] / (1 + (w)))

/* Finally some defines, which have mainly historical reasons... */#define SILVIO#define MILLING_CUTTER#define GEOM#define MATHSURFS#define SHOW_BUFFER_

/* Finally some useful macros for calculations with complex numbers. */

#define Join(C,a,b) C.re = a, C.im = b /* C = a+ib */#define Split(C,a,b) a = C.re, b = C.im#define Conj(A,C) C.re = A.re, C.im = -A.im /* C = conj(A) */#define Abs(C) sqrt(C.re*C.re+C.im*C.im) /* length */#define CSquare(A) Mult(A, A)#define Sqrt(A) Pow(A, 0.5)#define RealMult(A,B) A.re*B.re-A.im*B.im /* Only real part of multiplication */

Glaeser-graphics/CODE/Proto.hBool sect_polys();Bool obj_outside_mirror();Bool intersect_polygons();Bool is_keyword();Bool end_of_input();Bool convex_polygon();Bool neighbors();Bool solve_quadratic_equation();Bool identical();Bool change_of_perspective();Bool draw_common_edge();Bool common_edge();Bool overlap();Bool sort_objects();Bool inside_poly();Bool negative();

Bool really_section();Bool spatial_hull();Bool clip_edge_with_polygon();Bool section_point();Bool section_line_edge();Bool local_visible();Bool axpoint();Bool sect_lightray_with_face();Bool really_continue();Bool within_edge();Bool area_exists();Bool still_to_draw();Bool section();Bool is_convex_poly2();Bool clip2d_line();Bool clip3d_line();

short relative_pos_of_hulls();short sect_line_face();short read_pos_int();short section_of_hulls();short find_all_succ_faces();short main_ortho_direction();short color_index();short sub_palette();short type_index();short curve_subtype();short geom_property_index();short phys_property_index();short convex_inter();short direction_in_face();short residual_intersection_point();short clip_edge_with_faces();short clip_edge_with_hiding_faces();short modify_and_check_zone();

float calc_formula();float read_float();float average_screen_dist();float dist_of_points();float z_value();float average_z_value();float max_z_value();double my_atan2();double angle();double angle2();

Face *continue_branch();Face *previous_face();

Polyhedron *side_of_eye();Polyhedron *side_of_light();Ubyte which_obj_is_first();float group_spin_angle();float obj_spin_angle();Spear *group_spin_axis();Spear *obj_spin_axis();

VOID *alloc_mem();VOID *mem_realloc();

void cubic_spline_curve(), akima_spline_curve(), b_spline_curve();void wireframe_of_object();void draw_depthcued_wireframe();void remove_hidden_parts();void draw_curve();void safe_open();void intersect_lines();void open_video();void min_max_vec_of_pool();void create_coord_box();void print_allocated_memory();void barycenter_of_face();void create_palettes();void fast_bounding_boxes();void convex_hull();void clip_patterns_with_shadows();void draw_sections_and_silhouette();void wire_frame_of_math_surface();void move_screen_center();void cartesian_coords();void change_distance();void free_mem();void rotate_object();void rotate_single_object();void translate_object();void grow_object();void scale_object();void stretch_object();void new_face_normals();void manipulate_group();void init_video_buffer();void manipulate_object();void update_slices();void rotate_group();void scale_group();void translate_group();void translate_whole_scene();void get_highlight();void initPostScript(), closePostScript();void transform_to_PostScript();void write_PostScript_macros();void pscript_line(), pscript_fill_poly(), pscript_outline_poly();

void open_graphics();void close_graphics();void swap_screens();void set_triangle();void set_quadrangle();void safe_exit();void clip_line_with_mirror();void draw_depthcued_wireframe();void fill_color_pool();void fill_contour_pool();void fill_halfspace_pool();void change_relative_position();void alloc_object();void alloc_group();void add_shadows_on_face();

FILE *prep_datafile();void install_define();void replace_define();

Complex Mirror(), Stretch(), Add(), Subt(), Mult(), Div(), Rez(), Pow(), Exp(), Sin(), Cos(), Log();Global void Init_fptr(calc_spline_curve, cubic_spline_curve);Global Bool (*clip_poly)();Global Bool (*clip_line)();Global void Init_fptr(display_scene, draw_depthcued_wireframe);Global void Init_fptr(draw_object, wireframe_of_object);Global void (*draw_line)();

Glaeser-graphics/CODE/Types.h/* TYPE DEFINITIONS: The following (mostly geometrical) definitions can be used especially in programs dealing with 3d-Graphics*/

#ifdef MAIN#define Global #define Init(var, value) var = value#define Init_fptr(ptr, function) (*ptr)() = function#else#define Global extern#define Init(var, value) var#define Init_fptr(ptr, function) (*ptr)()#endif

#define MAX_UBYTE ((1 ': Azim[0] -= PI/ 4; New_eye = TRUE; break; case 'name, "GLEITSTUECK")) break; if (g == hi_g) safe_exit("no glide"); glide = g;

for (g = group_pool; g < hi_g; g++) if (!strcmp(g->name, "POLGERADE")) break; if (g == hi_g) safe_exit("no polgerade"); polgerade = g;

hi_t = (t = Object_pool) + Total_objects; for (; t < hi_t; t++) if (!strcmp(t->name, "FRAESER_ANSATZ")) break; if (t == hi_t) safe_exit("no target"); target = t->bary_center;

for (t = Object_pool; t < hi_t; t++) if (!strcmp(t->name, "FRAESER")) break; if (t == hi_t) safe_exit("no cutter"); cutter = t; Alloc_array(Spear, cutter->animate->spin_axis, 1, ""); Alloc_array(float, cutter->animate->spin_angle, 1, ""); cutter->animate->spin_angle[0] = 8 * (PI / 180); v = (Vector *) cutter->animate->spin_axis[0].dir; (*v)[X] = (*v)[Y] = 0; (*v)[Z] = 1;

for (t = Object_pool; t < hi_t; t++) if (!strcmp(t->name, "POL")) break; if (t == hi_t) safe_exit("no pole"); pole = t->bary_center; cutter->animate->action = FALSE; (cutter+ 1)->animate->action = FALSE; } Subt_vec2(dir1, *pole, *target); angle = my_atan2(dir1[Y], dir1[X]); delta_angle = angle - prev_angle; prev_angle = angle; glide->animate->spin_angle[0] = delta_angle; polgerade->animate->spin_angle[0] = delta_angle;

Subt_vec2(dir2, *pole, *(cutter->bary_center)); Delta_dist = (d = Length2(dir1) -3) - Length2(dir2); normalize_vec2(dir1); v = glide->animate->move_vec; (*v)[X] = Delta_dist * dir1[X]; (*v)[Y] = Delta_dist * dir1[Y]; (*v)[Z] = 0;

v = (Vector *) group_spin_axis(glide); Copy_vec(*v, *pole); v = (Vector *) group_spin_axis(polgerade); Copy_vec(*v, *pole); rotate_cutter();}

rotate_cutter(){ Spear axis; float angle; register Face * f, *hi_f; short i; Vector *verts[3]; Copy_vec(axis.point, *cutter->bary_center); axis.dir[X] = axis.dir[Y] = 0; axis.dir[Z] = 1; angle = obj_spin_angle(cutter); rotate_single_object(cutter, axis, angle); rotate_single_object(cutter + 1, axis, angle);

hi_f = (f = cutter->faces[0]) + cutter->no_of_faces; for (; f < hi_f; f++) { for (i = 0; i < 3; i++) verts[i] = Screen_to_world(f->vertices[i]); normal_vector((Vector *) f->normal, verts); } new_face_constants(cutter); hi_f = (f = (cutter+ 1)->faces[0]) + (cutter+ 1)->no_of_faces; for (; f < hi_f; f++) { for (i = 0; i < 3; i++) verts[i] = Screen_to_world(f->vertices[i]); normal_vector((Vector *) f->normal, verts); } new_face_constants(cutter + 1);}

#endif

Glaeser-graphics/CODE/g_functs.c/* SYSTEM DEPENDENCIES: With the following subroutines it is possible to write C-programs which are system-independent. Each command which depends on the computer on the computer that is used (in this case a SILICON GRAPHICS workstation) should be written in the described manner! Some commands even differ with the used compiler.In this case the UNIX compiler (Standard C according to Kernigham Ritchie) was used.*/

#include "3d_std.h"

void iris_explain_keyboard(){ if (!Replay_only) { fprintf(Output, "Use 'a','b','c','d',...\n"); fprintf(Output, "and + 'a' etc. to manipulate the animation\n"); } else { fprintf(Output, "Use 's' for single step mode\n"); fprintf(Output, "Use 'f' for freeze a while\n"); fprintf(Output, "Use 'c' for 'cyclic'\n"); } fprintf(Output, "Use 'q' to quit\n");}

void iris_open_graphics() { keepaspect((long) XMAX - XMIN, (long) YMAX - YMIN); winopen("Fast Graphics"); Window_opened = TRUE; set_screen_constants(); G_clear_screen(BLACK); qdevice(LEFTMOUSE); qdevice(MIDDLEMOUSE); qdevice(RIGHTMOUSE); qdevice(KEYBD); fprintf(Output, "window size %d x %d\n", Window_width, Window_height); glcompat(GLC_OLDPOLYGON, FALSE); subpixel(TRUE); concave(FALSE); mmode(MSINGLE); ortho2(-0.5, Window_width + 0.5, - 0.5, Window_height + 0.5); doublebuffer(); if (Z_buffer.on && Hard_zbuffer) lsetdepth(0x0, 0x7fffff), zbuffer(TRUE), zclear(); shademodel(Smooth_shading ? GOURAUD : FLAT); if (Prepare_video) open_video(); if (!Replay_only) create_palettes(); gconfig(); G_explain_keyboard();}

void iris_set_pixel(x, y) float x, y;{ rectf(x-0.2, y-0.2, x+1.2, y+1.2); if (PScript.file) write_PScript_pixel(x - 0.2, y - 0.2);}

char iris_which_key(){ char c = '0'; if (getbutton(BACKSLASHKEY)) { fprintf(Output, "You have pressed the backslash-key.\n"); fprintf(Output, "I will sleep now till you wake me up with the\n"); fprintf(Output, "backslash-key once again!\n"); sleep(2); while (!getbutton(BACKSLASHKEY)) ; fprintf(Output, "I'm back again!\n"); sleep(1); } if (getbutton(LEFTSHIFTKEY)) { if (getbutton(AKEY)) c = 'A'; else if (getbutton(BKEY)) c = 'B'; else if (getbutton(CKEY)) c = 'C'; else if (getbutton(DKEY)) c = 'D'; else if (getbutton(EKEY)) c = 'E'; else if (getbutton(FKEY)) c = 'F'; else if (getbutton(GKEY)) c = 'G'; else if (getbutton(HKEY)) c = 'H'; else if (getbutton(IKEY)) c = 'I'; else if (getbutton(JKEY)) c = 'J'; else if (getbutton(KKEY)) c = 'K'; else if (getbutton(LKEY)) c = 'L'; else if (getbutton(MKEY)) c = 'M'; else if (getbutton(NKEY)) c = 'N'; else if (getbutton(OKEY)) c = 'O'; else if (getbutton(PKEY)) c = 'P'; else if (getbutton(RKEY)) c = 'R'; else if (getbutton(SKEY)) c = 'S'; else if (getbutton(TKEY)) c = 'T'; else if (getbutton(XKEY)) c = 'X'; else if (getbutton(YKEY)) c = 'Y'; else if (getbutton(ZKEY)) c = 'Z'; else if (getbutton(EQUALKEY)) { c = '+'; G_beep(); } else if (getbutton(PERIODKEY)) c = '>'; else if (getbutton(COMMAKEY)) c = 'spin_angle; *spin_angle= read_float(); *spin_angle *= (PI/ 180); if (fabs(*spin_angle) > EPS) { animate->action = Action = TRUE; animate->spin = TRUE; } } else if (!strcmp(Comment, "move")) { v = (Vector *) animate->move_vec; Fread_vec(*v); if (fabs((*v)[X]) + fabs((*v)[Y]) + fabs((*v)[Z]) > EPS) { animate->move = TRUE; animate->action = Action = TRUE; } } else if (!strcmp(Comment, "grow")) { v = (Vector *) animate->growth_vec; Fread_vec(*v); if (fabs((*v)[X]) + fabs((*v)[Y]) + fabs((*v)[Z]) > EPS) { animate->grow = TRUE; animate->action = Action = TRUE; } } else if (!strcmp(Comment, "scale")) { Get_comment(); must_be_keyword(60); /* 'factor' */ animate->Scale_factor = read_float(); Get_comment(); must_be_keyword(22); /* 'center' */ center = animate->scale_center; Fread_vec(*center); if (fabs(animate->Scale_factor) > EPS) { animate->scale = TRUE; animate->action = Action = TRUE; } }}

void grow_object(obj, t) Polyhedron *obj; Vector t;{ short n = obj->no_of_vertices / 2;

translate_pool(obj->vertices + n, n, t); bb_of_obj(obj); center_of_pool(obj->bary_center, obj->no_of_vertices, obj->vertices); if (Face_consts_done) new_face_constants(obj); if (Frame > 0 && Reflections && obj < Mirror_pool) reflect_obj(obj);}

void grow_group(group) Obj_group *group;{ Polyhedron *obj = group->primitives[0], *hi_obj = obj + group->no_of_primitives; register Vector *t = (Vector *) group->animate->growth_vec, *v, *hi_v;

for (; obj < hi_obj; obj++) grow_object(obj, *t); /* if (group->animate->spin) { v = (Vector *) group_spin_axis(group); Add_vec(*v, *v, *t); } hi_v = (v = group->bounding_box) + 9; for (; v < hi_v; v++) Add_vec(*v, *v, *t);*/}

void translate_whole_scene(t) Vector t;{ register Vector *world = Coord_pool, *hi_world = world + Total_vertices; Polyhedron *obj, *hi_obj; Obj_group *group, *Hi_group; Vector *v;

Hi_group = (group = group_pool) + No_of_groups; for (; group < Hi_group; group++) translate_group(group, t); if (!Reflections) return; hi_obj = (obj = Object_pool) + Total_objects; translate_pool(mirror_in_world, 4, t); for (; obj < hi_obj; obj++) reflect_obj(obj);}

void apply_t(v, center, how) Vector v, center; char * how;{ float lambda = center[Z] / (center[Z] - v[Z]); v[X] *= lambda; v[Y] *= lambda; if (how[1] == '2') v[Z] *= (0.25 * lambda); else v[Z] *= 1.0;} void t_object(obj, center, how) Polyhedron *obj; Vector center; char * how;{ register Vector *v = obj->vertices, *hi_v = obj->hi_coord;

for (; v < hi_v; v++) apply_t(*v, center, how); if (Face_consts_done) { new_face_constants(obj); hi_v = (v = obj->bounding_box) + 9; for (; v < hi_v; v++) apply_t(*v, center, how); }}

void t_group(group, center, how) Obj_group *group; Vector center; char * how;{ Polyhedron *obj = group->primitives[0], *hi_obj = obj + group->no_of_primitives; register Vector *v, *hi_v;

for (; obj < hi_obj; obj++) t_object(obj, center, how); hi_v = (v = group->bounding_box) + 9; for (; v < hi_v; v++) apply_t(*v, center, how);}

void scale_group(group, center, factor) Obj_group *group; Vector center; Vector factor;{ Polyhedron *obj = group->primitives[0], *hi_obj = obj + group->no_of_primitives; register Vector *v, *hi_v;

for (; obj < hi_obj; obj++) scale_object(obj, center, factor); if (group->animate->spin/* || group->animate->move*/) { v = (Vector *) group_spin_axis(group); stretch(*v, center, factor); } hi_v = (v = group->bounding_box) + 9; for (; v < hi_v; v++) stretch(*v, center, factor);}

Bool end_of_input(){ Polyhedron *obj;

if (feof(Input)) return TRUE; if (*Comment != '$') return FALSE; Get_comment(); safe_exit("unknown keyword after '$'");}

draw_cross(p) Vector2 p;{ Vector2 a, b;

a[X] = p[X] - 10; a[Y] = p[Y]; b[X] = p[X] + 10; b[Y] = p[Y]; draw_line2(a, b); a[X] = p[X]; a[Y] = p[Y] - 10; b[X] = p[X]; b[Y] = p[Y] + 10; draw_line2(a, b);}

float e00, e01, e02, e10, e11, e12, e20, e21, e22; /* Eulerian matrix */

#define euler_rotation(v)\ x =(v)[X], y =(v)[Y], z =(v)[Z],\ (v)[X] = e00 * x + e01 * y + e02 * z,\ (v)[Y] = e10 * x + e11 * y + e12 * z,\ (v)[Z] = e20 * x + e21 * y + e22 * z

void rotate1(obj, R) Polyhedron *obj; Rot_matrix R;{ register Vector *v = obj->vertices, *hi_v = obj->hi_coord; register Face *f, *hi_f; Vector tmp;

/* rotate all vertices */ for (; v < hi_v; v++) { Copy_vec(tmp, *v); vec_mult_matrix(*v, tmp, R); } hi_v = (v = obj->bounding_box) + 9; for (; v < hi_v; v++) { Copy_vec(tmp, *v); vec_mult_matrix(*v, tmp, R); }/* if (obj->animate->move) { v = obj->animate->move_vec; Copy_vec(tmp, *v); vec_mult_matrix(*v, tmp, R); }*/ if (Face_consts_done) { /* rotate Face normals */ hi_f = (f = obj->faces[0]) + obj->no_of_faces; for (; f < hi_f; f++) { Copy_vec(tmp, f->normal); vec_mult_matrix(f->normal, tmp, R); } }}

void general_rotation(pool, n, axis, angle) Vector *pool; short n; Spear *axis; double angle;{ Rot_matrix R; register Vector *v, *hi_v = pool + n, *t = (Vector *) axis->point; Vector tmp;

for (v = pool; v < hi_v; v++) Subt_vec(*v, *t, *v); fill_general_rot_matrix(R, angle, axis->dir); for (v = pool; v < hi_v; v++) { Copy_vec(tmp, *v); vec_mult_matrix(*v, tmp, R); } for (v = pool; v < hi_v; v++) Add_vec(*v, *t, *v);}

void rotate_single_object(obj, axis, angle) Polyhedron *obj; Spear axis; double angle;{ Bool general_case; Rot_matrix R; register Vector *v, *hi_v, *t; static Vector zero = {0, 0, 0}; Vector t1;

t = (Vector *) axis.point; if (identical(zero, *t)) general_case = FALSE; else { general_case = TRUE; Turn_vec(t1, *t); /* translate axis into Target (has no impact on face normals) */ translate_object(obj, t1); }

fill_general_rot_matrix(R, angle, axis.dir); rotate1(obj, R);

if (general_case) { /* translate axis back (has no impact on Face normals) */ translate_object(obj, *t); } if (Face_consts_done) new_face_constants(obj); if (Frame > 0 && Reflections && obj < Mirror_pool) reflect_obj(obj);}

void manipulate_group(group) Obj_group *group;{ Vector t, euler; short i, i0 = group->no_of_primitives; Vector stretch_factor; Vector stretch_center; Bool anim; Vector *v; Anim_info *animate = group->animate; Read_comment = FALSE; bb_of_group(group); while (!end_of_input()) { Get_comment(); anim = FALSE; if (end_of_input()) return; if (!strcmp(Comment, "spin") || !strcmp(Comment, "move") || !strcmp(Comment, "scale") || !strcmp(Comment, "grow")) { read_anim(animate); for (i = 0; i < i0; i++) group->primitives[i]->animate->action = TRUE; anim = TRUE; } else if (!strcmp(Comment,"deformation")) { float z, t; void deform_group(); z = read_float(); t = read_float(); deform_group(group, z, t); } else if (!strcmp(Comment,"translation")) { get_trans(t); translate_group(group, t); } else if (!strcmp(Comment,"rotation")) { Vector *vertex, *hi_vertex; float x, y, z; Polyhedron *obj; Spear *axis;

get_euler(euler); for (i = 0; i < i0 ; i++) { obj = group->primitives[i]; rotate_object(obj, euler); if (obj->animate->spin) { axis = obj_spin_axis(obj); euler_rotation(axis->point); euler_rotation(axis->dir); } } hi_vertex = (vertex = group->bounding_box) + 9; for (; vertex< hi_vertex; vertex++) euler_rotation(*vertex); if (animate->spin) { axis = group_spin_axis(group); euler_rotation(axis->point); euler_rotation(axis->dir); } } else if (!strcmp(Comment, "T1") || !strcmp(Comment, "T2")) { Vector center; center[X] = read_float(); center[Y] = read_float(); center[Z] = read_float(); t_group(group, center, Comment); } else if (is_keyword(38)) { /* stretch_factor */ Get_comment(); must_be_keyword(22); /* center */ Fread_vec(stretch_center); Get_comment(); if (is_keyword(60)) { /* factor */ stretch_factor[X] = read_float(); stretch_factor[Y] = stretch_factor[Z] = stretch_factor[X]; } else { must_be_keyword(110); /* factors */ stretch_factor[X] = read_float(); stretch_factor[Y] = read_float(); stretch_factor[Z] = read_float(); } scale_group(group, stretch_center, stretch_factor); if (animate->spin) { Spear *axis;

axis = group_spin_axis(group); stretch(axis->point, stretch_center, stretch_factor); } } else { if (anim) Get_comment(); return; } } }

extern Bool single_object;

void manipulate_object(obj) Polyhedron *obj;{ Vector t, euler; Vector stretch_factor; Bool anim; Anim_info *animate = obj->animate;

if (No_more_data) return; if (Read_comment) { Get_comment(); Read_comment= FALSE; }

bb_of_obj(obj); center_of_pool(obj->bary_center, obj->no_of_vertices, obj->vertices); obj->hi_coord = Cur_vec; do { anim = FALSE; if (end_of_input()) return; if (!strcmp(Comment, "spin") || !strcmp(Comment, "move") || !strcmp(Comment, "scale") || !strcmp(Comment, "grow")) { read_anim(animate); anim = TRUE; } else if (!strcmp(Comment,"deformation")) { float z, t; void deform_object(); z = read_float(); t = read_float(); deform_object(obj, z, t); } else if (!strcmp(Comment,"translation")) { get_trans(t); translate_object(obj,t); } else if (!strcmp(Comment,"rotation")) { get_euler(euler); rotate_object(obj,euler); if (animate->spin) { float x, y, z; Spear *axis;

axis = obj_spin_axis(obj); euler_rotation(axis->point); euler_rotation(axis->dir); } } else if (is_keyword(38)) { /* stretch */ Vector stretch_center;

Get_comment(); must_be_keyword(22); /* center */ Fread_vec(stretch_center); Get_comment(); if (is_keyword(60)) { /* factor */ stretch_factor[X] = read_float(); stretch_factor[Y] = stretch_factor[Z] = stretch_factor[X]; } else { must_be_keyword(110); /* factors */ stretch_factor[X] = read_float(); stretch_factor[Y] = read_float(); stretch_factor[Z] = read_float(); } scale_object(obj, stretch_center, stretch_factor); } else if (!strcmp(Comment,"}") || single_object) { if (!single_object) manipulate_group(Cur_group); single_object = TRUE; return; } else { single_object = FALSE; if (anim) Get_comment(); return; } Get_comment(); } while (!end_of_input());}

void deform_object(obj, z, t) Polyhedron *obj; float z, t;{ Vector *v = obj->vertices, *hi_v = obj->hi_coord; float k;

if (z == 0) safe_exit("deformation center must not equal 0"); for ( ; v < hi_v; v++) { k = t * (z - (*v)[Z]) / z; (*v)[X] *= k; (*v)[Y] *= k; } if (Face_consts_done) new_face_constants(obj); if (Frame > 0 && Reflections && obj < Mirror_pool) reflect_obj(obj);}void translate_object(obj,t) Polyhedron *obj; Vector t;{ short n = obj->hi_coord - obj->vertices;

translate_pool(obj->vertices, n, t); translate_pool((Vector *) obj->axis.point, 1, t); translate_pool(obj->bounding_box, 9, t); if (obj->type == MATH_SURF) { translate_pool(obj->axis.point, 1, t); update_slices(obj); } if (Face_consts_done) new_face_constants(obj); if (obj->animate->action) { if (obj->animate->spin) translate_pool((Vector *) obj_spin_axis(obj)->point, 1, t); } if (Frame > 0 && Reflections && obj < Mirror_pool) reflect_obj(obj);}

void deform_group(G, z, t) Obj_group *G; float z, t;{ Polyhedron *obj = G->primitives[0], *hi_obj = obj + G->no_of_primitives;

for (; obj < hi_obj; obj++) deform_object(obj, z, t); }

void translate_group(G, t) Obj_group *G; Vector t;{ Polyhedron *obj = G->primitives[0], *hi_obj = obj + G->no_of_primitives;

for (; obj < hi_obj; obj++) translate_object(obj, t); translate_pool(G->bounding_box, 9, t); if (G->animate->action) { if (G->animate->spin) translate_pool((Vector *) group_spin_axis(G)->point, 1, t); }}

void rotate_group(group, spin_axis, spin_angle) Obj_group *group; Spear *spin_axis; float spin_angle;{ Polyhedron *obj, *hi_obj; static Spear axis = { 0, 0, 0 }, *a;

hi_obj = (obj = group->primitives[0]) + group->no_of_primitives; for (; obj < hi_obj; obj++) { rotate_single_object(obj, *spin_axis, spin_angle); if (obj->animate->spin) { a = obj_spin_axis(obj); general_rotation((Vector *) a->point, 1, spin_axis, spin_angle); Copy_vec(axis.dir, spin_axis->dir); general_rotation((Vector *) a->dir, 1, &axis, spin_angle); } } general_rotation(group->bounding_box, 9, spin_axis, spin_angle); /* if (group->animate->move) { fill_general_rot_matrix(R, angle, axis.dir); }*/ if (group->animate->grow) general_rotation(group->animate->growth_vec, 1, spin_axis, spin_angle); }

extern Bool ax_through_origin;extern Vector ax_point;

void rotate_object(obj,euler) Polyhedron *obj; Vector euler;{ register float x,y,z; register Vector *v, *hi_v = obj->hi_coord; double c1,c2,c3,s1,s2,s3; /* abbreviations */ double _azim, _elev, _twist; Vector neg_ax_point; Vector *b, *hi_b;

_azim = euler[0] * (PI/ 180); _elev = euler[1] * (PI/ 180); _twist = euler[2] * (PI/ 180); s1 = sin(_elev); s2 = sin(_twist); s3 = sin(_azim); c1 = cos(_elev); c2 = cos(_twist); c3 = cos(_azim);

e00 = c2 * c3 - c1 * s2 * s3; e01 = c2 * s3 + c1 * s2 * c3; e02 = s1 * s2; e10 = -c1 * c2 * s3 - s2 * c3; e11 = c1 * c2 * c3 - s2 * s3; e12 = s1 * c2; e20 = s1 * s3; e21 = -s1 * c3; e22 = c1;

if (obj->type == MATH_SURF) { euler_rotation(obj->axis.dir); update_slices(obj); } if (ax_through_origin || (ax_point[X] == 0 && ax_point[Y] == 0 && ax_point[Z] == 0)) { for (v = obj->vertices; v < hi_v; v++) euler_rotation(*v); hi_b = (b = obj->bounding_box) + 9; for (; b < hi_b; b++) euler_rotation(*b); } else { Turn_vec(neg_ax_point, ax_point); translate_object(obj, neg_ax_point); for (v = obj->vertices; v < hi_v; v++) euler_rotation(*v); hi_b = (b = obj->bounding_box) + 9; for (; b < hi_b; b++) euler_rotation(*b); translate_object(obj, ax_point); if (Face_consts_done) new_face_normals(obj); }}

void new_face_normals(obj) Polyhedron *obj;{ register Face *f = obj->faces[0], *hi_f = f + obj ->no_of_faces; register Vector *n; register float x, y, z;

fprintf(Output, "new normals\n"); for (; f < hi_f; f++) { n = (Vector *) f->normal; euler_rotation(*n); }}

Glaeser-graphics/CODE/neighbor.c#include "3d_std.h"

void check_neighbors(obj) Polyhedron *obj;{ register Face *f, *hi_f, *lo_f, *f1, *f2; Vector *a, *b, **v, **v1, **hi_v; short i, j, temp, n1, found;

/*if (obj->geom_property == CONCAVE) return;*/ if (obj->faces[0]->neighbor_faces) { fprintf(Output, "neighbors of %s already done\n", obj->name); return; } alloc_neighbor_faces(&i, obj); switch (obj->type) { default: hi_f= (f = lo_f = obj->faces[0]) + obj->no_of_faces; for (; f < hi_f; f++) { found = 0; for (f1 = lo_f; f1 < hi_f; f1++) { if (f == f1) continue; if (common_edge(&a, &b, &i, &j, f, f1)) { if (i > j) { Swap(i, j); Print("Swapped"); G_beep(); } if (j - i == f->no_of_vertices - 1) i = j; else if (j - i != 1) Print("FUNNY: No neighbor points"); f2 = (Face *) f->neighbor_faces[i]; if (f2 != NULL) { if (f2 < lo_f || f2 > hi_f) Print("BAD1"); else Print("DOUBLE"); } f->neighbor_faces[i] = (struct Face *) f1; if (++found > f->no_of_vertices) break; } } } return; } /* switch */}

Glaeser-graphics/CODE/normals.c#include "3d_std.h"

Bool Turn_normal = FALSE;

Bool Closed[2];

void average_normals(normal, grid, imax, jmax) Vector **normal; /* Average normals in grid points (2d) */ Vector **grid; /* Grid of basepoints (2 - dimensional) */ short imax, jmax; { Vector n, diff[4]; short i, j, k, k1; register Vector *p, *sum; Vector *v[4];

Closed[0] = identical(grid[0][0], grid[0][jmax - 1]); if (Closed[0]) Print("Closed[0]"); Closed[1] = identical(grid[0][0], grid[imax - 1][0]); if (Closed[1]) Print("Closed[1]"); for (i = 0; i < imax; i++) for (j = 0; j < jmax; j++) { p = v[0] = v[1] = v[2] = v[3] = (Vector *) grid[i][j]; if (i > 0) v[0] = (Vector *) grid[i - 1][j]; else if (Closed[1]) v[0] = (Vector *) grid[imax - 2][j]; if (j > 0) v[1] = (Vector *) grid[i][j - 1]; else if (Closed[0]) v[1] = (Vector *) grid[i][jmax - 2]; if (i+ 1 < imax) v[2] = (Vector *) grid[i+ 1][j]; else if (Closed[1]) v[2] = (Vector *) grid[1][j]; if (j+ 1 < jmax) v[3] = (Vector *) grid[i][j+ 1]; else if (Closed[0]) v[3] = (Vector *) grid[i][1]; for (k = 0; k < 4; k++) if (v[k] != p) Subt_vec(diff[k], *p, *v[k]); sum = (Vector *) normal[i][j]; Zero_vec(*sum); for (k = 0, k1 = 1; k < 4; k++, k1 = (k1+ 1) % 4) { if (v[k] != p && v[k1] != p) { normalized_normal_of_2_vectors(n, diff[k1], diff[k]); Add_vec(*sum, *sum, n); } } normalize_vec(*sum); if (Turn_normal) Turn_vec(*sum, *sum); }}

void fill_normal_pool(obj) Polyhedron *obj;{ short i; Vector **grid;

Alloc_2d_array(Vector, obj->normal, obj->size1, obj->size2); Alloc_ptr_array(Vector, grid, obj->size1, "grid"); grid[0] = obj->vertices; for (i = 1; i < obj->size1; i++) grid[i] = grid[i - 1] + obj->size2; average_normals(obj->normal, grid, obj->size1, obj->size2); Free_array(grid, "grid");}

short integrate_normal(normal, v, f, f0) Vector *normal; Vector *v; Face *f, *f0;{ register Vector **v0, **hi_v0; Vector *n, *n0;

if (!f0) return 0; hi_v0 = (v0 = f0->vertices) + f0->no_of_vertices; for ( ; v0 < hi_v0; v0++) if (v == *v0) { /* Is angle of face normals small enough? */ n = (Vector *) f->normal; n0 = (Vector *) f0->normal; if (Dot_product(*n, *n0) > 0.92) { /* about 24 degrees (reg. 15) */ Add_vec(*normal, *normal, *n0); return 1; } } return 0;}

void optimize_normals(obj) Polyhedron *obj;{ short i, j, n = obj->no_of_vertices; float k; Bool *done; Face *f, *lo_f, *hi_f, *f0; Vector **v, **hi_v; short idx; struct Face **nf, **hi_nf; Vector *n0, *normal, *v0 = obj->vertices;

Alloc_2d_array(Vector, obj->normal, 1, n); n0 = obj->normal[0]; Alloc_array(Bool, done, n, "done"); for (i = 0; i < n; i++) done[i] = FALSE; hi_f = (lo_f = obj->faces[0]) + obj->no_of_faces; for (f = lo_f ; f < hi_f; f++) { f->normals_modified = FALSE; hi_v = (v = f->vertices) + f->no_of_vertices; for ( ; v < hi_v; v++) { idx = *v - v0; if (idx > n) safe_exit("idx too high"); if (!done[idx]) { hi_nf = (nf = f->neighbor_faces) + f->no_of_vertices; normal = n0 + idx; Copy_vec(*normal, f->normal); j = 1; if (obj->no_of_faces > 1) for (; nf < hi_nf; nf++) { f0 = (Face *) *nf; if (f0 >= lo_f && f0 < hi_f) j += integrate_normal(normal, *v, f, f0); else if (f0 < lo_f) fprintf(Output, "nface %ld too low (%s)\n", lo_f - f0, obj->name); else fprintf(Output, "nface too high (%s)\n", obj->name); } if (j > 1) k = 1.0/ j, Scale_vec(*normal, *normal, k), f->normals_modified = TRUE; done[idx] = TRUE; } } } Free_array(done, "done"); for (f = lo_f ; f < hi_f; f++) if (!f->normals_modified && f->no_of_vertices neighbor_faces) + f->no_of_vertices; for (j = 0; nf < hi_nf; nf++) { f0 = (Face *) *nf; if (f0 >= lo_f && f0 < hi_f) j += f0->normals_modified; } if (j >= 2) f->normals_modified = TRUE; }}

Glaeser-graphics/CODE/objects.c#include "3d_std.h"

void adapt_all_info_to_new_object(new,old) Polyhedron *new, *old;{ register short i, n; register long coord_diff; register Vector *old_vec = old->vertices, **old_edge = old->edges; Vector **old_coord_ptr, **new_coord_ptr; static Face *old_face, *new_face; short j, j0, n0; Face **nf1, **nf2; new->parent_group_index = Cur_group - group_pool; new->type = old->type; new->subtype = old->subtype; new->receives_shadow = old->receives_shadow; new->geom_property = old->geom_property; new->patterns = old->patterns; if (new->phys_property == DEFAULT) { new->phys_property = old->phys_property; } new->subtype = old->subtype;

/* adapt vertices */ n = new->no_of_vertices = old->no_of_vertices; memory_check(n); fprintf(Output,"%s ", new->name); message(7); fprintf(Output," %s\n", old->name); new->vertices = Cur_vec; n = old->hi_coord - old->vertices; new->hi_coord = Cur_vec + n; for (i = 0; i < n; i++, Cur_vec++, old_vec++) Copy_vec(*Cur_vec,*old_vec); coord_diff = new->vertices - old->vertices;

if (old->type != MATH_SURF) { long h; /* adapt edges */ n = 2 * (new->no_of_edges = old->no_of_edges); new->edges = Cur_edge; for (i = 0; i < n; i++) *Cur_edge++ = *old_edge++ + coord_diff; if (old->no_of_faces == 0) return; /* adapt faces */ n = new->no_of_faces = old->no_of_faces; Alloc_ptr_array(Face, new->faces, 1, "NF"); Alloc_array(Face, new->faces[0], n, "new faces"); if (old->phys_property != new->phys_property) fprintf(Output, "Warning: phys. property of %s ignored\n", new->name); new_face = new->faces[0]; old_face = old->faces[0]; for (i = 0; i < n; i++, old_face++, new_face++) { if (old_face->color == old->color_index) new_face->color = new->color_index; else new_face->color = old_face->color; new_face->phys_property = old_face->phys_property; if (old_face->paintings) { Alloc_array(Pattern, new_face->paintings, 1, "PT"); copy_all_paintings(new_face, old_face,coord_diff); } else new_face->paintings = NULL; j0 = new_face->no_of_vertices = old_face->no_of_vertices; old_coord_ptr = old_face->vertices; new_coord_ptr = Alloc_ptr_array(Vector, new_face->vertices, j0, "NC"); for (j = 0; j < j0; j++) *new_coord_ptr++ = *old_coord_ptr++ + coord_diff; } alloc_neighbor_faces(&n0, new); new_face = new->faces[0]; old_face = old->faces[0]; coord_diff = (long) new_face; h = (long) old_face; coord_diff -= h; for (i = 0; i < n; i++, new_face++, old_face++) { nf2 = (Face **) new_face->neighbor_faces; nf1 = (Face **) old_face->neighbor_faces; j0 = new_face->no_of_vertices; for (j = 0; j < j0; j++) { h = (long) old_face->neighbor_faces[j]; h += coord_diff; new_face->neighbor_faces[j] = (struct Face *)h; } } } else { /* MATH_SURF */ Polyhedron *help;

new->size1 = old->size1; new->size2 = old->size2; if (new->subtype == FUNCTION_GRAPH) error_msg(5); help = Cur_object; Cur_object = new; allocate_faces(SPHERE); quadrangulation(); slice_surf_of_rev(); Cur_object = help; Copy_vec(new->axis.point, old->axis.point); Copy_vec(new->axis.dir, old->axis.dir); clear_faces(new); } Read_comment = TRUE;}

Glaeser-graphics/CODE/options.c#include "3d_std.h"

void draw_box(min, max)Vector min, max;{ Vector2 rec[4];

Copy_vec2(rec[0],min); rec[1][X] = max[X]; rec[1][Y] = min[Y]; Copy_vec2(rec[2],max); rec[3][X] = min[X]; rec[3][Y] = max[Y]; draw_poly2(4,rec,NOT_CLOSED);}

void show_bounding_boxes(){ Obj_group *group; Polyhedron *obj, *hi_obj, *corr_obj;

if (Draw_mode == WIRE_FRAME) min_max_depth(); for (group = group_pool; group < Hi_group; group++) { set_hue("gray", 50); draw_box(group->box_min[0], group->box_max[0]); hi_obj = (obj = group->primitives[0]) + group->no_of_primitives; for (; obj < hi_obj; obj++) { set_hue2(obj->color_index, 50); draw_box(obj->box_min[0], obj->box_max[0]); if (Reflections) { corr_obj = Mirror_pool + obj->index; draw_box(corr_obj->box_min[0], corr_obj->box_max[0]); } } }}

show_object_groups(){ for (Cur_group = group_pool; Cur_group < Hi_group; Cur_group++) { set_hue("yellow", 80); draw_box3(Cur_group->bounding_box); } /* for (Cur_object = Object_pool; Cur_object < Hi_object; Cur_object++) { set_hue("gray", 50); draw_box3(Cur_object->bounding_box); } */}

extern Bool Draw_mirror_later;

void show_contours(system, pool) short system; /* screen contour or light contour */ Polyhedron *pool;{ register Vector **vertex, **hi_vertex; Polyhedron *obj, *hi_obj;

if (Reflections && Draw_mirror_later || Draw_mode == WIRE_FRAME) return; set_hue("gray", 99); /* white */ hi_obj = (obj = pool) + Total_objects; for (; obj < hi_obj; obj++) { if (TRUE || obj->geom_property != CONCAVE) { vertex = obj->contour[system]; hi_vertex = vertex + obj->size_of_contour[system]; G_move(**vertex); for (++vertex; vertex< hi_vertex; vertex++) G_draw(**vertex); vertex = obj->contour[system]; G_draw(**vertex); G_close_line(); } }}

Glaeser-graphics/CODE/ortho.c#include "3d_std.h"

#ifdef TRUE

void follow_line();short Curve_index = 0, Max_curve_index = 15000;double Tan_angle;Vector *Curve_pool;Spear Cur_line;Bool Alert = FALSE;

initialize_lines(){ Tan_angle = tan((double) Inclination_angle * PI/ 180); Alloc_array(Vector, Curve_pool, Max_curve_index + 3, "mxc"); Hi_slice=(Cur_slice = Cur_object->slices)+ Cur_object->no_of_slices; for (; Cur_slice < Hi_slice; Cur_slice++) { Hi_ring =(Cur_ring= Cur_slice->rings)+ Cur_slice->no_of_rings; for (; Cur_ring < Hi_ring; Cur_ring++) { Hi_face =(Cur_face= Cur_ring->faces)+ Cur_ring->no_of_faces; for (; Cur_face< Hi_face; Cur_face++) { Cur_face->No_of_curves= 0; Alloc_array(short, Cur_face->curves, 4, "crv"); } } }}

void determine_family_of_curves(obj) Polyhedron *obj;{ Spear start; short i = 0; Vector sections[2]; Face *f, *hi_f;

fprintf(Output, "family of curves...\n"); initialize_lines(); Hi_slice=(Cur_slice = obj->slices)+ obj->no_of_slices; for (; Cur_slice < Hi_slice; Cur_slice += 3,i += 2) { if (i > 8) i = 0; Hi_ring =(Cur_ring = Cur_slice->rings)+ Cur_slice->no_of_rings; for (; Cur_ring < Hi_ring; Cur_ring++) { hi_f=(f = Cur_ring->faces)+ Cur_ring->no_of_faces; for (f; f < hi_f; f += 8) { barycenter_of_face(start.point,f); if (direction_in_face(start.dir,f->normal)) { if (sect_line_face(sections,&start,f)) follow_line(f,sections,start.dir); } } } } fprintf(Output, "%d lines found in triangles\n",Curve_index/ 2); }

void follow_line(f, start_knot, start_dir) Face *f; Vector start_knot[], start_dir;{ Face *start_f[2], *cur_f, *prec_f, *succ_f; short no_of_branches, i; short n; Vector cur_knot; short dir_of_branch; short total_new_faces = 0;

Alert = TRUE; no_of_branches = find_all_succ_faces(f, start_f, start_knot); Alert = FALSE; if (!no_of_branches) { (f->No_of_curves)--; if (f->no_of_neighbor_faces > 1) Print("No branches"); } else fprintf(Output, "%d branches expected\n", no_of_branches);

for (i = 0; i < no_of_branches; i++) { Copy_vec(Cur_line.point,start_knot[i]); Copy_vec(Cur_line.dir, start_dir); dir_of_branch = residual_intersection_point(cur_knot,start_f[i]); if (!dir_of_branch) { (f->No_of_curves)--; break; } prec_f = f; cur_f = start_f[i]; for (n = 0; n < 1000; n++) { succ_f = continue_branch(cur_knot, cur_f, prec_f, dir_of_branch); if (!succ_f || (succ_f == cur_f && cur_f == prec_f)) break; prec_f = cur_f; cur_f = succ_f; } total_new_faces += n; fprintf(Output, " %d new faces", n); } /* fprintf(Output, "\n"); */ if (!total_new_faces) (f->No_of_curves)--;}

Face *continue_branch(knot, f, prec_f, dir_of_branch) Vector knot; Face *f, *prec_f; short dir_of_branch;{ struct Face **cur_neighbor, **hi_neighbor; Face *neighbor; short cur_dir; Vector correct_knot, dir_in_f, dir_in_neighbor, average_dir;

Copy_vec(correct_knot, knot); hi_neighbor =(cur_neighbor= f->neighbor_faces)+ f->no_of_neighbor_faces; for (; cur_neighbor< hi_neighbor; cur_neighbor++) { neighbor=(Face *) *cur_neighbor; if (neighbor && neighbor!= prec_f) { if (really_continue(knot,f,neighbor)) { if (direction_in_face(Cur_line.dir, neighbor->normal)) {

/* the branch should continue in this neighbor face */ Copy_vec(Cur_line.point, correct_knot); cur_dir = residual_intersection_point(knot, neighbor); if (cur_dir == dir_of_branch) { return neighbor; } else if (cur_dir) (neighbor->No_of_curves)--;

/* three directions in space */ Copy_vec(dir_in_neighbor,Cur_line.dir); direction_in_face(dir_in_f,f->normal); Add_vec(average_dir,dir_in_f,dir_in_neighbor);

/* Possibility: Spear stays in neighbor with direction of f*/ Copy_vec(Cur_line.point,correct_knot); project_on_plane(Cur_line.dir,dir_in_f,neighbor->normal); cur_dir = residual_intersection_point(knot,neighbor); if (cur_dir == dir_of_branch) { return neighbor; } else if (cur_dir) (neighbor->No_of_curves)--;

/* Possibility: Spear stays in neighbor with the average direction of f and neighbor */ Copy_vec(Cur_line.point,correct_knot); project_on_plane(Cur_line.dir,average_dir,neighbor->normal); cur_dir = residual_intersection_point(knot,neighbor); if (cur_dir == dir_of_branch) { return neighbor; } else if (cur_dir) (neighbor->No_of_curves)--;

/* Possibility: Spear goes back to f with the average direction of the faces */ Copy_vec(Cur_line.point,correct_knot); project_on_plane(Cur_line.dir,average_dir,f->normal); cur_dir = residual_intersection_point(knot,f); if (cur_dir == dir_of_branch) { return f; } else if (cur_dir) (f->No_of_curves)--;

/* Possibility: Spear goes back to f with the direction of the neighbor face */ Copy_vec(Cur_line.point,correct_knot); project_on_plane(Cur_line.dir,dir_in_neighbor,f->normal); cur_dir = residual_intersection_point(knot,f); if (cur_dir == dir_of_branch) { return f; } else if (cur_dir) (f->No_of_curves)--; /* take_last_chance(knot,f,neighbor,dir_of_branch); return neighbor; */ } } } } return NULL;}

fsign(x)float x;{ if (x > EPS) return(1); else if (x < -EPS) return(-1); else return(0);}

/*take_last_chance(knot,f,neighbor,dir_of_branch)Vector knot;Face *f, *neighbor;short dir_of_branch;{ short idx_a, idx_b;

Vector *a,*b, *c, diff; Vector **v = neighbor->vertices, **hi= v+ neighbor->no_of_vertices; double lambda= 0.05;

common_edge(&a, &b, &idx_a, &idx_b, f, neighbor); if (fsign((*a)[Z]-(*b)[Z]) == dir_of_branch) c = a; else c = b; for (; v < hi; v++) if ((*v)!= c) break; Subt_vec(diff,*c,**v); Linear_comb(knot,*c,diff,lambda);}*/

create_more_space(f,n)Face *f;short n;{ register short *old = f->curves, *new; register short i = 0, imax = 2 * n;

new = Alloc_array(short, f->curves, 10 * n + 2, "Nsz"); for (; i < imax; i++) new[i] = old[i]; Free_array(old, "FCR");}

/* The next function returns the number of all neighbor faces of the face *f that are connected with the very first spear in *f. It also transfers pointers to these faces and it even stores the new lines in these faces. */

short find_all_succ_faces(f,succ_face,knot)Face *f;Face *succ_face[];Vector knot[];{ struct Face **cur_neighbor, **hi_neighbor; Face *neighbor; short found = 0;

hi_neighbor =(cur_neighbor= f->neighbor_faces)+ f->no_of_neighbor_faces; for (; cur_neighbor< hi_neighbor; cur_neighbor++) { neighbor=(Face *) *cur_neighbor; if (neighbor && really_continue(knot[found],f,neighbor)) { succ_face[found++]= neighbor; if (found == 2) return found; } } return found;}

/* Select those points on the lines on the face which are also on the neighbor face. */

Bool really_continue(knot,f1,f2)Vector knot;Face *f1, *f2;{ Vector *a, *b; short idx_a, idx_b;

if (!common_edge(&a, &b, &idx_a, &idx_b, f1, f2)) { if (Alert) Print("No common edge"); return FALSE; } if (!within_edge(knot,*a,*b)) return FALSE; return TRUE;}

short direction_of_line(f)Face *f;{ short n; Vector *a, *b, *c, *d; short *index, i, hi_i;

if (Curve_index > Max_curve_index) safe_exit("Max_curve_index reached"); b =(a = Curve_pool+ Curve_index - 2)+ 1; if (f->No_of_curves> 2) { index = f->curves; i = 0; hi_i= 2 * f->No_of_curves - 2; while (i < hi_i) { c = Curve_pool+ index[i++]; d = Curve_pool+ index[i++]; if (identical(*a,*c) || identical(*a,*d)) { fprintf(Output, " loop!"); Curve_index -= 2; return 0; } } } n = ++(f->No_of_curves); if (n == 2 || n == 10 || n == 50) create_more_space(f,n); return fsign((*b)[Z]-(*a)[Z]);}

short direction_in_face(direction, nrm) Vector direction, nrm;{ double lambda[2]; Vector ortho, hor; double a,b,c; /* coefficients of quadratic equation */

ortho[X]= nrm[X]*nrm[Z]; ortho[Y]= nrm[Y]*nrm[Z]; ortho[Z]= -(nrm[X]*nrm[X]+ nrm[Y]*nrm[Y]); if (fabs((double)ortho[Z]) < EPS) { Print_vec(nrm); fprintf(Output, "\n\t\tno direction in face!\n"); return FALSE; } if (Curve_type== ORTHOGONALS) { Copy_vec(direction,ortho); return TRUE; }

normalize_vec(ortho); hor[X]= -nrm[Y]; hor[Y]= nrm[X]; hor[Z]= 0; normalize_vec(hor);

switch (Curve_type) { case LOXODROMES: Linear_comb(direction,hor,ortho,Tan_angle); return TRUE; case INCLINATION: a = ortho[Z]*ortho[Z]- Tan_angle * Square2(ortho); b = 2 * (hor[Z]*ortho[Z]- Tan_angle * (Dot_product2(hor,ortho))); c = hor[Z]*hor[Z]- Tan_angle * Square2(hor); if (!solve_quadratic_equation(lambda,a,b,c)) return FALSE; Linear_comb(direction,hor,ortho,lambda[0]); return TRUE; } return FALSE;}

add_curves(f)Face *f;{ Vector *a, *b; short *index; short max_color = 10; short i, hi_i;

depth_color(f, 2, max_color); index = f->curves; i = 0; hi_i= 2 * f->No_of_curves; while (i < hi_i) { a = Curve_pool+ index[i++]; b = Curve_pool+ index[i++]; draw_line3(*a,*b); }}

short residual_intersection_point(resid,f)Vector resid;Face *f;{ short cur_index = 2 * f->No_of_curves; Vector **a, **b, **hi= f->vertices+ f->no_of_vertices, **trivial = NULL; Vector *cur_section =(Vector *)Curve_pool[Curve_index];

for (a = f->vertices, b = a+ 1; a < hi; a++,b++) { if (b == hi) b = f->vertices; if (within_edge(Cur_line.point,**a,**b)) { Copy_vec(*cur_section,Cur_line.p