Subversion Repositories eduke32

Rev

Rev 8579 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
278 Plagman 1
// blah
1609 plagman 2
 
5195 hendricks2 3
#if defined USE_OPENGL && defined POLYMER
686 plagman 4
 
6074 hendricks2 5
#include "compat.h"
2985 helixhorne 6
 
686 plagman 7
#define POLYMER_C
286 terminx 8
#include "polymer.h"
1298 plagman 9
#include "engine_priv.h"
4387 terminx 10
#include "xxhash.h"
3758 terminx 11
#include "texcache.h"
286 terminx 12
 
304 Plagman 13
// CVARS
1307 plagman 14
int32_t         pr_lighting = 1;
15
int32_t         pr_normalmapping = 1;
16
int32_t         pr_specularmapping = 1;
17
int32_t         pr_shadows = 1;
18
int32_t         pr_shadowcount = 5;
1350 terminx 19
int32_t         pr_shadowdetail = 4;
1408 plagman 20
int32_t         pr_shadowfiltering = 1;
1454 terminx 21
int32_t         pr_maxlightpasses = 10;
1305 plagman 22
int32_t         pr_maxlightpriority = PR_MAXLIGHTPRIORITY;
7329 terminx 23
int32_t         pr_fov = 512;
3769 terminx 24
double          pr_customaspect = 0.0f;
1212 plagman 25
int32_t         pr_billboardingmode = 1;
26
int32_t         pr_verbosity = 1;       // 0: silent, 1: errors and one-times, 2: multiple-times, 3: flood
27
int32_t         pr_wireframe = 0;
28
int32_t         pr_vbos = 2;
5296 Plagman 29
int32_t         pr_buckets = 0;
1212 plagman 30
int32_t         pr_gpusmoothing = 1;
1284 plagman 31
int32_t         pr_overrideparallax = 0;
1285 plagman 32
float           pr_parallaxscale = 0.1f;
33
float           pr_parallaxbias = 0.0f;
34
int32_t         pr_overridespecular = 0;
35
float           pr_specularpower = 15.0f;
36
float           pr_specularfactor = 1.0f;
1748 plagman 37
int32_t         pr_highpalookups = 1;
3737 Plagman 38
int32_t         pr_artmapping = 1;
1814 plagman 39
int32_t         pr_overridehud = 0;
40
float           pr_hudxadd = 0.0f;
41
float           pr_hudyadd = 0.0f;
42
float           pr_hudzadd = 0.0f;
43
int32_t         pr_hudangadd = 0;
7329 terminx 44
int32_t         pr_hudfov = 512;
1818 plagman 45
float           pr_overridemodelscale = 0.0f;
1445 plagman 46
int32_t         pr_ati_fboworkaround = 0;
1446 plagman 47
int32_t         pr_ati_nodepthoffset = 0;
1789 helixhorne 48
#ifdef __APPLE__
49
int32_t         pr_ati_textureformat_one = 0;
50
#endif
5266 Plagman 51
int32_t         pr_nullrender = 0; // 1: no draw, 2: no draw or updates
278 Plagman 52
 
1425 terminx 53
int32_t         r_pr_maxlightpasses = 5; // value of the cvar (not live value), used to detect changes
54
 
6656 pogokeen 55
GLenum          mapvbousage = GL_STREAM_DRAW;
56
GLenum          modelvbousage = GL_STATIC_DRAW;
741 plagman 57
 
1153 plagman 58
// BUILD DATA
304 Plagman 59
_prsector       *prsectors[MAXSECTORS];
60
_prwall         *prwalls[MAXWALLS];
1676 terminx 61
_prsprite       *prsprites[MAXSPRITES];
1165 plagman 62
_prmaterial     mdspritematerial;
1782 plagman 63
_prhighpalookup prhighpalookups[MAXBASEPALS][MAXPALOOKUPS];
733 plagman 64
 
3729 Plagman 65
// One U8 texture per tile
66
GLuint          prartmaps[MAXTILES];
67
// 256 U8U8U8 values per basepal
68
GLuint          prbasepalmaps[MAXBASEPALS];
69
// numshades full indirections (32*256) per lookup
70
GLuint          prlookups[MAXPALOOKUPS];
71
 
5294 Plagman 72
GLuint          prmapvbo;
6656 pogokeen 73
const GLsizeiptr proneplanesize = sizeof(_prvert) * 4;
74
const GLintptr prwalldatasize = sizeof(_prvert)* 4 * 3; // wall, over and mask planes for every wall
75
GLintptr prwalldataoffset;
5294 Plagman 76
 
5298 Plagman 77
GLuint          prindexringvbo;
78
GLuint          *prindexring;
6656 pogokeen 79
const GLsizeiptr prindexringsize = 65535;
80
GLintptr prindexringoffset;
5298 Plagman 81
 
82
const GLbitfield prindexringmapflags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
83
 
5296 Plagman 84
_prbucket       *prbuckethead;
85
int32_t         prcanbucket;
86
 
5294 Plagman 87
static const _prvert  vertsprite[4] =
723 terminx 88
{
5294 Plagman 89
    {
90
        -0.5f, 0.0f, 0.0f,
91
        0.0f, 1.0f,
92
        0xff, 0xff, 0xff, 0xff,
93
    },
94
    {
95
        0.5f, 0.0f, 0.0f,
96
        1.0f, 1.0f,
97
        0xff, 0xff, 0xff, 0xff,
98
    },
99
    {
100
        0.5f, 1.0f, 0.0f,
101
        1.0f, 0.0f,
102
        0xff, 0xff, 0xff, 0xff,
103
    },
104
    {
105
        -0.5f, 1.0f, 0.0f,
106
        0.0f, 0.0f,
107
        0xff, 0xff, 0xff, 0xff,
108
    },
683 plagman 109
};
110
 
5294 Plagman 111
static const _prvert  horizsprite[4] =
723 terminx 112
{
5294 Plagman 113
    {
114
        -0.5f, 0.0f, 0.5f,
115
        0.0f, 0.0f,
116
        0xff, 0xff, 0xff, 0xff,
117
    },
118
    {
119
        0.5f, 0.0f, 0.5f,
120
        1.0f, 0.0f,
121
        0xff, 0xff, 0xff, 0xff,
122
    },
123
    {
124
        0.5f, 0.0f, -0.5f,
125
        1.0f, 1.0f,
126
        0xff, 0xff, 0xff, 0xff,
127
    },
128
    {
129
        -0.5f, 0.0f, -0.5f,
130
        0.0f, 1.0f,
131
        0xff, 0xff, 0xff, 0xff,
132
    },
683 plagman 133
};
134
 
1676 terminx 135
static const GLfloat  skyboxdata[4 * 5 * 6] =
779 plagman 136
{
137
    // -ZY
138
    -0.5f, -0.5f, 0.5f,
139
    0.0f, 1.0f,
140
    -0.5f, -0.5f, -0.5f,
141
    1.0f, 1.0f,
142
    -0.5f, 0.5f, -0.5f,
143
    1.0f, 0.0f,
144
    -0.5f, 0.5f, 0.5f,
145
    0.0f, 0.0f,
146
 
147
    // XY
148
    -0.5f, -0.5f, -0.5f,
149
    0.0f, 1.0f,
150
    0.5f, -0.5f, -0.5f,
151
    1.0f, 1.0f,
152
    0.5f, 0.5f, -0.5f,
153
    1.0f, 0.0f,
154
    -0.5f, 0.5f, -0.5f,
155
    0.0f, 0.0f,
156
 
157
    // ZY
158
    0.5f, -0.5f, -0.5f,
159
    0.0f, 1.0f,
160
    0.5f, -0.5f, 0.5f,
161
    1.0f, 1.0f,
162
    0.5f, 0.5f, 0.5f,
163
    1.0f, 0.0f,
164
    0.5f, 0.5f, -0.5f,
165
    0.0f, 0.0f,
166
 
167
    // -XY
168
    0.5f, -0.5f, 0.5f,
169
    0.0f, 1.0f,
170
    -0.5f, -0.5f, 0.5f,
171
    1.0f, 1.0f,
172
    -0.5f, 0.5f, 0.5f,
173
    1.0f, 0.0f,
174
    0.5f, 0.5f, 0.5f,
175
    0.0f, 0.0f,
176
 
177
    // XZ
178
    -0.5f, 0.5f, -0.5f,
179
    1.0f, 1.0f,
180
    0.5f, 0.5f, -0.5f,
181
    1.0f, 0.0f,
182
    0.5f, 0.5f, 0.5f,
183
    0.0f, 0.0f,
184
    -0.5f, 0.5f, 0.5f,
185
    0.0f, 1.0f,
186
 
187
    // X-Z
188
    -0.5f, -0.5f, 0.5f,
189
    0.0f, 0.0f,
190
    0.5f, -0.5f, 0.5f,
191
    0.0f, 1.0f,
192
    0.5f, -0.5f, -0.5f,
193
    1.0f, 1.0f,
194
    -0.5f, -0.5f, -0.5f,
195
    1.0f, 0.0f,
196
};
197
 
780 plagman 198
GLuint          skyboxdatavbo;
199
 
8579 hendricks2 200
GLfloat         artskydata[PSKYOFF_MAX*2];
779 plagman 201
 
1153 plagman 202
// LIGHTS
4600 terminx 203
static _prplanelist *plpool;
1457 terminx 204
#pragma pack(push,1)
1152 plagman 205
_prlight        prlights[PR_MAXLIGHTS];
1212 plagman 206
int32_t         lightcount;
1242 plagman 207
int32_t         curlight;
1457 terminx 208
#pragma pack(pop)
1288 plagman 209
 
1676 terminx 210
static const GLfloat  shadowBias[] =
1268 plagman 211
{
212
    0.5, 0.0, 0.0, 0.0,
213
    0.0, 0.5, 0.0, 0.0,
214
    0.0, 0.0, 0.5, 0.0,
215
    0.5, 0.5, 0.5, 1.0
216
};
217
 
