home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------------
-
- RAW to 3D Studio Converter
- Copyright (c) 1993 Steve Anger
-
- Reads a list of triangle coordinates in raw ASCII text format and
- outputs a 3D Studio ASCII save file. This file may be freely modified and
- distributed.
-
- CompuServe: 70714,3113
- Internet: 70714.3113@compuserve.com
- YCCMR BBS: (708)358-5611
-
- --------------------------------------------------------------------------*/
-
- #ifndef __GNUC__
- #include <alloc.h>
- #endif
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <values.h>
- #include <ctype.h>
-
- #define VERSION "v1.1"
- #define MAX_TEXTURE 400
-
- #ifdef __TURBOC__
- extern unsigned _stklen = 16384;
- #endif
-
- #define DEFAULT 0
- #define TEXTURE 2
-
- #define HASHSIZE (1000)
-
- #define VERTEX_LIMIT (65500)
-
- typedef struct {
- float x, y, z;
- } Vector;
-
- typedef char *Material;
-
- typedef struct {
- int vert[3];
- int text_index;
- } Triangle;
-
- typedef struct VList {
- int vert;
- struct VList *next;
- } VertList;
-
- Material *mtable; /* Material table */
- int mmax; /* Maximum size of table */
- int msize; /* Current size */
-
- Vector *vtable; /* Vertice table */
- int vmax; /* Maximum size of table */
- int vsize; /* Current size */
-
- Triangle *ttable; /* Triangle table */
- int tmax; /* Maximum size of table */
- int tsize; /* Current size */
-
- VertList *vert_hash[HASHSIZE]; /* Hash table for looking up vertices */
-
- char last_material[64] = "";
- int material_index;
- char object_name[64] = "";
-
- FILE *in, *out;
- char infile[64]; /* Name of input file */
- char outfile[64]; /* Name of output file */
- int format; /* Input file format type */
- long line_cnt; /* Line number */
- int reverse; /* Reverse vertex ordering */
- int initialized;
-
- float ax, ay, az;
- float bx, by, bz;
- float cx, cy, cz;
- char new_obj_name[80];
- char new_material[80];
- char obj_name[80] = "";
-
- void process_args (int argc, char *argv[]);
- char *next_token (FILE *f);
- int parse_input (FILE *f);
- char upcase (char c);
- void set_material (char *material_name);
- int add_tri (float ax, float ay, float az, float bx, float by, float bz, float
- cx, float cy, float cz);
- void init_object (void);
- void cleanup_object (void);
- void write_file (char *obj_name);
- int material_lookup (char *material_name);
- int vert_lookup (float x, float y, float z);
- void abortmsg (char *msg, int exit_code);
- void add_ext (char *fname, char *ext, int force);
- void fswap (float *a, float *b);
-
-
- int main (int argc, char *argv[])
- {
- int obj_cnt;
- int done;
-
- process_args (argc, argv);
-
- in = fopen (infile, "r");
- if (in == NULL) {
- printf ("Error opening input file %s\n", infile);
- exit(1);
- }
-
- out = fopen (outfile, "w");
- if (out == NULL) {
- printf ("Error opening output file %s\n", outfile);
- exit(1);
- }
-
- /* Use the name of the file as default object name */
- strcpy (obj_name, infile);
- add_ext (obj_name, "", 1);
-
- line_cnt = 0;
- obj_cnt = 0;
- initialized = 0;
- done = 0;
-
- printf ("Reading file...\n");
-
- while (!done) {
- switch (parse_input (in)) {
- /* End of file */
- case 0: done = 1;
- break;
-
- case 1: strcpy (new_material, "");
- set_material (new_material);
- add_tri (ax, ay, az, bx, by, bz, cx, cy, cz);
- break;
-
- case 2: set_material (new_material);
- add_tri (ax, ay, az, bx, by, bz, cx, cy, cz);
- break;
-
- case 3: if (tsize > 0) {
- write_file (obj_name);
- ++obj_cnt;
- }
-
- strcpy (obj_name, new_obj_name);
- printf ("Working on: %s\n", obj_name);
- break;
- }
- }
-
- write_file (obj_name);
- ++obj_cnt;
-
- fclose (in);
- fclose (out);
-
- printf ("\n");
-
- return 0;
- }
-
-
- void process_args (int argc, char *argv[])
- {
- int i;
-
- printf ("\n");
- printf ("Raw to 3D Studio Converter %s - Copyright (c) 1993 Steve Anger\n", VERSION);
- #if defined(__GNUC__) && defined(i386)
- printf ("32 bit version. DOS Extender Copyright (c) 1991 DJ Delorie\n");
- #endif
- printf ("This program is freely distributable\n");
- printf ("\n");
-
- if (argc < 2) {
- printf ("Usage: raw23ds inputfile[.raw] [outputfile[.asc]] [options]\n\n");
- printf ("Options: -r - Reverse vertex ordering\n");
- printf (" -m - Input file has materials specified\n");
- printf ("\nex. raw23ds chess.raw chess.asc\n\n");
- exit(1);
- }
-
- infile[0] = '\0';
- outfile[0] = '\0';
-
- format = DEFAULT;
- reverse = 0;
-
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-' || argv[i][0] == '/') {
- switch (upcase(argv[i][1])) {
- case 'M': format = TEXTURE;
- break;
-
- case 'R': reverse = 1;
- break;
-
- default : printf ("\nInvalid option -%c\n", argv[i][1]);
- exit (1);
- }
- }
- else if (infile[0] == '\0') {
- strcpy (infile, argv[i]);
- add_ext (infile, "raw", 0);
- }
- else if (outfile[0] == '\0') {
- strcpy (outfile, argv[i]);
- add_ext (outfile, "asc", 0);
- }
- else
- abortmsg ("Too many file names specified.\n", 1);
- }
-
- if (outfile[0] == '\0') {
- strcpy (outfile, infile);
- add_ext (outfile, "asc", 1);
- }
- }
-
-
- char *next_token (FILE *f)
- {
- char QUOTE = '\"';
- static char token[128];
- int index, comment, quoted;
- char ch;
-
- index = 0;
- comment = 0;
-
- strcpy (token, "");
-
- /* Skip the white space */
- while (1) {
- ch = fgetc (f);
-
- if (feof(f))
- break;
-
- if (ch == '\n')
- ++line_cnt;
- else if (ch == '{')
- comment += 1;
- else if (ch == '}')
- comment = (comment > 0) ? (comment - 1) : 0;
- else if (!isspace(ch) && !comment)
- break;
- }
-
- if (feof(f))
- return token;
-
- quoted = (ch == QUOTE);
-
- if (!quoted)
- ungetc (ch, f);
-
- while (1) {
- ch = fgetc (f);
-
- if (feof(f))
- break;
-
- if (ch == '\n')
- ++line_cnt;
-
- if ((quoted && ch == QUOTE) || (!quoted && isspace(ch)))
- break;
-
- if (index < 127)
- token[index++] = ch;
- }
-
- token[index] = '\0';
-
- return token;
- }
-
-
- int parse_input (FILE *f)
- {
- static int name_seq = 0;
- static char base_name[64];
- int token_cnt, expected, result;
- char *token;
- char tokens[12][64];
-
- token_cnt = 0;
- expected = 0;
- result = -1;
-
- /* 3DS can't handle more than 65536 vertices per object.
- Split huge objects into multiple pieces */
- if (vsize > (VERTEX_LIMIT-4)) {
- name_seq++;
-
- if (name_seq == 1)
- strcpy (base_name, obj_name);
-
- sprintf (new_obj_name, "%s_%d", base_name, name_seq+1);
-
- return 3; /* New object name */
- }
-
- /* How many tokens to expect per triangle */
- switch (format) {
- case DEFAULT: expected = 9;
- break;
-
- case TEXTURE: expected = 10;
- break;
- }
-
- do {
- token = next_token (f);
-
- if (strlen(token) == 0)
- break;
-
- if (!isdigit(token[0]) && token[0] != '+' && token[0] != '-') {
- if (token_cnt == 0) {
- strcpy (new_obj_name, token);
- name_seq = 0;
- return 3; /* New object name */
- }
- else if (token_cnt != 9 || expected != 10) {
- printf ("Error in input file, line %ld. Misplaced object name.\n", line_cnt);
- exit(1);
- }
- }
-
- strcpy (tokens[token_cnt++], token);
- } while (token_cnt < expected);
-
- if (token_cnt == 0)
- return 0; /* End of file */
-
- if (token_cnt != expected) {
- printf ("Error in input file, line %ld. Unexpected end of file.\n", line_cnt);
- exit(1);
- }
-
- switch (format) {
- case DEFAULT: /* Ax Ay Az Bx By Bz Cx Cy Cz */
- ax = atof(tokens[0]);
- ay = atof(tokens[1]);
- az = atof(tokens[2]);
- bx = atof(tokens[3]);
- by = atof(tokens[4]);
- bz = atof(tokens[5]);
- cx = atof(tokens[6]);
- cy = atof(tokens[7]);
- cz = atof(tokens[8]);
- result = 1;
- break;
-
- case TEXTURE: /* Ax Ay Az Bx By Bz Cx Cy Cz Texture */
- ax = atof(tokens[0]);
- ay = atof(tokens[1]);
- az = atof(tokens[2]);
- bx = atof(tokens[3]);
- by = atof(tokens[4]);
- bz = atof(tokens[5]);
- cx = atof(tokens[6]);
- cy = atof(tokens[7]);
- cz = atof(tokens[8]);
- strcpy (new_material, tokens[9]);
- result = 2;
- break;
- }
-
- if (reverse) {
- fswap (&ax, &bx);
- fswap (&ay, &by);
- fswap (&az, &bz);
- }
-
- return result;
- }
-
-
- /* Convert character 'c' top upper case */
- char upcase (char c)
- {
- if (c >= 'a' && c <= 'z')
- c = c - 'a' + 'A';
-
- return c;
- }
-
-
- void set_material (char *material_name)
- {
- char new_material[64];
-
- strcpy (new_material, material_name);
-
- if (strcmp (last_material, new_material) != 0) {
- strcpy (last_material, new_material);
- material_index = material_lookup (new_material);
- }
- }
-
-
- /* Add a new triangle to the database */
- int add_tri (float ax, float ay, float az,
- float bx, float by, float bz,
- float cx, float cy, float cz)
- {
- if (!initialized)
- init_object();
-
- ++tsize;
- if (tsize > tmax) {
- /* table not big enough, expand it */
- tmax = tmax + 100;
- ttable = realloc (ttable, tmax * sizeof(Triangle));
- if (ttable == NULL)
- abortmsg ("Insufficient memory for triangles.\n", 1);
- }
-
- /* Look up the vertex and material indexes */
- ttable[tsize-1].vert[0] = vert_lookup (ax, ay, az);
- ttable[tsize-1].vert[1] = vert_lookup (bx, by, bz);
- ttable[tsize-1].vert[2] = vert_lookup (cx, cy, cz);
-
- ttable[tsize-1].text_index = material_index;
-
- return 0;
- }
-
-
- void init_object()
- {
- int i;
-
- material_index = -1;
- strcpy (last_material, "");
-
- /* Allocate memory for material table */
- mmax = 10;
- msize = 0;
- mtable = malloc (mmax * sizeof(Material));
- if (mtable == NULL)
- abortmsg ("Insufficient memory for materials.", 1);
-
- /* Allocate memory for vertex lookup table */
- vmax = 1000;
- vsize = 0;
- vtable = malloc (vmax * sizeof(Vector));
- if (vtable == NULL)
- abortmsg ("Insufficient memory for vertices.", 1);
-
- /* Allocate memory for triangle lookup table */
- tmax = 1000;
- tsize = 0;
- ttable = malloc (tmax * sizeof(Triangle));
- if (ttable == NULL)
- abortmsg ("Insufficient memory for triangles.", 1);
-
- /* Initialize the vertex lookup hash table */
- for (i = 0; i < HASHSIZE; i++)
- vert_hash[i] = NULL;
-
- initialized = 1;
- }
-
-
- void cleanup_object()
- {
- int i;
-
- free (vtable);
- free (ttable);
-
- for (i = 0; i < msize; i++)
- free (mtable[i]);
-
- free (mtable);
-
- tsize = 0;
- vsize = 0;
- msize = 0;
-
- initialized = 0;
- }
-
-
- void write_file (char *obj_name)
- {
- int i;
-
- if (!initialized || tsize == 0)
- return;
-
- fprintf (out, "Named object: \"%s\"\n", obj_name);
- fprintf (out, "Tri-mesh, Vertices: %d Faces: %d\n", vsize, tsize);
-
- fprintf (out, "Vertex list:\n");
- for (i = 0; i < vsize; i++) {
- fprintf (out, "Vertex %d: X: %f Y: %f Z: %f\n",
- i, vtable[i].x, vtable[i].y, vtable[i].z);
- }
-
- fprintf (out, "Face list:\n");
- for (i = 0; i < tsize; i++) {
- fprintf (out, "Face %d: A:%d B:%d C:%d\n",
- i, ttable[i].vert[0], ttable[i].vert[1], ttable[i].vert[2]);
-
- if (ttable[i].text_index >= 0)
- fprintf (out, "Material:\"%s\"\n", mtable[ttable[i].text_index]);
-
- fprintf (out, "Smoothing: 1\n");
- }
-
- fprintf (out, "\n\n");
-
- cleanup_object();
- }
-
-
- int material_lookup (char *material_name)
- {
- int i;
-
- if (!initialized)
- init_object();
-
- if (strlen(material_name) == 0)
- return -1;
-
- /* The material table is usually small so just do a simple linear search */
- for (i = msize-1; i >= 0; i--) {
- if (strcmp (mtable[i], material_name) == 0)
- break;
- }
-
- if (i >= 0)
- return i;
-
- /* not found, insert the new material into the table */
- ++msize;
- if (msize > mmax) {
- /* table not big enough, resize it */
- mmax = mmax + 10;
- mtable = realloc (mtable, mmax * sizeof(Material));
- if (mtable == NULL)
- abortmsg ("Insufficient memory to expand material table.", 1);
- }
-
- mtable[msize-1] = malloc (strlen(material_name) + 1);
- if (mtable[msize-1] == NULL)
- abortmsg ("Insufficient memory for material name.", 1);
-
- strcpy (mtable[msize-1], material_name);
-
- return (msize-1);
- }
-
-
- /* Find the specified vertex in the vertex table */
- int vert_lookup (float x, float y, float z)
- {
- VertList *p, *new_node;
- unsigned hash;
-
- /* Vertex table is usually very large, use hash lookup */
- hash = (unsigned)((int)(326.4*x) ^ (int)(694.7*y) ^ (int)(1423.6*z)) % HASHSIZE;
-
- for (p = vert_hash[hash]; p != NULL; p = p->next) {
- if (vtable[p->vert].x == x && vtable[p->vert].y == y &&
- vtable[p->vert].z == z) break;
- }
-
- if (p != NULL)
- return (p->vert); /* found, return the table index */
-
- /* not found, insert the new vertex into the table */
- ++vsize;
- if (vsize > vmax) {
- /* table not big enough, expand it */
- vmax = vmax + 100;
- vtable = realloc (vtable, vmax * sizeof(Vector));
- if (vtable == NULL)
- abortmsg ("Insufficient memory for vertices.\n", 1);
- }
-
- vtable[vsize-1].x = x;
- vtable[vsize-1].y = y;
- vtable[vsize-1].z = z;
-
- new_node = malloc (sizeof(VertList));
- if (new_node == NULL)
- abortmsg ("Insufficient memory for hash table.", 1);
-
- new_node->vert = vsize-1;
- new_node->next = vert_hash[hash];
- vert_hash[hash] = new_node;
-
- return (vsize-1);
- }
-
-
- void abortmsg (char *msg, int exit_code)
- {
- printf ("\n%s\n", msg);
- exit (exit_code);
- }
-
-
- void add_ext (char *fname, char *ext, int force)
- {
- int i;
-
- for (i = 0; i < strlen(fname); i++)
- if (fname[i] == '.') break;
-
- if (fname[i] == '\0' || force) {
- if (strlen(ext) > 0)
- fname[i++] = '.';
-
- strcpy (&fname[i], ext);
- }
- }
-
-
- void fswap (float *a, float *b)
- {
- float temp;
-
- temp = *a;
- *a = *b;
- *b = temp;
- }
-
-
-