[comp.sources.amiga] v90i252: DKBTrace 2.01 - DKBtrace Ray-Tracer, Part04/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 252
Archive-name: applications/dkbtrace-2.01/part04

#!/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 4 (of 10)."
# Contents:  src/DumpToIFF.c src/ibm.c src/iff.c src/objects.c
#   src/quadrics.c
# Wrapped by tadguy@abcfd20 on Mon Sep  3 19:21:18 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/DumpToIFF.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/DumpToIFF.c'\"
else
echo shar: Extracting \"'src/DumpToIFF.c'\" \(13811 characters\)
sed "s/^X//" >'src/DumpToIFF.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X*                                   dumptoiff.c
X*
X*   from DKBTrace (c) 1990  David Buck
X*
X*  This file converts the raw output from the ray tracer into HAM files.
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*
X*****************************************************************************/
X
X
X#include <stdio.h>
X#include <exec/types.h>
X#include <intuition/intuition.h>
X#include <graphics/display.h>
X#include <libraries/dos.h>
X#include <proto/all.h>
X#include "config.h"
X#include "iff.h"
X#include "dumptoiff.h"
X#include "dumproto.h"
X
Xstruct IntuitionBase *IntuitionBase;
Xstruct GfxBase *GfxBase;
Xstruct Screen *s;
X
X#define extract_red(x) ((x & 0xF00) >> 8)
X#define extract_green(x) ((x & 0x0F0) >> 4)
X#define extract_blue(x) (x & 0x00F)
X
Xstruct NewScreen MyScreen =
X   {
X   0, 0,
X   SCREEN_WIDTH, SCREEN_HEIGHT,
X   6,
X   0, 1,
X   INTERLACE | HAM,
X   0,
X   NULL,
X   (UBYTE *) "DumpToIFF",
X   NULL,
X   NULL
X   };
X
XUWORD ColourTbl[16] = { 0x000, 0x111, 0x222, 0x333, 0x444, 0x555, 0x666,
X                        0x777, 0x888, 0x999, 0xaaa, 0xbbb, 0xccc, 0xddd,
X                        0xeee, 0xfff };
X
XLONG last_y = -1;
XIMAGE Raw_Image;
X
XFILE *fp, *palette_file, *output_palette_file;
Xchar input_filename[100], palette_filename[100], output_filename[100];
Xchar output_palette_filename[100];
X
X
Xint output_file, read_palette, write_palette, dithering;
Xvoid get_parameters(int argc, char **argv);
X
Xvoid main (argc, argv) 
X   int argc;
X   char **argv;
X   {
X   unsigned int red, green, blue, i;
X   unsigned int x, y, index;
X
X   if (argc < 2)
X     {
X     printf ("\nUsage:  DumpToIFF [options] <dump_filename> <iff_file_name> [<palette_filename>]\n");
X     printf ("            Options:\n");
X     printf ("               -d           - No dithering\n");
X     printf ("               -pfilename   - Write a palette file\n");
X     exit(0);
X     }
X
X   Close_Threshold = 5;
X
X   fp = NULL;
X   read_palette = FALSE;
X   write_palette = FALSE;
X   output_file = FALSE;
X   dithering = TRUE;
X
X   IntuitionBase = (struct IntuitionBase *)
X                    OpenLibrary ("intuition.library",INT_REV);
X   if (IntuitionBase == NULL)
X      exit(FALSE);
X
X   GfxBase = (struct GfxBase *)
X                      OpenLibrary ("graphics.library", GR_REV);
X   if (GfxBase == NULL)
X      exit(FALSE);
X
X   get_parameters(argc, argv);
X
X   printf ("Reading raw file\n");
X   read_raw_image (&Raw_Image, input_filename);
X
X
X   if (dithering) {
X      printf ("Dithering...\n");
X      dither(&Raw_Image);
X      }
X
X   printf ("Processing...\n");
X   if (read_palette) {
X      if ((palette_file = fopen (palette_filename, "r")) == NULL) {
X         display_close();
X         exit(FALSE);
X         }
X
X      for (i = 0 ; i < 16 ; i++) {
X         if (fscanf (palette_file, "%d %d %d", &red, &green, &blue) != 3) {
X            printf ("Error reading palette file\n");
X            exit (1);
X            }
X
X         ColourTbl[i] = ((red & 0x0f) << 8) |
X                        ((green & 0x0f) << 4) | (blue & 0x0f);
X         }
X      }
X   else {
X      start_recording_colours();
X
X      for (y = 0 ; y < Raw_Image.height ; y++) {
X         for (x = 0 ; x < Raw_Image.width ; x++) {
X            index = y*Raw_Image.width + x;
X            process (x, y, Raw_Image.red[index],
X                           Raw_Image.green[index],
X                           Raw_Image.blue[index]);
X         
X            }
X         }
X      choose_palette();
X      }
X
X   /* Write out the palette file */
X   if (write_palette) {
X      if ((output_palette_file = fopen (output_palette_filename, "w")) == NULL)
X         {
X         printf ("Cannot create palette file\n");
X         exit (1);
X         }
X
X      
X      for (i = 0 ; i < 16 ; i++)
X         fprintf (output_palette_file, "%d %d %d\n",
X                  extract_red(ColourTbl[i]),
X                  extract_green(ColourTbl[i]),
X                  extract_blue(ColourTbl[i]));
X
X
X      fclose(output_palette_file);
X      }
X
X   printf ("Displaying...\n");
X
X   MyScreen.Width = Raw_Image.width+1;
X   MyScreen.Height = Raw_Image.height;
X   if ((s = (struct Screen *) OpenScreen (&MyScreen))
X          == NULL)
X      exit (FALSE);
X
X   ShowTitle (s, FALSE);
X
X
X   SetAPen (&(s->RastPort), 7L);
X   RectFill (&(s -> RastPort), 0L, 0L, Raw_Image.width, Raw_Image.height-1);
X
X   LoadRGB4 (&(s->ViewPort), ColourTbl, 16L);
X
X   for (y = 0 ; y < Raw_Image.height ; y++) {
X      for (x = 0 ; x < Raw_Image.width ; x++) {
X            index = y*Raw_Image.width + x;
X            display_plot (x, y, Raw_Image.red[index],
X                                Raw_Image.green[index],
X                                Raw_Image.blue[index]);
X         }
X      }
X
X   if (output_file)
X      ConvertToIFF(output_filename);
X
X   printf ("Finished\n");
X   display_close();
X   }
X
Xvoid get_parameters (argc, argv)
X   int argc;
X   char **argv;
X   {
X   int i, filename_number;
X
X   filename_number = 0;
X   for (i = 1 ; i < argc ; i++) {
X      if (argv[i][0] == '-')
X         switch (argv[i][1]) {
X            case 'd':  dithering = FALSE;
X                       break;
X
X            case 'p':  strcpy (output_palette_filename, &argv[i][2]);
X                       write_palette = TRUE;
X                       break;
X
X            default:   printf ("Unknown option\n");
X                       break;
X            }
X      else
X         switch (filename_number) {
X            case 0: strcpy (input_filename, argv[i]);
X                    filename_number++;
X                    break;
X
X            case 1: strcpy (output_filename, argv[i]);
X                    output_file = TRUE;
X                    filename_number++;
X                    break;
X
X            case 2: strcpy (palette_filename, argv[i]);
X                    filename_number++;
X                    read_palette = TRUE;
X                    break;
X
X            default: printf ("Too many filenames in commandline\n");
X                     exit(1);
X            }
X      }
X   if (filename_number == 0) {
X      printf ("No input file specified\n");
X      exit(1);
X      }
X   }
X
X
Xvoid display_close ()
X   {
X   if (fp != NULL)
X      fclose (fp);
X   CloseScreen (s);
X   CloseLibrary (GfxBase) ;
X   CloseLibrary (IntuitionBase) ;
X   }
X
Xvoid display_plot (x, y, new_red, new_green, new_blue)
X   LONG x, y, new_red, new_green, new_blue;
X   {
X   LONG colour, newline;
X
X   new_red &= 0xFF;
X   new_green &= 0xFF;
X   new_blue &= 0xFF;
X
X   new_red /= 16;
X   new_green /= 16;
X   new_blue /= 16;
X
X   newline = 0;
X   if (last_y != y) {
X      newline = 1;
X      last_y = y;
X      reset_colours();
X      SetAPen (&(s -> RastPort), 0);
X      WritePixel (&(s -> RastPort), 0, y);
X      }
X
X   colour = best_colour (new_red, new_blue, new_green);
X   SetAPen (&(s -> RastPort), colour);
X   WritePixel (&(s -> RastPort), x+1, y);
X   }
X
X
Xvoid dither (Image)
X   IMAGE *Image;
X   {
X   long index;
X   short i, j, new_red, new_green, new_blue,
X       red_error, green_error, blue_error;
X
X   red_error = 0;
X   green_error = 0;
X   blue_error = 0;
X
X   for (j = 0 ; j < Image->height ; j++)
X      for (i = 0 ; i < Image->width ; i++) {
X         index = j * Image->width + i;
X         red_error = Image->red[index] % 16;
X         green_error = Image->green[index] % 16;
X         blue_error = Image->blue[index] % 16;
X
X         if (i < Image->width-1) {
X            new_red = Image->red[index+1] + red_error * 7 / 16;
X            new_green = Image->green[index+1] + green_error * 7 / 16;
X            new_blue = Image->blue[index+1] + blue_error * 7 / 16;
X            Image->red[index+1] = (new_red>255) ? 255 : new_red;
X            Image->green[index+1] = (new_green>255) ? 255 : new_green;
X            Image->blue[index+1] = (new_blue>255) ? 255 : new_blue;
X            }
X
X         if (j < Image->height-1) {
X            index += Image->width;
X            if (i != 0) {
X               new_red = Image->red[index-1] + red_error * 3 / 16;
X               new_green = Image->green[index-1] + green_error * 3 / 16;
X               new_blue = Image->blue[index-1] + blue_error * 3 / 16;
X               Image->red[index-1] = (new_red>255) ? 255 : new_red;
X               Image->green[index-1] = (new_green>255) ? 255 : new_green;
X               Image->blue[index-1] = (new_blue>255) ? 255 : new_blue;
X               }
X
X
X            new_red = Image->red[index] + red_error * 5 / 16;
X            new_green = Image->green[index] + green_error * 5 / 16;
X            new_blue = Image->blue[index] + blue_error * 5 / 16;
X            Image->red[index] = (new_red>255) ? 255 : new_red;
X            Image->green[index] = (new_green>255) ? 255 : new_green;
X            Image->blue[index] = (new_blue>255) ? 255 : new_blue;
X
X            if (i < Image->width-1) {
X               new_red = Image->red[index+1] + red_error / 16;
X               new_green = Image->green[index+1] + green_error / 16;
X               new_blue = Image->blue[index+1] + blue_error / 16;
X               Image->red[index+1] = (new_red>255) ? 255 : new_red;
X               Image->green[index+1] = (new_green>255) ? 255 : new_green;
X               Image->blue[index+1] = (new_blue>255) ? 255 : new_blue;
X               }
X            }
X         }
X   }
X
X
Xvoid process (x, y, new_red, new_green, new_blue)
X   LONG x, y, new_red, new_green, new_blue;
X   {
X   LONG newline;
X
X   new_red &= 0xFF;
X   new_green &= 0xFF;
X   new_blue &= 0xFF;
X
X   new_red /= 16;
X   new_green /= 16;
X   new_blue /= 16;
X
X   newline = 0;
X   if (last_y != y) {
X     newline = 1;
X     last_y = y;
X     reset_colours();
X     }
X
X   record_colours (new_red, new_green, new_blue);
X   }
X
X
Xvoid ConvertToIFF(file_name)
X   char *file_name;
X   {
X   char *buffer;
X   BPTR file;
X   BOOL PutPict();
X
X   if ((file = Open (file_name, MODE_NEWFILE)) == 0) {
X      printf ("\nCannot open IFF file\n");
X      exit (0);
X      }
X
X   buffer = malloc(BUFFER_SIZE);
X   if (PutPict (file, &(s->ViewPort), buffer, BUFFER_SIZE))
X      printf ("\nIFF write error\n");
X   Close (file);
X   }
X
Xint read_raw_byte(f)
X   FILE *f;
X   {
X   int c;
X   if ((c = getc(f)) == EOF)
X      return (-1);
X   return (c);
X   }
X
Xint read_raw_word(f)
X   FILE *f;
X   {
X   int byte1, byte2;
X
X   byte1 = read_raw_byte(f);
X   if (byte1 == -1)
X      return(-1);
X
X   byte2 = read_raw_byte(f);
X   if (byte2 == -1)
X      return(-1);
X
X   return (byte1 + byte2*256);
X   }
X
Xvoid read_raw_image(Image, filename)
X   IMAGE *Image;
X   char *filename;
X   {
X   FILE *f;
X   int byte, i, index, row, pixels;
X
X   if ((f = fopen(filename, "rb")) == NULL) {
X      printf ("Cannot open raw file %s\n", filename);
X      exit(1);
X      }
X
X   Image->width = read_raw_word(f);
X   if (Image->width == -1) {
X      printf ("Cannot read size in dump file\n");
X      exit(1);
X      }
X
X   Image->height = read_raw_word(f);
X   if (Image->height == -1) {
X      printf ("Cannot read size in dump file: %s\n", filename);
X      exit(1);
X      }
X
X   pixels = Image->width * Image->height;
X
X   if (((Image->red = (unsigned char *) malloc(pixels))==NULL) ||
X       ((Image->green = (unsigned char *) malloc(pixels))==NULL) ||
X       ((Image->blue = (unsigned char *) malloc(pixels))==NULL)) {
X      printf ("Cannot allocate memory for picture: %s\n", filename);
X      exit(1);
X      }
X
X   for (i = 0 ; i < pixels ; i++) {
X      Image->red[i] = 0;
X      Image->green[i] = 0;
X      Image->blue[i] = 0;
X      }
X
X   row = read_raw_word(f);
X   while (row != -1) {
X      for (i = 0 ; i < Image->width ; i++) {
X         index = row*Image->width + i;
X
X         byte = read_raw_byte(f);
X         if (byte == -1) {
X            printf ("Unexpected end of file in raw image: %s\n", filename);
X            exit(1);
X            }
X         Image->red[index] = byte;
X         }
X
X      for (i = 0 ; i < Image->width ; i++) {
X         index = row*Image->width + i;
X
X         byte = read_raw_byte(f);
X         if (byte == -1) {
X            printf ("Unexpected end of file in raw image: %s\n", filename);
X            exit(1);
X            }
X         Image->green[index] = byte;
X         }
X
X      for (i = 0 ; i < Image->width ; i++) {
X         index = row*Image->width + i;
X
X         byte = read_raw_byte(f);
X         if (byte == -1) {
X            printf ("Unexpected end of file in raw image: %s\n", filename);
X            exit(1);
X            }
X         Image->blue[index] = byte;
X         }
X      row = read_raw_word(f);
X      }
X   fclose (f);
X   }
END_OF_FILE
if test 13811 -ne `wc -c <'src/DumpToIFF.c'`; then
    echo shar: \"'src/DumpToIFF.c'\" unpacked with wrong size!