1163 plagman 218
// MATERIALS
4600 terminx 219
static const _prprogrambit   prprogrambits[PR_BIT_COUNT] = {
1152 plagman 220
    {
1222 plagman 221
        1 << PR_BIT_HEADER,
222
        // vert_def
223
        "#version 120\n"
1255 plagman 224
        "#extension GL_ARB_texture_rectangle : enable\n"
1222 plagman 225
        "\n",
226
        // vert_prog
227
        "",
228
        // frag_def
229
        "#version 120\n"
1255 plagman 230
        "#extension GL_ARB_texture_rectangle : enable\n"
1222 plagman 231
        "\n",
232
        // frag_prog
233
        "",
234
    },
235
    {
1167 plagman 236
        1 << PR_BIT_ANIM_INTERPOLATION,
237
        // vert_def
238
        "attribute vec4 nextFrameData;\n"
1239 plagman 239
        "attribute vec4 nextFrameNormal;\n"
1167 plagman 240
        "uniform float frameProgress;\n"
241
        "\n",
242
        // vert_prog
243
        "  vec4 currentFramePosition;\n"
244
        "  vec4 nextFramePosition;\n"
1169 plagman 245
        "\n"
1239 plagman 246
        "  currentFramePosition = curVertex * (1.0 - frameProgress);\n"
1167 plagman 247
        "  nextFramePosition = nextFrameData * frameProgress;\n"
1239 plagman 248
        "  curVertex = currentFramePosition + nextFramePosition;\n"
249
        "\n"
250
        "  currentFramePosition = vec4(curNormal, 1.0) * (1.0 - frameProgress);\n"
251
        "  nextFramePosition = nextFrameNormal * frameProgress;\n"
252
        "  curNormal = vec3(currentFramePosition + nextFramePosition);\n"
1167 plagman 253
        "\n",
254
        // frag_def
255
        "",
256
        // frag_prog
257
        "",
258
    },
259
    {
1242 plagman 260
        1 << PR_BIT_LIGHTING_PASS,
261
        // vert_def
262
        "",
263
        // vert_prog
264
        "",
265
        // frag_def
266
        "",
267
        // frag_prog
268
        "  isLightingPass = 1;\n"
269
        "  result = vec4(0.0, 0.0, 0.0, 1.0);\n"
270
        "\n",
271
    },
272
    {
1244 plagman 273
        1 << PR_BIT_NORMAL_MAP,
274
        // vert_def
275
        "attribute vec3 T;\n"
276
        "attribute vec3 B;\n"
277
        "attribute vec3 N;\n"
1283 plagman 278
        "uniform vec3 eyePosition;\n"
1284 plagman 279
        "varying vec3 tangentSpaceEyeVec;\n"
1244 plagman 280
        "\n",
281
        // vert_prog
1591 plagman 282
        "  TBN = mat3(T, B, N);\n"
1284 plagman 283
        "  tangentSpaceEyeVec = eyePosition - vec3(curVertex);\n"
284
        "  tangentSpaceEyeVec = TBN * tangentSpaceEyeVec;\n"
1244 plagman 285
        "\n"
286
        "  isNormalMapped = 1;\n"
287
        "\n",
288
        // frag_def
289
        "uniform sampler2D normalMap;\n"
1284 plagman 290
        "uniform vec2 normalBias;\n"
291
        "varying vec3 tangentSpaceEyeVec;\n"
1244 plagman 292
        "\n",
293
        // frag_prog
1284 plagman 294
        "  vec4 normalStep;\n"
295
        "  float biasedHeight;\n"
1283 plagman 296
        "\n"
1284 plagman 297
        "  eyeVec = normalize(tangentSpaceEyeVec);\n"
298
        "\n"
5845 terminx 299
        "  for (int i = 0; i < 4; i++) {\n"
1284 plagman 300
        "    normalStep = texture2D(normalMap, commonTexCoord.st);\n"
301
        "    biasedHeight = normalStep.a * normalBias.x - normalBias.y;\n"
302
        "    commonTexCoord += (biasedHeight - commonTexCoord.z) * normalStep.z * eyeVec;\n"
303
        "  }\n"
304
        "\n"
305
        "  normalTexel = texture2D(normalMap, commonTexCoord.st);\n"
306
        "\n"
1244 plagman 307
        "  isNormalMapped = 1;\n"
308
        "\n",
309
    },
310
    {
3729 Plagman 311
        1 << PR_BIT_ART_MAP,
312
        // vert_def
3739 Plagman 313
        "varying vec3 horizDistance;\n"
3729 Plagman 314
        "\n",
315
        // vert_prog
3737 Plagman 316
        "  gl_TexCoord[0] = gl_MultiTexCoord0;\n"
3739 Plagman 317
        "  horizDistance = vec3(gl_ModelViewMatrix * curVertex);\n"
3729 Plagman 318
        "\n",
319
        // frag_def
320
        "uniform sampler2D artMap;\n"
321
        "uniform sampler2D basePalMap;\n"
3740 Plagman 322
        "uniform sampler2DRect lookupMap;\n"
3737 Plagman 323
        "uniform float shadeOffset;\n"
324
        "uniform float visibility;\n"
3739 Plagman 325
        "varying vec3 horizDistance;\n"
3729 Plagman 326
        "\n",
327
        // frag_prog
3962 helixhorne 328
 
6590 hendricks2 329
        "  float shadeLookup = length(horizDistance) / 1.024 * visibility;\n"
3740 Plagman 330
        "  shadeLookup = shadeLookup + shadeOffset;\n"
3737 Plagman 331
        "\n"
3740 Plagman 332
        "  float colorIndex = texture2D(artMap, commonTexCoord.st).r * 256.0;\n"
333
        "  float colorIndexNear = texture2DRect(lookupMap, vec2(colorIndex, floor(shadeLookup))).r;\n"
334
        "  float colorIndexFar = texture2DRect(lookupMap, vec2(colorIndex, floor(shadeLookup + 1.0))).r;\n"
335
        "  float colorIndexFullbright = texture2DRect(lookupMap, vec2(colorIndex, 0.0)).r;\n"
3729 Plagman 336
        "\n"
3737 Plagman 337
        "  vec3 texelNear = texture2D(basePalMap, vec2(colorIndexNear, 0.5)).rgb;\n"
338
        "  vec3 texelFar = texture2D(basePalMap, vec2(colorIndexFar, 0.5)).rgb;\n"
5349 hendricks2 339
        "  diffuseTexel.rgb = texture2D(basePalMap, vec2(colorIndexFullbright, 0.5)).rgb;\n"
3738 Plagman 340
        "\n"
341
        "  if (isLightingPass == 0) {\n"
5349 hendricks2 342
        "    result.rgb = mix(texelNear, texelFar, fract(shadeLookup));\n"
3738 Plagman 343
        "    result.a = 1.0;\n"
3740 Plagman 344
        "    if (colorIndex == 256.0)\n"
3738 Plagman 345
        "      result.a = 0.0;\n"
346
        "  }\n"
3729 Plagman 347
        "\n",
348
    },
349
    {
1162 plagman 350
        1 << PR_BIT_DIFFUSE_MAP,
351
        // vert_def
1168 plagman 352
        "uniform vec2 diffuseScale;\n"
353
        "\n",
1162 plagman 354
        // vert_prog
1280 plagman 355
        "  gl_TexCoord[0] = vec4(diffuseScale, 1.0, 1.0) * gl_MultiTexCoord0;\n"
1162 plagman 356
        "\n",
357
        // frag_def
358
        "uniform sampler2D diffuseMap;\n"
359
        "\n",
360
        // frag_prog
1284 plagman 361
        "  diffuseTexel = texture2D(diffuseMap, commonTexCoord.st);\n"
1745 plagman 362
        "\n",
363
    },
364
    {
1757 plagman 365
        1 << PR_BIT_DIFFUSE_DETAIL_MAP,
1745 plagman 366
        // vert_def
1757 plagman 367
        "uniform vec2 detailScale;\n"
368
        "varying vec2 fragDetailScale;\n"
369
        "\n",
1745 plagman 370
        // vert_prog
1757 plagman 371
        "  fragDetailScale = detailScale;\n"
372
        "  if (isNormalMapped == 0)\n"
373
        "    gl_TexCoord[1] = vec4(detailScale, 1.0, 1.0) * gl_MultiTexCoord0;\n"
374
        "\n",
1745 plagman 375
        // frag_def
1757 plagman 376
        "uniform sampler2D detailMap;\n"
377
        "varying vec2 fragDetailScale;\n"
1745 plagman 378
        "\n",
379
        // frag_prog
1757 plagman 380
        "  if (isNormalMapped == 0)\n"
381
        "    diffuseTexel *= texture2D(detailMap, gl_TexCoord[1].st);\n"
382
        "  else\n"
383
        "    diffuseTexel *= texture2D(detailMap, commonTexCoord.st * fragDetailScale);\n"
384
        "  diffuseTexel.rgb *= 2.0;\n"
1745 plagman 385
        "\n",
386
    },
387
    {
1757 plagman 388
        1 << PR_BIT_DIFFUSE_MODULATION,
1745 plagman 389
        // vert_def
390
        "",
391
        // vert_prog
1757 plagman 392
        "  gl_FrontColor = gl_Color;\n"
393
        "\n",
1745 plagman 394
        // frag_def
395
        "",
396
        // frag_prog
1242 plagman 397
        "  if (isLightingPass == 0)\n"
1773 plagman 398
        "    result *= vec4(gl_Color);\n"
1162 plagman 399
        "\n",
400
    },
401
    {
1773 plagman 402
        1 << PR_BIT_DIFFUSE_MAP2,
1168 plagman 403
        // vert_def
1757 plagman 404
        "",
1168 plagman 405
        // vert_prog
1757 plagman 406
        "",
1168 plagman 407
        // frag_def
1773 plagman 408
        "",
1168 plagman 409
        // frag_prog
1773 plagman 410
        "  if (isLightingPass == 0)\n"
411
        "    result *= diffuseTexel;\n"
1168 plagman 412
        "\n",
413
    },
414
    {
1773 plagman 415
        1 << PR_BIT_HIGHPALOOKUP_MAP,
1160 plagman 416
        // vert_def
417
        "",
418
        // vert_prog
1757 plagman 419
        "",
1160 plagman 420
        // frag_def
1773 plagman 421
        "uniform sampler3D highPalookupMap;\n"
422
        "\n",
1160 plagman 423
        // frag_prog
1783 plagman 424
        "  float highPalScale = 0.9921875; // for 6 bits\n"
425
        "  float highPalBias = 0.00390625;\n"
426
        "\n"
1242 plagman 427
        "  if (isLightingPass == 0)\n"
1783 plagman 428
        "    result.rgb = texture3D(highPalookupMap, result.rgb * highPalScale + highPalBias).rgb;\n"
429
        "  diffuseTexel.rgb = texture3D(highPalookupMap, diffuseTexel.rgb * highPalScale + highPalBias).rgb;\n"
1160 plagman 430
        "\n",
1154 plagman 431
    },
432
    {
1281 plagman 433
        1 << PR_BIT_SPECULAR_MAP,
434
        // vert_def
435
        "",
436
        // vert_prog
437
        "",
438
        // frag_def
439
        "uniform sampler2D specMap;\n"
440
        "\n",
441
        // frag_prog
1284 plagman 442
        "  specTexel = texture2D(specMap, commonTexCoord.st);\n"
1382 plagman 443
        "\n"
444
        "  isSpecularMapped = 1;\n"
1281 plagman 445
        "\n",
446
    },
447
    {
1278 plagman 448
        1 << PR_BIT_SPECULAR_MATERIAL,
449
        // vert_def
450
        "",
451
        // vert_prog
452
        "",
453
        // frag_def
454
        "uniform vec2 specMaterial;\n"
455
        "\n",
456
        // frag_prog
457
        "  specularMaterial = specMaterial;\n"
458
        "\n",
459
    },
460
    {
1277 plagman 461
        1 << PR_BIT_MIRROR_MAP,
1255 plagman 462
        // vert_def
463
        "",
464
        // vert_prog
465
        "",
466
        // frag_def
467
        "uniform sampler2DRect mirrorMap;\n"
468
        "\n",
469
        // frag_prog
470
        "  vec4 mirrorTexel;\n"
471
        "  vec2 mirrorCoords;\n"
472
        "\n"
473
        "  mirrorCoords = gl_FragCoord.st;\n"
474
        "  if (isNormalMapped == 1) {\n"
475
        "    mirrorCoords += 100.0 * (normalTexel.rg - 0.5);\n"
476
        "  }\n"
477
        "  mirrorTexel = texture2DRect(mirrorMap, mirrorCoords);\n"
1282 plagman 478
        "  result = vec4((result.rgb * (1.0 - specTexel.a)) + (mirrorTexel.rgb * specTexel.rgb * specTexel.a), result.a);\n"
1255 plagman 479
        "\n",
480
    },
481
    {
1298 plagman 482
        1 << PR_BIT_FOG,
483
        // vert_def
484
        "",
485
        // vert_prog
486
        "",
487
        // frag_def
3301 helixhorne 488
#ifdef PR_LINEAR_FOG
489
        "uniform bool linearFog;\n"
490
#endif
1298 plagman 491
        "",
492
        // frag_prog
493
        "  float fragDepth;\n"
494
        "  float fogFactor;\n"
495
        "\n"
6590 hendricks2 496
        "  fragDepth = gl_FragCoord.z / gl_FragCoord.w;\n"
3301 helixhorne 497
#ifdef PR_LINEAR_FOG
498
        "  if (!linearFog) {\n"
499
#endif
500
        "    fragDepth *= fragDepth;\n"
501
        "    fogFactor = exp2(-gl_Fog.density * gl_Fog.density * fragDepth * 1.442695);\n"
502
#ifdef PR_LINEAR_FOG
503
        "  } else {\n"
6590 hendricks2 504
        "    fogFactor = gl_Fog.scale * (gl_Fog.end - fragDepth);\n"
3301 helixhorne 505
        "    fogFactor = clamp(fogFactor, 0.0, 1.0);"
506
        "  }\n"
507
#endif
1298 plagman 508
        "  result.rgb = mix(gl_Fog.color.rgb, result.rgb, fogFactor);\n"
509
        "\n",
510
    },
511
    {
1277 plagman 512
        1 << PR_BIT_GLOW_MAP,
1242 plagman 513
        // vert_def
514
        "",
515
        // vert_prog
1280 plagman 516
        "",
1242 plagman 517
        // frag_def
518
        "uniform sampler2D glowMap;\n"
519
        "\n",
520
        // frag_prog
521
        "  vec4 glowTexel;\n"
522
        "\n"
1284 plagman 523
        "  glowTexel = texture2D(glowMap, commonTexCoord.st);\n"
1242 plagman 524
        "  result = vec4((result.rgb * (1.0 - glowTexel.a)) + (glowTexel.rgb * glowTexel.a), result.a);\n"
525
        "\n",
526
    },
527
    {
1674 plagman 528
        1 << PR_BIT_PROJECTION_MAP,
1268 plagman 529
        // vert_def
530
        "uniform mat4 shadowProjMatrix;\n"
531
        "\n",
532
        // vert_prog
1323 plagman 533
        "  gl_TexCoord[2] = shadowProjMatrix * curVertex;\n"
1268 plagman 534
        "\n",
535
        // frag_def
1674 plagman 536
        "",
537
        // frag_prog
538
        "",
539
    },
540
    {
541
        1 << PR_BIT_SHADOW_MAP,
542
        // vert_def
543
        "",
544
        // vert_prog
545
        "",
546
        // frag_def
1268 plagman 547
        "uniform sampler2DShadow shadowMap;\n"
548
        "\n",
549
        // frag_prog
1323 plagman 550
        "  shadowResult = shadow2DProj(shadowMap, gl_TexCoord[2]).a;\n"
1268 plagman 551
        "\n",
552
    },
553
    {
1377 plagman 554
        1 << PR_BIT_LIGHT_MAP,
555
        // vert_def
556
        "",
557
        // vert_prog
558
        "",
559
        // frag_def
560
        "uniform sampler2D lightMap;\n"
561
        "\n",
562
        // frag_prog
2055 plagman 563
        "  lightTexel = texture2D(lightMap, vec2(gl_TexCoord[2].s, -gl_TexCoord[2].t) / gl_TexCoord[2].q).rgb;\n"
1377 plagman 564
        "\n",
565
    },
566
    {
1266 plagman 567
        1 << PR_BIT_SPOT_LIGHT,
568
        // vert_def
569
        "",
570
        // vert_prog
571
        "",
572
        // frag_def
573
        "uniform vec3 spotDir;\n"
574
        "uniform vec2 spotRadius;\n"
575
        "\n",
576
        // frag_prog
577
        "  spotVector = spotDir;\n"
578
        "  spotCosRadius = spotRadius;\n"
579
        "  isSpotLight = 1;\n"
580
        "\n",
581
    },
582
    {
1170 plagman 583
        1 << PR_BIT_POINT_LIGHT,
584
        // vert_def
585
        "varying vec3 vertexNormal;\n"
1243 plagman 586
        "varying vec3 eyeVector;\n"
587
        "varying vec3 lightVector;\n"
1244 plagman 588
        "varying vec3 tangentSpaceLightVector;\n"
1170 plagman 589
        "\n",
590
        // vert_prog
1243 plagman 591
        "  vec3 vertexPos;\n"
592
        "\n"
1239 plagman 593
        "  vertexPos = vec3(gl_ModelViewMatrix * curVertex);\n"
1243 plagman 594
        "  eyeVector = -vertexPos;\n"
595
        "  lightVector = gl_LightSource[0].ambient.rgb - vertexPos;\n"
1244 plagman 596
        "\n"
597
        "  if (isNormalMapped == 1) {\n"
1283 plagman 598
        "    tangentSpaceLightVector = gl_LightSource[0].specular.rgb - vec3(curVertex);\n"
599
        "    tangentSpaceLightVector = TBN * tangentSpaceLightVector;\n"
1244 plagman 600
        "  } else\n"
601
        "    vertexNormal = normalize(gl_NormalMatrix * curNormal);\n"
1170 plagman 602
        "\n",
603
        // frag_def
604
        "varying vec3 vertexNormal;\n"
1243 plagman 605
        "varying vec3 eyeVector;\n"
606
        "varying vec3 lightVector;\n"
1244 plagman 607
        "varying vec3 tangentSpaceLightVector;\n"
1170 plagman 608
        "\n",
609
        // frag_prog
1243 plagman 610
        "  float pointLightDistance;\n"
1170 plagman 611
        "  float lightAttenuation;\n"
1266 plagman 612
        "  float spotAttenuation;\n"
613
        "  vec3 N, L, E, R, D;\n"
1243 plagman 614
        "  vec3 lightDiffuse;\n"
615
        "  float lightSpecular;\n"
616
        "  float NdotL;\n"
1266 plagman 617
        "  float spotCosAngle;\n"
1170 plagman 618
        "\n"
1243 plagman 619
        "  L = normalize(lightVector);\n"
1211 plagman 620
        "\n"
1406 plagman 621
        "  pointLightDistance = dot(lightVector,lightVector);\n"
622
        "  lightAttenuation = clamp(1.0 - pointLightDistance * gl_LightSource[0].linearAttenuation, 0.0, 1.0);\n"
1266 plagman 623
        "  spotAttenuation = 1.0;\n"
1243 plagman 624
        "\n"
1266 plagman 625
        "  if (isSpotLight == 1) {\n"
626
        "    D = normalize(spotVector);\n"
627
        "    spotCosAngle = dot(-L, D);\n"
628
        "    spotAttenuation = clamp((spotCosAngle - spotCosRadius.x) * spotCosRadius.y, 0.0, 1.0);\n"
629
        "  }\n"
630
        "\n"
1265 plagman 631
        "  if (isNormalMapped == 1) {\n"
1284 plagman 632
        "    E = eyeVec;\n"
1283 plagman 633
        "    N = normalize(2.0 * (normalTexel.rgb - 0.5));\n"
634
        "    L = normalize(tangentSpaceLightVector);\n"
1284 plagman 635
        "  } else {\n"
636
        "    E = normalize(eyeVector);\n"
1265 plagman 637
        "    N = normalize(vertexNormal);\n"
1284 plagman 638
        "  }\n"
1265 plagman 639
        "  NdotL = max(dot(N, L), 0.0);\n"
1243 plagman 640
        "\n"
1265 plagman 641
        "  R = reflect(-L, N);\n"
1243 plagman 642
        "\n"
1381 plagman 643
        "  lightDiffuse = gl_Color.a * shadowResult * lightTexel *\n"
1266 plagman 644
        "                 gl_LightSource[0].diffuse.rgb * lightAttenuation * spotAttenuation;\n"
1381 plagman 645
        "  result += vec4(lightDiffuse * diffuseTexel.a * diffuseTexel.rgb * NdotL, 0.0);\n"
1243 plagman 646
        "\n"
1383 plagman 647
        "  if (isSpecularMapped == 0)\n"
1382 plagman 648
        "    specTexel.rgb = diffuseTexel.rgb * diffuseTexel.a;\n"
649
        "\n"
1281 plagman 650
        "  lightSpecular = pow( max(dot(R, E), 0.0), specularMaterial.x * specTexel.a) * specularMaterial.y;\n"
1380 plagman 651
        "  result += vec4(lightDiffuse * specTexel.rgb * lightSpecular, 0.0);\n"
1170 plagman 652
        "\n",
653
    },
654
    {
1222 plagman 655
        1 << PR_BIT_FOOTER,
1160 plagman 656
        // vert_def
657
        "void main(void)\n"
1167 plagman 658
        "{\n"
1239 plagman 659
        "  vec4 curVertex = gl_Vertex;\n"
660
        "  vec3 curNormal = gl_Normal;\n"
1244 plagman 661
        "  int isNormalMapped = 0;\n"
662
        "  mat3 TBN;\n"
1280 plagman 663
        "\n"
664
        "  gl_TexCoord[0] = gl_MultiTexCoord0;\n"
1167 plagman 665
        "\n",
1160 plagman 666
        // vert_prog
1239 plagman 667
        "  gl_Position = gl_ModelViewProjectionMatrix * curVertex;\n"
1160 plagman 668
        "}\n",
669
        // frag_def
670
        "void main(void)\n"
671
        "{\n"
1284 plagman 672
        "  vec3 commonTexCoord = vec3(gl_TexCoord[0].st, 0.0);\n"
1160 plagman 673
        "  vec4 result = vec4(1.0, 1.0, 1.0, 1.0);\n"
1233 plagman 674
        "  vec4 diffuseTexel = vec4(1.0, 1.0, 1.0, 1.0);\n"
1281 plagman 675
        "  vec4 specTexel = vec4(1.0, 1.0, 1.0, 1.0);\n"
1244 plagman 676
        "  vec4 normalTexel;\n"
1242 plagman 677
        "  int isLightingPass = 0;\n"
1244 plagman 678
        "  int isNormalMapped = 0;\n"
1382 plagman 679
        "  int isSpecularMapped = 0;\n"
1284 plagman 680
        "  vec3 eyeVec;\n"
1266 plagman 681
        "  int isSpotLight = 0;\n"
682
        "  vec3 spotVector;\n"
683
        "  vec2 spotCosRadius;\n"
1323 plagman 684
        "  float shadowResult = 1.0;\n"
1285 plagman 685
        "  vec2 specularMaterial = vec2(15.0, 1.0);\n"
1377 plagman 686
        "  vec3 lightTexel = vec3(1.0, 1.0, 1.0);\n"
1160 plagman 687
        "\n",
688
        // frag_prog
689
        "  gl_FragColor = result;\n"
690
        "}\n",
1152 plagman 691
    }
692
};
693
 
