Subversion Repositories eduke32

Rev

Rev 5024 | 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 &&
4605 terminx 445
        (!usehightile || !hicfindsubst(tile, pal)) &&
3982 terminx 446
        (!usemodels || md_tilehasmodel(tile, pal) < 0))
447
        shade >>= 1;
448
 
4904 terminx 449
    Bmemcpy(fogcol, &fogtable[pal<<2], sizeof(fogcol));
450
 
4393 helixhorne 451
    if (r_usenewshading < 2)
3768 terminx 452
        fogcalc_old(shade, vis);
3763 terminx 453
    else
454
    {
4904 terminx 455
        float combvis = (float) globalvisibility * (uint8_t) (vis+16);
3303 helixhorne 456
 
457
        if (combvis == 0)
458
        {
4393 helixhorne 459
            if (r_usenewshading == 2 && shade > 0)
3959 helixhorne 460
            {
461
                // beg = -D*shade, end = D*(NUMSHADES-1-shade)
462
                //  => end/beg = -(NUMSHADES-1-shade)/shade
4904 terminx 463
                fogresult = (float) -FULLVIS_BEGIN;
464
                fogresult2 = FULLVIS_BEGIN * (float) (numshades-1-shade)/shade;
3959 helixhorne 465
            }
466
            else
467
            {
4904 terminx 468
                fogresult = (float) FULLVIS_BEGIN;
469
                fogresult2 = (float) FULLVIS_END;
3959 helixhorne 470
            }
3303 helixhorne 471
        }
4904 terminx 472
        else if (r_usenewshading == 3 && shade >= numshades-1)
4452 helixhorne 473
        {
474
            fogresult = -1;
475
            fogresult2 = 0;
476
        }
477
        else
478
        {
4658 terminx 479
            combvis = 1.f/combvis;
480
            fogresult = (r_usenewshading == 3 && shade > 0) ? 0 : -(FOGDISTCONST * shade) * combvis;
481
            fogresult2 = (FOGDISTCONST * (numshades-1-shade)) * combvis;
4452 helixhorne 482
        }
3303 helixhorne 483
    }
3763 terminx 484
}
3303 helixhorne 485
 
3763 terminx 486
void calc_and_apply_fog(int32_t tile, int32_t shade, int32_t vis, int32_t pal)
487
{
488
    fogcalc(tile, shade, vis, pal);
489
    bglFogfv(GL_FOG_COLOR, fogcol);
3303 helixhorne 490
 
4393 helixhorne 491
    if (r_usenewshading < 2)
4904 terminx 492
        bglFogf(GL_FOG_DENSITY, fogresult);
493
    else
3763 terminx 494
    {
4904 terminx 495
        bglFogf(GL_FOG_START, fogresult);
496
        bglFogf(GL_FOG_END, fogresult2);
3763 terminx 497
    }
3303 helixhorne 498
}
499
 
3763 terminx 500
void calc_and_apply_fog_factor(int32_t tile, int32_t shade, int32_t vis, int32_t pal, float factor)
3303 helixhorne 501
{
4393 helixhorne 502
    // NOTE: for r_usenewshading >= 2, the fog beginning/ending distance results are
3959 helixhorne 503
    // unused.
3763 terminx 504
    fogcalc(tile, shade, vis, pal);
505
    bglFogfv(GL_FOG_COLOR, fogcol);
3303 helixhorne 506
 
4393 helixhorne 507
    if (r_usenewshading < 2)
4904 terminx 508
        bglFogf(GL_FOG_DENSITY, fogresult*factor);
509
    else
3303 helixhorne 510
    {
4904 terminx 511
        bglFogf(GL_FOG_START, (GLfloat) FULLVIS_BEGIN);
512
        bglFogf(GL_FOG_END, (GLfloat) FULLVIS_END);
3763 terminx 513
    }
3303 helixhorne 514
}
515
////////////////////
516
 
1357 terminx 517
 
3401 helixhorne 518
static float get_projhack_ratio(void)
519
{
4904 terminx 520
    float rv;
521
 
3401 helixhorne 522
    if (glprojectionhacks == 1)
523
    {
4904 terminx 524
        float const mul = (gshang * gshang);
525
        rv = 1.05f + mul * mul * mul * mul;
3401 helixhorne 526
    }
4904 terminx 527
    else if (glprojectionhacks == 2)
3401 helixhorne 528
    {
4904 terminx 529
        float const abs_shang = Bfabsf(gshang);
4907 terminx 530
        rv = (abs_shang > 0.7f) ?
531
            1.05f + 4.f * (abs_shang - 0.7f) : 1.f;
3401 helixhorne 532
    }
4904 terminx 533
    else
534
        rv = 1.f;
3401 helixhorne 535
 
536
    // No projection hacks (legacy or new-aspect)
4904 terminx 537
    return rv;
3401 helixhorne 538
}
539
 
3041 helixhorne 540
static void resizeglcheck(void)
5 Plagman 541
{
4605 terminx 542
#ifdef REDBLUEMODE
584 terminx 543
    if (glredbluemode < lastglredbluemode)
544
    {
109 terminx 545
        glox1 = -1;
546
        bglColorMask(1,1,1,1);
584 terminx 547
    }
548
    else if (glredbluemode != lastglredbluemode)
549
    {
109 terminx 550
        redblueclearcnt = 0;
551
    }
552
    lastglredbluemode = glredbluemode;
4605 terminx 553
#endif
5 Plagman 554
 
5001 terminx 555
#ifndef EDUKE32_GLES
109 terminx 556
    //FUK
557
    if (lastglpolygonmode != glpolygonmode)
558
    {
559
        lastglpolygonmode = glpolygonmode;
331 terminx 560
        switch (glpolygonmode)
109 terminx 561
        {
562
        default:
331 terminx 563
        case 0:
564
            bglPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break;
565
        case 1:
566
            bglPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break;
567
        case 2:
568
            bglPolygonMode(GL_FRONT_AND_BACK,GL_POINT); break;
109 terminx 569
        }
570
    }
571
    if (glpolygonmode) //FUK
572
    {
573
        bglClearColor(1.0,1.0,1.0,0.0);
574
        bglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
575
        bglDisable(GL_TEXTURE_2D);
576
    }
5001 terminx 577
#else
578
    bglPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
579
#endif
5 Plagman 580
 
109 terminx 581
    if ((glox1 != windowx1) || (gloy1 != windowy1) || (glox2 != windowx2) || (gloy2 != windowy2))
582
    {
3401 helixhorne 583
        const int32_t ourxdimen = (windowx2-windowx1+1);
4658 terminx 584
        float ratio = get_projhack_ratio();
3401 helixhorne 585
        const int32_t fovcorrect = (ratio==0) ? 0 : (int32_t)(ourxdimen*ratio - ourxdimen);
4623 terminx 586
        float m[4][4];
1114 terminx 587
 
1454 terminx 588
        glox1 = (float)windowx1; gloy1 = (float)windowy1;
589
        glox2 = (float)windowx2; gloy2 = (float)windowy2;
109 terminx 590
 
1961 helixhorne 591
        bglViewport(windowx1-(fovcorrect/2), yres-(windowy2+1),
3401 helixhorne 592
                    ourxdimen+fovcorrect, windowy2-windowy1+1);
5 Plagman 593
 
109 terminx 594
        bglMatrixMode(GL_PROJECTION);
4675 terminx 595
        Bmemset(m,0,sizeof(m));
4658 terminx 596
        ratio = 1.f/ratio;
597
        m[0][0] = fydimen * ratio; m[0][2] = 1.f;
4656 terminx 598
        m[1][1] = fxdimen; m[1][2] = 1.f;
4658 terminx 599
        m[2][2] = 1.f; m[2][3] = fydimen * ratio;
4605 terminx 600
        m[3][2] =-1.f;
109 terminx 601
        bglLoadMatrixf(&m[0][0]);
5 Plagman 602
 
109 terminx 603
        bglMatrixMode(GL_MODELVIEW);
604
        bglLoadIdentity();
5 Plagman 605
 
1064 terminx 606
#ifdef USE_OPENGL
109 terminx 607
        if (!nofog) bglEnable(GL_FOG);
1064 terminx 608
#endif
5 Plagman 609
 
109 terminx 610
        //bglEnable(GL_TEXTURE_2D);
611
    }
5 Plagman 612
}
613
 
4639 terminx 614
static void fixtransparency(coltype *dapic, vec2_t dasiz, vec2_t dasiz2, int32_t dameth)
5 Plagman 615
{
4485 helixhorne 616
    int32_t y, naxsiz2;
4639 terminx 617
    vec2_t doxy = { dasiz2.x-1, dasiz2.y-1 };
5 Plagman 618
 
4639 terminx 619
    if (dameth&4) { doxy.x = min(doxy.x, dasiz.x); doxy.y = min(doxy.y, dasiz.y); }
620
    else { dasiz = dasiz2; } //Make repeating textures duplicate top/left parts
3695 helixhorne 621
 
4639 terminx 622
    dasiz.x--; dasiz.y--; naxsiz2 = -dasiz2.x; //Hacks for optimization inside loop
5 Plagman 623
 
109 terminx 624
    //Set transparent pixels to average color of neighboring opaque pixels
625
    //Doing this makes bilinear filtering look much better for masked textures (I.E. sprites)
4639 terminx 626
    for (y=doxy.y; y>=0; y--)
109 terminx 627
    {
4485 helixhorne 628
        int32_t x;
4639 terminx 629
        coltype * wpptr = &dapic[y*dasiz2.x+doxy.x];
4485 helixhorne 630
 
4639 terminx 631
        for (x=doxy.x; x>=0; x--,wpptr--)
109 terminx 632
        {
4485 helixhorne 633
            int32_t r=0, g=0, b=0, j=0;
634
 
109 terminx 635
            if (wpptr->a) continue;
3111 helixhorne 636
 
109 terminx 637
            r = g = b = j = 0;
3041 helixhorne 638
            if ((x>     0) && (wpptr[     -1].a)) { r += wpptr[     -1].r; g += wpptr[     -1].g; b += wpptr[     -1].b; j++; }
4639 terminx 639
            if ((x<dasiz.x) && (wpptr[     +1].a)) { r += wpptr[     +1].r; g += wpptr[     +1].g; b += wpptr[     +1].b; j++; }
3041 helixhorne 640
            if ((y>     0) && (wpptr[naxsiz2].a)) { r += wpptr[naxsiz2].r; g += wpptr[naxsiz2].g; b += wpptr[naxsiz2].b; j++; }
4639 terminx 641
            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 642
            switch (j)
109 terminx 643
            {
331 terminx 644
            case 1:
645
                wpptr->r =   r            ; wpptr->g =   g            ; wpptr->b =   b            ; break;
646
            case 2:
647
                wpptr->r = ((r   +  1)>>1); wpptr->g = ((g   +  1)>>1); wpptr->b = ((b   +  1)>>1); break;
648
            case 3:
649
                wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); break;
650
            case 4:
651
                wpptr->r = ((r   +  2)>>2); wpptr->g = ((g   +  2)>>2); wpptr->b = ((b   +  2)>>2); break;
109 terminx 652
            }
653
        }
654
    }
