home *** CD-ROM | disk | FTP | other *** search
/ Using VRML (Special Edition) / Special_Edition_Using_VRML_CDROM_Que_1996.iso / webpages / objects / chap32 / nff2vrml.c < prev    next >
C/C++ Source or Header  |  1995-11-03  |  8KB  |  287 lines

  1. /* Convert a Sense8 NFF file into VRML */
  2.  
  3. /* Written by Bernie Roehl, October 1995 */
  4.  
  5. /*
  6.    NFF Features not supported:
  7.         Textures (VRML doesn't yet support PER_FACE texture maps)
  8.         24-bit color specifiers (12 bit is assumed)
  9.  
  10.    Also, normal handling is not working right (NFF and VRML have very
  11.    different ideas about how it should work)
  12.  
  13.  */
  14.  
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19.  
  20. typedef struct { float x, y, z; } Vertex;
  21.  
  22. typedef struct
  23.     {
  24.     int npts;                  /* number of points in this polygon */
  25.     int *points;               /* indices into the vertex array */
  26.     int color;                 /* index into the array of color values */
  27.     } Poly;
  28.  
  29. typedef unsigned long Color;
  30.  
  31. Color *colors = NULL;          /* one entry for each *unique* color */
  32. int ncolors = 0;               /* number of unique colors defined */
  33.  
  34. Vertex *vertices = NULL;       /* the array of vertices */
  35. int nvertices = 0;             /* number of vertices defined */
  36.  
  37. Vertex *normals = NULL;        /* the array of normals */
  38. int nnormals = 0;              /* number of normals defined */
  39.  
  40. Poly *polys = NULL;            /* polygons */
  41. int npolys = 0;                /* number of polygons defined */
  42.  
  43. float scale = 1.0;             /* scale factor */
  44.  
  45. char objname[256];             /* the name of the object */
  46. int shading = 0;               /* shading flag (not currently used) */
  47. int solid = 1;                 /* set if backface removal okay */
  48.  
  49. Vertex camloc = { 0, 0, 0 };   /* camera location (currently not used) */
  50. Vertex camdir = { 0, 0, 0 };   /* camera direction (currently not used) */
  51.  
  52. char *progname = "NFF2VRML";   /* name of this program */
  53.  
  54. /* read a line, stripping comments and skipping blank lines */
  55. /* returns 0 at end of file */
  56. int getline(char *buff)
  57.     {
  58.     do
  59.         {
  60.         char *p;
  61.         if (gets(buff) == NULL)  /* end of file */
  62.             return 0;
  63.         p = strstr(buff, "//");  /* look for start of comment */
  64.         if (p)
  65.             *p = '\0';    /* truncate the line at that point */
  66.         } while (buff[0] == '\0');  /* skip blank lines */
  67.     return 1;   /* not end of file */
  68.     }
  69.  
  70. void *ecalloc(int nitems, int size)
  71.     {
  72.     void *p = calloc(nitems, size);
  73.     if (p == NULL)
  74.         {
  75.         fprintf(stderr, "%s: calloc() failed -- not enough memory\n", progname);
  76.         exit(1);
  77.         }
  78.     return p;
  79.     }
  80.  
  81. void make_camera(void)
  82.     {
  83.     int i;
  84.     float minx, maxx, miny, maxy, minz, maxz;
  85.     /* compute bounding box */
  86.     minx = maxx = vertices[0].x;
  87.     miny = maxy = vertices[0].y;
  88.     minz = maxz = vertices[0].z;
  89.     for (i = 1; i < nvertices; ++i)
  90.         {
  91.         if (vertices[i].x < minx)
  92.             minx = vertices[i].x;
  93.         if (vertices[i].x > maxx)
  94.             maxx = vertices[i].x;
  95.         if (vertices[i].y < miny)
  96.             miny = vertices[i].y;
  97.         if (vertices[i].y > maxy)
  98.             maxy = vertices[i].y;
  99.         if (vertices[i].z < minz)
  100.             minz = vertices[i].z;
  101.         if (vertices[i].z > maxz)
  102.             maxz = vertices[i].z;
  103.         }
  104.     printf("\tPerspectiveCamera { position %f %f %f }\n",
  105.         (minx + maxx) / 2, -(miny + maxy) / 2, maxz + (maxz - minz));
  106.     }
  107.  
  108. void main(int argc, char *argv[])
  109.     {
  110.     char buff[256];
  111.     int i, j;
  112.  
  113.     if (argc > 1)
  114.         sscanf(argv[1], "%f", &scale);
  115.  
  116.     getline(buff);
  117.     if (strnicmp(buff, "nff", 3))
  118.         {
  119.         fprintf(stderr, "No header line -- not a valid NFF file\n");
  120.         exit(1);
  121.         }
  122.  
  123.     while (getline(buff))
  124.         {
  125.         if (isdigit(buff[0]))
  126.             break;
  127.         if (!strnicmp(buff, "viewpos", 7))
  128.             sscanf(buff, "viewpos %f %f %f", &camloc.x, &camloc.y, &camloc.z);
  129.         else if (!strnicmp(buff, "viewdir", 7))
  130.             sscanf(buff, "viewdir %f %f %f", &camdir.x, &camdir.y, &camdir.z);
  131.         else if (!strnicmp(buff, "version", 7))
  132.             {
  133.             float version;
  134.             sscanf(buff, "version %f", &version);
  135.             if (version != 2.0)
  136.                 fprintf(stderr, "Warning: NFF version is %f, not 2.0\n", version);
  137.             }
  138.         else
  139.             {
  140.             char tempstr[100];
  141.             /* pick up object name */
  142.             if (sscanf(buff, "%s %s", objname, tempstr) == 2)
  143.                 shading = toupper(tempstr[9]) == 'n';
  144.             }
  145.         }
  146.  
  147.     /* first line is number of vertices */
  148.     nvertices = atoi(buff);
  149.  
  150.     vertices = ecalloc(nvertices, sizeof(Vertex));
  151.  
  152.     normals = ecalloc(nvertices, sizeof(Vertex));
  153.  
  154.     /* read the vertices themselves */
  155.     for (i = 0; i < nvertices; ++i)
  156.         {
  157.         float x, y, z;
  158.         int m;
  159.         getline(buff);
  160.         m = sscanf(buff, "%f %f %f norm %f %f %f",
  161.             &vertices[i].x, &vertices[i].y, &vertices[i].z,
  162.             &normals[nnormals].x, &normals[nnormals].y, &normals[nnormals].z);
  163.         if (m >= 6)
  164.             ++nnormals;
  165.         }
  166.  
  167.     /* next line is the number of polygons */
  168.     getline(buff);
  169.     npolys = atoi(buff);
  170.     
  171.     /* allocate the polygon array */
  172.     polys = ecalloc(npolys, sizeof(Poly));
  173.  
  174.     /* allocate the color array; at worst, we'll need one for each polygon */
  175.     colors = ecalloc(npolys, sizeof(Color));
  176.  
  177.     /* read the polygons */
  178.     for (i = 0; i < npolys; ++i)
  179.         {
  180.         Color col;
  181.         char *p;
  182.  
  183.         /* read the next line of input */
  184.         getline(buff);
  185.  
  186.         /* if any of the polys are double-sided, the object can't be solid */
  187.         if (strstr(buff, "both"))
  188.             solid = 0;
  189.  
  190.         /* read the number of points */
  191.         polys[i].npts = strtoul(buff, &p, 0);
  192.  
  193.         /* allocate the array of points for this polygon */
  194.         polys[i].points = ecalloc(polys[i].npts, sizeof(int));
  195.  
  196.         /* read the points themselves */
  197.         for (j = 0; j < polys[i].npts; ++j)
  198.             polys[i].points[j] = strtoul(p, &p, 0);
  199.  
  200.         /* read the color (assume 12-bit) */
  201.         col = strtoul(p, &p, 0);
  202.  
  203.         /* see if we've already got this color in the array */
  204.         for (j = 0; j < ncolors; ++j)
  205.             if (colors[j] == col)
  206.                 break;
  207.  
  208.         /* if it's a new color, add it to the array of colors */
  209.         if (j >= ncolors)
  210.             colors[ncolors++] = col;
  211.         polys[i].color = j;
  212.         }
  213.  
  214.     /* put out header */
  215.     printf("#VRML V1.0 ascii\n# Converted by NFF2VRML\n\n");
  216.     printf("Separator {\n");
  217.  
  218.     make_camera();
  219.  
  220.     /* put the object name out inside an Info node */
  221.     if (objname[0])
  222.         printf("\tDEF Title Info { string \"%s\" }\n", objname);
  223.  
  224.     /* faces are counterclockwise; if none of the faces were double-sided,
  225.        then it's a SOLID shape */
  226.     printf("\tShapeHints { vertexOrdering COUNTERCLOCKWISE %s }\n",
  227.         solid ? "shapeType SOLID" : "shapeType UNKNOWN_SHAPE_TYPE");
  228.  
  229.     printf("\tMaterialBinding { value PER_FACE_INDEXED }\n");
  230.  
  231.     /* emit the coordinates */
  232.     printf("\tCoordinate3 {\n\t\tpoint [\n");
  233.     for (i = 0; i < nvertices; ++i)
  234.         printf("\t\t\t%f %f %f,\n",
  235.             vertices[i].x * scale,
  236.             -vertices[i].y * scale,   /* coordinate system is flipped */
  237.             vertices[i].z * scale);
  238.     printf("\t\t]\n\t}\n");
  239.  
  240. #ifdef NORMALS_WORKING
  241.     /* if any normals were specified, emit them */
  242.     if (nnormals == nvertices)
  243.         {
  244.         printf("\tNormal {\n\t\tvector [\n");
  245.         for (i = 0; i < nnormals; ++i)
  246.             printf("\t\t\t%f %f %f,\n", normals[i].x, normals[i].y, normals[i].z);
  247.         printf("\t\t]\n");
  248.         }
  249. #endif
  250.  
  251.     /* put out the unique colors as materials */
  252.     printf("\tMaterial {\n\t\tdiffuseColor [\n");
  253.     for (i = 0; i < ncolors; ++i)
  254.         printf("\t\t\t%f %f %f,\n", ((colors[i] >> 8) & 0x0F)/15.0, ((colors[i] >> 4) & 0x0F)/15.0, (colors[i] & 0x0F)/15.0);
  255.     printf("\t\t]\n\t}\n");
  256.  
  257.     printf("\tIndexedFaceSet {\n");
  258.  
  259.     /* put out the actual polygons */
  260.     printf("\t\tcoordIndex [\n");
  261.     for (i = 0; i < npolys; ++i)
  262.         {
  263.         printf("\t\t\t");
  264.         for (j = 0; j < polys[i].npts; ++j)
  265.             printf("%d,", polys[i].points[j]);
  266.         printf("-1,\n");
  267.     }
  268.     printf("\t\t]\n");
  269.  
  270.     /* and their material indices */
  271.     printf("\t\tmaterialIndex [\n");
  272.     for (i = 0; i < npolys; ++i)
  273.         {
  274.         if (i % 10 == 0)
  275.             printf("\t\t\t");
  276.         printf("%d, ", polys[i].color);
  277.         if ((i+1) % 10 == 0)  /* see if we've filled a line */
  278.             printf("\n");
  279.         }
  280.     if (i % 10 != 0)
  281.         printf("\n");
  282.     printf("\t\t]\n");
  283.  
  284.     printf("\t}\n");
  285.     printf("}\n");
  286.     }
  287.