home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Zone / VRZONE.ISO / mac / PC / VDF / VDF.ZIP / VDF2WLD.C < prev    next >
C/C++ Source or Header  |  1994-11-21  |  11KB  |  335 lines

  1. /* Convert a VDF file to a WLD file and a number of PLG files */
  2.  
  3. /* Written by Bernie Roehl, November 1994 */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include "vdf.h"
  8.  
  9. static VDF_COLOR rend386_palette[256] =
  10.     {
  11. #include "rendpal.c"
  12.     };
  13.  
  14. void main(int argc, char *argv[])
  15.     {
  16.     VDF_DATA *ptr;
  17.     void dump_wld(char *filename, VDF_DATA *ptr, char *orig_filename);
  18.     void dump_plg(VDF_DATA *ptr);
  19.     if (argc < 3)
  20.         {
  21.         fprintf(stderr, "usage: VDF2WLD infile.wld outfile.vdf\n");
  22.         exit(1);
  23.         }
  24.     ptr = vdf_readfile(argv[1]);
  25.     if (ptr == NULL)
  26.         {
  27.         puts(vdf_get_read_error());
  28.         exit(3);
  29.         }
  30.     dump_wld(argv[2], ptr, argv[1]);
  31.     dump_plg(ptr);
  32.     }
  33.  
  34. #include <alloc.h>
  35.  
  36. void *vdf_malloc(unsigned int nbytes)
  37.     {
  38.     return malloc(nbytes);
  39.     }
  40.  
  41. void vdf_free(void *ptr)
  42.     {
  43.     free(ptr);
  44.     }
  45.  
  46. #include <math.h>
  47.  
  48. /* find the weighted "distance" between two colors */
  49.  
  50. static float color_distance(VDF_COLOR *color1, VDF_COLOR *color2)
  51.     {
  52.     float dr, dg, db;
  53.     dr = 0.3 * (color1->red - color2->red);
  54.     dg = 0.6 * (color1->green - color2->green);
  55.     db = 0.1 * (color1->blue - color2->blue);
  56.     return dr * dr + dg * dg + db * db;
  57.     }
  58.  
  59. /* find the palette entry that most closely matches a color */
  60.  
  61. static int map_color(VDF_COLOR *color)
  62.     {
  63.     int closest, i;
  64.     float distance = color_distance(color, &rend386_palette[closest = 0]);
  65.     for (i = 1; i < 256; ++i)
  66.         {
  67.         float d = color_distance(color, &rend386_palette[i]);
  68.         if (d < distance)
  69.             {
  70.             distance = d;
  71.             closest = i;
  72.             }
  73.         }
  74.     return closest;
  75.     }
  76.  
  77. /* convert a color to 4-bit hue */
  78.  
  79. static unsigned int map_hue(VDF_COLOR *color)
  80.     {
  81.     return (map_color(color) & 0xF0) << 4;
  82.     }
  83.  
  84. /* convert the albedo (reflectivity) of a material to the range 0 to 255 */
  85.  
  86. static unsigned int convert_albedo(VDF_MATERIAL *mat)
  87.     {
  88.     return (unsigned int) (mat->albedo * 255);
  89.     }
  90.  
  91. /* convert a material specification into a 16-bit surface descriptor */
  92.  
  93. static unsigned int map_material(VDF_MATERIAL *mat)
  94.     {
  95.     unsigned int descriptor;
  96.     /* set first nybble */
  97.     if (mat->rendering_mode == VDF_RENDER_UNLIT)
  98.         return map_color(&mat->ambient_color);
  99.     if (mat->refractive_index != 0.00)
  100.         descriptor = 0x3000;
  101.     else if (mat->specular_exponent != 0.00)
  102.         descriptor = 0x2000;
  103.     else
  104.         descriptor = 0x1000;
  105.     /* set second nybble */
  106.     if (mat->hue != -1)
  107.         descriptor |= ((mat->hue << 8) & 0x0F00);
  108.     else
  109.         switch (descriptor)
  110.             {
  111.             case 0x1000: descriptor |= convert_albedo(mat); break;
  112.             case 0x2000: descriptor |= map_hue(&mat->specular_color); break;
  113.             case 0x3000: descriptor |= map_hue(&mat->specular_color); break;
  114.             }
  115.     /* set third and fourth nybbles */
  116.     if ((descriptor & 0xF000) == 0x1000)  /* flat-shaded gets "brightness" */
  117.         descriptor |= convert_albedo(mat);
  118.     else
  119.         descriptor |= (rand() & 0xFF);  /* random offsets for glass and metal */
  120.     return descriptor;
  121.     }
  122.  
  123. static unsigned int light_magnitude(VDF_COLOR *color)
  124.     {
  125.     return 127 * sqrt(color->red * color->red + color->green * color->green + color->blue * color->blue);
  126.     }
  127.  
  128. static void dump_wld(char *filename, VDF_DATA *ptr, char *orig_filename)
  129.     {
  130.     FILE *outfile = fopen(filename, "w");
  131.     VDF_HUMAN_DATA *p;
  132.     VDF_MATERIAL *mat;
  133.     VDF_MATERIAL_TABLE *table;
  134.     VDF_OBJECT *object;
  135.     VDF_LIGHT *light;
  136.     VDF_CAMERA *camera;
  137.     if (outfile == NULL)
  138.         {
  139.         fprintf(stderr, "Could not create %s'\n", filename);
  140.         exit(1);
  141.         }
  142.     if (ptr->title)
  143.         fprintf(outfile, "# %s\n", ptr->title);
  144.     fprintf(outfile, "#\n");
  145.     fprintf(outfile, "# Generated by VDF2WLD\n");
  146.     fprintf(outfile, "# Converted from '%s'\n", orig_filename);
  147.     fprintf(outfile, "#\n");
  148.     /* WORLD INFORMATION */
  149.     if (ptr->copyright_message)
  150.         fprintf(outfile, "# %s\n", ptr->copyright_message);
  151.     if (ptr->usage_restrictions)
  152.         fprintf(outfile, "# %s\n", ptr->usage_restrictions);
  153.     fprintf(outfile, "#\n");
  154.     if (ptr->created)
  155.         if (ptr->created->person)
  156.             {
  157.             fprintf(outfile, "# Created by %s\n", ptr->created->person);
  158.             if (ptr->created->date)
  159.                 {
  160.                 fprintf(outfile, "#         on %2.2s/%2.2s/%2.2s\n", &ptr->created->date[4], &ptr->created->date[6], &ptr->created->date[2]);
  161.                 if (ptr->created->time)
  162.                     fprintf(outfile, "#         at %2.2s:%2.2s:%2.2s\n", &ptr->created->time[0], &ptr->created->time[2], &ptr->created->time[4]);
  163.                 }
  164.             }
  165.     for (p = ptr->modified; p; p = p->next)
  166.         if (p->person)
  167.             {
  168.             fprintf(outfile, "# Modified by %s\n", p->person);
  169.             if (p->date)
  170.                 {
  171.                 fprintf(outfile, "#          on %2.2s/%2.2s/%2.2s\n", &p->date[4], &p->date[6], &p->date[2]);
  172.                 if (p->time)
  173.                 fprintf(outfile, "#          at %2.2s:%2.2s:%2.2s\n", &p->time[0], &p->time[2], &p->time[4]);
  174.                 }
  175.             }
  176.     fprintf(outfile, "\n");
  177.     if (ptr->title) fprintf(outfile, "title %s\n\n", ptr->title);
  178.     /* WORLD ATTRIBUTES */
  179.     if (ptr->world_attributes)
  180.         {
  181.         if (ptr->world_attributes->scale != 1.0)
  182.             fprintf(outfile, "worldscale %f\n", ptr->world_attributes->scale);
  183.         fprintf(outfile, "ambient %d\n", (int) (ptr->world_attributes->ambient_light.red * 127));
  184.         if (!ptr->world_attributes->has_horizon)
  185.             fprintf(outfile, "options h\n");
  186.         fprintf(outfile, "skycolor %d\n", map_color(&ptr->world_attributes->sky_color));
  187.         fprintf(outfile, "groundcolor %d\n", map_color(&ptr->world_attributes->ground_color));
  188.         }
  189.     fprintf(outfile, "\n");
  190.     /* SURFACES */
  191.     for (mat = ptr->materials; mat; mat = mat->next)
  192.         fprintf(outfile, "surfacedef SURF_%lX 0x%04X\n", (long) mat->id, map_material(mat));
  193.     fprintf(outfile, "\n");
  194.     for (table = ptr->material_tables; table; table = table->next)
  195.         {
  196.         int i;
  197.         fprintf(outfile, "surfacemap MAP_%lX %ld\n", (long) table->id, (long) table->count + 1);
  198.         for (i = 0; i < table->count; ++i)
  199.             fprintf(outfile, "surface %d SURF_%lX\n", i + 1, (long) table->material_references[i]->id);
  200.         fprintf(outfile, "\n");
  201.         }
  202.     /* OBJECTS */
  203.     for (object = ptr->objects; object; object = object->next)
  204.         {
  205.         if (object->shape == NULL)  /* no geometry -- it's a "segment" */
  206.             {
  207.             fprintf(outfile, "segment OBJ_%lX=", (long) object->id);
  208.             if (object->parent)
  209.                 fprintf(outfile, "OBJ_%lxX", (long) object->parent->id);
  210.             else
  211.                 fprintf(outfile, "world");
  212.              fprintf(outfile, " %f,%f,%f %f,%f,%f",
  213.                 object->rotx, object->roty, object->rotz,
  214.                 object->location.x, object->location.y, object->location.z);
  215.             }
  216.         else    /* has geometry -- it's an "object" */
  217.             {
  218.             if (object->n_used)  /* if this it's referenced, it needs a name */
  219.                 fprintf(outfile, "object OBJ_%lX=", (long) object->id);
  220.             else
  221.                 fprintf(outfile, "object ");
  222.             fprintf(outfile, "%lX.plg %f,%f,%f %f,%f,%f %f,%f,%f 0",
  223.                 (long) object->shape->id,
  224.                 object->scaled_by.x, object->scaled_by.y, object->scaled_by.z,
  225.                 object->rotx, object->roty, object->rotz,
  226.                 object->location.x, object->location.y, object->location.z);
  227.             if (object->material_table)
  228.                 fprintf(outfile, " MAP_%lX", (long) object->material_table->id);
  229.             else if (object->shape->material_table)
  230.                 fprintf(outfile, " MAP_%lX", (long) object->shape->material_table->id);
  231.             else
  232.                 fprintf(outfile, " .");
  233.             if (object->parent)
  234.                 fprintf(outfile, " OBJ_%lX", (long) object->parent->id);
  235.             }
  236.         fprintf(outfile, "\n");
  237.         }
  238.     fprintf(outfile, "\n");
  239.     /* LIGHTS */
  240.     for (light = ptr->lights; light; light = light->next)
  241.         {
  242.         if (light->associated_with == NULL)
  243.             continue;  /* ignore lights that aren't associated with objects */
  244.         if (light->associated_with->shape)
  245.             fprintf(outfile, "mlight 0,0,0 %d %d OBJ_%lX\n",
  246.                 (light->type == VDF_LIGHT_DIRECTIONAL) ? 0 : 1,
  247.                 light_magnitude(&light->color), (long) light->associated_with->id);
  248.         else
  249.             fprintf(outfile, "light %f,%f,%f %d\n",
  250.                 light->associated_with->location.x, light->associated_with->location.y, light->associated_with->location.z,
  251.                 (light->type == VDF_LIGHT_DIRECTIONAL) ? 0 : 1);
  252.         }
  253.     fprintf(outfile, "\n");
  254.     /* CAMERAS */
  255.     for (camera = ptr->cameras; camera; camera = camera->next)
  256.         {
  257.         if (camera->associated_with == NULL)
  258.             continue;  /* ignore cameras that aren't associated with objects */
  259.         fprintf(outfile, "camera %s %f,%f,%f %f,%f,%f %f 1.00 1000000.0\n",
  260.             camera->name ? camera->name : "no_name",
  261.             camera->associated_with->location.x, camera->associated_with->location.y, camera->associated_with->location.z, 
  262.             camera->associated_with->rotx, camera->associated_with->roty, camera->associated_with->rotz,
  263.             tan((camera->field_of_view/2) * 3.14159 / 180.0));
  264.         if (camera->associated_with->shape)
  265.             fprintf(outfile, "attachview OBJ_%lX\n", (long) camera->associated_with->id);
  266.         }
  267.     fprintf(outfile, "\n");
  268.     fprintf(outfile, "# end of file\n");
  269.     }
  270.  
  271. static void dump_plg_data(VDF_SHAPE *shape, FILE *out)
  272.     {
  273.     int np = shape->nfacets, i;
  274.     for (i = 0; i < shape->nfacets; ++i)
  275.         if (shape->facets[i].is_doublesided)
  276.             ++np;
  277.     fprintf(out, "dummyname_%ld %ld %ld\n",
  278.         (long) floor(shape->lod_size), (long) shape->nvertices, (long) np);
  279.     for (i = 0; i < shape->nvertices; ++i)
  280.         {
  281.         VDF_VERTEX *vertex = &shape->vertices[i];
  282.         fprintf(out, "%f %f %f\n", vertex->vector.x, vertex->vector.y, vertex->vector.z);
  283.         }
  284.     for (i = 0; i < shape->nfacets; ++i)
  285.         {
  286.         VDF_FACET *facet = &shape->facets[i];
  287.         int j;
  288.         fprintf(out, "0x%04.4X %ld", 0x8000 | (facet->front_material + 1), (long) facet->npoints);
  289.         for (j = facet->npoints-1; j >= 0; --j)
  290.             {
  291.             VDF_POINT *p = &facet->points[j];
  292.             fprintf(out, " %ld", (long) p->vertnum);
  293.             }
  294.         fprintf(out, "\n");
  295.         if (facet->is_doublesided)
  296.             {
  297.             fprintf(out, "0x%04.4X %ld", 0x8000 | (facet->back_material + 1), (long) facet->npoints);
  298.             for (j = 0; j < facet->npoints; ++j)
  299.                 {
  300.                 VDF_POINT *p = &facet->points[j];
  301.                 fprintf(out, " %ld", (long) p->vertnum);
  302.                 }
  303.             fprintf(out, "\n");
  304.             }
  305.         }
  306.     }
  307.  
  308. static void dump_plg(VDF_DATA *ptr)
  309.     {
  310.     VDF_SHAPE *shape;
  311.     for (shape = ptr->shapes; shape; shape = shape->next)
  312.         {
  313.         char fname[100];
  314.         FILE *plgout;
  315.         VDF_SHAPE *currshape;
  316.         if (shape->n_used == 0)  /* ignore shapes that nobody references */
  317.             continue;
  318.         /* if it's referenced by other shapes (more detail versions) then
  319.            this shape will be dumped while dumping that shape */
  320.         sprintf(fname, "%lX.plg", (long) shape->id);
  321.         plgout = fopen(fname, "w");
  322.         if (plgout == NULL)
  323.             {
  324.             fprintf(stderr, "Warning: could not create '%s'\n", fname);
  325.             continue;
  326.             }
  327.         if (shape->replaces)
  328.             fprintf(plgout, "##MULTI\n");
  329.         for (currshape = shape; currshape; currshape = currshape->replaces)
  330.             dump_plg_data(currshape, plgout);
  331.         fclose(plgout);
  332.         }
  333.     }
  334.  
  335.