5 Plagman 655
}
656
 
4488 helixhorne 657
void uploadtexture(int32_t doalloc, int32_t xsiz, int32_t ysiz, int32_t intexfmt, int32_t texfmt,
658
                   coltype *pic, int32_t tsizx, int32_t tsizy, int32_t dameth)
5 Plagman 659
{
4485 helixhorne 660
    int32_t x2, y2, j, js=0;
4486 helixhorne 661
    const int32_t hi = (dameth & DAMETH_HI) ? 1 : 0;
662
    const int32_t nocompress = (dameth & DAMETH_NOCOMPRESS) ? 1 : 0;
5 Plagman 663
 
4486 helixhorne 664
    dameth &= ~(DAMETH_HI|DAMETH_NOCOMPRESS);
916 terminx 665
 
584 terminx 666
    if (gltexmaxsize <= 0)
667
    {
109 terminx 668
        GLint i = 0;
669
        bglGetIntegerv(GL_MAX_TEXTURE_SIZE, &i);
670
        if (!i) gltexmaxsize = 6;   // 2^6 = 64 == default GL max texture size
584 terminx 671
        else
672
        {
109 terminx 673
            gltexmaxsize = 0;
674
            for (; i>1; i>>=1) gltexmaxsize++;
675
        }
676
    }
5 Plagman 677
 
109 terminx 678
    js = max(0,min(gltexmaxsize-1,gltexmiplevel));
679
    gltexmiplevel = js;
680
    while ((xsiz>>js) > (1<<gltexmaxsize) || (ysiz>>js) > (1<<gltexmaxsize)) js++;
5 Plagman 681
 
990 terminx 682
    if (hi && !nocompress) js = r_downsize;
916 terminx 683
 
109 terminx 684
    /*
685
    OSD_Printf("Uploading %dx%d %s as %s\n", xsiz,ysiz,
1625 terminx 686
            (texfmt==GL_RGBA?"GL_RGBA":
687
             texfmt==GL_RGB?"GL_RGB":
688
             texfmt==GL_BGR?"GL_BGR":
689
             texfmt==GL_BGRA?"GL_BGRA":"other"),
690
            (intexfmt==GL_RGBA?"GL_RGBA":
691
             intexfmt==GL_RGB?"GL_RGB":
692
             intexfmt==GL_COMPRESSED_RGBA_ARB?"GL_COMPRESSED_RGBA_ARB":
693
             intexfmt==GL_COMPRESSED_RGB_ARB?"GL_COMPRESSED_RGB_ARB":"other"));
109 terminx 694
    */
695
 
584 terminx 696
    if (js == 0)
697
    {
109 terminx 698
        if (doalloc&1)
699
            bglTexImage2D(GL_TEXTURE_2D,0,intexfmt,xsiz,ysiz,0,texfmt,GL_UNSIGNED_BYTE,pic); //loading 1st time
700
        else
701
            bglTexSubImage2D(GL_TEXTURE_2D,0,0,0,xsiz,ysiz,texfmt,GL_UNSIGNED_BYTE,pic); //overwrite old texture
702
    }
703
 
5 Plagman 704
#if 0
109 terminx 705
    gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8,xsiz,ysiz,texfmt,GL_UNSIGNED_BYTE,pic); //Needs C++ to link?
5 Plagman 706
#elif 1
109 terminx 707
    x2 = xsiz; y2 = ysiz;
1229 terminx 708
    for (j=1; (x2 > 1) || (y2 > 1); j++)
109 terminx 709
    {
4485 helixhorne 710
        int32_t y;
711
        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 712
        //x3 = ((x2+1)>>1); y3 = ((y2+1)>>1);
4485 helixhorne 713
 
1229 terminx 714
        for (y=0; y<y3; y++)
109 terminx 715
        {
4485 helixhorne 716
            int32_t x;
717
            coltype *wpptr = &pic[y*x3], *rpptr = &pic[(y<<1)*x2];
718
 
1229 terminx 719
            for (x=0; x<x3; x++,wpptr++,rpptr+=2)
109 terminx 720
            {
4485 helixhorne 721
                int32_t r=0, g=0, b=0, a=0, k=0;
722
 
3041 helixhorne 723
                if (rpptr[0].a)                  { r += rpptr[0].r; g += rpptr[0].g; b += rpptr[0].b; a += rpptr[0].a; k++; }
724
                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 725
                if (y+y+1 < y2)
726
                {
3041 helixhorne 727
                    if ((rpptr[x2].a)) { r += rpptr[x2  ].r; g += rpptr[x2  ].g; b += rpptr[x2  ].b; a += rpptr[x2  ].a; k++; }
728
                    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 729
                }
331 terminx 730
                switch (k)
109 terminx 731
                {
732
                case 0:
331 terminx 733
                case 1:
734
                    wpptr->r = r; wpptr->g = g; wpptr->b = b; wpptr->a = a; break;
735
                case 2:
736
                    wpptr->r = ((r+1)>>1); wpptr->g = ((g+1)>>1); wpptr->b = ((b+1)>>1); wpptr->a = ((a+1)>>1); break;
737
                case 3:
738
                    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;
739
                case 4:
740
                    wpptr->r = ((r+2)>>2); wpptr->g = ((g+2)>>2); wpptr->b = ((b+2)>>2); wpptr->a = ((a+2)>>2); break;
741
                default:
4680 terminx 742
                    EDUKE32_UNREACHABLE_SECTION(break);
109 terminx 743
                }
744
                //if (wpptr->a) wpptr->a = 255;
745
            }
746
        }
4639 terminx 747
 
748
        if (tsizx >= 0)
749
        {
750
            vec2_t tsizzle;
751
            vec2_t mnizzle = { x3, y3 };
752
 
753
            tsizzle.x = (tsizx+(1<<j)-1)>>j;
754
            tsizzle.y = (tsizy+(1<<j)-1)>>j;
755
            fixtransparency(pic, tsizzle, mnizzle, dameth);
756
        }
757
 
584 terminx 758
        if (j >= js)
759
        {
109 terminx 760
            if (doalloc&1)
761
                bglTexImage2D(GL_TEXTURE_2D,j-js,intexfmt,x3,y3,0,texfmt,GL_UNSIGNED_BYTE,pic); //loading 1st time
762
            else
763
                bglTexSubImage2D(GL_TEXTURE_2D,j-js,0,0,x3,y3,texfmt,GL_UNSIGNED_BYTE,pic); //overwrite old texture
764
        }
765
        x2 = x3; y2 = y3;
766
    }
5 Plagman 767
#endif
768
}
769
 
2141 helixhorne 770
 
2142 helixhorne 771
#if 0
2141 helixhorne 772
// TODO: make configurable
773
static int32_t tile_is_sky(int32_t tilenum)
774
{
2142 helixhorne 775
    return return (tilenum >= 78 /*CLOUDYOCEAN*/ && tilenum <= 99 /*REDSKY2*/);
2141 helixhorne 776
}
2142 helixhorne 777
#else
778
# define tile_is_sky(x) (0)
779
#endif
2141 helixhorne 780
 
5001 terminx 781
static void texture_setup(const int32_t dameth, int filter)
3041 helixhorne 782
{
4623 terminx 783
    const GLuint clamp_mode = glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP;
784
 
5001 terminx 785
    if (filter == -1)
786
        filter = gltexfiltermode;
3041 helixhorne 787
 
5001 terminx 788
    gltexfiltermode = clamp(gltexfiltermode, 0, NUMGLFILTERMODES - 1);
789
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfiltermodes[filter].mag);
790
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfiltermodes[filter].min);
791
 
792
#ifndef EDUKE32_GLES
4605 terminx 793
    if (glinfo.maxanisotropy > 1.f)
3041 helixhorne 794
    {
5001 terminx 795
        uint32_t i = (unsigned)Blrintf(glinfo.maxanisotropy);
4623 terminx 796
 
797
        if ((unsigned)glanisotropy > i)
798
            glanisotropy = i;
799
 
3041 helixhorne 800
        bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glanisotropy);
801
    }
5001 terminx 802
#endif
3041 helixhorne 803
 
4486 helixhorne 804
    if (!(dameth & DAMETH_CLAMPED))
3041 helixhorne 805
    {
4623 terminx 806
        bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, !tile_is_sky(dapic) ? GL_REPEAT : clamp_mode);
3041 helixhorne 807
        bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
808
    }
809
    else
810
    {
5001 terminx 811
        // For sprite textures, clamping looks better than wrapping
4623 terminx 812
        bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_mode);
813
        bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp_mode);
3041 helixhorne 814
    }
815
}
816
 