1162 plagman 694
_prprograminfo  prprograms[1 << PR_BIT_COUNT];
1152 plagman 695
 
1252 plagman 696
int32_t         overridematerial;
1554 plagman 697
int32_t         globaloldoverridematerial;
1252 plagman 698
 
1812 plagman 699
int32_t         rotatespritematerialbits;
700
 
1255 plagman 701
// RENDER TARGETS
702
_prrt           *prrts;
703
 
311 Plagman 704
// CONTROL
1211 plagman 705
GLfloat         spritemodelview[16];
1594 plagman 706
GLfloat         mdspritespace[4][4];
1211 plagman 707
GLfloat         rootmodelviewmatrix[16];
708
GLfloat         *curmodelviewmatrix;
1373 plagman 709
GLfloat         rootskymodelviewmatrix[16];
710
GLfloat         *curskymodelviewmatrix;
525 Plagman 711
 
1313 plagman 712
static int16_t  sectorqueue[MAXSECTORS];
713
static int16_t  querydelay[MAXSECTORS];
714
static GLuint   queryid[MAXWALLS];
715
static int16_t  drawingstate[MAXSECTORS];
716
 
1980 plagman 717
int16_t         *cursectormasks;
718
int16_t         *cursectormaskcount;
719
 
1235 plagman 720
float           horizang;
6725 terminx 721
fix16_t         viewangle;
1235 plagman 722
 
1212 plagman 723
int32_t         depth;
1255 plagman 724
_prmirror       mirrors[10];
311 Plagman 725
 
4644 hendricks2 726
#if defined __clang__ && defined __APPLE__
727
// XXX: OS X 10.9 deprecated GLUtesselator.
728
#pragma clang diagnostic push
729
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
730
#endif
283 Plagman 731
GLUtesselator*  prtess;
4644 hendricks2 732
#if defined __clang__ && defined __APPLE__
733
#pragma clang diagnostic pop
734
#endif
278 Plagman 735
 
3977 helixhorne 736
static int16_t  cursky;
737
static char     curskypal;
738
static int8_t   curskyshade;
739
static float    curskyangmul = 1;
551 Plagman 740
 
697 plagman 741
_pranimatespritesinfo asi;
742
 
1554 plagman 743
int32_t         polymersearching;
1456 helixhorne 744
 
2032 plagman 745
int32_t         culledface;
746
 
304 Plagman 747
// EXTERNAL FUNCTIONS
1212 plagman 748
int32_t             polymer_init(void)
278 Plagman 749
{
6828 terminx 750
    int32_t         i, j, t = timerGetTicks();
278 Plagman 751
 
1361 terminx 752
    if (pr_verbosity >= 1) OSD_Printf("Initializing Polymer subsystem...\n");
278 Plagman 753
 
1506 plagman 754
    if (!glinfo.texnpot ||
755
        !glinfo.depthtex ||
756
        !glinfo.shadow ||
757
        !glinfo.fbos ||
758
        !glinfo.rect ||
759
        !glinfo.multitex ||
760
        !glinfo.vbos ||
761
        !glinfo.occlusionqueries ||
762
        !glinfo.glsl)
763
    {
764
        OSD_Printf("PR : Your video card driver/combo doesn't support the necessary features!\n");
765
        OSD_Printf("PR : Disabling Polymer...\n");
5803 terminx 766
        return 0;
1506 plagman 767
    }
768
 
1943 helixhorne 769
    // clean up existing stuff since it will be initialized again if we're re-entering here
770
    polymer_uninit();
1942 helixhorne 771
 
1330 terminx 772
    Bmemset(&prsectors[0], 0, sizeof(prsectors[0]) * MAXSECTORS);
773
    Bmemset(&prwalls[0], 0, sizeof(prwalls[0]) * MAXWALLS);
283 Plagman 774
 
462 terminx 775
    prtess = bgluNewTess();
283 Plagman 776
    if (prtess == 0)
777
    {
1361 terminx 778
        OSD_Printf("PR : Tessellation object initialization failed!\n");
5803 terminx 779
        return 0;
283 Plagman 780
    }
781
 
304 Plagman 782
    polymer_loadboard();
783
 
779 plagman 784
    polymer_initartsky();
1300 plagman 785
    skyboxdatavbo = 0;
316 Plagman 786
 
1300 plagman 787
    i = 0;
1301 plagman 788
    while (i < nextmodelid)
789
    {
790
        if (models[i])
791
        {
792
            md3model_t* m;
793
 
794
            m = (md3model_t*)models[i];
795
            m->indices = NULL;
796
        }
797
        i++;
798
    }
799
 
800
    i = 0;
1300 plagman 801
    while (i < (1 << PR_BIT_COUNT))
802
    {
803
        prprograms[i].handle = 0;
804
        i++;
805
    }
806
 
1252 plagman 807
    overridematerial = 0xFFFFFFFF;
808
 
1554 plagman 809
    polymersearching = FALSE;
810
 
1307 plagman 811
    polymer_initrendertargets(pr_shadowcount + 1);
1943 helixhorne 812
 
1748 plagman 813
    // Prime highpalookup maps
814
    i = 0;
1782 plagman 815
    while (i < MAXBASEPALS)
1748 plagman 816
    {
1782 plagman 817
        j = 0;
818
        while (j < MAXPALOOKUPS)
1748 plagman 819
        {
1782 plagman 820
            if (prhighpalookups[i][j].data)
821
            {
6656 pogokeen 822
                glGenTextures(1, &prhighpalookups[i][j].map);
823
                glBindTexture(GL_TEXTURE_3D, prhighpalookups[i][j].map);
824
                glTexImage3D(GL_TEXTURE_3D,                // target
1782 plagman 825
                              0,                            // mip level
826
                              GL_RGBA,                      // internalFormat
827
                              PR_HIGHPALOOKUP_DIM,          // width
828
                              PR_HIGHPALOOKUP_DIM,          // height
829
                              PR_HIGHPALOOKUP_DIM,          // depth
830
                              0,                            // border
831
                              GL_BGRA,                      // upload format
832
                              GL_UNSIGNED_BYTE,             // upload component type
833
                              prhighpalookups[i][j].data);     // data pointer
6656 pogokeen 834
                glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
835
                glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
836
                glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
837
                glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
838
                glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
839
                glBindTexture(GL_TEXTURE_3D, 0);
1782 plagman 840
            }
841
            j++;
1745 plagman 842
        }
1748 plagman 843
        i++;
1745 plagman 844
    }
845
 
2073 helixhorne 846
#ifndef __APPLE__
2056 plagman 847
    if (glinfo.debugoutput) {
848
        // Enable everything.
6656 pogokeen 849
        glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
850
        glDebugMessageCallbackARB((GLDEBUGPROCARB)polymer_debugoutputcallback, NULL);
851
        glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
2056 plagman 852
    }
2073 helixhorne 853
#endif
2056 plagman 854
 
6828 terminx 855
    if (pr_verbosity >= 1) OSD_Printf("PR : Initialization complete in %d ms.\n", timerGetTicks()-t);
1554 plagman 856
 
5803 terminx 857
    return 1;
278 Plagman 858
}
859
 
1390 terminx 860
void                polymer_uninit(void)
861
{
1782 plagman 862
    int32_t         i, j;
1748 plagman 863
 
1943 helixhorne 864
    if (prtess)
865
    {
866
        bgluDeleteTess(prtess);
867
        prtess = NULL;
868
    }
869
 
1390 terminx 870
    polymer_freeboard();
1943 helixhorne 871
 
872
    polymer_initrendertargets(0);
873
 
1748 plagman 874
    i = 0;
1782 plagman 875
    while (i < MAXBASEPALS)
1748 plagman 876
    {
1782 plagman 877
        j = 0;
878
        while (j < MAXPALOOKUPS)
879
        {
1969 helixhorne 880
//            if (prhighpalookups[i][j].data) {
5352 hendricks2 881
//                DO_FREE_AND_NULL(prhighpalookups[i][j].data);
1969 helixhorne 882
//            }
1782 plagman 883
            if (prhighpalookups[i][j].map) {
6656 pogokeen 884
                glDeleteTextures(1, &prhighpalookups[i][j].map);
2045 helixhorne 885
                prhighpalookups[i][j].map = 0;
1782 plagman 886
            }
887
            j++;
5768 hendricks2 888
        }
1748 plagman 889
        i++;
890
    }
4600 terminx 891
 
892
    i = 0;
893
    while (plpool)
894
    {
895
        _prplanelist*   next = plpool->n;
896
 
7705 terminx 897
        Xfree(plpool);
4600 terminx 898
        plpool = next;
899
        i++;
900
    }
901
 
902
    if (pr_verbosity >= 3)
903
        OSD_Printf("PR: freed %d planelists\n", i);
1390 terminx 904
}
905
 
1814 plagman 906
void                polymer_setaspect(int32_t ang)
99 terminx 907
{
1507 plagman 908
    float           aspect;
5877 hendricks2 909
    float fang = (float)ang * atanf(fviewingrange*(1.f/65536.f)) * (4.f/fPI);
1507 plagman 910
 
7329 terminx 911
    // use horizontal fov instead of vertical
7343 terminx 912
    fang = atanf(tanf(fang * (fPI / 2048.f)) * float(windowxy2.y - windowxy1.y + 1) / float(windowxy2.x - windowxy1.x + 1) *
913
                      float(xdim) / float(ydim) * (3.f / 4.f)) * (2048.f / fPI);
7329 terminx 914
 
1814 plagman 915
    if (pr_customaspect != 0.0f)
916
        aspect = pr_customaspect;
917
    else
5800 terminx 918
        aspect = (float)(windowxy2.x-windowxy1.x+1) /
919
                 (float)(windowxy2.y-windowxy1.y+1);
1814 plagman 920
 
6656 pogokeen 921
    glMatrixMode(GL_PROJECTION);
922
    glLoadIdentity();
5877 hendricks2 923
    bgluPerspective(fang * (360.f/2048.f), aspect, 0.01f, 100.0f);
1814 plagman 924
}
925
 
926
void                polymer_glinit(void)
927
{
6656 pogokeen 928
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
929
    glClearStencil(0);
930
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
6939 pogokeen 931
    glViewport(windowxy1.x, ydim-(windowxy2.y+1),windowxy2.x-windowxy1.x+1, windowxy2.y-windowxy1.y+1);
283 Plagman 932
 
6656 pogokeen 933
    glEnable(GL_DEPTH_TEST);
934
    glDepthFunc(GL_LEQUAL);
320 Plagman 935
 
6656 pogokeen 936
    glDisable(GL_BLEND);
937
    glDisable(GL_ALPHA_TEST);
1255 plagman 938
 
283 Plagman 939
    if (pr_wireframe)
6656 pogokeen 940
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
283 Plagman 941
    else
6656 pogokeen 942
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
2032 plagman 943
 
1814 plagman 944
    polymer_setaspect(pr_fov);
283 Plagman 945
 
6656 pogokeen 946
    glMatrixMode(GL_MODELVIEW);
947
    glLoadIdentity();
304 Plagman 948
 
6656 pogokeen 949
    glEnableClientState(GL_VERTEX_ARRAY);
950
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
304 Plagman 951
 
6656 pogokeen 952
    glDisable(GL_FOG);
316 Plagman 953
 
2032 plagman 954
    culledface = GL_BACK;
6656 pogokeen 955
    glCullFace(GL_BACK);
956
    glFrontFace(GL_CCW);
2032 plagman 957
 
6656 pogokeen 958
    glEnable(GL_CULL_FACE);
99 terminx 959
}
286 terminx 960
 
1596 plagman 961
void                polymer_resetlights(void)
962
{
963
    int32_t         i;
964
    _prsector       *s;
965
    _prwall         *w;
966
 
967
    i = 0;
968
    while (i < numsectors)
969
    {
970
        s = prsectors[i];
971
 
972
        if (!s) {
973
            i++;
974
            continue;
975
        }
976
 
977
        polymer_resetplanelights(&s->floor);
978
        polymer_resetplanelights(&s->ceil);
979
 
980
        i++;
981
    }
982
 
983
    i = 0;
984
    while (i < numwalls)
985
    {
986
        w = prwalls[i];
987
 
988
        if (!w) {
989
            i++;
990
            continue;
991
        }
992
 
993
        polymer_resetplanelights(&w->wall);
994
        polymer_resetplanelights(&w->over);
995
        polymer_resetplanelights(&w->mask);
996
 
997
        i++;
998
    }
999
 
1000
    i = 0;
1001
    while (i < PR_MAXLIGHTS)
1002
    {
1003
        prlights[i].flags.active = 0;
1004
        i++;
1005
    }
1006
 
1007
    lightcount = 0;
1652 terminx 1008
 
6831 terminx 1009
    if (!engineLoadMHK(NULL))
2236 helixhorne 1010
        OSD_Printf("polymer_resetlights: reloaded maphack\n");
1596 plagman 1011
}
1012
 
