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