Subversion Repositories eduke32

Rev

Rev 885 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 Plagman 1
/**************************************************************************************************
2
"POLYMOST" code written by Ken Silverman
3
Ken Silverman's official web site: http://www.advsys.net/ken
4
 
5
Motivation:
6
When 3D Realms released the Duke Nukem 3D source code, I thought somebody would do a OpenGL or
7
Direct3D port. Well, after a few months passed, I saw no sign of somebody working on a true
8
hardware-accelerated port of Build, just people saying it wasn't possible. Eventually, I realized
9
the only way this was going to happen was for me to do it myself. First, I needed to port Build to
10
Windows. I could have done it myself, but instead I thought I'd ask my Australian buddy, Jonathon
11
Fowler, if he would upgrade his Windows port to my favorite compiler (MSVC) - which he did. Once
12
that was done, I was ready to start the "POLYMOST" project.
13
 
14
About:
15
This source file is basically a complete rewrite of the entire rendering part of the Build engine.
16
There are small pieces in ENGINE.C to activate this code, and other minor hacks in other source
17
files, but most of it is in here. If you're looking for polymost-related code in the other source
18
files, you should find most of them by searching for either "polymost" or "rendmode". Speaking of
19
rendmode, there are now 4 rendering modes in Build:
20
 
21
        rendmode 0: The original code I wrote from 1993-1997
22
        rendmode 1: Solid-color rendering: my debug code before I did texture mapping
23
        rendmode 2: Software rendering before I started the OpenGL code (Note: this is just a quick
24
                                                hack to make testing easier - it's not optimized to my usual standards!)
25
        rendmode 3: The OpenGL code
26
 
27
The original Build engine did hidden surface removal by using a vertical span buffer on the tops
28
and bottoms of walls. This worked nice back in the day, but it it's not suitable for a polygon
29
engine. So I decided to write a brand new hidden surface removal algorithm - using the same idea
30
as the original Build - but one that worked with vectors instead of already rasterized data.
31
 
32
Brief history:
33
06/20/2000: I release Build Source code
34
04/01/2003: 3D Realms releases Duke Nukem 3D source code
35
10/04/2003: Jonathon Fowler gets his Windows port working in Visual C
36
10/04/2003: I start writing POLYMOST.BAS, a new hidden surface removal algorithm for Build that
37
                                        works on a polygon level instead of spans.
38
10/16/2003: Ported POLYMOST.BAS to C inside JonoF KenBuild's ENGINE.C; later this code was split
39
                                        out of ENGINE.C and put in this file, POLYMOST.C.
40
12/10/2003: Started OpenGL code for POLYMOST (rendmode 3)
41
12/23/2003: 1st public release
42
01/01/2004: 2nd public release: fixed stray lines, status bar, mirrors, sky, and lots of other bugs.
43
 
44
----------------------------------------------------------------------------------------------------
45
 
46
Todo list (in approximate chronological order):
47
 
48
High priority:
49
        *   BOTH: Do accurate software sorting/chopping for sprites: drawing in wrong order is bad :/
50
        *   BOTH: Fix hall of mirrors near "zenith". Call polymost_drawrooms twice?
51
        * OPENGL: drawmapview()
52
 
53
Low priority:
54
        * SOFT6D: Do back-face culling of sprites during up/down/tilt transformation (top of drawpoly)
55
        * SOFT6D: Fix depth shading: use saturation&LUT
56
        * SOFT6D: Optimize using hyperbolic mapping (similar to KUBE algo)
57
        * SOFT6D: Slab6-style voxel sprites. How to accelerate? :/
58
        * OPENGL: KENBUILD: Write flipping code for floor mirrors
59
        *   BOTH: KENBUILD: Parallaxing sky modes 1&2
60
        *   BOTH: Masked/1-way walls don't clip correctly to sectors of intersecting ceiling/floor slopes
61
        *   BOTH: Editart x-center is not working correctly with Duke's camera/turret sprites
62
        *   BOTH: Get rid of horizontal line above Duke full-screen status bar
63
        *   BOTH: Combine ceilings/floors into a single triangle strip (should lower poly count by 2x)
64
        *   BOTH: Optimize/clean up texture-map setup equations
65
 
66
**************************************************************************************************/
67
 
584 terminx 68
int animateoffs(short tilenum, short fakevar);
697 plagman 69
int rendmode=0;
584 terminx 70
int usemodels=1, usehightile=1;
5 Plagman 71
 
72
#include <math.h> //<-important!
584 terminx 73
typedef struct { float x, cy[2], fy[2]; int n, p, tag, ctag, ftag; } vsptyp;
5 Plagman 74
#define VSPMAX 4096 //<- careful!
75
static vsptyp vsp[VSPMAX];
584 terminx 76
static int vcnt, gtag;
5 Plagman 77
 
78
static double dxb1[MAXWALLSB], dxb2[MAXWALLSB];
79
 
80
#define SCISDIST 1.0 //1.0: Close plane clipping distance
81
#define USEZBUFFER 1 //1:use zbuffer (slow, nice sprite rendering), 0:no zbuffer (fast, bad sprite rendering)
82
#define LINTERPSIZ 4 //log2 of interpolation size. 4:pretty fast&acceptable quality, 0:best quality/slow!
83
#define DEPTHDEBUG 0 //1:render distance instead of texture, for debugging only!, 0:default
431 terminx 84
#define FOGSCALE 0.0000640
5 Plagman 85
#define PI 3.14159265358979323
86
 
774 plagman 87
float shadescale = 1.050;
379 terminx 88
 
5 Plagman 89
static double gyxscale, gxyaspect, gviewxrange, ghalfx, grhalfxdown10, grhalfxdown10x, ghoriz;
90
static double gcosang, gsinang, gcosang2, gsinang2;
91
static double gchang, gshang, gctang, gstang, gvisibility;
307 Plagman 92
float gtang = 0.0;
5 Plagman 93
double guo, gux, guy; //Screen-based texture mapping parameters
94
double gvo, gvx, gvy;
95
double gdo, gdx, gdy;
96
 
97
#if (USEZBUFFER != 0)
786 qbix79 98
int  zbufysiz = 0, zbufbpl = 0, *zbufoff = 0;
99
intptr_t zbufmem = 0;
5 Plagman 100
#endif
101
 
102
#ifdef USE_OPENGL
590 plagman 103
static int srepeat = 0, trepeat = 0;
104
 
584 terminx 105
int glredbluemode = 0;
106
static int lastglredbluemode = 0, redblueclearcnt = 0;
5 Plagman 107
 
584 terminx 108
static struct glfiltermodes
109
{
109 terminx 110
    char *name;
584 terminx 111
    int min,mag;
112
} glfiltermodes[] =
113
{
114
    {"GL_NEAREST",GL_NEAREST,GL_NEAREST},
115
    {"GL_LINEAR",GL_LINEAR,GL_LINEAR},
116
    {"GL_NEAREST_MIPMAP_NEAREST",GL_NEAREST_MIPMAP_NEAREST,GL_NEAREST},
117
    {"GL_LINEAR_MIPMAP_NEAREST",GL_LINEAR_MIPMAP_NEAREST,GL_LINEAR},
118
    {"GL_NEAREST_MIPMAP_LINEAR",GL_NEAREST_MIPMAP_LINEAR,GL_NEAREST},
119
    {"GL_LINEAR_MIPMAP_LINEAR",GL_LINEAR_MIPMAP_LINEAR,GL_LINEAR}
120
};
5 Plagman 121
#define numglfiltermodes (sizeof(glfiltermodes)/sizeof(glfiltermodes[0]))
122
 
584 terminx 123
int glanisotropy = 1;            // 0 = maximum supported by card
124
int glusetexcompr = 1;
125
int gltexfiltermode = 2; // GL_NEAREST_MIPMAP_NEAREST
126
int glusetexcache = 0;
127
int glusetexcachecompression = 1;
128
int glmultisample = 0, glnvmultisamplehint = 0;
129
int gltexmaxsize = 0;      // 0 means autodetection on first run
130
int gltexmiplevel = 0;          // discards this many mipmap levels
131
static int lastglpolygonmode = 0; //FUK
132
int glpolygonmode = 0;     // 0:GL_FILL,1:GL_LINE,2:GL_POINT //FUK
133
int glwidescreen = 0;
134
int glprojectionhacks = 1;
5 Plagman 135
static GLuint polymosttext = 0;
136
extern char nofog;
228 Plagman 137
 
244 Plagman 138
// Those THREE globals control the drawing of fullbright tiles
584 terminx 139
static int fullbrightloadingpass = 0;
140
static int fullbrightdrawingpass = 0;
141
static int shadeforfullbrightpass;
228 Plagman 142
 
446 Plagman 143
// Depth peeling control
584 terminx 144
int r_depthpeeling = 0;    // cvar toggling general depth peeling usage
145
int r_peelscount = 5;      // cvar controlling the number of peeling layers
146
int r_curpeel = -1;        // cvar controlling the display of independant peeling layers
498 terminx 147
static float curpolygonoffset;     // internal polygon offset stack for drawing flat sprites to avoid depth fighting
584 terminx 148
static int peelcompiling = 0;     // internal control var to disable blending when compiling the peeling display list
149
static int newpeelscount = 0;     // temporary var for peels count changing during the game
446 Plagman 150
 
151
// Depth peeling data
498 terminx 152
static GLuint ztexture[3];         // secondary Z-buffers identifier
153
static GLuint *peels;              // peels identifiers
154
static GLuint *peelfbos;           // peels FBOs identifiers
155
static GLuint peelprogram[2];      // ARBfp peeling fragment program
446 Plagman 156
 
460 Plagman 157
// Detail mapping cvar
584 terminx 158
int r_detailmapping = 1;
459 Plagman 159
 
497 Plagman 160
// Glow mapping cvar
584 terminx 161
int r_glowmapping = 1;
497 Plagman 162
 
513 Plagman 163
// Vertex Array model drawing cvar
584 terminx 164
int r_vertexarrays = 1;
513 Plagman 165
 
519 Plagman 166
// Vertex Buffer Objects model drawing cvars
584 terminx 167
int r_vbos = 0;
168
int r_vbocount = 64;
513 Plagman 169
 
525 Plagman 170
// model animation smoothing cvar
584 terminx 171
int r_animsmoothing = 1;
519 Plagman 172
 
623 plagman 173
// polymost ART sky control
174
int r_parallaxskyclamping = 1;
175
int r_parallaxskypanning = 0;
176
 
881 terminx 177
// line of sight checks before mddraw()
178
int r_cullobstructedmodels = 0;
882 terminx 179
#define CULL_DELAY 5
881 terminx 180
 
883 terminx 181
// fullbright cvar
886 terminx 182
int r_fullbrights = 1;
883 terminx 183
 
621 plagman 184
static float fogresult, fogcol[4];
393 terminx 185
 
612 terminx 186
// making this a macro should speed things up at the expense of code size
187
#define fogcalc(shade, vis, pal) \
188
{ \
622 terminx 189
    fogresult = (float)gvisibility*(vis+16+(shade<0?(-shade*shade)*0.125f:(shade*shade)*0.125f)); \
190
    if (vis > 239) fogresult = (float)gvisibility*((vis-240+(shade<0?(-shade*shade)*0.125f:(shade*shade)*0.125f))/(klabs(vis-256))); \
612 terminx 191
    fogresult = min(max(fogresult, 0.01f),10.f); \
192
    fogcol[0] = (float)palookupfog[pal].r / 63.f; \
193
    fogcol[1] = (float)palookupfog[pal].g / 63.f; \
194
    fogcol[2] = (float)palookupfog[pal].b / 63.f; \
195
    fogcol[3] = 0; \
356 terminx 196
}
5 Plagman 197
#endif
198
 
199
#if defined(USE_MSC_PRAGMAS)
584 terminx 200
static inline void ftol(float f, int *a)
5 Plagman 201
{
109 terminx 202
    _asm
203
    {
204
        mov eax, a
205
        fld f
206
        fistp dword ptr [eax]
207
    }
5 Plagman 208
}
209
 
584 terminx 210
static inline void dtol(double d, int *a)
5 Plagman 211
{
109 terminx 212
    _asm
213
    {
214
        mov eax, a
215
        fld d
216
        fistp dword ptr [eax]
217
    }
5 Plagman 218
}
219
#elif defined(USE_WATCOM_PRAGMAS)
220
 
221
#pragma aux ftol =\
222
        "fistp dword ptr [eax]",\
223
        parm [eax 8087]
224
#pragma aux dtol =\
225
        "fistp dword ptr [eax]",\
226
        parm [eax 8087]
227
 
228
#elif defined(USE_GCC_PRAGMAS)
229
 
584 terminx 230
static inline void ftol(float f, int *a)
5 Plagman 231
{
584 terminx 232
    __asm__ __volatile__(
5 Plagman 233
#if 0 //(__GNUC__ >= 3)
109 terminx 234
        "flds %1; fistpl %0;"
5 Plagman 235
#else
726 terminx 236
        "flds %1; fistpl (%0);"
5 Plagman 237
#endif
584 terminx 238
    : "=r"(a) : "m"(f) : "memory","cc");
5 Plagman 239
}
240
 
584 terminx 241
static inline void dtol(double d, int *a)
5 Plagman 242
{
584 terminx 243
    __asm__ __volatile__(
5 Plagman 244
#if 0 //(__GNUC__ >= 3)
109 terminx 245
        "fldl %1; fistpl %0;"
5 Plagman 246
#else
726 terminx 247
        "fldl %1; fistpl (%0);"
5 Plagman 248
#endif
584 terminx 249
    : "=r"(a) : "m"(d) : "memory","cc");
5 Plagman 250
}
251
 
252
#else
584 terminx 253
static inline void ftol(float f, int *a)
5 Plagman 254
{
584 terminx 255
    *a = (int)f;
5 Plagman 256
}
257
 
