/*****************************************************************************
*
*                                    Sculpt2dat.c
*
*   from DKBTrace (c) 1990  David Buck
*
*  This program reads a Sculpt-Animate 3D format scene file and generates an
*  output file that may be read in to DKBTrace.
*
* This software is freely distributable. The source and/or object code may be
* copied or uploaded to communications services so long as this notice remains
* at the top of each file.  If any changes are made to the program, you must
* clearly indicate in the documentation and in the programs startup message
* who it was who made the changes. The documentation should also describe what
* those changes were. This software may not be included in whole or in
* part into any commercial package without the express written consent of the
* author.  It may, however, be included in other public domain or freely
* distributed software so long as the proper credit for the software is given.
*
* This software is provided as is without any guarantees or warranty. Although
* the author has attempted to find and correct any bugs in the software, he
* is not responsible for any damage caused by the use of the software.  The
* author is under no obligation to provide service, corrections, or upgrades
* to this package.
*
* Despite all the legal stuff above, if you do find bugs, I would like to hear
* about them.  Also, if you have any comments or questions, you may contact me
* at the following address:
*
*     David Buck
*     22C Sonnet Cres.
*     Nepean Ontario
*     Canada, K2H 8W7
*
*  I can also be reached on the following bulleton boards:
*
*     ATX              (613) 526-4141
*     OMX              (613) 731-3419
*     Mystic           (613) 731-0088 or (613) 731-6698
*
*  Fidonet:   1:163/109.9
*  Internet:  David_Buck@Carleton.CA
*
*  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
*
*     Lattice BBS                      (708) 916-1200
*     The Information Exchange BBS     (708) 945-5575
*     Stillwaters BBS                  (708) 403-2826
*
*****************************************************************************/


#include <stdio.h>
#include "frame.h"
#include "dkbproto.h"

void read_iff_file(void);

IMAGE_COLOUR *iff_colour_map;
int colourmap_size;
FILE *f, *out;

static CHUNK_HEADER Chunk_Header;

DBL *vertices_x, *vertices_y, *vertices_z;
DBL max_x, max_y, max_z, min_x, min_y, min_z;
#define FABS(x) ((x<0.0)?-x:x)

#define FORM 0x464f524dL
#define SC3D 0x53433344L
#define VERT 0x56455254L
#define FACE 0x46414345L

#define CMPNONE 0

char *Textures[7] = {"Dull", "Shiny", "Mirror", "Luminous", "Glass", "Metal", "Glass2"};

void iff_error ()
   {
   printf ("Invalid iff file\n");
   exit(1);
   }

int read_byte(f)
   FILE *f;
   {
   int c;
   if ((c = getc(f)) == EOF)
      iff_error();
   return (c);
   }

int read_word(f)
   FILE *f;
   {
   int result;

   result = read_byte(f)*256;
   result += read_byte(f);
   return (result);
   }

long read_long(f)
   FILE *f;
   {
   int i;
   long result;

   result = 0;
   for (i = 0 ; i < 4 ; i++)
      result = result * 256 + read_byte(f);

   return (result);
   }

void Read_Chunk_Header (f, dest)
   FILE *f;
   CHUNK_HEADER *dest;
   {
   dest->name = read_long(f);
   dest->size = (int) read_long(f);
   }

