]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/qdata_heretic2/images.c
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / images.c
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 #include "qdata.h"\r
23 \r
24 #ifdef _WIN32\r
25  #include <windows.h>\r
26 #endif\r
27 \r
28 #include <GL/gl.h>\r
29 \r
30 #if 1\r
31         extern char             *g_outputDir;\r
32 #endif // _QDATA\r
33 \r
34 char            mip_prefix[1024];               // directory to dump the textures in\r
35 \r
36 qboolean        colormap_issued;\r
37 byte            colormap_palette[768];\r
38 \r
39 unsigned total_x = 0;\r
40 unsigned total_y = 0;\r
41 unsigned total_textures = 0;\r
42 \r
43 #define MAX_IMAGE_SIZE 512\r
44 \r
45 #if     0\r
46 /*\r
47 ==============\r
48 RemapZero\r
49 \r
50 Replaces all 0 bytes in an image with the closest palette entry.\r
51 This is because NT won't let us change index 0, so any palette\r
52 animation leaves those pixels untouched.\r
53 ==============\r
54 */\r
55 void RemapZero (byte *pixels, byte *palette, int width, int height)\r
56 {\r
57         int             i, c;\r
58         int             alt_zero;\r
59         int             value, best;\r
60 \r
61         alt_zero = 0;\r
62         best = 9999999;\r
63         for (i=1 ; i<255 ; i++)\r
64         {\r
65                 value = palette[i*3+0]+palette[i*3+1]+palette[i*3+2];\r
66                 if (value < best)\r
67                 {\r
68                         best = value;\r
69                         alt_zero = i;\r
70                 }\r
71         }\r
72 \r
73         c = width*height;\r
74         for (i=0 ; i<c ; i++)\r
75                 if (pixels[i] == 0)\r
76                         pixels[i] = alt_zero;\r
77 }\r
78 \r
79 #endif\r
80 \r
81 \r
82 // ********************************************************************\r
83 // **  Mip Map Pre-Processing Routines\r
84 // ********************************************************************\r
85 \r
86 #define intensity_value 1\r
87 \r
88 static unsigned image_pal[256];\r
89 \r
90 #define MAX_LAST 25\r
91 \r
92 long palette_r[256], palette_g[256], palette_b[256];\r
93 long last_r[MAX_LAST],last_g[MAX_LAST],last_b[MAX_LAST], last_i[MAX_LAST], last_place;\r
94 \r
95 long cached;\r
96 \r
97 void PrepareConvert(unsigned *palette)\r
98 {\r
99         int i;\r
100 \r
101         for(i=0;i<256;i++)\r
102         {\r
103                 palette_r[i] = (palette[i] & 0x00ff0000) >> 16;\r
104                 palette_g[i] = (palette[i] & 0x0000ff00) >> 8;\r
105                 palette_b[i] = (palette[i] & 0x000000ff);\r
106         }\r
107 \r
108         for(i=0;i<MAX_LAST;i++)\r
109                 last_r[i] = -1;\r
110 \r
111         last_place = -1;\r
112 }\r
113 \r
114 int ConvertTrueColorToPal(unsigned r, unsigned g, unsigned b)\r
115 {\r
116         int i;\r
117         long min_dist;\r
118         int min_index;\r
119         long dist;\r
120         long dr, dg, db, biggest_delta;\r
121 \r
122         for(i=0;i<MAX_LAST;i++)\r
123                 if (r == last_r[i] && g == last_g[i] && b == last_b[i])\r
124                 {\r
125                         cached++;\r
126                         return last_i[i];\r
127                 }\r
128 \r
129         min_dist = 256 * 256 + 256 * 256 + 256 * 256;\r
130         biggest_delta = 256*256;\r
131         min_index = 0;\r
132 \r
133         for (i=0;i<256;i++)\r
134         {\r
135                 dr = abs(palette_r[i] - r);\r
136                 if (dr > biggest_delta)\r
137                         continue;\r
138                 dg = abs(palette_g[i] - g);\r
139                 if (dg > biggest_delta)\r
140                         continue;\r
141                 db = abs(palette_b[i] - b);\r
142                 if (db > biggest_delta)\r
143                         continue;\r
144 \r
145                 dist = dr * dr + dg * dg + db * db;\r
146                 if (dist < min_dist)\r
147                 {\r
148                         min_dist = dist;\r
149                         min_index = i;\r
150                         if (min_dist == 0) break;\r
151 \r
152                         dist = dr;\r
153                         if (dg > dist) dist = dg;\r
154                         if (db > dist) dist = db;\r
155                         if (dist < biggest_delta)\r
156                                 biggest_delta = dist;\r
157                 }\r
158         }\r
159 \r
160         last_place++;\r
161         if (last_place >= MAX_LAST)\r
162                 last_place = 0;\r
163 \r
164         last_r[last_place] = r;\r
165         last_g[last_place] = g;\r
166         last_b[last_place] = b;\r
167         last_i[last_place] = min_index;\r
168 \r
169         return min_index;\r
170 }\r
171 \r
172 \r
173 void GL_ResampleTexture8P (byte *in, int inwidth, int inheight, byte *out,  \r
174                                                    int outwidth, int outheight, palette_t *palette)\r
175 {\r
176         int             i, j;\r
177         byte    *inrow, *inrow2;\r
178         unsigned        frac, fracstep;\r
179         unsigned        p1[1024], p2[1024], *p1p, *p2p;\r
180         palette_t       *c1,*c2,*c3,*c4;\r
181         unsigned        r,g,b;\r
182         \r
183         fracstep = inwidth*0x10000/outwidth;\r
184 \r
185         frac = fracstep>>2;\r
186         for (i=0 ; i<outwidth ; i++)\r
187         {\r
188                 p1[i] = frac>>16;\r
189                 frac += fracstep;\r
190         }\r
191         frac = 3*(fracstep>>2);\r
192         for (i=0 ; i<outwidth ; i++)\r
193         {\r
194                 p2[i] = frac>>16;\r
195                 frac += fracstep;\r
196         }\r
197 \r
198         cached = 0;\r
199         \r
200         for (i=0 ; i<outheight ; i++)//, out += outwidth)\r
201         {\r
202                 inrow = in + inwidth*(int)((i+0.25)*inheight/outheight);\r
203                 inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight);\r
204 \r
205                 p1p = p1;\r
206                 p2p = p2;\r
207                 for (j=0 ; j<outwidth ; j++)\r
208                 {\r
209                         c1 = &palette[*((byte *)inrow + (*p1p))];\r
210                         c2 = &palette[*((byte *)inrow + (*p2p))];\r
211                         c3 = &palette[*((byte *)inrow2 + (*p1p++))];\r
212                         c4 = &palette[*((byte *)inrow2 + (*p2p++))];\r
213 \r
214                         r = ((unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r)>>2;\r
215                         g = ((unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g)>>2;\r
216                         b = ((unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b)>>2;\r
217 \r
218                         *out++ = ConvertTrueColorToPal(r,g,b);\r
219                 }\r
220         }\r
221 }\r
222 \r
223 void GL_MipMap8P(byte *out, byte *in, int width, int height, palette_t *palette)\r
224 {\r
225         int                     i, j;\r
226         palette_t       *c1,*c2,*c3,*c4;\r
227         unsigned        r,g,b;\r
228 \r
229         cached = 0;\r
230         memset(out, 0, 256 * 256);\r
231         width <<= 1;\r
232         height <<= 1;\r
233 \r
234         for (i = 0; i < height; i += 2, in += width)\r
235         {\r
236                 for (j = 0; j < width; j += 2)\r
237                 {\r
238                         c1 = &palette[in[0]];\r
239                         c3 = &palette[in[width]];\r
240                         in++;\r
241                         c2 = &palette[in[0]];\r
242                         c4 = &palette[in[width]];\r
243                         in++;\r
244 \r
245                         r = ((unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r) >> 2;\r
246                         g = ((unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g) >> 2;\r
247                         b = ((unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b) >> 2;\r
248 \r
249                         *out++ = ConvertTrueColorToPal(r, g, b);\r
250                 }\r
251         }\r
252 }\r
253 \r
254 \r
255 miptex_t *CreateMip(byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip)\r
256 {\r
257         int                     scaled_width, scaled_height;\r
258         int                     i,j,r,g,b;\r
259         byte            intensitytable[256];\r
260         byte            scaled[256*256];\r
261         byte            out[256*256];\r
262         int                     miplevel;\r
263         miptex_t        *mp;\r
264         byte            *pos;\r
265         int                     size;\r
266 \r
267         for (i=0 ; i<256 ; i++)\r
268         {\r
269                 j = i * intensity_value;\r
270                 if (j > 255)\r
271                         j = 255;\r
272                 intensitytable[i] = j;\r
273         }\r
274 \r
275         for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)\r
276                 ;\r
277         if (1 && scaled_width > width && 1)\r
278                 scaled_width >>= 1;\r
279         for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)\r
280                 ;\r
281         if (1 && scaled_height > height && 1)\r
282                 scaled_height >>= 1;\r
283 \r
284         // don't ever bother with >256 textures\r
285         if (scaled_width > 256)\r
286                 scaled_width = 256;\r
287         if (scaled_height > 256)\r
288                 scaled_height = 256;\r
289 \r
290         if (scaled_width < 1)\r
291                 scaled_width = 1;\r
292         if (scaled_height < 1)\r
293                 scaled_height = 1;\r
294 \r
295         size = sizeof(*mp) + (scaled_width*scaled_height*3);\r
296         mp = (miptex_t *)SafeMalloc(size, "CreateMip");\r
297         memset(mp,0,size);\r
298 \r
299         mp->version = MIP_VERSION;\r
300 \r
301         for(i=j=0;i<256;i++,j+=3)\r
302         {\r
303                 mp->palette[i].r = r = intensitytable[palette[j]];\r
304                 mp->palette[i].g = g = intensitytable[palette[j+1]];\r
305                 mp->palette[i].b = b = intensitytable[palette[j+2]];\r
306                 image_pal[i] = 0xff000000 | (r<<16) | (g<<8) | (b);\r
307         }\r
308 \r
309         PrepareConvert(image_pal);\r
310 \r
311         if (scaled_width == width && scaled_height == height)\r
312         {\r
313                 memcpy (scaled, data, width*height);\r
314         }\r
315         else\r
316                 GL_ResampleTexture8P (data, width, height, scaled, scaled_width, scaled_height, mp->palette);\r
317 \r
318         pos = (byte *)(mp + 1);\r
319         miplevel = 0;\r
320 \r
321         while ((scaled_width >= 1 || scaled_height >= 1) && (miplevel <= MIPLEVELS-1) && (!miplevel || mip))\r
322         {\r
323                 if (scaled_width < 1)\r
324                         scaled_width = 1;\r
325                 if (scaled_height < 1)\r
326                         scaled_height = 1;\r
327 \r
328                 if(miplevel > 0)\r
329                         GL_MipMap8P(out, (byte *)scaled, scaled_width, scaled_height, mp->palette);\r
330                 else\r
331                         memcpy(out, scaled, 256 * 256);\r
332 \r
333                 mp->width[miplevel] = scaled_width;\r
334                 mp->height[miplevel] = scaled_height;\r
335                 mp->offsets[miplevel] = pos - ((byte *)(mp));\r
336                 memcpy(pos, out, scaled_width * scaled_height);\r
337                 memcpy(scaled, out, 256 * 256);\r
338                 pos += scaled_width * scaled_height;\r
339 \r
340                 scaled_width >>= 1;\r
341                 scaled_height >>= 1;\r
342 \r
343                 miplevel++;\r
344         }\r
345 \r
346         *FinalSize = pos - ((byte *)(mp));\r
347 \r
348         return mp;\r
349 }\r
350 \r
351 \r
352 void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out,  int outwidth, int outheight)\r
353 {\r
354         int             i, j;\r
355         unsigned        *inrow, *inrow2;\r
356         unsigned        frac, fracstep;\r
357         unsigned        p1[1024], p2[1024];\r
358         byte            *pix1, *pix2, *pix3, *pix4;\r
359 \r
360         fracstep = inwidth*0x10000/outwidth;\r
361 \r
362         frac = fracstep>>2;\r
363         for (i=0 ; i<outwidth ; i++)\r
364         {\r
365                 p1[i] = 4*(frac>>16);\r
366                 frac += fracstep;\r
367         }\r
368         frac = 3*(fracstep>>2);\r
369         for (i=0 ; i<outwidth ; i++)\r
370         {\r
371                 p2[i] = 4*(frac>>16);\r
372                 frac += fracstep;\r
373         }\r
374 \r
375         for (i=0 ; i<outheight ; i++, out += outwidth)\r
376         {\r
377                 inrow = in + inwidth*(int)((i+0.25)*inheight/outheight);\r
378                 inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight);\r
379                 frac = fracstep >> 1;\r
380                 for (j=0 ; j<outwidth ; j++)\r
381                 {\r
382                         pix1 = (byte *)inrow + p1[j];\r
383                         pix2 = (byte *)inrow + p2[j];\r
384                         pix3 = (byte *)inrow2 + p1[j];\r
385                         pix4 = (byte *)inrow2 + p2[j];\r
386                         ((byte *)(out+j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2;\r
387                         ((byte *)(out+j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2;\r
388                         ((byte *)(out+j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2;\r
389                         ((byte *)(out+j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2;\r
390                 }\r
391         }\r
392 }\r
393 \r
394 void GL_MipMap (byte *out, byte *in, int width, int height)\r
395 {\r
396         int             i, j;\r
397 \r
398         width <<=3;\r
399         height <<= 1;\r
400         for (i=0 ; i<height ; i++, in+=width)\r
401         {\r
402                 for (j=0 ; j<width ; j+=8, out+=4, in+=8)\r
403                 {\r
404                         out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;\r
405                         out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;\r
406                         out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;\r
407                         out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;\r
408                 }\r
409         }\r
410 }\r
411 \r
412 miptex32_t *CreateMip32(unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip)\r
413 {\r
414         int                             scaled_width, scaled_height;\r
415         unsigned                scaled[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];\r
416         unsigned                out[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];\r
417         int                             miplevel;\r
418         miptex32_t              *mp;\r
419         byte                    *pos;\r
420         int                             size;\r
421         paletteRGBA_t   *test;\r
422 \r
423         for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)\r
424                 ;\r
425         if (1 && scaled_width > width && 1)\r
426                 scaled_width >>= 1;\r
427         for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)\r
428                 ;\r
429         if (1 && scaled_height > height && 1)\r
430                 scaled_height >>= 1;\r
431 \r
432         // don't ever bother with >256 textures\r
433         if (scaled_width > MAX_IMAGE_SIZE)\r
434                 scaled_width = MAX_IMAGE_SIZE;\r
435         if (scaled_height > MAX_IMAGE_SIZE)\r
436                 scaled_height = MAX_IMAGE_SIZE;\r
437 \r
438         if (scaled_width < 1)\r
439                 scaled_width = 1;\r
440         if (scaled_height < 1)\r
441                 scaled_height = 1;\r
442 \r
443         size = sizeof(*mp) + (scaled_width*scaled_height*3*4);\r
444         mp = (miptex32_t *)SafeMalloc(size, "CreateMip");\r
445         memset(mp,0,size);\r
446 \r
447         mp->version = MIP32_VERSION;\r
448 \r
449         size = width*height;\r
450         test = (paletteRGBA_t *)data;\r
451         while(size)\r
452         {\r
453                 if (test->a != 255)\r
454                 {\r
455                         mp->flags |= LittleLong(SURF_ALPHA_TEXTURE);\r
456                         break;\r
457                 }\r
458 \r
459                 size--;\r
460                 test++;\r
461         }\r
462 \r
463         if (scaled_width == width && scaled_height == height)\r
464         {\r
465                 memcpy (scaled, data, width*height*4);\r
466         }\r
467         else\r
468                 GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);\r
469 \r
470         pos = (byte *)(mp + 1);\r
471         miplevel = 0;\r
472 \r
473         while ((scaled_width >= 1 || scaled_height >= 1) && (miplevel <= MIPLEVELS-1) && (!miplevel || mip))\r
474         {\r
475                 if (scaled_width < 1)\r
476                         scaled_width = 1;\r
477                 if (scaled_height < 1)\r
478                         scaled_height = 1;\r
479 \r
480                 if (miplevel > 0)\r
481                 {\r
482                         GL_MipMap((byte *)out, (byte *)scaled, scaled_width, scaled_height);\r
483                 }\r
484                 else\r
485                 {\r
486                         memcpy(out, scaled, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4);\r
487                 }\r
488 \r
489                 mp->width[miplevel] = scaled_width;\r
490                 mp->height[miplevel] = scaled_height;\r
491                 mp->offsets[miplevel] = pos - ((byte *)(mp));\r
492                 memcpy(pos, out, scaled_width * scaled_height * 4);\r
493                 memcpy(scaled, out, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4);\r
494                 pos += scaled_width * scaled_height * 4;\r
495 \r
496                 scaled_width >>= 1;\r
497                 scaled_height >>= 1;\r
498 \r
499                 miplevel++;\r
500         }\r
501 \r
502         *FinalSize = pos - ((byte *)(mp));\r
503 \r
504         return mp;\r
505 }\r
506 \r
507 /*\r
508 ==============\r
509 Cmd_Grab\r
510 \r
511 $grab filename x y width height\r
512 ==============\r
513 */\r
514 void Cmd_Grab (void)\r
515 {\r
516         int             xl,yl,w,h,y;\r
517         byte                    *cropped;\r
518         char                    savename[1024];\r
519         char                    dest[1024];\r
520 \r
521         GetScriptToken (false);\r
522 \r
523         if (token[0] == '/' || token[0] == '\\')\r
524                 sprintf (savename, "%s%s.pcx", gamedir, token+1);\r
525         else\r
526                 sprintf (savename, "%spics/%s.pcx", gamedir, token);\r
527 \r
528         if (g_release)\r
529         {\r
530                 if (token[0] == '/' || token[0] == '\\')\r
531                         sprintf (dest, "%s.pcx", token+1);\r
532                 else\r
533                         sprintf (dest, "pics/%s.pcx", token);\r
534 \r
535                 ReleaseFile (dest);\r
536                 return;\r
537         }\r
538 \r
539         GetScriptToken (false);\r
540         xl = atoi (token);\r
541         GetScriptToken (false);\r
542         yl = atoi (token);\r
543         GetScriptToken (false);\r
544         w = atoi (token);\r
545         GetScriptToken (false);\r
546         h = atoi (token);\r
547 \r
548         if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)\r
549                 Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);\r
550 \r
551         // crop it to the proper size\r
552         cropped = (byte *) SafeMalloc (w*h, "Cmd_Grab");\r
553         for (y=0 ; y<h ; y++)\r
554         {\r
555                 memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);\r
556         }\r
557 \r
558         // save off the new image\r
559         printf ("saving %s\n", savename);\r
560         CreatePath (savename);\r
561         WritePCXfile (savename, cropped, w,     h, lbmpalette);\r
562 \r
563         free (cropped);\r
564 }\r
565 \r
566 /*\r
567 ==============\r
568 Cmd_Raw\r
569 \r
570 $grab filename x y width height\r
571 ==============\r
572 */\r
573 void Cmd_Raw (void)\r
574 {\r
575         int             xl,yl,w,h,y;\r
576         byte                    *cropped;\r
577         char                    savename[1024];\r
578         char                    dest[1024];\r
579 \r
580         GetScriptToken (false);\r
581 \r
582         sprintf (savename, "%s%s.lmp", gamedir, token);\r
583 \r
584         if (g_release)\r
585         {\r
586                 sprintf (dest, "%s.lmp", token);\r
587                 ReleaseFile (dest);\r
588                 return;\r
589         }\r
590 \r
591         GetScriptToken (false);\r
592         xl = atoi (token);\r
593         GetScriptToken (false);\r
594         yl = atoi (token);\r
595         GetScriptToken (false);\r
596         w = atoi (token);\r
597         GetScriptToken (false);\r
598         h = atoi (token);\r
599 \r
600         if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)\r
601                 Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);\r
602 \r
603         // crop it to the proper size\r
604         cropped = (byte *) SafeMalloc (w*h, "Cmd_Raw");\r
605         for (y=0 ; y<h ; y++)\r
606         {\r
607                 memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);\r
608         }\r
609 \r
610         // save off the new image\r
611         printf ("saving %s\n", savename);\r
612         CreatePath (savename);\r
613 \r
614         SaveFile (savename, cropped, w*h);\r
615 \r
616         free (cropped);\r
617 }\r
618 \r
619 /*\r
620 =============================================================================\r
621 \r
622 COLORMAP GRABBING\r
623 \r
624 =============================================================================\r
625 */\r
626 \r
627 /*\r
628 ===============\r
629 BestColor\r
630 ===============\r
631 */\r
632 byte BestColor (int r, int g, int b, int start, int stop)\r
633 {\r
634         int     i;\r
635         int     dr, dg, db;\r
636         int     bestdistortion, distortion;\r
637         int     bestcolor;\r
638         byte    *pal;\r
639 \r
640 //\r
641 // let any color go to 0 as a last resort\r
642 //\r
643         bestdistortion = 256*256*4;\r
644         bestcolor = 0;\r
645 \r
646         pal = colormap_palette + start*3;\r
647         for (i=start ; i<= stop ; i++)\r
648         {\r
649                 dr = r - (int)pal[0];\r
650                 dg = g - (int)pal[1];\r
651                 db = b - (int)pal[2];\r
652                 pal += 3;\r
653                 distortion = dr*dr + dg*dg + db*db;\r
654                 if (distortion < bestdistortion)\r
655                 {\r
656                         if (!distortion)\r
657                                 return i;               // perfect match\r
658 \r
659                         bestdistortion = distortion;\r
660                         bestcolor = i;\r
661                 }\r
662         }\r
663 \r
664         return bestcolor;\r
665 }\r
666 \r
667 \r
668 /*\r
669 ==============\r
670 Cmd_Colormap\r
671 \r
672 $colormap filename\r
673 \r
674   the brightes colormap is first in the table (FIXME: reverse this now?)\r
675 \r
676   64 rows of 256 : lightmaps\r
677   256 rows of 256 : translucency table\r
678 ==============\r
679 */\r
680 void Cmd_Colormap (void)\r
681 {\r
682         int             levels, brights;\r
683         int             l, c;\r
684         float   frac, red, green, blue;\r
685         float   range;\r
686         byte    *cropped, *lump_p;\r
687         char    savename[1024];\r
688         char    dest[1024];\r
689 \r
690         colormap_issued = true;\r
691         if (!g_release)\r
692                 memcpy (colormap_palette, lbmpalette, 768);\r
693 \r
694         if (!ScriptTokenAvailable ())\r
695         {       // just setting colormap_issued\r
696                 return;\r
697         }\r
698 \r
699         GetScriptToken (false);\r
700         sprintf (savename, "%spics/%s.pcx", gamedir, token);\r
701 \r
702         if (g_release)\r
703         {\r
704                 sprintf (dest, "pics/%s.pcx", token);\r
705                 ReleaseFile (dest);\r
706                 return;\r
707         }\r
708 \r
709         range = 2;\r
710         levels = 64;\r
711         brights = 1;    // ignore 255 (transparent)\r
712 \r
713         cropped = (byte *) SafeMalloc((levels+256)*256, "Cmd_ColorMap");\r
714         lump_p = cropped;\r
715 \r
716 // shaded levels\r
717         for (l=0;l<levels;l++)\r
718         {\r
719                 frac = range - range*(float)l/(levels-1);\r
720                 for (c=0 ; c<256-brights ; c++)\r
721                 {\r
722                         red = lbmpalette[c*3];\r
723                         green = lbmpalette[c*3+1];\r
724                         blue = lbmpalette[c*3+2];\r
725 \r
726                         red = (int)(red*frac+0.5);\r
727                         green = (int)(green*frac+0.5);\r
728                         blue = (int)(blue*frac+0.5);\r
729                         \r
730 //\r
731 // note: 254 instead of 255 because 255 is the transparent color, and we\r
732 // don't want anything remapping to that\r
733 // don't use color 0, because NT can't remap that (or 255)\r
734 //\r
735                         *lump_p++ = BestColor(red,green,blue, 1, 254);\r
736                 }\r
737 \r
738                 // fullbrights allways stay the same\r
739                 for ( ; c<256 ; c++)\r
740                         *lump_p++ = c;\r
741         }\r
742         \r
743 // 66% transparancy table\r
744         for (l=0;l<255;l++)\r
745         {\r
746                 for (c=0 ; c<255 ; c++)\r
747                 {\r
748                         red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;\r
749                         green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;\r
750                         blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;\r
751 \r
752                         *lump_p++ = BestColor(red,green,blue, 1, 254);\r
753                 }\r
754                 *lump_p++ = 255;\r
755         }\r
756         for (c=0 ; c<256 ; c++)\r
757                 *lump_p++ = 255;\r
758         \r
759         // save off the new image\r
760         printf ("saving %s\n", savename);\r
761         CreatePath (savename);\r
762         WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);\r
763 \r
764         free (cropped);\r
765 }\r
766 \r
767 /*\r
768 =============================================================================\r
769 \r
770 MIPTEX GRABBING\r
771 \r
772 =============================================================================\r
773 */\r
774 \r
775 byte    pixdata[256];\r
776 \r
777 int             d_red, d_green, d_blue;\r
778 \r
779 byte    palmap[32][32][32];\r
780 qboolean        palmap_built;\r
781 \r
782 /*\r
783 =============\r
784 FindColor\r
785 =============\r
786 */\r
787 int FindColor (int r, int g, int b)\r
788 {\r
789         int             bestcolor;\r
790 \r
791         if (r > 255)\r
792                 r = 255;\r
793         if (r < 0)\r
794                 r = 0;\r
795         if (g > 255)\r
796                 g = 255;\r
797         if (g < 0)\r
798                 g = 0;\r
799         if (b > 255)\r
800                 b = 255;\r
801         if (b < 0)\r
802                 b = 0;\r
803 #ifndef TABLECOLORS\r
804         bestcolor = BestColor (r, g, b, 0, 254);\r
805 #else\r
806         bestcolor = palmap[r>>3][g>>3][b>>3];\r
807 #endif\r
808 \r
809         return bestcolor;\r
810 }\r
811 \r
812 \r
813 void BuildPalmap (void)\r
814 {\r
815 #ifdef TABLECOLORS\r
816         int             r, g, b;\r
817         int             bestcolor;\r
818 \r
819         if (palmap_built)\r
820                 return;\r
821         palmap_built = true;\r
822 \r
823         for (r=4 ; r<256 ; r+=8)\r
824         {\r
825                 for (g=4 ; g<256 ; g+=8)\r
826                 {\r
827                         for (b=4 ; b<256 ; b+=8)\r
828                         {\r
829                                 bestcolor = BestColor (r, g, b, 1, 254);\r
830                                 palmap[r>>3][g>>3][b>>3] = bestcolor;\r
831                         }\r
832                 }\r
833         }\r
834 #endif\r
835 \r
836         if (!colormap_issued)\r
837                 Error ("You must issue a $colormap command first");\r
838 \r
839 }\r
840 \r
841 /*\r
842 =============\r
843 AveragePixels\r
844 =============\r
845 */\r
846 byte AveragePixels (int count)\r
847 {\r
848         int             r,g,b;\r
849         int             i;\r
850         int             vis;\r
851         int             pix;\r
852         int             bestcolor;\r
853         byte    *pal;\r
854         int             fullbright;\r
855         \r
856         vis = 0;\r
857         r = g = b = 0;\r
858         fullbright = 0;\r
859         for (i=0 ; i<count ; i++)\r
860         {\r
861                 pix = pixdata[i];\r
862                 \r
863                 r += lbmpalette[pix*3];\r
864                 g += lbmpalette[pix*3+1];\r
865                 b += lbmpalette[pix*3+2];\r
866                 vis++;\r
867         }\r
868                 \r
869         r /= vis;\r
870         g /= vis;\r
871         b /= vis;\r
872 \r
873         // error diffusion\r
874         r += d_red;\r
875         g += d_green;\r
876         b += d_blue;\r
877         \r
878 //\r
879 // find the best color\r
880 //\r
881         bestcolor = FindColor (r, g, b);\r
882 \r
883         // error diffusion\r
884         pal = colormap_palette + bestcolor*3;\r
885         d_red = r - (int)pal[0];\r
886         d_green = g - (int)pal[1];\r
887         d_blue = b - (int)pal[2];\r
888 \r
889         return bestcolor;\r
890 }\r
891 \r
892 \r
893 typedef enum\r
894 {\r
895         pt_contents,\r
896         pt_flags,\r
897         pt_animvalue,\r
898         pt_altnamevalue,\r
899         pt_damagenamevalue,\r
900         pt_flagvalue,\r
901         pt_materialvalue,\r
902         pt_scale,\r
903         pt_mip,\r
904         pt_detail,\r
905         pt_gl,\r
906         pt_nomip,\r
907         pt_detailer,\r
908 } parmtype_t;\r
909 \r
910 typedef struct\r
911 {\r
912         char    *name;\r
913         int             flags;\r
914         parmtype_t      type;\r
915 } mipparm_t;\r
916 \r
917 mipparm_t       mipparms[] =\r
918 {\r
919         // utility content attributes\r
920         {"pushpull",CONTENTS_PUSHPULL, pt_contents},\r
921         {"water",       CONTENTS_WATER, pt_contents},\r
922         {"slime",       CONTENTS_SLIME, pt_contents},           // mildly damaging\r
923         {"lava",        CONTENTS_LAVA, pt_contents},            // very damaging\r
924         {"window",      CONTENTS_WINDOW, pt_contents},  // solid, but doesn't eat internal textures\r
925         {"mist",        CONTENTS_MIST, pt_contents},    // non-solid window\r
926         {"origin",      CONTENTS_ORIGIN, pt_contents},  // center of rotating brushes\r
927         {"playerclip",  CONTENTS_PLAYERCLIP, pt_contents},\r
928         {"monsterclip", CONTENTS_MONSTERCLIP, pt_contents},\r
929 \r
930         // utility surface attributes\r
931         {"hint",        SURF_HINT, pt_flags},\r
932         {"skip",        SURF_SKIP, pt_flags},\r
933         {"light",       SURF_LIGHT, pt_flagvalue},              // value is the light quantity\r
934 \r
935         {"animspeed",SURF_ANIMSPEED, pt_flagvalue},             // value will hold the anim speed in fps\r
936 \r
937         // texture chaining\r
938         {"anim",        0,                      pt_animvalue},          // animname is the next animation\r
939         {"alt",         0,                      pt_altnamevalue},       // altname is the alternate texture\r
940         {"damage",      0,                      pt_damagenamevalue},    // damagename is the damage texture\r
941         {"scale",       0,                      pt_scale},              // next two values are for scale\r
942         {"mip",         0,                      pt_mip},                \r
943         {"detail",      0,                      pt_detail},             \r
944 \r
945         {"GL_ZERO",                                     GL_ZERO,                                pt_gl},\r
946         {"GL_ONE",                                      GL_ONE,                                 pt_gl},\r
947         {"GL_SRC_COLOR",                        GL_SRC_COLOR,                   pt_gl},\r
948         {"GL_ONE_MINUS_SRC_COLOR",      GL_ONE_MINUS_SRC_COLOR, pt_gl},\r
949         {"GL_DST_COLOR",                        GL_DST_COLOR,                   pt_gl},\r
950         {"GL_ONE_MINUS_DST_COLOR",      GL_ONE_MINUS_DST_COLOR, pt_gl},\r
951         {"GL_SRC_ALPHA",                        GL_SRC_ALPHA,                   pt_gl},\r
952         {"GL_ONE_MINUS_SRC_ALPHA",      GL_ONE_MINUS_SRC_ALPHA, pt_gl},\r
953         {"GL_DST_ALPHA",                        GL_DST_ALPHA,                   pt_gl},\r
954         {"GL_ONE_MINUS_DST_ALPHA",      GL_ONE_MINUS_DST_ALPHA, pt_gl},\r
955         {"GL_SRC_ALPHA_SATURATE",       GL_SRC_ALPHA_SATURATE,  pt_gl},\r
956 \r
957         // server attributes\r
958         {"slick",       SURF_SLICK, pt_flags},\r
959 \r
960         // drawing attributes\r
961         {"sky",         SURF_SKY, pt_flags},\r
962         {"warping",     SURF_WARP, pt_flags},           // only valid with 64x64 textures\r
963         {"trans33",     SURF_TRANS33, pt_flags},        // translucent should allso set fullbright\r
964         {"trans66",     SURF_TRANS66, pt_flags},\r
965         {"flowing",     SURF_FLOWING, pt_flags},        // flow direction towards angle 0\r
966         {"nodraw",      SURF_NODRAW, pt_flags}, // for clip textures and trigger textures\r
967         {"alpha",       SURF_ALPHA_TEXTURE, pt_flags},\r
968         {"undulate",    SURF_UNDULATE, pt_flags},               // rock surface up and down...\r
969         {"skyreflect",  SURF_SKYREFLECT, pt_flags},             // liquid will somewhat reflect the sky - not quite finished....\r
970 \r
971         {"material", SURF_MATERIAL, pt_materialvalue},\r
972         {"metal",       SURF_TYPE_METAL, pt_flags},\r
973         {"stone",       SURF_TYPE_STONE, pt_flags},\r
974         {"wood",        SURF_TYPE_WOOD, pt_flags},\r
975 \r
976         {"m_nomip", 0, pt_nomip},\r
977         {"m_detail", 0, pt_detailer},\r
978 \r
979         {NULL, 0, pt_contents}\r
980 };\r
981 \r
982 /*\r
983 ==============\r
984 Cmd_Mip\r
985 \r
986 $mip filename x y width height <OPTIONS>\r
987 must be multiples of sixteen\r
988 SURF_WINDOW\r
989 ==============\r
990 */\r
991 \r
992 void Cmd_Mip (void)\r
993 {\r
994         int             xl,yl,xh,yh,w,h;\r
995         byte            *dest, *source;\r
996         int                             flags, value, contents;\r
997         mipparm_t               *mp;\r
998         char                    lumpname[128];\r
999         char                    altname[128];\r
1000         char                    animname[128];\r
1001         char                    damagename[128];\r
1002         byte                    buffer[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];\r
1003         unsigned                bufferl[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];\r
1004         materialtype_t  *mat;\r
1005         char                    filename[1024];\r
1006         unsigned        *destl, *sourcel;\r
1007         int             linedelta, x, y;\r
1008         int                             size;\r
1009         miptex_t                *qtex;\r
1010         miptex32_t              *qtex32;\r
1011         float                   scale_x, scale_y;\r
1012         int                             mip_scale;\r
1013         // detail texturing\r
1014         char                    dt_name[128];\r
1015         float                   dt_scale_x, dt_scale_y;\r
1016         float                   dt_u, dt_v;\r
1017         float                   dt_alpha;\r
1018         int                             dt_src_blend_mode, dt_dst_blend_mode;\r
1019         int                             flags2;\r
1020 \r
1021 \r
1022         GetScriptToken (false);\r
1023         strcpy (lumpname, token);\r
1024         \r
1025         GetScriptToken (false);\r
1026         xl = atoi (token);\r
1027         GetScriptToken (false);\r
1028         yl = atoi (token);\r
1029         GetScriptToken (false);\r
1030         w = atoi (token);\r
1031         GetScriptToken (false);\r
1032         h = atoi (token);\r
1033 \r
1034         total_x += w;\r
1035         total_y += h;\r
1036         total_textures++;\r
1037 \r
1038         if ( (w & 15) || (h & 15) )\r
1039                 Error ("line %i: miptex sizes must be multiples of 16", scriptline);\r
1040 \r
1041         flags = 0;\r
1042         flags2 = 0;\r
1043         contents = 0;\r
1044         value = 0;\r
1045         mip_scale = 0;\r
1046 \r
1047         altname[0] = animname[0] = damagename[0] = 0;\r
1048 \r
1049         scale_x = scale_y = 0.5;\r
1050 \r
1051         // detail texturing\r
1052         dt_name[0] = 0;\r
1053         dt_scale_x = dt_scale_y = 0.0;\r
1054         dt_u = dt_v = 0.0;\r
1055         dt_alpha = 0.0;\r
1056         dt_src_blend_mode = dt_dst_blend_mode = 0;\r
1057 \r
1058         // get optional flags and values\r
1059         while (ScriptTokenAvailable ())\r
1060         {\r
1061                 GetScriptToken (false);\r
1062         \r
1063                 for (mp=mipparms ; mp->name ; mp++)\r
1064                 {\r
1065                         if (!strcmp(mp->name, token))\r
1066                         {\r
1067                                 switch (mp->type)\r
1068                                 {\r
1069                                         case pt_animvalue:\r
1070                                                 GetScriptToken (false); // specify the next animation frame\r
1071                                                 strcpy (animname, token);\r
1072                                                 break;\r
1073                                         case pt_altnamevalue:\r
1074                                                 GetScriptToken (false); // specify the alternate texture\r
1075                                                 strcpy (altname, token);\r
1076                                                 break;\r
1077                                         case pt_damagenamevalue:\r
1078                                                 GetScriptToken (false); // specify the damage texture\r
1079                                                 strcpy (damagename, token);\r
1080                                                 break;\r
1081                                         case pt_flags:\r
1082                                                 flags |= mp->flags;\r
1083                                                 break;\r
1084                                         case pt_contents:\r
1085                                                 contents |= mp->flags;\r
1086                                                 break;\r
1087                                         case pt_flagvalue:\r
1088                                                 flags |= mp->flags;\r
1089                                                 GetScriptToken (false); // specify the light value\r
1090                                                 value = atoi(token);\r
1091                                                 break;\r
1092                                         case pt_materialvalue:\r
1093                                                 GetScriptToken(false);\r
1094                                                 for (mat=materialtypes ; mat->name ; mat++)\r
1095                                                 {\r
1096                                                         if (!strcmp(mat->name, token))\r
1097                                                         {\r
1098                                                                 // assumes SURF_MATERIAL is in top 8 bits\r
1099                                                                 flags = (flags & 0x0FFFFFF) | (mat->value << 24);\r
1100                                                                 break;\r
1101                                                         }\r
1102                                                 }\r
1103                                                 break;\r
1104                                         case pt_scale:\r
1105                                                 GetScriptToken (false); // specify the x scale\r
1106                                                 scale_x = atof(token);\r
1107                                                 GetScriptToken (false); // specify the y scale\r
1108                                                 scale_y = atof(token);\r
1109                                                 break;\r
1110 \r
1111                                         case pt_mip:\r
1112                                                 mip_scale = 1;\r
1113                                                 break;\r
1114 \r
1115                                         case pt_detailer:\r
1116                                                 flags2 |= MIP32_DETAILER_FLAG2;\r
1117                                                 break;\r
1118 \r
1119                                         case pt_nomip:\r
1120                                                 flags2 |= MIP32_NOMIP_FLAG2;\r
1121                                                 break;\r
1122 \r
1123                                         case pt_detail:\r
1124                                                 GetScriptToken(false);\r
1125                                                 strcpy(dt_name, token);\r
1126                                                 GetScriptToken(false);\r
1127                                                 dt_scale_x = atof(token);\r
1128                                                 GetScriptToken(false);\r
1129                                                 dt_scale_y = atof(token);\r
1130                                                 GetScriptToken(false);\r
1131                                                 dt_u = atof(token);\r
1132                                                 GetScriptToken(false);\r
1133                                                 dt_v = atof(token);\r
1134                                                 GetScriptToken(false);\r
1135                                                 dt_alpha = atof(token);\r
1136                                                 GetScriptToken(false);\r
1137                                                 for (mp=mipparms ; mp->name ; mp++)\r
1138                                                 {\r
1139                                                         if (!strcmp(mp->name, token))\r
1140                                                         {\r
1141                                                                 if (mp->type == pt_gl)\r
1142                                                                 {\r
1143                                                                         dt_src_blend_mode = mp->flags;\r
1144                                                                         break;\r
1145                                                                 }\r
1146                                                         }\r
1147                                                 }\r
1148                                                 if (!mp->name)\r
1149                                                 {\r
1150                                                         Error ("line %i: invalid gl blend mode %s", scriptline, token);\r
1151                                                 }\r
1152                                                 GetScriptToken (false);\r
1153                                                 for (mp=mipparms ; mp->name ; mp++)\r
1154                                                 {\r
1155                                                         if (!strcmp(mp->name, token))\r
1156                                                         {\r
1157                                                                 if (mp->type == pt_gl)\r
1158                                                                 {\r
1159                                                                         dt_dst_blend_mode = mp->flags;\r
1160                                                                         break;\r
1161                                                                 }\r
1162                                                         }\r
1163                                                 }\r
1164                                                 if (!mp->name)\r
1165                                                 {\r
1166                                                         Error ("line %i: invalid gl blend mode %s", scriptline, token);\r
1167                                                 }\r
1168                                                 break;\r
1169                                 }\r
1170                                 break;\r
1171                         }\r
1172                 }\r
1173                 if (!mp->name)\r
1174                         Error ("line %i: unknown parm %s", scriptline, token);\r
1175         }\r
1176 \r
1177         if (g_release)\r
1178                 return; // textures are only released by $maps\r
1179 \r
1180         xh = xl+w;\r
1181         yh = yl+h;\r
1182         if (xh*yh > MAX_IMAGE_SIZE*MAX_IMAGE_SIZE)\r
1183         {\r
1184                 Error("line %i image %s: image is too big!", scriptline, lumpname);\r
1185         }\r
1186                 \r
1187         if (TrueColorImage)\r
1188         {\r
1189                 if (xl >= longimagewidth || xh > longimagewidth ||\r
1190                         yl >= longimageheight || yh > longimageheight)\r
1191                 {\r
1192                         Error ("line %i image %s: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, lumpname, xl,yl,w,h,longimagewidth,longimageheight);\r
1193                 }\r
1194 \r
1195                 sourcel = longimage + (yl*longimagewidth) + xl;\r
1196                 destl = bufferl;\r
1197                 linedelta = (longimagewidth - w);\r
1198 \r
1199                 for (y=yl ; y<yh ; y++)\r
1200                 {\r
1201                         for (x=xl ; x<xh ; x++)\r
1202                         {\r
1203                                 *destl++ = *sourcel++;  // RGBA\r
1204                         }\r
1205                         sourcel += linedelta;\r
1206                 }\r
1207 \r
1208                 qtex32 = CreateMip32(bufferl, w, h, &size, true);\r
1209 \r
1210                 qtex32->flags |= LittleLong(flags);\r
1211                 qtex32->flags2 |= LittleLong(flags2);\r
1212                 qtex32->contents = LittleLong(contents);\r
1213                 qtex32->value = LittleLong(value);\r
1214                 qtex32->scale_x = scale_x;\r
1215                 qtex32->scale_y = scale_y;\r
1216                 qtex32->mip_scale = mip_scale;\r
1217                 sprintf (qtex32->name, "%s/%s", mip_prefix, lumpname);\r
1218                 if (animname[0])\r
1219                 {\r
1220                         sprintf (qtex32->animname, "%s/%s", mip_prefix, animname);\r
1221                 }\r
1222                 if (altname[0])\r
1223                 {\r
1224                         sprintf (qtex32->altname, "%s/%s", mip_prefix, altname);\r
1225                 }\r
1226                 if (damagename[0])\r
1227                 {\r
1228                         sprintf (qtex32->damagename, "%s/%s", mip_prefix, damagename);\r
1229                 }\r
1230                 if (dt_name[0] & ((flags2 & MIP32_DETAILER_FLAG2) == 0)) \r
1231                 {\r
1232                         sprintf (qtex32->dt_name, "%s/%s", mip_prefix, dt_name);\r
1233                         qtex32->dt_scale_x = dt_scale_x;\r
1234                         qtex32->dt_scale_y = dt_scale_y;\r
1235                         qtex32->dt_u = dt_u;\r
1236                         qtex32->dt_v = dt_v;\r
1237                         qtex32->dt_alpha = dt_alpha;\r
1238                         qtex32->dt_src_blend_mode = dt_src_blend_mode;\r
1239                         qtex32->dt_dst_blend_mode = dt_dst_blend_mode;\r
1240                 }\r
1241                 \r
1242         //\r
1243         // write it out\r
1244         //\r
1245                 sprintf (filename, "%stextures/%s/%s.m32", g_outputDir, mip_prefix, lumpname);\r
1246                 if(qtex32->flags & (SURF_ALPHA_TEXTURE))\r
1247                         printf ("writing %s with ALPHA\n", filename);\r
1248                 else\r
1249                         printf ("writing %s\n", filename);\r
1250                 SaveFile (filename, (byte *)qtex32, size);\r
1251 \r
1252                 free (qtex32);\r
1253         }\r
1254         else\r
1255         {\r
1256                 if (xl >= byteimagewidth || xh > byteimagewidth ||\r
1257                         yl >= byteimageheight || yh > byteimageheight)\r
1258                 {\r
1259                         Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight);\r
1260                 }\r
1261 \r
1262                 source = byteimage + yl*byteimagewidth + xl;\r
1263                 dest = buffer;\r
1264                 linedelta = byteimagewidth - w;\r
1265 \r
1266                 for (y=yl ; y<yh ; y++)\r
1267                 {\r
1268                         for (x=xl ; x<xh ; x++)\r
1269                         {\r
1270                                 *dest++ = *source++;\r
1271                         }\r
1272                         source += linedelta;\r
1273                 }\r
1274 \r
1275                 qtex = CreateMip(buffer, w, h, lbmpalette, &size, true);\r
1276 \r
1277                 qtex->flags = LittleLong(flags);\r
1278                 qtex->contents = LittleLong(contents);\r
1279                 qtex->value = LittleLong(value);\r
1280                 sprintf (qtex->name, "%s/%s", mip_prefix, lumpname);\r
1281                 if (animname[0])\r
1282                         sprintf (qtex->animname, "%s/%s", mip_prefix, animname);\r
1283                 \r
1284         //\r
1285         // write it out\r
1286         //\r
1287                 sprintf (filename, "%stextures/%s/%s.m8", g_outputDir, mip_prefix, lumpname);\r
1288                 printf ("writing %s\n", filename);\r
1289                 SaveFile (filename, (byte *)qtex, size);\r
1290 \r
1291                 free (qtex);\r
1292         }\r
1293 }\r
1294 \r
1295 /*\r
1296 ===============\r
1297 Cmd_Mippal\r
1298 ===============\r
1299 */\r
1300 void Cmd_Mippal (void)\r
1301 {\r
1302         colormap_issued = true;\r
1303         if (g_release)\r
1304                 return;\r
1305 \r
1306         memcpy (colormap_palette, lbmpalette, 768);\r
1307 \r
1308         BuildPalmap();\r
1309 }\r
1310 \r
1311 \r
1312 /*\r
1313 ===============\r
1314 Cmd_Mipdir\r
1315 ===============\r
1316 */\r
1317 void Cmd_Mipdir (void)\r
1318 {\r
1319         char    filename[1024];\r
1320 \r
1321         GetScriptToken (false);\r
1322         strcpy (mip_prefix, token);\r
1323         // create the directory if needed\r
1324         sprintf (filename, "%stextures", g_outputDir);\r
1325         Q_mkdir (filename); \r
1326         sprintf (filename, "%stextures/%s", g_outputDir, mip_prefix);\r
1327         Q_mkdir (filename); \r
1328 }\r
1329 \r
1330 \r
1331 /*\r
1332 =============================================================================\r
1333 \r
1334 ENVIRONMENT MAP GRABBING\r
1335 \r
1336 Creates six pcx files from tga files without any palette edge seams\r
1337 also copies the tga files for GL rendering.\r
1338 =============================================================================\r
1339 */\r
1340 \r
1341 // 3dstudio environment map suffixes\r
1342 char    *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};\r
1343 \r
1344 /*\r
1345 =================\r
1346 Cmd_Environment\r
1347 =================\r
1348 */\r
1349 void Cmd_Environment (void)\r
1350 {\r
1351         char    name[1024];\r
1352         int             i, x, y;\r
1353         byte    image[256*256];\r
1354         byte    *tga;\r
1355 \r
1356         GetScriptToken (false);\r
1357 \r
1358         if (g_release)\r
1359         {\r
1360                 for (i=0 ; i<6 ; i++)\r
1361                 {\r
1362                         sprintf (name, "env/%s%s.pcx", token, suf[i]);\r
1363                         ReleaseFile (name);\r
1364                         sprintf (name, "env/%s%s.tga", token, suf[i]);\r
1365                         ReleaseFile (name);\r
1366                 }\r
1367                 return;\r
1368         }\r
1369         // get the palette\r
1370         BuildPalmap ();\r
1371 \r
1372         sprintf (name, "%senv/", gamedir);\r
1373         CreatePath (name);\r
1374 \r
1375         // convert the images\r
1376         for (i=0 ; i<6 ; i++)\r
1377         {\r
1378                 sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);\r
1379                 printf ("loading %s...\n", name);\r
1380                 LoadTGA (name, &tga, NULL, NULL);\r
1381 \r
1382                 for (y=0 ; y<256 ; y++)\r
1383                 {\r
1384                         for (x=0 ; x<256 ; x++)\r
1385                         {\r
1386                                 image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);\r
1387                         }\r
1388                 }\r
1389                 free (tga);\r
1390                 sprintf (name, "%senv/%s%s.pcx", gamedir, token, suf[i]);\r
1391                 if (FileTime (name) != -1)\r
1392                         printf ("%s already exists, not overwriting.\n", name);\r
1393                 else\r
1394                         WritePCXfile (name, image, 256, 256, colormap_palette);\r
1395         }\r
1396 }\r
1397 \r