[comp.sources.amiga] v90i251: DKBTrace 2.01 - DKBtrace Ray-Tracer, Part03/10

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.