fi
# end of 'src/DumpToIFF.c'
fi
if test -f 'src/ibm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/ibm.c'\"
else
echo shar: Extracting \"'src/ibm.c'\" \(10840 characters\)
sed "s/^X//" >'src/ibm.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X*                                      ibm.c
X*
X*   from DKBTrace (c) 1990  David Buck
X*
X*  This module implements the IBM-specific routines for 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#include "frame.h"
X#include "dkbproto.h"
X
X/* IBM VGA "colour" output routines for MS/DOS by Aaron A. Collins.  This
X   will deliver approximate colorings using HSV values for the approximation.
X   The pallette map is divided into 4 parts - upper and lower half generated
X   with full and half "value" (intensity), respectively.  These halves are
X   further halved by full and half saturation values of each range (pastels).
X   There are three constant colors, black, white, and grey.  They are used
X   when the saturation is low enough that the hue becomes undefined, and which
X   one is selected is based on a simple range map of "value".  Usage of the
X   pallette is accomplished by converting the requested color RGB into an HSV
X   value.  If the saturation is too low (< .25) then black, white or grey is
X   selected.  If there is enough saturation to consider looking at the hue,
X   then the hue range of 1-63 is scaled into one of the 4 pallette quadrants
X   based on its "value" and "saturation" characteristics.
X*/
X
X#include <dos.h>	/* MS-DOS specific - for int86() REGS struct, etc. */
X
Xvoid set_pallette_register(unsigned, unsigned, unsigned, unsigned);
Xvoid hsv_to_rgb(DBL, DBL, DBL, unsigned *, unsigned *, unsigned *);
Xvoid rgb_to_hsv(unsigned, unsigned, unsigned, DBL *, DBL *, DBL *);
X
Xextern unsigned _stklen = 32768U;   /* HUGE stack for HEAVY recursion */
Xextern int Options;
X
Xvoid display_init()
X   {
X   union REGS inr, outr;
X   register unsigned m;
X   unsigned r, g, b;
X   register DBL hue, sat, val;
X
X   inr.x.ax = 0x0013;           /* setup to VGA 320x200x256 (mode 13H) */
X   int86(0x10, &inr, &outr);
X
X   inr.x.ax = 0x1010;           /* make pallette register 0 black */
X   inr.x.bx = 0;
X   inr.h.ch = inr.h.cl = inr.h.dh = 0;   /* full off */
X   int86(0x10, &inr, &outr);
X
X   inr.x.ax = 0x1010;           /* make pallette register 64 white */
X   inr.x.bx = 64;
X   inr.h.ch = inr.h.cl = inr.h.dh = 63;  /* full on */
X   int86(0x10, &inr, &outr);
X
X   inr.x.ax = 0x1010;           /* make pallette register 128 dark grey */
X   inr.x.bx = 128;
X   inr.h.ch = inr.h.cl = inr.h.dh = 31;  /* half on (dark grey) */
X   int86(0x10, &inr, &outr);
X
X   inr.x.ax = 0x1010;           /* make pallette register 192 lite grey */
X   inr.x.bx = 192;
X   inr.h.ch = inr.h.cl = inr.h.dh = 48;  /* 3/4 on (lite grey) */
X   int86(0x10, &inr, &outr);
X
X   for (m = 1; m < 64; m++)     /* for the 1st 64 colors... */
X      {
X      sat = 0.5;                /* start with the saturation and intensity low */
X      val = 0.5;
X      hue = 360.0 * ((DBL)(m)) / 64.0;   /* normalize to 360 */
X      hsv_to_rgb (hue, sat, val, &r, &g, &b);
X      set_pallette_register (m, r, g, b); /* set m to rgb value */
X
X      sat = 1.0;                /* high saturation and half intensity (shades) */
X      val = 0.50;
X      hue = 360.0 * ((DBL)(m)) / 64.0;   /* normalize to 360 */
X      hsv_to_rgb (hue, sat, val, &r, &g, &b);
X      set_pallette_register (m + 64, r, g, b);  /* set m + 64 */
X
X      sat = 0.5;                /* half saturation and high intensity (pastels) */
X      val = 1.0;
X
X      hue = 360.0 * ((DBL)(m)) / 64.0;   /* normalize to 360 */
X      hsv_to_rgb (hue, sat, val, &r, &g, &b);
X      set_pallette_register (m + 128, r, g, b); /* set m + 128 */
X
X      sat = 1.0;                /* normal full HSV set at full intensity */
X      val = 1.0;
X   
X      hue = 360.0 * ((DBL)(m)) / 64.0;   /* normalize to 360 */
X      hsv_to_rgb (hue, sat, val, &r, &g, &b);
X      set_pallette_register (m + 192, r, g, b); /* set m + 192 */
X      }
X   return;
X   }
X
Xvoid display_finished ()
X   {
X   if (Options & PROMPTEXIT)
X      {
X      printf ("\007\007");   /* long beep */
X      getch();
X      }
X   }
X
Xvoid display_close()   /* setup to Text 80x25 (mode 3) */
X   {
X   union REGS inr, outr;
X
X   inr.x.ax = 0x0003;
X   int86(0x10, &inr, &outr);
X   return;
X   }
X
Xvoid display_plot (x, y, Red, Green, Blue)   /* plot a single RGB pixel */
X   int x, y;
X   char Red, Green, Blue;
X   {
X   register unsigned char color;
X   unsigned char far *fp;
X   DBL h, s, v;
X
X   /* Translate RGB value to best of 256 pallete Colors (by HSV?) */
X
X   rgb_to_hsv((unsigned)Red,(unsigned)Green,(unsigned)Blue, &h, &s, &v);
X
X   if (s < 0.25)   /* black or white if no saturation of color... */
X      {
X      if (v < 0.25)
X         color = 0;        /* black */
X      else if (v > 0.75)
X         color = 64;       /* white */
X      else if (v > 0.5)
X         color = 192;      /* lite grey */
X      else
X         color = 128;      /* dark grey */
X      }
X   else
X      {
X      color = (unsigned char) (64.0 * ((DBL)(h)) / 360.0);
X
X      if (!color)
X         color = 1;        /* avoid black, white or grey */
X      
X      if (color > 63)
X         color = 63;       /* avoid same */
X
X      if (v > 0.50)
X         color |= 0x80;    /* colors 128-255 for high inten. */
X
X      if (s > 0.50)        /* more than half saturated? */
X         color |= 0x40;    /* color range 64-128 or 192-255 */
X      }
X
X   fp = MK_FP(0xa000, 320 * y + x);
X
X   *fp = color;            /* normalize color to 256 */
X
X   return;
X   }
X
Xvoid set_pallette_register (Val, Red, Green, Blue)
X   unsigned Val;
X   unsigned Red, Green, Blue;
X   {
X   union REGS Regs;
X
X   Regs.x.ax = 0x1010;              /* Set one pallette register function */
X   Regs.x.bx = Val;                 /* the pallette register to set (color #) */
X   Regs.h.dh = (char) Red & 0xff;   /* set the gun values (6 bits ea.) */
X   Regs.h.ch = (char) Green & 0xff;
X   Regs.h.cl = (char) Blue & 0xff;
X   int86(0x10, &Regs, &Regs);       /* Do the video interrupt */
X   }
X
X/* Conversion from Hue, Saturation, Value to Red, Green, and Blue and back */
X/* From "Computer Graphics", Donald Hearn & M. Pauline Baker, p. 304 */
X
Xvoid hsv_to_rgb(hue, s, v, r, g, b)
X   DBL hue, s, v;               /* hue (0.0 to 360.0) s and v are from 0.0 - 1.0) */
X   unsigned *r, *g, *b;         /* values from 0 to 63 */
X   {
X   register DBL i, f, p1, p2, p3;
X   register DBL xh;
X   register DBL nr, ng, nb;     /* rgb values of 0.0 - 1.0      */
X
X   if (hue == 360.0)
X      hue = 0.0;                /* (THIS LOOKS BACKWARDS BUT OK) */
X
X   xh = hue / 60.0;             /* convert hue to be in 0,6     */
X   i = floor(xh);               /* i = greatest integer <= h    */
X   f = xh - i;                  /* f = fractional part of h     */
X   p1 = v * (1 - s);
X   p2 = v * (1 - (s * f));
X   p3 = v * (1 - (s * (1 - f)));
X
X   switch ((int) i)
X      {
X      case 0:
X         nr = v;
X         ng = p3;
X         nb = p1;
X         break;
X      case 1:
X         nr = p2;
X         ng = v;
X         nb = p1;
X         break;
X      case 2:
X         nr = p1;
X         ng = v;
X         nb = p3;
X         break;
X      case 3:
X         nr = p1;
X         ng = p2;
X         nb = v;
X         break;
X      case 4:
X         nr = p3;
X         ng = p1;
X         nb = v;
X         break;
X      case 5:
X         nr = v;
X         ng = p1;
X         nb = p2;
X         break;
X        }
X
X   *r = (unsigned)(nr * 63.0); /* Normalize the values to 63 */
X   *g = (unsigned)(ng * 63.0);
X   *b = (unsigned)(nb * 63.0);
X   
X   return;
X   }
X
Xvoid rgb_to_hsv(r, g, b, h, s, v)
X   unsigned r, g, b;
X   DBL *h, *s, *v;
X   {
X   register DBL m, r1, g1, b1;
X   register DBL nr, ng, nb;      /* rgb values of 0.0 - 1.0      */
X   register DBL nh, ns, nv;      /* hsv local values */
X
X   nr = (DBL) r / 255.0;
X   ng = (DBL) g / 255.0;
X   nb = (DBL) b / 255.0;
X
X   nv = max (nr, max (ng, nb));
X   m = min (nr, min (ng, nb));
X
X   if (nv != 0.0)                /* if no value, it's black! */
X      ns = (nv - m) / nv;
X   else
X      ns = 0.0;                 /* black = no colour saturation */
X
X   if (ns == 0.0)                /* hue undefined if no saturation */
X   {
X      *h = 0.0;                  /* return black level (?) */
X      *s = 0.0;
X      *v = nv;
X      return;
X   }
X
X   r1 = (nv - nr) / (nv - m);    /* distance of color from red   */
X   g1 = (nv - ng) / (nv - m);    /* distance of color from green   */
X   b1 = (nv - nb) / (nv - m);    /* distance of color from blue   */
X
X   if (nv == nr)
X   {
X      if (m == ng)
X         nh = 5. + b1;
X      else
X         nh = 1. - g1;
X   } 
X
X   if (nv == ng)
X      {
X      if (m == nb)
X         nh = 1. + r1;
X      else
X         nh = 3. - b1;
X      }
X
X   if (nv == nb)
X      {
X      if (m == nr)
X         nh = 3. + g1;
X      else
X         nh = 5. - r1;
X      }
X
X   *h = nh * 60.0;      /* return h converted to degrees */
X   *s = ns;
X   *v = nv;
X   return;
X   }
X
X#if !__STDC__
X
X/* ANSI Standard random number generator */
X
Xstatic unsigned long int next = 1;
X
Xint rand()
X   {
X   next = next * 1103515245L + 12345L;
X   return ((int) (next / 0x10000L) & 0x7FFF);
X   }
X
Xvoid srand(seed)
X   unsigned int seed;
X   {
X   next = seed;
X   }
X
X#endif
END_OF_FILE
if test 10840 -ne `wc -c <'src/ibm.c'`; then
    echo shar: \"'src/ibm.c'\" unpacked with wrong size!