4491 helixhorne 817
void gloadtile_art(int32_t dapic, int32_t dapal, int32_t dashade, int32_t dameth, pthtyp *pth, int32_t doalloc)
5 Plagman 818
{
3146 helixhorne 819
    static int32_t fullbrightloadingpass = 0;
820
 
4639 terminx 821
    vec2_t siz, tsiz = tilesiz[dapic];
3146 helixhorne 822
 
584 terminx 823
    if (!glinfo.texnpot)
824
    {
5001 terminx 825
        for (siz.x = 1; siz.x < tsiz.x; siz.x += siz.x);
826
        for (siz.y = 1; siz.y < tsiz.y; siz.y += siz.y);
584 terminx 827
    }
828
    else
829
    {
4639 terminx 830
        if ((tsiz.x|tsiz.y) == 0)
831
            siz.x = siz.y = 1;
584 terminx 832
        else
833
        {
4639 terminx 834
            siz.x = tsiz.x;
835
            siz.y = tsiz.y;
109 terminx 836
        }
837
    }
5 Plagman 838
 
5001 terminx 839
    coltype *pic = (coltype *)Xmalloc(siz.x*siz.y*sizeof(coltype));
840
    char hasalpha = 0, hasfullbright = 0;
5 Plagman 841
 
109 terminx 842
    if (!waloff[dapic])
843
    {
844
        //Force invalid textures to draw something - an almost purely transparency texture
845
        //This allows the Z-buffer to be updated for mirrors (which are invalidated textures)
846
        pic[0].r = pic[0].g = pic[0].b = 0; pic[0].a = 1;
4639 terminx 847
        tsiz.x = tsiz.y = 1; hasalpha = 1;
109 terminx 848
    }
849
    else
850
    {
4898 terminx 851
        const int dofullbright = !(picanm[dapic].sf & PICANM_NOFULLBRIGHT_BIT);
3145 helixhorne 852
 
4898 terminx 853
        for (int y = 0; y < siz.y; y++)
109 terminx 854
        {
4898 terminx 855
            coltype *wpptr = &pic[y * siz.x];
856
            int32_t y2 = (y < tsiz.y) ? y : y - tsiz.y;
3146 helixhorne 857
 
4898 terminx 858
            for (int x = 0; x < siz.x; x++, wpptr++)
109 terminx 859
            {
4485 helixhorne 860
                int32_t dacol;
4639 terminx 861
                int32_t x2 = (x < tsiz.x) ? x : x-tsiz.x;
3146 helixhorne 862
 
4639 terminx 863
                if ((dameth & DAMETH_CLAMPED) && (x >= tsiz.x || y >= tsiz.y)) //Clamp texture
4485 helixhorne 864
                {
865
                    wpptr->r = wpptr->g = wpptr->b = wpptr->a = 0;
866
                    continue;
867
                }
3146 helixhorne 868
 
4639 terminx 869
                dacol = *(char *)(waloff[dapic]+x2*tsiz.y+y2);
3146 helixhorne 870
 
248 terminx 871
                if (!fullbrightloadingpass)
584 terminx 872
                {
873
                    // regular texture
3145 helixhorne 874
                    if (dacol > 239 && dacol != 255 && dofullbright)
248 terminx 875
                        hasfullbright = 1;
3146 helixhorne 876
 
248 terminx 877
                    wpptr->a = 255;
878
                }
3146 helixhorne 879
                else
584 terminx 880
                {
881
                    // texture with only fullbright areas
882
                    if (dacol < 240)    // regular colors
883
                    {
3146 helixhorne 884
                        wpptr->a = 0;
885
                        hasalpha = 1;
584 terminx 886
                    }
887
                    else   // fullbright
888
                    {
248 terminx 889
                        wpptr->a = 255;
890
                    }
891
                }
3146 helixhorne 892
 
248 terminx 893
                if (dacol != 255)
584 terminx 894
                {
3761 terminx 895
                    char *p = (char *)(palookup[dapal])+(int32_t)(dashade<<8);
896
                    dacol = (uint8_t)p[dacol];
248 terminx 897
                }
584 terminx 898
                else
899
                {
3146 helixhorne 900
                    wpptr->a = 0;
901
                    hasalpha = 1;
109 terminx 902
                }
3146 helixhorne 903
 
904
                bricolor((palette_t *)wpptr, dacol);
109 terminx 905
            }
906
        }
907
    }
5 Plagman 908
 
1762 terminx 909
    if (doalloc) bglGenTextures(1,(GLuint *)&pth->glpic); //# of textures (make OpenGL allocate structure)
109 terminx 910
    bglBindTexture(GL_TEXTURE_2D,pth->glpic);
5 Plagman 911
 
4639 terminx 912
    fixtransparency(pic,tsiz,siz,dameth);
4498 helixhorne 913
 
5001 terminx 914
    int32_t npoty = 0;
915
 
4639 terminx 916
    if (polymost_want_npotytex(dameth, siz.y) &&
917
            tsiz.x==siz.x && tsiz.y==siz.y)  // XXX
4498 helixhorne 918
    {
919
        const int32_t nextpoty = 1<<((picsiz[dapic]>>4)+1);
4639 terminx 920
        const int32_t ydif = nextpoty - siz.y;
4498 helixhorne 921
        coltype *paddedpic;
922
 
4639 terminx 923
        Bassert(ydif > 0 && ydif < siz.y);
4498 helixhorne 924
 
4639 terminx 925
        paddedpic = (coltype*) Xrealloc(pic, siz.x*nextpoty*sizeof(coltype));
4498 helixhorne 926
 
927
        pic = paddedpic;
4639 terminx 928
        Bmemcpy(&pic[siz.x*siz.y], pic, siz.x*ydif*sizeof(coltype));
929
        siz.y = tsiz.y = nextpoty;
4498 helixhorne 930
 
931
        npoty = PTH_NPOTWALL;
932
    }
933
 
5001 terminx 934
    uploadtexture(doalloc, siz.x, siz.y, hasalpha ? GL_RGBA : GL_RGB, GL_RGBA, pic, tsiz.x, tsiz.y, dameth);
5 Plagman 935
 
2978 helixhorne 936
    Bfree(pic);
5 Plagman 937
 
5001 terminx 938
    texture_setup(dameth, -1);
939
 
109 terminx 940
    pth->picnum = dapic;
941
    pth->palnum = dapal;
3761 terminx 942
    pth->shade = dashade;
109 terminx 943
    pth->effects = 0;
4498 helixhorne 944
    pth->flags = TO_PTH_CLAMPED(dameth) | (hasalpha*PTH_HASALPHA) | npoty;
109 terminx 945
    pth->hicr = NULL;
946
 
3146 helixhorne 947
    if (hasfullbright && !fullbrightloadingpass)
248 terminx 948
    {
3146 helixhorne 949
        // Load the ONLY texture that'll be assembled with the regular one to
950
        // make the final texture with fullbright pixels.
248 terminx 951
        fullbrightloadingpass = 1;
4485 helixhorne 952
 
4491 helixhorne 953
        pth->ofb = (pthtyp *)Xcalloc(1,sizeof(pthtyp));
4486 helixhorne 954
        pth->flags |= PTH_HASFULLBRIGHT;
235 Plagman 955
 
4491 helixhorne 956
        gloadtile_art(dapic, dapal, 0, dameth, pth->ofb, 1);
4485 helixhorne 957
 
248 terminx 958
        fullbrightloadingpass = 0;
959
    }
5 Plagman 960
}
961
 
3758 terminx 962
int32_t gloadtile_hi(int32_t dapic,int32_t dapalnum, int32_t facen, hicreplctyp *hicr,
2639 helixhorne 963
                            int32_t dameth, pthtyp *pth, int32_t doalloc, char effect)