void read_iff_file()
   {
   int i;
   int vert1, vert2, vert3;
   unsigned int texture;
   DBL red, green, blue;

   max_x = max_y = max_z = -10000000.0;
   min_x = min_y = min_z = 10000000.0;

   while (1) {
      Read_Chunk_Header(f, &Chunk_Header);
      switch ((int) Chunk_Header.name) {
         case FORM: if (read_long(f) != SC3D)
                       iff_error();
                    break;

         case VERT: vertices_x = (DBL *)
                        malloc (Chunk_Header.size * (sizeof(DBL)/sizeof(long)));
                    vertices_y = (DBL *)
                        malloc (Chunk_Header.size * (sizeof(DBL)/sizeof(long)));
                    vertices_z = (DBL *)
                        malloc (Chunk_Header.size * (sizeof(DBL)/sizeof(long)));
                    for (i = 0 ; i < Chunk_Header.size/12 ; i++) {
                       vertices_x[i] = read_long(f) / 10000.0;
                       if (vertices_x[i] < min_x)
                          min_x = vertices_x[i];
                       if (vertices_x[i] > max_x)
                          max_x = vertices_x[i];

                       vertices_y[i] = read_long(f) / 10000.0;
                       if (vertices_y[i] < min_y)
                          min_y = vertices_y[i];
                       if (vertices_y[i] > max_y)
                          max_y = vertices_y[i];

                       vertices_z[i] = read_long(f) / 10000.0;
                       if (vertices_z[i] < min_z)
                          min_z = vertices_z[i];
                       if (vertices_z[i] > max_z)
                          max_z = vertices_z[i];
                       }
                    break;

         case FACE: for (i = 0 ; i < Chunk_Header.size/16 ; i++) {
                       vert1 = (int) read_long(f);
                       vert2 = (int) read_long(f);
                       vert3 = (int) read_long(f);
                       red = read_byte(f) / 255.0;
                       green = read_byte(f) / 255.0;
                       blue = read_byte(f) / 255.0;

		       texture = read_byte(f);
		       texture &= 0x07;		/* mask upper bits */

		       fprintf (out, "OBJECT TRIANGLE <%f %f %f> <%f %f %f> <%f %f %f> END_TRIANGLE COLOUR RED %f GREEN %f BLUE %f TEXTURE %s END_TEXTURE END_OBJECT\n",
                          vertices_x[vert1], vertices_y[vert1], vertices_z[vert1],
                          vertices_x[vert2], vertices_y[vert2], vertices_z[vert2],
                          vertices_x[vert3], vertices_y[vert3], vertices_z[vert3],
                          red, green, blue, Textures[texture]);
                       }
                    return;

         default:
            for (i = 0 ; i < Chunk_Header.size ; i++)
               if (getc(f) == EOF)
                  iff_error();
            break;
         }
      }
   }

void main (argc, argv)
   int argc;
   char **argv;
   {
   if (argc != 3) {
      printf ("Usage: %s <scene-file> <output-file>\n", argv[0]);
      exit (1);
      }
   
   if ((f = fopen(argv[1], "rb")) == NULL) {
      printf ("Cannot open IFF file %s\n", argv[1]);
      exit(1);
      }

   if ((out = fopen(argv[2], "w")) == NULL) {
      printf ("Cannot open output file %s\n", argv[1]);
      exit(1);
      }
   
   fprintf(out, "COMPOSITE\n");
   read_iff_file();
   fprintf(out, "   BOUNDED_BY\n      INTERSECTION\n");
   fprintf(out, "         PLANE <1.0  0.0  0.0> %1.02f END_PLANE\n", FABS(max_x) * 1.01);
   fprintf(out, "         PLANE <-1.0 0.0  0.0> %1.02f END_PLANE\n", FABS(min_x) * 1.01);
   fprintf(out, "         PLANE <0.0  1.0  0.0> %1.02f END_PLANE\n", FABS(max_y) * 1.01);
   fprintf(out, "         PLANE <0.0 -1.0  0.0> %1.02f END_PLANE\n", FABS(min_y) * 1.01);
   fprintf(out, "         PLANE <0.0  0.0  1.0> %1.02f END_PLANE\n", FABS(max_z) * 1.01);
   fprintf(out, "         PLANE <0.0  0.0 -1.0> %1.02f END_PLANE\n", FABS(min_z) * 1.01);
   fprintf(out, "      END_INTERSECTION\n   END_BOUND\n   \nEND_COMPOSITE\n");
   printf ("X values range from %f to %f\n", min_x, max_x);
   printf ("Y values range from %f to %f\n", min_y, max_y);
   printf ("Z values range from %f to %f\n", min_z, max_z);
   fclose(f);
   fclose(out);
   }