584 terminx 258
static inline void dtol(double d, int *a)
5 Plagman 259
{
584 terminx 260
    *a = (int)d;
5 Plagman 261
}
262
#endif
263
 
584 terminx 264
static inline int imod(int a, int b)
5 Plagman 265
{
109 terminx 266
    if (a >= 0) return(a%b);
267
    return(((a+1)%b)+b-1);
5 Plagman 268
}
269
 
584 terminx 270
void drawline2d(float x0, float y0, float x1, float y1, char col)
5 Plagman 271
{
109 terminx 272
    float f, dx, dy, fxres, fyres;
584 terminx 273
    int e, inc, x, y;
274
    unsigned int up16;
5 Plagman 275
 
109 terminx 276
    dx = x1-x0; dy = y1-y0; if ((dx == 0) && (dy == 0)) return;
277
    fxres = (float)xdimen; fyres = (float)ydimen;
584 terminx 278
    if (x0 >= fxres) { if (x1 >= fxres) return; y0 += (fxres-x0)*dy/dx; x0 = fxres; }
279
    else if (x0 <      0) { if (x1 <      0) return; y0 += (0-x0)*dy/dx; x0 =     0; }
280
    if (x1 >= fxres) {                          y1 += (fxres-x1)*dy/dx; x1 = fxres; }
281
    else if (x1 <      0) {                          y1 += (0-x1)*dy/dx; x1 =     0; }
109 terminx 282
    if (y0 >= fyres) { if (y1 >= fyres) return; x0 += (fyres-y0)*dx/dy; y0 = fyres; }
584 terminx 283
    else if (y0 <      0) { if (y1 <      0) return; x0 += (0-y0)*dx/dy; y0 =     0; }
284
    if (y1 >= fyres) {                          x1 += (fyres-y1)*dx/dy; y1 = fyres; }
285
    else if (y1 <      0) {                          x1 += (0-y1)*dx/dy; y1 =     0; }
5 Plagman 286
 
109 terminx 287
    if (fabs(dx) > fabs(dy))
288
    {
289
        if (x0 > x1) { f = x0; x0 = x1; x1 = f; f = y0; y0 = y1; y1 = f; }
584 terminx 290
        y = (int)(y0*65536.f)+32768;
291
        inc = (int)(dy/dx*65536.f+.5f);
292
        x = (int)(x0+.5); if (x < 0) { y -= inc*x; x = 0; } //if for safety
293
        e = (int)(x1+.5); if (e > xdimen) e = xdimen;       //if for safety
109 terminx 294
        up16 = (ydimen<<16);
584 terminx 295
        for (;x<e;x++,y+=inc) if ((unsigned int)y < up16) *(char *)(ylookup[y>>16]+x+frameoffset) = col;
109 terminx 296
    }
297
    else
298
    {
299
        if (y0 > y1) { f = x0; x0 = x1; x1 = f; f = y0; y0 = y1; y1 = f; }
584 terminx 300
        x = (int)(x0*65536.f)+32768;
301
        inc = (int)(dx/dy*65536.f+.5f);
302
        y = (int)(y0+.5); if (y < 0) { x -= inc*y; y = 0; } //if for safety
303
        e = (int)(y1+.5); if (e > ydimen) e = ydimen;       //if for safety
109 terminx 304
        up16 = (xdimen<<16);
584 terminx 305
        for (;y<e;y++,x+=inc) if ((unsigned int)x < up16) *(char *)(ylookup[y]+(x>>16)+frameoffset) = col;
109 terminx 306
    }
5 Plagman 307
}
308
 
309
#ifdef USE_OPENGL
310
typedef struct { unsigned char r, g, b, a; } coltype;
311
 
584 terminx 312
static void uploadtexture(int doalloc, int xsiz, int ysiz, int intexfmt, int texfmt, coltype *pic, int tsizx, int tsizy, int dameth);
5 Plagman 313
 
314
#include "md4.h"
315
 
316
#define USELZF
317
#define USEKENFILTER 1
318
 
319
#ifdef USELZF
320
#       include "lzf.h"
321
#else
322
#       include "lzwnew.h"
323
#endif
324
 
325
static char TEXCACHEDIR[] = "texcache";
584 terminx 326
typedef struct
327
{
109 terminx 328
    char magic[8];      // 'Polymost'
584 terminx 329
    int xdim, ydim;     // of image, unpadded
330
    int flags;          // 1 = !2^x, 2 = has alpha, 4 = lzw compressed
5 Plagman 331
} texcacheheader;
584 terminx 332
typedef struct
333
{
334
    int size;
335
    int format;
336
    int xdim, ydim;     // of mipmap (possibly padded)
337
    int border, depth;
5 Plagman 338
} texcachepicture;
339
 
584 terminx 340
int dxtfilter(int fil, texcachepicture *pict, char *pic, void *midbuf, char *packbuf, unsigned int miplen);
5 Plagman 341
int dedxtfilter(int fil, texcachepicture *pict, char *pic, void *midbuf, char *packbuf, int ispacked);
342
 
343
static inline void phex(unsigned char v, char *s);
584 terminx 344
void writexcache(char *fn, int len, int dameth, char effect, texcacheheader *head);
5 Plagman 345
 
606 terminx 346
int mdtims, omdtims;
5 Plagman 347
float alphahackarray[MAXTILES];
348
#include "mdsprite.c"
349
 
350
//--------------------------------------------------------------------------------------------------
351
//TEXTURE MANAGEMENT: treats same texture with different .PAL as a separate texture. This makes the
352
//   max number of virtual textures very large (MAXTILES*256). Instead of allocating a handle for
353
//   every virtual texture, I use a cache where indexing is managed through a hash table.
354
//
355
 
283 Plagman 356
// moved into polymost.h
357
/*typedef struct pthtyp_t
5 Plagman 358
{
109 terminx 359
    struct pthtyp_t *next;
360
    GLuint glpic;
361
    short picnum;
362
    char palnum;
363
    char effects;
228 Plagman 364
    char flags;      // 1 = clamped (dameth&4), 2 = hightile, 4 = skybox face, 8 = hasalpha, 16 = hasfullbright, 128 = invalidated
109 terminx 365
    char skyface;
366
    hicreplctyp *hicr;
5 Plagman 367
 
109 terminx 368
    unsigned short sizx, sizy;
369
    float scalex, scaley;
235 Plagman 370
    struct pthtyp_t *wofb; // without fullbright
371
    struct pthtyp_t *ofb; // only fullbright
286 terminx 372
} pthtyp;*/
5 Plagman 373
 
374
#define GLTEXCACHEADSIZ 8192
375
static pthtyp *gltexcachead[GLTEXCACHEADSIZ];
376
 
779 plagman 377
int drawingskybox = 0;
5 Plagman 378
 
587 terminx 379
pthtyp *pichead;
380
 
584 terminx 381
int gloadtile_art(int,int,int,pthtyp*,int);
587 terminx 382
int gloadtile_hi(int,int,int,hicreplctyp*,int,pthtyp*,int,char);
5 Plagman 383
static int hicprecaching = 0;
584 terminx 384
pthtyp * gltexcache(int dapicnum, int dapalnum, int dameth)
5 Plagman 385
{
584 terminx 386
    int i, j;
109 terminx 387
    hicreplctyp *si;
499 Plagman 388
    pthtyp *pth, *pth2;
5 Plagman 389
 
109 terminx 390
    j = (dapicnum&(GLTEXCACHEADSIZ-1));
5 Plagman 391
 
109 terminx 392
    if (usehightile) si = hicfindsubst(dapicnum,dapalnum,drawingskybox);
393
    else si = NULL;
584 terminx 394
    if (!si)
395
    {
109 terminx 396
        if (drawingskybox) return NULL;
397
        goto tryart;
398
    }
5 Plagman 399
 
109 terminx 400
    /* if palette > 0 && replacement found
401
     *    no effects are applied to the texture
402
     * else if palette > 0 && no replacement found
403
     *    effects are applied to the palette 0 texture if it exists
404
     */
5 Plagman 405
 
587 terminx 406
    pichead=gltexcachead[j]; // for palmaps
109 terminx 407
    // load a replacement
587 terminx 408
    for (pth=pichead; pth; pth=pth->next)
584 terminx 409
    {
109 terminx 410
        if (pth->picnum == dapicnum &&
411
                pth->palnum == si->palnum &&
412
                (si->palnum>0 ? 1 : (pth->effects == hictinting[dapalnum].f)) &&
413
                (pth->flags & (1+2+4)) == (((dameth&4)>>2)+2+((drawingskybox>0)<<2)) &&
414
                (drawingskybox>0 ? (pth->skyface == drawingskybox) : 1)
415
           )
416
        {
417
            if (pth->flags & 128)
418
            {
419
                pth->flags &= ~128;
587 terminx 420
                if (gloadtile_hi(dapicnum,dapalnum,drawingskybox,si,dameth,pth,0,
584 terminx 421
                                 (si->palnum>0) ? 0 : hictinting[dapalnum].f))    // reload tile
422
                {
109 terminx 423
                    if (drawingskybox) return NULL;
424
                    goto tryart;   // failed, so try for ART
425
                }
426
            }
427
            return(pth);
428
        }
429
    }
5 Plagman 430
 
499 Plagman 431
 
109 terminx 432
    pth = (pthtyp *)calloc(1,sizeof(pthtyp));
433
    if (!pth) return NULL;
5 Plagman 434
 
499 Plagman 435
    // possibly fetch an already loaded multitexture :_)
436
    if (dapalnum >= (MAXPALOOKUPS - RESERVEDPALS))
437
        for (i = (GLTEXCACHEADSIZ - 1); i >= 0; i--)
584 terminx 438
            for (pth2=gltexcachead[i]; pth2; pth2=pth2->next)
439
            {
499 Plagman 440
                if ((pth2->hicr) && (pth2->hicr->filename) && (Bstrcasecmp(pth2->hicr->filename, si->filename) == 0))
441
                {
442
                    memcpy(pth, pth2, sizeof(pthtyp));
443
                    pth->picnum = dapicnum;
515 terminx 444
                    pth->flags = ((dameth&4)>>2) + 2 + ((drawingskybox>0)<<2);
519 Plagman 445
                    if (pth2->flags & 8) pth->flags |= 8; //hasalpha
499 Plagman 446
                    pth->hicr = si;
447
                    pth->next = gltexcachead[j];
723 terminx 448
 
499 Plagman 449
                    gltexcachead[j] = pth;
450
                    return(pth);
451
                }
452
            }
453
 
587 terminx 454
    if (gloadtile_hi(dapicnum,dapalnum,drawingskybox,si,dameth,pth,1, (si->palnum>0) ? 0 : hictinting[dapalnum].f))
584 terminx 455
    {
109 terminx 456
        free(pth);
457
        if (drawingskybox) return NULL;
458
        goto tryart;   // failed, so try for ART
459
    }
460
    pth->palnum = si->palnum;
461
    pth->next = gltexcachead[j];
462
    gltexcachead[j] = pth;
463
    return(pth);
5 Plagman 464
 
465
tryart:
109 terminx 466
    if (hicprecaching) return NULL;
5 Plagman 467
 
109 terminx 468
    // load from art
331 terminx 469
    for (pth=gltexcachead[j]; pth; pth=pth->next)
109 terminx 470
        if (pth->picnum == dapicnum &&
471
                pth->palnum == dapalnum &&
472
                (pth->flags & (1+2)) == ((dameth&4)>>2)
473
           )
474
        {
235 Plagman 475
            if (pth->flags & 128)
109 terminx 476
            {
248 terminx 477
                pth->flags &= ~128;
109 terminx 478
                if (gloadtile_art(dapicnum,dapalnum,dameth,pth,0)) return NULL; //reload tile (for animations)
479
            }
480
            return(pth);
481
        }
5 Plagman 482
 
109 terminx 483
    pth = (pthtyp *)calloc(1,sizeof(pthtyp));
484
    if (!pth) return NULL;
5 Plagman 485
 
584 terminx 486
    if (gloadtile_art(dapicnum,dapalnum,dameth,pth,1))
487
    {
109 terminx 488
        free(pth);
489
        return NULL;
490
    }
491
    pth->next = gltexcachead[j];
492
    gltexcachead[j] = pth;
235 Plagman 493
 
109 terminx 494
    return(pth);
5 Plagman 495
}
496
 
584 terminx 497
int gltexmayhavealpha(int dapicnum, int dapalnum)
5 Plagman 498
{
584 terminx 499
    int j = (dapicnum&(GLTEXCACHEADSIZ-1));
109 terminx 500
    pthtyp *pth;
5 Plagman 501
 
331 terminx 502
    for (pth=gltexcachead[j]; pth; pth=pth->next)
109 terminx 503
        if ((pth->picnum == dapicnum) && (pth->palnum == dapalnum))
504
            return((pth->flags&8) != 0);
505
    return(1);
5 Plagman 506
}
507
 
584 terminx 508
void gltexinvalidate(int dapicnum, int dapalnum, int dameth)
5 Plagman 509
{
654 terminx 510
    int j;
109 terminx 511
    pthtyp *pth;
5 Plagman 512
 
109 terminx 513
    j = (dapicnum&(GLTEXCACHEADSIZ-1));
331 terminx 514
    for (pth=gltexcachead[j]; pth; pth=pth->next)
584 terminx 515
        if (pth->picnum == dapicnum && pth->palnum == dapalnum && (pth->flags & 1) == ((dameth&4)>>2))
248 terminx 516
        {
517
            pth->flags |= 128;
518
            if (pth->flags & 16)
519
                pth->ofb->flags |= 128;
520
        }
5 Plagman 521
}
522
 
