amiga-request@abcfd20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (09/04/90)
Submitted-by: David Schanen <mtv@milton.u.washington.edu>
Posting-number: Volume 90, Issue 251
Archive-name: applications/dkbtrace-2.01/part03
#!/bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 10)."
# Contents: src/Sculpt2dkb.c src/amiga.c src/csg.c src/gif.c
# src/iffw.c src/matrices.c src/planes.c src/spheres.c
# Wrapped by tadguy@abcfd20 on Mon Sep 3 19:21:17 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/Sculpt2dkb.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/Sculpt2dkb.c'\"
else
echo shar: Extracting \"'src/Sculpt2dkb.c'\" \(7547 characters\)
sed "s/^X//" >'src/Sculpt2dkb.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X* Sculpt2dat.c
X*
X* from DKBTrace (c) 1990 David Buck
X*
X* This program reads a Sculpt-Animate 3D format scene file and generates an
X* output file that may be read in to DKBTrace.
X*
X* This software is freely distributable. The source and/or object code may be
X* copied or uploaded to communications services so long as this notice remains
X* at the top of each file. If any changes are made to the program, you must
X* clearly indicate in the documentation and in the programs startup message
X* who it was who made the changes. The documentation should also describe what
X* those changes were. This software may not be included in whole or in
X* part into any commercial package without the express written consent of the
X* author. It may, however, be included in other public domain or freely
X* distributed software so long as the proper credit for the software is given.
X*
X* This software is provided as is without any guarantees or warranty. Although
X* the author has attempted to find and correct any bugs in the software, he
X* is not responsible for any damage caused by the use of the software. The
X* author is under no obligation to provide service, corrections, or upgrades
X* to this package.
X*
X* Despite all the legal stuff above, if you do find bugs, I would like to hear
X* about them. Also, if you have any comments or questions, you may contact me
X* at the following address:
X*
X* David Buck
X* 22C Sonnet Cres.
X* Nepean Ontario
X* Canada, K2H 8W7
X*
X* I can also be reached on the following bulleton boards:
X*
X* ATX (613) 526-4141
X* OMX (613) 731-3419
X* Mystic (613) 731-0088 or (613) 731-6698
X*
X* Fidonet: 1:163/109.9
X* Internet: David_Buck@Carleton.CA
X*
X* IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
X*
X* Lattice BBS (708) 916-1200
X* The Information Exchange BBS (708) 945-5575
X* Stillwaters BBS (708) 403-2826
X*
X*****************************************************************************/
X
X
X#include <stdio.h>
X#include "frame.h"
X#include "dkbproto.h"
X
Xvoid read_iff_file(void);
X
XIMAGE_COLOUR *iff_colour_map;
Xint colourmap_size;
XFILE *f, *out;
X
Xstatic CHUNK_HEADER Chunk_Header;
X
XDBL *vertices_x, *vertices_y, *vertices_z;
XDBL max_x, max_y, max_z, min_x, min_y, min_z;
X#define FABS(x) ((x<0.0)?-x:x)
X
X#define FORM 0x464f524dL
X#define SC3D 0x53433344L
X#define VERT 0x56455254L
X#define FACE 0x46414345L
X
X#define CMPNONE 0
X
Xchar *Textures[7] = {"Dull", "Shiny", "Mirror", "Luminous", "Glass", "Metal", "Glass2"};
X
Xvoid iff_error ()
X {
X printf ("Invalid iff file\n");
X exit(1);
X }
X
Xint read_byte(f)
X FILE *f;
X {
X int c;
X if ((c = getc(f)) == EOF)
X iff_error();
X return (c);
X }
X
Xint read_word(f)
X FILE *f;
X {
X int result;
X
X result = read_byte(f)*256;
X result += read_byte(f);
X return (result);
X }
X
Xlong read_long(f)
X FILE *f;
X {
X int i;
X long result;
X
X result = 0;
X for (i = 0 ; i < 4 ; i++)
X result = result * 256 + read_byte(f);
X
X return (result);
X }
X
Xvoid Read_Chunk_Header (f, dest)
X FILE *f;
X CHUNK_HEADER *dest;
X {
X dest->name = read_long(f);
X dest->size = (int) read_long(f);
X }
X
Xvoid read_iff_file()
X {
X int i;
X int vert1, vert2, vert3;
X unsigned int texture;
X DBL red, green, blue;
X
X max_x = max_y = max_z = -10000000.0;
X min_x = min_y = min_z = 10000000.0;
X
X while (1) {
X Read_Chunk_Header(f, &Chunk_Header);
X switch ((int) Chunk_Header.name) {
X case FORM: if (read_long(f) != SC3D)
X iff_error();
X break;
X
X case VERT: vertices_x = (DBL *)
X malloc (Chunk_Header.size * (sizeof(DBL)/sizeof(long)));
X vertices_y = (DBL *)
X malloc (Chunk_Header.size * (sizeof(DBL)/sizeof(long)));
X vertices_z = (DBL *)
X malloc (Chunk_Header.size * (sizeof(DBL)/sizeof(long)));
X for (i = 0 ; i < Chunk_Header.size/12 ; i++) {
X vertices_x[i] = read_long(f) / 10000.0;
X if (vertices_x[i] < min_x)
X min_x = vertices_x[i];
X if (vertices_x[i] > max_x)
X max_x = vertices_x[i];
X
X vertices_y[i] = read_long(f) / 10000.0;
X if (vertices_y[i] < min_y)
X min_y = vertices_y[i];
X if (vertices_y[i] > max_y)
X max_y = vertices_y[i];
X
X vertices_z[i] = read_long(f) / 10000.0;
X if (vertices_z[i] < min_z)
X min_z = vertices_z[i];
X if (vertices_z[i] > max_z)
X max_z = vertices_z[i];
X }
X break;
X
X case FACE: for (i = 0 ; i < Chunk_Header.size/16 ; i++) {
X vert1 = (int) read_long(f);
X vert2 = (int) read_long(f);
X vert3 = (int) read_long(f);
X red = read_byte(f) / 255.0;
X green = read_byte(f) / 255.0;
X blue = read_byte(f) / 255.0;
X
X texture = read_byte(f);
X texture &= 0x07; /* mask upper bits */
X
X fprintf (out, "OBJECT TRIANGLE <%f %f %f> <%f %f %f> <%f %f %f> END_TRIANGLE COLOUR RED %f GREEN %f BLUE %f TEXTURE %s END_TEXTURE END_OBJECT\n",
X vertices_x[vert1], vertices_y[vert1], vertices_z[vert1],
X vertices_x[vert2], vertices_y[vert2], vertices_z[vert2],
X vertices_x[vert3], vertices_y[vert3], vertices_z[vert3],
X red, green, blue, Textures[texture]);
X }
X return;
X
X default:
X for (i = 0 ; i < Chunk_Header.size ; i++)
X if (getc(f) == EOF)
X iff_error();
X break;
X }
X }
X }
X
Xvoid main (argc, argv)
X int argc;
X char **argv;
X {
X if (argc != 3) {
X printf ("Usage: %s <scene-file> <output-file>\n", argv[0]);
X exit (1);
X }
X
X if ((f = fopen(argv[1], "rb")) == NULL) {
X printf ("Cannot open IFF file %s\n", argv[1]);
X exit(1);
X }
X
X if ((out = fopen(argv[2], "w")) == NULL) {
X printf ("Cannot open output file %s\n", argv[1]);
X exit(1);
X }
X
X fprintf(out, "COMPOSITE\n");
X read_iff_file();
X fprintf(out, " BOUNDED_BY\n INTERSECTION\n");
X fprintf(out, " PLANE <1.0 0.0 0.0> %1.02f END_PLANE\n", FABS(max_x) * 1.01);
X fprintf(out, " PLANE <-1.0 0.0 0.0> %1.02f END_PLANE\n", FABS(min_x) * 1.01);
X fprintf(out, " PLANE <0.0 1.0 0.0> %1.02f END_PLANE\n", FABS(max_y) * 1.01);
X fprintf(out, " PLANE <0.0 -1.0 0.0> %1.02f END_PLANE\n", FABS(min_y) * 1.01);
X fprintf(out, " PLANE <0.0 0.0 1.0> %1.02f END_PLANE\n", FABS(max_z) * 1.01);
X fprintf(out, " PLANE <0.0 0.0 -1.0> %1.02f END_PLANE\n", FABS(min_z) * 1.01);
X fprintf(out, " END_INTERSECTION\n END_BOUND\n \nEND_COMPOSITE\n");
X printf ("X values range from %f to %f\n", min_x, max_x);
X printf ("Y values range from %f to %f\n", min_y, max_y);
X printf ("Z values range from %f to %f\n", min_z, max_z);
X fclose(f);
X fclose(out);
X }
END_OF_FILE
if test 7547 -ne `wc -c <'src/Sculpt2dkb.c'`; then
echo shar: \"'src/Sculpt2dkb.c'\" unpacked with wrong size!
fi
# end of 'src/Sculpt2dkb.c'
fi
if test -f 'src/amiga.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/amiga.c'\"
else
echo shar: Extracting \"'src/amiga.c'\" \(6939 characters\)
sed "s/^X//" >'src/amiga.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X* amiga.c
X*
X* from DKBTrace (c) 1990 David Buck
X*
X* This module handles all of the Amiga-specific code for the raytracer.
X*
X*
X* This software is freely distributable. The source and/or object code may be
X* copied or uploaded to communications services so long as this notice remains
X* at the top of each file. If any changes are made to the program, you must
X* clearly indicate in the documentation and in the programs startup message
X* who it was who made the changes. The documentation should also describe what
X* those changes were. This software may not be included in whole or in
X* part into any commercial package without the express written consent of the
X* author. It may, however, be included in other public domain or freely
X* distributed software so long as the proper credit for the software is given.
X*
X* This software is provided as is without any guarantees or warranty. Although
X* the author has attempted to find and correct any bugs in the software, he
X* is not responsible for any damage caused by the use of the software. The
X* author is under no obligation to provide service, corrections, or upgrades
X* to this package.
X*
X* Despite all the legal stuff above, if you do find bugs, I would like to hear
X* about them. Also, if you have any comments or questions, you may contact me
X* at the following address:
X*
X* David Buck
X* 22C Sonnet Cres.
X* Nepean Ontario
X* Canada, K2H 8W7
X*
X* I can also be reached on the following bulleton boards:
X*
X* ATX (613) 526-4141
X* OMX (613) 731-3419
X* Mystic (613) 731-0088 or (613) 731-6698
X*
X* Fidonet: 1:163/109.9
X* Internet: David_Buck@Carleton.CA
X*
X* IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
X*
X* Lattice BBS (708) 916-1200
X* The Information Exchange BBS (708) 945-5575
X* Stillwaters BBS (708) 403-2826
X*
X*****************************************************************************/
X
X#include "frame.h"
X#include "dkbproto.h"
X
X#include <proto/exec.h>
X#include <proto/intuition.h>
X#include <proto/graphics.h>
X#include <proto/dos.h>
X#include <exec/types.h>
X#include <intuition/intuition.h>
X#include <graphics/display.h>
X
Xvoid geta4(void);
Xvoid Requestor_Handler(void);
Xvoid Amiga_open(void);
Xvoid Amiga_close(void);
Xvoid open_requestor(void);
Xvoid close_requestor(void);
Xextern int Options;
X
X#define INT_REV 29L
X#define GR_REV 29L
X
Xstruct IntuitionBase *IntuitionBase;
Xstruct GfxBase *GfxBase;
Xstruct Screen *s;
Xstruct Window *w;
Xstruct Task *Requestor_Task;
X
Xvolatile int Requestor_Running;
Xvolatile extern int Stop_Flag;
X
X#define SCREEN_WIDTH 320
X#define SCREEN_HEIGHT 400
X
Xstruct NewScreen MyScreen =
X {
X 0, 0,
X SCREEN_WIDTH, SCREEN_HEIGHT,
X 6,
X 0, 1,
X INTERLACE | HAM,
X SCREENQUIET,
X NULL,
X (UBYTE *) "DKB Ray Trace",
X NULL,
X NULL
X };
X
Xstruct Window *Requestor_Window;
Xstruct MsgPort *Requestor_Port;
X
Xstruct IntuiText Body_Text =
X {0, 1, JAM1, 5, 10, NULL, (UBYTE *) "Click to abort the picture", NULL};
X
Xstruct IntuiText Abort_Text =
X {0, 1, JAM1, 5, 3, NULL, (UBYTE *) "Abort", NULL};
X
XUWORD ColorTbl[16] = { 0x000, 0x111, 0x222, 0x333, 0x444, 0x555, 0x666,
X 0x777, 0x888, 0x999, 0xaaa, 0xbbb, 0xccc, 0xddd,
X 0xeee, 0xfff };
X
XLONG last_red = 0, last_green = 0, last_blue = 0, last_y = -1;
X
Xvoid Requestor_Handler ()
X {
X Requestor_Port = CreatePort ("ray trace port", 0L);
X Requestor_Window = BuildSysRequest
X (NULL, &Body_Text, NULL, &Abort_Text, GADGETUP, 280L, 60L);
X Wait ((1 << Requestor_Port -> mp_SigBit)
X | (1 << Requestor_Window -> UserPort -> mp_SigBit));
X
X Requestor_Running = FALSE;
X Stop_Flag = TRUE;
X }
X
Xvoid Amiga_open()
X {
X IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library",INT_REV);
X if (IntuitionBase == NULL)
X exit(FALSE);
X
X GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", GR_REV);
X if (GfxBase == NULL)
X exit(FALSE);
X Requestor_Running = FALSE;
X }
X
Xvoid Amiga_close()
X {
X if (Requestor_Running) {
X Signal (Requestor_Task, 1 << Requestor_Port -> mp_SigBit);
X Delay (2L);
X }
X
X if (Requestor_Window)
X FreeSysRequest (Requestor_Window);
X
X Requestor_Window = NULL;
X
X CloseLibrary (GfxBase) ;
X CloseLibrary (IntuitionBase) ;
X }
X
Xvoid open_requestor()
X {
X Requestor_Window = NULL;
X Stop_Flag = FALSE;
X Requestor_Running = TRUE;
X Requestor_Task = CreateTask ("Raytrace Requestor", 2L,
X (APTR) Requestor_Handler, 20000L);
X }
X
Xvoid display_finished ()
X {
X if (Requestor_Running) {
X Signal (Requestor_Task, 1 << Requestor_Port -> mp_SigBit);
X Delay (2L);
X }
X
X if (Requestor_Window)
X FreeSysRequest (Requestor_Window);
X
X Requestor_Window = NULL;
X if (Options & PROMPTEXIT)
X {
X printf ("Finished.\nPress CR to quit.\n");
X getchar();
X }
X }
X
Xvoid display_init ()
X {
X Amiga_open();
X open_requestor();
X
X Delay (10);
X if ((s = (struct Screen *) OpenScreen (&MyScreen)) == NULL)
X exit (FALSE);
X
X ShowTitle (s, FALSE);
X
X LoadRGB4 (&(s->ViewPort), ColorTbl, 16L);
X SetAPen (&(s->RastPort), 7L);
X RectFill (&(s -> RastPort), 0L, 0L, 319L, 399L);
X }
X
Xvoid display_close ()
X {
X if (Requestor_Running) {
X Signal (Requestor_Task, 1 << Requestor_Port -> mp_SigBit);
X Delay (2L);
X }
X
X if (Requestor_Window)
X FreeSysRequest (Requestor_Window);
X
X Requestor_Window = NULL;
X
X CloseScreen (s);
X }
X
X#define absdif(x,y) ((x > y) ? (x - y) : (y - x))
X#define max3(x,y,z) ((x>y)?((x>z)?1:3):((y>z)?2:3))
X
Xvoid display_plot (x, y, Red, Green, Blue)
X int x, y;
X char Red, Green, Blue;
X {
X register LONG delta_red, delta_green, delta_blue, colour;
X static int Last_Colour = 0;
X
X if ((x >= SCREEN_WIDTH-1 ) || (y >= SCREEN_HEIGHT))
X return;
X
X Red = (Red >> 4) & 0x0F;
X Green = (Green >> 4) & 0x0F;
X Blue = (Blue >> 4) & 0x0F;
X
X if (last_y != y) {
X last_y = y;
X last_red = last_green = last_blue = 0;
X Last_Colour = 0;
X SetAPen (&(s -> RastPort), 0);
X WritePixel (&(s -> RastPort), 0, y);
X }
X
X delta_red = absdif (Red, last_red);
X delta_green = absdif (Green, last_green);
X delta_blue = absdif (Blue, last_blue);
X
X switch (max3(delta_red, delta_green, delta_blue)) {
X case 1:
X last_red = Red;
X colour = 0x20 + Red;
X break;
X case 2:
X last_green = Green;
X colour = 0x30 + Green;
X break;
X case 3:
X last_blue = Blue;
X colour = 0x10 + Blue;
X break;
X }
X
X if (colour != Last_Colour)
X {
X SetAPen (&(s -> RastPort), colour);
X Last_Colour = colour;
X }
X WritePixel (&(s -> RastPort), x+1, y);
X }
X
END_OF_FILE
if test 6939 -ne `wc -c <'src/amiga.c'`; then
echo shar: \"'src/amiga.c'\" unpacked with wrong size!
fi
# end of 'src/amiga.c'
fi
if test -f 'src/csg.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/csg.c'\"
else
echo shar: Extracting \"'src/csg.c'\" \(7895 characters\)
sed "s/^X//" >'src/csg.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X* csg.c
X*
X* from DKBTrace (c) 1990 David Buck
X*
X* This module implements routines for constructive solid geometry.
X*
X* This software is freely distributable. The source and/or object code may be
X* copied or uploaded to communications services so long as this notice remains
X* at the top of each file. If any changes are made to the program, you must
X* clearly indicate in the documentation and in the programs startup message
X* who it was who made the changes. The documentation should also describe what
X* those changes were. This software may not be included in whole or in
X* part into any commercial package without the express written consent of the
X* author. It may, however, be included in other public domain or freely
X* distributed software so long as the proper credit for the software is given.
X*
X* This software is provided as is without any guarantees or warranty. Although
X* the author has attempted to find and correct any bugs in the software, he
X* is not responsible for any damage caused by the use of the software. The
X* author is under no obligation to provide service, corrections, or upgrades
X* to this package.
X*
X* Despite all the legal stuff above, if you do find bugs, I would like to hear
X* about them. Also, if you have any comments or questions, you may contact me
X* at the following address:
X*
X* David Buck
X* 22C Sonnet Cres.
X* Nepean Ontario
X* Canada, K2H 8W7
X*
X* I can also be reached on the following bulleton boards:
X*
X* ATX (613) 526-4141
X* OMX (613) 731-3419
X* Mystic (613) 731-0088 or (613) 731-6698
X*
X* Fidonet: 1:163/109.9
X* Internet: David_Buck@Carleton.CA
X*
X* IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
X*
X* Lattice BBS (708) 916-1200
X* The Information Exchange BBS (708) 945-5575
X* Stillwaters BBS (708) 403-2826
X*
X*****************************************************************************/
X
X
X#include "frame.h"
X#include "vector.h"
X#include "dkbproto.h"
X
XMETHODS CSG_Union_Methods =
X { Object_Intersect, All_CSG_Union_Intersections,
X Inside_CSG_Union, NULL,
X Copy_CSG,
X Translate_CSG, Rotate_CSG,
X Scale_CSG, Invert_CSG};
X
XMETHODS CSG_Intersection_Methods =
X { Object_Intersect, All_CSG_Intersection_Intersections,
X Inside_CSG_Intersection, NULL,
X Copy_CSG,
X Translate_CSG, Rotate_CSG,
X Scale_CSG, Invert_CSG};
X
Xextern RAY *VP_Ray;
Xextern unsigned long Options;
X
Xint All_CSG_Union_Intersections (Object, Ray, Depth_Queue)
X OBJECT *Object;
X RAY *Ray;
X PRIOQ *Depth_Queue;
X {
X register int Intersection_Found;
X CSG_SHAPE *Shape = (CSG_SHAPE *) Object;
X SHAPE *Local_Shape;
X
X Intersection_Found = FALSE;
X for (Local_Shape = Shape -> Shapes;
X Local_Shape != NULL ;
X Local_Shape = Local_Shape -> Next_Object)
X
X if (All_Intersections ((OBJECT *) Local_Shape, Ray, Depth_Queue))
X Intersection_Found = TRUE;
X
X return (Intersection_Found);
X }
X
Xint All_CSG_Intersection_Intersections (Object, Ray, Depth_Queue)
X OBJECT *Object;
X RAY *Ray;
X PRIOQ *Depth_Queue;
X {
X int Intersection_Found, Any_Intersection_Found;
X CSG_SHAPE *Shape = (CSG_SHAPE *) Object;
X SHAPE *Local_Shape, *Shape2;
X PRIOQ *Local_Depth_Queue;
X INTERSECTION *Local_Intersection;
X
X Local_Depth_Queue = pq_new (128);
X
X Any_Intersection_Found = FALSE;
X
X for (Local_Shape = Shape -> Shapes ;
X Local_Shape != NULL ;
X Local_Shape = Local_Shape -> Next_Object) {
X
X All_Intersections ((OBJECT *) Local_Shape, Ray, Local_Depth_Queue);
X
X for (Local_Intersection = pq_get_highest (Local_Depth_Queue);
X Local_Intersection != NULL ;
X pq_delete_highest (Local_Depth_Queue),
X Local_Intersection = pq_get_highest (Local_Depth_Queue)) {
X
X Intersection_Found = TRUE;
X
X for (Shape2 = Shape -> Shapes;
X Shape2 != NULL ;
X Shape2 = Shape2 -> Next_Object)
X
X if (Shape2 != Local_Shape)
X if (!Inside (&Local_Intersection -> Point, (OBJECT *) Shape2)) {
X Intersection_Found = FALSE;
X break;
X }
X
X if (Intersection_Found) {
X pq_add (Depth_Queue, Local_Intersection);
X Any_Intersection_Found = TRUE;
X }
X }
X }
X
X pq_free (Local_Depth_Queue);
X
X return (Any_Intersection_Found);
X }
X
Xint Inside_CSG_Union (Point, Object)
X VECTOR *Point;
X OBJECT *Object;
X {
X CSG_SHAPE *Shape = (CSG_SHAPE *) Object;
X SHAPE *Local_Shape;
X
X for (Local_Shape = Shape -> Shapes ;
X Local_Shape != NULL ;
X Local_Shape = Local_Shape -> Next_Object)
X
X if (Inside (Point, (OBJECT *) Local_Shape))
X return (TRUE);
X return (FALSE);
X }
X
Xint Inside_CSG_Intersection (Point, Object)
X OBJECT *Object;
X VECTOR *Point;
X {
X SHAPE *Local_Shape;
X CSG_SHAPE *Shape = (CSG_SHAPE *) Object;
X
X for (Local_Shape = Shape -> Shapes ;
X Local_Shape != NULL ;
X Local_Shape = Local_Shape -> Next_Object)
X
X if (!Inside (Point, (OBJECT *) Local_Shape))
X return (FALSE);
X
X return (TRUE);
X }
X
Xvoid *Copy_CSG (Object)
X OBJECT *Object;
X {
X CSG_SHAPE *Shape = (CSG_SHAPE *) Object;
X CSG_SHAPE *New_Shape;
X SHAPE *Local_Shape, *Copied_Shape;
X
X New_Shape = Get_CSG_Shape ();
X New_Shape->Methods = Shape->Methods;
X New_Shape->Type = Shape->Type;
X New_Shape -> Next_Object = NULL;
X New_Shape -> Shapes = NULL;
X
X for (Local_Shape = Shape -> Shapes;
X Local_Shape != NULL ;
X Local_Shape = Local_Shape -> Next_Object) {
X
X Copied_Shape = (SHAPE *) Copy ((OBJECT *) Local_Shape);
X Link ((OBJECT *) Copied_Shape,
X (OBJECT **) &(Copied_Shape -> Next_Object),
X (OBJECT **) &(New_Shape -> Shapes));
X }
X return (New_Shape);
X }
X
Xvoid Translate_CSG (Object, Vector)
X OBJECT *Object;
X VECTOR *Vector;
X {
X SHAPE *Local_Shape;
X
X for (Local_Shape = ((CSG_SHAPE *) Object) -> Shapes;
X Local_Shape != NULL ;
X Local_Shape = Local_Shape -> Next_Object)
X
X Translate ((OBJECT *) Local_Shape, Vector);
X }
X
Xvoid Rotate_CSG (Object, Vector)
X OBJECT *Object;
X VECTOR *Vector;
X {
X SHAPE *Local_Shape;
X
X for (Local_Shape = ((CSG_SHAPE *) Object) -> Shapes;
X Local_Shape != NULL ;
X Local_Shape = Local_Shape -> Next_Object)
X
X Rotate ((OBJECT *) Local_Shape, Vector);
X }
X
Xvoid Scale_CSG (Object, Vector)
X OBJECT *Object;
X VECTOR *Vector;
X {
X SHAPE *Local_Shape;
X
X for (Local_Shape = ((CSG_SHAPE *) Object) -> Shapes;
X Local_Shape != NULL ;
X Local_Shape = Local_Shape -> Next_Object)
X
X Scale ((OBJECT *) Local_Shape, Vector);
X }
X
Xvoid Invert_CSG (Object)
X OBJECT *Object;
X {
X SHAPE *Local_Shape;
X CSG_SHAPE *Csg = (CSG_SHAPE *) Object;
X
X if (Csg->Type == CSG_INTERSECTION_TYPE) {
X Csg->Type = CSG_UNION_TYPE;
X Csg->Methods = &CSG_Union_Methods;
X }
X else if (Csg->Type == CSG_UNION_TYPE) {
X Csg->Type = CSG_INTERSECTION_TYPE;
X Csg->Methods = &CSG_Intersection_Methods;
X }
X
X for (Local_Shape = Csg -> Shapes;
X Local_Shape != NULL ;
X Local_Shape = Local_Shape -> Next_Object)
X
X Invert ((OBJECT *) Local_Shape);
X }
X
Xvoid Set_CSG_Parents (Shape, Object)
X CSG_SHAPE *Shape;
X OBJECT *Object;
X {
X SHAPE *Local_Shape;
X
X for (Local_Shape = Shape -> Shapes;
X Local_Shape != NULL ;
X Local_Shape = Local_Shape -> Next_Object) {
X
X Local_Shape->Parent_Object = Object;
X if ((Local_Shape->Type == CSG_UNION_TYPE) ||
X (Local_Shape->Type == CSG_INTERSECTION_TYPE))
X Set_CSG_Parents((CSG_SHAPE *)Local_Shape, Object);
X }
X }
X
END_OF_FILE
if test 7895 -ne `wc -c <'src/csg.c'`; then
echo shar: \"'src/csg.c'\" unpacked with wrong size!
fi
# end of 'src/csg.c'
fi
if test -f 'src/gif.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/gif.c'\"
else
echo shar: Extracting \"'src/gif.c'\" \(7511 characters\)
sed "s/^X//" >'src/gif.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X* gif.c
X*
X* from DKBTrace (c) 1990 David Buck
X*
X* Gif-format file reader.
X*
X* NOTE: Portions of this module were written by Steve Bennett and are used
X* here with his permission.
X*
X* This software is freely distributable. The source and/or object code may be
X* copied or uploaded to communications services so long as this notice remains
X* at the top of each file. If any changes are made to the program, you must
X* clearly indicate in the documentation and in the programs startup message
X* who it was who made the changes. The documentation should also describe what
X* those changes were. This software may not be included in whole or in
X* part into any commercial package without the express written consent of the
X* author. It may, however, be included in other public domain or freely
X* distributed software so long as the proper credit for the software is given.
X*
X* This software is provided as is without any guarantees or warranty. Although
X* the author has attempted to find and correct any bugs in the software, he
X* is not responsible for any damage caused by the use of the software. The
X* author is under no obligation to provide service, corrections, or upgrades
X* to this package.
X*
X* Despite all the legal stuff above, if you do find bugs, I would like to hear
X* about them. Also, if you have any comments or questions, you may contact me
X* at the following address:
X*
X* David Buck
X* 22C Sonnet Cres.
X* Nepean Ontario
X* Canada, K2H 8W7
X*
X* I can also be reached on the following bulleton boards:
X*
X* ATX (613) 526-4141
X* OMX (613) 731-3419
X* Mystic (613) 731-0088 or (613) 731-6698
X*
X* Fidonet: 1:163/109.9
X* Internet: David_Buck@Carleton.CA
X*
X* IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
X*
X* Lattice BBS (708) 916-1200
X* The Information Exchange BBS (708) 945-5575
X* Stillwaters BBS (708) 403-2826
X*
X*****************************************************************************/
X
X/*
X The following routines were borrowed freely from FRACTINT, and represent
X a generalized GIF file decoder. This seems the best, most universal format
X for reading in Bitmapped images. GIF is a Copyright of Compuserve, Inc.
X Swiped and converted to entirely "C" coded routines by AAC for the most
X in future portability!
X*/
X
X#include "frame.h"
X#include "dkbproto.h"
X
Xstatic IMAGE *Current_Image;
Xstatic int Bitmap_Line;
Xstatic FILE *Bit_File;
Xunsigned char *decoderline /* [2049] */ ; /* write-line routines use this */
X
Xstatic IMAGE_COLOUR *gif_colour_map;
Xstatic int colourmap_size;
X
Xint out_line (pixels, linelen)
X unsigned char *pixels;
X int linelen;
X {
X register int x;
X register unsigned addr;
X
X addr = linelen * Bitmap_Line--;
X
X for (x = 0; x < linelen; x++) {
X Current_Image->red[addr+x] = gif_colour_map[*pixels].Red;
X Current_Image->green[addr+x] = gif_colour_map[*pixels].Green;
X Current_Image->blue[addr+x] = gif_colour_map[*pixels].Blue;
X pixels++;
X }
X
X return (0);
X }
X
X#define READ_ERROR -1
X
Xint get_byte() /* get byte from file, return the next byte or an error */
X {
X register int byte;
X
X if ((byte = getc(Bit_File)) != EOF)
X return (byte);
X else {
X printf ("Premature end of file reading GIF image\n");
X exit (1);
X }
X return (0); /* Keep the compiler happy */
X }
X
X/* Main GIF file decoder. */
X
Xvoid read_gif_image(Image, filename)
X IMAGE *Image;
X char *filename;
X {
X register int i, j, status;
X unsigned finished, planes;
X unsigned char buffer[16];
X
X status = 0;
X Current_Image = Image;
X
X if ((Bit_File = fopen(filename, "rb")) == NULL) {
X printf ("Cannot open GIF file %s\n", filename);
X exit(1);
X }
X
X /* zero out the full write-line */
X if ((decoderline = (unsigned char *) malloc (2049)) == NULL) {
X printf ("Cannot allocate space for gif decoder line\n");
X fclose (Bit_File);
X exit (1);
X }
X
X for (i = 0; i < 2049; i++)
X decoderline[i] = (unsigned char) 0;
X
X /* Get the screen description */
X for (i = 0; i < 13; i++)
X buffer[i] = (unsigned char)get_byte();
X
X if (strncmp(buffer,"GIF87a",3) || /* use updated GIF specs */
X buffer[3] < '0' || buffer[3] > '9' ||
X buffer[4] < '0' || buffer[4] > '9' ||
X buffer[5] < 'A' || buffer[5] > 'z' ) {
X
X printf ("Invalid GIF file format: %s\n", filename);
X fclose(Bit_File);
X exit (1);
X }
X
X planes = ((unsigned)buffer[10] & 0x0F) + 1;
X colourmap_size = (int)(1 << planes);
X if ((gif_colour_map = (IMAGE_COLOUR *)
X malloc (colourmap_size * sizeof (IMAGE_COLOUR))) == NULL) {
X printf ("Cannot allocate gif colour map\n");
X fclose (Bit_File);
X exit (1);
X }
X
X if ((buffer[10] & 0x80) == 0) { /* color map (better be!) */
X printf ("Invalid GIF file format: %s\n", filename);
X fclose(Bit_File);
X exit (1);
X }
X
X for (i = 0; i < colourmap_size ; i++) {
X gif_colour_map[i].Red = (unsigned char)get_byte();
X gif_colour_map[i].Green = (unsigned char)get_byte();
X gif_colour_map[i].Blue = (unsigned char)get_byte();
X }
X
X /* Now display one or more GIF objects */
X finished = FALSE;
X while (!finished) {
X switch (get_byte()) {
X case ';': /* End of the GIF dataset */
X finished = TRUE;
X status = 0;
X break;
X
X case '!': /* GIF Extension Block */
X get_byte(); /* read (and ignore) the ID */
X while ((i = get_byte()) > 0) /* get data len*/
X for (j = 0; j < i; j++)
X get_byte(); /* flush data */
X break;
X
X case ',': /* Start of image object. get description */
X for (i = 0; i < 9; i++) {
X if ((buffer[i] = (unsigned char)get_byte()) < 0) {
X status = -1;
X break;
X }
X }
X
X if (status < 0) {
X finished = TRUE;
X break;
X }
X
X Image->iwidth = buffer[4] | (buffer[5] << 8);
X Image->iheight = buffer[6] | (buffer[7] << 8);
X Image->width = (DBL) Image->iwidth;
X Image->height = (DBL) Image->iheight;
X
X if (Image->iwidth > BITMAP_X_SIZE ||
X Image->iheight > BITMAP_Y_SIZE) {
X printf("\nBitmap File TOO BIG!!\n");
X fclose(Bit_File);
X exit (1);
X }
X
X Bitmap_Line = Image->iheight - 1;
X
X if (((Image->red = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL) ||
X ((Image->green = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL) ||
X ((Image->blue = (unsigned char *) malloc(Image->iwidth*Image->iheight))==NULL)) {
X printf ("Cannot allocate memory for picture\n");
X exit(1);
X }
X
X /* Setup the color palette for the image */
X status = decoder ((short) Image->iwidth); /*put bytes in Buf*/
X finished = TRUE;
X break;
X
X default:
X status = -1;
X finished = TRUE;
X break;
X }
X }
X
X free (decoderline);
X free (gif_colour_map);
X fclose(Bit_File);
X }
END_OF_FILE
if test 7511 -ne `wc -c <'src/gif.c'`; then
echo shar: \"'src/gif.c'\" unpacked with wrong size!
fi
# end of 'src/gif.c'
fi
if test -f 'src/iffw.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/iffw.c'\"
else
echo shar: Extracting \"'src/iffw.c'\" \(7573 characters\)
sed "s/^X//" >'src/iffw.c' <<'END_OF_FILE'
X/*----------------------------------------------------------------------*
X * IFFW.C Support routines for writing IFF-85 files. 1/23/86
X * (IFF is Interchange Format File.)
X *
X * By Jerry Morrison and Steve Shaw, Electronic Arts.
X * This software is in the public domain.
X *
X * This version for the Commodore-Amiga computer.
X *----------------------------------------------------------------------*/
X#include "iff/iff.h"
X#include "iff/gio.h"
X
X/* ---------- IFF Writer -----------------------------------------------*/
X
X/* A macro to test if a chunk size is definite, i.e. not szNotYetKnown.*/
X#define Known(size) ( (size) != szNotYetKnown )
X
X/* Yet another weird macro to make the source code simpler...*/
X#define IfIffp(expr) {if (iffp == IFF_OKAY) iffp = (expr);}
X
X/* ---------- OpenWIFF -------------------------------------------------*/
X
XIFFP OpenWIFF(file, new0, limit) BPTR file; GroupContext *new0; LONG limit; {
X register GroupContext *new = new0;
X register IFFP iffp = IFF_OKAY;
X
X new->parent = NULL;
X new->clientFrame = NULL;
X new->file = file;
X new->position = 0;
X new->bound = limit;
X new->ckHdr.ckID = NULL_CHUNK; /* indicates no current chunk */
X new->ckHdr.ckSize = new->bytesSoFar = 0;
X
X if (0 > Seek(file, 0, OFFSET_BEGINNING)) /* Go to start of the file.*/
X iffp = DOS_ERROR;
X else if ( Known(limit) && IS_ODD(limit) )
X iffp = CLIENT_ERROR;
X return(iffp);
X }
X
X/* ---------- StartWGroup ----------------------------------------------*/
XIFFP StartWGroup(parent, groupType, groupSize, subtype, new)
X GroupContext *parent, *new; ID groupType, subtype; LONG groupSize; {
X register IFFP iffp;
X
X iffp = PutCkHdr(parent, groupType, groupSize);
X IfIffp( IFFWriteBytes(parent, (BYTE *)&subtype, sizeof(ID)) );
X IfIffp( OpenWGroup(parent, new) );
X return(iffp);
X }
X
X/* ---------- OpenWGroup -----------------------------------------------*/
XIFFP OpenWGroup(parent0, new0) GroupContext *parent0, *new0; {
X register GroupContext *parent = parent0;
X register GroupContext *new = new0;
X register LONG ckEnd;
X register IFFP iffp = IFF_OKAY;
X
X new->parent = parent;
X new->clientFrame = parent->clientFrame;
X new->file = parent->file;
X new->position = parent->position;
X new->bound = parent->bound;
X new->ckHdr.ckID = NULL_CHUNK;
X new->ckHdr.ckSize = new->bytesSoFar = 0;
X
X if ( Known(parent->ckHdr.ckSize) ) {
X ckEnd = new->position + ChunkMoreBytes(parent);
X if ( new->bound == szNotYetKnown || new->bound > ckEnd )
X new->bound = ckEnd;
X };
X
X if ( parent->ckHdr.ckID == NULL_CHUNK || /* not currently writing a chunk*/
X IS_ODD(new->position) ||
X (Known(new->bound) && IS_ODD(new->bound)) )
X iffp = CLIENT_ERROR;
X return(iffp);
X }
X
X/* ---------- CloseWGroup ----------------------------------------------*/
XIFFP CloseWGroup(old0) GroupContext *old0; {
X register GroupContext *old = old0;
X IFFP iffp = IFF_OKAY;
X
X if ( old->ckHdr.ckID != NULL_CHUNK ) /* didn't close the last chunk */
X iffp = CLIENT_ERROR;
X else if ( old->parent == NULL ) { /* top level file context */
X if (GWriteFlush(old->file) < 0) iffp = DOS_ERROR;
X }
X else { /* update parent context */
X old->parent->bytesSoFar += old->position - old->parent->position;
X old->parent->position = old->position;
X };
X return(iffp);
X }
X
X/* ---------- EndWGroup ------------------------------------------------*/
XIFFP EndWGroup(old) GroupContext *old; {
X register GroupContext *parent = old->parent;
X register IFFP iffp;
X
X iffp = CloseWGroup(old);
X IfIffp( PutCkEnd(parent) );
X return(iffp);
X }
X
X/* ---------- PutCk ----------------------------------------------------*/
XIFFP PutCk(context, ckID, ckSize, data)
X GroupContext *context; ID ckID; LONG ckSize; BYTE *data; {
X register IFFP iffp = IFF_OKAY;
X
X if ( ckSize == szNotYetKnown )
X iffp = CLIENT_ERROR;
X IfIffp( PutCkHdr(context, ckID, ckSize) );
X IfIffp( IFFWriteBytes(context, data, ckSize) );
X IfIffp( PutCkEnd(context) );
X return(iffp);
X }
X
X/* ---------- PutCkHdr -------------------------------------------------*/
XIFFP PutCkHdr(context0, ckID, ckSize)
X GroupContext *context0; ID ckID; LONG ckSize; {
X register GroupContext *context = context0;
X LONG minPSize = sizeof(ChunkHeader); /* physical chunk >= minPSize bytes*/
X
X /* CLIENT_ERROR if we're already inside a chunk or asked to write
X * other than one FORM, LIST, or CAT at the top level of a file */
X /* Also, non-positive ID values are illegal and used for error codes.*/
X /* (We could check for other illegal IDs...)*/
X if ( context->ckHdr.ckID != NULL_CHUNK || ckID <= 0 )
X return(CLIENT_ERROR);
X else if (context->parent == NULL) {
X switch (ckID) {
X case FORM: case LIST: case CAT: break;
X default: return(CLIENT_ERROR);
X }
X if (context->position != 0)
X return(CLIENT_ERROR);
X }
X
X if ( Known(ckSize) ) {
X if ( ckSize < 0 )
X return(CLIENT_ERROR);
X minPSize += ckSize;
X };
X if ( Known(context->bound) &&
X context->position + minPSize > context->bound )
X return(CLIENT_ERROR);
X
X context->ckHdr.ckID = ckID;
X context->ckHdr.ckSize = ckSize;
X context->bytesSoFar = 0;
X if (0 >
X GWrite(context->file, (BYTE *)&context->ckHdr, sizeof(ChunkHeader))
X )
X return(DOS_ERROR);
X context->position += sizeof(ChunkHeader);
X return(IFF_OKAY);
X }
X
X/* ---------- IFFWriteBytes ---------------------------------------------*/
XIFFP IFFWriteBytes(context0, data, nBytes)
X GroupContext *context0; BYTE *data; LONG nBytes; {
X register GroupContext *context = context0;
X
X if ( context->ckHdr.ckID == NULL_CHUNK || /* not in a chunk */
X nBytes < 0 || /* negative nBytes */
X (Known(context->bound) && /* overflow context */
X context->position + nBytes > context->bound) ||
X (Known(context->ckHdr.ckSize) && /* overflow chunk */
X context->bytesSoFar + nBytes > context->ckHdr.ckSize) )
X return(CLIENT_ERROR);
X
X if (0 > GWrite(context->file, data, nBytes))
X return(DOS_ERROR);
X
X context->bytesSoFar += nBytes;
X context->position += nBytes;
X return(IFF_OKAY);
X }
X
X/* ---------- PutCkEnd -------------------------------------------------*/
XIFFP PutCkEnd(context0) GroupContext *context0; {
X register GroupContext *context = context0;
X WORD zero = 0; /* padding source */
X
X if ( context->ckHdr.ckID == NULL_CHUNK ) /* not in a chunk */
X return(CLIENT_ERROR);
X
X if ( context->ckHdr.ckSize == szNotYetKnown ) {
X /* go back and set the chunk size to bytesSoFar */
X if ( 0 >
XGSeek(context->file, -(context->bytesSoFar + sizeof(LONG)), OFFSET_CURRENT) ||
X 0 >
XGWrite(context->file, (BYTE *)&context->bytesSoFar, sizeof(LONG)) ||
X 0 >
XGSeek(context->file, context->bytesSoFar, OFFSET_CURRENT) )
X return(DOS_ERROR);
X }
X else { /* make sure the client wrote as many bytes as planned */
X if ( context->ckHdr.ckSize != context->bytesSoFar )
X return(CLIENT_ERROR);
X };
X
X /* Write a pad byte if needed to bring us up to an even boundary.
X * Since the context end must be even, and since we haven't
X * overwritten the context, if we're on an odd position there must
X * be room for a pad byte. */
X if ( IS_ODD(context->bytesSoFar) ) {
X if ( 0 > GWrite(context->file, (BYTE *)&zero, 1) )
X return(DOS_ERROR);
X context->position += 1;
X };
X
X context->ckHdr.ckID = NULL_CHUNK;
X context->ckHdr.ckSize = context->bytesSoFar = 0;
X return(IFF_OKAY);
X }
X
END_OF_FILE
if test 7573 -ne `wc -c <'src/iffw.c'`; then
echo shar: \"'src/iffw.c'\" unpacked with wrong size!
fi
# end of 'src/iffw.c'
fi
if test -f 'src/matrices.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/matrices.c'\"
else
echo shar: Extracting \"'src/matrices.c'\" \(9507 characters\)
sed "s/^X//" >'src/matrices.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X* matrices.c
X*
X* from DKBTrace (c) 1990 David Buck
X*
X* This module contains code to manipulate 4x4 matrices.
X*
X* This software is freely distributable. The source and/or object code may be
X* copied or uploaded to communications services so long as this notice remains
X* at the top of each file. If any changes are made to the program, you must
X* clearly indicate in the documentation and in the programs startup message
X* who it was who made the changes. The documentation should also describe what
X* those changes were. This software may not be included in whole or in
X* part into any commercial package without the express written consent of the
X* author. It may, however, be included in other public domain or freely
X* distributed software so long as the proper credit for the software is given.
X*
X* This software is provided as is without any guarantees or warranty. Although
X* the author has attempted to find and correct any bugs in the software, he
X* is not responsible for any damage caused by the use of the software. The
X* author is under no obligation to provide service, corrections, or upgrades
X* to this package.
X*
X* Despite all the legal stuff above, if you do find bugs, I would like to hear
X* about them. Also, if you have any comments or questions, you may contact me
X* at the following address:
X*
X* David Buck
X* 22C Sonnet Cres.
X* Nepean Ontario
X* Canada, K2H 8W7
X*
X* I can also be reached on the following bulleton boards:
X*
X* ATX (613) 526-4141
X* OMX (613) 731-3419
X* Mystic (613) 731-0088 or (613) 731-6698
X*
X* Fidonet: 1:163/109.9
X* Internet: David_Buck@Carleton.CA
X*
X* IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
X*
X* Lattice BBS (708) 916-1200
X* The Information Exchange BBS (708) 945-5575
X* Stillwaters BBS (708) 403-2826
X*
X*****************************************************************************/
X
X
X#include "frame.h"
X#include "vector.h"
X#include "dkbproto.h"
X
X#ifndef PI
X#define PI 3.141592653689793
X#endif
X
Xvoid MZero (result)
X MATRIX *result;
X {
X/* Initialize the matrix to the following values:
X 0.0 0.0 0.0 0.0
X 0.0 0.0 0.0 0.0
X 0.0 0.0 0.0 0.0
X 0.0 0.0 0.0 0.0
X*/
X register int i, j;
X
X for (i = 0 ; i < 4 ; i++)
X for (j = 0 ; j < 4 ; j++)
X (*result)[i][j] = 0.0;
X }
X
Xvoid MIdentity (result)
X MATRIX *result;
X {
X/* Initialize the matrix to the following values:
X 1.0 0.0 0.0 0.0
X 0.0 1.0 0.0 0.0
X 0.0 0.0 1.0 0.0
X 0.0 0.0 0.0 1.0
X*/
X register int i, j;
X
X for (i = 0 ; i < 4 ; i++)
X for (j = 0 ; j < 4 ; j++)
X if (i == j)
X (*result)[i][j] = 1.0;
X else
X (*result)[i][j] = 0.0;
X }
X
Xvoid MTimes (result, matrix1, matrix2)
X MATRIX *result, *matrix1, *matrix2;
X {
X register int i, j, k;
X MATRIX temp_matrix;
X
X for (i = 0 ; i < 4 ; i++)
X for (j = 0 ; j < 4 ; j++) {
X temp_matrix[i][j] = 0.0;
X for (k = 0 ; k < 4 ; k++)
X temp_matrix[i][j] += (*matrix1)[i][k] * (*matrix2)[k][j];
X }
X
X for (i = 0 ; i < 4 ; i++)
X for (j = 0 ; j < 4 ; j++)
X (*result)[i][j] = temp_matrix[i][j];
X }
X
X
Xvoid MAdd (result, matrix1, matrix2)
X MATRIX *result, *matrix1, *matrix2;
X {
X register int i, j;
X
X for (i = 0 ; i < 4 ; i++)
X for (j = 0 ; j < 4 ; j++)
X (*result)[i][j] = (*matrix1)[i][j] + (*matrix2)[i][j];
X }
X
Xvoid MSub (result, matrix1, matrix2)
X MATRIX *result, *matrix1, *matrix2;
X {
X register int i, j;
X
X for (i = 0 ; i < 4 ; i++)
X for (j = 0 ; j < 4 ; j++)
X (*result)[i][j] = (*matrix1)[i][j] - (*matrix2)[i][j];
X }
X
Xvoid MScale (result, matrix1, amount)
XMATRIX *result, *matrix1;
XDBL amount;
X{
X register int i, j;
X
X for (i = 0 ; i < 4 ; i++)
X for (j = 0 ; j < 4 ; j++)
X if (amount == 1.0)
X (*result)[i][j] = (*matrix1)[i][j]; /* just copy */
X else
X (*result)[i][j] = (*matrix1)[i][j] * amount;
X return;
X}
X
Xvoid MTranspose (result, matrix1)
X MATRIX *result, *matrix1;
X {
X register int i, j;
X MATRIX temp_matrix;
X
X for (i = 0 ; i < 4 ; i++)
X for (j = 0 ; j < 4 ; j++)
X temp_matrix[i][j] = (*matrix1)[j][i];
X
X for (i = 0 ; i < 4 ; i++)
X for (j = 0 ; j < 4 ; j++)
X (*result)[i][j] = temp_matrix[i][j];
X }
X
X
Xvoid MTransformVector (result, vector, transformation)
X VECTOR *result, *vector;
X TRANSFORMATION *transformation;
X {
X register int i;
X DBL answer_array[4];
X MATRIX *matrix;
X
X matrix = &transformation -> matrix;
X
X for (i = 0 ; i < 4 ; i++)
X answer_array[i] = vector -> x * (*matrix)[0][i]
X + vector -> y * (*matrix)[1][i]
X + vector -> z * (*matrix)[2][i]
X + (*matrix)[3][i];
X
X result -> x = answer_array[0];
X result -> y = answer_array[1];
X result -> z = answer_array[2];
X }
X
Xvoid MInverseTransformVector (result, vector, transformation)
X VECTOR *result, *vector;
X TRANSFORMATION *transformation;
X {
X register int i;
X DBL answer_array[4];
X MATRIX *matrix;
X
X matrix = &transformation -> inverse;
X
X for (i = 0 ; i < 4 ; i++)
X answer_array[i] = vector -> x * (*matrix)[0][i]
X + vector -> y * (*matrix)[1][i]
X + vector -> z * (*matrix)[2][i]
X + (*matrix)[3][i];
X
X result -> x = answer_array[0];
X result -> y = answer_array[1];
X result -> z = answer_array[2];
X }
X
Xvoid Get_Scaling_Transformation (result, vector)
X TRANSFORMATION *result;
X VECTOR *vector;
X {
X MIdentity (&result -> matrix);
X (result -> matrix)[0][0] = vector -> x;
X (result -> matrix)[1][1] = vector -> y;
X (result -> matrix)[2][2] = vector -> z;
X
X MIdentity (&result -> inverse);
X (result -> inverse)[0][0] = 1.0 / vector -> x;
X (result -> inverse)[1][1]= 1.0 / vector -> y;
X (result -> inverse)[2][2] = 1.0 / vector -> z;
X }
X
Xvoid Get_Inversion_Transformation (result)
X TRANSFORMATION *result;
X {
X MIdentity (&result -> matrix);
X (result -> matrix)[0][0] = -1.0;
X (result -> matrix)[1][1] = -1.0;
X (result -> matrix)[2][2] = -1.0;
X (result -> matrix)[3][3] = -1.0;
X
X
X (result -> inverse)[0][0] = -1.0;
X (result -> inverse)[1][1] = -1.0;
X (result -> inverse)[2][2] = -1.0;
X (result -> inverse)[3][3] = -1.0;
X }
X
Xvoid Get_Translation_Transformation (transformation, vector)
X TRANSFORMATION *transformation;
X VECTOR *vector;
X {
X MIdentity (&transformation -> matrix);
X (transformation -> matrix)[3][0] = vector -> x;
X (transformation -> matrix)[3][1] = vector -> y;
X (transformation -> matrix)[3][2] = vector -> z;
X
X MIdentity (&transformation -> inverse);
X (transformation -> inverse)[3][0] = 0.0 - vector -> x;
X (transformation -> inverse)[3][1] = 0.0 - vector -> y;
X (transformation -> inverse)[3][2] = 0.0 - vector -> z;
X }
X
Xvoid Get_Rotation_Transformation (transformation, vector)
X TRANSFORMATION *transformation;
X VECTOR *vector;
X {
X MATRIX Matrix;
X VECTOR Radian_Vector;
X register DBL cosx, cosy, cosz, sinx, siny, sinz;
X
X VScale (Radian_Vector, *vector, PI/180.0);
X MIdentity (&transformation -> matrix);
X cosx = cos (Radian_Vector.x);
X sinx = sin (Radian_Vector.x);
X cosy = cos (Radian_Vector.y);
X siny = sin (Radian_Vector.y);
X cosz = cos (Radian_Vector.z);
X sinz = sin (Radian_Vector.z);
X
X (transformation -> matrix) [1][1] = cosx;
X (transformation -> matrix) [2][2] = cosx;
X (transformation -> matrix) [1][2] = 0.0 - sinx;
X (transformation -> matrix) [2][1] = sinx;
X MTranspose (&transformation -> inverse, &transformation -> matrix);
X
X MIdentity (&Matrix);
X Matrix [0][0] = cosy;
X Matrix [2][2] = cosy;
X Matrix [0][2] = siny;
X Matrix [2][0] = 0.0 - siny;
X MTimes (&transformation -> matrix, &transformation -> matrix, &Matrix);
X MTranspose (&Matrix, &Matrix);
X MTimes (&transformation -> inverse, &Matrix, &transformation -> inverse);
X
X MIdentity (&Matrix);
X Matrix [0][0] = cosz;
X Matrix [1][1] = cosz;
X Matrix [0][1] = 0.0 - sinz;
X Matrix [1][0] = sinz;
X MTimes (&transformation -> matrix, &transformation -> matrix, &Matrix);
X MTranspose (&Matrix, &Matrix);
X MTimes (&transformation -> inverse, &Matrix, &transformation -> inverse);
X }
X
Xvoid Get_Look_At_Transformation (result, Look_At, Up, Right)
X TRANSFORMATION *result;
X VECTOR *Look_At, *Up, *Right;
X {
X MIdentity (&result -> inverse);
X (result -> matrix)[0][0] = Right->x;
X (result -> matrix)[0][1] = Right->y;
X (result -> matrix)[0][2] = Right->z;
X (result -> matrix)[1][0] = Up->x;
X (result -> matrix)[1][1] = Up->y;
X (result -> matrix)[1][2] = Up->z;
X (result -> matrix)[2][0] = Look_At->x;
X (result -> matrix)[2][1] = Look_At->y;
X (result -> matrix)[2][2] = Look_At->z;
X
X MIdentity (&result -> matrix);
X MTranspose (&result -> matrix, &result -> inverse);
X }
X
Xvoid Compose_Transformations (Original_Transformation, New_Transformation)
X TRANSFORMATION *Original_Transformation, *New_Transformation;
X {
X MTimes (&Original_Transformation -> matrix,
X &Original_Transformation -> matrix,
X &New_Transformation -> matrix);
X
X MTimes (&Original_Transformation -> inverse,
X &New_Transformation -> inverse,
X &Original_Transformation -> inverse);
X }
END_OF_FILE
if test 9507 -ne `wc -c <'src/matrices.c'`; then
echo shar: \"'src/matrices.c'\" unpacked with wrong size!
fi
# end of 'src/matrices.c'
fi
if test -f 'src/planes.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/planes.c'\"
else
echo shar: Extracting \"'src/planes.c'\" \(6704 characters\)
sed "s/^X//" >'src/planes.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X* planes.c
X*
X* from DKBTrace (c) 1990 David Buck
X*
X* This module implements functions that manipulate planes.
X*
X* This software is freely distributable. The source and/or object code may be
X* copied or uploaded to communications services so long as this notice remains
X* at the top of each file. If any changes are made to the program, you must
X* clearly indicate in the documentation and in the programs startup message
X* who it was who made the changes. The documentation should also describe what
X* those changes were. This software may not be included in whole or in
X* part into any commercial package without the express written consent of the
X* author. It may, however, be included in other public domain or freely
X* distributed software so long as the proper credit for the software is given.
X*
X* This software is provided as is without any guarantees or warranty. Although
X* the author has attempted to find and correct any bugs in the software, he
X* is not responsible for any damage caused by the use of the software. The
X* author is under no obligation to provide service, corrections, or upgrades
X* to this package.
X*
X* Despite all the legal stuff above, if you do find bugs, I would like to hear
X* about them. Also, if you have any comments or questions, you may contact me
X* at the following address:
X*
X* David Buck
X* 22C Sonnet Cres.
X* Nepean Ontario
X* Canada, K2H 8W7
X*
X* I can also be reached on the following bulleton boards:
X*
X* ATX (613) 526-4141
X* OMX (613) 731-3419
X* Mystic (613) 731-0088 or (613) 731-6698
X*
X* Fidonet: 1:163/109.9
X* Internet: David_Buck@Carleton.CA
X*
X* IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
X*
X* Lattice BBS (708) 916-1200
X* The Information Exchange BBS (708) 945-5575
X* Stillwaters BBS (708) 403-2826
X*
X*****************************************************************************/
X
X
X#include "frame.h"
X#include "vector.h"
X#include "dkbproto.h"
X
XMETHODS Plane_Methods =
X { Object_Intersect, All_Plane_Intersections,
X Inside_Plane, Plane_Normal,
X Copy_Plane,
X Translate_Plane, Rotate_Plane,
X Scale_Plane, Invert_Plane};
X
X#define Small_Tolerance 0.001
X
Xextern PLANE *Get_Plane_Shape();
X
Xextern RAY *VP_Ray;
Xextern long Ray_Plane_Tests, Ray_Plane_Tests_Succeeded;
X
Xint All_Plane_Intersections (Object, Ray, Depth_Queue)
X OBJECT *Object;
X RAY *Ray;
X PRIOQ *Depth_Queue;
X {
X PLANE *Shape = (PLANE *) Object;
X DBL Depth;
X VECTOR Intersection_Point;
X INTERSECTION Local_Element;
X
X if (Intersect_Plane (Ray, Shape, &Depth))
X if (Depth > Small_Tolerance)
X {
X Local_Element.Depth = Depth;
X Local_Element.Object = Shape -> Parent_Object;
X VScale (Intersection_Point, Ray -> Direction, Depth);
X VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
X Local_Element.Point = Intersection_Point;
X Local_Element.Shape = (SHAPE *)Shape;
X pq_add (Depth_Queue, &Local_Element);
X return (TRUE);
X }
X
X return (FALSE);
X }
X
Xint Intersect_Plane (Ray, Plane, Depth)
X RAY *Ray;
X PLANE *Plane;
X DBL *Depth;
X {
X DBL NormalDotOrigin, NormalDotDirection;
X
X Ray_Plane_Tests++;
X if (Ray == VP_Ray) {
X if (!Plane->VPCached) {
X VDot (Plane->VPNormDotOrigin, Plane->Normal_Vector, Ray->Initial);
X Plane->VPNormDotOrigin += Plane->Distance;
X Plane->VPNormDotOrigin *= -1.0;
X Plane->VPCached = TRUE;
X }
X
X VDot (NormalDotDirection, Plane->Normal_Vector, Ray->Direction);
X if ((NormalDotDirection < Small_Tolerance) &&
X (NormalDotDirection > -Small_Tolerance))
X return (FALSE);
X
X *Depth = Plane->VPNormDotOrigin / NormalDotDirection;
X if ((*Depth >= Small_Tolerance) || (*Depth <= Max_Distance)) {
X Ray_Plane_Tests_Succeeded++;
X return (TRUE);
X }
X else
X return (FALSE);
X }
X else {
X VDot (NormalDotOrigin, Plane->Normal_Vector, Ray->Initial);
X NormalDotOrigin += Plane->Distance;
X NormalDotOrigin *= -1.0;
X
X VDot (NormalDotDirection, Plane->Normal_Vector, Ray->Direction);
X if ((NormalDotDirection < Small_Tolerance) &&
X (NormalDotDirection > -Small_Tolerance))
X return (FALSE);
X
X *Depth = NormalDotOrigin / NormalDotDirection;
X if ((*Depth >= Small_Tolerance) || (*Depth <= Max_Distance)) {
X Ray_Plane_Tests_Succeeded++;
X return (TRUE);
X }
X else
X return (FALSE);
X }
X }
X
Xint Inside_Plane (Point, Object)
X VECTOR *Point;
X OBJECT *Object;
X {
X PLANE *Plane = (PLANE *) Object;
X DBL Temp;
X
X VDot (Temp, *Point, Plane->Normal_Vector);
X return ((Temp + Plane->Distance) <= Small_Tolerance);
X }
X
Xvoid Plane_Normal (Result, Object, Intersection_Point)
X OBJECT *Object;
X VECTOR *Result, *Intersection_Point;
X {
X PLANE *Plane = (PLANE *) Object;
X
X *Result = Plane->Normal_Vector;
X Perturb_Normal (Result, Plane->Parent_Object,
X Intersection_Point, Result);
X }
X
Xvoid *Copy_Plane (Object)
X OBJECT *Object;
X {
X PLANE *New_Shape;
X
X New_Shape = Get_Plane_Shape ();
X *New_Shape = * ((PLANE *)Object);
X New_Shape -> Next_Object = NULL;
X return (New_Shape);
X }
X
Xvoid Translate_Plane (Object, Vector)
X OBJECT *Object;
X VECTOR *Vector;
X {
X PLANE *Plane = (PLANE *) Object;
X VECTOR Translation;
X
X VEvaluate (Translation, Plane->Normal_Vector, *Vector);
X Plane->Distance -= Translation.x + Translation.y + Translation.z;
X }
X
Xvoid Rotate_Plane (Object, Vector)
X OBJECT *Object;
X VECTOR *Vector;
X {
X TRANSFORMATION Transformation;
X
X Get_Rotation_Transformation (&Transformation, Vector);
X MTransformVector (&((PLANE *) Object)->Normal_Vector,
X &((PLANE *) Object)->Normal_Vector, &Transformation);
X }
X
Xvoid Scale_Plane (Object, Vector)
X OBJECT *Object;
X VECTOR *Vector;
X {
X DBL Length;
X PLANE *Plane = (PLANE *) Object;
X
X Plane->Normal_Vector.x = Plane->Normal_Vector.x / Vector->x;
X Plane->Normal_Vector.y = Plane->Normal_Vector.y / Vector->y;
X Plane->Normal_Vector.z = Plane->Normal_Vector.z / Vector->z;
X
X VLength(Length, Plane->Normal_Vector);
X VScale (Plane->Normal_Vector, Plane->Normal_Vector, 1.0 / Length);
X Plane->Distance /= Length;
X }
X
Xvoid Invert_Plane (Object)
X OBJECT *Object;
X {
X PLANE *Plane = (PLANE *) Object;
X
X VScale (Plane->Normal_Vector, Plane->Normal_Vector, -1.0);
X Plane->Distance *= -1.0;
X }
X
END_OF_FILE
if test 6704 -ne `wc -c <'src/planes.c'`; then
echo shar: \"'src/planes.c'\" unpacked with wrong size!
fi
# end of 'src/planes.c'
fi
if test -f 'src/spheres.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/spheres.c'\"
else
echo shar: Extracting \"'src/spheres.c'\" \(7715 characters\)
sed "s/^X//" >'src/spheres.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X* spheres.c
X*
X* from DKBTrace (c) 1990 David Buck
X*
X* This module implements the sphere primitive.
X*
X* This software is freely distributable. The source and/or object code may be
X* copied or uploaded to communications services so long as this notice remains
X* at the top of each file. If any changes are made to the program, you must
X* clearly indicate in the documentation and in the programs startup message
X* who it was who made the changes. The documentation should also describe what
X* those changes were. This software may not be included in whole or in
X* part into any commercial package without the express written consent of the
X* author. It may, however, be included in other public domain or freely
X* distributed software so long as the proper credit for the software is given.
X*
X* This software is provided as is without any guarantees or warranty. Although
X* the author has attempted to find and correct any bugs in the software, he
X* is not responsible for any damage caused by the use of the software. The
X* author is under no obligation to provide service, corrections, or upgrades
X* to this package.
X*
X* Despite all the legal stuff above, if you do find bugs, I would like to hear
X* about them. Also, if you have any comments or questions, you may contact me
X* at the following address:
X*
X* David Buck
X* 22C Sonnet Cres.
X* Nepean Ontario
X* Canada, K2H 8W7
X*
X* I can also be reached on the following bulleton boards:
X*
X* ATX (613) 526-4141
X* OMX (613) 731-3419
X* Mystic (613) 731-0088 or (613) 731-6698
X*
X* Fidonet: 1:163/109.9
X* Internet: David_Buck@Carleton.CA
X*
X* IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
X*
X* Lattice BBS (708) 916-1200
X* The Information Exchange BBS (708) 945-5575
X* Stillwaters BBS (708) 403-2826
X*
X*****************************************************************************/
X
X#include "frame.h"
X#include "vector.h"
X#include "dkbproto.h"
X
X#define Small_Tolerance 0.001
X
XMETHODS Sphere_Methods =
X { Object_Intersect, All_Sphere_Intersections,
X Inside_Sphere, Sphere_Normal,
X Copy_Sphere,
X Translate_Sphere, Rotate_Sphere,
X Scale_Sphere, Invert_Sphere};
X
Xextern SPHERE *Get_Sphere_Shape();
X
Xextern RAY *VP_Ray;
Xextern long Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded;
X
Xint All_Sphere_Intersections (Object, Ray, Depth_Queue)
X OBJECT *Object;
X RAY *Ray;
X PRIOQ *Depth_Queue;
X {
X DBL Depth1, Depth2;
X VECTOR Intersection_Point;
X INTERSECTION Local_Element;
X register int Intersection_Found;
X SPHERE *Shape = (SPHERE *) Object;
X
X Intersection_Found = FALSE;
X if (Intersect_Sphere (Ray, Shape, &Depth1, &Depth2))
X {
X Local_Element.Depth = Depth1;
X Local_Element.Object = Shape -> Parent_Object;
X VScale (Intersection_Point, Ray -> Direction, Depth1);
X VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
X Local_Element.Point = Intersection_Point;
X Local_Element.Shape = (SHAPE *)Shape;
X pq_add (Depth_Queue, &Local_Element);
X Intersection_Found = TRUE;
X
X if (Depth2 != Depth1)
X {
X Local_Element.Depth = Depth2;
X Local_Element.Object = Shape -> Parent_Object;
X VScale (Intersection_Point, Ray -> Direction, Depth2);
X VAdd (Intersection_Point, Intersection_Point, Ray -> Initial);
X Local_Element.Point = Intersection_Point;
X Local_Element.Shape = (SHAPE *) Shape;
X pq_add (Depth_Queue, &Local_Element);
X Intersection_Found = TRUE;
X }
X }
X return (Intersection_Found);
X }
X
Xint Intersect_Sphere (Ray, Sphere, Depth1, Depth2)
X RAY *Ray;
X SPHERE *Sphere;
X DBL *Depth1, *Depth2;
X {
X VECTOR Origin_To_Center;
X DBL OCSquared, t_Closest_Approach, Half_Chord, t_Half_Chord_Squared;
X short inside;
X
X Ray_Sphere_Tests++;
X if (Ray == VP_Ray) {
X if (!Sphere->VPCached) {
X VSub (Sphere->VPOtoC, Sphere->Center, Ray->Initial);
X VDot (Sphere->VPOCSquared, Sphere->VPOtoC, Sphere->VPOtoC);
X Sphere->VPinside = (Sphere->VPOCSquared < Sphere->Radius_Squared);
X Sphere->VPCached = TRUE;
X }
X VDot (t_Closest_Approach, Sphere->VPOtoC, Ray->Direction);
X if (!Sphere->VPinside && (t_Closest_Approach < Small_Tolerance))
X return (FALSE);
X t_Half_Chord_Squared = Sphere->Radius_Squared - Sphere->VPOCSquared +
X (t_Closest_Approach * t_Closest_Approach);
X }
X else {
X VSub (Origin_To_Center, Sphere->Center, Ray->Initial);
X VDot (OCSquared, Origin_To_Center, Origin_To_Center);
X inside = (OCSquared < Sphere->Radius_Squared);
X VDot (t_Closest_Approach, Origin_To_Center, Ray->Direction);
X if (!inside && (t_Closest_Approach < Small_Tolerance))
X return (FALSE);
X
X t_Half_Chord_Squared = Sphere->Radius_Squared - OCSquared +
X (t_Closest_Approach * t_Closest_Approach);
X }
X
X if (t_Half_Chord_Squared < Small_Tolerance)
X return (FALSE);
X
X Half_Chord = sqrt (t_Half_Chord_Squared);
X *Depth1 = t_Closest_Approach + Half_Chord;
X *Depth2 = t_Closest_Approach - Half_Chord;
X
X if ((*Depth1 < Small_Tolerance) || (*Depth1 > Max_Distance))
X if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
X return (FALSE);
X else
X *Depth1 = *Depth2;
X else
X if ((*Depth2 < Small_Tolerance) || (*Depth2 > Max_Distance))
X *Depth2 = *Depth1;
X
X Ray_Sphere_Tests_Succeeded++;
X return (TRUE);
X }
X
Xint Inside_Sphere (Point, Object)
X VECTOR *Point;
X OBJECT *Object;
X {
X VECTOR Origin_To_Center;
X DBL OCSquared;
X SPHERE *Sphere = (SPHERE *) Object;
X
X VSub (Origin_To_Center, Sphere->Center, *Point);
X VDot (OCSquared, Origin_To_Center, Origin_To_Center);
X
X if (Sphere->Inverted)
X return (OCSquared - Sphere->Radius_Squared > Small_Tolerance);
X else
X return (OCSquared - Sphere->Radius_Squared < Small_Tolerance);
X }
X
Xvoid Sphere_Normal (Result, Object, Intersection_Point)
X OBJECT *Object;
X VECTOR *Result, *Intersection_Point;
X {
X SPHERE *Sphere = (SPHERE *) Object;
X
X VSub (*Result, *Intersection_Point, Sphere->Center);
X VScale (*Result, *Result, Sphere->Inverse_Radius);
X Perturb_Normal (Result, Sphere -> Parent_Object,
X Intersection_Point, Result);
X }
X
Xvoid *Copy_Sphere (Object)
X OBJECT *Object;
X {
X SPHERE *New_Shape;
X
X New_Shape = Get_Sphere_Shape ();
X *New_Shape = *((SPHERE *) Object);
X New_Shape -> Next_Object = NULL;
X return (New_Shape);
X }
X
Xvoid Translate_Sphere (Object, Vector)
X OBJECT *Object;
X VECTOR *Vector;
X {
X VAdd (((SPHERE *) Object)->Center, ((SPHERE *) Object)->Center, *Vector);
X }
X
Xvoid Rotate_Sphere (Object, Vector)
X OBJECT *Object;
X VECTOR *Vector;
X {
X TRANSFORMATION Transformation;
X
X Get_Rotation_Transformation (&Transformation, Vector);
X MTransformVector (&((SPHERE *) Object)->Center,
X &((SPHERE *) Object)->Center, &Transformation);
X }
X
Xvoid Scale_Sphere (Object, Vector)
X OBJECT *Object;
X VECTOR *Vector;
X {
X SPHERE *Sphere = (SPHERE *) Object;
X
X if ((Vector->x != Vector->y) ||
X (Vector->x != Vector->z)) {
X printf ("Error - you cannot scale a sphere unevenly\n");
X exit (1);
X }
X
X VScale (Sphere->Center, Sphere->Center, Vector->x);
X Sphere->Radius *= Vector->x;
X Sphere->Radius_Squared = Sphere->Radius * Sphere->Radius;
X Sphere->Inverse_Radius = 1.0 / Sphere->Radius;
X }
X
Xvoid Invert_Sphere (Object)
X OBJECT *Object;
X {
X ((SPHERE *) Object)->Inverted ^= TRUE;
X }
END_OF_FILE
if test 7715 -ne `wc -c <'src/spheres.c'`; then
echo shar: \"'src/spheres.c'\" unpacked with wrong size!
fi
# end of 'src/spheres.c'
fi
echo shar: End of archive 3 \(of 10\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 10 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.