5 Plagman 964
{
5001 terminx 965
    if (!hicr) return -1;
966
 
4485 helixhorne 967
    coltype *pic = NULL;
5 Plagman 968
 
5001 terminx 969
    char *picfil = NULL, *fn;
970
    int32_t picfillen, intexfmt = GL_RGBA, filh;
5 Plagman 971
 
1784 helixhorne 972
    int32_t startticks=0, willprint=0;
1754 helixhorne 973
 
584 terminx 974
    if (facen > 0)
975
    {
109 terminx 976
        if (!hicr->skybox) return -1;
977
        if (facen > 6) return -1;
978
        if (!hicr->skybox->face[facen-1]) return -1;
979
        fn = hicr->skybox->face[facen-1];
584 terminx 980
    }
981
    else
982
    {
109 terminx 983
        if (!hicr->filename) return -1;
984
        fn = hicr->filename;
985
    }
5 Plagman 986
 
4680 terminx 987
    if (EDUKE32_PREDICT_FALSE((filh = kopen4load(fn, 0)) < 0))
584 terminx 988
    {
921 terminx 989
        OSD_Printf("hightile: %s (pic %d) not found\n", fn, dapic);
4605 terminx 990
        return -2;
109 terminx 991
    }
4485 helixhorne 992
 
109 terminx 993
    picfillen = kfilelength(filh);
5 Plagman 994
 
109 terminx 995
    kclose(filh);       // FIXME: shouldn't have to do this. bug in cache1d.c
5 Plagman 996
 
5001 terminx 997
    char hasalpha = 255;
998
    texcacheheader cachead;
999
    int32_t gotcache = texcache_readtexheader(fn, picfillen+(dapalnum<<8), dameth, effect, &cachead, 0);
1000
    vec2_t siz ={ 0, 0 }, tsiz;
4485 helixhorne 1001
 
3758 terminx 1002
    if (gotcache && !texcache_loadtile(&cachead, &doalloc, pth))
584 terminx 1003
    {
4639 terminx 1004
        tsiz.x = cachead.xdim;
1005
        tsiz.y = cachead.ydim;
4486 helixhorne 1006
        hasalpha = (cachead.flags & CACHEAD_HASALPHA) ? 0 : 255;
584 terminx 1007
    }
1008
    else
1009
    {
2639 helixhorne 1010
        int32_t r, g, b;
4485 helixhorne 1011
        int32_t j, y;
2639 helixhorne 1012
 
3758 terminx 1013
        gotcache = 0;   // the compressed version will be saved to disk
5 Plagman 1014
 
109 terminx 1015
        if ((filh = kopen4load(fn, 0)) < 0) return -1;
5 Plagman 1016
 
4491 helixhorne 1017
        picfil = (char *)Xmalloc(picfillen+1);
4680 terminx 1018
        if (EDUKE32_PREDICT_FALSE(kread(filh, picfil, picfillen) != picfillen))
2069 helixhorne 1019
            initprintf("warning: didn't fully read %s\n", fn);
1020
        // prevent
1021
        // Conditional jump or move depends on uninitialised value(s)
1022
        //  at kpegrend (kplib.c:1655)
1023
        picfil[picfillen] = 0;
109 terminx 1024
        kclose(filh);
5 Plagman 1025
 
109 terminx 1026
        // tsizx/y = replacement texture's natural size
1027
        // xsiz/y = 2^x size of replacement
5 Plagman 1028
 
4639 terminx 1029
        kpgetdim(picfil,picfillen,&tsiz.x,&tsiz.y);
1030
        if (tsiz.x == 0 || tsiz.y == 0) { Bfree(picfil); return -1; }
5 Plagman 1031
 
4639 terminx 1032
        pth->siz.x = tsiz.x;
1033
        pth->siz.y = tsiz.y;
1034
 
584 terminx 1035
        if (!glinfo.texnpot)
1036
        {
4639 terminx 1037
            for (siz.x=1; siz.x<tsiz.x; siz.x+=siz.x);
1038
            for (siz.y=1; siz.y<tsiz.y; siz.y+=siz.y);
584 terminx 1039
        }
1040
        else
1041
        {
4639 terminx 1042
            siz.x = tsiz.x;
1043
            siz.y = tsiz.y;
109 terminx 1044
        }
4639 terminx 1045
        pic = (coltype *)Xcalloc(siz.x,siz.y*sizeof(coltype));
5 Plagman 1046
 
1754 helixhorne 1047
        startticks = getticks();
1048
 
5001 terminx 1049
        static coltype *lastpic = NULL;
1050
        static char *lastfn = NULL;
1051
        static int32_t lastsize = 0;
1052
 
1610 helixhorne 1053
        if (lastpic && lastfn && !Bstrcmp(lastfn,fn))
1054
        {
1784 helixhorne 1055
            willprint=1;
4639 terminx 1056
            Bmemcpy(pic, lastpic, siz.x*siz.y*sizeof(coltype));
1610 helixhorne 1057
        }
1058
        else
1059
        {
4639 terminx 1060
            if (kprender(picfil,picfillen,(intptr_t)pic,siz.x*sizeof(coltype),siz.x,siz.y)) { Bfree(picfil); Bfree(pic); return -2; }
1784 helixhorne 1061
            willprint=2;
665 terminx 1062
 
1610 helixhorne 1063
            if (hicprecaching)
1064
            {
1065
                lastfn = fn;  // careful...
1066
                if (!lastpic)
1067
                {
4639 terminx 1068
                    lastpic = (coltype *)Bmalloc(siz.x*siz.y*sizeof(coltype));
1069
                    lastsize = siz.x*siz.y;
1610 helixhorne 1070
                }
4639 terminx 1071
                else if (lastsize < siz.x*siz.y)
1610 helixhorne 1072
                {
1073
                    Bfree(lastpic);
4639 terminx 1074
                    lastpic = (coltype *)Bmalloc(siz.x*siz.y*sizeof(coltype));
1610 helixhorne 1075
                }
1076
                if (lastpic)
4639 terminx 1077
                    Bmemcpy(lastpic, pic, siz.x*siz.y*sizeof(coltype));
1610 helixhorne 1078
            }
1079
            else if (lastpic)
1080
            {
1081
                Bfree(lastpic); lastpic=NULL;
1082
                lastfn = NULL;
1083
                lastsize = 0;
1084
            }
1085
        }
1086
 
665 terminx 1087
        r=(glinfo.bgra)?hictinting[dapalnum].r:hictinting[dapalnum].b;
1088
        g=hictinting[dapalnum].g;
1089
        b=(glinfo.bgra)?hictinting[dapalnum].b:hictinting[dapalnum].r;
4639 terminx 1090
        for (y=0,j=0; y<tsiz.y; y++,j+=siz.x)
109 terminx 1091
        {
1092
            coltype tcol;
2639 helixhorne 1093
            char *cptr = britable[gammabrightness ? 0 : curbrightness];
4485 helixhorne 1094
            coltype *rpptr = &pic[j];
5 Plagman 1095
 
4485 helixhorne 1096
            int32_t x;
1097
 
4639 terminx 1098
            for (x=0; x<tsiz.x; x++)
109 terminx 1099
            {
1100
                tcol.b = cptr[rpptr[x].b];
1101
                tcol.g = cptr[rpptr[x].g];
1102
                tcol.r = cptr[rpptr[x].r];
4639 terminx 1103
                tcol.a = rpptr[x].a;
1104
                hasalpha &= rpptr[x].a;
5 Plagman 1105
 
4486 helixhorne 1106
                if (effect & HICTINT_GRAYSCALE)
584 terminx 1107
                {
4889 terminx 1108
                    tcol.g = tcol.r = tcol.b = (uint8_t) ((tcol.r * GRAYSCALE_COEFF_RED) + (tcol.g * GRAYSCALE_COEFF_GREEN) +
1109
                                                          (tcol.b * GRAYSCALE_COEFF_BLUE));
109 terminx 1110
                }
4486 helixhorne 1111
 
1112
                if (effect & HICTINT_INVERT)
584 terminx 1113
                {
109 terminx 1114
                    tcol.b = 255-tcol.b;
1115
                    tcol.g = 255-tcol.g;
1116
                    tcol.r = 255-tcol.r;
1117
                }
4486 helixhorne 1118
 
1119
                if (effect & HICTINT_COLORIZE)
665 terminx 1120
                {
1205 terminx 1121
                    tcol.b = min((int32_t)((tcol.b)*r)/64,255);
1122
                    tcol.g = min((int32_t)((tcol.g)*g)/64,255);
1123
                    tcol.r = min((int32_t)((tcol.r)*b)/64,255);
665 terminx 1124
                }
5 Plagman 1125
 
4639 terminx 1126
                rpptr[x] = tcol;
109 terminx 1127
            }
1128
        }
2639 helixhorne 1129
 
4486 helixhorne 1130
        if ((!(dameth & DAMETH_CLAMPED)) || facen) //Duplicate texture pixels (wrapping tricks for non power of 2 texture sizes)
109 terminx 1131
        {
4639 terminx 1132
            if (siz.x > tsiz.x) //Copy left to right
109 terminx 1133
            {
1205 terminx 1134
                int32_t *lptr = (int32_t *)pic;
4639 terminx 1135
                for (y=0; y<tsiz.y; y++,lptr+=siz.x)
1136
                    Bmemcpy(&lptr[tsiz.x],lptr,(siz.x-tsiz.x)<<2);
109 terminx 1137
            }
4639 terminx 1138
            if (siz.y > tsiz.y)  //Copy top to bottom
1139
                Bmemcpy(&pic[siz.x*tsiz.y],pic,(siz.y-tsiz.y)*siz.x<<2);
109 terminx 1140
        }
2639 helixhorne 1141
 
5001 terminx 1142
        int32_t texfmt;
1143
 
584 terminx 1144
        if (!glinfo.bgra)
1145
        {
5001 terminx 1146
            texfmt = GL_RGBA;
1147
 
4639 terminx 1148
            for (j=siz.x*siz.y-1; j>=0; j--)
109 terminx 1149
                swapchar(&pic[j].r, &pic[j].b);
584 terminx 1150
        }
1151
        else texfmt = GL_BGRA;
2639 helixhorne 1152
 
1527 terminx 1153
        Bfree(picfil); picfil = 0;
5 Plagman 1154
 
4639 terminx 1155
        if (tsiz.x>>r_downsize <= tilesiz[dapic].x || tsiz.y>>r_downsize <= tilesiz[dapic].y)
4486 helixhorne 1156
            hicr->flags |= (HICR_NOCOMPRESS + HICR_NOSAVE);
1336 terminx 1157
 
4486 helixhorne 1158
        if (glinfo.texcompr && glusetexcompr && !(hicr->flags & HICR_NOSAVE))
1761 terminx 1159
            intexfmt = (hasalpha == 255) ? GL_COMPRESSED_RGB_ARB : GL_COMPRESSED_RGBA_ARB;
109 terminx 1160
        else if (hasalpha == 255) intexfmt = GL_RGB;
5 Plagman 1161
 
2639 helixhorne 1162
        if ((doalloc&3)==1)
1163
            bglGenTextures(1, &pth->glpic); //# of textures (make OpenGL allocate structure)
109 terminx 1164
        bglBindTexture(GL_TEXTURE_2D,pth->glpic);
5 Plagman 1165
 
4639 terminx 1166
        fixtransparency(pic,tsiz,siz,dameth);
1167
        uploadtexture(doalloc,siz.x,siz.y,intexfmt,texfmt,pic,-1,tsiz.y,
4486 helixhorne 1168
                      dameth | DAMETH_HI | (hicr->flags & HICR_NOCOMPRESS ? DAMETH_NOCOMPRESS : 0));
109 terminx 1169
    }
5 Plagman 1170
 
109 terminx 1171
    // precalculate scaling parameters for replacement
584 terminx 1172
    if (facen > 0)
1173
    {
4639 terminx 1174
        pth->scale.x = (float)tsiz.x * (1.0f/64.f);
1175
        pth->scale.y = (float)tsiz.y * (1.0f/64.f);
584 terminx 1176
    }
1177
    else
1178
    {
4639 terminx 1179
        pth->scale.x = (float)tsiz.x / (float)tilesiz[dapic].x;
1180
        pth->scale.y = (float)tsiz.y / (float)tilesiz[dapic].y;
109 terminx 1181
    }
5 Plagman 1182
 
5001 terminx 1183
#ifdef EDUKE32_TOUCH_DEVICES
1184
    texture_setup(dameth, 5);
1185
#else
1186
    texture_setup(dameth, -1);
1187
#endif
2639 helixhorne 1188
 
4623 terminx 1189
    DO_FREE_AND_NULL(pic);
109 terminx 1190
 
4639 terminx 1191
    if (tsiz.x>>r_downsize <= tilesiz[dapic].x || tsiz.y>>r_downsize <= tilesiz[dapic].y)
1192
        hicr->flags |= HICR_NOCOMPRESS | HICR_NOSAVE;
1336 terminx 1193
 
109 terminx 1194
    pth->picnum = dapic;
1195
    pth->effects = effect;
4639 terminx 1196
    pth->flags = TO_PTH_CLAMPED(dameth) | PTH_HIGHTILE | ((facen>0) * PTH_SKYBOX) | ((hasalpha != 255) ? PTH_HASALPHA : 0);
109 terminx 1197
    pth->skyface = facen;
1198
    pth->hicr = hicr;
1199
 
4752 terminx 1200
    if (!gotcache && glinfo.texcompr && glusetexcompr && glusetexcache && !(hicr->flags & HICR_NOSAVE))
1201
    {
1202
        const int32_t nonpow2 = check_nonpow2(siz.x) || check_nonpow2(siz.y);
4485 helixhorne 1203
 
4752 terminx 1204
        // save off the compressed version
1205
        cachead.quality = (hicr->flags & HICR_NOCOMPRESS) ? 0 : r_downsize;
1206
        cachead.xdim = tsiz.x >> cachead.quality;
1207
        cachead.ydim = tsiz.y >> cachead.quality;
4485 helixhorne 1208
 
4752 terminx 1209
        // handle nocompress:
1210
        cachead.flags = nonpow2 * CACHEAD_NONPOW2 | (hasalpha != 255 ? CACHEAD_HASALPHA : 0) |
1211
                        (hicr->flags & HICR_NOCOMPRESS ? CACHEAD_NOCOMPRESS : 0);
4486 helixhorne 1212
 
4752 terminx 1213
        ///            OSD_Printf("Caching \"%s\"\n", fn);
1214
        texcache_writetex(fn, picfillen + (dapalnum << 8), dameth, effect, &cachead);
1754 helixhorne 1215
 
4752 terminx 1216
        if (willprint)
1217
        {
1218
            int32_t etime = getticks() - startticks;
1219
            if (etime >= MIN_CACHETIME_PRINT)
1220
                OSD_Printf("Load tile %4d: p%d-m%d-e%d %s... cached... %d ms\n", dapic, dapalnum, dameth, effect,
1221
                           willprint == 2 ? fn : "", etime);
1222
            willprint = 0;
109 terminx 1223
        }
4752 terminx 1224
        else
1225
            OSD_Printf("Cached \"%s\"\n", fn);
1226
    }
109 terminx 1227
 
1784 helixhorne 1228
    if (willprint)
1229
    {
1230
        int32_t etime = getticks()-startticks;
1231
        if (etime>=MIN_CACHETIME_PRINT)
1232
            OSD_Printf("Load tile %4d: p%d-m%d-e%d %s... %d ms\n", dapic, dapalnum, dameth, effect,
1233
                       willprint==2 ? fn : "", etime);
1234
    }
1754 helixhorne 1235
 
109 terminx 1236
    return 0;
5 Plagman 1237
}
1238
 
4623 terminx 1239
void polymost_setupdetailtexture(const int32_t texunits, const int32_t tex)
1240
{
1241
    bglActiveTextureARB(texunits);
1242
 
1243
    bglEnable(GL_TEXTURE_2D);
1244
    bglBindTexture(GL_TEXTURE_2D, tex);
1245
 
1246
    bglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1247
    bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
1248
 
1249
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1250
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1251
 
1252
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
1253
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
1254
 
1255
    bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
1256
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
1257
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1258
 
1259
    bglTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2.0f);
1260
 
1261
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1262
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1263
}
1264
 
1265
void polymost_setupglowtexture(const int32_t texunits, const int32_t tex)
1266
{
1267
    bglActiveTextureARB(texunits);
1268
 
1269
    bglEnable(GL_TEXTURE_2D);
1270
    bglBindTexture(GL_TEXTURE_2D, tex);
1271
 
1272
    bglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1273
    bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
1274
 
1275
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1276
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
1277
 
1278
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
1279
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
1280
 
1281
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
1282
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA);
1283
 