109 terminx 523
//Make all textures "dirty" so they reload, but not re-allocate
524
//This should be much faster than polymost_glreset()
525
//Use this for palette effects ... but not ones that change every frame!
584 terminx 526
void gltexinvalidateall()
5 Plagman 527
{
584 terminx 528
    int j;
109 terminx 529
    pthtyp *pth;
5 Plagman 530
 
331 terminx 531
    for (j=GLTEXCACHEADSIZ-1;j>=0;j--)
532
        for (pth=gltexcachead[j];pth;pth=pth->next)
248 terminx 533
        {
109 terminx 534
            pth->flags |= 128;
248 terminx 535
            if (pth->flags & 16)
536
                pth->ofb->flags |= 128;
537
        }
109 terminx 538
    clearskins();
5 Plagman 539
#ifdef DEBUGGINGAIDS
109 terminx 540
    OSD_Printf("gltexinvalidateall()\n");
5 Plagman 541
#endif
542
}
543
 
584 terminx 544
void gltexinvalidate8()
415 terminx 545
{
584 terminx 546
    int j;
415 terminx 547
    pthtyp *pth;
5 Plagman 548
 
415 terminx 549
    for (j=GLTEXCACHEADSIZ-1;j>=0;j--)
550
        for (pth=gltexcachead[j];pth;pth=pth->next)
551
        {
552
            if (pth->hicr == NULL)
553
            {
554
                pth->flags |= 128;
555
                if (pth->flags & 16)
556
                    pth->ofb->flags |= 128;
557
            }
558
        }
559
#ifdef DEBUGGINGAIDS
560
    OSD_Printf("gltexinvalidate8()\n");
561
#endif
562
}
563
 
584 terminx 564
void gltexapplyprops(void)
5 Plagman 565
{
584 terminx 566
    int i;
109 terminx 567
    pthtyp *pth;
5 Plagman 568
 
109 terminx 569
    if (glinfo.maxanisotropy > 1.0)
570
    {
584 terminx 571
        if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy) glanisotropy = (int)glinfo.maxanisotropy;
109 terminx 572
    }
5 Plagman 573
 
109 terminx 574
    if (gltexfiltermode < 0) gltexfiltermode = 0;
584 terminx 575
    else if (gltexfiltermode >= (int)numglfiltermodes) gltexfiltermode = numglfiltermodes-1;
576
    for (i=GLTEXCACHEADSIZ-1;i>=0;i--)
577
    {
578
        for (pth=gltexcachead[i];pth;pth=pth->next)
579
        {
109 terminx 580
            bglBindTexture(GL_TEXTURE_2D,pth->glpic);
581
            bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
582
            bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
583
            if (glinfo.maxanisotropy > 1.0)
584
                bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
886 terminx 585
            if (r_fullbrights && pth->flags & 16)
248 terminx 586
            {
587
                bglBindTexture(GL_TEXTURE_2D,pth->ofb->glpic);
588
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
589
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
590
                if (glinfo.maxanisotropy > 1.0)
591
                    bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
592
            }
109 terminx 593
        }
594
    }
5 Plagman 595
 
109 terminx 596
    {
597
        int j;
598
        mdskinmap_t *sk;
599
        md2model *m;
600
 
601
        for (i=0;i<nextmodelid;i++)
602
        {
603
            m = (md2model *)models[i];
604
            if (m->mdnum < 2) continue;
605
            for (j=0;j<m->numskins*(HICEFFECTMASK+1);j++)
606
            {
607
                if (!m->texid[j]) continue;
608
                bglBindTexture(GL_TEXTURE_2D,m->texid[j]);
609
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
610
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
611
                if (glinfo.maxanisotropy > 1.0)
612
                    bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
613
            }
614
 
615
            for (sk=m->skinmap;sk;sk=sk->next)
616
                for (j=0;j<(HICEFFECTMASK+1);j++)
617
                {
618
                    if (!sk->texid[j]) continue;
619
                    bglBindTexture(GL_TEXTURE_2D,sk->texid[j]);
620
                    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
621
                    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
622
                    if (glinfo.maxanisotropy > 1.0)
623
                        bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
624
                }
625
        }
626
    }
5 Plagman 627
}
628
 
629
//--------------------------------------------------------------------------------------------------
630
 
631
static float glox1, gloy1, glox2, gloy2;
632
 
109 terminx 633
//Use this for both initialization and uninitialization of OpenGL.
5 Plagman 634
static int gltexcacnum = -1;
584 terminx 635
void polymost_glreset()
5 Plagman 636
{
584 terminx 637
    int i;
109 terminx 638
    pthtyp *pth, *next;
639
    //Reset if this is -1 (meaning 1st texture call ever), or > 0 (textures in memory)
640
    if (gltexcacnum < 0)
641
    {
642
        gltexcacnum = 0;
5 Plagman 643
 
109 terminx 644
        //Hack for polymost_dorotatesprite calls before 1st polymost_drawrooms()
645
        gcosang = gcosang2 = ((double)16384)/262144.0;
646
        gsinang = gsinang2 = ((double)    0)/262144.0;
647
    }
648
    else
649
    {
584 terminx 650
        for (i=GLTEXCACHEADSIZ-1; i>=0; i--)
651
        {
652
            for (pth=gltexcachead[i]; pth;)
653
            {
109 terminx 654
                next = pth->next;
248 terminx 655
                if (pth->flags & 16) // fullbright textures
656
                {
657
                    bglDeleteTextures(1,&pth->ofb->glpic);
658
                    free(pth->ofb);
659
                }
109 terminx 660
                bglDeleteTextures(1,&pth->glpic);
587 terminx 661
                if (pth->palmap)
662
                {
663
                    //_initprintf("Kill #%d\n",pth->palmap);
664
                    free(pth->palmap);pth->palmap=0;
665
                }
109 terminx 666
                free(pth);
667
                pth = next;
668
            }
669
            gltexcachead[i] = NULL;
670
        }
671
        clearskins();
672
    }
673
 
674
    if (polymosttext) bglDeleteTextures(1,&polymosttext);
675
    polymosttext=0;
676
 
677
    memset(gltexcachead,0,sizeof(gltexcachead));
678
    glox1 = -1;
446 Plagman 679
 
680
    // Depth peeling cleanup
681
    if (peels)
682
    {
454 Plagman 683
        bglDeleteProgramsARB(2, peelprogram);
684
        bglDeleteFramebuffersEXT(r_peelscount + 1, peelfbos);
685
        bglDeleteTextures(r_peelscount + 1, peels);
686
        bglDeleteTextures(3, ztexture);
446 Plagman 687
        free(peels);
688
        free(peelfbos);
689
 
690
        peels = NULL;
691
    }
5 Plagman 692
}
693
 
627 terminx 694
// one-time initialization of OpenGL for polymost
5 Plagman 695
void polymost_glinit()
696
{
109 terminx 697
    GLfloat col[4];
439 Plagman 698
    int     i;
584 terminx 699
    char    notpeeledprogramstring[] =
700
        "!!ARBfp1.0\n"
701
        "OPTION ARB_fog_exp2;\n"
702
        "OPTION ARB_fragment_program_shadow;\n"
703
        "TEMP texsample;\n"
704
        "TEMP depthresult;\n"
705
        "TEX depthresult, fragment.position, texture[1], SHADOWRECT;\n"
706
        "ADD depthresult.a, depthresult.a, -0.5;\n"
707
        "KIL depthresult.a;\n"
708
        "TEX texsample, fragment.texcoord[0], texture[0], 2D;\n"
709
        "MUL result.color, fragment.color, texsample;\n"
710
        "END\n";
711
    char    peeledprogramstring[] =
712
        "!!ARBfp1.0\n"
713
        "OPTION ARB_fog_exp2;\n"
714
        "OPTION ARB_fragment_program_shadow;\n"
715
        "TEMP texsample;\n"
716
        "TEMP depthresult;\n"
717
        "TEX depthresult, fragment.position, texture[2], SHADOWRECT;\n"
718
        "ADD depthresult.a, depthresult.a, -0.5;\n"
719
        "KIL depthresult.a;\n"
720
        "TEX depthresult, fragment.position, texture[1], SHADOWRECT;\n"
721
        "ADD depthresult.a, depthresult.a, -0.5;\n"
722
        "KIL depthresult.a;\n"
723
        "TEX texsample, fragment.texcoord[0], texture[0], 2D;\n"
724
        "MUL result.color, fragment.color, texsample;\n"
725
        "END\n";
5 Plagman 726
 
415 terminx 727
#if 1
387 terminx 728
    if (!Bstrcmp(glinfo.vendor, "ATI Technologies Inc."))
729
    {
730
        initprintf("polymost_glinit(): ATI detected, GL_FOG_HINT = GL_DONT_CARE\n");
731
        bglHint(GL_FOG_HINT,GL_DONT_CARE);
732
    }
733
    else
734
    {
735
        bglHint(GL_FOG_HINT,GL_NICEST);
736
    }
404 terminx 737
#else
738
    bglHint(GL_FOG_HINT,GL_DONT_CARE);
739
#endif
584 terminx 740
 
503 Plagman 741
    bglFogi(GL_FOG_MODE,GL_EXP2);
109 terminx 742
    bglFogf(GL_FOG_DENSITY,1.0); //must be > 0, default is 1
584 terminx 743
    /*    bglFogf(GL_FOG_START,0.0); //default is 0
744
        bglFogf(GL_FOG_END,1.0); //default is 1 */
109 terminx 745
    col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0; //range:0 to 1
746
    bglFogfv(GL_FOG_COLOR,col); //default is 0,0,0,0
5 Plagman 747
 
109 terminx 748
    bglBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
749
 
118 terminx 750
    //bglHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
751
    //bglEnable(GL_LINE_SMOOTH);
752
 
584 terminx 753
    if (glmultisample > 0 && glinfo.multisample)
754
    {
109 terminx 755
        if (glinfo.nvmultisamplehint)
756
            bglHint(GL_MULTISAMPLE_FILTER_HINT_NV, glnvmultisamplehint ? GL_NICEST:GL_FASTEST);
757
        bglEnable(GL_MULTISAMPLE_ARB);
758
    }
439 Plagman 759
 
459 Plagman 760
    if (r_depthpeeling && (!glinfo.arbfp || !glinfo.depthtex || !glinfo.shadow || !glinfo.fbos || !glinfo.rect || !glinfo.multitex))
439 Plagman 761
    {
459 Plagman 762
        OSD_Printf("Your OpenGL implementation doesn't support depth peeling. Disabling...\n");
446 Plagman 763
        r_depthpeeling = 0;
764
    }
765
 
497 Plagman 766
    if (r_detailmapping && (!glinfo.multitex || !glinfo.envcombine))
459 Plagman 767
    {
768
        OSD_Printf("Your OpenGL implementation doesn't support detail mapping. Disabling...\n");
460 Plagman 769
        r_detailmapping = 0;
459 Plagman 770
    }
771
 
497 Plagman 772
    if (r_glowmapping && (!glinfo.multitex || !glinfo.envcombine))
773
    {
774
        OSD_Printf("Your OpenGL implementation doesn't support glow mapping. Disabling...\n");
775
        r_glowmapping = 0;
776
    }
777
 
519 Plagman 778
    if (r_vbos && (!glinfo.vbos))
779
    {
780
        OSD_Printf("Your OpenGL implementation doesn't support Vertex Buffer Objects. Disabling...\n");
781
        r_vbos = 0;
782
    }
783
 
446 Plagman 784
    //depth peeling initialization
785
    if (r_depthpeeling)
786
    {
787
        if (newpeelscount)
788
        {
789
            r_peelscount = newpeelscount;
790
            newpeelscount = 0;
791
        }
454 Plagman 792
        // create the secondary Z-buffers and the Z-backbuffer
497 Plagman 793
        bglGenTextures(3, ztexture);
794
 
795
        i = 0;
796
        while (i < 3)
797
        {
798
            bglBindTexture(GL_TEXTURE_RECTANGLE, ztexture[i]);
799
            bglCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_DEPTH_COMPONENT, 0, 0, xdim, ydim, 0);
800
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
801
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
802
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP);
803
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP);
804
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
805
            if (i < 2)
806
                bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_FUNC_ARB, GL_GREATER);
807
            else
808
                bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LESS);
809
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);
810
 
811
            i++;
812
        }
813
 
814
        // create the various peeling layers as well as the FBOs to render to them
815
        peels = malloc((r_peelscount + 1) * sizeof(GLuint));
816
        bglGenTextures(r_peelscount + 1, peels);
817
 
818
        peelfbos = malloc((r_peelscount + 1) * sizeof(GLuint));
819
        bglGenFramebuffersEXT(r_peelscount + 1, peelfbos);
820
 
821
        i = 0;
822
        while (i <= r_peelscount)
823
        {
824
            bglBindTexture(GL_TEXTURE_RECTANGLE, peels[i]);
825
            bglCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, xdim, ydim, 0);
826
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
827
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
828
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP);
829
            bglTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP);
830
 
831
            bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, peelfbos[i]);
832
            bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE, peels[i], 0);
833
            if (i == r_peelscount) // bakcbuffer
834
                bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE, ztexture[2], 0);
454 Plagman 835
            else if (i < (r_peelscount - 1))
497 Plagman 836
                bglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE, ztexture[i % 2], 0);
837
 
838
            if (bglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
839
            {
840
                OSD_Printf("FBO #%d initialization failed.\n", i);
841
            }
842
 
446 Plagman 843
            bglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
497 Plagman 844
 
845
            i++;
846
        }
847
 
848
        // create the peeling fragment programs
849
        bglGenProgramsARB(2, peelprogram);
850
        bglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, peelprogram[0]);
851
        bglProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(notpeeledprogramstring), notpeeledprogramstring);
852
        bglBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, peelprogram[1]);
853
        bglProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(peeledprogramstring), peeledprogramstring);
439 Plagman 854
    }
513 Plagman 855
 
856
    bglEnableClientState(GL_VERTEX_ARRAY);
