home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Amiga / Jeux / demos / crystalPPC.lha / texture.cpp < prev    next >
C/C++ Source or Header  |  1998-05-05  |  27KB  |  1,041 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 TEXTURE_H
  10. #include "texture.h"
  11. #endif
  12.  
  13. #ifndef POLYTEXT_H
  14. #include "polytext.h"
  15. #endif
  16.  
  17. #ifndef LIGHT_H
  18. #include "light.h"
  19. #endif
  20.  
  21. #ifndef TOKEN_H
  22. #include "token.h"
  23. #endif
  24.  
  25. #ifndef CONFIG_H
  26. #include "config.h"
  27. #endif
  28.  
  29. #ifndef POLYGON_H
  30. #include "polygon.h"
  31. #endif
  32.  
  33. #include <clib/powerpc_protos.h>
  34.  
  35. extern double tb_scale_hi;
  36. extern double tb_scale_lo;
  37.  
  38. int I_GetTime (void);
  39.  
  40. //---------------------------------------------------------------------------
  41.  
  42. TextureCache cache;
  43. Filter very_light_glass ("very_light_glass");
  44. Filter light_glass ("light_glass");
  45. Filter medium_glass ("medium_glass");
  46. Filter dark_glass ("dark_glass");
  47. Filter very_dark_glass ("very_dark_glass");
  48. Filter filter_color_red ("filter_color_red");
  49. Filter filter_color_blue ("filter_color_blue");
  50. Filter filter_color_green ("filter_color_green");
  51. Filter filter_color_yellow ("filter_color_yellow");
  52. Filter filter_m100 ("filter_m100");
  53. Filter filter_m75 ("filter_m75");
  54. Filter filter_m50 ("filter_m50");
  55. Filter filter_m25 ("filter_m25");
  56. Filter filter_0 ("filter_0");
  57. Filter filter_25 ("filter_25");
  58. Filter filter_50 ("filter_50");
  59. Filter filter_75 ("filter_75");
  60. Filter filter_100 ("filter_100");
  61.  
  62. //---------------------------------------------------------------------------
  63.  
  64. Texture::Texture (int w, int h)
  65. {
  66.   gf = new_graphic_file ();
  67.   gf->width = w;
  68.   gf->height = h;
  69.   gf->palette_entries = 0;
  70.   gf->bitmap = (unsigned char*)malloc (w * h);
  71.   gf->type = gfPaletted;
  72.  
  73.   usage = NULL;
  74.   strcpy (Texture::name, name);
  75.   transparent = -1;
  76.   filtered = FALSE;
  77.   filters = NULL;
  78.   switch (gf->width)
  79.   {
  80.     case 8: shf_w = 3; and_w = 0x7; break;
  81.     case 16: shf_w = 4; and_w = 0xf; break;
  82.     case 32: shf_w = 5; and_w = 0x1f; break;
  83.     case 64: shf_w = 6; and_w = 0x3f; break;
  84.     case 128: shf_w = 7; and_w = 0x7f; break;
  85.     case 256: shf_w = 8; and_w = 0xff; break;
  86.     case 512: shf_w = 9; and_w = 0x1ff; break;
  87.     case 1024: shf_w = 10; and_w = 0x3ff; break;
  88.   }
  89.   switch (gf->height)
  90.   {
  91.     case 8: shf_h = 3; and_h = 0x7; break;
  92.     case 16: shf_h = 4; and_h = 0xf; break;
  93.     case 32: shf_h = 5; and_h = 0x1f; break;
  94.     case 64: shf_h = 6; and_h = 0x3f; break;
  95.     case 128: shf_h = 7; and_h = 0x7f; break;
  96.     case 256: shf_h = 8; and_h = 0xff; break;
  97.     case 512: shf_h = 9; and_h = 0x1ff; break;
  98.     case 1024: shf_h = 10; and_h = 0x3ff; break;
  99.   }
  100. }
  101.  
  102. Texture::Texture (char* name)
  103. {
  104.   FILE* fp = fopen (name, "rb");
  105.   gf = LoadGIF (fp, name);
  106.   fclose (fp);
  107.   usage = NULL;
  108.   strcpy (Texture::name, name);
  109.   transparent = -1;
  110.   filtered = FALSE;
  111.   filters = NULL;
  112.   switch (gf->width)
  113.   {
  114.     case 8: shf_w = 3; and_w = 0x7; break;
  115.     case 16: shf_w = 4; and_w = 0xf; break;
  116.     case 32: shf_w = 5; and_w = 0x1f; break;
  117.     case 64: shf_w = 6; and_w = 0x3f; break;
  118.     case 128: shf_w = 7; and_w = 0x7f; break;
  119.     case 256: shf_w = 8; and_w = 0xff; break;
  120.     case 512: shf_w = 9; and_w = 0x1ff; break;
  121.     case 1024: shf_w = 10; and_w = 0x3ff; break;
  122.   }
  123.   switch (gf->height)
  124.   {
  125.     case 8: shf_h = 3; and_h = 0x7; break;
  126.     case 16: shf_h = 4; and_h = 0xf; break;
  127.     case 32: shf_h = 5; and_h = 0x1f; break;
  128.     case 64: shf_h = 6; and_h = 0x3f; break;
  129.     case 128: shf_h = 7; and_h = 0x7f; break;
  130.     case 256: shf_h = 8; and_h = 0xff; break;
  131.     case 512: shf_h = 9; and_h = 0x1ff; break;
  132.     case 1024: shf_h = 10; and_h = 0x3ff; break;
  133.   }
  134. }
  135.  
  136. // This function must be called AFTER color remapping.
  137. void Texture::set_transparent (int col)
  138. {
  139.   transparent = col; // @@@ Currently, only 0 supported
  140. }
  141.  
  142. void Texture::set_filter (int col, Filter* filter)
  143. {
  144.   int i;
  145.   filtered = TRUE;
  146.   if (!filters)
  147.   {
  148.     filters = new Filter* [256];
  149.     for (i = 0 ; i < 256 ; i++)
  150.       filters[i] = NULL;
  151.   }
  152.   filters[col] = filter;
  153. }
  154.  
  155. Texture::~Texture ()
  156. {
  157.   //@@@@@@@@@@if (gf) free_graphic_file (gf);
  158.   if (usage) delete [] usage;
  159.   if (filters) delete [] filters;
  160. }
  161.  
  162. int cmp_colorusage (const void* v1, const void* v2)
  163. {
  164.   ColorUsage* u1 = (ColorUsage*)v1;
  165.   ColorUsage* u2 = (ColorUsage*)v2;
  166.   if (u1->cnt < u2->cnt) return 1;
  167.   else if (u1->cnt > u2->cnt) return -1;
  168.   else return 0;
  169. }
  170.  
  171. void Texture::clear_color_usage ()
  172. {
  173.   if (usage)
  174.   {
  175.     delete [] usage;
  176.     usage = NULL;
  177.   }
  178. }
  179.  
  180. void Texture::compute_color_usage ()
  181. {
  182.   int i, x, y;
  183.   if (!usage) usage = new ColorUsage [256];
  184.   for (i = 0 ; i < gf->palette_entries ; i++)
  185.   {
  186.     usage[i].color = gf->palette[i];
  187.     usage[i].cnt = 0;
  188.     usage[i].idx = i;
  189.   }
  190.   unsigned char* d = gf->bitmap;
  191.   for (y = 0 ; y < gf->height ; y++)
  192.     for (x = 0 ; x < gf->width ; x++)
  193.       usage[*d++].cnt++;
  194.   qsort (usage, gf->palette_entries, sizeof (ColorUsage), cmp_colorusage);
  195. }
  196.  
  197. void Texture::remap_palette (Textures* new_palette)
  198. {
  199.   int i, j, x, y;
  200.   int trans[256];
  201.   int used[256];
  202.   for (i = 0 ; i < 256 ; i++) used[i] = FALSE;
  203.   for (i = 0 ; i < gf->palette_entries ; i++)
  204.   {
  205.     if (i != transparent && (!filtered || filters[i] == NULL))
  206.     {
  207.       trans[i] = new_palette->find_rgb_slow (gf->palette[i].red,
  208.                     gf->palette[i].green, gf->palette[i].blue);
  209.       used[trans[i]] = TRUE;
  210.     }
  211.     else trans[i] = -1;
  212.   }
  213.  
  214.   // All entries which are still -1 are used for non-colors (eg: filters and
  215.   // transparency. Remap them to unused color slots.
  216.   for (i = 0 ; i < gf->palette_entries ; i++)
  217.     if (trans[i] == -1)
  218.     {
  219.       for (j = 0 ; j < 256 ; j++)
  220.     if (!used[j]) { trans[i] = j; used[j] = TRUE; break; }
  221.     }
  222.  
  223.   unsigned char* d = gf->bitmap;
  224.   for (y = 0 ; y < gf->height ; y++)
  225.     for (x = 0 ; x < gf->width ; x++)
  226.     {
  227.       *d = trans[*d];
  228.       d++;
  229.     }
  230.  
  231.   if (filters)
  232.   {
  233.     Filter** ff = new Filter* [256];
  234.     for (i = 0 ; i < 256 ; i++)
  235.       ff[i] = NULL;
  236.     for (i = 0 ; i < gf->palette_entries ; i++)
  237.       ff[trans[i]] = filters[i];
  238.     CopyMemPPC (ff, filters,sizeof (Filter*)*256);
  239.     delete [] ff;
  240.   }
  241. }
  242.  
  243. void Texture::save (FILE* fp, int indent)
  244. {
  245.   int i;
  246.   char sp[100]; strcpy (sp, spaces); sp[indent] = 0;
  247.   fprintf (fp, "%sTEXTURE '%s' (", sp, name);
  248.   fprintf (fp, "TRANSPARENT=%d", transparent);
  249.   if (filtered)
  250.   {
  251.     fprintf (fp, "\n");
  252.     for (i = 0 ; i < 256 ; i++)
  253.       if (filters[i])
  254.     fprintf (fp, "%s  FILTER %d='%s'\n", sp, i, filters[i]->get_name ());
  255.     fprintf (fp, "%s)\n", sp);
  256.   }
  257.   else
  258.     fprintf (fp, ")\n");
  259. }
  260.  
  261. void Texture::load (char** buf)
  262. {
  263.   char* t;
  264.   int i;
  265.  
  266.   skip_token (buf, "TEXTURE");
  267.   t = get_token (buf);
  268.   strcpy (name, t);
  269.   skip_token (buf, "(", "Expected '%s' instead of '%s' after the name of a TEXTURE!\n");
  270.  
  271.   while (TRUE)
  272.   {
  273.     t = get_token (buf);
  274.     if (*t == ')' || *t == 0) break;
  275.     if (!strcmp (t, "TRANSPARENT"))
  276.     {
  277.       skip_token (buf, "=", "Expected '%s' instead of '%s' after TRANSPARENT!\n");
  278.       transparent = get_token_int (buf);
  279.     }
  280.     else if (!strcmp (t, "FILTER"))
  281.     {
  282.       i = get_token_int (buf);
  283.       skip_token (buf, "=", "Expected '%s' instead of '%s' after FILTER!\n");
  284.       t = get_token (buf);
  285.       if (!strcmp (t, "light_glass")) set_filter (i, &light_glass);
  286.       else if (!strcmp (t, "dark_glass")) set_filter (i, &dark_glass);
  287.       else if (!strcmp (t, "very_dark_glass")) set_filter (i, &very_dark_glass);
  288.       else if (!strcmp (t, "medium_glass")) set_filter (i, &medium_glass);
  289.       else if (!strcmp (t, "very_light_glass")) set_filter (i, &very_light_glass);
  290.       else if (!strcmp (t, "filter_color_red")) set_filter (i, &filter_color_red);
  291.       else if (!strcmp (t, "filter_color_green")) set_filter (i, &filter_color_green);
  292.       else if (!strcmp (t, "filter_color_blue")) set_filter (i, &filter_color_blue);
  293.       else if (!strcmp (t, "filter_color_yellow")) set_filter (i, &filter_color_yellow);
  294.       else if (!strcmp (t, "filter_m100")) set_filter (i, &filter_m100);
  295.       else if (!strcmp (t, "filter_m75")) set_filter (i, &filter_m75);
  296.       else if (!strcmp (t, "filter_m50")) set_filter (i, &filter_m50);
  297.       else if (!strcmp (t, "filter_m25")) set_filter (i, &filter_m25);
  298.       else if (!strcmp (t, "filter_0")) set_filter (i, &filter_0);
  299.       else if (!strcmp (t, "filter_25")) set_filter (i, &filter_25);
  300.       else if (!strcmp (t, "filter_50")) set_filter (i, &filter_50);
  301.       else if (!strcmp (t, "filter_75")) set_filter (i, &filter_75);
  302.       else if (!strcmp (t, "filter_100")) set_filter (i, &filter_100);
  303.       else
  304.       {
  305.     printf ("Never heard of filter '%s' in my whole existance!\n", t);
  306.     exit (0);
  307.       }
  308.     }
  309.   }
  310. }
  311.  
  312. //---------------------------------------------------------------------------
  313.  
  314. #define PREFERED_DIST 16333
  315. #define PREFERED_COL_DIST 133333
  316.  
  317. Textures::Textures (int max)
  318. {
  319.   max_textures = max;
  320.   num_textures = 0;
  321.   textures = new Texture* [max];
  322.   textured = TRUE;
  323.   mipmapped = 1;
  324.  
  325.   do_lighting = TRUE;
  326.   read_config ();
  327. }
  328.  
  329. void Textures::read_config ()
  330. {
  331.   char* p;
  332.  
  333.   prefered_dist = config.get_int ("RGB_DIST", PREFERED_DIST);
  334.   prefered_col_dist = config.get_int ("RGB_COL_DIST", PREFERED_COL_DIST);
  335.   p = config.get_str ("MIPMAP_NICE", "nice");
  336.   if (!strcmp (p, "nice")) mipmap_nice = MIPMAP_NICE;
  337.   else if (!strcmp (p, "ugly")) mipmap_nice = MIPMAP_UGLY;
  338.   else if (!strcmp (p, "default")) mipmap_nice = MIPMAP_DEFAULT;
  339.   else
  340.   {
  341.     printf ("Bad value '%s' for MIPMAP_NICE!\n", p);
  342.     exit (0);
  343.   }
  344.  
  345.   p = config.get_str ("TABLE1", "white");
  346.   if (!strcmp (p, "white")) color_table1 = TABLE_WHITE;
  347.   else if (!strcmp (p, "red")) color_table1 = TABLE_RED;
  348.   else if (!strcmp (p, "green")) color_table1 = TABLE_GREEN;
  349.   else if (!strcmp (p, "blue")) color_table1 = TABLE_BLUE;
  350.   else
  351.   {
  352.     printf ("Bad value '%s' for TABLE1!\n", p);
  353.     exit (0);
  354.   }
  355.  
  356.   p = config.get_str ("TABLE2", "red");
  357.   if (!strcmp (p, "white")) color_table2 = TABLE_WHITE;
  358.   else if (!strcmp (p, "red")) color_table2 = TABLE_RED;
  359.   else if (!strcmp (p, "green")) color_table2 = TABLE_GREEN;
  360.   else if (!strcmp (p, "blue")) color_table2 = TABLE_BLUE;
  361.   else
  362.   {
  363.     printf ("Bad value '%s' for TABLE2!\n", p);
  364.     exit (0);
  365.   }
  366.  
  367.   p = config.get_str ("TABLE3", "blue");
  368.   if (!strcmp (p, "white")) color_table3 = TABLE_WHITE;
  369.   else if (!strcmp (p, "red")) color_table3 = TABLE_RED;
  370.   else if (!strcmp (p, "green")) color_table3 = TABLE_GREEN;
  371.   else if (!strcmp (p, "blue")) color_table3 = TABLE_BLUE;
  372.   else
  373.   {
  374.     printf ("Bad value '%s' for TABLE3!\n", p);
  375.     exit (0);
  376.   }
  377. }
  378.  
  379. Textures::~Textures ()
  380. {
  381.   if (textures) delete [] textures;
  382. }
  383.  
  384. Texture* Textures::new_texture (char* name)
  385. {
  386.   Texture* t = new Texture (name);
  387.   textures[num_textures++] = t;
  388.   return t;
  389. }
  390.  
  391. int Textures::get_texture_idx (char* name)
  392. {
  393.   int i;
  394.   for (i = 0 ; i < num_textures ; i++)
  395.     if (!strcmp (textures[i]->get_name (), name)) return i;
  396.   return -1;
  397. }
  398.  
  399. int Textures::find_rgb (int r, int g, int b)
  400. {
  401.   return find_rgb_slow (r, g, b);
  402. }
  403.  
  404. int Textures::find_rgb_slow (int r, int g, int b)
  405. {
  406.   int i, min, dist, mindist;
  407.   mindist = 1000*256*256; min = -1;
  408.  
  409.   for(i = 0 ; i < 256 ; i++)
  410.     if (alloc[i])
  411.     {
  412.       dist = 299*(r-pal[i].red)*(r-pal[i].red)+
  413.     587*(g-pal[i].green)*(g-pal[i].green)+
  414.     114*(b-pal[i].blue)*(b-pal[i].blue);
  415.       if (dist == 0) return i;
  416.       if (dist < mindist) { mindist = dist; min = i; }
  417.     }
  418.   return min;
  419. }
  420.  
  421. int Textures::alloc_rgb (int r, int g, int b, int dist)
  422. {
  423.   int d, j;
  424.   if (r < 0) r = 0; else if (r > 255) r = 255;
  425.   if (g < 0) g = 0; else if (g > 255) g = 255;
  426.   if (b < 0) b = 0; else if (b > 255) b = 255;
  427.  
  428.   int i = find_rgb_slow (r, g, b);
  429.   if (i != -1)
  430.   {
  431.     d = 299*(r-pal[i].red)*(r-pal[i].red)+
  432.       587*(g-pal[i].green)*(g-pal[i].green)+
  433.       114*(b-pal[i].blue)*(b-pal[i].blue);
  434.   }
  435.   if (i == -1 || d > dist)
  436.   {
  437.     for (j = 0 ; j < 256 ; j++)
  438.       if (!alloc[j])
  439.       {
  440.         alloc[j] = TRUE;
  441.     pal[j].red = r;
  442.     pal[j].green = g;
  443.     pal[j].blue = b;
  444.     return j;
  445.       }
  446.     return i; // We couldn't allocate a new color, return best fit
  447.   }
  448.   else return i;
  449. }
  450.  
  451. struct SortRed
  452. {
  453.   int idx;
  454.   int red;
  455. };
  456.  
  457. int cmp_red (const void* v1, const void* v2)
  458. {
  459.   SortRed* u1 = (SortRed*)v1;
  460.   SortRed* u2 = (SortRed*)v2;
  461.   if (u1->red < u2->red) return -1;
  462.   else if (u1->red > u2->red) return 1;
  463.   else return 0;
  464. }
  465.  
  466. void Textures::compute_palette ()
  467. {
  468.   int i, j, t;
  469.  
  470.   printf ("Computing palette... "); fflush (stdout);
  471.  
  472.   for (i = 1 ; i < 256 ; i++)
  473.     alloc[i] = FALSE;
  474.  
  475.   // By allocating black at 0 and white at 255 we are compatible with
  476.   // the Windows palette (those two colors cannot be modified).
  477.   alloc[0] = TRUE;
  478.   pal[0].red = 0;
  479.   pal[0].green = 0;
  480.   pal[0].blue = 0;
  481.   alloc[255] = TRUE;
  482.   pal[255].red = 255;
  483.   pal[255].green = 255;
  484.   pal[255].blue = 255;
  485.  
  486.   // First compute the usage of all colors of all textures.
  487.   // These usage lists will be sorted so that the most frequently
  488.   // used color of each textures is put first.
  489.   for (i = 0 ; i < num_textures ; i++)
  490.     textures[i]->compute_color_usage ();
  491.  
  492.   int pr1, pg1, pb1, pr2, pg2, pb2, pr3, pg3, pb3;
  493.   if (color_table1 == TABLE_RED)        { pr1 = 50; pg1 = 0; pb1 = 0; }
  494.   else if (color_table1 == TABLE_GREEN) { pr1 = 0; pg1 = 50; pb1 = 0; }
  495.   else if (color_table1 == TABLE_BLUE)  { pr1 = 0; pg1 = 0; pb1 = 50; }
  496.   else { pr1 = 0; pg1 = 0; pb1 = 0; }
  497.   if (color_table2 == TABLE_RED)        { pr2 = 50; pg2 = 0; pb2 = 0; }
  498.   else if (color_table2 == TABLE_GREEN) { pr2 = 0; pg2 = 50; pb2 = 0; }
  499.   else if (color_table2 == TABLE_BLUE)  { pr2 = 0; pg2 = 0; pb2 = 50; }
  500.   else { pr2 = 0; pg2 = 0; pb2 = 0; }
  501.   if (color_table3 == TABLE_RED)        { pr3 = 50; pg3 = 0; pb3 = 0; }
  502.   else if (color_table3 == TABLE_GREEN) { pr3 = 0; pg3 = 50; pb3 = 0; }
  503.   else if (color_table3 == TABLE_BLUE)  { pr3 = 0; pg3 = 0; pb3 = 50; }
  504.   else { pr3 = 0; pg3 = 0; pb3 = 0; }
  505.  
  506.   // Then allocate colors for all textures at the same time.
  507.   for (i = 0 ; i < 256 ; i++)
  508.   {
  509.     for (t = 0 ; t < num_textures ; t++)
  510.       if (i < textures[t]->get_num_colors ())
  511.       {
  512.     j = textures[t]->get_usage (i).idx;
  513.     if (j != textures[t]->get_transparent () && (!textures[t]->get_filtered () ||
  514.                              textures[t]->get_filters()[j] == NULL))
  515.     {
  516.       alloc_rgb (
  517.              textures[t]->get_usage (i).color.red,
  518.              textures[t]->get_usage (i).color.green,
  519.              textures[t]->get_usage (i).color.blue,
  520.              prefered_dist);
  521.       if (pr1 || pg1 || pb1)
  522.         alloc_rgb (
  523.                textures[t]->get_usage (i).color.red+pr1,
  524.                textures[t]->get_usage (i).color.green+pg1,
  525.                textures[t]->get_usage (i).color.blue+pb1,
  526.                prefered_col_dist);
  527.       if (pr2 || pg2 || pb2)
  528.         alloc_rgb (
  529.                textures[t]->get_usage (i).color.red+pr2,
  530.                textures[t]->get_usage (i).color.green+pg2,
  531.                textures[t]->get_usage (i).color.blue+pb2,
  532.                prefered_col_dist);
  533.       if (pr3 || pg3 || pb3)
  534.         alloc_rgb (
  535.                textures[t]->get_usage (i).color.red+pr3,
  536.                textures[t]->get_usage (i).color.green+pg3,
  537.                textures[t]->get_usage (i).color.blue+pb3,
  538.                prefered_col_dist);
  539.     }
  540.       }
  541.   }
  542.  
  543.   // Remap all textures according to the new colormap.
  544.   for (i = 0 ; i < num_textures ; i++)
  545.     textures[i]->remap_palette (this);
  546.  
  547.   for (i = 0 ; i < num_textures ; i++)
  548.     textures[i]->clear_color_usage ();
  549.  
  550.   black_color = find_rgb (0, 0, 0);
  551.   white_color = find_rgb (255, 255, 255);
  552.   red_color = find_rgb (255, 0, 0);
  553.   blue_color = find_rgb (0, 0, 255);
  554.   yellow_color = find_rgb (255, 255, 0);
  555.   green_color = find_rgb (0, 255, 0);
  556.  
  557.   printf ("DONE\n");
  558. }
  559.  
  560. int Textures::find_rgb_map (int r, int g, int b, int map_type, int l)
  561. {
  562.   int nr = r, ng = g, nb = b;
  563.   switch (map_type)
  564.   {
  565.     case TABLE_WHITE:
  566.       nr = l*r / 200;
  567.       ng = l*g / 200;
  568.       nb = l*b / 200;
  569.       break;
  570.     case TABLE_RED:
  571.       nr = r+l;
  572.       ng = g;
  573.       nb = b;
  574.       break;
  575.     case TABLE_BLUE:
  576.       nr = r;
  577.       ng = g;
  578.       nb = b+l;
  579.       break;
  580.     case TABLE_GREEN:
  581.       nr = r;
  582.       ng = g+l;
  583.       nb = b;
  584.       break;
  585.   }
  586.   return find_rgb (nr, ng, nb);
  587. }
  588.  
  589. void Textures::compute_light_tables ()
  590. {
  591.   int l, i;
  592.   int r, g, b;
  593.  
  594.   if (color_table1 == TABLE_WHITE) level1 = DEFAULT_LIGHT_LEVEL; else level1 = 0;
  595.   if (color_table2 == TABLE_WHITE) level2 = DEFAULT_LIGHT_LEVEL; else level2 = 0;
  596.   if (color_table3 == TABLE_WHITE) level3 = DEFAULT_LIGHT_LEVEL; else level3 = 0;
  597.  
  598.   // Light level 200 is normal
  599.  
  600.   printf ("Computing light tables... "); fflush (stdout);
  601.  
  602.   FILE* fp = fopen ("light.tables", "rb");
  603.   if (fp)
  604.   {
  605.     printf ("reading from file... "); fflush (stdout);
  606.     for (i = 0 ; i < 256 ; i++)
  607.       for (l = 0 ; l < 256 ; l++)
  608.       {
  609.         fread ((void*)&(light[l][i]), sizeof (unsigned char), 1, fp);
  610.         fread ((void*)&(red_light[l][i]), sizeof (unsigned char), 1, fp);
  611.         fread ((void*)&(blue_light[l][i]), sizeof (unsigned char), 1, fp);
  612.       }
  613.     fclose (fp);
  614.   }
  615.   else
  616.   {
  617.     fp = fopen ("light.tables", "wb");
  618.     time_t s1 = I_GetTime(), s2;
  619.     for (i = 0 ; i < 256 ; i++)
  620.       if (alloc[i])
  621.       {
  622.         r = pal[i].red;
  623.         g = pal[i].green;
  624.         b = pal[i].blue;
  625.         for (l = 0 ; l < 256 ; l++)
  626.         {
  627.       light[l][i] = find_rgb_map (r, g, b, color_table1, l);
  628.       red_light[l][i] = find_rgb_map (r, g, b, color_table2, l);
  629.       blue_light[l][i] = find_rgb_map (r, g, b, color_table3, l);
  630.       fwrite ((void*)&(light[l][i]), sizeof (unsigned char), 1, fp);
  631.       fwrite ((void*)&(red_light[l][i]), sizeof (unsigned char), 1, fp);
  632.       fwrite ((void*)&(blue_light[l][i]), sizeof (unsigned char), 1, fp);
  633.         }
  634.       }
  635.     s2 = I_GetTime();
  636.     printf ("(Elapsed time = %ld seconds) ", s2-s1);
  637.     fclose (fp);
  638.   }
  639.  
  640.   printf ("DONE\n");
  641. }
  642.  
  643. void Textures::create_mipmap_textures ()
  644. {
  645.   int i, j, mm, start, stop;
  646.   int r, g, b;
  647.  
  648.   rnum_textures = num_textures;
  649.  
  650.   printf ("Create mipmapped textures ... "); fflush (stdout);
  651.  
  652.   for (mm = 1 ; mm <= 3 ; mm++)
  653.   {
  654.     if (mm == 1)
  655.     {
  656.       offs_mipmap1 = num_textures;
  657.       start = 0;
  658.       stop = offs_mipmap1;
  659.     }
  660.     else if (mm == 2)
  661.     {
  662.       offs_mipmap2 = num_textures;
  663.       start = offs_mipmap1;
  664.       stop = offs_mipmap2;
  665.       printf ("level 2 ... "); fflush (stdout);
  666.     }
  667.     else
  668.     {
  669.       offs_mipmap3 = num_textures;
  670.       start = offs_mipmap2;
  671.       stop = offs_mipmap3;
  672.       printf ("level 3 ... "); fflush (stdout);
  673.     }
  674.  
  675.     for (i = start ; i < stop ; i++)
  676.     {
  677.       int w, h, w2, h2, x, y;
  678.       w = textures[i]->get_width ();
  679.       h = textures[i]->get_height ();
  680.       w2 = w/2;
  681.       h2 = h/2;
  682.       Texture* t = new Texture (w2, h2);
  683.       textures[num_textures++] = t;
  684.       unsigned char* bm = textures[i]->get_bitmap ();
  685.       unsigned char* bm2 = t->get_bitmap ();
  686.  
  687.       t->set_transparent (textures[i]->get_transparent ());
  688.       int tran = textures[i]->get_transparent () != -1;
  689.       int filt = textures[i]->get_filtered ();
  690.       if (filt)
  691.       {
  692.     Filter** f = textures[i]->get_filters ();
  693.     for (j = 0 ; j < 256 ; j++)
  694.       if (f[j]) t->set_filter (j, f[j]);
  695.       }
  696.  
  697.       if (tran || filt || mipmap_nice == MIPMAP_UGLY)
  698.     for (y = 0 ; y < h2 ; y++)
  699.     {
  700.       for (x = 0 ; x < w2 ; x++)
  701.       {
  702.         *bm2++ = *bm;
  703.         bm += 2;
  704.       }
  705.       bm += w;
  706.     }
  707.       else if (mipmap_nice == MIPMAP_DEFAULT)
  708.     for (y = 0 ; y < h2 ; y++)
  709.     {
  710.       for (x = 0 ; x < w2 ; x++)
  711.       {
  712.         // @@@ Consider a more accurate algorithm that shifts the source bitmap one
  713.         // half pixel. In the current implementation there is a small shift in the
  714.         // texture data.
  715.         r = pal[*bm].red + pal[*(bm+1)].red + pal[*(bm+w)].red + pal[*(bm+w+1)].red;
  716.         g = pal[*bm].green + pal[*(bm+1)].green + pal[*(bm+w)].green + pal[*(bm+w+1)].green;
  717.         b = pal[*bm].blue + pal[*(bm+1)].blue + pal[*(bm+w)].blue + pal[*(bm+w+1)].blue;
  718.         *bm2++ = find_rgb (r/4, g/4, b/4);
  719.         bm += 2;
  720.       }
  721.       bm += w;
  722.     }
  723.       else
  724.       {
  725.     int m11, m12, m13;
  726.     int m21, m22, m23;
  727.     int m31, m32, m33;
  728.     for (y = 0 ; y < h ; y += 2)
  729.     {
  730.       for (x = 0 ; x < w ; x += 2)
  731.       {
  732.         m11 = ((x-1+w)%w) + ((y-1+h)%h) * w;
  733.         m12 = x           + ((y-1+h)%h) * w;
  734.         m13 = ((x+1)%w)   + ((y-1+h)%h) * w;
  735.         m21 = ((x-1+w)%w) + y * w;
  736.         m22 = x           + y * w;
  737.         m23 = ((x+1)%w)   + y * w;
  738.         m31 = ((x-1+w)%w) + ((y+1)%h) * w;
  739.         m32 = x           + ((y+1)%h) * w;
  740.         m33 = ((x+1)%w)   + ((y+1)%h) * w;
  741.         r =   pal[bm[m11]].red +   2*pal[bm[m12]].red +     pal[bm[m13]].red +
  742.             2*pal[bm[m21]].red +   4*pal[bm[m22]].red +   2*pal[bm[m23]].red +
  743.               pal[bm[m31]].red +   2*pal[bm[m32]].red +     pal[bm[m33]].red;
  744.         g =   pal[bm[m11]].green + 2*pal[bm[m12]].green +   pal[bm[m13]].green +
  745.             2*pal[bm[m21]].green + 4*pal[bm[m22]].green + 2*pal[bm[m23]].green +
  746.               pal[bm[m31]].green + 2*pal[bm[m32]].green +   pal[bm[m33]].green;
  747.         b =   pal[bm[m11]].blue +  2*pal[bm[m12]].blue +    pal[bm[m13]].blue +
  748.             2*pal[bm[m21]].blue +  4*pal[bm[m22]].blue +  2*pal[bm[m23]].blue +
  749.               pal[bm[m31]].blue +  2*pal[bm[m32]].blue +    pal[bm[m33]].blue;
  750.         *bm2++ = find_rgb (r/16, g/16, b/16);
  751.       }
  752.     }
  753.       }
  754.     }
  755.   }
  756.  
  757.   printf ("DONE\n");
  758. }
  759.  
  760. #include <exec/types.h>
  761.  
  762. extern ULONG rtgpal[770];
  763.  
  764.  
  765. void Textures::alloc_palette (Graphics* g)
  766. {
  767.   int i;
  768.   for (i = 0 ; i < 256 ; i++)
  769.   {
  770.    if (alloc[i])
  771.    {
  772.     rtgpal[3*i+1]=pal[i].red*0x01010101;
  773.     rtgpal[3*i+2]=pal[i].green*0x01010101;
  774.     rtgpal[3*i+3]=pal[i].blue*0x01010101;
  775.     graphicsPalette[i].red=pal[i].red;
  776.     graphicsPalette[i].green=pal[i].green;
  777.     graphicsPalette[i].blue=pal[i].blue;
  778.    }
  779.    else
  780.    {
  781.     rtgpal[3*i+1]=graphicsPalette[i].red*0x01010101;
  782.     rtgpal[3*i+2]=graphicsPalette[i].green*0x01010101;
  783.     rtgpal[3*i+3]=graphicsPalette[i].blue*0x01010101;
  784.    }
  785.   }
  786.   rtgpal[769]=0;
  787.   rtgpal[0]=256*65536+0;
  788.   g->SetRGB(0,0,0,0);
  789. }
  790.  
  791. void Textures::save (FILE* fp, int indent)
  792. {
  793.   int i;
  794.   char sp[100]; strcpy (sp, spaces); sp[indent] = 0;
  795.   fprintf (fp, "%sTEXTURES (\n", sp);
  796.   fprintf (fp, "%s  MAX_TEXTURES=%d\n", sp, max_textures);
  797.   for (i = 0 ; i < rnum_textures ; i++) textures[i]->save (fp, indent+2);
  798.   fprintf (fp, "%s)\n", sp);
  799. }
  800.  
  801. void Textures::load (char** buf)
  802. {
  803.   char* t;
  804.   char* old_buf;
  805.   Texture* tex;
  806.  
  807.   skip_token (buf, "TEXTURES");
  808.   skip_token (buf, "(", "Expected '%s' instead of '%s' after TEXTURES statement!\n");
  809.  
  810.   num_textures = 0;
  811.  
  812.   while (TRUE)
  813.   {
  814.     old_buf = *buf;
  815.     t = get_token (buf);
  816.     if (*t == ')' || *t == 0) break;
  817.     if (!strcmp (t, "MAX_TEXTURES"))
  818.     {
  819.       skip_token (buf, "=", "Expected '%s' instead of '%s' after MAX_TEXTURES!\n");
  820.       max_textures = get_token_int (buf);
  821.       if (textures) delete [] textures;
  822.       textures = new Texture* [max_textures];
  823.     }
  824.     else if (!strcmp (t, "TEXTURE"))
  825.     {
  826.       t = get_token (buf);
  827.       tex = new_texture (t);
  828.       *buf = old_buf;
  829.       tex->load (buf);
  830.     }
  831.   }
  832.  
  833.   compute_palette ();
  834.   compute_light_tables ();
  835.   create_mipmap_textures ();
  836. }
  837.  
  838. //---------------------------------------------------------------------------
  839.  
  840. void Filter::init_filters (Textures* tex)
  841. {
  842.   ::very_light_glass.light_glass (tex);
  843.   ::light_glass.light_glass (tex);
  844.   ::dark_glass.dark_glass (tex);
  845.   ::very_dark_glass.very_dark_glass (tex);
  846.   ::medium_glass.medium_glass (tex);
  847.   ::filter_color_red.add_color (tex, 50, 0, 0);
  848.   ::filter_color_blue.add_color (tex, 0, 0, 50);
  849.   ::filter_color_green.add_color (tex, 0, 50, 0);
  850.   ::filter_color_yellow.add_color (tex, 50, 50, 0);
  851.   ::filter_m100.add_color (tex, -100, -100, -100);
  852.   ::filter_m75.add_color (tex, -75, -75, -75);
  853.   ::filter_m50.add_color (tex, -50, -50, -50);
  854.   ::filter_m25.add_color (tex, -25, -25, -25);
  855.   ::filter_0.add_color (tex, 0, 0, 0);
  856.   ::filter_25.add_color (tex, 25, 25, 25);
  857.   ::filter_50.add_color (tex, 50, 50, 50);
  858.   ::filter_75.add_color (tex, 75, 75, 75);
  859.   ::filter_100.add_color (tex, 100, 100, 100);
  860. }
  861.  
  862. Filter::Filter (char* name)
  863. {
  864.   strcpy (Filter::name, name);
  865.   trans = new unsigned char [256];
  866. }
  867.  
  868. Filter::~Filter ()
  869. {
  870.   if (trans) delete [] trans;
  871. }
  872.  
  873. void Filter::mean_with_color (Textures* tex, int rg, int gg, int bg, int weight)
  874. {
  875.   int i, r, g, b, rd, gd, bd;
  876.   rg *= weight;
  877.   bg *= weight;
  878.   gg *= weight;
  879.   for (i = 0 ; i < 256 ; i++)
  880.     if (tex->get_pal_alloced (i))
  881.     {
  882.       r = tex->get_pal_red (i);
  883.       g = tex->get_pal_green (i);
  884.       b = tex->get_pal_blue (i);
  885.       rd = (r+rg)/2;
  886.       gd = (g+gg)/2;
  887.       bd = (b+bg)/2;
  888.       trans[i] = tex->find_rgb (rd, gd, bd);
  889.     }
  890. }
  891.  
  892. void Filter::add_color (Textures* tex, int rg, int gg, int bg)
  893. {
  894.   int i, r, g, b, rd, gd, bd;
  895.   for (i = 0 ; i < 256 ; i++)
  896.     if (tex->get_pal_alloced (i))
  897.     {
  898.       r = tex->get_pal_red (i);
  899.       g = tex->get_pal_green (i);
  900.       b = tex->get_pal_blue (i);
  901.       rd = r+rg;
  902.       gd = g+gg;
  903.       bd = b+bg;
  904.       trans[i] = tex->find_rgb (rd, gd, bd);
  905.     }
  906. }
  907.  
  908. void Filter::very_light_glass (Textures* tex)
  909. {
  910.   mean_with_color (tex, 220, 240, 250, 1);
  911. }
  912.  
  913. void Filter::light_glass (Textures* tex)
  914. {
  915.   mean_with_color (tex, 200, 220, 240, 1);
  916. }
  917.  
  918. void Filter::medium_glass (Textures* tex)
  919. {
  920.   mean_with_color (tex, 190, 210, 230, 1);
  921. }
  922.  
  923. void Filter::dark_glass (Textures* tex)
  924. {
  925.   mean_with_color (tex, 180, 200, 220, 1);
  926. }
  927.  
  928. void Filter::very_dark_glass (Textures* tex)
  929. {
  930.   mean_with_color (tex, 150, 180, 180, 1);
  931. }
  932.  
  933. void Filter::transparent (Textures* tex)
  934. {
  935.   (void)tex;
  936.   int i;
  937.   for (i = 0 ; i < 256 ; i++)
  938.     trans[i] = i;
  939. }
  940.  
  941. //---------------------------------------------------------------------------
  942.  
  943. TextureCache::TextureCache ()
  944. {
  945.   clear ();
  946. }
  947.  
  948. TextureCache::~TextureCache ()
  949. {
  950. }
  951.  
  952. void TextureCache::clear ()
  953. {
  954.   while (first)
  955.   {
  956.     PolyTexture* n = first->next;
  957.     first->next = first->prev = NULL;
  958.     first->in_cache = FALSE;
  959.     if (first->tmap)
  960.     {
  961.       delete [] first->tmap;
  962.       first->tmap = NULL;
  963.     }
  964.     first = n;
  965.   }
  966.  
  967.   first = last = NULL;
  968.   total_size = 0;
  969.   total_textures = 0;
  970. }
  971.  
  972. void TextureCache::dump ()
  973. {
  974.   printf ("Texture cache information:\n");
  975.   printf ("  There are %d textures in the cache\n", total_textures);
  976.   printf ("  with a total size of %ld bytes\n", total_size);
  977.   int mean;
  978.   if (total_textures == 0) mean = 0;
  979.   else mean = total_size/total_textures;
  980.   printf ("  giving %d bytes per texture in the cache.\n", mean);
  981. }
  982.  
  983. void TextureCache::use_texture (PolyTexture* pt, Textures* textures)
  984. {
  985.   if (!pt->polygon->get_lightmap ()) return;
  986.  
  987.   if (pt->in_cache)
  988.   {
  989.     // Texture is already in the cache.
  990.  
  991.     // Unlink texture and put it in front (MRU).
  992.     if (pt != first)
  993.     {
  994.       if (pt->prev) pt->prev->next = pt->next;
  995.       else first = pt->next;
  996.       if (pt->next) pt->next->prev = pt->prev;
  997.       else last = pt->prev;
  998.  
  999.       pt->prev = NULL;
  1000.       pt->next = first;
  1001.       if (first) first->prev = pt;
  1002.       else last = pt;
  1003.       first = pt;
  1004.     }
  1005.   }
  1006.   else
  1007.   {
  1008.     // Texture is not in the cache.
  1009.     while (total_size + pt->size >= MAX_CACHE_SIZE)
  1010.     {
  1011.       // Total size of textures in cache is too high. Remove the last one.
  1012.       PolyTexture* l = last;
  1013.       last = last->prev;
  1014.       if (last) last->next = NULL;
  1015.       else first = NULL;
  1016.       l->prev = NULL;
  1017.       l->in_cache = FALSE;
  1018.       if (l->tmap)
  1019.       {
  1020.     delete [] l->tmap;
  1021.     l->tmap = NULL;
  1022.       }
  1023.       total_textures--;
  1024.       total_size -= l->size;
  1025.     }
  1026.     total_textures++;
  1027.     total_size += pt->size;
  1028.  
  1029.     // Add new texture to cache.
  1030.     pt->next = first;
  1031.     pt->prev = NULL;
  1032.     if (first) first->prev = pt;
  1033.     else last = pt;
  1034.     first = pt;
  1035.     pt->in_cache = TRUE;
  1036.     pt->create_lighted_texture (textures);
  1037.   }
  1038. }
  1039.  
  1040. //---------------------------------------------------------------------------
  1041.