304 Plagman 1013
void                polymer_loadboard(void)
286 terminx 1014
{
1212 plagman 1015
    int32_t         i;
286 terminx 1016
 
1390 terminx 1017
    polymer_freeboard();
1385 terminx 1018
 
5294 Plagman 1019
    // in the big map buffer, sectors have floor and ceiling vertices for each wall first, then walls
1020
    prwalldataoffset = numwalls * 2 * sizeof(_prvert);
1021
 
6656 pogokeen 1022
    glGenBuffers(1, &prmapvbo);
1023
    glBindBuffer(GL_ARRAY_BUFFER, prmapvbo);
1024
    glBufferData(GL_ARRAY_BUFFER, prwalldataoffset + (numwalls * prwalldatasize), NULL, mapvbousage);
1025
    glBindBuffer(GL_ARRAY_BUFFER, 0);
5294 Plagman 1026
 
6656 pogokeen 1027
    glGenBuffers(1, &prindexringvbo);
1028
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prindexringvbo);
5298 Plagman 1029
 
5344 Plagman 1030
    if (pr_buckets)
1031
    {
6656 pogokeen 1032
        glBufferStorage(GL_ELEMENT_ARRAY_BUFFER, prindexringsize * sizeof(GLuint), NULL, prindexringmapflags | GL_DYNAMIC_STORAGE_BIT);
1033
        prindexring = (GLuint*)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, prindexringsize * sizeof(GLuint), prindexringmapflags);
5344 Plagman 1034
    }
5298 Plagman 1035
 
6656 pogokeen 1036
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
5298 Plagman 1037
 
304 Plagman 1038
    i = 0;
1039
    while (i < numsectors)
1040
    {
1041
        polymer_initsector(i);
1042
        polymer_updatesector(i);
1043
        i++;
1044
    }
1045
 
1046
    i = 0;
1047
    while (i < numwalls)
1048
    {
1049
        polymer_initwall(i);
1050
        polymer_updatewall(i);
1051
        i++;
1052
    }
1053
 
320 Plagman 1054
    polymer_getsky();
1055
 
1397 plagman 1056
    polymer_resetlights();
1057
 
1645 terminx 1058
    if (pr_verbosity >= 1 && numsectors) OSD_Printf("PR : Board loaded.\n");
304 Plagman 1059
}
662 plagman 1060
 
7620 pogokeen 1061
int32_t polymer_printtext256(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol, const char *name, char fontsize)
1062
{
1063
    //POGOTODO: Polymer should implement this so it's no longer coupled with Polymost & reliant on the fixed-function pipeline
1064
    glEnable(GL_TEXTURE_2D);
1065
    int32_t returnVal = polymost_printtext256(xpos, ypos, col, backcol, name, fontsize);
1066
    glDisable(GL_TEXTURE_2D);
1067
    return returnVal;
1068
}
1069
 
1070
void polymer_fillpolygon(int32_t npoints)
1071
{
1072
    //POGOTODO: Polymer should implement this so it's no longer coupled with Polymost & reliant on the fixed-function pipeline
1073
    glEnable(GL_TEXTURE_2D);
1074
    polymost_fillpolygon(npoints);
1075
    glDisable(GL_TEXTURE_2D);
1076
}
1077
 
3977 helixhorne 1078
// The parallaxed ART sky angle divisor corresponding to a horizfrac of 32768.
1079
#define DEFAULT_ARTSKY_ANGDIV 4.3027f
1080
 
6725 terminx 1081
void polymer_drawrooms(int32_t daposx, int32_t daposy, int32_t daposz, fix16_t daang, fix16_t dahoriz, int16_t dacursectnum)
304 Plagman 1082
{
1212 plagman 1083
    int16_t         cursectnum;
1291 plagman 1084
    int32_t         i, cursectflorz, cursectceilz;
1374 plagman 1085
    float           skyhoriz, ang, tiltang;
696 plagman 1086
    float           pos[3];
1374 plagman 1087
    pthtyp*         pth;
304 Plagman 1088
 
6829 terminx 1089
    if (videoGetRenderMode() == REND_CLASSIC) return;
1337 terminx 1090
 
6828 terminx 1091
    videoBeginDrawing();
1337 terminx 1092
 
1338 terminx 1093
    // TODO: support for screen resizing
5984 hendricks2 1094
    // frameoffset = frameplace + windowxy1.y*bytesperline + windowxy1.x;
1338 terminx 1095
 
304 Plagman 1096
    if (pr_verbosity >= 3) OSD_Printf("PR : Drawing rooms...\n");
1097
 
6558 hendricks2 1098
    // fogcalc_old needs this
1298 plagman 1099
    gvisibility = ((float)globalvisibility)*FOGSCALE;
1100
 
6725 terminx 1101
    ang = fix16_to_float(daang) * (360.f/2048.f);
7339 terminx 1102
    horizang = -(float)atan2f(fix16_to_float(dahoriz) - 100.f, 128.f) * (180.f * (float)M_1_PI);
310 Plagman 1103
    tiltang = (gtang * 90.0f);
1104
 
1457 terminx 1105
    pos[0] = (float)daposy;
697 plagman 1106
    pos[1] = -(float)(daposz) / 16.0f;
1457 terminx 1107
    pos[2] = -(float)daposx;
310 Plagman 1108
 
1397 plagman 1109
    polymer_updatelights();
1304 plagman 1110
 
1397 plagman 1111
//     polymer_resetlights();
1112
//     if (pr_lighting)
1113
//         polymer_applylights();
1114
 
1268 plagman 1115
    depth = 0;
1116
 
1332 plagman 1117
    if (pr_shadows && lightcount && (pr_shadowcount > 0))
1307 plagman 1118
        polymer_prepareshadows();
1119
 
1374 plagman 1120
    // hack for parallax skies
1121
    skyhoriz = horizang;
1122
    if (skyhoriz < -180.0f)
1123
        skyhoriz += 360.0f;
1124
 
1125
    drawingskybox = 1;
5464 hendricks2 1126
    pth = texcache_fetch(cursky, 0, 0, DAMETH_NOMASK);
1374 plagman 1127
    drawingskybox = 0;
1128
 
1129
    // if it's not a skybox, make the sky parallax
3977 helixhorne 1130
    // DEFAULT_ARTSKY_ANGDIV is computed from eyeballed values
1374 plagman 1131
    // need to recompute it if we ever change the max horiz amplitude
4486 helixhorne 1132
    if (!pth || !(pth->flags & PTH_SKYBOX))
3977 helixhorne 1133
        skyhoriz *= curskyangmul;
1374 plagman 1134
 
6656 pogokeen 1135
    glMatrixMode(GL_MODELVIEW);
1136
    glLoadIdentity();
310 Plagman 1137
 
6656 pogokeen 1138
    glRotatef(tiltang, 0.0f, 0.0f, -1.0f);
1139
    glRotatef(skyhoriz, 1.0f, 0.0f, 0.0f);
1140
    glRotatef(ang, 0.0f, 1.0f, 0.0f);
310 Plagman 1141
 
6656 pogokeen 1142
    glScalef(1.0f / 1000.0f, 1.0f / 1000.0f, 1.0f / 1000.0f);
1143
    glTranslatef(-pos[0], -pos[1], -pos[2]);
316 Plagman 1144
 
6656 pogokeen 1145
    glGetFloatv(GL_MODELVIEW_MATRIX, rootskymodelviewmatrix);
4600 terminx 1146
 
1373 plagman 1147
    curskymodelviewmatrix = rootskymodelviewmatrix;
1148
 
6656 pogokeen 1149
    glMatrixMode(GL_MODELVIEW);
1150
    glLoadIdentity();
1373 plagman 1151
 
6656 pogokeen 1152
    glRotatef(tiltang, 0.0f, 0.0f, -1.0f);
1153
    glRotatef(horizang, 1.0f, 0.0f, 0.0f);
1154
    glRotatef(ang, 0.0f, 1.0f, 0.0f);
1373 plagman 1155
 
6656 pogokeen 1156
    glScalef(1.0f / 1000.0f, 1.0f / 1000.0f, 1.0f / 1000.0f);
1157
    glTranslatef(-pos[0], -pos[1], -pos[2]);
310 Plagman 1158
 
6656 pogokeen 1159
    glGetFloatv(GL_MODELVIEW_MATRIX, rootmodelviewmatrix);
525 Plagman 1160
 
689 plagman 1161
    cursectnum = dacursectnum;
7484 terminx 1162
    updatesector(daposx, daposy, &cursectnum);
3037 helixhorne 1163
 
1164
    if (cursectnum >= 0 && cursectnum < numsectors)
689 plagman 1165
        dacursectnum = cursectnum;
2256 helixhorne 1166
    else if (pr_verbosity>=2)
1167
        OSD_Printf("PR : got sector %d after update!\n", cursectnum);
689 plagman 1168
 
717 plagman 1169
    // unflag all sectors
1425 terminx 1170
    i = numsectors-1;
1171
    while (i >= 0)
717 plagman 1172
    {
1428 plagman 1173
        prsectors[i]->flags.uptodate = 0;
717 plagman 1174
        prsectors[i]->wallsproffset = 0.0f;
1175
        prsectors[i]->floorsproffset = 0.0f;
1425 terminx 1176
        i--;
717 plagman 1177
    }
1425 terminx 1178
    i = numwalls-1;
1179
    while (i >= 0)
717 plagman 1180
    {
1428 plagman 1181
        prwalls[i]->flags.uptodate = 0;
1425 terminx 1182
        i--;
717 plagman 1183
    }
1184
 
1554 plagman 1185
    if (searchit == 2 && !polymersearching)
1186
    {
1187
        globaloldoverridematerial = overridematerial;
1188
        overridematerial = prprogrambits[PR_BIT_DIFFUSE_MODULATION].bit;
1758 plagman 1189
        overridematerial |= prprogrambits[PR_BIT_DIFFUSE_MAP2].bit;
1554 plagman 1190
        polymersearching = TRUE;
1191
    }
1192
    if (!searchit && polymersearching) {
1193
        overridematerial = globaloldoverridematerial;
1194
        polymersearching = FALSE;
1195
    }
1196
 
1657 terminx 1197
    if (dacursectnum > -1 && dacursectnum < numsectors)
1198
        getzsofslope(dacursectnum, daposx, daposy, &cursectceilz, &cursectflorz);
1291 plagman 1199
 
689 plagman 1200
    // external view (editor)
717 plagman 1201
    if ((dacursectnum < 0) || (dacursectnum >= numsectors) ||
1291 plagman 1202
            (daposz > cursectflorz) ||
1203
            (daposz < cursectceilz))
311 Plagman 1204
    {
5296 Plagman 1205
        prcanbucket = 1;
1206
 
2256 helixhorne 1207
        if (!editstatus && pr_verbosity>=1)
2565 helixhorne 1208
        {
1209
            if ((unsigned)dacursectnum < (unsigned)numsectors)
1210
                OSD_Printf("PR : EXT sec=%d  z=%d (%d, %d)\n", dacursectnum, daposz, cursectflorz, cursectceilz);
1211
            else
2566 helixhorne 1212
                OSD_Printf("PR : EXT sec=%d  z=%d\n", dacursectnum, daposz);
2565 helixhorne 1213
        }
2256 helixhorne 1214
 
1569 plagman 1215
        curmodelviewmatrix = rootmodelviewmatrix;
1425 terminx 1216
        i = numsectors-1;
1217
        while (i >= 0)
311 Plagman 1218
        {
1219
            polymer_updatesector(i);
1980 plagman 1220
            polymer_drawsector(i, FALSE);
697 plagman 1221
            polymer_scansprites(i, tsprite, &spritesortcnt);
1425 terminx 1222
            i--;
311 Plagman 1223
        }
1224
 
1425 terminx 1225
        i = numwalls-1;
1226
        while (i >= 0)
311 Plagman 1227
        {
1228
            polymer_updatewall(i);
699 plagman 1229
            polymer_drawwall(sectorofwall(i), i);
1425 terminx 1230
            i--;
320 Plagman 1231
        }
5296 Plagman 1232
 
1233
        polymer_emptybuckets();
1234
 
6760 terminx 1235
        viewangle = daang;
6828 terminx 1236
        videoEndDrawing();
320 Plagman 1237
        return;
1238
    }
331 terminx 1239
 
696 plagman 1240
    // GO!
1241
    polymer_displayrooms(dacursectnum);
525 Plagman 1242
 
1224 plagman 1243
    curmodelviewmatrix = rootmodelviewmatrix;
1244
 
1245
    // build globals used by rotatesprite
6760 terminx 1246
    viewangle = daang;
3471 helixhorne 1247
    set_globalang(daang);
662 plagman 1248
 
1224 plagman 1249
    // polymost globals used by polymost_dorotatesprite
5877 hendricks2 1250
    gcosang = fcosglobalang*(1./262144.f);
1251
    gsinang = fsinglobalang*(1./262144.f);
1252
    gcosang2 = gcosang*fviewingrange*(1./65536.f);
1253
    gsinang2 = gsinang*fviewingrange*(1./65536.f);
1224 plagman 1254
 
551 Plagman 1255
    if (pr_verbosity >= 3) OSD_Printf("PR : Rooms drawn.\n");
6828 terminx 1256
    videoEndDrawing();
525 Plagman 1257
}
1258
 
666 plagman 1259
void                polymer_drawmasks(void)
1260
{
6656 pogokeen 1261
    glEnable(GL_ALPHA_TEST);
1262
    glEnable(GL_BLEND);
1263
//     glEnable(GL_POLYGON_OFFSET_FILL);
670 plagman 1264
 
1980 plagman 1265
//     while (--spritesortcnt)
1266
//     {
1267
//         tspriteptr[spritesortcnt] = &tsprite[spritesortcnt];
1268
//         polymer_drawsprite(spritesortcnt);
1269
//     }
1270
 
6656 pogokeen 1271
    glEnable(GL_CULL_FACE);
1990 plagman 1272
 
1982 plagman 1273
    if (cursectormaskcount) {
1274
        // We (kind of) queue sector masks near to far, so drawing them in reverse
1275
        // order is the sane approach here. Of course impossible cases will arise.
1276
        while (*cursectormaskcount) {
1277
            polymer_drawsector(cursectormasks[--(*cursectormaskcount)], TRUE);
1278
        }
1279
 
1280
        // This should _always_ be called after a corresponding pr_displayrooms()
1281
        // unless we're in "external view" mode, which was checked above.
1282
        // Both the top-level game drawrooms and the recursive internal passes
1283
        // should be accounted for here. If these free cause corruption, there's
1284
        // an accounting bug somewhere.
5352 hendricks2 1285
        DO_FREE_AND_NULL(cursectormaskcount);
1286
        DO_FREE_AND_NULL(cursectormasks);
666 plagman 1287
    }
670 plagman 1288
 
6656 pogokeen 1289
    glDisable(GL_CULL_FACE);
1990 plagman 1290
 
6656 pogokeen 1291
//     glDisable(GL_POLYGON_OFFSET_FILL);
1292
    glDisable(GL_BLEND);
1293
    glDisable(GL_ALPHA_TEST);
666 plagman 1294
}
1295
 