fi
# end of 'src/ibm.c'
fi
if test -f 'src/iff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/iff.c'\"
else
echo shar: Extracting \"'src/iff.c'\" \(10876 characters\)
sed "s/^X//" >'src/iff.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X*                                     iff.c
X*
X*   from DKBTrace (c) 1990  David Buck
X*
X*  This file implements a simple IFF format file reader.
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 "dkbproto.h"
X
Xstatic IMAGE_COLOUR *iff_colour_map;
Xstatic int colourmap_size;
Xstatic CHUNK_HEADER Chunk_Header;
X
X#define FORM 0x464f524dL
X#define ILBM 0x494c424dL
X#define BMHD 0x424d4844L
X#define CAMG 0x43414d47L
X#define CMAP 0x434d4150L
X#define BODY 0x424f4459L
X#define CMPNONE 0
X
X#define HAM 0x800
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 = read_long(f);
X   }
X
Xvoid read_iff_image(Image, filename)
X   IMAGE *Image;
X   char *filename;
X   {
X   FILE *f;
X   unsigned char **row_bytes;
X   int c, i, j, k, creg, index, nBytes, nBytesRead, nPlanes, compression,
X       mask, byte_index, count, viewmodes;
X   int Previous_Red, Previous_Green, Previous_Blue;
X
X   if ((f = fopen(filename, "rb")) == NULL) {
X      printf ("Cannot open IFF file %s\n", filename);
X      exit(1);
X      }
X
X   Previous_Red = Previous_Green = Previous_Blue = 0;
X
X   viewmodes = 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) != ILBM)
X                        iff_error();
X                     break;
X
X         case BMHD:  Image->iwidth = read_word(f);
X                     Image->width = (DBL)Image->iwidth;
X                     Image->iheight = read_word(f);
X                     Image->height = (DBL)Image->iheight;
X                     read_word(f);  /* x position ignored */
X                     read_word(f);  /* y position ignored */
X                     nPlanes = read_byte(f);
X                     colourmap_size = 1<<nPlanes;
X                     read_byte(f);   /* masking ignored */
X                     compression = read_byte(f);   /* masking ignored */
X                     read_byte(f);   /* pad */
X                     read_word(f);   /* Transparent colour ignored */
X                     read_word(f);   /* Aspect ratio ignored */
X                     read_word(f);   /* page width ignored */
X                     read_word(f);   /* page height ignored */
X                     break;
X
X         case CAMG:  viewmodes = (int) read_long(f);   /* Viewmodes */
X                     if (viewmodes & HAM)
X                        colourmap_size = 16;
X                     break;
X
X         case CMAP:  colourmap_size = (int) Chunk_Header.size / 3;
X
X                     if ((iff_colour_map = (IMAGE_COLOUR *) malloc(sizeof(IMAGE_COLOUR)*colourmap_size)) == NULL)
X                        iff_error();
X
X                     for (i = 0 ; i < colourmap_size ; i++) {
X                        iff_colour_map[i].Red = read_byte(f);
X                        iff_colour_map[i].Green = read_byte(f);
X                        iff_colour_map[i].Blue = read_byte(f);
X                        }
X                     Previous_Red = iff_colour_map[0].Red;
X                     Previous_Green = iff_colour_map[0].Green;
X                     Previous_Blue = iff_colour_map[0].Blue;
X                     for (i = colourmap_size*3 ; i < Chunk_Header.size ; i++)
X                        read_byte(f);
X 
X                     break;
X
X         case BODY:  if ((row_bytes = (unsigned char **) malloc (4*nPlanes)) == NULL) {
X                        printf ("Not enough memory\n");
X                        exit(1);
X                        }
X
X                     for (i = 0 ; i < nPlanes ; i++)
X                        if ((row_bytes[i] = (unsigned char *) malloc((Image->iwidth+7)/8)) == NULL) {
X                           printf ("Not enough memory\n");
X                           exit(1);
X                        }
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                     for (i = 0 ; i < Image->iheight ; i++) {
X                        for (j = 0 ; j < nPlanes ; j++)
X                           if (compression == CMPNONE) {
X                              for (k = 0 ; k < (Image->iwidth+7)/8 ; k++)
X                                 row_bytes[j][k] = read_byte(f);
X                           if ((Image->iwidth & 7) != 0)
X                              read_byte(f);
X                           }
X                        else {
X                           nBytes = 0;
X                           nBytesRead = 0;
X                           while (nBytes != (Image->iwidth+7)/8) {
X                              c = read_byte(f);
X                              nBytesRead++;
X                              if ((c >= 0) && (c <= 127))
X                                 for (k = 0 ; k <= c ; k++)
X                                    row_bytes[j][nBytes++] = read_byte(f);
X                              else if ((c >= 129) && (c <= 255)) {
X                                 count = 257-c;
X                                 c = read_byte(f);
X                                 nBytesRead++;
X                                 for (k = 0 ; k < count ; k++)
X                                    row_bytes[j][nBytes++] = c;
X                                 }
X                              }
X                      	   }
X
X                        mask = 0x80;
X                        byte_index = 0;
X                        for (j = 0 ; j < Image->iwidth ; j++) {
X                           creg = 0;
X                           for (k = nPlanes-1 ; k >= 0 ; k--)
X                              if (row_bytes[k][byte_index] & mask)
X                                creg = creg*2 + 1;
X                              else
X                                creg *= 2;
X
X                           index = (Image->iheight-i-1)*Image->iwidth + j;
X
X                           if (viewmodes & HAM) {
X                              switch (creg >> 4) {
X                                 case 0:
X                                    Previous_Red = Image->red[index] = iff_colour_map[creg].Red;
X                                    Previous_Green = Image->green[index] = iff_colour_map[creg].Green;
X                                    Previous_Blue = Image->blue[index] = iff_colour_map[creg].Blue;
X                                    break;
X
X                                 case 1:
X                                    Image->red[index] = Previous_Red;
X                                    Image->green[index] = Previous_Green;
X                                    Previous_Blue = Image->blue[index] = ((creg & 0xf)<<4) + (creg&0xf);
X                                    break;
X
X                                 case 2:
X                                    Previous_Red = Image->red[index] = ((creg & 0xf)<<4) + (creg&0xf);
X                                    Image->green[index] = Previous_Green;
X                                    Image->blue[index] = Previous_Blue;
X                                    break;
X
X                                 case 3:
X                                    Image->red[index] = Previous_Red;
X                                    Previous_Green = Image->green[index] = ((creg & 0xf)<<4) + (creg&0xf);
X                                    Image->blue[index] = Previous_Blue;
X                                    break;
X                                 }
X                              }
X                           else {
X                              Image->red[index] = iff_colour_map[creg].Red;
X                              Image->green[index] = iff_colour_map[creg].Green;
X                              Image->blue[index] = iff_colour_map[creg].Blue;
X                              }
X
X                           mask >>= 1;
X                           if (mask == 0) {
X                              mask = 0x80;
X                              byte_index++;
X                              }
X                           }
X                        }
X
X                     free (row_bytes);
X                     fclose (f);
X                     return;
X         default:
X            for (i = 0 ; i < Chunk_Header.size ; i++)
X               if (getc(f) == EOF)
X                  iff_error();
X            break;
X         }
X      }
X   }
END_OF_FILE
if test 10876 -ne `wc -c <'src/iff.c'`; then
    echo shar: \"'src/iff.c'\" unpacked with wrong size!