857
    bglEnableClientState(GL_TEXTURE_COORD_ARRAY);
5 Plagman 858
}
859
 
584 terminx 860
void resizeglcheck()
5 Plagman 861
{
109 terminx 862
    float m[4][4];
26 terminx 863
    int fovcorrect;
5 Plagman 864
 
584 terminx 865
    if (glredbluemode < lastglredbluemode)
866
    {
109 terminx 867
        glox1 = -1;
868
        bglColorMask(1,1,1,1);
584 terminx 869
    }
870
    else if (glredbluemode != lastglredbluemode)
871
    {
109 terminx 872
        redblueclearcnt = 0;
873
    }
874
    lastglredbluemode = glredbluemode;
5 Plagman 875
 
109 terminx 876
    //FUK
877
    if (lastglpolygonmode != glpolygonmode)
878
    {
879
        lastglpolygonmode = glpolygonmode;
331 terminx 880
        switch (glpolygonmode)
109 terminx 881
        {
882
        default:
331 terminx 883
        case 0:
884
            bglPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break;
885
        case 1:
886
            bglPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break;
887
        case 2:
888
            bglPolygonMode(GL_FRONT_AND_BACK,GL_POINT); break;
109 terminx 889
        }
890
    }
891
    if (glpolygonmode) //FUK
892
    {
893
        bglClearColor(1.0,1.0,1.0,0.0);
894
        bglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
895
        bglDisable(GL_TEXTURE_2D);
896
    }
5 Plagman 897
 
109 terminx 898
    if ((glox1 != windowx1) || (gloy1 != windowy1) || (glox2 != windowx2) || (gloy2 != windowy2))
899
    {
900
        glox1 = windowx1; gloy1 = windowy1;
901
        glox2 = windowx2; gloy2 = windowy2;
902
 
204 terminx 903
        fovcorrect = glprojectionhacks?(glwidescreen?0:(((windowx2-windowx1+1) * 1.2) - (windowx2-windowx1+1))):0;
5 Plagman 904
 
109 terminx 905
        bglViewport(windowx1 - (fovcorrect / 2), yres-(windowy2+1),windowx2-windowx1+1 + fovcorrect, windowy2-windowy1+1);
5 Plagman 906
 
109 terminx 907
        bglMatrixMode(GL_PROJECTION);
908
        memset(m,0,sizeof(m));
204 terminx 909
        m[0][0] = (float)ydimen / (glprojectionhacks?1.2:1); m[0][2] = 1.0;
109 terminx 910
        m[1][1] = (float)xdimen; m[1][2] = 1.0;
204 terminx 911
        m[2][2] = 1.0; m[2][3] = (float)ydimen / (glprojectionhacks?1.2:1);
109 terminx 912
        m[3][2] =-1.0;
913
        bglLoadMatrixf(&m[0][0]);
914
        //bglLoadIdentity();
5 Plagman 915
 
109 terminx 916
        bglMatrixMode(GL_MODELVIEW);
917
        bglLoadIdentity();
5 Plagman 918
 
109 terminx 919
        if (!nofog) bglEnable(GL_FOG);
5 Plagman 920
 
109 terminx 921
        //bglEnable(GL_TEXTURE_2D);
922
    }
5 Plagman 923
}
924
 
584 terminx 925
void fixtransparency(coltype *dapic, int daxsiz, int daysiz, int daxsiz2, int daysiz2, int dameth)
5 Plagman 926
{
109 terminx 927
    coltype *wpptr;
584 terminx 928
    int j, x, y, r, g, b, dox, doy, naxsiz2;
5 Plagman 929
 
109 terminx 930
    dox = daxsiz2-1; doy = daysiz2-1;
931
    if (dameth&4) { dox = min(dox,daxsiz); doy = min(doy,daysiz); }
932
    else { daxsiz = daxsiz2; daysiz = daysiz2; } //Make repeating textures duplicate top/left parts
5 Plagman 933
 
109 terminx 934
    daxsiz--; daysiz--; naxsiz2 = -daxsiz2; //Hacks for optimization inside loop
5 Plagman 935
 
109 terminx 936
    //Set transparent pixels to average color of neighboring opaque pixels
937
    //Doing this makes bilinear filtering look much better for masked textures (I.E. sprites)
331 terminx 938
    for (y=doy;y>=0;y--)
109 terminx 939
    {
940
        wpptr = &dapic[y*daxsiz2+dox];
331 terminx 941
        for (x=dox;x>=0;x--,wpptr--)
109 terminx 942
        {
943
            if (wpptr->a) continue;
944
            r = g = b = j = 0;
584 terminx 945
            if ((x>     0) && (wpptr[     -1].a)) { r += (int)wpptr[     -1].r; g += (int)wpptr[     -1].g; b += (int)wpptr[     -1].b; j++; }
946
            if ((x<daxsiz) && (wpptr[     +1].a)) { r += (int)wpptr[     +1].r; g += (int)wpptr[     +1].g; b += (int)wpptr[     +1].b; j++; }
947
            if ((y>     0) && (wpptr[naxsiz2].a)) { r += (int)wpptr[naxsiz2].r; g += (int)wpptr[naxsiz2].g; b += (int)wpptr[naxsiz2].b; j++; }
948
            if ((y<daysiz) && (wpptr[daxsiz2].a)) { r += (int)wpptr[daxsiz2].r; g += (int)wpptr[daxsiz2].g; b += (int)wpptr[daxsiz2].b; j++; }
331 terminx 949
            switch (j)
109 terminx 950
            {
331 terminx 951
            case 1:
952
                wpptr->r =   r            ; wpptr->g =   g            ; wpptr->b =   b            ; break;
953
            case 2:
954
                wpptr->r = ((r   +  1)>>1); wpptr->g = ((g   +  1)>>1); wpptr->b = ((b   +  1)>>1); break;
955
            case 3:
956
                wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); break;
957
            case 4:
958
                wpptr->r = ((r   +  2)>>2); wpptr->g = ((g   +  2)>>2); wpptr->b = ((b   +  2)>>2); break;
959
            default:
960
                break;
109 terminx 961
            }
962
        }
963
    }
5 Plagman 964
}
965
 
584 terminx 966
static void uploadtexture(int doalloc, int xsiz, int ysiz, int intexfmt, int texfmt, coltype *pic, int tsizx, int tsizy, int dameth)
5 Plagman 967
{
109 terminx 968
    coltype *wpptr, *rpptr;
584 terminx 969
    int x2, y2, j, js=0, x3, y3, y, x, r, g, b, a, k;
5 Plagman 970
 
584 terminx 971
    if (gltexmaxsize <= 0)
972
    {
109 terminx 973
        GLint i = 0;
974
        bglGetIntegerv(GL_MAX_TEXTURE_SIZE, &i);
975
        if (!i) gltexmaxsize = 6;   // 2^6 = 64 == default GL max texture size
584 terminx 976
        else
977
        {
109 terminx 978
            gltexmaxsize = 0;
979
            for (; i>1; i>>=1) gltexmaxsize++;
980
        }
981
    }
5 Plagman 982
 
109 terminx 983
    js = max(0,min(gltexmaxsize-1,gltexmiplevel));
984
    gltexmiplevel = js;
985
    while ((xsiz>>js) > (1<<gltexmaxsize) || (ysiz>>js) > (1<<gltexmaxsize)) js++;
5 Plagman 986
 
109 terminx 987
    /*
988
    OSD_Printf("Uploading %dx%d %s as %s\n", xsiz,ysiz,
989
                (texfmt==GL_RGBA?"GL_RGBA":
990
                 texfmt==GL_RGB?"GL_RGB":
991
                 texfmt==GL_BGR?"GL_BGR":
992
                 texfmt==GL_BGRA?"GL_BGRA":"other"),
993
                (intexfmt==GL_RGBA?"GL_RGBA":
994
                 intexfmt==GL_RGB?"GL_RGB":
995
                 intexfmt==GL_COMPRESSED_RGBA_ARB?"GL_COMPRESSED_RGBA_ARB":
996
                 intexfmt==GL_COMPRESSED_RGB_ARB?"GL_COMPRESSED_RGB_ARB":"other"));
997
    */
998
 
584 terminx 999
    if (js == 0)
1000
    {
109 terminx 1001
        if (doalloc&1)
1002
            bglTexImage2D(GL_TEXTURE_2D,0,intexfmt,xsiz,ysiz,0,texfmt,GL_UNSIGNED_BYTE,pic); //loading 1st time
1003
        else
1004
            bglTexSubImage2D(GL_TEXTURE_2D,0,0,0,xsiz,ysiz,texfmt,GL_UNSIGNED_BYTE,pic); //overwrite old texture
1005
    }
1006
 
5 Plagman 1007
#if 0
109 terminx 1008
    gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8,xsiz,ysiz,texfmt,GL_UNSIGNED_BYTE,pic); //Needs C++ to link?
5 Plagman 1009
#elif 1
109 terminx 1010
    x2 = xsiz; y2 = ysiz;
331 terminx 1011
    for (j=1;(x2 > 1) || (y2 > 1);j++)
109 terminx 1012
    {
1013
        //x3 = ((x2+1)>>1); y3 = ((y2+1)>>1);
1014
        x3 = max(1, x2 >> 1); y3 = max(1, y2 >> 1);             // this came from the GL_ARB_texture_non_power_of_two spec
331 terminx 1015
        for (y=0;y<y3;y++)
109 terminx 1016
        {
1017
            wpptr = &pic[y*x3]; rpptr = &pic[(y<<1)*x2];
331 terminx 1018
            for (x=0;x<x3;x++,wpptr++,rpptr+=2)
109 terminx 1019
            {
1020
                r = g = b = a = k = 0;
584 terminx 1021
                if (rpptr[0].a)                  { r += (int)rpptr[0].r; g += (int)rpptr[0].g; b += (int)rpptr[0].b; a += (int)rpptr[0].a; k++; }
1022
                if ((x+x+1 < x2) && (rpptr[1].a)) { r += (int)rpptr[1].r; g += (int)rpptr[1].g; b += (int)rpptr[1].b; a += (int)rpptr[1].a; k++; }
109 terminx 1023
                if (y+y+1 < y2)
1024
                {
584 terminx 1025
                    if ((rpptr[x2].a)) { r += (int)rpptr[x2  ].r; g += (int)rpptr[x2  ].g; b += (int)rpptr[x2  ].b; a += (int)rpptr[x2  ].a; k++; }
1026
                    if ((x+x+1 < x2) && (rpptr[x2+1].a)) { r += (int)rpptr[x2+1].r; g += (int)rpptr[x2+1].g; b += (int)rpptr[x2+1].b; a += (int)rpptr[x2+1].a; k++; }
109 terminx 1027
                }
331 terminx 1028
                switch (k)
109 terminx 1029
                {
1030
                case 0:
331 terminx 1031
                case 1:
1032
                    wpptr->r = r; wpptr->g = g; wpptr->b = b; wpptr->a = a; break;
1033
                case 2:
1034
                    wpptr->r = ((r+1)>>1); wpptr->g = ((g+1)>>1); wpptr->b = ((b+1)>>1); wpptr->a = ((a+1)>>1); break;
1035
                case 3:
1036
                    wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); wpptr->a = ((a*85+128)>>8); break;
1037
                case 4:
1038
                    wpptr->r = ((r+2)>>2); wpptr->g = ((g+2)>>2); wpptr->b = ((b+2)>>2); wpptr->a = ((a+2)>>2); break;
1039
                default:
1040
                    break;
109 terminx 1041
                }
1042
                //if (wpptr->a) wpptr->a = 255;
1043
            }
1044
        }
1045
        if (tsizx >= 0) fixtransparency(pic,(tsizx+(1<<j)-1)>>j,(tsizy+(1<<j)-1)>>j,x3,y3,dameth);
584 terminx 1046
        if (j >= js)
1047
        {
109 terminx 1048
            if (doalloc&1)
1049
                bglTexImage2D(GL_TEXTURE_2D,j-js,intexfmt,x3,y3,0,texfmt,GL_UNSIGNED_BYTE,pic); //loading 1st time
1050
            else
1051
                bglTexSubImage2D(GL_TEXTURE_2D,j-js,0,0,x3,y3,texfmt,GL_UNSIGNED_BYTE,pic); //overwrite old texture
1052
        }
1053
        x2 = x3; y2 = y3;
1054
    }
5 Plagman 1055
#endif
1056
}
1057
 