1554 plagman 1296
void                polymer_editorpick(void)
1297
{
1298
    GLubyte         picked[3];
1299
    int16_t         num;
1300
 
6656 pogokeen 1301
    glReadPixels(searchx, ydim - searchy, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, picked);
1554 plagman 1302
 
5174 hendricks2 1303
    num = B_UNBUF16(&picked[1]);
1554 plagman 1304
 
1305
    searchstat = picked[0];
1306
 
1307
    switch (searchstat) {
1308
    case 0: // wall
1794 plagman 1309
    case 5: // botomwall
1554 plagman 1310
    case 4: // 1-way/masked wall
1575 plagman 1311
        searchsector = sectorofwall(num);
1554 plagman 1312
        searchbottomwall = searchwall = num;
1848 helixhorne 1313
        searchisbottom = (searchstat==5);
1794 plagman 1314
        if (searchstat == 5) {
1315
            searchstat = 0;
1316
            if (wall[num].nextwall >= 0 && (wall[num].cstat & 2)) {
1317
                searchbottomwall = wall[num].nextwall;
1318
            }
1319
        }
1554 plagman 1320
        break;
1321
    case 1: // floor
1322
    case 2: // ceiling
1323
        searchsector = num;
1710 helixhorne 1324
 
1325
        // Apologies to Plagman for littering here, but this feature is quite essential
1326
        {
1327
            GLdouble model[16];
1328
            GLdouble proj[16];
1329
            GLint view[4];
1330
 
1331
            GLdouble x,y,z;
1332
            GLfloat scr[3], scrv[3];
1333
            GLdouble scrx,scry,scrz;
1334
            GLfloat dadepth;
1335
 
1336
            int16_t k, bestk=0;
3178 helixhorne 1337
            GLfloat bestwdistsq = (GLfloat)3.4e38, wdistsq;
1710 helixhorne 1338
            GLfloat w1[2], w2[2], w21[2], pw1[2], pw2[2];
1339
            GLfloat ptonline[2];
1340
            GLfloat scrvxz[2];
1341
            GLfloat scrvxznorm, scrvxzn[2], scrpxz[2];
1342
            GLfloat w1d, w2d;
1343
            walltype *wal = &wall[sector[searchsector].wallptr];
1344
 
1345
            GLfloat t, svcoeff, p[2];
1346
            GLfloat *pl;
1347
 
6656 pogokeen 1348
            glGetDoublev(GL_MODELVIEW_MATRIX, model);
1349
            glGetDoublev(GL_PROJECTION_MATRIX, proj);
1350
            glGetIntegerv(GL_VIEWPORT, view);
1710 helixhorne 1351
 
6656 pogokeen 1352
            glReadPixels(searchx, ydim-searchy, 1,1, GL_DEPTH_COMPONENT, GL_FLOAT, &dadepth);
1710 helixhorne 1353
            bgluUnProject(searchx, ydim-searchy, dadepth,  model, proj, view,  &x, &y, &z);
1354
            bgluUnProject(searchx, ydim-searchy, 0.0,  model, proj, view,  &scrx, &scry, &scrz);
1355
 
1356
            scr[0]=scrx, scr[1]=scry, scr[2]=scrz;
1357
 
5294 Plagman 1358
            scrv[0] = x-scrx;
1359
            scrv[1] = y-scry;
1360
            scrv[2] = z-scrz;
1710 helixhorne 1361
 
1362
            scrvxz[0] = x-scrx;
1363
            scrvxz[1] = z-scrz;
1364
 
1843 helixhorne 1365
            if (prsectors[searchsector]==NULL)
1366
            {
1367
                //OSD_Printf("polymer_editorpick: prsectors[searchsector]==NULL !!!\n");
1368
                searchwall = sector[num].wallptr;
1369
            }
1710 helixhorne 1370
            else
1843 helixhorne 1371
            {
1372
                if (searchstat==1)
2610 helixhorne 1373
                    pl = prsectors[searchsector]->ceil.plane;
1843 helixhorne 1374
                else
2610 helixhorne 1375
                    pl = prsectors[searchsector]->floor.plane;
1710 helixhorne 1376
 
2610 helixhorne 1377
                if (pl == NULL)
1378
                {
1379
                    searchwall = sector[num].wallptr;
1380
                    return;
1381
                }
1382
 
1843 helixhorne 1383
                t = dot3f(pl,scrv);
1384
                svcoeff = -(dot3f(pl,scr)+pl[3])/t;
1710 helixhorne 1385
 
1843 helixhorne 1386
                // point on plane (x and z)
1387
                p[0] = scrx + svcoeff*scrv[0];
1388
                p[1] = scrz + svcoeff*scrv[2];
1710 helixhorne 1389
 
1843 helixhorne 1390
                for (k=0; k<sector[searchsector].wallnum; k++)
1391
                {
1392
                    w1[1] = -(float)wal[k].x;
1393
                    w1[0] = (float)wal[k].y;
1394
                    w2[1] = -(float)wall[wal[k].point2].x;
1395
                    w2[0] = (float)wall[wal[k].point2].y;
1710 helixhorne 1396
 
1843 helixhorne 1397
                    scrvxznorm = sqrt(dot2f(scrvxz,scrvxz));
1398
                    scrvxzn[0] = scrvxz[1]/scrvxznorm;
1399
                    scrvxzn[1] = -scrvxz[0]/scrvxznorm;
1710 helixhorne 1400
 
1843 helixhorne 1401
                    relvec2f(p,w1, pw1);
1402
                    relvec2f(p,w2, pw2);
1403
                    relvec2f(w2,w1, w21);
1710 helixhorne 1404
 
1843 helixhorne 1405
                    w1d = dot2f(scrvxzn,pw1);
1406
                    w2d = dot2f(scrvxzn,pw2);
1407
                    w2d = -w2d;
1408
                    if (w1d <= 0 || w2d <= 0)
1409
                        continue;
1710 helixhorne 1410
 
1843 helixhorne 1411
                    ptonline[0] = w2[0]+(w2d/(w1d+w2d))*w21[0];
1412
                    ptonline[1] = w2[1]+(w2d/(w1d+w2d))*w21[1];
1413
                    relvec2f(p,ptonline, scrpxz);
1414
                    if (dot2f(scrvxz,scrpxz)<0)
1415
                        continue;
1710 helixhorne 1416
 
1843 helixhorne 1417
                    wdistsq = dot2f(scrpxz,scrpxz);
1418
                    if (wdistsq < bestwdistsq)
1419
                    {
1420
                        bestk = k;
1421
                        bestwdistsq = wdistsq;
1422
                    }
1710 helixhorne 1423
                }
1843 helixhorne 1424
 
1425
                searchwall = sector[searchsector].wallptr + bestk;
1710 helixhorne 1426
            }
1427
        }
1428
        // :P
1429
 
1430
//        searchwall = sector[num].wallptr;
1554 plagman 1431
        break;
1432
    case 3:
1433
        // sprite
1575 plagman 1434
        searchsector = sprite[num].sectnum;
1554 plagman 1435
        searchwall = num;
1436
        break;
1437
    }
1438
 
1439
    searchit = 0;
1440
}
1441
 
5465 hendricks2 1442
void                polymer_inb4rotatesprite(int16_t tilenum, char pal, int8_t shade, int32_t method)
310 Plagman 1443
{
1812 plagman 1444
    _prmaterial     rotatespritematerial;
1445
 
5465 hendricks2 1446
    polymer_getbuildmaterial(&rotatespritematerial, tilenum, pal, shade, 0, method);
1812 plagman 1447
 
4600 terminx 1448
    rotatespritematerialbits = polymer_bindmaterial(&rotatespritematerial, NULL, 0);
310 Plagman 1449
}
1450
 
1812 plagman 1451
void                polymer_postrotatesprite(void)
1452
{
1453
    polymer_unbindmaterial(rotatespritematerialbits);
1454
}
1455
 
7072 terminx 1456
static void         polymer_setupdiffusemodulation(_prplane *plane, GLubyte modulation, const GLubyte *data)
4600 terminx 1457
{
1458
    plane->material.diffusemodulation[0] = modulation;
7072 terminx 1459
    plane->material.diffusemodulation[1] = ((GLubyte const *) data)[0];
1460
    plane->material.diffusemodulation[2] = ((GLubyte const *) data)[1];
4600 terminx 1461
    plane->material.diffusemodulation[3] = 0xFF;
6355 hendricks2 1462
}
4600 terminx 1463
 
6355 hendricks2 1464
static void         polymer_drawsearchplane(_prplane *plane, GLubyte *oldcolor, GLubyte modulation, GLubyte *data)
1465
{
1466
    Bmemcpy(oldcolor, plane->material.diffusemodulation, sizeof(GLubyte) * 4);
1467
 
1468
    polymer_setupdiffusemodulation(plane, modulation, data);
1469
 
4600 terminx 1470
    polymer_drawplane(plane);
1471
 
6355 hendricks2 1472
    Bmemcpy(plane->material.diffusemodulation, oldcolor, sizeof(GLubyte) * 4);
4600 terminx 1473
}
1474
 
1205 terminx 1475
void                polymer_drawmaskwall(int32_t damaskwallcnt)
310 Plagman 1476
{
7603 terminx 1477
    usectorptr_t      sec;
1298 plagman 1478
    walltype        *wal;
687 plagman 1479
    _prwall         *w;
1554 plagman 1480
    GLubyte         oldcolor[4];
687 plagman 1481
 
1482
    if (pr_verbosity >= 3) OSD_Printf("PR : Masked wall %i...\n", damaskwallcnt);
1483
 
7603 terminx 1484
    sec = (usectorptr_t)&sector[sectorofwall(maskwall[damaskwallcnt])];
1298 plagman 1485
    wal = &wall[maskwall[damaskwallcnt]];
687 plagman 1486
    w = prwalls[maskwall[damaskwallcnt]];
1487
 
6656 pogokeen 1488
    glEnable(GL_CULL_FACE);
1255 plagman 1489
 
1554 plagman 1490
    if (searchit == 2) {
4600 terminx 1491
        polymer_drawsearchplane(&w->mask, oldcolor, 0x04, (GLubyte *)&maskwall[damaskwallcnt]);
1978 plagman 1492
    } else {
7424 terminx 1493
        calc_and_apply_fog(fogshade(wal->shade, wal->pal), sec->visibility, get_floor_fogpal(sec));
4600 terminx 1494
        polymer_drawplane(&w->mask);
1554 plagman 1495
    }
1496
 
6656 pogokeen 1497
    glDisable(GL_CULL_FACE);
310 Plagman 1498
}
1499
 
1676 terminx 1500
void                polymer_drawsprite(int32_t snum)
1501
{
1502
    int32_t         i, j, cs;
1503
    _prsprite       *s;
1397 plagman 1504
 
7603 terminx 1505
    auto const tspr = tspriteptr[snum];
1506
    usectorptr_t sec;
3722 helixhorne 1507
 
1676 terminx 1508
    if (pr_verbosity >= 3) OSD_Printf("PR : Sprite %i...\n", snum);
1405 plagman 1509
 
3717 helixhorne 1510
    if (bad_tspr(tspr))
1511
        return;
1676 terminx 1512
 
8523 hendricks2 1513
    if ((tspr->clipdist & TSPR_FLAGS_NO_SHADOW) && (depth && !mirrors[depth-1].plane))
1676 terminx 1514
        return;
1515
 
8523 hendricks2 1516
    if ((tspr->clipdist & TSPR_FLAGS_INVISIBLE_WITH_SHADOW) && (!depth || mirrors[depth-1].plane))
1676 terminx 1517
        return;
1518
 
7873 terminx 1519
    int const spritenum = tspr->owner;
7889 pogokeen 1520
    Bassert(spritenum < MAXSPRITES+MAXUNIQHUDID);
3580 hendricks2 1521
 
7889 pogokeen 1522
    tileUpdatePicnum(&tspr->picnum, (unsigned)spritenum < MAXSPRITES ? spritenum+32768 : 0);
7873 terminx 1523
 
7603 terminx 1524
    sec = (usectorptr_t)&sector[tspr->sectnum];
1525
    calc_and_apply_fog(fogshade(tspr->shade, tspr->pal), sec->visibility, get_floor_fogpal((usectorptr_t)&sector[tspr->sectnum]));
1676 terminx 1526
 
1680 plagman 1527
    if (usemodels && tile2model[Ptile2tile(tspr->picnum,tspr->pal)].modelid >= 0 &&
1528
        tile2model[Ptile2tile(tspr->picnum,tspr->pal)].framenum >= 0 &&
7873 terminx 1529
        !(spriteext[spritenum].flags & SPREXT_NOTMD))
1235 plagman 1530
    {
6656 pogokeen 1531
        glEnable(GL_CULL_FACE);
2032 plagman 1532
        SWITCH_CULL_DIRECTION;
1676 terminx 1533
        polymer_drawmdsprite(tspr);
2032 plagman 1534
        SWITCH_CULL_DIRECTION;
6656 pogokeen 1535
        glDisable(GL_CULL_FACE);
1676 terminx 1536
        return;
1537
    }
1538
 
1539
    cs = tspr->cstat;
1540
 
1681 plagman 1541
    // I think messing with the tspr is safe at this point?
1542
    // If not, change that to modify a temp position in updatesprite itself.
1543
    // I don't think this flags are meant to change on the fly so it'd possibly
1544
    // be safe to cache a plane that has them applied.
7873 terminx 1545
    if (spriteext[spritenum].flags & SPREXT_AWAY1)
1681 plagman 1546
    {
1547
        tspr->x += sintable[(tspr->ang + 512) & 2047] >> 13;
1548
        tspr->y += sintable[tspr->ang & 2047] >> 13;
1549
    }
7873 terminx 1550
    else if (spriteext[spritenum].flags & SPREXT_AWAY2)
1681 plagman 1551
    {
1552
        tspr->x -= sintable[(tspr->ang + 512) & 2047] >> 13;
1553
        tspr->y -= sintable[tspr->ang & 2047] >> 13;
1554
    }
1555
 
1676 terminx 1556
    polymer_updatesprite(snum);
1557
 
7889 pogokeen 1558
    Bassert(spritenum < MAXSPRITES);
7873 terminx 1559
    s = prsprites[spritenum];
3722 helixhorne 1560
 
1561
    if (s == NULL)
1676 terminx 1562
        return;
1563
 
1564
    switch ((tspr->cstat>>4) & 3)
1565
    {
1566
    case 1:
1567
        prsectors[tspr->sectnum]->wallsproffset += 0.5f;
1568
        if (!depth || mirrors[depth-1].plane)
6656 pogokeen 1569
            glPolygonOffset(-1.0f, -1.0f);
1676 terminx 1570
        break;
1571
    case 2:
1572
        prsectors[tspr->sectnum]->floorsproffset += 0.5f;
1573
        if (!depth || mirrors[depth-1].plane)
6656 pogokeen 1574
            glPolygonOffset(-1.0f, -1.0f);
1676 terminx 1575
        break;
1576
    }
1577
 
1578
    if ((cs & 48) == 0)
1579
    {
1580
        int32_t curpriority = 0;
1581
 
1582
        s->plane.lightcount = 0;
1583
 
1584
        while ((curpriority < pr_maxlightpriority) && (!depth || mirrors[depth-1].plane))
1405 plagman 1585
        {
1676 terminx 1586
            i = j = 0;
1587
            while (j < lightcount)
1588
            {
1680 plagman 1589
                while (!prlights[i].flags.active)
1590
                    i++;
1405 plagman 1591
 
1680 plagman 1592
                if (prlights[i].priority != curpriority)
1593
                {
1594
                    i++;
1595
                    j++;
1596
                    continue;
1597
                }
1598
 
1676 terminx 1599
                if (polymer_planeinlight(&s->plane, &prlights[i]))
1680 plagman 1600
                    s->plane.lights[s->plane.lightcount++] = i;
1601
 
1405 plagman 1602
                i++;
1603
                j++;
1604
            }
1676 terminx 1605
            curpriority++;
1397 plagman 1606
        }
1235 plagman 1607
    }
1608
 
7873 terminx 1609
    if (automapping == 1)
1610
        show2dsprite[spritenum>>3] |= pow2char[spritenum&7];
1611
 
3869 helixhorne 1612
    if ((tspr->cstat & 64) && (tspr->cstat & SPR_ALIGN_MASK))
1613
    {
1614
        if ((tspr->cstat & SPR_ALIGN_MASK)==SPR_FLOOR && (tspr->cstat & SPR_YFLIP))
1615
            SWITCH_CULL_DIRECTION;
6656 pogokeen 1616
        glEnable(GL_CULL_FACE);
3869 helixhorne 1617
    }
691 plagman 1618
 
1676 terminx 1619
    if ((!depth || mirrors[depth-1].plane) && !pr_ati_nodepthoffset)
6656 pogokeen 1620
        glEnable(GL_POLYGON_OFFSET_FILL);
774 plagman 1621
 
1676 terminx 1622
    polymer_drawplane(&s->plane);
667 plagman 1623
 
1676 terminx 1624
    if ((!depth || mirrors[depth-1].plane) && !pr_ati_nodepthoffset)
6656 pogokeen 1625
        glDisable(GL_POLYGON_OFFSET_FILL);
774 plagman 1626
 
3869 helixhorne 1627
    if ((tspr->cstat & 64) && (tspr->cstat & SPR_ALIGN_MASK))
1628
    {
1629
        if ((tspr->cstat & SPR_ALIGN_MASK)==SPR_FLOOR && (tspr->cstat & SPR_YFLIP))
1630
            SWITCH_CULL_DIRECTION;
6656 pogokeen 1631
        glDisable(GL_CULL_FACE);
3869 helixhorne 1632
    }
310 Plagman 1633
}
1634
 
