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.