]> icculus.org git repositories - taylor/freespace2.git/blob - src/graphics/colors.cpp
The Great Newline Fix
[taylor/freespace2.git] / src / graphics / colors.cpp
1 /*
2  * $Logfile: /Freespace2/code/Graphics/Colors.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Functions to deal with colors & alphacolors
8  *
9  * $Log$
10  * Revision 1.2  2002/05/07 03:16:45  theoddone33
11  * The Great Newline Fix
12  *
13  * Revision 1.1.1.1  2002/05/03 03:28:09  root
14  * Initial import.
15  *
16  * 
17  * 7     7/08/99 10:52a Dave
18  * New multiplayer interpolation scheme. Not 100% done yet, but still
19  * better than the old way.
20  * 
21  * 6     1/14/99 12:48a Dave
22  * Todo list bug fixes. Made a pass at putting briefing icons back into
23  * FRED. Sort of works :(
24  * 
25  * 5     12/02/98 5:47p Dave
26  * Put in interface xstr code. Converted barracks screen to new format.
27  * 
28  * 4     11/30/98 5:31p Dave
29  * Fixed up Fred support for software mode.
30  * 
31  * 3     11/30/98 1:07p Dave
32  * 16 bit conversion, first run.
33  * 
34  * 2     10/07/98 10:52a Dave
35  * Initial checkin.
36  * 
37  * 1     10/07/98 10:48a Dave
38  * 
39  * 35    5/19/98 3:32p John
40  * upped alpha colors
41  * 
42  * 34    5/13/98 10:22p John
43  * Added cfile functions to read/write rle compressed blocks of data.
44  * Made palman use it for .clr files.  Made alphacolors calculate on the
45  * fly rather than caching to/from disk.
46  * 
47  * 33    4/30/98 4:53p John
48  * Restructured and cleaned up cfile code.  Added capability to read off
49  * of CD-ROM drive and out of multiple pack files.
50  * 
51  * 32    4/10/98 5:20p John
52  * Changed RGB in lighting structure to be ubytes.  Removed old
53  * not-necessary 24 bpp software stuff.
54  * 
55  * 31    4/09/98 11:04p John
56  * Changed ID's in output files to make more sense.
57  * 
58  * 30    4/01/98 3:05p Adam
59  * Reduced gamma on text.
60  * 
61  * 29    3/29/98 2:36p John
62  * fixed bug with reloading fullscreen colros
63  * 
64  * 28    3/25/98 8:07p John
65  * Restructured software rendering into two modules; One for windowed
66  * debug mode and one for DirectX fullscreen.   
67  * 
68  * 27    3/24/98 4:22p John
69  * fixed warning
70  * 
71  * 26    3/24/98 3:58p John
72  * Put in (hopefully) final gamma setting code.
73  * 
74  * 25    3/10/98 4:18p John
75  * Cleaned up graphics lib.  Took out most unused gr functions.   Made D3D
76  * & Glide have popups and print screen.  Took out all >8bpp software
77  * support.  Made Fred zbuffer.  Made zbuffer allocate dynamically to
78  * support Fred.  Made zbuffering key off of functions rather than one
79  * global variable.
80  * 
81  * 24    2/07/98 7:50p John
82  * Added code so that we can use the old blending type of alphacolors if
83  * we want to.  Made the stars use them.
84  * 
85  * 23    1/13/98 10:20a John
86  * Added code to support "glass" in alphacolors
87  * 
88  * 22    1/02/98 9:10p Lawrance
89  * Big changes to how colors get set on the HUD.
90  * 
91  * 21    12/30/97 4:32p John
92  * 
93  * 20    12/02/97 3:59p John
94  * Added first rev of thruster glow, along with variable levels of
95  * translucency, which retquired some restructing of palman.
96  * 
97  * 19    11/30/97 4:26p John
98  * Added 32-bpp antialiased line.   Took gamma out of alphacolor
99  * calculation.
100  * 
101  * 18    11/29/97 2:06p John
102  * added mode 16-bpp support
103  * 
104  * 17    11/21/97 11:32a John
105  * Added nebulas.   Fixed some warpout bugs.
106  * 
107  * 16    11/14/97 12:30p John
108  * Fixed some DirectX bugs.  Moved the 8-16 xlat tables into Graphics
109  * libs.  Made 16-bpp DirectX modes know what bitmap format they're in.
110  * 
111  * 15    11/05/97 11:20p Lawrance
112  * increase number of alpha colors to 52
113  * 
114  * 14    11/04/97 6:32p Hoffoss
115  * Changes to hotkey screen.  Needed to add new colors for
116  * Color_text_active*.
117  * 
118  * 13    10/31/97 10:47a John
119  * upped clr version to force rebuild after changing palette code.
120  * 
121  * 12    10/14/97 4:50p John
122  * more 16 bpp stuff.
123  * 
124  * 11    10/14/97 8:08a John
125  * added a bunch more 16 bit support
126  * 
127  * 10    10/09/97 5:23p John
128  * Added support for more 16-bpp functions
129  * 
130  * 9     10/03/97 9:10a John
131  * added better antialiased line drawer
132  * 
133  * 8     9/20/97 8:16a John
134  * Made .clr files go into the Cache directory. Replaced cfopen(name,NULL)
135  * to delete a file with cf_delete.
136  * 
137  * 7     9/09/97 10:46a Sandeep
138  * fixed warning level 4
139  * 
140  * 6     7/18/97 12:40p John
141  * cached alphacolors to disk.  Also made cfopen be able to delete a file
142  * by passing NULL for mode.
143  * 
144  * 5     7/16/97 3:07p John
145  * 
146  * 4     6/18/97 12:07p John
147  * fixed some color bugs
148  * 
149  * 3     6/18/97 9:46a John
150  * added first rev of d3d shader.   Made HUD target use medium detail
151  * models.  Took out some color debug messages.
152  * 
153  * 2     6/17/97 7:04p John
154  * added d3d support for gradients.
155  * fixed some color bugs by adding screen signatures instead of watching
156  * flags and palette changes.
157  * 
158  * 1     6/17/97 12:01p John
159  *
160  * $NoKeywords: $
161  */
162
163 #include "pstypes.h"
164 #include "2d.h"
165 #include "grinternal.h"
166 #include "colors.h"
167 #include "palman.h"
168 #include "cfile.h"
169 #include "systemvars.h"
170
171 //#define MAX_ALPHACOLORS 36
172 #define MAX_ALPHACOLORS 72
173
174 alphacolor Alphacolors[MAX_ALPHACOLORS];
175 static int Alphacolors_intited = 0;
176
177 alphacolor * Current_alphacolor = NULL;
178
179
180 void calc_alphacolor_hud_type( alphacolor * ac )
181 {
182 #ifndef HARDWARE_ONLY
183         int i,j;
184         int tr,tg,tb, Sr, Sg, Sb;
185         ubyte * pal;
186         int r, g, b, alpha;
187         float falpha;
188
189         Assert(Alphacolors_intited);
190
191 //      mprintf(( "Calculating alphacolor for %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha ));
192
193         falpha = i2fl(ac->alpha)/255.0f;
194         if ( falpha<0.0f ) falpha = 0.0f; else if ( falpha > 1.0f ) falpha = 1.0f;
195
196         alpha = ac->alpha >> 4;
197         if (alpha < 0 ) alpha = 0; else if (alpha > 15 ) alpha = 15;
198         r = ac->r;
199         if (r < 0 ) r = 0; else if (r > 255 ) r = 255;
200         g = ac->g;
201         if (g < 0 ) g = 0; else if (g > 255 ) g = 255;
202         b = ac->b;
203         if (b < 0 ) b = 0; else if (b > 255 ) b = 255;
204
205         int ii[16];
206
207         for (j=1; j<15; j++ )   {
208
209                 // JAS: Use 1.5/Gamma instead of 1/Gamma because on Adam's
210                 // PC a gamma of 1.2 makes text look good, but his gamma is
211                 // really 1.8.   1.8/1.2 = 1.5
212                 float factor = falpha * (float)pow(i2fl(j)/14.0f, 1.5f/Gr_gamma);
213                 //float factor = i2fl(j)/14.0f;
214
215                 tr = fl2i( i2fl(r) * factor );
216                 tg = fl2i( i2fl(g) * factor );
217                 tb = fl2i( i2fl(b) * factor );
218
219                 ii[j] = tr;
220                 if ( tg > ii[j] )       ii[j] = tg;
221                 if ( tb > ii[j] )       ii[j] = tb;
222         }
223
224         pal = gr_palette;
225
226         int m = r;
227         if ( g > m ) m = g;
228         if ( b > m ) m = b;
229
230         ubyte ri[256], gi[256], bi[256];
231
232         if ( m > 0 )    {
233                 for (i=0; i<256; i++ )  {
234                         ri[i] = ubyte((i*r)/m);
235                         gi[i] = ubyte((i*g)/m);
236                         bi[i] = ubyte((i*b)/m);
237                 }
238         } else {
239                 for (i=0; i<256; i++ )  {
240                         ri[i] = 0;
241                         gi[i] = 0;
242                         bi[i] = 0;
243                 }
244         }
245
246         for (i=0; i<256; i++ )  {
247                 Sr = pal[0];
248                 Sg = pal[1];
249                 Sb = pal[2];
250                 pal += 3;
251
252                 int dst_intensity = Sr;
253                 if ( Sg > dst_intensity ) dst_intensity = Sg;
254                 if ( Sb > dst_intensity ) dst_intensity = Sb;
255
256                 ac->table.lookup[0][i] = (unsigned char)i;
257
258                 for (j=1; j<15; j++ )   {
259
260                         int tmp_i = max( ii[j], dst_intensity );
261
262                         ac->table.lookup[j][i] = (unsigned char)palette_find(ri[tmp_i],gi[tmp_i],bi[tmp_i]);
263                 }
264
265                 float di = (i2fl(Sr)*.30f+i2fl(Sg)*0.60f+i2fl(Sb)*.10f)/255.0f;
266                 float factor = 0.0f + di*0.75f;
267
268                 tr = fl2i( factor*i2fl(r)*falpha );
269                 tg = fl2i( factor*i2fl(g)*falpha );
270                 tb = fl2i( factor*i2fl(b)*falpha );
271
272                 if ( tr > 255 ) tr = 255; else if ( tr < 0 ) tr = 0;
273                 if ( tg > 255 ) tg = 255; else if ( tg < 0 ) tg = 0; 
274                 if ( tb > 255 ) tb = 255; else if ( tb < 0 ) tb = 0;
275
276                 ac->table.lookup[15][i] = (unsigned char)palette_find(tr,tg,tb);
277                 //ac->table.lookup[15][i] = (unsigned char)palette_find(255,0,0);
278
279         }
280 #endif
281 }
282
283 // Old way to calculate alpha colors
284
285 void calc_alphacolor_blend_type( alphacolor * ac )
286 {
287 #ifndef HARDWARE_ONLY
288         int i,j;
289         int tr,tg,tb, Sr, Sg, Sb;
290         int Dr, Dg, Db;
291         ubyte * pal;
292         int r, g, b, alpha;
293
294         Assert(Alphacolors_intited);
295
296 //      mprintf(( "Calculating alphacolor for %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha ));
297
298         alpha = ac->alpha >> 4;
299         if (alpha < 0 ) alpha = 0; else if (alpha > 15 ) alpha = 15;
300         r = ac->r;
301         if (r < 0 ) r = 0; else if (r > 255 ) r = 255;
302         g = ac->g;
303         if (g < 0 ) g = 0; else if (g > 255 ) g = 255;
304         b = ac->b;
305         if (b < 0 ) b = 0; else if (b > 255 ) b = 255;
306
307         int gamma_j1[16];
308
309         for (j=1; j<16; j++ )   {
310                 // JAS: Use 1.5/Gamma instead of 1/Gamma because on Adam's
311                 // PC a gamma of 1.2 makes text look good, but his gamma is
312                 // really 1.8.   1.8/1.2 = 1.5
313                 gamma_j1[j] = (int)((pow(i2fl(j)/15.0f, 1.5f/Gr_gamma)*16.0f) + 0.5);
314         }
315
316         pal = gr_palette;
317
318         for (i=0; i<256; i++ )  {
319                 Sr = pal[0];
320                 Sg = pal[1];
321                 Sb = pal[2];
322                 pal += 3;
323         
324                 Dr = ( Sr*(16-alpha) + (r*alpha) ) >> 4;
325                 Dg = ( Sg*(16-alpha) + (g*alpha) ) >> 4;
326                 Db = ( Sb*(16-alpha) + (b*alpha) ) >> 4;
327
328                 ac->table.lookup[0][i] = (unsigned char)i;
329
330                 for (j=1; j<16; j++ )   {
331
332                         int j1 = gamma_j1[j];
333
334                         tr = ( Sr*(16-j1) + (Dr*j1) ) >> 4;
335                         tg = ( Sg*(16-j1) + (Dg*j1) ) >> 4;
336                         tb = ( Sb*(16-j1) + (Db*j1) ) >> 4;
337
338                         if ( tr > 255 ) tr = 255; else if ( tr < 0 ) tr = 0;
339                         if ( tg > 255 ) tg = 255; else if ( tg < 0 ) tg = 0; 
340                         if ( tb > 255 ) tb = 255; else if ( tb < 0 ) tb = 0;
341
342                         ac->table.lookup[j][i] = (unsigned char)palette_find(tr,tg,tb);
343                 }
344         }
345 #endif
346 }
347
348 void calc_alphacolor( alphacolor * ac )
349 {
350         switch(ac->type)        {
351         case AC_TYPE_HUD:
352                 calc_alphacolor_hud_type(ac);
353                 break;
354         case AC_TYPE_BLEND:
355                 calc_alphacolor_blend_type(ac);
356                 break;
357         default:
358                 Int3();         // Passing an invalid type of alphacolor!
359         }
360 }
361
362 void grx_init_alphacolors()
363 {
364         int i;
365         
366         Alphacolors_intited = 1;
367
368         for (i=0; i<MAX_ALPHACOLORS; i++ )      {
369                 Alphacolors[i].used = 0;
370                 Alphacolors[i].clr = NULL;
371         }
372
373         Current_alphacolor = NULL;
374 }
375
376
377
378 void grx_init_alphacolor( color *clr, int r, int g, int b, int alpha, int type )
379 {
380         int n;
381         alphacolor *ac;
382         
383         if(Game_mode & GM_STANDALONE_SERVER){
384                 return;
385         }
386
387         if (!Alphacolors_intited) return;
388
389         if ( alpha < 0 ) alpha = 0;
390         if ( alpha > 255 ) alpha = 255;
391
392         n = -1;
393         if ( (clr->magic == 0xAC01) && (clr->is_alphacolor) )   {
394                 if ( (clr->alphacolor >= 0) && (clr->alphacolor < MAX_ALPHACOLORS))     {
395                         if ( Alphacolors[clr->alphacolor].used && (Alphacolors[clr->alphacolor].clr==clr) )     {
396                                 n = clr->alphacolor;
397                         }
398                 }
399         }
400
401         int changed = 0;
402
403         if ( n==-1 )    {
404                 for (n=0; n<MAX_ALPHACOLORS; n++ )      {
405                         if (!Alphacolors[n].used) break;
406                 }
407                 if ( n == MAX_ALPHACOLORS )     
408                         Error( LOCATION, "Out of alphacolors!\n" );
409         } else {
410                 changed = 1;
411         }
412
413
414         // Create the alphacolor
415         ac = &Alphacolors[n];
416
417         if ( changed && (ac->r!=r || ac->g!=g || ac->b!=b || ac->alpha!=alpha || ac->type != type ) )   {
418                 // we're changing the color, so delete the old cache file
419                 //mprintf(( "Changing ac from %d,%d,%d,%d to %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha, r, g, b, alpha ));
420                 //ac_delete_cached(ac);
421         }
422
423         ac->used = 1;
424         ac->r = r;
425         ac->g = g;
426         ac->b = b;
427         ac->alpha = alpha;
428         ac->type = type;
429         ac->clr=clr;
430         
431         calc_alphacolor(ac);
432
433         grx_init_color( clr, r, g, b );
434
435         // Link the alphacolor to the color
436         clr->alpha = (unsigned char)alpha;
437         clr->ac_type = (ubyte)type;
438         clr->alphacolor = n;
439         clr->is_alphacolor = 1;
440 }
441
442
443 void grx_get_color( int * r, int * g, int * b )
444 {
445         if (r) *r = gr_screen.current_color.red;
446         if (g) *g = gr_screen.current_color.green;
447         if (b) *b = gr_screen.current_color.blue;
448 }
449
450 void grx_init_color( color * dst, int r, int g, int b )
451 {
452         dst->screen_sig = gr_screen.signature;
453         dst->red = (unsigned char)r;
454         dst->green = (unsigned char)g;
455         dst->blue = (unsigned char)b;
456         dst->alpha = 255;
457         dst->ac_type = AC_TYPE_NONE;
458         dst->is_alphacolor = 0;
459         dst->alphacolor = -1;
460         dst->magic = 0xAC01;
461
462         dst->raw8 = (unsigned char)palette_find( r, g, b );
463 }
464
465 void grx_set_color_fast( color * dst )
466 {
467         if ( dst->magic != 0xAC01 ) return;
468
469         if ( dst->screen_sig != gr_screen.signature )   {
470                 if ( dst->is_alphacolor )       {
471                         grx_init_alphacolor( dst, dst->red, dst->green, dst->blue, dst->alpha, dst->ac_type );
472                 } else {
473                         grx_init_color( dst, dst->red, dst->green, dst->blue );
474                 }
475         }
476
477         gr_screen.current_color = *dst;
478         
479         if ( dst->is_alphacolor )       {
480                 Assert( dst->alphacolor > -1 );
481                 Assert( dst->alphacolor <= MAX_ALPHACOLORS );
482                 Assert( Alphacolors[dst->alphacolor].used );
483
484                 // Current_alphacolor = &Alphacolors[dst->alphacolor];
485                 Current_alphacolor = NULL;
486         } else {
487                 Current_alphacolor = NULL;
488         }
489 }
490
491
492 void grx_set_color( int r, int g, int b )
493 {
494         Assert((r >= 0) && (r < 256));
495         Assert((g >= 0) && (g < 256));
496         Assert((b >= 0) && (b < 256));
497
498 //      if ( r!=0 || g!=0 || b!=0 )     {
499 //              mprintf(( "Setcolor: %d,%d,%d\n", r,g,b ));
500 //      }
501         grx_init_color( &gr_screen.current_color, r, g, b );
502         Current_alphacolor = NULL;
503 }
504
505 void calc_alphacolor_hud_type_old( alphacolor_old * ac )
506 {
507         int i,j;
508         int tr,tg,tb, Sr, Sg, Sb;
509         ubyte * pal;
510         int r, g, b, alpha;
511         float falpha;
512
513         // Assert(Alphacolors_intited);
514
515 //      mprintf(( "Calculating alphacolor for %d,%d,%d,%d\n", ac->r, ac->g, ac->b, ac->alpha ));
516
517         falpha = i2fl(ac->alpha)/255.0f;
518         if ( falpha<0.0f ) falpha = 0.0f; else if ( falpha > 1.0f ) falpha = 1.0f;
519
520         alpha = ac->alpha >> 4;
521         if (alpha < 0 ) alpha = 0; else if (alpha > 15 ) alpha = 15;
522         r = ac->r;
523         if (r < 0 ) r = 0; else if (r > 255 ) r = 255;
524         g = ac->g;
525         if (g < 0 ) g = 0; else if (g > 255 ) g = 255;
526         b = ac->b;
527         if (b < 0 ) b = 0; else if (b > 255 ) b = 255;
528
529         int ii[16];
530
531         for (j=1; j<15; j++ )   {
532
533                 // JAS: Use 1.5/Gamma instead of 1/Gamma because on Adam's
534                 // PC a gamma of 1.2 makes text look good, but his gamma is
535                 // really 1.8.   1.8/1.2 = 1.5
536                 float factor = falpha * (float)pow(i2fl(j)/14.0f, 1.5f/Gr_gamma);
537                 //float factor = i2fl(j)/14.0f;
538
539                 tr = fl2i( i2fl(r) * factor );
540                 tg = fl2i( i2fl(g) * factor );
541                 tb = fl2i( i2fl(b) * factor );
542
543                 ii[j] = tr;
544                 if ( tg > ii[j] )       ii[j] = tg;
545                 if ( tb > ii[j] )       ii[j] = tb;
546         }
547
548         pal = gr_palette;
549
550         int m = r;
551         if ( g > m ) m = g;
552         if ( b > m ) m = b;
553
554         ubyte ri[256], gi[256], bi[256];
555
556         if ( m > 0 )    {
557                 for (i=0; i<256; i++ )  {
558                         ri[i] = ubyte((i*r)/m);
559                         gi[i] = ubyte((i*g)/m);
560                         bi[i] = ubyte((i*b)/m);
561                 }
562         } else {
563                 for (i=0; i<256; i++ )  {
564                         ri[i] = 0;
565                         gi[i] = 0;
566                         bi[i] = 0;
567                 }
568         }
569
570         for (i=0; i<256; i++ )  {
571                 Sr = pal[0];
572                 Sg = pal[1];
573                 Sb = pal[2];
574                 pal += 3;
575
576                 int dst_intensity = Sr;
577                 if ( Sg > dst_intensity ) dst_intensity = Sg;
578                 if ( Sb > dst_intensity ) dst_intensity = Sb;
579
580                 ac->table.lookup[0][i] = (unsigned char)i;
581
582                 for (j=1; j<15; j++ )   {
583
584                         int tmp_i = max( ii[j], dst_intensity );
585
586                         ac->table.lookup[j][i] = (unsigned char)palette_find(ri[tmp_i],gi[tmp_i],bi[tmp_i]);
587                 }
588
589                 float di = (i2fl(Sr)*.30f+i2fl(Sg)*0.60f+i2fl(Sb)*.10f)/255.0f;
590                 float factor = 0.0f + di*0.75f;
591
592                 tr = fl2i( factor*i2fl(r)*falpha );
593                 tg = fl2i( factor*i2fl(g)*falpha );
594                 tb = fl2i( factor*i2fl(b)*falpha );
595
596                 if ( tr > 255 ) tr = 255; else if ( tr < 0 ) tr = 0;
597                 if ( tg > 255 ) tg = 255; else if ( tg < 0 ) tg = 0; 
598                 if ( tb > 255 ) tb = 255; else if ( tb < 0 ) tb = 0;
599
600                 ac->table.lookup[15][i] = (unsigned char)palette_find(tr,tg,tb);
601                 //ac->table.lookup[15][i] = (unsigned char)palette_find(255,0,0);
602         }
603 }
604
605 void calc_alphacolor_old(alphacolor_old *ac)
606 {
607         Assert(Fred_running);
608         calc_alphacolor_hud_type_old(ac);
609 }