8428 hendricks2 1635
void                polymer_setanimatesprites(animatespritesptr animatesprites, int32_t x, int32_t y, int32_t z, int32_t a, int32_t smoothratio)
697 plagman 1636
{
1637
    asi.animatesprites = animatesprites;
1638
    asi.x = x;
1639
    asi.y = y;
8428 hendricks2 1640
    asi.z = z;
697 plagman 1641
    asi.a = a;
1642
    asi.smoothratio = smoothratio;
1643
}
1644
 
1397 plagman 1645
int16_t             polymer_addlight(_prlight* light)
1646
{
1457 terminx 1647
    int32_t         lighti;
1397 plagman 1648
 
1425 terminx 1649
    if (lightcount >= PR_MAXLIGHTS || light->priority > pr_maxlightpriority || !pr_lighting)
5803 terminx 1650
        return -1;
1417 plagman 1651
 
1397 plagman 1652
    if ((light->sector == -1) || (light->sector >= numsectors))
5803 terminx 1653
        return -1;
1397 plagman 1654
 
1655
    lighti = 0;
1676 terminx 1656
    while ((lighti < PR_MAXLIGHTS) && (prlights[lighti].flags.active))
1397 plagman 1657
        lighti++;
1658
 
1659
    if (lighti == PR_MAXLIGHTS)
5803 terminx 1660
        return -1;
3381 helixhorne 1661
#if 0
3027 helixhorne 1662
    // Spot lights disabled on ATI cards because they cause crashes with
1663
    // Catalyst 12.8 drivers.
1664
    // See: http://forums.duke4.net/topic/5723-hrp-polymer-crash/
1665
    if (pr_ati_fboworkaround && light->radius)
5803 terminx 1666
        return -1;
3381 helixhorne 1667
#endif
1425 terminx 1668
    Bmemcpy(&prlights[lighti], light, sizeof(_prlight));
1397 plagman 1669
 
3093 Plagman 1670
    if (light->radius) {
1397 plagman 1671
        polymer_processspotlight(&prlights[lighti]);
1672
 
2058 plagman 1673
        // get the texture handle for the lightmap
1674
        if (light->tilenum > 0) {
1675
            int16_t     picnum = light->tilenum;
1676
            pthtyp*     pth;
1677
 
7722 terminx 1678
            tileUpdatePicnum(&picnum, 0);
2058 plagman 1679
 
1680
            if (!waloff[picnum])
6830 terminx 1681
                tileLoad(picnum);
2058 plagman 1682
 
1683
            pth = NULL;
5464 hendricks2 1684
            pth = texcache_fetch(picnum, 0, 0, DAMETH_NOMASK);
2058 plagman 1685
 
1686
            if (pth)
1687
                light->lightmap = pth->glpic;
1688
        }
1689
    }
1690
 
1397 plagman 1691
    prlights[lighti].flags.isinview = 0;
1692
    prlights[lighti].flags.active = 1;
1693
 
2069 helixhorne 1694
    prlights[lighti].flags.invalidate = 0;
1695
 
1413 plagman 1696
    prlights[lighti].planecount = 0;
1697
    prlights[lighti].planelist = NULL;
1698
 
1397 plagman 1699
    polymer_culllight(lighti);
1700
 
1701
    lightcount++;
1702
 
5803 terminx 1703
    return lighti;
1397 plagman 1704
}
1705
 
1706
void                polymer_deletelight(int16_t lighti)
1707
{
1404 plagman 1708
    if (!prlights[lighti].flags.active)
2236 helixhorne 1709
    {
1710
#ifdef DEBUGGINGAIDS
2250 helixhorne 1711
        if (pr_verbosity >= 2)
2236 helixhorne 1712
            OSD_Printf("PR : Called polymer_deletelight on inactive light\n");
1713
        // currently known cases: when reloading maphack lights (didn't set maphacklightcnt=0
1714
        // but did loadmaphack()->delete_maphack_lights() after polymer_resetlights())
1715
#endif
1404 plagman 1716
        return;
2236 helixhorne 1717
    }
1404 plagman 1718
 
1397 plagman 1719
    polymer_removelight(lighti);
1720
 
1721
    prlights[lighti].flags.active = 0;
1722
 
1723
    lightcount--;
1724
}
1725
 
1425 terminx 1726
void                polymer_invalidatelights(void)
1727
{
1728
    int32_t         i = PR_MAXLIGHTS-1;
1729
 
1730
    do
1676 terminx 1731
        prlights[i].flags.invalidate = prlights[i].flags.active;
1425 terminx 1732
    while (i--);
1733
}
1734
 
1428 plagman 1735
void                polymer_texinvalidate(void)
1736
{
2053 plagman 1737
    int32_t         i;
1428 plagman 1738
 
2053 plagman 1739
    i = 0;
1740
 
1741
    while (i < MAXSPRITES) {
4303 helixhorne 1742
        polymer_invalidatesprite(i);
2053 plagman 1743
        i++;
1744
    }
1745
 
1746
    i = numsectors - 1;
1747
 
1676 terminx 1748
    if (!numsectors || !prsectors[i])
1430 terminx 1749
        return;
2053 plagman 1750
 
1676 terminx 1751
    do
1752
        prsectors[i--]->flags.invalidtex = 1;
1753
    while (i >= 0);
1430 terminx 1754
 
2053 plagman 1755
    i = numwalls - 1;
1676 terminx 1756
    do
1757
        prwalls[i--]->flags.invalidtex = 1;
1758
    while (i >= 0);
1428 plagman 1759
}
1760
 
1782 plagman 1761
void                polymer_definehighpalookup(char basepalnum, char palnum, char *data)
1748 plagman 1762
{
4491 helixhorne 1763
    prhighpalookups[basepalnum][palnum].data = (char *)Xmalloc(PR_HIGHPALOOKUP_DATA_SIZE);
5768 hendricks2 1764
 
1782 plagman 1765
    Bmemcpy(prhighpalookups[basepalnum][palnum].data, data, PR_HIGHPALOOKUP_DATA_SIZE);
1748 plagman 1766
}
1767
 
2056 plagman 1768
int32_t             polymer_havehighpalookup(int32_t basepalnum, int32_t palnum)
2045 helixhorne 1769
{
1770
    if ((uint32_t)basepalnum >= MAXBASEPALS || (uint32_t)palnum >= MAXPALOOKUPS)
1771
        return 0;
1772
 
1773
    return (prhighpalookups[basepalnum][palnum].data != NULL);
1774
}
1775
 
1776
 
