Subversion Repositories eduke32

Rev

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

Rev Author Line No. Line
5 Plagman 1
/**************************************************************************************************
5001 terminx 2
"POLYMOST" code originally written by Ken Silverman
5 Plagman 3
Ken Silverman's official web site: http://www.advsys.net/ken
4
**************************************************************************************************/
5
 
1173 terminx 6
 
1820 terminx 7
#ifdef USE_OPENGL
1173 terminx 8
 
9
#include "compat.h"
10
#include "build.h"
3758 terminx 11
#include "glbuild.h"
12
#include "mdsprite.h"
1173 terminx 13
#include "pragmas.h"
14
#include "baselayer.h"
15
#include "osd.h"
16
#include "engine_priv.h"
17
#include "hightile.h"
18
#include "polymost.h"
1593 terminx 19
#include "polymer.h"
1173 terminx 20
#include "cache1d.h"
21
#include "kplib.h"
3758 terminx 22
#include "texcache.h"
4652 terminx 23
#include "common.h"
1173 terminx 24
 
5001 terminx 25
#ifdef EDUKE32_GLES
26
#include "jwzgles.h"
27
#endif
28
 
1652 terminx 29
#ifndef _WIN32
30
extern int32_t filelength(int h); // kplib.c
31
#endif
32
 
1173 terminx 33
extern char textfont[2048], smalltextfont[2048];
34
 
1205 terminx 35
int32_t rendmode=0;
4439 terminx 36
#ifdef __ANDROID__
37
int32_t usemodels=0;
38
#else
39
int32_t usemodels=1;
40
#endif
41
int32_t usehightile=1;
4090 hendricks2 42
int32_t vsync=0;
5 Plagman 43
 
44
#include <math.h> //<-important!
4652 terminx 45
#include <float.h>
4605 terminx 46
 
2002 helixhorne 47
typedef struct { float x, cy[2], fy[2]; int32_t tag; int16_t n, p, ctag, ftag; } vsptyp;
5 Plagman 48
#define VSPMAX 4096 //<- careful!
49
static vsptyp vsp[VSPMAX];
2002 helixhorne 50
static int32_t gtag;
5 Plagman 51
 
4605 terminx 52
static float dxb1[MAXWALLSB], dxb2[MAXWALLSB];
5 Plagman 53
 
4652 terminx 54
#define SCISDIST .9999f  //1.0: Close plane clipping distance
5 Plagman 55
 
3403 helixhorne 56
float shadescale = 1.0f;
1848 helixhorne 57
int32_t shadescale_unbounded = 0;
379 terminx 58
 
4393 helixhorne 59
int32_t r_usenewshading = 3;
4459 helixhorne 60
int32_t r_usetileshades = 2;
4498 helixhorne 61
int32_t r_npotwallmode = 0;
1943 helixhorne 62
 
4605 terminx 63
static float gviewxrange;
64
static float ghoriz;
65
float gxyaspect;
66
float gyxscale, ghalfx, grhalfxdown10, grhalfxdown10x;
67
float gcosang, gsinang, gcosang2, gsinang2;
68
float gchang, gshang, gctang, gstang, gvisibility;
69
float gtang = 0.f;
70
static double guo, gux, guy; //Screen-based texture mapping parameters
71
static double gvo, gvx, gvy;
72
static double gdo, gdx, gdy;
4667 terminx 73
float fcosglobalang, fsinglobalang;
4768 hendricks2 74
float fxdim, fydim, fydimen, fviewingrange;
1706 helixhorne 75
static int32_t preview_mouseaim=0;  // when 1, displays a CROSSHAIR tsprite at the _real_ aimed position
76
 
5 Plagman 77
#ifdef USE_OPENGL
1205 terminx 78
static int32_t srepeat = 0, trepeat = 0;
590 plagman 79
 
4605 terminx 80
#ifdef REDBLUEMODE
1205 terminx 81
int32_t glredbluemode = 0;
82
static int32_t lastglredbluemode = 0, redblueclearcnt = 0;
4605 terminx 83
#endif
5 Plagman 84
 
3041 helixhorne 85
struct glfiltermodes glfiltermodes[NUMGLFILTERMODES] =
584 terminx 86
{
87
    {"GL_NEAREST",GL_NEAREST,GL_NEAREST},
88
    {"GL_LINEAR",GL_LINEAR,GL_LINEAR},
89
    {"GL_NEAREST_MIPMAP_NEAREST",GL_NEAREST_MIPMAP_NEAREST,GL_NEAREST},
90
    {"GL_LINEAR_MIPMAP_NEAREST",GL_LINEAR_MIPMAP_NEAREST,GL_LINEAR},
91
    {"GL_NEAREST_MIPMAP_LINEAR",GL_NEAREST_MIPMAP_LINEAR,GL_NEAREST},
92
    {"GL_LINEAR_MIPMAP_LINEAR",GL_LINEAR_MIPMAP_LINEAR,GL_LINEAR}
93
};
5 Plagman 94
 
1205 terminx 95
int32_t glanisotropy = 1;            // 0 = maximum supported by card
5001 terminx 96
int32_t gltexfiltermode = 2; // GL_NEAREST_MIPMAP_NEAREST
97
 
98
#ifdef EDUKE32_GLES
99
int32_t glusetexcompr = 0;
100
int32_t glusetexcache = 0, glusememcache = 0;
101
#else
1205 terminx 102
int32_t glusetexcompr = 1;
2145 helixhorne 103
int32_t glusetexcache = 2, glusememcache = 1;
5001 terminx 104
int32_t glpolygonmode = 0;     // 0:GL_FILL,1:GL_LINE,2:GL_POINT //FUK
1205 terminx 105
int32_t glmultisample = 0, glnvmultisamplehint = 0;
5001 terminx 106
static int32_t lastglpolygonmode = 0; //FUK
107
int32_t r_detailmapping = 1;
108
int32_t r_glowmapping = 1;
109
#endif
110
 
1205 terminx 111
int32_t gltexmaxsize = 0;      // 0 means autodetection on first run
112
int32_t gltexmiplevel = 0;              // discards this many mipmap levels
113
int32_t glprojectionhacks = 1;
5 Plagman 114
static GLuint polymosttext = 0;
3784 terminx 115
int32_t glrendmode = REND_POLYMOST;
228 Plagman 116
 
3146 helixhorne 117
// This variable, and 'shadeforfullbrightpass' control the drawing of
118
// fullbright tiles.  Also see 'fullbrightloadingpass'.
1205 terminx 119
static int32_t fullbrightdrawingpass = 0;
228 Plagman 120
 
1205 terminx 121
int32_t r_vertexarrays = 1;
122
int32_t r_vbos = 1;
123
int32_t r_vbocount = 64;
124
int32_t r_animsmoothing = 1;
125
int32_t r_fullbrights = 1;
3387 helixhorne 126
int32_t r_downsize = 0;
1634 terminx 127
int32_t r_downsizevar = -1;
916 terminx 128
 
1329 terminx 129
// used for fogcalc
4623 terminx 130
static float fogresult, fogresult2, fogcol[4], fogtable[4*MAXPALOOKUPS];
5 Plagman 131
#endif
132
 
4623 terminx 133
static const float float_trans[4] = { 1.0f, 1.0f, 0.66f, 0.33f };
134
 
3758 terminx 135
char ptempbuf[MAXWALLSB<<1];
1173 terminx 136
 
1064 terminx 137
// polymost ART sky control
1205 terminx 138
int32_t r_parallaxskyclamping = 1;
139
int32_t r_parallaxskypanning = 0;
1064 terminx 140
 
2045 helixhorne 141
#define MIN_CACHETIME_PRINT 10
1784 helixhorne 142
 
4675 terminx 143
// this was faster in MSVC but slower with GCC... currently unknown on ARM where both
144
// the FPU and possibly the optimization path in the compiler need improvement
145
#if 0
146
static inline int32_t __float_as_int(float f) { return *(int32_t *) &f; }
147
static inline float __int_as_float(int32_t d) { return *(float *) &d; }
148
static inline float Bfabsf(float f) { return __int_as_float(__float_as_int(f)&0x7fffffff); }
149
#else
150
#define Bfabsf fabsf
151
#endif
152
 
5 Plagman 153
#ifdef USE_OPENGL
1652 terminx 154
int32_t mdtims, omdtims;
155
float alphahackarray[MAXTILES];
1205 terminx 156
int32_t drawingskybox = 0;
3758 terminx 157
int32_t hicprecaching = 0;
5 Plagman 158
 
4690 terminx 159
#if 0
1221 terminx 160
static inline int32_t gltexmayhavealpha(int32_t dapicnum, int32_t dapalnum)
5 Plagman 161
{
3146 helixhorne 162
    const int32_t j = (dapicnum&(GLTEXCACHEADSIZ-1));
109 terminx 163
    pthtyp *pth;
5 Plagman 164
 
3781 terminx 165
    for (pth=texcache.list[j]; pth; pth=pth->next)
3146 helixhorne 166
        if (pth->picnum == dapicnum && pth->palnum == dapalnum)
4486 helixhorne 167
            return ((pth->flags&PTH_HASALPHA) != 0);
3146 helixhorne 168
 
169
    return 1;
5 Plagman 170
}
4690 terminx 171
#endif
5 Plagman 172
 
1205 terminx 173
void gltexinvalidate(int32_t dapicnum, int32_t dapalnum, int32_t dameth)
5 Plagman 174
{
3146 helixhorne 175
    const int32_t j = (dapicnum&(GLTEXCACHEADSIZ-1));
109 terminx 176
    pthtyp *pth;
5 Plagman 177
 
3781 terminx 178
    for (pth=texcache.list[j]; pth; pth=pth->next)
4486 helixhorne 179
        if (pth->picnum == dapicnum && pth->palnum == dapalnum &&
180
            (pth->flags & PTH_CLAMPED) == TO_PTH_CLAMPED(dameth))
248 terminx 181
        {
4486 helixhorne 182
            pth->flags |= PTH_INVALIDATED;
183
            if (pth->flags & PTH_HASFULLBRIGHT)
184
                pth->ofb->flags |= PTH_INVALIDATED;
248 terminx 185
        }
5 Plagman 186
}
187
 
109 terminx 188
//Make all textures "dirty" so they reload, but not re-allocate
189
//This should be much faster than polymost_glreset()
190
//Use this for palette effects ... but not ones that change every frame!
3765 terminx 191
void gltexinvalidatetype(int32_t type)
5 Plagman 192
{
1205 terminx 193
    int32_t j;
109 terminx 194
    pthtyp *pth;
5 Plagman 195
 
4667 terminx 196
    for (j=0; j<=GLTEXCACHEADSIZ-1; j++)
3758 terminx 197
    {
3781 terminx 198
        for (pth=texcache.list[j]; pth; pth=pth->next)
248 terminx 199
        {
3765 terminx 200
            if (type == INVALIDATE_ALL || (type == INVALIDATE_ART && pth->hicr == NULL))
415 terminx 201
            {
4486 helixhorne 202
                pth->flags |= PTH_INVALIDATED;
203
                if (pth->flags & PTH_HASFULLBRIGHT)
204
                    pth->ofb->flags |= PTH_INVALIDATED;
415 terminx 205
            }
206
        }
3758 terminx 207
    }
208
 
3765 terminx 209
    if (type == INVALIDATE_ALL)
3758 terminx 210
        clearskins();
415 terminx 211
#ifdef DEBUGGINGAIDS
3758 terminx 212
    OSD_Printf("gltexinvalidateall()\n");
415 terminx 213
#endif
214
}
215
 
5001 terminx 216
static void bind_2d_texture(GLuint texture, int filter)
3041 helixhorne 217
{
5001 terminx 218
    if (filter == -1)
219
        filter = gltexfiltermode;
220
 
3041 helixhorne 221
    bglBindTexture(GL_TEXTURE_2D, texture);
5001 terminx 222
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfiltermodes[filter].mag);
223
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfiltermodes[filter].min);
224
#ifndef EDUKE32_GLES
4605 terminx 225
    if (glinfo.maxanisotropy > 1.f)
3041 helixhorne 226
        bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glanisotropy);
5001 terminx 227
#endif
3041 helixhorne 228
}
229
 
584 terminx 230
void gltexapplyprops(void)
5 Plagman 231
{
1205 terminx 232
    int32_t i;
109 terminx 233
    pthtyp *pth;
5 Plagman 234
 
3784 terminx 235
    if (getrendermode() == REND_CLASSIC)
3628 helixhorne 236
        return;
237
 
4605 terminx 238
    if (glinfo.maxanisotropy > 1.f)
109 terminx 239
    {
3041 helixhorne 240
        if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy)
241
            glanisotropy = (int32_t)glinfo.maxanisotropy;
109 terminx 242
    }
5 Plagman 243
 
3041 helixhorne 244
    gltexfiltermode = clamp(gltexfiltermode, 0, NUMGLFILTERMODES-1);
245
 
4667 terminx 246
    for (i=0; i<=GLTEXCACHEADSIZ-1; i++)
584 terminx 247
    {
3781 terminx 248
        for (pth=texcache.list[i]; pth; pth=pth->next)
584 terminx 249
        {
5001 terminx 250
#ifndef EDUKE32_TOUCH_DEVICES
251
            bind_2d_texture(pth->glpic, -1);
3041 helixhorne 252
 
4486 helixhorne 253
            if (r_fullbrights && pth->flags & PTH_HASFULLBRIGHT)
5001 terminx 254
                bind_2d_texture(pth->ofb->glpic, -1);
255
#else
256
            bind_2d_texture(pth->glpic, pth->flags & PTH_HIGHTILE ? 5 : -1);
257
 
258
            if (r_fullbrights && pth->flags & PTH_HASFULLBRIGHT)
259
                bind_2d_texture(pth->ofb->glpic, pth->flags & PTH_HIGHTILE ? 5 : -1);
260
#endif
109 terminx 261
        }
262
    }
5 Plagman 263
 
5001 terminx 264
    int32_t j;
