home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Homebrewer's Handbook / vr.iso / vr386 / objfile.c < prev    next >
C/C++ Source or Header  |  1996-03-19  |  11KB  |  423 lines

  1. /* PLG file i/o */
  2. // NEW version by Dave Stampe
  3.  
  4. /* Original PLG loader written by Bernie Roehl, March 1992 */
  5. // PLG prescanning for total vertex pointers added by Dave Stampe, 22/11/93
  6.  
  7. // This is a COMPLETE REWRITE for VR-386, by Dave Stampe 8/1/94
  8.  
  9. /*
  10.  This code is part of the VR-386 project, created by Dave Stampe.
  11.  VR-386 is a desendent of REND386, created by Dave Stampe and
  12.  Bernie Roehl.  Almost all the code has been rewritten by Dave
  13.  Stampre for VR-386.
  14.  
  15.  Copyright (c) 1994 by Dave Stampe:
  16.  May be freely used to write software for release into the public domain
  17.  or for educational use; all commercial endeavours MUST contact Dave Stampe
  18.  (dstampe@psych.toronto.edu) for permission to incorporate any part of
  19.  this software or source code into their products!  Usually there is no
  20.  charge for under 50-100 items for low-cost or shareware products, and terms
  21.  are reasonable.  Any royalties are used for development, so equipment is
  22.  often acceptable payment.
  23.  
  24.  ATTRIBUTION:  If you use any part of this source code or the libraries
  25.  in your projects, you must give attribution to VR-386 and Dave Stampe,
  26.  and any other authors in your documentation, source code, and at startup
  27.  of your program.  Let's keep the freeware ball rolling!
  28.  
  29.  DEVELOPMENT: VR-386 is a effort to develop the process started by
  30.  REND386, improving programmer access by rewriting the code and supplying
  31.  a standard API.  If you write improvements, add new functions rather
  32.  than rewriting current functions.  This will make it possible to
  33.  include you improved code in the next API release.  YOU can help advance
  34.  VR-386.  Comments on the API are welcome.
  35.  
  36.  CONTACT: dstampe@psych.toronto.edu
  37. */
  38.  
  39.  
  40.  
  41. #include <stdio.h>
  42. #include <stdlib.h>  /* atoi(), atol() */
  43. #include <string.h>
  44. #include <alloc.h>
  45. #include <ctype.h>   /* isalnum() */
  46.  
  47. #include "vr_api.h"
  48. #include "intmath.h"
  49.  
  50. static int load_err = 0; /* set if an error was encountered during loading */
  51. static int err_line = 1; /* line on which error occurred */
  52.  
  53. static char *plg_errmsgs[] = {
  54.     "No error",
  55.     "Bad syntax in header line",
  56.     "Couldn't create new object",
  57.     "Couldn't add representation",
  58.     "Early EOF while reading vertices",
  59.     "Bad syntax in vertex line",
  60.     "Early EOF while reading polygons",
  61.     "Missing vertex count in polygon line",
  62.     "Missing vertex index in polygon line",
  63.     "Couldn't add polygon",
  64.     "Vertex number out of range",
  65.     NULL };
  66.  
  67. static char errm[50];
  68.  
  69. char *plg_error(int *errnum)
  70. {
  71.   if(errnum) *errnum = load_err;
  72.   if(!load_err) return NULL;
  73.   sprintf(errm, "File line %d: %s", plg_errmsgs[-load_err]);
  74.   return errm;
  75. }
  76.  
  77.  
  78. static float xrescale = 1, yrescale = 1, zrescale = 1;
  79. static MATRIX obj_xform;
  80.  
  81.  
  82. void strip_comment(char *buff) /* also trim newline character(s) */
  83. {
  84.   char *p;
  85.  
  86.   if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; /* trim newline */
  87.   if ((p = strchr(buff, '#')) != NULL) *p = '\0'; /* trim comment */
  88.   if ((p = strchr(buff, '*')) != NULL) *p = '\0'; /* future expansion */
  89.   if(sscanf(buff,"%*s")==EOF) buff[0] = 0; /* dump tabs, etc */
  90. }
  91.  
  92. static long default_size;
  93. static int maxpolys;
  94. static int maxverts;
  95. static int multirep = 0;
  96.  
  97. static int prescan = 0;        // PRESCAN to find total poly vertices
  98. static int tpverts = 0;
  99. static int tpvcount = 0;
  100.  
  101.  
  102.     // if <obj> is null, creates new fixed object
  103.     // else loads new representation to <obj>
  104. static int load_in_plg_file(FILE *in, OBJECT **obj)
  105. {
  106.   char tbuff[1000], objname[100];
  107.   int nv, np, i;
  108.   char *p;
  109.   int size = 0;
  110.   int multi = (*obj) ? 1 : 0; /* multi-reps if not null object */
  111.  
  112.   tpvcount = 0;
  113.   multirep = 0;
  114.  
  115.     /* skip blank lines */
  116.   do {
  117.        if (fgets(tbuff, sizeof(tbuff), in) == NULL) return -1;
  118.        ++err_line;
  119.        if (strstr(tbuff,"#MULTI")) multi++;
  120.        if (multi) multirep++;
  121.        strip_comment(tbuff);
  122.      }
  123.   while (tbuff[0] == '\0');               // NEW NOW LOADS TPVERTS
  124.  
  125.   if (sscanf(tbuff, "%s %d %d %d", objname, &nv, &np, &tpverts) < 3)
  126.     {
  127.       load_err = -1;
  128.       return -1;
  129.     }
  130.  
  131.   if(tpverts)     // we got our count!
  132.     {
  133.       prescan = 0;
  134.     }
  135.  
  136.   if (multi && (p = strchr(objname, '_')) != NULL)
  137.     {
  138.       *p++ = 0;
  139.       size = atoi(p);
  140.     }
  141.   else size = default_size; /* default: use largest detail always */
  142.  
  143.   if(!prescan)
  144.     {
  145.       if (*obj == NULL)
  146.     {
  147.       if ((*obj = create_fixed_object(nv, np, tpverts)) == NULL)
  148.         {
  149.           load_err = -2;
  150.           return -1;
  151.         }
  152.       set_representation_size(*obj, size);
  153.     }
  154.       else
  155.     {
  156.       if (add_representation(*obj, size, nv, np, tpverts) == NULL)
  157.         {
  158.           load_err = -3;
  159.           return -1;
  160.         }
  161.     }
  162.     }
  163.  
  164.   maxpolys = np;
  165.   maxverts = nv;
  166.  
  167.   for (i = 0; i < nv; ++i) /* load in vertices */
  168.     {
  169.       float x, y, z;
  170.         /* skip blank lines */
  171.       do
  172.     {
  173.       if (fgets(tbuff, sizeof(tbuff), in) == NULL)
  174.         {
  175.           load_err = -4;
  176.           return -1;
  177.         }
  178.       ++err_line;
  179.       strip_comment(tbuff);
  180.     }
  181.      while (tbuff[0] == '\0');
  182.  
  183.       if (sscanf(tbuff, "%f %f %f", &x, &y, &z) != 3)
  184.     {
  185.       load_err = -5;
  186.       return -1;
  187.     }
  188.  
  189.       if(!prescan)    // map the vertex
  190.     {
  191.       COORD xx = x*xrescale;
  192.       COORD yy = y*yrescale;
  193.       COORD zz = z*zrescale;
  194.  
  195.       matrix_point(obj_xform, &xx, &yy, &zz);
  196.       add_vertex(*obj, xx, yy, zz);
  197.     }
  198.     }
  199.  
  200.   for (i = 0; i < np; ++i) /* load polygons */
  201.     {
  202.       int j, npoints;
  203.       unsigned color;
  204.       POLY *poly;
  205.       char *p;
  206.         /* skip blank lines */
  207.       do
  208.     {
  209.       if (fgets(tbuff, sizeof(tbuff), in) == NULL)
  210.         {
  211.           load_err = -6;
  212.           return -1;
  213.         }
  214.      ++err_line;
  215.      strip_comment(tbuff);
  216.     }
  217.       while (tbuff[0] == '\0');
  218.  
  219.       color = convert_color(tbuff,&p);
  220.       if ((p = strtok(p, " \t")) == NULL)
  221.     {
  222.       load_err = -7;
  223.       return -1;
  224.     }
  225.       npoints = atoi(p);
  226.       if (prescan)
  227.     {
  228.       tpvcount += npoints;   // this is all prescan wanted!
  229.     }
  230.       else
  231.     {
  232.       if ((poly = add_poly(*obj, color, npoints)) == NULL)
  233.         {
  234.           load_err = -9;
  235.           return -1;
  236.         }
  237.       for (j = 0; j < npoints; ++j)
  238.         {
  239.           int vertnum;
  240.           if ((p = strtok(NULL, " \t")) == NULL)
  241.         {
  242.           load_err = -8;
  243.           return -1;
  244.         }
  245.           vertnum = atoi(p);
  246.           if (vertnum < 0 || vertnum >= maxverts)
  247.         {
  248.           load_err = -10;
  249.           return -1;
  250.         }
  251.           add_point(*obj, poly, vertnum);
  252.         }
  253.       compute_object(*obj); /* will do current rep only */
  254.     }
  255.     }
  256.   load_err = 0;
  257.   return 0;
  258. }
  259.  
  260.  
  261.     // read file with prescan if it doesn't have total poly verts
  262.     // if <obj> is null, creates new fixed object
  263.     // else loads new representation to <obj>
  264. static int read_plg_file(FILE *in, VISOBJ **obj)
  265. {
  266.  int retc;
  267.  long fptr = ftell(in);
  268.  prescan = 1;
  269.  tpverts = 0;
  270.  if (0!=(retc=load_in_plg_file(in, obj))) return retc;
  271.  
  272.  if(!prescan) return retc;    // we got total poly verts thru file!
  273.  
  274.  fseek(in, fptr, 0);
  275.  prescan = 0;
  276.  tpverts = tpvcount;
  277.  return load_in_plg_file(in, obj);
  278. }
  279.  
  280.     // create the matrix and scales for object loading
  281. void create_obj_xform(POSE *p, float xs, float ys, float zs)
  282. {
  283.   if (p->x == DONTCARE) p->x = 0;
  284.   if (p->y == DONTCARE) p->y = 0;
  285.   if (p->z == DONTCARE) p->z = 0;
  286.   if (p->rx == DONTCARE) p->rx = 0;
  287.   if (p->ry == DONTCARE) p->ry = 0;
  288.   if (p->rz == DONTCARE) p->rz = 0;
  289.   multi_matrix(obj_xform, p->rx, p->ry, p->rz, p->x, p->y, p->z, RYXZ);
  290.   if (xs<=0.001) xrescale = 0.001; else xrescale = xs;
  291.   if (ys<=0.001) yrescale = 0.001; else yrescale = ys;
  292.   if (zs<=0.001) zrescale = 0.001; else zrescale = zs;
  293. }
  294.  
  295.            // loads a new rep to an old object.
  296.            // useful to create morphing animations
  297.            // just loads FIRST if not multi-rep file
  298. OBJECT *load_extra_plg_representation(FILE *in, OBJECT *obj, POSE *p,
  299.                     float sx, float sy, float sz, WORD size)
  300. {
  301.   int ocount = 0;
  302.   default_size = size;
  303.   load_err = 0;
  304.   err_line = 1;
  305.   create_obj_xform(p, sx, sy, sz);
  306.  
  307.   while (read_plg_file(in, &obj) == 0)    // read all we can
  308.     {
  309.       ocount++;
  310.       if (!multirep) break;
  311.     }
  312.   default_size = 0;
  313.   if (ocount == 0) return NULL;
  314.   return obj;
  315. }
  316.  
  317.     // loads single and multi-rep files
  318.     // will load only one object: call again if not EOF
  319. OBJECT *load_plg_object(FILE *in, POSE *p,
  320.         float sx, float sy, float sz, WORD depth)
  321. {
  322.   OBJECT *obj = NULL;
  323.   int ocount = 0;
  324.  
  325.   default_size = 0;
  326.   load_err = 0;
  327.   err_line = 1;
  328.   create_obj_xform(p, sx, sy, sz);
  329.  
  330.   while (read_plg_file(in, &obj) == 0)
  331.     {
  332.       ocount++;
  333.       if (!multirep) break;
  334.     }
  335.   if (ocount == 0) return NULL;
  336.   set_object_sorting(obj, depth);
  337.   mark_object_invisible(obj);     // invisible till placed in world
  338.   return obj;
  339. }
  340.  
  341.  
  342. WORD load_plg_to_objlist(FILE *in, OBJLIST *objlist, WORD maxobj, POSE *p,
  343.              float sx, float sy, float sz, WORD depth)
  344. {
  345.   VISOBJ *obj;
  346.   int olcount = 0;
  347.   int ocount;
  348.  
  349.   default_size = 0;
  350.   load_err = 0;
  351.   err_line = 1;
  352.   create_obj_xform(p, sx, sy, sz);
  353.  
  354.   while(!feof(in) && olcount<maxobj)
  355.     {
  356.       ocount = 0;
  357.       obj = NULL;
  358.       while (read_plg_file(in, &obj) == 0)
  359.     {
  360.       ocount++;
  361.       if (!multirep) break;
  362.     }
  363.       if (ocount == 0) goto load_failed;
  364.       set_object_sorting(obj, depth);
  365.       mark_object_invisible(obj); // invisible to keep on list till placed in world
  366.       add_to_objlist(objlist, obj);
  367.       olcount++;
  368.     }
  369. load_failed:
  370.   return olcount;
  371. }
  372.  
  373.  
  374.  
  375.  
  376.                 // save a PLG object
  377.                 // no name
  378. BOOL save_plg(OBJECT *obj, FILE *out, BOOL world)
  379. {
  380.   int nv, np, tv, i;         /* now saves all representations */
  381.   char buff[100];
  382.   int multi = 0;
  383.  
  384.   if(!(obj=object2visobj(obj))) return -1;    // is a segment!
  385.  
  386.   select_first_representation(obj);           // test if multiple representations
  387.   multi = select_next_representation(obj);
  388.   select_first_representation(obj);           // back to first
  389.  
  390.   if(multi) fprintf(out, "##MULTI\n");
  391.  
  392.   do
  393.     {
  394.       get_obj_info(obj, &nv, &np);
  395.       tv = total_object_pverts(obj);  // now saves total vtx count for future upgrades
  396.       fprintf(out, "SAVED %d %d *d\n", nv, np, tv);
  397.       for (i = 0; i < nv; ++i)
  398.     {
  399.       long x, y, z;
  400.  
  401.       if (world) get_vertex_world_info(obj, i, &x, &y, &z);
  402.       else get_vertex_info(obj, i, &x, &y, &z);
  403.       fprintf(out, "%ld %ld %ld\n", x, y, z);
  404.     }
  405.       for (i = 0; i < np; ++i)
  406.     {
  407.       int j, n, verts[1000];
  408.       unsigned c;
  409.  
  410.       get_poly_info(obj, i, &c, &n);
  411.       fprintf(out, "0x%04.4X %d", c & 0x7FFF, n);
  412.       for (j = 0; j < n; ++j)
  413.         {
  414.          fprintf(out, " %d", get_poly_vertex_index(obj, i, j));
  415.         }
  416.       fprintf(out, "\n");
  417.     }
  418.     }
  419.      while (!select_next_representation(obj));
  420.  
  421.   return 0;
  422. }
  423.