696 plagman 1777
// CORE
4600 terminx 1778
static void         polymer_displayrooms(const int16_t dacursectnum)
696 plagman 1779
{
7603 terminx 1780
    usectorptr_t      sec;
1252 plagman 1781
    int32_t         i;
1975 plagman 1782
    int16_t         bunchnum;
1783
    int16_t         ns;
696 plagman 1784
    GLint           result;
1252 plagman 1785
    int16_t         doquery;
1212 plagman 1786
    int32_t         front;
1787
    int32_t         back;
1373 plagman 1788
    GLfloat         localskymodelviewmatrix[16];
1211 plagman 1789
    GLfloat         localmodelviewmatrix[16];
1268 plagman 1790
    GLfloat         localprojectionmatrix[16];
696 plagman 1791
    float           frustum[5 * 4];
1212 plagman 1792
    int32_t         localspritesortcnt;
8519 hendricks2 1793
    tspritetype     localtsprite[MAXSPRITESONSCREEN];
1313 plagman 1794
    int16_t         localmaskwall[MAXWALLSB];
1312 terminx 1795
    int16_t         localmaskwallcnt;
1255 plagman 1796
    _prmirror       mirrorlist[10];
1797
    int             mirrorcount;
1980 plagman 1798
    int16_t         *localsectormasks;
1799
    int16_t         *localsectormaskcount;
1255 plagman 1800
    int32_t         gx, gy, gz, px, py, pz;
1801
    GLdouble        plane[4];
1802
    float           coeff;
696 plagman 1803
 
1268 plagman 1804
    curmodelviewmatrix = localmodelviewmatrix;
6656 pogokeen 1805
    glGetFloatv(GL_MODELVIEW_MATRIX, localmodelviewmatrix);
1806
    glGetFloatv(GL_PROJECTION_MATRIX, localprojectionmatrix);
696 plagman 1807
 
1268 plagman 1808
    polymer_extractfrustum(localmodelviewmatrix, localprojectionmatrix, frustum);
696 plagman 1809
 
1332 plagman 1810
    Bmemset(querydelay, 0, sizeof(int16_t) * numsectors);
1811
    Bmemset(queryid, 0, sizeof(GLuint) * numwalls);
1812
    Bmemset(drawingstate, 0, sizeof(int16_t) * numsectors);
696 plagman 1813
 
1814
    front = 0;
1252 plagman 1815
    back = 1;
1816
    sectorqueue[0] = dacursectnum;
696 plagman 1817
    drawingstate[dacursectnum] = 1;
1818
 
1252 plagman 1819
    localspritesortcnt = localmaskwallcnt = 0;
696 plagman 1820
 
1255 plagman 1821
    mirrorcount = 0;
1822
 
4491 helixhorne 1823
    localsectormasks = (int16_t *)Xmalloc(sizeof(int16_t) * numsectors);
1824
    localsectormaskcount = (int16_t *)Xcalloc(sizeof(int16_t), 1);
1980 plagman 1825
    cursectormasks = localsectormasks;
1826
    cursectormaskcount = localsectormaskcount;
1827
 
6656 pogokeen 1828
    glDisable(GL_DEPTH_TEST);
1829
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1418 plagman 1830
    polymer_drawsky(cursky, curskypal, curskyshade);
6656 pogokeen 1831
    glEnable(GL_DEPTH_TEST);
1373 plagman 1832
 
1252 plagman 1833
    // depth-only occlusion testing pass
1255 plagman 1834
//     overridematerial = 0;
696 plagman 1835
 
5296 Plagman 1836
    prcanbucket = 1;
1837
 
1332 plagman 1838
    while (front != back)
696 plagman 1839
    {
7603 terminx 1840
        sec = (usectorptr_t)&sector[sectorqueue[front]];
696 plagman 1841
 
1842
        polymer_pokesector(sectorqueue[front]);
1980 plagman 1843
        polymer_drawsector(sectorqueue[front], FALSE);
697 plagman 1844
        polymer_scansprites(sectorqueue[front], localtsprite, &localspritesortcnt);
696 plagman 1845
 
1252 plagman 1846
        doquery = 0;
696 plagman 1847
 
1425 terminx 1848
        i = sec->wallnum-1;
1412 terminx 1849
        do
696 plagman 1850
        {
1413 plagman 1851
            // if we have a level boundary somewhere in the sector,
1852
            // consider these walls as visportals
5298 Plagman 1853
            if (wall[sec->wallptr + i].nextsector < 0 && pr_buckets == 0)
1413 plagman 1854
                doquery = 1;
1252 plagman 1855
        }
1676 terminx 1856
        while (--i >= 0);
1252 plagman 1857
 
1425 terminx 1858
        i = sec->wallnum-1;
1859
        while (i >= 0)
1252 plagman 1860
        {
1550 plagman 1861
            if ((wall[sec->wallptr + i].nextsector >= 0) &&
1394 plagman 1862
                (wallvisible(globalposx, globalposy, sec->wallptr + i)) &&
1267 plagman 1863
                (polymer_planeinfrustum(&prwalls[sec->wallptr + i]->mask, frustum)))
696 plagman 1864
            {
1328 plagman 1865
                if ((prwalls[sec->wallptr + i]->mask.vertcount == 4) &&
1866
                    !(prwalls[sec->wallptr + i]->underover & 4) &&
1867
                    !(prwalls[sec->wallptr + i]->underover & 8))
1320 plagman 1868
                {
1328 plagman 1869
                    // early exit for closed sectors
1320 plagman 1870
                    _prwall         *w;
1871
 
1872
                    w = prwalls[sec->wallptr + i];
1873
 
5294 Plagman 1874
                    if ((w->mask.buffer[0].y >= w->mask.buffer[3].y) &&
1875
                        (w->mask.buffer[1].y >= w->mask.buffer[2].y))
1320 plagman 1876
                    {
1425 terminx 1877
                        i--;
1320 plagman 1878
                        continue;
1879
                    }
1880
                }
1881
 
1979 plagman 1882
                if ((wall[sec->wallptr + i].cstat & 48) == 16)
4830 helixhorne 1883
                {
1884
                    int pic = wall[sec->wallptr + i].overpicnum;
1255 plagman 1885
 
4830 helixhorne 1886
                    if (tilesiz[pic].x > 0 && tilesiz[pic].y > 0)
1887
                        localmaskwall[localmaskwallcnt++] = sec->wallptr + i;
1888
                }
1889
 
1277 plagman 1890
                if (!depth && (overridematerial & prprogrambits[PR_BIT_MIRROR_MAP].bit) &&
1255 plagman 1891
                     wall[sec->wallptr + i].overpicnum == 560 &&
1287 plagman 1892
                     wall[sec->wallptr + i].cstat & 32)
1255 plagman 1893
                {
1287 plagman 1894
                    mirrorlist[mirrorcount].plane = &prwalls[sec->wallptr + i]->mask;
1255 plagman 1895
                    mirrorlist[mirrorcount].sectnum = sectorqueue[front];
1896
                    mirrorlist[mirrorcount].wallnum = sec->wallptr + i;
1897
                    mirrorcount++;
1898
                }
1899
 
1328 plagman 1900
                if (!(wall[sec->wallptr + i].cstat & 32)) {
1901
                    if (doquery && (!drawingstate[wall[sec->wallptr + i].nextsector]))
1902
                    {
1903
                        float pos[3], sqdist;
1904
                        int32_t oldoverridematerial;
696 plagman 1905
 
5877 hendricks2 1906
                        pos[0] = fglobalposy;
1907
                        pos[1] = fglobalposz * (-1.f/16.f);
1908
                        pos[2] = -fglobalposx;
696 plagman 1909
 
1328 plagman 1910
                        sqdist = prwalls[sec->wallptr + i]->mask.plane[0] * pos[0] +
1911
                                 prwalls[sec->wallptr + i]->mask.plane[1] * pos[1] +
1912
                                 prwalls[sec->wallptr + i]->mask.plane[2] * pos[2] +
1913
                                 prwalls[sec->wallptr + i]->mask.plane[3];
704 plagman 1914
 
1328 plagman 1915
                        // hack to avoid occlusion querying portals that are too close to the viewpoint
1916
                        // this is needed because of the near z-clipping plane;
1917
                        if (sqdist < 100)
1918
                            queryid[sec->wallptr + i] = 0xFFFFFFFF;
1919
                        else {
1920
                            _prwall         *w;
1255 plagman 1921
 
1328 plagman 1922
                            w = prwalls[sec->wallptr + i];
1255 plagman 1923
 
6656 pogokeen 1924
                            glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1925
                            glDepthMask(GL_FALSE);
696 plagman 1926
 
6656 pogokeen 1927
                            glGenQueries(1, &queryid[sec->wallptr + i]);
1928
                            glBeginQuery(GL_SAMPLES_PASSED, queryid[sec->wallptr + i]);
1270 plagman 1929
 
1328 plagman 1930
                            oldoverridematerial = overridematerial;
1931
                            overridematerial = 0;
1270 plagman 1932
 
1328 plagman 1933
                            if ((w->underover & 4) && (w->underover & 1))
1934
                                polymer_drawplane(&w->wall);
1935
                            polymer_drawplane(&w->mask);
1936
                            if ((w->underover & 8) && (w->underover & 2))
1937
                                polymer_drawplane(&w->over);
1270 plagman 1938
 
1328 plagman 1939
                            overridematerial = oldoverridematerial;
1940
 
6656 pogokeen 1941
                            glEndQuery(GL_SAMPLES_PASSED);
1328 plagman 1942
 
6656 pogokeen 1943
                            glDepthMask(GL_TRUE);
1944
                            glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1328 plagman 1945
                        }
1946
                    } else
1993 plagman 1947
                        queryid[sec->wallptr + i] = 0xFFFFFFFF;
1328 plagman 1948
                }
1252 plagman 1949
            }
696 plagman 1950
 
1425 terminx 1951
            i--;
1252 plagman 1952
        }
741 plagman 1953
 
1976 plagman 1954
        // Cram as much CPU or GPU work as we can between queuing the
1955
        // occlusion queries and reaping them.
1956
        i = sec->wallnum-1;
1957
        do
1958
        {
1959
            if (wallvisible(globalposx, globalposy, sec->wallptr + i))
1960
                polymer_drawwall(sectorqueue[front], sec->wallptr + i);
1961
        }
1962
        while (--i >= 0);
2204 helixhorne 1963
#ifdef YAX_ENABLE
1975 plagman 1964
        // queue ROR neighbors
3658 helixhorne 1965
        if ((bunchnum = yax_getbunch(sectorqueue[front], YAX_FLOOR)) >= 0) {
1975 plagman 1966
 
1967
            for (SECTORS_OF_BUNCH(bunchnum, YAX_CEILING, ns)) {
1968
 
1969
                if (ns >= 0 && !drawingstate[ns] &&
1970
                    polymer_planeinfrustum(&prsectors[ns]->ceil, frustum)) {
1971
 
1972
                    sectorqueue[back++] = ns;
1973
                    drawingstate[ns] = 1;
1974
                }
1975
            }
1976
        }
1977
 
3658 helixhorne 1978
        if ((bunchnum = yax_getbunch(sectorqueue[front], YAX_CEILING)) >= 0) {
1975 plagman 1979
 
1980
            for (SECTORS_OF_BUNCH(bunchnum, YAX_FLOOR, ns)) {
1981
 
1982
                if (ns >= 0 && !drawingstate[ns] &&
1983
                    polymer_planeinfrustum(&prsectors[ns]->floor, frustum)) {
1984
 
1985
                    sectorqueue[back++] = ns;
1986
                    drawingstate[ns] = 1;
1987
                }
1988
            }
1989
        }
2204 helixhorne 1990
#endif
1425 terminx 1991
        i = sec->wallnum-1;
1412 terminx 1992
        do
1252 plagman 1993
        {
1994
            if ((queryid[sec->wallptr + i]) &&
1995
                (!drawingstate[wall[sec->wallptr + i].nextsector]))
1996
            {
1997
                // REAP
1998
                result = 0;
1301 plagman 1999
                if (doquery && (queryid[sec->wallptr + i] != 0xFFFFFFFF))
1252 plagman 2000
                {
6656 pogokeen 2001
                    glGetQueryObjectiv(queryid[sec->wallptr + i],
2002
                                           GL_QUERY_RESULT,
1252 plagman 2003
                                           &result);
6656 pogokeen 2004
                    glDeleteQueries(1, &queryid[sec->wallptr + i]);
1301 plagman 2005
                } else if (queryid[sec->wallptr + i] == 0xFFFFFFFF)
1270 plagman 2006
                    result = 1;
2007
 
1252 plagman 2008
                queryid[sec->wallptr + i] = 0;
741 plagman 2009
 
1252 plagman 2010
                if (result || !doquery)
2011
                {
2012
                    sectorqueue[back++] = wall[sec->wallptr + i].nextsector;
2013
                    drawingstate[wall[sec->wallptr + i].nextsector] = 1;
2014
                }
1993 plagman 2015
            } else if (queryid[sec->wallptr + i] &&
2016
                       queryid[sec->wallptr + i] != 0xFFFFFFFF)
2017
            {
6656 pogokeen 2018
                glDeleteQueries(1, &queryid[sec->wallptr + i]);
1993 plagman 2019
                queryid[sec->wallptr + i] = 0;
1252 plagman 2020
            }
2021
        }
1676 terminx 2022
        while (--i >= 0);
696 plagman 2023
 
1252 plagman 2024
        front++;
2025
    }
696 plagman 2026
 
5296 Plagman 2027
    polymer_emptybuckets();
2028
 
1252 plagman 2029
    // do the actual shaded drawing
1255 plagman 2030
//     overridematerial = 0xFFFFFFFF;
696 plagman 2031
 
1252 plagman 2032
    // go through the sector queue again
1255 plagman 2033
//     front = 0;
2034
//     while (front < back)
2035
//     {
2036
//         sec = &sector[sectorqueue[front]];
5768 hendricks2 2037
//
1255 plagman 2038
//         polymer_drawsector(sectorqueue[front]);
5768 hendricks2 2039
//
1255 plagman 2040
//         i = 0;
2041
//         while (i < sec->wallnum)
2042
//         {
2043
//             polymer_drawwall(sectorqueue[front], sec->wallptr + i);
5768 hendricks2 2044
//
1255 plagman 2045
//             i++;
2046
//         }
5768 hendricks2 2047
//
1255 plagman 2048
//         front++;
2049
//     }
2050
 
1425 terminx 2051
    i = mirrorcount-1;
2052
    while (i >= 0)
1252 plagman 2053
    {
6656 pogokeen 2054
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prrts[0].fbo);
2055
        glPushAttrib(GL_VIEWPORT_BIT);
6939 pogokeen 2056
        glViewport(windowxy1.x, ydim-(windowxy2.y+1),windowxy2.x-windowxy1.x+1, windowxy2.y-windowxy1.y+1);
1252 plagman 2057
 
6656 pogokeen 2058
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1252 plagman 2059
 
1373 plagman 2060
        Bmemcpy(localskymodelviewmatrix, curskymodelviewmatrix, sizeof(GLfloat) * 16);
2061
        curskymodelviewmatrix = localskymodelviewmatrix;
2062
 
6656 pogokeen 2063
        glMatrixMode(GL_MODELVIEW);
2064
        glPushMatrix();
1252 plagman 2065
 
1255 plagman 2066
        plane[0] = mirrorlist[i].plane->plane[0];
2067
        plane[1] = mirrorlist[i].plane->plane[1];
2068
        plane[2] = mirrorlist[i].plane->plane[2];
2069
        plane[3] = mirrorlist[i].plane->plane[3];
1252 plagman 2070
 
6656 pogokeen 2071
        glClipPlane(GL_CLIP_PLANE0, plane);
1255 plagman 2072
        polymer_inb4mirror(mirrorlist[i].plane->buffer, mirrorlist[i].plane->plane);
2032 plagman 2073
        SWITCH_CULL_DIRECTION;
6656 pogokeen 2074
        //glEnable(GL_CLIP_PLANE0);
1255 plagman 2075
 
2076
        if (mirrorlist[i].wallnum >= 0)
7736 pogokeen 2077
            renderPrepareMirror(globalposx, globalposy, globalposz, qglobalang, qglobalhoriz,
2078
                                mirrorlist[i].wallnum, &gx, &gy, &viewangle);
1255 plagman 2079
 
2080
        gx = globalposx;
2081
        gy = globalposy;
2082
        gz = globalposz;
2083
 
2084
        // map the player pos from build to polymer
2085
        px = globalposy;
2086
        py = -globalposz / 16;
2087
        pz = -globalposx;
2088
 
2089
        // calculate new player position on the other side of the mirror
2090
        // this way the basic build visibility shit can be used (wallvisible)
2091
        coeff = mirrorlist[i].plane->plane[0] * px +
2092
                mirrorlist[i].plane->plane[1] * py +
2093
                mirrorlist[i].plane->plane[2] * pz +
2094
                mirrorlist[i].plane->plane[3];
2095
 
2096
        coeff /= (float)(mirrorlist[i].plane->plane[0] * mirrorlist[i].plane->plane[0] +
2097
                         mirrorlist[i].plane->plane[1] * mirrorlist[i].plane->plane[1] +
2098
                         mirrorlist[i].plane->plane[2] * mirrorlist[i].plane->plane[2]);
2099
 
1457 terminx 2100
        px = (int32_t)(-coeff*mirrorlist[i].plane->plane[0]*2 + px);
2101
        py = (int32_t)(-coeff*mirrorlist[i].plane->plane[1]*2 + py);
2102
        pz = (int32_t)(-coeff*mirrorlist[i].plane->plane[2]*2 + pz);
1255 plagman 2103
 
2104
        // map back from polymer to build
4667 terminx 2105
        set_globalpos(-pz, px, -py * 16);
1255 plagman 2106
 
2107
        mirrors[depth++] = mirrorlist[i];
2108
        polymer_displayrooms(mirrorlist[i].sectnum);
2109
        depth--;
2110
 
1980 plagman 2111
        cursectormasks = localsectormasks;
2112
        cursectormaskcount = localsectormaskcount;
2113
 
4667 terminx 2114
        set_globalpos(gx, gy, gz);
1255 plagman 2115
 
6656 pogokeen 2116
        glDisable(GL_CLIP_PLANE0);
2032 plagman 2117
        SWITCH_CULL_DIRECTION;
6656 pogokeen 2118
        glMatrixMode(GL_MODELVIEW);
2119
        glPopMatrix();
1255 plagman 2120
 
6656 pogokeen 2121
        glPopAttrib();
2122
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1255 plagman 2123
 
2124
        mirrorlist[i].plane->material.mirrormap = prrts[0].color;
2125
        polymer_drawplane(mirrorlist[i].plane);
2126
        mirrorlist[i].plane->material.mirrormap = 0;
2127
 
1425 terminx 2128
        i--;
696 plagman 2129
    }
2130
 
697 plagman 2131
    spritesortcnt = localspritesortcnt;
8519 hendricks2 2132
    Bmemcpy(tsprite, localtsprite, sizeof(tspritetype) * spritesortcnt);
697 plagman 2133
    maskwallcnt = localmaskwallcnt;
1332 plagman 2134
    Bmemcpy(maskwall, localmaskwall, sizeof(int16_t) * maskwallcnt);
697 plagman 2135
 
1255 plagman 2136
    if (depth)
2137
    {
3471 helixhorne 2138
        set_globalang(viewangle);
1255 plagman 2139
 
1272 plagman 2140
        if (mirrors[depth - 1].plane)
2141
            display_mirror = 1;
1255 plagman 2142
        polymer_animatesprites();
1272 plagman 2143
        if (mirrors[depth - 1].plane)
2144
            display_mirror = 0;
1255 plagman 2145
 
6656 pogokeen 2146
        glDisable(GL_CULL_FACE);
6831 terminx 2147
        renderDrawMasks();
6656 pogokeen 2148
        glEnable(GL_CULL_FACE);
1255 plagman 2149
    }
7072 terminx 2150
    }
696 plagman 2151
 
5296 Plagman 2152
static void         polymer_emptybuckets(void)
2153
{
2154
    _prbucket *bucket = prbuckethead;
2155
 
5344 Plagman 2156
    if (pr_buckets == 0)
2157
        return;
2158
 
6656 pogokeen 2159
    glBindBuffer(GL_ARRAY_BUFFER, prmapvbo);
2160
    glVertexPointer(3, GL_FLOAT, sizeof(_prvert), NULL);
2161
    glTexCoordPointer(2, GL_FLOAT, sizeof(_prvert), (GLvoid *)(3 * sizeof(GLfloat)));
5296 Plagman 2162
 
6656 pogokeen 2163
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, prindexringvbo);
5298 Plagman 2164
 
2165
    uint32_t indexcount = 0;
5296 Plagman 2166
    while (bucket != NULL)
2167
    {
5298 Plagman 2168
        indexcount += bucket->count;
2169
 
2170
        bucket = bucket->next;
2171
    }
2172
 
2173
    // ensure space in index ring, wrap otherwise
5456 hendricks2 2174
    if (indexcount + prindexringoffset >= (unsigned)prindexringsize)
5298 Plagman 2175
    {
6656 pogokeen 2176
        glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
2177
        prindexring = (GLuint *)glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, prindexringsize * sizeof(GLuint), GL_MAP_INVALIDATE_BUFFER_BIT | prindexringmapflags);
