allow more light contributions to the grid; remove a weird fudge
[divverent/netradiant.git] / tools / quake3 / q3data / images.c
1 /*
2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #include "q3data.h"
23
24 byte                    *byteimage, *lbmpalette;
25 int                             byteimagewidth, byteimageheight;
26
27
28 char            mip_prefix[1024];               // directory to dump the textures in
29
30 qboolean        colormap_issued;
31 byte            colormap_palette[768];
32
33 /*
34 ==============
35 Cmd_Grab
36
37 $grab filename x y width height
38 ==============
39 */
40 void Cmd_Grab (void)
41 {
42         int             xl,yl,w,h,y;
43         byte                    *cropped;
44         char                    savename[1024];
45         char                    dest[1024];
46
47         GetToken (qfalse);
48
49         if (token[0] == '/' || token[0] == '\\')
50                 sprintf (savename, "%s%s.pcx", writedir, token+1);
51         else
52                 sprintf (savename, "%spics/%s.pcx", writedir, token);
53
54         if (g_release)
55         {
56                 if (token[0] == '/' || token[0] == '\\')
57                         sprintf (dest, "%s.pcx", token+1);
58                 else
59                         sprintf (dest, "pics/%s.pcx", token);
60
61                 ReleaseFile (dest);
62                 return;
63         }
64
65         GetToken (qfalse);
66         xl = atoi (token);
67         GetToken (qfalse);
68         yl = atoi (token);
69         GetToken (qfalse);
70         w = atoi (token);
71         GetToken (qfalse);
72         h = atoi (token);
73
74         if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
75                 Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
76
77         // crop it to the proper size
78         cropped = malloc (w*h);
79         for (y=0 ; y<h ; y++)
80         {
81                 memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
82         }
83
84         // save off the new image
85         printf ("saving %s\n", savename);
86         CreatePath (savename);
87         WritePCXfile (savename, cropped, w,     h, lbmpalette);
88
89         free (cropped);
90 }
91
92 /*
93 ==============
94 Cmd_Raw
95
96 $grab filename x y width height
97 ==============
98 */
99 void Cmd_Raw (void)
100 {
101         int             xl,yl,w,h,y;
102         byte                    *cropped;
103         char                    savename[1024];
104         char                    dest[1024];
105
106         GetToken (qfalse);
107
108         sprintf (savename, "%s%s.lmp", writedir, token);
109
110         if (g_release)
111         {
112                 sprintf (dest, "%s.lmp", token);
113                 ReleaseFile (dest);
114                 return;
115         }
116
117         GetToken (qfalse);
118         xl = atoi (token);
119         GetToken (qfalse);
120         yl = atoi (token);
121         GetToken (qfalse);
122         w = atoi (token);
123         GetToken (qfalse);
124         h = atoi (token);
125
126         if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
127                 Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
128
129         // crop it to the proper size
130         cropped = malloc (w*h);
131         for (y=0 ; y<h ; y++)
132         {
133                 memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
134         }
135
136         // save off the new image
137         printf ("saving %s\n", savename);
138         CreatePath (savename);
139
140         SaveFile (savename, cropped, w*h);
141
142         free (cropped);
143 }
144
145 /*
146 =============================================================================
147
148 COLORMAP GRABBING
149
150 =============================================================================
151 */
152
153 /*
154 ===============
155 BestColor
156 ===============
157 */
158 byte BestColor (int r, int g, int b, int start, int stop)
159 {
160         int     i;
161         int     dr, dg, db;
162         int     bestdistortion, distortion;
163         int     bestcolor;
164         byte    *pal;
165
166 //
167 // let any color go to 0 as a last resort
168 //
169         bestdistortion = 256*256*4;
170         bestcolor = 0;
171
172         pal = colormap_palette + start*3;
173         for (i=start ; i<= stop ; i++)
174         {
175                 dr = r - (int)pal[0];
176                 dg = g - (int)pal[1];
177                 db = b - (int)pal[2];
178                 pal += 3;
179                 distortion = dr*dr + dg*dg + db*db;
180                 if (distortion < bestdistortion)
181                 {
182                         if (!distortion)
183                                 return i;               // perfect match
184
185                         bestdistortion = distortion;
186                         bestcolor = i;
187                 }
188         }
189
190         return bestcolor;
191 }
192
193
194 /*
195 ==============
196 Cmd_Colormap
197
198 $colormap filename
199
200   the brightes colormap is first in the table (FIXME: reverse this now?)
201
202   64 rows of 256 : lightmaps
203   256 rows of 256 : translucency table
204 ==============
205 */
206 void Cmd_Colormap (void)
207 {
208         int             levels, brights;
209         int             l, c;
210         float   frac, red, green, blue;
211         float   range;
212         byte    *cropped, *lump_p;
213         char    savename[1024];
214         char    dest[1024];
215
216         colormap_issued = qtrue;
217         if (!g_release)
218                 memcpy (colormap_palette, lbmpalette, 768);
219
220         if (!TokenAvailable ())
221         {       // just setting colormap_issued
222                 return;
223         }
224
225         GetToken (qfalse);
226         sprintf (savename, "%spics/%s.pcx", writedir, token);
227
228         if (g_release)
229         {
230                 sprintf (dest, "pics/%s.pcx", token);
231                 ReleaseFile (dest);
232                 return;
233         }
234
235         range = 2;
236         levels = 64;
237         brights = 1;    // ignore 255 (transparent)
238
239         cropped = malloc((levels+256)*256);
240         lump_p = cropped;
241
242 // shaded levels
243         for (l=0;l<levels;l++)
244         {
245                 frac = range - range*(float)l/(levels-1);
246                 for (c=0 ; c<256-brights ; c++)
247                 {
248                         red = lbmpalette[c*3];
249                         green = lbmpalette[c*3+1];
250                         blue = lbmpalette[c*3+2];
251
252                         red = (int)(red*frac+0.5);
253                         green = (int)(green*frac+0.5);
254                         blue = (int)(blue*frac+0.5);
255                         
256 //
257 // note: 254 instead of 255 because 255 is the transparent color, and we
258 // don't want anything remapping to that
259 // don't use color 0, because NT can't remap that (or 255)
260 //
261                         *lump_p++ = BestColor(red,green,blue, 1, 254);
262                 }
263
264                 // fullbrights allways stay the same
265                 for ( ; c<256 ; c++)
266                         *lump_p++ = c;
267         }
268         
269 // 66% transparancy table
270         for (l=0;l<255;l++)
271         {
272                 for (c=0 ; c<255 ; c++)
273                 {
274                         red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
275                         green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
276                         blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
277
278                         *lump_p++ = BestColor(red,green,blue, 1, 254);
279                 }
280                 *lump_p++ = 255;
281         }
282         for (c=0 ; c<256 ; c++)
283                 *lump_p++ = 255;
284         
285         // save off the new image
286         printf ("saving %s\n", savename);
287         CreatePath (savename);
288         WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
289
290         free (cropped);
291 }
292
293 /*
294 =============================================================================
295
296 MIPTEX GRABBING
297
298 =============================================================================
299 */
300
301 byte    pixdata[256];
302
303 int             d_red, d_green, d_blue;
304
305 byte    palmap[32][32][32];
306 qboolean        palmap_built;
307
308 /*
309 =============
310 FindColor
311 =============
312 */
313 int FindColor (int r, int g, int b)
314 {
315         int             bestcolor;
316
317         if (r > 255)
318                 r = 255;
319         if (r < 0)
320                 r = 0;
321         if (g > 255)
322                 g = 255;
323         if (g < 0)
324                 g = 0;
325         if (b > 255)
326                 b = 255;
327         if (b < 0)
328                 b = 0;
329 #ifndef TABLECOLORS
330         bestcolor = BestColor (r, g, b, 0, 254);
331 #else
332         bestcolor = palmap[r>>3][g>>3][b>>3];
333 #endif
334
335         return bestcolor;
336 }
337
338
339 void BuildPalmap (void)
340 {
341 #ifdef TABLECOLORS
342         int             r, g, b;
343         int             bestcolor;
344
345         if (palmap_built)
346                 return;
347         palmap_built = qtrue;
348
349         for (r=4 ; r<256 ; r+=8)
350         {
351                 for (g=4 ; g<256 ; g+=8)
352                 {
353                         for (b=4 ; b<256 ; b+=8)
354                         {
355                                 bestcolor = BestColor (r, g, b, 1, 254);
356                                 palmap[r>>3][g>>3][b>>3] = bestcolor;
357                         }
358                 }
359         }
360 #endif
361
362         if (!colormap_issued)
363                 Error ("You must issue a $colormap command first");
364
365 }
366
367 /*
368 =============
369 AveragePixels
370 =============
371 */
372 byte AveragePixels (int count)
373 {
374         int             r,g,b;
375         int             i;
376         int             vis;
377         int             pix;
378         int             bestcolor;
379         byte    *pal;
380         int             fullbright;
381         
382         vis = 0;
383         r = g = b = 0;
384         fullbright = 0;
385         for (i=0 ; i<count ; i++)
386         {
387                 pix = pixdata[i];
388                 
389                 r += lbmpalette[pix*3];
390                 g += lbmpalette[pix*3+1];
391                 b += lbmpalette[pix*3+2];
392                 vis++;
393         }
394                 
395         r /= vis;
396         g /= vis;
397         b /= vis;
398
399         // error diffusion
400         r += d_red;
401         g += d_green;
402         b += d_blue;
403         
404 //
405 // find the best color
406 //
407         bestcolor = FindColor (r, g, b);
408
409         // error diffusion
410         pal = colormap_palette + bestcolor*3;
411         d_red = r - (int)pal[0];
412         d_green = g - (int)pal[1];
413         d_blue = b - (int)pal[2];
414
415         return bestcolor;
416 }
417
418
419
420 /*
421 =============================================================================
422
423 ENVIRONMENT MAP GRABBING
424
425 Creates six pcx files from tga files without any palette edge seams
426 also copies the tga files for GL rendering.
427 =============================================================================
428 */
429
430 // 3dstudio environment map suffixes
431 char    *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
432
433 /*
434 =================
435 Cmd_Environment
436 =================
437 */
438 void Cmd_Environment (void)
439 {
440         char    name[1024];
441         int             i, x, y;
442         byte    image[256*256];
443         byte    *tga;
444
445         GetToken (qfalse);
446
447         if (g_release)
448         {
449                 for (i=0 ; i<6 ; i++)
450                 {
451                         sprintf (name, "env/%s%s.pcx", token, suf[i]);
452                         ReleaseFile (name);
453                         sprintf (name, "env/%s%s.tga", token, suf[i]);
454                         ReleaseFile (name);
455                 }
456                 return;
457         }
458         // get the palette
459         BuildPalmap ();
460
461         sprintf (name, "%senv/", gamedir);
462         CreatePath (name);
463
464         // convert the images
465         for (i=0 ; i<6 ; i++)
466         {
467                 sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);
468                 printf ("loading %s...\n", name);
469                 LoadTGA (name, &tga, NULL, NULL);
470
471                 for (y=0 ; y<256 ; y++)
472                 {
473                         for (x=0 ; x<256 ; x++)
474                         {
475                                 image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);
476                         }
477                 }
478                 free (tga);
479                 sprintf (name, "%senv/%s%s.pcx", writedir, token, suf[i]);
480                 if (FileTime (name) != -1)
481                         printf ("%s already exists, not overwriting.\n", name);
482                 else
483                         WritePCXfile (name, image, 256, 256, colormap_palette);
484         }
485 }
486