265
    mdskinmap_t *sk;
266
    md2model_t *m;
267
 
268
    for (i=0; i<nextmodelid; i++)
109 terminx 269
    {
5001 terminx 270
        m = (md2model_t *)models[i];
271
        if (m->mdnum < 2) continue;
272
        for (j=0; j<m->numskins*(HICEFFECTMASK+1); j++)
273
        {
274
            if (!m->texid[j]) continue;
275
            bind_2d_texture(m->texid[j], -1);
276
        }
109 terminx 277
 
5001 terminx 278
        for (sk=m->skinmap; sk; sk=sk->next)
279
            for (j=0; j<(HICEFFECTMASK+1); j++)
109 terminx 280
            {
5001 terminx 281
                if (!sk->texid[j]) continue;
282
                bind_2d_texture(sk->texid[j], -1);
109 terminx 283
            }
284
    }
5 Plagman 285
}
286
 
287
//--------------------------------------------------------------------------------------------------
3758 terminx 288
 
1173 terminx 289
float glox1, gloy1, glox2, gloy2;
5 Plagman 290
 
109 terminx 291
//Use this for both initialization and uninitialization of OpenGL.
1205 terminx 292
static int32_t gltexcacnum = -1;
1652 terminx 293
 
584 terminx 294
void polymost_glreset()
5 Plagman 295
{
1205 terminx 296
    int32_t i;
109 terminx 297
    pthtyp *pth, *next;
1220 terminx 298
 
4667 terminx 299
    for (i=0; i<=MAXPALOOKUPS-1; i++)
1220 terminx 300
    {
4667 terminx 301
        fogtable[i<<2] = palookupfog[i].r * (1.f/63.f);
302
        fogtable[(i<<2)+1] = palookupfog[i].g * (1.f/63.f);
303
        fogtable[(i<<2)+2] = palookupfog[i].b * (1.f/63.f);
1220 terminx 304
        fogtable[(i<<2)+3] = 0;
305
    }
306
 
109 terminx 307
    //Reset if this is -1 (meaning 1st texture call ever), or > 0 (textures in memory)
308
    if (gltexcacnum < 0)
309
    {
310
        gltexcacnum = 0;
5 Plagman 311
 
109 terminx 312
        //Hack for polymost_dorotatesprite calls before 1st polymost_drawrooms()
4605 terminx 313
        gcosang = gcosang2 = 16384.f/262144.f;
314
        gsinang = gsinang2 = 0.f/262144.f;
109 terminx 315
    }
316
    else
317
    {
4667 terminx 318
        for (i=0; i<=GLTEXCACHEADSIZ-1; i++)
584 terminx 319
        {
3781 terminx 320
            for (pth=texcache.list[i]; pth;)
584 terminx 321
            {
109 terminx 322
                next = pth->next;
4486 helixhorne 323
                if (pth->flags & PTH_HASFULLBRIGHT)
248 terminx 324
                {
325
                    bglDeleteTextures(1,&pth->ofb->glpic);
1527 terminx 326
                    Bfree(pth->ofb);
248 terminx 327
                }
2639 helixhorne 328
 
109 terminx 329
                bglDeleteTextures(1,&pth->glpic);
1527 terminx 330
                Bfree(pth);
109 terminx 331
                pth = next;
332
            }
2639 helixhorne 333
 
3781 terminx 334
            texcache.list[i] = NULL;
109 terminx 335
        }
336
        clearskins();
337
    }
338
 
2639 helixhorne 339
    if (polymosttext)
340
        bglDeleteTextures(1,&polymosttext);
109 terminx 341
    polymosttext=0;
342
 
4639 terminx 343
    md_freevbos();
1317 terminx 344
 
4675 terminx 345
    Bmemset(texcache.list,0,sizeof(texcache.list));
109 terminx 346
    glox1 = -1;
446 Plagman 347
 
3758 terminx 348
    texcache_freeptrs();
5001 terminx 349
    texcache_syncmemcache();
1155 terminx 350
 
2014 helixhorne 351
#ifdef DEBUGGINGAIDS
352
    OSD_Printf("polymost_glreset()\n");
353
#endif
5 Plagman 354
}
355
 
2240 helixhorne 356
 
627 terminx 357
// one-time initialization of OpenGL for polymost
5 Plagman 358
void polymost_glinit()
359
{
5001 terminx 360
    bglHint(GL_FOG_HINT, GL_NICEST);
4904 terminx 361
    bglFogi(GL_FOG_MODE, (r_usenewshading < 2) ? GL_EXP2 : GL_LINEAR);
3301 helixhorne 362
    bglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
109 terminx 363
 
2579 plagman 364
    bglPixelStorei(GL_PACK_ALIGNMENT, 1);
3729 Plagman 365
    bglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
2579 plagman 366
 
118 terminx 367
    //bglHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
368
    //bglEnable(GL_LINE_SMOOTH);
369
 
5001 terminx 370
#ifndef EDUKE32_GLES
584 terminx 371
    if (glmultisample > 0 && glinfo.multisample)
372
    {
109 terminx 373
        if (glinfo.nvmultisamplehint)
374
            bglHint(GL_MULTISAMPLE_FILTER_HINT_NV, glnvmultisamplehint ? GL_NICEST:GL_FASTEST);
375
        bglEnable(GL_MULTISAMPLE_ARB);
376
    }
439 Plagman 377
 
497 Plagman 378
    if (r_detailmapping && (!glinfo.multitex || !glinfo.envcombine))
459 Plagman 379
    {
380
        OSD_Printf("Your OpenGL implementation doesn't support detail mapping. Disabling...\n");
460 Plagman 381
        r_detailmapping = 0;
459 Plagman 382
    }
383
 
497 Plagman 384
    if (r_glowmapping && (!glinfo.multitex || !glinfo.envcombine))
385
    {
386
        OSD_Printf("Your OpenGL implementation doesn't support glow mapping. Disabling...\n");
387
        r_glowmapping = 0;
388
    }
5001 terminx 389
#endif
497 Plagman 390
 
519 Plagman 391
    if (r_vbos && (!glinfo.vbos))
392
    {
393
        OSD_Printf("Your OpenGL implementation doesn't support Vertex Buffer Objects. Disabling...\n");
394
        r_vbos = 0;
395
    }
396
 
513 Plagman 397
    bglEnableClientState(GL_VERTEX_ARRAY);
398
    bglEnableClientState(GL_TEXTURE_COORD_ARRAY);
1155 terminx 399
 
3758 terminx 400
    texcache_init();
401
    texcache_loadoffsets();
3761 terminx 402
    texcache_openfiles();
403
 
404
    texcache_setupmemcache();
405
    texcache_checkgarbage();
5 Plagman 406
}
407
 
3303 helixhorne 408
////////// VISIBILITY FOG ROUTINES //////////
4904 terminx 409
extern int32_t nofog;  // in windows/SDL layers
3303 helixhorne 410
 
4393 helixhorne 411
// only for r_usenewshading < 2 (not preferred)
3768 terminx 412
static void fogcalc_old(int32_t shade, int32_t vis)
3763 terminx 413
{
414
    float f;
415
 
416
    if (r_usenewshading==1)
417
    {
418
        f = 0.9f * shade;
419
        f = (vis > 239) ? (float)(gvisibility*((vis-240+f))) :
420
            (float)(gvisibility*(vis+16+f));
421
    }
422
    else
423
    {
424
        f = (shade < 0) ? shade * 3.5f : shade * .66f;
425
        f = (vis > 239) ? (float)(gvisibility*((vis-240+f)/(klabs(vis-256)))) :
426
            (float)(gvisibility*(vis+16+f));
427
    }
428
 
429
    if (f < 0.001f)
430
        f = 0.001f;
431
    else if (f > 100.0f)
432
        f = 100.0f;
433
 
434
    fogresult = f;
435
}
436
 
3303 helixhorne 437
// For GL_LINEAR fog:
3307 helixhorne 438
#define FOGDISTCONST 600
3959 helixhorne 439
#define FULLVIS_BEGIN 2.9e30
440
#define FULLVIS_END 3.0e30
3303 helixhorne 441
 
3763 terminx 442
static inline void fogcalc(int32_t tile, int32_t shade, int32_t vis, int32_t pal)
3303 helixhorne 443
{
4904 terminx 444
    if (shade > 0 && getrendermode() == REND_POLYMOST && r_usetileshades == 1 &&
5056 hendricks2 445
        !(globalflags & GLOBAL_NO_GL_TILESHADES) &&
4605 terminx 446
        (!usehightile || !hicfindsubst(tile, pal)) &&
3982 terminx 447
        (!usemodels || md_tilehasmodel(tile, pal) < 0))
448
        shade >>= 1;
449
 
4904 terminx 450
    Bmemcpy(fogcol, &fogtable[pal<<2], sizeof(fogcol));
451
 
4393 helixhorne 452
    if (r_usenewshading < 2)
3768 terminx 453
        fogcalc_old(shade, vis);
3763 terminx 454
    else
455
    {
4904 terminx 456
        float combvis = (float) globalvisibility * (uint8_t) (vis+16);
3303 helixhorne 457
 
458
        if (combvis == 0)
459
        {
4393 helixhorne 460
            if (r_usenewshading == 2 && shade > 0)
3959 helixhorne 461
            {
462
                // beg = -D*shade, end = D*(NUMSHADES-1-shade)
463
                //  => end/beg = -(NUMSHADES-1-shade)/shade
4904 terminx 464
                fogresult = (float) -FULLVIS_BEGIN;
465
                fogresult2 = FULLVIS_BEGIN * (float) (numshades-1-shade)/shade;
3959 helixhorne 466
            }
467
            else
468
            {
4904 terminx 469
                fogresult = (float) FULLVIS_BEGIN;
470
                fogresult2 = (float) FULLVIS_END;
3959 helixhorne 471
            }
3303 helixhorne 472
        }
4904 terminx 473
        else if (r_usenewshading == 3 && shade >= numshades-1)
4452 helixhorne 474
        {
475
            fogresult = -1;
476
            fogresult2 = 0;
477
        }
478
        else
479
        {
4658 terminx 480
            combvis = 1.f/combvis;
481
            fogresult = (r_usenewshading == 3 && shade > 0) ? 0 : -(FOGDISTCONST * shade) * combvis;
482
            fogresult2 = (FOGDISTCONST * (numshades-1-shade)) * combvis;
4452 helixhorne 483
        }
3303 helixhorne 484
    }
3763 terminx 485
}
3303 helixhorne 486
 
3763 terminx 487
void calc_and_apply_fog(int32_t tile, int32_t shade, int32_t vis, int32_t pal)
488
{
489
    fogcalc(tile, shade, vis, pal);
490
    bglFogfv(GL_FOG_COLOR, fogcol);
3303 helixhorne 491
 
4393 helixhorne 492
    if (r_usenewshading < 2)
4904 terminx 493
        bglFogf(GL_FOG_DENSITY, fogresult);
494
    else
3763 terminx 495
    {
4904 terminx 496
        bglFogf(GL_FOG_START, fogresult);
497
        bglFogf(GL_FOG_END, fogresult2);
3763 terminx 498
    }
3303 helixhorne 499
}
500
 
3763 terminx 501
void calc_and_apply_fog_factor(int32_t tile, int32_t shade, int32_t vis, int32_t pal, float factor)
3303 helixhorne 502
{
4393 helixhorne 503
    // NOTE: for r_usenewshading >= 2, the fog beginning/ending distance results are
3959 helixhorne 504
    // unused.
3763 terminx 505
    fogcalc(tile, shade, vis, pal);
506
    bglFogfv(GL_FOG_COLOR, fogcol);
3303 helixhorne 507
 
4393 helixhorne 508
    if (r_usenewshading < 2)
4904 terminx 509
        bglFogf(GL_FOG_DENSITY, fogresult*factor);
510
    else
3303 helixhorne 511
    {
4904 terminx 512
        bglFogf(GL_FOG_START, (GLfloat) FULLVIS_BEGIN);
513
        bglFogf(GL_FOG_END, (GLfloat) FULLVIS_END);
3763 terminx 514
    }
3303 helixhorne 515
}
516
////////////////////
517
 
1357 terminx 518
 
3401 helixhorne 519
static float get_projhack_ratio(void)
520
{
4904 terminx 521
    float rv;
522
 
3401 helixhorne 523
    if (glprojectionhacks == 1)
524
    {
4904 terminx 525
        float const mul = (gshang * gshang);
526
        rv = 1.05f + mul * mul * mul * mul;
3401 helixhorne 527
    }
4904 terminx 528
    else if (glprojectionhacks == 2)
3401 helixhorne 529
    {
4904 terminx 530
        float const abs_shang = Bfabsf(gshang);
4907 terminx 531
        rv = (abs_shang > 0.7f) ?
532
            1.05f + 4.f * (abs_shang - 0.7f) : 1.f;
3401 helixhorne 533
    }
4904 terminx 534
    else
535
        rv = 1.f;
3401 helixhorne 536
 
537
    // No projection hacks (legacy or new-aspect)
4904 terminx 538
    return rv;
3401 helixhorne 539
}
540
 