584 terminx 1058
int gloadtile_art(int dapic, int dapal, int dameth, pthtyp *pth, int doalloc)
5 Plagman 1059
{
109 terminx 1060
    coltype *pic, *wpptr;
654 terminx 1061
    int x, y, x2, y2, xsiz, ysiz, dacol, tsizx, tsizy;
228 Plagman 1062
    char hasalpha = 0, hasfullbright = 0;
5 Plagman 1063
 
109 terminx 1064
    tsizx = tilesizx[dapic];
1065
    tsizy = tilesizy[dapic];
584 terminx 1066
    if (!glinfo.texnpot)
1067
    {
331 terminx 1068
        for (xsiz=1;xsiz<tsizx;xsiz+=xsiz);
1069
        for (ysiz=1;ysiz<tsizy;ysiz+=ysiz);
584 terminx 1070
    }
1071
    else
1072
    {
1073
        if ((tsizx|tsizy) == 0)
1074
        {
109 terminx 1075
            xsiz = ysiz = 1;
584 terminx 1076
        }
1077
        else
1078
        {
109 terminx 1079
            xsiz = tsizx;
1080
            ysiz = tsizy;
1081
        }
1082
    }
5 Plagman 1083
 
109 terminx 1084
    pic = (coltype *)malloc(xsiz*ysiz*sizeof(coltype));
1085
    if (!pic) return 1;
5 Plagman 1086
 
109 terminx 1087
    if (!waloff[dapic])
1088
    {
1089
        //Force invalid textures to draw something - an almost purely transparency texture
1090
        //This allows the Z-buffer to be updated for mirrors (which are invalidated textures)
1091
        pic[0].r = pic[0].g = pic[0].b = 0; pic[0].a = 1;
1092
        tsizx = tsizy = 1; hasalpha = 1;
1093
    }
1094
    else
1095
    {
331 terminx 1096
        for (y=0;y<ysiz;y++)
109 terminx 1097
        {
1098
            if (y < tsizy) y2 = y; else y2 = y-tsizy;
1099
            wpptr = &pic[y*xsiz];
331 terminx 1100
            for (x=0;x<xsiz;x++,wpptr++)
109 terminx 1101
            {
1102
                if ((dameth&4) && ((x >= tsizx) || (y >= tsizy))) //Clamp texture
584 terminx 1103
                    { wpptr->r = wpptr->g = wpptr->b = wpptr->a = 0; continue; }
109 terminx 1104
                if (x < tsizx) x2 = x; else x2 = x-tsizx;
584 terminx 1105
                dacol = (int)(*(unsigned char *)(waloff[dapic]+x2*tsizy+y2));
248 terminx 1106
                if (!fullbrightloadingpass)
584 terminx 1107
                {
1108
                    // regular texture
248 terminx 1109
                    if ((dacol > 239) && (dacol != 255))
1110
                        hasfullbright = 1;
1111
                    wpptr->a = 255;
1112
                }
1113
                else if (fullbrightloadingpass == 1)
584 terminx 1114
                {
1115
                    // texture with only fullbright areas
1116
                    if (dacol < 240)    // regular colors
1117
                    {
248 terminx 1118
                        wpptr->a = 0; hasalpha = 1;
584 terminx 1119
                    }
1120
                    else   // fullbright
1121
                    {
248 terminx 1122
                        wpptr->a = 255;
1123
                    }
1124
                }
1125
                if (dacol != 255)
584 terminx 1126
                    dacol = (int)((unsigned char)palookup[dapal][dacol]);
1127
                else
1128
                {
248 terminx 1129
                    wpptr->a = 0; hasalpha = 1;
1130
                }
584 terminx 1131
                if (gammabrightness)
1132
                {
109 terminx 1133
                    wpptr->r = curpalette[dacol].r;
1134
                    wpptr->g = curpalette[dacol].g;
1135
                    wpptr->b = curpalette[dacol].b;
584 terminx 1136
                }
1137
                else
1138
                {
109 terminx 1139
                    wpptr->r = britable[curbrightness][ curpalette[dacol].r ];
1140
                    wpptr->g = britable[curbrightness][ curpalette[dacol].g ];
1141
                    wpptr->b = britable[curbrightness][ curpalette[dacol].b ];
1142
                }
1143
            }
1144
        }
1145
    }
5 Plagman 1146
 
109 terminx 1147
    if (doalloc) bglGenTextures(1,(GLuint*)&pth->glpic);  //# of textures (make OpenGL allocate structure)
1148
    bglBindTexture(GL_TEXTURE_2D,pth->glpic);
5 Plagman 1149
 
109 terminx 1150
    fixtransparency(pic,tsizx,tsizy,xsiz,ysiz,dameth);
1151
    uploadtexture(doalloc,xsiz,ysiz,hasalpha?GL_RGBA:GL_RGB,GL_RGBA,pic,tsizx,tsizy,dameth);
5 Plagman 1152
 
109 terminx 1153
    if (gltexfiltermode < 0) gltexfiltermode = 0;
584 terminx 1154
    else if (gltexfiltermode >= (int)numglfiltermodes) gltexfiltermode = numglfiltermodes-1;
109 terminx 1155
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
1156
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
5 Plagman 1157
 
109 terminx 1158
    if (glinfo.maxanisotropy > 1.0)
1159
    {
584 terminx 1160
        if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy) glanisotropy = (int)glinfo.maxanisotropy;
109 terminx 1161
        bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
1162
    }
5 Plagman 1163
 
109 terminx 1164
    if (!(dameth&4))
1165
    {
1166
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
1167
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
1168
    }
1169
    else
584 terminx 1170
    {
1171
        //For sprite textures, clamping looks better than wrapping
109 terminx 1172
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
1173
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
1174
    }
5 Plagman 1175
 
109 terminx 1176
    if (pic) free(pic);
5 Plagman 1177
 
109 terminx 1178
    pth->picnum = dapic;
1179
    pth->palnum = dapal;
1180
    pth->effects = 0;
228 Plagman 1181
    pth->flags = ((dameth&4)>>2) | (hasalpha<<3) | (hasfullbright<<4);
109 terminx 1182
    pth->hicr = NULL;
1183
 
248 terminx 1184
    if ((hasfullbright) && (!fullbrightloadingpass))
1185
    {
1186
        // load the ONLY texture that'll be assembled with the regular one to make the final texture with fullbright pixels
1187
        fullbrightloadingpass = 1;
1188
        pth->ofb = (pthtyp *)calloc(1,sizeof(pthtyp));
1189
        if (!pth->ofb) return 1;
1190
        if (gloadtile_art(dapic, dapal, dameth, pth->ofb, 1)) return 1;
235 Plagman 1191
 
248 terminx 1192
        fullbrightloadingpass = 0;
1193
    }
109 terminx 1194
    return 0;
5 Plagman 1195
}
1196
 
1197
// JONOF'S COMPRESSED TEXTURE CACHE STUFF ---------------------------------------------------
1198
static inline void phex(unsigned char v, char *s)
1199
{
109 terminx 1200
    int x;
1201
    x = v>>4;
1202
    s[0] = x<10 ? (x+'0') : (x-10+'a');
1203
    x = v&15;
1204
    s[1] = x<10 ? (x+'0') : (x-10+'a');
5 Plagman 1205
}
1206
 
584 terminx 1207
int trytexcache(char *fn, int len, int dameth, char effect, texcacheheader *head)
5 Plagman 1208
{
584 terminx 1209
    int fil, fp;
109 terminx 1210
    char cachefn[BMAX_PATH], *cp;
1211
    unsigned char mdsum[16];
1212
 
1213
    if (!glinfo.texcompr || !glusetexcompr || !glusetexcache) return -1;
584 terminx 1214
    if (!bglCompressedTexImage2DARB || !bglGetCompressedTexImageARB)
1215
    {
109 terminx 1216
        // lacking the necessary extensions to do this
1217
        initprintf("Warning: the GL driver lacks necessary functions to use caching\n");
1218
        glusetexcache = 0;
1219
        return -1;
1220
    }
1221
 
194 terminx 1222
    md4once((unsigned char *)fn, strlen(fn), mdsum);
109 terminx 1223
    for (cp = cachefn, fp = 0; (*cp = TEXCACHEDIR[fp]); cp++,fp++);
1224
    *(cp++) = '/';
1225
    for (fp = 0; fp < 16; phex(mdsum[fp++], cp), cp+=2);
584 terminx 1226
    sprintf(cp, "-%x-%x%x", len, dameth, effect);
109 terminx 1227
 
1228
    fil = kopen4load(cachefn, 0);
1229
    if (fil < 0) return -1;
1230
 
1231
    /* initprintf("Loading cached tex: %s\n", cachefn); */
1232
 
1233
    if (kread(fil, head, sizeof(texcacheheader)) < (int)sizeof(texcacheheader)) goto failure;
1234
    if (memcmp(head->magic, "Polymost", 8)) goto failure;
1235
 
1236
    head->xdim = B_LITTLE32(head->xdim);
1237
    head->ydim = B_LITTLE32(head->ydim);
1238
    head->flags = B_LITTLE32(head->flags);
1239
 
883 terminx 1240
    if (gltexmaxsize && (head->xdim > (1<<gltexmaxsize) || head->ydim > (1<<gltexmaxsize))) goto failure;
109 terminx 1241
    if (!glinfo.texnpot && (head->flags & 1)) goto failure;
1242
 
1243
    return fil;
5 Plagman 1244
failure:
109 terminx 1245
    kclose(fil);
1246
    return -1;
5 Plagman 1247
}
1248
 
584 terminx 1249
void writexcache(char *fn, int len, int dameth, char effect, texcacheheader *head)
5 Plagman 1250
{
584 terminx 1251
    int fil=-1, fp;
109 terminx 1252
    char cachefn[BMAX_PATH], *cp;
1253
    unsigned char mdsum[16];
1254
    texcachepicture pict;
1255
    char *pic = NULL, *packbuf = NULL;
1256
    void *midbuf = NULL;
584 terminx 1257
    unsigned int alloclen=0, level, miplen;
1258
    unsigned int padx=0, pady=0;
109 terminx 1259
    GLuint gi;
5 Plagman 1260
 
728 terminx 1261
    if (!glinfo.texcompr || !glusetexcompr || !glusetexcache) {initprintf("\n");return;}
584 terminx 1262
    if (!bglCompressedTexImage2DARB || !bglGetCompressedTexImageARB)
1263
    {
109 terminx 1264
        // lacking the necessary extensions to do this
1265
        initprintf("Warning: the GL driver lacks necessary functions to use caching\n");
1266
        glusetexcache = 0;
1267
        return;
1268
    }
5 Plagman 1269
 
109 terminx 1270
    {
1271
        struct stat st;
584 terminx 1272
        if (stat(TEXCACHEDIR, &st) < 0)
1273
        {
1274
            if (errno == ENOENT)     // path doesn't exist
1275
            {
109 terminx 1276
                // try to create the cache directory
584 terminx 1277
                if (Bmkdir(TEXCACHEDIR, S_IRWXU) < 0)
1278
                {
109 terminx 1279
                    initprintf("Failed to create texture cache directory %s\n", TEXCACHEDIR);
1280
                    glusetexcache = 0;
1281
                    return;
584 terminx 1282
                }
1283
                else initprintf("Created texture cache directory %s\n", TEXCACHEDIR);
1284
            }
1285
            else
1286
            {
109 terminx 1287
                // another type of failure
1288
                glusetexcache = 0;
1289
                return;
1290
            }
584 terminx 1291
        }
1292
        else if ((st.st_mode & S_IFDIR) != S_IFDIR)
1293
        {
109 terminx 1294
            // cache directory isn't a directory
1295
            glusetexcache = 0;
1296
            return;
1297
        }
1298
    }
5 Plagman 1299
 
109 terminx 1300
    gi = GL_FALSE;
347 terminx 1301
    bglGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, (GLint *)&gi);
109 terminx 1302
    if (gi != GL_TRUE) return;
5 Plagman 1303
 
194 terminx 1304
    md4once((unsigned char *)fn, strlen(fn), mdsum);
109 terminx 1305
    for (cp = cachefn, fp = 0; (*cp = TEXCACHEDIR[fp]); cp++,fp++);
1306
    *(cp++) = '/';
1307
    for (fp = 0; fp < 16; phex(mdsum[fp++], cp), cp+=2);
584 terminx 1308
    sprintf(cp, "-%x-%x%x", len, dameth, effect);
5 Plagman 1309
 
109 terminx 1310
    initprintf("Writing cached tex: %s\n", cachefn);
5 Plagman 1311
 
109 terminx 1312
    fil = Bopen(cachefn,BO_BINARY|BO_CREAT|BO_TRUNC|BO_RDWR,BS_IREAD|BS_IWRITE);
1313
    if (fil < 0) return;
5 Plagman 1314
 
109 terminx 1315
    memcpy(head->magic, "Polymost", 8);   // sizes are set by caller
5 Plagman 1316
 
109 terminx 1317
    if (glusetexcachecompression) head->flags |= 4;
5 Plagman 1318
 
109 terminx 1319
    head->xdim = B_LITTLE32(head->xdim);
1320
    head->ydim = B_LITTLE32(head->ydim);
1321
    head->flags = B_LITTLE32(head->flags);
5 Plagman 1322
 
109 terminx 1323
    if (Bwrite(fil, head, sizeof(texcacheheader)) != sizeof(texcacheheader)) goto failure;
5 Plagman 1324
 
109 terminx 1325
    bglGetError();
584 terminx 1326
    for (level = 0; level==0 || (padx > 1 || pady > 1); level++)
1327
    {
347 terminx 1328
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED_ARB, (GLint *)&gi);
109 terminx 1329
        if (bglGetError() != GL_NO_ERROR) goto failure;
1330
        if (gi != GL_TRUE) goto failure;   // an uncompressed mipmap
347 terminx 1331
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_INTERNAL_FORMAT, (GLint *)&gi);
109 terminx 1332
        if (bglGetError() != GL_NO_ERROR) goto failure;
1333
        pict.format = B_LITTLE32(gi);
347 terminx 1334
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_WIDTH, (GLint *)&gi);
109 terminx 1335
        if (bglGetError() != GL_NO_ERROR) goto failure;
1336
        padx = gi; pict.xdim = B_LITTLE32(gi);
347 terminx 1337
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_HEIGHT, (GLint *)&gi);
109 terminx 1338
        if (bglGetError() != GL_NO_ERROR) goto failure;
1339
        pady = gi; pict.ydim = B_LITTLE32(gi);
347 terminx 1340
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_BORDER, (GLint *)&gi);
109 terminx 1341
        if (bglGetError() != GL_NO_ERROR) goto failure;
1342
        pict.border = B_LITTLE32(gi);
347 terminx 1343
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_DEPTH, (GLint *)&gi);
109 terminx 1344
        if (bglGetError() != GL_NO_ERROR) goto failure;
1345
        pict.depth = B_LITTLE32(gi);
347 terminx 1346
        bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, (GLint *)&gi);
109 terminx 1347
        if (bglGetError() != GL_NO_ERROR) goto failure;
584 terminx 1348
        miplen = (int)gi; pict.size = B_LITTLE32(gi);
5 Plagman 1349
 
584 terminx 1350
        if (alloclen < miplen)
