home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Virtual Reality Zone
/
VRZONE.ISO
/
mac
/
PC
/
VDF
/
VDF.ZIP
/
VDF2WLD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-11-21
|
11KB
|
335 lines
/* Convert a VDF file to a WLD file and a number of PLG files */
/* Written by Bernie Roehl, November 1994 */
#include <stdio.h>
#include <stdlib.h>
#include "vdf.h"
static VDF_COLOR rend386_palette[256] =
{
#include "rendpal.c"
};
void main(int argc, char *argv[])
{
VDF_DATA *ptr;
void dump_wld(char *filename, VDF_DATA *ptr, char *orig_filename);
void dump_plg(VDF_DATA *ptr);
if (argc < 3)
{
fprintf(stderr, "usage: VDF2WLD infile.wld outfile.vdf\n");
exit(1);
}
ptr = vdf_readfile(argv[1]);
if (ptr == NULL)
{
puts(vdf_get_read_error());
exit(3);
}
dump_wld(argv[2], ptr, argv[1]);
dump_plg(ptr);
}
#include <alloc.h>
void *vdf_malloc(unsigned int nbytes)
{
return malloc(nbytes);
}
void vdf_free(void *ptr)
{
free(ptr);
}
#include <math.h>
/* find the weighted "distance" between two colors */
static float color_distance(VDF_COLOR *color1, VDF_COLOR *color2)
{
float dr, dg, db;
dr = 0.3 * (color1->red - color2->red);
dg = 0.6 * (color1->green - color2->green);
db = 0.1 * (color1->blue - color2->blue);
return dr * dr + dg * dg + db * db;
}
/* find the palette entry that most closely matches a color */
static int map_color(VDF_COLOR *color)
{
int closest, i;
float distance = color_distance(color, &rend386_palette[closest = 0]);
for (i = 1; i < 256; ++i)
{
float d = color_distance(color, &rend386_palette[i]);
if (d < distance)
{
distance = d;
closest = i;
}
}
return closest;
}
/* convert a color to 4-bit hue */
static unsigned int map_hue(VDF_COLOR *color)
{
return (map_color(color) & 0xF0) << 4;
}
/* convert the albedo (reflectivity) of a material to the range 0 to 255 */
static unsigned int convert_albedo(VDF_MATERIAL *mat)
{
return (unsigned int) (mat->albedo * 255);
}
/* convert a material specification into a 16-bit surface descriptor */
static unsigned int map_material(VDF_MATERIAL *mat)
{
unsigned int descriptor;
/* set first nybble */
if (mat->rendering_mode == VDF_RENDER_UNLIT)
return map_color(&mat->ambient_color);
if (mat->refractive_index != 0.00)
descriptor = 0x3000;
else if (mat->specular_exponent != 0.00)
descriptor = 0x2000;
else
descriptor = 0x1000;
/* set second nybble */
if (mat->hue != -1)
descriptor |= ((mat->hue << 8) & 0x0F00);
else
switch (descriptor)
{
case 0x1000: descriptor |= convert_albedo(mat); break;
case 0x2000: descriptor |= map_hue(&mat->specular_color); break;
case 0x3000: descriptor |= map_hue(&mat->specular_color); break;
}
/* set third and fourth nybbles */
if ((descriptor & 0xF000) == 0x1000) /* flat-shaded gets "brightness" */
descriptor |= convert_albedo(mat);
else
descriptor |= (rand() & 0xFF); /* random offsets for glass and metal */
return descriptor;
}
static unsigned int light_magnitude(VDF_COLOR *color)
{
return 127 * sqrt(color->red * color->red + color->green * color->green + color->blue * color->blue);
}
static void dump_wld(char *filename, VDF_DATA *ptr, char *orig_filename)
{
FILE *outfile = fopen(filename, "w");
VDF_HUMAN_DATA *p;
VDF_MATERIAL *mat;
VDF_MATERIAL_TABLE *table;
VDF_OBJECT *object;
VDF_LIGHT *light;
VDF_CAMERA *camera;
if (outfile == NULL)
{
fprintf(stderr, "Could not create %s'\n", filename);
exit(1);
}
if (ptr->title)
fprintf(outfile, "# %s\n", ptr->title);
fprintf(outfile, "#\n");
fprintf(outfile, "# Generated by VDF2WLD\n");
fprintf(outfile, "# Converted from '%s'\n", orig_filename);
fprintf(outfile, "#\n");
/* WORLD INFORMATION */
if (ptr->copyright_message)
fprintf(outfile, "# %s\n", ptr->copyright_message);
if (ptr->usage_restrictions)
fprintf(outfile, "# %s\n", ptr->usage_restrictions);
fprintf(outfile, "#\n");
if (ptr->created)
if (ptr->created->person)
{
fprintf(outfile, "# Created by %s\n", ptr->created->person);
if (ptr->created->date)
{
fprintf(outfile, "# on %2.2s/%2.2s/%2.2s\n", &ptr->created->date[4], &ptr->created->date[6], &ptr->created->date[2]);
if (ptr->created->time)
fprintf(outfile, "# at %2.2s:%2.2s:%2.2s\n", &ptr->created->time[0], &ptr->created->time[2], &ptr->created->time[4]);
}
}
for (p = ptr->modified; p; p = p->next)
if (p->person)
{
fprintf(outfile, "# Modified by %s\n", p->person);
if (p->date)
{
fprintf(outfile, "# on %2.2s/%2.2s/%2.2s\n", &p->date[4], &p->date[6], &p->date[2]);
if (p->time)
fprintf(outfile, "# at %2.2s:%2.2s:%2.2s\n", &p->time[0], &p->time[2], &p->time[4]);
}
}
fprintf(outfile, "\n");
if (ptr->title) fprintf(outfile, "title %s\n\n", ptr->title);
/* WORLD ATTRIBUTES */
if (ptr->world_attributes)
{
if (ptr->world_attributes->scale != 1.0)
fprintf(outfile, "worldscale %f\n", ptr->world_attributes->scale);
fprintf(outfile, "ambient %d\n", (int) (ptr->world_attributes->ambient_light.red * 127));
if (!ptr->world_attributes->has_horizon)
fprintf(outfile, "options h\n");
fprintf(outfile, "skycolor %d\n", map_color(&ptr->world_attributes->sky_color));
fprintf(outfile, "groundcolor %d\n", map_color(&ptr->world_attributes->ground_color));
}
fprintf(outfile, "\n");
/* SURFACES */
for (mat = ptr->materials; mat; mat = mat->next)
fprintf(outfile, "surfacedef SURF_%lX 0x%04X\n", (long) mat->id, map_material(mat));
fprintf(outfile, "\n");
for (table = ptr->material_tables; table; table = table->next)
{
int i;
fprintf(outfile, "surfacemap MAP_%lX %ld\n", (long) table->id, (long) table->count + 1);
for (i = 0; i < table->count; ++i)
fprintf(outfile, "surface %d SURF_%lX\n", i + 1, (long) table->material_references[i]->id);
fprintf(outfile, "\n");
}
/* OBJECTS */
for (object = ptr->objects; object; object = object->next)
{
if (object->shape == NULL) /* no geometry -- it's a "segment" */
{
fprintf(outfile, "segment OBJ_%lX=", (long) object->id);
if (object->parent)
fprintf(outfile, "OBJ_%lxX", (long) object->parent->id);
else
fprintf(outfile, "world");
fprintf(outfile, " %f,%f,%f %f,%f,%f",
object->rotx, object->roty, object->rotz,
object->location.x, object->location.y, object->location.z);
}
else /* has geometry -- it's an "object" */
{
if (object->n_used) /* if this it's referenced, it needs a name */
fprintf(outfile, "object OBJ_%lX=", (long) object->id);
else
fprintf(outfile, "object ");
fprintf(outfile, "%lX.plg %f,%f,%f %f,%f,%f %f,%f,%f 0",
(long) object->shape->id,
object->scaled_by.x, object->scaled_by.y, object->scaled_by.z,
object->rotx, object->roty, object->rotz,
object->location.x, object->location.y, object->location.z);
if (object->material_table)
fprintf(outfile, " MAP_%lX", (long) object->material_table->id);
else if (object->shape->material_table)
fprintf(outfile, " MAP_%lX", (long) object->shape->material_table->id);
else
fprintf(outfile, " .");
if (object->parent)
fprintf(outfile, " OBJ_%lX", (long) object->parent->id);
}
fprintf(outfile, "\n");
}
fprintf(outfile, "\n");
/* LIGHTS */
for (light = ptr->lights; light; light = light->next)
{
if (light->associated_with == NULL)
continue; /* ignore lights that aren't associated with objects */
if (light->associated_with->shape)
fprintf(outfile, "mlight 0,0,0 %d %d OBJ_%lX\n",
(light->type == VDF_LIGHT_DIRECTIONAL) ? 0 : 1,
light_magnitude(&light->color), (long) light->associated_with->id);
else
fprintf(outfile, "light %f,%f,%f %d\n",
light->associated_with->location.x, light->associated_with->location.y, light->associated_with->location.z,
(light->type == VDF_LIGHT_DIRECTIONAL) ? 0 : 1);
}
fprintf(outfile, "\n");
/* CAMERAS */
for (camera = ptr->cameras; camera; camera = camera->next)
{
if (camera->associated_with == NULL)
continue; /* ignore cameras that aren't associated with objects */
fprintf(outfile, "camera %s %f,%f,%f %f,%f,%f %f 1.00 1000000.0\n",
camera->name ? camera->name : "no_name",
camera->associated_with->location.x, camera->associated_with->location.y, camera->associated_with->location.z,
camera->associated_with->rotx, camera->associated_with->roty, camera->associated_with->rotz,
tan((camera->field_of_view/2) * 3.14159 / 180.0));
if (camera->associated_with->shape)
fprintf(outfile, "attachview OBJ_%lX\n", (long) camera->associated_with->id);
}
fprintf(outfile, "\n");
fprintf(outfile, "# end of file\n");
}
static void dump_plg_data(VDF_SHAPE *shape, FILE *out)
{
int np = shape->nfacets, i;
for (i = 0; i < shape->nfacets; ++i)
if (shape->facets[i].is_doublesided)
++np;
fprintf(out, "dummyname_%ld %ld %ld\n",
(long) floor(shape->lod_size), (long) shape->nvertices, (long) np);
for (i = 0; i < shape->nvertices; ++i)
{
VDF_VERTEX *vertex = &shape->vertices[i];
fprintf(out, "%f %f %f\n", vertex->vector.x, vertex->vector.y, vertex->vector.z);
}
for (i = 0; i < shape->nfacets; ++i)
{
VDF_FACET *facet = &shape->facets[i];
int j;
fprintf(out, "0x%04.4X %ld", 0x8000 | (facet->front_material + 1), (long) facet->npoints);
for (j = facet->npoints-1; j >= 0; --j)
{
VDF_POINT *p = &facet->points[j];
fprintf(out, " %ld", (long) p->vertnum);
}
fprintf(out, "\n");
if (facet->is_doublesided)
{
fprintf(out, "0x%04.4X %ld", 0x8000 | (facet->back_material + 1), (long) facet->npoints);
for (j = 0; j < facet->npoints; ++j)
{
VDF_POINT *p = &facet->points[j];
fprintf(out, " %ld", (long) p->vertnum);
}
fprintf(out, "\n");
}
}
}
static void dump_plg(VDF_DATA *ptr)
{
VDF_SHAPE *shape;
for (shape = ptr->shapes; shape; shape = shape->next)
{
char fname[100];
FILE *plgout;
VDF_SHAPE *currshape;
if (shape->n_used == 0) /* ignore shapes that nobody references */
continue;
/* if it's referenced by other shapes (more detail versions) then
this shape will be dumped while dumping that shape */
sprintf(fname, "%lX.plg", (long) shape->id);
plgout = fopen(fname, "w");
if (plgout == NULL)
{
fprintf(stderr, "Warning: could not create '%s'\n", fname);
continue;
}
if (shape->replaces)
fprintf(plgout, "##MULTI\n");
for (currshape = shape; currshape; currshape = currshape->replaces)
dump_plg_data(currshape, plgout);
fclose(plgout);
}
}