3041 helixhorne 541
static void resizeglcheck(void)
5 Plagman 542
{
4605 terminx 543
#ifdef REDBLUEMODE
584 terminx 544
    if (glredbluemode < lastglredbluemode)
545
    {
109 terminx 546
        glox1 = -1;
547
        bglColorMask(1,1,1,1);
584 terminx 548
    }
549
    else if (glredbluemode != lastglredbluemode)
550
    {
109 terminx 551
        redblueclearcnt = 0;
552
    }
553
    lastglredbluemode = glredbluemode;
4605 terminx 554
#endif
5 Plagman 555
 
5001 terminx 556
#ifndef EDUKE32_GLES
109 terminx 557
    //FUK
558
    if (lastglpolygonmode != glpolygonmode)
559
    {
560
        lastglpolygonmode = glpolygonmode;
331 terminx 561
        switch (glpolygonmode)
109 terminx 562
        {
563
        default:
331 terminx 564
        case 0:
565
            bglPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break;
566
        case 1:
567
            bglPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break;
568
        case 2:
569
            bglPolygonMode(GL_FRONT_AND_BACK,GL_POINT); break;
109 terminx 570
        }
571
    }
572
    if (glpolygonmode) //FUK
573
    {
574
        bglClearColor(1.0,1.0,1.0,0.0);
575
        bglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
576
        bglDisable(GL_TEXTURE_2D);
577
    }
5001 terminx 578
#else
579
    bglPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
580
#endif
5 Plagman 581
 
109 terminx 582
    if ((glox1 != windowx1) || (gloy1 != windowy1) || (glox2 != windowx2) || (gloy2 != windowy2))
583
    {
3401 helixhorne 584
        const int32_t ourxdimen = (windowx2-windowx1+1);
4658 terminx 585
        float ratio = get_projhack_ratio();
3401 helixhorne 586
        const int32_t fovcorrect = (ratio==0) ? 0 : (int32_t)(ourxdimen*ratio - ourxdimen);
4623 terminx 587
        float m[4][4];
1114 terminx 588
 
1454 terminx 589
        glox1 = (float)windowx1; gloy1 = (float)windowy1;
590
        glox2 = (float)windowx2; gloy2 = (float)windowy2;
109 terminx 591
 
1961 helixhorne 592
        bglViewport(windowx1-(fovcorrect/2), yres-(windowy2+1),
3401 helixhorne 593
                    ourxdimen+fovcorrect, windowy2-windowy1+1);
5 Plagman 594
 
109 terminx 595
        bglMatrixMode(GL_PROJECTION);
4675 terminx 596
        Bmemset(m,0,sizeof(m));
4658 terminx 597
        ratio = 1.f/ratio;
598
        m[0][0] = fydimen * ratio; m[0][2] = 1.f;
4656 terminx 599
        m[1][1] = fxdimen; m[1][2] = 1.f;
4658 terminx 600
        m[2][2] = 1.f; m[2][3] = fydimen * ratio;
4605 terminx 601
        m[3][2] =-1.f;
109 terminx 602
        bglLoadMatrixf(&m[0][0]);
5 Plagman 603
 
109 terminx 604
        bglMatrixMode(GL_MODELVIEW);
605
        bglLoadIdentity();
5 Plagman 606
 
1064 terminx 607
#ifdef USE_OPENGL
109 terminx 608
        if (!nofog) bglEnable(GL_FOG);
1064 terminx 609
#endif
5 Plagman 610
 
109 terminx 611
        //bglEnable(GL_TEXTURE_2D);
612
    }
5 Plagman 613
}
614
 
4639 terminx 615
static void fixtransparency(coltype *dapic, vec2_t dasiz, vec2_t dasiz2, int32_t dameth)
5 Plagman 616
{
4485 helixhorne 617
    int32_t y, naxsiz2;
4639 terminx 618
    vec2_t doxy = { dasiz2.x-1, dasiz2.y-1 };
5 Plagman 619
 
4639 terminx 620
    if (dameth&4) { doxy.x = min(doxy.x, dasiz.x); doxy.y = min(doxy.y, dasiz.y); }
621
    else { dasiz = dasiz2; } //Make repeating textures duplicate top/left parts
3695 helixhorne 622
 
4639 terminx 623
    dasiz.x--; dasiz.y--; naxsiz2 = -dasiz2.x; //Hacks for optimization inside loop
5 Plagman 624
 
109 terminx 625
    //Set transparent pixels to average color of neighboring opaque pixels
626
    //Doing this makes bilinear filtering look much better for masked textures (I.E. sprites)
4639 terminx 627
    for (y=doxy.y; y>=0; y--)
109 terminx 628
    {
4485 helixhorne 629
        int32_t x;
4639 terminx 630
        coltype * wpptr = &dapic[y*dasiz2.x+doxy.x];
4485 helixhorne 631
 
4639 terminx 632
        for (x=doxy.x; x>=0; x--,wpptr--)
109 terminx 633
        {
4485 helixhorne 634
            int32_t r=0, g=0, b=0, j=0;
635
 
109 terminx 636
            if (wpptr->a) continue;
3111 helixhorne 637
 
109 terminx 638
            r = g = b = j = 0;
3041 helixhorne 639
            if ((x>     0) && (wpptr[     -1].a)) { r += wpptr[     -1].r; g += wpptr[     -1].g; b += wpptr[     -1].b; j++; }
4639 terminx 640
            if ((x<dasiz.x) && (wpptr[     +1].a)) { r += wpptr[     +1].r; g += wpptr[     +1].g; b += wpptr[     +1].b; j++; }
3041 helixhorne 641
            if ((y>     0) && (wpptr[naxsiz2].a)) { r += wpptr[naxsiz2].r; g += wpptr[naxsiz2].g; b += wpptr[naxsiz2].b; j++; }
4639 terminx 642
            if ((y<dasiz.y) && (wpptr[dasiz2.x].a)) { r += wpptr[dasiz2.x].r; g += wpptr[dasiz2.x].g; b += wpptr[dasiz2.x].b; j++; }
331 terminx 643
            switch (j)
109 terminx 644
            {
331 terminx 645
            case 1:
646
                wpptr->r =   r            ; wpptr->g =   g            ; wpptr->b =   b            ; break;
647
            case 2:
648
                wpptr->r = ((r   +  1)>>1); wpptr->g = ((g   +  1)>>1); wpptr->b = ((b   +  1)>>1); break;
649
            case 3:
650
                wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); break;
651
            case 4:
652
                wpptr->r = ((r   +  2)>>2); wpptr->g = ((g   +  2)>>2); wpptr->b = ((b   +  2)>>2); break;
109 terminx 653
            }
654
        }
655
    }
5 Plagman 656
}
657
 
4488 helixhorne 658
void uploadtexture(int32_t doalloc, int32_t xsiz, int32_t ysiz, int32_t intexfmt, int32_t texfmt,
659
                   coltype *pic, int32_t tsizx, int32_t tsizy, int32_t dameth)
5 Plagman 660
{
4485 helixhorne 661
    int32_t x2, y2, j, js=0;
4486 helixhorne 662
    const int32_t hi = (dameth & DAMETH_HI) ? 1 : 0;
663
    const int32_t nocompress = (dameth & DAMETH_NOCOMPRESS) ? 1 : 0;
5 Plagman 664
 
4486 helixhorne 665
    dameth &= ~(DAMETH_HI|DAMETH_NOCOMPRESS);
916 terminx 666
 
584 terminx 667
    if (gltexmaxsize <= 0)
668
    {
109 terminx 669
        GLint i = 0;
670
        bglGetIntegerv(GL_MAX_TEXTURE_SIZE, &i);
671
        if (!i) gltexmaxsize = 6;   // 2^6 = 64 == default GL max texture size
584 terminx 672
        else
673
        {
109 terminx 674
            gltexmaxsize = 0;
675
            for (; i>1; i>>=1) gltexmaxsize++;
676
        }
677
    }
5 Plagman 678
 
109 terminx 679
    js = max(0,min(gltexmaxsize-1,gltexmiplevel));
680
    gltexmiplevel = js;
681
    while ((xsiz>>js) > (1<<gltexmaxsize) || (ysiz>>js) > (1<<gltexmaxsize)) js++;
5 Plagman 682
 
990 terminx 683
    if (hi && !nocompress) js = r_downsize;
916 terminx 684
 
109 terminx 685
    /*
686
    OSD_Printf("Uploading %dx%d %s as %s\n", xsiz,ysiz,
1625 terminx 687
            (texfmt==GL_RGBA?"GL_RGBA":
688
             texfmt==GL_RGB?"GL_RGB":
689
             texfmt==GL_BGR?"GL_BGR":
690
             texfmt==GL_BGRA?"GL_BGRA":"other"),
691
            (intexfmt==GL_RGBA?"GL_RGBA":
692
             intexfmt==GL_RGB?"GL_RGB":
693
             intexfmt==GL_COMPRESSED_RGBA_ARB?"GL_COMPRESSED_RGBA_ARB":
694
             intexfmt==GL_COMPRESSED_RGB_ARB?"GL_COMPRESSED_RGB_ARB":"other"));
109 terminx 695
    */
696
 
584 terminx 697
    if (js == 0)
698
    {
109 terminx 699
        if (doalloc&1)
700
            bglTexImage2D(GL_TEXTURE_2D,0,intexfmt,xsiz,ysiz,0,texfmt,GL_UNSIGNED_BYTE,pic); //loading 1st time
701
        else
702
            bglTexSubImage2D(GL_TEXTURE_2D,0,0,0,xsiz,ysiz,texfmt,GL_UNSIGNED_BYTE,pic); //overwrite old texture
703
    }
704
 
5 Plagman 705
#if 0
109 terminx 706
    gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8,xsiz,ysiz,texfmt,GL_UNSIGNED_BYTE,pic); //Needs C++ to link?
5 Plagman 707
#elif 1
109 terminx 708
    x2 = xsiz; y2 = ysiz;
1229 terminx 709
    for (j=1; (x2 > 1) || (y2 > 1); j++)
109 terminx 710
    {
4485 helixhorne 711
        int32_t y;
712
        int32_t x3 = max(1, x2 >> 1), y3 = max(1, y2 >> 1);  // this came from the GL_ARB_texture_non_power_of_two spec
109 terminx 713
        //x3 = ((x2+1)>>1); y3 = ((y2+1)>>1);
4485 helixhorne 714
 
1229 terminx 715
        for (y=0; y<y3; y++)
109 terminx 716
        {
4485 helixhorne 717
            int32_t x;
718
            coltype *wpptr = &pic[y*x3], *rpptr = &pic[(y<<1)*x2];
719
 
1229 terminx 720
            for (x=0; x<x3; x++,wpptr++,rpptr+=2)
109 terminx 721
            {
4485 helixhorne 722
                int32_t r=0, g=0, b=0, a=0, k=0;
723
 
3041 helixhorne 724
                if (rpptr[0].a)                  { r += rpptr[0].r; g += rpptr[0].g; b += rpptr[0].b; a += rpptr[0].a; k++; }
725
                if ((x+x+1 < x2) && (rpptr[1].a)) { r += rpptr[1].r; g += rpptr[1].g; b += rpptr[1].b; a += rpptr[1].a; k++; }
109 terminx 726
                if (y+y+1 < y2)
727
                {
3041 helixhorne 728
                    if ((rpptr[x2].a)) { r += rpptr[x2  ].r; g += rpptr[x2  ].g; b += rpptr[x2  ].b; a += rpptr[x2  ].a; k++; }
729
                    if ((x+x+1 < x2) && (rpptr[x2+1].a)) { r += rpptr[x2+1].r; g += rpptr[x2+1].g; b += rpptr[x2+1].b; a += rpptr[x2+1].a; k++; }
109 terminx 730
                }
331 terminx 731
                switch (k)
109 terminx 732
                {
733
                case 0:
331 terminx 734
                case 1:
735
                    wpptr->r = r; wpptr->g = g; wpptr->b = b; wpptr->a = a; break;
736
                case 2:
737
                    wpptr->r = ((r+1)>>1); wpptr->g = ((g+1)>>1); wpptr->b = ((b+1)>>1); wpptr->a = ((a+1)>>1); break;
738
                case 3:
739
                    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;
740
                case 4:
741
                    wpptr->r = ((r+2)>>2); wpptr->g = ((g+2)>>2); wpptr->b = ((b+2)>>2); wpptr->a = ((a+2)>>2); break;
742
                default:
4680 terminx 743
                    EDUKE32_UNREACHABLE_SECTION(break);
109 terminx 744
                }
745
                //if (wpptr->a) wpptr->a = 255;
746
            }
747
        }
4639 terminx 748
 
749
        if (tsizx >= 0)
750
        {
751
            vec2_t tsizzle;
752
            vec2_t mnizzle = { x3, y3 };
753
 
754
            tsizzle.x = (tsizx+(1<<j)-1)>>j;
755
            tsizzle.y = (tsizy+(1<<j)-1)>>j;
756
            fixtransparency(pic, tsizzle, mnizzle, dameth);
757
        }
758
 
584 terminx 759
        if (j >= js)
760
        {
109 terminx 761
            if (doalloc&1)
762
                bglTexImage2D(GL_TEXTURE_2D,j-js,intexfmt,x3,y3,0,texfmt,GL_UNSIGNED_BYTE,pic); //loading 1st time
763
            else
764
                bglTexSubImage2D(GL_TEXTURE_2D,j-js,0,0,x3,y3,texfmt,GL_UNSIGNED_BYTE,pic); //overwrite old texture
765
        }
766
        x2 = x3; y2 = y3;
767
    }
5 Plagman 768
#endif
769
}
770
 
2141 helixhorne 771
 
2142 helixhorne 772
#if 0
2141 helixhorne 773
// TODO: make configurable
774
static int32_t tile_is_sky(int32_t tilenum)
775
{
2142 helixhorne 776
    return return (tilenum >= 78 /*CLOUDYOCEAN*/ && tilenum <= 99 /*REDSKY2*/);
2141 helixhorne 777
}
2142 helixhorne 778
#else
779
# define tile_is_sky(x) (0)
780
#endif
2141 helixhorne 781
 
5001 terminx 782
static void texture_setup(const int32_t dameth, int filter)
3041 helixhorne 783
{
4623 terminx 784
    const GLuint clamp_mode = glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP;
785
 
5001 terminx 786
    if (filter == -1)
787
        filter = gltexfiltermode;
3041 helixhorne 788
 
5001 terminx 789
    gltexfiltermode = clamp(gltexfiltermode, 0, NUMGLFILTERMODES - 1);
790
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfiltermodes[filter].mag);
791
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfiltermodes[filter].min);
792
 
793
#ifndef EDUKE32_GLES
4605 terminx 794
    if (glinfo.maxanisotropy > 1.f)