1284
    bglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
1285
    bglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
1286
    bglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
1287
 
1288
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
1289
    bglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
1290
}
5 Plagman 1291
#endif
1292
 
109 terminx 1293
//(dpx,dpy) specifies an n-sided polygon. The polygon must be a convex clockwise loop.
1294
//    n must be <= 8 (assume clipping can double number of vertices)
1295
//method: 0:solid, 1:masked(255 is transparent), 2:transluscent #1, 3:transluscent #2
1296
//    +4 means it's a sprite, so wraparound isn't needed
3543 hendricks2 1297
 
1298
// drawpoly's hack globals
1205 terminx 1299
static int32_t pow2xsplit = 0, skyclamphack = 0;
3543 hendricks2 1300
static float alpha = 0.f;
5 Plagman 1301
 
4640 terminx 1302
static inline pthtyp *our_texcache_fetch(int32_t dameth)
4010 helixhorne 1303
{
1304
    // r_usetileshades 1 is TX's method.
4640 terminx 1305
    return texcache_fetch(globalpicnum, globalpal, getpalookup((r_usetileshades == 1) ? globvis>>3 : 0, globalshade), dameth);
4010 helixhorne 1306
}
1307
 
4671 terminx 1308
static void drawpoly(vec2f_t *dpxy, int32_t n, int32_t method)
5 Plagman 1309
{
4623 terminx 1310
    const int32_t method_ = method;
1311
    int32_t i, j, k;
1312
    vec2_t tsiz;
1313
    float f, r, ox, oy, oz, ox2, oy2, oz2, dd[16], uu[16], vv[16], px[16], py[16];
4406 helixhorne 1314
 
2014 helixhorne 1315
#ifdef YAX_ENABLE
1316
    if (g_nodraw) return;
1317
#endif
5 Plagman 1318
 
4605 terminx 1319
    if (method == -1 || (uint32_t)globalpicnum >= MAXTILES) return;
1320
 
109 terminx 1321
    if (n == 3)
1322
    {
4671 terminx 1323
        if ((dpxy[0].x-dpxy[1].x) * (dpxy[2].y-dpxy[1].y) >=
1324
            (dpxy[2].x-dpxy[1].x) * (dpxy[0].y-dpxy[1].y)) return; //for triangle
109 terminx 1325
    }
1326
    else
1327
    {
1328
        f = 0; //f is area of polygon / 2
4671 terminx 1329
        for (i=n-2,j=n-1,k=0; k<n; i=j,j=k,k++)
1330
            f += (dpxy[i].x-dpxy[k].x)*dpxy[j].y;
109 terminx 1331
        if (f <= 0) return;
1332
    }
5 Plagman 1333
 
109 terminx 1334
    //Load texture (globalpicnum)
1335
    setgotpic(globalpicnum);
4623 terminx 1336
    tsiz = tilesiz[globalpicnum];
1337
 
355 terminx 1338
    if (palookup[globalpal] == NULL)
1339
        globalpal = 0;
109 terminx 1340
    if (!waloff[globalpicnum])
1341
    {
1342
        loadtile(globalpicnum);
1343
        if (!waloff[globalpicnum])
1344
        {
3784 terminx 1345
            if (getrendermode() < REND_POLYMOST) return;
4623 terminx 1346
            tsiz.x = tsiz.y = 1;
1347
            method = 1; //Hack to update Z-buffer for invalid mirror textures
109 terminx 1348
        }
1349
    }
5 Plagman 1350
 
4605 terminx 1351
    j = 0;
1352
 
4623 terminx 1353
    for (i=0; i<n; i++)
109 terminx 1354
    {
4671 terminx 1355
        ox = dpxy[i].x-ghalfx;
1356
        oy = dpxy[i].y-ghoriz;
4623 terminx 1357
        oz = ghalfx;
5 Plagman 1358
 
4623 terminx 1359
        //Up/down rotation
1360
        ox2 = ox;
1361
        oy2 = oy*gchang - oz*gshang;
1362
        oz2 = oy*gshang + oz*gchang;
5 Plagman 1363
 
4623 terminx 1364
        //Tilt rotation
1365
        ox = ox2*gctang - oy2*gstang;
1366
        oy = ox2*gstang + oy2*gctang;
1367
        oz = oz2;
5 Plagman 1368
 
4623 terminx 1369
        r = ghalfx / oz;
5 Plagman 1370
 
4671 terminx 1371
        dd[j] = (dpxy[i].x*gdx + dpxy[i].y*gdy + gdo)*r;
1372
        uu[j] = (dpxy[i].x*gux + dpxy[i].y*guy + guo)*r;
1373
        vv[j] = (dpxy[i].x*gvx + dpxy[i].y*gvy + gvo)*r;
5 Plagman 1374
 
4623 terminx 1375
        px[j] = ox*r + ghalfx;
1376
        py[j] = oy*r + ghoriz;
1377
        if ((!j) || (px[j] != px[j-1]) || (py[j] != py[j-1])) j++;
109 terminx 1378
    }
4623 terminx 1379
 
109 terminx 1380
    while ((j >= 3) && (px[j-1] == px[0]) && (py[j-1] == py[0])) j--;
1381
    if (j < 3) return;
5 Plagman 1382
 
1383
#ifdef USE_OPENGL
3784 terminx 1384
    if (getrendermode() >= REND_POLYMOST)
109 terminx 1385
    {
4605 terminx 1386
        float hackscx = 1.f, hackscy = 1.f;
4406 helixhorne 1387
        int32_t texunits = GL_TEXTURE0_ARB;
4605 terminx 1388
        int32_t xx, yy;
5 Plagman 1389
 
4623 terminx 1390
        int32_t jj = j;
1391
 
4489 helixhorne 1392
        if (skyclamphack) method |= DAMETH_CLAMPED;
5001 terminx 1393
        pthtyp *pth = our_texcache_fetch(method&(~3));
244 Plagman 1394
 
1920 helixhorne 1395
        if (!pth)
1396
        {
1397
            if (editstatus)
1398
            {
1399
                Bsprintf(ptempbuf, "pth==NULL! (bad pal?) pic=%d pal=%d", globalpicnum, globalpal);
1400
                polymost_printext256(8,8, editorcolors[15],editorcolors[5], ptempbuf, 0);
1401
            }
1402
            return;
1403
        }
1404
 
4623 terminx 1405
        if (pth->flags & PTH_HASFULLBRIGHT && r_fullbrights && indrawroomsandmasks)
1406
        {
1407
            if (!fullbrightdrawingpass)
1408
                fullbrightdrawingpass = 1;
1409
            else if (fullbrightdrawingpass == 2)
1410
                pth = pth->ofb;
1411
        }
244 Plagman 1412
 
3741 Plagman 1413
        // If we aren't rendmode 3, we're in Polymer, which means this code is
1414
        // used for rotatesprite only. Polymer handles all the material stuff,
1415
        // just submit the geometry and don't mess with textures.
3784 terminx 1416
        if (getrendermode() == REND_POLYMOST)
3741 Plagman 1417
        {
1418
            bglBindTexture(GL_TEXTURE_2D, pth ? pth->glpic : 0);
5 Plagman 1419
 
3741 Plagman 1420
            if (srepeat)
1421
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
1422
            if (trepeat)
1423
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
1424
        }
590 plagman 1425
 
504 Plagman 1426
        // texture scale by parkar request
4680 terminx 1427
        if (pth && pth->hicr && !drawingskybox && ((pth->hicr->scale.x != 1.0f) || (pth->hicr->scale.y != 1.0f)))
504 Plagman 1428
        {
1429
            bglMatrixMode(GL_TEXTURE);
1430
            bglLoadIdentity();
4680 terminx 1431
            bglScalef(pth->hicr->scale.x, pth->hicr->scale.y, 1.0f);
504 Plagman 1432
            bglMatrixMode(GL_MODELVIEW);
1433
        }
1434
 
5001 terminx 1435
#ifndef EDUKE32_GLES
504 Plagman 1436
        // detail texture
5001 terminx 1437
        pthtyp *detailpth = NULL;
4605 terminx 1438
        if (r_detailmapping && usehightile && !drawingskybox && hicfindsubst(globalpicnum, DETAILPAL))
3761 terminx 1439
            detailpth = texcache_fetch(globalpicnum, DETAILPAL, 0, method&(~3));
459 Plagman 1440
 
1226 plagman 1441
        if (detailpth && detailpth->hicr && (detailpth->hicr->palnum == DETAILPAL))
459 Plagman 1442
        {
4623 terminx 1443
            polymost_setupdetailtexture(++texunits, detailpth ? detailpth->glpic : 0);
459 Plagman 1444
 
4680 terminx 1445
            f = detailpth ? detailpth->hicr->scale.x : 1.f;
459 Plagman 1446
 
497 Plagman 1447
            bglMatrixMode(GL_TEXTURE);
1448
            bglLoadIdentity();
512 Plagman 1449
 
4680 terminx 1450
            if (pth && pth->hicr && ((pth->hicr->scale.x != 1.0f) || (pth->hicr->scale.y != 1.0f)))
1451
                bglScalef(pth->hicr->scale.x, pth->hicr->scale.y, 1.0f);
512 Plagman 1452
 
4680 terminx 1453
            if (detailpth && detailpth->hicr && ((detailpth->hicr->scale.x != 1.0f) || (detailpth->hicr->scale.y != 1.0f)))
1454
                bglScalef(detailpth->hicr->scale.x, detailpth->hicr->scale.y, 1.0f);
512 Plagman 1455
 
497 Plagman 1456
            bglMatrixMode(GL_MODELVIEW);
459 Plagman 1457
        }
1458
 
504 Plagman 1459
        // glow texture
5001 terminx 1460
        pthtyp *glowpth = NULL;
4605 terminx 1461
        if (r_glowmapping && usehightile && !drawingskybox && hicfindsubst(globalpicnum, GLOWPAL))
3761 terminx 1462
            glowpth = texcache_fetch(globalpicnum, GLOWPAL, 0, method&(~3));
497 Plagman 1463
 
1226 plagman 1464
        if (glowpth && glowpth->hicr && (glowpth->hicr->palnum == GLOWPAL))
4623 terminx 1465
            polymost_setupglowtexture(++texunits, glowpth ? glowpth->glpic : 0);
5001 terminx 1466
#endif
497 Plagman 1467
 
4486 helixhorne 1468
        if (pth && (pth->flags & PTH_HIGHTILE))
109 terminx 1469
        {
4639 terminx 1470
            hackscx = pth->scale.x;
1471
            hackscy = pth->scale.y;
1472
            tsiz.x = pth->siz.x;
1473
            tsiz.y = pth->siz.y;
109 terminx 1474
        }
5 Plagman 1475
 
4623 terminx 1476
        xx = tsiz.x;
1477
        yy = tsiz.y;
4605 terminx 1478
 
584 terminx 1479
        if (!glinfo.texnpot)
1480
        {
4623 terminx 1481
            for (xx=1; xx<tsiz.x; xx+=xx)
2416 helixhorne 1482
            {
1483
                /* do nothing */
1484
            }
4623 terminx 1485
            for (yy=1; yy<tsiz.y; yy+=yy)
2416 helixhorne 1486
            {
1487
                /* do nothing */
1488
            }
584 terminx 1489
        }
5 Plagman 1490
 
4605 terminx 1491
        ox2 = 1.0f/xx;
1492
        oy2 = 1.0f/yy;
1493
 
584 terminx 1494
        if ((!(method&3)) && (!fullbrightdrawingpass))
1495
        {
475 Plagman 1496
            bglDisable(GL_BLEND);
1229 terminx 1497
            bglDisable(GL_ALPHA_TEST);
584 terminx 1498
        }
1499
        else
1500
        {
4605 terminx 1501
            float al = 0.f; // PLAG : default alphacut was 0.32 before goodalpha
1502
            if (pth && pth->hicr && pth->hicr->alphacut >= 0.f) al = pth->hicr->alphacut;
109 terminx 1503
            if (alphahackarray[globalpicnum])
1504
                al=alphahackarray[globalpicnum];
4605 terminx 1505
            if (!waloff[globalpicnum]) al = 0.f;        // invalid textures ignore the alpha cutoff settings
1229 terminx 1506
            bglEnable(GL_BLEND);
109 terminx 1507
            bglEnable(GL_ALPHA_TEST);
1508
            bglAlphaFunc(GL_GREATER,al);
1509
        }
5 Plagman 1510
 
109 terminx 1511
        {
1512
            float pc[4];
3763 terminx 1513
 
4394 helixhorne 1514
#ifdef POLYMER
4605 terminx 1515
            if (getrendermode() == REND_POLYMER && pr_artmapping && polymer_eligible_for_artmap(globalpicnum, pth))
4394 helixhorne 1516
                pc[0] = pc[1] = pc[2] = 1.0f;
1517
            else
1518
#endif
1519
                pc[0] = pc[1] = pc[2] = getshadefactor(globalshade);
1520
 
3543 hendricks2 1521
            // spriteext full alpha control
4623 terminx 1522
            pc[3] = float_trans[method&3] * (1.f - alpha);
3543 hendricks2 1523
 
109 terminx 1524
            // tinting happens only to hightile textures, and only if the texture we're
1525
            // rendering isn't for the same palette as what we asked for
4486 helixhorne 1526
            if (!(hictinting[globalpal].f & HICTINT_COLORIZE))
943 terminx 1527
            {
4486 helixhorne 1528
                if (pth && (pth->flags & PTH_HIGHTILE))
384 terminx 1529
                {
5055 hendricks2 1530
                    if (pth->palnum != globalpal || (hictinting[globalpal].f & HICTINT_APPLYOVERALTPAL))
4487 helixhorne 1531
                        hictinting_apply(pc, globalpal);
1532
 
1533
                    if (have_basepal_tint())
1534
                        hictinting_apply(pc, MAXPALOOKUPS-1);
384 terminx 1535
                }
943 terminx 1536
                // hack: this is for drawing the 8-bit crosshair recolored in polymost
4486 helixhorne 1537
                else if (hictinting[globalpal].f & HICTINT_USEONART)
4487 helixhorne 1538
                    hictinting_apply(pc, globalpal);
943 terminx 1539
            }
384 terminx 1540
 
109 terminx 1541
            bglColor4f(pc[0],pc[1],pc[2],pc[3]);
1542
        }
5 Plagman 1543
 
109 terminx 1544
        //Hack for walls&masked walls which use textures that are not a power of 2
4623 terminx 1545
        if ((pow2xsplit) && (tsiz.x != xx))
109 terminx 1546
        {
4623 terminx 1547
            int32_t nn, ix0, ix1;
5 Plagman 1548
 
4623 terminx 1549
            float ngdx = 0.f, ngdy = 0.f, ngdo = 0.f, ngux = 0.f, nguy = 0.f, nguo = 0.f, uoffs;
1550
            float ngvx = 0.f, ngvy = 0.f, ngvo = 0.f, dp, up, vp, du0 = 0.f, du1 = 0.f, dui, duj;
1551
 
1552
            ox = py[1]-py[2]; oy = py[2]-py[0]; oz = py[0]-py[1];
1553
            r = 1.f / (ox*px[0] + oy*px[1] + oz*px[2]);
1554
            ngdx = (ox*dd[0] + oy*dd[1] + oz*dd[2])*r;
1555
            ngux = (ox*uu[0] + oy*uu[1] + oz*uu[2])*r;
1556
            ngvx = (ox*vv[0] + oy*vv[1] + oz*vv[2])*r;
1557
            ox = px[2]-px[1]; oy = px[0]-px[2]; oz = px[1]-px[0];
1558
            ngdy = (ox*dd[0] + oy*dd[1] + oz*dd[2])*r;
1559
            nguy = (ox*uu[0] + oy*uu[1] + oz*uu[2])*r;
1560
            ngvy = (ox*vv[0] + oy*vv[1] + oz*vv[2])*r;
1561
            ox = px[0]-0.5f; oy = py[0]-0.5f; //.5 centers texture nicely
1562
            ngdo = dd[0] - ox*ngdx - oy*ngdy;
1563
            nguo = uu[0] - ox*ngux - oy*nguy;
1564
            ngvo = vv[0] - ox*ngvx - oy*ngvy;
1565
 
109 terminx 1566
            ngux *= hackscx; nguy *= hackscx; nguo *= hackscx;
1567
            ngvx *= hackscy; ngvy *= hackscy; ngvo *= hackscy;
4623 terminx 1568
            uoffs = ((float)(xx-tsiz.x)*0.5f);
109 terminx 1569
            ngux -= ngdx*uoffs;
1570
            nguy -= ngdy*uoffs;
1571
            nguo -= ngdo*uoffs;
5 Plagman 1572
 
109 terminx 1573
            //Find min&max u coordinates (du0...du1)
4623 terminx 1574
            for (i=0; i<jj; i++)
109 terminx 1575
            {
1576
                ox = px[i]; oy = py[i];
1577
                f = (ox*ngux + oy*nguy + nguo) / (ox*ngdx + oy*ngdy + ngdo);
1578
                if (!i) { du0 = du1 = f; continue; }
1579
                if (f < du0) du0 = f;
1580
                else if (f > du1) du1 = f;
1581
            }
5 Plagman 1582
 
4623 terminx 1583
            f = 1.0f/tsiz.x;
4605 terminx 1584
            ix0 = Blrintf(floorf(du0*f));
1585
            ix1 = Blrintf(floorf(du1*f));
1229 terminx 1586
            for (; ix0<=ix1; ix0++)
109 terminx 1587
            {
4623 terminx 1588
                du0 = (float)(ix0*tsiz.x);   // + uoffs;
1589
                du1 = (float)((ix0+1)*tsiz.x); // + uoffs;
5 Plagman 1590
 
109 terminx 1591
                i = 0; nn = 0;
1592
                duj = (px[i]*ngux + py[i]*nguy + nguo) / (px[i]*ngdx + py[i]*ngdy + ngdo);
1593
                do
1594
                {
4623 terminx 1595
                    j = i+1; if (j == jj) j = 0;
5 Plagman 1596
 
4605 terminx 1597
                    dui = duj;
1598
                    duj = (px[j]*ngux + py[j]*nguy + nguo) / (px[j]*ngdx + py[j]*ngdy + ngdo);
5 Plagman 1599
 
4605 terminx 1600
                    if ((du0 <= dui) && (dui <= du1))
1601
                    {
1602
                        uu[nn] = px[i];
1603
                        vv[nn] = py[i];
1604
                        nn++;
1605
                    }
1606
 
1607
                    //ox*(ngux-ngdx*du1) + oy*(nguy-ngdy*du1) + (nguo-ngdo*du1) = 0
1608
                    //(px[j]-px[i])*f + px[i] = ox
1609
                    //(py[j]-py[i])*f + py[i] = oy
1610
 
1611
                    ///Solve for f
1612
                    //((px[j]-px[i])*f + px[i])*(ngux-ngdx*du1) +
1613
                    //((py[j]-py[i])*f + py[i])*(nguy-ngdy*du1) + (nguo-ngdo*du1) = 0
1614
 
1615
#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)); \
1616
                                        uu[nn] = (px[j]-px[i])*f + px[i]; vv[nn] = (py[j]-py[i])*f + py[i]; nn++; } while (0)
1617
 
109 terminx 1618
                    if (duj <= dui)
1619
                    {
1620
                        if ((du1 < duj) != (du1 < dui))
4605 terminx 1621
                            DRAWPOLY_MATH_BULLSHIT(du1);
109 terminx 1622
                        if ((du0 < duj) != (du0 < dui))
4605 terminx 1623
                            DRAWPOLY_MATH_BULLSHIT(du0);
109 terminx 1624
                    }
1625
                    else
1626
                    {
1627
                        if ((du0 < duj) != (du0 < dui))
4605 terminx 1628
                            DRAWPOLY_MATH_BULLSHIT(du0);
109 terminx 1629
                        if ((du1 < duj) != (du1 < dui))
4605 terminx 1630
                            DRAWPOLY_MATH_BULLSHIT(du1);
109 terminx 1631
                    }
1632
                    i = j;
4605 terminx 1633
 
1634
#undef DRAWPOLY_MATH_BULLSHIT
1635
 
584 terminx 1636
                }
1637
                while (i);
4605 terminx 1638
 
109 terminx 1639
                if (nn < 3) continue;
5 Plagman 1640
 
109 terminx 1641
                bglBegin(GL_TRIANGLE_FAN);
1229 terminx 1642
                for (i=0; i<nn; i++)
109 terminx 1643
                {
1644
                    ox = uu[i]; oy = vv[i];
1645
                    dp = ox*ngdx + oy*ngdy + ngdo;
1646
                    up = ox*ngux + oy*nguy + nguo;
1647
                    vp = ox*ngvx + oy*ngvy + ngvo;
4605 terminx 1648
                    r = 1.f/dp;
497 Plagman 1649
                    if (texunits > GL_TEXTURE0_ARB)
459 Plagman 1650
                    {
497 Plagman 1651
                        j = GL_TEXTURE0_ARB;
1652
                        while (j <= texunits)
4605 terminx 1653
                            bglMultiTexCoord2fARB(j++, (up*r-du0+uoffs)*ox2,vp*r*oy2);
459 Plagman 1654
                    }
1655
                    else
4605 terminx 1656
                        bglTexCoord2f((up*r-du0+uoffs)*ox2,vp*r*oy2);
1657
                    bglVertex3f((ox-ghalfx)*r*grhalfxdown10x,(ghoriz-oy)*r*grhalfxdown10,r*(1.f/1024.f));
109 terminx 1658
                }
1659
                bglEnd();
1660
            }
1661
        }
1662
        else
1663
        {
1664
            ox2 *= hackscx; oy2 *= hackscy;
1665
            bglBegin(GL_TRIANGLE_FAN);
4623 terminx 1666
            for (i=0; i<jj; i++)
109 terminx 1667
            {
4605 terminx 1668
                r = 1.f/dd[i];
497 Plagman 1669
                if (texunits > GL_TEXTURE0_ARB)
459 Plagman 1670
                {
497 Plagman 1671
                    j = GL_TEXTURE0_ARB;
1672
                    while (j <= texunits)
4605 terminx 1673
                        bglMultiTexCoord2fARB(j++, uu[i]*r*ox2,vv[i]*r*oy2);
459 Plagman 1674
                }
497 Plagman 1675
                else
4605 terminx 1676
                    bglTexCoord2f(uu[i]*r*ox2,vv[i]*r*oy2);
1677
                bglVertex3f((px[i]-ghalfx)*r*grhalfxdown10x,(ghoriz-py[i])*r*grhalfxdown10,r*(1.f/1024.f));
109 terminx 1678
            }
1679
            bglEnd();
1680
        }
497 Plagman 1681
 
504 Plagman 1682
        while (texunits >= GL_TEXTURE0_ARB)
461 Plagman 1683
        {
666 plagman 1684
            bglActiveTextureARB(texunits);
504 Plagman 1685
            bglMatrixMode(GL_TEXTURE);
1686
            bglLoadIdentity();
1687
            bglMatrixMode(GL_MODELVIEW);
1688
            if (texunits > GL_TEXTURE0_ARB)
497 Plagman 1689
            {
501 Plagman 1690
                bglTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0f);
497 Plagman 1691
                bglDisable(GL_TEXTURE_2D);
1692
            }
666 plagman 1693
            texunits--;
461 Plagman 1694
        }