fi
# end of 'src/iff.c'
fi
if test -f 'src/objects.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/objects.c'\"
else
echo shar: Extracting \"'src/objects.c'\" \(11964 characters\)
sed "s/^X//" >'src/objects.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X*                                    objects.c
X*
X*   from DKBTrace (c) 1990  David Buck
X*
X*  This module implements the methods for objects and composite objects.
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
Xextern RAY *VP_Ray;
Xextern long Bounding_Region_Tests, Bounding_Region_Tests_Succeeded;
X
XMETHODS Composite_Methods =
X   { Object_Intersect, All_Composite_Intersections,
X     Inside_Composite_Object, NULL,
X     Copy_Composite_Object,
X     Translate_Composite_Object, Rotate_Composite_Object,
X     Scale_Composite_Object, Invert_Composite_Object};
X
XMETHODS Basic_Object_Methods =
X   { Object_Intersect, All_Object_Intersections,
X     Inside_Basic_Object, NULL,
X     Copy_Basic_Object,
X     Translate_Basic_Object, Rotate_Basic_Object,
X     Scale_Basic_Object, Invert_Basic_Object};
X
X
XINTERSECTION *Object_Intersect (Object, Ray)
X   OBJECT *Object;
X   RAY *Ray;
X   {
X   INTERSECTION *Local_Intersection, *Queue_Element;
X   PRIOQ *Depth_Queue;
X
X   Depth_Queue = pq_new (128);
X
X   if ((All_Intersections (Object, Ray, Depth_Queue))
X      && ((Queue_Element = pq_get_highest (Depth_Queue)) != NULL))
X      {
X      Local_Intersection = (INTERSECTION *) malloc(sizeof(INTERSECTION));
X      Local_Intersection -> Point = Queue_Element -> Point;
X      Local_Intersection -> Shape = Queue_Element -> Shape;
X      Local_Intersection -> Depth = Queue_Element -> Depth;
X      Local_Intersection -> Object = Queue_Element -> Object;
X      pq_free (Depth_Queue);
X      return (Local_Intersection);
X      }
X   else
X      {
X      pq_free (Depth_Queue);
X      return (NULL);
X      }
X   }
X
Xint All_Composite_Intersections (Object, Ray, Depth_Queue)
X   OBJECT *Object;
X   RAY *Ray;
X   PRIOQ *Depth_Queue;
X   {
X   register int Intersection_Found;
X   SHAPE *Bounding_Shape;
X   INTERSECTION *Local_Intersection;
X   OBJECT *Local_Object;
X
X   for (Bounding_Shape = ((COMPOSITE *) Object) -> Bounding_Shapes ;
X        Bounding_Shape != NULL ;
X        Bounding_Shape = Bounding_Shape -> Next_Object) {
X
X     Bounding_Region_Tests++;
X     if ((Local_Intersection = Intersection ((OBJECT *) Bounding_Shape, Ray)) != NULL)
X        free (Local_Intersection);
X     else
X        if (!Inside (&Ray -> Initial, (OBJECT *) Bounding_Shape))
X           return (FALSE);
X     Bounding_Region_Tests_Succeeded++;
X     }
X
X   Intersection_Found = FALSE;
X   for (Local_Object = ((COMPOSITE *) Object) -> Objects ;
X        Local_Object != NULL ;
X        Local_Object = Local_Object -> Next_Object)
X
X      if (All_Intersections (Local_Object, Ray, Depth_Queue))
X         Intersection_Found = TRUE;
X
X   return (Intersection_Found);
X   }
X
Xint All_Object_Intersections (Object, Ray, Depth_Queue)
X   OBJECT *Object;
X   RAY *Ray;
X   PRIOQ *Depth_Queue;
X   {
X   INTERSECTION *Local_Intersection;
X   SHAPE *Bounding_Shape;
X
X   for (Bounding_Shape = Object -> Bounding_Shapes ;
X        Bounding_Shape != NULL ;
X        Bounding_Shape = Bounding_Shape -> Next_Object) {
X
X      Bounding_Region_Tests++;
X      if ((Local_Intersection = Intersection ((OBJECT *) Bounding_Shape, Ray)) != NULL)
X         free (Local_Intersection);
X      else
X         if (!Inside (&Ray -> Initial, (OBJECT *) Bounding_Shape))
X            return (FALSE);
X      Bounding_Region_Tests_Succeeded++;
X      }
X
X   All_Intersections ((OBJECT *) Object -> Shape, Ray, Depth_Queue);
X
X   if (pq_is_empty (Depth_Queue))
X     return (FALSE);
X   return (TRUE);
X   }
X
X
Xint Inside_Basic_Object (Point, Object)
X   VECTOR *Point;
X   OBJECT *Object;
X   {
X   SHAPE *Bounding_Shape;
X
X   for (Bounding_Shape = Object -> Bounding_Shapes ;
X        Bounding_Shape != NULL ;
X        Bounding_Shape = Bounding_Shape -> Next_Object)
X
X      if (!Inside (Point, (OBJECT *) Bounding_Shape))
X         return (FALSE);
X
X   if (Inside (Point, (OBJECT *) Object -> Shape))
X      return (TRUE);
X   return (FALSE);
X   }
X
Xint Inside_Composite_Object (Point, Object)
X   VECTOR *Point;
X   OBJECT *Object;
X   {
X   SHAPE *Bounding_Shape;
X   OBJECT *Local_Object;
X
X   for (Bounding_Shape = ((COMPOSITE *) Object) -> Bounding_Shapes ;
X        Bounding_Shape != NULL ;
X        Bounding_Shape = Bounding_Shape -> Next_Object)
X
X     if (!Inside (Point, (OBJECT *) Bounding_Shape))
X       return (FALSE);
X
X   for (Local_Object = ((COMPOSITE *) Object) -> Objects ;
X        Local_Object != NULL ;
X        Local_Object = Local_Object -> Next_Object)
X
X      if (Inside (Point, Local_Object))
X         return (TRUE);
X
X   return (FALSE);
X   }
X
Xvoid *Copy_Basic_Object (Object)
X   OBJECT *Object;
X   {
X   SHAPE *Local_Shape, *Copied_Shape;
X   OBJECT *New_Object;
X
X   New_Object = Get_Object();
X   *New_Object = *Object;
X   New_Object -> Next_Object = NULL;
X   New_Object -> Bounding_Shapes = NULL;
X   for (Local_Shape = Object -> Bounding_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_Object -> Bounding_Shapes));
X      Copied_Shape -> Parent_Object = Object;
X      }
X
X   New_Object -> Shape = (SHAPE *) Copy((OBJECT *) Object -> Shape);
X   Object -> Shape -> Parent_Object = Object;
X   return (New_Object);
X   }
X
Xvoid *Copy_Composite_Object (Object)
X   OBJECT *Object;
X   {
X   COMPOSITE *New_Object;
X   SHAPE *Local_Shape;
X   OBJECT *Local_Object, *Copied_Object;
X
X   New_Object = Get_Composite_Object();
X   *New_Object = *((COMPOSITE *) Object);
X   New_Object -> Next_Object = NULL;
X   New_Object -> Objects = NULL;
X   for (Local_Object = ((COMPOSITE *) Object) -> Objects;
X        Local_Object != NULL ;
X        Local_Object = Local_Object -> Next_Object) {
X
X      Copied_Object = (OBJECT *) Copy(Local_Object);
X      Link (Copied_Object,
X            &(Copied_Object -> Next_Object),
X            &(New_Object -> Objects));
X      }
X
X   New_Object -> Bounding_Shapes = NULL;
X   for (Local_Shape = ((COMPOSITE *) Object) -> Bounding_Shapes;
X        Local_Shape != NULL ;
X        Local_Shape = Local_Shape -> Next_Object) {
X
X      Copied_Object = (OBJECT *) Copy((OBJECT *) Local_Shape);
X      Link (Copied_Object,
X            &(Copied_Object -> Next_Object),
X            (OBJECT **) &(New_Object -> Bounding_Shapes));
X      }
X   return (New_Object);
X   }
X
Xvoid Translate_Basic_Object (Object, Vector)
X   OBJECT *Object;
X   VECTOR *Vector;
X   {
X   SHAPE *Local_Shape;
X
X   for (Local_Shape = Object -> Bounding_Shapes ;
X        Local_Shape != NULL ;
X        Local_Shape = Local_Shape -> Next_Object)
X
X      Translate ((OBJECT *) Local_Shape, Vector);
X
X   Translate ((OBJECT *) Object -> Shape, Vector);
X
X   VAdd (Object -> Object_Center, Object -> Object_Center, *Vector);
X   }
X
Xvoid Rotate_Basic_Object (Object, Vector)
X   OBJECT *Object;
X   VECTOR *Vector;
X   {
X   SHAPE *Local_Shape;
X   TRANSFORMATION Transformation;
X
X   for (Local_Shape = Object -> Bounding_Shapes ;
X        Local_Shape != NULL ;
X        Local_Shape = Local_Shape -> Next_Object)
X
X      Rotate ((OBJECT *) Local_Shape, Vector);
X
X   Rotate ((OBJECT *) Object -> Shape, Vector);
X   Get_Rotation_Transformation (&Transformation, Vector);
X   MTransformVector (&Object->Object_Center,
X                     &Object->Object_Center, &Transformation);
X   }
X
Xvoid Scale_Basic_Object (Object, Vector)
X   OBJECT *Object;
X   VECTOR *Vector;
X   {
X   SHAPE *Local_Shape;
X
X   for (Local_Shape = Object -> Bounding_Shapes ;
X        Local_Shape != NULL ;
X        Local_Shape = Local_Shape -> Next_Object)
X
X      Scale ((OBJECT *) Local_Shape, Vector);
X
X   Scale ((OBJECT *) Object -> Shape, Vector);
X
X   VEvaluate (Object -> Object_Center, Object -> Object_Center, *Vector);
X   }
X
Xvoid Translate_Composite_Object (Object, Vector)
X   OBJECT *Object;
X   VECTOR *Vector;
X   {
X   OBJECT *Local_Object;
X   SHAPE *Local_Shape;
X
X   for (Local_Object = ((COMPOSITE *) Object) -> Objects;
X        Local_Object != NULL ;
X        Local_Object = Local_Object -> Next_Object)
X 
X      Translate (Local_Object, Vector);   
X
X   for (Local_Shape = ((COMPOSITE *) Object) -> Bounding_Shapes ;
X        Local_Shape != NULL ;
X        Local_Shape = Local_Shape -> Next_Object)
X
X      Translate ((OBJECT *) Local_Shape, Vector);
X   }
X
Xvoid Rotate_Composite_Object (Object, Vector)
X   OBJECT *Object;
X   VECTOR *Vector;
X   {
X   OBJECT *Local_Object;
X   SHAPE *Local_Shape;
X
X   for (Local_Object = ((COMPOSITE *) Object) -> Objects;
X        Local_Object != NULL ;
X        Local_Object = Local_Object -> Next_Object)
X 
X      Rotate (Local_Object, Vector);   
X
X   for (Local_Shape = ((COMPOSITE *) Object) -> Bounding_Shapes ;
X        Local_Shape != NULL ;
X        Local_Shape = Local_Shape -> Next_Object)
X
X      Rotate ((OBJECT *) Local_Shape, Vector);
X   }
X
Xvoid Scale_Composite_Object (Object, Vector)
X   OBJECT *Object;
X   VECTOR *Vector;
X   {
X   OBJECT *Local_Object;
X   SHAPE *Local_Shape;
X
X   for (Local_Object = ((COMPOSITE *) Object) -> Objects;
X        Local_Object != NULL ;
X        Local_Object = Local_Object -> Next_Object)
X 
X      Scale (Local_Object, Vector);   
X
X   for (Local_Shape = ((COMPOSITE *) Object) -> Bounding_Shapes ;
X        Local_Shape != NULL ;
X        Local_Shape = Local_Shape -> Next_Object)
X
X      Scale ((OBJECT *) Local_Shape, Vector);
X   }
X
X
Xvoid Invert_Basic_Object (Object)
X   OBJECT *Object;
X   {
X   SHAPE *Local_Shape;
X
X   for (Local_Shape = Object -> Bounding_Shapes ;
X        Local_Shape != NULL ;
X        Local_Shape = Local_Shape -> Next_Object)
X
X      Invert ((OBJECT *) Local_Shape);
X   Invert ((OBJECT *) Object -> Shape);
X   }
X
Xvoid Invert_Composite_Object (Object)
X   OBJECT *Object;
X   {
X   OBJECT *Local_Object;
X   SHAPE *Local_Shape;
X
X   for (Local_Object = ((COMPOSITE *)Object) -> Objects;
X        Local_Object != NULL ;
X        Local_Object = Local_Object -> Next_Object)
X
X      Invert (Local_Object);   
X
X   for (Local_Shape = ((COMPOSITE *) Object) -> Bounding_Shapes ;
X        Local_Shape != NULL ;
X        Local_Shape = Local_Shape -> Next_Object)
X
X      Invert ((OBJECT *) Local_Shape);
X   }
END_OF_FILE
if test 11964 -ne `wc -c <'src/objects.c'`; then
    echo shar: \"'src/objects.c'\" unpacked with wrong size!