3041 helixhorne 795
    {
5001 terminx 796
        uint32_t i = (unsigned)Blrintf(glinfo.maxanisotropy);
4623 terminx 797
 
798
        if ((unsigned)glanisotropy > i)
799
            glanisotropy = i;
800
 
3041 helixhorne 801
        bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glanisotropy);
802
    }
5001 terminx 803
#endif
3041 helixhorne 804
 
4486 helixhorne 805
    if (!(dameth & DAMETH_CLAMPED))
3041 helixhorne 806
    {
4623 terminx 807
        bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, !tile_is_sky(dapic) ? GL_REPEAT : clamp_mode);
3041 helixhorne 808
        bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
809
    }
810
    else
811
    {
5001 terminx 812
        // For sprite textures, clamping looks better than wrapping
4623 terminx 813
        bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_mode);
814
        bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp_mode);
3041 helixhorne 815
    }
816
}
817
 
4491 helixhorne 818
void gloadtile_art(int32_t dapic, int32_t dapal, int32_t dashade, int32_t dameth, pthtyp *pth, int32_t doalloc)
5 Plagman 819
{
3146 helixhorne 820
    static int32_t fullbrightloadingpass = 0;
821
 
4639 terminx 822
    vec2_t siz, tsiz = tilesiz[dapic];
3146 helixhorne 823
 
584 terminx 824
    if (!glinfo.texnpot)
825
    {
5001 terminx 826
        for (siz.x = 1; siz.x < tsiz.x; siz.x += siz.x);
827
        for (siz.y = 1; siz.y < tsiz.y; siz.y += siz.y);
584 terminx 828
    }
829
    else
830
    {
4639 terminx 831
        if ((tsiz.x|tsiz.y) == 0)
832
            siz.x = siz.y = 1;
584 terminx 833
        else
834
        {
4639 terminx 835
            siz.x = tsiz.x;
836
            siz.y = tsiz.y;
109 terminx 837
        }
838
    }
5 Plagman 839
 
5001 terminx 840
    coltype *pic = (coltype *)Xmalloc(siz.x*siz.y*sizeof(coltype));
841
    char hasalpha = 0, hasfullbright = 0;
5 Plagman 842
 
109 terminx 843
    if (!waloff[dapic])
844
    {
845
        //Force invalid textures to draw something - an almost purely transparency texture
846
        //This allows the Z-buffer to be updated for mirrors (which are invalidated textures)
847
        pic[0].r = pic[0].g = pic[0].b = 0; pic[0].a = 1;
4639 terminx 848
        tsiz.x = tsiz.y = 1; hasalpha = 1;
109 terminx 849
    }
850
    else
851
    {
5056 hendricks2 852
        const int dofullbright = !(picanm[dapic].sf & PICANM_NOFULLBRIGHT_BIT) && !(globalflags & GLOBAL_NO_GL_FULLBRIGHT);
3145 helixhorne 853
 
4898 terminx 854
        for (int y = 0; y < siz.y; y++)
109 terminx 855
        {
4898 terminx 856
            coltype *wpptr = &pic[y * siz.x];
857
            int32_t y2 = (y < tsiz.y) ? y : y - tsiz.y;
3146 helixhorne 858
 
4898 terminx 859
            for (int x = 0; x < siz.x; x++, wpptr++)
109 terminx 860
            {
4485 helixhorne 861
                int32_t dacol;
4639 terminx 862
                int32_t x2 = (x < tsiz.x) ? x : x-tsiz.x;
3146 helixhorne 863
 
4639 terminx 864
                if ((dameth & DAMETH_CLAMPED) && (x >= tsiz.x || y >= tsiz.y)) //Clamp texture
4485 helixhorne 865
                {
866
                    wpptr->r = wpptr->g = wpptr->b = wpptr->a = 0;
867
                    continue;
868
                }
3146 helixhorne 869
 
4639 terminx 870
                dacol = *(char *)(waloff[dapic]+x2*tsiz.y+y2);
3146 helixhorne 871
 
248 terminx 872
                if (!fullbrightloadingpass)
584 terminx 873
                {
874
                    // regular texture
3145 helixhorne 875
                    if (dacol > 239 && dacol != 255 && dofullbright)
248 terminx 876
                        hasfullbright = 1;
3146 helixhorne 877
 
248 terminx 878
                    wpptr->a = 255;
879
                }
3146 helixhorne 880
                else
584 terminx 881
                {
882
                    // texture with only fullbright areas
883
                    if (dacol < 240)    // regular colors
884
                    {
3146 helixhorne 885
                        wpptr->a = 0;
886
                        hasalpha = 1;
584 terminx 887
                    }
888
                    else   // fullbright
889
                    {
248 terminx 890
                        wpptr->a = 255;
891
                    }
892
                }
3146 helixhorne 893
 
248 terminx 894
                if (dacol != 255)
584 terminx 895
                {
3761 terminx 896
                    char *p = (char *)(palookup[dapal])+(int32_t)(dashade<<8);
897
                    dacol = (uint8_t)p[dacol];
248 terminx 898
                }
584 terminx 899
                else
900
                {
3146 helixhorne 901
                    wpptr->a = 0;
902
                    hasalpha = 1;
109 terminx 903
                }
3146 helixhorne 904
 
905
                bricolor((palette_t *)wpptr, dacol);
109 terminx 906
            }
907
        }
908
    }
5 Plagman 909
 
1762 terminx 910
    if (doalloc) bglGenTextures(1,(GLuint *)&pth->glpic); //# of textures (make OpenGL allocate structure)
109 terminx 911
    bglBindTexture(GL_TEXTURE_2D,pth->glpic);
5 Plagman 912
 
4639 terminx 913
    fixtransparency(pic,tsiz,siz,dameth);
4498 helixhorne 914
 
5001 terminx 915
    int32_t npoty = 0;
916
 
4639 terminx 917
    if (polymost_want_npotytex(dameth, siz.y) &&
918
            tsiz.x==siz.x && tsiz.y==siz.y)  // XXX
4498 helixhorne 919
    {
920
        const int32_t nextpoty = 1<<((picsiz[dapic]>>4)+1);
4639 terminx 921
        const int32_t ydif = nextpoty - siz.y;
4498 helixhorne 922
        coltype *paddedpic;
923
 
4639 terminx 924
        Bassert(ydif > 0 && ydif < siz.y);
4498 helixhorne 925
 
4639 terminx 926
        paddedpic = (coltype*) Xrealloc(pic, siz.x*nextpoty*sizeof(coltype));
4498 helixhorne 927
 
928
        pic = paddedpic;
4639 terminx 929
        Bmemcpy(&pic[siz.x*siz.y], pic, siz.x*ydif*sizeof(coltype));
930
        siz.y = tsiz.y = nextpoty;
4498 helixhorne 931
 
932
        npoty = PTH_NPOTWALL;
933
    }
934
 
5001 terminx 935
    uploadtexture(doalloc, siz.x, siz.y, hasalpha ? GL_RGBA : GL_RGB, GL_RGBA, pic, tsiz.x, tsiz.y, dameth);
5 Plagman 936
 
2978 helixhorne 937
    Bfree(pic);
5 Plagman 938
 
5001 terminx 939
    texture_setup(dameth, -1);
940
 
109 terminx 941
    pth->picnum = dapic;
942
    pth->palnum = dapal;
3761 terminx 943
    pth->shade = dashade;
109 terminx 944
    pth->effects = 0;
4498 helixhorne 945
    pth->flags = TO_PTH_CLAMPED(dameth) | (hasalpha*PTH_HASALPHA) | npoty;
109 terminx 946
    pth->hicr = NULL;
947
 
3146 helixhorne 948
    if (hasfullbright && !fullbrightloadingpass)
248 terminx 949
    {
3146 helixhorne 950
        // Load the ONLY texture that'll be assembled with the regular one to
951
        // make the final texture with fullbright pixels.
248 terminx 952
        fullbrightloadingpass = 1;
4485 helixhorne 953
 
4491 helixhorne 954
        pth->ofb = (pthtyp *)Xcalloc(1,sizeof(pthtyp));
4486 helixhorne 955
        pth->flags |= PTH_HASFULLBRIGHT;
235 Plagman 956
 
4491 helixhorne 957
        gloadtile_art(dapic, dapal, 0, dameth, pth->ofb, 1);
4485 helixhorne 958
 
248 terminx 959
        fullbrightloadingpass = 0;
960
    }
5 Plagman 961
}
962
 
3758 terminx 963
int32_t gloadtile_hi(int32_t dapic,int32_t dapalnum, int32_t facen, hicreplctyp *hicr,
2639 helixhorne 964
                            int32_t dameth, pthtyp *pth, int32_t doalloc, char effect)
