home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Issue 2 / Freelog_HS_3_Setp_Oct_Nov_2000_CD2.mdx / Arcade / Orbit / src / ac3d.c next >
C/C++ Source or Header  |  1999-09-28  |  27KB  |  1,343 lines

  1. /*
  2.  
  3. ORBIT, a freeware space combat simulator
  4. Copyright (C) 1999  Steve Belczyk <steve1@genesis.nred.ma.us>
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20. */
  21.  
  22. #include "orbit.h"
  23.  
  24. /*
  25.  *  Stuff to load AC3D files
  26.  *
  27.  *  Most of this is based on ac-to-gl, by Steve Baker <sjbaker1@airmail.net>
  28.  */
  29.  
  30. int DoMaterial (char *s);
  31. int DoObject (char *s);
  32. int DoACName (char *s);
  33. int DoData (char *s);
  34. int DoTexture (char *s);
  35. int DoTexrep (char *s);
  36. int DoRot (char *s);
  37. int DoLoc (char *s);
  38. int DoUrl (char *s);
  39. int DoNumvert (char *s);
  40. int DoNumsurf (char *s);
  41. int DoSurf (char *s);
  42. int DoMat (char *s);
  43. int DoRefs (char *s);
  44. int DoKids (char *s);
  45.  
  46. int DoObjWorld (char *s);
  47. int DoObjPoly (char *s);
  48. int DoObjGroup (char *s);
  49. void SkipSpaces (char **s);
  50. void SkipQuotes (char **s);
  51. void RemoveQuotes (char *s);
  52. void load_sgi_texture (char *s);
  53.  
  54. #define MAX_TEXTURES 1000    /* This *ought* to be enough! */
  55. char *texture_fnames [MAX_TEXTURES];
  56.  
  57. int acsmooth;        /* Smooth surface? */
  58. int acsurfpass;        /* Pass through surface */
  59. #define PASS_NORMAL (0)    /* Get normals */
  60. #define PASS_RENDER (1) /* Render */
  61.  
  62. struct
  63. {
  64.     int id;            /* Texture id */
  65.     char name[64];    /* Name */
  66. } tex[MAX_TEXTURES];
  67. int ntex;
  68.  
  69. struct ACVertex
  70. {
  71.     float v[3];     /* Vertex coords */
  72.     float normal[3]; /* Normal */
  73.     float n;        /* Number of normals to average */
  74. } *vtab;
  75.  
  76. int num_materials = 0;
  77. int num_textures = 0;
  78. int nv;            /* Number of vertices in vtab */
  79.  
  80. int last_flags = -1;
  81. int last_mat;
  82. int last_num_kids = -1;
  83. int current_flags = -1;
  84. int texture_enabled = 0;
  85. int need_texture = 0;
  86. int firsttime2;
  87.  
  88. #define PARSE_CONT   0
  89. #define PARSE_POP    1
  90.  
  91. int matlist[1024];
  92. int modelnum;
  93. FILE *acfd;
  94.  
  95. struct Tag
  96. {
  97.     char *token;
  98.     int (*func) (char *s);
  99. };
  100.  
  101. struct Tag top_tags [] =
  102. {
  103.     {"MATERIAL", DoMaterial},
  104.     {"OBJECT"  , DoObject  },
  105. };
  106.  
  107. InitTextures()
  108. {
  109.     int t;
  110.  
  111.     for (t=0; t<MAX_TEXTURES; t++)
  112.     {
  113.         tex[t].id = (-1);
  114.         tex[t].name[0] = 0;
  115.     }
  116.  
  117.     ntex = 0;
  118. }
  119.  
  120. LoadAC3D (name)
  121. char *name;
  122. {
  123.     char buffer[1024], *s, fn[128];
  124.     int firsttime, m;
  125.  
  126.     /* See if it's already loaded */
  127.     for (m=0; m<NMODELS; m++)
  128.     {
  129.         if (!strcmp (model[m].name, name)) return (m);
  130.     }
  131.  
  132.     Log ("LoadAC3D: Loading model %s", name);
  133.  
  134.     /* Find an unused model index */
  135.     m = modelnum = FindModel();
  136.     strcpy (model[m].name, name);
  137.     model[m].in_use = 1;
  138.  
  139.     /* Init bounding box */
  140.     model[m].lobound[0] = model[m].lobound[1] = model[m].lobound[2] = 0.0;
  141.     model[m].hibound[0] = model[m].hibound[1] = model[m].hibound[2] = 0.0;
  142.  
  143.     /* Get a list id */
  144.     model[m].list = glGenLists (1);
  145.  
  146.     /* Construct file name */
  147.     sprintf (fn, "models/%s", name);
  148.  
  149.     /* Open it */
  150.     if (NULL == (acfd = fopen (fn, "rt")))
  151.     {
  152.         Log ("LoadAC3D: Can't open %s, giving up!", fn);
  153.         return (-1);
  154.     }
  155.  
  156.     firsttime = 1;
  157.     firsttime2 = 1;
  158.  
  159.     num_materials = 0;
  160.     num_textures = 0;
  161.     vtab = NULL;
  162.     last_flags = -1 ;
  163.     last_num_kids = -1 ;
  164.     current_flags = -1 ;
  165.     texture_enabled = 0;
  166.     need_texture = 0;
  167.     last_mat = -1;
  168.  
  169.     /* Look for and define textures */
  170.     ScanForTextures();
  171.  
  172.     while (fgets (buffer, 1024, acfd) != NULL)
  173.     {
  174.         s = buffer ;
  175.  
  176.         /* Skip leading whitespace */
  177.         SkipSpaces (&s);
  178.  
  179.         /* Skip blank lines and comments */
  180.         if ( *s < ' ' && *s != '\t' ) continue;
  181.         if ( *s == '#' || *s == ';' ) continue;
  182.  
  183.         if (firsttime)
  184.         {
  185.             firsttime = 0;
  186.  
  187.             if (strncmp (s, "AC3D", 4) != 0)
  188.             {
  189.                 Log ("LoadAC3d: %s is not an AC3D format file", fn);
  190.                 return (-1);
  191.             }
  192.         }
  193.         else
  194.         {
  195.             Search (top_tags, s);
  196.         }
  197.     }
  198.  
  199.     glShadeModel (GL_FLAT);
  200.     glEndList();
  201.     fclose (acfd);
  202.  
  203.     Log ("LoadAC3D: Lo bounds: %lf %lf %lf", model[m].lobound[0],
  204.             model[m].lobound[1], model[m].lobound[2]);
  205.     Log ("LoadAC3D: Hi bounds: %lf %lf %lf", model[m].hibound[0],
  206.             model[m].hibound[1], model[m].hibound[2]);
  207.  
  208.     /* All is well */
  209.     return m;
  210. }
  211.  
  212. ScanForTextures()
  213. /*
  214.  *  Look through the AC3D file for all "texture" lines
  215.  */
  216. {
  217.     char buf[1024], fn[256];
  218.  
  219.     /* Look for "texture" lines */
  220.     while (NULL != fgets (buf, 1024, acfd))
  221.     {
  222.         if (1 == sscanf (buf, "texture %s", fn))
  223.         {
  224.             RemoveQuotes (fn);
  225.             LoadTexture (fn);
  226.         }
  227.     }
  228.  
  229.     /* Rewind the file */
  230.     fseek (acfd, 0, SEEK_SET);
  231. }
  232.  
  233. LoadTexture (s)
  234. char *s;
  235. /*
  236.  *  Load a texture file
  237.  */
  238. {
  239.     char fn[256];
  240.  
  241.     Log ("LoadTexture: Loading texture %s", s);
  242.  
  243.     /* Construct file name */
  244.     sprintf (fn, "models/%s", s);
  245.  
  246.     /* Get a texture id */
  247.     glGenTextures (1, &tex[ntex].id);
  248.     strcpy (tex[ntex].name, s);
  249.  
  250.     /* Define the texture */
  251.     glBindTexture (GL_TEXTURE_2D, tex[ntex].id);
  252.     glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
  253.     load_sgi_texture (fn);
  254.     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  255.     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  256.     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  257.     glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  258.  
  259.     ntex++;
  260. }
  261.  
  262. void ACNormalize (float *v)
  263. {
  264.     float mag;
  265.  
  266.     mag = sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  267.  
  268.     if (mag == 0.0f)
  269.     {
  270.         v[0] = v[1] = 0.0f;
  271.         v[2] = 1.0f;
  272.         return;
  273.     }
  274.  
  275.     v[0] /= mag;
  276.     v[1] /= mag;
  277.     v[2] /= mag;
  278. }
  279.  
  280. void CrossProduct (float *dst, float *a, float *b)
  281. {
  282.     dst[0] = a[1] * b[2] - a[2] * b[1];
  283.     dst[1] = a[2] * b[0] - a[0] * b[2];
  284.     dst[2] = a[0] * b[1] - a[1] * b[0];
  285. }
  286.  
  287. void MakeNormal (float *dst, float *a, float *b, float *c)
  288. {
  289.     float ab[3];
  290.     float ac[3];
  291.  
  292.     ab[0] = b[0] - a[0];
  293.     ab[1] = b[1] - a[1];
  294.     ab[2] = b[2] - a[2];
  295.     ACNormalize (ab);
  296.  
  297.     ac[0] = c[0] - a[0];
  298.     ac[1] = c[1] - a[1];
  299.     ac[2] = c[2] - a[2];
  300.     ACNormalize (ac);
  301.  
  302.     CrossProduct (dst, ab, ac);
  303.     ACNormalize (dst);
  304. }
  305.  
  306. void SkipSpaces (char **s)
  307. {
  308.     while (**s == ' ' || **s == '\t') (*s)++;
  309. }
  310.  
  311. void SkipQuotes (char **s)
  312. {
  313.     char *t;
  314.  
  315.     SkipSpaces (s);
  316.  
  317.     if (**s == '\"')
  318.     {
  319.         (*s)++;
  320.         t = *s;
  321.         while (*t != '\0' && *t != '\"') t++;
  322.  
  323.         if ( *t != '\"' )
  324.             Log ("SkipQuotes: Mismatched double-quote in '%s'\n", *s);
  325.  
  326.         *t = '\0';
  327.     }
  328.     else
  329.     {
  330.         Log ("SkipQuuotes: Expected double-quote in '%s'", *s);
  331.     }
  332. }
  333.  
  334. void RemoveQuotes (char *s)
  335. /*
  336.  *  Remove quotes from string
  337.  */
  338. {
  339.     char *t;
  340.     int i, j, len;
  341.  
  342.     len = strlen (s);
  343.     t = (char *) malloc (len+1);
  344.     strcpy (t, s);
  345.     j = 0;
  346.  
  347.     for (i=0; i<len; i++)
  348.     {
  349.         if (t[i] != '"')
  350.         {
  351.             s[j++] = t[i];
  352.         }
  353.     }
  354.     s[j] = 0;
  355.  
  356.     free (t);
  357. }
  358.  
  359. int Search (struct Tag *tags, char *s)
  360. {
  361.     int i;
  362.  
  363.     SkipSpaces (&s);
  364.  
  365.     for (i=0; tags[i].token != NULL; i++)
  366.     {
  367.         if (!strncasecmp (tags[i].token, s, strlen (tags[i].token)))
  368.         {
  369.             s += strlen (tags[i].token);
  370.             SkipSpaces (&s);
  371.             return (*(tags[i].func))(s);
  372.         }
  373.     }
  374.  
  375.     Log ("Search: Unrecognised token '%s'", s);
  376.     exit (1);
  377.     return 0;
  378. }
  379.  
  380. struct Tag object_tags[] =
  381. {
  382.     {"name"   , DoACName},
  383.     {"data"   , DoData},
  384.     {"texture", DoTexture},
  385.     {"texrep" , DoTexrep},
  386.     {"rot"    , DoRot},
  387.     {"loc"    , DoLoc},
  388.     {"url"    , DoUrl},
  389.     {"numvert", DoNumvert},
  390.     {"numsurf", DoNumsurf},
  391.     {"kids"   , DoKids},
  392.     {NULL, NULL }
  393. };
  394.  
  395. struct Tag surf_tag[] =
  396. {
  397.     {"SURF", DoSurf},
  398.     {NULL, NULL}
  399. };
  400.  
  401. struct Tag surface_tags[] =
  402. {
  403.     {"mat" , DoMat },
  404.     {"refs", DoRefs},
  405.     {NULL, NULL}
  406. };
  407.  
  408. struct Tag obj_type_tags[] =
  409. {
  410.     {"world", DoObjWorld},
  411.     {"poly" , DoObjPoly },
  412.     {"group", DoObjGroup},
  413.     {NULL, NULL}
  414. };
  415.  
  416. #define OBJ_WORLD  0
  417. #define OBJ_POLY   1
  418. #define OBJ_GROUP  2
  419.  
  420. int DoObjWorld (char *s)
  421. {
  422.     return OBJ_WORLD;
  423.  
  424. int DoObjPoly (char *s)
  425. {
  426.     return OBJ_POLY;
  427. }
  428.  
  429. int DoObjGroup (char *s)
  430. {
  431.     return OBJ_GROUP;
  432. }
  433.  
  434. void DoBegin (int flags)
  435. {
  436.     if (last_flags == -1) last_flags = ~flags;
  437.  
  438.     if (((flags>>4) & 0x01) != ((last_flags>>4) & 0x01))
  439.     {
  440.         if ((flags>>4) & 0x01)
  441.         {
  442.             /* Smooth Shaded */
  443.             acsmooth = 1;
  444.         }
  445.         else
  446.         {
  447.             /* Flat Shaded */
  448.             acsmooth = 0;
  449.         }
  450.     }
  451. /**
  452.     if (((flags>>4) & 0x02) != ((last_flags>>4) & 0x02))
  453.     {
  454.         if ((flags>>4) & 0x02)
  455.         {
  456.             if (acsurfpass == PASS_RENDER) glDisable (GL_CULL_FACE);
  457.         }
  458.         else
  459.         {
  460.             if (acsurfpass == PASS_RENDER) glEnable (GL_CULL_FACE);
  461.         }
  462.     }
  463.  
  464.     if ((last_flags & 0x0F) == 0  && (flags & 0x0F) != 0)
  465.     {
  466.         if (acsurfpass == PASS_RENDER) glDisable (GL_LIGHTING);
  467.     }
  468.     else if ((last_flags & 0x0F) != 0  && (flags & 0x0F) == 0)
  469.     {
  470.         if (acsurfpass == PASS_RENDER) glEnable (GL_LIGHTING);
  471.     }
  472. **/
  473.     last_flags = flags;
  474.  
  475.     switch (flags & 0x0F)
  476.     {
  477.     case 0:    if (acsurfpass == PASS_RENDER) glBegin (GL_POLYGON);
  478.         break;
  479.  
  480.     case 1:    if (acsurfpass == PASS_RENDER) glBegin (GL_LINE_LOOP);
  481.         break;
  482.  
  483.     case 2:    if (acsurfpass == PASS_RENDER) glBegin (GL_LINE_STRIP);
  484.         break;
  485.  
  486.     default:
  487.         Log ("DoBegin: Illegal surface type 0x%02x", flags);
  488.         break;
  489.     }
  490. }
  491.  
  492. int DoMaterial (char *s)
  493. {
  494.     char name[1024], *nm;
  495.     float rgb[3], amb[3], emis[3], spec[3], trans;
  496.     int shi;
  497.  
  498.     if (15 != sscanf (s,
  499.         "%s rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f",
  500.         name, &rgb[0], &rgb[1], &rgb[2], &amb[0], &amb[1], &amb[2],
  501.         &emis[0], &emis[1], &emis[2], &spec[0], &spec[1], &spec[2], &shi, &trans))
  502.     {
  503.         Log ("DoMaterial: Can't parse this MATERIAL: %s", s);
  504.     }
  505.     else
  506.     {
  507.         nm = name;
  508.         SkipQuotes (&nm);
  509.  
  510.         /* Get a list for this material */
  511.         matlist[num_materials] = glGenLists (1);
  512.  
  513.         glNewList (matlist[num_materials], GL_COMPILE );
  514.         glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, amb);
  515.         glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, rgb);
  516.         glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, spec);
  517.         glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION, emis);
  518.         glMaterialf  (GL_FRONT_AND_BACK, GL_SHININESS, shi);
  519.         glEndList();
  520.     }
  521.     num_materials++;
  522.  
  523.     return PARSE_CONT;
  524. }
  525.  
  526. int DoObject (char *s)
  527. {
  528.     int i, obj_type, num_kids;
  529.     char buffer[1024];
  530.  
  531.     if (firsttime2)
  532.     {
  533.         glNewList (model[modelnum].list, GL_COMPILE);
  534.         glShadeModel (GL_SMOOTH);
  535.         firsttime2 = 0;
  536.     }
  537.  
  538.     obj_type = Search (obj_type_tags, s);  
  539.  
  540.     switch (obj_type)
  541.     {
  542.     case OBJ_WORLD:
  543.         break;
  544.  
  545.     case OBJ_POLY:
  546.         break;
  547.  
  548.     case OBJ_GROUP:
  549.         break;
  550.     }
  551.  
  552.     need_texture = 0;
  553.  
  554.     glPushMatrix();
  555.  
  556.     while (NULL != fgets (buffer, 1024, acfd))
  557.     {
  558.         if (Search (object_tags, buffer) == PARSE_POP) break;
  559.     }
  560.  
  561.     num_kids = last_num_kids;
  562.  
  563.     for (i=0; i<num_kids; i++)
  564.     {
  565.         fgets (buffer, 1024, acfd);
  566.         Search (top_tags, buffer);
  567.     }
  568.  
  569.     glPopMatrix();
  570.  
  571.     return PARSE_CONT;
  572. }
  573.  
  574. int DoACName (char *s)
  575. {
  576.     SkipQuotes (&s);
  577.     return PARSE_CONT;
  578. }
  579.  
  580. int DoData (char *s)
  581. {
  582.     int i, len;
  583.  
  584.     len = strtol (s, NULL, 0);
  585.     Log ("DoData: WARNING - data string encountered");
  586.     for (i=0; i<len; i++) fgetc (acfd);
  587.  
  588.     return PARSE_CONT;
  589. }
  590.  
  591. int GetTexture (char *s)
  592. {
  593.     int t;
  594.  
  595.     for (t=0; t<ntex; t++)
  596.     {
  597.         if (!strcasecmp (s, tex[t].name)) return t;
  598.     }
  599.  
  600.     return 0;
  601. }
  602.  
  603. int DoTexture (char *s)
  604. {
  605.     static int last_tex = -1;
  606.     int t;
  607.  
  608.     SkipQuotes (&s);
  609.  
  610.     t = GetTexture (s);
  611.  
  612.     if (t != last_tex)
  613.     {
  614.         glBindTexture (GL_TEXTURE_2D, tex[t].id);
  615.  
  616.         last_tex = t;
  617.     }
  618.  
  619.     need_texture = 1;
  620.  
  621.     return PARSE_CONT;
  622. }
  623.  
  624. int DoTexrep (char *s)
  625. {
  626.     float texrep[2];
  627.  
  628.     if (2 != sscanf (s, "%f %f", &texrep[0], &texrep[1]))
  629.         Log ("DoTextrep: Illegal texrep record: %s", s);
  630.  
  631.     return PARSE_CONT;
  632. }
  633.  
  634. int DoRot (char *s)
  635. {
  636.     float mat[4][4];
  637.  
  638.     mat[0][3] = mat[1][3] = mat[2][3] = mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
  639.     mat[3][3] = 1.0f; 
  640.  
  641.     if (9 != sscanf (s, "%f %f %f %f %f %f %f %f %f",
  642.         &mat[0][0], &mat[0][1], &mat[0][2],
  643.         &mat[1][0], &mat[1][1], &mat[1][2],
  644.         &mat[2][0], &mat[2][1], &mat[2][2]))
  645.     {
  646.         Log ("DoRot: Illegal rot record: %s", s);
  647.     }
  648.  
  649.     glMultMatrixf (mat);
  650.  
  651.     return PARSE_CONT ;
  652. }
  653.  
  654. int DoLoc (char *s)
  655. {
  656.     float loc[3];
  657.  
  658.     if (3 != sscanf (s, "%f %f %f", &loc[0], &loc[1], &loc[2]))
  659.     {
  660.         Log ("DoLoc: Illegal loc record: %s", s);
  661.     }
  662.  
  663.     loc[0] /= 100.0;
  664.     loc[1] /= 100.0;
  665.     loc[2] /= 100.0;
  666.     glTranslatef (loc[0], loc[1], loc[2]);
  667.  
  668.     return PARSE_CONT;
  669. }
  670.  
  671. int DoUrl (char *s)
  672. {
  673.     SkipQuotes (&s);
  674.     return PARSE_CONT;
  675. }
  676.  
  677. int DoNumvert (char *s)
  678. {
  679.     char buffer[1024];
  680.     int i;
  681.  
  682.     nv = strtol (s, NULL, 0);
  683.  
  684.     if (vtab != NULL) free (vtab) ;
  685.  
  686.     vtab = (struct ACVertex *) malloc (3*nv*sizeof(struct ACVertex));
  687.  
  688.     for (i=0; i<nv; i++)
  689.     {
  690.         fgets (buffer, 1024, acfd);
  691.  
  692.         if (3 != sscanf (buffer, "%f %f %f", &vtab[i].v[0], &vtab[i].v[1], &vtab[i].v[2]))
  693.         {
  694.             Log ("DoNumvert: Illegal vertex record: %s", buffer);
  695.         }
  696.         vtab[i].v[0] /= 100.0;
  697.         vtab[i].v[1] /= 100.0;
  698.         vtab[i].v[2] /= 100.0;
  699.  
  700.         vtab[i].normal[0] = vtab[i].normal[1] = vtab[i].normal[2] = 0.0;
  701.         vtab[i].n = 0.0;
  702.  
  703.         if (vtab[i].v[0] < model[modelnum].lobound[0]) model[modelnum].lobound[0] = vtab[i].v[0];
  704.         if (vtab[i].v[1] < model[modelnum].lobound[1]) model[modelnum].lobound[1] = vtab[i].v[1];
  705.         if (vtab[i].v[2] < model[modelnum].lobound[2]) model[modelnum].lobound[2] = vtab[i].v[2];
  706.         if (vtab[i].v[0] > model[modelnum].hibound[0]) model[modelnum].hibound[0] = vtab[i].v[0];
  707.         if (vtab[i].v[1] > model[modelnum].hibound[1]) model[modelnum].hibound[1] = vtab[i].v[1];
  708.         if (vtab[i].v[2] > model[modelnum].hibound[2]) model[modelnum].hibound[2] = vtab[i].v[2];
  709.     }
  710.  
  711.     return PARSE_CONT;
  712. }
  713.  
  714. int DoNumsurf (char *s)
  715. {
  716.     int i, ns, v;
  717.     long pos, p;
  718.     char buffer[1024];
  719.  
  720.     ns = strtol (s, NULL, 0);
  721.  
  722.     /* Do first pass to average normals */
  723.     pos = ftell (acfd);
  724.     acsurfpass = PASS_NORMAL;
  725.     for (i=0; i<ns; i++)
  726.     {
  727.         p = ftell (acfd);
  728.         fgets (buffer, 1024, acfd);
  729.         Search (surf_tag, buffer);
  730.     }
  731.  
  732.     /* Back to beginning of object */
  733.     fseek (acfd, pos, SEEK_SET);
  734.  
  735.     /* Average normals */
  736.     for (v=0; v<nv; v++)
  737.     {
  738.         vtab[v].normal[0] /= vtab[v].n;
  739.         vtab[v].normal[1] /= vtab[v].n;
  740.         vtab[v].normal[2] /= vtab[v].n;
  741.     }
  742.  
  743.     /* Now render */
  744.     acsurfpass = PASS_RENDER;
  745.     last_mat = (-1);
  746.  
  747.     for (i=0; i<ns; i++)
  748.     {
  749.         p = ftell (acfd);
  750.         fgets (buffer, 1024, acfd);
  751.         Search (surf_tag, buffer);
  752.     }
  753.  
  754.     return PARSE_CONT;
  755. }
  756.  
  757. int DoSurf (char *s)
  758. {
  759.     char buffer[1024];
  760.  
  761.     current_flags = strtol (s, NULL, 0);
  762.  
  763.     while (NULL != fgets (buffer, 1024, acfd))
  764.     {
  765.         if (Search (surface_tags, buffer) == PARSE_POP) break;
  766.     }
  767.  
  768.     return PARSE_CONT ;
  769. }
  770.  
  771. int DoMat (char *s)
  772. {
  773.     int mat;
  774.  
  775.     mat = strtol (s, NULL, 0);
  776.  
  777.     if (mat != last_mat)
  778.     {
  779.         if (acsurfpass == PASS_RENDER) glCallList (matlist[mat]);
  780.         last_mat = mat;
  781.     }
  782.  
  783.     return PARSE_CONT ;
  784. }
  785.  
  786. int DoRefs (char *s)
  787. {
  788.     int i;
  789.     int nrefs;
  790.     char buffer[1024] ;
  791.     int *vlist;
  792.     float *tlistu, *tlistv, nrm[3];
  793.  
  794.     nrefs = strtol (s, NULL, 0);
  795.  
  796.     if (nrefs == 0) return PARSE_POP;
  797.  
  798.     if (need_texture && !texture_enabled)
  799.     {
  800.         if (acsurfpass == PASS_RENDER) glEnable (GL_TEXTURE_2D);
  801.         texture_enabled = 1;
  802.     }
  803.     else if (!need_texture && texture_enabled)
  804.     {
  805.         if (acsurfpass == PASS_RENDER) glDisable (GL_TEXTURE_2D);
  806.         texture_enabled = 0;
  807.     }
  808.  
  809.     vlist  = (int *) malloc (sizeof(int)*nrefs);
  810.     tlistu = (float *) malloc (sizeof(float)*nrefs) ;
  811.     tlistv = (float *) malloc (sizeof(float)*nrefs) ;
  812.  
  813.     DoBegin (current_flags);
  814.  
  815.     for (i=0; i<nrefs; i++)
  816.     {
  817.         fgets (buffer, 1024, acfd);
  818.  
  819.         if (3 != sscanf (buffer, "%d %f %f", &vlist[i], &tlistu[i], &tlistv[i]))
  820.         {
  821.             Log ("DoRefs: Illegal ref record: %s", buffer);
  822.             exit (1);
  823.         }
  824.     }
  825.  
  826.     if (nrefs >= 3)
  827.     {
  828.         MakeNormal (nrm, vtab[vlist[0]].v, vtab[vlist[1]].v, vtab[vlist[2]].v);
  829.  
  830.         if (!acsmooth && (acsurfpass == PASS_RENDER))
  831.         {
  832.             glNormal3fv (nrm);
  833.         }
  834.     }
  835.  
  836.     for (i=0; i<nrefs; i++)
  837.     {
  838.         /* Maintain normal first pass */
  839.         if (acsmooth && (acsurfpass == PASS_NORMAL))
  840.         {
  841.             MaintainNormal (vlist[i], nrm);
  842.         }
  843.  
  844.         /* Render second pass */
  845.         if (acsmooth && (acsurfpass == PASS_RENDER))
  846.         {
  847.             glNormal3fv (vtab[vlist[i]].normal);
  848.         }
  849.  
  850.         if (acsurfpass == PASS_RENDER)
  851.         {
  852.             glTexCoord2f (tlistu[i], tlistv[i]);
  853.             glVertex3fv (vtab[vlist[i]].v);
  854.         }
  855.     }
  856.  
  857.     free (vlist);
  858.     free (tlistu);
  859.     free (tlistv);
  860.  
  861.     if (acsurfpass == PASS_RENDER) glEnd();
  862.  
  863.     return PARSE_POP;
  864. }
  865.  
  866. int DoKids (char *s)
  867. {
  868.     last_num_kids = strtol (s, NULL, 0);
  869.     return PARSE_POP;
  870. }
  871.  
  872. MaintainNormal (i, n)
  873. int i;
  874. float n[3];
  875. /*
  876.  *  Maintain a vertex normal
  877.  */
  878. {
  879.     vtab[i].n += 1.0;
  880.  
  881.     vtab[i].normal[0] += n[0];
  882.     vtab[i].normal[1] += n[1];
  883.     vtab[i].normal[2] += n[2];
  884. }
  885.  
  886. /** ------------- The rest loads SGI texture files --------------- **/
  887.  
  888. /* Some magic constants in the file header. */
  889.  
  890. #define SGI_IMG_MAGIC           0x01DA
  891. #define SGI_IMG_SWABBED_MAGIC   0xDA01   /* This is how it appears on a PC */
  892. #define SGI_IMG_VERBATIM        0
  893. #define SGI_IMG_RLE             1
  894.  
  895. static int            sgi_max ;
  896. static int            sgi_min ;
  897. static int            sgi_colormap ;
  898. static unsigned short sgi_magic ;
  899. static char           sgi_type ;
  900. static char           sgi_bpp ;
  901. static unsigned int  *sgi_start ;
  902. static int           *sgi_leng ;
  903. static unsigned char *sgi_temp ;
  904. static int            sgi_swapped ;
  905. static FILE          *sgi_fd ;
  906. static unsigned short sgi_dim ;
  907. static unsigned short sgi_xsize ;
  908. static unsigned short sgi_ysize ;
  909. static unsigned short sgi_zsize ;
  910.  
  911. static void makeConsistentHeader ()
  912. {
  913.   /*
  914.     Sanity checks - and a workaround for buggy RGB files generated by
  915.     the MultiGen Paint program because it will sometimes get confused
  916.     about the way to represent maps with more than one component.
  917.  
  918.     eg   Y > 1, Number of dimensions == 1
  919.          Z > 1, Number of dimensions == 2
  920.   */
  921.  
  922.   if ( sgi_ysize > 1 && sgi_dim < 2 ) sgi_dim = 2 ;
  923.   if ( sgi_zsize > 1 && sgi_dim < 3 ) sgi_dim = 3 ;
  924.   if ( sgi_dim < 1 ) sgi_ysize = 1 ;
  925.   if ( sgi_dim < 2 ) sgi_zsize = 1 ;
  926.   if ( sgi_dim > 3 ) sgi_dim   = 3 ;
  927.   if ( sgi_zsize < 1 && sgi_ysize == 1 ) sgi_dim = 1 ;
  928.   if ( sgi_zsize < 1 && sgi_ysize != 1 ) sgi_dim = 2 ;
  929.   if ( sgi_zsize >= 1 ) sgi_dim = 3 ;
  930.  
  931.   /*
  932.     A very few SGI image files have 2 bytes per component - this
  933.     tool cannot deal with those kinds of files. 
  934.   */
  935.  
  936.   if ( sgi_bpp == 2 )
  937.   {
  938.     Log ("makeConsistentHeader: Can't work with SGI images with %d bpp", sgi_bpp);
  939.     exit (1);
  940.   }
  941.  
  942.   sgi_bpp = 1 ;
  943.   sgi_min = 0 ;
  944.   sgi_max = 255 ;
  945.   sgi_magic = SGI_IMG_MAGIC ;
  946.   sgi_colormap = 0 ;
  947. }
  948.  
  949. static void swab_short ( unsigned short *x )
  950. {
  951.   if ( sgi_swapped )
  952.     *x = (( *x >>  8 ) & 0x00FF ) | 
  953.          (( *x <<  8 ) & 0xFF00 ) ;
  954. }
  955.  
  956. static void swab_int ( unsigned int *x )
  957. {
  958.   if ( sgi_swapped )
  959.     *x = (( *x >> 24 ) & 0x000000FF ) | 
  960.          (( *x >>  8 ) & 0x0000FF00 ) | 
  961.          (( *x <<  8 ) & 0x00FF0000 ) | 
  962.          (( *x << 24 ) & 0xFF000000 ) ;
  963. }
  964.  
  965. static void swab_int_array ( int *x, int leng )
  966. {
  967.   int i;
  968.  
  969.   if ( ! sgi_swapped )
  970.     return ;
  971.  
  972.   for ( i = 0 ; i < leng ; i++ )
  973.   {
  974.     *x = (( *x >> 24 ) & 0x000000FF ) | 
  975.          (( *x >>  8 ) & 0x0000FF00 ) | 
  976.          (( *x <<  8 ) & 0x00FF0000 ) | 
  977.          (( *x << 24 ) & 0xFF000000 ) ;
  978.     x++ ;
  979.   }
  980. }
  981.  
  982.  
  983. static unsigned char readByte ()
  984. {
  985.   unsigned char x ;
  986.   fread ( & x, sizeof(unsigned char), 1, sgi_fd ) ;
  987.   return x ;
  988. }
  989.  
  990. static unsigned short readShort ()
  991. {
  992.   unsigned short x ;
  993.   fread ( & x, sizeof(unsigned short), 1, sgi_fd ) ;
  994.   swab_short ( & x ) ;
  995.   return x ;
  996. }
  997.  
  998. static unsigned int readInt ()
  999. {
  1000.   unsigned int x ;
  1001.   fread ( & x, sizeof(unsigned int), 1, sgi_fd ) ;
  1002.   swab_int ( & x ) ;
  1003.   return x ;
  1004. }
  1005.  
  1006.  
  1007. static void getRow ( unsigned char *buf, int y, int z )
  1008. {
  1009.     unsigned char pixel, count ;
  1010.  
  1011.   if ( y >= sgi_ysize ) y = sgi_ysize - 1 ;
  1012.   if ( z >= sgi_zsize ) z = sgi_zsize - 1 ;
  1013.  
  1014.   fseek ( sgi_fd, sgi_start [ z * sgi_ysize + y ], SEEK_SET ) ;
  1015.  
  1016.   if ( sgi_type == SGI_IMG_RLE )
  1017.   {
  1018.     unsigned char *tmpp = sgi_temp ;
  1019.     unsigned char *bufp = buf ;
  1020.  
  1021.     fread ( sgi_temp, 1, sgi_leng [ z * sgi_ysize + y ], sgi_fd ) ;
  1022.  
  1023.     while ( 1 )
  1024.     {
  1025.       pixel = *tmpp++ ;
  1026.  
  1027.       count = ( pixel & 0x7f ) ;
  1028.  
  1029.       if ( count == 0 )
  1030.     break ;
  1031.  
  1032.       if ( pixel & 0x80 )
  1033.       {
  1034.         while ( count-- )
  1035.       *bufp++ = *tmpp++ ;
  1036.       }
  1037.       else
  1038.       {
  1039.         pixel = *tmpp++ ;
  1040.  
  1041.     while ( count-- )
  1042.           *bufp++ = pixel ;
  1043.       }
  1044.     }
  1045.   }
  1046.   else
  1047.     fread ( buf, 1, sgi_xsize, sgi_fd ) ;
  1048. }
  1049.  
  1050.  
  1051. static void getPlane ( unsigned char *buf, int z )
  1052. {
  1053.   int y;
  1054.   if ( sgi_fd == NULL )
  1055.     return ;
  1056.  
  1057.   if ( z >= sgi_zsize ) z = sgi_zsize - 1 ;
  1058.  
  1059.   for ( y = 0 ; y < sgi_ysize ; y++ )
  1060.     getRow ( & buf [ y * sgi_xsize ], y, z ) ;
  1061. }
  1062.  
  1063.  
  1064.  
  1065. static void getImage ( unsigned char *buf )
  1066. {
  1067.   int y, z;
  1068.  
  1069.   if ( sgi_fd == NULL )
  1070.     return ;
  1071.  
  1072.   for (y = 0 ; y < sgi_ysize ; y++ )
  1073.     for (z = 0 ; z < sgi_zsize ; z++ )
  1074.       getRow ( & buf [ ( z * sgi_ysize + y ) * sgi_xsize ], y, z ) ;
  1075. }
  1076.  
  1077. void load_sgi_texture ( char *fname )
  1078. {
  1079.   int i, tablen, x, y, l, maxlen;
  1080.   GLubyte *texels [ 20 ], *ptr ;
  1081.   unsigned char *rbuf, *gbuf, *bbuf, *abuf;
  1082.   int lev, map_level;
  1083.   int j, x2, y2, c;
  1084.  
  1085.   sgi_dim   = 0 ;
  1086.   sgi_start = NULL ;
  1087.   sgi_leng  = NULL ;
  1088.   sgi_temp  = NULL ;
  1089.  
  1090.   sgi_swapped = 0 ;
  1091.  
  1092.   sgi_fd = fopen ( fname, "rb" ) ;
  1093.  
  1094.   if ( sgi_fd == NULL )
  1095.   {
  1096.     Log ("load_sgi_texture: Failed to open '%s' for reading.", fname ) ;
  1097.     return ;
  1098.   }
  1099.  
  1100.   sgi_magic = readShort () ;
  1101.  
  1102.   if ( sgi_magic != SGI_IMG_MAGIC && sgi_magic != SGI_IMG_SWABBED_MAGIC )
  1103.   {
  1104.     Log ("load_sgi_texture: %s: Unrecognised magic number 0x%04x", fname, sgi_magic ) ;
  1105.     exit ( 1 ) ;
  1106.   }
  1107.  
  1108.   if ( sgi_magic == SGI_IMG_SWABBED_MAGIC )
  1109.   {
  1110.     sgi_swapped = 1 ;
  1111.     swab_short ( & sgi_magic ) ;
  1112.   }
  1113.  
  1114.   sgi_type  = readByte  () ;
  1115.   sgi_bpp   = readByte  () ;
  1116.   sgi_dim   = readShort () ;
  1117.  
  1118.   /*
  1119.     This is a backstop test - if for some reason the magic number isn't swabbed, this
  1120.     test will still catch a swabbed file. Of course images with more than 256 dimensions
  1121.     are not catered for :-)
  1122.   */
  1123.  
  1124.   if ( sgi_dim > 255 )
  1125.   {
  1126.     Log ("load_sgi_texture: %s: Bad swabbing?!?", fname ) ;
  1127.     sgi_swapped = ! sgi_swapped ;
  1128.     swab_short ( & sgi_dim ) ;
  1129.     sgi_magic = SGI_IMG_MAGIC ;
  1130.   }
  1131.  
  1132.   sgi_xsize = readShort () ;
  1133.   sgi_ysize = readShort () ;
  1134.   sgi_zsize = readShort () ;
  1135.   sgi_min   = readInt   () ;  
  1136.   sgi_max   = readInt   () ;  
  1137.               readInt   () ;  /* Dummy field */
  1138.  
  1139.   for (i = 0 ; i < 80 ; i++ )
  1140.     readByte () ;         /* Name field */
  1141.  
  1142.   sgi_colormap = readInt () ;
  1143.  
  1144.   for (i = 0 ; i < 404 ; i++ )
  1145.     readByte () ;         /* Dummy field */
  1146.  
  1147.   makeConsistentHeader () ;
  1148.  
  1149.   tablen = sgi_ysize * sgi_zsize ;
  1150.   sgi_start = (unsigned int *) malloc (tablen*sizeof(unsigned int)) ;
  1151.   sgi_leng  = (int *) malloc (sizeof(int)*tablen) ;
  1152.  
  1153.   if ( sgi_type == SGI_IMG_RLE )
  1154.   {
  1155.     fread ( sgi_start, sizeof ( unsigned int ), tablen, sgi_fd ) ;
  1156.     fread ( sgi_leng , sizeof (  int ), tablen, sgi_fd ) ;
  1157.     swab_int_array ( (int *) sgi_start, tablen ) ;
  1158.     swab_int_array ( (int *) sgi_leng , tablen ) ;
  1159.  
  1160.     maxlen = 0 ;
  1161.  
  1162.     for (i = 0 ; i < tablen ; i++ )
  1163.       if ( sgi_leng [ i ] > maxlen )
  1164.         maxlen = sgi_leng [ i ] ;
  1165.  
  1166.     sgi_temp = (unsigned char *) malloc (maxlen) ;
  1167.   }
  1168.   else
  1169.   {
  1170.     sgi_temp = NULL ;
  1171.  
  1172.     for (i = 0 ; i < sgi_zsize ; i++ )
  1173.       for (j = 0 ; j < sgi_ysize ; j++ )
  1174.       {
  1175.         sgi_start [ i * sgi_ysize + j ] = sgi_xsize * ( i * sgi_ysize + j ) + 512 ;
  1176.         sgi_leng  [ i * sgi_ysize + j ] = sgi_xsize ;
  1177.       }
  1178.   }
  1179.  
  1180.   if ( sgi_zsize <= 0 || sgi_zsize > 4 )
  1181.   {
  1182.     Log ("load_sgi_texture: %s: Not an int/inta/rgb/rgba image?!?", fname ) ;
  1183.     exit ( 1 ) ;
  1184.   }
  1185.  
  1186.  
  1187.   for (i = 0 ; i < 20 ; i++ )
  1188.     texels [ 0 ] = NULL ;
  1189.  
  1190.   texels [ 0 ] = (GLubyte *) malloc (sizeof(GLubyte)* sgi_xsize * sgi_ysize * sgi_zsize ) ;
  1191.  
  1192.   ptr = texels [ 0 ] ;
  1193.  
  1194.   rbuf = malloc (sgi_xsize);
  1195.   gbuf = (sgi_zsize>1) ? malloc(sgi_xsize): (unsigned char *) NULL ;
  1196.   bbuf = (sgi_zsize>2) ? malloc(sgi_xsize): (unsigned char *) NULL ;
  1197.   abuf = (sgi_zsize>3) ? malloc(sgi_xsize): (unsigned char *) NULL ;
  1198.  
  1199.   for ( y = 0 ; y < sgi_ysize ; y++ )
  1200.   {
  1201.     switch ( sgi_zsize )
  1202.     {
  1203.       case 1 :
  1204.     getRow ( rbuf, y, 0 ) ;
  1205.  
  1206.     for ( x = 0 ; x < sgi_xsize ; x++ )
  1207.       *ptr++ = rbuf [ x ] ;
  1208.  
  1209.     break ;
  1210.  
  1211.       case 2 :
  1212.     getRow ( rbuf, y, 0 ) ;
  1213.     getRow ( gbuf, y, 1 ) ;
  1214.  
  1215.     for (x = 0 ; x < sgi_xsize ; x++ )
  1216.     {
  1217.       *ptr++ = rbuf [ x ] ;
  1218.       *ptr++ = gbuf [ x ] ;
  1219.     }
  1220.     break ;
  1221.  
  1222.       case 3 :
  1223.         getRow ( rbuf, y, 0 ) ;
  1224.     getRow ( gbuf, y, 1 ) ;
  1225.     getRow ( bbuf, y, 2 ) ;
  1226.  
  1227.     for (x = 0 ; x < sgi_xsize ; x++ )
  1228.     {
  1229.       *ptr++ = rbuf [ x ] ;
  1230.       *ptr++ = gbuf [ x ] ;
  1231.       *ptr++ = bbuf [ x ] ;
  1232.     }
  1233.     break ;
  1234.  
  1235.       case 4 :
  1236.         getRow ( rbuf, y, 0 ) ;
  1237.     getRow ( gbuf, y, 1 ) ;
  1238.     getRow ( bbuf, y, 2 ) ;
  1239.     getRow ( abuf, y, 3 ) ;
  1240.  
  1241.     for (x = 0 ; x < sgi_xsize ; x++ )
  1242.     {
  1243.       *ptr++ = rbuf [ x ] ;
  1244.       *ptr++ = gbuf [ x ] ;
  1245.       *ptr++ = bbuf [ x ] ;
  1246.       *ptr++ = abuf [ x ] ;
  1247.     }
  1248.     break ;
  1249.     }
  1250.   }
  1251.  
  1252.   for ( lev = 0 ; (( sgi_xsize >> (lev+1) ) != 0 ||
  1253.                    ( sgi_ysize >> (lev+1) ) != 0 ) ; lev++ )
  1254.   {
  1255.     /* Suffix '1' is the higher level map, suffix '2' is the lower level. */
  1256.  
  1257.     int l1 =  lev  ;
  1258.     int l2 = lev+1 ;
  1259.     int w1 = sgi_xsize >> l1 ;
  1260.     int h1 = sgi_ysize >> l1 ;
  1261.     int w2 = sgi_xsize >> l2 ;
  1262.     int h2 = sgi_ysize >> l2 ;
  1263.  
  1264.     if ( w1 <= 0 ) w1 = 1 ;
  1265.     if ( h1 <= 0 ) h1 = 1 ;
  1266.     if ( w2 <= 0 ) w2 = 1 ;
  1267.     if ( h2 <= 0 ) h2 = 1 ;
  1268.  
  1269.     texels[l2] = (GLubyte *) malloc (sizeof(GLubyte)*  w2 * h2 * sgi_zsize ) ;
  1270.  
  1271.     for (x2 = 0 ; x2 < w2 ; x2++ )
  1272.       for (y2 = 0 ; y2 < h2 ; y2++ )
  1273.         for (c = 0 ; c < sgi_zsize ; c++ )
  1274.         {
  1275.           int x1   = x2 + x2 ;
  1276.           int x1_1 = ( x1 + 1 ) % w1 ;
  1277.           int y1   = y2 + y2 ;
  1278.           int y1_1 = ( y1 + 1 ) % h1 ;
  1279.  
  1280.       int t1 = texels [ l1 ] [ (y1   * w1 + x1  ) * sgi_zsize + c ] ;
  1281.       int t2 = texels [ l1 ] [ (y1_1 * w1 + x1  ) * sgi_zsize + c ] ;
  1282.       int t3 = texels [ l1 ] [ (y1   * w1 + x1_1) * sgi_zsize + c ] ;
  1283.       int t4 = texels [ l1 ] [ (y1_1 * w1 + x1_1) * sgi_zsize + c ] ;
  1284.  
  1285.           texels [ l2 ] [ (y2 * w2 + x2) * sgi_zsize + c ] =
  1286.                                            ( t1 + t2 + t3 + t4 ) / 4 ;
  1287.         }
  1288.   }
  1289.  
  1290.   texels [ lev+1 ] = NULL ;
  1291.  
  1292.   if (rbuf != NULL) free (rbuf)  ;
  1293.   if (gbuf != NULL) free (gbuf)  ;
  1294.   if (bbuf != NULL) free (bbuf)  ;
  1295.   if (abuf != NULL) free (abuf)  ;
  1296.  
  1297.   if ( ! ((sgi_xsize & (sgi_xsize-1))==0) ||
  1298.        ! ((sgi_ysize & (sgi_ysize-1))==0) )
  1299.   {
  1300.     Log ("load_sgi_texture: %s: Map is not a power-of-two in size!", fname ) ;
  1301.     exit ( 1 ) ;
  1302.   }
  1303.  
  1304.   glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ) ;
  1305.  
  1306.   map_level = 0 ;
  1307.  
  1308.   if ( sgi_xsize > 256 || sgi_ysize > 256 )
  1309.   {
  1310.     while ( sgi_xsize > 256 || sgi_ysize > 256 )
  1311.     {
  1312.       if (texels[0] != NULL) free (texels[0]) ;
  1313.       sgi_xsize >>= 1 ;
  1314.       sgi_ysize >>= 1 ;
  1315.  
  1316.       for (l = 0 ; texels [ l ] != NULL ; l++ )
  1317.     texels [ l ] = texels [ l+1 ] ;
  1318.     }
  1319.   }
  1320.  
  1321.   for (i = 0 ; texels [ i ] != NULL ; i++ )
  1322.   {
  1323.     int w = sgi_xsize>>i ;
  1324.     int h = sgi_ysize>>i ;
  1325.  
  1326.     if ( w <= 0 ) w = 1 ;
  1327.     if ( h <= 0 ) h = 1 ;
  1328.  
  1329.     glTexImage2D  ( GL_TEXTURE_2D,
  1330.                      map_level, sgi_zsize, w, h, 0 /* Border */,
  1331.                             (sgi_zsize==1)?GL_LUMINANCE:
  1332.                             (sgi_zsize==2)?GL_LUMINANCE_ALPHA:
  1333.                             (sgi_zsize==3)?GL_RGB:
  1334.                                            GL_RGBA,
  1335.                             GL_UNSIGNED_BYTE, (GLvoid *) texels[i] ) ;
  1336.     map_level++ ;
  1337.   }
  1338.  
  1339.   fclose (sgi_fd);
  1340. }
  1341.  
  1342.