home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / shareware / crystalppc / polyset.cpp < prev    next >
C/C++ Source or Header  |  1998-06-08  |  10KB  |  413 lines

  1. #include <math.h>
  2. #include <time.h>
  3. #include "system.h"
  4.  
  5. #ifndef DEF_H
  6. #include "def.h"
  7. #endif
  8.  
  9. #ifndef POLYSET_H
  10. #include "polyset.h"
  11. #endif
  12.  
  13. #ifndef TOKEN_H
  14. #include "token.h"
  15. #endif
  16.  
  17. #ifndef POLYGON_H
  18. #include "polygon.h"
  19. #endif
  20.  
  21. #ifndef TEXTURE_H
  22. #include "texture.h"
  23. #endif
  24.  
  25. #ifndef WORLD_H
  26. #include "world.h"
  27. #endif
  28.  
  29. #ifndef CAMERA_H
  30. #include "camera.h"
  31. #endif
  32.  
  33. #ifndef SECTOR_H
  34. #include "sector.h"
  35. #endif
  36.  
  37. #ifndef SCAN_H
  38. #include "scan.h"
  39. #endif
  40.  
  41. //---------------------------------------------------------------------------
  42.  
  43. PolygonSet::PolygonSet (char* name, int type, int max_v, int max_p) : CsObject (name, type)
  44. {
  45.   num_vertices = 0;
  46.   num_polygon = 0;
  47.  
  48.   vertices = NULL;
  49.   polygon = NULL;
  50.  
  51.   set_max (max_v, max_p);
  52. }
  53.  
  54. void PolygonSet::set_max (int max_v, int max_p)
  55. {
  56.   if (vertices) delete [] vertices;
  57.   if (polygon) delete [] polygon;
  58.   max_vertices = max_v;
  59.   vertices = new Vertex [max_vertices];
  60.   max_polygon = max_p;
  61.   polygon = new Polygon3D* [max_polygon];
  62. }
  63.  
  64. PolygonSet::~PolygonSet ()
  65. {
  66.   if (vertices) delete [] vertices;
  67.   if (polygon) delete [] polygon;
  68. }
  69.  
  70. void PolygonSet::set_vertex (int idx, float x, float y, float z)
  71. {
  72.   // By default all vertices are set with the same object space and world space.
  73.   vertices[idx].set_o (x, y, z);
  74.   vertices[idx].set (x, y, z);
  75.   if (idx >= num_vertices) num_vertices = idx+1;
  76. }
  77.  
  78. Polygon3D* PolygonSet::get_polygon (char* name)
  79. {
  80.   int i;
  81.   for (i = 0 ; i < num_polygon ; i++)
  82.     if (!strcmp (polygon[i]->get_name (), name)) return polygon[i];
  83.   return NULL;
  84. }
  85.  
  86. Polygon3D* PolygonSet::new_polygon (char* name, int max, Textures* textures, char* tex_name)
  87. {
  88.   return new_polygon (name, max, textures, textures->get_texture_idx (tex_name));
  89. }
  90.  
  91. Polygon3D* PolygonSet::new_polygon (char* name, int max, Textures* textures, int texnr)
  92. {
  93.   Polygon3D* p = new Polygon3D (name, max, textures, texnr);
  94.   polygon[num_polygon++] = p;
  95.   p->set_poly_set (this);
  96.   p->set_sector (sector);
  97.   return p;
  98. }
  99.  
  100. void PolygonSet::add_polygon (Polygon3D* poly)
  101. {
  102.   // Here we could try to include a test for the right orientation
  103.   // of the polygon.
  104.   polygon[num_polygon++] = poly;
  105.   poly->set_poly_set (this);
  106. }
  107.  
  108. Polygon3D* PolygonSet::intersect_segment (Vector3& start, Vector3& end, Vector3& isect)
  109. {
  110.   int i;
  111.   for (i = 0 ; i < num_polygon ; i++)
  112.   {
  113.     if (polygon[i]->intersect_segment (start, end, isect)) return polygon[i];
  114.   }
  115.   return NULL;
  116. }
  117.  
  118. void PolygonSet::dump ()
  119. {
  120.   MSG (("========================================================\n"));
  121.   MSG (("Dump sector '%s':\n", name));
  122.   MSG (("    num_vertices=%d max_vertices=%d num_polygon=%d max_polygon=%d\n",
  123.     num_vertices, max_vertices, num_polygon, max_polygon));
  124.   int i;
  125.  
  126.   MSG (("Vertices:\n"));
  127.   for (i = 0 ; i < num_vertices ; i++)
  128.   {
  129.     MSG (("Vertex[%d]=", i));
  130.     vertices[i].dump ();
  131.     MSG (("\n"));
  132.   }
  133.   MSG (("Polygons:\n"));
  134.   for (i = 0 ; i < num_polygon ; i++)
  135.   {
  136.     polygon[i]->dump ();
  137.   }
  138. }
  139.  
  140. void PolygonSet::save (FILE* fp, int indent, Textures* textures, char* setname)
  141. {
  142.   char sp[100]; strcpy (sp, spaces); sp[indent] = 0;
  143.   fprintf (fp, "%s%s '%s' (\n", sp, setname, name);
  144.   fprintf (fp, "%s  MAX_VERTICES=%d\n", sp, max_vertices);
  145.   fprintf (fp, "%s  MAX_POLYGON=%d\n", sp, max_polygon);
  146.   int i;
  147.   for (i = 0 ; i < num_vertices ; i++)
  148.     vertices[i].save (fp, indent+2);
  149.   for (i = 0 ; i < num_polygon ; i++)
  150.     polygon[i]->save (fp, indent+2, textures);
  151. }
  152.  
  153. void PolygonSet::load (World* w, char** buf, Textures* textures, char* setname)
  154. {
  155.   char* t;
  156.   char* old_buf;
  157.   int i;
  158.   num_vertices = 0;
  159.   num_polygon = 0;
  160.   int default_texnr = -1;
  161.   float default_texlen = 1;
  162.  
  163.   skip_token (buf, setname);
  164.   t = get_token (buf);
  165.   strcpy (name, t);
  166.   skip_token (buf, "(", "Expected '%s' instead of '%s' after the name of a POLYGONSET!\n");
  167.  
  168.   while (TRUE)
  169.   {
  170.     old_buf = *buf;
  171.     t = get_token (buf);
  172.     if (*t == ')' || *t == 0) break;
  173.     if (!strcmp (t, "MAX_VERTICES"))
  174.     {
  175.       skip_token (buf, "=", "Expected '%s' instead of '%s' after MAX_VERTICES!\n");
  176.       i = get_token_int (buf);
  177.       set_max (i, max_polygon);
  178.     }
  179.     else if (!strcmp (t, "MAX_POLYGON"))
  180.     {
  181.       skip_token (buf, "=", "Expected '%s' instead of '%s' after MAX_POLYGON!\n");
  182.       i = get_token_int (buf);
  183.       set_max (max_vertices, i);
  184.     }
  185.     else if (!strcmp (t, "VERTEX"))
  186.     {
  187.       *buf = old_buf;
  188.       vertices[num_vertices++].load (buf);
  189.     }
  190.     else if (!strcmp (t, "POLYGON"))
  191.     {
  192.       t = get_token (buf);
  193.       Polygon3D* p = new_polygon (t, 10, textures, 0);
  194.       *buf = old_buf;
  195.       p->load (w, buf, textures, default_texnr, default_texlen);
  196.     }
  197.     else if (!strcmp (t, "TEXNR"))
  198.     {
  199.       skip_token (buf, "=", "Expected '%s' instead of '%s' after TEXNR!\n");
  200.       t = get_token (buf);
  201.       default_texnr = textures->get_texture_idx (t);
  202.       if (default_texnr == -1)
  203.       {
  204.         printf ("Couldn't find texture named '%s'!\n", t);
  205.       }
  206.     }
  207.     else if (!strcmp (t, "TEXLEN"))
  208.     {
  209.       skip_token (buf, "=", "Expected '%s' instead of '%s' after TEXLEN!\n");
  210.       default_texlen = get_token_float (buf);
  211.     }
  212.     else if (!strcmp (t, "TRIGGER"))
  213.     {
  214.       t = get_token (buf);
  215.       if (!strcmp (t, "activate"))
  216.       {
  217.     skip_token (buf, ":", "Expected '%s' instead of '%s' in TRIGGER!\n");
  218.     t = get_token (buf);
  219.     Script* s = w->get_script (t);
  220.     if (!s)
  221.     {
  222.       printf ("Don't know script '%s'!\n", t);
  223.       exit (0);
  224.     }
  225.     new_activate_trigger (s);
  226.       }
  227.       else
  228.       {
  229.     printf ("Trigger '%s' not supported or known for object '%s'!\n", t, name);
  230.     exit (0);
  231.       }
  232.     }
  233.     else break;
  234.   }
  235.   *buf = old_buf;
  236. }
  237.  
  238. int PolygonSet::transform_world2cam (Matrix3& m_w2c, Matrix3& m_c2w, Vector3& v_w2c)
  239. {
  240.   (void)m_c2w;
  241.   int i, cnt_vis;
  242.  
  243.   cnt_vis = 0;
  244.   for (i = 0 ; i < num_vertices ; i++)
  245.   {
  246.     vertices[i].world_to_camera (m_w2c, v_w2c);
  247.     if (vertices[i].get_tz () >= SMALL_Z) cnt_vis++; 
  248.   }
  249.  
  250.   return cnt_vis > 0;
  251. }
  252.  
  253. Polygon3D* PolygonSet::select_polygon (Camera* c, ViewPolygon* view, int xx, int yy)
  254. {
  255.   int i;
  256.   Vector2 v;
  257.   v.x = (float)xx;
  258.   v.y = (float)yy;
  259.  
  260.   if (transform_world2cam (c->m_world2cam, c->m_cam2world, c->v_world2cam))
  261.   {
  262.     for (i = 0 ; i < num_polygon ; i++)
  263.     {
  264.       if (polygon[i]->do_perspective (Scan::c->m_world2cam, Scan::c->m_cam2world,
  265.                       Scan::c->v_world2cam, &Polygon2D::clipped))
  266.       {
  267.     if (Polygon2D::clipped.clip_poly_variant (view))
  268.     {
  269.       if (v.in_poly_2d (Polygon2D::clipped.get_vertices (),
  270.                 Polygon2D::clipped.get_num_vertices (),
  271.                 &Polygon2D::clipped.get_bounding_box ()) == POLY_IN)
  272.       {
  273.         Sector* s = polygon[i]->get_portal ();
  274.         if (s)
  275.         {
  276.           ViewPolygon* new_view = Polygon2D::clipped.create_view ();
  277.           if (new_view)
  278.           {
  279.         Polygon3D* rc = s->select_polygon (c, new_view, xx, yy);
  280.         delete new_view;
  281.         return rc;
  282.           }
  283.         }
  284.         return polygon[i];
  285.       }
  286.     }
  287.       }
  288.     }
  289.   }
  290.   return NULL;
  291. }
  292.  
  293. Vertex* PolygonSet::select_vertex (Camera* c, ViewPolygon* view, int xx, int yy)
  294. {
  295.   (void)c;
  296.   int i, j;
  297.   j = -1;
  298.   float mindist = 1000000000.;
  299.   float dist;
  300.   float fx = (float)xx;
  301.   float fy = (float)yy;
  302.  
  303.   for (i = 0 ; i < num_vertices ; i++)
  304.   {
  305.     float x = vertices[i].get_tx ();
  306.     float y = vertices[i].get_ty ();
  307.     float z = vertices[i].get_tz ();
  308.     if (z < SMALL_Z) continue;
  309.     Vector2 v;
  310.     v.x = (ASPECT * x) / z + (FRAME_WIDTH/2);
  311.     v.y = (ASPECT * y) / z + (FRAME_HEIGHT/2);
  312.     if (v.in_poly_2d (view->get_vertices (), view->get_num_vertices (),
  313.               &view->get_bounding_box ()) != POLY_IN) continue;
  314.     dist = (fx-v.x)*(fx-v.x) + (fy-v.y)*(fy-v.y);
  315.     if (dist < mindist) { mindist = dist; j = i; }
  316.   }
  317.   return &vertices[j];
  318. }
  319.  
  320. void PolygonSet::edit_draw_vertices ()
  321. {
  322.   int i, j;
  323.   int col;
  324.  
  325.   for (i = 0 ; i < num_vertices ; i++)
  326.   {
  327.     col = -1;
  328.     if (Scan::c->edit_mode == MODE_VERTEX) col = Scan::textures->white ();
  329.     for (j = 0 ; j < Scan::c->num_sel_verts ; j++)
  330.       if (Scan::c->sel_vertex[j] == &vertices[i])
  331.       {
  332.     col = Scan::textures->red ();
  333.     break;
  334.       }
  335.     if (Scan::c->edit_mode != MODE_VERTEX && col != Scan::textures->red ()) continue;
  336.  
  337.     float x = vertices[i].get_tx ();
  338.     float y = vertices[i].get_ty ();
  339.     float z = vertices[i].get_tz ();
  340.     if (z < SMALL_Z) continue;
  341.     x = (ASPECT * x) / z + (FRAME_WIDTH/2);
  342.     y = (ASPECT * y) / z + (FRAME_HEIGHT/2);
  343.     int xx = QInt (x);
  344.     int yy = QInt (y);
  345.     Scan::g->SetPixel (xx, yy, col);
  346.     Scan::g->SetPixel (xx-1, yy, col);
  347.     Scan::g->SetPixel (xx+1, yy, col);
  348.     Scan::g->SetPixel (xx-2, yy, col);
  349.     Scan::g->SetPixel (xx+2, yy, col);
  350.     Scan::g->SetPixel (xx, yy-1, col);
  351.     Scan::g->SetPixel (xx, yy+1, col);
  352.     Scan::g->SetPixel (xx, yy-2, col);
  353.     Scan::g->SetPixel (xx, yy+2, col);
  354.   }
  355. }
  356.  
  357. void PolygonSet::edit_split_poly (Camera* c, Textures* textures)
  358. {
  359.   int pidx = 0, i, j;
  360.   char name[50];
  361.   Polygon3D* pnew[MAX_SEL_VERTEX];
  362.   int idx[MAX_SEL_VERTEX];
  363.   float x, y, z;
  364.  
  365.   Polygon3D* p = c->sel_polygon;
  366.  
  367.   for (i = 0 ; i < num_polygon ; i++)
  368.     if (polygon[i] == p) { pidx = i; break; }
  369.  
  370.   strcpy (name, p->get_name ());
  371.   strcat (name, "A");
  372.  
  373.   x = y = z = 0;
  374.   for (i = 0 ; i < c->num_sel_verts ; i++)
  375.   {
  376.     name[strlen (name)-1] = i+'A';
  377.     pnew[i] = new_polygon (name, p->get_max_vertices (), textures, p->get_texnr ());
  378.     pnew[i]->set_texture_space (p);
  379.     for (j = 0 ; j < p->get_num_vertices () ; j++)
  380.       if (&(p->vtex (j)) == c->sel_vertex[i]) { idx[i] = j; break; }
  381.     if (j == p->get_num_vertices ()) return; // ERROR!
  382.     x += p->vtex (j).get_ox ();
  383.     y += p->vtex (j).get_oy ();
  384.     z += p->vtex (j).get_oz ();
  385.   }
  386.   x /= c->num_sel_verts;
  387.   y /= c->num_sel_verts;
  388.   z /= c->num_sel_verts;
  389.  
  390.   set_vertex (num_vertices, x, y, z);
  391.  
  392.   for (i = 0 ; i < c->num_sel_verts ; i++)
  393.   {
  394.     int j1;
  395.     j = idx[i];
  396.     j1 = idx[(i+1) % c->num_sel_verts];
  397.     pnew[i]->add_vertex (num_vertices-1);
  398.     while (j != j1)
  399.     {
  400.       pnew[i]->add_vertex (p->get_vertices_idx ()[j]);
  401.       j = (j+1) % p->get_num_vertices ();
  402.     }
  403.     pnew[i]->add_vertex (p->get_vertices_idx ()[j1]);
  404.   }
  405.  
  406.   delete p;
  407.   polygon[pidx] = pnew[0];
  408.   for (i = 1 ; i < c->num_sel_verts ; i++)
  409.     polygon[num_polygon++] = pnew[i];
  410. }
  411.  
  412. //---------------------------------------------------------------------------
  413.