5 Plagman 965
{
5001 terminx 966
    if (!hicr) return -1;
967
 
4485 helixhorne 968
    coltype *pic = NULL;
5 Plagman 969
 
5001 terminx 970
    char *picfil = NULL, *fn;
971
    int32_t picfillen, intexfmt = GL_RGBA, filh;
5 Plagman 972
 
1784 helixhorne 973
    int32_t startticks=0, willprint=0;
1754 helixhorne 974
 
584 terminx 975
    if (facen > 0)
976
    {
109 terminx 977
        if (!hicr->skybox) return -1;
978
        if (facen > 6) return -1;
979
        if (!hicr->skybox->face[facen-1]) return -1;
980
        fn = hicr->skybox->face[facen-1];
584 terminx 981
    }
982
    else
983
    {
109 terminx 984
        if (!hicr->filename) return -1;
985
        fn = hicr->filename;
986
    }
5 Plagman 987
 
4680 terminx 988
    if (EDUKE32_PREDICT_FALSE((filh = kopen4load(fn, 0)) < 0))
584 terminx 989
    {
921 terminx 990
        OSD_Printf("hightile: %s (pic %d) not found\n", fn, dapic);
4605 terminx 991
        return -2;
109 terminx 992
    }
4485 helixhorne 993
 
109 terminx 994
    picfillen = kfilelength(filh);
5 Plagman 995
 
109 terminx 996
    kclose(filh);       // FIXME: shouldn't have to do this. bug in cache1d.c
5 Plagman 997
 
5001 terminx 998
    char hasalpha = 255;
999
    texcacheheader cachead;
1000
    int32_t gotcache = texcache_readtexheader(fn, picfillen+(dapalnum<<8), dameth, effect, &cachead, 0);
1001
    vec2_t siz ={ 0, 0 }, tsiz;
4485 helixhorne 1002
 
3758 terminx 1003
    if (gotcache && !texcache_loadtile(&cachead, &doalloc, pth))
584 terminx 1004
    {
4639 terminx 1005
        tsiz.x = cachead.xdim;
1006
        tsiz.y = cachead.ydim;
4486 helixhorne 1007
        hasalpha = (cachead.flags & CACHEAD_HASALPHA) ? 0 : 255;
584 terminx 1008
    }
1009
    else
1010
    {
2639 helixhorne 1011
        int32_t r, g, b;
4485 helixhorne 1012
        int32_t j, y;
2639 helixhorne 1013
 
3758 terminx 1014
        gotcache = 0;   // the compressed version will be saved to disk
5 Plagman 1015
 
109 terminx 1016
        if ((filh = kopen4load(fn, 0)) < 0) return -1;
5 Plagman 1017
 
4491 helixhorne 1018
        picfil = (char *)Xmalloc(picfillen+1);
4680 terminx 1019
        if (EDUKE32_PREDICT_FALSE(kread(filh, picfil, picfillen) != picfillen))
2069 helixhorne 1020
            initprintf("warning: didn't fully read %s\n", fn);
1021
        // prevent
1022
        // Conditional jump or move depends on uninitialised value(s)
1023
        //  at kpegrend (kplib.c:1655)
1024
        picfil[picfillen] = 0;
109 terminx 1025
        kclose(filh);
5 Plagman 1026
 
109 terminx 1027
        // tsizx/y = replacement texture's natural size
1028
        // xsiz/y = 2^x size of replacement
5 Plagman 1029
 
4639 terminx 1030
        kpgetdim(picfil,picfillen,&tsiz.x,&tsiz.y);
1031
        if (tsiz.x == 0 || tsiz.y == 0) { Bfree(picfil); return -1; }
5 Plagman 1032
 
4639 terminx 1033
        pth->siz.x = tsiz.x;
1034
        pth->siz.y = tsiz.y;
1035
 
584 terminx 1036
        if (!glinfo.texnpot)
1037
        {
4639 terminx 1038
            for (siz.x=1; siz.x<tsiz.x; siz.x+=siz.x);
1039
            for (siz.y=1; siz.y<tsiz.y; siz.y+=siz.y);
584 terminx 1040
        }
1041
        else
1042
        {
4639 terminx 1043
            siz.x = tsiz.x;
1044
            siz.y = tsiz.y;
109 terminx 1045
        }
4639 terminx 1046
        pic = (coltype *)Xcalloc(siz.x,siz.y*sizeof(coltype));
5 Plagman 1047
 
1754 helixhorne 1048
        startticks = getticks();
1049
 
5001 terminx 1050
        static coltype *lastpic = NULL;
1051
        static char *lastfn = NULL;
1052
        static int32_t lastsize = 0;
1053
 
1610 helixhorne 1054
        if (lastpic && lastfn && !Bstrcmp(lastfn,fn))
1055
        {
1784 helixhorne 1056
            willprint=1;
4639 terminx 1057
            Bmemcpy(pic, lastpic, siz.x*siz.y*sizeof(coltype));
1610 helixhorne 1058
        }
1059
        else
1060
        {
4639 terminx 1061
            if (kprender(picfil,picfillen,(intptr_t)pic,siz.x*sizeof(coltype),siz.x,siz.y)) { Bfree(picfil); Bfree(pic); return -2; }
1784 helixhorne 1062
            willprint=2;
665 terminx 1063
 
1610 helixhorne 1064
            if (hicprecaching)
1065
            {
1066
                lastfn = fn;  // careful...
1067
                if (!lastpic)
1068
                {
4639 terminx 1069
                    lastpic = (coltype *)Bmalloc(siz.x*siz.y*sizeof(coltype));
1070
                    lastsize = siz.x*siz.y;
1610 helixhorne 1071
                }
4639 terminx 1072
                else if (lastsize < siz.x*siz.y)
1610 helixhorne 1073
                {
1074
                    Bfree(lastpic);
4639 terminx 1075
                    lastpic = (coltype *)Bmalloc(siz.x*siz.y*sizeof(coltype));
1610 helixhorne 1076
                }
1077
                if (lastpic)
4639 terminx 1078
                    Bmemcpy(lastpic, pic, siz.x*siz.y*sizeof(coltype));
1610 helixhorne 1079
            }
1080
            else if (lastpic)
1081
            {
1082
                Bfree(lastpic); lastpic=NULL;
1083
                lastfn = NULL;
1084
                lastsize = 0;
1085
            }
1086
        }
1087
 
665 terminx 1088
        r=(glinfo.bgra)?hictinting[dapalnum].r:hictinting[dapalnum].b;
1089
        g=hictinting[dapalnum].g;
1090
        b=(glinfo.bgra)?hictinting[dapalnum].b:hictinting[dapalnum].r;
4639 terminx 1091
        for (y=0,j=0; y<tsiz.y; y++,j+=siz.x)
109 terminx 1092
        {
1093
            coltype tcol;
2639 helixhorne 1094
            char *cptr = britable[gammabrightness ? 0 : curbrightness];
4485 helixhorne 1095
            coltype *rpptr = &pic[j];
5 Plagman 1096
 
4485 helixhorne 1097
            int32_t x;
1098
 
4639 terminx 1099
            for (x=0; x<tsiz.x; x++)
109 terminx 1100
            {
1101
                tcol.b = cptr[rpptr[x].b];
1102
                tcol.g = cptr[rpptr[x].g];
1103
                tcol.r = cptr[rpptr[x].r];
4639 terminx 1104
                tcol.a = rpptr[x].a;
1105
                hasalpha &= rpptr[x].a;
5 Plagman 1106
 
4486 helixhorne 1107
                if (effect & HICTINT_GRAYSCALE)
584 terminx 1108
                {
4889 terminx 1109
                    tcol.g = tcol.r = tcol.b = (uint8_t) ((tcol.r * GRAYSCALE_COEFF_RED) + (tcol.g * GRAYSCALE_COEFF_GREEN) +
1110
                                                          (tcol.b * GRAYSCALE_COEFF_BLUE));
109 terminx 1111
                }
4486 helixhorne 1112
 
1113
                if (effect & HICTINT_INVERT)
584 terminx 1114
                {
109 terminx 1115
                    tcol.b = 255-tcol.b;
1116
                    tcol.g = 255-tcol.g;
1117
                    tcol.r = 255-tcol.r;
1118
                }
4486 helixhorne 1119
 
1120
                if (effect & HICTINT_COLORIZE)
665 terminx 1121
                {
1205 terminx 1122
                    tcol.b = min((int32_t)((tcol.b)*r)/64,255);
1123
                    tcol.g = min((int32_t)((tcol.g)*g)/64,255);
1124
                    tcol.r = min((int32_t)((tcol.r)*b)/64,255);
665 terminx 1125
                }
5 Plagman 1126
 
4639 terminx 1127
                rpptr[x] = tcol;
109 terminx 1128
            }
1129
        }
2639 helixhorne 1130
 
4486 helixhorne 1131
        if ((!(dameth & DAMETH_CLAMPED)) || facen) //Duplicate texture pixels (wrapping tricks for non power of 2 texture sizes)
109 terminx 1132
        {
4639 terminx 1133
            if (siz.x > tsiz.x) //Copy left to right
109 terminx 1134
            {
1205 terminx 1135
                int32_t *lptr = (int32_t *)pic;
4639 terminx 1136
                for (y=0; y<tsiz.y; y++,lptr+=siz.x)
1137
                    Bmemcpy(&lptr[tsiz.x],lptr,(siz.x-tsiz.x)<<2);
109 terminx 1138
            }
4639 terminx 1139
            if (siz.y > tsiz.y)  //Copy top to bottom
1140
                Bmemcpy(&pic[siz.x*tsiz.y],pic,(siz.y-tsiz.y)*siz.x<<2);
109 terminx 1141
        }
2639 helixhorne 1142
 
5001 terminx 1143
        int32_t texfmt;
1144
 
584 terminx 1145
        if (!glinfo.bgra)
1146
        {
5001 terminx 1147
            texfmt = GL_RGBA;
1148
 
4639 terminx 1149
            for (j=siz.x*siz.y-1; j>=0; j--)
109 terminx 1150
                swapchar(&pic[j].r, &pic[j].b);
584 terminx 1151
        }
1152
        else texfmt = GL_BGRA;
2639 helixhorne 1153
 
1527 terminx 1154
        Bfree(picfil); picfil = 0;
5 Plagman 1155
 
4639 terminx 1156
        if (tsiz.x>>r_downsize <= tilesiz[dapic].x || tsiz.y>>r_downsize <= tilesiz[dapic].y)
4486 helixhorne 1157
            hicr->flags |= (HICR_NOCOMPRESS + HICR_NOSAVE);
1336 terminx 1158
 
4486 helixhorne 1159
        if (glinfo.texcompr && glusetexcompr && !(hicr->flags & HICR_NOSAVE))
1761 terminx 1160
            intexfmt = (hasalpha == 255) ? GL_COMPRESSED_RGB_ARB : GL_COMPRESSED_RGBA_ARB;
109 terminx 1161
        else if (hasalpha == 255) intexfmt = GL_RGB;
5 Plagman 1162
 
2639 helixhorne 1163
        if ((doalloc&3)==1)
1164
            bglGenTextures(1, &pth->glpic); //# of textures (make OpenGL allocate structure)
109 terminx 1165
        bglBindTexture(GL_TEXTURE_2D,pth->glpic);
5 Plagman 1166
 
4639 terminx 1167
        fixtransparency(pic,tsiz,siz,dameth);
1168
        uploadtexture(doalloc,siz.x,siz.y,intexfmt,texfmt,pic,-1,tsiz.y,
4486 helixhorne 1169
                      dameth | DAMETH_HI | (hicr->flags & HICR_NOCOMPRESS ? DAMETH_NOCOMPRESS : 0));
109 terminx 1170
    }
5 Plagman 1171
 
109 terminx 1172
    // precalculate scaling parameters for replacement
584 terminx 1173
    if (facen > 0)
1174
    {
4639 terminx 1175
        pth->scale.x = (float)tsiz.x * (1.0f/64.f);
1176
        pth->scale.y = (float)tsiz.y * (1.0f/64.f);
584 terminx 1177
    }
1178
    else
1179
    {
4639 terminx 1180
        pth->scale.x = (float)tsiz.x / (float)tilesiz[dapic].x;
1181
        pth->scale.y = (float)tsiz.y / (float)tilesiz[dapic].y;
109 terminx 1182
    }
5 Plagman 1183
 
5001 terminx 1184
#ifdef EDUKE32_TOUCH_DEVICES
1185
    texture_setup(dameth, 5);
1186
#else
1187
    texture_setup(dameth, -1);
1188
#endif
2639 helixhorne 1189
 
4623 terminx 1190
    DO_FREE_AND_NULL(pic);
109 terminx 1191
 
4639 terminx 1192
    if (tsiz.x>>r_downsize <= tilesiz[dapic].x || tsiz.y>>r_downsize <= tilesiz[dapic].y)
1193
        hicr->flags |= HICR_NOCOMPRESS | HICR_NOSAVE;
1336 terminx 1194
 
109 terminx 1195
    pth->picnum = dapic;
1196
    pth->effects = effect;
4639 terminx 1197
    pth->flags = TO_PTH_CLAMPED(dameth) | PTH_HIGHTILE | ((facen>0) * PTH_SKYBOX) | ((hasalpha != 255) ? PTH_HASALPHA : 0);
109 terminx 1198
    pth->skyface = facen;
1199
    pth->hicr = hicr;
1200
 
4752 terminx 1201
    if (!gotcache && glinfo.texcompr && glusetexcompr && glusetexcache && !(hicr->flags & HICR_NOSAVE))
1202
    {
1203
        const int32_t nonpow2 = check_nonpow2(siz.x) || check_nonpow2(siz.y);
4485 helixhorne 1204
 
4752 terminx 1205
        // save off the compressed version
1206
        cachead.quality = (hicr->flags & HICR_NOCOMPRESS) ? 0 : r_downsize;
1207
        cachead.xdim = tsiz.x >> cachead.quality;
1208
        cachead.ydim = tsiz.y >> cachead.quality;
4485 helixhorne 1209
 
4752 terminx 1210
        // handle nocompress:
1211
        cachead.flags = nonpow2 * CACHEAD_NONPOW2 | (hasalpha != 255 ? CACHEAD_HASALPHA : 0) |
1212
                        (hicr->flags & HICR_NOCOMPRESS ? CACHEAD_NOCOMPRESS : 0);
4486 helixhorne 1213
 
4752 terminx 1214
        ///            OSD_Printf("Caching \"%s\"\n", fn);
1215
        texcache_writetex(fn, picfillen + (dapalnum << 8), dameth, effect, &cachead);
1754 helixhorne 1216
 
4752 terminx 1217
        if (willprint)
1218
        {
1219
            int32_t etime = getticks() - startticks;
1220
            if (etime >= MIN_CACHETIME_PRINT)
1221
                OSD_Printf("Load tile %4d: p%d-m%d-e%d %s... cached... %d ms\n", dapic, dapalnum, dameth, effect,
1222
                           willprint == 2 ? fn : "", etime);
1223
            willprint = 0;
109 terminx 1224
        }
4752 terminx 1225
        else
1226
            OSD_Printf("Cached \"%s\"\n", fn);
1227
    }
109 terminx 1228
 
1784 helixhorne 1229
    if (willprint)
1230
    {
1231
        int32_t etime = getticks()-startticks;
1232
        if (etime>=MIN_CACHETIME_PRINT)
1233
            OSD_Printf("Load tile %4d: p%d-m%d-e%d %s... %d ms\n", dapic, dapalnum, dameth, effect,
1234
                       willprint==2 ? fn : "", etime);
1235
    }
1754 helixhorne 1236
 
109 terminx 1237
    return 0;
5 Plagman 1238
}
1239
 
4623 terminx 1240
void polymost_setupdetailtexture(const int32_t texunits, const int32_t tex)
1241
{
1242
    bglActiveTextureARB(texunits);
1243
 
1244
    bglEnable(GL_TEXTURE_2D);
1245
    bglBindTexture(GL_TEXTURE_2D, tex);
1246
 
1247
    bglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1248
    bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
1249
 
1250
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1251
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1252
 
1253
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
1254
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
1255
 
1256
    bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
1257
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
1258
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1259
 
1260
    bglTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2.0f);
1261
 
1262
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1263
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1264
}
1265
 
1266
void polymost_setupglowtexture(const int32_t texunits, const int32_t tex)
1267
{
1268
    bglActiveTextureARB(texunits);
1269
 
1270
    bglEnable(GL_TEXTURE_2D);
1271
    bglBindTexture(GL_TEXTURE_2D, tex);
1272
 
1273
    bglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1274
    bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
1275
 
1276
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1277
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1278
 
1279
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
1280
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
1281
 
1282
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
1283
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA);
1284
 
1285
    bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
1286
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
1287
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1288
 
1289
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1290
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1291
}
5 Plagman 1292
#endif
1293
 
109 terminx 1294
//(dpx,dpy) specifies an n-sided polygon. The polygon must be a convex clockwise loop.
1295
//    n must be <= 8 (assume clipping can double number of vertices)
1296
//method: 0:solid, 1:masked(255 is transparent), 2:transluscent #1, 3:transluscent #2
1297
//    +4 means it's a sprite, so wraparound isn't needed
3543 hendricks2 1298
 
1299
// drawpoly's hack globals
1205 terminx 1300
static int32_t pow2xsplit = 0, skyclamphack = 0;
3543 hendricks2 1301
static float alpha = 0.f;
5 Plagman 1302
 
4640 terminx 1303
static inline pthtyp *our_texcache_fetch(int32_t dameth)
4010 helixhorne 1304
{
1305
    // r_usetileshades 1 is TX's method.
5056 hendricks2 1306
    return texcache_fetch(globalpicnum, globalpal, getpalookup((r_usetileshades == 1 && !(globalflags & GLOBAL_NO_GL_TILESHADES)) ? globvis>>3 : 0, globalshade), dameth);
4010 helixhorne 1307
}
1308
 