1351
        {
109 terminx 1352
            void *picc = realloc(pic, miplen);
1353
            if (!picc) goto failure; else pic = picc;
1354
            alloclen = miplen;
5 Plagman 1355
 
109 terminx 1356
            picc = realloc(packbuf, alloclen+16);
1357
            if (!picc) goto failure; else packbuf = picc;
5 Plagman 1358
 
109 terminx 1359
            picc = realloc(midbuf, miplen);
1360
            if (!picc) goto failure; else midbuf = picc;
1361
        }
5 Plagman 1362
 
109 terminx 1363
        bglGetCompressedTexImageARB(GL_TEXTURE_2D, level, pic);
1364
        if (bglGetError() != GL_NO_ERROR) goto failure;
5 Plagman 1365
 
109 terminx 1366
        if (Bwrite(fil, &pict, sizeof(texcachepicture)) != sizeof(texcachepicture)) goto failure;
1367
        if (dxtfilter(fil, &pict, pic, midbuf, packbuf, miplen)) goto failure;
1368
    }
5 Plagman 1369
 
1370
failure:
109 terminx 1371
    if (fil>=0) Bclose(fil);
1372
    if (midbuf) free(midbuf);
1373
    if (pic) free(pic);
1374
    if (packbuf) free(packbuf);
5 Plagman 1375
}
1376
 
587 terminx 1377
int gloadtile_cached(int fil, texcacheheader *head, int *doalloc, pthtyp *pth,int dapalnum)
5 Plagman 1378
{
109 terminx 1379
    int level, r;
1380
    texcachepicture pict;
1381
    char *pic = NULL, *packbuf = NULL;
1382
    void *midbuf = NULL;
584 terminx 1383
    int alloclen=0;
5 Plagman 1384
 
654 terminx 1385
    UNREFERENCED_PARAMETER(dapalnum);
1386
 
584 terminx 1387
    if (*doalloc&1)
1388
    {
109 terminx 1389
        bglGenTextures(1,(GLuint*)&pth->glpic);  //# of textures (make OpenGL allocate structure)
1390
        *doalloc |= 2;   // prevents bglGenTextures being called again if we fail in here
1391
    }
1392
    bglBindTexture(GL_TEXTURE_2D,pth->glpic);
5 Plagman 1393
 
109 terminx 1394
    pth->sizx = head->xdim;
1395
    pth->sizy = head->ydim;
5 Plagman 1396
 
109 terminx 1397
    bglGetError();
5 Plagman 1398
 
109 terminx 1399
    // load the mipmaps
584 terminx 1400
    for (level = 0; level==0 || (pict.xdim > 1 || pict.ydim > 1); level++)
1401
    {
109 terminx 1402
        r = kread(fil, &pict, sizeof(texcachepicture));
1403
        if (r < (int)sizeof(texcachepicture)) goto failure;
5 Plagman 1404
 
109 terminx 1405
        pict.size = B_LITTLE32(pict.size);
1406
        pict.format = B_LITTLE32(pict.format);
1407
        pict.xdim = B_LITTLE32(pict.xdim);
1408
        pict.ydim = B_LITTLE32(pict.ydim);
1409
        pict.border = B_LITTLE32(pict.border);
1410
        pict.depth = B_LITTLE32(pict.depth);
5 Plagman 1411
 
584 terminx 1412
        if (alloclen < pict.size)
1413
        {
109 terminx 1414
            void *picc = realloc(pic, pict.size);
1415
            if (!picc) goto failure; else pic = picc;
1416
            alloclen = pict.size;
5 Plagman 1417
 
109 terminx 1418
            picc = realloc(packbuf, alloclen+16);
1419
            if (!picc) goto failure; else packbuf = picc;
5 Plagman 1420
 
109 terminx 1421
            picc = realloc(midbuf, pict.size);
1422
            if (!picc) goto failure; else midbuf = picc;
1423
        }
5 Plagman 1424
 
109 terminx 1425
        if (dedxtfilter(fil, &pict, pic, midbuf, packbuf, (head->flags&4)==4)) goto failure;
5 Plagman 1426
 
109 terminx 1427
        bglCompressedTexImage2DARB(GL_TEXTURE_2D,level,pict.format,pict.xdim,pict.ydim,pict.border,
1428
                                   pict.size,pic);
1429
        if (bglGetError() != GL_NO_ERROR) goto failure;
614 terminx 1430
 
1431
        {
1432
            GLint format;
1433
            bglGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_INTERNAL_FORMAT, &format);
1434
            if (bglGetError() != GL_NO_ERROR) goto failure;
1435
            format = B_LITTLE32(format);
1436
            if (pict.format != format)
1437
            {
1438
                initprintf("invalid texture cache file format %d %d\n",pict.format, format);
1439
                goto failure;
1440
            }
1441
        }
1442
 
109 terminx 1443
    }
5 Plagman 1444
 
109 terminx 1445
    if (midbuf) free(midbuf);
1446
    if (pic) free(pic);
1447
    if (packbuf) free(packbuf);
1448
    return 0;
5 Plagman 1449
failure:
109 terminx 1450
    if (midbuf) free(midbuf);
1451
    if (pic) free(pic);
1452
    if (packbuf) free(packbuf);
1453
    return -1;
5 Plagman 1454
}
1455
// --------------------------------------------------- JONOF'S COMPRESSED TEXTURE CACHE STUFF
723 terminx 1456
static void applypalmapsT(char *pic, int sizx, int sizy, int dapic,int dapalnum, int dameth)
587 terminx 1457
{
1458
    //_initprintf("%d\n",pal);
1459
    int stage;
723 terminx 1460
    pthtyp *pichead1=pichead;
1461
 
587 terminx 1462
    for (stage=0;stage<MAXPALCONV;stage++)
1463
    {
723 terminx 1464
        int pal1=0,pal2=dapalnum;
589 plagman 1465
        pthtyp *pth;
723 terminx 1466
        getpalmap(&stage,&pal1,&pal2);
587 terminx 1467
        if (!pal1)return;
5 Plagman 1468
 
723 terminx 1469
        //_initprintf("Pal: %d\n",pal1);
1470
        if (hicfindsubst(dapic, pal1, 0))
1471
            gltexcache(dapic, pal1, dameth);
1472
        for (pth=pichead1; pth; pth=pth->next)
587 terminx 1473
            if (pth->palnum ==pal1&&pth->palmap)break;
1474
        if (!pth||pth->size!=sizx*sizy)continue;
1475
 
1476
        applypalmap(pic,pth->palmap,pth->size,pal2);
1477
    }
1478
}
1479
 
1480
int gloadtile_hi(int dapic,int dapalnum, int facen, hicreplctyp *hicr, int dameth, pthtyp *pth, int doalloc, char effect)
5 Plagman 1481
{
109 terminx 1482
    coltype *pic = NULL, *rpptr;
654 terminx 1483
    int j, x, y, xsiz=0, ysiz=0, tsizx, tsizy;
665 terminx 1484
    int r, g, b;
5 Plagman 1485
 
109 terminx 1486
    char *picfil = NULL, *fn, hasalpha = 255;
584 terminx 1487
    int picfillen, texfmt = GL_RGBA, intexfmt = GL_RGBA, filh;
5 Plagman 1488
 
584 terminx 1489
    int cachefil = -1;
109 terminx 1490
    texcacheheader cachead;
5 Plagman 1491
 
109 terminx 1492
    if (!hicr) return -1;
584 terminx 1493
    if (facen > 0)
1494
    {
109 terminx 1495
        if (!hicr->skybox) return -1;
1496
        if (facen > 6) return -1;
1497
        if (!hicr->skybox->face[facen-1]) return -1;
1498
        fn = hicr->skybox->face[facen-1];
584 terminx 1499
    }
1500
    else
1501
    {
109 terminx 1502
        if (!hicr->filename) return -1;
1503
        fn = hicr->filename;
1504
    }
5 Plagman 1505
 
584 terminx 1506
    if ((filh = kopen4load(fn, 0)) < 0)
1507
    {
109 terminx 1508
        initprintf("hightile: %s (pic %d) not found\n", fn, dapic);
1509
        if (facen > 0)
1510
            hicr->skybox->ignore = 1;
1511
        else
1512
            hicr->ignore = 1;
1513
        return -1;
1514
    }
1515
    picfillen = kfilelength(filh);
5 Plagman 1516
 
109 terminx 1517
    kclose(filh);       // FIXME: shouldn't have to do this. bug in cache1d.c
5 Plagman 1518
 
587 terminx 1519
    cachefil = trytexcache(fn, picfillen+(dapalnum<<8), dameth, effect, &cachead);
1520
    if (cachefil >= 0 && !gloadtile_cached(cachefil, &cachead, &doalloc, pth, dapalnum))
584 terminx 1521
    {
109 terminx 1522
        tsizx = cachead.xdim;
1523
        tsizy = cachead.ydim;
1524
        hasalpha = (cachead.flags & 2) ? 0 : 255;
1525
        kclose(cachefil);
1526
        //kclose(filh); // FIXME: uncomment when cache1d.c is fixed
1527
        // cachefil >= 0, so it won't be rewritten
584 terminx 1528
    }
1529
    else
1530
    {
109 terminx 1531
        if (cachefil >= 0) kclose(cachefil);
1532
        cachefil = -1;  // the compressed version will be saved to disk
5 Plagman 1533
 
109 terminx 1534
        if ((filh = kopen4load(fn, 0)) < 0) return -1;
5 Plagman 1535
 
584 terminx 1536
        picfil = (char *)malloc(picfillen); if (!picfil) { kclose(filh); return 1; }
109 terminx 1537
        kread(filh, picfil, picfillen);
1538
        kclose(filh);
5 Plagman 1539
 
109 terminx 1540
        // tsizx/y = replacement texture's natural size
1541
        // xsiz/y = 2^x size of replacement
5 Plagman 1542
 
109 terminx 1543
        kpgetdim(picfil,picfillen,&tsizx,&tsizy);
1544
        if (tsizx == 0 || tsizy == 0) { free(picfil); return -1; }
1545
        pth->sizx = tsizx;
1546
        pth->sizy = tsizy;
5 Plagman 1547
 
584 terminx 1548
        if (!glinfo.texnpot)
1549
        {
331 terminx 1550
            for (xsiz=1;xsiz<tsizx;xsiz+=xsiz);
1551
            for (ysiz=1;ysiz<tsizy;ysiz+=ysiz);
584 terminx 1552
        }
1553
        else
1554
        {
109 terminx 1555
            xsiz = tsizx;
1556
            ysiz = tsizy;
1557
        }
1558
        pic = (coltype *)calloc(xsiz,ysiz*sizeof(coltype)); if (!pic) { free(picfil); return 1; }
5 Plagman 1559
 
737 qbix79 1560
        if (kprender(picfil,picfillen,(intptr_t)pic,xsiz*sizeof(coltype),xsiz,ysiz,0,0)) { free(picfil); free(pic); return -2; }
723 terminx 1561
        applypalmapsT((char *)pic,tsizx,tsizy,dapic,dapalnum,dameth);
665 terminx 1562
 
1563
        r=(glinfo.bgra)?hictinting[dapalnum].r:hictinting[dapalnum].b;
1564
        g=hictinting[dapalnum].g;
1565
        b=(glinfo.bgra)?hictinting[dapalnum].b:hictinting[dapalnum].r;
331 terminx 1566
        for (y=0,j=0;y<tsizy;y++,j+=xsiz)
109 terminx 1567
        {
1568
            coltype tcol;
1569
            char *cptr = &britable[gammabrightness ? 0 : curbrightness][0];
1570
            rpptr = &pic[j];
5 Plagman 1571
 
331 terminx 1572
            for (x=0;x<tsizx;x++)
109 terminx 1573
            {
1574
                tcol.b = cptr[rpptr[x].b];
1575
                tcol.g = cptr[rpptr[x].g];
1576
                tcol.r = cptr[rpptr[x].r];
1577
                tcol.a = rpptr[x].a; hasalpha &= rpptr[x].a;
5 Plagman 1578
 
584 terminx 1579
                if (effect & 1)
1580
                {
109 terminx 1581
                    // greyscale
1582
                    tcol.b = max(tcol.b, max(tcol.g, tcol.r));
1583
                    tcol.g = tcol.r = tcol.b;
1584
                }
584 terminx 1585
                if (effect & 2)
1586
                {
109 terminx 1587
                    // invert
1588
                    tcol.b = 255-tcol.b;
1589
                    tcol.g = 255-tcol.g;
1590
                    tcol.r = 255-tcol.r;
1591
                }
665 terminx 1592
                if (effect & 4)
1593
                {
1594
                    // colorize
1595
                    tcol.b = min((int)((tcol.b)*r)/64,255);
1596
                    tcol.g = min((int)((tcol.g)*g)/64,255);
1597
                    tcol.r = min((int)((tcol.r)*b)/64,255);
1598
                }
5 Plagman 1599
 
109 terminx 1600
                rpptr[x].b = tcol.b;
1601
                rpptr[x].g = tcol.g;
1602
                rpptr[x].r = tcol.r;
1603
                rpptr[x].a = tcol.a;
1604
            }
1605
        }
1606
        if ((!(dameth&4)) || (facen)) //Duplicate texture pixels (wrapping tricks for non power of 2 texture sizes)
1607
        {
1608
            if (xsiz > tsizx) //Copy left to right
1609
            {
584 terminx 1610
                int *lptr = (int *)pic;
331 terminx 1611
                for (y=0;y<tsizy;y++,lptr+=xsiz)
109 terminx 1612
                    memcpy(&lptr[tsizx],lptr,(xsiz-tsizx)<<2);
1613
            }
1614
            if (ysiz > tsizy)  //Copy top to bottom
1615
                memcpy(&pic[xsiz*tsizy],pic,(ysiz-tsizy)*xsiz<<2);
1616
        }
584 terminx 1617
        if (!glinfo.bgra)
1618
        {
1619
            for (j=xsiz*ysiz-1;j>=0;j--)
1620
            {
109 terminx 1621
                swapchar(&pic[j].r, &pic[j].b);
1622
            }
584 terminx 1623
        }
1624
        else texfmt = GL_BGRA;
109 terminx 1625
        free(picfil); picfil = 0;
5 Plagman 1626
 
109 terminx 1627
        if (glinfo.texcompr && glusetexcompr && !(hicr->flags & 1))
1628
            intexfmt = (hasalpha == 255) ? GL_COMPRESSED_RGB_ARB : GL_COMPRESSED_RGBA_ARB;
1629
        else if (hasalpha == 255) intexfmt = GL_RGB;
5 Plagman 1630
 
109 terminx 1631
        if ((doalloc&3)==1) bglGenTextures(1,(GLuint*)&pth->glpic);  //# of textures (make OpenGL allocate structure)
1632
        bglBindTexture(GL_TEXTURE_2D,pth->glpic);
5 Plagman 1633
 
587 terminx 1634
        if (dapalnum>=SPECPAL&&dapalnum<=REDPAL)
1635
        {
1636
            //_initprintf("%cLoaded palamp %d(%dx%d)",pth->palmap?'+':'-',dapalnum,xsiz,ysiz);
1637
            if (!pth->palmap)
1638
            {
1639
                pth->size=xsiz*ysiz;
1640
                pth->palmap=malloc(pth->size*4);
1641
                memcpy(pth->palmap,pic,pth->size*4);
1642
            }
1643
            cachefil=0;
1644
        }
109 terminx 1645
        fixtransparency(pic,tsizx,tsizy,xsiz,ysiz,dameth);
1646
        uploadtexture(doalloc,xsiz,ysiz,intexfmt,texfmt,pic,-1,tsizy,dameth);
1647
    }
5 Plagman 1648
 
109 terminx 1649
    // precalculate scaling parameters for replacement
584 terminx 1650
    if (facen > 0)
1651
    {
109 terminx 1652
        pth->scalex = ((float)tsizx) / 64.0;
1653
        pth->scaley = ((float)tsizy) / 64.0;
584 terminx 1654
    }
1655
    else
1656
    {
109 terminx 1657
        pth->scalex = ((float)tsizx) / ((float)tilesizx[dapic]);
1658
        pth->scaley = ((float)tsizy) / ((float)tilesizy[dapic]);
1659
    }
5 Plagman 1660
 
109 terminx 1661
    if (gltexfiltermode < 0) gltexfiltermode = 0;
584 terminx 1662
    else if (gltexfiltermode >= (int)numglfiltermodes) gltexfiltermode = numglfiltermodes-1;
109 terminx 1663
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
1664
    bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
5 Plagman 1665
 
109 terminx 1666
    if (glinfo.maxanisotropy > 1.0)
1667
    {
584 terminx 1668
        if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy) glanisotropy = (int)glinfo.maxanisotropy;
109 terminx 1669
        bglTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
1670
    }
