]> icculus.org git repositories - theoddone33/hhexen.git/blob - base/r_data.c
osezer patch 009
[theoddone33/hhexen.git] / base / r_data.c
1
2 //**************************************************************************
3 //**
4 //** r_data.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile$
7 //** $Revision$
8 //** $Date$
9 //** $Author$
10 //**
11 //**************************************************************************
12
13 #include "h2def.h"
14 #include "r_local.h"
15 #include "p_local.h"
16
17 #if 0
18 // Moved these structures to r_local.h for RENDER3D.
19
20 typedef struct
21 {
22         int             originx;        // block origin (allways UL), which has allready
23         int             originy;        // accounted  for the patch's internal origin
24         int             patch;
25 } texpatch_t;
26
27 // a maptexturedef_t describes a rectangular texture, which is composed of one
28 // or more mappatch_t structures that arrange graphic patches
29 typedef struct
30 {
31         char            name[8];                // for switch changing, etc
32         short           width;
33         short           height;
34         short           patchcount;
35         texpatch_t      patches[1];             // [patchcount] drawn back to front
36                                                                 //  into the cached texture
37 } texture_t;
38 #endif
39
40
41 int             firstflat, lastflat, numflats;
42 int             firstpatch, lastpatch, numpatches;
43 int             firstspritelump, lastspritelump, numspritelumps;
44
45 int                     numtextures;
46 texture_t       **textures;
47 int                     *texturewidthmask;
48 fixed_t         *textureheight;         // needed for texture pegging
49 int                     *texturecompositesize;
50 short           **texturecolumnlump;
51 unsigned short          **texturecolumnofs;
52 byte            **texturecomposite;
53
54 int                     *flattranslation;               // for global animation
55 int                     *texturetranslation;    // for global animation
56
57 fixed_t         *spritewidth;           // needed for pre rendering
58 fixed_t         *spriteoffset;
59 fixed_t         *spritetopoffset;
60
61 lighttable_t    *colormaps;
62
63
64 /*
65 ==============================================================================
66
67                                                 MAPTEXTURE_T CACHING
68
69 when a texture is first needed, it counts the number of composite columns
70 required in the texture and allocates space for a column directory and any
71 new columns.  The directory will simply point inside other patches if there
72 is only one patch in a given column, but any columns with multiple patches
73 will have new column_ts generated.
74
75 ==============================================================================
76 */
77
78 /*
79 ===================
80 =
81 = R_DrawColumnInCache
82 =
83 = Clip and draw a column from a patch into a cached post
84 =
85 ===================
86 */
87
88 void R_DrawColumnInCache (column_t *patch, byte *cache, int originy, int cacheheight)
89 {
90         int             count, position;
91         byte    *source, *dest;
92         
93         dest = (byte *)cache + 3;
94         
95         while (patch->topdelta != 0xff)
96         {
97                 source = (byte *)patch + 3;
98                 count = patch->length;
99                 position = originy + patch->topdelta;
100                 if (position < 0)
101                 {
102                         count += position;
103                         position = 0;
104                 }
105                 if (position + count > cacheheight)
106                         count = cacheheight - position;
107                 if (count > 0)
108                         memcpy (cache + position, source, count);
109                 
110                 patch = (column_t *)(  (byte *)patch + patch->length
111 + 4);
112         }
113 }
114
115
116 /*
117 ===================
118 =
119 = R_GenerateComposite
120 =
121 ===================
122 */
123
124 void R_GenerateComposite (int texnum)
125 {
126         byte            *block;
127         texture_t       *texture;
128         texpatch_t      *patch; 
129         patch_t         *realpatch;
130         int                     x, x1, x2;
131         int                     i;
132         column_t        *patchcol;
133         short           *collump;
134         unsigned short *colofs;
135         
136         texture = textures[texnum];
137         block = Z_Malloc (texturecompositesize[texnum], PU_STATIC, 
138                 &texturecomposite[texnum]);     
139         collump = texturecolumnlump[texnum];
140         colofs = texturecolumnofs[texnum];
141                 
142 //
143 // composite the columns together
144 //
145         patch = texture->patches;
146                 
147         for (i=0 , patch = texture->patches; i<texture->patchcount ; i++, patch++)
148         {
149                 realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
150                 x1 = patch->originx;
151                 x2 = x1 + SHORT(realpatch->width);
152
153                 if (x1<0)
154                         x = 0;
155                 else
156                         x = x1;
157                 if (x2 > texture->width)
158                         x2 = texture->width;
159
160                 for ( ; x<x2 ; x++)
161                 {
162                         if (collump[x] >= 0)
163                                 continue;               // column does not have multiple patches
164                         patchcol = (column_t *)((byte *)realpatch + 
165                                 LONG(realpatch->columnofs[x-x1]));
166                         R_DrawColumnInCache (patchcol, block + colofs[x], patch->originy,
167                         texture->height);
168                 }
169                                                 
170         }
171
172 // now that the texture has been built, it is purgable
173         Z_ChangeTag (block, PU_CACHE);
174 }
175
176
177 /*
178 ===================
179 =
180 = R_GenerateLookup
181 =
182 ===================
183 */
184
185 void R_GenerateLookup (int texnum)
186 {
187         texture_t       *texture;
188         byte            *patchcount;            // [texture->width]
189         texpatch_t      *patch; 
190         patch_t         *realpatch;
191         int                     x, x1, x2;
192         int                     i;
193         short           *collump;
194         unsigned short  *colofs;
195         
196         texture = textures[texnum];
197
198         texturecomposite[texnum] = 0;   // composited not created yet
199         texturecompositesize[texnum] = 0;
200         collump = texturecolumnlump[texnum];
201         colofs = texturecolumnofs[texnum];
202         
203 //
204 // count the number of columns that are covered by more than one patch
205 // fill in the lump / offset, so columns with only a single patch are
206 // all done
207 //
208         patchcount = (byte *)malloc (texture->width);
209         memset (patchcount, 0, texture->width);
210         patch = texture->patches;
211                 
212         for (i=0 , patch = texture->patches; i<texture->patchcount ; i++, patch++)
213         {
214                 realpatch = W_CacheLumpNum (patch->patch, PU_CACHE);
215                 x1 = patch->originx;
216                 x2 = x1 + SHORT(realpatch->width);
217                 if (x1 < 0)
218                         x = 0;
219                 else
220                         x = x1;
221                 if (x2 > texture->width)
222                         x2 = texture->width;
223                 for ( ; x<x2 ; x++)
224                 {
225                         patchcount[x]++;
226                         collump[x] = patch->patch;
227                         colofs[x] = LONG(realpatch->columnofs[x-x1])+3;
228                 }
229         }
230         
231         for (x=0 ; x<texture->width ; x++)
232         {
233                 if (!patchcount[x])
234                 {
235                         ST_Message ("R_GenerateLookup: column without a patch (%s)\n", texture->name);
236                         free (patchcount);
237                         return;
238                 }
239 //                      I_Error ("R_GenerateLookup: column without a patch");
240                 if (patchcount[x] > 1)
241                 {
242                         collump[x] = -1;        // use the cached block
243                         colofs[x] = texturecompositesize[texnum];
244                         if (texturecompositesize[texnum] > 0x10000-texture->height)
245                                 I_Error ("R_GenerateLookup: texture %i is >64k",texnum);
246                         texturecompositesize[texnum] += texture->height;
247                 }
248         }       
249         free (patchcount);
250 }
251
252
253 /*
254 ================
255 =
256 = R_GetColumn
257 =
258 ================
259 */
260
261 byte *R_GetColumn (int tex, int col)
262 {
263         int     lump, ofs;
264         
265         col &= texturewidthmask[tex];
266         lump = texturecolumnlump[tex][col];
267         ofs = texturecolumnofs[tex][col];
268         if (lump > 0)
269                 return (byte *)W_CacheLumpNum(lump,PU_CACHE)+ofs;
270         if (!texturecomposite[tex])
271                 R_GenerateComposite (tex);
272         return texturecomposite[tex] + ofs;
273 }
274
275
276 /*
277 ==================
278 =
279 = R_InitTextures
280 =
281 = Initializes the texture list with the textures from the world map
282 =
283 ==================
284 */
285
286 void R_InitTextures (void)
287 {
288         maptexture_t    *mtexture;
289         texture_t               *texture;
290         mappatch_t      *mpatch;
291         texpatch_t      *patch;
292         int                     i,j;
293         int                     *maptex, *maptex2, *maptex1;
294         char            name[9], *names, *name_p;
295         int                     *patchlookup;
296         int                     totalwidth;
297         int                     nummappatches;
298         int                     offset, maxoff, maxoff2;
299         int                     numtextures1, numtextures2;
300         int                     *directory;
301
302 //
303 // load the patch names from pnames.lmp
304 //
305         name[8] = 0;
306         names = W_CacheLumpName ("PNAMES", PU_STATIC);
307         nummappatches = LONG ( *((int *)names) );
308         name_p = names+4;
309         patchlookup =  (int *)malloc(nummappatches*sizeof(*patchlookup));
310         for (i=0 ; i<nummappatches ; i++)
311         {
312                 strncpy (name,name_p+i*8, 8);
313                 patchlookup[i] = W_CheckNumForName (name);
314         }
315         Z_Free (names);
316
317 //
318 // load the map texture definitions from textures.lmp
319 //
320         maptex = maptex1 = W_CacheLumpName ("TEXTURE1", PU_STATIC);
321         numtextures1 = LONG(*maptex);
322         maxoff = W_LumpLength (W_GetNumForName ("TEXTURE1"));
323         directory = maptex+1;
324
325         if (W_CheckNumForName ("TEXTURE2") != -1)
326         {
327                 maptex2 = W_CacheLumpName ("TEXTURE2", PU_STATIC);
328                 numtextures2 = LONG(*maptex2);
329                 maxoff2 = W_LumpLength (W_GetNumForName ("TEXTURE2"));
330         }
331         else
332         {
333                 maptex2 = NULL;
334                 numtextures2 = 0;
335                 maxoff2 = 0;
336         }
337         numtextures = numtextures1 + numtextures2;
338
339         textures = Z_Malloc (numtextures*4, PU_STATIC, 0);
340         texturecolumnlump = Z_Malloc (numtextures*4, PU_STATIC, 0);
341         texturecolumnofs = Z_Malloc (numtextures*4, PU_STATIC, 0);
342         texturecomposite = Z_Malloc (numtextures*4, PU_STATIC, 0);
343         texturecompositesize = Z_Malloc (numtextures*4, PU_STATIC, 0);
344         texturewidthmask = Z_Malloc (numtextures*4, PU_STATIC, 0);
345         textureheight = Z_Malloc (numtextures*4, PU_STATIC, 0);
346
347         totalwidth = 0;
348
349         for (i=0 ; i<numtextures ; i++, directory++)
350         {
351                 if (i == numtextures1)
352                 {       // start looking in second texture file
353                         maptex = maptex2;
354                         maxoff = maxoff2;
355                         directory = maptex+1;
356                 }
357
358                 offset = LONG(*directory);
359                 if (offset > maxoff)
360                         I_Error ("R_InitTextures: bad texture directory");
361                 mtexture = (maptexture_t *) ( (byte *)maptex + offset);
362                 texture = textures[i] = Z_Malloc (sizeof(texture_t) 
363                         + sizeof(texpatch_t)*(SHORT(mtexture->patchcount)-1), PU_STATIC,
364                         0);
365                 texture->width = SHORT(mtexture->width);
366                 texture->height = SHORT(mtexture->height);
367                 texture->patchcount = SHORT(mtexture->patchcount);
368                 memcpy (texture->name, mtexture->name, sizeof(texture->name));
369                 mpatch = &mtexture->patches[0];
370                 patch = &texture->patches[0];
371                 for (j=0 ; j<texture->patchcount ; j++, mpatch++, patch++)
372                 {
373                         patch->originx = SHORT(mpatch->originx);
374                         patch->originy = SHORT(mpatch->originy);
375                         patch->patch = patchlookup[SHORT(mpatch->patch)];
376                         if (patch->patch == -1)
377                                 I_Error (
378                                 "R_InitTextures: Missing patch in texture %s",texture->name);
379                 }               
380                 texturecolumnlump[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
381                 texturecolumnofs[i] = Z_Malloc (texture->width*2, PU_STATIC,0);
382                 j = 1;
383                 while (j*2 <= texture->width)
384                         j<<=1;
385                 texturewidthmask[i] = j-1;
386                 textureheight[i] = texture->height<<FRACBITS;
387                 
388                 totalwidth += texture->width;
389         }
390
391         Z_Free (maptex1);
392         if (maptex2)
393                 Z_Free (maptex2);
394
395 //
396 // precalculate whatever possible
397 //              
398         for (i=0 ; i<numtextures ; i++)
399         {
400                 R_GenerateLookup (i);
401                 if(!(i&31)) ST_Progress();
402         }
403
404 //
405 // translation table for global animation
406 //
407         texturetranslation = Z_Malloc ((numtextures+1)*4, PU_STATIC, 0);
408         for (i=0 ; i<numtextures ; i++)
409                 texturetranslation[i] = i;
410
411         free (patchlookup);
412 }
413
414
415 /*
416 ================
417 =
418 = R_InitFlats
419 =
420 =================
421 */
422
423 void R_InitFlats (void)
424 {
425         int             i;
426         
427         firstflat = W_GetNumForName ("F_START") + 1;
428         lastflat = W_GetNumForName ("F_END") - 1;
429         numflats = lastflat - firstflat + 1;
430         
431 // translation table for global animation
432         flattranslation = Z_Malloc ((numflats+1)*4, PU_STATIC, 0);
433         for (i=0 ; i<numflats ; i++)
434                 flattranslation[i] = i;
435 }
436
437
438 /*
439 ================
440 =
441 = R_InitSpriteLumps
442 =
443 = Finds the width and hoffset of all sprites in the wad, so the sprite doesn't
444 = need to be cached just for the header during rendering
445 =================
446 */
447
448 void R_InitSpriteLumps (void)
449 {
450         int             i;
451         patch_t *patch;
452
453         firstspritelump = W_GetNumForName ("S_START") + 1;
454         lastspritelump = W_GetNumForName ("S_END") - 1;
455         numspritelumps = lastspritelump - firstspritelump + 1;
456         spritewidth = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
457         spriteoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
458         spritetopoffset = Z_Malloc (numspritelumps*4, PU_STATIC, 0);
459
460         for (i=0 ; i< numspritelumps ; i++)
461         {
462                 if (!(i&127)) ST_Progress();
463                 patch = W_CacheLumpNum (firstspritelump+i, PU_CACHE);
464                 spritewidth[i] = SHORT(patch->width)<<FRACBITS;
465                 spriteoffset[i] = SHORT(patch->leftoffset)<<FRACBITS;
466                 spritetopoffset[i] = SHORT(patch->topoffset)<<FRACBITS;
467         }
468 }
469
470
471 /*
472 ================
473 =
474 = R_InitColormaps
475 =
476 =================
477 */
478
479 void R_InitColormaps (void)
480 {
481         int     lump, length;
482 //
483 // load in the light tables
484 // 256 byte align tables
485 //
486         lump = W_GetNumForName("COLORMAP");
487         length = W_LumpLength (lump) + 255;
488         colormaps = Z_Malloc (length, PU_STATIC, 0);
489         colormaps = (byte *)( ((int)colormaps + 255)&~0xff);
490         W_ReadLump (lump,colormaps);
491 }
492
493
494 /*
495 ================
496 =
497 = R_InitData
498 =
499 = Locates all the lumps that will be used by all views
500 = Must be called after W_Init
501 =================
502 */
503
504 void R_InitData (void)
505 {
506         R_InitTextures();
507         R_InitFlats();
508         R_InitSpriteLumps();
509         R_InitColormaps();
510 }
511
512 //=============================================================================
513
514 /*
515 ================
516 =
517 = R_FlatNumForName
518 =
519 ================
520 */
521
522 int     R_FlatNumForName (char *name)
523 {
524         int             i;
525         char    namet[9];
526
527         i = W_CheckNumForName (name);
528         if (i == -1)
529         {
530                 namet[8] = 0;
531                 memcpy (namet, name,8);
532                 I_Error ("R_FlatNumForName: %s not found",namet);
533         }
534         return i - firstflat;
535 }
536
537
538 /*
539 ================
540 =
541 = R_CheckTextureNumForName
542 =
543 ================
544 */
545
546 int     R_CheckTextureNumForName (char *name)
547 {
548         int             i;
549         
550         if (name[0] == '-')             // no texture marker
551                 return 0;
552                 
553     //KR
554     //printf( "%s\n", name );
555         for (i=0 ; i<numtextures ; i++)
556     {
557         //printf( "%d %s\n", i, textures[i]->name );
558                 if (!strncasecmp (textures[i]->name, name, 8) )
559                         return i;
560     }
561                 
562         return -1;
563 }
564
565
566 /*
567 ================
568 =
569 = R_TextureNumForName
570 =
571 ================
572 */
573
574 int     R_TextureNumForName (char *name)
575 {
576         int             i;
577         //char  namet[9];
578         
579         i = R_CheckTextureNumForName (name);
580         if (i==-1)
581     {
582 #ifdef DEMO_WAD
583         printf("R_TextureNumForName: %s not found!  Assuming shareware wad.\n",
584                 name);
585         return 1;
586 #else
587                 I_Error ("R_TextureNumForName: %s not found",name);
588 #endif
589     }
590         
591         return i;
592 }
593
594
595 /*
596 =================
597 =
598 = R_PrecacheLevel
599 =
600 = Preloads all relevent graphics for the level
601 =================
602 */
603
604 int             flatmemory, texturememory, spritememory;
605
606 void R_PrecacheLevel (void)
607 {
608         char                    *flatpresent;
609         char                    *texturepresent;
610         char                    *spritepresent;
611         int                             i,j,k, lump;
612         texture_t               *texture;
613         thinker_t               *th;
614         spriteframe_t   *sf;
615
616         if (demoplayback)
617                 return;
618                         
619 //
620 // precache flats
621 //      
622         flatpresent = (char*)malloc(numflats);
623         memset (flatpresent,0,numflats);        
624         for (i=0 ; i<numsectors ; i++)
625         {
626                 flatpresent[sectors[i].floorpic] = 1;
627                 flatpresent[sectors[i].ceilingpic] = 1;
628         }
629         
630         flatmemory = 0;
631         for (i=0 ; i<numflats ; i++)
632                 if (flatpresent[i])
633                 {
634                         lump = firstflat + i;
635                         flatmemory += lumpinfo[lump].size;
636                         W_CacheLumpNum(lump, PU_CACHE);
637                 }
638                 
639 //
640 // precache textures
641 //
642         texturepresent = (char*) malloc(numtextures);
643         memset (texturepresent,0, numtextures);
644         
645         for (i=0 ; i<numsides ; i++)
646         {
647                 texturepresent[sides[i].toptexture] = 1;
648                 texturepresent[sides[i].midtexture] = 1;
649                 texturepresent[sides[i].bottomtexture] = 1;
650         }
651         
652         texturepresent[Sky1Texture] = 1;
653         texturepresent[Sky2Texture] = 1;
654
655         texturememory = 0;
656         for (i=0 ; i<numtextures ; i++)
657         {
658                 if (!texturepresent[i])
659                         continue;
660                 texture = textures[i];
661                 for (j=0 ; j<texture->patchcount ; j++)
662                 {
663                         lump = texture->patches[j].patch;
664                         texturememory += lumpinfo[lump].size;
665                         W_CacheLumpNum(lump , PU_CACHE);
666                 }
667         }
668         
669 //
670 // precache sprites
671 //
672         spritepresent = (char*)malloc(numsprites);
673         memset (spritepresent,0, numsprites);
674         
675         for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
676         {
677                 if (th->function == P_MobjThinker)
678                         spritepresent[((mobj_t *)th)->sprite] = 1;
679         }
680         
681         spritememory = 0;
682         for (i=0 ; i<numsprites ; i++)
683         {
684                 if (!spritepresent[i])
685                         continue;
686                 for (j=0 ; j<sprites[i].numframes ; j++)
687                 {
688                         sf = &sprites[i].spriteframes[j];
689                         for (k=0 ; k<8 ; k++)
690                         {
691                                 lump = firstspritelump + sf->lump[k];
692                                 spritememory += lumpinfo[lump].size;
693                                 W_CacheLumpNum(lump , PU_CACHE);
694                         }
695                 }
696         }
697         free (flatpresent);
698         free (texturepresent);
699         free (spritepresent);
700 }
701