5298 Plagman 2178
        prindexringoffset = 0;
2179
    }
2180
 
2181
    // put indices in the ring, all at once
2182
    bucket = prbuckethead;
2183
 
2184
    while (bucket != NULL)
2185
    {
5296 Plagman 2186
        if (bucket->count == 0)
2187
        {
2188
            bucket = bucket->next;
2189
            continue;
2190
        }
2191
 
5298 Plagman 2192
        memcpy(&prindexring[prindexringoffset], bucket->indices, bucket->count * sizeof(GLuint));
2193
 
2194
        bucket->indiceoffset = (GLuint*)(prindexringoffset * sizeof(GLuint));
2195
 
2196
        prindexringoffset += bucket->count;
2197
 
2198
        bucket = bucket->next;
2199
    }
2200
 
2201
    bucket = prbuckethead;
2202
 
2203
    while (bucket != NULL)
2204
    {
2205
        if (bucket->count == 0)
2206
        {
2207
            bucket = bucket->next;
2208
            continue;
2209
        }
2210
 
5296 Plagman 2211
        int32_t materialbits = polymer_bindmaterial(&bucket->material, NULL, 0);
2212
 
6656 pogokeen 2213
        glDrawElements(GL_TRIANGLES, bucket->count, GL_UNSIGNED_INT, bucket->indiceoffset);
5296 Plagman 2214
 
2215
        polymer_unbindmaterial(materialbits);
2216
 
2217
        bucket->count = 0;
2218
 
2219
        bucket = bucket->next;
2220
    }
2221
 
6656 pogokeen 2222
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
2223
    glBindBuffer(GL_ARRAY_BUFFER, 0);
5296 Plagman 2224
 
2225
    prcanbucket = 0;
2226
}
2227
 
6061 hendricks2 2228
static hashtable_t h_buckets      = { 2048, NULL };
5479 terminx 2229
 
5296 Plagman 2230
static _prbucket*   polymer_findbucket(int16_t tilenum, char pal)
2231
{
5479 terminx 2232
    char propstr[16];
5296 Plagman 2233
 
5479 terminx 2234
    Bsprintf(propstr, "%d_%d", tilenum, pal);
2235
 
2236
    _prbucket *bucketptr = prbuckethead ? (_prbucket *)hash_find(&h_buckets, propstr) : NULL;
2237
 
5296 Plagman 2238
    // find bucket
2239
 
2240
    // no buckets or no bucket found, create one
5479 terminx 2241
    if (bucketptr == NULL || (intptr_t)bucketptr == -1)
5296 Plagman 2242
    {
2243
        bucketptr = (_prbucket *)Xmalloc(sizeof (_prbucket));
2244
 
5479 terminx 2245
        if (h_buckets.items == NULL)
2246
            hash_init(&h_buckets);
2247
 
5296 Plagman 2248
        // insert, since most likely to use same pattern next frame
2249
        // will need to reorder by MRU first every once in a while
2250
        // or move to hashing lookup
2251
        bucketptr->next = prbuckethead;
2252
        prbuckethead = bucketptr;
2253
 
2254
        bucketptr->tilenum = tilenum;
2255
        bucketptr->pal = pal;
2256
 
2257
        bucketptr->invalidmaterial = 1;
2258
 
2259
        bucketptr->count = 0;
2260
        bucketptr->buffersize = 1024;
2261
        bucketptr->indices = (GLuint *)Xmalloc(bucketptr->buffersize * sizeof(GLuint));
5479 terminx 2262
 
2263
        hash_add(&h_buckets, propstr, (intptr_t)bucketptr, 1);
5296 Plagman 2264
    }
2265
 
2266
    return bucketptr;
2267
}
2268
 
2269
static void         polymer_bucketplane(_prplane* plane)
2270
{
2271
    _prbucket *bucketptr = plane->bucket;
2272
    uint32_t neededindicecount;
5344 Plagman 2273
    int32_t i;
5296 Plagman 2274
 
2275
    // we don't keep buffers for quads
2276
    neededindicecount = (plane->indicescount == 0) ? 6 : plane->indicescount;
2277
 
2278
    // ensure size
2279
    while (bucketptr->count + neededindicecount >= bucketptr->buffersize)
2280
    {
2281
        bucketptr->buffersize *= 2;
2282
        bucketptr->indices = (GLuint *)Xrealloc(bucketptr->indices, bucketptr->buffersize * sizeof(GLuint));
2283
    }
2284
 
2285
    // queue indices
2286
    i = 0;
2287
 
2288
    if (plane->indicescount > 0)
2289
    {
2290
        while (i < plane->indicescount)
2291
        {
2292
            bucketptr->indices[bucketptr->count] = plane->indices[i] + plane->mapvbo_vertoffset;
2293
            bucketptr->count++;
2294
            i++;
2295
        }
2296
    }
2297
    else
2298
    {
2299
        static const uint32_t quadindices[6] = { 0, 1, 2, 0, 2, 3 };
2300
 
2301
        while (i < 6)
2302
        {
2303
            bucketptr->indices[bucketptr->count] = quadindices[i] + plane->mapvbo_vertoffset;
2304
            bucketptr->count++;
2305
            i++;
2306
        }
2307
    }
2308
}
2309
 
1255 plagman 2310
static void         polymer_drawplane(_prplane* plane)
696 plagman 2311
{
1212 plagman 2312
    int32_t         materialbits;
699 plagman 2313
 
5294 Plagman 2314
    if (pr_nullrender >= 1) return;
5266 Plagman 2315
 
1241 plagman 2316
    // debug code for drawing plane inverse TBN
6656 pogokeen 2317
//     glDisable(GL_TEXTURE_2D);
2318
//     glBegin(GL_LINES);
2319
//     glColor4f(1.0, 0.0, 0.0, 1.0);
2320
//     glVertex3f(plane->buffer[0],
1241 plagman 2321
//                 plane->buffer[1],
2322
//                 plane->buffer[2]);
6656 pogokeen 2323
//     glVertex3f(plane->buffer[0] + plane->t[0] * 50,
1241 plagman 2324
//                 plane->buffer[1] + plane->t[1] * 50,
2325
//                 plane->buffer[2] + plane->t[2] * 50);
6656 pogokeen 2326
//     glColor4f(0.0, 1.0, 0.0, 1.0);
2327
//     glVertex3f(plane->buffer[0],
1241 plagman 2328
//                 plane->buffer[1],
2329
//                 plane->buffer[2]);
6656 pogokeen 2330
//     glVertex3f(plane->buffer[0] + plane->b[0] * 50,
1241 plagman 2331
//                 plane->buffer[1] + plane->b[1] * 50,
2332
//                 plane->buffer[2] + plane->b[2] * 50);
6656 pogokeen 2333
//     glColor4f(0.0, 0.0, 1.0, 1.0);
2334
//     glVertex3f(plane->buffer[0],
1241 plagman 2335
//                 plane->buffer[1],
2336
//                 plane->buffer[2]);
6656 pogokeen 2337
//     glVertex3f(plane->buffer[0] + plane->n[0] * 50,
1241 plagman 2338
//                 plane->buffer[1] + plane->n[1] * 50,
2339
//                 plane->buffer[2] + plane->n[2] * 50);
6656 pogokeen 2340
//     glEnd();
2341
//     glEnable(GL_TEXTURE_2D);
1241 plagman 2342
 
2343
    // debug code for drawing plane normals
6656 pogokeen 2344
//     glDisable(GL_TEXTURE_2D);
2345
//     glBegin(GL_LINES);
2346
//     glColor4f(1.0, 1.0, 1.0, 1.0);
2347
//     glVertex3f(plane->buffer[0],
1241 plagman 2348
//                 plane->buffer[1],
2349
//                 plane->buffer[2]);
6656 pogokeen 2350
//     glVertex3f(plane->buffer[0] + plane->plane[0] * 50,
1241 plagman 2351
//                 plane->buffer[1] + plane->plane[1] * 50,
2352
//                 plane->buffer[2] + plane->plane[2] * 50);
6656 pogokeen 2353
//     glEnd();
2354
//     glEnable(GL_TEXTURE_2D);
1241 plagman 2355
 
5296 Plagman 2356
    if (pr_buckets && pr_vbos > 0 && prcanbucket && plane->bucket)
2357
    {
2358
        polymer_bucketplane(plane);
2359
        return;
2360
    }
2361
 
6656 pogokeen 2362
    glNormal3f((float)(plane->plane[0]), (float)(plane->plane[1]), (float)(plane->plane[2]));
699 plagman 2363
 
5294 Plagman 2364
    GLuint planevbo;
6656 pogokeen 2365
    GLintptr geomfbooffset;
5294 Plagman 2366
 
6760 terminx 2367
    if (plane->mapvbo_vertoffset != (uint32_t)-1)
1263 plagman 2368
    {
5294 Plagman 2369
        planevbo = prmapvbo;
5296 Plagman 2370
        geomfbooffset = plane->mapvbo_vertoffset * sizeof(_prvert);
5294 Plagman 2371
    }
2372
    else
2373
    {
2374
        planevbo = plane->vbo;
5295 Plagman 2375
        geomfbooffset = 0;
5294 Plagman 2376
    }
2377
 
2378
    if (planevbo && (pr_vbos > 0))
2379
    {
6656 pogokeen 2380
        glBindBuffer(GL_ARRAY_BUFFER, planevbo);
2381
        glVertexPointer(3, GL_FLOAT, sizeof(_prvert), (GLvoid *)(geomfbooffset));
2382
        glTexCoordPointer(2, GL_FLOAT, sizeof(_prvert), (GLvoid *)(geomfbooffset + (3 * sizeof(GLfloat))));
1263 plagman 2383
        if (plane->indices)
6656 pogokeen 2384
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, plane->ivbo);
1263 plagman 2385
    } else {
6656 pogokeen 2386
        glVertexPointer(3, GL_FLOAT, sizeof(_prvert), &plane->buffer->x);
2387
        glTexCoordPointer(2, GL_FLOAT, sizeof(_prvert), &plane->buffer->u);
1263 plagman 2388
    }
2389
 
1413 plagman 2390
    curlight = 0;
2391
    do {
4600 terminx 2392
        materialbits = polymer_bindmaterial(&plane->material, plane->lights, plane->lightcount);
1242 plagman 2393
 
1244 plagman 2394
        if (materialbits & prprogrambits[PR_BIT_NORMAL_MAP].bit)
2395
        {
6656 pogokeen 2396
            glVertexAttrib3fv(prprograms[materialbits].attrib_T, &plane->tbn[0][0]);
2397
            glVertexAttrib3fv(prprograms[materialbits].attrib_B, &plane->tbn[1][0]);
2398
            glVertexAttrib3fv(prprograms[materialbits].attrib_N, &plane->tbn[2][0]);
1244 plagman 2399
        }
2400
 
1263 plagman 2401
        if (plane->indices)
1242 plagman 2402
        {
5294 Plagman 2403
            if (planevbo && (pr_vbos > 0))
6656 pogokeen 2404
                glDrawElements(GL_TRIANGLES, plane->indicescount, GL_UNSIGNED_SHORT, NULL);
1263 plagman 2405
            else
6656 pogokeen 2406
                glDrawElements(GL_TRIANGLES, plane->indicescount, GL_UNSIGNED_SHORT, plane->indices);
1263 plagman 2407
        } else
6656 pogokeen 2408
            glDrawArrays(GL_QUADS, 0, 4);
1242 plagman 2409
 
2410
        polymer_unbindmaterial(materialbits);
2411
 
1397 plagman 2412
        if (plane->lightcount && (!depth || mirrors[depth-1].plane))
2413
            prlights[plane->lights[curlight]].flags.isinview = 1;
2414
 
1242 plagman 2415
        curlight++;
1416 plagman 2416
    } while ((curlight < plane->lightcount) && (curlight < pr_maxlightpasses) && (!depth || mirrors[depth-1].plane));
1263 plagman 2417
 
5294 Plagman 2418
    if (planevbo && (pr_vbos > 0))
1263 plagman 2419
    {
6656 pogokeen 2420
        glBindBuffer(GL_ARRAY_BUFFER, 0);
1263 plagman 2421
        if (plane->indices)
6656 pogokeen 2422
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1263 plagman 2423
    }
699 plagman 2424
}
2425
 
7072 terminx 2426
static inline void  polymer_inb4mirror(_prvert* buffer, const GLfloat* plane)
699 plagman 2427
{
696 plagman 2428
    float           pv;
2429
    float           reflectionmatrix[16];
2430
 
5294 Plagman 2431
    pv = buffer->x * plane[0] +
2432
         buffer->y * plane[1] +
2433
         buffer->z * plane[2];
696 plagman 2434
 
699 plagman 2435
    reflectionmatrix[0] = 1 - (2 * plane[0] * plane[0]);
2436
    reflectionmatrix[1] = -2 * plane[0] * plane[1];
2437
    reflectionmatrix[2] = -2 * plane[0] * plane[2];
696 plagman 2438
    reflectionmatrix[3] = 0;
2439
 
699 plagman 2440
    reflectionmatrix[4] = -2 * plane[0] * plane[1];
2441
    reflectionmatrix[5] = 1 - (2 * plane[1] * plane[1]);
2442
    reflectionmatrix[6] = -2 * plane[1] * plane[2];
696 plagman 2443
    reflectionmatrix[7] = 0;
2444
 
699 plagman 2445
    reflectionmatrix[8] = -2 * plane[0] * plane[2];
2446
    reflectionmatrix[9] = -2 * plane[1] * plane[2];
2447
    reflectionmatrix[10] = 1 - (2 * plane[2] * plane[2]);
696 plagman 2448
    reflectionmatrix[11] = 0;
2449
 
699 plagman 2450
    reflectionmatrix[12] = 2 * pv * plane[0];
2451
    reflectionmatrix[13] = 2 * pv * plane[1];
2452
    reflectionmatrix[14] = 2 * pv * plane[2];
696 plagman 2453
    reflectionmatrix[15] = 1;
2454
 
6656 pogokeen 2455
    glMultMatrixf(reflectionmatrix);
1373 plagman 2456
 
6656 pogokeen 2457
    glPushMatrix();
2458
    glLoadMatrixf(curskymodelviewmatrix);
2459
    glMultMatrixf(reflectionmatrix);
2460
    glGetFloatv(GL_MODELVIEW_MATRIX, curskymodelviewmatrix);
2461
    glPopMatrix();
696 plagman 2462
}
2463
 
697 plagman 2464
static void         polymer_animatesprites(void)
2465
{
719 plagman 2466
    if (asi.animatesprites)
8428 hendricks2 2467
        asi.animatesprites(globalposx, globalposy, globalposz, fix16_to_int(viewangle), asi.smoothratio);
697 plagman 2468
}
2469
 
1390 terminx 2470
static void         polymer_freeboard(void)
1387 plagman 2471
{
2472
    int32_t         i;
2473
 
2474
    i = 0;
2475
    while (i < MAXSECTORS)
2476
    {
2477
        if (prsectors[i])
2478
        {
7705 terminx 2479
            Xfree(prsectors[i]->verts);
2480
            Xfree(prsectors[i]->floor.buffer);
2481
            Xfree(prsectors[i]->ceil.buffer);
2482
  &n