497 Plagman 1695
 
3784 terminx 1696
        if (getrendermode() == REND_POLYMOST)
3741 Plagman 1697
        {
1698
            if (srepeat)
1699
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
1700
            if (trepeat)
1701
                bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
1702
        }
590 plagman 1703
 
248 terminx 1704
        if (fullbrightdrawingpass == 1) // tile has fullbright colors ?
1705
        {
3146 helixhorne 1706
            int32_t shadeforfullbrightpass = globalshade; // save the current shade
248 terminx 1707
            fullbrightdrawingpass = 2;
388 terminx 1708
            globalshade = -128; // fullbright
621 plagman 1709
            bglDisable(GL_FOG);
4671 terminx 1710
            drawpoly(dpxy, n, method_); // draw them afterwards, then. :)
5001 terminx 1711
            if (!nofog) bglEnable(GL_FOG);
248 terminx 1712
            globalshade = shadeforfullbrightpass;
1713
            fullbrightdrawingpass = 0;
1714
        }
109 terminx 1715
        return;
1716
    }
5 Plagman 1717
#endif
1718
}
1719
 
2002 helixhorne 1720
 
4898 terminx 1721
static inline void vsp_finalize_init(vsptyp *vsp, int32_t vcnt)
2002 helixhorne 1722
{
1723
    int32_t i;
1724
 
1725
    for (i=0; i<vcnt; i++)
1726
    {
1727
        vsp[i].cy[1] = vsp[i+1].cy[0]; vsp[i].ctag = i;
1728
        vsp[i].fy[1] = vsp[i+1].fy[0]; vsp[i].ftag = i;
1729
        vsp[i].n = i+1; vsp[i].p = i-1;
1730
//        vsp[i].tag = -1;
1731
    }
1732
    vsp[vcnt-1].n = 0; vsp[0].p = vcnt-1;
1733
 
1734
    //VSPMAX-1 is dummy empty node
1735
    for (i=vcnt; i<VSPMAX; i++) { vsp[i].n = i+1; vsp[i].p = i-1; }
1736
    vsp[VSPMAX-1].n = vcnt; vsp[vcnt].p = VSPMAX-1;
1737
}
1738
 