5 Plagman 1671
 
109 terminx 1672
    if (!(dameth&4))
1673
    {
1674
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
1675
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
1676
    }
1677
    else
584 terminx 1678
    {
1679
        //For sprite textures, clamping looks better than wrapping
109 terminx 1680
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
1681
        bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
1682
    }
5 Plagman 1683
 
109 terminx 1684
    if (pic) free(pic);
1685
 
1686
    pth->picnum = dapic;
1687
    pth->effects = effect;
1688
    pth->flags = ((dameth&4)>>2) + 2 + ((facen>0)<<2); if (hasalpha != 255) pth->flags |= 8;
1689
    pth->skyface = facen;
1690
    pth->hicr = hicr;
1691
 
584 terminx 1692
    if (cachefil < 0)
1693
    {
109 terminx 1694
        // save off the compressed version
1695
        cachead.xdim = tsizx;
1696
        cachead.ydim = tsizy;
1697
        x = 0;
584 terminx 1698
        for (j=0;j<31;j++)
1699
        {
109 terminx 1700
            if (xsiz == pow2long[j]) { x |= 1; }
1701
            if (ysiz == pow2long[j]) { x |= 2; }
1702
        }
1703
        cachead.flags = (x!=3) | (hasalpha != 255 ? 2 : 0);
710 terminx 1704
        initprintf("No cached tex for tile %d pal %d. ",dapic,dapalnum);
587 terminx 1705
        writexcache(fn, picfillen+(dapalnum<<8), dameth, effect, &cachead);
109 terminx 1706
    }
1707
 
1708
    return 0;
5 Plagman 1709
}
1710
 
1711
#endif
1712
 
109 terminx 1713
//(dpx,dpy) specifies an n-sided polygon. The polygon must be a convex clockwise loop.
1714
//    n must be <= 8 (assume clipping can double number of vertices)
1715
//method: 0:solid, 1:masked(255 is transparent), 2:transluscent #1, 3:transluscent #2
1716
//    +4 means it's a sprite, so wraparound isn't needed
584 terminx 1717
static int pow2xsplit = 0, skyclamphack = 0;
5 Plagman 1718
 
584 terminx 1719
void drawpoly(double *dpx, double *dpy, int n, int method)
5 Plagman 1720
{
331 terminx 1721
#define PI 3.14159265358979323
109 terminx 1722
    double ngdx = 0.0, ngdy = 0.0, ngdo = 0.0, ngux = 0.0, nguy = 0.0, nguo = 0.0;
1723
    double ngvx = 0.0, ngvy = 0.0, ngvo = 0.0, dp, up, vp, rdp, du0 = 0.0, du1 = 0.0, dui, duj;
1724
    double ngdx2, ngux2, ngvx2;
1725
    double f, r, ox, oy, oz, ox2, oy2, oz2, dd[16], uu[16], vv[16], px[16], py[16], uoffs;
584 terminx 1726
    int i, j, k, x, y, z, nn, ix0, ix1, mini, maxi, tsizx, tsizy, tsizxm1 = 0, tsizym1 = 0, ltsizy = 0;
1727
    int xx, yy, xi, d0, u0, v0, d1, u1, v1, xmodnice = 0, ymulnice = 0, dorot;
109 terminx 1728
    char dacol = 0, *walptr, *palptr = NULL, *vidp, *vide;
5 Plagman 1729
#ifdef USE_OPENGL
654 terminx 1730
    pthtyp *pth, *detailpth, *glowpth;
497 Plagman 1731
    int texunits = GL_TEXTURE0_ARB;
5 Plagman 1732
#endif
248 terminx 1733
    // backup of the n for possible redrawing of fullbright
584 terminx 1734
    int n_ = n, method_ = method;
5 Plagman 1735
 
109 terminx 1736
    if (method == -1) return;
5 Plagman 1737
 
109 terminx 1738
    if (n == 3)
1739
    {
1740
        if ((dpx[0]-dpx[1])*(dpy[2]-dpy[1]) >= (dpx[2]-dpx[1])*(dpy[0]-dpy[1])) return; //for triangle
1741
    }
1742
    else
1743
    {
1744
        f = 0; //f is area of polygon / 2
331 terminx 1745
        for (i=n-2,j=n-1,k=0;k<n;i=j,j=k,k++) f += (dpx[i]-dpx[k])*dpy[j];
109 terminx 1746
        if (f <= 0) return;
1747
    }
5 Plagman 1748
 
109 terminx 1749
    //Load texture (globalpicnum)
584 terminx 1750
    if ((unsigned int)globalpicnum >= MAXTILES) globalpicnum = 0;
109 terminx 1751
    setgotpic(globalpicnum);
1752
    tsizx = tilesizx[globalpicnum];
1753
    tsizy = tilesizy[globalpicnum];
355 terminx 1754
    if (palookup[globalpal] == NULL)
1755
        globalpal = 0;
109 terminx 1756
    if (!waloff[globalpicnum])
1757
    {
1758
        loadtile(globalpicnum);
1759
        if (!waloff[globalpicnum])
1760
        {
278 Plagman 1761
            if (rendmode < 3) return;
109 terminx 1762
            tsizx = tsizy = 1; method = 1; //Hack to update Z-buffer for invalid mirror textures
1763
        }
1764
    }
1765
    walptr = (char *)waloff[globalpicnum];
5 Plagman 1766
 
109 terminx 1767
    j = 0; dorot = ((gchang != 1.0) || (gctang != 1.0));
1768
    if (dorot)
1769
    {
331 terminx 1770
        for (i=0;i<n;i++)
109 terminx 1771
        {
1772
            ox = dpx[i]-ghalfx;
1773
            oy = dpy[i]-ghoriz;
1774
            oz = ghalfx;
5 Plagman 1775
 
109 terminx 1776
            //Up/down rotation
1777
            ox2 = ox;
1778
            oy2 = oy*gchang - oz*gshang;
1779
            oz2 = oy*gshang + oz*gchang;
5 Plagman 1780
 
109 terminx 1781
            //Tilt rotation
1782
            ox = ox2*gctang - oy2*gstang;
1783
            oy = ox2*gstang + oy2*gctang;
1784
            oz = oz2;
5 Plagman 1785
 
278 Plagman 1786
            if ((oz < SCISDIST) && (rendmode < 3)) return; //annoying hack to avoid bugs in software rendering
5 Plagman 1787
 
109 terminx 1788
            r = ghalfx / oz;
5 Plagman 1789
 
109 terminx 1790
            dd[j] = (dpx[i]*gdx + dpy[i]*gdy + gdo)*r;
1791
            uu[j] = (dpx[i]*gux + dpy[i]*guy + guo)*r;
1792
            vv[j] = (dpx[i]*gvx + dpy[i]*gvy + gvo)*r;
5 Plagman 1793
 
109 terminx 1794
            px[j] = ox*r + ghalfx;
1795
            py[j] = oy*r + ghoriz;
1796
            if ((!j) || (px[j] != px[j-1]) || (py[j] != py[j-1])) j++;
1797
        }
1798
    }
1799
    else
1800
    {
331 terminx 1801
        for (i=0;i<n;i++)
109 terminx 1802
        {
1803
            px[j] = dpx[i];
1804
            py[j] = dpy[i];
1805
            if ((!j) || (px[j] != px[j-1]) || (py[j] != py[j-1])) j++;
1806
        }
1807
    }
1808
    while ((j >= 3) && (px[j-1] == px[0]) && (py[j-1] == py[0])) j--;
1809
    if (j < 3) return;
1810
    n = j;
5 Plagman 1811
 
1812
#ifdef USE_OPENGL
278 Plagman 1813
    if (rendmode >= 3)
109 terminx 1814
    {
1815
        float hackscx, hackscy;
5 Plagman 1816
 
109 terminx 1817
        if (skyclamphack) method |= 4;
1818
        pth = gltexcache(globalpicnum,globalpal,method&(~3));
244 Plagman 1819
 
886 terminx 1820
        if (r_fullbrights && pth->flags & 16)
248 terminx 1821
            if (indrawroomsandmasks)
1822
            {
1823
                if (!fullbrightdrawingpass)
1824
                    fullbrightdrawingpass = 1;
1825
                else if (fullbrightdrawingpass == 2)
1826
                    pth = pth->ofb;
1827
            }
244 Plagman 1828
 
109 terminx 1829
        bglBindTexture(GL_TEXTURE_2D, pth ? pth->glpic : 0);
5 Plagman 1830
 
590 plagman 1831
        if (srepeat)
1832
            bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
1833
        if (trepeat)
1834
            bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
1835
 
504 Plagman 1836
        // texture scale by parkar request
506 terminx 1837
        if (pth && pth->hicr && ((pth->hicr->xscale != 1.0f) || (pth->hicr->yscale != 1.0f)) && !drawingskybox)
504 Plagman 1838
        {
1839
            bglMatrixMode(GL_TEXTURE);
1840
            bglLoadIdentity();
1841
            bglScalef(pth->hicr->xscale, pth->hicr->yscale, 1.0f);
1842
            bglMatrixMode(GL_MODELVIEW);
1843
        }
1844
 
1845
        // detail texture
459 Plagman 1846
        detailpth = NULL;
503 Plagman 1847
        if (r_detailmapping && usehightile && !r_depthpeeling && !drawingskybox &&
584 terminx 1848
                hicfindsubst(globalpicnum, DETAILPAL, 0))
497 Plagman 1849
            detailpth = gltexcache(globalpicnum, DETAILPAL, method&(~3));
459 Plagman 1850
 
1851
        if (detailpth && (detailpth->hicr->palnum == DETAILPAL))
1852
        {
497 Plagman 1853
            bglActiveTextureARB(++texunits);
459 Plagman 1854
 
1855
            bglEnable(GL_TEXTURE_2D);
1856
            bglBindTexture(GL_TEXTURE_2D, detailpth ? detailpth->glpic : 0);
1857
 
497 Plagman 1858
            bglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
459 Plagman 1859
            bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
1860
 
497 Plagman 1861
            bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1862
            bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
459 Plagman 1863
 
497 Plagman 1864
            bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
1865
            bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
584 terminx 1866
 
459 Plagman 1867
            bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
497 Plagman 1868
            bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
1869
            bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
459 Plagman 1870
 
497 Plagman 1871
            bglTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2.0f);
1872
 
459 Plagman 1873
            bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
1874
            bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
1875
 
1876
 
504 Plagman 1877
            f = detailpth ? detailpth->hicr->xscale : 1.0;
459 Plagman 1878
 
497 Plagman 1879
            bglMatrixMode(GL_TEXTURE);
1880
            bglLoadIdentity();
512 Plagman 1881
 
1882
            if (pth && pth->hicr && ((pth->hicr->xscale != 1.0f) || (pth->hicr->yscale != 1.0f)))
1883
                bglScalef(pth->hicr->xscale, pth->hicr->yscale, 1.0f);
1884
 
1885
            if (detailpth && detailpth->hicr && ((detailpth->hicr->xscale != 1.0f) || (detailpth->hicr->yscale != 1.0f)))
1886
                bglScalef(detailpth->hicr->xscale, detailpth->hicr->yscale, 1.0f);
1887
 
497 Plagman 1888
            bglMatrixMode(GL_MODELVIEW);
459 Plagman 1889
        }
1890
 
504 Plagman 1891
        // glow texture
497 Plagman 1892
        glowpth = NULL;
503 Plagman 1893
        if (r_glowmapping && usehightile && !r_depthpeeling && !drawingskybox &&
584 terminx 1894
                hicfindsubst(globalpicnum, GLOWPAL, 0))
497 Plagman 1895
            glowpth = gltexcache(globalpicnum, GLOWPAL, method&(~3));
1896
 
1897
        if (glowpth && (glowpth->hicr->palnum == GLOWPAL))
1898
        {
1899
            bglActiveTextureARB(++texunits);
1900
 
1901
            bglEnable(GL_TEXTURE_2D);
1902
            bglBindTexture(GL_TEXTURE_2D, glowpth ? glowpth->glpic : 0);
1903
 
1904
            bglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1905
            bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
1906
 
1907
            bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1908
            bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1909
 
1910
            bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
1911
            bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
1912
 
1913
            bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
1914
            bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA);
1915
 
1916
            bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
1917
            bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
1918
            bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1919
 
1920
            bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
1921
            bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
1922
        }
