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 >
Wrap
C/C++ Source or Header
|
1995-11-03
|
8KB
|
287 lines
/* Convert a Sense8 NFF file into VRML */
/* Written by Bernie Roehl, October 1995 */
/*
NFF Features not supported:
Textures (VRML doesn't yet support PER_FACE texture maps)
24-bit color specifiers (12 bit is assumed)
Also, normal handling is not working right (NFF and VRML have very
different ideas about how it should work)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct { float x, y, z; } Vertex;
typedef struct
{
int npts; /* number of points in this polygon */
int *points; /* indices into the vertex array */
int color; /* index into the array of color values */
} Poly;
typedef unsigned long Color;
Color *colors = NULL; /* one entry for each *unique* color */
int ncolors = 0; /* number of unique colors defined */
Vertex *vertices = NULL; /* the array of vertices */
int nvertices = 0; /* number of vertices defined */
Vertex *normals = NULL; /* the array of normals */
int nnormals = 0; /* number of normals defined */
Poly *polys = NULL; /* polygons */
int npolys = 0; /* number of polygons defined */
float scale = 1.0; /* scale factor */
char objname[256]; /* the name of the object */
int shading = 0; /* shading flag (not currently used) */
int solid = 1; /* set if backface removal okay */
Vertex camloc = { 0, 0, 0 }; /* camera location (currently not used) */
Vertex camdir = { 0, 0, 0 }; /* camera direction (currently not used) */
char *progname = "NFF2VRML"; /* name of this program */
/* read a line, stripping comments and skipping blank lines */
/* returns 0 at end of file */
int getline(char *buff)
{
do
{
char *p;
if (gets(buff) == NULL) /* end of file */
return 0;
p = strstr(buff, "//"); /* look for start of comment */
if (p)
*p = '\0'; /* truncate the line at that point */
} while (buff[0] == '\0'); /* skip blank lines */
return 1; /* not end of file */
}
void *ecalloc(int nitems, int size)
{
void *p = calloc(nitems, size);
if (p == NULL)
{
fprintf(stderr, "%s: calloc() failed -- not enough memory\n", progname);
exit(1);
}
return p;
}
void make_camera(void)
{
int i;
float minx, maxx, miny, maxy, minz, maxz;
/* compute bounding box */
minx = maxx = vertices[0].x;
miny = maxy = vertices[0].y;
minz = maxz = vertices[0].z;
for (i = 1; i < nvertices; ++i)
{
if (vertices[i].x < minx)
minx = vertices[i].x;
if (vertices[i].x > maxx)
maxx = vertices[i].x;
if (vertices[i].y < miny)
miny = vertices[i].y;
if (vertices[i].y > maxy)
maxy = vertices[i].y;
if (vertices[i].z < minz)
minz = vertices[i].z;
if (vertices[i].z > maxz)
maxz = vertices[i].z;
}
printf("\tPerspectiveCamera { position %f %f %f }\n",
(minx + maxx) / 2, -(miny + maxy) / 2, maxz + (maxz - minz));
}
void main(int argc, char *argv[])
{
char buff[256];
int i, j;
if (argc > 1)
sscanf(argv[1], "%f", &scale);
getline(buff);
if (strnicmp(buff, "nff", 3))
{
fprintf(stderr, "No header line -- not a valid NFF file\n");
exit(1);
}
while (getline(buff))
{
if (isdigit(buff[0]))
break;
if (!strnicmp(buff, "viewpos", 7))
sscanf(buff, "viewpos %f %f %f", &camloc.x, &camloc.y, &camloc.z);
else if (!strnicmp(buff, "viewdir", 7))
sscanf(buff, "viewdir %f %f %f", &camdir.x, &camdir.y, &camdir.z);
else if (!strnicmp(buff, "version", 7))
{
float version;
sscanf(buff, "version %f", &version);
if (version != 2.0)
fprintf(stderr, "Warning: NFF version is %f, not 2.0\n", version);
}
else
{
char tempstr[100];
/* pick up object name */
if (sscanf(buff, "%s %s", objname, tempstr) == 2)
shading = toupper(tempstr[9]) == 'n';
}
}
/* first line is number of vertices */
nvertices = atoi(buff);
vertices = ecalloc(nvertices, sizeof(Vertex));
normals = ecalloc(nvertices, sizeof(Vertex));
/* read the vertices themselves */
for (i = 0; i < nvertices; ++i)
{
float x, y, z;
int m;
getline(buff);
m = sscanf(buff, "%f %f %f norm %f %f %f",
&vertices[i].x, &vertices[i].y, &vertices[i].z,
&normals[nnormals].x, &normals[nnormals].y, &normals[nnormals].z);
if (m >= 6)
++nnormals;
}
/* next line is the number of polygons */
getline(buff);
npolys = atoi(buff);
/* allocate the polygon array */
polys = ecalloc(npolys, sizeof(Poly));
/* allocate the color array; at worst, we'll need one for each polygon */
colors = ecalloc(npolys, sizeof(Color));
/* read the polygons */
for (i = 0; i < npolys; ++i)
{
Color col;
char *p;
/* read the next line of input */
getline(buff);
/* if any of the polys are double-sided, the object can't be solid */
if (strstr(buff, "both"))
solid = 0;
/* read the number of points */
polys[i].npts = strtoul(buff, &p, 0);
/* allocate the array of points for this polygon */
polys[i].points = ecalloc(polys[i].npts, sizeof(int));
/* read the points themselves */
for (j = 0; j < polys[i].npts; ++j)
polys[i].points[j] = strtoul(p, &p, 0);
/* read the color (assume 12-bit) */
col = strtoul(p, &p, 0);
/* see if we've already got this color in the array */
for (j = 0; j < ncolors; ++j)
if (colors[j] == col)
break;
/* if it's a new color, add it to the array of colors */
if (j >= ncolors)
colors[ncolors++] = col;
polys[i].color = j;
}
/* put out header */
printf("#VRML V1.0 ascii\n# Converted by NFF2VRML\n\n");
printf("Separator {\n");
make_camera();
/* put the object name out inside an Info node */
if (objname[0])
printf("\tDEF Title Info { string \"%s\" }\n", objname);
/* faces are counterclockwise; if none of the faces were double-sided,
then it's a SOLID shape */
printf("\tShapeHints { vertexOrdering COUNTERCLOCKWISE %s }\n",
solid ? "shapeType SOLID" : "shapeType UNKNOWN_SHAPE_TYPE");
printf("\tMaterialBinding { value PER_FACE_INDEXED }\n");
/* emit the coordinates */
printf("\tCoordinate3 {\n\t\tpoint [\n");
for (i = 0; i < nvertices; ++i)
printf("\t\t\t%f %f %f,\n",
vertices[i].x * scale,
-vertices[i].y * scale, /* coordinate system is flipped */
vertices[i].z * scale);
printf("\t\t]\n\t}\n");
#ifdef NORMALS_WORKING
/* if any normals were specified, emit them */
if (nnormals == nvertices)
{
printf("\tNormal {\n\t\tvector [\n");
for (i = 0; i < nnormals; ++i)
printf("\t\t\t%f %f %f,\n", normals[i].x, normals[i].y, normals[i].z);
printf("\t\t]\n");
}
#endif
/* put out the unique colors as materials */
printf("\tMaterial {\n\t\tdiffuseColor [\n");
for (i = 0; i < ncolors; ++i)
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);
printf("\t\t]\n\t}\n");
printf("\tIndexedFaceSet {\n");
/* put out the actual polygons */
printf("\t\tcoordIndex [\n");
for (i = 0; i < npolys; ++i)
{
printf("\t\t\t");
for (j = 0; j < polys[i].npts; ++j)
printf("%d,", polys[i].points[j]);
printf("-1,\n");
}
printf("\t\t]\n");
/* and their material indices */
printf("\t\tmaterialIndex [\n");
for (i = 0; i < npolys; ++i)
{
if (i % 10 == 0)
printf("\t\t\t");
printf("%d, ", polys[i].color);
if ((i+1) % 10 == 0) /* see if we've filled a line */
printf("\n");
}
if (i % 10 != 0)
printf("\n");
printf("\t\t]\n");
printf("\t}\n");
printf("}\n");
}