home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Issue 2 / Freelog_HS_3_Setp_Oct_Nov_2000_CD2.mdx / Arcade / Orbit / src / model.c < prev    next >
C/C++ Source or Header  |  1999-09-27  |  9KB  |  492 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.  *  Routines to manipulate object models.
  26.  *  Models are stored as "triangle" files in the "models" directory.
  27.  */
  28.  
  29. InitModels()
  30. /*
  31.  *  Set up models structures
  32.  */
  33. {
  34.     int m;
  35.  
  36.     for (m=0; m<NMODELS; m++)
  37.     {
  38.         model[m].in_use = 0;
  39.         model[m].name[0] = 0;
  40.         model[m].list = (-1);
  41.     }
  42. }
  43.  
  44. ResetModels()
  45. /*
  46.  *  Get rid of all models
  47.  */
  48. {
  49.     int m;
  50.  
  51.     for (m=0; m<NMODELS; m++)
  52.     {
  53.         model[m].in_use = 0;
  54.         model[m].name[0] = 0;
  55.         if (glIsList (model[m].list)) glDeleteLists (model[m].list, 1);
  56.         model[m].list = (-1);
  57.     }
  58. }
  59.  
  60. int FindModel ()
  61. /*
  62.  *  Find an unused model
  63.  */
  64. {
  65.     int m;
  66.  
  67.     for (m=0; m<NMODELS; m++)
  68.     {
  69.         if (!model[m].in_use) return (m);
  70.     }
  71.  
  72.     Log ("FindModel: Out of models!  Increase NMODELS in orbit.h!");
  73.     FinishSound();
  74.     CloseLog();
  75.     exit (0);
  76. }
  77.  
  78. struct tri_struct
  79. {
  80.     int v1, v2, v3;
  81.     int hex;
  82.     int done;
  83.     double norm[3];
  84. } *tri;
  85.  
  86. struct vert_struct
  87. {
  88.     double v[3];
  89. } *vert;
  90.  
  91. int ntris;
  92. int nverts;
  93. int verts;
  94. int parity;
  95. int orphans;
  96. int length;
  97. int stripped;
  98. int lasthex;
  99.  
  100. int LoadModel (name)
  101. char *name;
  102. /*
  103.  *  Load a triangle file, make display list, return list ID
  104.  */
  105. {
  106.     char fn[32];
  107.     FILE *fd;
  108.     int hex, m, len;
  109.     double v1[3], v2[3], v3[3], n1[3], n2[3], norm[3];
  110.  
  111.     /* Hand off if it's an AC3D model */
  112.     len = strlen (name);
  113.     if ( (len > 3) && (!strcasecmp (&name[len-2], "ac")) )
  114.     {
  115.         return (LoadAC3D (name));
  116.     }
  117.  
  118.     /* See if it's already loaded */
  119.     for (m=0; m<NMODELS; m++)
  120.     {
  121.         if (!strcmp (model[m].name, name)) return (m);
  122.     }
  123.  
  124.     Log ("LoadModel: Loading model %s", name);
  125.  
  126.     /* Allocate space for triangles and vertices */
  127.     if (NULL == (tri = (struct tri_struct *)
  128.         malloc (4096 * sizeof (struct tri_struct))))
  129.     {
  130.         OutOfMemory();
  131.     }
  132.     if (NULL == (vert = (struct vert_struct *)
  133.         malloc (4096 * sizeof (struct vert_struct))))
  134.     {
  135.         OutOfMemory();
  136.     }
  137.  
  138.     /* Find an unused model index */
  139.     m = FindModel();
  140.     strcpy (model[m].name, name);
  141.     model[m].in_use = 1;
  142.  
  143.     /* Get a list id */
  144.     model[m].list = glGenLists (1);
  145.     glNewList (model[m].list, GL_COMPILE);
  146.  
  147.     /* Construct file name */
  148.     sprintf (fn, "models/%s", name);
  149.  
  150.     /* Open it */
  151.     if (NULL == (fd = fopen (fn, "r")))
  152.     {
  153.         Log ("LoadModel: Can't open %s, giving up!", fn);
  154.         return (-1);
  155.     }
  156.  
  157.     ntris = 0;
  158.     verts = 0;
  159.     nverts = 0;
  160.     orphans = 0;
  161.     lasthex = -1;
  162.  
  163.     /* Read them triangles */
  164.     while (10 == fscanf (fd, "%lf %lf %lf %lf %lf %lf %lf %lf %lf %i",
  165.         &v1[0], &v1[1], &v1[2], &v2[0], &v2[1], &v2[2],
  166.         &v3[0], &v3[1], &v3[2], &hex))
  167.     {
  168.         Vdiv (v1, v1, 100.0);
  169.         Vdiv (v2, v2, 100.0);
  170.         Vdiv (v3, v3, 100.0);
  171.  
  172.         /* Compute normal */
  173.         Vsub (n1, v3, v2);
  174.         Normalize (n1);
  175.         Vsub (n2, v1, v2);
  176.         Normalize (n2);
  177.         Crossp (norm, n1, n2);
  178.         Normalize (norm);
  179.  
  180.         /* Make triangle structure */
  181.         tri[ntris].v1 = AddVertex (v1);
  182.         tri[ntris].v2 = AddVertex (v2);
  183.         tri[ntris].v3 = AddVertex (v3);
  184.  
  185.         Vset (tri[ntris].norm, norm);
  186.         tri[ntris].done = 0;
  187.         tri[ntris].hex = hex;
  188.  
  189.         ntris++;
  190.     }
  191.     fclose (fd);
  192.  
  193.     /* Make models about the same size in network games */
  194.     if (am_client || am_server) ScaleModel (m);
  195.  
  196.     /* Make into triangle strips */
  197.     MakeStrips();
  198.  
  199.     glEndList();
  200.  
  201.     /* Construct bounding box */
  202.     ModelBounds (m);
  203.  
  204.     free (tri);
  205.     free (vert);
  206.  
  207.     return (m);
  208. }
  209.  
  210. MakeStrips()
  211. /*
  212.  *  Since the triangle model consists of sparse triangles and we
  213.  *  want to use triangle strips for performance, this routine slices
  214.  *  and dices the triangles to make them into strips where it can.
  215.  *  The result is not optimal, but it typically cuts the number of
  216.  *  transformed vertices in half and sometimes does much better.
  217.  */
  218. {
  219.     int t, a;
  220.  
  221.     Log ("MakeStrips: Total triangles: %d", ntris);
  222.     Log ("MakeStrips: Total vertices: %d", nverts);
  223.  
  224.     /* While there are more */
  225.     while ((-1) != (t = FindTriangle()))
  226.     {
  227.         verts += 3;
  228.         parity = 0;
  229.         stripped = 0;
  230.         length = 1;
  231.  
  232.         glBegin (GL_TRIANGLE_STRIP);
  233.  
  234.         /* While there is an adjacent triangle */
  235.         while ((-1) != (a = FindAdjacent(t)))
  236.         {
  237.             if (length == 1)
  238.             {
  239.                 Normal (t);
  240.                 Vertex (tri[t].v1);
  241.                 Vertex (tri[t].v2);
  242.                 Vertex (tri[t].v3);
  243.             }
  244.             Normal (a);
  245.             Vertex (tri[a].v3);
  246.             stripped++;
  247.             tri[t].done = 1;
  248.             tri[a].done = 1;
  249.             t = a;
  250.             verts++;
  251.             parity = !parity;
  252.             length++;
  253.         }
  254.  
  255.         if (!stripped)
  256.         {
  257.             flop (t);
  258.             while ((-1) != (a = FindAdjacent(t)))
  259.             {
  260.                 if (length == 1)
  261.                 {
  262.                     Normal (t);
  263.                     Vertex (tri[t].v1);
  264.                     Vertex (tri[t].v2);
  265.                     Vertex (tri[t].v3);
  266.                 }
  267.                 Normal (a);
  268.                 Vertex (tri[a].v3);
  269.                 stripped++;
  270.                 tri[t].done = 1;
  271.                 tri[a].done = 1;
  272.                 t = a;
  273.                 verts++;
  274.                 parity = !parity;
  275.                 length++;
  276.             }
  277.         }
  278.  
  279.         if (!stripped)
  280.         {
  281.             flop (t);
  282.             while ((-1) != (a = FindAdjacent(t)))
  283.             {
  284.                 if (length == 1)
  285.                 {
  286.                     Normal (t);
  287.                     Vertex (tri[t].v1);
  288.                     Vertex (tri[t].v2);
  289.                     Vertex (tri[t].v3);
  290.                 }
  291.                 Normal (a);
  292.                 Vertex (tri[a].v3);
  293.                 stripped++;
  294.                 tri[t].done = 1;
  295.                 tri[a].done = 1;
  296.                 t = a;
  297.                 verts++;
  298.                 parity = !parity;
  299.                 length++;
  300.             }
  301.         }
  302.  
  303.         if (!stripped)
  304.         {
  305.             Normal (t);
  306.             Vertex (tri[t].v1);
  307.             Vertex (tri[t].v2);
  308.             Vertex (tri[t].v3);
  309.  
  310.             /* We get here if triangle t couldn't be put
  311.                in a triangle strip */
  312.             tri[t].done = 1;
  313.             orphans++;
  314.         }
  315.  
  316.         glEnd();
  317.     }
  318.  
  319.     Log ("MakeStrips: Rendered vertices: %d (would have been %d, bare minimum %d)",
  320.         verts, 3*ntris, nverts);
  321.     Log ("MakeStrips: Orphaned triangles: %d", orphans);
  322. }
  323.  
  324. int FindTriangle()
  325. {
  326.     int t;
  327.  
  328.     for (t = 0; t<ntris; t++)
  329.     {
  330.         if (!tri[t].done) return (t);
  331.     }
  332.     return (-1);
  333. }
  334.  
  335. int FindAdjacent (t)
  336. int t;
  337. {
  338.     int a, i;
  339.  
  340.     for (a=0; a<ntris; a++)
  341.     {
  342.         if ( (a != t) && (!tri[a].done) )
  343.         {
  344.             if (parity == 0)
  345.             {
  346.             for (i=0; i<3; i++)
  347.             {
  348.                 if ( (tri[t].v2 == tri[a].v2) &&
  349.                      (tri[t].v3 == tri[a].v1) &&
  350.                      (tri[t].hex == tri[a].hex) )
  351.                     return (a);
  352.                 flop (a);
  353.             }
  354.             }
  355.             else
  356.             {
  357.             for (i=0; i<3; i++)
  358.             {
  359.                 if ( (tri[t].v3 == tri[a].v2) &&
  360.                      (tri[t].v1 == tri[a].v1) &&
  361.                      (tri[t].hex == tri[a].hex) )
  362.                     return (a);
  363.                 flop (a);
  364.             }
  365.             }
  366.         }
  367.     }
  368.     return (-1);
  369. }
  370.  
  371. flop (t)
  372. int t;
  373. {
  374.     int v;
  375.  
  376.     v = tri[t].v1;
  377.     tri[t].v1 = tri[t].v2;
  378.     tri[t].v2 = tri[t].v3;
  379.     tri[t].v3 = v;
  380. }
  381.  
  382. int Veq (v1, v2)
  383. int v1, v2;
  384. {
  385.     return (v1 == v2);
  386. }
  387.  
  388. int AddVertex (v)
  389. double v[3];
  390. {
  391.     int i;
  392.  
  393.     for (i=0; i<nverts; i++)
  394.     {
  395.         if ( (v[0] == vert[i].v[0]) &&
  396.              (v[1] == vert[i].v[1]) &&
  397.              (v[2] == vert[i].v[2]) ) return (i);
  398.     }
  399.  
  400.     Vset (vert[nverts].v, v);
  401.     nverts++;
  402.  
  403.     return (nverts-1);
  404. }
  405.  
  406. Vertex (v)
  407. int v;
  408. {
  409.     glVertex3d (vert[v].v[0], vert[v].v[1], vert[v].v[2]);
  410. }
  411.  
  412. Normal (t)
  413. int t;
  414. {
  415.     float color[3];
  416.  
  417.     if (tri[t].hex != lasthex)
  418.     {
  419.         lasthex = tri[t].hex;
  420.         color[0] = ((float) (tri[t].hex / 65536)) / 256.0;
  421.         color[1] = ((float) ((tri[t].hex % 65536) / 256)) / 256.0;
  422.         color[2] = ((float) (tri[t].hex % 256)) / 256.0;
  423.         glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, color);
  424.         glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, color);
  425.     }
  426.     glNormal3dv (tri[t].norm);
  427. }
  428.  
  429. ModelBounds (m)
  430. int m;
  431. /*
  432.  *  Construct bounding box of model m
  433.  */
  434. {
  435.     int i, v;
  436.     double mm;
  437.  
  438.     for (i=0; i<3; i++)
  439.     {
  440.         model[m].lobound[i] = model[m].hibound[i] = vert[0].v[i];
  441.     }
  442.  
  443.     for (v=1; v<nverts; v++)
  444.     {
  445.         for (i=0; i<3; i++)
  446.         {
  447.             if (vert[v].v[i] < model[m].lobound[i])
  448.                 model[m].lobound[i] = vert[v].v[i];
  449.  
  450.             if (vert[v].v[i] > model[m].hibound[i])
  451.                 model[m].hibound[i] = vert[v].v[i];
  452.         }
  453.     }
  454.  
  455.     Log ("ModelBounds: Lo bounds: %lf %lf %lf", model[m].lobound[0],
  456.             model[m].lobound[1], model[m].lobound[2]);
  457.     Log ("ModelBounds: Hi bounds: %lf %lf %lf", model[m].hibound[0],
  458.             model[m].hibound[1], model[m].hibound[2]);
  459.  
  460.     /* Figure radius of bounding sphere */
  461.     model[m].radius = Mag (model[m].lobound);
  462.     if ((mm = Mag (model[m].hibound)) > model[m].radius)
  463.         model[m].radius = mm;
  464.     model[m].radius2 = model[m].radius * model[m].radius;
  465. }
  466.  
  467. ScaleModel (m)
  468. /*
  469.  *  Make models a uniform size
  470.  */
  471. {
  472.     double ratio;
  473.     int v, i;
  474.  
  475.     /* Compute existing model bounds */
  476.     ModelBounds (m);
  477.  
  478.     if (model[m].radius == 0.0) return;
  479.  
  480.     /* Want everything to have a radius of, say, 0.030 */
  481.     ratio = model[m].radius / 0.030;
  482.  
  483.     /* Scale all the vertices */
  484.     for (v=0; v<nverts; v++)
  485.     {
  486.         for (i=0; i<3; i++)
  487.         {
  488.             vert[v].v[i] /= ratio;
  489.         }
  490.     }
  491. }
  492.