fi
# end of 'src/objects.c'
fi
if test -f 'src/quadrics.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/quadrics.c'\"
else
echo shar: Extracting \"'src/quadrics.c'\" \(11498 characters\)
sed "s/^X//" >'src/quadrics.c' <<'END_OF_FILE'
X/*****************************************************************************
X*
X*                                   quadrics.c
X*
X*   from DKBTrace (c) 1990  David Buck
X*
X*  This module implements the code for the quadric shape 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
X#include "frame.h"
X#include "vector.h"
X#include "dkbproto.h"
X
XMETHODS Quadric_Methods =
X   { Object_Intersect, All_Quadric_Intersections,
X     Inside_Quadric, Quadric_Normal,
X     Copy_Quadric,
X     Translate_Quadric, Rotate_Quadric,
X     Scale_Quadric, Invert_Quadric};
X
Xextern RAY *VP_Ray;
Xextern long Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded;
X
Xint All_Quadric_Intersections (Object, Ray, Depth_Queue)
X   OBJECT *Object;
X   RAY *Ray;
X   PRIOQ *Depth_Queue;
X   {
X   QUADRIC *Shape = (QUADRIC *) Object;
X   DBL Depth1, Depth2;
X   VECTOR Intersection_Point;
X   INTERSECTION Local_Element;
X   register int Intersection_Found;
X
X   Intersection_Found = FALSE;
X   if (Intersect_Quadric (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_Quadric (Ray, Shape, Depth1, Depth2)
X   RAY *Ray;
X   QUADRIC *Shape;
X   DBL *Depth1, *Depth2;
X   {
X   register DBL Square_Term, Linear_Term, Constant_Term, Temp_Term;
X   register DBL Determinant, Determinant_2, A2, BMinus;
X
X   Ray_Quadric_Tests++;
X   if (!Ray->Quadric_Constants_Cached)
X      Make_Ray(Ray);
X
X   if (Shape -> Non_Zero_Square_Term)
X      {
X      VDot (Square_Term, Shape -> Object_2_Terms, Ray -> Direction_2);
X      VDot (Temp_Term, Shape -> Object_Mixed_Terms, Ray -> Mixed_Dir_Dir);
X      Square_Term += Temp_Term;
X      }
X   else
X      Square_Term = 0.0;
X
X   VDot (Linear_Term, Shape -> Object_2_Terms, Ray -> Initial_Direction);
X   Linear_Term *= 2.0;
X   VDot (Temp_Term, Shape -> Object_Terms, Ray -> Direction);
X   Linear_Term += Temp_Term;
X   VDot (Temp_Term, Shape -> Object_Mixed_Terms, Ray -> Mixed_Init_Dir);
X   Linear_Term += Temp_Term;
X
X   if (Ray == VP_Ray)
X      if (!Shape -> Constant_Cached)
X         {
X         VDot (Constant_Term, Shape -> Object_2_Terms, Ray -> Initial_2);
X         VDot (Temp_Term, Shape -> Object_Terms, Ray -> Initial);
X         Constant_Term +=  Temp_Term + Shape -> Object_Constant;
X         Shape -> Object_VP_Constant = Constant_Term;
X         Shape -> Constant_Cached = TRUE;
X         }
X      else
X         Constant_Term = Shape -> Object_VP_Constant;
X   else
X      {
X      VDot (Constant_Term, Shape -> Object_2_Terms, Ray -> Initial_2);
X      VDot (Temp_Term, Shape -> Object_Terms, Ray -> Initial);
X      Constant_Term += Temp_Term + Shape -> Object_Constant;
X      }
X
X   VDot (Temp_Term, Shape -> Object_Mixed_Terms, 
X         Ray -> Mixed_Initial_Initial);
X   Constant_Term += Temp_Term;
X
X   if (Square_Term != 0.0)
X      {
X  /* The equation is quadratic - find its roots */
X
X      Determinant_2 = Linear_Term * Linear_Term - 4.0 * Square_Term * Constant_Term;
X
X      if (Determinant_2 < 0.0)
X         return (FALSE);
X
X      Determinant = sqrt (Determinant_2);
X      A2 = Square_Term * 2.0;
X      BMinus = Linear_Term * -1.0;
X
X      *Depth1 = (BMinus + Determinant) / A2;
X      *Depth2 = (BMinus - Determinant) / A2;
X      }
X   else
X      {
X    /* There are no quadratic terms.  Solve the linear equation instead. */
X      if (Linear_Term == 0.0)
X         return (FALSE);
X
X      *Depth1 = Constant_Term * -1.0 / Linear_Term;
X      *Depth2 = *Depth1;
X      }
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_Quadric_Tests_Succeeded++;
X   return (TRUE);
X   }
X
Xint Inside_Quadric (Point, Object)
X   VECTOR *Point;
X   OBJECT *Object;
X   {
X   QUADRIC *Shape = (QUADRIC *) Object;
X   VECTOR New_Point;
X   register DBL Result, Linear_Term, Square_Term;
X
X   VDot (Linear_Term, *Point, Shape -> Object_Terms);
X   Result = Linear_Term + Shape -> Object_Constant;
X   VSquareTerms (New_Point, *Point);
X   VDot (Square_Term, New_Point, Shape -> Object_2_Terms);
X   Result += Square_Term;
X   Result += Shape -> Object_Mixed_Terms.x * (Point -> x) * (Point -> y)
X            + Shape -> Object_Mixed_Terms.y * (Point -> x) * (Point -> z)
X            + Shape -> Object_Mixed_Terms.z * (Point -> y) * (Point -> z);
X
X   if (Result < Small_Tolerance)
X      return (TRUE);
X
X   return (FALSE);
X   }
X
Xvoid Quadric_Normal (Result, Object, Intersection_Point)
X   VECTOR *Result, *Intersection_Point;
X   OBJECT *Object;
X   {
X   QUADRIC *Intersection_Shape = (QUADRIC *) Object;
X   VECTOR Derivative_Linear;
X
X   VScale (Derivative_Linear, Intersection_Shape -> Object_2_Terms, 2.0);
X   VEvaluate (*Result, Derivative_Linear, *Intersection_Point);
X   VAdd (*Result, *Result, Intersection_Shape -> Object_Terms);
X
X   Result -> x += 
X         Intersection_Shape -> Object_Mixed_Terms.x * Intersection_Point -> y +
X         Intersection_Shape -> Object_Mixed_Terms.y * Intersection_Point -> z;
X
X
X   Result -> y +=
X         Intersection_Shape -> Object_Mixed_Terms.x * Intersection_Point -> x +
X         Intersection_Shape -> Object_Mixed_Terms.z * Intersection_Point -> z;
X
X   Result -> z +=
X         Intersection_Shape -> Object_Mixed_Terms.y * Intersection_Point -> x +
X         Intersection_Shape -> Object_Mixed_Terms.z * Intersection_Point -> y;
X
X   VNormalize (*Result, *Result);
X   Perturb_Normal (Result, Intersection_Shape -> Parent_Object,
X                   Intersection_Point, Result);
X   }
X
Xvoid *Copy_Quadric (Object)
X   OBJECT *Object;
X   {
X   QUADRIC *New_Shape;
X
X   New_Shape = Get_Quadric_Shape ();
X   *New_Shape = *((QUADRIC *) Object);
X   New_Shape -> Next_Object = NULL;
X   return (New_Shape);
X   }
X
Xvoid Transform_Quadric (Shape, Transformation)
X   QUADRIC *Shape;
X   TRANSFORMATION *Transformation;
X   {
X   MATRIX Quadric_Matrix, Transform_Transposed;
X
X   Quadric_To_Matrix (Shape, (MATRIX *) &Quadric_Matrix[0][0]);
X   MTimes ((MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &(Transformation -> inverse[0][0]), (MATRIX *) &Quadric_Matrix[0][0]);
X   MTranspose ((MATRIX *) &Transform_Transposed[0][0], (MATRIX *) &(Transformation -> inverse[0][0]));
X   MTimes ((MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &Quadric_Matrix[0][0], (MATRIX *) &Transform_Transposed[0][0]);
X   Matrix_To_Quadric ((MATRIX *) &Quadric_Matrix[0][0], Shape);
X   }
X
Xvoid Quadric_To_Matrix (Quadric, Matrix)
X   QUADRIC *Quadric;
X   MATRIX *Matrix;
X   {
X   MZero (Matrix);
X   (*Matrix)[0][0] = Quadric -> Object_2_Terms.x;
X   (*Matrix)[1][1] = Quadric -> Object_2_Terms.y;
X   (*Matrix)[2][2] = Quadric -> Object_2_Terms.z;
X   (*Matrix)[0][1] = Quadric -> Object_Mixed_Terms.x;
X   (*Matrix)[0][2] = Quadric -> Object_Mixed_Terms.y;
X   (*Matrix)[0][3] = Quadric -> Object_Terms.x;
X   (*Matrix)[1][2] = Quadric -> Object_Mixed_Terms.z;
X   (*Matrix)[1][3] = Quadric -> Object_Terms.y;
X   (*Matrix)[2][3] = Quadric -> Object_Terms.z;
X   (*Matrix)[3][3] = Quadric -> Object_Constant;
X   }
X
Xvoid Matrix_To_Quadric (Matrix, Quadric)
X   MATRIX *Matrix;
X   QUADRIC *Quadric;
X   {
X   Quadric -> Object_2_Terms.x = (*Matrix)[0][0];
X   Quadric -> Object_2_Terms.y = (*Matrix)[1][1];
X   Quadric -> Object_2_Terms.z = (*Matrix)[2][2];
X   Quadric -> Object_Mixed_Terms.x = (*Matrix)[0][1] + (*Matrix)[1][0];
X   Quadric -> Object_Mixed_Terms.y = (*Matrix)[0][2] + (*Matrix)[2][0];
X   Quadric -> Object_Terms.x = (*Matrix)[0][3] + (*Matrix)[3][0];
X   Quadric -> Object_Mixed_Terms.z = (*Matrix)[1][2] + (*Matrix)[2][1];
X   Quadric -> Object_Terms.y = (*Matrix)[1][3] + (*Matrix)[3][1];
X   Quadric -> Object_Terms.z = (*Matrix)[2][3] + (*Matrix)[3][2];
X   Quadric -> Object_Constant = (*Matrix)[3][3];
X   }
X
Xvoid Translate_Quadric (Object, Vector)
X   OBJECT *Object;
X   VECTOR *Vector;
X   {
X   TRANSFORMATION Transformation;
X
X   Get_Translation_Transformation (&Transformation, Vector);
X   Transform_Quadric ((QUADRIC *) Object, &Transformation);
X   }
X
Xvoid Rotate_Quadric (Object, Vector)
X   OBJECT *Object;
X   VECTOR *Vector;
X   {
X   TRANSFORMATION Transformation;
X
X   Get_Rotation_Transformation (&Transformation, Vector);
X   Transform_Quadric ((QUADRIC *) Object, &Transformation);
X   }
X
Xvoid Scale_Quadric (Object, Vector)
X   OBJECT *Object;
X   VECTOR *Vector;
X   {
X   TRANSFORMATION Transformation;
X
X   Get_Scaling_Transformation (&Transformation, Vector);
X   Transform_Quadric ((QUADRIC *) Object, &Transformation);
X   }
X
Xvoid Invert_Quadric (Object)
X   OBJECT *Object;
X   {
X   QUADRIC *Shape = (QUADRIC *) Object;
X
X   VScale (Shape -> Object_2_Terms, Shape -> Object_2_Terms, -1.0);
X   VScale (Shape -> Object_Mixed_Terms, Shape -> Object_Mixed_Terms, -1.0);
X   VScale (Shape -> Object_Terms, Shape -> Object_Terms, -1.0);
X   Shape -> Object_Constant *= -1.0;
X   }
END_OF_FILE
if test 11498 -ne `wc -c <'src/quadrics.c'`; then
    echo shar: \"'src/quadrics.c'\" unpacked with wrong size!
fi
# end of 'src/quadrics.c'
fi
echo shar: End of archive 4 \(of 10\).
cp /dev/null ark4isdone
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.