Subversion Repositories eduke32

Rev

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