4671 terminx 1309
static void drawpoly(vec2f_t *dpxy, int32_t n, int32_t method)
5 Plagman 1310
{
4623 terminx 1311
    const int32_t method_ = method;
1312
    int32_t i, j, k;
1313
    vec2_t tsiz;
1314
    float f, r, ox, oy, oz, ox2, oy2, oz2, dd[16], uu[16], vv[16], px[16], py[16];
4406 helixhorne 1315
 
2014 helixhorne 1316
#ifdef YAX_ENABLE
1317
    if (g_nodraw) return;
1318
#endif
5 Plagman 1319
 
4605 terminx 1320
    if (method == -1 || (uint32_t)globalpicnum >= MAXTILES) return;
1321
 
109 terminx 1322
    if (n == 3)
1323
    {
4671 terminx 1324
        if ((dpxy[0].x-dpxy[1].x) * (dpxy[2].y-dpxy[1].y) >=
1325
            (dpxy[2].x-dpxy[1].x) * (dpxy[0].y-dpxy[1].y)) return; //for triangle
109 terminx 1326
    }
1327
    else
1328
    {
1329
        f = 0; //f is area of polygon / 2
4671 terminx 1330
        for (i=n-2,j=n-1,k=0; k<n; i=j,j=k,k++)
1331
            f += (dpxy[i].x-dpxy[k].x)*dpxy[j].y;
109 terminx 1332
        if (f <= 0) return;
1333
    }
5 Plagman 1334
 
109 terminx 1335
    //Load texture (globalpicnum)
1336
    setgotpic(globalpicnum);
4623 terminx 1337
    tsiz = tilesiz[globalpicnum];
1338
 
355 terminx 1339
    if (palookup[globalpal] == NULL)
1340
        globalpal = 0;
109 terminx 1341
    if (!waloff[globalpicnum])
1342
    {
1343
        loadtile(globalpicnum);
1344
        if (!waloff[globalpicnum])
1345
        {
3784 terminx 1346
            if (getrendermode() < REND_POLYMOST) return;
4623 terminx 1347
            tsiz.x = tsiz.y = 1;
1348
            method = 1; //Hack to update Z-buffer for invalid mirror textures
109 terminx 1349
        }
1350
    }
5 Plagman 1351
 
4605 terminx 1352
    j = 0;
1353
 
4623 terminx 1354
    for (i=0; i<n; i++)
109 terminx 1355
    {
4671 terminx 1356
        ox = dpxy[i].x-ghalfx;
1357
        oy = dpxy[i].y-ghoriz;
4623 terminx 1358
        oz = ghalfx;
5 Plagman 1359
 
4623 terminx 1360
        //Up/down rotation
1361
        ox2 = ox;
1362
        oy2 = oy*gchang - oz*gshang;
1363
        oz2 = oy*gshang + oz*gchang;
5 Plagman 1364
 
4623 terminx 1365
        //Tilt rotation
1366
        ox = ox2*gctang - oy2*gstang;
1367
        oy = ox2*gstang + oy2*gctang;
1368
        oz = oz2;
5 Plagman 1369
 
4623 terminx 1370
        r = ghalfx / oz;
5 Plagman 1371
 
4671 terminx 1372
        dd[j] = (dpxy[i].x*gdx + dpxy[i].y*gdy + gdo)*r;
1373
        uu[j] = (dpxy[i].x*gux + dpxy[i].y*guy + guo)*r;
1374
        vv[j] = (dpxy[i].x*gvx + dpxy[i].y*gvy + gvo)*r;
5 Plagman 1375
 
4623 terminx 1376
        px[j] = ox*r + ghalfx;
1377
        py[j] = oy*r + ghoriz;
1378
        if ((!j) || (px[j] != px[j-1]) || (py[j] != py[j-1])) j++;
109 terminx 1379
    }
4623 terminx 1380
 
109 terminx 1381
    while ((j >= 3) && (px[j-1] == px[0]) && (py[j-1] == py[0])) j--;
1382
    if (j < 3) return;
5 Plagman 1383
 
1384
#ifdef USE_OPENGL
3784 terminx 1385
    if (getrendermode() >= REND_POLYMOST)
109 terminx 1386
    {
4605 terminx 1387
        float hackscx = 1.f, hackscy = 1.f;
4406 helixhorne 1388
        int32_t texunits = GL_TEXTURE0_ARB;
4605 terminx 1389
        int32_t xx, yy;
5 Plagman 1390
 
4623 terminx 1391
        int32_t jj = j;
1392
 
4489 helixhorne 1393
        if (skyclamphack) method |= DAMETH_CLAMPED;
5001 terminx 1394
        pthtyp *pth = our_texcache_fetch(method&(~3));
244 Plagman 1395
 
1920 helixhorne 1396
        if (!pth)
1397
        {
1398
            if (editstatus)
1399
            {
1400
                Bsprintf(ptempbuf, "pth==NULL! (bad pal?) pic=%d pal=%d", globalpicnum, globalpal);
1401
                polymost_printext256(8,8, editorcolors[15],editorcolors[5], ptempbuf, 0);
1402
            }
1403
            return;
1404
        }
1405
 
4623 terminx 1406
        if (pth->flags & PTH_HASFULLBRIGHT && r_fullbrights && indrawroomsandmasks)
1407
        {
1408
            if (!fullbrightdrawingpass)
1409
                fullbrightdrawingpass = 1;
1410
            else if (fullbrightdrawingpass == 2)
1411
                pth = pth->ofb;
1412
        }
244 Plagman 1413
 
3741 Plagman 1414
        // If we aren't rendmode 3, we're in Polymer, which means this code is
1415
        // used for rotatesprite only. Polymer handles all the material stuff,
1416
        // just submit the geometry and don't mess with textures.
3784 terminx 1417
        if (getrendermode() == REND_POLYMOST)
3741 Plagman 1418
        {
1419
            bglBindTexture(GL_TEXTURE_2D, pth ? pth->glpic : 0);
5 Plagman 1420
 
3741 Plagman 1421
            if (srepeat)
1422
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
1423
            if (trepeat)
1424
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
1425
        }
590 plagman 1426
 
504 Plagman 1427
        // texture scale by parkar request
4680 terminx 1428
        if (pth && pth->hicr && !drawingskybox && ((pth->hicr->scale.x != 1.0f) || (pth->hicr->scale.y != 1.0f)))
504 Plagman 1429
        {
1430
            bglMatrixMode(GL_TEXTURE);
1431
            bglLoadIdentity();
4680 terminx 1432
            bglScalef(pth->hicr->scale.x, pth->hicr->scale.y, 1.0f);
504 Plagman 1433
            bglMatrixMode(GL_MODELVIEW);
1434
        }
1435
 
5001 terminx 1436
#ifndef EDUKE32_GLES
504 Plagman 1437
        // detail texture
5001 terminx 1438
        pthtyp *detailpth = NULL;
4605 terminx 1439
        if (r_detailmapping && usehightile && !drawingskybox && hicfindsubst(globalpicnum, DETAILPAL))
3761 terminx 1440
            detailpth = texcache_fetch(globalpicnum, DETAILPAL, 0, method&(~3));
459 Plagman 1441
 
1226 plagman 1442
        if (detailpth && detailpth->hicr && (detailpth->hicr->palnum == DETAILPAL))
459 Plagman 1443
        {
4623 terminx 1444
            polymost_setupdetailtexture(++texunits, detailpth ? detailpth->glpic : 0);
459 Plagman 1445
 
4680 terminx 1446
            f = detailpth ? detailpth->hicr->scale.x : 1.f;
459 Plagman 1447
 
497 Plagman 1448
            bglMatrixMode(GL_TEXTURE);
1449
            bglLoadIdentity();
512 Plagman 1450
 
4680 terminx 1451
            if (pth && pth->hicr && ((pth->hicr->scale.x != 1.0f) || (pth->hicr->scale.y != 1.0f)))
1452
                bglScalef(pth->hicr->scale.x, pth->hicr->scale.y, 1.0f);
512 Plagman 1453
 
4680 terminx 1454
            if (detailpth && detailpth->hicr && ((detailpth->hicr->scale.x != 1.0f) || (detailpth->hicr->scale.y != 1.0f)))
1455
                bglScalef(detailpth->hicr->scale.x, detailpth->hicr->scale.y, 1.0f);
512 Plagman 1456
 
497 Plagman 1457
            bglMatrixMode(GL_MODELVIEW);
459 Plagman 1458
        }
1459
 
504 Plagman 1460
        // glow texture
5001 terminx 1461
        pthtyp *glowpth = NULL;
4605 terminx 1462
        if (r_glowmapping && usehightile && !drawingskybox && hicfindsubst(globalpicnum, GLOWPAL))
3761 terminx 1463
            glowpth = texcache_fetch(globalpicnum, GLOWPAL, 0, method&(~3));
497 Plagman 1464
 
1226 plagman 1465
        if (glowpth && glowpth->hicr && (glowpth->hicr->palnum == GLOWPAL))
4623 terminx 1466
            polymost_setupglowtexture(++texunits, glowpth ? glowpth->glpic : 0);
5001 terminx 1467
#endif
497 Plagman 1468
 
4486 helixhorne 1469
        if (pth && (pth->flags & PTH_HIGHTILE))
109 terminx 1470
        {
4639 terminx 1471
            hackscx = pth->scale.x;
1472
            hackscy = pth->scale.y;
1473
            tsiz.x = pth->siz.x;
1474
            tsiz.y = pth->siz.y;
109 terminx 1475
        }
5 Plagman 1476
 
4623 terminx 1477
        xx = tsiz.x;
1478
        yy = tsiz.y;
4605 terminx 1479
 
584 terminx 1480
        if (!glinfo.texnpot)
1481
        {
4623 terminx 1482
            for (xx=1; xx<tsiz.x; xx+=xx)
2416 helixhorne 1483
            {
1484
                /* do nothing */
1485
            }
4623 terminx 1486
            for (yy=1; yy<tsiz.y; yy+=yy)
2416 helixhorne 1487
            {
1488
                /* do nothing */
1489
            }
584 terminx 1490
        }
5 Plagman 1491
 
4605 terminx 1492
        ox2 = 1.0f/xx;
1493
        oy2 = 1.0f/yy;
1494
 
584 terminx 1495
        if ((!(method&3)) && (!fullbrightdrawingpass))
1496
        {
475 Plagman 1497
            bglDisable(GL_BLEND);
1229 terminx 1498
            bglDisable(GL_ALPHA_TEST);
584 terminx 1499
        }
1500
        else
1501
        {
4605 terminx 1502
            float al = 0.f; // PLAG : default alphacut was 0.32 before goodalpha
1503
            if (pth && pth->hicr && pth->hicr->alphacut >= 0.f) al = pth->hicr->alphacut;
109 terminx 1504
            if (alphahackarray[globalpicnum])
1505
                al=alphahackarray[globalpicnum];
4605 terminx 1506
            if (!waloff[globalpicnum]) al = 0.f;        // invalid textures ignore the alpha cutoff settings
1229 terminx 1507
            bglEnable(GL_BLEND);
109 terminx 1508
            bglEnable(GL_ALPHA_TEST);
1509
            bglAlphaFunc(GL_GREATER,al);
1510
        }
5 Plagman 1511
 
109 terminx 1512
        {
1513
            float pc[4];
3763 terminx 1514
 
4394 helixhorne 1515
#ifdef POLYMER
5056 hendricks2 1516
            if (getrendermode() == REND_POLYMER && pr_artmapping && !(globalflags & GLOBAL_NO_GL_TILESHADES) && polymer_eligible_for_artmap(globalpicnum, pth))
4394 helixhorne 1517
                pc[0] = pc[1] = pc[2] = 1.0f;
1518
            else
1519
#endif
1520
                pc[0] = pc[1] = pc[2] = getshadefactor(globalshade);
1521
 
3543 hendricks2 1522
            // spriteext full alpha control
4623 terminx 1523
            pc[3] = float_trans[method&3] * (1.f - alpha);
3543 hendricks2 1524
 
109 terminx 1525
            // tinting happens only to hightile textures, and only if the texture we're
1526
            // rendering isn't for the same palette as what we asked for
4486 helixhorne 1527
            if (!(hictinting[globalpal].f & HICTINT_COLORIZE))
943 terminx 1528
            {
4486 helixhorne 1529
                if (pth && (pth->flags & PTH_HIGHTILE))
384 terminx 1530
                {
5055 hendricks2 1531
                    if (pth->palnum != globalpal || (hictinting[globalpal].f & HICTINT_APPLYOVERALTPAL))
4487 helixhorne 1532
                        hictinting_apply(pc, globalpal);
1533
 
1534
                    if (have_basepal_tint())
1535
                        hictinting_apply(pc, MAXPALOOKUPS-1);
384 terminx 1536
                }
943 terminx 1537
                // hack: this is for drawing the 8-bit crosshair recolored in polymost
4486 helixhorne 1538
                else if (hictinting[globalpal].f & HICTINT_USEONART)
4487 helixhorne 1539
                    hictinting_apply(pc, globalpal);
943 terminx 1540
            }
384 terminx 1541
 
109 terminx 1542
            bglColor4f(pc[0],pc[1],pc[2],pc[3]);
1543
        }
5 Plagman 1544
 
109 terminx 1545
        //Hack for walls&masked walls which use textures that are not a power of 2
4623 terminx 1546
        if ((pow2xsplit) && (tsiz.x != xx))
109 terminx 1547
        {
4623 terminx 1548
            int32_t nn, ix0, ix1;
5 Plagman 1549
 
4623 terminx 1550
            float ngdx = 0.f, ngdy = 0.f, ngdo = 0.f, ngux = 0.f, nguy = 0.f, nguo = 0.f, uoffs;
1551
            float ngvx = 0.f, ngvy = 0.f, ngvo = 0.f, dp, up, vp, du0 = 0.f, du1 = 0.f, dui, duj;
1552
 
1553
            ox = py[1]-py[2]; oy = py[2]-py[0]; oz = py[0]-py[1];
1554
            r = 1.f / (ox*px[0] + oy*px[1] + oz*px[2]);
1555
            ngdx = (ox*dd[0] + oy*dd[1] + oz*dd[2])*r;
1556
            ngux = (ox*uu[0] + oy*uu[1] + oz*uu[2])*r;
1557
            ngvx = (ox*vv[0] + oy*vv[1] + oz*vv[2])*r;
1558
            ox = px[2]-px[1]; oy = px[0]-px[2]; oz = px[1]-px[0];
1559
            ngdy = (ox*dd[0] + oy*dd[1] + oz*dd[2])*r;
1560
            nguy = (ox*uu[0] + oy*uu[1] + oz*uu[2])*r;
1561
            ngvy = (ox*vv[0] + oy*vv[1] + oz*vv[2])*r;
1562
            ox = px[0]-0.5f; oy = py[0]-0.5f; //.5 centers texture nicely
1563
            ngdo = dd[0] - ox*ngdx - oy*ngdy;
1564
            nguo = uu[0] - ox*ngux - oy*nguy;
1565
            ngvo = vv[0] - ox*ngvx - oy*ngvy;
1566
 
109 terminx 1567
            ngux *= hackscx; nguy *= hackscx; nguo *= hackscx;
1568
            ngvx *= hackscy; ngvy *= hackscy; ngvo *= hackscy;
4623 terminx 1569
            uoffs = ((float)(xx-tsiz.x)*0.5f);
109 terminx 1570
            ngux -= ngdx*uoffs;
1571
            nguy -= ngdy*uoffs;
1572
            nguo -= ngdo*uoffs;
5 Plagman 1573
 
109 terminx 1574
            //Find min&max u coordinates (du0...du1)
4623 terminx 1575
            for (i=0; i<jj; i++)
109 terminx 1576
            {
1577
                ox = px[i]; oy = py[i];
1578
                f = (ox*ngux + oy*nguy + nguo) / (ox*ngdx + oy*ngdy + ngdo);
1579
                if (!i) { du0 = du1 = f; continue; }
1580
                if (f < du0) du0 = f;
1581
                else if (f > du1) du1 = f;
1582
            }
5 Plagman 1583
 
4623 terminx 1584
            f = 1.0f/tsiz.x;
4605 terminx 1585
            ix0 = Blrintf(floorf(du0*f));
1586
            ix1 = Blrintf(floorf(du1*f));
1229 terminx 1587
            for (; ix0<=ix1; ix0++)
109 terminx 1588
            {
4623 terminx 1589
                du0 = (float)(ix0*tsiz.x);   // + uoffs;
1590
                du1 = (float)((ix0+1)*tsiz.x); // + uoffs;
5 Plagman 1591
 
109 terminx 1592
                i = 0; nn = 0;
1593
                duj = (px[i]*ngux + py[i]*nguy + nguo) / (px[i]*ngdx + py[i]*ngdy + ngdo);
1594
                do
1595
                {
4623 terminx 1596
                    j = i+1; if (j == jj) j = 0;
5 Plagman 1597
 
4605 terminx 1598
                    dui = duj;
1599
                    duj = (px[j]*ngux + py[j]*nguy + nguo) / (px[j]*ngdx + py[j]*ngdy + ngdo);
5 Plagman 1600
 
4605 terminx 1601
                    if ((du0 <= dui) && (dui <= du1))
1602
                    {
1603
                        uu[nn] = px[i];
1604
                        vv[nn] = py[i];
1605
                        nn++;
1606
                    }
1607
 
1608
                    //ox*(ngux-ngdx*du1) + oy*(nguy-ngdy*du1) + (nguo-ngdo*du1) = 0
1609
                    //(px[j]-px[i])*f + px[i] = ox
1610
                    //(py[j]-py[i])*f + py[i] = oy
1611
 
1612
                    ///Solve for f
1613
                    //((px[j]-px[i])*f + px[i])*(ngux-ngdx*du1) +
1614
                    //((py[j]-py[i])*f + py[i])*(nguy-ngdy*du1) + (nguo-ngdo*du1) = 0
1615
 
1616
#define DRAWPOLY_MATH_BULLSHIT(X) do { f = -(px[i] *(ngux-ngdx*X) + py[i] *(nguy-ngdy*X) + (nguo-ngdo*X)) / ((px[j]-px[i])*(ngux-ngdx*X) + (py[j]-py[i])*(nguy-ngdy*X)); \
1617
                                        uu[nn] = (px[j]-px[i])*f + px[i]; vv[nn] = (py[j]-py[i])*f + py[i]; nn++; } while (0)
1618
 
109 terminx 1619
                    if (duj <= dui)
1620
                    {
1621
                        if ((du1 < duj) != (du1 < dui))
4605 terminx 1622
                            DRAWPOLY_MATH_BULLSHIT(du1);
109 terminx 1623
                        if ((du0 < duj) != (du0 < dui))
4605 terminx 1624
                            DRAWPOLY_MATH_BULLSHIT(du0);
109 terminx 1625
                    }
1626
                    else
1627
                    {
1628
                        if ((du0 < duj) != (du0 < dui))
4605 terminx 1629
                            DRAWPOLY_MATH_BULLSHIT(du0);
109 terminx 1630
                        if ((du1 < duj) != (du1 < dui))
4605 terminx 1631
                            DRAWPOLY_MATH_BULLSHIT(du1);
109 terminx 1632
                    }
1633
                    i = j;
4605 terminx 1634
 
1635
#undef DRAWPOLY_MATH_BULLSHIT
1636
 
584 terminx 1637
                }
1638
                while (i);
4605 terminx 1639
 
109 terminx 1640
                if (nn < 3) continue;
5 Plagman 1641
 
109 terminx 1642
                bglBegin(GL_TRIANGLE_FAN);
1229 terminx 1643
                for (i=0; i<nn; i++)
109 terminx 1644
                {
1645
                    ox = uu[i]; oy = vv[i];
1646
                    dp = ox*ngdx + oy*ngdy + ngdo;
1647
                    up = ox*ngux + oy*nguy + nguo;
1648
                    vp = ox*ngvx + oy*ngvy + ngvo;
4605 terminx 1649
                    r = 1.f/dp;
497 Plagman 1650
                    if (texunits > GL_TEXTURE0_ARB)
459 Plagman 1651
                    {
497 Plagman 1652
                        j = GL_TEXTURE0_ARB;
1653
                        while (j <= texunits)
4605 terminx 1654
                            bglMultiTexCoord2fARB(j++, (up*r-du0+uoffs)*ox2,vp*r*oy2);
459 Plagman 1655
                    }
1656
                    else
4605 terminx 1657
                        bglTexCoord2f((up*r-du0+uoffs)*ox2,vp*r*oy2);
1658
                    bglVertex3f((ox-ghalfx)*r*grhalfxdown10x,(ghoriz-oy)*r*grhalfxdown10,r*(1.f/1024.f));
109 terminx 1659
                }
1660
                bglEnd();
1661
            }
1662
        }
1663
        else
1664
        {
1665
            ox2 *= hackscx; oy2 *= hackscy;
1666
            bglBegin(GL_TRIANGLE_FAN);
4623 terminx 1667
            for (i=0; i<jj; i++)
109 terminx 1668
            {
4605 terminx 1669
                r = 1.f/dd[i];
497 Plagman 1670
                if (texunits > GL_TEXTURE0_ARB)
459 Plagman 1671
                {
497 Plagman 1672
                    j = GL_TEXTURE0_ARB;
1673
                    while (j <= texunits)
4605 terminx 1674
                        bglMultiTexCoord2fARB(j++, uu[i]*r*ox2,vv[i]*r*oy2);
459 Plagman 1675
                }
497 Plagman 1676
                else
4605 terminx 1677
                    bglTexCoord2f(uu[i]*r*ox2,vv[i]*r*oy2);
1678
                bglVertex3f((px[i]-ghalfx)*r*grhalfxdown10x,(ghoriz-py[i])*r*grhalfxdown10,r*(1.f/1024.f));
109 terminx 1679
            }
1680
            bglEnd();
1681
        }
497 Plagman 1682
 
504 Plagman 1683
        while (texunits >= GL_TEXTURE0_ARB)
461 Plagman 1684
        {
666 plagman 1685
            bglActiveTextureARB(texunits);
504 Plagman 1686
            bglMatrixMode(GL_TEXTURE);
1687
            bglLoadIdentity();
1688
            bglMatrixMode(GL_MODELVIEW);
1689
            if (texunits > GL_TEXTURE0_ARB)
497 Plagman 1690
            {
501 Plagman 1691
                bglTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
497 Plagman 1692
                bglDisable(GL_TEXTURE_2D);
1693
            }
666 plagman 1694
            texunits--;
461 Plagman 1695
        }
497 Plagman 1696
 
3784 terminx 1697
        if (getrendermode() == REND_POLYMOST)
3741 Plagman 1698
        {
1699
            if (srepeat)
1700
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
1701
            if (trepeat)
1702
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
1703
        }
590 plagman 1704
 
248 terminx 1705
        if (fullbrightdrawingpass == 1) // tile has fullbright colors ?
1706
        {
3146 helixhorne 1707
            int32_t shadeforfullbrightpass = globalshade; // save the current shade
248 terminx 1708
            fullbrightdrawingpass = 2;
388 terminx 1709
            globalshade = -128; // fullbright
621 plagman 1710
            bglDisable(GL_FOG);
4671 terminx 1711
            drawpoly(dpxy, n, method_); // draw them afterwards, then. :)
5001 terminx 1712
            if (!nofog) bglEnable(GL_FOG);
248 terminx 1713
            globalshade = shadeforfullbrightpass;
1714
            fullbrightdrawingpass = 0;
1715
        }
109 terminx 1716
        return;
1717
    }
