home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Amiga / Jeux / demos / crystalPPC.lha / polygon.cpp < prev    next >
C/C++ Source or Header  |  1998-05-05  |  44KB  |  1,635 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 POLYGON_H
  10. #include "polygon.h"
  11. #endif
  12.  
  13. #ifndef SCAN_H
  14. #include "scan.h"
  15. #endif
  16.  
  17. #ifndef TEXTURE_H
  18. #include "texture.h"
  19. #endif
  20.  
  21. #ifndef POLYPLANE_H
  22. #include "polyplan.h"
  23. #endif
  24.  
  25. #ifndef TOKEN_H
  26. #include "token.h"
  27. #endif
  28.  
  29. #ifndef SECTOR_H
  30. #include "sector.h"
  31. #endif
  32.  
  33. #ifndef WORLD_H
  34. #include "world.h"
  35. #endif
  36.  
  37. #ifndef LIGHT_H
  38. #include "light.h"
  39. #endif
  40.  
  41. #ifndef LIGHTMAP_H
  42. #include "lightmap.h"
  43. #endif
  44.  
  45. //#ifndef OCCLUS_H
  46. //#include "occlus.h"
  47. //#endif
  48. #include <clib/powerpc_protos.h>
  49.  
  50. //---------------------------------------------------------------------------
  51.  
  52. // Given a camera space coordinate, calculate the texture space coordinates
  53. // (u,v) coordinates. This is a theoretical function which is never used
  54. // anywhere but I don't remove it since it documents the core of the
  55. // perspective correct texture mapping equations.
  56.  
  57. void get_uv (float x, float y, float z, Matrix3& m_cam2tex, Vector3& v_cam2tex,
  58.         float* p_u, float* p_v)
  59. {
  60.   // From: T = Mct * (C - Vct)
  61.   x -= v_cam2tex.x;
  62.   y -= v_cam2tex.y;
  63.   z -= v_cam2tex.z;
  64.   *p_u = m_cam2tex.m11*x+m_cam2tex.m12*y+m_cam2tex.m13*z;
  65.   *p_v = m_cam2tex.m21*x+m_cam2tex.m22*y+m_cam2tex.m23*z;
  66. }
  67.  
  68. //---------------------------------------------------------------------------
  69.  
  70. Polygon3D::Polygon3D (char* name, int max, Textures* textures, int texnr)
  71. {
  72.   max_vertices = max;
  73.   vertices_idx = new int [max];
  74.   num_vertices = 0;
  75.  
  76.   strcpy (Polygon3D::name, name);
  77.  
  78.   portal = NULL;
  79.  
  80.   tex = new PolyTexture ();
  81.   tex->set_polygon (this);
  82.   tex->set_texnr (textures, texnr);
  83.  
  84.   tex1 = new PolyTexture ();
  85.   tex1->set_polygon (this);
  86.   tex1->set_texnr (textures, textures->get_mipmap1_nr (texnr));
  87.  
  88.   tex2 = new PolyTexture ();
  89.   tex2->set_polygon (this);
  90.   tex2->set_texnr (textures, textures->get_mipmap2_nr (texnr));
  91.  
  92.   tex3 = new PolyTexture ();
  93.   tex3->set_polygon (this);
  94.   tex3->set_texnr (textures, textures->get_mipmap3_nr (texnr));
  95.  
  96.   plane = NULL;
  97.   delete_plane = FALSE;
  98.  
  99.   do_warp_space = FALSE;
  100.   no_mipmap = FALSE;
  101.   no_lighting = FALSE;
  102.  
  103.   lightmap = lightmap1 = lightmap2 = lightmap3 = NULL;
  104. }
  105.  
  106. Polygon3D::~Polygon3D ()
  107. {
  108.   if (vertices_idx) delete [] vertices_idx;
  109.   if (tex) delete tex;
  110.   if (tex1) delete tex1;
  111.   if (tex2) delete tex2;
  112.   if (tex3) delete tex3;
  113.   if (plane && delete_plane) delete plane;
  114.   if (lightmap) delete lightmap;
  115.   if (lightmap1) delete lightmap1;
  116.   if (lightmap2) delete lightmap2;
  117.   if (lightmap3) delete lightmap3;
  118. }
  119.  
  120. void Polygon3D::set_texnr (Textures* textures, int texnr)
  121. {
  122.   tex->set_texnr (textures, texnr);
  123.   tex1->set_texnr (textures, textures->get_mipmap1_nr (texnr));
  124.   tex2->set_texnr (textures, textures->get_mipmap2_nr (texnr));
  125.   tex3->set_texnr (textures, textures->get_mipmap3_nr (texnr));
  126. }
  127.  
  128. PolyTexture* Polygon3D::get_polytex (int mipmap)
  129. {
  130.   switch (mipmap)
  131.   {
  132.     case 0: return tex;
  133.     case 1: return tex1;
  134.     case 2: return tex2;
  135.     case 3: return tex3;
  136.   }
  137.   return tex;
  138. }
  139.  
  140. PolyTexture* Polygon3D::get_polytex (float z_dist)
  141. {
  142.   if (z_dist < ZDIST_MIPMAP1) return tex;
  143.   if (z_dist < ZDIST_MIPMAP2) return tex1;
  144.   if (z_dist < ZDIST_MIPMAP3) return tex2;
  145.   return tex3;
  146. }
  147.  
  148. void Polygon3D::warp_space (Matrix3& m_w2c, Matrix3& m_c2w, Vector3& v_w2c)
  149. {
  150.   if (do_warp_space)
  151.   {
  152.     m_w2c *= m_warp;
  153.  
  154.     Matrix3 m = m_warp_inv;
  155.     m *= m_c2w;
  156.     m_c2w = m;
  157.  
  158.     v_w2c += v_warp;
  159.   }
  160. }
  161.  
  162. void Polygon3D::set_warp (Matrix3& m_w, Vector3& v_w)
  163. {
  164.   do_warp_space = TRUE;
  165.   m_warp = m_w;
  166.   m_warp_inv = m_w;
  167.   m_warp_inv.inverse ();
  168.   v_warp = v_w;
  169. }
  170.  
  171. int Polygon3D::same_plane (Polygon3D* p)
  172. {
  173.   if (p->plane == plane) return TRUE;
  174.  
  175.   if (ABS (p->A-A) > .001) return FALSE;
  176.   if (ABS (p->B-B) > .001) return FALSE;
  177.   if (ABS (p->C-C) > .001) return FALSE;
  178.   if (ABS (p->D-D) > .001) return FALSE;
  179.   return TRUE;
  180. }
  181.  
  182. void Polygon3D::compute_normal ()
  183. {
  184.   PlaneNormal (&Ao, &Bo, &Co);
  185.   Do = -Ao*vtex (0).get_ox () - Bo*vtex (0).get_oy () - Co*vtex (0).get_oz ();
  186.  
  187.   // By default the world space normal is equal to the object space normal.
  188.   A = Ao;
  189.   B = Bo;
  190.   C = Co;
  191.   D = Do;
  192. }
  193.  
  194. void Polygon3D::get_camera_normal (float* p_A, float* p_B, float* p_C, float* p_D)
  195. {
  196.   *p_A = Ac;
  197.   *p_B = Bc;
  198.   *p_C = Cc;
  199.   *p_D = Dc;
  200. }
  201.  
  202. void Polygon3D::get_world_normal (float* p_A, float* p_B, float* p_C, float* p_D)
  203. {
  204.   *p_A = A;
  205.   *p_B = B;
  206.   *p_C = C;
  207.   *p_D = D;
  208. }
  209.  
  210. void Polygon3D::normal_object_to_world (Matrix3& m_o2w, Matrix3& m_w2o, Vector3& v_o2w)
  211. {
  212.   (void)m_w2o; (void)v_o2w;
  213.   // Transform the plane normal.
  214.   Vector3 v; v.x = Ao; v.y = Bo; v.z = Co;
  215.   Vector3 v2;
  216.   m_o2w.transform (v, v2);
  217.   A = v2.x; B = v2.y; C = v2.z;
  218.   D = -A*vtex (0).get_x () - B*vtex (0).get_y () - C*vtex (0).get_z ();
  219. }
  220.  
  221. void Polygon3D::normal_world_to_camera (Matrix3& m_w2c, Matrix3& m_c2w, Vector3& v_w2c)
  222. {
  223.   (void)m_c2w; (void)v_w2c;
  224.   // Transform the plane normal.
  225.   Vector3 v; v.x = A; v.y = B; v.z = C;
  226.   Vector3 v2;
  227.   m_w2c.transform (v, v2);
  228.   Ac = v2.x; Bc = v2.y; Cc = v2.z;
  229.   Dc = -Ac*vtex (0).get_tx () - Bc*vtex (0).get_ty () - Cc*vtex (0).get_tz ();
  230. }
  231.  
  232. void Polygon3D::object_to_world (Matrix3& m_o2w, Matrix3& m_w2o, Vector3& v_o2w)
  233. {
  234.   plane->object_to_world (m_o2w, m_w2o, v_o2w);
  235.   normal_object_to_world (m_o2w, m_w2o, v_o2w);
  236. }
  237.  
  238. float Polygon3D::sq_distance (Vector3& v)
  239. {
  240.   float n = A*v.x + B*v.y + C*v.z + D;
  241.   // The normal is normalized (has unit length) so this is
  242.   // all we need to calculate the squared distance.
  243.   return n*n;
  244.   //return (n*n) / (A*A + B*B + C*C);
  245. }
  246.  
  247. void Polygon3D::closest_point (Vector3& v, Vector3& isect)
  248. {
  249.   // The normal is normalized (has unit length) so this is
  250.   // all we need to calculate the squared distance.
  251.   float r = A*v.x + B*v.y + C*v.z + D;
  252.   //  float r = (A*v.x + B*v.y + C*v.z + D) / (A*A + B*B + C*C);
  253.  
  254.   isect.x = r*(-A-v.x)+v.x;
  255.   isect.y = r*(-B-v.y)+v.y;
  256.   isect.z = r*(-C-v.z)+v.z;
  257. }
  258.  
  259. void Polygon3D::precalculate ()
  260. {
  261.   tex->create_bounding_texture_box (); tex->lm = NULL;
  262.   tex1->create_bounding_texture_box (); tex1->lm = NULL;
  263.   tex2->create_bounding_texture_box (); tex2->lm = NULL;
  264.   tex3->create_bounding_texture_box (); tex3->lm = NULL;
  265.  
  266.   lightmap = lightmap1 = lightmap2 = lightmap3 = NULL;
  267.   if (!no_lighting && tex->w*tex->h < 1000000 && !tex->get_texture ()->get_filtered ())
  268.   {
  269.     lightmap = new LightMap ();
  270.     lightmap->alloc (tex->w, tex->h, this);
  271.     tex->mipmap_size = 16; tex->lm = lightmap;
  272.   }
  273. }
  274.  
  275. void Polygon3D::mipmap_settings (int setting)
  276. {
  277.   if (!lightmap) return;
  278.  
  279.   if (lightmap1) { delete lightmap1; lightmap1 = NULL; }
  280.   if (lightmap2) { delete lightmap2; lightmap2 = NULL; }
  281.   if (lightmap3) { delete lightmap3; lightmap3 = NULL; }
  282.  
  283.   switch (setting)
  284.   {
  285.     case MIPMAP_SHADOW_ACCURATE:
  286.       tex1->mipmap_size = 8; tex1->lm = lightmap;
  287.       tex2->mipmap_size = 4; tex2->lm = lightmap;
  288.       tex3->mipmap_size = 2; tex3->lm = lightmap;
  289.       break;
  290.     case MIPMAP_SHADOW_INACCURATE:
  291.       lightmap1 = new LightMap ();
  292.       lightmap1->mipmap_lightmap (tex1->w, tex1->h, lightmap, tex->w, tex->h);
  293.       lightmap2 = new LightMap ();
  294.       lightmap2->mipmap_lightmap (tex2->w, tex2->h, lightmap1, tex1->w, tex1->h);
  295.       lightmap3 = new LightMap ();
  296.       lightmap3->mipmap_lightmap (tex3->w, tex3->h, lightmap2, tex2->w, tex2->h);
  297.       tex1->mipmap_size = 16; tex1->lm = lightmap1;
  298.       tex2->mipmap_size = 16; tex2->lm = lightmap2;
  299.       tex3->mipmap_size = 16; tex3->lm = lightmap3;
  300.       break;
  301.     case MIPMAP_SHADOW_REASONABLE:
  302.       lightmap2 = new LightMap ();
  303.       lightmap2->mipmap_lightmap (tex1->w, tex1->h, lightmap, tex->w, tex->h);
  304.       tex1->mipmap_size = 8; tex1->lm = lightmap;
  305.       tex2->mipmap_size = 8; tex2->lm = lightmap2;
  306.       tex3->mipmap_size = 4; tex3->lm = lightmap2;
  307.       break;
  308.   }
  309. }
  310.  
  311. void Polygon3D::set_texture_space (PolyPlane* pl)
  312. {
  313.   compute_normal ();
  314.  
  315.   if (plane && delete_plane) delete plane;
  316.   plane = pl;
  317.   delete_plane = FALSE;
  318.  
  319.   precalculate ();
  320. }
  321.  
  322. void Polygon3D::set_texture_space (Polygon3D* copy_from)
  323. {
  324.   compute_normal ();
  325.  
  326.   if (plane && delete_plane) delete plane;
  327.   plane = copy_from->plane;
  328.   delete_plane = FALSE;
  329.  
  330.   precalculate ();
  331. }
  332.  
  333. void Polygon3D::set_texture_space (Matrix3& tx_matrix, Vector3& tx_vector)
  334. {
  335.   compute_normal ();
  336.  
  337.   if (plane && delete_plane) delete plane;
  338.   plane = new PolyPlane ("-");
  339.   delete_plane = TRUE;
  340.   plane->set_texture_space (tx_matrix, tx_vector);
  341.  
  342.   precalculate ();
  343. }
  344.  
  345. void Polygon3D::set_texture_space (Vertex& v_orig, Vertex& v1, float len1)
  346. {
  347.   float xo = v_orig.get_ox ();
  348.   float yo = v_orig.get_oy ();
  349.   float zo = v_orig.get_oz ();
  350.   float x1 = v1.get_ox ();
  351.   float y1 = v1.get_oy ();
  352.   float z1 = v1.get_oz ();
  353.   set_texture_space (xo, yo, zo, x1, y1, z1, len1);
  354. }
  355.  
  356. void Polygon3D::set_texture_space (Vertex& v_orig,
  357.         Vertex& v1, float len1,
  358.         Vertex& v2, float len2)
  359. {
  360.   compute_normal ();
  361.  
  362.   if (plane && delete_plane) delete plane;
  363.   plane = new PolyPlane ("-");
  364.   delete_plane = TRUE;
  365.   plane->set_texture_space (v_orig, v1, len1, v2, len2);
  366.  
  367.   precalculate ();
  368. }
  369.  
  370. void Polygon3D::set_texture_space (
  371.         float xo, float yo, float zo,
  372.         float x1, float y1, float z1,
  373.         float len1)
  374. {
  375.   compute_normal ();
  376.  
  377.   float l1 = sqrt ((xo-x1)*(xo-x1) + (yo-y1)*(yo-y1) + (zo-z1)*(zo-z1));
  378.   x1 = (x1-xo) / l1;
  379.   y1 = (y1-yo) / l1;
  380.   z1 = (z1-zo) / l1;
  381.  
  382.   float x2, y2, z2;
  383.  
  384.   // The cross product of the given vector and the normal of
  385.   // the polygon plane is a vector which is perpendicular on
  386.   // both (and thus is also on the plane).
  387.   x2 = y1*C-z1*B;
  388.   y2 = z1*A-x1*C;
  389.   z2 = x1*B-y1*A;
  390.  
  391.   float l2 = sqrt (x2*x2 + y2*y2 + z2*z2);
  392.  
  393.   x1 *= len1;
  394.   y1 *= len1;
  395.   z1 *= len1;
  396.   x2 = x2*len1 / l2;
  397.   y2 = y2*len1 / l2;
  398.   z2 = z2*len1 / l2;
  399.  
  400.   float l3 = sqrt (A*A + B*B + C*C);
  401.   float a, b, c;
  402.   a = A*len1 / l3;
  403.   b = B*len1 / l3;
  404.   c = C*len1 / l3;
  405.  
  406.   if (plane && delete_plane) delete plane;
  407.   plane = new PolyPlane ("-");
  408.   delete_plane = TRUE;
  409.   plane->set_texture_space (xo, yo, zo, x1, y1, z1, x2, y2, z2, a, b, c);
  410.  
  411.   precalculate ();
  412. }
  413.  
  414. void Polygon3D::set_texture_space (
  415.         float xo, float yo, float zo,
  416.         float x1, float y1, float z1,
  417.         float len1,
  418.         float x2, float y2, float z2,
  419.         float len2)
  420. {
  421.   compute_normal ();
  422.  
  423.   if (plane && delete_plane) delete plane;
  424.   plane = new PolyPlane ("-");
  425.   delete_plane = TRUE;
  426.   plane->set_texture_space (xo, yo, zo, x1, y1, z1, len1, x2, y2, z2, len2);
  427.  
  428.   precalculate ();
  429. }
  430.  
  431. void Polygon3D::set_texture_space (Vertex& v_orig, Vertex& v_u, Vertex& v_v)
  432. {
  433.   compute_normal ();
  434.  
  435.   if (plane && delete_plane) delete plane;
  436.   plane = new PolyPlane ("-");
  437.   delete_plane = TRUE;
  438.   plane->set_texture_space (v_orig, v_u, v_v);
  439.  
  440.   precalculate ();
  441. }
  442.  
  443. void Polygon3D::set_texture_space (float xo, float yo, float zo,
  444.                           float xu, float yu, float zu,
  445.                           float xv, float yv, float zv)
  446. {
  447.   compute_normal ();
  448.  
  449.   if (plane && delete_plane) delete plane;
  450.   plane = new PolyPlane ("-");
  451.   delete_plane = TRUE;
  452.   plane->set_texture_space (xo, yo, zo, xu, yu, zu, xv, yv, zv);
  453.  
  454.   precalculate ();
  455. }
  456.  
  457. void Polygon3D::set_texture_space (
  458.         float xo, float yo, float zo,
  459.         float xu, float yu, float zu,
  460.         float xv, float yv, float zv,
  461.         float xw, float yw, float zw)
  462. {
  463.   compute_normal ();
  464.  
  465.   if (plane && delete_plane) delete plane;
  466.   plane = new PolyPlane ("-");
  467.   delete_plane = TRUE;
  468.   plane->set_texture_space (xo, yo, zo, xu, yu, zu, xv, yv, zv, xw, yw, zw);
  469.  
  470.   precalculate ();
  471. }
  472.  
  473. void Polygon3D::shine (Light* light)
  474. {
  475.   if (shine_done) return;
  476.   shine_done = TRUE;
  477.   tex->shine (light);
  478. }
  479.  
  480. void Polygon3D::setup_dyn_light (DynLight* light, float sq_dist)
  481. {
  482.   if (shine_done) return;
  483.   shine_done = TRUE;
  484.   light->add_polygon (this);
  485.   tex->setup_dyn_light (light, sq_dist);
  486.   if (tex1) tex1->setup_dyn_light (light, sq_dist);
  487.   if (tex2) tex2->setup_dyn_light (light, sq_dist);
  488.   if (tex3) tex3->setup_dyn_light (light, sq_dist);
  489. }
  490.  
  491. void Polygon3D::add_vertex (int v)
  492. {
  493.   vertices_idx[num_vertices] = v;
  494.   num_vertices++;
  495.   if (num_vertices > max_vertices)
  496.         dprintf ("OVERFLOW add_vertex!\n");
  497. }
  498.  
  499. enum InFlag { IN_P, IN_Q, IN_UNKNOWN };
  500.  
  501. void Polygon3D::PlaneNormal (float* yz, float* zx, float* xy)
  502. {
  503.   float ayz = 0;
  504.   float azx = 0;
  505.   float axy = 0;
  506.   int i, i1;
  507.   float x1, y1, z1, x, y, z;
  508.  
  509.   i1 = num_vertices-1;
  510.   for (i = 0 ; i < num_vertices ; i++)
  511.   {
  512.     x = vtex (i).get_x ();
  513.     y = vtex (i).get_y ();
  514.     z = vtex (i).get_z ();
  515.     x1 = vtex (i1).get_x ();
  516.     y1 = vtex (i1).get_y ();
  517.     z1 = vtex (i1).get_z ();
  518.     ayz += (z1+z) * (y-y1);
  519.     azx += (x1+x) * (z-z1);
  520.     axy += (y1+y) * (x-x1);
  521.     i1 = i;
  522.   }
  523.  
  524.   float d = sqrt (ayz*ayz + azx*azx + axy*axy);
  525.  
  526.   *yz = ayz / d;
  527.   *zx = azx / d;
  528.   *xy = axy / d;
  529. }
  530.  
  531. int Polygon3D::visible_from_point (Vector3& p)
  532. {
  533.   // Back-face culling.
  534.   float dot = A*(vtex (0).get_x ()-p.x) + B*(vtex (0).get_y ()-p.y) + C*(vtex (0).get_z ()-p.z);
  535.   return dot > 0;
  536. }
  537.  
  538. int Polygon3D::do_perspective (Matrix3& m_w2c, Matrix3& m_c2w, Vector3& v_w2c, Polygon2D* dest)
  539. {
  540.   int i, i1, cnt_vis;
  541.   float r;
  542.   int zs, z1s;
  543.  
  544.   // Count the number of visible vertices for this polygon (note
  545.   // that the transformation from world to camera space for all the
  546.   // vertices has been done earlier).
  547.   // If there are no visible vertices this polygon need not be drawn.
  548.   cnt_vis = 0;
  549.   for (i = 0 ; i < num_vertices ; i++)
  550.     if (vtex (i).get_tz () >= SMALL_Z) cnt_vis++;
  551.   if (cnt_vis == 0) return FALSE;
  552.  
  553.   // Perform backface culling.
  554.   // Note! The plane normal needs to be correctly calculated for this
  555.   // to work!
  556.   if (!visible_from_point (v_w2c)) return FALSE;
  557.  
  558.   dest->make_empty ();
  559.  
  560.   if (cnt_vis < num_vertices)
  561.   {
  562.     // Some vertices are visible and some are not, so we need to clip
  563.     // against z=SMALL_Z.
  564.     i1 = num_vertices-1;
  565.     Vector3 isect;
  566.     for (i = 0 ; i < num_vertices ; i++)
  567.     {
  568.       zs = vtex (i).get_tz () < SMALL_Z;
  569.       z1s = vtex (i1).get_tz () < SMALL_Z;
  570.  
  571.       if (z1s && !zs)
  572.       {
  573.         r = Segment::intersect_z_plane_3d (SMALL_Z, vtex (i1).get_tv (), vtex (i).get_tv (), isect);
  574.         dest->add_perspective (isect);
  575.         dest->add_perspective (vtex (i).get_tv ());
  576.       }
  577.       else if (!z1s && zs)
  578.       {
  579.         r = Segment::intersect_z_plane_3d (SMALL_Z, vtex (i1).get_tv (), vtex (i).get_tv (), isect);
  580.         dest->add_perspective (isect);
  581.       }
  582.       else if (!z1s && !zs)
  583.       {
  584.         dest->add_perspective (vtex (i).get_tv ());
  585.       }
  586.       i1 = i;
  587.     }
  588.   }
  589.   else
  590.   {
  591.     // All vertices are visible, just do perspective projection.
  592.     for (i = 0 ; i < num_vertices ; i++)
  593.       dest->add_perspective (vtex (i).get_tv ());
  594.   }
  595.  
  596.   // If polygon is still visible we also create the matrix to transform
  597.   // camera space to texture space.
  598.   plane->transform_world2cam (m_w2c, m_c2w, v_w2c);
  599.  
  600.   // We also transform the plane normal to camera space.
  601.   normal_world_to_camera (m_w2c, m_c2w, v_w2c);
  602.  
  603.   return TRUE;
  604. }
  605.  
  606. void Polygon3D::dump ()
  607. {
  608.   MSG (("Dump polygon '%s':\n", name));
  609.   MSG (("    num_vertices=%d  max_vertices=%d\n", num_vertices, max_vertices));
  610.   if (portal) MSG (("    Polygon is a portal to sector '%s'.\n", portal->get_name ()));
  611.   int i;
  612.   for (i = 0 ; i < num_vertices ; i++)
  613.     MSG (("        v[%d]: (%2.2f,%2.2f,%2.2f)  camera:(%2.2f,%2.2f,%2.2f)\n",
  614.         i,
  615.         vtex (i).get_x (),
  616.         vtex (i).get_y (),
  617.         vtex (i).get_z (),
  618.         vtex (i).get_tx (),
  619.         vtex (i).get_ty (),
  620.         vtex (i).get_tz ()));
  621.   fflush (stdout);
  622. }
  623.  
  624. int Polygon3D::intersect_segment (Vector3& start, Vector3& end, Vector3& isect)
  625. {
  626.   float x1 = start.x;
  627.   float y1 = start.y;
  628.   float z1 = start.z;
  629.   float x2 = end.x;
  630.   float y2 = end.y;
  631.   float z2 = end.z;
  632.   float r, num, denom;
  633.  
  634.   // @@@ Note! I think this algorithm can be done more efficiently.
  635.   // I have had no time yet to look at it closely.
  636.  
  637.   // First we do backface culling on the polygon with respect to
  638.   // the starting point of the beam.
  639.   if (!visible_from_point (start)) return FALSE;
  640.  
  641.   // So now we have the plane equation of the polygon:
  642.   // A*x + B*y + C*z + D = 0
  643.   //
  644.   // We also have the parameter line equations of the ray
  645.   // going through 'start' and 'end':
  646.   // x = r*(x2-x1)+x1
  647.   // y = r*(y2-y1)+y1
  648.   // z = r*(z2-z1)+z1
  649.   //
  650.   // =>   A*(r*(x2-x1)+x1) + B*(r*(y2-y1)+y1) + C*(r*(z2-z1)+z1) + D = 0
  651.  
  652.   denom = A*(x2-x1) + B*(y2-y1) + C*(z2-z1);
  653.   if (ABS (denom) < SMALL_EPSILON) return FALSE;        // Lines are parallel
  654.  
  655.   num = - (A*x1 + B*y1 + C*z1 + D);
  656.   r = num / denom;
  657.  
  658.   // If r is not in [0,1] the intersection point is not on the segment.
  659.   if (r < -SMALL_EPSILON || r > 1) return FALSE;
  660.  
  661.   isect.x = r*(x2-x1)+x1;
  662.   isect.y = r*(y2-y1)+y1;
  663.   isect.z = r*(z2-z1)+z1;
  664.  
  665.   // At this point we know that the segment intersects with the plane of the
  666.   // polygon. Now we check if the intersection point is in the polygon.
  667.   int rc = in_poly_3d (isect);
  668.   return rc != POLY_OUT;
  669. }
  670.  
  671. int Polygon3D::in_poly_3d (Vector3& vv)
  672. {
  673.   int i, j, dj;
  674.   Vector2 v2[200];
  675.   Vector2 v;
  676.   Box box;
  677.  
  678.   box.start_bounding_box ();
  679.  
  680.   // Using the plane normal of the polygon we determine the most
  681.   // distinguising two components (x, y, or z) that we are going to use
  682.   // to use a 2D test with.
  683.   // @@@ Note! I'm not very satisfied with this algorithm. I think it
  684.   // should be possible to do this completely in 3D, but I'm not such
  685.   // an expert on this. Maybe someone else can help?
  686.  
  687.   if (ABS (C) > ABS (A) && ABS (C) > ABS (B))
  688.   {
  689.     // Use x and y.
  690.     if (C < 0) { j = num_vertices-1; dj = -1; } // Make clockwise
  691.     else { j = 0 ; dj = 1; }
  692.     for (i = 0 ; i < num_vertices ; i++)
  693.     {
  694.       v2[i].x = vtex (j).get_x ();;
  695.       v2[i].y = vtex (j).get_y ();
  696.       box.add_bounding_vertex (v2[i].x, v2[i].y);
  697.       j += dj;
  698.     }
  699.     v.x = vv.x;
  700.     v.y = vv.y;
  701.   }
  702.   else if (ABS (A) > ABS (B) && ABS (A) > ABS (C))
  703.   {
  704.     // Use y and z.
  705.     if (A < 0) { j = num_vertices-1; dj = -1; } // Make clockwise
  706.     else { j = 0 ; dj = 1; }
  707.     for (i = 0 ; i < num_vertices ; i++)
  708.     {
  709.       v2[i].x = vtex (j).get_y ();
  710.       v2[i].y = vtex (j).get_z ();
  711.       box.add_bounding_vertex (v2[i].x, v2[i].y);
  712.       j += dj;
  713.     }
  714.     v.x = vv.y;
  715.     v.y = vv.z;
  716.   }
  717.   else
  718.   {
  719.     // Use x and z.
  720.     if (B > 0) { j = num_vertices-1; dj = -1; } // Make clockwise
  721.     else { j = 0 ; dj = 1; }
  722.     for (i = 0 ; i < num_vertices ; i++)
  723.     {
  724.       v2[i].x = vtex (j).get_x ();
  725.       v2[i].y = vtex (j).get_z ();
  726.       box.add_bounding_vertex (v2[i].x, v2[i].y);
  727.       j += dj;
  728.     }
  729.     v.x = vv.x;
  730.     v.y = vv.z;
  731.   }
  732.  
  733.   return v.in_poly_2d (v2, num_vertices, &box);
  734. }
  735.  
  736. void Polygon3D::save (FILE* fp, int indent, Textures* textures)
  737. {
  738.   char sp[100]; strcpy (sp, spaces); sp[indent] = 0;
  739.   fprintf (fp, "%sPOLYGON '%s' (\n", sp, name);
  740.   fprintf (fp, "%s  MAX_VERTICES=%d\n", sp, max_vertices);
  741.   fprintf (fp, "%s  TEXNR='%s'\n", sp, textures->get_texture (tex->texnr)->get_name ());
  742.   if (portal) fprintf (fp, "%s  PORTAL='%s'\n", sp, portal->get_name ());
  743.  
  744.   if (no_mipmap) fprintf (fp, "%s  MIPMAP=no\n", sp);
  745.   if (no_lighting) fprintf (fp, "%s  LIGHTING=no\n", sp);
  746.  
  747.   if (!delete_plane && plane->get_name ()[0] != '-')
  748.   {
  749.     fprintf (fp, "%s  TEXTURE=(PLANE '%s')\n", sp, plane->get_name ());
  750.   }
  751.   else
  752.   {
  753.     fprintf (fp, "%s  TEXTURE=(\n", sp);
  754.     plane->m_world2tex.save (fp, indent+4);
  755.     plane->v_world2tex.save (fp, indent+4);
  756.     fprintf (fp, "%s  )\n", sp);
  757.   }
  758.  
  759.   if (do_warp_space)
  760.   {
  761.     fprintf (fp, "%s  WARP=(\n", sp);
  762.     m_warp.save (fp, indent+4);
  763.     v_warp.save (fp, indent+4);
  764.     fprintf (fp, "%s  )\n", sp);
  765.   }
  766.  
  767.   int i;
  768.   if (num_vertices)
  769.   {
  770.     fprintf (fp, "%s  VERTICES=[%d", sp, vertices_idx[0]);
  771.     for (i = 1 ; i < num_vertices ; i++)
  772.       fprintf (fp, ",%d", vertices_idx[i]);
  773.     fprintf (fp, "]\n");
  774.   }
  775.   fprintf (fp, "%s)\n", sp);
  776. }
  777.  
  778. void Polygon3D::load (World* w, char** buf, Textures* textures, int default_texnr,
  779.                       float default_texlen)
  780. {
  781.   char* t;
  782.   int i;
  783.   char* old_buf;
  784.  
  785.   skip_token (buf, "POLYGON");
  786.   t = get_token (buf);
  787.   strcpy (name, t);
  788.   skip_token (buf, "(", "Expected '%s' instead of '%s' after the name of a POLYGON!\n");
  789.  
  790.   int texnr;
  791.   if (default_texnr == -1) texnr = 0;
  792.   else
  793.   {
  794.     texnr = default_texnr;
  795.     set_texnr (textures, texnr);
  796.   }
  797.  
  798.   portal = NULL; // Default
  799.  
  800.   int tx1_given = FALSE, tx2_given = FALSE;
  801.   Vector3 tx1_orig, tx1, tx2;
  802.   float tx1_len = default_texlen, tx2_len = default_texlen;
  803.   float tx_len = default_texlen;
  804.   Matrix3 tx_matrix;
  805.   Vector3 tx_vector;
  806.   char plane_name[30];
  807.   plane_name[0] = 0;
  808.  
  809.   do_warp_space = FALSE;
  810.   no_lighting = FALSE;
  811.   no_mipmap = FALSE;
  812.  
  813.   while (TRUE)
  814.   {
  815.     t = get_token (buf);
  816.     if (*t == ')' || *t == 0) break;
  817.     if (!strcmp (t, "MAX_VERTICES"))
  818.     {
  819.       skip_token (buf, "=", "Expected '%s' instead of '%s' after MAX_VERTICES!\n");
  820.       max_vertices = get_token_int (buf);
  821.       if (vertices_idx) delete [] vertices_idx;
  822.       vertices_idx = new int [max_vertices];
  823.     }
  824.     else if (!strcmp (t, "TEXNR"))
  825.     {
  826.       skip_token (buf, "=", "Expected '%s' instead of '%s' after TEXNR!\n");
  827.       t = get_token (buf);
  828.       texnr = textures->get_texture_idx (t);
  829.       if (texnr == -1)
  830.       {
  831.         printf ("Couldn't find texture named '%s'!\n", t);
  832.       }
  833.       set_texnr (textures, texnr);
  834.     }
  835.     else if (!strcmp (t, "LIGHTING"))
  836.     {
  837.       skip_token (buf, "=", "Expected '%s' instead of '%s' after LIGHTING!\n");
  838.       t = get_token (buf);
  839.       no_lighting = !!strcmp (t, "yes");
  840.     }
  841.     else if (!strcmp (t, "MIPMAP"))
  842.     {
  843.       skip_token (buf, "=", "Expected '%s' instead of '%s' after MIPMAP!\n");
  844.       t = get_token (buf);
  845.       no_mipmap = !!strcmp (t, "yes");
  846.     }
  847.     else if (!strcmp (t, "PORTAL"))
  848.     {
  849.       skip_token (buf, "=", "Expected '%s' instead of '%s' after PORTAL!\n");
  850.       t = get_token (buf);
  851.       portal = w->get_sector (t);
  852.       if (!portal)
  853.         portal = w->new_sector (t, 10, 10);  // This will later be defined correctly
  854.     }
  855.     else if (!strcmp (t, "WARP"))
  856.     {
  857.       do_warp_space = TRUE;
  858.       skip_token (buf, "=", "Expected '%s' instead of '%s' after TEXTURE!\n");
  859.       skip_token (buf, "(", "Expected '%s' instead of '%s' to open TEXTURE statement!\n");
  860.       while (TRUE)
  861.       {
  862.         old_buf = *buf;
  863.         t = get_token (buf);
  864.         if (*t == ')' || *t == 0) break;
  865.         else if (!strcmp (t, "MATRIX"))
  866.         {
  867.           *buf = old_buf;
  868.           m_warp.load (buf);
  869.           m_warp_inv = m_warp;
  870.           m_warp_inv.inverse ();
  871.         }
  872.         else if (!strcmp (t, "("))
  873.         {
  874.           *buf = old_buf;
  875.           v_warp.load (buf);
  876.         }
  877.         else
  878.         {
  879.           printf ("What is '%s' doing in a POLYGON/WARP statement?\n", t);
  880.         }
  881.       }
  882.     }
  883.     else if (!strcmp (t, "TEXTURE"))
  884.     {
  885.       skip_token (buf, "=", "Expected '%s' instead of '%s' after TEXTURE!\n");
  886.       skip_token (buf, "(", "Expected '%s' instead of '%s' to open TEXTURE statement!\n");
  887.       while (TRUE)
  888.       {
  889.         old_buf = *buf;
  890.         t = get_token (buf);
  891.         if (*t == ')' || *t == 0) break;
  892.         if (!strcmp (t, "ORIG"))
  893.         {
  894.           skip_token (buf, "=", "Expected '%s' instead of '%s' after POLYGON/ORIG!\n");
  895.           tx1_given = TRUE;
  896.           tx1_orig.load (buf);
  897.         }
  898.         else if (!strcmp (t, "FIRST"))
  899.         {
  900.           skip_token (buf, "=", "Expected '%s' instead of '%s' after POLYGON/FIRST!\n");
  901.           tx1_given = TRUE;
  902.           tx1.load (buf);
  903.         }
  904.         else if (!strcmp (t, "FIRST_LEN"))
  905.         {
  906.           skip_token (buf, "=", "Expected '%s' instead of '%s' after POLYGON/FIRST_LEN!\n");
  907.           tx1_len = get_token_float (buf);
  908.           tx1_given = TRUE;
  909.         }
  910.         else if (!strcmp (t, "SECOND"))
  911.         {
  912.           skip_token (buf, "=", "Expected '%s' instead of '%s' after POLYGON/SECOND!\n");
  913.           tx2_given = TRUE;
  914.           tx2.load (buf);
  915.         }
  916.         else if (!strcmp (t, "SECOND_LEN"))
  917.         {
  918.           skip_token (buf, "=", "Expected '%s' instead of '%s' after POLYGON/SECOND_LEN!\n");
  919.           tx2_len = get_token_float (buf);
  920.           tx2_given = TRUE;
  921.         }
  922.         else if (!strcmp (t, "LEN"))
  923.         {
  924.           skip_token (buf, "=", "Expected '%s' instead of '%s' after POLYGON/LEN!\n");
  925.           tx_len = get_token_float (buf);
  926.         }
  927.         else if (!strcmp (t, "MATRIX"))
  928.         {
  929.           *buf = old_buf;
  930.           tx_matrix.load (buf);
  931.           tx_len = 0;
  932.         }
  933.         else if (!strcmp (t, "("))
  934.         {
  935.           *buf = old_buf;
  936.           tx_vector.load (buf);
  937.           tx_len = 0;
  938.         }
  939.         else if (!strcmp (t, "PLANE"))
  940.         {
  941.           t = get_token (buf);
  942.           strcpy (plane_name, t);
  943.           tx_len = 0;
  944.         }
  945.         else
  946.         {
  947.           printf ("What is '%s' doing in a POLYGON/TEXTURE statement?\n", t);
  948.         }
  949.       }
  950.     }
  951.     else if (!strcmp (t, "VERTICES"))
  952.     {
  953.       skip_token (buf, "=", "Expected '%s' instead of '%s' after VERTICES!\n");
  954.       t = get_token (buf);
  955.       while (*t && *t != ']')
  956.       {
  957.         if (*t != '[' && *t != ',')
  958.         {
  959.           printf ("Expected '[' or ',' instead of '%s' in vertex list!\n", t);
  960.         }
  961.         i = get_token_int (buf);
  962.         add_vertex (i);
  963.         t = get_token (buf);
  964.       }
  965.     }
  966.     else
  967.     {
  968.       printf ("What is '%s' doing in a POLYGON statement?\n", t);
  969.     }
  970.   }
  971.  
  972.   if (tx1_given)
  973.     if (tx2_given) set_texture_space (tx1_orig.x, tx1_orig.y, tx1_orig.z,
  974.                                       tx1.x, tx1.y, tx1.z, tx1_len,
  975.                                       tx2.x, tx2.y, tx2.z, tx2_len);
  976.     else set_texture_space (tx1_orig.x, tx1_orig.y, tx1_orig.z,
  977.                             tx1.x, tx1.y, tx1.z, tx1_len);
  978.   else if (plane_name[0]) set_texture_space (w->get_plane (plane_name));
  979.   else if (tx_len)
  980.   {
  981.     // If a length is given (with 'LEN') we will take the first two vertices
  982.     // and calculate the texture orientation from them (with the given
  983.     // length).
  984.     set_texture_space (poly_set->vtex (vertices_idx[0]),
  985.                        poly_set->vtex (vertices_idx[1]), tx_len);
  986.   }
  987.   else set_texture_space (tx_matrix, tx_vector);
  988. }
  989.  
  990. //---------------------------------------------------------------------------
  991.  
  992. Polygon2D Polygon2D::clipped (MAX_VERTICES);
  993.  
  994. Polygon2D::Polygon2D (int max)
  995. {
  996.   max_vertices = max;
  997.   vertices = new Vector2 [max];
  998.   make_empty ();
  999. }
  1000.  
  1001. Polygon2D::Polygon2D (Polygon2D& copy)
  1002. {
  1003.   max_vertices = copy.max_vertices;
  1004.   vertices = new Vector2 [max_vertices];
  1005.   num_vertices = copy.num_vertices;
  1006.   CopyMemPPC (copy.vertices, vertices,sizeof (Vector2)*num_vertices);
  1007.   bbox = copy.bbox;
  1008. }
  1009.  
  1010. Polygon2D::~Polygon2D ()
  1011. {
  1012.   if (vertices) delete [] vertices;
  1013. }
  1014.  
  1015. void Polygon2D::make_empty ()
  1016. {
  1017.   num_vertices = 0;
  1018.   bbox.start_bounding_box ();
  1019. }
  1020.  
  1021. void Polygon2D::add_vertex (float x, float y)
  1022. {
  1023.   vertices[num_vertices].x = x;
  1024.   vertices[num_vertices].y = y;
  1025.   num_vertices++;
  1026.   bbox.add_bounding_vertex (x, y);
  1027.   if (num_vertices > max_vertices) dprintf ("OVERFLOW add_vertex!\n");
  1028. }
  1029.  
  1030. void Polygon2D::add_perspective (float x, float y, float z)
  1031. {
  1032.   float iz = ASPECT/z;
  1033.   float px, py;
  1034.  
  1035.   if (num_vertices >= max_vertices) dprintf ("OVERFLOW add_perspective!\n");
  1036.  
  1037.   px = x * iz + (FRAME_WIDTH/2);
  1038.   py = y * iz + (FRAME_HEIGHT/2);
  1039.   vertices[num_vertices].x = px;
  1040.   vertices[num_vertices].y = py;
  1041.  
  1042.   num_vertices++;
  1043.   bbox.add_bounding_vertex (px, py);
  1044. }
  1045.  
  1046. #if USE_OCCLUSION
  1047. int Polygon2D::clip_to_occlusion (Occlusion* o)
  1048. {
  1049.   if (o->hull_is_empty ()) return TRUE;
  1050.  
  1051.   int i, in;
  1052.   for (i = 0 ; i < num_vertices ; i++)
  1053.   {
  1054.     in = o->point_in_hull (vertices[i]);
  1055.     if (in == POLY_OUT) return TRUE;
  1056.   }
  1057.   return FALSE;
  1058. }
  1059. #endif
  1060.  
  1061. // This is a variant of clip_poly that I use because I can't seem to get
  1062. // that version working in all cases. clip_poly will probably be faster
  1063. // than this version, but this version always works (I think).
  1064. int Polygon2D::clip_poly_variant (Vector2* Q, int m, Box* box)
  1065. {
  1066.   if (!overlap_bounding_box (box)) return FALSE;
  1067.  
  1068.   int i, i1;
  1069.  
  1070.   i1 = m-1;
  1071.   for (i = 0 ; i < m ; i++)
  1072.   {
  1073.     clip_poly_plane (Q[i1], Q[i]);
  1074.     if (num_vertices < 3) return FALSE;
  1075.     i1 = i;
  1076.   }
  1077.  
  1078.   return TRUE;
  1079. }
  1080.  
  1081. // Clip a polygon against a plane.
  1082. void Polygon2D::clip_poly_plane (Vector2& v1, Vector2& v2)
  1083. {
  1084.   Vector2 nclip[100];
  1085.   int num_nclip = 0;
  1086.   int i, i1;
  1087.   float r;
  1088.   Vector2 isect;
  1089.   int side, side1;
  1090.   int isect_happened = 0;
  1091.  
  1092.   bbox.start_bounding_box ();
  1093.  
  1094.   i1 = num_vertices-1;
  1095.   side1 = vertices[i1].which_side_2d (v1, v2);
  1096.  
  1097.   for (i = 0 ; i < num_vertices ; i++)
  1098.   {
  1099.     side = vertices[i].which_side_2d (v1, v2);
  1100.  
  1101.     if ((side1 < 0 && side > 0) || (side1 > 0 && side < 0))
  1102.       if (!Segment::intersect_segment_line (vertices[i1], vertices[i], v1, v2, isect, &r))
  1103.       {
  1104. #       if 0
  1105.         MSG (("Strange! there should be an intersection!\n"));
  1106.         MSG (("    segment: (%2.2f,%2.2f)-(%2.2f,%2.2f) with\n",
  1107.               vertices[i1].x, vertices[i1].y, vertices[i].x, vertices[i].y));
  1108.         MSG (("    line:    (%2.2f,%2.2f)-(%2.2f,%2.2f)\n",
  1109.               v1.x, v1.y, v2.x, v2.y));
  1110. #       endif
  1111.       }
  1112.       else
  1113.       {
  1114.         isect_happened++;
  1115.         nclip[num_nclip] = isect;
  1116.         num_nclip++;
  1117.         bbox.add_bounding_vertex (isect);
  1118.       }
  1119.  
  1120.     if (side >= 0)
  1121.     {
  1122.       nclip[num_nclip] = vertices[i];
  1123.       num_nclip++;
  1124.       bbox.add_bounding_vertex (vertices[i]);
  1125.     }
  1126.  
  1127.     i1 = i;
  1128.     side1 = side;
  1129.   }
  1130.  
  1131.   if (isect_happened || num_nclip != num_vertices)
  1132.   {
  1133.     for (i = 0 ; i < num_nclip ; i++) vertices[i] = nclip[i];
  1134.     num_vertices = num_nclip;
  1135.   }
  1136. }
  1137.  
  1138. int Polygon2D::clip_poly (Vector2* Q, int m, Box* box, Polygon2D* dest)
  1139. {
  1140.   dest->make_empty ();
  1141.   if (!overlap_bounding_box (box)) return FALSE;
  1142.  
  1143.   // This polygon is P; Q is the view_poly
  1144.   int a, b;             // Indices on P and Q
  1145.   int a1, b1;           // a-1, b-1
  1146.   Vector2* va, * vb;    // Pointer to respective vertices
  1147.   Vector2* va1, * vb1;
  1148.   Vector2 A, B;         // Directed edges on P and Q
  1149.   float cross;          // A x B
  1150.   int bHA, aHB;         // b in H(A), a in H(b)
  1151.   Vector2 p;            // Point of intersection
  1152.   InFlag inflag;        // Which polygon is known to be inside
  1153.   int i;
  1154.   int aa, ba;           // # advances on a & b indices (from 1st intersection)
  1155.   int reset = FALSE;    // Have the advance counters ever been reset?
  1156.   int n;                // # vertices of P (resp.)
  1157.   float r;
  1158.  
  1159.   a = 0; b = 0; aa = 0; ba = 0;
  1160.   i = 0;
  1161.   inflag = IN_UNKNOWN;
  1162.   n = num_vertices;
  1163.  
  1164.   do
  1165.   {
  1166.     // Computations of key variables.
  1167.     a1 = (a+n-1) % n;
  1168.     b1 = (b+m-1) % m;
  1169.     va = &vertices[a];
  1170.     va1 = &vertices[a1];
  1171.     vb = &Q[b];
  1172.     vb1 = &Q[b1];
  1173.  
  1174.     A.x = va->x - va1->x;
  1175.     A.y = va->y - va1->y;
  1176.     B.x = vb->x - vb1->x;
  1177.     B.y = vb->y - vb1->y;
  1178.  
  1179.     // Compute twice the signed area of the triangle determined by
  1180.     // 0 (origin), A and B. Positive if 0, A and B are oriented ccw,
  1181.     // and negative if cw.
  1182.     // cross = Vector2::Area2 (0, 0, A.x, A.y, B.x, B.y);
  1183.     cross = A.x * B.y - B.x * A.y;
  1184.     if (ABS (cross) < SMALL_EPSILON) cross = 0;
  1185.  
  1186.     // bHA is TRUE if vb is strictly to the right of va1-va.
  1187.     bHA = Vector2::Right (va1->x, va1->y, va->x, va->y, vb->x, vb->y);
  1188.  
  1189.     // aHB is TRUE if va is strictly to the right of vb1-vb.
  1190.     aHB = Vector2::Right (vb1->x, vb1->y, vb->x, vb->y, va->x, va->y);
  1191.  
  1192.     // If A & B intersect, update inflag.
  1193.     if (Segment::intersect_segments (*va1, *va, *vb1, *vb, p, &r))
  1194.     {
  1195.       if (inflag == IN_UNKNOWN && !reset)
  1196.       {
  1197.         aa = ba = 0;
  1198.         reset = TRUE;
  1199.       }
  1200.       dest->add_vertex (p);
  1201.       if (aHB) inflag = IN_P;
  1202.       else if (bHA) inflag = IN_Q;
  1203.     }
  1204.  
  1205.     // Advance rules.
  1206.     if (ABS (cross) < SMALL_EPSILON && !bHA && !aHB)
  1207.     {
  1208.       if (inflag == IN_P)
  1209.       {
  1210.         b = (b+1) % m;
  1211.         ba++;
  1212.         //b = Advance (verbose, b, &ba, m, inflag == IN_Q, vb->x, vb->y);
  1213.       }
  1214.       else
  1215.       {
  1216.         a = (a+1) % n;
  1217.         aa++;
  1218.         //a = Advance (verbose, a, &aa, n, inflag == IN_P, va->x, va->y);
  1219.       }
  1220.     }
  1221.     else if (cross <= 0)
  1222.     {
  1223.       if (bHA)
  1224.       {
  1225.         if (inflag == IN_P)
  1226.         {
  1227.           if (va->in_poly_2d (Q, m, box) == POLY_OUT) inflag = IN_Q;
  1228.           else dest->add_vertex (*va);
  1229.         }
  1230.  
  1231.         a = (a+1) % n;
  1232.         aa++;
  1233.  
  1234.         //a = Advance (verbose, a, &aa, n, inflag == IN_P, va->x, va->y);
  1235.       }
  1236.       else
  1237.       {
  1238.         if (inflag == IN_Q) dest->add_vertex (*vb);
  1239.  
  1240.         b = (b+1) % m;
  1241.         ba++;
  1242.  
  1243.         //b = Advance (verbose, b, &ba, m, inflag == IN_Q, vb->x, vb->y);
  1244.       }
  1245.     }
  1246.     else
  1247.     {
  1248.       if (aHB)
  1249.       {
  1250.         if (inflag == IN_Q) dest->add_vertex (*vb);
  1251.  
  1252.         b = (b+1) % m;
  1253.         ba++;
  1254.  
  1255.         //b = Advance (verbose, b, &ba, m, inflag == IN_Q, vb->x, vb->y);
  1256.       }
  1257.       else
  1258.       {
  1259.         if (inflag == IN_P)
  1260.         {
  1261.           if (va->in_poly_2d (Q, m, box) == POLY_OUT) inflag = IN_Q;
  1262.           else dest->add_vertex (*va);
  1263.         }
  1264.  
  1265.         a = (a+1) % n;
  1266.         aa++;
  1267.  
  1268.         //a = Advance (verbose, a, &aa, n, inflag == IN_P, va->x, va->y);
  1269.       }
  1270.     }
  1271.   }
  1272.   // Quit when both adv. indices have cycled, or one has cycled twice. 
  1273.   while ( ((aa < n) || (ba < m)) && (aa < n+n) && (ba < m+m) );
  1274.  
  1275.   // Deal with special cases.
  1276.   if (inflag == IN_UNKNOWN) 
  1277.   {
  1278.     // The boundaries of P and Q do not cross.
  1279.     if (vertices[0].in_poly_2d (Q, m, box) != POLY_OUT)
  1280.     {
  1281.       // P is in Q. This poly need not be clipped.
  1282.       for (i = 0 ; i < num_vertices ; i++) dest->add_vertex (vertices[i]);
  1283.     }
  1284.     else
  1285.     {
  1286.       if (Q[0].in_poly_2d (vertices, n, &bbox) != POLY_OUT)
  1287.       {
  1288.         // Q is in P.
  1289.         for (i = 0 ; i < m ; i++) dest->add_vertex (Q[i]);
  1290.       }
  1291.       else
  1292.         // P and Q are independent.
  1293.         return FALSE;
  1294.     }
  1295.   }
  1296.  
  1297.   return TRUE;
  1298. }
  1299.  
  1300. ViewPolygon* Polygon2D::create_view ()
  1301. {
  1302.   if (!num_vertices) return NULL;
  1303.  
  1304.   ViewPolygon* view = new ViewPolygon (20);
  1305.   int i;
  1306.  
  1307.   for (i = 0 ; i < num_vertices ; i++)
  1308.     view->add_vertex (vertices[i]);
  1309.  
  1310.   return view;
  1311. }
  1312.  
  1313. void Polygon2D::draw (int col)
  1314. {
  1315.   int i;
  1316.   int x1, y1, x2, y2;
  1317.  
  1318.   if (!num_vertices) return;
  1319.  
  1320.   x1 = QRound (vertices[num_vertices-1].x);
  1321.   y1 = QRound (vertices[num_vertices-1].y);
  1322.   for (i = 0 ; i < num_vertices ; i++)
  1323.   {
  1324.     x2 = QRound (vertices[i].x);
  1325.     y2 = QRound (vertices[i].y);
  1326.     Scan::g->SetLine (x1, y1, x2, y2, col);
  1327.  
  1328.     x1 = x2;
  1329.     y1 = y2;
  1330.   }
  1331. }
  1332.  
  1333. void Polygon2D::draw_filled (Polygon3D* poly, int use_z_buf)
  1334. {
  1335.   int i;
  1336.   float sy1, sy2;
  1337.   int yy1, yy2;
  1338.   float sy;
  1339.   float P1, P2, P3, P4;
  1340.   float Q1, Q2, Q3, Q4;
  1341.   unsigned char* d;
  1342.   int yy, xxL;
  1343.   int max_i, min_i;
  1344.   float max_y, min_y;
  1345.   float min_z;
  1346.   unsigned long* z_buf;
  1347.   float inv_z, u_div_z, v_div_z;
  1348.   void (*dscan) (int len, unsigned char* d, unsigned long* z_buf,
  1349.                 float inv_z, float u_div_z, float v_div_z,
  1350.                 float dM, float dJ1, float dK1);
  1351.  
  1352.   if (num_vertices < 3) return;
  1353.  
  1354.   // Get the plane normal of the polygon. Using this we can calculate
  1355.   // '1/z' at every screen space point.
  1356.   float Ac, Bc, Cc, Dc, inv_Dc;
  1357.   poly->get_camera_normal (&Ac, &Bc, &Cc, &Dc);
  1358.   inv_Dc = 1/Dc;
  1359.   float M = -Ac*inv_Dc*(1./ASPECT);
  1360.   float N = -Bc*inv_Dc*(1./ASPECT);
  1361.   float O = -Cc*inv_Dc;
  1362.  
  1363.   // Compute the min_y and max_y for this polygon in screen space coordinates.
  1364.   // We are going to use these to scan the polygon from top to bottom.
  1365.   // Also compute the min_z in camera space coordinates. This is going to be
  1366.   // used for mipmapping.
  1367.   min_i = max_i = 0;
  1368.   min_y = max_y = vertices[0].y;
  1369.   min_z = M*(vertices[0].x-FRAME_WIDTH/2) + N*(vertices[0].y-FRAME_HEIGHT/2) + O;
  1370.   for (i = 1 ; i < num_vertices ; i++)
  1371.   {
  1372.     if (vertices[i].y > max_y)
  1373.     {
  1374.       max_y = vertices[i].y;
  1375.       max_i = i;
  1376.     }
  1377.     else if (vertices[i].y < min_y)
  1378.     {
  1379.       min_y = vertices[i].y;
  1380.       min_i = i;
  1381.     }
  1382.     inv_z = M*(vertices[i].x-FRAME_WIDTH/2) + N*(vertices[i].y-FRAME_HEIGHT/2) + O;
  1383.     if (inv_z > min_z) min_z = inv_z;
  1384.   }
  1385.  
  1386.   // Mipmapping.
  1387.   PolyTexture* tex;
  1388.   if (poly->get_no_mipmap () || Scan::textures->mipmapped == 0) tex = poly->get_polytex (0);
  1389.   else if (Scan::textures->mipmapped == 1) tex = poly->get_polytex ((float)1./min_z); // @@@ Don't use 1/z
  1390.   else tex = poly->get_polytex (3);
  1391.   PolyPlane* pl = poly->get_plane ();
  1392.   cache.use_texture (tex, Scan::textures);
  1393.   Scan::init_draw (poly, tex);
  1394.  
  1395.   // @@@ The texture transform matrix is currently written as T = M*(C-V)
  1396.   // (with V being the transform vector, M the transform matrix, and C
  1397.   // the position in camera space coordinates. It would be better (more
  1398.   // suitable for the following calculations) if it would be written
  1399.   // as T = M*C - V.
  1400.   P1 = pl->m_cam2tex.m11;
  1401.   P2 = pl->m_cam2tex.m12;
  1402.   P3 = pl->m_cam2tex.m13;
  1403.   P4 = -(P1*pl->v_cam2tex.x + P2*pl->v_cam2tex.y + P3*pl->v_cam2tex.z);
  1404.   Q1 = pl->m_cam2tex.m21;
  1405.   Q2 = pl->m_cam2tex.m22;
  1406.   Q3 = pl->m_cam2tex.m23;
  1407.   Q4 = -(Q1*pl->v_cam2tex.x + Q2*pl->v_cam2tex.y + Q3*pl->v_cam2tex.z);
  1408.  
  1409.   if (Scan::tmap2)
  1410.   {
  1411.     P1 *= Scan::tw; P2 *= Scan::tw; P3 *= Scan::tw; P4 *= Scan::tw;
  1412.     Q1 *= Scan::th; Q2 *= Scan::th; Q3 *= Scan::th; Q4 *= Scan::th;
  1413.     P4 -= Scan::fdu; Q4 -= Scan::fdv;
  1414.   }
  1415.  
  1416.   // Precompute everything so that we can calculate (u,v) (texture space
  1417.   // coordinates) for every (sx,sy) (screen space coordinates). We make
  1418.   // use of the fact that 1/z, u/z and v/z are linear in screen space.
  1419.   float R1 = P1*(1./ASPECT);
  1420.   float R2 = P2*(1./ASPECT);
  1421.   float S1 = Q1*(1./ASPECT);
  1422.   float S2 = Q2*(1./ASPECT);
  1423.  
  1424.   float J1 = R1+P4*M;
  1425.   float J2 = R2+P4*N;
  1426.   float J3 = P3+P4*O;
  1427.   float K1 = S1+Q4*M;
  1428.   float K2 = S2+Q4*N;
  1429.   float K3 = Q3+Q4*O;
  1430.  
  1431.   // Steps for interpolating horizontally accross a scanline.
  1432.   float dM = M*INTERPOL_STEP;
  1433.   float dJ1 = J1*INTERPOL_STEP;
  1434.   float dK1 = K1*INTERPOL_STEP;
  1435.  
  1436.   // Select the right scanline drawing function.
  1437.   if (Scan::textures->textured)
  1438.   {
  1439.     if (use_z_buf)
  1440.     {
  1441.       if (Scan::tmap2) dscan = Scan::draw_scanline_z_buf_map;
  1442.       else dscan = Scan::draw_scanline_z_buf;
  1443.     }
  1444.     else if (Scan::texture->get_filtered ()) dscan = Scan::draw_scanline_filtered;
  1445.     else if (Scan::texture->get_transparent () != -1) dscan = Scan::draw_scanline_transp;
  1446.     else if (Scan::tmap2) dscan = Scan::draw_scanline_map;
  1447.     else dscan = Scan::draw_scanline;
  1448.   }
  1449.   else
  1450.   {
  1451.     if (use_z_buf) dscan = Scan::draw_scanline_z_buf_flat;
  1452.     else dscan = Scan::draw_scanline_flat;
  1453.   }
  1454.  
  1455.   // Scan both sides of the polygon at once.
  1456.   // We start with two pointers at the top (as seen in y-inverted
  1457.   // screen-space: bottom of display) and advance them until both
  1458.   // join together at the bottom. The way this algorithm works, this
  1459.   // should happen automatically; the left pointer is only advanced
  1460.   // when it is farther away from the bottom than the right pointer
  1461.   // and vice versa.
  1462.   // Using this we effectively partition our polygon in trapezoids
  1463.   // with at most two triangles (one at the top and one at the bottom).
  1464. # define BOTH 0
  1465. # define LEFT 1
  1466. # define RIGHT 2
  1467.   int iL, iR, advance;
  1468.   float dd;
  1469.   float syL, sx1L, sx2L, dL, sxL;
  1470.   int yyL;
  1471.   float syR, sx1R, sx2R, dR, sxR;
  1472.   int yyR;
  1473.  
  1474.   sy1 = vertices[max_i].y;
  1475.   yy1 = QRound (sy1);
  1476.   sx1L = sx1R = vertices[max_i].x;
  1477.  
  1478.   iL = (max_i-1+num_vertices)%num_vertices;
  1479.   iR = (max_i+1)%num_vertices;
  1480.  
  1481.   syL = vertices[iL].y;
  1482.   yyL = QRound (syL);
  1483.  
  1484.   syR = vertices[iR].y;
  1485.   yyR = QRound (syR);
  1486.  
  1487.   for (;;)
  1488.   {
  1489.     if (yyL == yyR)
  1490.     {
  1491.       sy2 = syL;
  1492.       yy2 = yyL;
  1493.       sx2L = vertices[iL].x;
  1494.       sx2R = vertices[iR].x;
  1495.  
  1496.       advance = BOTH;
  1497.     }
  1498.     else if (yyL < yyR)
  1499.     {
  1500.       sy2 = syR;
  1501.       yy2 = yyR;
  1502.       sx2R = vertices[iR].x;
  1503.       if (ABS (syL-sy1) < EPSILON)
  1504.         sx2L = sx1L;
  1505.       else
  1506.         sx2L = (vertices[iL].x-sx1L) * (sy2-sy1) / (syL-sy1) + sx1L;
  1507.  
  1508.       advance = RIGHT;
  1509.     }
  1510.     else
  1511.     {
  1512.       sy2 = syL;
  1513.       yy2 = yyL;
  1514.       sx2L = vertices[iL].x;
  1515.       if (ABS (syR-sy1) < EPSILON)
  1516.         sx2R = sx1R;
  1517.       else
  1518.         sx2R = (vertices[iR].x-sx1R) * (sy2-sy1) / (syR-sy1) + sx1R;
  1519.  
  1520.       advance = LEFT;
  1521.     }
  1522.  
  1523.     // We are now drawing a trapezoid defined by:
  1524.     //   - floating point perspective corrected screen coordinates (screen space):
  1525.     //         (sx1L,sy1) - (sx1R,sy1)
  1526.     //              |            |
  1527.     //         (sx2L,sy2) - (sx2R,sy2)
  1528.  
  1529.     if (ABS (sy1-sy2) < 1.0)
  1530.     {
  1531.       // The trapezoid is not very high. This is a seperate case to
  1532.       // eliminate overflow errors in this case.
  1533.       sy = (float)(yy1-FRAME_HEIGHT/2);
  1534.       xxL = QRound (sx1L);
  1535.       sxL = (float)(xxL-FRAME_WIDTH/2);
  1536.  
  1537.       // d = graphicsData+FRAME_WIDTH*(FRAME_HEIGHT-yy1)+xxL;
  1538.       d = PixelAt (xxL, FRAME_HEIGHT-yy1);
  1539.       z_buf = Scan::z_buffer+FRAME_WIDTH*(FRAME_HEIGHT-yy1)+xxL;
  1540.  
  1541.       inv_z = M*sxL + N*sy + O;
  1542.       u_div_z = J1*sxL + J2*sy + J3;
  1543.       v_div_z = K1*sxL + K2*sy + K3;
  1544.  
  1545.       dscan (QRound (sx1R-sx1L)+1, d, z_buf, inv_z, u_div_z, v_div_z, dM, dJ1, dK1);
  1546.     }
  1547.     else
  1548.     {
  1549.       dd = 1 / (sy2-sy1);
  1550.  
  1551.       // Instead of using sy1-FRAME_HEIGHT/2 which would give a more
  1552.       // 'accurate' result, we use yy1 which is the rounded version.
  1553.       // This way we vastly increase the precision of the texture mapper.
  1554.       // The result of this is that the textures are now rock-steady
  1555.       // while moving; even in low-resolution.
  1556.       // Something similar is done for sxL and sxR.
  1557.       sxL = (float)QRound (sx1L-FRAME_WIDTH/2);
  1558.       sxR = (float)QRound (sx1R-FRAME_WIDTH/2);
  1559.       sy = (float)(yy1-FRAME_HEIGHT/2);
  1560.       dL = (sx2L-sx1L)*dd;
  1561.       dR = (sx2R-sx1R)*dd;
  1562.  
  1563.       // Steps for interpolating vertically over scanlines.
  1564.       float vd_inv_z = dL*M+N;
  1565.       float vd_u_div_z = dL*J1+J2;
  1566.       float vd_v_div_z = dL*K1+K2;
  1567.  
  1568.       inv_z = M*sxL + N*sy + O;
  1569.       u_div_z = J1*sxL + J2*sy + J3;
  1570.       v_div_z = K1*sxL + K2*sy + K3;
  1571.  
  1572.       // @@@ There are still things that can be moved outside the loop.
  1573.       // But beware of problems with converting from float to int and rounding!
  1574.  
  1575.       for (yy = yy1 ; yy > yy2 ; yy--)
  1576.       {
  1577.         xxL = QRound (sxL+FRAME_WIDTH/2);
  1578.  
  1579.         //d = graphicsData+FRAME_WIDTH*(FRAME_HEIGHT-yy)+xxL;
  1580.         d = PixelAt (xxL, FRAME_HEIGHT-yy);
  1581.         z_buf = Scan::z_buffer+FRAME_WIDTH*(FRAME_HEIGHT-yy)+xxL;
  1582.  
  1583.         dscan (QRound (sxR-sxL)+1, d, z_buf, inv_z, u_div_z, v_div_z, dM, dJ1, dK1);
  1584.  
  1585.         sxL -= dL;
  1586.         sxR -= dR;
  1587.         inv_z -= vd_inv_z;
  1588.         u_div_z -= vd_u_div_z;
  1589.         v_div_z -= vd_v_div_z;
  1590.       }
  1591.     }
  1592.  
  1593.     if (iL == iR) break;
  1594.  
  1595.     if (advance == BOTH)
  1596.     {
  1597.       iL = (iL-1+num_vertices)%num_vertices;
  1598.       // To make sure that the two pointers will not accidentally miss each
  1599.       // other we only advance the right pointer if it is not equal to the
  1600.       // left one.
  1601.       if (iL != iR) iR = (iR+1)%num_vertices;
  1602.     }
  1603.     else if (advance == LEFT) iL = (iL-1+num_vertices)%num_vertices;
  1604.     else iR = (iR+1)%num_vertices;
  1605.  
  1606.     if (advance == BOTH || advance == LEFT)
  1607.     {
  1608.       syL = vertices[iL].y;
  1609.       yyL = QRound (syL);
  1610.     }
  1611.     if (advance == BOTH || advance == RIGHT)
  1612.     {
  1613.       syR = vertices[iR].y;
  1614.       yyR = QRound (syR);
  1615.     }
  1616.  
  1617.     sx1L = sx2L;
  1618.     sx1R = sx2R;
  1619.     sy1 = sy2;
  1620.     yy1 = yy2;
  1621.   }
  1622. }
  1623.  
  1624. void Polygon2D::dump (char* name)
  1625. {
  1626.   MSG (("Dump polygon 2D '%s':\n", name));
  1627.   MSG (("    num_vertices=%d  max_vertices=%d\n", num_vertices, max_vertices));
  1628.   int i;
  1629.   for (i = 0 ; i < num_vertices ; i++)
  1630.     MSG (("        v[%d]: (%2.2f,%2.2f)\n", i, vertices[i].x, vertices[i].y));
  1631.   fflush (stdout);
  1632. }
  1633.  
  1634. //---------------------------------------------------------------------------
  1635.