1923
 
109 terminx 1924
        if (pth && (pth->flags & 2))
1925
        {
1926
            hackscx = pth->scalex;
1927
            hackscy = pth->scaley;
1928
            tsizx = pth->sizx;
1929
            tsizy = pth->sizy;
1930
        }
1931
        else { hackscx = 1.0; hackscy = 1.0; }
5 Plagman 1932
 
584 terminx 1933
        if (!glinfo.texnpot)
1934
        {
331 terminx 1935
            for (xx=1;xx<tsizx;xx+=xx); ox2 = (double)1.0/(double)xx;
1936
            for (yy=1;yy<tsizy;yy+=yy); oy2 = (double)1.0/(double)yy;
584 terminx 1937
        }
1938
        else
1939
        {
109 terminx 1940
            xx = tsizx; ox2 = (double)1.0/(double)xx;
1941
            yy = tsizy; oy2 = (double)1.0/(double)yy;
1942
        }
5 Plagman 1943
 
584 terminx 1944
        if ((!(method&3)) && (!fullbrightdrawingpass))
1945
        {
475 Plagman 1946
            bglDisable(GL_BLEND);
439 Plagman 1947
            if (!peelcompiling)
1948
                bglDisable(GL_ALPHA_TEST);
584 terminx 1949
        }
1950
        else
1951
        {
109 terminx 1952
            float al = 0.0; // PLAG : default alphacut was 0.32 before goodalpha
1953
            if (pth && pth->hicr && pth->hicr->alphacut >= 0.0) al = pth->hicr->alphacut;
1954
            if (alphahackarray[globalpicnum])
1955
                al=alphahackarray[globalpicnum];
1956
            if (!waloff[globalpicnum]) al = 0.0;        // invalid textures ignore the alpha cutoff settings
439 Plagman 1957
            if (!peelcompiling)
1958
                bglEnable(GL_BLEND);
109 terminx 1959
            bglEnable(GL_ALPHA_TEST);
1960
            bglAlphaFunc(GL_GREATER,al);
1961
        }
5 Plagman 1962
 
109 terminx 1963
        if (!dorot)
1964
        {
331 terminx 1965
            for (i=n-1;i>=0;i--)
109 terminx 1966
            {
1967
                dd[i] = px[i]*gdx + py[i]*gdy + gdo;
1968
                uu[i] = px[i]*gux + py[i]*guy + guo;
1969
                vv[i] = px[i]*gvx + py[i]*gvy + gvo;
1970
            }
1971
        }
5 Plagman 1972
 
109 terminx 1973
        {
1974
            float pc[4];
379 terminx 1975
            f = ((float)(numpalookups-min(max(globalshade * shadescale,0),numpalookups)))/((float)numpalookups);
109 terminx 1976
            pc[0] = pc[1] = pc[2] = f;
331 terminx 1977
            switch (method&3)
109 terminx 1978
            {
347 terminx 1979
            default:
331 terminx 1980
            case 0:
1981
                pc[3] = 1.0; break;
1982
            case 1:
1983
                pc[3] = 1.0; break;
1984
            case 2:
1985
                pc[3] = 0.66; break;
1986
            case 3:
1987
                pc[3] = 0.33; break;
109 terminx 1988
            }
1989
            // tinting happens only to hightile textures, and only if the texture we're
1990
            // rendering isn't for the same palette as what we asked for
665 terminx 1991
            if (!(hictinting[globalpal].f&4))
708 terminx 1992
                if (pth && (pth->flags & 2))
384 terminx 1993
                {
708 terminx 1994
                    if (pth->palnum != globalpal)
1995
                    {
1996
                        // apply tinting for replaced textures
1997
                        pc[0] *= (float)hictinting[globalpal].r / 255.0;
1998
                        pc[1] *= (float)hictinting[globalpal].g / 255.0;
1999
                        pc[2] *= (float)hictinting[globalpal].b / 255.0;
2000
                    }
2001
                    if (hictinting[MAXPALOOKUPS-1].r != 255 || hictinting[MAXPALOOKUPS-1].g != 255 || hictinting[MAXPALOOKUPS-1].b != 255)
2002
                    {
2003
                        pc[0] *= (float)hictinting[MAXPALOOKUPS-1].r / 255.0;
2004
                        pc[1] *= (float)hictinting[MAXPALOOKUPS-1].g / 255.0;
2005
                        pc[2] *= (float)hictinting[MAXPALOOKUPS-1].b / 255.0;
2006
                    }
384 terminx 2007
                }
2008
 
109 terminx 2009
            bglColor4f(pc[0],pc[1],pc[2],pc[3]);
2010
        }
5 Plagman 2011
 
109 terminx 2012
        //Hack for walls&masked walls which use textures that are not a power of 2
2013
        if ((pow2xsplit) && (tsizx != xx))
2014
        {
2015
            if (!dorot)
2016
            {
2017
                ngdx = gdx; ngdy = gdy; ngdo = gdo+(ngdx+ngdy)*.5;
2018
                ngux = gux; nguy = guy; nguo = guo+(ngux+nguy)*.5;
2019
                ngvx = gvx; ngvy = gvy; ngvo = gvo+(ngvx+ngvy)*.5;
2020
            }
2021
            else
2022
            {
2023
                ox = py[1]-py[2]; oy = py[2]-py[0]; oz = py[0]-py[1];
2024
                r = 1.0 / (ox*px[0] + oy*px[1] + oz*px[2]);
2025
                ngdx = (ox*dd[0] + oy*dd[1] + oz*dd[2])*r;
2026
                ngux = (ox*uu[0] + oy*uu[1] + oz*uu[2])*r;
2027
                ngvx = (ox*vv[0] + oy*vv[1] + oz*vv[2])*r;
2028
                ox = px[2]-px[1]; oy = px[0]-px[2]; oz = px[1]-px[0];
2029
                ngdy = (ox*dd[0] + oy*dd[1] + oz*dd[2])*r;
2030
                nguy = (ox*uu[0] + oy*uu[1] + oz*uu[2])*r;
2031
                ngvy = (ox*vv[0] + oy*vv[1] + oz*vv[2])*r;
2032
                ox = px[0]-.5; oy = py[0]-.5; //.5 centers texture nicely
2033
                ngdo = dd[0] - ox*ngdx - oy*ngdy;
2034
                nguo = uu[0] - ox*ngux - oy*nguy;
2035
                ngvo = vv[0] - ox*ngvx - oy*ngvy;
2036
            }
5 Plagman 2037
 
109 terminx 2038
            ngux *= hackscx; nguy *= hackscx; nguo *= hackscx;
2039
            ngvx *= hackscy; ngvy *= hackscy; ngvo *= hackscy;
2040
            uoffs = ((double)(xx-tsizx)*.5);
2041
            ngux -= ngdx*uoffs;
2042
            nguy -= ngdy*uoffs;
2043
            nguo -= ngdo*uoffs;
5 Plagman 2044
 
109 terminx 2045
            //Find min&max u coordinates (du0...du1)
331 terminx 2046
            for (i=0;i<n;i++)
109 terminx 2047
            {
2048
                ox = px[i]; oy = py[i];
2049
                f = (ox*ngux + oy*nguy + nguo) / (ox*ngdx + oy*ngdy + ngdo);
2050
                if (!i) { du0 = du1 = f; continue; }
2051
                if (f < du0) du0 = f;
2052
                else if (f > du1) du1 = f;
2053
            }
5 Plagman 2054
 
109 terminx 2055
            f = 1.0/(double)tsizx;
584 terminx 2056
            ix0 = (int)floor(du0*f);
2057
            ix1 = (int)floor(du1*f);
331 terminx 2058
            for (;ix0<=ix1;ix0++)
109 terminx 2059
            {
584 terminx 2060
                du0 = (double)((ix0)*tsizx);   // + uoffs;
109 terminx 2061
                du1 = (double)((ix0+1)*tsizx); // + uoffs;
5 Plagman 2062
 
109 terminx 2063
                i = 0; nn = 0;
2064
                duj = (px[i]*ngux + py[i]*nguy + nguo) / (px[i]*ngdx + py[i]*ngdy + ngdo);
2065
                do
2066
                {
2067
                    j = i+1; if (j == n) j = 0;
5 Plagman 2068
 
109 terminx 2069
                    dui = duj; duj = (px[j]*ngux + py[j]*nguy + nguo) / (px[j]*ngdx + py[j]*ngdy + ngdo);
5 Plagman 2070
 
584 terminx 2071
                    if ((du0 <= dui) && (dui <= du1)) { uu[nn] = px[i]; vv[nn] = py[i]; nn++; }
109 terminx 2072
                    if (duj <= dui)
2073
                    {
2074
                        if ((du1 < duj) != (du1 < dui))
2075
                        {
2076
                            //ox*(ngux-ngdx*du1) + oy*(nguy-ngdy*du1) + (nguo-ngdo*du1) = 0
2077
                            //(px[j]-px[i])*f + px[i] = ox
2078
                            //(py[j]-py[i])*f + py[i] = oy
5 Plagman 2079
 
109 terminx 2080
                            ///Solve for f
2081
                            //((px[j]-px[i])*f + px[i])*(ngux-ngdx*du1) +
2082
                            //((py[j]-py[i])*f + py[i])*(nguy-ngdy*du1) + (nguo-ngdo*du1) = 0
5 Plagman 2083
 
584 terminx 2084
                            f = -(px[i] *(ngux-ngdx*du1) +  py[i]       *(nguy-ngdy*du1) + (nguo-ngdo*du1)) /
109 terminx 2085
                                ((px[j]-px[i])*(ngux-ngdx*du1) + (py[j]-py[i])*(nguy-ngdy*du1));
2086
                            uu[nn] = (px[j]-px[i])*f + px[i];
2087
                            vv[nn] = (py[j]-py[i])*f + py[i]; nn++;
2088
                        }
2089
                        if ((du0 < duj) != (du0 < dui))
2090
                        {
584 terminx 2091
                            f = -(px[i] *(ngux-ngdx*du0) +        py[i] *(nguy-ngdy*du0) + (nguo-ngdo*du0)) /
109 terminx 2092
                                ((px[j]-px[i])*(ngux-ngdx*du0) + (py[j]-py[i])*(nguy-ngdy*du0));
2093
                            uu[nn] = (px[j]-px[i])*f + px[i];
2094
                            vv[nn] = (py[j]-py[i])*f + py[i]; nn++;
2095
                        }
2096
                    }
2097
                    else
2098
                    {
2099
                        if ((du0 < duj) != (du0 < dui))
2100
                        {
584 terminx 2101
                            f = -(px[i] *(ngux-ngdx*du0) +        py[i] *(nguy-ngdy*du0) + (nguo-ngdo*du0)) /
109 terminx 2102
                                ((px[j]-px[i])*(ngux-ngdx*du0) + (py[j]-py[i])*(nguy-ngdy*du0));
2103
                            uu[nn] = (px[j]-px[i])*f + px[i];
2104
                            vv[nn] = (py[j]-py[i])*f + py[i]; nn++;
2105
                        }
2106
                        if ((du1 < duj) != (du1 < dui))
2107
                        {
584 terminx 2108
                            f = -(px[i] *(ngux-ngdx*du1) +  py[i]       *(nguy-ngdy*du1) + (nguo-ngdo*du1)) /
109 terminx 2109
                                ((px[j]-px[i])*(ngux-ngdx*du1) + (py[j]-py[i])*(nguy-ngdy*du1));
2110
                            uu[nn] = (px[j]-px[i])*f + px[i];
2111
                            vv[nn] = (py[j]-py[i])*f + py[i]; nn++;
2112
                        }
2113
                    }
2114
                    i = j;
584 terminx 2115
                }
2116
                while (i);
109 terminx 2117
                if (nn < 3) continue;
5 Plagman 2118
 
109 terminx 2119
                bglBegin(GL_TRIANGLE_FAN);
331 terminx 2120
                for (i=0;i<nn;i++)
109 terminx 2121
                {
2122
                    ox = uu[i]; oy = vv[i];
2123
                    dp = ox*ngdx + oy*ngdy + ngdo;
2124
                    up = ox*ngux + oy*nguy + nguo;
2125
                    vp = ox*ngvx + oy*ngvy + ngvo;
459 Plagman 2126
                    r = 1.0/dp;
497 Plagman 2127
                    if (texunits > GL_TEXTURE0_ARB)