home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / 3dstudio / utility / raw3ds / raw23ds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-05  |  14.1 KB  |  648 lines

  1. /*-------------------------------------------------------------------------
  2.  
  3.                RAW to 3D Studio Converter
  4.              Copyright (c) 1993 Steve Anger
  5.  
  6.    Reads a list of triangle coordinates in raw ASCII text format and
  7.  outputs a 3D Studio ASCII save file. This file may be freely modified and
  8.  distributed.
  9.  
  10.                       CompuServe: 70714,3113
  11.                     Internet: 70714.3113@compuserve.com
  12.                        YCCMR BBS: (708)358-5611
  13.  
  14. --------------------------------------------------------------------------*/
  15.  
  16. #ifndef __GNUC__
  17. #include <alloc.h>
  18. #endif
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <values.h>
  24. #include <ctype.h>
  25.  
  26. #define VERSION "v1.1"
  27. #define MAX_TEXTURE 400
  28.  
  29. #ifdef __TURBOC__
  30. extern unsigned _stklen = 16384;
  31. #endif
  32.  
  33. #define DEFAULT  0
  34. #define TEXTURE  2
  35.  
  36. #define HASHSIZE (1000)
  37.  
  38. #define VERTEX_LIMIT (65500)
  39.  
  40. typedef struct {
  41.     float x, y, z;
  42. } Vector;
  43.  
  44. typedef char *Material;
  45.  
  46. typedef struct {
  47.     int vert[3];
  48.     int text_index;
  49. } Triangle;
  50.  
  51. typedef struct VList {
  52.     int          vert;
  53.     struct VList *next;
  54. } VertList;
  55.  
  56. Material  *mtable;         /* Material table */
  57. int       mmax;            /* Maximum size of table */
  58. int       msize;           /* Current size */
  59.  
  60. Vector    *vtable;         /* Vertice table */
  61. int       vmax;            /* Maximum size of table */
  62. int       vsize;           /* Current size */
  63.  
  64. Triangle  *ttable;         /* Triangle table */
  65. int       tmax;            /* Maximum size of table */
  66. int       tsize;           /* Current size */
  67.  
  68. VertList  *vert_hash[HASHSIZE];  /* Hash table for looking up vertices */
  69.  
  70. char      last_material[64] = "";
  71. int       material_index;
  72. char      object_name[64] = "";
  73.  
  74. FILE  *in, *out;
  75. char  infile[64];       /* Name of input file */
  76. char  outfile[64];      /* Name of output file */
  77. int   format;           /* Input file format type */
  78. long  line_cnt;         /* Line number */
  79. int   reverse;          /* Reverse vertex ordering */
  80. int   initialized;
  81.  
  82. float ax, ay, az;
  83. float bx, by, bz;
  84. float cx, cy, cz;
  85. char  new_obj_name[80];
  86. char  new_material[80];
  87. char  obj_name[80] = "";
  88.  
  89. void process_args (int argc, char *argv[]);
  90. char *next_token (FILE *f);
  91. int parse_input (FILE *f);
  92. char upcase (char c);
  93. void set_material (char *material_name);
  94. int add_tri (float ax, float ay, float az, float bx, float by, float bz, float
  95.      cx, float cy, float cz);
  96. void init_object (void);
  97. void cleanup_object (void);
  98. void write_file (char *obj_name);
  99. int material_lookup (char *material_name);
  100. int vert_lookup (float x, float y, float z);
  101. void abortmsg (char *msg, int exit_code);
  102. void add_ext (char *fname, char *ext, int force);
  103. void fswap (float *a, float *b);
  104.  
  105.  
  106. int main (int argc, char *argv[])
  107. {
  108.     int   obj_cnt;
  109.     int   done;
  110.  
  111.     process_args (argc, argv);
  112.  
  113.     in = fopen (infile, "r");
  114.     if (in == NULL) {
  115.     printf ("Error opening input file %s\n", infile);
  116.     exit(1);
  117.     }
  118.  
  119.     out = fopen (outfile, "w");
  120.     if (out == NULL) {
  121.     printf ("Error opening output file %s\n", outfile);
  122.     exit(1);
  123.     }
  124.  
  125.     /* Use the name of the file as default object name */
  126.     strcpy (obj_name, infile);
  127.     add_ext (obj_name, "", 1);
  128.  
  129.     line_cnt = 0;
  130.     obj_cnt = 0;
  131.     initialized = 0;
  132.     done = 0;
  133.  
  134.     printf ("Reading file...\n");
  135.  
  136.     while (!done) {
  137.     switch (parse_input (in)) {
  138.         /* End of file */
  139.         case  0: done = 1;
  140.              break;
  141.  
  142.         case  1: strcpy (new_material, "");
  143.              set_material (new_material);
  144.              add_tri (ax, ay, az, bx, by, bz, cx, cy, cz);
  145.              break;
  146.  
  147.         case  2: set_material (new_material);
  148.              add_tri (ax, ay, az, bx, by, bz, cx, cy, cz);
  149.              break;
  150.  
  151.         case  3: if (tsize > 0) {
  152.              write_file (obj_name);
  153.              ++obj_cnt;
  154.              }
  155.  
  156.              strcpy (obj_name, new_obj_name);
  157.              printf ("Working on: %s\n", obj_name);
  158.              break;
  159.     }
  160.     }
  161.  
  162.     write_file (obj_name);
  163.     ++obj_cnt;
  164.  
  165.     fclose (in);
  166.     fclose (out);
  167.  
  168.     printf ("\n");
  169.  
  170.     return 0;
  171. }
  172.  
  173.  
  174. void process_args (int argc, char *argv[])
  175. {
  176.     int i;
  177.  
  178.     printf ("\n");
  179.     printf ("Raw to 3D Studio Converter %s - Copyright (c) 1993 Steve Anger\n", VERSION);
  180. #if defined(__GNUC__) && defined(i386)
  181.     printf ("32 bit version. DOS Extender Copyright (c) 1991 DJ Delorie\n");
  182. #endif
  183.     printf ("This program is freely distributable\n");
  184.     printf ("\n");
  185.  
  186.     if (argc < 2) {
  187.     printf ("Usage: raw23ds inputfile[.raw] [outputfile[.asc]] [options]\n\n");
  188.     printf ("Options: -r  - Reverse vertex ordering\n");
  189.     printf ("         -m  - Input file has materials specified\n");
  190.     printf ("\nex. raw23ds chess.raw chess.asc\n\n");
  191.     exit(1);
  192.     }
  193.  
  194.     infile[0] = '\0';
  195.     outfile[0] = '\0';
  196.  
  197.     format = DEFAULT;
  198.     reverse = 0;
  199.  
  200.     for (i = 1; i < argc; i++) {
  201.     if (argv[i][0] == '-' || argv[i][0] == '/') {
  202.         switch (upcase(argv[i][1])) {
  203.         case 'M': format = TEXTURE;
  204.               break;
  205.  
  206.         case 'R': reverse = 1;
  207.               break;
  208.  
  209.         default : printf ("\nInvalid option -%c\n", argv[i][1]);
  210.               exit (1);
  211.         }
  212.     }
  213.     else if (infile[0] == '\0') {
  214.         strcpy (infile, argv[i]);
  215.         add_ext (infile, "raw", 0);
  216.     }
  217.     else if (outfile[0] == '\0') {
  218.         strcpy (outfile, argv[i]);
  219.         add_ext (outfile, "asc", 0);
  220.     }
  221.     else
  222.         abortmsg ("Too many file names specified.\n", 1);
  223.     }
  224.  
  225.     if (outfile[0] == '\0') {
  226.     strcpy (outfile, infile);
  227.     add_ext (outfile, "asc", 1);
  228.     }
  229. }
  230.  
  231.  
  232. char *next_token (FILE *f)
  233. {
  234.     char QUOTE = '\"';
  235.     static char token[128];
  236.     int  index, comment, quoted;
  237.     char ch;
  238.  
  239.     index = 0;
  240.     comment = 0;
  241.  
  242.     strcpy (token, "");
  243.  
  244.     /* Skip the white space */
  245.     while (1) {
  246.     ch = fgetc (f);
  247.  
  248.     if (feof(f))
  249.         break;
  250.  
  251.     if (ch == '\n')
  252.        ++line_cnt;
  253.     else if (ch == '{')
  254.         comment += 1;
  255.     else if (ch == '}')
  256.         comment = (comment > 0) ? (comment - 1) : 0;
  257.     else if (!isspace(ch) && !comment)
  258.         break;
  259.     }
  260.  
  261.     if (feof(f))
  262.     return token;
  263.  
  264.     quoted = (ch == QUOTE);
  265.  
  266.     if (!quoted)
  267.     ungetc (ch, f);
  268.  
  269.     while (1) {
  270.     ch = fgetc (f);
  271.  
  272.     if (feof(f))
  273.        break;
  274.  
  275.     if (ch == '\n')
  276.         ++line_cnt;
  277.  
  278.     if ((quoted && ch == QUOTE) || (!quoted && isspace(ch)))
  279.         break;
  280.  
  281.     if (index < 127)
  282.         token[index++] = ch;
  283.     }
  284.  
  285.     token[index] = '\0';
  286.  
  287.     return token;
  288. }
  289.  
  290.  
  291. int parse_input (FILE *f)
  292. {
  293.     static int name_seq = 0;
  294.     static char base_name[64];
  295.     int   token_cnt, expected, result;
  296.     char  *token;
  297.     char  tokens[12][64];
  298.  
  299.     token_cnt = 0;
  300.     expected  = 0;
  301.     result    = -1;
  302.  
  303.     /* 3DS can't handle more than 65536 vertices per object.
  304.        Split huge objects into multiple pieces */
  305.     if (vsize > (VERTEX_LIMIT-4)) {
  306.     name_seq++;
  307.  
  308.     if (name_seq == 1)
  309.         strcpy (base_name, obj_name);
  310.  
  311.     sprintf (new_obj_name, "%s_%d", base_name, name_seq+1);
  312.  
  313.     return 3; /* New object name */
  314.     }
  315.  
  316.     /* How many tokens to expect per triangle */
  317.     switch (format) {
  318.     case DEFAULT:  expected = 9;
  319.                break;
  320.  
  321.     case TEXTURE:  expected = 10;
  322.                break;
  323.     }
  324.  
  325.     do {
  326.     token = next_token (f);
  327.  
  328.     if (strlen(token) == 0)
  329.         break;
  330.  
  331.     if (!isdigit(token[0]) && token[0] != '+' && token[0] != '-') {
  332.         if (token_cnt == 0) {
  333.         strcpy (new_obj_name, token);
  334.         name_seq = 0;
  335.         return 3; /* New object name */
  336.         }
  337.         else if (token_cnt != 9 || expected != 10) {
  338.         printf ("Error in input file, line %ld. Misplaced object name.\n", line_cnt);
  339.         exit(1);
  340.         }
  341.     }
  342.  
  343.     strcpy (tokens[token_cnt++], token);
  344.     } while (token_cnt < expected);
  345.  
  346.     if (token_cnt == 0)
  347.     return 0; /* End of file */
  348.  
  349.     if (token_cnt != expected) {
  350.     printf ("Error in input file, line %ld. Unexpected end of file.\n", line_cnt);
  351.     exit(1);
  352.     }
  353.  
  354.     switch (format) {
  355.     case DEFAULT:  /* Ax Ay Az Bx By Bz Cx Cy Cz */
  356.         ax    = atof(tokens[0]);
  357.         ay    = atof(tokens[1]);
  358.         az    = atof(tokens[2]);
  359.         bx    = atof(tokens[3]);
  360.         by    = atof(tokens[4]);
  361.         bz    = atof(tokens[5]);
  362.         cx    = atof(tokens[6]);
  363.         cy    = atof(tokens[7]);
  364.         cz    = atof(tokens[8]);
  365.         result = 1;
  366.         break;
  367.  
  368.     case TEXTURE:  /* Ax Ay Az Bx By Bz Cx Cy Cz Texture */
  369.         ax    = atof(tokens[0]);
  370.         ay    = atof(tokens[1]);
  371.         az    = atof(tokens[2]);
  372.         bx    = atof(tokens[3]);
  373.         by    = atof(tokens[4]);
  374.         bz    = atof(tokens[5]);
  375.         cx    = atof(tokens[6]);
  376.         cy    = atof(tokens[7]);
  377.         cz    = atof(tokens[8]);
  378.         strcpy (new_material, tokens[9]);
  379.         result = 2;
  380.         break;
  381.     }
  382.  
  383.     if (reverse) {
  384.     fswap (&ax, &bx);
  385.     fswap (&ay, &by);
  386.     fswap (&az, &bz);
  387.     }
  388.  
  389.     return result;
  390. }
  391.  
  392.  
  393. /* Convert character 'c' top upper case */
  394. char upcase (char c)
  395. {
  396.     if (c >= 'a' && c <= 'z')
  397.     c = c - 'a' + 'A';
  398.  
  399.     return c;
  400. }
  401.  
  402.  
  403. void set_material (char *material_name)
  404. {
  405.     char new_material[64];
  406.  
  407.     strcpy (new_material, material_name);
  408.  
  409.     if (strcmp (last_material, new_material) != 0) {
  410.     strcpy (last_material, new_material);
  411.     material_index = material_lookup (new_material);
  412.     }
  413. }
  414.  
  415.  
  416. /* Add a new triangle to the database */
  417. int add_tri (float  ax, float  ay, float  az,
  418.          float  bx, float  by, float  bz,
  419.          float  cx, float  cy, float  cz)
  420. {
  421.     if (!initialized)
  422.     init_object();
  423.  
  424.     ++tsize;
  425.     if (tsize > tmax) {
  426.     /* table not big enough, expand it */
  427.     tmax = tmax + 100;
  428.     ttable = realloc (ttable, tmax * sizeof(Triangle));
  429.     if (ttable == NULL)
  430.         abortmsg ("Insufficient memory for triangles.\n", 1);
  431.     }
  432.  
  433.     /* Look up the vertex and material indexes */
  434.     ttable[tsize-1].vert[0] = vert_lookup (ax, ay, az);
  435.     ttable[tsize-1].vert[1] = vert_lookup (bx, by, bz);
  436.     ttable[tsize-1].vert[2] = vert_lookup (cx, cy, cz);
  437.  
  438.     ttable[tsize-1].text_index = material_index;
  439.  
  440.     return 0;
  441. }
  442.  
  443.  
  444. void init_object()
  445. {
  446.     int i;
  447.  
  448.     material_index = -1;
  449.     strcpy (last_material, "");
  450.  
  451.     /* Allocate memory for material table */
  452.     mmax   = 10;
  453.     msize  = 0;
  454.     mtable = malloc (mmax * sizeof(Material));
  455.     if (mtable == NULL)
  456.     abortmsg ("Insufficient memory for materials.", 1);
  457.  
  458.     /* Allocate memory for vertex lookup table */
  459.     vmax   = 1000;
  460.     vsize  = 0;
  461.     vtable = malloc (vmax * sizeof(Vector));
  462.     if (vtable == NULL)
  463.     abortmsg ("Insufficient memory for vertices.", 1);
  464.  
  465.     /* Allocate memory for triangle lookup table */
  466.     tmax   = 1000;
  467.     tsize  = 0;
  468.     ttable = malloc (tmax * sizeof(Triangle));
  469.     if (ttable == NULL)
  470.     abortmsg ("Insufficient memory for triangles.", 1);
  471.  
  472.     /* Initialize the vertex lookup hash table */
  473.     for (i = 0; i < HASHSIZE; i++)
  474.     vert_hash[i] = NULL;
  475.  
  476.     initialized = 1;
  477. }
  478.  
  479.  
  480. void cleanup_object()
  481. {
  482.     int i;
  483.  
  484.     free (vtable);
  485.     free (ttable);
  486.  
  487.     for (i = 0; i < msize; i++)
  488.     free (mtable[i]);
  489.  
  490.     free (mtable);
  491.  
  492.     tsize = 0;
  493.     vsize = 0;
  494.     msize = 0;
  495.  
  496.     initialized = 0;
  497. }
  498.  
  499.  
  500. void write_file (char *obj_name)
  501. {
  502.     int i;
  503.  
  504.     if (!initialized || tsize == 0)
  505.     return;
  506.  
  507.     fprintf (out, "Named object: \"%s\"\n", obj_name);
  508.     fprintf (out, "Tri-mesh, Vertices: %d  Faces: %d\n", vsize, tsize);
  509.  
  510.     fprintf (out, "Vertex list:\n");
  511.     for (i = 0; i < vsize; i++) {
  512.     fprintf (out, "Vertex %d:  X: %f Y: %f Z: %f\n",
  513.          i, vtable[i].x, vtable[i].y, vtable[i].z);
  514.     }
  515.  
  516.     fprintf (out, "Face list:\n");
  517.     for (i = 0; i < tsize; i++) {
  518.     fprintf (out, "Face %d: A:%d B:%d C:%d\n",
  519.          i, ttable[i].vert[0], ttable[i].vert[1], ttable[i].vert[2]);
  520.  
  521.     if (ttable[i].text_index >= 0)
  522.         fprintf (out, "Material:\"%s\"\n", mtable[ttable[i].text_index]);
  523.  
  524.     fprintf (out, "Smoothing: 1\n");
  525.     }
  526.  
  527.     fprintf (out, "\n\n");
  528.  
  529.     cleanup_object();
  530. }
  531.  
  532.  
  533. int material_lookup (char *material_name)
  534. {
  535.     int i;
  536.  
  537.     if (!initialized)
  538.     init_object();
  539.  
  540.     if (strlen(material_name) == 0)
  541.     return -1;
  542.  
  543.     /* The material table is usually small so just do a simple linear search */
  544.     for (i = msize-1; i >= 0; i--) {
  545.     if (strcmp (mtable[i], material_name) == 0)
  546.         break;
  547.     }
  548.  
  549.     if (i >= 0)
  550.     return i;
  551.  
  552.     /* not found, insert the new material into the table */
  553.     ++msize;
  554.     if (msize > mmax) {
  555.     /* table not big enough, resize it */
  556.     mmax = mmax + 10;
  557.     mtable = realloc (mtable, mmax * sizeof(Material));
  558.     if (mtable == NULL)
  559.         abortmsg ("Insufficient memory to expand material table.", 1);
  560.     }
  561.  
  562.     mtable[msize-1] = malloc (strlen(material_name) + 1);
  563.     if (mtable[msize-1] == NULL)
  564.     abortmsg ("Insufficient memory for material name.", 1);
  565.  
  566.     strcpy (mtable[msize-1], material_name);
  567.  
  568.     return (msize-1);
  569. }
  570.  
  571.  
  572. /* Find the specified vertex in the vertex table */
  573. int vert_lookup (float  x, float  y, float  z)
  574. {
  575.     VertList *p, *new_node;
  576.     unsigned hash;
  577.  
  578.     /* Vertex table is usually very large, use hash lookup */
  579.     hash = (unsigned)((int)(326.4*x) ^ (int)(694.7*y) ^ (int)(1423.6*z)) % HASHSIZE;
  580.  
  581.     for (p = vert_hash[hash]; p != NULL; p = p->next) {
  582.     if (vtable[p->vert].x == x && vtable[p->vert].y == y &&
  583.         vtable[p->vert].z == z) break;
  584.     }
  585.  
  586.     if (p != NULL)
  587.     return (p->vert);   /* found, return the table index */
  588.  
  589.     /* not found, insert the new vertex into the table */
  590.     ++vsize;
  591.     if (vsize > vmax) {
  592.     /* table not big enough, expand it */
  593.     vmax = vmax + 100;
  594.     vtable = realloc (vtable, vmax * sizeof(Vector));
  595.     if (vtable == NULL)
  596.         abortmsg ("Insufficient memory for vertices.\n", 1);
  597.     }
  598.  
  599.     vtable[vsize-1].x = x;
  600.     vtable[vsize-1].y = y;
  601.     vtable[vsize-1].z = z;
  602.  
  603.     new_node = malloc (sizeof(VertList));
  604.     if (new_node == NULL)
  605.     abortmsg ("Insufficient memory for hash table.", 1);
  606.  
  607.     new_node->vert  = vsize-1;
  608.     new_node->next  = vert_hash[hash];
  609.     vert_hash[hash] = new_node;
  610.  
  611.     return (vsize-1);
  612. }
  613.  
  614.  
  615. void abortmsg (char *msg, int exit_code)
  616. {
  617.     printf ("\n%s\n", msg);
  618.     exit (exit_code);
  619. }
  620.  
  621.  
  622. void add_ext (char *fname, char *ext, int force)
  623. {
  624.     int i;
  625.  
  626.     for (i = 0; i < strlen(fname); i++)
  627.     if (fname[i] == '.') break;
  628.  
  629.     if (fname[i] == '\0' || force) {
  630.     if (strlen(ext) > 0)
  631.         fname[i++] = '.';
  632.  
  633.     strcpy (&fname[i], ext);
  634.     }
  635. }
  636.  
  637.  
  638. void fswap (float *a, float *b)
  639. {
  640.     float temp;
  641.  
  642.     temp = *a;
  643.     *a = *b;
  644.     *b = temp;
  645. }
  646.  
  647.  
  648.