5 Plagman 1718
#endif
1719
}
1720
 
2002 helixhorne 1721
 
4898 terminx 1722
static inline void vsp_finalize_init(vsptyp *vsp, int32_t vcnt)
2002 helixhorne 1723
{
1724
    int32_t i;
1725
 
1726
    for (i=0; i<vcnt; i++)
1727
    {
1728
        vsp[i].cy[1] = vsp[i+1].cy[0]; vsp[i].ctag = i;
1729
        vsp[i].fy[1] = vsp[i+1].fy[0]; vsp[i].ftag = i;
1730
        vsp[i].n = i+1; vsp[i].p = i-1;
1731
//        vsp[i].tag = -1;
1732
    }
1733
    vsp[vcnt-1].n = 0; vsp[0].p = vcnt-1;
1734
 
1735
    //VSPMAX-1 is dummy empty node
1736
    for (i=vcnt; i<VSPMAX; i++) { vsp[i].n = i+1; vsp[i].p = i-1; }
1737
    vsp[VSPMAX-1].n = vcnt; vsp[vcnt].p = VSPMAX-1;
1738
}
1739
 
1740
static inline void vsdel(vsptyp *vsp, int32_t i)
5 Plagman 1741
{
109 terminx 1742
    //Delete i
4623 terminx 1743
    vsp[vsp[i].n].p = vsp[i].p;
1744
    vsp[vsp[i].p].n = vsp[i].n;
5 Plagman 1745
 
109 terminx 1746
    //Add i to empty list
1747
    vsp[i].n = vsp[VSPMAX-1].n;
1748
    vsp[i].p = VSPMAX-1;
1749
    vsp[vsp[VSPMAX-1].n].p = i;
1750
    vsp[VSPMAX-1].n = i;
5 Plagman 1751
}
1752
 
2002 helixhorne 1753
static inline int32_t vsinsaft(vsptyp *vsp, int32_t i)
5 Plagman 1754
{
109 terminx 1755
    //i = next element from empty list
4623 terminx 1756
    int32_t r = vsp[VSPMAX-1].n;
109 terminx 1757
    vsp[vsp[r].n].p = VSPMAX-1;
1758
    vsp[VSPMAX-1].n = vsp[r].n;
5 Plagman 1759
 
109 terminx 1760
    vsp[r] = vsp[i]; //copy i to r
5 Plagman 1761
 
109 terminx 1762
    //insert r after i
1763
    vsp[r].p = i; vsp[r].n = vsp[i].n;
1764
    vsp[vsp[i].n].p = r; vsp[i].n = r;
5 Plagman 1765
 
109 terminx 1766
    return(r);
5 Plagman 1767
}
1768
 
1205 terminx 1769
static int32_t domostpolymethod = 0;
5 Plagman 1770
 