1739
static inline void vsdel(vsptyp *vsp, int32_t i)
5 Plagman 1740
{
109 terminx 1741
    //Delete i
4623 terminx 1742
    vsp[vsp[i].n].p = vsp[i].p;
1743
    vsp[vsp[i].p].n = vsp[i].n;
5 Plagman 1744
 
109 terminx 1745
    //Add i to empty list
1746
    vsp[i].n = vsp[VSPMAX-1].n;
1747
    vsp[i].p = VSPMAX-1;
1748
    vsp[vsp[VSPMAX-1].n].p = i;
1749
    vsp[VSPMAX-1].n = i;
5 Plagman 1750
}
1751
 
2002 helixhorne 1752
static inline int32_t vsinsaft(vsptyp *vsp, int32_t i)
5 Plagman 1753
{
109 terminx 1754
    //i = next element from empty list
4623 terminx 1755
    int32_t r = vsp[VSPMAX-1].n;
109 terminx 1756
    vsp[vsp[r].n].p = VSPMAX-1;
1757
    vsp[VSPMAX-1].n = vsp[r].n;
5 Plagman 1758
 
109 terminx 1759
    vsp[r] = vsp[i]; //copy i to r
5 Plagman 1760
 
109 terminx 1761
    //insert r after i
1762
    vsp[r].p = i; vsp[r].n = vsp[i].n;
1763
    vsp[vsp[i].n].p = r; vsp[i].n = r;
5 Plagman 1764
 
109 terminx 1765
    return(r);
5 Plagman 1766
}
1767
 
1205 terminx 1768
static int32_t domostpolymethod = 0;
5 Plagman 1769
 
