Subversion Repositories eduke32

Rev

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