584 terminx 1771
void domost(float x0, float y0, float x1, float y1)
5 Plagman 1772
{
4675 terminx 1773
    vec2f_t dpxy[4], n0, n1;
1774
    float slop, dx;
2002 helixhorne 1775
    float spx[4], /*spy[4],*/ cy[2], cv[2];
4675 terminx 1776
    int32_t i, k, z, vcnt = 0, scnt, newi, dir = 0, spt[4];
5 Plagman 1777
 
3555 hendricks2 1778
    alpha = 0.f;
1779
 
109 terminx 1780
    if (x0 < x1)
1781
    {
1782
        dir = 1; //clip dmost (floor)
4623 terminx 1783
        y0 -= .01f;
1784
        y1 -= .01f;
109 terminx 1785
    }
1786
    else
1787
    {
1788
        if (x0 == x1) return;
4605 terminx 1789
        swapfloat(&x0, &x1);
1790
        swapfloat(&y0, &y1);
4623 terminx 1791
        //dir = 0; //clip umost (ceiling)
109 terminx 1792
        //y0 += .01; y1 += .01; //necessary?
1793
    }
5 Plagman 1794
 
109 terminx 1795
    slop = (y1-y0)/(x1-x0);
1229 terminx 1796
    for (i=vsp[0].n; i; i=newi)
109 terminx 1797
    {
4675 terminx 1798
        newi = vsp[i].n; n0.x = vsp[i].x; n1.x = vsp[newi].x;
1799
        if ((x0 >= n1.x) || (n0.x >= x1) || (vsp[i].ctag <= 0)) continue;
1800
        dx = n1.x-n0.x;
109 terminx 1801
        cy[0] = vsp[i].cy[0]; cv[0] = vsp[i].cy[1]-cy[0];
1802
        cy[1] = vsp[i].fy[0]; cv[1] = vsp[i].fy[1]-cy[1];
5 Plagman 1803
 
109 terminx 1804
        scnt = 0;
5 Plagman 1805
 
109 terminx 1806
        //Test if left edge requires split (x0,y0) (nx0,cy(0)),<dx,cv(0)>
4675 terminx 1807
        if ((x0 > n0.x) && (x0 < n1.x))
109 terminx 1808
        {
4675 terminx 1809
            const float t = (x0-n0.x)*cv[dir] - (y0-cy[dir])*dx;
4623 terminx 1810
            if (((!dir) && (t < 0.f)) || ((dir) && (t > 0.f)))
2002 helixhorne 1811
                { spx[scnt] = x0; /*spy[scnt] = y0;*/ spt[scnt] = -1; scnt++; }
109 terminx 1812
        }
5 Plagman 1813
 
4675 terminx 1814
        //Test for intersection on umost (0) and dmost (1)
1815
 
109 terminx 1816
        {
4690 terminx 1817
            const float d[2] ={
4675 terminx 1818
                ((y0-y1) * dx) - ((x0-x1) * cv[0]),
4690 terminx 1819
                ((y0-y1) * dx) - ((x0-x1) * cv[1])
4675 terminx 1820
            };
4623 terminx 1821
 
4690 terminx 1822
            const float n[2] ={
4675 terminx 1823
                ((y0-cy[0]) * dx) - ((x0-n0.x) * cv[0]),
4690 terminx 1824
                ((y0-cy[1]) * dx) - ((x0-n0.x) * cv[1])
4675 terminx 1825
            };
4671 terminx 1826
 
4690 terminx 1827
            const float fnx[2] ={
4675 terminx 1828
                x0 + ((n[0]/d[0]) * (x1-x0)),
4690 terminx 1829
                x0 + ((n[1]/d[1]) * (x1-x0))
4675 terminx 1830
            };
1831
 
1832
            if ((Bfabsf(d[0]) > Bfabsf(n[0])) && (d[0] * n[0] >= 0.f) && (fnx[0] > n0.x) && (fnx[0] < n1.x))
1833
                spx[scnt] = fnx[0], spt[scnt++] = 0;
1834
 
1835
            if ((Bfabsf(d[1]) > Bfabsf(n[1])) && (d[1] * n[1] >= 0.f) && (fnx[1] > n0.x) && (fnx[1] < n1.x))
1836
                spx[scnt] = fnx[1], spt[scnt++] = 1;
109 terminx 1837
        }
5 Plagman 1838
 
109 terminx 1839
        //Nice hack to avoid full sort later :)
1840
        if ((scnt >= 2) && (spx[scnt-1] < spx[scnt-2]))
1841
        {
4605 terminx 1842
            swapfloat(&spx[scnt-1], &spx[scnt-2]);
1843
            swaplong(&spt[scnt-1], &spt[scnt-2]);
2002 helixhorne 1844
            /* f = spy[scnt-1]; spy[scnt-1] = spy[scnt-2]; spy[scnt-2] = f; */
109 terminx 1845
        }
5 Plagman 1846
 
109 terminx 1847
        //Test if right edge requires split
4675 terminx 1848
        if ((x1 > n0.x) && (x1 < n1.x))
109 terminx 1849
        {
4675 terminx 1850
            const float t = (x1-n0.x)*cv[dir] - (y1-cy[dir])*dx;
109 terminx 1851
            if (((!dir) && (t < 0)) || ((dir) && (t > 0)))
2002 helixhorne 1852
                { spx[scnt] = x1; /* spy[scnt] = y1; */ spt[scnt] = -1; scnt++; }
109 terminx 1853
        }
5 Plagman 1854
 
109 terminx 1855
        vsp[i].tag = vsp[newi].tag = -1;
4671 terminx 1856
 
1857
        dx = 1.f/dx;
1858
 
1229 terminx 1859
        for (z=0; z<=scnt; z++,i=vcnt)
109 terminx 1860
        {
4898 terminx 1861
            float t;
4671 terminx 1862
 
4675 terminx 1863
            if (z == scnt)
1864
                goto skip;
5 Plagman 1865
 
4675 terminx 1866
            t = (spx[z]-n0.x)*dx;
1867
            vcnt = vsinsaft(vsp, i);
1868
            vsp[i].cy[1] = t*cv[0] + cy[0];
1869
            vsp[i].fy[1] = t*cv[1] + cy[1];
1870
            vsp[vcnt].x = spx[z];
1871
            vsp[vcnt].cy[0] = vsp[i].cy[1];
1872
            vsp[vcnt].fy[0] = vsp[i].fy[1];
1873
            vsp[vcnt].tag = spt[z];
1874
 
4930 helixhorne 1875
skip: ;
4898 terminx 1876
            int32_t ni = vsp[i].n; if (!ni) continue; //this 'if' fixes many bugs!
1877
            float dx0 = vsp[i].x; if (x0 > dx0) continue;
1878
            float dx1 = vsp[ni].x; if (x1 < dx1) continue;
4675 terminx 1879
            n0.y = (dx0-x0)*slop + y0;
1880
            n1.y = (dx1-x0)*slop + y0;
5 Plagman 1881
 
109 terminx 1882
            //      dx0           dx1
1883
            //       ~             ~
1884
            //----------------------------
1885
            //     t0+=0         t1+=0
1886
            //   vsp[i].cy[0]  vsp[i].cy[1]
1887
            //============================
1888
            //     t0+=1         t1+=3
1889
            //============================
1890
            //   vsp[i].fy[0]    vsp[i].fy[1]
1891
            //     t0+=2         t1+=6
1892
            //
1893
            //     ny0 ?         ny1 ?
5 Plagman 1894
 
109 terminx 1895
            k = 1+3;
4675 terminx 1896
            if ((vsp[i].tag == 0) || (n0.y <= vsp[i].cy[0]+.01f)) k--;
1897
            if ((vsp[i].tag == 1) || (n0.y >= vsp[i].fy[0]-.01f)) k++;
1898
            if ((vsp[ni].tag == 0) || (n1.y <= vsp[i].cy[1]+.01f)) k -= 3;
1899
            if ((vsp[ni].tag == 1) || (n1.y >= vsp[i].fy[1]-.01f)) k += 3;
5 Plagman 1900
 
4671 terminx 1901
            dpxy[0].x = dx0;
1902
            dpxy[1].x = dx1;
4605 terminx 1903
 
109 terminx 1904
            if (!dir)
1905
            {
4671 terminx 1906
                dpxy[0].y = vsp[i].cy[0];
1907
                dpxy[1].y = vsp[i].cy[1];
2002 helixhorne 1908
 
331 terminx 1909
                switch (k)
109 terminx 1910
                {
4675 terminx 1911
                case 4:
1912
                case 5:
1913
                case 7:
1914
                    dpxy[2].x = dx1; dpxy[3].x = dx0;
1915
                    dpxy[2].y = n1.y; dpxy[3].y = n0.y;
1916
                    vsp[i].cy[0] = n0.y; vsp[i].cy[1] = n1.y; vsp[i].ctag = gtag;
1917
                    drawpoly(dpxy, 4, domostpolymethod);
1918
                    break;
331 terminx 1919
                case 1:
1920
                case 2:
4671 terminx 1921
                    dpxy[2].x = dx0;
4675 terminx 1922
                    dpxy[2].y = n0.y;
1923
                    vsp[i].cy[0] = n0.y; vsp[i].ctag = gtag;
4671 terminx 1924
                    drawpoly(dpxy, 3, domostpolymethod);
4623 terminx 1925
                    break;
331 terminx 1926
                case 3:
1927
                case 6:
4671 terminx 1928
                    dpxy[2].x = dx1;
4675 terminx 1929
                    dpxy[2].y = n1.y;
1930
                    vsp[i].cy[1] = n1.y; vsp[i].ctag = gtag;
4671 terminx 1931
                    drawpoly(dpxy, 3, domostpolymethod);
4623 terminx 1932
                    break;
109 terminx 1933
                case 8:
4671 terminx 1934
                    dpxy[2].x = dx1; dpxy[2].y = vsp[i].fy[1];
1935
                    dpxy[3].x = dx0; dpxy[3].y = vsp[i].fy[0];
4623 terminx 1936
                    vsp[i].ctag = vsp[i].ftag = -1;
4671 terminx 1937
                    drawpoly(dpxy, 4, domostpolymethod);
331 terminx 1938
                default:
4623 terminx 1939
                    break;
109 terminx 1940
                }
1941
            }
1942
            else
1943
            {
331 terminx 1944
                switch (k)
109 terminx 1945
                {
4675 terminx 1946
                case 4:
1947
                case 3:
1948
                case 1:
1949
                    dpxy[2].x = dx1; dpxy[3].x = dx0;
1950
                    dpxy[0].y = n0.y; dpxy[1].y = n1.y; dpxy[2].y = vsp[i].fy[1]; dpxy[3].y = vsp[i].fy[0];
1951
                    vsp[i].fy[0] = n0.y; vsp[i].fy[1] = n1.y; vsp[i].ftag = gtag;
1952
                    drawpoly(dpxy, 4, domostpolymethod);
1953
                    break;
331 terminx 1954
                case 7:
1955
                case 6:
4671 terminx 1956
                    dpxy[2].x = dx0;
4675 terminx 1957
                    dpxy[0].y = n0.y; dpxy[1].y = vsp[i].fy[1]; dpxy[2].y = vsp[i].fy[0];
1958
                    vsp[i].fy[0] = n0.y; vsp[i].ftag = gtag;
4671 terminx 1959
                    drawpoly(dpxy, 3, domostpolymethod);
4623 terminx 1960
                    break;
331 terminx 1961
                case 5:
1962
                case 2:
4671 terminx 1963
                    dpxy[2].x = dx1;
4675 terminx 1964
                    dpxy[0].y = vsp[i].fy[0]; dpxy[1].y = n1.y; dpxy[2].y = vsp[i].fy[1];
1965
                    vsp[i].fy[1] = n1.y; vsp[i].ftag = gtag;
4671 terminx 1966
                    drawpoly(dpxy, 3, domostpolymethod);
4623 terminx 1967
                    break;
109 terminx 1968
                case 0:
4671 terminx 1969
                    dpxy[2].x = dx1; dpxy[3].x = dx0;
1970
                    dpxy[0].y = vsp[i].cy[0]; dpxy[1].y = vsp[i].cy[1]; dpxy[2].y = vsp[i].fy[1]; dpxy[3].y = vsp[i].fy[0];
4623 terminx 1971
                    vsp[i].ctag = vsp[i].ftag = -1;
4671 terminx 1972
                    drawpoly(dpxy, 4, domostpolymethod);
331 terminx 1973
                default:
4623 terminx 1974
                    break;
109 terminx 1975
                }
1976
            }
1977
        }
1978
    }
5 Plagman 1979
 
109 terminx 1980
    gtag++;
1981
 
1982
    //Combine neighboring vertical strips with matching collinear top&bottom edges
1983
    //This prevents x-splits from propagating through the entire scan
1984
    i = vsp[0].n;
4623 terminx 1985
 
109 terminx 1986
    while (i)
1987
    {
4671 terminx 1988
        int32_t ni = vsp[i].n;
2002 helixhorne 1989
 
1990
        if ((vsp[i].cy[0] >= vsp[i].fy[0]) && (vsp[i].cy[1] >= vsp[i].fy[1]))
1991
            vsp[i].ctag = vsp[i].ftag = -1;
1992
 
109 terminx 1993
        if ((vsp[i].ctag == vsp[ni].ctag) && (vsp[i].ftag == vsp[ni].ftag))
2002 helixhorne 1994
        {
1995
            vsp[i].cy[1] = vsp[ni].cy[1];
1996
            vsp[i].fy[1] = vsp[ni].fy[1];
1997
            vsdel(vsp, ni);
1998
        }
109 terminx 1999
        else i = ni;
2000
    }
5 Plagman 2001
}
2002
 
4652 terminx 2003
void polymost_editorfunc(void)
2004
{
4656 terminx 2005
    vec3_t v;
2006
    vec3f_t o, o2;
4652 terminx 2007
    int32_t cz, fz;
2008
    hitdata_t hit;
2009
    vec3_t vect;
2010
    const float ratio = get_projhack_ratio();
2011
 
2012
    o2.x = (searchx-ghalfx)/ratio;
2013
    o2.y = (searchy-ghoriz)/ratio;  // ghoriz is (ydimen>>1) here
2014
    o2.z = ghalfx;
2015
 
2016
    //Tilt rotation
2017
    o.x = o2.x*gctang + o2.y*gstang;
2018
    o.y = o2.y*gctang - o2.x*gstang;
2019
    o.z = o2.z;
2020
 
2021
    //Up/down rotation
2022
    o2.x = o.z*gchang - o.y*gshang;
2023
    o2.y = o.x;
2024
    o2.z = o.y*gchang + o.z*gshang;
2025
 
2026
    //Standard Left/right rotation
4656 terminx 2027
    v.x = Blrintf (o2.x*fcosglobalang - o2.y*fsinglobalang);
2028
    v.y = Blrintf (o2.x*fsinglobalang + o2.y*fcosglobalang);
2029
    v.z = Blrintf (o2.z*16384.f);
4652 terminx 2030
 
2031
    vect.x = globalposx;
2032
    vect.y = globalposy;
2033
    vect.z = globalposz;
2034
 
2035
    hitallsprites = 1;
2036
    hitscan((const vec3_t *) &vect, globalcursectnum, //Start position
2037
        v.x>>10, v.y>>10, v.z>>6, &hit, 0xffff0030);
2038
 
2039
    if (hit.sect != -1) // if hitsect is -1, hitscan overflowed somewhere
2040
    {
2041
        getzsofslope(hit.sect, hit.pos.x, hit.pos.y, &cz, &fz);
2042
        hitallsprites = 0;
2043
 
2044
        searchsector = hit.sect;
2045
        if (hit.pos.z<cz) searchstat = 1;
2046
        else if (hit.pos.z>fz) searchstat = 2;
2047
        else if (hit.wall >= 0)
2048
        {
2049
            searchbottomwall = searchwall = hit.wall; searchstat = 0;
2050
            if (wall[hit.wall].nextwall >= 0)
2051
            {
2052
                int32_t cz, fz;
2053
                getzsofslope(wall[hit.wall].nextsector, hit.pos.x, hit.pos.y, &cz, &fz);
2054
                if (hit.pos.z > fz)
2055
                {
2056
                    searchisbottom = 1;
2057
                    if (wall[hit.wall].cstat&2) //'2' bottoms of walls
2058
                        searchbottomwall = wall[hit.wall].nextwall;
2059
                }
2060
                else
2061
                {
2062
                    searchisbottom = 0;
2063
                    if ((hit.pos.z > cz) && (wall[hit.wall].cstat&(16+32))) //masking or 1-way
2064
                        searchstat =