584 terminx 1770
void domost(float x0, float y0, float x1, float y1)
5 Plagman 1771
{
4675 terminx 1772
    vec2f_t dpxy[4], n0, n1;
1773
    float slop, dx;
2002 helixhorne 1774
    float spx[4], /*spy[4],*/ cy[2], cv[2];
4675 terminx 1775
    int32_t i, k, z, vcnt = 0, scnt, newi, dir = 0, spt[4];
5 Plagman 1776
 
3555 hendricks2 1777
    alpha = 0.f;
1778
 
109 terminx 1779
    if (x0 < x1)
1780
    {
1781
        dir = 1; //clip dmost (floor)
4623 terminx 1782
        y0 -= .01f;
1783
        y1 -= .01f;
109 terminx 1784
    }
1785
    else
1786
    {
1787
        if (x0 == x1) return;
4605 terminx 1788
        swapfloat(&x0, &x1);
1789
        swapfloat(&y0, &y1);
4623 terminx 1790
        //dir = 0; //clip umost (ceiling)
109 terminx 1791
        //y0 += .01; y1 += .01; //necessary?
1792
    }
5 Plagman 1793
 
109 terminx 1794
    slop = (y1-y0)/(x1-x0);
1229 terminx 1795
    for (i=vsp[0].n; i; i=newi)
109 terminx 1796
    {
4675 terminx 1797
        newi = vsp[i].n; n0.x = vsp[i].x; n1.x = vsp[newi].x;
1798
        if ((x0 >= n1.x) || (n0.x >= x1) || (vsp[i].ctag <= 0)) continue;
1799
        dx = n1.x-n0.x;
109 terminx 1800
        cy[0] = vsp[i].cy[0]; cv[0] = vsp[i].cy[1]-cy[0];
1801
        cy[1] = vsp[i].fy[0]; cv[1] = vsp[i].fy[1]-cy[1];
5 Plagman 1802
 
109 terminx 1803
        scnt = 0;
5 Plagman 1804
 
109 terminx 1805
        //Test if left edge requires split (x0,y0) (nx0,cy(0)),<dx,cv(0)>
4675 terminx 1806
        if ((x0 > n0.x) && (x0 < n1.x))
109 terminx 1807
        {
4675 terminx 1808
            const float t = (x0-n0.x)*cv[dir] - (y0-cy[dir])*dx;
4623 terminx 1809
            if (((!dir) && (t < 0.f)) || ((dir) && (t > 0.f)))
2002 helixhorne 1810
                { spx[scnt] = x0; /*spy[scnt] = y0;*/ spt[scnt] = -1; scnt++; }
109 terminx 1811
        }
5 Plagman 1812
 
4675 terminx 1813
        //Test for intersection on umost (0) and dmost (1)
1814
 
109 terminx 1815
        {
4690 terminx 1816
            const float d[2] ={
4675 terminx 1817
                ((y0-y1) * dx) - ((x0-x1) * cv[0]),
4690 terminx 1818
                ((y0-y1) * dx) - ((x0-x1) * cv[1])
4675 terminx 1819
            };
4623 terminx 1820
 
4690 terminx 1821
            const float n[2] ={
4675 terminx 1822
                ((y0-cy[0]) * dx) - ((x0-n0.x) * cv[0]),
4690 terminx 1823
                ((y0-cy[1]) * dx) - ((x0-n0.x) * cv[1])
4675 terminx 1824
            };
4671 terminx 1825
 
4690 terminx 1826
            const float fnx[2] ={
4675 terminx 1827
                x0 + ((n[0]/d[0]) * (x1-x0)),
4690 terminx 1828
                x0 + ((n[1]/d[1]) * (x1-x0))
4675 terminx 1829
            };
1830
 
1831
            if ((Bfabsf(d[0]) > Bfabsf(n[0])) && (d[0] * n[0] >= 0.f) && (fnx[0] > n0.x) && (fnx[0] < n1.x))
1832
                spx[scnt] = fnx[0], spt[scnt++] = 0;
1833
 
1834
            if ((Bfabsf(d[1]) > Bfabsf(n[1])) && (d[1] * n[1] >= 0.f) && (fnx[1] > n0.x) && (fnx[1] < n1.x))
1835
                spx[scnt] = fnx[1], spt[scnt++] = 1;
109 terminx 1836
        }
5 Plagman 1837
 
109 terminx 1838
        //Nice hack to avoid full sort later :)
1839
        if ((scnt >= 2) && (spx[scnt-1] < spx[scnt-2]))
1840
        {
4605 terminx 1841
            swapfloat(&spx[scnt-1], &spx[scnt-2]);
1842
            swaplong(&spt[scnt-1], &spt[scnt-2]);
2002 helixhorne 1843
            /* f = spy[scnt-1]; spy[scnt-1] = spy[scnt-2]; spy[scnt-2] = f; */
109 terminx 1844
        }
5 Plagman 1845
 
109 terminx 1846
        //Test if right edge requires split
4675 terminx 1847
        if ((x1 > n0.x) && (x1 < n1.x))
109 terminx 1848
        {
4675 terminx 1849
            const float t = (x1-n0.x)*cv[dir] - (y1-cy[dir])*dx;
109 terminx 1850
            if (((!dir) && (t < 0)) || ((dir) && (t > 0)))
2002 helixhorne 1851
                { spx[scnt] = x1; /* spy[scnt] = y1; */ spt[scnt] = -1; scnt++; }
109 terminx 1852
        }
5 Plagman 1853
 
109 terminx 1854
        vsp[i].tag = vsp[newi].tag = -1;
4671 terminx 1855
 
1856
        dx = 1.f/dx;
1857
 
1229 terminx 1858
        for (z=0; z<=scnt; z++,i=vcnt)
109 terminx 1859
        {
4898 terminx 1860
            float t;
4671 terminx 1861
 
4675 terminx 1862
            if (z == scnt)
1863
                goto skip;
5 Plagman 1864
 
4675 terminx 1865
            t = (spx[z]-n0.x)*dx;
1866
            vcnt = vsinsaft(vsp, i);
1867
            vsp[i].cy[1] = t*cv[0] + cy[0];
1868
            vsp[i].fy[1] = t*cv[1] + cy[1];
1869
            vsp[vcnt].x = spx[z];
1870
            vsp[vcnt].cy[0] = vsp[i].cy[1];
1871
            vsp[vcnt].fy[0] = vsp[i].fy[1];
1872
            vsp[vcnt].tag = spt[z];
1873
 
4930 helixhorne 1874
skip: ;
4898 terminx 1875
            int32_t ni = vsp[i].n; if (!ni) continue; //this 'if' fixes many bugs!
1876
            float dx0 = vsp[i].x; if (x0 > dx0) continue;
1877
            float dx1 = vsp[ni].x; if (x1 < dx1) continue;
4675 terminx 1878
            n0.y = (dx0-x0)*slop + y0;
1879
            n1.y = (dx1-x0)*slop + y0;
5 Plagman 1880
 
109 terminx 1881
            //      dx0           dx1
1882
            //       ~             ~
1883
            //----------------------------
1884
            //     t0+=0         t1+=0
1885
            //   vsp[i].cy[0]  vsp[i].cy[1]
1886
            //============================
1887
            //     t0+=1         t1+=3
1888
            //============================
1889
            //   vsp[i].fy[0]    vsp[i].fy[1]
1890
            //     t0+=2         t1+=6
1891
            //
1892
            //     ny0 ?         ny1 ?
5 Plagman 1893
 
109 terminx 1894
            k = 1+3;
4675 terminx 1895
            if ((vsp[i].tag == 0) || (n0.y <= vsp[i].cy[0]+.01f)) k--;
1896
            if ((vsp[i].tag == 1) || (n0.y >= vsp[i].fy[0]-.01f)) k++;
1897
            if ((vsp[ni].tag == 0) || (n1.y <= vsp[i].cy[1]+.01f)) k -= 3;
1898
            if ((vsp[ni].tag == 1) || (n1.y >= vsp[i].fy[1]-.01f)) k += 3;
5 Plagman 1899
 
4671 terminx 1900
            dpxy[0].x = dx0;
1901
            dpxy[1].x = dx1;
4605 terminx 1902
 
109 terminx 1903
            if (!dir)
1904
            {
4671 terminx 1905
                dpxy[0].y = vsp[i].cy[0];
1906
                dpxy[1].y = vsp[i].cy[1];
2002 helixhorne 1907
 
331 terminx 1908
                switch (k)
109 terminx 1909
                {
4675 terminx 1910
                case 4:
1911
                case 5:
1912
                case 7:
1913
                    dpxy[2].x = dx1; dpxy[3].x = dx0;
1914
                    dpxy[2].y = n1.y; dpxy[3].y = n0.y;
1915
                    vsp[i].cy[0] = n0.y; vsp[i].cy[1] = n1.y; vsp[i].ctag = gtag;
1916
                    drawpoly(dpxy, 4, domostpolymethod);
1917
                    break;
331 terminx 1918
                case 1:
1919
                case 2:
4671 terminx 1920
                    dpxy[2].x = dx0;
4675 terminx 1921
                    dpxy[2].y = n0.y;
1922
                    vsp[i].cy[0] = n0.y; vsp[i].ctag = gtag;
4671 terminx 1923
                    drawpoly(dpxy, 3, domostpolymethod);
4623 terminx 1924
                    break;
331 terminx 1925
                case 3:
1926
                case 6:
4671 terminx 1927
                    dpxy[2].x = dx1;
4675 terminx 1928
                    dpxy[2].y = n1.y;
1929
                    vsp[i].cy[1] = n1.y; vsp[i].ctag = gtag;
4671 terminx 1930
                    drawpoly(dpxy, 3, domostpolymethod);
4623 terminx 1931
                    break;
109 terminx 1932
                case 8:
4671 terminx 1933
                    dpxy[2].x = dx1; dpxy[2].y = vsp[i].fy[1];
1934
                    dpxy[3].x = dx0; dpxy[3].y = vsp[i].fy[0];
4623 terminx 1935
                    vsp[i].ctag = vsp[i].ftag = -1;
4671 terminx 1936
                    drawpoly(dpxy, 4, domostpolymethod);
331 terminx 1937
                default:
4623 terminx 1938
                    break;
109 terminx 1939
                }
1940
            }
1941
            else
1942
            {
331 terminx 1943
                switch (k)
109 terminx 1944
                {
4675 terminx 1945
                case 4:
1946
                case 3:
1947
                case 1:
1948
                    dpxy[2].x = dx1; dpxy[3].x = dx0;
1949
                    dpxy[0].y = n0.y; dpxy[1].y = n1.y; dpxy[2].y = vsp[i].fy[1]; dpxy[3].y = vsp[i].fy[0];
1950
                    vsp[i].fy[0] = n0.y; vsp[i].fy[1] = n1.y; vsp[i].ftag = gtag;
1951
                    drawpoly(dpxy, 4, domostpolymethod);
1952
                    break;
331 terminx 1953
                case 7:
1954
                case 6:
4671 terminx 1955
                    dpxy[2].x = dx0;
4675 terminx 1956
                    dpxy[0].y = n0.y; dpxy[1].y = vsp[i].fy[1]; dpxy[2].y = vsp[i].fy[0];
1957
                    vsp[i].fy[0] = n0.y; vsp[i].ftag = gtag;
4671 terminx 1958
                    drawpoly(dpxy, 3, domostpolymethod);
4623 terminx 1959
                    break;
331 terminx 1960
                case 5:
1961
                case 2:
4671 terminx 1962
                    dpxy[2].x = dx1;
4675 terminx 1963
                    dpxy[0].y = vsp[i].fy[0]; dpxy[1].y = n1.y; dpxy[2].y = vsp[i].fy[1];
1964
                    vsp[i].fy[1] = n1.y; vsp[i].ftag = gtag;
4671 terminx 1965
                    drawpoly(dpxy, 3, domostpolymethod);
4623 terminx 1966
                    break;
109 terminx 1967
                case 0:
4671 terminx 1968
                    dpxy[2].x = dx1; dpxy[3].x = dx0;
1969
                    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 1970
                    vsp[i].ctag = vsp[i].ftag = -1;
4671 terminx 1971
                    drawpoly(dpxy, 4, domostpolymethod);
331 terminx 1972
                default:
4623 terminx 1973
                    break;
109 terminx 1974
                }
1975
            }
1976
        }
1977
    }
5 Plagman 1978
 
109 terminx 1979
    gtag++;
1980
 
1981
    //Combine neighboring vertical strips with matching collinear top&bottom edges
1982
    //This prevents x-splits from propagating through the entire scan
1983
    i = vsp[0].n;
4623 terminx 1984
 
109 terminx 1985
    while (i)
1986
    {
4671 terminx 1987
        int32_t ni = vsp[i].n;
2002 helixhorne 1988
 
1989
        if ((vsp[i].cy[0] >= vsp[i].fy[0]) && (vsp[i].cy[1] >= vsp[i].fy[1]))
1990
            vsp[i].ctag = vsp[i].ftag = -1;
1991
 
109 terminx 1992
        if ((vsp[i].ctag == vsp[ni].ctag) && (vsp[i].ftag == vsp[ni].ftag))
2002 helixhorne 1993
        {
1994
            vsp[i].cy[1] = vsp[ni].cy[1];
1995
            vsp[i].fy[1] = vsp[ni].fy[1];
1996
            vsdel(vsp, ni);
1997
        }
109 terminx 1998
        else i = ni;
1999
    }
5 Plagman 2000
}
2001
 
4652 terminx 2002
void polymost_editorfunc(void)
2003
{
4656 terminx 2004
    vec3_t v;
2005
    vec3f_t o, o2;
4652 terminx 2006
    int32_t cz, fz;
2007
    hitdata_t hit;
2008
    vec3_t vect;
2009
    const float ratio = get_projhack_ratio();
2010
 
2011
    o2.x = (searchx-ghalfx)/ratio;
2012
    o2.y = (searchy-ghoriz)/ratio;  // ghoriz is (ydimen>>1) here
2013
    o2.z = ghalfx;
2014
 
2015
    //Tilt rotation
2016
    o.x = o2.x*gctang + o2.y*gstang;
2017
    o.y = o2.y*gctang - o2.x*gstang;
2018
    o.z = o2.z;
2019
 
2020
    //Up/down rotation
2021
    o2.x = o.z*gchang - o.y*gshang;
2022
    o2.y = o.x;
2023
    o2.z = o.y*gchang + o.z*gshang;
2024
 
2025
    //Standard Left/right rotation
4656 terminx 2026
    v.x = Blrintf (o2.x*fcosglobalang - o2.y*fsinglobalang);
2027
    v.y = Blrintf (o2.x*fsinglobalang + o2.y*fcosglobalang);
2028
    v.z = Blrintf (o2.z*16384.f);
4652 terminx 2029
 
2030
    vect.x = globalposx;
2031
    vect.y = globalposy;
2032
    vect.z = globalposz;
2033
 
2034
    hitallsprites = 1;
2035
    hitscan((const vec3_t *) &vect, globalcursectnum, //Start position
2036
        v.x>>10, v.y>>10, v.z>>6, &hit, 0xffff0030);
2037
 
2038
    if (hit.sect != -1) // if hitsect is -1, hitscan overflowed somewhere
2039
    {
2040
        getzsofslope(hit.sect, hit.pos.x, hit.pos.y, &cz, &fz);
2041
        hitallsprites = 0;
2042
 
2043
        searchsector = hit.sect;
2044
        if (hit.pos.z<cz) searchstat = 1;
2045
        else if (hit.pos.z>fz) searchstat = 2;
2046
        else if (hit.wall >= 0)
2047
        {
2048
            searchbottomwall = searchwall = hit.wall; searchstat = 0;
2049
            if (wall[hit.wall].nextwall >= 0)
2050
            {
2051
                int32_t cz, fz;
2052
                getzsofslope(wall[hit.wall].nextsector, hit.pos.x, hit.pos.y, &cz, &fz);
2053
                if (hit.pos.z > fz)
2054
                {
2055
                    searchisbottom = 1;
2056
                    if (wall[hit.wall].cstat&2) //'2' bottoms of walls
2057
                        searchbottomwall = wall[hit.wall].nextwall;
2058
                }
2059
                else
2060
                {
2061
                    searchisbottom = 0;
2062
                    if ((hit.pos.z > cz) && (wall[hit.wall].cstat&(16+32))) //masking or 1-way
2063
                        searchstat = 4;
2064
                }
2065
            }
2066
        }
2067
        else if (hit.sprite >= 0)