2006-04-13 20:47:06 +00:00
|
|
|
/**************************************************************************************************
|
2015-02-11 05:23:04 +00:00
|
|
|
"POLYMOST" code originally written by Ken Silverman
|
2006-04-13 20:47:06 +00:00
|
|
|
Ken Silverman's official web site: http://www.advsys.net/ken
|
2018-02-16 06:38:34 +00:00
|
|
|
|
|
|
|
"POLYMOST2" changes Copyright (c) 2018, Alex Dawson
|
2006-04-13 20:47:06 +00:00
|
|
|
**************************************************************************************************/
|
|
|
|
|
2008-12-02 10:44:39 +00:00
|
|
|
|
2011-03-04 08:50:58 +00:00
|
|
|
#ifdef USE_OPENGL
|
2008-12-02 10:44:39 +00:00
|
|
|
|
|
|
|
#include "compat.h"
|
|
|
|
#include "build.h"
|
2018-02-16 06:38:21 +00:00
|
|
|
#include "glad/glad.h"
|
2013-05-15 02:17:17 +00:00
|
|
|
#include "mdsprite.h"
|
2008-12-02 10:44:39 +00:00
|
|
|
#include "pragmas.h"
|
|
|
|
#include "baselayer.h"
|
|
|
|
#include "osd.h"
|
|
|
|
#include "engine_priv.h"
|
|
|
|
#include "hightile.h"
|
|
|
|
#include "polymost.h"
|
2010-01-23 22:12:02 +00:00
|
|
|
#include "polymer.h"
|
2008-12-02 10:44:39 +00:00
|
|
|
#include "cache1d.h"
|
|
|
|
#include "kplib.h"
|
2013-05-15 02:17:17 +00:00
|
|
|
#include "texcache.h"
|
2014-10-25 03:26:31 +00:00
|
|
|
#include "common.h"
|
2016-06-21 00:33:06 +00:00
|
|
|
#include "palette.h"
|
2018-05-08 17:32:16 +00:00
|
|
|
#include "tilepacker.h"
|
2019-09-16 17:35:04 +00:00
|
|
|
#include "../../glbackend/glbackend.h"
|
2008-12-02 10:44:39 +00:00
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
#include "vfs.h"
|
2010-05-25 10:56:00 +00:00
|
|
|
|
2008-12-02 10:44:39 +00:00
|
|
|
extern char textfont[2048], smalltextfont[2048];
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t rendmode=0;
|
2014-04-14 16:30:23 +00:00
|
|
|
int32_t usemodels=1;
|
|
|
|
int32_t usehightile=1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-09-04 19:44:07 +00:00
|
|
|
typedef struct { float x, cy[2], fy[2]; int32_t tag; int16_t n, p, ctag, ftag; } vsptyp;
|
2017-11-30 23:54:18 +00:00
|
|
|
#define VSPMAX 2048 //<- careful!
|
2006-04-13 20:47:06 +00:00
|
|
|
static vsptyp vsp[VSPMAX];
|
2011-09-04 19:44:07 +00:00
|
|
|
static int32_t gtag;
|
2019-03-19 17:07:53 +00:00
|
|
|
static float xbl, xbr, xbt, xbb;
|
2019-03-02 23:22:12 +00:00
|
|
|
int32_t domost_rejectcount;
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
typedef struct { float x, cy[2]; int32_t tag; int16_t n, p, ctag; } yax_vsptyp;
|
|
|
|
static yax_vsptyp yax_vsp[YAX_MAXBUNCHES*2][VSPMAX];
|
|
|
|
typedef struct { float x0, x1, cy[2], fy[2]; } yax_hole_t;
|
|
|
|
static yax_hole_t yax_holecf[2][VSPMAX];
|
|
|
|
static int32_t yax_holencf[2];
|
|
|
|
static int32_t yax_drawcf = -1;
|
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-09-30 04:06:05 +00:00
|
|
|
static float dxb1[MAXWALLSB], dxb2[MAXWALLSB];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
#define SCISDIST 1.0f //1.0: Close plane clipping distance
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
#define SOFTROTMAT 0
|
|
|
|
|
2013-01-17 21:59:17 +00:00
|
|
|
float shadescale = 1.0f;
|
2011-03-17 23:37:38 +00:00
|
|
|
int32_t shadescale_unbounded = 0;
|
2006-12-04 04:08:14 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
int32_t r_enablepolymost2 = 0;
|
2018-03-21 20:41:26 +00:00
|
|
|
int32_t r_pogoDebug = 0;
|
2017-11-29 07:29:33 +00:00
|
|
|
int32_t r_usenewshading = 4;
|
2014-05-01 16:55:50 +00:00
|
|
|
int32_t r_usetileshades = 2;
|
2019-03-19 17:08:43 +00:00
|
|
|
int32_t r_npotwallmode = 2;
|
2011-07-24 15:15:57 +00:00
|
|
|
|
2014-09-30 04:06:05 +00:00
|
|
|
static float gviewxrange;
|
|
|
|
static float ghoriz;
|
2019-03-19 17:08:05 +00:00
|
|
|
double gxyaspect;
|
2014-09-30 04:06:05 +00:00
|
|
|
float gyxscale, ghalfx, grhalfxdown10, grhalfxdown10x;
|
|
|
|
float gcosang, gsinang, gcosang2, gsinang2;
|
|
|
|
float gchang, gshang, gctang, gstang, gvisibility;
|
|
|
|
float gtang = 0.f;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-03-19 17:08:43 +00:00
|
|
|
static vec3d_t xtex, ytex, otex, xtex2, ytex2, otex2;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2014-10-25 03:32:26 +00:00
|
|
|
float fcosglobalang, fsinglobalang;
|
2014-11-28 08:14:00 +00:00
|
|
|
float fxdim, fydim, fydimen, fviewingrange;
|
2015-07-08 03:34:27 +00:00
|
|
|
static int32_t preview_mouseaim=1; // when 1, displays a CROSSHAIR tsprite at the _real_ aimed position
|
2010-09-06 23:08:35 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
static int32_t drawpoly_srepeat = 0, drawpoly_trepeat = 0;
|
2018-02-16 06:37:58 +00:00
|
|
|
#define MAX_DRAWPOLY_VERTS 8
|
2008-01-03 21:54:58 +00:00
|
|
|
|
2012-10-01 17:52:25 +00:00
|
|
|
struct glfiltermodes glfiltermodes[NUMGLFILTERMODES] =
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
|
|
|
{"GL_NEAREST",GL_NEAREST,GL_NEAREST},
|
|
|
|
{"GL_LINEAR",GL_LINEAR,GL_LINEAR},
|
|
|
|
{"GL_NEAREST_MIPMAP_NEAREST",GL_NEAREST_MIPMAP_NEAREST,GL_NEAREST},
|
|
|
|
{"GL_LINEAR_MIPMAP_NEAREST",GL_LINEAR_MIPMAP_NEAREST,GL_LINEAR},
|
|
|
|
{"GL_NEAREST_MIPMAP_LINEAR",GL_NEAREST_MIPMAP_LINEAR,GL_NEAREST},
|
|
|
|
{"GL_LINEAR_MIPMAP_LINEAR",GL_LINEAR_MIPMAP_LINEAR,GL_LINEAR}
|
|
|
|
};
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-11-09 22:51:39 +00:00
|
|
|
int32_t glanisotropy = 0; // 0 = maximum supported by card
|
2015-03-28 09:49:37 +00:00
|
|
|
int32_t gltexfiltermode = TEXFILTER_OFF;
|
2015-02-11 05:23:04 +00:00
|
|
|
|
|
|
|
#ifdef EDUKE32_GLES
|
2016-03-28 05:16:14 +00:00
|
|
|
int32_t glusetexcompr = 2;
|
2015-02-11 05:23:04 +00:00
|
|
|
int32_t glusetexcache = 0, glusememcache = 0;
|
|
|
|
#else
|
|
|
|
int32_t glusetexcompr = 1;
|
2011-12-03 13:13:28 +00:00
|
|
|
int32_t glusetexcache = 2, glusememcache = 1;
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t r_polygonmode = 0; // 0:GL_FILL,1:GL_LINE,2:GL_POINT //FUK
|
2015-02-11 05:23:04 +00:00
|
|
|
static int32_t lastglpolygonmode = 0; //FUK
|
2016-01-08 01:33:20 +00:00
|
|
|
#endif
|
|
|
|
#ifdef USE_GLEXT
|
|
|
|
int32_t glmultisample = 0, glnvmultisamplehint = 0;
|
2015-02-11 05:23:04 +00:00
|
|
|
int32_t r_detailmapping = 1;
|
|
|
|
int32_t r_glowmapping = 1;
|
|
|
|
#endif
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t gltexmaxsize = 0; // 0 means autodetection on first run
|
|
|
|
int32_t gltexmiplevel = 0; // discards this many mipmap levels
|
|
|
|
int32_t glprojectionhacks = 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
static GLuint polymosttext = 0;
|
2013-05-17 03:44:09 +00:00
|
|
|
int32_t glrendmode = REND_POLYMOST;
|
2006-07-21 21:53:31 +00:00
|
|
|
|
2012-11-10 14:11:20 +00:00
|
|
|
// This variable, and 'shadeforfullbrightpass' control the drawing of
|
|
|
|
// fullbright tiles. Also see 'fullbrightloadingpass'.
|
2006-07-21 21:53:31 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
int32_t r_fullbrights = 1;
|
2016-01-08 01:33:20 +00:00
|
|
|
#ifdef USE_GLEXT
|
2018-02-16 06:38:48 +00:00
|
|
|
//POGOTODO: we no longer support rendering without VBOs -- update any outdated pre-GL2 code that renders without VBOs
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t r_vbocount = 64;
|
2016-01-08 01:33:20 +00:00
|
|
|
#endif
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t r_animsmoothing = 1;
|
2013-01-08 23:12:59 +00:00
|
|
|
int32_t r_downsize = 0;
|
2010-05-09 08:51:25 +00:00
|
|
|
int32_t r_downsizevar = -1;
|
2008-07-29 05:43:47 +00:00
|
|
|
|
2009-04-16 06:41:24 +00:00
|
|
|
// used for fogcalc
|
2015-03-24 00:40:48 +00:00
|
|
|
static float fogresult, fogresult2;
|
|
|
|
coltypef fogcol, fogtable[MAXPALOOKUPS];
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
static uint32_t currentShaderProgramID = 0;
|
2018-05-08 17:32:16 +00:00
|
|
|
static GLenum currentActiveTexture = 0;
|
|
|
|
static uint32_t currentTextureID = 0;
|
2018-03-21 20:41:26 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
static GLuint quadVertsID = 0;
|
2018-03-21 20:41:26 +00:00
|
|
|
static GLuint polymost2BasicShaderProgramID = 0;
|
2018-02-16 06:38:34 +00:00
|
|
|
static GLint texSamplerLoc = -1;
|
|
|
|
static GLint fullBrightSamplerLoc = -1;
|
|
|
|
static GLint projMatrixLoc = -1;
|
|
|
|
static GLint mvMatrixLoc = -1;
|
|
|
|
static GLint texOffsetLoc = -1;
|
|
|
|
static GLint texScaleLoc = -1;
|
|
|
|
static GLint tintLoc = -1;
|
|
|
|
static GLint alphaLoc = -1;
|
|
|
|
static GLint fogRangeLoc = -1;
|
|
|
|
static GLint fogColorLoc = -1;
|
|
|
|
|
2018-03-21 20:41:32 +00:00
|
|
|
#define PALSWAP_TEXTURE_SIZE 2048
|
2018-03-21 20:41:26 +00:00
|
|
|
int32_t r_useindexedcolortextures = -1;
|
2018-05-08 17:32:16 +00:00
|
|
|
static GLuint tilesheetTexIDs[MAXTILESHEETS];
|
|
|
|
static GLint tilesheetSize = 0;
|
|
|
|
static vec2f_t tilesheetHalfTexelSize = { 0.f, 0.f };
|
2018-03-21 20:41:26 +00:00
|
|
|
static int32_t lastbasepal = -1;
|
|
|
|
static GLuint paletteTextureIDs[MAXBASEPALS];
|
2018-03-21 20:41:32 +00:00
|
|
|
static GLuint palswapTextureID = 0;
|
2018-03-21 20:41:26 +00:00
|
|
|
static GLuint polymost1CurrentShaderProgramID = 0;
|
|
|
|
static GLuint polymost1BasicShaderProgramID = 0;
|
|
|
|
static GLuint polymost1ExtendedShaderProgramID = 0;
|
|
|
|
static GLint polymost1TexSamplerLoc = -1;
|
|
|
|
static GLint polymost1PalSwapSamplerLoc = -1;
|
|
|
|
static GLint polymost1PaletteSamplerLoc = -1;
|
|
|
|
static GLint polymost1DetailSamplerLoc = -1;
|
|
|
|
static GLint polymost1GlowSamplerLoc = -1;
|
2018-05-08 17:32:16 +00:00
|
|
|
static GLint polymost1TexturePosSizeLoc = -1;
|
|
|
|
static vec4f_t polymost1TexturePosSize = { 0.f, 0.f, 1.f, 1.f };
|
|
|
|
static GLint polymost1HalfTexelSizeLoc = -1;
|
|
|
|
static vec2f_t polymost1HalfTexelSize = { 0.f, 0.f };
|
2018-03-21 20:41:32 +00:00
|
|
|
static GLint polymost1PalswapPosLoc = -1;
|
2018-05-08 17:32:16 +00:00
|
|
|
static vec2f_t polymost1PalswapPos = { 0.f, 0.f };
|
2018-03-21 20:41:32 +00:00
|
|
|
static GLint polymost1PalswapSizeLoc = -1;
|
2018-05-08 17:32:16 +00:00
|
|
|
static vec2f_t polymost1PalswapSize = { 0.f, 0.f };
|
|
|
|
static vec2f_t polymost1PalswapInnerSize = { 0.f, 0.f };
|
2018-03-21 20:41:26 +00:00
|
|
|
static GLint polymost1ShadeLoc = -1;
|
|
|
|
static float polymost1Shade = 0.f;
|
2019-03-19 17:08:39 +00:00
|
|
|
static GLint polymost1NumShadesLoc = -1;
|
|
|
|
static float polymost1NumShades = 64.f;
|
|
|
|
static GLint polymost1VisFactorLoc = -1;
|
|
|
|
static float polymost1VisFactor = 128.f;
|
2018-03-21 20:41:26 +00:00
|
|
|
static GLint polymost1FogEnabledLoc = -1;
|
|
|
|
static float polymost1FogEnabled = 1.f;
|
|
|
|
static GLint polymost1UseColorOnlyLoc = -1;
|
|
|
|
static float polymost1UseColorOnly = 0.f;
|
|
|
|
static GLint polymost1UsePaletteLoc = -1;
|
|
|
|
static float polymost1UsePalette = 1.f;
|
|
|
|
static GLint polymost1UseDetailMappingLoc = -1;
|
|
|
|
static float polymost1UseDetailMapping = 0.f;
|
|
|
|
static GLint polymost1UseGlowMappingLoc = -1;
|
|
|
|
static float polymost1UseGlowMapping = 0.f;
|
2019-03-19 17:08:43 +00:00
|
|
|
static GLint polymost1NPOTEmulationLoc = -1;
|
|
|
|
static float polymost1NPOTEmulation = 0.f;
|
|
|
|
static GLint polymost1NPOTEmulationFactorLoc = -1;
|
|
|
|
static float polymost1NPOTEmulationFactor = 1.f;
|
|
|
|
static GLint polymost1NPOTEmulationXOffsetLoc = -1;
|
|
|
|
static float polymost1NPOTEmulationXOffset = 0.f;
|
2019-03-19 17:08:39 +00:00
|
|
|
static GLint polymost1RotMatrixLoc = -1;
|
|
|
|
static float polymost1RotMatrix[16] = { 1.f, 0.f, 0.f, 0.f,
|
|
|
|
0.f, 1.f, 0.f, 0.f,
|
|
|
|
0.f, 0.f, 1.f, 0.f,
|
|
|
|
0.f, 0.f, 0.f, 1.f };
|
2018-03-21 20:41:26 +00:00
|
|
|
|
2017-06-10 08:19:47 +00:00
|
|
|
static inline float float_trans(uint32_t maskprops, uint8_t blend)
|
2016-10-09 07:55:23 +00:00
|
|
|
{
|
|
|
|
switch (maskprops)
|
|
|
|
{
|
|
|
|
case DAMETH_TRANS1:
|
|
|
|
case DAMETH_TRANS2:
|
|
|
|
return glblend[blend].def[maskprops-2].alpha;
|
|
|
|
default:
|
|
|
|
return 1.0f;
|
|
|
|
}
|
|
|
|
}
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2013-05-15 02:17:17 +00:00
|
|
|
char ptempbuf[MAXWALLSB<<1];
|
2008-12-02 10:44:39 +00:00
|
|
|
|
2008-09-12 02:07:44 +00:00
|
|
|
// polymost ART sky control
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t r_parallaxskyclamping = 1;
|
2017-11-29 07:29:54 +00:00
|
|
|
int32_t r_parallaxskypanning = 1;
|
2008-09-12 02:07:44 +00:00
|
|
|
|
2011-09-28 20:30:24 +00:00
|
|
|
#define MIN_CACHETIME_PRINT 10
|
2011-01-30 11:02:28 +00:00
|
|
|
|
2019-09-13 19:43:05 +00:00
|
|
|
static const int THCACHESIZE = 200;
|
|
|
|
static GLuint TextureHandleCache[THCACHESIZE];
|
|
|
|
static int currentindex = THCACHESIZE;
|
|
|
|
|
|
|
|
void GetTextureHandle(GLuint *handle)
|
|
|
|
{
|
|
|
|
// Generating large numbers of texture IDs piece by piece does not work well on modern NVidia drivers.
|
|
|
|
|
|
|
|
if (currentindex == THCACHESIZE)
|
|
|
|
{
|
|
|
|
currentindex = 0;
|
|
|
|
glGenTextures(THCACHESIZE, TextureHandleCache);
|
|
|
|
}
|
|
|
|
else currentindex++;
|
|
|
|
*handle = TextureHandleCache[currentindex];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-10-25 03:34:25 +00:00
|
|
|
// this was faster in MSVC but slower with GCC... currently unknown on ARM where both
|
|
|
|
// the FPU and possibly the optimization path in the compiler need improvement
|
|
|
|
#if 0
|
2015-04-18 21:59:20 +00:00
|
|
|
static inline int32_t __float_as_int(float f) { return *(int32_t *) &f; }
|
2014-10-25 03:34:25 +00:00
|
|
|
static inline float __int_as_float(int32_t d) { return *(float *) &d; }
|
|
|
|
static inline float Bfabsf(float f) { return __int_as_float(__float_as_int(f)&0x7fffffff); }
|
|
|
|
#else
|
|
|
|
#define Bfabsf fabsf
|
|
|
|
#endif
|
|
|
|
|
2010-05-25 10:56:00 +00:00
|
|
|
int32_t mdtims, omdtims;
|
2015-03-24 00:40:33 +00:00
|
|
|
uint8_t alphahackarray[MAXTILES];
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t drawingskybox = 0;
|
2013-05-15 02:17:17 +00:00
|
|
|
int32_t hicprecaching = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-07-08 03:34:27 +00:00
|
|
|
hitdata_t polymost_hitdata;
|
|
|
|
|
2014-10-29 17:02:50 +00:00
|
|
|
#if 0
|
2009-02-02 01:49:14 +00:00
|
|
|
static inline int32_t gltexmayhavealpha(int32_t dapicnum, int32_t dapalnum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2012-11-10 14:11:20 +00:00
|
|
|
const int32_t j = (dapicnum&(GLTEXCACHEADSIZ-1));
|
2006-04-24 19:04:22 +00:00
|
|
|
pthtyp *pth;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-05-17 03:42:37 +00:00
|
|
|
for (pth=texcache.list[j]; pth; pth=pth->next)
|
2012-11-10 14:11:20 +00:00
|
|
|
if (pth->picnum == dapicnum && pth->palnum == dapalnum)
|
2014-05-28 22:40:16 +00:00
|
|
|
return ((pth->flags&PTH_HASALPHA) != 0);
|
2012-11-10 14:11:20 +00:00
|
|
|
|
|
|
|
return 1;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2014-10-29 17:02:50 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
void gltexinvalidate(int32_t dapicnum, int32_t dapalnum, int32_t dameth)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
const int32_t pic = (dapicnum&(GLTEXCACHEADSIZ-1));
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
for (pthtyp *pth=texcache.list[pic]; pth; pth=pth->next)
|
2014-05-28 22:40:16 +00:00
|
|
|
if (pth->picnum == dapicnum && pth->palnum == dapalnum &&
|
|
|
|
(pth->flags & PTH_CLAMPED) == TO_PTH_CLAMPED(dameth))
|
2006-07-24 02:47:47 +00:00
|
|
|
{
|
2014-05-28 22:40:16 +00:00
|
|
|
pth->flags |= PTH_INVALIDATED;
|
|
|
|
if (pth->flags & PTH_HASFULLBRIGHT)
|
|
|
|
pth->ofb->flags |= PTH_INVALIDATED;
|
2006-07-24 02:47:47 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Make all textures "dirty" so they reload, but not re-allocate
|
|
|
|
//This should be much faster than polymost_glreset()
|
|
|
|
//Use this for palette effects ... but not ones that change every frame!
|
2013-05-15 02:20:08 +00:00
|
|
|
void gltexinvalidatetype(int32_t type)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j=0; j<=GLTEXCACHEADSIZ-1; j++)
|
2013-05-15 02:17:17 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
for (pthtyp *pth=texcache.list[j]; pth; pth=pth->next)
|
2006-12-12 09:28:37 +00:00
|
|
|
{
|
2018-03-21 20:41:26 +00:00
|
|
|
if (type == INVALIDATE_ALL ||
|
|
|
|
(type == INVALIDATE_ALL_NON_INDEXED && !(pth->flags & PTH_INDEXED)) ||
|
|
|
|
(type == INVALIDATE_ART && pth->hicr == NULL) ||
|
|
|
|
(type == INVALIDATE_ART_NON_INDEXED && pth->hicr == NULL && !(pth->flags & PTH_INDEXED)))
|
2006-12-12 09:28:37 +00:00
|
|
|
{
|
2014-05-28 22:40:16 +00:00
|
|
|
pth->flags |= PTH_INVALIDATED;
|
|
|
|
if (pth->flags & PTH_HASFULLBRIGHT)
|
|
|
|
pth->ofb->flags |= PTH_INVALIDATED;
|
2006-12-12 09:28:37 +00:00
|
|
|
}
|
|
|
|
}
|
2013-05-15 02:17:17 +00:00
|
|
|
}
|
|
|
|
|
2015-12-26 15:42:09 +00:00
|
|
|
clearskins(type);
|
|
|
|
|
2006-12-12 09:28:37 +00:00
|
|
|
#ifdef DEBUGGINGAIDS
|
2013-05-15 02:17:17 +00:00
|
|
|
OSD_Printf("gltexinvalidateall()\n");
|
2006-12-12 09:28:37 +00:00
|
|
|
#endif
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-02-11 05:23:04 +00:00
|
|
|
static void bind_2d_texture(GLuint texture, int filter)
|
2012-10-01 17:52:25 +00:00
|
|
|
{
|
2015-02-11 05:23:04 +00:00
|
|
|
if (filter == -1)
|
|
|
|
filter = gltexfiltermode;
|
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfiltermodes[filter].mag);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfiltermodes[filter].min);
|
2016-01-08 01:33:20 +00:00
|
|
|
#ifdef USE_GLEXT
|
2014-09-30 04:06:05 +00:00
|
|
|
if (glinfo.maxanisotropy > 1.f)
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glanisotropy);
|
2015-02-11 05:23:04 +00:00
|
|
|
#endif
|
2012-10-01 17:52:25 +00:00
|
|
|
}
|
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
void gltexapplyprops(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_CLASSIC)
|
2013-03-31 18:57:59 +00:00
|
|
|
return;
|
|
|
|
|
2014-09-30 04:06:05 +00:00
|
|
|
if (glinfo.maxanisotropy > 1.f)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2012-10-01 17:52:25 +00:00
|
|
|
if (glanisotropy <= 0 || glanisotropy > glinfo.maxanisotropy)
|
|
|
|
glanisotropy = (int32_t)glinfo.maxanisotropy;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2012-10-01 17:52:25 +00:00
|
|
|
gltexfiltermode = clamp(gltexfiltermode, 0, NUMGLFILTERMODES-1);
|
2018-03-21 20:41:26 +00:00
|
|
|
r_useindexedcolortextures = !gltexfiltermode;
|
2012-10-01 17:52:25 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<=GLTEXCACHEADSIZ-1; i++)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
for (pthtyp *pth=texcache.list[i]; pth; pth=pth->next)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2018-03-21 20:41:26 +00:00
|
|
|
if (pth->flags & PTH_INDEXED)
|
|
|
|
{
|
|
|
|
//POGO: indexed textures should not be filtered
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-10-25 23:31:30 +00:00
|
|
|
int32_t const filter = (pth->flags & PTH_FORCEFILTER) ? TEXFILTER_ON : -1;
|
2015-02-11 05:23:04 +00:00
|
|
|
|
2015-03-28 09:49:37 +00:00
|
|
|
bind_2d_texture(pth->glpic, filter);
|
2012-10-01 17:52:25 +00:00
|
|
|
|
2014-05-28 22:40:16 +00:00
|
|
|
if (r_fullbrights && pth->flags & PTH_HASFULLBRIGHT)
|
2015-03-28 09:49:37 +00:00
|
|
|
bind_2d_texture(pth->ofb->glpic, filter);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<nextmodelid; i++)
|
2015-02-11 05:23:04 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
md2model_t *m = (md2model_t *)models[i];
|
|
|
|
|
|
|
|
if (m->mdnum < 2)
|
|
|
|
continue;
|
|
|
|
|
2017-06-21 13:46:36 +00:00
|
|
|
for (bssize_t j = 0; j < m->numskins * HICTINT_MEMORY_COMBINATIONS; j++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!m->texid[j])
|
|
|
|
continue;
|
2015-02-11 05:23:04 +00:00
|
|
|
bind_2d_texture(m->texid[j], -1);
|
|
|
|
}
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
for (mdskinmap_t *sk = m->skinmap; sk; sk = sk->next)
|
2017-06-21 13:46:36 +00:00
|
|
|
for (bssize_t j = 0; j < HICTINT_MEMORY_COMBINATIONS; j++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!sk->texid[j])
|
|
|
|
continue;
|
2018-10-25 23:31:30 +00:00
|
|
|
bind_2d_texture(sk->texid[j], (sk->flags & HICR_FORCEFILTER) ? TEXFILTER_ON : -1);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------------------------
|
2013-05-15 02:17:17 +00:00
|
|
|
|
2008-12-02 10:44:39 +00:00
|
|
|
float glox1, gloy1, glox2, gloy2;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Use this for both initialization and uninitialization of OpenGL.
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t gltexcacnum = -1;
|
2010-05-25 10:56:00 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
//in-place multiply m0=m0*m1
|
2018-10-16 06:09:09 +00:00
|
|
|
static float* multiplyMatrix4f(float m0[4*4], const float m1[4*4])
|
2018-02-16 06:38:34 +00:00
|
|
|
{
|
|
|
|
float mR[4*4];
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
#define multMatrix4RowCol(r, c) mR[r*4+c] = m0[r*4]*m1[c] + m0[r*4+1]*m1[c+4] + m0[r*4+2]*m1[c+8] + m0[r*4+3]*m1[c+12]
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
multMatrix4RowCol(0, 0);
|
|
|
|
multMatrix4RowCol(0, 1);
|
|
|
|
multMatrix4RowCol(0, 2);
|
|
|
|
multMatrix4RowCol(0, 3);
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
multMatrix4RowCol(1, 0);
|
|
|
|
multMatrix4RowCol(1, 1);
|
|
|
|
multMatrix4RowCol(1, 2);
|
|
|
|
multMatrix4RowCol(1, 3);
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
multMatrix4RowCol(2, 0);
|
|
|
|
multMatrix4RowCol(2, 1);
|
|
|
|
multMatrix4RowCol(2, 2);
|
|
|
|
multMatrix4RowCol(2, 3);
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
multMatrix4RowCol(3, 0);
|
|
|
|
multMatrix4RowCol(3, 1);
|
|
|
|
multMatrix4RowCol(3, 2);
|
|
|
|
multMatrix4RowCol(3, 3);
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
Bmemcpy(m0, mR, sizeof(float)*4*4);
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
return m0;
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
#undef multMatrix4RowCol
|
|
|
|
}
|
|
|
|
|
|
|
|
static void calcmat(vec3f_t a0, const vec2f_t *offset, float f, float mat[16], int16_t angle)
|
|
|
|
{
|
|
|
|
float g;
|
|
|
|
float k0, k1, k2, k3, k4, k5, k6, k7;
|
|
|
|
|
|
|
|
k0 = a0.y;
|
|
|
|
k1 = a0.x;
|
|
|
|
a0.x += offset->x;
|
|
|
|
a0.z += offset->y;
|
|
|
|
f = gcosang2*gshang;
|
|
|
|
g = gsinang2*gshang;
|
|
|
|
k4 = (float)sintable[(angle+1024)&2047] * (1.f/16384.f);
|
|
|
|
k5 = (float)sintable[(angle+512)&2047] * (1.f/16384.f);
|
|
|
|
k2 = k0*(1-k4)+k1*k5;
|
|
|
|
k3 = k1*(1-k4)-k0*k5;
|
|
|
|
k6 = f*gstang - gsinang*gctang; k7 = g*gstang + gcosang*gctang;
|
|
|
|
mat[0] = k4*k6 + k5*k7; mat[4] = gchang*gstang; mat[ 8] = k4*k7 - k5*k6; mat[12] = k2*k6 + k3*k7;
|
|
|
|
k6 = f*gctang + gsinang*gstang; k7 = g*gctang - gcosang*gstang;
|
|
|
|
mat[1] = k4*k6 + k5*k7; mat[5] = gchang*gctang; mat[ 9] = k4*k7 - k5*k6; mat[13] = k2*k6 + k3*k7;
|
|
|
|
k6 = gcosang2*gchang; k7 = gsinang2*gchang;
|
|
|
|
mat[2] = k4*k6 + k5*k7; mat[6] =-gshang; mat[10] = k4*k7 - k5*k6; mat[14] = k2*k6 + k3*k7;
|
|
|
|
|
|
|
|
mat[12] = (mat[12] + a0.y*mat[0]) + (a0.z*mat[4] + a0.x*mat[ 8]);
|
|
|
|
mat[13] = (mat[13] + a0.y*mat[1]) + (a0.z*mat[5] + a0.x*mat[ 9]);
|
|
|
|
mat[14] = (mat[14] + a0.y*mat[2]) + (a0.z*mat[6] + a0.x*mat[10]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static GLuint polymost2_compileShader(GLenum shaderType, const char* const source)
|
|
|
|
{
|
|
|
|
GLuint shaderID = glCreateShader(shaderType);
|
|
|
|
if (shaderID == 0)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
const char* const sources[1] = {source};
|
|
|
|
glShaderSource(shaderID,
|
|
|
|
1,
|
|
|
|
sources,
|
|
|
|
NULL);
|
|
|
|
glCompileShader(shaderID);
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-17 06:38:15 +00:00
|
|
|
GLint compileStatus;
|
|
|
|
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compileStatus);
|
|
|
|
if (!compileStatus)
|
2018-02-16 06:38:34 +00:00
|
|
|
{
|
2018-02-17 06:38:15 +00:00
|
|
|
GLint logLength;
|
|
|
|
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength);
|
2018-07-30 23:01:48 +00:00
|
|
|
OSD_Printf("Compile Status: %u\n", compileStatus);
|
2018-02-17 06:38:15 +00:00
|
|
|
if (logLength > 0)
|
|
|
|
{
|
2018-10-25 23:28:56 +00:00
|
|
|
char *infoLog = (char*)Xmalloc(logLength);
|
2018-02-17 06:38:15 +00:00
|
|
|
glGetShaderInfoLog(shaderID, logLength, &logLength, infoLog);
|
|
|
|
OSD_Printf("Log:\n%s\n", infoLog);
|
|
|
|
free(infoLog);
|
|
|
|
}
|
2018-02-16 06:38:34 +00:00
|
|
|
}
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
return shaderID;
|
|
|
|
}
|
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
void polymost_glreset()
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<=MAXPALOOKUPS-1; i++)
|
2009-01-31 00:02:14 +00:00
|
|
|
{
|
2015-09-23 17:55:11 +00:00
|
|
|
fogtable[i].r = palookupfog[i].r * (1.f/255.f);
|
|
|
|
fogtable[i].g = palookupfog[i].g * (1.f/255.f);
|
|
|
|
fogtable[i].b = palookupfog[i].b * (1.f/255.f);
|
2015-03-24 00:40:48 +00:00
|
|
|
fogtable[i].a = 0;
|
2009-01-31 00:02:14 +00:00
|
|
|
}
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Reset if this is -1 (meaning 1st texture call ever), or > 0 (textures in memory)
|
|
|
|
if (gltexcacnum < 0)
|
|
|
|
{
|
|
|
|
gltexcacnum = 0;
|
|
|
|
|
|
|
|
//Hack for polymost_dorotatesprite calls before 1st polymost_drawrooms()
|
2014-09-30 04:06:05 +00:00
|
|
|
gcosang = gcosang2 = 16384.f/262144.f;
|
2015-03-24 00:40:48 +00:00
|
|
|
gsinang = gsinang2 = 0.f;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i = 0; i <= GLTEXCACHEADSIZ-1; i++)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
for (pthtyp *pth = texcache.list[i]; pth;)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
pthtyp *const next = pth->next;
|
|
|
|
|
2014-05-28 22:40:16 +00:00
|
|
|
if (pth->flags & PTH_HASFULLBRIGHT)
|
2006-07-24 02:47:47 +00:00
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glDeleteTextures(1, &pth->ofb->glpic);
|
2009-10-07 06:47:35 +00:00
|
|
|
Bfree(pth->ofb);
|
2006-07-24 02:47:47 +00:00
|
|
|
}
|
2012-05-05 22:23:44 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glDeleteTextures(1, &pth->glpic);
|
2009-10-07 06:47:35 +00:00
|
|
|
Bfree(pth);
|
2006-04-24 19:04:22 +00:00
|
|
|
pth = next;
|
|
|
|
}
|
2012-05-05 22:23:44 +00:00
|
|
|
|
2013-05-17 03:42:37 +00:00
|
|
|
texcache.list[i] = NULL;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-12-26 15:42:09 +00:00
|
|
|
clearskins(INVALIDATE_ALL);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2012-05-05 22:23:44 +00:00
|
|
|
if (polymosttext)
|
2018-02-16 06:38:21 +00:00
|
|
|
glDeleteTextures(1,&polymosttext);
|
2006-04-24 19:04:22 +00:00
|
|
|
polymosttext=0;
|
|
|
|
|
2014-10-25 03:34:25 +00:00
|
|
|
Bmemset(texcache.list,0,sizeof(texcache.list));
|
2006-04-24 19:04:22 +00:00
|
|
|
glox1 = -1;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-05-15 02:17:17 +00:00
|
|
|
texcache_freeptrs();
|
2013-05-15 02:19:14 +00:00
|
|
|
texcache_syncmemcache();
|
2015-02-11 05:23:04 +00:00
|
|
|
|
2011-09-10 15:44:53 +00:00
|
|
|
#ifdef DEBUGGINGAIDS
|
|
|
|
OSD_Printf("polymost_glreset()\n");
|
|
|
|
#endif
|
2007-01-06 01:29:45 +00:00
|
|
|
}
|
2006-12-31 06:32:04 +00:00
|
|
|
|
2016-05-04 00:25:24 +00:00
|
|
|
#if defined EDUKE32_GLES
|
|
|
|
static void Polymost_DetermineTextureFormatSupport(void);
|
|
|
|
#endif
|
2012-01-10 23:43:18 +00:00
|
|
|
|
2018-02-16 06:37:58 +00:00
|
|
|
// reset vertex pointers to polymost default
|
|
|
|
void polymost_resetVertexPointers()
|
|
|
|
{
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_resetProgram();
|
|
|
|
}
|
|
|
|
|
|
|
|
void polymost_disableProgram()
|
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (videoGetRenderMode() != REND_POLYMOST)
|
|
|
|
return;
|
|
|
|
|
|
|
|
useShaderProgram(0);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void polymost_resetProgram()
|
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (videoGetRenderMode() != REND_POLYMOST)
|
|
|
|
return;
|
2018-03-21 20:41:32 +00:00
|
|
|
|
2019-03-19 17:09:06 +00:00
|
|
|
if (r_enablepolymost2)
|
|
|
|
useShaderProgram(polymost2BasicShaderProgramID);
|
|
|
|
else
|
|
|
|
useShaderProgram(polymost1CurrentShaderProgramID);
|
|
|
|
|
|
|
|
// ensure that palswapTexture and paletteTexture[curbasepal] is bound
|
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, palswapTextureID);
|
|
|
|
glActiveTexture(GL_TEXTURE2);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, paletteTextureIDs[curbasepal]);
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void polymost_setCurrentShaderProgram(uint32_t programID)
|
|
|
|
{
|
|
|
|
polymost1CurrentShaderProgramID = programID;
|
|
|
|
useShaderProgram(programID);
|
|
|
|
|
|
|
|
//update the uniform locations
|
|
|
|
polymost1TexSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_texture");
|
|
|
|
polymost1PalSwapSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_palswap");
|
|
|
|
polymost1PaletteSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_palette");
|
|
|
|
polymost1DetailSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_detail");
|
|
|
|
polymost1GlowSamplerLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "s_glow");
|
2018-05-08 17:32:16 +00:00
|
|
|
polymost1TexturePosSizeLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_texturePosSize");
|
|
|
|
polymost1HalfTexelSizeLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_halfTexelSize");
|
2018-03-21 20:41:32 +00:00
|
|
|
polymost1PalswapPosLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_palswapPos");
|
|
|
|
polymost1PalswapSizeLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_palswapSize");
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost1ShadeLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_shade");
|
2019-03-19 17:08:39 +00:00
|
|
|
polymost1NumShadesLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_numShades");
|
|
|
|
polymost1VisFactorLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_visFactor");
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost1FogEnabledLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_fogEnabled");
|
|
|
|
polymost1UsePaletteLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_usePalette");
|
|
|
|
polymost1UseColorOnlyLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_useColorOnly");
|
|
|
|
polymost1UseDetailMappingLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_useDetailMapping");
|
|
|
|
polymost1UseGlowMappingLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_useGlowMapping");
|
2019-03-19 17:08:43 +00:00
|
|
|
polymost1NPOTEmulationLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_npotEmulation");
|
|
|
|
polymost1NPOTEmulationFactorLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_npotEmulationFactor");
|
|
|
|
polymost1NPOTEmulationXOffsetLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_npotEmulationXOffset");
|
2019-03-19 17:08:39 +00:00
|
|
|
polymost1RotMatrixLoc = glGetUniformLocation(polymost1CurrentShaderProgramID, "u_rotMatrix");
|
2018-03-21 20:41:26 +00:00
|
|
|
|
|
|
|
//set the uniforms to the current values
|
2018-05-08 17:32:16 +00:00
|
|
|
glUniform4f(polymost1TexturePosSizeLoc, polymost1TexturePosSize.x, polymost1TexturePosSize.y, polymost1TexturePosSize.z, polymost1TexturePosSize.w);
|
|
|
|
glUniform2f(polymost1HalfTexelSizeLoc, polymost1HalfTexelSize.x, polymost1HalfTexelSize.y);
|
2018-03-21 20:41:32 +00:00
|
|
|
glUniform2f(polymost1PalswapPosLoc, polymost1PalswapPos.x, polymost1PalswapPos.y);
|
|
|
|
glUniform2f(polymost1PalswapSizeLoc, polymost1PalswapInnerSize.x, polymost1PalswapInnerSize.y);
|
2018-03-21 20:41:26 +00:00
|
|
|
glUniform1f(polymost1ShadeLoc, polymost1Shade);
|
2019-03-19 17:08:39 +00:00
|
|
|
glUniform1f(polymost1NumShadesLoc, polymost1NumShades);
|
|
|
|
glUniform1f(polymost1VisFactorLoc, polymost1VisFactor);
|
2018-03-21 20:41:26 +00:00
|
|
|
glUniform1f(polymost1FogEnabledLoc, polymost1FogEnabled);
|
|
|
|
glUniform1f(polymost1UseColorOnlyLoc, polymost1UseColorOnly);
|
|
|
|
glUniform1f(polymost1UsePaletteLoc, polymost1UsePalette);
|
|
|
|
glUniform1f(polymost1UseDetailMappingLoc, polymost1UseDetailMapping);
|
|
|
|
glUniform1f(polymost1UseGlowMappingLoc, polymost1UseGlowMapping);
|
2019-03-19 17:08:43 +00:00
|
|
|
glUniform1f(polymost1NPOTEmulationLoc, polymost1NPOTEmulation);
|
|
|
|
glUniform1f(polymost1NPOTEmulationFactorLoc, polymost1NPOTEmulationFactor);
|
|
|
|
glUniform1f(polymost1NPOTEmulationXOffsetLoc, polymost1NPOTEmulationXOffset);
|
2019-03-19 17:08:39 +00:00
|
|
|
glUniformMatrix4fv(polymost1RotMatrixLoc, 1, false, polymost1RotMatrix);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:29:30 +00:00
|
|
|
void polymost_setTexturePosSize(vec4f_t const &texturePosSize)
|
2018-05-08 17:32:16 +00:00
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (currentShaderProgramID != polymost1CurrentShaderProgramID)
|
|
|
|
return;
|
|
|
|
|
|
|
|
polymost1TexturePosSize = texturePosSize;
|
|
|
|
glUniform4f(polymost1TexturePosSizeLoc, polymost1TexturePosSize.x, polymost1TexturePosSize.y, polymost1TexturePosSize.z, polymost1TexturePosSize.w);
|
2018-05-08 17:32:16 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:29:30 +00:00
|
|
|
static inline void polymost_setHalfTexelSize(vec2f_t const &halfTexelSize)
|
2018-05-08 17:32:16 +00:00
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (currentShaderProgramID != polymost1CurrentShaderProgramID || (halfTexelSize.x == polymost1HalfTexelSize.x && halfTexelSize.y == polymost1HalfTexelSize.y))
|
|
|
|
return;
|
|
|
|
|
|
|
|
polymost1HalfTexelSize = halfTexelSize;
|
|
|
|
glUniform2f(polymost1HalfTexelSizeLoc, polymost1HalfTexelSize.x, polymost1HalfTexelSize.y);
|
2018-05-08 17:32:16 +00:00
|
|
|
}
|
|
|
|
|
2018-03-21 20:41:32 +00:00
|
|
|
static void polymost_setPalswap(uint32_t index)
|
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
static uint32_t lastPalswapIndex;
|
2018-03-21 20:41:32 +00:00
|
|
|
|
2019-03-19 17:09:06 +00:00
|
|
|
if (currentShaderProgramID != polymost1CurrentShaderProgramID || index == lastPalswapIndex)
|
|
|
|
return;
|
|
|
|
|
|
|
|
lastPalswapIndex = index;
|
|
|
|
polymost1PalswapPos.x = index*polymost1PalswapSize.x;
|
|
|
|
polymost1PalswapPos.y = floorf(polymost1PalswapPos.x);
|
|
|
|
polymost1PalswapPos.x = polymost1PalswapPos.x - polymost1PalswapPos.y + (0.5f/PALSWAP_TEXTURE_SIZE);
|
|
|
|
polymost1PalswapPos.y = polymost1PalswapPos.y * polymost1PalswapSize.y + (0.5f/PALSWAP_TEXTURE_SIZE);
|
|
|
|
glUniform2f(polymost1PalswapPosLoc, polymost1PalswapPos.x, polymost1PalswapPos.y);
|
2018-03-21 20:41:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void polymost_setPalswapSize(uint32_t width, uint32_t height)
|
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (currentShaderProgramID != polymost1CurrentShaderProgramID)
|
|
|
|
return;
|
|
|
|
|
|
|
|
polymost1PalswapSize.x = width*(1.f/PALSWAP_TEXTURE_SIZE);
|
|
|
|
polymost1PalswapSize.y = height*(1.f/PALSWAP_TEXTURE_SIZE);
|
|
|
|
polymost1PalswapInnerSize.x = (width-1)*(1.f/PALSWAP_TEXTURE_SIZE);
|
|
|
|
polymost1PalswapInnerSize.y = (height-1)*(1.f/PALSWAP_TEXTURE_SIZE);
|
|
|
|
glUniform2f(polymost1PalswapSizeLoc, polymost1PalswapInnerSize.x, polymost1PalswapInnerSize.y);
|
2018-03-21 20:41:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void polymost_setShade(int32_t shade)
|
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (currentShaderProgramID != polymost1CurrentShaderProgramID)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!r_usetileshades || (globalflags & GLOBAL_NO_GL_TILESHADES))
|
|
|
|
shade = 0;
|
|
|
|
#if 0
|
|
|
|
else
|
|
|
|
shade = getpalookup(r_usetileshades == 1, shade);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int32_t lastShade;
|
|
|
|
static int32_t lastNumShades;
|
|
|
|
|
|
|
|
if (shade != lastShade)
|
2018-03-21 20:41:32 +00:00
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
lastShade = shade;
|
|
|
|
polymost1Shade = shade;
|
|
|
|
glUniform1f(polymost1ShadeLoc, polymost1Shade);
|
|
|
|
}
|
2018-07-03 04:29:19 +00:00
|
|
|
|
2019-03-19 17:09:06 +00:00
|
|
|
if (numshades != lastNumShades)
|
|
|
|
{
|
|
|
|
lastNumShades = numshades;
|
|
|
|
polymost1NumShades = numshades;
|
|
|
|
glUniform1f(polymost1NumShadesLoc, polymost1NumShades);
|
2019-03-19 17:08:39 +00:00
|
|
|
}
|
|
|
|
}
|
2018-03-21 20:41:32 +00:00
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
static void polymost_setVisibility(float visibility)
|
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (currentShaderProgramID != polymost1CurrentShaderProgramID)
|
|
|
|
return;
|
|
|
|
|
|
|
|
polymost1VisFactor = visibility * fviewingrange * (1.f / (64.f * 65536.f));
|
|
|
|
glUniform1f(polymost1VisFactorLoc, polymost1VisFactor);
|
2018-03-21 20:41:32 +00:00
|
|
|
}
|
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
void polymost_setFogEnabled(char fogEnabled)
|
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (currentShaderProgramID != polymost1CurrentShaderProgramID || fogEnabled == polymost1FogEnabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
polymost1FogEnabled = fogEnabled;
|
|
|
|
glUniform1f(polymost1FogEnabledLoc, polymost1FogEnabled);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void polymost_useColorOnly(char useColorOnly)
|
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (currentShaderProgramID != polymost1CurrentShaderProgramID || useColorOnly == polymost1UseColorOnly)
|
|
|
|
return;
|
|
|
|
|
|
|
|
polymost1UseColorOnly = useColorOnly;
|
|
|
|
glUniform1f(polymost1UseColorOnlyLoc, polymost1UseColorOnly);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void polymost_usePaletteIndexing(char usePaletteIndexing)
|
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (currentShaderProgramID != polymost1CurrentShaderProgramID || usePaletteIndexing == polymost1UsePalette)
|
|
|
|
return;
|
|
|
|
|
|
|
|
polymost1UsePalette = usePaletteIndexing;
|
|
|
|
glUniform1f(polymost1UsePaletteLoc, polymost1UsePalette);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void polymost_useDetailMapping(char useDetailMapping)
|
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (currentShaderProgramID != polymost1CurrentShaderProgramID || useDetailMapping == polymost1UseDetailMapping)
|
|
|
|
return;
|
2018-03-21 20:41:32 +00:00
|
|
|
|
2019-03-19 17:09:06 +00:00
|
|
|
if (useDetailMapping)
|
|
|
|
polymost_setCurrentShaderProgram(polymost1ExtendedShaderProgramID);
|
2018-03-21 20:41:26 +00:00
|
|
|
|
2019-03-19 17:09:06 +00:00
|
|
|
polymost1UseDetailMapping = useDetailMapping;
|
|
|
|
glUniform1f(polymost1UseDetailMappingLoc, polymost1UseDetailMapping);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void polymost_useGlowMapping(char useGlowMapping)
|
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (currentShaderProgramID != polymost1CurrentShaderProgramID || useGlowMapping == polymost1UseGlowMapping)
|
|
|
|
return;
|
2018-03-21 20:41:32 +00:00
|
|
|
|
2019-03-19 17:09:06 +00:00
|
|
|
if (useGlowMapping)
|
|
|
|
polymost_setCurrentShaderProgram(polymost1ExtendedShaderProgramID);
|
2018-03-21 20:41:26 +00:00
|
|
|
|
2019-03-19 17:09:06 +00:00
|
|
|
polymost1UseGlowMapping = useGlowMapping;
|
|
|
|
glUniform1f(polymost1UseGlowMappingLoc, polymost1UseGlowMapping);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
|
2019-03-19 17:08:43 +00:00
|
|
|
void polymost_npotEmulation(char npotEmulation, float factor, float xOffset)
|
|
|
|
{
|
2019-03-19 17:09:06 +00:00
|
|
|
if (currentShaderProgramID != polymost1CurrentShaderProgramID || npotEmulation == polymost1NPOTEmulation)
|
|
|
|
return;
|
|
|
|
|
|
|
|
polymost1NPOTEmulation = npotEmulation;
|
|
|
|
glUniform1f(polymost1NPOTEmulationLoc, polymost1NPOTEmulation);
|
|
|
|
polymost1NPOTEmulationFactor = factor;
|
|
|
|
glUniform1f(polymost1NPOTEmulationFactorLoc, polymost1NPOTEmulationFactor);
|
|
|
|
polymost1NPOTEmulationXOffset = xOffset;
|
|
|
|
glUniform1f(polymost1NPOTEmulationXOffsetLoc, polymost1NPOTEmulationXOffset);
|
2019-03-19 17:08:43 +00:00
|
|
|
}
|
|
|
|
|
2018-05-08 17:32:16 +00:00
|
|
|
void polymost_activeTexture(GLenum texture)
|
|
|
|
{
|
|
|
|
currentActiveTexture = texture;
|
|
|
|
glad_glActiveTexture(texture);
|
|
|
|
}
|
|
|
|
|
|
|
|
//POGOTODO: replace this and polymost_activeTexture with proper draw call organization
|
|
|
|
void polymost_bindTexture(GLenum target, uint32_t textureID)
|
|
|
|
{
|
|
|
|
if (currentTextureID != textureID ||
|
|
|
|
textureID == 0 ||
|
|
|
|
currentActiveTexture != GL_TEXTURE0 ||
|
|
|
|
videoGetRenderMode() != REND_POLYMOST)
|
|
|
|
{
|
|
|
|
glad_glBindTexture(target, textureID);
|
|
|
|
if (currentActiveTexture == GL_TEXTURE0)
|
|
|
|
{
|
|
|
|
currentTextureID = textureID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-25 23:31:30 +00:00
|
|
|
static void polymost_bindPth(pthtyp const * const pPth)
|
2018-05-08 17:32:16 +00:00
|
|
|
{
|
2018-10-07 05:23:25 +00:00
|
|
|
Bassert(pPth);
|
|
|
|
|
2018-05-08 17:32:16 +00:00
|
|
|
vec4f_t texturePosSize = { 0.f, 0.f, 1.f, 1.f };
|
|
|
|
vec2f_t halfTexelSize = { 0.f, 0.f };
|
2018-05-08 22:47:55 +00:00
|
|
|
if ((pPth->flags & PTH_INDEXED) &&
|
2018-05-08 17:32:16 +00:00
|
|
|
!(pPth->flags & PTH_HIGHTILE))
|
|
|
|
{
|
|
|
|
Tile tile;
|
|
|
|
char tileIsPacked = tilepacker_getTile(waloff[pPth->picnum] ? pPth->picnum+1 : 0, &tile);
|
|
|
|
//POGO: check the width and height to ensure that the tile hasn't been changed for a user tile that has different dimensions
|
|
|
|
if (tileIsPacked &&
|
|
|
|
(!waloff[pPth->picnum] ||
|
|
|
|
(tile.rect.width == (uint32_t) tilesiz[pPth->picnum].y &&
|
|
|
|
tile.rect.height == (uint32_t) tilesiz[pPth->picnum].x)))
|
|
|
|
{
|
|
|
|
texturePosSize = { tile.rect.u/(float) tilesheetSize,
|
|
|
|
tile.rect.v/(float) tilesheetSize,
|
|
|
|
tile.rect.width/(float) tilesheetSize,
|
|
|
|
tile.rect.height/(float) tilesheetSize };
|
|
|
|
halfTexelSize = tilesheetHalfTexelSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
polymost_setTexturePosSize(texturePosSize);
|
|
|
|
polymost_setHalfTexelSize(halfTexelSize);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, pPth->glpic);
|
|
|
|
}
|
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
void useShaderProgram(uint32_t shaderID)
|
|
|
|
{
|
|
|
|
glUseProgram(shaderID);
|
|
|
|
currentShaderProgramID = shaderID;
|
2018-02-16 06:37:58 +00:00
|
|
|
}
|
|
|
|
|
2008-02-24 00:46:57 +00:00
|
|
|
// one-time initialization of OpenGL for polymost
|
2006-04-13 20:47:06 +00:00
|
|
|
void polymost_glinit()
|
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glHint(GL_FOG_HINT, GL_NICEST);
|
|
|
|
glFogi(GL_FOG_MODE, (r_usenewshading < 2) ? GL_EXP2 : GL_LINEAR);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
2012-04-01 04:24:57 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
|
|
|
|
//glEnable(GL_LINE_SMOOTH);
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
if (r_useindexedcolortextures == -1)
|
|
|
|
{
|
|
|
|
//POGO: r_useindexedcolortextures has never been set, so force it to be enabled
|
|
|
|
gltexfiltermode = 0;
|
|
|
|
}
|
|
|
|
|
2018-02-16 06:38:48 +00:00
|
|
|
#ifdef USE_GLEXT
|
|
|
|
if (glmultisample > 0 && glinfo.multisample)
|
|
|
|
{
|
|
|
|
if (glinfo.nvmultisamplehint)
|
|
|
|
glHint(GL_MULTISAMPLE_FILTER_HINT_NV, glnvmultisamplehint ? GL_NICEST:GL_FASTEST);
|
|
|
|
glEnable(GL_MULTISAMPLE);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-05-08 17:32:16 +00:00
|
|
|
currentTextureID = 0;
|
|
|
|
|
|
|
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &tilesheetSize);
|
|
|
|
tilesheetHalfTexelSize = { 0.5f/tilesheetSize, 0.5f/tilesheetSize };
|
|
|
|
vec2_t maxTexDimensions = { tilesheetSize, tilesheetSize };
|
|
|
|
char allPacked = false;
|
|
|
|
static uint32_t numTilesheets = 0;
|
|
|
|
//POGO: only pack the tilesheets once
|
|
|
|
if (numTilesheets == 0)
|
|
|
|
{
|
|
|
|
// add a blank texture for tileUID 0
|
|
|
|
tilepacker_addTile(0, 2, 2);
|
|
|
|
for (int picnum = 0; picnum < MAXTILES; ++picnum)
|
|
|
|
{
|
|
|
|
tilepacker_addTile(picnum+1, (uint32_t) tilesiz[picnum].y, (uint32_t) tilesiz[picnum].x);
|
|
|
|
}
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
tilepacker_initTilesheet(numTilesheets, tilesheetSize, tilesheetSize);
|
|
|
|
allPacked = tilepacker_pack(numTilesheets);
|
|
|
|
++numTilesheets;
|
|
|
|
} while (!allPacked && numTilesheets < MAXTILESHEETS);
|
|
|
|
}
|
|
|
|
for (uint32_t i = 0; i < numTilesheets; ++i)
|
|
|
|
{
|
2019-09-16 19:27:07 +00:00
|
|
|
GetTextureHandle(tilesheetTexIDs+i);
|
2018-05-08 17:32:16 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, tilesheetTexIDs[i]);
|
|
|
|
uploadtextureindexed(true, {0, 0}, maxTexDimensions, (intptr_t) NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char blankTex[] = {255, 255,
|
|
|
|
255, 255};
|
|
|
|
Tile blankTile;
|
|
|
|
tilepacker_getTile(0, &blankTile);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, tilesheetTexIDs[blankTile.tilesheetID]);
|
|
|
|
uploadtextureindexed(false, {(int32_t) blankTile.rect.u, (int32_t) blankTile.rect.v}, {2, 2}, (intptr_t) blankTex);
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
const char* const POLYMOST2_BASIC_VERTEX_SHADER_CODE =
|
2018-02-16 06:38:34 +00:00
|
|
|
"#version 110\n\
|
|
|
|
\n\
|
|
|
|
// input\n\
|
|
|
|
attribute vec3 i_vertPos;\n\
|
|
|
|
attribute vec2 i_texCoord;\n\
|
|
|
|
uniform mat4 u_mvMatrix;\n\
|
|
|
|
uniform mat4 u_projMatrix;\n\
|
|
|
|
uniform vec2 u_texOffset;\n\
|
|
|
|
uniform vec2 u_texScale;\n\
|
|
|
|
\n\
|
|
|
|
// output\n\
|
|
|
|
varying vec2 v_texCoord;\n\
|
|
|
|
varying float v_distance;\n\
|
|
|
|
\n\
|
|
|
|
void main()\n\
|
|
|
|
{\n\
|
|
|
|
vec4 eyeCoordPosition = u_mvMatrix * vec4(i_vertPos, 1.0);\n\
|
|
|
|
gl_Position = u_projMatrix * eyeCoordPosition;\n\
|
|
|
|
\n\
|
|
|
|
eyeCoordPosition.xyz /= eyeCoordPosition.w;\n\
|
|
|
|
\n\
|
|
|
|
v_texCoord = i_texCoord * u_texScale + u_texOffset;\n\
|
|
|
|
v_distance = eyeCoordPosition.z;\n\
|
|
|
|
}\n";
|
2018-03-21 20:41:26 +00:00
|
|
|
const char* const POLYMOST2_BASIC_FRAGMENT_SHADER_CODE =
|
2018-02-16 06:38:34 +00:00
|
|
|
"#version 110\n\
|
|
|
|
\n\
|
|
|
|
varying vec2 v_texCoord;\n\
|
|
|
|
uniform sampler2D s_texture;\n\
|
|
|
|
uniform sampler2D s_fullBright;\n\
|
|
|
|
\n\
|
|
|
|
uniform vec4 u_tint;\n\
|
|
|
|
uniform float u_alpha;\n\
|
|
|
|
\n\
|
|
|
|
varying float v_distance;\n\
|
|
|
|
uniform vec2 u_fogRange;\n\
|
|
|
|
uniform vec4 u_fogColor;\n\
|
|
|
|
\n\
|
|
|
|
const float c_zero = 0.0;\n\
|
|
|
|
const float c_one = 1.0;\n\
|
|
|
|
\n\
|
|
|
|
void main()\n\
|
|
|
|
{\n\
|
|
|
|
vec4 color = texture2D(s_texture, v_texCoord);\n\
|
|
|
|
vec4 fullBrightColor = texture2D(s_fullBright, v_texCoord);\n\
|
|
|
|
\n\
|
|
|
|
float fogFactor = clamp((u_fogRange.y-v_distance)/(u_fogRange.y-u_fogRange.x), c_zero, c_one);\n\
|
|
|
|
\n\
|
|
|
|
color.rgb = mix(u_fogColor.rgb, color.rgb, fogFactor);\n\
|
|
|
|
color.rgb *= u_tint.rgb * u_tint.a * color.a;\n\
|
|
|
|
color.rgb = mix(color.rgb, fullBrightColor.rgb, fullBrightColor.a);\n\
|
|
|
|
\n\
|
|
|
|
color.a *= u_alpha;\n\
|
|
|
|
\n\
|
|
|
|
gl_FragColor = color;\n\
|
|
|
|
}\n";
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost2BasicShaderProgramID = glCreateProgram();
|
|
|
|
GLuint polymost2BasicVertexShaderID = polymost2_compileShader(GL_VERTEX_SHADER, POLYMOST2_BASIC_VERTEX_SHADER_CODE);
|
|
|
|
GLuint polymost2BasicFragmentShaderID = polymost2_compileShader(GL_FRAGMENT_SHADER, POLYMOST2_BASIC_FRAGMENT_SHADER_CODE);
|
|
|
|
glBindAttribLocation(polymost2BasicShaderProgramID, 0, "i_vertPos");
|
|
|
|
glBindAttribLocation(polymost2BasicShaderProgramID, 1, "i_texCoord");
|
|
|
|
glAttachShader(polymost2BasicShaderProgramID, polymost2BasicVertexShaderID);
|
|
|
|
glAttachShader(polymost2BasicShaderProgramID, polymost2BasicFragmentShaderID);
|
|
|
|
glLinkProgram(polymost2BasicShaderProgramID);
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
// Get the attribute/uniform locations
|
2018-03-21 20:41:26 +00:00
|
|
|
texSamplerLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "s_texture");
|
|
|
|
fullBrightSamplerLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "s_fullBright");
|
|
|
|
projMatrixLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_projMatrix");
|
|
|
|
mvMatrixLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_mvMatrix");
|
|
|
|
texOffsetLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_texOffset");
|
|
|
|
texScaleLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_texScale");
|
|
|
|
tintLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_tint");
|
|
|
|
alphaLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_alpha");
|
|
|
|
fogRangeLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_fogRange");
|
|
|
|
fogColorLoc = glGetUniformLocation(polymost2BasicShaderProgramID, "u_fogColor");
|
|
|
|
|
|
|
|
const char* const POLYMOST1_BASIC_VERTEX_SHADER_CODE =
|
|
|
|
"#version 110\n\
|
|
|
|
\n\
|
|
|
|
varying vec4 v_color;\n\
|
2019-03-19 17:08:39 +00:00
|
|
|
varying float v_distance;\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
//u_texturePosSize is the texture position & size packaged into a single vec4 as {pos.x, pos.y, size.x, size.y}\n\
|
|
|
|
uniform vec4 u_texturePosSize;\n\
|
|
|
|
uniform float u_usePalette;\n\
|
2019-03-19 17:08:39 +00:00
|
|
|
uniform mat4 u_rotMatrix;\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
const float c_zero = 0.0;\n\
|
|
|
|
const float c_one = 1.0;\n\
|
|
|
|
\n\
|
|
|
|
void main()\n\
|
|
|
|
{\n\
|
2019-03-19 17:08:39 +00:00
|
|
|
vec4 vertex = u_rotMatrix * gl_Vertex;\n\
|
|
|
|
vec4 eyeCoordPosition = gl_ModelViewMatrix * vertex;\n\
|
|
|
|
gl_Position = gl_ModelViewProjectionMatrix * vertex;\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
|
|
|
eyeCoordPosition.xyz /= eyeCoordPosition.w;\n\
|
|
|
|
\n\
|
|
|
|
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
gl_TexCoord[0] = mix(gl_TexCoord[0].xyzw, gl_TexCoord[0].yxzw, u_usePalette);\n\
|
|
|
|
\n\
|
2019-09-13 20:27:20 +00:00
|
|
|
gl_TexCoord[3] = gl_TextureMatrix[3] * gl_MultiTexCoord3;\n\
|
|
|
|
gl_TexCoord[4] = gl_TextureMatrix[4] * gl_MultiTexCoord4;\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
gl_FogFragCoord = abs(eyeCoordPosition.z);\n\
|
|
|
|
//gl_FogFragCoord = clamp((gl_Fog.end-abs(eyeCoordPosition.z))*gl_Fog.scale, c_zero, c_one);\n\
|
|
|
|
\n\
|
|
|
|
v_color = gl_Color;\n\
|
2019-03-19 17:08:39 +00:00
|
|
|
v_distance = gl_Vertex.z;\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
}\n";
|
|
|
|
const char* const POLYMOST1_BASIC_FRAGMENT_SHADER_CODE =
|
|
|
|
"#version 110\n\
|
|
|
|
\n\
|
|
|
|
//s_texture points to an indexed color texture\n\
|
|
|
|
uniform sampler2D s_texture;\n\
|
|
|
|
//s_palswap is the palette swap texture where u is the color index and v is the shade\n\
|
|
|
|
uniform sampler2D s_palswap;\n\
|
|
|
|
//s_palette is the base palette texture where u is the color index\n\
|
|
|
|
uniform sampler2D s_palette;\n\
|
|
|
|
\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
//u_texturePosSize is the texture position & size packaged into a single vec4 as {pos.x, pos.y, size.x, size.y}\n\
|
|
|
|
uniform vec4 u_texturePosSize;\n\
|
|
|
|
uniform vec2 u_halfTexelSize;\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
uniform vec2 u_palswapPos;\n\
|
|
|
|
uniform vec2 u_palswapSize;\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
uniform float u_shade;\n\
|
2019-03-19 17:08:39 +00:00
|
|
|
uniform float u_numShades;\n\
|
|
|
|
uniform float u_visFactor;\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
uniform float u_fogEnabled;\n\
|
|
|
|
\n\
|
|
|
|
uniform float u_useColorOnly;\n\
|
|
|
|
uniform float u_usePalette;\n\
|
2019-03-19 17:08:43 +00:00
|
|
|
uniform float u_npotEmulation;\n\
|
|
|
|
uniform float u_npotEmulationFactor;\n\
|
|
|
|
uniform float u_npotEmulationXOffset;\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
|
|
|
varying vec4 v_color;\n\
|
2019-03-19 17:08:39 +00:00
|
|
|
varying float v_distance;\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
const float c_basepalScale = 255.0/256.0;\n\
|
|
|
|
const float c_basepalOffset = 0.5/256.0;\n\
|
|
|
|
\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
const float c_zero = 0.0;\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
const float c_one = 1.0;\n\
|
|
|
|
const float c_two = 2.0;\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
const vec4 c_vec4_one = vec4(c_one);\n\
|
2018-07-03 04:29:23 +00:00
|
|
|
const float c_wrapThreshold = 0.9;\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
|
|
|
void main()\n\
|
|
|
|
{\n\
|
2019-03-19 17:08:43 +00:00
|
|
|
float coordY = mix(gl_TexCoord[0].y,gl_TexCoord[0].x,u_usePalette);\n\
|
|
|
|
float coordX = mix(gl_TexCoord[0].x,gl_TexCoord[0].y,u_usePalette);\n\
|
|
|
|
float period = floor(coordY/u_npotEmulationFactor);\n\
|
|
|
|
coordX += u_npotEmulationXOffset*floor(mod(coordY,u_npotEmulationFactor));\n\
|
|
|
|
coordY = period+mod(coordY,u_npotEmulationFactor);\n\
|
|
|
|
vec2 newCoord = mix(gl_TexCoord[0].xy,mix(vec2(coordX,coordY),vec2(coordY,coordX),u_usePalette),u_npotEmulation);\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
//GLSL 130+ could alternatively use texture2DGrad()\n\
|
2019-03-19 17:08:43 +00:00
|
|
|
vec2 transitionBlend = fwidth(floor(newCoord.xy));\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
transitionBlend = fwidth(transitionBlend)+transitionBlend;\n\
|
2019-03-19 17:08:43 +00:00
|
|
|
vec2 texCoord = mix(fract(newCoord.xy), abs(c_one-mod(newCoord.xy+c_one, c_two)), transitionBlend);\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
texCoord = clamp(u_texturePosSize.zw*texCoord, u_halfTexelSize, u_texturePosSize.zw-u_halfTexelSize);\n\
|
|
|
|
vec4 color = texture2D(s_texture, u_texturePosSize.xy+texCoord);\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
2019-03-19 17:08:39 +00:00
|
|
|
float shade = clamp(floor(u_shade+u_visFactor*v_distance), c_zero, u_numShades-c_one)/u_numShades;\n\
|
|
|
|
float colorIndex = texture2D(s_palswap, u_palswapPos+u_palswapSize*vec2(color.r, shade)).r;\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
colorIndex = c_basepalOffset + c_basepalScale*colorIndex;\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
vec4 palettedColor = texture2D(s_palette, vec2(colorIndex, c_zero));\n\
|
2018-07-03 04:29:19 +00:00
|
|
|
float fullbright = u_usePalette*palettedColor.a;\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
palettedColor.a = c_one-floor(color.r);\n\
|
|
|
|
color = mix(color, palettedColor, u_usePalette);\n\
|
|
|
|
\n\
|
|
|
|
color = mix(color, c_vec4_one, u_useColorOnly);\n\
|
|
|
|
\n\
|
|
|
|
// DEBUG \n\
|
|
|
|
//color = texture2D(s_palswap, gl_TexCoord[0].xy);\n\
|
|
|
|
//color = texture2D(s_palette, gl_TexCoord[0].xy);\n\
|
|
|
|
//color = texture2D(s_texture, gl_TexCoord[0].yx);\n\
|
|
|
|
\n\
|
2018-07-03 04:29:19 +00:00
|
|
|
color.rgb = mix(v_color.rgb*color.rgb, color.rgb, fullbright);\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
2019-03-19 17:08:39 +00:00
|
|
|
float fogEnabled = mix(u_fogEnabled, c_zero, u_usePalette);\n\
|
|
|
|
fullbright = max(c_one-fogEnabled, fullbright);\n\
|
2018-07-03 04:29:19 +00:00
|
|
|
float fogFactor = clamp((gl_Fog.end-gl_FogFragCoord)*gl_Fog.scale, fullbright, c_one);\n\
|
|
|
|
//float fogFactor = clamp(gl_FogFragCoord, fullbright, c_one);\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
color.rgb = mix(gl_Fog.color.rgb, color.rgb, fogFactor);\n\
|
|
|
|
\n\
|
|
|
|
color.a *= v_color.a;\n\
|
|
|
|
\n\
|
|
|
|
gl_FragColor = color;\n\
|
|
|
|
}\n";
|
|
|
|
const char* const POLYMOST1_EXTENDED_FRAGMENT_SHADER_CODE =
|
2018-03-21 20:41:32 +00:00
|
|
|
"#version 110\n\
|
|
|
|
\n\
|
|
|
|
//s_texture points to an indexed color texture\n\
|
|
|
|
uniform sampler2D s_texture;\n\
|
|
|
|
//s_palswap is the palette swap texture where u is the color index and v is the shade\n\
|
|
|
|
uniform sampler2D s_palswap;\n\
|
|
|
|
//s_palette is the base palette texture where u is the color index\n\
|
|
|
|
uniform sampler2D s_palette;\n\
|
|
|
|
\n\
|
|
|
|
uniform sampler2D s_detail;\n\
|
|
|
|
uniform sampler2D s_glow;\n\
|
|
|
|
\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
//u_texturePosSize is the texture position & size packaged into a single vec4 as {pos.x, pos.y, size.x, size.y}\n\
|
|
|
|
uniform vec4 u_texturePosSize;\n\
|
|
|
|
uniform vec2 u_halfTexelSize;\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
uniform vec2 u_palswapPos;\n\
|
|
|
|
uniform vec2 u_palswapSize;\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
uniform float u_shade;\n\
|
2019-03-19 17:08:39 +00:00
|
|
|
uniform float u_numShades;\n\
|
|
|
|
uniform float u_visFactor;\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
uniform float u_fogEnabled;\n\
|
|
|
|
\n\
|
|
|
|
uniform float u_useColorOnly;\n\
|
|
|
|
uniform float u_usePalette;\n\
|
2019-03-19 17:08:43 +00:00
|
|
|
uniform float u_npotEmulation;\n\
|
|
|
|
uniform float u_npotEmulationFactor;\n\
|
|
|
|
uniform float u_npotEmulationXOffset;\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
\n\
|
|
|
|
uniform float u_useDetailMapping;\n\
|
|
|
|
uniform float u_useGlowMapping;\n\
|
|
|
|
\n\
|
|
|
|
varying vec4 v_color;\n\
|
2019-03-19 17:08:39 +00:00
|
|
|
varying float v_distance;\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
\n\
|
|
|
|
const float c_basepalScale = 255.0/256.0;\n\
|
|
|
|
const float c_basepalOffset = 0.5/256.0;\n\
|
|
|
|
\n\
|
|
|
|
const float c_zero = 0.0;\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
const float c_one = 1.0;\n\
|
|
|
|
const float c_two = 2.0;\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
const vec4 c_vec4_one = vec4(c_one);\n\
|
2018-07-03 04:29:23 +00:00
|
|
|
const float c_wrapThreshold = 0.9;\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
\n\
|
|
|
|
void main()\n\
|
|
|
|
{\n\
|
2019-03-19 17:08:43 +00:00
|
|
|
float coordY = mix(gl_TexCoord[0].y,gl_TexCoord[0].x,u_usePalette);\n\
|
|
|
|
float coordX = mix(gl_TexCoord[0].x,gl_TexCoord[0].y,u_usePalette);\n\
|
|
|
|
float period = floor(coordY/u_npotEmulationFactor);\n\
|
|
|
|
coordX += u_npotEmulationXOffset*floor(mod(coordY,u_npotEmulationFactor));\n\
|
|
|
|
coordY = period+mod(coordY,u_npotEmulationFactor);\n\
|
|
|
|
vec2 newCoord = mix(gl_TexCoord[0].xy,mix(vec2(coordX,coordY),vec2(coordY,coordX),u_usePalette),u_npotEmulation);\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
//GLSL 130+ could alternatively use texture2DGrad()\n\
|
2019-03-19 17:08:43 +00:00
|
|
|
vec2 transitionBlend = fwidth(floor(newCoord.xy));\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
transitionBlend = fwidth(transitionBlend)+transitionBlend;\n\
|
2019-03-19 17:08:43 +00:00
|
|
|
vec2 texCoord = mix(fract(newCoord.xy), abs(c_one-mod(newCoord.xy+c_one, c_two)), transitionBlend);\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
texCoord = clamp(u_texturePosSize.zw*texCoord, u_halfTexelSize, u_texturePosSize.zw-u_halfTexelSize);\n\
|
|
|
|
vec4 color = texture2D(s_texture, u_texturePosSize.xy+texCoord);\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
2019-03-19 17:08:39 +00:00
|
|
|
float shade = clamp(floor(u_shade+u_visFactor*v_distance), c_zero, u_numShades-c_one)/u_numShades;\n\
|
|
|
|
float colorIndex = texture2D(s_palswap, u_palswapPos+u_palswapSize*vec2(color.r, shade)).r;\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
colorIndex = c_basepalOffset + c_basepalScale*colorIndex;\n\
|
|
|
|
vec4 palettedColor = texture2D(s_palette, vec2(colorIndex, c_zero));\n\
|
2018-07-03 04:29:19 +00:00
|
|
|
float fullbright = u_usePalette*palettedColor.a;\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
palettedColor.a = c_one-floor(color.r);\n\
|
|
|
|
color = mix(color, palettedColor, u_usePalette);\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
vec4 detailColor = texture2D(s_detail, gl_TexCoord[3].xy);\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
detailColor = mix(c_vec4_one, 2.0*detailColor, u_useDetailMapping*detailColor.a);\n\
|
|
|
|
color.rgb *= detailColor.rgb;\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
color = mix(color, c_vec4_one, u_useColorOnly);\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
// DEBUG \n\
|
|
|
|
//color = texture2D(s_palswap, gl_TexCoord[0].xy);\n\
|
|
|
|
//color = texture2D(s_palette, gl_TexCoord[0].xy);\n\
|
|
|
|
//color = texture2D(s_texture, gl_TexCoord[0].yx);\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
2018-07-03 04:29:19 +00:00
|
|
|
color.rgb = mix(v_color.rgb*color.rgb, color.rgb, fullbright);\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
2019-03-19 17:08:39 +00:00
|
|
|
float fogEnabled = mix(u_fogEnabled, c_zero, u_usePalette);\n\
|
|
|
|
fullbright = max(c_one-fogEnabled, fullbright);\n\
|
2018-07-03 04:29:19 +00:00
|
|
|
float fogFactor = clamp((gl_Fog.end-gl_FogFragCoord)*gl_Fog.scale, fullbright, c_one);\n\
|
|
|
|
//float fogFactor = clamp(gl_FogFragCoord, fullbright, c_one);\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
color.rgb = mix(gl_Fog.color.rgb, color.rgb, fogFactor);\n\
|
|
|
|
\n\
|
2018-05-08 17:32:16 +00:00
|
|
|
vec4 glowColor = texture2D(s_glow, gl_TexCoord[4].xy);\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
color.rgb = mix(color.rgb, glowColor.rgb, u_useGlowMapping*glowColor.a*(c_one-u_useColorOnly));\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
color.a *= v_color.a;\n\
|
2018-03-21 20:41:26 +00:00
|
|
|
\n\
|
2018-03-21 20:41:32 +00:00
|
|
|
gl_FragColor = color;\n\
|
|
|
|
}\n";
|
2018-03-21 20:41:26 +00:00
|
|
|
|
|
|
|
polymost1BasicShaderProgramID = glCreateProgram();
|
|
|
|
GLuint polymost1BasicVertexShaderID = polymost2_compileShader(GL_VERTEX_SHADER, POLYMOST1_BASIC_VERTEX_SHADER_CODE);
|
|
|
|
GLuint polymost1BasicFragmentShaderID = polymost2_compileShader(GL_FRAGMENT_SHADER, POLYMOST1_BASIC_FRAGMENT_SHADER_CODE);
|
|
|
|
glAttachShader(polymost1BasicShaderProgramID, polymost1BasicVertexShaderID);
|
|
|
|
glAttachShader(polymost1BasicShaderProgramID, polymost1BasicFragmentShaderID);
|
|
|
|
glLinkProgram(polymost1BasicShaderProgramID);
|
|
|
|
|
|
|
|
polymost1ExtendedShaderProgramID = glCreateProgram();
|
|
|
|
GLuint polymost1ExtendedFragmentShaderID = polymost2_compileShader(GL_FRAGMENT_SHADER, POLYMOST1_EXTENDED_FRAGMENT_SHADER_CODE);
|
|
|
|
glAttachShader(polymost1ExtendedShaderProgramID, polymost1BasicVertexShaderID);
|
|
|
|
glAttachShader(polymost1ExtendedShaderProgramID, polymost1ExtendedFragmentShaderID);
|
|
|
|
glLinkProgram(polymost1ExtendedShaderProgramID);
|
|
|
|
|
|
|
|
// set defaults
|
|
|
|
polymost_setCurrentShaderProgram(polymost1ExtendedShaderProgramID);
|
|
|
|
glUniform1i(polymost1TexSamplerLoc, 0);
|
|
|
|
glUniform1i(polymost1PalSwapSamplerLoc, 1);
|
|
|
|
glUniform1i(polymost1PaletteSamplerLoc, 2);
|
|
|
|
glUniform1i(polymost1DetailSamplerLoc, 3);
|
|
|
|
glUniform1i(polymost1GlowSamplerLoc, 4);
|
2018-03-21 20:41:32 +00:00
|
|
|
polymost_setPalswapSize(256, numshades+1);
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_setCurrentShaderProgram(polymost1BasicShaderProgramID);
|
|
|
|
glUniform1i(polymost1TexSamplerLoc, 0);
|
|
|
|
glUniform1i(polymost1PalSwapSamplerLoc, 1);
|
|
|
|
glUniform1i(polymost1PaletteSamplerLoc, 2);
|
|
|
|
useShaderProgram(0);
|
|
|
|
|
|
|
|
lastbasepal = -1;
|
|
|
|
for (int basepalnum = 0; basepalnum < MAXBASEPALS; ++basepalnum)
|
|
|
|
{
|
|
|
|
paletteTextureIDs[basepalnum] = 0;
|
|
|
|
uploadbasepalette(basepalnum);
|
|
|
|
}
|
2018-03-21 20:41:32 +00:00
|
|
|
palswapTextureID = 0;
|
2018-03-21 20:41:26 +00:00
|
|
|
for (int palookupnum = 0; palookupnum < MAXPALOOKUPS; ++palookupnum)
|
|
|
|
{
|
|
|
|
uploadpalswap(palookupnum);
|
|
|
|
}
|
2007-03-08 03:07:10 +00:00
|
|
|
|
2018-02-16 06:37:58 +00:00
|
|
|
polymost_resetVertexPointers();
|
2008-11-25 13:06:36 +00:00
|
|
|
|
2013-05-15 02:17:17 +00:00
|
|
|
texcache_init();
|
|
|
|
texcache_loadoffsets();
|
2013-05-15 02:18:27 +00:00
|
|
|
texcache_openfiles();
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2013-05-15 02:18:27 +00:00
|
|
|
texcache_setupmemcache();
|
|
|
|
texcache_checkgarbage();
|
2016-05-02 18:29:32 +00:00
|
|
|
|
2016-05-04 00:25:24 +00:00
|
|
|
#if defined EDUKE32_GLES
|
|
|
|
Polymost_DetermineTextureFormatSupport();
|
|
|
|
#endif
|
2008-11-25 13:06:36 +00:00
|
|
|
}
|
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
void polymost_init()
|
|
|
|
{
|
|
|
|
lastbasepal = -1;
|
|
|
|
polymost_resetVertexPointers();
|
|
|
|
}
|
|
|
|
|
2012-12-16 19:18:18 +00:00
|
|
|
////////// VISIBILITY FOG ROUTINES //////////
|
|
|
|
|
2014-03-23 23:14:48 +00:00
|
|
|
// only for r_usenewshading < 2 (not preferred)
|
2013-05-15 02:21:05 +00:00
|
|
|
static void fogcalc_old(int32_t shade, int32_t vis)
|
2013-05-15 02:19:14 +00:00
|
|
|
{
|
|
|
|
float f;
|
|
|
|
|
2018-10-25 23:31:01 +00:00
|
|
|
if (r_usenewshading == 1)
|
2013-05-15 02:19:14 +00:00
|
|
|
{
|
|
|
|
f = 0.9f * shade;
|
2018-10-25 23:31:01 +00:00
|
|
|
f = (vis > 239) ? (float)(gvisibility * (vis - 240 + f)) :
|
|
|
|
(float)(gvisibility * (vis + 16 + f));
|
2013-05-15 02:19:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
f = (shade < 0) ? shade * 3.5f : shade * .66f;
|
2018-10-25 23:31:01 +00:00
|
|
|
f = (vis > 239) ? (float)(gvisibility * ((vis - 240 + f) / (klabs(vis - 256)))) :
|
|
|
|
(float)(gvisibility * (vis + 16 + f));
|
2013-05-15 02:19:14 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:31:01 +00:00
|
|
|
fogresult = clamp(f, 0.001f, 100.0f);
|
2013-05-15 02:19:14 +00:00
|
|
|
}
|
|
|
|
|
2012-12-16 19:18:18 +00:00
|
|
|
// For GL_LINEAR fog:
|
2012-12-20 12:04:34 +00:00
|
|
|
#define FOGDISTCONST 600
|
2016-01-11 05:05:38 +00:00
|
|
|
#define FULLVIS_BEGIN 2.9e30f
|
|
|
|
#define FULLVIS_END 3.0e30f
|
2012-12-16 19:18:18 +00:00
|
|
|
|
2013-05-15 02:19:14 +00:00
|
|
|
static inline void fogcalc(int32_t tile, int32_t shade, int32_t vis, int32_t pal)
|
2012-12-16 19:18:18 +00:00
|
|
|
{
|
2018-04-12 21:03:12 +00:00
|
|
|
if (shade > 0 && videoGetRenderMode() == REND_POLYMOST && r_usetileshades == 1 &&
|
2015-03-09 20:32:36 +00:00
|
|
|
!(globalflags & GLOBAL_NO_GL_TILESHADES) &&
|
2017-06-21 13:46:59 +00:00
|
|
|
(!usehightile || !hicfindsubst(tile, pal, hictinting[pal].f & HICTINT_ALWAYSUSEART)) &&
|
2013-08-06 23:51:38 +00:00
|
|
|
(!usemodels || md_tilehasmodel(tile, pal) < 0))
|
|
|
|
shade >>= 1;
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
fogcol = fogtable[pal];
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2014-03-23 23:14:48 +00:00
|
|
|
if (r_usenewshading < 2)
|
2012-12-16 19:18:18 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
fogcalc_old(shade, vis);
|
|
|
|
return;
|
|
|
|
}
|
2012-12-16 19:18:18 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float combvis = (float) globalvisibility * (uint8_t) (vis+16);
|
|
|
|
|
|
|
|
if (combvis == 0)
|
|
|
|
{
|
|
|
|
if (r_usenewshading == 2 && shade > 0)
|
2014-04-19 22:42:23 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
// beg = -D*shade, end = D*(NUMSHADES-1-shade)
|
|
|
|
// => end/beg = -(NUMSHADES-1-shade)/shade
|
2018-10-25 23:31:01 +00:00
|
|
|
fogresult = -FULLVIS_BEGIN;
|
|
|
|
fogresult2 = FULLVIS_BEGIN * (float)(numshades-1-shade) / shade;
|
2014-04-19 22:42:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-25 23:31:01 +00:00
|
|
|
fogresult = FULLVIS_BEGIN;
|
|
|
|
fogresult2 = FULLVIS_END;
|
2014-04-19 22:42:23 +00:00
|
|
|
}
|
2012-12-16 19:18:18 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
else if (r_usenewshading == 3 && shade >= numshades-1)
|
|
|
|
{
|
|
|
|
fogresult = -1;
|
|
|
|
fogresult2 = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
combvis = 1.f/combvis;
|
2018-10-25 23:31:01 +00:00
|
|
|
fogresult = (r_usenewshading == 3 && shade > 0) ? 0.f : -(FOGDISTCONST * shade) * combvis;
|
2015-03-24 00:40:33 +00:00
|
|
|
fogresult2 = (FOGDISTCONST * (numshades-1-shade)) * combvis;
|
|
|
|
}
|
2013-05-15 02:19:14 +00:00
|
|
|
}
|
2012-12-16 19:18:18 +00:00
|
|
|
|
2017-11-29 07:29:33 +00:00
|
|
|
#define GL_FOG_MAX 1.0e37f
|
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
void polymost2_calc_fog(int32_t shade, int32_t vis, int32_t pal)
|
|
|
|
{
|
|
|
|
if (nofog) return;
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
fogresult = 0.f;
|
|
|
|
fogcol = fogtable[pal];
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
if (((uint8_t)(vis + 16)) > 0 && g_visibility > 0)
|
|
|
|
{
|
2018-08-02 01:21:16 +00:00
|
|
|
constexpr GLfloat glfogconstant = 262144.f;
|
2018-02-16 06:38:34 +00:00
|
|
|
GLfloat fogrange = (frealmaxshade * glfogconstant) / (((uint8_t)(vis + 16)) * globalvisibility);
|
|
|
|
GLfloat normalizedshade = shade / frealmaxshade;
|
|
|
|
GLfloat fogshade = normalizedshade * fogrange;
|
|
|
|
|
2018-08-02 01:21:16 +00:00
|
|
|
// fogresult = -fogshade; // uncomment this to incorporate shades in the fog
|
2018-02-16 06:38:34 +00:00
|
|
|
fogresult2 = fogrange - fogshade;
|
|
|
|
}
|
2018-08-02 01:21:16 +00:00
|
|
|
else
|
|
|
|
fogresult2 = -GL_FOG_MAX; // hide fog behind the camera
|
2018-02-16 06:38:34 +00:00
|
|
|
}
|
|
|
|
|
2013-05-15 02:19:14 +00:00
|
|
|
void calc_and_apply_fog(int32_t tile, int32_t shade, int32_t vis, int32_t pal)
|
|
|
|
{
|
2016-04-13 04:04:07 +00:00
|
|
|
if (nofog) return;
|
|
|
|
|
2017-11-29 07:29:33 +00:00
|
|
|
if (r_usenewshading == 4)
|
|
|
|
{
|
|
|
|
fogresult = 0.f;
|
|
|
|
fogcol = fogtable[pal];
|
|
|
|
|
2018-01-26 04:35:06 +00:00
|
|
|
if (((uint8_t)(vis + 16)) > 0 && globalvisibility > 0)
|
2017-11-29 07:29:33 +00:00
|
|
|
{
|
2018-08-02 01:21:16 +00:00
|
|
|
constexpr GLfloat glfogconstant = 262144.f;
|
2017-11-29 07:29:33 +00:00
|
|
|
GLfloat fogrange = (frealmaxshade * glfogconstant) / (((uint8_t)(vis + 16)) * globalvisibility);
|
|
|
|
GLfloat normalizedshade = shade / frealmaxshade;
|
|
|
|
GLfloat fogshade = normalizedshade * fogrange;
|
|
|
|
|
2018-08-02 01:21:16 +00:00
|
|
|
// fogresult = -fogshade; // uncomment this to incorporate shades in the fog
|
2017-11-29 07:29:33 +00:00
|
|
|
fogresult2 = fogrange - fogshade;
|
|
|
|
}
|
2018-08-02 01:21:16 +00:00
|
|
|
else
|
|
|
|
fogresult2 = -GL_FOG_MAX; // hide fog behind the camera
|
2017-11-29 07:29:33 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glFogf(GL_FOG_START, fogresult);
|
|
|
|
glFogf(GL_FOG_END, fogresult2);
|
|
|
|
glFogfv(GL_FOG_COLOR, (GLfloat *)&fogcol);
|
2017-11-29 07:29:33 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-05-15 02:19:14 +00:00
|
|
|
fogcalc(tile, shade, vis, pal);
|
2018-02-16 06:38:21 +00:00
|
|
|
glFogfv(GL_FOG_COLOR, (GLfloat *)&fogcol);
|
2012-12-16 19:18:18 +00:00
|
|
|
|
2014-03-23 23:14:48 +00:00
|
|
|
if (r_usenewshading < 2)
|
2018-02-16 06:38:21 +00:00
|
|
|
glFogf(GL_FOG_DENSITY, fogresult);
|
2015-01-11 04:56:58 +00:00
|
|
|
else
|
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glFogf(GL_FOG_START, fogresult);
|
|
|
|
glFogf(GL_FOG_END, fogresult2);
|
2012-12-16 19:18:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-15 02:19:14 +00:00
|
|
|
void calc_and_apply_fog_factor(int32_t tile, int32_t shade, int32_t vis, int32_t pal, float factor)
|
2012-12-16 19:18:18 +00:00
|
|
|
{
|
2016-04-13 04:04:07 +00:00
|
|
|
if (nofog) return;
|
|
|
|
|
2017-11-29 07:29:33 +00:00
|
|
|
if (r_usenewshading == 4)
|
|
|
|
{
|
|
|
|
fogcol = fogtable[pal];
|
|
|
|
|
|
|
|
if (((uint8_t)(vis + 16)) > 0 && ((((uint8_t)(vis + 16)) / 8.f) + shade) > 0)
|
|
|
|
{
|
|
|
|
GLfloat normalizedshade = shade / frealmaxshade;
|
|
|
|
GLfloat fogrange = (((uint8_t)(vis + 16)) / (8.f * frealmaxshade)) + normalizedshade;
|
|
|
|
|
2018-08-02 01:21:16 +00:00
|
|
|
// subtract shades from fog
|
2017-11-29 07:29:33 +00:00
|
|
|
if (shade > 0 && shade < realmaxshade)
|
|
|
|
fogrange = (fogrange - normalizedshade) / (1.f - normalizedshade);
|
|
|
|
|
|
|
|
fogresult = -(GL_FOG_MAX * fogrange);
|
|
|
|
fogresult2 = GL_FOG_MAX - (GL_FOG_MAX * fogrange);
|
|
|
|
}
|
2018-08-02 01:21:16 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
fogresult = 0.f;
|
|
|
|
fogresult2 = -GL_FOG_MAX; // hide fog behind the camera
|
|
|
|
}
|
2017-11-29 07:29:33 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glFogf(GL_FOG_START, fogresult);
|
|
|
|
glFogf(GL_FOG_END, fogresult2);
|
|
|
|
glFogfv(GL_FOG_COLOR, (GLfloat *)&fogcol);
|
2017-11-29 07:29:33 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-03-23 23:14:48 +00:00
|
|
|
// NOTE: for r_usenewshading >= 2, the fog beginning/ending distance results are
|
2013-07-18 18:08:10 +00:00
|
|
|
// unused.
|
2013-05-15 02:19:14 +00:00
|
|
|
fogcalc(tile, shade, vis, pal);
|
2018-02-16 06:38:21 +00:00
|
|
|
glFogfv(GL_FOG_COLOR, (GLfloat *)&fogcol);
|
2012-12-16 19:18:18 +00:00
|
|
|
|
2014-03-23 23:14:48 +00:00
|
|
|
if (r_usenewshading < 2)
|
2018-02-16 06:38:21 +00:00
|
|
|
glFogf(GL_FOG_DENSITY, fogresult*factor);
|
2015-01-11 04:56:58 +00:00
|
|
|
else
|
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glFogf(GL_FOG_START, (GLfloat) FULLVIS_BEGIN);
|
|
|
|
glFogf(GL_FOG_END, (GLfloat) FULLVIS_END);
|
2012-12-16 19:18:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
////////////////////
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-01-17 21:59:05 +00:00
|
|
|
static float get_projhack_ratio(void)
|
|
|
|
{
|
2015-05-26 00:48:04 +00:00
|
|
|
if (glprojectionhacks)
|
2013-01-17 21:59:05 +00:00
|
|
|
{
|
2019-02-18 22:02:33 +00:00
|
|
|
float const projhack_zoom = 1.4f *
|
|
|
|
// adjust for the FOV, increasing the FOV reduces the zenith glitch
|
|
|
|
// don't apply if the zenith is cut from the viewing area
|
|
|
|
(65536.f / fviewingrange) *
|
|
|
|
(float)(windowxy2.y-windowxy1.y+1) /
|
|
|
|
(float)(windowxy2.x-windowxy1.x+1) *
|
|
|
|
(float)(xdim)/(float)(ydim);
|
|
|
|
if (projhack_zoom < 1.f)
|
|
|
|
return 1.f;
|
2017-11-30 02:57:23 +00:00
|
|
|
static constexpr float const maxcoshoriz = 0.540971179375801f; // 128/sqrt(128^2+199^2) = cos of an horiz diff of 199
|
2019-02-18 22:02:33 +00:00
|
|
|
float const factor = (projhack_zoom - 1.f) * (1.f / maxcoshoriz);
|
2017-11-30 02:57:23 +00:00
|
|
|
return 1.f + (factor * (1.f - Bfabsf(gchang)));
|
2013-01-17 21:59:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// No projection hacks (legacy or new-aspect)
|
2015-05-26 00:48:04 +00:00
|
|
|
return 1.f;
|
2013-01-17 21:59:05 +00:00
|
|
|
}
|
|
|
|
|
2012-10-01 17:52:25 +00:00
|
|
|
static void resizeglcheck(void)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-02-11 05:23:04 +00:00
|
|
|
#ifndef EDUKE32_GLES
|
2006-04-24 19:04:22 +00:00
|
|
|
//FUK
|
2015-03-24 00:40:33 +00:00
|
|
|
if (lastglpolygonmode != r_polygonmode)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
lastglpolygonmode = r_polygonmode;
|
|
|
|
switch (r_polygonmode)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
default:
|
2006-11-13 23:12:47 +00:00
|
|
|
case 0:
|
2018-02-16 06:38:21 +00:00
|
|
|
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 1:
|
2018-02-16 06:38:21 +00:00
|
|
|
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 2:
|
2018-02-16 06:38:21 +00:00
|
|
|
glPolygonMode(GL_FRONT_AND_BACK,GL_POINT); break;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
if (r_polygonmode) //FUK
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glClearColor(1.0,1.0,1.0,0.0);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-02-11 05:23:04 +00:00
|
|
|
#else
|
2018-02-16 06:38:21 +00:00
|
|
|
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
|
2015-02-11 05:23:04 +00:00
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
if ((glox1 != windowxy1.x) || (gloy1 != windowxy1.y) || (glox2 != windowxy2.x) || (gloy2 != windowxy2.y))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
const int32_t ourxdimen = (windowxy2.x-windowxy1.x+1);
|
2014-10-25 03:29:21 +00:00
|
|
|
float ratio = get_projhack_ratio();
|
2015-05-26 00:48:04 +00:00
|
|
|
const int32_t fovcorrect = (int32_t)(ourxdimen*ratio - ourxdimen);
|
2017-11-30 02:57:23 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
ratio = 1.f/ratio;
|
2008-10-24 09:20:38 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
glox1 = (float)windowxy1.x; gloy1 = (float)windowxy1.y;
|
|
|
|
glox2 = (float)windowxy2.x; gloy2 = (float)windowxy2.y;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-07-14 21:36:44 +00:00
|
|
|
glViewport(windowxy1.x-(fovcorrect/2), ydim-(windowxy2.y+1),
|
2016-06-21 00:34:18 +00:00
|
|
|
ourxdimen+fovcorrect, windowxy2.y-windowxy1.y+1);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
float m[4][4];
|
2014-10-25 03:34:25 +00:00
|
|
|
Bmemset(m,0,sizeof(m));
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
|
2014-10-25 03:29:21 +00:00
|
|
|
m[0][0] = fydimen * ratio; m[0][2] = 1.f;
|
2014-10-25 03:27:35 +00:00
|
|
|
m[1][1] = fxdimen; m[1][2] = 1.f;
|
2014-10-25 03:29:21 +00:00
|
|
|
m[2][2] = 1.f; m[2][3] = fydimen * ratio;
|
2014-09-30 04:06:05 +00:00
|
|
|
m[3][2] =-1.f;
|
2018-02-16 06:38:21 +00:00
|
|
|
glLoadMatrixf(&m[0][0]);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
if (!nofog) polymost_setFogEnabled(true);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
//glEnable(GL_TEXTURE_2D);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2014-09-30 04:18:43 +00:00
|
|
|
static void fixtransparency(coltype *dapic, vec2_t dasiz, vec2_t dasiz2, int32_t dameth)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-12-04 11:52:58 +00:00
|
|
|
if (!(dameth & DAMETH_MASKPROPS))
|
|
|
|
return;
|
|
|
|
|
2014-09-30 04:18:43 +00:00
|
|
|
vec2_t doxy = { dasiz2.x-1, dasiz2.y-1 };
|
2013-04-21 19:55:11 +00:00
|
|
|
|
2015-12-04 11:52:54 +00:00
|
|
|
if (dameth & DAMETH_CLAMPED) { doxy.x = min(doxy.x, dasiz.x); doxy.y = min(doxy.y, dasiz.y); }
|
2014-09-30 04:18:43 +00:00
|
|
|
else { dasiz = dasiz2; } //Make repeating textures duplicate top/left parts
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
dasiz.x--; dasiz.y--; //Hacks for optimization inside loop
|
|
|
|
int32_t const naxsiz2 = -dasiz2.x;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Set transparent pixels to average color of neighboring opaque pixels
|
|
|
|
//Doing this makes bilinear filtering look much better for masked textures (I.E. sprites)
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t y=doxy.y; y>=0; y--)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2014-09-30 04:18:43 +00:00
|
|
|
coltype * wpptr = &dapic[y*dasiz2.x+doxy.x];
|
2014-05-28 22:40:15 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t x=doxy.x; x>=0; x--,wpptr--)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
if (wpptr->a) continue;
|
2012-11-03 19:32:48 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int r = 0, g = 0, b = 0, j = 0;
|
|
|
|
|
2012-10-01 17:52:25 +00:00
|
|
|
if ((x> 0) && (wpptr[ -1].a)) { r += wpptr[ -1].r; g += wpptr[ -1].g; b += wpptr[ -1].b; j++; }
|
2014-09-30 04:18:43 +00:00
|
|
|
if ((x<dasiz.x) && (wpptr[ +1].a)) { r += wpptr[ +1].r; g += wpptr[ +1].g; b += wpptr[ +1].b; j++; }
|
2012-10-01 17:52:25 +00:00
|
|
|
if ((y> 0) && (wpptr[naxsiz2].a)) { r += wpptr[naxsiz2].r; g += wpptr[naxsiz2].g; b += wpptr[naxsiz2].b; j++; }
|
2014-09-30 04:18:43 +00:00
|
|
|
if ((y<dasiz.y) && (wpptr[dasiz2.x].a)) { r += wpptr[dasiz2.x].r; g += wpptr[dasiz2.x].g; b += wpptr[dasiz2.x].b; j++; }
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (j)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2006-11-13 23:12:47 +00:00
|
|
|
case 1:
|
|
|
|
wpptr->r = r ; wpptr->g = g ; wpptr->b = b ; break;
|
|
|
|
case 2:
|
|
|
|
wpptr->r = ((r + 1)>>1); wpptr->g = ((g + 1)>>1); wpptr->b = ((b + 1)>>1); break;
|
|
|
|
case 3:
|
|
|
|
wpptr->r = ((r*85+128)>>8); wpptr->g = ((g*85+128)>>8); wpptr->b = ((b*85+128)>>8); break;
|
|
|
|
case 4:
|
|
|
|
wpptr->r = ((r + 2)>>2); wpptr->g = ((g + 2)>>2); wpptr->b = ((b + 2)>>2); break;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2016-02-29 06:34:20 +00:00
|
|
|
|
2016-03-28 05:16:14 +00:00
|
|
|
static void Polymost_SendTexToDriver(int32_t const doalloc,
|
|
|
|
vec2_t const siz,
|
|
|
|
int32_t const texfmt,
|
|
|
|
coltype const * const pic,
|
|
|
|
int32_t const intexfmt,
|
2016-05-04 00:25:24 +00:00
|
|
|
#if defined EDUKE32_GLES
|
|
|
|
int32_t const comprtexfmt,
|
2016-03-28 05:16:14 +00:00
|
|
|
int32_t const texcompress_ok,
|
|
|
|
#endif
|
|
|
|
int32_t const level)
|
|
|
|
{
|
|
|
|
|
2018-02-16 06:38:02 +00:00
|
|
|
#if B_BIG_ENDIAN
|
|
|
|
GLenum type = GL_UNSIGNED_INT_8_8_8_8;
|
|
|
|
#else
|
|
|
|
GLenum type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
|
|
|
#endif
|
2016-05-04 00:25:24 +00:00
|
|
|
if (doalloc & 1)
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, level, intexfmt, siz.x,siz.y, 0, texfmt, type, pic);
|
2016-05-04 00:25:24 +00:00
|
|
|
else
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, level, 0,0, siz.x,siz.y, texfmt, type, pic);
|
2019-09-16 16:00:19 +00:00
|
|
|
glGenerateMipmap(GL_TEXTURE_2D);
|
2016-03-28 05:16:14 +00:00
|
|
|
}
|
|
|
|
|
2019-09-16 16:00:19 +00:00
|
|
|
|
2016-02-29 06:34:20 +00:00
|
|
|
void uploadtexture(int32_t doalloc, vec2_t siz, int32_t texfmt,
|
2019-09-16 16:00:19 +00:00
|
|
|
coltype* pic, vec2_t tsiz, int32_t dameth)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-09-16 16:00:19 +00:00
|
|
|
int32_t intexfmt = GL_RGBA8;
|
|
|
|
#ifdef TIMING
|
|
|
|
cycle_t clock;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-09-16 16:00:19 +00:00
|
|
|
clock.Reset();
|
|
|
|
clock.Clock();
|
2016-03-28 05:16:14 +00:00
|
|
|
#endif
|
2019-09-16 16:00:19 +00:00
|
|
|
Polymost_SendTexToDriver(doalloc, siz, texfmt, pic,
|
|
|
|
intexfmt,
|
|
|
|
0);
|
2019-09-13 20:27:20 +00:00
|
|
|
|
2019-09-16 16:00:19 +00:00
|
|
|
#ifdef TIMING
|
|
|
|
clock.Unclock();
|
2014-09-30 04:18:43 +00:00
|
|
|
|
2019-09-16 16:00:19 +00:00
|
|
|
static int ttt;
|
|
|
|
OSD_Printf("%d: texture upload %d x %d took %2.3f ms\n", ttt++, siz.x, siz.y, clock.TimeMS());
|
2016-03-28 05:16:14 +00:00
|
|
|
#endif
|
2019-09-13 20:27:20 +00:00
|
|
|
|
2019-09-16 16:00:19 +00:00
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2018-05-08 17:32:16 +00:00
|
|
|
void uploadtextureindexed(int32_t doalloc, vec2_t offset, vec2_t siz, intptr_t tile)
|
2018-03-21 20:41:26 +00:00
|
|
|
{
|
|
|
|
if (doalloc & 1)
|
2018-05-08 17:32:16 +00:00
|
|
|
{
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
|
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, siz.y, siz.x, 0, GL_RED, GL_UNSIGNED_BYTE, (void*) tile);
|
2018-05-08 17:32:16 +00:00
|
|
|
}
|
2018-03-21 20:41:26 +00:00
|
|
|
else
|
2018-05-08 17:32:16 +00:00
|
|
|
{
|
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, offset.x, offset.y, siz.y, siz.x, GL_RED, GL_UNSIGNED_BYTE, (void*) tile);
|
|
|
|
}
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void uploadbasepalette(int32_t basepalnum)
|
|
|
|
{
|
|
|
|
if (!polymost1BasicShaderProgramID)
|
|
|
|
{
|
|
|
|
//POGO: if we haven't initialized properly yet, we shouldn't be uploading base palettes
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!basepaltable[basepalnum])
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-07-03 04:29:19 +00:00
|
|
|
//POGO: this is only necessary for GL fog/vertex color shade compatibility, since those features don't index into shade tables
|
2018-03-21 20:41:26 +00:00
|
|
|
uint8_t basepalWFullBrightInfo[4*256];
|
|
|
|
for (int i = 0; i < 256; ++i)
|
|
|
|
{
|
|
|
|
basepalWFullBrightInfo[i*4] = basepaltable[basepalnum][i*3];
|
|
|
|
basepalWFullBrightInfo[i*4+1] = basepaltable[basepalnum][i*3+1];
|
|
|
|
basepalWFullBrightInfo[i*4+2] = basepaltable[basepalnum][i*3+2];
|
|
|
|
basepalWFullBrightInfo[i*4+3] = 0-(IsPaletteIndexFullbright(i) != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
char allocateTexture = !paletteTextureIDs[basepalnum];
|
|
|
|
if (allocateTexture)
|
|
|
|
{
|
2019-09-13 19:43:05 +00:00
|
|
|
GetTextureHandle(&paletteTextureIDs[basepalnum]);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
glBindTexture(GL_TEXTURE_2D, paletteTextureIDs[basepalnum]);
|
|
|
|
if (allocateTexture)
|
|
|
|
{
|
2018-03-21 20:41:32 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
2018-05-08 17:32:16 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
|
2018-03-21 20:41:32 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
2018-03-21 20:41:26 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, basepalWFullBrightInfo);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 1, GL_RGBA, GL_UNSIGNED_BYTE, basepalWFullBrightInfo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void uploadpalswap(int32_t palookupnum)
|
|
|
|
{
|
|
|
|
if (!polymost1BasicShaderProgramID)
|
|
|
|
{
|
|
|
|
//POGO: if we haven't initialized properly yet, we shouldn't be uploading palette swap tables
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!palookup[palookupnum])
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-03-21 20:41:32 +00:00
|
|
|
char allocateTexture = !palswapTextureID;
|
2018-03-21 20:41:26 +00:00
|
|
|
if (allocateTexture)
|
|
|
|
{
|
2019-09-13 19:43:05 +00:00
|
|
|
GetTextureHandle(&palswapTextureID);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
2018-03-21 20:41:32 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, palswapTextureID);
|
2018-03-21 20:41:26 +00:00
|
|
|
if (allocateTexture)
|
|
|
|
{
|
2018-03-21 20:41:32 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
2018-05-08 17:32:16 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
|
2018-03-21 20:41:32 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, PALSWAP_TEXTURE_SIZE, PALSWAP_TEXTURE_SIZE, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
2018-03-21 20:41:32 +00:00
|
|
|
|
|
|
|
int32_t column = palookupnum%(PALSWAP_TEXTURE_SIZE/256);
|
|
|
|
int32_t row = palookupnum/(PALSWAP_TEXTURE_SIZE/256);
|
|
|
|
int32_t rowOffset = (numshades+1)*row;
|
|
|
|
if (rowOffset > PALSWAP_TEXTURE_SIZE)
|
2018-03-21 20:41:26 +00:00
|
|
|
{
|
2018-03-21 20:41:32 +00:00
|
|
|
OSD_Printf("Polymost: palswaps are too large for palswap tilesheet!\n");
|
|
|
|
return;
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
2018-03-21 20:41:32 +00:00
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 256*column, rowOffset, 256, numshades+1, GL_RED, GL_UNSIGNED_BYTE, palookup[palookupnum]);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
|
2011-11-26 22:41:09 +00:00
|
|
|
|
2011-11-27 12:02:41 +00:00
|
|
|
#if 0
|
2011-11-26 22:41:09 +00:00
|
|
|
// TODO: make configurable
|
|
|
|
static int32_t tile_is_sky(int32_t tilenum)
|
|
|
|
{
|
2011-11-27 12:02:41 +00:00
|
|
|
return return (tilenum >= 78 /*CLOUDYOCEAN*/ && tilenum <= 99 /*REDSKY2*/);
|
2011-11-26 22:41:09 +00:00
|
|
|
}
|
2016-12-26 06:02:06 +00:00
|
|
|
# define clamp_if_tile_is_sky(x, y) (tile_is_sky(x) ? (y) : GL_REPEAT)
|
2011-11-27 12:02:41 +00:00
|
|
|
#else
|
2016-12-26 06:02:06 +00:00
|
|
|
# define clamp_if_tile_is_sky(x, y) (GL_REPEAT)
|
2011-11-27 12:02:41 +00:00
|
|
|
#endif
|
2011-11-26 22:41:09 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
static void polymost_setuptexture(const int32_t dameth, int filter)
|
2012-10-01 17:52:25 +00:00
|
|
|
{
|
2014-09-30 04:14:21 +00:00
|
|
|
const GLuint clamp_mode = glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP;
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
gltexfiltermode = clamp(gltexfiltermode, 0, NUMGLFILTERMODES-1);
|
|
|
|
|
2015-02-11 05:23:04 +00:00
|
|
|
if (filter == -1)
|
|
|
|
filter = gltexfiltermode;
|
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfiltermodes[filter].mag);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfiltermodes[filter].min);
|
2012-10-01 17:52:25 +00:00
|
|
|
|
2016-01-08 01:33:20 +00:00
|
|
|
#ifdef USE_GLEXT
|
2014-09-30 04:06:05 +00:00
|
|
|
if (glinfo.maxanisotropy > 1.f)
|
2012-10-01 17:52:25 +00:00
|
|
|
{
|
2015-02-11 05:23:04 +00:00
|
|
|
uint32_t i = (unsigned)Blrintf(glinfo.maxanisotropy);
|
2014-09-30 04:14:21 +00:00
|
|
|
|
|
|
|
if ((unsigned)glanisotropy > i)
|
|
|
|
glanisotropy = i;
|
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, glanisotropy);
|
2012-10-01 17:52:25 +00:00
|
|
|
}
|
2015-02-11 05:23:04 +00:00
|
|
|
#endif
|
2012-10-01 17:52:25 +00:00
|
|
|
|
2014-05-28 22:40:16 +00:00
|
|
|
if (!(dameth & DAMETH_CLAMPED))
|
2012-10-01 17:52:25 +00:00
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_if_tile_is_sky(dapic, clamp_mode));
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
2012-10-01 17:52:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-02-11 05:23:04 +00:00
|
|
|
// For sprite textures, clamping looks better than wrapping
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_mode);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp_mode);
|
2012-10-01 17:52:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
static void gloadtile_art_indexed(int32_t dapic, int32_t dameth, pthtyp *pth, int32_t doalloc)
|
|
|
|
{
|
|
|
|
vec2s_t const & tsizart = tilesiz[dapic];
|
|
|
|
vec2_t siz = { tsizart.x, tsizart.y };
|
|
|
|
//POGOTODO: npoty
|
|
|
|
char npoty = 0;
|
|
|
|
|
|
|
|
//POGOTODO: if !glinfo.texnpot, then we could allocate a texture of the pow2 size, and then populate the subportion using buffersubdata func
|
|
|
|
//if (!glinfo.texnpot)
|
|
|
|
|
2018-05-08 17:32:16 +00:00
|
|
|
Tile tile = {};
|
2018-03-21 20:41:26 +00:00
|
|
|
if (waloff[dapic])
|
|
|
|
{
|
2018-05-08 17:32:16 +00:00
|
|
|
char tileIsPacked = tilepacker_getTile(dapic+1, &tile);
|
|
|
|
if (tileIsPacked &&
|
|
|
|
tile.rect.width == (uint32_t) tsizart.y &&
|
|
|
|
tile.rect.height == (uint32_t) tsizart.x)
|
|
|
|
{
|
|
|
|
pth->glpic = tilesheetTexIDs[tile.tilesheetID];
|
|
|
|
doalloc = false;
|
|
|
|
}
|
|
|
|
else if (doalloc)
|
2018-03-21 20:41:26 +00:00
|
|
|
{
|
2019-09-13 19:43:05 +00:00
|
|
|
GetTextureHandle((GLuint *)&pth->glpic);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
2018-05-08 17:32:16 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, pth->glpic);
|
2018-03-21 20:41:26 +00:00
|
|
|
|
2018-05-08 17:32:16 +00:00
|
|
|
if (doalloc)
|
|
|
|
{
|
|
|
|
const GLuint clamp_mode = glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP;
|
|
|
|
if (!(dameth & DAMETH_CLAMPED))
|
|
|
|
{
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_if_tile_is_sky(dapic, clamp_mode));
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// For sprite textures, clamping looks better than wrapping
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_mode);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp_mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uploadtextureindexed(doalloc, {(int32_t) tile.rect.u, (int32_t) tile.rect.v}, siz, waloff[dapic]);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-05-08 17:32:16 +00:00
|
|
|
tilepacker_getTile(0, &tile);
|
|
|
|
pth->glpic = tilesheetTexIDs[tile.tilesheetID];
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pth->picnum = dapic;
|
|
|
|
pth->palnum = 0;
|
|
|
|
pth->shade = 0;
|
|
|
|
pth->effects = 0;
|
|
|
|
pth->flags = TO_PTH_CLAMPED(dameth) | TO_PTH_NOTRANSFIX(dameth) | PTH_HASALPHA | (npoty*PTH_NPOTWALL) | PTH_INDEXED;
|
|
|
|
pth->hicr = NULL;
|
|
|
|
}
|
|
|
|
|
2015-04-14 08:07:41 +00:00
|
|
|
void gloadtile_art(int32_t dapic, int32_t dapal, int32_t tintpalnum, int32_t dashade, int32_t dameth, pthtyp *pth, int32_t doalloc)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-03-21 20:41:26 +00:00
|
|
|
if (dameth & PTH_INDEXED)
|
|
|
|
{
|
|
|
|
return gloadtile_art_indexed(dapic, dameth, pth, doalloc);
|
|
|
|
}
|
|
|
|
|
2012-11-10 14:11:20 +00:00
|
|
|
static int32_t fullbrightloadingpass = 0;
|
2017-06-24 09:21:13 +00:00
|
|
|
vec2s_t const & tsizart = tilesiz[dapic];
|
|
|
|
vec2_t siz = { 0, 0 }, tsiz = { tsizart.x, tsizart.y };
|
2018-10-16 06:09:54 +00:00
|
|
|
int const picdim = tsiz.x*tsiz.y;
|
2016-05-04 00:25:13 +00:00
|
|
|
char hasalpha = 0, hasfullbright = 0;
|
2016-05-04 00:25:17 +00:00
|
|
|
char npoty = 0;
|
2012-11-10 14:11:20 +00:00
|
|
|
|
2016-05-04 00:25:17 +00:00
|
|
|
texcacheheader cachead;
|
|
|
|
char texcacheid[BMAX_PATH];
|
|
|
|
{
|
|
|
|
// Absolutely disgusting.
|
|
|
|
uint32_t firstint = 0;
|
|
|
|
if (waloff[dapic])
|
|
|
|
Bmemcpy(&firstint, (void *)waloff[dapic], min(4, picdim));
|
|
|
|
sprintf(texcacheid, "%08x", firstint);
|
|
|
|
}
|
|
|
|
texcache_calcid(texcacheid, texcacheid, picdim | ((unsigned)dapal<<24u), DAMETH_NARROW_MASKPROPS(dameth) | ((unsigned)dapic<<8u) | ((unsigned)dashade<<24u), tintpalnum);
|
|
|
|
int32_t gotcache = texcache_readtexheader(texcacheid, &cachead, 0);
|
|
|
|
|
|
|
|
if (gotcache && !texcache_loadtile(&cachead, &doalloc, pth))
|
|
|
|
{
|
|
|
|
hasalpha = !!(cachead.flags & CACHEAD_HASALPHA);
|
|
|
|
hasfullbright = !!(cachead.flags & CACHEAD_HASFULLBRIGHT);
|
|
|
|
npoty = !!(cachead.flags & CACHEAD_NPOTWALL);
|
|
|
|
}
|
|
|
|
else
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2016-05-04 00:25:13 +00:00
|
|
|
if (!glinfo.texnpot)
|
|
|
|
{
|
|
|
|
for (siz.x = 1; siz.x < tsiz.x; siz.x += siz.x) { }
|
|
|
|
for (siz.y = 1; siz.y < tsiz.y; siz.y += siz.y) { }
|
|
|
|
}
|
2007-12-12 17:42:14 +00:00
|
|
|
else
|
2016-05-04 00:25:13 +00:00
|
|
|
{
|
|
|
|
if ((tsiz.x|tsiz.y) == 0)
|
|
|
|
siz.x = siz.y = 1;
|
|
|
|
else
|
|
|
|
siz = tsiz;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
coltype *pic = (coltype *)Xmalloc(siz.x*siz.y*sizeof(coltype));
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
if (!waloff[dapic])
|
|
|
|
{
|
|
|
|
//Force invalid textures to draw something - an almost purely transparency texture
|
|
|
|
//This allows the Z-buffer to be updated for mirrors (which are invalidated textures)
|
|
|
|
pic[0].r = pic[0].g = pic[0].b = 0; pic[0].a = 1;
|
|
|
|
tsiz.x = tsiz.y = 1; hasalpha = 1;
|
|
|
|
}
|
|
|
|
else
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2016-05-04 00:25:13 +00:00
|
|
|
const int dofullbright = !(picanm[dapic].sf & PICANM_NOFULLBRIGHT_BIT) && !(globalflags & GLOBAL_NO_GL_FULLBRIGHT);
|
2012-11-10 14:11:20 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t y = 0; y < siz.y; y++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2016-05-04 00:25:13 +00:00
|
|
|
coltype *wpptr = &pic[y * siz.x];
|
|
|
|
int32_t y2 = (y < tsiz.y) ? y : y - tsiz.y;
|
2012-11-10 14:11:20 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t x = 0; x < siz.x; x++, wpptr++)
|
2014-05-28 22:40:15 +00:00
|
|
|
{
|
2016-05-04 00:25:13 +00:00
|
|
|
int32_t dacol;
|
|
|
|
int32_t x2 = (x < tsiz.x) ? x : x-tsiz.x;
|
2012-11-10 14:11:20 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
if ((dameth & DAMETH_CLAMPED) && (x >= tsiz.x || y >= tsiz.y)) //Clamp texture
|
|
|
|
{
|
|
|
|
wpptr->r = wpptr->g = wpptr->b = wpptr->a = 0;
|
|
|
|
continue;
|
|
|
|
}
|
2015-12-20 05:18:47 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
dacol = *(char *)(waloff[dapic]+x2*tsiz.y+y2);
|
2015-12-20 05:18:47 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
if (dacol == 255)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2012-11-10 14:11:20 +00:00
|
|
|
wpptr->a = 0;
|
|
|
|
hasalpha = 1;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2016-05-04 00:25:13 +00:00
|
|
|
else
|
|
|
|
wpptr->a = 255;
|
2015-04-14 08:07:41 +00:00
|
|
|
|
2017-09-19 19:10:33 +00:00
|
|
|
char *p = (char *)(palookup[dapal])+(int32_t)(dashade<<8);
|
|
|
|
dacol = (uint8_t)p[dacol];
|
2015-04-14 08:07:41 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
if (!fullbrightloadingpass)
|
2015-04-14 08:07:41 +00:00
|
|
|
{
|
2016-05-04 00:25:13 +00:00
|
|
|
// regular texture
|
|
|
|
if (IsPaletteIndexFullbright(dacol) && dofullbright)
|
|
|
|
hasfullbright = 1;
|
2015-04-14 08:07:41 +00:00
|
|
|
}
|
2016-05-04 00:25:13 +00:00
|
|
|
else
|
2015-04-14 08:07:41 +00:00
|
|
|
{
|
2016-05-04 00:25:13 +00:00
|
|
|
// texture with only fullbright areas
|
|
|
|
if (!IsPaletteIndexFullbright(dacol)) // regular colors
|
|
|
|
{
|
|
|
|
wpptr->a = 0;
|
|
|
|
hasalpha = 1;
|
|
|
|
}
|
2015-04-14 08:07:41 +00:00
|
|
|
}
|
2015-04-14 08:08:02 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
bricolor((palette_t *)wpptr, dacol);
|
|
|
|
|
|
|
|
if (!fullbrightloadingpass && tintpalnum >= 0)
|
2015-04-14 08:08:02 +00:00
|
|
|
{
|
2017-06-21 13:46:44 +00:00
|
|
|
polytint_t const & tint = hictinting[tintpalnum];
|
|
|
|
polytintflags_t const effect = tint.f;
|
|
|
|
uint8_t const r = tint.r;
|
|
|
|
uint8_t const g = tint.g;
|
|
|
|
uint8_t const b = tint.b;
|
2016-05-04 00:25:13 +00:00
|
|
|
|
|
|
|
if (effect & HICTINT_GRAYSCALE)
|
|
|
|
{
|
|
|
|
wpptr->g = wpptr->r = wpptr->b = (uint8_t) ((wpptr->r * GRAYSCALE_COEFF_RED) +
|
|
|
|
(wpptr->g * GRAYSCALE_COEFF_GREEN) +
|
|
|
|
(wpptr->b * GRAYSCALE_COEFF_BLUE));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (effect & HICTINT_INVERT)
|
|
|
|
{
|
|
|
|
wpptr->b = 255 - wpptr->b;
|
|
|
|
wpptr->g = 255 - wpptr->g;
|
|
|
|
wpptr->r = 255 - wpptr->r;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (effect & HICTINT_COLORIZE)
|
|
|
|
{
|
|
|
|
wpptr->b = min((int32_t)((wpptr->b) * b) >> 6, 255);
|
|
|
|
wpptr->g = min((int32_t)((wpptr->g) * g) >> 6, 255);
|
|
|
|
wpptr->r = min((int32_t)((wpptr->r) * r) >> 6, 255);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (effect & HICTINT_BLENDMASK)
|
|
|
|
{
|
|
|
|
case HICTINT_BLEND_SCREEN:
|
|
|
|
wpptr->b = 255 - (((255 - wpptr->b) * (255 - b)) >> 8);
|
|
|
|
wpptr->g = 255 - (((255 - wpptr->g) * (255 - g)) >> 8);
|
|
|
|
wpptr->r = 255 - (((255 - wpptr->r) * (255 - r)) >> 8);
|
|
|
|
break;
|
|
|
|
case HICTINT_BLEND_OVERLAY:
|
|
|
|
wpptr->b = wpptr->b < 128 ? (wpptr->b * b) >> 7 : 255 - (((255 - wpptr->b) * (255 - b)) >> 7);
|
|
|
|
wpptr->g = wpptr->g < 128 ? (wpptr->g * g) >> 7 : 255 - (((255 - wpptr->g) * (255 - g)) >> 7);
|
|
|
|
wpptr->r = wpptr->r < 128 ? (wpptr->r * r) >> 7 : 255 - (((255 - wpptr->r) * (255 - r)) >> 7);
|
|
|
|
break;
|
|
|
|
case HICTINT_BLEND_HARDLIGHT:
|
|
|
|
wpptr->b = b < 128 ? (wpptr->b * b) >> 7 : 255 - (((255 - wpptr->b) * (255 - b)) >> 7);
|
|
|
|
wpptr->g = g < 128 ? (wpptr->g * g) >> 7 : 255 - (((255 - wpptr->g) * (255 - g)) >> 7);
|
|
|
|
wpptr->r = r < 128 ? (wpptr->r * r) >> 7 : 255 - (((255 - wpptr->r) * (255 - r)) >> 7);
|
|
|
|
break;
|
|
|
|
}
|
2015-04-14 08:08:02 +00:00
|
|
|
}
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:02 +00:00
|
|
|
//swap r & b so that we deal with the data as BGRA
|
|
|
|
uint8_t tmpR = wpptr->r;
|
|
|
|
wpptr->r = wpptr->b;
|
|
|
|
wpptr->b = tmpR;
|
2015-04-14 08:07:41 +00:00
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-13 19:43:05 +00:00
|
|
|
if (doalloc) GetTextureHandle((GLuint *)&pth->glpic); //# of textures (make OpenGL allocate structure)
|
2018-05-08 17:32:16 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, pth->glpic);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
fixtransparency(pic,tsiz,siz,dameth);
|
2014-06-01 11:55:19 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
if (polymost_want_npotytex(dameth, siz.y) && tsiz.x == siz.x && tsiz.y == siz.y) // XXX
|
|
|
|
{
|
|
|
|
const int32_t nextpoty = 1 << ((picsiz[dapic] >> 4) + 1);
|
|
|
|
const int32_t ydif = nextpoty - siz.y;
|
|
|
|
coltype *paddedpic;
|
2014-06-01 11:55:19 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
Bassert(ydif < siz.y);
|
2014-06-01 11:55:19 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
paddedpic = (coltype *)Xrealloc(pic, siz.x * nextpoty * sizeof(coltype));
|
2014-06-01 11:55:19 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
pic = paddedpic;
|
|
|
|
Bmemcpy(&pic[siz.x * siz.y], pic, siz.x * ydif * sizeof(coltype));
|
|
|
|
siz.y = tsiz.y = nextpoty;
|
2014-06-01 11:55:19 +00:00
|
|
|
|
2016-05-04 00:25:17 +00:00
|
|
|
npoty = 1;
|
2016-05-04 00:25:13 +00:00
|
|
|
}
|
2014-06-01 11:55:19 +00:00
|
|
|
|
2018-02-16 06:38:02 +00:00
|
|
|
uploadtexture(doalloc, siz, GL_BGRA, pic, tsiz,
|
2016-05-04 00:25:13 +00:00
|
|
|
dameth | DAMETH_ARTIMMUNITY |
|
|
|
|
(dapic >= MAXUSERTILES ? (DAMETH_NOTEXCOMPRESS|DAMETH_NODOWNSIZE) : 0) | /* never process these short-lived tiles */
|
2016-05-04 00:25:17 +00:00
|
|
|
(hasfullbright ? DAMETH_HASFULLBRIGHT : 0) |
|
|
|
|
(npoty ? DAMETH_NPOTWALL : 0) |
|
2016-05-04 00:25:13 +00:00
|
|
|
(hasalpha ? (DAMETH_HASALPHA|DAMETH_ONEBITALPHA) : 0));
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-05-04 00:25:13 +00:00
|
|
|
Bfree(pic);
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
polymost_setuptexture(dameth, -1);
|
2015-02-11 05:23:04 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
pth->picnum = dapic;
|
|
|
|
pth->palnum = dapal;
|
2013-05-15 02:18:27 +00:00
|
|
|
pth->shade = dashade;
|
2006-04-24 19:04:22 +00:00
|
|
|
pth->effects = 0;
|
2016-05-04 00:25:17 +00:00
|
|
|
pth->flags = TO_PTH_CLAMPED(dameth) | TO_PTH_NOTRANSFIX(dameth) | (hasalpha*PTH_HASALPHA) | (npoty*PTH_NPOTWALL);
|
2006-04-24 19:04:22 +00:00
|
|
|
pth->hicr = NULL;
|
|
|
|
|
2016-05-04 00:25:17 +00:00
|
|
|
#if defined USE_GLEXT && !defined EDUKE32_GLES
|
|
|
|
if (!gotcache && glinfo.texcompr && glusetexcache && glusetexcompr == 2 && dapic < MAXUSERTILES)
|
|
|
|
{
|
|
|
|
cachead.quality = 0;
|
|
|
|
cachead.xdim = tsiz.x;
|
|
|
|
cachead.ydim = tsiz.y;
|
|
|
|
|
|
|
|
cachead.flags = (check_nonpow2(siz.x) || check_nonpow2(siz.y)) * CACHEAD_NONPOW2 |
|
|
|
|
npoty * CACHEAD_NPOTWALL |
|
|
|
|
hasalpha * CACHEAD_HASALPHA | hasfullbright * CACHEAD_HASFULLBRIGHT | CACHEAD_NODOWNSIZE;
|
|
|
|
|
|
|
|
texcache_writetex_fromdriver(texcacheid, &cachead);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-11-10 14:11:20 +00:00
|
|
|
if (hasfullbright && !fullbrightloadingpass)
|
2006-07-24 02:47:47 +00:00
|
|
|
{
|
2012-11-10 14:11:20 +00:00
|
|
|
// Load the ONLY texture that'll be assembled with the regular one to
|
|
|
|
// make the final texture with fullbright pixels.
|
2006-07-24 02:47:47 +00:00
|
|
|
fullbrightloadingpass = 1;
|
2014-05-28 22:40:15 +00:00
|
|
|
|
2017-12-02 12:42:40 +00:00
|
|
|
if (!pth->ofb)
|
|
|
|
pth->ofb = (pthtyp *)Xcalloc(1,sizeof(pthtyp));
|
|
|
|
|
2014-05-28 22:40:16 +00:00
|
|
|
pth->flags |= PTH_HASFULLBRIGHT;
|
2014-05-28 22:40:15 +00:00
|
|
|
|
2016-06-05 04:46:40 +00:00
|
|
|
gloadtile_art(dapic, dapal, -1, 0, (dameth & ~DAMETH_MASKPROPS) | DAMETH_MASK, pth->ofb, 1);
|
2006-07-22 02:32:03 +00:00
|
|
|
|
2006-07-24 02:47:47 +00:00
|
|
|
fullbrightloadingpass = 0;
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2013-05-15 02:17:17 +00:00
|
|
|
int32_t gloadtile_hi(int32_t dapic,int32_t dapalnum, int32_t facen, hicreplctyp *hicr,
|
2017-06-21 13:46:44 +00:00
|
|
|
int32_t dameth, pthtyp *pth, int32_t doalloc, polytintflags_t effect)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-02-11 05:23:04 +00:00
|
|
|
if (!hicr) return -1;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-05-03 07:05:21 +00:00
|
|
|
char *fn;
|
2011-01-09 18:53:06 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (facen > 0)
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!hicr->skybox || facen > 6 || !hicr->skybox->face[facen-1])
|
|
|
|
return -1;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
fn = hicr->skybox->face[facen-1];
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!hicr->filename)
|
|
|
|
return -1;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
fn = hicr->filename;
|
|
|
|
}
|
|
|
|
|
2019-03-01 08:51:50 +00:00
|
|
|
buildvfs_kfd filh;
|
|
|
|
if (EDUKE32_PREDICT_FALSE((filh = kopen4load(fn, 0)) == buildvfs_kfd_invalid))
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2008-07-30 02:51:32 +00:00
|
|
|
OSD_Printf("hightile: %s (pic %d) not found\n", fn, dapic);
|
2014-09-30 04:06:05 +00:00
|
|
|
return -2;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2014-05-28 22:40:15 +00:00
|
|
|
|
2016-03-04 19:24:54 +00:00
|
|
|
int32_t picfillen = kfilelength(filh);
|
2006-04-24 19:04:22 +00:00
|
|
|
kclose(filh); // FIXME: shouldn't have to do this. bug in cache1d.c
|
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
int32_t startticks = timerGetTicks(), willprint = 0;
|
2016-03-04 19:24:54 +00:00
|
|
|
|
|
|
|
char hasalpha;
|
2015-02-11 05:23:04 +00:00
|
|
|
texcacheheader cachead;
|
2016-05-04 00:25:02 +00:00
|
|
|
char texcacheid[BMAX_PATH];
|
2017-06-21 13:46:36 +00:00
|
|
|
texcache_calcid(texcacheid, fn, picfillen+(dapalnum<<8), DAMETH_NARROW_MASKPROPS(dameth), effect & HICTINT_IN_MEMORY);
|
2016-05-04 00:25:02 +00:00
|
|
|
int32_t gotcache = texcache_readtexheader(texcacheid, &cachead, 0);
|
2015-05-03 07:05:21 +00:00
|
|
|
vec2_t siz = { 0, 0 }, tsiz = { 0, 0 };
|
2014-05-28 22:40:15 +00:00
|
|
|
|
2013-05-15 02:17:17 +00:00
|
|
|
if (gotcache && !texcache_loadtile(&cachead, &doalloc, pth))
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2014-09-30 04:18:43 +00:00
|
|
|
tsiz.x = cachead.xdim;
|
|
|
|
tsiz.y = cachead.ydim;
|
2016-03-04 19:24:54 +00:00
|
|
|
hasalpha = !!(cachead.flags & CACHEAD_HASALPHA);
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-03-04 19:24:54 +00:00
|
|
|
// CODEDUP: mdloadskin
|
|
|
|
|
2015-05-03 07:05:21 +00:00
|
|
|
int32_t isart = 0;
|
2012-05-05 22:23:44 +00:00
|
|
|
|
2013-05-15 02:17:17 +00:00
|
|
|
gotcache = 0; // the compressed version will be saved to disk
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-05-03 07:05:21 +00:00
|
|
|
int32_t const length = kpzbufload(fn);
|
|
|
|
if (length == 0)
|
|
|
|
return -1;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-05-03 07:05:21 +00:00
|
|
|
// tsizx/y = replacement texture's natural size
|
|
|
|
// xsiz/y = 2^x size of replacement
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-05-03 07:05:21 +00:00
|
|
|
#ifdef WITHKPLIB
|
|
|
|
kpgetdim(kpzbuf,picfillen,&tsiz.x,&tsiz.y);
|
|
|
|
#endif
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-05-03 07:05:21 +00:00
|
|
|
if (tsiz.x == 0 || tsiz.y == 0)
|
|
|
|
{
|
2018-04-12 21:03:30 +00:00
|
|
|
if (artCheckUnitFileHeader((uint8_t *)kpzbuf, picfillen))
|
2015-05-03 07:05:21 +00:00
|
|
|
return -1;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-05-03 07:05:21 +00:00
|
|
|
tsiz.x = B_LITTLE16(B_UNBUF16(&kpzbuf[16]));
|
|
|
|
tsiz.y = B_LITTLE16(B_UNBUF16(&kpzbuf[18]));
|
|
|
|
|
|
|
|
if (tsiz.x == 0 || tsiz.y == 0)
|
|
|
|
return -1;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-05-03 07:05:21 +00:00
|
|
|
isart = 1;
|
|
|
|
}
|
2014-09-30 04:18:43 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
pth->siz = tsiz;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (!glinfo.texnpot)
|
|
|
|
{
|
2016-01-12 10:31:12 +00:00
|
|
|
for (siz.x=1; siz.x<tsiz.x; siz.x+=siz.x) { }
|
|
|
|
for (siz.y=1; siz.y<tsiz.y; siz.y+=siz.y) { }
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
else
|
2015-03-24 00:40:33 +00:00
|
|
|
siz = tsiz;
|
|
|
|
|
2015-05-03 07:05:21 +00:00
|
|
|
if (isart)
|
|
|
|
{
|
|
|
|
if (tsiz.x * tsiz.y + ARTv1_UNITOFFSET > picfillen)
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t const bytesperline = siz.x * sizeof(coltype);
|
2016-03-04 19:24:54 +00:00
|
|
|
coltype *pic = (coltype *)Xcalloc(siz.y, bytesperline);
|
2011-01-09 18:53:06 +00:00
|
|
|
|
2015-02-11 05:23:04 +00:00
|
|
|
static coltype *lastpic = NULL;
|
|
|
|
static char *lastfn = NULL;
|
|
|
|
static int32_t lastsize = 0;
|
|
|
|
|
2010-03-11 23:35:22 +00:00
|
|
|
if (lastpic && lastfn && !Bstrcmp(lastfn,fn))
|
|
|
|
{
|
2011-01-30 11:02:28 +00:00
|
|
|
willprint=1;
|
2014-09-30 04:18:43 +00:00
|
|
|
Bmemcpy(pic, lastpic, siz.x*siz.y*sizeof(coltype));
|
2010-03-11 23:35:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-05-03 07:05:21 +00:00
|
|
|
if (isart)
|
|
|
|
{
|
2018-04-12 21:03:30 +00:00
|
|
|
artConvertRGB((palette_t *)pic, (uint8_t *)&kpzbuf[ARTv1_UNITOFFSET], siz.x, tsiz.x, tsiz.y);
|
2015-05-03 07:05:21 +00:00
|
|
|
}
|
|
|
|
#ifdef WITHKPLIB
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (kprender(kpzbuf,picfillen,(intptr_t)pic,bytesperline,siz.x,siz.y))
|
|
|
|
{
|
|
|
|
Bfree(pic);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-01-30 11:02:28 +00:00
|
|
|
willprint=2;
|
2010-03-11 23:35:22 +00:00
|
|
|
|
|
|
|
if (hicprecaching)
|
|
|
|
{
|
|
|
|
lastfn = fn; // careful...
|
|
|
|
if (!lastpic)
|
|
|
|
{
|
2018-10-25 23:28:56 +00:00
|
|
|
lastpic = (coltype *)Xmalloc(siz.x*siz.y*sizeof(coltype));
|
2014-09-30 04:18:43 +00:00
|
|
|
lastsize = siz.x*siz.y;
|
2010-03-11 23:35:22 +00:00
|
|
|
}
|
2014-09-30 04:18:43 +00:00
|
|
|
else if (lastsize < siz.x*siz.y)
|
2010-03-11 23:35:22 +00:00
|
|
|
{
|
|
|
|
Bfree(lastpic);
|
2018-10-25 23:28:56 +00:00
|
|
|
lastpic = (coltype *)Xmalloc(siz.x*siz.y*sizeof(coltype));
|
2010-03-11 23:35:22 +00:00
|
|
|
}
|
|
|
|
if (lastpic)
|
2014-09-30 04:18:43 +00:00
|
|
|
Bmemcpy(lastpic, pic, siz.x*siz.y*sizeof(coltype));
|
2010-03-11 23:35:22 +00:00
|
|
|
}
|
|
|
|
else if (lastpic)
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
DO_FREE_AND_NULL(lastpic);
|
2010-03-11 23:35:22 +00:00
|
|
|
lastfn = NULL;
|
|
|
|
lastsize = 0;
|
|
|
|
}
|
|
|
|
}
|
2008-03-27 21:32:23 +00:00
|
|
|
|
2016-03-04 19:24:54 +00:00
|
|
|
char *cptr = britable[gammabrightness ? 0 : curbrightness];
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2017-06-21 13:46:50 +00:00
|
|
|
polytint_t const & tint = hictinting[dapalnum];
|
|
|
|
int32_t r = (glinfo.bgra) ? tint.r : tint.b;
|
|
|
|
int32_t g = tint.g;
|
|
|
|
int32_t b = (glinfo.bgra) ? tint.b : tint.r;
|
2014-05-28 22:40:15 +00:00
|
|
|
|
2016-03-04 19:24:54 +00:00
|
|
|
char al = 255;
|
2016-03-07 11:22:02 +00:00
|
|
|
char onebitalpha = 1;
|
2016-03-04 19:24:54 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t y = 0, j = 0; y < tsiz.y; ++y, j += siz.x)
|
2016-03-04 19:24:54 +00:00
|
|
|
{
|
|
|
|
coltype tcol, *rpptr = &pic[j];
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t x = 0; x < tsiz.x; ++x)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
tcol.b = cptr[rpptr[x].b];
|
|
|
|
tcol.g = cptr[rpptr[x].g];
|
|
|
|
tcol.r = cptr[rpptr[x].r];
|
2016-03-07 11:22:02 +00:00
|
|
|
al &= tcol.a = rpptr[x].a;
|
|
|
|
onebitalpha &= tcol.a == 0 || tcol.a == 255;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2014-05-28 22:40:16 +00:00
|
|
|
if (effect & HICTINT_GRAYSCALE)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2015-04-14 21:17:52 +00:00
|
|
|
tcol.g = tcol.r = tcol.b = (uint8_t) ((tcol.b * GRAYSCALE_COEFF_RED) +
|
2015-03-24 00:40:33 +00:00
|
|
|
(tcol.g * GRAYSCALE_COEFF_GREEN) +
|
2015-04-14 21:17:52 +00:00
|
|
|
(tcol.r * GRAYSCALE_COEFF_BLUE));
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2014-05-28 22:40:16 +00:00
|
|
|
|
|
|
|
if (effect & HICTINT_INVERT)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
tcol.b = 255 - tcol.b;
|
|
|
|
tcol.g = 255 - tcol.g;
|
|
|
|
tcol.r = 255 - tcol.r;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2014-05-28 22:40:16 +00:00
|
|
|
|
|
|
|
if (effect & HICTINT_COLORIZE)
|
2008-03-27 21:32:23 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
tcol.b = min((int32_t)((tcol.b) * r) >> 6, 255);
|
|
|
|
tcol.g = min((int32_t)((tcol.g) * g) >> 6, 255);
|
|
|
|
tcol.r = min((int32_t)((tcol.r) * b) >> 6, 255);
|
2008-03-27 21:32:23 +00:00
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-04-14 08:08:02 +00:00
|
|
|
switch (effect & HICTINT_BLENDMASK)
|
|
|
|
{
|
|
|
|
case HICTINT_BLEND_SCREEN:
|
|
|
|
tcol.b = 255 - (((255 - tcol.b) * (255 - r)) >> 8);
|
|
|
|
tcol.g = 255 - (((255 - tcol.g) * (255 - g)) >> 8);
|
|
|
|
tcol.r = 255 - (((255 - tcol.r) * (255 - b)) >> 8);
|
|
|
|
break;
|
|
|
|
case HICTINT_BLEND_OVERLAY:
|
|
|
|
tcol.b = tcol.b < 128 ? (tcol.b * r) >> 7 : 255 - (((255 - tcol.b) * (255 - r)) >> 7);
|
|
|
|
tcol.g = tcol.g < 128 ? (tcol.g * g) >> 7 : 255 - (((255 - tcol.g) * (255 - g)) >> 7);
|
|
|
|
tcol.r = tcol.r < 128 ? (tcol.r * b) >> 7 : 255 - (((255 - tcol.r) * (255 - b)) >> 7);
|
|
|
|
break;
|
|
|
|
case HICTINT_BLEND_HARDLIGHT:
|
|
|
|
tcol.b = r < 128 ? (tcol.b * r) >> 7 : 255 - (((255 - tcol.b) * (255 - r)) >> 7);
|
|
|
|
tcol.g = g < 128 ? (tcol.g * g) >> 7 : 255 - (((255 - tcol.g) * (255 - g)) >> 7);
|
|
|
|
tcol.r = b < 128 ? (tcol.r * b) >> 7 : 255 - (((255 - tcol.r) * (255 - b)) >> 7);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-09-30 04:18:43 +00:00
|
|
|
rpptr[x] = tcol;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
2012-05-05 22:23:44 +00:00
|
|
|
|
2016-03-04 19:24:54 +00:00
|
|
|
hasalpha = (al != 255);
|
|
|
|
|
2014-05-28 22:40:16 +00:00
|
|
|
if ((!(dameth & DAMETH_CLAMPED)) || facen) //Duplicate texture pixels (wrapping tricks for non power of 2 texture sizes)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (siz.x > tsiz.x) // Copy left to right
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2016-03-04 19:24:54 +00:00
|
|
|
for (int32_t y = 0, *lptr = (int32_t *)pic; y < tsiz.y; y++, lptr += siz.x)
|
2015-03-24 00:40:33 +00:00
|
|
|
Bmemcpy(&lptr[tsiz.x], lptr, (siz.x - tsiz.x) << 2);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if (siz.y > tsiz.y) // Copy top to bottom
|
|
|
|
Bmemcpy(&pic[siz.x * tsiz.y], pic, (siz.y - tsiz.y) * siz.x << 2);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2012-05-05 22:23:44 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (!glinfo.bgra)
|
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=siz.x*siz.y, j=0; j<i; j++)
|
2006-04-24 19:04:22 +00:00
|
|
|
swapchar(&pic[j].r, &pic[j].b);
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2016-03-04 19:24:54 +00:00
|
|
|
|
|
|
|
// end CODEDUP
|
2012-05-05 22:23:44 +00:00
|
|
|
|
2014-09-30 04:18:43 +00:00
|
|
|
if (tsiz.x>>r_downsize <= tilesiz[dapic].x || tsiz.y>>r_downsize <= tilesiz[dapic].y)
|
2016-03-07 11:21:55 +00:00
|
|
|
hicr->flags |= HICR_ARTIMMUNITY;
|
2009-04-23 07:09:24 +00:00
|
|
|
|
2012-05-05 22:23:44 +00:00
|
|
|
if ((doalloc&3)==1)
|
2019-09-13 19:43:05 +00:00
|
|
|
GetTextureHandle(&pth->glpic); //# of textures (make OpenGL allocate structure)
|
2018-05-08 17:32:16 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, pth->glpic);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2014-09-30 04:18:43 +00:00
|
|
|
fixtransparency(pic,tsiz,siz,dameth);
|
2016-02-17 19:08:32 +00:00
|
|
|
|
2016-03-04 19:24:54 +00:00
|
|
|
int32_t const texfmt = glinfo.bgra ? GL_BGRA : GL_RGBA;
|
|
|
|
|
2016-02-29 06:34:20 +00:00
|
|
|
uploadtexture(doalloc,siz,texfmt,pic,tsiz,
|
|
|
|
dameth | DAMETH_HI | DAMETH_NOFIX |
|
|
|
|
TO_DAMETH_NODOWNSIZE(hicr->flags) |
|
|
|
|
TO_DAMETH_NOTEXCOMPRESS(hicr->flags) |
|
2016-03-07 11:21:55 +00:00
|
|
|
TO_DAMETH_ARTIMMUNITY(hicr->flags) |
|
2016-03-07 11:22:02 +00:00
|
|
|
(onebitalpha ? DAMETH_ONEBITALPHA : 0) |
|
2016-03-04 19:24:54 +00:00
|
|
|
(hasalpha ? DAMETH_HASALPHA : 0));
|
|
|
|
|
|
|
|
Bfree(pic);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// precalculate scaling parameters for replacement
|
2007-12-12 17:42:14 +00:00
|
|
|
if (facen > 0)
|
|
|
|
{
|
2014-09-30 04:18:43 +00:00
|
|
|
pth->scale.x = (float)tsiz.x * (1.0f/64.f);
|
|
|
|
pth->scale.y = (float)tsiz.y * (1.0f/64.f);
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-09-30 04:18:43 +00:00
|
|
|
pth->scale.x = (float)tsiz.x / (float)tilesiz[dapic].x;
|
|
|
|
pth->scale.y = (float)tsiz.y / (float)tilesiz[dapic].y;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 23:31:30 +00:00
|
|
|
polymost_setuptexture(dameth, (hicr->flags & HICR_FORCEFILTER) ? TEXFILTER_ON : -1);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2014-09-30 04:18:43 +00:00
|
|
|
if (tsiz.x>>r_downsize <= tilesiz[dapic].x || tsiz.y>>r_downsize <= tilesiz[dapic].y)
|
2016-03-07 11:21:55 +00:00
|
|
|
hicr->flags |= HICR_ARTIMMUNITY;
|
2009-04-23 07:09:24 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
pth->picnum = dapic;
|
|
|
|
pth->effects = effect;
|
2015-12-04 11:52:58 +00:00
|
|
|
pth->flags = TO_PTH_CLAMPED(dameth) | TO_PTH_NOTRANSFIX(dameth) |
|
|
|
|
PTH_HIGHTILE | ((facen>0) * PTH_SKYBOX) |
|
2016-03-04 19:24:54 +00:00
|
|
|
(hasalpha ? PTH_HASALPHA : 0) |
|
2018-10-25 23:31:30 +00:00
|
|
|
((hicr->flags & HICR_FORCEFILTER) ? PTH_FORCEFILTER : 0);
|
2006-04-24 19:04:22 +00:00
|
|
|
pth->skyface = facen;
|
|
|
|
pth->hicr = hicr;
|
|
|
|
|
2016-05-04 00:25:06 +00:00
|
|
|
#if defined USE_GLEXT && !defined EDUKE32_GLES
|
2016-03-07 11:21:58 +00:00
|
|
|
if (!gotcache && glinfo.texcompr && glusetexcache && !(hicr->flags & HICR_NOTEXCOMPRESS) &&
|
|
|
|
(glusetexcompr == 2 || (glusetexcompr && !(hicr->flags & HICR_ARTIMMUNITY))))
|
2014-11-22 12:34:29 +00:00
|
|
|
{
|
|
|
|
const int32_t nonpow2 = check_nonpow2(siz.x) || check_nonpow2(siz.y);
|
2014-05-28 22:40:15 +00:00
|
|
|
|
2014-11-22 12:34:29 +00:00
|
|
|
// save off the compressed version
|
2016-03-07 11:21:55 +00:00
|
|
|
cachead.quality = (hicr->flags & (HICR_NODOWNSIZE|HICR_ARTIMMUNITY)) ? 0 : r_downsize;
|
2014-11-22 12:34:29 +00:00
|
|
|
cachead.xdim = tsiz.x >> cachead.quality;
|
|
|
|
cachead.ydim = tsiz.y >> cachead.quality;
|
2014-05-28 22:40:15 +00:00
|
|
|
|
2016-02-29 06:34:12 +00:00
|
|
|
// handle nodownsize:
|
2016-03-04 19:24:54 +00:00
|
|
|
cachead.flags = nonpow2 * CACHEAD_NONPOW2 | (hasalpha ? CACHEAD_HASALPHA : 0) |
|
2018-10-25 23:31:30 +00:00
|
|
|
((hicr->flags & (HICR_NODOWNSIZE|HICR_ARTIMMUNITY)) ? CACHEAD_NODOWNSIZE : 0);
|
2014-05-28 22:40:16 +00:00
|
|
|
|
2014-11-22 12:34:29 +00:00
|
|
|
/// OSD_Printf("Caching \"%s\"\n", fn);
|
2016-05-04 00:25:06 +00:00
|
|
|
texcache_writetex_fromdriver(texcacheid, &cachead);
|
2011-01-09 18:53:06 +00:00
|
|
|
|
2014-11-22 12:34:29 +00:00
|
|
|
if (willprint)
|
|
|
|
{
|
2018-04-12 21:02:51 +00:00
|
|
|
int32_t etime = timerGetTicks() - startticks;
|
2014-11-22 12:34:29 +00:00
|
|
|
if (etime >= MIN_CACHETIME_PRINT)
|
|
|
|
OSD_Printf("Load tile %4d: p%d-m%d-e%d %s... cached... %d ms\n", dapic, dapalnum, dameth, effect,
|
|
|
|
willprint == 2 ? fn : "", etime);
|
|
|
|
willprint = 0;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2014-11-22 12:34:29 +00:00
|
|
|
else
|
|
|
|
OSD_Printf("Cached \"%s\"\n", fn);
|
|
|
|
}
|
2016-05-04 00:25:06 +00:00
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2011-01-30 11:02:28 +00:00
|
|
|
if (willprint)
|
|
|
|
{
|
2018-04-12 21:02:51 +00:00
|
|
|
int32_t etime = timerGetTicks()-startticks;
|
2011-01-30 11:02:28 +00:00
|
|
|
if (etime>=MIN_CACHETIME_PRINT)
|
|
|
|
OSD_Printf("Load tile %4d: p%d-m%d-e%d %s... %d ms\n", dapic, dapalnum, dameth, effect,
|
|
|
|
willprint==2 ? fn : "", etime);
|
|
|
|
}
|
2011-01-09 18:53:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2016-01-08 01:33:20 +00:00
|
|
|
#ifdef USE_GLEXT
|
2014-09-30 04:14:21 +00:00
|
|
|
void polymost_setupdetailtexture(const int32_t texunits, const int32_t tex)
|
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glActiveTexture(texunits);
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
2014-09-30 04:14:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void polymost_setupglowtexture(const int32_t texunits, const int32_t tex)
|
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glActiveTexture(texunits);
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
2014-09-30 04:14:21 +00:00
|
|
|
}
|
2015-05-16 20:16:27 +00:00
|
|
|
#endif
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//(dpx,dpy) specifies an n-sided polygon. The polygon must be a convex clockwise loop.
|
|
|
|
// n must be <= 8 (assume clipping can double number of vertices)
|
|
|
|
//method: 0:solid, 1:masked(255 is transparent), 2:transluscent #1, 3:transluscent #2
|
|
|
|
// +4 means it's a sprite, so wraparound isn't needed
|
2013-03-04 01:23:29 +00:00
|
|
|
|
|
|
|
// drawpoly's hack globals
|
2019-03-19 17:08:51 +00:00
|
|
|
static int32_t pow2xsplit = 0, skyclamphack = 0, skyzbufferhack = 0;
|
2015-03-24 00:40:33 +00:00
|
|
|
static float drawpoly_alpha = 0.f;
|
2016-10-09 07:55:23 +00:00
|
|
|
static uint8_t drawpoly_blend = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2014-09-30 18:18:15 +00:00
|
|
|
static inline pthtyp *our_texcache_fetch(int32_t dameth)
|
2013-08-12 15:18:12 +00:00
|
|
|
{
|
2017-11-29 07:29:33 +00:00
|
|
|
if (r_usenewshading == 4)
|
|
|
|
return texcache_fetch(globalpicnum, globalpal, getpalookup((r_usetileshades == 1 && !(globalflags & GLOBAL_NO_GL_TILESHADES)), globalshade), dameth);
|
|
|
|
|
2013-08-12 15:18:12 +00:00
|
|
|
// r_usetileshades 1 is TX's method.
|
2015-03-09 20:32:36 +00:00
|
|
|
return texcache_fetch(globalpicnum, globalpal, getpalookup((r_usetileshades == 1 && !(globalflags & GLOBAL_NO_GL_TILESHADES)) ? globvis>>3 : 0, globalshade), dameth);
|
2013-08-12 15:18:12 +00:00
|
|
|
}
|
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
|
2018-03-21 20:41:32 +00:00
|
|
|
static void polymost_updatePalette()
|
2018-03-21 20:41:26 +00:00
|
|
|
{
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() != REND_POLYMOST)
|
2019-09-16 16:10:28 +00:00
|
|
|
{
|
2018-03-21 20:41:26 +00:00
|
|
|
return;
|
2019-09-16 16:10:28 +00:00
|
|
|
}
|
2018-03-21 20:41:26 +00:00
|
|
|
|
2018-03-21 20:41:32 +00:00
|
|
|
polymost_setPalswap(globalpal);
|
|
|
|
polymost_setShade(globalshade);
|
2018-03-21 20:41:26 +00:00
|
|
|
|
|
|
|
//POGO: only bind the base pal once when it's swapped
|
|
|
|
if (curbasepal != lastbasepal)
|
|
|
|
{
|
|
|
|
glActiveTexture(GL_TEXTURE2);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, paletteTextureIDs[curbasepal]);
|
|
|
|
lastbasepal = curbasepal;
|
2018-03-21 20:41:32 +00:00
|
|
|
glActiveTexture(GL_TEXTURE0);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-13 20:27:20 +00:00
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
static void polymost_updaterotmat(void)
|
|
|
|
{
|
|
|
|
if (currentShaderProgramID == polymost1CurrentShaderProgramID)
|
|
|
|
{
|
|
|
|
float matrix[16] = {
|
|
|
|
1.f, 0.f, 0.f, 0.f,
|
|
|
|
0.f, 1.f, 0.f, 0.f,
|
|
|
|
0.f, 0.f, 1.f, 0.f,
|
|
|
|
0.f, 0.f, 0.f, 1.f,
|
|
|
|
};
|
|
|
|
#if !SOFTROTMAT
|
|
|
|
//Up/down rotation
|
|
|
|
float udmatrix[16] = {
|
|
|
|
1.f, 0.f, 0.f, 0.f,
|
|
|
|
0.f, gchang, -gshang, 0.f,
|
|
|
|
0.f, gshang, gchang, 0.f,
|
|
|
|
0.f, 0.f, 0.f, 1.f,
|
|
|
|
};
|
|
|
|
// Tilt rotation
|
|
|
|
float tiltmatrix[16] = {
|
|
|
|
gctang, -gstang, 0.f, 0.f,
|
|
|
|
gstang, gctang, 0.f, 0.f,
|
|
|
|
0.f, 0.f, 1.f, 0.f,
|
|
|
|
0.f, 0.f, 0.f, 1.f,
|
|
|
|
};
|
|
|
|
multiplyMatrix4f(matrix, udmatrix);
|
|
|
|
multiplyMatrix4f(matrix, tiltmatrix);
|
|
|
|
#endif
|
|
|
|
Bmemcpy(polymost1RotMatrix, matrix, sizeof(matrix));
|
|
|
|
glUniformMatrix4fv(polymost1RotMatrixLoc, 1, false, polymost1RotMatrix);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void polymost_identityrotmat(void)
|
|
|
|
{
|
|
|
|
if (currentShaderProgramID == polymost1CurrentShaderProgramID)
|
|
|
|
{
|
|
|
|
float matrix[16] = {
|
|
|
|
1.f, 0.f, 0.f, 0.f,
|
|
|
|
0.f, 1.f, 0.f, 0.f,
|
|
|
|
0.f, 0.f, 1.f, 0.f,
|
|
|
|
0.f, 0.f, 0.f, 1.f,
|
|
|
|
};
|
|
|
|
Bmemcpy(polymost1RotMatrix, matrix, sizeof(matrix));
|
|
|
|
glUniformMatrix4fv(polymost1RotMatrixLoc, 1, false, polymost1RotMatrix);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
static void polymost_drawpoly(vec2f_t const * const dpxy, int32_t const n, int32_t method)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
if (method == DAMETH_BACKFACECULL ||
|
2011-09-10 15:44:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2016-06-21 00:34:18 +00:00
|
|
|
g_nodraw ||
|
2011-09-10 15:44:53 +00:00
|
|
|
#endif
|
2016-06-21 00:34:18 +00:00
|
|
|
(uint32_t)globalpicnum >= MAXTILES)
|
|
|
|
return;
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
const int32_t method_ = method;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (n == 3)
|
|
|
|
{
|
2014-10-25 03:33:26 +00:00
|
|
|
if ((dpxy[0].x-dpxy[1].x) * (dpxy[2].y-dpxy[1].y) >=
|
|
|
|
(dpxy[2].x-dpxy[1].x) * (dpxy[0].y-dpxy[1].y)) return; //for triangle
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
float f = 0; //f is area of polygon / 2
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=n-2, j=n-1,k=0; k<n; i=j,j=k,k++)
|
2014-10-25 03:33:26 +00:00
|
|
|
f += (dpxy[i].x-dpxy[k].x)*dpxy[j].y;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (f <= 0) return;
|
|
|
|
}
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (palookup[globalpal] == NULL)
|
|
|
|
globalpal = 0;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Load texture (globalpicnum)
|
|
|
|
setgotpic(globalpicnum);
|
2017-06-24 09:21:13 +00:00
|
|
|
vec2s_t const & tsizart = tilesiz[globalpicnum];
|
|
|
|
vec2_t tsiz = { tsizart.x, tsizart.y };
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (!waloff[globalpicnum])
|
|
|
|
{
|
2018-04-12 21:03:30 +00:00
|
|
|
tileLoad(globalpicnum);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (!waloff[globalpicnum])
|
|
|
|
{
|
2014-09-30 04:14:21 +00:00
|
|
|
tsiz.x = tsiz.y = 1;
|
2015-12-04 11:52:54 +00:00
|
|
|
method = DAMETH_MASK; //Hack to update Z-buffer for invalid mirror textures
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 06:37:58 +00:00
|
|
|
Bassert(n <= MAX_DRAWPOLY_VERTS);
|
2015-07-08 03:34:20 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int j = 0;
|
|
|
|
float px[8], py[8], dd[8], uu[8], vv[8];
|
2019-03-19 17:08:39 +00:00
|
|
|
#if SOFTROTMAT
|
2015-03-24 00:40:33 +00:00
|
|
|
float const ozgs = ghalfx * gshang,
|
|
|
|
ozgc = ghalfx * gchang;
|
2019-03-19 17:08:39 +00:00
|
|
|
#endif
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<n; ++i)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2019-03-19 17:08:39 +00:00
|
|
|
#if SOFTROTMAT
|
2014-09-30 04:14:21 +00:00
|
|
|
//Up/down rotation
|
2016-06-21 00:34:18 +00:00
|
|
|
vec3f_t const orot = { dpxy[i].x - ghalfx,
|
|
|
|
(dpxy[i].y - ghoriz) * gchang - ozgs,
|
|
|
|
(dpxy[i].y - ghoriz) * gshang + ozgc };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// Tilt rotation
|
|
|
|
float const r = ghalfx / orot.z;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
px[j] = ghalfx + (((orot.x * gctang) - (orot.y * gstang)) * r);
|
|
|
|
py[j] = ghoriz + (((orot.x * gstang) + (orot.y * gctang)) * r);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
dd[j] = (dpxy[i].x * xtex.d + dpxy[i].y * ytex.d + otex.d) * r;
|
|
|
|
uu[j] = (dpxy[i].x * xtex.u + dpxy[i].y * ytex.u + otex.u) * r;
|
|
|
|
vv[j] = (dpxy[i].x * xtex.v + dpxy[i].y * ytex.v + otex.v) * r;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if ((!j) || (px[j] != px[j-1]) || (py[j] != py[j-1]))
|
|
|
|
j++;
|
2019-03-19 17:08:39 +00:00
|
|
|
#else
|
|
|
|
px[j] = dpxy[i].x;
|
|
|
|
py[j] = dpxy[i].y;
|
|
|
|
|
|
|
|
dd[j] = (dpxy[i].x * xtex.d + dpxy[i].y * ytex.d + otex.d);
|
|
|
|
uu[j] = (dpxy[i].x * xtex.u + dpxy[i].y * ytex.u + otex.u);
|
|
|
|
vv[j] = (dpxy[i].x * xtex.v + dpxy[i].y * ytex.v + otex.v);
|
|
|
|
j++;
|
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
while ((j >= 3) && (px[j-1] == px[0]) && (py[j-1] == py[0])) j--;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (j < 3)
|
|
|
|
return;
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int const npoints = j;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (skyclamphack) method |= DAMETH_CLAMPED;
|
2006-07-22 22:52:24 +00:00
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
pthtyp *pth = our_texcache_fetch(method | (videoGetRenderMode() == REND_POLYMOST && r_useindexedcolortextures ? PTH_INDEXED : 0));
|
2011-06-26 13:00:31 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!pth)
|
|
|
|
{
|
|
|
|
if (editstatus)
|
2014-09-30 04:14:21 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
Bsprintf(ptempbuf, "pth==NULL! (bad pal?) pic=%d pal=%d", globalpicnum, globalpal);
|
|
|
|
polymost_printext256(8,8, editorcolors[15],editorcolors[5], ptempbuf, 0);
|
2014-09-30 04:14:21 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-07-22 22:52:24 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
static int32_t fullbright_pass = 0;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-11-25 12:07:41 +00:00
|
|
|
if (pth->flags & PTH_HASFULLBRIGHT && r_fullbrights)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
|
|
|
if (!fullbright_pass)
|
|
|
|
fullbright_pass = 1;
|
|
|
|
else if (fullbright_pass == 2)
|
|
|
|
pth = pth->ofb;
|
|
|
|
}
|
2008-01-03 21:54:58 +00:00
|
|
|
|
2018-10-07 05:23:25 +00:00
|
|
|
Bassert(pth);
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// If we aren't rendmode 3, we're in Polymer, which means this code is
|
|
|
|
// used for rotatesprite only. Polymer handles all the material stuff,
|
|
|
|
// just submit the geometry and don't mess with textures.
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2018-10-07 05:23:25 +00:00
|
|
|
polymost_bindPth(pth);
|
2018-03-21 20:41:26 +00:00
|
|
|
|
2018-10-07 05:23:25 +00:00
|
|
|
//POGOTODO: I could move this into bindPth
|
|
|
|
if (!(pth->flags & PTH_INDEXED))
|
|
|
|
polymost_usePaletteIndexing(false);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if (drawpoly_srepeat)
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
|
2015-03-24 00:40:33 +00:00
|
|
|
if (drawpoly_trepeat)
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
|
2015-03-24 00:40:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// texture scale by parkar request
|
2018-10-07 05:23:25 +00:00
|
|
|
if (pth->hicr && !drawingskybox && ((pth->hicr->scale.x != 1.0f) || (pth->hicr->scale.y != 1.0f)))
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
|
|
glLoadIdentity();
|
|
|
|
glScalef(pth->hicr->scale.x, pth->hicr->scale.y, 1.0f);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
2015-03-24 00:40:33 +00:00
|
|
|
}
|
|
|
|
|
2016-01-08 01:33:20 +00:00
|
|
|
#ifdef USE_GLEXT
|
2018-02-16 06:38:21 +00:00
|
|
|
int32_t texunits = GL_TEXTURE0;
|
2007-02-17 02:23:50 +00:00
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
2018-03-21 20:41:26 +00:00
|
|
|
{
|
2018-03-21 20:41:32 +00:00
|
|
|
polymost_updatePalette();
|
2018-03-21 20:41:26 +00:00
|
|
|
texunits += 4;
|
|
|
|
}
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// detail texture
|
|
|
|
if (r_detailmapping)
|
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
pthtyp *detailpth = NULL;
|
|
|
|
|
2017-06-21 13:46:54 +00:00
|
|
|
if (usehightile && !drawingskybox && hicfindsubst(globalpicnum, DETAILPAL, 1) &&
|
2015-12-04 11:52:58 +00:00
|
|
|
(detailpth = texcache_fetch(globalpicnum, DETAILPAL, 0, method & ~DAMETH_MASKPROPS)) &&
|
2018-10-25 23:29:38 +00:00
|
|
|
detailpth->hicr && detailpth->hicr->palnum == DETAILPAL)
|
2007-01-15 09:08:57 +00:00
|
|
|
{
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_useDetailMapping(true);
|
2018-04-12 21:03:12 +00:00
|
|
|
polymost_setupdetailtexture(videoGetRenderMode() == REND_POLYMOST ? GL_TEXTURE3 : ++texunits, detailpth->glpic);
|
2007-01-15 09:08:57 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
|
|
glLoadIdentity();
|
2007-03-01 18:19:11 +00:00
|
|
|
|
2018-10-07 05:23:25 +00:00
|
|
|
if (pth->hicr && ((pth->hicr->scale.x != 1.0f) || (pth->hicr->scale.y != 1.0f)))
|
2018-02-16 06:38:21 +00:00
|
|
|
glScalef(pth->hicr->scale.x, pth->hicr->scale.y, 1.0f);
|
2007-03-01 18:19:11 +00:00
|
|
|
|
2018-02-16 06:37:58 +00:00
|
|
|
if ((detailpth->hicr->scale.x != 1.0f) || (detailpth->hicr->scale.y != 1.0f))
|
2018-02-16 06:38:21 +00:00
|
|
|
glScalef(detailpth->hicr->scale.x, detailpth->hicr->scale.y, 1.0f);
|
2007-03-01 18:19:11 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
2018-03-21 20:41:32 +00:00
|
|
|
glActiveTexture(GL_TEXTURE0);
|
2007-01-15 09:08:57 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
}
|
2007-01-15 09:08:57 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// glow texture
|
|
|
|
if (r_glowmapping)
|
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
pthtyp *glowpth = NULL;
|
|
|
|
|
2017-06-21 13:46:54 +00:00
|
|
|
if (usehightile && !drawingskybox && hicfindsubst(globalpicnum, GLOWPAL, 1) &&
|
2016-06-05 04:46:40 +00:00
|
|
|
(glowpth = texcache_fetch(globalpicnum, GLOWPAL, 0, (method & ~DAMETH_MASKPROPS) | DAMETH_MASK)) &&
|
2018-10-25 23:29:38 +00:00
|
|
|
glowpth->hicr && (glowpth->hicr->palnum == GLOWPAL))
|
2018-02-16 06:37:58 +00:00
|
|
|
{
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_useGlowMapping(true);
|
2018-04-12 21:03:12 +00:00
|
|
|
polymost_setupglowtexture(videoGetRenderMode() == REND_POLYMOST ? GL_TEXTURE4 : ++texunits, glowpth->glpic);
|
2018-03-21 20:41:32 +00:00
|
|
|
glActiveTexture(GL_TEXTURE0);
|
2018-02-16 06:37:58 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
}
|
2019-03-19 17:08:43 +00:00
|
|
|
|
|
|
|
if (glinfo.texnpot && r_npotwallmode == 2 && (method & DAMETH_WALL) != 0)
|
|
|
|
{
|
|
|
|
int32_t size = tilesiz[globalpicnum].y;
|
|
|
|
int32_t size2;
|
|
|
|
for (size2 = 1; size2 < size; size2 += size2) {}
|
|
|
|
if (size == size2)
|
|
|
|
polymost_npotEmulation(false, 1.f, 0.f);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float xOffset = 1.f / tilesiz[globalpicnum].x;
|
|
|
|
polymost_npotEmulation(true, (1.f*size2) / size, xOffset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
polymost_npotEmulation(false, 1.f, 0.f);
|
|
|
|
}
|
2015-02-11 05:23:04 +00:00
|
|
|
#endif
|
2007-02-15 01:35:34 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2f_t hacksc = { 1.f, 1.f };
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2018-10-07 05:23:25 +00:00
|
|
|
if (pth->flags & PTH_HIGHTILE)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
|
|
|
hacksc = pth->scale;
|
|
|
|
tsiz = pth->siz;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2_t tsiz2 = tsiz;
|
|
|
|
|
|
|
|
if (!glinfo.texnpot)
|
|
|
|
{
|
|
|
|
for (tsiz2.x = 1; tsiz2.x < tsiz.x; tsiz2.x += tsiz2.x)
|
|
|
|
; /* do nothing */
|
|
|
|
for (tsiz2.y = 1; tsiz2.y < tsiz.y; tsiz2.y += tsiz2.y)
|
|
|
|
; /* do nothing */
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2019-03-19 17:08:51 +00:00
|
|
|
static int32_t skyzbufferhack_pass = 0;
|
|
|
|
|
2018-05-17 22:33:13 +00:00
|
|
|
if (!waloff[globalpicnum])
|
|
|
|
{
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
}
|
|
|
|
else if (!(method & DAMETH_MASKPROPS) && fullbright_pass < 2)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
2015-03-24 00:40:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-25 23:29:38 +00:00
|
|
|
float const al = alphahackarray[globalpicnum] != 0 ? alphahackarray[globalpicnum] * (1.f/255.f) :
|
|
|
|
(pth->hicr && pth->hicr->alphacut >= 0.f ? pth->hicr->alphacut : 0.f);
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glAlphaFunc(GL_GREATER, al);
|
2018-02-16 06:38:07 +00:00
|
|
|
handle_blend((method & DAMETH_MASKPROPS) > DAMETH_MASK, drawpoly_blend, (method & DAMETH_MASKPROPS) == DAMETH_TRANS2);
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
2015-03-24 00:40:33 +00:00
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float pc[4];
|
2014-03-23 23:14:50 +00:00
|
|
|
|
|
|
|
#ifdef POLYMER
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMER && pr_artmapping && !(globalflags & GLOBAL_NO_GL_TILESHADES) && polymer_eligible_for_artmap(globalpicnum, pth))
|
2015-03-24 00:40:33 +00:00
|
|
|
pc[0] = pc[1] = pc[2] = 1.0f;
|
|
|
|
else
|
2014-03-23 23:14:50 +00:00
|
|
|
#endif
|
2017-12-12 05:13:58 +00:00
|
|
|
{
|
|
|
|
polytint_t const & tint = hictinting[globalpal];
|
2018-10-07 05:23:25 +00:00
|
|
|
float shadeFactor = (pth->flags & PTH_INDEXED) &&
|
2018-07-03 04:29:19 +00:00
|
|
|
r_usetileshades &&
|
|
|
|
!(globalflags & GLOBAL_NO_GL_TILESHADES) ? 1.f : getshadefactor(globalshade);
|
2018-03-21 20:41:26 +00:00
|
|
|
pc[0] = (1.f-(tint.sr*(1.f/255.f)))*shadeFactor+(tint.sr*(1.f/255.f));
|
|
|
|
pc[1] = (1.f-(tint.sg*(1.f/255.f)))*shadeFactor+(tint.sg*(1.f/255.f));
|
|
|
|
pc[2] = (1.f-(tint.sb*(1.f/255.f)))*shadeFactor+(tint.sb*(1.f/255.f));
|
2017-12-12 05:13:58 +00:00
|
|
|
}
|
2013-05-15 02:19:14 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// spriteext full alpha control
|
2016-10-09 07:55:23 +00:00
|
|
|
pc[3] = float_trans(method & DAMETH_MASKPROPS, drawpoly_blend) * (1.f - drawpoly_alpha);
|
|
|
|
|
2018-10-07 05:23:25 +00:00
|
|
|
// tinting
|
|
|
|
polytintflags_t const tintflags = hictinting[globalpal].f;
|
|
|
|
if (!(tintflags & HICTINT_PRECOMPUTED))
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2018-10-07 05:23:25 +00:00
|
|
|
if (pth->flags & PTH_HIGHTILE)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2018-10-07 05:23:25 +00:00
|
|
|
if (pth->palnum != globalpal || (pth->effects & HICTINT_IN_MEMORY) || (tintflags & HICTINT_APPLYOVERALTPAL))
|
2015-03-24 00:40:33 +00:00
|
|
|
hictinting_apply(pc, globalpal);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2018-10-07 05:23:25 +00:00
|
|
|
else if (tintflags & (HICTINT_USEONART|HICTINT_ALWAYSUSEART))
|
|
|
|
hictinting_apply(pc, globalpal);
|
|
|
|
}
|
2015-04-14 21:18:08 +00:00
|
|
|
|
2018-10-07 05:23:25 +00:00
|
|
|
// global tinting
|
|
|
|
if ((pth->flags & PTH_HIGHTILE) && have_basepal_tint())
|
|
|
|
hictinting_apply(pc, MAXPALOOKUPS-1);
|
2018-01-26 04:35:11 +00:00
|
|
|
|
2018-10-07 05:23:25 +00:00
|
|
|
globaltinting_apply(pc);
|
2018-02-26 14:46:36 +00:00
|
|
|
|
2019-03-19 17:08:51 +00:00
|
|
|
if (skyzbufferhack_pass)
|
|
|
|
pc[3] = 0.01f;
|
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glColor4f(pc[0], pc[1], pc[2], pc[3]);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
//POGOTODO: remove this, replace it with a shader implementation
|
2015-03-24 00:40:33 +00:00
|
|
|
//Hack for walls&masked walls which use textures that are not a power of 2
|
|
|
|
if ((pow2xsplit) && (tsiz.x != tsiz2.x))
|
|
|
|
{
|
|
|
|
vec3f_t const opxy[3] = { { py[1] - py[2], py[2] - py[0], py[0] - py[1] },
|
|
|
|
{ px[2] - px[1], px[0] - px[2], px[1] - px[0] },
|
|
|
|
{ px[0] - .5f, py[0] - .5f, 0 } };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float const r = 1.f / (opxy[0].x*px[0] + opxy[0].y*px[1] + opxy[0].z*px[2]);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
vec3f_t ngx = { (opxy[0].x * dd[0] + opxy[0].y * dd[1] + opxy[0].z * dd[2]) * r,
|
|
|
|
((opxy[0].x * uu[0] + opxy[0].y * uu[1] + opxy[0].z * uu[2]) * r) * hacksc.x,
|
|
|
|
((opxy[0].x * vv[0] + opxy[0].y * vv[1] + opxy[0].z * vv[2]) * r) * hacksc.y };
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
vec3f_t ngy = { (opxy[1].x * dd[0] + opxy[1].y * dd[1] + opxy[1].z * dd[2]) * r,
|
|
|
|
((opxy[1].x * uu[0] + opxy[1].y * uu[1] + opxy[1].z * uu[2]) * r) * hacksc.x,
|
|
|
|
((opxy[1].x * vv[0] + opxy[1].y * vv[1] + opxy[1].z * vv[2]) * r) * hacksc.y };
|
2015-03-24 03:33:57 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
vec3f_t ngo = { dd[0] - opxy[2].x * ngx.d - opxy[2].y * ngy.d,
|
|
|
|
(uu[0] - opxy[2].x * ngx.u - opxy[2].y * ngy.u) * hacksc.x,
|
|
|
|
(vv[0] - opxy[2].x * ngx.v - opxy[2].y * ngy.v) * hacksc.y };
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float const uoffs = ((float)(tsiz2.x - tsiz.x) * 0.5f);
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
ngx.u -= ngx.d * uoffs;
|
|
|
|
ngy.u -= ngy.d * uoffs;
|
|
|
|
ngo.u -= ngo.d * uoffs;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-01-30 16:02:29 +00:00
|
|
|
float du0 = 0.f, du1 = 0.f;
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
//Find min&max u coordinates (du0...du1)
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<npoints; ++i)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
|
|
|
vec2f_t const o = { px[i], py[i] };
|
2016-06-21 00:34:18 +00:00
|
|
|
float const f = (o.x*ngx.u + o.y*ngy.u + ngo.u) / (o.x*ngx.d + o.y*ngy.d + ngo.d);
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!i) { du0 = du1 = f; continue; }
|
|
|
|
if (f < du0) du0 = f;
|
|
|
|
else if (f > du1) du1 = f;
|
|
|
|
}
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float const rf = 1.0f / tsiz.x;
|
2016-06-21 00:34:18 +00:00
|
|
|
int const ix1 = (int)floorf(du1 * rf);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t ix0 = (int)floorf(du0 * rf); ix0 <= ix1; ++ix0)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
|
|
|
du0 = (float)(ix0 * tsiz.x); // + uoffs;
|
|
|
|
du1 = (float)((ix0 + 1) * tsiz.x); // + uoffs;
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
float duj = (px[0]*ngx.u + py[0]*ngy.u + ngo.u) / (px[0]*ngx.d + py[0]*ngy.d + ngo.d);
|
2015-03-24 00:40:33 +00:00
|
|
|
int i = 0, nn = 0;
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
j = i + 1;
|
|
|
|
|
|
|
|
if (j == npoints)
|
|
|
|
j = 0;
|
|
|
|
|
|
|
|
float const dui = duj;
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
duj = (px[j]*ngx.u + py[j]*ngy.u + ngo.u) / (px[j]*ngx.d + py[j]*ngy.d + ngo.d);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if ((du0 <= dui) && (dui <= du1))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
uu[nn] = px[i];
|
|
|
|
vv[nn] = py[i];
|
|
|
|
nn++;
|
|
|
|
}
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
//ox*(ngx.u-ngx.d*du1) + oy*(ngy.u-ngdy*du1) + (ngo.u-ngo.d*du1) = 0
|
2015-03-24 00:40:33 +00:00
|
|
|
//(px[j]-px[i])*f + px[i] = ox
|
|
|
|
//(py[j]-py[i])*f + py[i] = oy
|
|
|
|
|
|
|
|
///Solve for f
|
2016-06-21 00:34:18 +00:00
|
|
|
//((px[j]-px[i])*f + px[i])*(ngx.u-ngx.d*du1) +
|
|
|
|
//((py[j]-py[i])*f + py[i])*(ngy.u-ngdy*du1) + (ngo.u-ngo.d*du1) = 0
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2018-02-16 06:38:48 +00:00
|
|
|
//POGOTODO: this could be a static inline function -- the do/while loop should be just a pair of braces
|
2015-03-24 00:40:33 +00:00
|
|
|
#define DRAWPOLY_MATH_BULLSHIT(XXX) \
|
|
|
|
do \
|
|
|
|
{ \
|
2016-06-21 00:34:18 +00:00
|
|
|
float const f = -(px[i] * (ngx.u - ngx.d * XXX) + py[i] * (ngy.u - ngy.d * XXX) + (ngo.u - ngo.d * XXX)) / \
|
|
|
|
((px[j] - px[i]) * (ngx.u - ngx.d * XXX) + (py[j] - py[i]) * (ngy.u - ngy.d * XXX)); \
|
2015-03-24 00:40:33 +00:00
|
|
|
uu[nn] = (px[j] - px[i]) * f + px[i]; \
|
|
|
|
vv[nn] = (py[j] - py[i]) * f + py[i]; \
|
2016-06-21 00:34:18 +00:00
|
|
|
++nn; \
|
2015-03-24 00:40:33 +00:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
if (duj <= dui)
|
|
|
|
{
|
|
|
|
if ((du1 < duj) != (du1 < dui)) DRAWPOLY_MATH_BULLSHIT(du1);
|
|
|
|
if ((du0 < duj) != (du0 < dui)) DRAWPOLY_MATH_BULLSHIT(du0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((du0 < duj) != (du0 < dui)) DRAWPOLY_MATH_BULLSHIT(du0);
|
|
|
|
if ((du1 < duj) != (du1 < dui)) DRAWPOLY_MATH_BULLSHIT(du1);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
#undef DRAWPOLY_MATH_BULLSHIT
|
|
|
|
|
|
|
|
i = j;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
while (i);
|
|
|
|
|
|
|
|
if (nn < 3) continue;
|
|
|
|
|
2018-02-16 06:38:48 +00:00
|
|
|
vec2f_t const invtsiz2 = { 1.f / tsiz2.x, 1.f / tsiz2.y };
|
2019-09-16 17:35:04 +00:00
|
|
|
auto data = GLInterface.AllocVertices(nn);
|
|
|
|
auto vt = data.second;
|
|
|
|
for (i = 0; i<nn; ++i, vt++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2f_t const o = { uu[i], vv[i] };
|
2016-06-21 00:34:18 +00:00
|
|
|
vec3f_t const p = { o.x * ngx.d + o.y * ngy.d + ngo.d,
|
|
|
|
o.x * ngx.u + o.y * ngy.u + ngo.u,
|
|
|
|
o.x * ngx.v + o.y * ngy.v + ngo.v };
|
|
|
|
float const r = 1.f/p.d;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-09-16 16:12:16 +00:00
|
|
|
//update texcoords
|
2019-09-16 17:35:04 +00:00
|
|
|
vt->SetTexCoord(
|
2019-09-16 16:12:16 +00:00
|
|
|
(p.u * r - du0 + uoffs) * invtsiz2.x,
|
|
|
|
p.v * r * invtsiz2.y);
|
2019-09-13 20:27:20 +00:00
|
|
|
|
2019-09-16 16:12:16 +00:00
|
|
|
//update verts
|
2019-09-16 17:35:04 +00:00
|
|
|
vt->SetVertex(
|
2019-09-16 16:12:16 +00:00
|
|
|
(o.x - ghalfx) * r * grhalfxdown10x,
|
|
|
|
(ghoriz - o.y) * r * grhalfxdown10,
|
|
|
|
r * (1.f / 1024.f));
|
2018-02-16 06:38:48 +00:00
|
|
|
|
|
|
|
}
|
2019-09-16 17:35:04 +00:00
|
|
|
GLInterface.Draw(DT_TRIANGLE_FAN, data.first, nn);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
vec2f_t const scale = { 1.f / tsiz2.x * hacksc.x, 1.f / tsiz2.y * hacksc.y };
|
2019-09-16 17:35:04 +00:00
|
|
|
auto data = GLInterface.AllocVertices(npoints);
|
|
|
|
auto vt = data.second;
|
|
|
|
for (bssize_t i = 0; i < npoints; ++i, vt++)
|
2007-01-15 12:17:01 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
float const r = 1.f / dd[i];
|
|
|
|
|
2019-09-16 16:12:16 +00:00
|
|
|
//update texcoords
|
2019-09-16 17:35:04 +00:00
|
|
|
vt->SetTexCoord(
|
2019-09-16 16:12:16 +00:00
|
|
|
uu[i] * r * scale.x,
|
|
|
|
vv[i] * r * scale.y);
|
2018-02-16 06:38:48 +00:00
|
|
|
|
2019-09-16 16:12:16 +00:00
|
|
|
//update verts
|
2019-09-16 17:35:04 +00:00
|
|
|
vt->SetVertex(
|
2019-09-16 16:12:16 +00:00
|
|
|
(px[i] - ghalfx) * r * grhalfxdown10x,
|
|
|
|
(ghoriz - py[i]) * r * grhalfxdown10,
|
|
|
|
r * (1.f / 1024.f));
|
2019-09-13 20:27:20 +00:00
|
|
|
|
|
|
|
}
|
2019-09-16 17:35:04 +00:00
|
|
|
GLInterface.Draw(DT_TRIANGLE_FAN, data.first, npoints);
|
2019-09-16 16:12:16 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2016-01-08 01:33:20 +00:00
|
|
|
#ifdef USE_GLEXT
|
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_useDetailMapping(false);
|
|
|
|
polymost_useGlowMapping(false);
|
2019-03-19 17:08:43 +00:00
|
|
|
polymost_npotEmulation(false, 1.f, 0.f);
|
2016-01-08 01:33:20 +00:00
|
|
|
#endif
|
2018-10-07 05:23:25 +00:00
|
|
|
if (pth->hicr)
|
2018-03-21 20:41:32 +00:00
|
|
|
{
|
|
|
|
glMatrixMode(GL_TEXTURE);
|
|
|
|
glLoadIdentity();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2016-10-09 07:55:23 +00:00
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() != REND_POLYMOST)
|
2016-06-21 00:34:18 +00:00
|
|
|
return;
|
2011-09-04 19:44:07 +00:00
|
|
|
|
2018-10-07 05:23:25 +00:00
|
|
|
if (!(pth->flags & PTH_INDEXED))
|
2018-03-21 20:41:26 +00:00
|
|
|
{
|
|
|
|
// restore palette usage if we were just rendering a non-indexed color texture
|
|
|
|
polymost_usePaletteIndexing(true);
|
|
|
|
}
|
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
int const clamp_mode = glinfo.clamptoedge ? GL_CLAMP_TO_EDGE : GL_CLAMP;
|
2011-09-04 19:44:07 +00:00
|
|
|
|
2016-06-21 00:34:18 +00:00
|
|
|
if (drawpoly_srepeat)
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp_mode);
|
2016-06-21 00:34:18 +00:00
|
|
|
|
|
|
|
if (drawpoly_trepeat)
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp_mode);
|
2011-09-04 19:44:07 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (fullbright_pass == 1)
|
|
|
|
{
|
|
|
|
int32_t const shade = globalshade;
|
2011-09-04 19:44:07 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
globalshade = -128;
|
|
|
|
fullbright_pass = 2;
|
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_setFogEnabled(false);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glDepthFunc(GL_EQUAL);
|
2015-11-25 12:07:44 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
polymost_drawpoly(dpxy, n, method_);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glDepthFunc(GL_LEQUAL);
|
2015-11-25 12:07:44 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!nofog)
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_setFogEnabled(true);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
globalshade = shade;
|
|
|
|
fullbright_pass = 0;
|
|
|
|
}
|
2019-03-19 17:08:51 +00:00
|
|
|
|
|
|
|
if (skyzbufferhack && skyzbufferhack_pass == 0)
|
|
|
|
{
|
|
|
|
vec3d_t const bxtex = xtex, bytex = ytex, botex = otex;
|
|
|
|
xtex = xtex2, ytex = ytex2, otex = otex2;
|
|
|
|
skyzbufferhack_pass++;
|
|
|
|
polymost_drawpoly(dpxy, n, DAMETH_MASK);
|
|
|
|
xtex = bxtex, ytex = bytex, otex = botex;
|
|
|
|
skyzbufferhack_pass--;
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
static inline void vsp_finalize_init(int32_t const vcnt)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<vcnt; ++i)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
|
|
|
vsp[i].cy[1] = vsp[i+1].cy[0]; vsp[i].ctag = i;
|
|
|
|
vsp[i].fy[1] = vsp[i+1].fy[0]; vsp[i].ftag = i;
|
|
|
|
vsp[i].n = i+1; vsp[i].p = i-1;
|
|
|
|
// vsp[i].tag = -1;
|
|
|
|
}
|
|
|
|
vsp[vcnt-1].n = 0; vsp[0].p = vcnt-1;
|
|
|
|
|
|
|
|
//VSPMAX-1 is dummy empty node
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=vcnt; i<VSPMAX; i++) { vsp[i].n = i+1; vsp[i].p = i-1; }
|
2015-03-24 00:40:33 +00:00
|
|
|
vsp[VSPMAX-1].n = vcnt; vsp[vcnt].p = VSPMAX-1;
|
|
|
|
}
|
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
static inline void yax_vsp_finalize_init(int32_t const yaxbunch, int32_t const vcnt)
|
|
|
|
{
|
|
|
|
for (bssize_t i=0; i<vcnt; ++i)
|
|
|
|
{
|
|
|
|
yax_vsp[yaxbunch][i].cy[1] = yax_vsp[yaxbunch][i+1].cy[0]; yax_vsp[yaxbunch][i].ctag = i;
|
|
|
|
yax_vsp[yaxbunch][i].n = i+1; yax_vsp[yaxbunch][i].p = i-1;
|
|
|
|
// vsp[i].tag = -1;
|
|
|
|
}
|
|
|
|
yax_vsp[yaxbunch][vcnt-1].n = 0; yax_vsp[yaxbunch][0].p = vcnt-1;
|
|
|
|
|
|
|
|
//VSPMAX-1 is dummy empty node
|
|
|
|
for (bssize_t i=vcnt; i<VSPMAX; i++) { yax_vsp[yaxbunch][i].n = i+1; yax_vsp[yaxbunch][i].p = i-1; }
|
|
|
|
yax_vsp[yaxbunch][VSPMAX-1].n = vcnt; yax_vsp[yaxbunch][vcnt].p = VSPMAX-1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
#define COMBINE_STRIPS
|
|
|
|
|
|
|
|
#ifdef COMBINE_STRIPS
|
|
|
|
static inline void vsdel(int32_t const i)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
//Delete i
|
2015-07-08 03:34:20 +00:00
|
|
|
int const pi = vsp[i].p;
|
|
|
|
int const ni = vsp[i].n;
|
|
|
|
|
|
|
|
vsp[ni].p = pi;
|
|
|
|
vsp[pi].n = ni;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Add i to empty list
|
|
|
|
vsp[i].n = vsp[VSPMAX-1].n;
|
|
|
|
vsp[i].p = VSPMAX-1;
|
|
|
|
vsp[vsp[VSPMAX-1].n].p = i;
|
|
|
|
vsp[VSPMAX-1].n = i;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
2019-03-19 17:07:53 +00:00
|
|
|
# ifdef YAX_ENABLE
|
|
|
|
static inline void yax_vsdel(int32_t const yaxbunch, int32_t const i)
|
|
|
|
{
|
|
|
|
//Delete i
|
|
|
|
int const pi = yax_vsp[yaxbunch][i].p;
|
|
|
|
int const ni = yax_vsp[yaxbunch][i].n;
|
|
|
|
|
|
|
|
yax_vsp[yaxbunch][ni].p = pi;
|
|
|
|
yax_vsp[yaxbunch][pi].n = ni;
|
|
|
|
|
|
|
|
//Add i to empty list
|
|
|
|
yax_vsp[yaxbunch][i].n = yax_vsp[yaxbunch][VSPMAX - 1].n;
|
|
|
|
yax_vsp[yaxbunch][i].p = VSPMAX - 1;
|
|
|
|
yax_vsp[yaxbunch][yax_vsp[yaxbunch][VSPMAX - 1].n].p = i;
|
|
|
|
yax_vsp[yaxbunch][VSPMAX - 1].n = i;
|
|
|
|
}
|
|
|
|
# endif
|
2015-07-08 03:34:20 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
static inline int32_t vsinsaft(int32_t const i)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
//i = next element from empty list
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t const r = vsp[VSPMAX-1].n;
|
2006-04-24 19:04:22 +00:00
|
|
|
vsp[vsp[r].n].p = VSPMAX-1;
|
|
|
|
vsp[VSPMAX-1].n = vsp[r].n;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
vsp[r] = vsp[i]; //copy i to r
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//insert r after i
|
|
|
|
vsp[r].p = i; vsp[r].n = vsp[i].n;
|
|
|
|
vsp[vsp[i].n].p = r; vsp[i].n = r;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
return r;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
|
|
|
|
|
|
|
|
static inline int32_t yax_vsinsaft(int32_t const yaxbunch, int32_t const i)
|
|
|
|
{
|
|
|
|
//i = next element from empty list
|
|
|
|
int32_t const r = yax_vsp[yaxbunch][VSPMAX - 1].n;
|
|
|
|
yax_vsp[yaxbunch][yax_vsp[yaxbunch][r].n].p = VSPMAX - 1;
|
|
|
|
yax_vsp[yaxbunch][VSPMAX - 1].n = yax_vsp[yaxbunch][r].n;
|
|
|
|
|
|
|
|
yax_vsp[yaxbunch][r] = yax_vsp[yaxbunch][i]; //copy i to r
|
|
|
|
|
|
|
|
//insert r after i
|
|
|
|
yax_vsp[yaxbunch][r].p = i; yax_vsp[yaxbunch][r].n = yax_vsp[yaxbunch][i].n;
|
|
|
|
yax_vsp[yaxbunch][yax_vsp[yaxbunch][i].n].p = r; yax_vsp[yaxbunch][i].n = r;
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-12-04 11:52:54 +00:00
|
|
|
static int32_t domostpolymethod = DAMETH_NOMASK;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
#define DOMOST_OFFSET .01f
|
|
|
|
|
2019-03-04 23:49:11 +00:00
|
|
|
static void polymost_clipmost(vec2f_t *dpxy, int &n, float x0, float x1, float y0top, float y0bot, float y1top, float y1bot)
|
|
|
|
{
|
|
|
|
if (y0bot < y0top || y1bot < y1top)
|
|
|
|
return;
|
|
|
|
|
|
|
|
//Clip to (x0,y0top)-(x1,y1top)
|
|
|
|
|
|
|
|
vec2f_t dp2[8];
|
|
|
|
|
|
|
|
float t0, t1;
|
|
|
|
int n2 = 0;
|
|
|
|
t1 = -((dpxy[0].x - x0) * (y1top - y0top) - (dpxy[0].y - y0top) * (x1 - x0));
|
|
|
|
|
|
|
|
for (bssize_t i=0; i<n; i++)
|
|
|
|
{
|
|
|
|
int j = i + 1;
|
|
|
|
|
|
|
|
if (j >= n)
|
|
|
|
j = 0;
|
|
|
|
|
|
|
|
t0 = t1;
|
|
|
|
t1 = -((dpxy[j].x - x0) * (y1top - y0top) - (dpxy[j].y - y0top) * (x1 - x0));
|
|
|
|
|
|
|
|
if (t0 >= 0)
|
|
|
|
dp2[n2++] = dpxy[i];
|
|
|
|
|
|
|
|
if ((t0 >= 0) != (t1 >= 0) && (t0 <= 0) != (t1 <= 0))
|
|
|
|
{
|
|
|
|
float const r = t0 / (t0 - t1);
|
|
|
|
dp2[n2].x = (dpxy[j].x - dpxy[i].x) * r + dpxy[i].x;
|
|
|
|
dp2[n2].y = (dpxy[j].y - dpxy[i].y) * r + dpxy[i].y;
|
|
|
|
n2++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n2 < 3)
|
|
|
|
{
|
|
|
|
n = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Clip to (x1,y1bot)-(x0,y0bot)
|
|
|
|
t1 = -((dp2[0].x - x1) * (y0bot - y1bot) - (dp2[0].y - y1bot) * (x0 - x1));
|
|
|
|
n = 0;
|
|
|
|
|
|
|
|
for (bssize_t i = 0, j = 1; i < n2; j = ++i + 1)
|
|
|
|
{
|
|
|
|
if (j >= n2)
|
|
|
|
j = 0;
|
|
|
|
|
|
|
|
t0 = t1;
|
|
|
|
t1 = -((dp2[j].x - x1) * (y0bot - y1bot) - (dp2[j].y - y1bot) * (x0 - x1));
|
|
|
|
|
|
|
|
if (t0 >= 0)
|
|
|
|
dpxy[n++] = dp2[i];
|
|
|
|
|
|
|
|
if ((t0 >= 0) != (t1 >= 0) && (t0 <= 0) != (t1 <= 0))
|
|
|
|
{
|
|
|
|
float const r = t0 / (t0 - t1);
|
|
|
|
dpxy[n].x = (dp2[j].x - dp2[i].x) * r + dp2[i].x;
|
|
|
|
dpxy[n].y = (dp2[j].y - dp2[i].y) * r + dp2[i].y;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n < 3)
|
|
|
|
{
|
|
|
|
n = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void polymost_domost(float x0, float y0, float x1, float y1, float y0top = 0.f, float y0bot = -1.f, float y1top = 0.f, float y1bot = -1.f)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
int const dir = (x0 < x1);
|
2013-03-04 09:10:54 +00:00
|
|
|
|
2019-03-04 23:49:11 +00:00
|
|
|
y0top -= DOMOST_OFFSET;
|
|
|
|
y1top -= DOMOST_OFFSET;
|
|
|
|
y0bot += DOMOST_OFFSET;
|
|
|
|
y1bot += DOMOST_OFFSET;
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (dir) //clip dmost (floor)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
y0 -= DOMOST_OFFSET;
|
|
|
|
y1 -= DOMOST_OFFSET;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
else //clip umost (ceiling)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
if (x0 == x1) return;
|
2014-09-30 04:06:05 +00:00
|
|
|
swapfloat(&x0, &x1);
|
|
|
|
swapfloat(&y0, &y1);
|
2019-03-04 23:49:11 +00:00
|
|
|
swapfloat(&y0top, &y1top);
|
|
|
|
swapfloat(&y0bot, &y1bot);
|
2015-03-24 00:40:48 +00:00
|
|
|
y0 += DOMOST_OFFSET;
|
|
|
|
y1 += DOMOST_OFFSET; //necessary?
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2019-03-19 17:08:23 +00:00
|
|
|
x0 -= DOMOST_OFFSET;
|
|
|
|
x1 += DOMOST_OFFSET;
|
|
|
|
|
2019-03-02 23:22:12 +00:00
|
|
|
// Test if span is outside screen bounds
|
2019-03-19 17:08:39 +00:00
|
|
|
if (x1 < xbl || x0 > xbr)
|
2019-03-02 23:22:12 +00:00
|
|
|
{
|
|
|
|
domost_rejectcount++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-04 23:49:03 +00:00
|
|
|
vec2f_t dm0 = { x0, y0 };
|
|
|
|
vec2f_t dm1 = { x1, y1 };
|
2015-03-24 00:40:48 +00:00
|
|
|
|
|
|
|
float const slop = (dm1.y - dm0.y) / (dm1.x - dm0.x);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-03-04 23:49:03 +00:00
|
|
|
if (dm0.x < xbl)
|
|
|
|
{
|
|
|
|
dm0.y += slop*(xbl-dm0.x);
|
|
|
|
dm0.x = xbl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dm1.x > xbr)
|
|
|
|
{
|
|
|
|
dm1.y += slop*(xbr-dm1.x);
|
|
|
|
dm1.x = xbr;
|
|
|
|
}
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
drawpoly_alpha = 0.f;
|
2016-10-09 07:55:23 +00:00
|
|
|
drawpoly_blend = 0;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vec2f_t n0, n1;
|
2015-07-08 03:34:20 +00:00
|
|
|
float spx[4];
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t spt[4];
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t newi, i=vsp[0].n; i; i=newi)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2014-10-25 03:34:25 +00:00
|
|
|
newi = vsp[i].n; n0.x = vsp[i].x; n1.x = vsp[newi].x;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if ((dm0.x >= n1.x) || (n0.x >= dm1.x) || (vsp[i].ctag <= 0)) continue;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float const dx = n1.x-n0.x;
|
|
|
|
float const cy[2] = { vsp[i].cy[0], vsp[i].fy[0] },
|
|
|
|
cv[2] = { vsp[i].cy[1]-cy[0], vsp[i].fy[1]-cy[1] };
|
|
|
|
|
|
|
|
int scnt = 0;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
//Test if left edge requires split (dm0.x,dm0.y) (nx0,cy(0)),<dx,cv(0)>
|
|
|
|
if ((dm0.x > n0.x) && (dm0.x < n1.x))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
float const t = (dm0.x-n0.x)*cv[dir] - (dm0.y-cy[dir])*dx;
|
2014-09-30 04:14:21 +00:00
|
|
|
if (((!dir) && (t < 0.f)) || ((dir) && (t > 0.f)))
|
2015-07-08 03:34:20 +00:00
|
|
|
{ spx[scnt] = dm0.x; spt[scnt] = -1; scnt++; }
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2014-10-25 03:34:25 +00:00
|
|
|
//Test for intersection on umost (0) and dmost (1)
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2016-06-05 04:46:28 +00:00
|
|
|
float const d[2] = { ((dm0.y - dm1.y) * dx) - ((dm0.x - dm1.x) * cv[0]),
|
2015-03-24 00:40:48 +00:00
|
|
|
((dm0.y - dm1.y) * dx) - ((dm0.x - dm1.x) * cv[1]) };
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
float const n[2] = { ((dm0.y - cy[0]) * dx) - ((dm0.x - n0.x) * cv[0]),
|
|
|
|
((dm0.y - cy[1]) * dx) - ((dm0.x - n0.x) * cv[1]) };
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
float const fnx[2] = { dm0.x + ((n[0] / d[0]) * (dm1.x - dm0.x)),
|
|
|
|
dm0.x + ((n[1] / d[1]) * (dm1.x - dm0.x)) };
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if ((Bfabsf(d[0]) > Bfabsf(n[0])) && (d[0] * n[0] >= 0.f) && (fnx[0] > n0.x) && (fnx[0] < n1.x))
|
|
|
|
spx[scnt] = fnx[0], spt[scnt++] = 0;
|
|
|
|
|
|
|
|
if ((Bfabsf(d[1]) > Bfabsf(n[1])) && (d[1] * n[1] >= 0.f) && (fnx[1] > n0.x) && (fnx[1] < n1.x))
|
|
|
|
spx[scnt] = fnx[1], spt[scnt++] = 1;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Nice hack to avoid full sort later :)
|
|
|
|
if ((scnt >= 2) && (spx[scnt-1] < spx[scnt-2]))
|
|
|
|
{
|
2014-09-30 04:06:05 +00:00
|
|
|
swapfloat(&spx[scnt-1], &spx[scnt-2]);
|
|
|
|
swaplong(&spt[scnt-1], &spt[scnt-2]);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//Test if right edge requires split
|
2015-03-24 00:40:48 +00:00
|
|
|
if ((dm1.x > n0.x) && (dm1.x < n1.x))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2016-06-21 00:34:18 +00:00
|
|
|
float const t = (dm1.x-n0.x)*cv[dir] - (dm1.y-cy[dir])*dx;
|
|
|
|
if (((!dir) && (t < 0.f)) || ((dir) && (t > 0.f)))
|
2015-07-08 03:34:20 +00:00
|
|
|
{ spx[scnt] = dm1.x; spt[scnt] = -1; scnt++; }
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vsp[i].tag = vsp[newi].tag = -1;
|
2014-10-25 03:33:26 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float const rdx = 1.f/dx;
|
2014-10-25 03:33:26 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t z=0, vcnt=0; z<=scnt; z++,i=vcnt)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-01-11 04:55:07 +00:00
|
|
|
float t;
|
2014-10-25 03:33:26 +00:00
|
|
|
|
2014-10-25 03:34:25 +00:00
|
|
|
if (z == scnt)
|
|
|
|
goto skip;
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
t = (spx[z]-n0.x)*rdx;
|
2015-07-08 03:34:20 +00:00
|
|
|
vcnt = vsinsaft(i);
|
2014-10-25 03:34:25 +00:00
|
|
|
vsp[i].cy[1] = t*cv[0] + cy[0];
|
|
|
|
vsp[i].fy[1] = t*cv[1] + cy[1];
|
|
|
|
vsp[vcnt].x = spx[z];
|
|
|
|
vsp[vcnt].cy[0] = vsp[i].cy[1];
|
|
|
|
vsp[vcnt].fy[0] = vsp[i].fy[1];
|
|
|
|
vsp[vcnt].tag = spt[z];
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-01-18 20:21:17 +00:00
|
|
|
skip: ;
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t const ni = vsp[i].n; if (!ni) continue; //this 'if' fixes many bugs!
|
2015-03-24 00:40:48 +00:00
|
|
|
float const dx0 = vsp[i].x; if (dm0.x > dx0) continue;
|
|
|
|
float const dx1 = vsp[ni].x; if (dm1.x < dx1) continue;
|
|
|
|
n0.y = (dx0-dm0.x)*slop + dm0.y;
|
|
|
|
n1.y = (dx1-dm0.x)*slop + dm0.y;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
// dx0 dx1
|
|
|
|
// ~ ~
|
|
|
|
//----------------------------
|
|
|
|
// t0+=0 t1+=0
|
|
|
|
// vsp[i].cy[0] vsp[i].cy[1]
|
|
|
|
//============================
|
|
|
|
// t0+=1 t1+=3
|
|
|
|
//============================
|
|
|
|
// vsp[i].fy[0] vsp[i].fy[1]
|
|
|
|
// t0+=2 t1+=6
|
|
|
|
//
|
|
|
|
// ny0 ? ny1 ?
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int k = 4;
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if ((vsp[i].tag == 0) || (n0.y <= vsp[i].cy[0]+DOMOST_OFFSET)) k--;
|
|
|
|
if ((vsp[i].tag == 1) || (n0.y >= vsp[i].fy[0]-DOMOST_OFFSET)) k++;
|
|
|
|
if ((vsp[ni].tag == 0) || (n1.y <= vsp[i].cy[1]+DOMOST_OFFSET)) k -= 3;
|
|
|
|
if ((vsp[ni].tag == 1) || (n1.y >= vsp[i].fy[1]-DOMOST_OFFSET)) k += 3;
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (!dir)
|
|
|
|
{
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (k)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
case 4:
|
|
|
|
case 5:
|
|
|
|
case 7:
|
|
|
|
{
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (g_nodraw)
|
|
|
|
{
|
|
|
|
if (yax_drawcf != -1)
|
|
|
|
yax_holecf[yax_drawcf][yax_holencf[yax_drawcf]++] = { dx0, dx1, vsp[i].cy[0], vsp[i].cy[1], n0.y, n1.y };
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
vec2f_t dpxy[8] = {
|
|
|
|
{ dx0, vsp[i].cy[0] }, { dx1, vsp[i].cy[1] }, { dx1, n1.y }, { dx0, n0.y }
|
|
|
|
};
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
int n = 4;
|
|
|
|
polymost_clipmost(dpxy, n, x0, x1, y0top, y0bot, y1top, y1bot);
|
|
|
|
polymost_drawpoly(dpxy, n, domostpolymethod);
|
|
|
|
}
|
2019-03-04 23:49:11 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
vsp[i].cy[0] = n0.y;
|
|
|
|
vsp[i].cy[1] = n1.y;
|
|
|
|
vsp[i].ctag = gtag;
|
|
|
|
}
|
2014-09-30 04:14:21 +00:00
|
|
|
break;
|
2015-03-24 00:40:33 +00:00
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
{
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (g_nodraw)
|
|
|
|
{
|
|
|
|
if (yax_drawcf != -1)
|
|
|
|
yax_holecf[yax_drawcf][yax_holencf[yax_drawcf]++] = { dx0, dx1, vsp[i].cy[0], vsp[i].cy[1], n0.y, vsp[i].cy[1] };
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
vec2f_t dpxy[8] = { { dx0, vsp[i].cy[0] }, { dx1, vsp[i].cy[1] }, { dx0, n0.y } };
|
2019-03-04 23:49:11 +00:00
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
int n = 3;
|
|
|
|
polymost_clipmost(dpxy, n, x0, x1, y0top, y0bot, y1top, y1bot);
|
|
|
|
polymost_drawpoly(dpxy, n, domostpolymethod);
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vsp[i].cy[0] = n0.y;
|
|
|
|
vsp[i].ctag = gtag;
|
|
|
|
}
|
2014-09-30 04:14:21 +00:00
|
|
|
break;
|
2015-03-24 00:40:33 +00:00
|
|
|
case 3:
|
|
|
|
case 6:
|
|
|
|
{
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (g_nodraw)
|
|
|
|
{
|
|
|
|
if (yax_drawcf != -1)
|
|
|
|
yax_holecf[yax_drawcf][yax_holencf[yax_drawcf]++] = { dx0, dx1, vsp[i].cy[0], vsp[i].cy[1], vsp[i].cy[0], n1.y };
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
vec2f_t dpxy[8] = { { dx0, vsp[i].cy[0] }, { dx1, vsp[i].cy[1] }, { dx1, n1.y } };
|
2019-03-04 23:49:11 +00:00
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
int n = 3;
|
|
|
|
polymost_clipmost(dpxy, n, x0, x1, y0top, y0bot, y1top, y1bot);
|
|
|
|
polymost_drawpoly(dpxy, n, domostpolymethod);
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vsp[i].cy[1] = n1.y;
|
|
|
|
vsp[i].ctag = gtag;
|
|
|
|
}
|
2014-09-30 04:14:21 +00:00
|
|
|
break;
|
2015-03-24 00:40:33 +00:00
|
|
|
case 8:
|
|
|
|
{
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (g_nodraw)
|
|
|
|
{
|
|
|
|
if (yax_drawcf != -1)
|
|
|
|
yax_holecf[yax_drawcf][yax_holencf[yax_drawcf]++] = { dx0, dx1, vsp[i].cy[0], vsp[i].cy[1], vsp[i].fy[0], vsp[i].fy[1] };
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
vec2f_t dpxy[8] = {
|
|
|
|
{ dx0, vsp[i].cy[0] }, { dx1, vsp[i].cy[1] }, { dx1, vsp[i].fy[1] }, { dx0, vsp[i].fy[0] }
|
|
|
|
};
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
int n = 4;
|
|
|
|
polymost_clipmost(dpxy, n, x0, x1, y0top, y0bot, y1top, y1bot);
|
|
|
|
polymost_drawpoly(dpxy, n, domostpolymethod);
|
|
|
|
}
|
2019-03-04 23:49:11 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
vsp[i].ctag = vsp[i].ftag = -1;
|
|
|
|
}
|
|
|
|
default: break;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-11-13 23:12:47 +00:00
|
|
|
switch (k)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2014-10-25 03:34:25 +00:00
|
|
|
case 4:
|
|
|
|
case 3:
|
|
|
|
case 1:
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (g_nodraw)
|
|
|
|
{
|
|
|
|
if (yax_drawcf != -1)
|
|
|
|
yax_holecf[yax_drawcf][yax_holencf[yax_drawcf]++] = { dx0, dx1, n0.y, n1.y, vsp[i].fy[0], vsp[i].fy[1] };
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
vec2f_t dpxy[8] = {
|
|
|
|
{ dx0, n0.y }, { dx1, n1.y }, { dx1, vsp[i].fy[1] }, { dx0, vsp[i].fy[0] }
|
|
|
|
};
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
int n = 4;
|
|
|
|
polymost_clipmost(dpxy, n, x0, x1, y0top, y0bot, y1top, y1bot);
|
|
|
|
polymost_drawpoly(dpxy, n, domostpolymethod);
|
|
|
|
}
|
2019-03-04 23:49:11 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
vsp[i].fy[0] = n0.y;
|
|
|
|
vsp[i].fy[1] = n1.y;
|
|
|
|
vsp[i].ftag = gtag;
|
|
|
|
}
|
2014-10-25 03:34:25 +00:00
|
|
|
break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 7:
|
|
|
|
case 6:
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (g_nodraw)
|
|
|
|
{
|
|
|
|
if (yax_drawcf != -1)
|
|
|
|
yax_holecf[yax_drawcf][yax_holencf[yax_drawcf]++] = { dx0, dx1, n0.y, vsp[i].fy[1], vsp[i].fy[0], vsp[i].fy[1] };
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
vec2f_t dpxy[8] = { { dx0, n0.y }, { dx1, vsp[i].fy[1] }, { dx0, vsp[i].fy[0] } };
|
2019-03-04 23:49:11 +00:00
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
int n = 3;
|
|
|
|
polymost_clipmost(dpxy, n, x0, x1, y0top, y0bot, y1top, y1bot);
|
|
|
|
polymost_drawpoly(dpxy, n, domostpolymethod);
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vsp[i].fy[0] = n0.y;
|
|
|
|
vsp[i].ftag = gtag;
|
|
|
|
}
|
2014-09-30 04:14:21 +00:00
|
|
|
break;
|
2006-11-13 23:12:47 +00:00
|
|
|
case 5:
|
|
|
|
case 2:
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (g_nodraw)
|
|
|
|
{
|
|
|
|
if (yax_drawcf != -1)
|
|
|
|
yax_holecf[yax_drawcf][yax_holencf[yax_drawcf]++] = { dx0, dx1, vsp[i].fy[0], n1.y, vsp[i].fy[0], vsp[i].fy[1] };
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
vec2f_t dpxy[8] = { { dx0, vsp[i].fy[0] }, { dx1, n1.y }, { dx1, vsp[i].fy[1] } };
|
2019-03-04 23:49:11 +00:00
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
int n = 3;
|
|
|
|
polymost_clipmost(dpxy, n, x0, x1, y0top, y0bot, y1top, y1bot);
|
|
|
|
polymost_drawpoly(dpxy, n, domostpolymethod);
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vsp[i].fy[1] = n1.y;
|
|
|
|
vsp[i].ftag = gtag;
|
|
|
|
}
|
2014-09-30 04:14:21 +00:00
|
|
|
break;
|
2006-04-24 19:04:22 +00:00
|
|
|
case 0:
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (g_nodraw)
|
|
|
|
{
|
|
|
|
if (yax_drawcf != -1)
|
|
|
|
yax_holecf[yax_drawcf][yax_holencf[yax_drawcf]++] = { dx0, dx1, vsp[i].cy[0], vsp[i].cy[1], vsp[i].fy[0], vsp[i].fy[1] };
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
vec2f_t dpxy[8] = { { dx0, vsp[i].cy[0] }, { dx1, vsp[i].cy[1] }, { dx1, vsp[i].fy[1] }, { dx0, vsp[i].fy[0] } };
|
|
|
|
|
|
|
|
int n = 4;
|
|
|
|
polymost_clipmost(dpxy, n, x0, x1, y0top, y0bot, y1top, y1bot);
|
|
|
|
polymost_drawpoly(dpxy, n, domostpolymethod);
|
|
|
|
}
|
2019-03-04 23:49:11 +00:00
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
vsp[i].ctag = vsp[i].ftag = -1;
|
2015-03-24 00:40:33 +00:00
|
|
|
}
|
2006-11-13 23:12:47 +00:00
|
|
|
default:
|
2014-09-30 04:14:21 +00:00
|
|
|
break;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gtag++;
|
|
|
|
|
|
|
|
//Combine neighboring vertical strips with matching collinear top&bottom edges
|
|
|
|
//This prevents x-splits from propagating through the entire scan
|
2015-07-08 03:34:20 +00:00
|
|
|
#ifdef COMBINE_STRIPS
|
2015-03-24 00:40:33 +00:00
|
|
|
int i = vsp[0].n;
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2019-03-04 23:48:55 +00:00
|
|
|
do
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2019-03-19 17:07:37 +00:00
|
|
|
if ((vsp[i].cy[0] >= vsp[i].fy[0]) && (vsp[i].cy[1] >= vsp[i].fy[1]))
|
2011-09-04 19:44:07 +00:00
|
|
|
vsp[i].ctag = vsp[i].ftag = -1;
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int const ni = vsp[i].n;
|
|
|
|
|
2019-03-04 23:49:07 +00:00
|
|
|
if ((vsp[i].ctag == vsp[ni].ctag) && (vsp[i].ftag == vsp[ni].ftag))
|
2011-09-04 19:44:07 +00:00
|
|
|
{
|
|
|
|
vsp[i].cy[1] = vsp[ni].cy[1];
|
|
|
|
vsp[i].fy[1] = vsp[ni].fy[1];
|
2015-07-08 03:34:20 +00:00
|
|
|
vsdel(ni);
|
2011-09-04 19:44:07 +00:00
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
else i = ni;
|
|
|
|
}
|
2019-03-04 23:48:55 +00:00
|
|
|
while (i);
|
2015-07-08 03:34:20 +00:00
|
|
|
#endif
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
static void yax_polymost_domost(const int yaxbunch, float x0, float y0, float x1, float y1)
|
|
|
|
{
|
|
|
|
int const dir = (x0 < x1);
|
|
|
|
|
|
|
|
if (dir) //clip dmost (floor)
|
|
|
|
{
|
|
|
|
y0 -= DOMOST_OFFSET;
|
|
|
|
y1 -= DOMOST_OFFSET;
|
|
|
|
}
|
|
|
|
else //clip umost (ceiling)
|
|
|
|
{
|
|
|
|
if (x0 == x1) return;
|
|
|
|
swapfloat(&x0, &x1);
|
|
|
|
swapfloat(&y0, &y1);
|
|
|
|
y0 += DOMOST_OFFSET;
|
|
|
|
y1 += DOMOST_OFFSET; //necessary?
|
|
|
|
}
|
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
x0 -= DOMOST_OFFSET;
|
|
|
|
x1 += DOMOST_OFFSET;
|
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
// Test if span is outside screen bounds
|
2019-03-19 17:08:39 +00:00
|
|
|
if (x1 < xbl || x0 > xbr)
|
2019-03-19 17:07:53 +00:00
|
|
|
{
|
|
|
|
domost_rejectcount++;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec2f_t dm0 = { x0, y0 };
|
|
|
|
vec2f_t dm1 = { x1, y1 };
|
|
|
|
|
|
|
|
float const slop = (dm1.y - dm0.y) / (dm1.x - dm0.x);
|
|
|
|
|
|
|
|
if (dm0.x < xbl)
|
|
|
|
{
|
|
|
|
dm0.y += slop*(xbl-dm0.x);
|
|
|
|
dm0.x = xbl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dm1.x > xbr)
|
|
|
|
{
|
|
|
|
dm1.y += slop*(xbr-dm1.x);
|
|
|
|
dm1.x = xbr;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec2f_t n0, n1;
|
|
|
|
float spx[4];
|
|
|
|
int32_t spt[4];
|
|
|
|
|
|
|
|
for (bssize_t newi, i=yax_vsp[yaxbunch][0].n; i; i=newi)
|
|
|
|
{
|
|
|
|
newi = yax_vsp[yaxbunch][i].n; n0.x = yax_vsp[yaxbunch][i].x; n1.x = yax_vsp[yaxbunch][newi].x;
|
|
|
|
|
|
|
|
if ((dm0.x >= n1.x) || (n0.x >= dm1.x) || (yax_vsp[yaxbunch][i].ctag <= 0)) continue;
|
|
|
|
|
|
|
|
float const dx = n1.x-n0.x;
|
|
|
|
float const cy = yax_vsp[yaxbunch][i].cy[0],
|
|
|
|
cv = yax_vsp[yaxbunch][i].cy[1]-cy;
|
|
|
|
|
|
|
|
int scnt = 0;
|
|
|
|
|
|
|
|
//Test if left edge requires split (dm0.x,dm0.y) (nx0,cy(0)),<dx,cv(0)>
|
|
|
|
if ((dm0.x > n0.x) && (dm0.x < n1.x))
|
|
|
|
{
|
|
|
|
float const t = (dm0.x-n0.x)*cv - (dm0.y-cy)*dx;
|
|
|
|
if (((!dir) && (t < 0.f)) || ((dir) && (t > 0.f)))
|
|
|
|
{ spx[scnt] = dm0.x; spt[scnt] = -1; scnt++; }
|
|
|
|
}
|
|
|
|
|
|
|
|
//Test for intersection on umost (0) and dmost (1)
|
|
|
|
|
|
|
|
float const d = ((dm0.y - dm1.y) * dx) - ((dm0.x - dm1.x) * cv);
|
|
|
|
|
|
|
|
float const n = ((dm0.y - cy) * dx) - ((dm0.x - n0.x) * cv);
|
|
|
|
|
|
|
|
float const fnx = dm0.x + ((n / d) * (dm1.x - dm0.x));
|
|
|
|
|
|
|
|
if ((Bfabsf(d) > Bfabsf(n)) && (d * n >= 0.f) && (fnx > n0.x) && (fnx < n1.x))
|
|
|
|
spx[scnt] = fnx, spt[scnt++] = 0;
|
|
|
|
|
|
|
|
//Nice hack to avoid full sort later :)
|
|
|
|
if ((scnt >= 2) && (spx[scnt-1] < spx[scnt-2]))
|
|
|
|
{
|
|
|
|
swapfloat(&spx[scnt-1], &spx[scnt-2]);
|
|
|
|
swaplong(&spt[scnt-1], &spt[scnt-2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Test if right edge requires split
|
|
|
|
if ((dm1.x > n0.x) && (dm1.x < n1.x))
|
|
|
|
{
|
|
|
|
float const t = (dm1.x-n0.x)*cv - (dm1.y-cy)*dx;
|
|
|
|
if (((!dir) && (t < 0.f)) || ((dir) && (t > 0.f)))
|
|
|
|
{ spx[scnt] = dm1.x; spt[scnt] = -1; scnt++; }
|
|
|
|
}
|
|
|
|
|
|
|
|
yax_vsp[yaxbunch][i].tag = yax_vsp[yaxbunch][newi].tag = -1;
|
|
|
|
|
|
|
|
float const rdx = 1.f/dx;
|
|
|
|
|
|
|
|
for (bssize_t z=0, vcnt=0; z<=scnt; z++,i=vcnt)
|
|
|
|
{
|
|
|
|
float t;
|
|
|
|
|
|
|
|
if (z == scnt)
|
|
|
|
goto skip;
|
|
|
|
|
|
|
|
t = (spx[z]-n0.x)*rdx;
|
|
|
|
vcnt = yax_vsinsaft(yaxbunch, i);
|
|
|
|
yax_vsp[yaxbunch][i].cy[1] = t*cv + cy;
|
|
|
|
yax_vsp[yaxbunch][vcnt].x = spx[z];
|
|
|
|
yax_vsp[yaxbunch][vcnt].cy[0] = yax_vsp[yaxbunch][i].cy[1];
|
|
|
|
yax_vsp[yaxbunch][vcnt].tag = spt[z];
|
|
|
|
|
|
|
|
skip: ;
|
|
|
|
int32_t const ni = yax_vsp[yaxbunch][i].n; if (!ni) continue; //this 'if' fixes many bugs!
|
|
|
|
float const dx0 = yax_vsp[yaxbunch][i].x; if (dm0.x > dx0) continue;
|
|
|
|
float const dx1 = yax_vsp[yaxbunch][ni].x; if (dm1.x < dx1) continue;
|
|
|
|
n0.y = (dx0-dm0.x)*slop + dm0.y;
|
|
|
|
n1.y = (dx1-dm0.x)*slop + dm0.y;
|
|
|
|
|
|
|
|
// dx0 dx1
|
|
|
|
// ~ ~
|
|
|
|
//----------------------------
|
|
|
|
// t0+=0 t1+=0
|
|
|
|
// vsp[i].cy[0] vsp[i].cy[1]
|
|
|
|
//============================
|
|
|
|
// t0+=1 t1+=3
|
|
|
|
//============================
|
|
|
|
// vsp[i].fy[0] vsp[i].fy[1]
|
|
|
|
// t0+=2 t1+=6
|
|
|
|
//
|
|
|
|
// ny0 ? ny1 ?
|
|
|
|
|
|
|
|
int k = 4;
|
|
|
|
|
|
|
|
if (!dir)
|
|
|
|
{
|
|
|
|
if ((yax_vsp[yaxbunch][i].tag == 0) || (n0.y <= yax_vsp[yaxbunch][i].cy[0]+DOMOST_OFFSET)) k--;
|
|
|
|
if ((yax_vsp[yaxbunch][ni].tag == 0) || (n1.y <= yax_vsp[yaxbunch][i].cy[1]+DOMOST_OFFSET)) k -= 3;
|
|
|
|
switch (k)
|
|
|
|
{
|
|
|
|
case 4:
|
|
|
|
{
|
|
|
|
yax_vsp[yaxbunch][i].cy[0] = n0.y;
|
|
|
|
yax_vsp[yaxbunch][i].cy[1] = n1.y;
|
|
|
|
yax_vsp[yaxbunch][i].ctag = gtag;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
yax_vsp[yaxbunch][i].cy[0] = n0.y;
|
|
|
|
yax_vsp[yaxbunch][i].ctag = gtag;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
{
|
|
|
|
yax_vsp[yaxbunch][i].cy[1] = n1.y;
|
|
|
|
yax_vsp[yaxbunch][i].ctag = gtag;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((yax_vsp[yaxbunch][i].tag == 1) || (n0.y >= yax_vsp[yaxbunch][i].cy[0]-DOMOST_OFFSET)) k++;
|
|
|
|
if ((yax_vsp[yaxbunch][ni].tag == 1) || (n1.y >= yax_vsp[yaxbunch][i].cy[1]-DOMOST_OFFSET)) k += 3;
|
|
|
|
switch (k)
|
|
|
|
{
|
|
|
|
case 4:
|
|
|
|
{
|
|
|
|
yax_vsp[yaxbunch][i].cy[0] = n0.y;
|
|
|
|
yax_vsp[yaxbunch][i].cy[1] = n1.y;
|
|
|
|
yax_vsp[yaxbunch][i].ctag = gtag;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
case 6:
|
|
|
|
{
|
|
|
|
yax_vsp[yaxbunch][i].cy[0] = n0.y;
|
|
|
|
yax_vsp[yaxbunch][i].ctag = gtag;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
{
|
|
|
|
yax_vsp[yaxbunch][i].cy[1] = n1.y;
|
|
|
|
yax_vsp[yaxbunch][i].ctag = gtag;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gtag++;
|
|
|
|
|
|
|
|
//Combine neighboring vertical strips with matching collinear top&bottom edges
|
|
|
|
//This prevents x-splits from propagating through the entire scan
|
|
|
|
#ifdef COMBINE_STRIPS
|
|
|
|
int i = yax_vsp[yaxbunch][0].n;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
int const ni = yax_vsp[yaxbunch][i].n;
|
|
|
|
|
|
|
|
if ((yax_vsp[yaxbunch][i].ctag == yax_vsp[yaxbunch][ni].ctag))
|
|
|
|
{
|
|
|
|
yax_vsp[yaxbunch][i].cy[1] = yax_vsp[yaxbunch][ni].cy[1];
|
|
|
|
yax_vsdel(yaxbunch, ni);
|
|
|
|
}
|
|
|
|
else i = ni;
|
|
|
|
}
|
|
|
|
while (i);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-07-08 03:34:27 +00:00
|
|
|
#define POINT2(i) (wall[wall[i].point2])
|
|
|
|
|
2014-10-25 03:26:31 +00:00
|
|
|
void polymost_editorfunc(void)
|
|
|
|
{
|
2015-07-08 03:34:27 +00:00
|
|
|
const float ratio = (r_usenewaspect ? (fxdim / fydim) / (320.f / 240.f) : 1.f) * (1.f / get_projhack_ratio());
|
|
|
|
|
2015-05-26 00:48:04 +00:00
|
|
|
vec3f_t tvect = { (searchx - ghalfx) * ratio, (searchy - ghoriz) * ratio, ghalfx };
|
2014-10-25 03:26:31 +00:00
|
|
|
|
|
|
|
//Tilt rotation
|
2015-05-26 00:48:04 +00:00
|
|
|
vec3f_t o = { tvect.x * gctang + tvect.y * gstang, tvect.y * gctang - tvect.x * gstang, tvect.z };
|
2014-10-25 03:26:31 +00:00
|
|
|
|
|
|
|
//Up/down rotation
|
2015-05-26 00:48:04 +00:00
|
|
|
tvect.x = o.z*gchang - o.y*gshang;
|
|
|
|
tvect.y = o.x;
|
|
|
|
tvect.z = o.y*gchang + o.z*gshang;
|
2014-10-25 03:26:31 +00:00
|
|
|
|
|
|
|
//Standard Left/right rotation
|
2015-05-26 00:48:04 +00:00
|
|
|
vec3_t v = { Blrintf(tvect.x * fcosglobalang - tvect.y * fsinglobalang),
|
|
|
|
Blrintf(tvect.x * fsinglobalang + tvect.y * fcosglobalang), Blrintf(tvect.z * 16384.f) };
|
|
|
|
|
|
|
|
vec3_t vect = { globalposx, globalposy, globalposz };
|
2014-10-25 03:26:31 +00:00
|
|
|
|
2015-07-08 03:34:27 +00:00
|
|
|
hitdata_t *hit = &polymost_hitdata;
|
2014-10-25 03:26:31 +00:00
|
|
|
|
|
|
|
hitallsprites = 1;
|
2015-05-26 00:48:04 +00:00
|
|
|
|
2014-10-25 03:26:31 +00:00
|
|
|
hitscan((const vec3_t *) &vect, globalcursectnum, //Start position
|
2015-07-08 03:34:27 +00:00
|
|
|
v.x>>10, v.y>>10, v.z>>6, hit, 0xffff0030);
|
2014-10-25 03:26:31 +00:00
|
|
|
|
2015-07-08 03:34:27 +00:00
|
|
|
if (hit->sect != -1) // if hitsect is -1, hitscan overflowed somewhere
|
2014-10-25 03:26:31 +00:00
|
|
|
{
|
2015-05-26 00:48:04 +00:00
|
|
|
int32_t cz, fz;
|
2015-07-08 03:34:27 +00:00
|
|
|
getzsofslope(hit->sect, hit->pos.x, hit->pos.y, &cz, &fz);
|
2014-10-25 03:26:31 +00:00
|
|
|
hitallsprites = 0;
|
|
|
|
|
2015-07-08 03:34:27 +00:00
|
|
|
searchsector = hit->sect;
|
|
|
|
if (hit->pos.z<cz) searchstat = 1;
|
|
|
|
else if (hit->pos.z>fz) searchstat = 2;
|
|
|
|
else if (hit->wall >= 0)
|
2014-10-25 03:26:31 +00:00
|
|
|
{
|
2015-07-08 03:34:27 +00:00
|
|
|
searchbottomwall = searchwall = hit->wall; searchstat = 0;
|
|
|
|
if (wall[hit->wall].nextwall >= 0)
|
2014-10-25 03:26:31 +00:00
|
|
|
{
|
2015-07-08 03:34:27 +00:00
|
|
|
getzsofslope(wall[hit->wall].nextsector, hit->pos.x, hit->pos.y, &cz, &fz);
|
|
|
|
if (hit->pos.z > fz)
|
2014-10-25 03:26:31 +00:00
|
|
|
{
|
|
|
|
searchisbottom = 1;
|
2015-07-08 03:34:27 +00:00
|
|
|
if (wall[hit->wall].cstat&2) //'2' bottoms of walls
|
|
|
|
searchbottomwall = wall[hit->wall].nextwall;
|
2014-10-25 03:26:31 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
searchisbottom = 0;
|
2015-07-08 03:34:27 +00:00
|
|
|
if ((hit->pos.z > cz) && (wall[hit->wall].cstat&(16+32))) //masking or 1-way
|
2014-10-25 03:26:31 +00:00
|
|
|
searchstat = 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-07-08 03:34:27 +00:00
|
|
|
else if (hit->sprite >= 0) { searchwall = hit->sprite; searchstat = 3; }
|
2014-10-25 03:26:31 +00:00
|
|
|
else
|
|
|
|
{
|
2015-07-08 03:34:27 +00:00
|
|
|
getzsofslope(hit->sect, hit->pos.x, hit->pos.y, &cz, &fz);
|
|
|
|
if ((hit->pos.z<<1) < cz+fz) searchstat = 1; else searchstat = 2;
|
2014-10-25 03:26:31 +00:00
|
|
|
//if (vz < 0) searchstat = 1; else searchstat = 2; //Won't work for slopes :/
|
|
|
|
}
|
|
|
|
|
2015-07-08 03:34:27 +00:00
|
|
|
if (preview_mouseaim)
|
2014-10-25 03:26:31 +00:00
|
|
|
{
|
2017-07-08 19:42:11 +00:00
|
|
|
if (spritesortcnt == maxspritesonscreen)
|
2015-07-08 03:34:27 +00:00
|
|
|
spritesortcnt--;
|
|
|
|
|
2016-06-21 00:33:58 +00:00
|
|
|
uspritetype *tsp = &tsprite[spritesortcnt];
|
2014-10-25 03:26:31 +00:00
|
|
|
double dadist, x, y, z;
|
2015-07-08 03:34:27 +00:00
|
|
|
Bmemcpy(tsp, &hit->pos, sizeof(vec3_t));
|
2014-10-25 03:26:31 +00:00
|
|
|
x = tsp->x-globalposx; y=tsp->y-globalposy; z=(tsp->z-globalposz)/16.0;
|
|
|
|
dadist = Bsqrt(x*x + y*y + z*z);
|
2015-07-08 03:34:27 +00:00
|
|
|
tsp->sectnum = hit->sect;
|
2014-10-25 03:26:31 +00:00
|
|
|
tsp->picnum = 2523; // CROSSHAIR
|
|
|
|
tsp->cstat = 128;
|
2015-07-08 03:34:27 +00:00
|
|
|
|
|
|
|
if (hit->wall != -1)
|
|
|
|
{
|
|
|
|
tsp->cstat |= 16;
|
|
|
|
int const ang = getangle(wall[hit->wall].x - POINT2(hit->wall).x, wall[hit->wall].y - POINT2(hit->wall).y);
|
|
|
|
tsp->ang = ang + 512;
|
|
|
|
|
2017-02-05 20:58:33 +00:00
|
|
|
vec2_t const offs = { sintable[(ang + 1024) & 2047] >> 11,
|
2015-07-08 03:34:27 +00:00
|
|
|
sintable[(ang + 512) & 2047] >> 11};
|
|
|
|
|
|
|
|
tsp->x -= offs.x;
|
|
|
|
tsp->y -= offs.y;
|
|
|
|
|
|
|
|
}
|
|
|
|
else if (hit->sprite == -1 && (hit->pos.z == sector[hit->sect].floorz || hit->pos.z == sector[hit->sect].ceilingz))
|
|
|
|
{
|
|
|
|
tsp->cstat = 32;
|
|
|
|
tsp->ang = getangle(hit->pos.x - globalposx, hit->pos.y - globalposy);
|
|
|
|
}
|
|
|
|
else if (hit->sprite >= 0)
|
|
|
|
{
|
|
|
|
if (sprite[hit->sprite].cstat & 16)
|
|
|
|
{
|
|
|
|
tsp->cstat |= 16;
|
|
|
|
tsp->ang = sprite[hit->sprite].ang;
|
|
|
|
}
|
|
|
|
|
|
|
|
else tsp->ang = (globalang + 1024) & 2047;
|
|
|
|
|
|
|
|
vec2_t const offs = { sintable[(tsp->ang + 1536) & 2047] >> 11,
|
|
|
|
sintable[(tsp->ang + 1024) & 2047] >> 11 };
|
|
|
|
|
|
|
|
tsp->x -= offs.x;
|
|
|
|
tsp->y -= offs.y;
|
|
|
|
}
|
|
|
|
static int lastupdate = 0;
|
|
|
|
static int shd = 30;
|
|
|
|
static int shdinc = 1;
|
|
|
|
|
|
|
|
if (totalclock > lastupdate)
|
|
|
|
{
|
|
|
|
shd += shdinc;
|
|
|
|
if (shd >= 30 || shd <= 0)
|
|
|
|
{
|
|
|
|
shdinc = -shdinc;
|
|
|
|
shd += shdinc;
|
|
|
|
}
|
|
|
|
lastupdate = totalclock + 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
tsp->shade = 30-shd;
|
2014-10-25 03:26:31 +00:00
|
|
|
tsp->owner = MAXSPRITES-1;
|
2015-07-08 03:34:27 +00:00
|
|
|
tsp->xrepeat = tsp->yrepeat = min(max(1, (int32_t) (dadist*((double)(shd*3)/3200.0))), 255);
|
2016-06-05 04:46:37 +00:00
|
|
|
tsp->extra = 0;
|
2014-10-25 03:26:31 +00:00
|
|
|
sprite[tsp->owner].xoffset = sprite[tsp->owner].yoffset = 0;
|
|
|
|
tspriteptr[spritesortcnt++] = tsp;
|
|
|
|
}
|
|
|
|
|
2015-10-20 07:15:15 +00:00
|
|
|
if ((searchstat == 1 || searchstat == 2) && searchsector >= 0)
|
2014-10-25 03:26:31 +00:00
|
|
|
{
|
2015-10-20 07:15:15 +00:00
|
|
|
vec2_t const scrv = { (v.x >> 12), (v.y >> 12) };
|
|
|
|
vec2_t const scrv_r = { scrv.y, -scrv.x };
|
|
|
|
walltype const * const wal = &wall[sector[searchsector].wallptr];
|
|
|
|
uint64_t bestwdistsq = 0x7fffffff;
|
|
|
|
int32_t bestk = -1;
|
2014-10-25 03:26:31 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t k = 0; k < sector[searchsector].wallnum; k++)
|
2014-10-25 03:26:31 +00:00
|
|
|
{
|
2015-10-20 07:15:15 +00:00
|
|
|
vec2_t const w1 = { wal[k].x, wal[k].y };
|
|
|
|
vec2_t const w2 = { wall[wal[k].point2].x, wall[wal[k].point2].y };
|
|
|
|
vec2_t const w21 = { w1.x - w2.x, w1.y - w2.y };
|
|
|
|
vec2_t const pw1 = { w1.x - hit->pos.x, w1.y - hit->pos.y };
|
|
|
|
vec2_t const pw2 = { w2.x - hit->pos.x, w2.y - hit->pos.y };
|
|
|
|
float w1d = (float)(scrv_r.x * pw1.x + scrv_r.y * pw1.y);
|
|
|
|
float w2d = (float)-(scrv_r.x * pw2.x + scrv_r.y * pw2.y);
|
|
|
|
|
|
|
|
if ((w1d == 0 && w2d == 0) || (w1d < 0 || w2d < 0))
|
2014-10-25 03:26:31 +00:00
|
|
|
continue;
|
2015-10-20 07:15:15 +00:00
|
|
|
|
|
|
|
vec2_t const ptonline = { (int32_t)(w2.x + (w2d / (w1d + w2d)) * w21.x),
|
|
|
|
(int32_t)(w2.y + (w2d / (w1d + w2d)) * w21.y) };
|
|
|
|
|
|
|
|
vec2_t const scrp = { ptonline.x - vect.x, ptonline.y - vect.y };
|
|
|
|
|
|
|
|
if (scrv.x * scrp.x + scrv.y * scrp.y <= 0)
|
2014-10-25 03:26:31 +00:00
|
|
|
continue;
|
2015-10-20 07:15:15 +00:00
|
|
|
|
|
|
|
int64_t const t1 = scrp.x;
|
|
|
|
int64_t const t2 = scrp.y;
|
|
|
|
|
|
|
|
uint64_t const wdistsq = t1 * t1 + t2 * t2;
|
|
|
|
|
2014-10-25 03:26:31 +00:00
|
|
|
if (wdistsq < bestwdistsq)
|
|
|
|
{
|
|
|
|
bestk = k;
|
|
|
|
bestwdistsq = wdistsq;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bestk >= 0)
|
|
|
|
searchwall = sector[searchsector].wallptr + bestk;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
searchit = 0;
|
|
|
|
}
|
|
|
|
|
2018-10-16 06:09:09 +00:00
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2011-03-19 18:07:12 +00:00
|
|
|
// variables that are set to ceiling- or floor-members, depending
|
|
|
|
// on which one is processed right now
|
|
|
|
static int32_t global_cf_z;
|
|
|
|
static float global_cf_xpanning, global_cf_ypanning, global_cf_heinum;
|
2014-04-05 11:28:08 +00:00
|
|
|
static int32_t global_cf_shade, global_cf_pal, global_cf_fogpal;
|
2011-03-19 18:07:12 +00:00
|
|
|
static int32_t (*global_getzofslope_func)(int16_t, int32_t, int32_t);
|
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
static void polymost_internal_nonparallaxed(vec2f_t n0, vec2f_t n1, float ryp0, float ryp1, float x0, float x1,
|
|
|
|
float y0, float y1, int32_t sectnum)
|
2011-03-19 18:07:12 +00:00
|
|
|
{
|
2015-07-08 03:34:20 +00:00
|
|
|
int const have_floor = sectnum & MAXSECTORS;
|
|
|
|
sectnum &= ~MAXSECTORS;
|
2016-06-21 00:33:58 +00:00
|
|
|
usectortype const * const sec = (usectortype *)§or[sectnum];
|
2011-03-19 18:07:12 +00:00
|
|
|
|
|
|
|
// comments from floor code:
|
|
|
|
//(singlobalang/-16384*(sx-ghalfx) + 0*(sy-ghoriz) + (cosviewingrangeglobalang/16384)*ghalfx)*d + globalposx = u*16
|
|
|
|
//(cosglobalang/ 16384*(sx-ghalfx) + 0*(sy-ghoriz) + (sinviewingrangeglobalang/16384)*ghalfx)*d + globalposy = v*16
|
|
|
|
//( 0*(sx-ghalfx) + 1*(sy-ghoriz) + ( 0)*ghalfx)*d + globalposz/16 = (sec->floorz/16)
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
float ft[4] = { fglobalposx, fglobalposy, fcosglobalang, fsinglobalang };
|
|
|
|
|
|
|
|
if (globalorientation & 64)
|
2011-03-19 18:07:12 +00:00
|
|
|
{
|
|
|
|
//relative alignment
|
2019-03-19 17:08:35 +00:00
|
|
|
vec2_t const xy = { wall[wall[sec->wallptr].point2].x - wall[sec->wallptr].x,
|
2019-03-19 17:08:39 +00:00
|
|
|
wall[wall[sec->wallptr].point2].y - wall[sec->wallptr].y };
|
2019-03-19 17:08:35 +00:00
|
|
|
float r;
|
2019-03-19 17:08:39 +00:00
|
|
|
|
2019-03-19 17:08:35 +00:00
|
|
|
if (globalorientation & 2)
|
|
|
|
{
|
|
|
|
int i = krecipasm(nsqrtasm(uhypsq(xy.x,xy.y)));
|
|
|
|
r = i * (1.f/1073741824.f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int i = nsqrtasm(uhypsq(xy.x,xy.y)); if (i == 0) i = 1024; else i = tabledivide32(1048576, i);
|
|
|
|
r = i * (1.f/1048576.f);
|
|
|
|
}
|
2015-07-08 03:34:20 +00:00
|
|
|
|
2019-03-19 17:08:35 +00:00
|
|
|
vec2f_t const fxy = { xy.x*r, xy.y*r };
|
2015-07-08 03:34:20 +00:00
|
|
|
|
|
|
|
ft[0] = ((float)(globalposx - wall[sec->wallptr].x)) * fxy.x + ((float)(globalposy - wall[sec->wallptr].y)) * fxy.y;
|
|
|
|
ft[1] = ((float)(globalposy - wall[sec->wallptr].y)) * fxy.x - ((float)(globalposx - wall[sec->wallptr].x)) * fxy.y;
|
2015-03-24 00:40:33 +00:00
|
|
|
ft[2] = fcosglobalang * fxy.x + fsinglobalang * fxy.y;
|
2015-07-08 03:34:20 +00:00
|
|
|
ft[3] = fsinglobalang * fxy.x - fcosglobalang * fxy.y;
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
globalorientation ^= (!(globalorientation & 4)) ? 32 : 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
xtex.d = 0;
|
|
|
|
ytex.d = gxyaspect;
|
|
|
|
|
|
|
|
if (!(globalorientation&2) && global_cf_z-globalposz) // PK 2012: don't allow div by zero
|
|
|
|
ytex.d /= (double)(global_cf_z-globalposz);
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
otex.d = -ghoriz * ytex.d;
|
|
|
|
|
|
|
|
if (globalorientation & 8)
|
|
|
|
{
|
|
|
|
ft[0] *= (1.f / 8.f);
|
|
|
|
ft[1] *= -(1.f / 8.f);
|
|
|
|
ft[2] *= (1.f / 2097152.f);
|
|
|
|
ft[3] *= (1.f / 2097152.f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ft[0] *= (1.f / 16.f);
|
|
|
|
ft[1] *= -(1.f / 16.f);
|
|
|
|
ft[2] *= (1.f / 4194304.f);
|
|
|
|
ft[3] *= (1.f / 4194304.f);
|
|
|
|
}
|
|
|
|
|
|
|
|
xtex.u = ft[3] * -(1.f / 65536.f) * (double)viewingrange;
|
|
|
|
xtex.v = ft[2] * -(1.f / 65536.f) * (double)viewingrange;
|
|
|
|
ytex.u = ft[0] * ytex.d;
|
|
|
|
ytex.v = ft[1] * ytex.d;
|
|
|
|
otex.u = ft[0] * otex.d;
|
|
|
|
otex.v = ft[1] * otex.d;
|
|
|
|
otex.u += (ft[2] - xtex.u) * ghalfx;
|
|
|
|
otex.v -= (ft[3] + xtex.v) * ghalfx;
|
2011-03-19 18:07:12 +00:00
|
|
|
|
|
|
|
//Texture flipping
|
|
|
|
if (globalorientation&4)
|
|
|
|
{
|
2016-05-13 22:15:28 +00:00
|
|
|
swapdouble(&xtex.u, &xtex.v);
|
|
|
|
swapdouble(&ytex.u, &ytex.v);
|
|
|
|
swapdouble(&otex.u, &otex.v);
|
2011-03-19 18:07:12 +00:00
|
|
|
}
|
2015-03-24 00:40:48 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (globalorientation&16) { xtex.u = -xtex.u; ytex.u = -ytex.u; otex.u = -otex.u; }
|
|
|
|
if (globalorientation&32) { xtex.v = -xtex.v; ytex.v = -ytex.v; otex.v = -otex.v; }
|
2011-03-19 18:07:12 +00:00
|
|
|
|
|
|
|
//Texture panning
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2f_t fxy = { global_cf_xpanning * ((float)(1 << (picsiz[globalpicnum] & 15))) * (1.0f / 256.f),
|
|
|
|
global_cf_ypanning * ((float)(1 << (picsiz[globalpicnum] >> 4))) * (1.0f / 256.f) };
|
|
|
|
|
2011-03-19 18:07:12 +00:00
|
|
|
if ((globalorientation&(2+64)) == (2+64)) //Hack for panning for slopes w/ relative alignment
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
float r = global_cf_heinum * (1.0f / 4096.f);
|
|
|
|
r = polymost_invsqrt_approximation(r * r + 1);
|
|
|
|
|
|
|
|
if (!(globalorientation & 4))
|
|
|
|
fxy.y *= r;
|
|
|
|
else
|
|
|
|
fxy.x *= r;
|
2011-03-19 18:07:12 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
ytex.u += ytex.d*fxy.x; otex.u += otex.d*fxy.x;
|
|
|
|
ytex.v += ytex.d*fxy.y; otex.v += otex.d*fxy.y;
|
2011-03-19 18:07:12 +00:00
|
|
|
|
|
|
|
if (globalorientation&2) //slopes
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
//Pick some point guaranteed to be not collinear to the 1st two points
|
2019-03-19 17:07:57 +00:00
|
|
|
vec2f_t dxy = { n1.y - n0.y, n0.x - n1.x };
|
|
|
|
|
|
|
|
float const dxyr = polymost_invsqrt_approximation(dxy.x * dxy.x + dxy.y * dxy.y);
|
|
|
|
|
|
|
|
dxy.x *= dxyr * 4096.f;
|
|
|
|
dxy.y *= dxyr * 4096.f;
|
|
|
|
|
|
|
|
vec2f_t const oxy = { n0.x + dxy.x, n0.y + dxy.y };
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float const ox2 = (oxy.y - fglobalposy) * gcosang - (oxy.x - fglobalposx) * gsinang;
|
|
|
|
float oy2 = 1.f / ((oxy.x - fglobalposx) * gcosang2 + (oxy.y - fglobalposy) * gsinang2);
|
2011-03-19 18:07:12 +00:00
|
|
|
|
2019-03-19 17:08:05 +00:00
|
|
|
double const px[3] = { x0, x1, (double)ghalfx * ox2 * oy2 + ghalfx };
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
oy2 *= gyxscale;
|
|
|
|
|
|
|
|
double py[3] = { ryp0 + (double)ghoriz, ryp1 + (double)ghoriz, oy2 + (double)ghoriz };
|
|
|
|
|
2017-06-09 06:40:17 +00:00
|
|
|
vec3d_t const duv[3] = {
|
|
|
|
{ (px[0] * xtex.d + py[0] * ytex.d + otex.d),
|
|
|
|
(px[0] * xtex.u + py[0] * ytex.u + otex.u),
|
|
|
|
(px[0] * xtex.v + py[0] * ytex.v + otex.v)
|
2015-04-18 21:59:19 +00:00
|
|
|
},
|
2017-06-09 06:40:17 +00:00
|
|
|
{ (px[1] * xtex.d + py[1] * ytex.d + otex.d),
|
|
|
|
(px[1] * xtex.u + py[1] * ytex.u + otex.u),
|
|
|
|
(px[1] * xtex.v + py[1] * ytex.v + otex.v)
|
2015-04-18 21:59:19 +00:00
|
|
|
},
|
2017-06-09 06:40:17 +00:00
|
|
|
{ (px[2] * xtex.d + py[2] * ytex.d + otex.d),
|
|
|
|
(px[2] * xtex.u + py[2] * ytex.u + otex.u),
|
|
|
|
(px[2] * xtex.v + py[2] * ytex.v + otex.v)
|
2015-04-18 21:59:19 +00:00
|
|
|
}
|
2015-03-24 00:40:48 +00:00
|
|
|
};
|
2011-03-19 18:07:12 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
py[0] = y0;
|
|
|
|
py[1] = y1;
|
2019-03-19 17:08:05 +00:00
|
|
|
py[2] = double(global_getzofslope_func(sectnum, Blrintf(oxy.x), Blrintf(oxy.y)) - globalposz) * oy2 + ghoriz;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vec3f_t oxyz[2] = { { (float)(py[1] - py[2]), (float)(py[2] - py[0]), (float)(py[0] - py[1]) },
|
|
|
|
{ (float)(px[2] - px[1]), (float)(px[0] - px[2]), (float)(px[1] - px[0]) } };
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
float const r = 1.f / (oxyz[0].x * px[0] + oxyz[0].y * px[1] + oxyz[0].z * px[2]);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
xtex.d = (oxyz[0].x * duv[0].d + oxyz[0].y * duv[1].d + oxyz[0].z * duv[2].d) * r;
|
|
|
|
xtex.u = (oxyz[0].x * duv[0].u + oxyz[0].y * duv[1].u + oxyz[0].z * duv[2].u) * r;
|
|
|
|
xtex.v = (oxyz[0].x * duv[0].v + oxyz[0].y * duv[1].v + oxyz[0].z * duv[2].v) * r;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
ytex.d = (oxyz[1].x * duv[0].d + oxyz[1].y * duv[1].d + oxyz[1].z * duv[2].d) * r;
|
|
|
|
ytex.u = (oxyz[1].x * duv[0].u + oxyz[1].y * duv[1].u + oxyz[1].z * duv[2].u) * r;
|
|
|
|
ytex.v = (oxyz[1].x * duv[0].v + oxyz[1].y * duv[1].v + oxyz[1].z * duv[2].v) * r;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
otex.d = duv[0].d - px[0] * xtex.d - py[0] * ytex.d;
|
|
|
|
otex.u = duv[0].u - px[0] * xtex.u - py[0] * ytex.u;
|
|
|
|
otex.v = duv[0].v - px[0] * xtex.v - py[0] * ytex.v;
|
2011-03-19 18:07:12 +00:00
|
|
|
|
|
|
|
if (globalorientation&64) //Hack for relative alignment on slopes
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
float r = global_cf_heinum * (1.0f / 4096.f);
|
2014-09-30 04:06:05 +00:00
|
|
|
r = Bsqrtf(r*r+1);
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!(globalorientation&4)) { xtex.v *= r; ytex.v *= r; otex.v *= r; }
|
|
|
|
else { xtex.u *= r; ytex.u *= r; otex.u *= r; }
|
2011-03-19 18:07:12 +00:00
|
|
|
}
|
|
|
|
}
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2015-12-04 11:52:54 +00:00
|
|
|
domostpolymethod = (globalorientation>>7) & DAMETH_MASKPROPS;
|
2014-09-30 04:06:05 +00:00
|
|
|
|
|
|
|
pow2xsplit = 0;
|
2015-03-24 00:40:33 +00:00
|
|
|
drawpoly_alpha = 0.f;
|
2016-10-09 07:55:23 +00:00
|
|
|
drawpoly_blend = 0;
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2017-12-12 05:14:06 +00:00
|
|
|
calc_and_apply_fog(globalpicnum, fogshade(global_cf_shade, global_cf_pal), sec->visibility,
|
2014-09-30 04:06:05 +00:00
|
|
|
POLYMOST_CHOOSE_FOG_PAL(global_cf_fogpal, global_cf_pal));
|
|
|
|
|
2011-03-19 18:07:12 +00:00
|
|
|
if (have_floor)
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (globalposz > getflorzofslope(sectnum, globalposx, globalposy))
|
2015-12-04 11:52:54 +00:00
|
|
|
domostpolymethod = DAMETH_BACKFACECULL; //Back-face culling
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
polymost_domost(x0, y0, x1, y1); //flor
|
2011-03-19 18:07:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (globalposz < getceilzofslope(sectnum, globalposx, globalposy))
|
2015-12-04 11:52:54 +00:00
|
|
|
domostpolymethod = DAMETH_BACKFACECULL; //Back-face culling
|
2012-12-14 19:28:09 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
polymost_domost(x1, y1, x0, y0); //ceil
|
2014-09-30 04:06:05 +00:00
|
|
|
}
|
2012-12-14 19:28:09 +00:00
|
|
|
|
2015-12-04 11:52:54 +00:00
|
|
|
domostpolymethod = DAMETH_NOMASK;
|
2011-03-19 18:07:12 +00:00
|
|
|
}
|
|
|
|
|
2014-09-30 04:06:05 +00:00
|
|
|
static void calc_ypanning(int32_t refposz, float ryp0, float ryp1,
|
|
|
|
float x0, float x1, uint8_t ypan, uint8_t yrepeat,
|
2012-07-08 21:47:14 +00:00
|
|
|
int32_t dopancor)
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
float const t0 = ((float)(refposz-globalposz))*ryp0 + ghoriz;
|
|
|
|
float const t1 = ((float)(refposz-globalposz))*ryp1 + ghoriz;
|
2019-03-19 17:08:05 +00:00
|
|
|
float t = (float(xtex.d*x0 + otex.d) * (float)yrepeat) / ((x1-x0) * ryp0 * 2048.f);
|
2015-03-24 00:40:33 +00:00
|
|
|
int i = (1<<(picsiz[globalpicnum]>>4));
|
|
|
|
if (i < tilesiz[globalpicnum].y) i <<= 1;
|
2012-07-08 21:47:14 +00:00
|
|
|
|
2013-07-04 19:38:37 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
if (g_loadedMapVersion >= 10)
|
2014-09-30 04:14:21 +00:00
|
|
|
i = tilesiz[globalpicnum].y;
|
2013-07-04 19:38:37 +00:00
|
|
|
else
|
|
|
|
#endif
|
2014-06-01 11:55:19 +00:00
|
|
|
if (polymost_is_npotmode())
|
|
|
|
{
|
2014-09-30 04:14:21 +00:00
|
|
|
t *= (float)tilesiz[globalpicnum].y / i;
|
|
|
|
i = tilesiz[globalpicnum].y;
|
2014-06-01 11:55:19 +00:00
|
|
|
}
|
2019-03-19 17:08:43 +00:00
|
|
|
else if (!(glinfo.texnpot && r_npotwallmode == 2) && dopancor)
|
2012-07-08 21:47:14 +00:00
|
|
|
{
|
2013-07-04 19:38:37 +00:00
|
|
|
// Carry out panning "correction" to make it look like classic in some
|
|
|
|
// cases, but failing in the general case.
|
2014-10-25 03:29:21 +00:00
|
|
|
int32_t yoffs = Blrintf((i-tilesiz[globalpicnum].y)*(255.f/i));
|
2012-07-08 21:47:14 +00:00
|
|
|
|
2013-07-04 19:38:37 +00:00
|
|
|
if (ypan > 256-yoffs)
|
|
|
|
ypan -= yoffs;
|
2012-07-08 21:47:14 +00:00
|
|
|
}
|
|
|
|
|
2019-03-19 17:08:05 +00:00
|
|
|
float const fy = (float)(ypan * i) * (1.f / 256.f);
|
|
|
|
|
|
|
|
xtex.v = double(t0 - t1) * t;
|
|
|
|
ytex.v = double(x1 - x0) * t;
|
|
|
|
otex.v = -xtex.v * x0 - ytex.v * t0 + fy * otex.d;
|
|
|
|
xtex.v += fy * xtex.d;
|
|
|
|
ytex.v += fy * ytex.d;
|
2012-07-08 21:47:14 +00:00
|
|
|
}
|
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
static inline int32_t testvisiblemost(float const x0, float const x1)
|
2014-09-30 04:14:21 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=vsp[0].n, newi; i; i=newi)
|
2014-09-30 04:14:21 +00:00
|
|
|
{
|
|
|
|
newi = vsp[i].n;
|
2015-07-08 03:34:20 +00:00
|
|
|
if ((x0 < vsp[newi].x) && (vsp[i].x < x1) && (vsp[i].ctag >= 0))
|
|
|
|
return 1;
|
2014-09-30 04:14:21 +00:00
|
|
|
}
|
2015-07-08 03:34:20 +00:00
|
|
|
return 0;
|
2014-09-30 04:14:21 +00:00
|
|
|
}
|
2012-07-08 21:47:14 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
static inline int polymost_getclosestpointonwall(vec2_t const * const pos, int32_t dawall, vec2_t * const n)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2_t const w = { wall[dawall].x, wall[dawall].y };
|
|
|
|
vec2_t const d = { POINT2(dawall).x - w.x, POINT2(dawall).y - w.y };
|
2019-03-19 17:08:05 +00:00
|
|
|
int64_t i = d.x * ((int64_t)pos->x - w.x) + d.y * ((int64_t)pos->y - w.y);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if (i < 0)
|
|
|
|
return 1;
|
|
|
|
|
2019-03-19 17:08:05 +00:00
|
|
|
int64_t const j = (int64_t)d.x * d.x + (int64_t)d.y * d.y;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if (i > j)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
i = tabledivide64((i << 15), j) << 15;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
n->x = w.x + ((d.x * i) >> 30);
|
|
|
|
n->y = w.y + ((d.y * i) >> 30);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2011-05-22 21:52:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
static void polymost_drawalls(int32_t const bunch)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
|
|
|
drawpoly_alpha = 0.f;
|
2016-10-09 07:55:23 +00:00
|
|
|
drawpoly_blend = 0;
|
2013-03-04 09:10:54 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t const sectnum = thesector[bunchfirst[bunch]];
|
2016-06-21 00:33:58 +00:00
|
|
|
usectortype const * const sec = (usectortype *)§or[sectnum];
|
2018-03-07 04:21:18 +00:00
|
|
|
float const fglobalang = fix16_to_float(qglobalang);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//DRAW WALLS SECTION!
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t z=bunchfirst[bunch]; z>=0; z=bunchp2[z])
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t const wallnum = thewall[z];
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-06-21 00:33:58 +00:00
|
|
|
uwalltype * const wal = (uwalltype *)&wall[wallnum], *wal2 = (uwalltype *)&wall[wal->point2];
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t const nextsectnum = wal->nextsector;
|
2016-06-21 00:33:58 +00:00
|
|
|
usectortype * const nextsec = nextsectnum>=0 ? (usectortype *)§or[nextsectnum] : NULL;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Offset&Rotate 3D coordinates to screen 3D space
|
2015-03-24 00:40:48 +00:00
|
|
|
vec2f_t walpos = { (float)(wal->x-globalposx), (float)(wal->y-globalposy) };
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
vec2f_t p0 = { walpos.y * gcosang - walpos.x * gsinang, walpos.x * gcosang2 + walpos.y * gsinang2 };
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2f_t const op0 = p0;
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
walpos.x = (float)(wal2->x-globalposx); walpos.y = (float)(wal2->y-globalposy);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
vec2f_t p1 = { walpos.y * gcosang - walpos.x * gsinang, walpos.x * gcosang2 + walpos.y * gsinang2 };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Clip to close parallel-screen plane
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vec2f_t n0, n1;
|
|
|
|
float t0, t1;
|
|
|
|
|
|
|
|
if (p0.y < SCISDIST)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (p1.y < SCISDIST) continue;
|
|
|
|
t0 = (SCISDIST-p0.y)/(p1.y-p0.y); p0.x = (p1.x-p0.x)*t0+p0.x; p0.y = SCISDIST;
|
2017-10-31 00:35:23 +00:00
|
|
|
n0.x = (wal2->x-wal->x)*t0+wal->x;
|
|
|
|
n0.y = (wal2->y-wal->y)*t0+wal->y;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2017-10-31 00:35:23 +00:00
|
|
|
else { t0 = 0.f; n0.x = (float)wal->x; n0.y = (float)wal->y; }
|
2015-03-24 00:40:33 +00:00
|
|
|
if (p1.y < SCISDIST)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
t1 = (SCISDIST-op0.y)/(p1.y-op0.y); p1.x = (p1.x-op0.x)*t1+op0.x; p1.y = SCISDIST;
|
2017-10-31 00:35:23 +00:00
|
|
|
n1.x = (wal2->x-wal->x)*t1+wal->x;
|
|
|
|
n1.y = (wal2->y-wal->y)*t1+wal->y;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2017-10-31 00:35:23 +00:00
|
|
|
else { t1 = 1.f; n1.x = (float)wal2->x; n1.y = (float)wal2->y; }
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float ryp0 = 1.f/p0.y, ryp1 = 1.f/p1.y;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Generate screen coordinates for front side of wall
|
2015-03-24 00:40:33 +00:00
|
|
|
float const x0 = ghalfx*p0.x*ryp0 + ghalfx, x1 = ghalfx*p1.x*ryp1 + ghalfx;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (x1 <= x0) continue;
|
|
|
|
|
|
|
|
ryp0 *= gyxscale; ryp1 *= gyxscale;
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t cz, fz;
|
|
|
|
|
|
|
|
getzsofslope(sectnum,/*Blrintf(nx0)*/(int)n0.x,/*Blrintf(ny0)*/(int)n0.y,&cz,&fz);
|
|
|
|
float const cy0 = ((float)(cz-globalposz))*ryp0 + ghoriz, fy0 = ((float)(fz-globalposz))*ryp0 + ghoriz;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
getzsofslope(sectnum,/*Blrintf(nx1)*/(int)n1.x,/*Blrintf(ny1)*/(int)n1.y,&cz,&fz);
|
|
|
|
float const cy1 = ((float)(cz-globalposz))*ryp1 + ghoriz, fy1 = ((float)(fz-globalposz))*ryp1 + ghoriz;
|
|
|
|
|
2019-03-19 17:08:43 +00:00
|
|
|
xtex2.d = (ryp0 - ryp1)*gxyaspect / (x0 - x1);
|
|
|
|
ytex2.d = 0;
|
|
|
|
otex2.d = ryp0 * gxyaspect - xtex2.d*x0;
|
|
|
|
|
|
|
|
xtex2.u = ytex2.u = otex2.u = 0;
|
|
|
|
xtex2.v = ytex2.v = otex2.v = 0;
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
yax_holencf[YAX_FLOOR] = 0;
|
|
|
|
yax_drawcf = YAX_FLOOR;
|
|
|
|
#endif
|
|
|
|
|
2019-03-19 17:08:43 +00:00
|
|
|
// Floor
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
globalpicnum = sec->floorpicnum;
|
|
|
|
globalshade = sec->floorshade;
|
|
|
|
globalpal = sec->floorpal;
|
2006-04-24 19:04:22 +00:00
|
|
|
globalorientation = sec->floorstat;
|
2015-03-24 00:40:33 +00:00
|
|
|
globvis = (sector[sectnum].visibility != 0) ?
|
|
|
|
mulscale4(globalcisibility, (uint8_t)(sector[sectnum].visibility + 16)) :
|
|
|
|
globalcisibility;
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis2 = (sector[sectnum].visibility != 0) ?
|
|
|
|
mulscale4(globalcisibility2, (uint8_t)(sector[sectnum].visibility + 16)) :
|
|
|
|
globalcisibility2;
|
|
|
|
polymost_setVisibility(globvis2);
|
2013-05-15 02:19:14 +00:00
|
|
|
|
2012-11-15 21:09:53 +00:00
|
|
|
DO_TILE_ANIM(globalpicnum, sectnum);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2017-11-29 07:29:48 +00:00
|
|
|
int32_t dapskybits, dapyoffs, daptileyscale;
|
|
|
|
int8_t const * dapskyoff = getpsky(globalpicnum, NULL, &dapskybits, &dapyoffs, &daptileyscale);
|
2011-05-22 21:52:22 +00:00
|
|
|
|
2014-04-05 11:28:10 +00:00
|
|
|
global_cf_fogpal = sec->fogpal;
|
2011-03-19 18:07:12 +00:00
|
|
|
global_cf_shade = sec->floorshade, global_cf_pal = sec->floorpal; global_cf_z = sec->floorz; // REFACT
|
|
|
|
global_cf_xpanning = sec->floorxpanning; global_cf_ypanning = sec->floorypanning, global_cf_heinum = sec->floorheinum;
|
|
|
|
global_getzofslope_func = &getflorzofslope;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2011-03-19 18:07:12 +00:00
|
|
|
if (!(globalorientation&1))
|
2011-05-22 21:52:22 +00:00
|
|
|
{
|
2019-03-19 17:07:53 +00:00
|
|
|
int32_t fz = getflorzofslope(sectnum, globalposx, globalposy);
|
|
|
|
if (globalposz <= fz)
|
2015-07-08 03:34:20 +00:00
|
|
|
polymost_internal_nonparallaxed(n0, n1, ryp0, ryp1, x0, x1, fy0, fy1, sectnum | MAXSECTORS);
|
2011-05-22 21:52:22 +00:00
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
else if ((nextsectnum < 0) || (!(sector[nextsectnum].floorstat&1)))
|
|
|
|
{
|
2015-11-01 19:56:33 +00:00
|
|
|
//Parallaxing sky... hacked for Ken's mountain texture
|
2016-04-13 04:04:07 +00:00
|
|
|
calc_and_apply_fog_factor(sec->floorpicnum, sec->floorshade, sec->visibility, sec->floorpal, 0.005f);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis2 = globalpisibility;
|
|
|
|
if (sec->visibility != 0)
|
|
|
|
globvis2 = mulscale4(globvis2, (uint8_t)(sec->visibility + 16));
|
|
|
|
float viscale = xdimscale*fxdimen*(.0000001f/256.f);
|
|
|
|
polymost_setVisibility(globvis2*viscale);
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
//Use clamping for tiled sky textures
|
2017-11-29 07:29:51 +00:00
|
|
|
//(don't wrap around edges if the sky use multiple panels)
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=(1<<dapskybits)-1; i>0; i--)
|
2015-03-24 00:40:33 +00:00
|
|
|
if (dapskyoff[i] != dapskyoff[i-1])
|
|
|
|
{ skyclamphack = r_parallaxskyclamping; break; }
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2019-03-19 17:08:51 +00:00
|
|
|
skyzbufferhack = 1;
|
|
|
|
|
2015-11-01 19:56:33 +00:00
|
|
|
if (!usehightile || !hicfindskybox(globalpicnum, globalpal))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
float const dd = fxdimen*.0000001f; //Adjust sky depth based on screen size!
|
|
|
|
float vv[2];
|
|
|
|
float t = (float)((1<<(picsiz[globalpicnum]&15))<<dapskybits);
|
2017-11-29 07:29:48 +00:00
|
|
|
vv[1] = dd*((float)xdimscale*fviewingrange) * (1.f/(daptileyscale*65536.f));
|
2016-10-14 07:40:50 +00:00
|
|
|
vv[0] = dd*((float)((tilesiz[globalpicnum].y>>1)+dapyoffs)) - vv[1]*ghoriz;
|
2015-03-24 00:40:33 +00:00
|
|
|
int i = (1<<(picsiz[globalpicnum]>>4)); if (i != tilesiz[globalpicnum].y) i += i;
|
2015-11-01 19:56:33 +00:00
|
|
|
vec3f_t o;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2017-12-12 05:14:09 +00:00
|
|
|
if ((tilesiz[globalpicnum].y * daptileyscale * (1.f/65536.f)) > 256)
|
2017-11-29 07:29:51 +00:00
|
|
|
{
|
|
|
|
//Hack to draw black rectangle below sky when looking down...
|
|
|
|
xtex.d = xtex.u = xtex.v = 0;
|
2015-03-24 00:40:48 +00:00
|
|
|
|
2019-03-19 17:08:05 +00:00
|
|
|
ytex.d = gxyaspect * (1.0 / 262144.0);
|
2017-11-29 07:29:51 +00:00
|
|
|
ytex.u = 0;
|
2019-03-19 17:08:05 +00:00
|
|
|
ytex.v = double(tilesiz[globalpicnum].y - 1) * ytex.d;
|
2015-03-24 00:40:48 +00:00
|
|
|
|
2017-11-29 07:29:51 +00:00
|
|
|
otex.d = -ghoriz * ytex.d;
|
|
|
|
otex.u = 0;
|
2019-03-19 17:08:05 +00:00
|
|
|
otex.v = double(tilesiz[globalpicnum].y - 1) * otex.d;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2017-11-29 07:29:51 +00:00
|
|
|
o.y = ((float)tilesiz[globalpicnum].y*dd-vv[0])/vv[1];
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2017-11-29 07:29:51 +00:00
|
|
|
if ((o.y > fy0) && (o.y > fy1))
|
|
|
|
polymost_domost(x0,o.y,x1,o.y);
|
|
|
|
else if ((o.y > fy0) != (o.y > fy1))
|
2015-11-01 19:56:33 +00:00
|
|
|
{
|
2017-11-29 07:29:51 +00:00
|
|
|
// fy0 fy1
|
|
|
|
// \ /
|
|
|
|
//oy---------- oy----------
|
|
|
|
// \ /
|
|
|
|
// fy1 fy0
|
|
|
|
o.x = (o.y-fy0)*(x1-x0)/(fy1-fy0) + x0;
|
|
|
|
if (o.y > fy0)
|
|
|
|
{
|
|
|
|
polymost_domost(x0,o.y,o.x,o.y);
|
|
|
|
polymost_domost(o.x,o.y,x1,fy1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
polymost_domost(x0,fy0,o.x,o.y);
|
|
|
|
polymost_domost(o.x,o.y,x1,o.y);
|
|
|
|
}
|
2015-11-01 19:56:33 +00:00
|
|
|
}
|
|
|
|
else
|
2017-11-29 07:29:51 +00:00
|
|
|
polymost_domost(x0,fy0,x1,fy1);
|
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2015-11-01 19:56:33 +00:00
|
|
|
else
|
2017-11-29 07:29:51 +00:00
|
|
|
skyclamphack = 0;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
xtex.d = xtex.v = 0;
|
|
|
|
ytex.d = ytex.u = 0;
|
|
|
|
otex.d = dd;
|
2019-03-19 17:08:05 +00:00
|
|
|
xtex.u = otex.d * (t * double(((uint64_t)xdimscale * yxaspect) * viewingrange)) *
|
|
|
|
(1.0 / (16384.0 * 65536.0 * 65536.0 * 5.0 * 1024.0));
|
2015-03-24 00:40:48 +00:00
|
|
|
ytex.v = vv[1];
|
2015-11-01 19:56:33 +00:00
|
|
|
otex.v = r_parallaxskypanning ? vv[0] + dd*(float)sec->floorypanning*(float)i*(1.f/256.f) : vv[0];
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
i = globalpicnum;
|
|
|
|
float const r = (fy1-fy0)/(x1-x0); //slope of line
|
|
|
|
o.y = fviewingrange/(ghalfx*256.f); o.z = 1.f/o.y;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-03-07 04:21:18 +00:00
|
|
|
int y = ((int32_t)(((x0-ghalfx)*o.y)+fglobalang)>>(11-dapskybits));
|
2015-03-24 00:40:33 +00:00
|
|
|
float fx = x0;
|
2006-04-24 19:04:22 +00:00
|
|
|
do
|
|
|
|
{
|
2011-05-22 21:52:22 +00:00
|
|
|
globalpicnum = dapskyoff[y&((1<<dapskybits)-1)]+i;
|
2018-03-07 04:21:18 +00:00
|
|
|
otex.u = otex.d*(t*((float)(fglobalang-(y<<(11-dapskybits)))) * (1.f/2048.f) + (float)((r_parallaxskypanning)?sec->floorxpanning:0)) - xtex.u*ghalfx;
|
2006-04-24 19:04:22 +00:00
|
|
|
y++;
|
2018-03-07 04:21:18 +00:00
|
|
|
o.x = fx; fx = ((float)((y<<(11-dapskybits))-fglobalang))*o.z+ghalfx;
|
2006-04-24 19:04:22 +00:00
|
|
|
if (fx > x1) { fx = x1; i = -1; }
|
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
pow2xsplit = 0; polymost_domost(o.x,(o.x-x0)*r+fy0,fx,(fx-x0)*r+fy0); //flor
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (i >= 0);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
else //NOTE: code copied from ceiling code... lots of duplicated stuff :/
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
//Skybox code for parallax floor!
|
2015-03-24 00:40:48 +00:00
|
|
|
float sky_t0, sky_t1; // _nx0, _ny0, _nx1, _ny1;
|
|
|
|
float sky_ryp0, sky_ryp1, sky_x0, sky_x1, sky_cy0, sky_fy0, sky_cy1, sky_fy1, sky_ox0, sky_ox1;
|
|
|
|
static vec2f_t const skywal[4] = { { -512, -512 }, { 512, -512 }, { 512, 512 }, { -512, 512 } };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
pow2xsplit = 0;
|
|
|
|
skyclamphack = 1;
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<4; i++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
walpos = skywal[i&3];
|
|
|
|
vec2f_t skyp0 = { walpos.y * gcosang - walpos.x * gsinang,
|
|
|
|
walpos.x * gcosang2 + walpos.y * gsinang2 };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
walpos = skywal[(i + 1) & 3];
|
|
|
|
vec2f_t skyp1 = { walpos.y * gcosang - walpos.x * gsinang,
|
|
|
|
walpos.x * gcosang2 + walpos.y * gsinang2 };
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vec2f_t const oskyp0 = skyp0;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Clip to close parallel-screen plane
|
2015-03-24 00:40:33 +00:00
|
|
|
if (skyp0.y < SCISDIST)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (skyp1.y < SCISDIST) continue;
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_t0 = (SCISDIST-skyp0.y)/(skyp1.y-skyp0.y); skyp0.x = (skyp1.x-skyp0.x)*sky_t0+skyp0.x; skyp0.y = SCISDIST;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:48 +00:00
|
|
|
else { sky_t0 = 0.f; }
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (skyp1.y < SCISDIST)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_t1 = (SCISDIST-oskyp0.y)/(skyp1.y-oskyp0.y); skyp1.x = (skyp1.x-oskyp0.x)*sky_t1+oskyp0.x; skyp1.y = SCISDIST;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-11-01 19:56:33 +00:00
|
|
|
else { sky_t1 = 1.f; }
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_ryp0 = 1.f/skyp0.y; sky_ryp1 = 1.f/skyp1.y;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Generate screen coordinates for front side of wall
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_x0 = ghalfx*skyp0.x*sky_ryp0 + ghalfx;
|
|
|
|
sky_x1 = ghalfx*skyp1.x*sky_ryp1 + ghalfx;
|
|
|
|
if ((sky_x1 <= sky_x0) || (sky_x0 >= x1) || (x0 >= sky_x1)) continue;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_ryp0 *= gyxscale; sky_ryp1 *= gyxscale;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_cy0 = -8192.f*sky_ryp0 + ghoriz;
|
|
|
|
sky_fy0 = 8192.f*sky_ryp0 + ghoriz;
|
|
|
|
sky_cy1 = -8192.f*sky_ryp1 + ghoriz;
|
|
|
|
sky_fy1 = 8192.f*sky_ryp1 + ghoriz;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_ox0 = sky_x0; sky_ox1 = sky_x1;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-11-01 19:56:33 +00:00
|
|
|
//Make sure: x0<=_x0<_x1<=x1
|
2015-07-08 03:34:20 +00:00
|
|
|
float nfy[2] = { fy0, fy1 };
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (sky_x0 < x0)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
float const t = (x0-sky_x0)/(sky_x1-sky_x0);
|
|
|
|
sky_cy0 += (sky_cy1-sky_cy0)*t;
|
|
|
|
sky_fy0 += (sky_fy1-sky_fy0)*t;
|
|
|
|
sky_x0 = x0;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-07-08 03:34:20 +00:00
|
|
|
else if (sky_x0 > x0) nfy[0] += (sky_x0-x0)*(fy1-fy0)/(x1-x0);
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (sky_x1 > x1)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
float const t = (x1-sky_x1)/(sky_x1-sky_x0);
|
|
|
|
sky_cy1 += (sky_cy1-sky_cy0)*t;
|
|
|
|
sky_fy1 += (sky_fy1-sky_fy0)*t;
|
|
|
|
sky_x1 = x1;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-07-08 03:34:20 +00:00
|
|
|
else if (sky_x1 < x1) nfy[1] += (sky_x1-x1)*(fy1-fy0)/(x1-x0);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
// (skybox floor)
|
|
|
|
//(_x0,_fy0)-(_x1,_fy1)
|
|
|
|
// (skybox wall)
|
|
|
|
//(_x0,_cy0)-(_x1,_cy1)
|
|
|
|
// (skybox ceiling)
|
|
|
|
//(_x0,nfy0)-(_x1,nfy1)
|
|
|
|
|
2015-11-01 19:56:33 +00:00
|
|
|
//floor of skybox
|
|
|
|
drawingskybox = 6; //floor/6th texture/index 5 of skybox
|
2015-03-24 00:40:33 +00:00
|
|
|
float const ft[4] = { 512 / 16, 512 / -16, fcosglobalang * (1.f / 2147483648.f),
|
2015-11-01 19:56:33 +00:00
|
|
|
fsinglobalang * (1.f / 2147483648.f) };
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
xtex.d = 0;
|
2019-03-19 17:08:05 +00:00
|
|
|
ytex.d = gxyaspect*(1.0/4194304.0);
|
2015-03-24 00:40:33 +00:00
|
|
|
otex.d = -ghoriz*ytex.d;
|
2015-11-01 19:56:33 +00:00
|
|
|
xtex.u = ft[3]*fviewingrange*(-1.0/65536.0);
|
|
|
|
xtex.v = ft[2]*fviewingrange*(-1.0/65536.0);
|
2015-03-24 00:40:33 +00:00
|
|
|
ytex.u = ft[0]*ytex.d; ytex.v = ft[1]*ytex.d;
|
|
|
|
otex.u = ft[0]*otex.d; otex.v = ft[1]*otex.d;
|
|
|
|
otex.u += (ft[2]-xtex.u)*ghalfx;
|
|
|
|
otex.v -= (ft[3]+xtex.v)*ghalfx;
|
|
|
|
xtex.v = -xtex.v; ytex.v = -ytex.v; otex.v = -otex.v; //y-flip skybox floor
|
|
|
|
|
2015-11-01 19:56:33 +00:00
|
|
|
if ((sky_fy0 > nfy[0]) && (sky_fy1 > nfy[1]))
|
|
|
|
polymost_domost(sky_x0,sky_fy0,sky_x1,sky_fy1);
|
2015-07-08 03:34:20 +00:00
|
|
|
else if ((sky_fy0 > nfy[0]) != (sky_fy1 > nfy[1]))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-11-01 19:56:33 +00:00
|
|
|
//(ox,oy) is intersection of: (_x0,_fy0)-(_x1,_fy1)
|
2006-04-24 19:04:22 +00:00
|
|
|
// (_x0,nfy0)-(_x1,nfy1)
|
2015-07-08 03:34:20 +00:00
|
|
|
float const t = (sky_fy0-nfy[0])/(nfy[1]-nfy[0]-sky_fy1+sky_fy0);
|
2015-11-01 19:56:33 +00:00
|
|
|
vec2f_t const o = { sky_x0 + (sky_x1-sky_x0)*t, sky_fy0 + (sky_fy1-sky_fy0)*t };
|
2015-07-08 03:34:20 +00:00
|
|
|
if (nfy[0] > sky_fy0)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2015-11-01 19:56:33 +00:00
|
|
|
polymost_domost(sky_x0,nfy[0],o.x,o.y);
|
|
|
|
polymost_domost(o.x,o.y,sky_x1,sky_fy1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
polymost_domost(sky_x0,sky_fy0,o.x,o.y);
|
|
|
|
polymost_domost(o.x,o.y,sky_x1,nfy[1]);
|
2015-03-24 00:40:33 +00:00
|
|
|
}
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2015-11-01 19:56:33 +00:00
|
|
|
else
|
|
|
|
polymost_domost(sky_x0,nfy[0],sky_x1,nfy[1]);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//wall of skybox
|
|
|
|
drawingskybox = i+1; //i+1th texture/index i of skybox
|
2019-03-19 17:08:05 +00:00
|
|
|
xtex.d = (sky_ryp0-sky_ryp1)*gxyaspect*(1.0/512.0) / (sky_ox0-sky_ox1);
|
2015-03-24 00:40:33 +00:00
|
|
|
ytex.d = 0;
|
2019-03-19 17:08:05 +00:00
|
|
|
otex.d = sky_ryp0*gxyaspect*(1.0/512.0) - xtex.d*sky_ox0;
|
|
|
|
xtex.u = (sky_t0*sky_ryp0 - sky_t1*sky_ryp1)*gxyaspect*(64.0/512.0) / (sky_ox0-sky_ox1);
|
|
|
|
otex.u = sky_t0*sky_ryp0*gxyaspect*(64.0/512.0) - xtex.u*sky_ox0;
|
2015-03-24 00:40:33 +00:00
|
|
|
ytex.u = 0;
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_t0 = -8192.f*sky_ryp0 + ghoriz;
|
|
|
|
sky_t1 = -8192.f*sky_ryp1 + ghoriz;
|
|
|
|
float const t = ((xtex.d*sky_ox0 + otex.d)*8.f) / ((sky_ox1-sky_ox0) * sky_ryp0 * 2048.f);
|
|
|
|
xtex.v = (sky_t0-sky_t1)*t;
|
|
|
|
ytex.v = (sky_ox1-sky_ox0)*t;
|
|
|
|
otex.v = -xtex.v*sky_ox0 - ytex.v*sky_t0;
|
2015-11-01 19:56:33 +00:00
|
|
|
|
|
|
|
if ((sky_cy0 > nfy[0]) && (sky_cy1 > nfy[1]))
|
|
|
|
polymost_domost(sky_x0,sky_cy0,sky_x1,sky_cy1);
|
2015-07-08 03:34:20 +00:00
|
|
|
else if ((sky_cy0 > nfy[0]) != (sky_cy1 > nfy[1]))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
//(ox,oy) is intersection of: (_x0,_fy0)-(_x1,_fy1)
|
|
|
|
// (_x0,nfy0)-(_x1,nfy1)
|
2015-07-08 03:34:20 +00:00
|
|
|
float const t = (sky_cy0-nfy[0])/(nfy[1]-nfy[0]-sky_cy1+sky_cy0);
|
2015-03-24 00:40:48 +00:00
|
|
|
vec2f_t const o = { sky_x0 + (sky_x1 - sky_x0) * t, sky_cy0 + (sky_cy1 - sky_cy0) * t };
|
2015-11-01 19:56:33 +00:00
|
|
|
if (nfy[0] > sky_cy0)
|
|
|
|
{
|
|
|
|
polymost_domost(sky_x0,nfy[0],o.x,o.y);
|
|
|
|
polymost_domost(o.x,o.y,sky_x1,sky_cy1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
polymost_domost(sky_x0,sky_cy0,o.x,o.y);
|
|
|
|
polymost_domost(o.x,o.y,sky_x1,nfy[1]);
|
|
|
|
}
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2015-11-01 19:56:33 +00:00
|
|
|
else
|
|
|
|
polymost_domost(sky_x0,nfy[0],sky_x1,nfy[1]);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2015-11-01 19:56:33 +00:00
|
|
|
//Ceiling of skybox
|
|
|
|
drawingskybox = 5; //ceiling/5th texture/index 4 of skybox
|
2015-03-24 00:40:33 +00:00
|
|
|
float const ft[4] = { 512 / 16, -512 / -16, fcosglobalang * (1.f / 2147483648.f),
|
|
|
|
fsinglobalang * (1.f / 2147483648.f) };
|
|
|
|
|
|
|
|
xtex.d = 0;
|
2019-03-19 17:08:05 +00:00
|
|
|
ytex.d = gxyaspect*(-1.0/4194304.0);
|
2015-03-24 00:40:33 +00:00
|
|
|
otex.d = -ghoriz*ytex.d;
|
2015-11-01 19:56:33 +00:00
|
|
|
xtex.u = ft[3]*fviewingrange*(-1.0/65536.0);
|
|
|
|
xtex.v = ft[2]*fviewingrange*(-1.0/65536.0);
|
2015-03-24 00:40:33 +00:00
|
|
|
ytex.u = ft[0]*ytex.d; ytex.v = ft[1]*ytex.d;
|
|
|
|
otex.u = ft[0]*otex.d; otex.v = ft[1]*otex.d;
|
|
|
|
otex.u += (ft[2]-xtex.u)*ghalfx;
|
|
|
|
otex.v -= (ft[3]+xtex.v)*ghalfx;
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
polymost_domost(x0,fy0,x1,fy1);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
skyclamphack = 0;
|
|
|
|
drawingskybox = 0;
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
skyclamphack = 0;
|
2019-03-19 17:08:51 +00:00
|
|
|
skyzbufferhack = 0;
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!nofog)
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_setFogEnabled(true);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2015-11-01 19:56:33 +00:00
|
|
|
// Ceiling
|
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
yax_holencf[YAX_CEILING] = 0;
|
|
|
|
yax_drawcf = YAX_CEILING;
|
|
|
|
#endif
|
|
|
|
|
2015-11-01 19:56:33 +00:00
|
|
|
globalpicnum = sec->ceilingpicnum;
|
|
|
|
globalshade = sec->ceilingshade;
|
|
|
|
globalpal = sec->ceilingpal;
|
2006-04-24 19:04:22 +00:00
|
|
|
globalorientation = sec->ceilingstat;
|
2015-11-01 19:56:33 +00:00
|
|
|
globvis = (sector[sectnum].visibility != 0) ?
|
|
|
|
mulscale4(globalcisibility, (uint8_t)(sector[sectnum].visibility + 16)) :
|
|
|
|
globalcisibility;
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis2 = (sector[sectnum].visibility != 0) ?
|
|
|
|
mulscale4(globalcisibility2, (uint8_t)(sector[sectnum].visibility + 16)) :
|
|
|
|
globalcisibility2;
|
|
|
|
polymost_setVisibility(globvis2);
|
2013-05-15 02:19:14 +00:00
|
|
|
|
2012-11-15 21:09:53 +00:00
|
|
|
DO_TILE_ANIM(globalpicnum, sectnum);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2017-11-29 07:29:48 +00:00
|
|
|
dapskyoff = getpsky(globalpicnum, NULL, &dapskybits, &dapyoffs, &daptileyscale);
|
2011-05-22 21:52:22 +00:00
|
|
|
|
2014-04-05 11:28:10 +00:00
|
|
|
global_cf_fogpal = sec->fogpal;
|
2011-03-19 18:07:12 +00:00
|
|
|
global_cf_shade = sec->ceilingshade, global_cf_pal = sec->ceilingpal; global_cf_z = sec->ceilingz; // REFACT
|
|
|
|
global_cf_xpanning = sec->ceilingxpanning; global_cf_ypanning = sec->ceilingypanning, global_cf_heinum = sec->ceilingheinum;
|
|
|
|
global_getzofslope_func = &getceilzofslope;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2011-03-19 18:07:12 +00:00
|
|
|
if (!(globalorientation&1))
|
2011-05-22 21:52:22 +00:00
|
|
|
{
|
2019-03-19 17:07:53 +00:00
|
|
|
int32_t cz = getceilzofslope(sectnum, globalposx, globalposy);
|
|
|
|
if (globalposz >= cz)
|
2015-07-08 03:34:20 +00:00
|
|
|
polymost_internal_nonparallaxed(n0, n1, ryp0, ryp1, x0, x1, cy0, cy1, sectnum);
|
2011-05-22 21:52:22 +00:00
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
else if ((nextsectnum < 0) || (!(sector[nextsectnum].ceilingstat&1)))
|
|
|
|
{
|
2015-11-01 19:56:33 +00:00
|
|
|
//Parallaxing sky... hacked for Ken's mountain texture
|
2016-04-13 04:04:07 +00:00
|
|
|
calc_and_apply_fog_factor(sec->ceilingpicnum, sec->ceilingshade, sec->visibility, sec->ceilingpal, 0.005f);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis2 = globalpisibility;
|
|
|
|
if (sec->visibility != 0)
|
|
|
|
globvis2 = mulscale4(globvis2, (uint8_t)(sec->visibility + 16));
|
|
|
|
float viscale = xdimscale*fxdimen*(.0000001f/256.f);
|
|
|
|
polymost_setVisibility(globvis2*viscale);
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
//Use clamping for tiled sky textures
|
2017-11-29 07:29:51 +00:00
|
|
|
//(don't wrap around edges if the sky use multiple panels)
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=(1<<dapskybits)-1; i>0; i--)
|
2015-03-24 00:40:33 +00:00
|
|
|
if (dapskyoff[i] != dapskyoff[i-1])
|
|
|
|
{ skyclamphack = r_parallaxskyclamping; break; }
|
2012-12-14 19:28:09 +00:00
|
|
|
|
2019-03-19 17:08:51 +00:00
|
|
|
skyzbufferhack = 1;
|
|
|
|
|
2015-11-01 19:56:33 +00:00
|
|
|
if (!usehightile || !hicfindskybox(globalpicnum, globalpal))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
float const dd = fxdimen*.0000001f; //Adjust sky depth based on screen size!
|
|
|
|
float vv[2];
|
|
|
|
float t = (float)((1<<(picsiz[globalpicnum]&15))<<dapskybits);
|
2017-11-29 07:29:48 +00:00
|
|
|
vv[1] = dd*((float)xdimscale*fviewingrange) * (1.f/(daptileyscale*65536.f));
|
2016-10-14 07:40:50 +00:00
|
|
|
vv[0] = dd*((float)((tilesiz[globalpicnum].y>>1)+dapyoffs)) - vv[1]*ghoriz;
|
2015-03-24 00:40:33 +00:00
|
|
|
int i = (1<<(picsiz[globalpicnum]>>4)); if (i != tilesiz[globalpicnum].y) i += i;
|
2015-11-01 19:56:33 +00:00
|
|
|
vec3f_t o;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2017-12-12 05:14:09 +00:00
|
|
|
if ((tilesiz[globalpicnum].y * daptileyscale * (1.f/65536.f)) > 256)
|
2017-11-29 07:29:51 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2017-11-29 07:29:51 +00:00
|
|
|
|
|
|
|
//Hack to draw color rectangle above sky when looking up...
|
|
|
|
xtex.d = xtex.u = xtex.v = 0;
|
|
|
|
|
2019-03-19 17:08:05 +00:00
|
|
|
ytex.d = gxyaspect * (1.0 / -262144.0);
|
2017-11-29 07:29:51 +00:00
|
|
|
ytex.u = 0;
|
|
|
|
ytex.v = 0;
|
|
|
|
|
|
|
|
otex.d = -ghoriz * ytex.d;
|
|
|
|
otex.u = 0;
|
|
|
|
otex.v = 0;
|
|
|
|
|
|
|
|
o.y = -vv[0]/vv[1];
|
|
|
|
|
|
|
|
if ((o.y < cy0) && (o.y < cy1))
|
|
|
|
polymost_domost(x1,o.y,x0,o.y);
|
|
|
|
else if ((o.y < cy0) != (o.y < cy1))
|
2015-11-01 19:56:33 +00:00
|
|
|
{
|
2017-11-29 07:29:51 +00:00
|
|
|
/* cy1 cy0
|
|
|
|
// / \
|
|
|
|
//oy---------- oy---------
|
|
|
|
// / \
|
|
|
|
// cy0 cy1 */
|
|
|
|
o.x = (o.y-cy0)*(x1-x0)/(cy1-cy0) + x0;
|
|
|
|
if (o.y < cy0)
|
|
|
|
{
|
|
|
|
polymost_domost(o.x,o.y,x0,o.y);
|
|
|
|
polymost_domost(x1,cy1,o.x,o.y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
polymost_domost(o.x,o.y,x0,cy0);
|
|
|
|
polymost_domost(x1,o.y,o.x,o.y);
|
|
|
|
}
|
2015-11-01 19:56:33 +00:00
|
|
|
}
|
2017-11-29 07:29:51 +00:00
|
|
|
else
|
|
|
|
polymost_domost(x1,cy1,x0,cy0);
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2015-11-01 19:56:33 +00:00
|
|
|
else
|
2017-11-29 07:29:51 +00:00
|
|
|
skyclamphack = 0;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-11-01 19:56:33 +00:00
|
|
|
xtex.d = xtex.v = 0;
|
|
|
|
ytex.d = ytex.u = 0;
|
|
|
|
otex.d = dd;
|
2019-03-19 17:08:05 +00:00
|
|
|
xtex.u = otex.d * (t * double(((uint64_t)xdimscale * yxaspect) * viewingrange)) *
|
|
|
|
(1.0 / (16384.0 * 65536.0 * 65536.0 * 5.0 * 1024.0));
|
2015-11-01 19:56:33 +00:00
|
|
|
ytex.v = vv[1];
|
|
|
|
otex.v = r_parallaxskypanning ? vv[0] + dd*(float)sec->ceilingypanning*(float)i*(1.f/256.f) : vv[0];
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-06-05 04:46:28 +00:00
|
|
|
i = globalpicnum;
|
2015-03-24 00:40:33 +00:00
|
|
|
float const r = (cy1-cy0)/(x1-x0); //slope of line
|
|
|
|
o.y = fviewingrange/(ghalfx*256.f); o.z = 1.f/o.y;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-03-07 04:21:18 +00:00
|
|
|
int y = ((int32_t)(((x0-ghalfx)*o.y)+fglobalang)>>(11-dapskybits));
|
2015-03-24 00:40:33 +00:00
|
|
|
float fx = x0;
|
2006-04-24 19:04:22 +00:00
|
|
|
do
|
|
|
|
{
|
2011-05-22 21:52:22 +00:00
|
|
|
globalpicnum = dapskyoff[y&((1<<dapskybits)-1)]+i;
|
2018-03-07 04:21:18 +00:00
|
|
|
otex.u = otex.d*(t*((float)(fglobalang-(y<<(11-dapskybits)))) * (1.f/2048.f) + (float)((r_parallaxskypanning)?sec->ceilingxpanning:0)) - xtex.u*ghalfx;
|
2006-04-24 19:04:22 +00:00
|
|
|
y++;
|
2018-03-07 04:21:18 +00:00
|
|
|
o.x = fx; fx = (((float) (y<<(11-dapskybits))-fglobalang))*o.z+ghalfx;
|
2006-04-24 19:04:22 +00:00
|
|
|
if (fx > x1) { fx = x1; i = -1; }
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
pow2xsplit = 0; polymost_domost(fx,(fx-x0)*r+cy0,o.x,(o.x-x0)*r+cy0); //ceil
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (i >= 0);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
else
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
|
|
|
//Skybox code for parallax ceiling!
|
2015-03-24 00:40:48 +00:00
|
|
|
float sky_t0, sky_t1; // _nx0, _ny0, _nx1, _ny1;
|
|
|
|
float sky_ryp0, sky_ryp1, sky_x0, sky_x1, sky_cy0, sky_fy0, sky_cy1, sky_fy1, sky_ox0, sky_ox1;
|
|
|
|
static vec2f_t const skywal[4] = { { -512, -512 }, { 512, -512 }, { 512, 512 }, { -512, 512 } };
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
pow2xsplit = 0;
|
|
|
|
skyclamphack = 1;
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<4; i++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
walpos = skywal[i&3];
|
2015-07-08 03:34:20 +00:00
|
|
|
vec2f_t skyp0 = { walpos.y * gcosang - walpos.x * gsinang,
|
|
|
|
walpos.x * gcosang2 + walpos.y * gsinang2 };
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
walpos = skywal[(i + 1) & 3];
|
|
|
|
vec2f_t skyp1 = { walpos.y * gcosang - walpos.x * gsinang,
|
|
|
|
walpos.x * gcosang2 + walpos.y * gsinang2 };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2f_t const oskyp0 = skyp0;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Clip to close parallel-screen plane
|
2015-03-24 00:40:33 +00:00
|
|
|
if (skyp0.y < SCISDIST)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (skyp1.y < SCISDIST) continue;
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_t0 = (SCISDIST-skyp0.y)/(skyp1.y-skyp0.y); skyp0.x = (skyp1.x-skyp0.x)*sky_t0+skyp0.x; skyp0.y = SCISDIST;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:48 +00:00
|
|
|
else { sky_t0 = 0.f; }
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if (skyp1.y < SCISDIST)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_t1 = (SCISDIST-oskyp0.y)/(skyp1.y-oskyp0.y); skyp1.x = (skyp1.x-oskyp0.x)*sky_t1+oskyp0.x; skyp1.y = SCISDIST;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:48 +00:00
|
|
|
else { sky_t1 = 1.f; }
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_ryp0 = 1.f/skyp0.y; sky_ryp1 = 1.f/skyp1.y;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Generate screen coordinates for front side of wall
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_x0 = ghalfx*skyp0.x*sky_ryp0 + ghalfx;
|
|
|
|
sky_x1 = ghalfx*skyp1.x*sky_ryp1 + ghalfx;
|
|
|
|
if ((sky_x1 <= sky_x0) || (sky_x0 >= x1) || (x0 >= sky_x1)) continue;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_ryp0 *= gyxscale; sky_ryp1 *= gyxscale;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_cy0 = -8192.f*sky_ryp0 + ghoriz;
|
|
|
|
sky_fy0 = 8192.f*sky_ryp0 + ghoriz;
|
|
|
|
sky_cy1 = -8192.f*sky_ryp1 + ghoriz;
|
|
|
|
sky_fy1 = 8192.f*sky_ryp1 + ghoriz;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_ox0 = sky_x0; sky_ox1 = sky_x1;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-11-01 19:56:33 +00:00
|
|
|
//Make sure: x0<=_x0<_x1<=x1
|
2015-03-24 00:40:33 +00:00
|
|
|
float ncy[2] = { cy0, cy1 };
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (sky_x0 < x0)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
float const t = (x0-sky_x0)/(sky_x1-sky_x0);
|
|
|
|
sky_cy0 += (sky_cy1-sky_cy0)*t;
|
|
|
|
sky_fy0 += (sky_fy1-sky_fy0)*t;
|
|
|
|
sky_x0 = x0;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:48 +00:00
|
|
|
else if (sky_x0 > x0) ncy[0] += (sky_x0-x0)*(cy1-cy0)/(x1-x0);
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (sky_x1 > x1)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
float const t = (x1-sky_x1)/(sky_x1-sky_x0);
|
|
|
|
sky_cy1 += (sky_cy1-sky_cy0)*t;
|
|
|
|
sky_fy1 += (sky_fy1-sky_fy0)*t;
|
|
|
|
sky_x1 = x1;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:48 +00:00
|
|
|
else if (sky_x1 < x1) ncy[1] += (sky_x1-x1)*(cy1-cy0)/(x1-x0);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
// (skybox ceiling)
|
|
|
|
//(_x0,_cy0)-(_x1,_cy1)
|
|
|
|
// (skybox wall)
|
|
|
|
//(_x0,_fy0)-(_x1,_fy1)
|
|
|
|
// (skybox floor)
|
|
|
|
//(_x0,ncy0)-(_x1,ncy1)
|
|
|
|
|
|
|
|
//ceiling of skybox
|
|
|
|
drawingskybox = 5; //ceiling/5th texture/index 4 of skybox
|
2015-03-24 00:40:33 +00:00
|
|
|
float const ft[4] = { 512 / 16, -512 / -16, fcosglobalang * (1.f / 2147483648.f),
|
|
|
|
fsinglobalang * (1.f / 2147483648.f) };
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
xtex.d = 0;
|
2019-03-19 17:08:05 +00:00
|
|
|
ytex.d = gxyaspect*(-1.0/4194304.0);
|
2015-03-24 00:40:33 +00:00
|
|
|
otex.d = -ghoriz*ytex.d;
|
2015-11-01 19:56:33 +00:00
|
|
|
xtex.u = ft[3]*fviewingrange*(-1.0/65536.0);
|
|
|
|
xtex.v = ft[2]*fviewingrange*(-1.0/65536.0);
|
2015-03-24 00:40:33 +00:00
|
|
|
ytex.u = ft[0]*ytex.d; ytex.v = ft[1]*ytex.d;
|
|
|
|
otex.u = ft[0]*otex.d; otex.v = ft[1]*otex.d;
|
|
|
|
otex.u += (ft[2]-xtex.u)*ghalfx;
|
|
|
|
otex.v -= (ft[3]+xtex.v)*ghalfx;
|
2015-11-01 19:56:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
if ((sky_cy0 < ncy[0]) && (sky_cy1 < ncy[1]))
|
|
|
|
polymost_domost(sky_x1,sky_cy1,sky_x0,sky_cy0);
|
2015-03-24 00:40:48 +00:00
|
|
|
else if ((sky_cy0 < ncy[0]) != (sky_cy1 < ncy[1]))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
//(ox,oy) is intersection of: (_x0,_cy0)-(_x1,_cy1)
|
|
|
|
// (_x0,ncy0)-(_x1,ncy1)
|
2015-03-24 00:40:48 +00:00
|
|
|
float const t = (sky_cy0-ncy[0])/(ncy[1]-ncy[0]-sky_cy1+sky_cy0);
|
|
|
|
vec2f_t const o = { sky_x0 + (sky_x1-sky_x0)*t, sky_cy0 + (sky_cy1-sky_cy0)*t };
|
2015-11-01 19:56:33 +00:00
|
|
|
if (ncy[0] < sky_cy0)
|
|
|
|
{
|
|
|
|
polymost_domost(o.x,o.y,sky_x0,ncy[0]);
|
|
|
|
polymost_domost(sky_x1,sky_cy1,o.x,o.y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
polymost_domost(o.x,o.y,sky_x0,sky_cy0);
|
|
|
|
polymost_domost(sky_x1,ncy[1],o.x,o.y);
|
|
|
|
}
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2015-11-01 19:56:33 +00:00
|
|
|
else
|
|
|
|
polymost_domost(sky_x1,ncy[1],sky_x0,ncy[0]);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//wall of skybox
|
|
|
|
drawingskybox = i+1; //i+1th texture/index i of skybox
|
2019-03-19 17:08:05 +00:00
|
|
|
xtex.d = (sky_ryp0-sky_ryp1)*gxyaspect*(1.0/512.0) / (sky_ox0-sky_ox1);
|
2015-03-24 00:40:33 +00:00
|
|
|
ytex.d = 0;
|
2019-03-19 17:08:05 +00:00
|
|
|
otex.d = sky_ryp0*gxyaspect*(1.0/512.0) - xtex.d*sky_ox0;
|
|
|
|
xtex.u = (sky_t0*sky_ryp0 - sky_t1*sky_ryp1)*gxyaspect*(64.0/512.0) / (sky_ox0-sky_ox1);
|
|
|
|
otex.u = sky_t0*sky_ryp0*gxyaspect*(64.0/512.0) - xtex.u*sky_ox0;
|
2015-03-24 00:40:33 +00:00
|
|
|
ytex.u = 0;
|
2015-03-24 00:40:48 +00:00
|
|
|
sky_t0 = -8192.f*sky_ryp0 + ghoriz;
|
|
|
|
sky_t1 = -8192.f*sky_ryp1 + ghoriz;
|
|
|
|
float const t = ((xtex.d*sky_ox0 + otex.d)*8.f) / ((sky_ox1-sky_ox0) * sky_ryp0 * 2048.f);
|
|
|
|
xtex.v = (sky_t0-sky_t1)*t;
|
|
|
|
ytex.v = (sky_ox1-sky_ox0)*t;
|
|
|
|
otex.v = -xtex.v*sky_ox0 - ytex.v*sky_t0;
|
2015-11-01 19:56:33 +00:00
|
|
|
|
|
|
|
if ((sky_fy0 < ncy[0]) && (sky_fy1 < ncy[1]))
|
|
|
|
polymost_domost(sky_x1,sky_fy1,sky_x0,sky_fy0);
|
2015-03-24 00:40:48 +00:00
|
|
|
else if ((sky_fy0 < ncy[0]) != (sky_fy1 < ncy[1]))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
//(ox,oy) is intersection of: (_x0,_fy0)-(_x1,_fy1)
|
|
|
|
// (_x0,ncy0)-(_x1,ncy1)
|
2015-03-24 00:40:48 +00:00
|
|
|
float const t = (sky_fy0-ncy[0])/(ncy[1]-ncy[0]-sky_fy1+sky_fy0);
|
|
|
|
vec2f_t const o = { sky_x0 + (sky_x1 - sky_x0) * t, sky_fy0 + (sky_fy1 - sky_fy0) * t };
|
2015-11-01 19:56:33 +00:00
|
|
|
if (ncy[0] < sky_fy0)
|
|
|
|
{
|
|
|
|
polymost_domost(o.x,o.y,sky_x0,ncy[0]);
|
|
|
|
polymost_domost(sky_x1,sky_fy1,o.x,o.y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
polymost_domost(o.x,o.y,sky_x0,sky_fy0);
|
|
|
|
polymost_domost(sky_x1,ncy[1],o.x,o.y);
|
|
|
|
}
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
2015-11-01 19:56:33 +00:00
|
|
|
else
|
|
|
|
polymost_domost(sky_x1,ncy[1],sky_x0,ncy[0]);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//Floor of skybox
|
|
|
|
drawingskybox = 6; //floor/6th texture/index 5 of skybox
|
2015-03-24 00:40:33 +00:00
|
|
|
float const ft[4] = { 512 / 16, 512 / -16, fcosglobalang * (1.f / 2147483648.f),
|
|
|
|
fsinglobalang * (1.f / 2147483648.f) };
|
2015-11-01 19:56:33 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
xtex.d = 0;
|
2019-03-19 17:08:05 +00:00
|
|
|
ytex.d = gxyaspect*(1.0/4194304.0);
|
2015-03-24 00:40:33 +00:00
|
|
|
otex.d = -ghoriz*ytex.d;
|
|
|
|
xtex.u = ft[3]*fviewingrange*(-1.0/65536.0);
|
|
|
|
xtex.v = ft[2]*fviewingrange*(-1.0/65536.0);
|
|
|
|
ytex.u = ft[0]*ytex.d; ytex.v = ft[1]*ytex.d;
|
|
|
|
otex.u = ft[0]*otex.d; otex.v = ft[1]*otex.d;
|
|
|
|
otex.u += (ft[2]-xtex.u)*ghalfx;
|
|
|
|
otex.v -= (ft[3]+xtex.v)*ghalfx;
|
|
|
|
xtex.v = -xtex.v; ytex.v = -ytex.v; otex.v = -otex.v; //y-flip skybox floor
|
2015-07-08 03:34:20 +00:00
|
|
|
polymost_domost(x1,cy1,x0,cy0);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
skyclamphack = 0;
|
|
|
|
drawingskybox = 0;
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
skyclamphack = 0;
|
2019-03-19 17:08:51 +00:00
|
|
|
skyzbufferhack = 0;
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!nofog)
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_setFogEnabled(true);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (g_nodraw)
|
|
|
|
{
|
|
|
|
int32_t baselevp, checkcf, i, j;
|
|
|
|
int16_t bn[2];
|
|
|
|
# if 0
|
|
|
|
int32_t obunchchk = (1 && yax_globalbunch>=0 &&
|
|
|
|
haveymost[yax_globalbunch>>3]&(1<<(yax_globalbunch&7)));
|
|
|
|
|
|
|
|
// if (obunchchk)
|
|
|
|
const int32_t x2 = yax_globalbunch*xdimen;
|
|
|
|
# endif
|
|
|
|
baselevp = (yax_globallev == YAX_MAXDRAWS);
|
|
|
|
|
|
|
|
yax_getbunches(sectnum, &bn[0], &bn[1]);
|
|
|
|
checkcf = (bn[0]>=0) + ((bn[1]>=0)<<1);
|
|
|
|
if (!baselevp)
|
|
|
|
checkcf &= (1<<yax_globalcf);
|
|
|
|
|
|
|
|
for (i=0; i<2; i++)
|
|
|
|
if (checkcf&(1<<i))
|
|
|
|
{
|
|
|
|
if ((haveymost[bn[i]>>3]&(1<<(bn[i]&7)))==0)
|
|
|
|
{
|
|
|
|
// init yax *most arrays for that bunch
|
|
|
|
haveymost[bn[i]>>3] |= (1<<(bn[i]&7));
|
|
|
|
yax_vsp[bn[i]*2][1].x = xbl;
|
|
|
|
yax_vsp[bn[i]*2][2].x = xbr;
|
|
|
|
yax_vsp[bn[i]*2][1].cy[0] = xbb;
|
|
|
|
yax_vsp[bn[i]*2][2].cy[0] = xbb;
|
|
|
|
yax_vsp_finalize_init(bn[i]*2, 3);
|
|
|
|
yax_vsp[bn[i]*2+1][1].x = xbl;
|
|
|
|
yax_vsp[bn[i]*2+1][2].x = xbr;
|
|
|
|
yax_vsp[bn[i]*2+1][1].cy[0] = xbt;
|
|
|
|
yax_vsp[bn[i]*2+1][2].cy[0] = xbt;
|
|
|
|
yax_vsp_finalize_init(bn[i]*2+1, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j < yax_holencf[i]; j++)
|
|
|
|
{
|
|
|
|
yax_hole_t *hole = &yax_holecf[i][j];
|
|
|
|
yax_polymost_domost(bn[i]*2, hole->x0, hole->cy[0], hole->x1, hole->cy[1]);
|
|
|
|
yax_polymost_domost(bn[i]*2+1, hole->x1, hole->fy[1], hole->x0, hole->fy[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-11-01 19:56:33 +00:00
|
|
|
// Wall
|
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
yax_drawcf = -1;
|
|
|
|
#endif
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
xtex.d = (ryp0-ryp1)*gxyaspect / (x0-x1);
|
|
|
|
ytex.d = 0;
|
|
|
|
otex.d = ryp0*gxyaspect - xtex.d*x0;
|
|
|
|
|
|
|
|
xtex.u = (t0*ryp0 - t1*ryp1)*gxyaspect*(float)wal->xrepeat*8.f / (x0-x1);
|
2019-03-19 17:08:05 +00:00
|
|
|
otex.u = t0*ryp0*gxyaspect*wal->xrepeat*8.0 - xtex.u*x0;
|
2015-03-24 00:40:33 +00:00
|
|
|
otex.u += (float)wal->xpanning*otex.d;
|
|
|
|
xtex.u += (float)wal->xpanning*xtex.d;
|
|
|
|
ytex.u = 0;
|
|
|
|
|
|
|
|
float const ogux = xtex.u, oguy = ytex.u, oguo = otex.u;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-12-04 11:52:54 +00:00
|
|
|
Bassert(domostpolymethod == DAMETH_NOMASK);
|
2014-06-01 11:55:19 +00:00
|
|
|
domostpolymethod = DAMETH_WALL;
|
2019-03-19 17:08:05 +00:00
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (yax_nomaskpass==0 || !yax_isislandwall(wallnum, !yax_globalcf) || (yax_nomaskdidit=1, 0))
|
|
|
|
#endif
|
2006-04-24 19:04:22 +00:00
|
|
|
if (nextsectnum >= 0)
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
getzsofslope(nextsectnum,/*Blrintf(nx0)*/(int)n0.x,/*Blrintf(ny0)*/(int)n0.y,&cz,&fz);
|
|
|
|
float const ocy0 = ((float)(cz-globalposz))*ryp0 + ghoriz;
|
|
|
|
float const ofy0 = ((float)(fz-globalposz))*ryp0 + ghoriz;
|
|
|
|
getzsofslope(nextsectnum,/*Blrintf(nx1)*/(int)n1.x,/*Blrintf(ny1)*/(int)n1.y,&cz,&fz);
|
|
|
|
float const ocy1 = ((float)(cz-globalposz))*ryp1 + ghoriz;
|
|
|
|
float const ofy1 = ((float)(fz-globalposz))*ryp1 + ghoriz;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
if ((wal->cstat&48) == 16) maskwall[maskwallcnt++] = z;
|
|
|
|
|
|
|
|
if (((cy0 < ocy0) || (cy1 < ocy1)) && (!((sec->ceilingstat§or[nextsectnum].ceilingstat)&1)))
|
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
globalpicnum = wal->picnum; globalshade = wal->shade; globalpal = (int32_t)((uint8_t)wal->pal);
|
2013-05-15 02:19:14 +00:00
|
|
|
globvis = globalvisibility;
|
|
|
|
if (sector[sectnum].visibility != 0) globvis = mulscale4(globvis, (uint8_t)(sector[sectnum].visibility+16));
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis2 = globalvisibility2;
|
|
|
|
if (sector[sectnum].visibility != 0) globvis2 = mulscale4(globvis2, (uint8_t)(sector[sectnum].visibility+16));
|
|
|
|
polymost_setVisibility(globvis2);
|
2018-11-18 18:13:48 +00:00
|
|
|
globalorientation = wal->cstat;
|
2012-11-15 21:09:53 +00:00
|
|
|
DO_TILE_ANIM(globalpicnum, wallnum+16384);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int i = (!(wal->cstat&4)) ? sector[nextsectnum].ceilingz : sec->ceilingz;
|
2008-03-27 21:32:23 +00:00
|
|
|
|
2012-07-09 19:00:14 +00:00
|
|
|
// over
|
2012-07-08 21:47:14 +00:00
|
|
|
calc_ypanning(i, ryp0, ryp1, x0, x1, wal->ypanning, wal->yrepeat, wal->cstat&4);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
if (wal->cstat&8) //xflip
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
float const t = (float)(wal->xrepeat*8 + wal->xpanning*2);
|
|
|
|
xtex.u = xtex.d*t - xtex.u;
|
|
|
|
ytex.u = ytex.d*t - ytex.u;
|
|
|
|
otex.u = otex.d*t - otex.u;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
if (wal->cstat&256) { xtex.v = -xtex.v; ytex.v = -ytex.v; otex.v = -otex.v; } //yflip
|
2012-12-14 19:28:09 +00:00
|
|
|
|
2017-12-12 05:14:06 +00:00
|
|
|
calc_and_apply_fog(wal->picnum, fogshade(wal->shade, wal->pal), sec->visibility, get_floor_fogpal(sec));
|
2012-12-14 19:28:09 +00:00
|
|
|
|
2019-03-04 23:49:11 +00:00
|
|
|
pow2xsplit = 1; polymost_domost(x1,ocy1,x0,ocy0,cy1,ocy1,cy0,ocy0);
|
2015-03-24 00:40:33 +00:00
|
|
|
if (wal->cstat&8) { xtex.u = ogux; ytex.u = oguy; otex.u = oguo; }
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
if (((ofy0 < fy0) || (ofy1 < fy1)) && (!((sec->floorstat§or[nextsectnum].floorstat)&1)))
|
|
|
|
{
|
2016-06-21 00:33:58 +00:00
|
|
|
uwalltype *nwal;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (!(wal->cstat&2)) nwal = wal;
|
|
|
|
else
|
|
|
|
{
|
2016-06-21 00:33:58 +00:00
|
|
|
nwal = (uwalltype *)&wall[wal->nextwall];
|
2015-03-24 00:40:33 +00:00
|
|
|
otex.u += (float)(nwal->xpanning - wal->xpanning) * otex.d;
|
|
|
|
xtex.u += (float)(nwal->xpanning - wal->xpanning) * xtex.d;
|
|
|
|
ytex.u += (float)(nwal->xpanning - wal->xpanning) * ytex.d;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2009-01-09 09:29:17 +00:00
|
|
|
globalpicnum = nwal->picnum; globalshade = nwal->shade; globalpal = (int32_t)((uint8_t)nwal->pal);
|
2013-05-15 02:19:14 +00:00
|
|
|
globvis = globalvisibility;
|
|
|
|
if (sector[sectnum].visibility != 0) globvis = mulscale4(globvis, (uint8_t)(sector[sectnum].visibility+16));
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis2 = globalvisibility2;
|
|
|
|
if (sector[sectnum].visibility != 0) globvis2 = mulscale4(globvis2, (uint8_t)(sector[sectnum].visibility+16));
|
|
|
|
polymost_setVisibility(globvis2);
|
2019-02-02 23:24:32 +00:00
|
|
|
globalorientation = nwal->cstat;
|
2012-11-15 21:09:53 +00:00
|
|
|
DO_TILE_ANIM(globalpicnum, wallnum+16384);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int i = (!(nwal->cstat&4)) ? sector[nextsectnum].floorz : sec->ceilingz;
|
2008-03-27 21:32:23 +00:00
|
|
|
|
2012-07-09 19:00:14 +00:00
|
|
|
// under
|
2012-07-08 21:47:14 +00:00
|
|
|
calc_ypanning(i, ryp0, ryp1, x0, x1, nwal->ypanning, wal->yrepeat, !(nwal->cstat&4));
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
if (wal->cstat&8) //xflip
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
float const t = (float)(wal->xrepeat*8 + nwal->xpanning*2);
|
|
|
|
xtex.u = xtex.d*t - xtex.u;
|
|
|
|
ytex.u = ytex.d*t - ytex.u;
|
|
|
|
otex.u = otex.d*t - otex.u;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
if (nwal->cstat&256) { xtex.v = -xtex.v; ytex.v = -ytex.v; otex.v = -otex.v; } //yflip
|
2012-12-14 19:28:09 +00:00
|
|
|
|
2017-12-12 05:14:06 +00:00
|
|
|
calc_and_apply_fog(nwal->picnum, fogshade(nwal->shade, nwal->pal), sec->visibility, get_floor_fogpal(sec));
|
2012-12-14 19:28:09 +00:00
|
|
|
|
2019-03-04 23:49:11 +00:00
|
|
|
pow2xsplit = 1; polymost_domost(x0,ofy0,x1,ofy1,ofy0,fy0,ofy1,fy1);
|
2015-03-24 00:40:33 +00:00
|
|
|
if (wal->cstat&(2+8)) { otex.u = oguo; xtex.u = ogux; ytex.u = oguy; }
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((nextsectnum < 0) || (wal->cstat&32)) //White/1-way wall
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
const int maskingOneWay = (nextsectnum >= 0 && (wal->cstat&32));
|
|
|
|
|
|
|
|
if (maskingOneWay)
|
|
|
|
{
|
|
|
|
vec2_t n, pos = { globalposx, globalposy };
|
|
|
|
if (!polymost_getclosestpointonwall(&pos, wallnum, &n) && klabs(pos.x - n.x) + klabs(pos.y - n.y) <= 128)
|
|
|
|
break;
|
|
|
|
}
|
2014-05-28 22:40:14 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
globalpicnum = (nextsectnum < 0) ? wal->picnum : wal->overpicnum;
|
2013-05-15 02:19:14 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
globalshade = wal->shade;
|
|
|
|
globalpal = wal->pal;
|
|
|
|
globvis = (sector[sectnum].visibility != 0) ?
|
|
|
|
mulscale4(globalvisibility, (uint8_t)(sector[sectnum].visibility + 16)) :
|
|
|
|
globalvisibility;
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis2 = (sector[sectnum].visibility != 0) ?
|
|
|
|
mulscale4(globalvisibility2, (uint8_t)(sector[sectnum].visibility + 16)) :
|
|
|
|
globalvisibility2;
|
|
|
|
polymost_setVisibility(globvis2);
|
2018-11-18 18:13:48 +00:00
|
|
|
globalorientation = wal->cstat;
|
2015-03-24 00:40:33 +00:00
|
|
|
DO_TILE_ANIM(globalpicnum, wallnum+16384);
|
2008-03-27 21:32:23 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int i;
|
|
|
|
int const nwcs4 = !(wal->cstat & 4);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (nextsectnum >= 0) { i = nwcs4 ? nextsec->ceilingz : sec->ceilingz; }
|
|
|
|
else { i = nwcs4 ? sec->ceilingz : sec->floorz; }
|
|
|
|
|
|
|
|
// white / 1-way
|
|
|
|
calc_ypanning(i, ryp0, ryp1, x0, x1, wal->ypanning, wal->yrepeat, nwcs4 && !maskingOneWay);
|
2012-12-14 19:28:09 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (wal->cstat&8) //xflip
|
|
|
|
{
|
|
|
|
float const t = (float) (wal->xrepeat*8 + wal->xpanning*2);
|
|
|
|
xtex.u = xtex.d*t - xtex.u;
|
|
|
|
ytex.u = ytex.d*t - ytex.u;
|
|
|
|
otex.u = otex.d*t - otex.u;
|
|
|
|
}
|
|
|
|
if (wal->cstat&256) { xtex.v = -xtex.v; ytex.v = -ytex.v; otex.v = -otex.v; } //yflip
|
2012-12-14 19:28:09 +00:00
|
|
|
|
2017-12-12 05:14:06 +00:00
|
|
|
calc_and_apply_fog(wal->picnum, fogshade(wal->shade, wal->pal), sec->visibility, get_floor_fogpal(sec));
|
2019-03-04 23:49:11 +00:00
|
|
|
pow2xsplit = 1; polymost_domost(x0, cy0, x1, cy1, cy0, fy0, cy1, fy1);
|
2015-03-24 00:40:33 +00:00
|
|
|
} while (0);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2015-12-04 11:52:54 +00:00
|
|
|
domostpolymethod = DAMETH_NOMASK;
|
2014-06-01 11:55:19 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (nextsectnum >= 0)
|
2015-07-08 03:34:20 +00:00
|
|
|
if ((!(gotsector[nextsectnum>>3]&pow2char[nextsectnum&7])) && testvisiblemost(x0,x1))
|
2006-04-24 19:04:22 +00:00
|
|
|
polymost_scansector(nextsectnum);
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2014-09-30 04:06:05 +00:00
|
|
|
static int32_t polymost_bunchfront(const int32_t b1, const int32_t b2)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
int b1f = bunchfirst[b1];
|
2014-10-25 03:34:25 +00:00
|
|
|
const float x2b2 = dxb2[bunchlast[b2]];
|
|
|
|
const float x1b1 = dxb1[b1f];
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2019-03-02 23:21:52 +00:00
|
|
|
if (nexttowardf(x1b1, x2b2) >= x2b2)
|
2014-10-25 03:34:25 +00:00
|
|
|
return -1;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
int b2f = bunchfirst[b2];
|
2015-03-24 00:40:33 +00:00
|
|
|
const float x1b2 = dxb1[b2f];
|
2014-10-25 03:34:25 +00:00
|
|
|
|
2019-03-02 23:21:52 +00:00
|
|
|
if (nexttowardf(x1b2, dxb2[bunchlast[b1]]) >= dxb2[bunchlast[b1]])
|
2015-03-24 00:40:33 +00:00
|
|
|
return -1;
|
2014-10-25 03:34:25 +00:00
|
|
|
|
2019-03-02 23:21:52 +00:00
|
|
|
if (nexttowardf(x1b1, x1b2) > x1b2)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2019-03-02 23:21:52 +00:00
|
|
|
while (nexttowardf(dxb2[b2f], x1b1) <= x1b1) b2f=bunchp2[b2f];
|
2015-03-24 00:40:48 +00:00
|
|
|
return wallfront(b1f, b2f);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-03-02 23:21:52 +00:00
|
|
|
while (nexttowardf(dxb2[b1f], x1b2) <= x1b2) b1f=bunchp2[b1f];
|
2015-03-24 00:40:48 +00:00
|
|
|
return wallfront(b1f, b2f);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2011-05-22 21:52:22 +00:00
|
|
|
void polymost_scansector(int32_t sectnum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
if (sectnum < 0) return;
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
sectorborder[0] = sectnum;
|
|
|
|
int sectorbordercnt = 1;
|
2006-04-24 19:04:22 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
sectnum = sectorborder[--sectorbordercnt];
|
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (scansector_collectsprites)
|
|
|
|
#endif
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t z=headspritesect[sectnum]; z>=0; z=nextspritesect[z])
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2016-06-21 00:33:58 +00:00
|
|
|
uspritetype const * const spr = (uspritetype *)&sprite[z];
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2016-10-25 05:43:42 +00:00
|
|
|
if ((spr->cstat & 0x8000 && !showinvisibility) || spr->xrepeat == 0 || spr->yrepeat == 0)
|
|
|
|
continue;
|
2016-05-13 22:15:28 +00:00
|
|
|
|
2016-10-25 05:43:42 +00:00
|
|
|
vec2_t const s = { spr->x-globalposx, spr->y-globalposy };
|
|
|
|
|
|
|
|
if ((spr->cstat&48) || (usemodels && tile2model[spr->picnum].modelid>=0) || ((s.x * gcosang) + (s.y * gsinang) > 0))
|
|
|
|
{
|
|
|
|
if ((spr->cstat&(64+48))!=(64+16) || dmulscale6(sintable[(spr->ang+512)&2047],-s.x, sintable[spr->ang&2047],-s.y) > 0)
|
2018-04-12 21:04:00 +00:00
|
|
|
if (renderAddTsprite(z, sectnum))
|
2016-10-25 05:43:42 +00:00
|
|
|
break;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gotsector[sectnum>>3] |= pow2char[sectnum&7];
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
int const bunchfrst = numbunches;
|
2017-12-20 08:35:49 +00:00
|
|
|
int const onumscans = numscans;
|
2015-03-24 00:40:48 +00:00
|
|
|
int const startwall = sector[sectnum].wallptr;
|
2017-12-20 08:35:49 +00:00
|
|
|
int const endwall = sector[sectnum].wallnum + startwall;
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
int scanfirst = numscans;
|
2017-12-20 08:35:49 +00:00
|
|
|
|
2019-03-02 23:21:52 +00:00
|
|
|
vec2d_t p2 = { 0, 0 };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-06-21 00:33:58 +00:00
|
|
|
uwalltype *wal;
|
2015-03-24 00:40:48 +00:00
|
|
|
int z;
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2016-06-21 00:33:58 +00:00
|
|
|
for (z=startwall,wal=(uwalltype *)&wall[z]; z<endwall; z++,wal++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2017-12-20 08:35:49 +00:00
|
|
|
uwalltype const *const wal2 = (uwalltype *)&wall[wal->point2];
|
|
|
|
|
2019-03-02 23:21:52 +00:00
|
|
|
vec2d_t const fp1 = { double(wal->x - globalposx), double(wal->y - globalposy) };
|
|
|
|
vec2d_t const fp2 = { double(wal2->x - globalposx), double(wal2->y - globalposy) };
|
2015-03-24 00:40:48 +00:00
|
|
|
|
|
|
|
int const nextsectnum = wal->nextsector; //Scan close sectors
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2017-12-17 09:27:27 +00:00
|
|
|
if (nextsectnum >= 0 && !(wal->cstat&32) && sectorbordercnt < ARRAY_SSIZE(sectorborder))
|
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (yax_nomaskpass==0 || !yax_isislandwall(z, !yax_globalcf) || (yax_nomaskdidit=1, 0))
|
|
|
|
#endif
|
2015-01-04 18:45:03 +00:00
|
|
|
if ((gotsector[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2019-03-02 23:21:52 +00:00
|
|
|
double const d = fp1.x*fp2.y - fp2.x*fp1.y;
|
|
|
|
vec2d_t const p1 = { fp2.x-fp1.x, fp2.y-fp1.y };
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2019-03-02 23:21:52 +00:00
|
|
|
// this said (SCISDIST*SCISDIST*260.f), but SCISDIST is 1 and the significance of 260 isn't obvious to me
|
|
|
|
// is 260 fudged to solve a problem, and does the problem still apply to our version of the renderer?
|
|
|
|
if (d*d < (p1.x*p1.x + p1.y*p1.y) * 256.f)
|
2015-01-04 18:45:03 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
sectorborder[sectorbordercnt++] = nextsectnum;
|
2015-01-04 18:45:03 +00:00
|
|
|
gotsector[nextsectnum>>3] |= pow2char[nextsectnum&7];
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2019-03-02 23:21:52 +00:00
|
|
|
vec2d_t p1;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if ((z == startwall) || (wall[z-1].point2 != z))
|
|
|
|
{
|
2019-03-02 23:21:52 +00:00
|
|
|
p1 = { (((fp1.y * fcosglobalang) - (fp1.x * fsinglobalang)) * (1.0/64.0)),
|
|
|
|
(((fp1.x * cosviewingrangeglobalang) + (fp1.y * sinviewingrangeglobalang)) * (1.0/64.0)) };
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2014-09-30 04:14:21 +00:00
|
|
|
else { p1 = p2; }
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2019-03-02 23:21:52 +00:00
|
|
|
p2 = { (((fp2.y * fcosglobalang) - (fp2.x * fsinglobalang)) * (1.0/64.0)),
|
|
|
|
(((fp2.x * cosviewingrangeglobalang) + (fp2.y * sinviewingrangeglobalang)) * (1.0/64.0)) };
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2016-05-13 22:15:28 +00:00
|
|
|
//if wall is facing you...
|
2019-03-02 23:21:52 +00:00
|
|
|
if ((p1.y >= SCISDIST || p2.y >= SCISDIST) && (nexttoward(p1.x*p2.y, p2.x*p1.y) < p2.x*p1.y))
|
2016-05-13 22:15:28 +00:00
|
|
|
{
|
2019-03-02 23:21:52 +00:00
|
|
|
dxb1[numscans] = (p1.y >= SCISDIST) ? float(p1.x*ghalfx/p1.y + ghalfx) : -1e32f;
|
|
|
|
dxb2[numscans] = (p2.y >= SCISDIST) ? float(p2.x*ghalfx/p2.y + ghalfx) : 1e32f;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2019-03-02 23:21:52 +00:00
|
|
|
if (nexttowardf(dxb1[numscans], dxb2[numscans]) < dxb2[numscans])
|
2016-05-13 22:15:28 +00:00
|
|
|
{
|
|
|
|
thesector[numscans] = sectnum;
|
|
|
|
thewall[numscans] = z;
|
|
|
|
bunchp2[numscans] = numscans + 1;
|
|
|
|
numscans++;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2016-05-13 22:15:28 +00:00
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
if ((wall[z].point2 < z) && (scanfirst < numscans))
|
2016-05-13 22:15:28 +00:00
|
|
|
{
|
|
|
|
bunchp2[numscans-1] = scanfirst;
|
|
|
|
scanfirst = numscans;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2017-12-20 08:35:49 +00:00
|
|
|
for (bssize_t z=onumscans; z<numscans; z++)
|
2016-05-13 22:15:28 +00:00
|
|
|
{
|
2019-03-02 23:21:52 +00:00
|
|
|
if ((wall[thewall[z]].point2 != thewall[bunchp2[z]]) || (dxb2[z] > nexttowardf(dxb1[bunchp2[z]], dxb2[z])))
|
2011-05-22 21:52:22 +00:00
|
|
|
{
|
2016-05-13 22:15:28 +00:00
|
|
|
bunchfirst[numbunches++] = bunchp2[z];
|
|
|
|
bunchp2[z] = -1;
|
2011-05-22 21:52:22 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (scansector_retfast)
|
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
}
|
2016-05-13 22:15:28 +00:00
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t z=bunchfrst; z<numbunches; z++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
int zz;
|
2016-01-12 10:31:12 +00:00
|
|
|
for (zz=bunchfirst[z]; bunchp2[zz]>=0; zz=bunchp2[zz]) { }
|
2006-04-24 19:04:22 +00:00
|
|
|
bunchlast[z] = zz;
|
|
|
|
}
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (sectorbordercnt > 0);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
/*Init viewport boundary (must be 4 point convex loop):
|
|
|
|
// (px[0],py[0]).----.(px[1],py[1])
|
|
|
|
// / \
|
|
|
|
// / \
|
|
|
|
// (px[3],py[3]).--------------.(px[2],py[2])
|
|
|
|
*/
|
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
static void polymost_initmosts(const float * px, const float * py, int const n)
|
2014-09-30 04:14:21 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (n < 3) return;
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t imin = (px[1] < px[0]);
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=n-1; i>=2; i--)
|
2016-05-13 22:15:28 +00:00
|
|
|
if (px[i] < px[imin]) imin = i;
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t vcnt = 1; //0 is dummy solid node
|
2014-09-30 04:14:21 +00:00
|
|
|
|
|
|
|
vsp[vcnt].x = px[imin];
|
|
|
|
vsp[vcnt].cy[0] = vsp[vcnt].fy[0] = py[imin];
|
|
|
|
vcnt++;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2016-06-05 04:46:28 +00:00
|
|
|
int i = imin+1, j = imin-1;
|
2015-03-24 00:40:33 +00:00
|
|
|
if (i >= n) i = 0;
|
|
|
|
if (j < 0) j = n-1;
|
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
do
|
|
|
|
{
|
|
|
|
if (px[i] < px[j])
|
|
|
|
{
|
2018-10-25 23:29:38 +00:00
|
|
|
if (px[i] <= vsp[vcnt-1].x) vcnt--;
|
2014-09-30 04:14:21 +00:00
|
|
|
vsp[vcnt].x = px[i];
|
|
|
|
vsp[vcnt].cy[0] = py[i];
|
2015-03-24 00:40:33 +00:00
|
|
|
int k = j+1; if (k >= n) k = 0;
|
2014-09-30 04:14:21 +00:00
|
|
|
//(px[k],py[k])
|
|
|
|
//(px[i],?)
|
|
|
|
//(px[j],py[j])
|
|
|
|
vsp[vcnt].fy[0] = (px[i]-px[k])*(py[j]-py[k])/(px[j]-px[k]) + py[k];
|
|
|
|
vcnt++;
|
|
|
|
i++; if (i >= n) i = 0;
|
|
|
|
}
|
|
|
|
else if (px[j] < px[i])
|
|
|
|
{
|
2018-10-25 23:29:38 +00:00
|
|
|
if (px[j] <= vsp[vcnt-1].x) vcnt--;
|
2014-09-30 04:14:21 +00:00
|
|
|
vsp[vcnt].x = px[j];
|
|
|
|
vsp[vcnt].fy[0] = py[j];
|
2015-03-24 00:40:33 +00:00
|
|
|
int k = i-1; if (k < 0) k = n-1;
|
2014-09-30 04:14:21 +00:00
|
|
|
//(px[k],py[k])
|
|
|
|
//(px[j],?)
|
|
|
|
//(px[i],py[i])
|
|
|
|
vsp[vcnt].cy[0] = (px[j]-px[k])*(py[i]-py[k])/(px[i]-px[k]) + py[k];
|
|
|
|
vcnt++;
|
|
|
|
j--; if (j < 0) j = n-1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-25 23:29:38 +00:00
|
|
|
if (px[i] <= vsp[vcnt-1].x) vcnt--;
|
2014-09-30 04:14:21 +00:00
|
|
|
vsp[vcnt].x = px[i];
|
|
|
|
vsp[vcnt].cy[0] = py[i];
|
|
|
|
vsp[vcnt].fy[0] = py[j];
|
|
|
|
vcnt++;
|
|
|
|
i++; if (i >= n) i = 0; if (i == j) break;
|
|
|
|
j--; if (j < 0) j = n-1;
|
|
|
|
}
|
|
|
|
} while (i != j);
|
|
|
|
|
|
|
|
if (px[i] > vsp[vcnt-1].x)
|
|
|
|
{
|
|
|
|
vsp[vcnt].x = px[i];
|
|
|
|
vsp[vcnt].cy[0] = vsp[vcnt].fy[0] = py[i];
|
|
|
|
vcnt++;
|
|
|
|
}
|
|
|
|
|
2019-03-02 23:22:12 +00:00
|
|
|
domost_rejectcount = 0;
|
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
vsp_finalize_init(vcnt);
|
2019-03-19 17:07:53 +00:00
|
|
|
|
|
|
|
xbl = px[0];
|
|
|
|
xbr = px[0];
|
|
|
|
xbt = py[0];
|
|
|
|
xbb = py[0];
|
|
|
|
|
|
|
|
for (bssize_t i=n-1; i>=1; i--)
|
|
|
|
{
|
|
|
|
if (xbl > px[i]) xbl = px[i];
|
|
|
|
if (xbr < px[i]) xbr = px[i];
|
|
|
|
if (xbt > py[i]) xbt = py[i];
|
|
|
|
if (xbb < py[i]) xbb = py[i];
|
|
|
|
}
|
|
|
|
|
2014-09-30 04:14:21 +00:00
|
|
|
gtag = vcnt;
|
|
|
|
}
|
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
void polymost_drawrooms()
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_CLASSIC) return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoBeginDrawing();
|
2016-06-21 00:34:18 +00:00
|
|
|
frameoffset = frameplace + windowxy1.y*bytesperline + windowxy1.x;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
resizeglcheck();
|
2011-05-18 22:44:09 +00:00
|
|
|
#ifdef YAX_ENABLE
|
2015-03-24 00:40:33 +00:00
|
|
|
if (numyaxbunches==0)
|
2011-05-18 22:44:09 +00:00
|
|
|
#endif
|
2015-03-24 00:40:33 +00:00
|
|
|
if (editstatus)
|
2018-02-16 06:38:21 +00:00
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
2013-09-14 17:59:01 +00:00
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (yax_polymostclearzbuffer)
|
|
|
|
#endif
|
2018-02-16 06:38:21 +00:00
|
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
2010-09-06 23:08:35 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
2019-03-19 17:07:53 +00:00
|
|
|
glDepthFunc(GL_ALWAYS); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS
|
2018-02-16 06:38:21 +00:00
|
|
|
// glDepthRange(0.0, 1.0); //<- this is more widely supported than glPolygonOffset
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Polymost supports true look up/down :) Here, we convert horizon to angle.
|
|
|
|
//gchang&gshang are cos&sin of this angle (respectively)
|
2014-09-30 04:06:05 +00:00
|
|
|
gyxscale = ((float)xdimenscale)*(1.0f/131072.f);
|
2019-03-19 17:08:05 +00:00
|
|
|
gxyaspect = ((double)xyaspect*fviewingrange)*(5.0/(65536.0*262144.0));
|
2014-10-25 03:27:35 +00:00
|
|
|
gviewxrange = fviewingrange * fxdimen * (1.f/(32768.f*1024.f));
|
2014-09-30 04:14:21 +00:00
|
|
|
gcosang = fcosglobalang*(1.0f/262144.f);
|
|
|
|
gsinang = fsinglobalang*(1.0f/262144.f);
|
2014-10-25 03:27:35 +00:00
|
|
|
gcosang2 = gcosang * (fviewingrange * (1.0f/65536.f));
|
|
|
|
gsinang2 = gsinang * (fviewingrange * (1.0f/65536.f));
|
2015-03-24 00:40:33 +00:00
|
|
|
ghalfx = (float)(xdimen>>1);
|
2014-09-30 04:06:05 +00:00
|
|
|
grhalfxdown10 = 1.f/(ghalfx*1024.f);
|
2018-03-07 04:21:05 +00:00
|
|
|
ghoriz = fix16_to_float(qglobalhoriz);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2006-07-02 17:33:49 +00:00
|
|
|
gvisibility = ((float)globalvisibility)*FOGSCALE;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//global cos/sin height angle
|
2015-03-24 00:40:33 +00:00
|
|
|
float r = (float)(ydimen>>1) - ghoriz;
|
2014-09-30 04:06:05 +00:00
|
|
|
gshang = r/Bsqrtf(r*r+ghalfx*ghalfx);
|
|
|
|
gchang = Bsqrtf(1.f-gshang*gshang);
|
2015-03-24 00:40:33 +00:00
|
|
|
ghoriz = (float)(ydimen>>1);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//global cos/sin tilt angle
|
2015-03-24 00:40:33 +00:00
|
|
|
gctang = cosf(gtang);
|
|
|
|
gstang = sinf(gtang);
|
2015-07-08 03:34:20 +00:00
|
|
|
|
|
|
|
if (Bfabsf(gstang) < .001f) // This hack avoids nasty precision bugs in domost()
|
|
|
|
{
|
|
|
|
gstang = 0.f;
|
|
|
|
gctang = (gctang > 0.f) ? 1.f : -1.f;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
if (inpreparemirror)
|
|
|
|
gstang = -gstang;
|
|
|
|
|
|
|
|
//Generate viewport trapezoid (for handling screen up/down)
|
2015-03-24 00:40:48 +00:00
|
|
|
vec3f_t p[4] = { { 0-1, 0-1, 0 },
|
2016-06-21 00:34:18 +00:00
|
|
|
{ (float)(windowxy2.x + 1 - windowxy1.x + 2), 0-1, 0 },
|
|
|
|
{ (float)(windowxy2.x + 1 - windowxy1.x + 2), (float)(windowxy2.y + 1 - windowxy1.y + 2), 0 },
|
|
|
|
{ 0-1, (float)(windowxy2.y + 1 - windowxy1.y + 2), 0 } };
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<4; i++)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
//Tilt rotation (backwards)
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2f_t const o = { p[i].x-ghalfx, p[i].y-ghoriz };
|
|
|
|
vec3f_t const o2 = { o.x*gctang + o.y*gstang, o.y*gctang - o.x*gstang, ghalfx };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Up/down rotation (backwards)
|
2015-03-24 00:40:33 +00:00
|
|
|
p[i].x = o2.x;
|
|
|
|
p[i].y = o2.y*gchang + o2.z*gshang;
|
|
|
|
p[i].z = o2.z*gchang - o2.y*gshang;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//Clip to SCISDIST plane
|
2015-03-24 00:40:48 +00:00
|
|
|
int n = 0;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vec3f_t p2[6];
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<4; i++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-26 21:42:19 +00:00
|
|
|
int const j = i < 3 ? i + 1 : 0;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if (p[i].z >= SCISDIST)
|
2015-03-24 00:40:48 +00:00
|
|
|
p2[n++] = p[i];
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if ((p[i].z >= SCISDIST) != (p[j].z >= SCISDIST))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
float const r = (SCISDIST - p[i].z) / (p[j].z - p[i].z);
|
2015-03-24 00:40:48 +00:00
|
|
|
p2[n].x = (p[j].x - p[i].x) * r + p[i].x;
|
|
|
|
p2[n].y = (p[j].y - p[i].y) * r + p[i].y;
|
|
|
|
p2[n].z = SCISDIST; n++;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
if (n < 3) { glDepthFunc(GL_LEQUAL); videoEndDrawing(); return; }
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
float sx[4], sy[4];
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i = 0; i < n; i++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
float const r = ghalfx / p2[i].z;
|
|
|
|
sx[i] = p2[i].x * r + ghalfx;
|
|
|
|
sy[i] = p2[i].y * r + ghoriz;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
polymost_initmosts(sx, sy, n);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2019-03-19 17:07:53 +00:00
|
|
|
#ifdef YAX_ENABLE
|
|
|
|
if (yax_globallev != YAX_MAXDRAWS)
|
|
|
|
{
|
|
|
|
int i, newi;
|
|
|
|
int32_t nodrawbak = g_nodraw;
|
|
|
|
g_nodraw = 1;
|
|
|
|
for (i = yax_vsp[yax_globalbunch*2][0].n; i; i=newi)
|
|
|
|
{
|
|
|
|
newi = yax_vsp[yax_globalbunch*2][i].n;
|
|
|
|
if (!newi)
|
|
|
|
break;
|
|
|
|
polymost_domost(yax_vsp[yax_globalbunch*2][newi].x, yax_vsp[yax_globalbunch*2][i].cy[1], yax_vsp[yax_globalbunch*2][i].x, yax_vsp[yax_globalbunch*2][i].cy[0]);
|
|
|
|
}
|
|
|
|
for (i = yax_vsp[yax_globalbunch*2+1][0].n; i; i=newi)
|
|
|
|
{
|
|
|
|
newi = yax_vsp[yax_globalbunch*2+1][i].n;
|
|
|
|
if (!newi)
|
|
|
|
break;
|
|
|
|
polymost_domost(yax_vsp[yax_globalbunch*2+1][i].x, yax_vsp[yax_globalbunch*2+1][i].cy[0], yax_vsp[yax_globalbunch*2+1][newi].x, yax_vsp[yax_globalbunch*2+1][i].cy[1]);
|
|
|
|
}
|
|
|
|
g_nodraw = nodrawbak;
|
|
|
|
}
|
|
|
|
//else if (!g_nodraw) { videoEndDrawing(); return; }
|
|
|
|
#endif
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (searchit == 2)
|
2014-10-25 03:26:31 +00:00
|
|
|
polymost_editorfunc();
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
polymost_updaterotmat();
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
numscans = numbunches = 0;
|
|
|
|
|
2012-01-26 21:57:51 +00:00
|
|
|
// MASKWALL_BAD_ACCESS
|
|
|
|
// Fixes access of stale maskwall[maskwallcnt] (a "scan" index, in BUILD lingo):
|
|
|
|
maskwallcnt = 0;
|
|
|
|
|
2015-08-01 08:41:14 +00:00
|
|
|
// NOTE: globalcursectnum has been already adjusted in ADJUST_GLOBALCURSECTNUM.
|
|
|
|
Bassert((unsigned)globalcursectnum < MAXSECTORS);
|
2006-04-24 19:04:22 +00:00
|
|
|
polymost_scansector(globalcursectnum);
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
grhalfxdown10x = grhalfxdown10;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (inpreparemirror)
|
|
|
|
{
|
|
|
|
grhalfxdown10x = -grhalfxdown10;
|
|
|
|
inpreparemirror = 0;
|
2012-03-08 19:15:03 +00:00
|
|
|
|
|
|
|
// see engine.c: INPREPAREMIRROR_NO_BUNCHES
|
|
|
|
if (numbunches > 0)
|
|
|
|
{
|
|
|
|
polymost_drawalls(0);
|
|
|
|
numbunches--;
|
|
|
|
bunchfirst[0] = bunchfirst[numbunches];
|
|
|
|
bunchlast[0] = bunchlast[numbunches];
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
while (numbunches > 0)
|
|
|
|
{
|
2014-10-25 03:34:25 +00:00
|
|
|
Bmemset(ptempbuf,0,numbunches+3); ptempbuf[0] = 1;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t closest = 0; //Almost works, but not quite :(
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=1; i<numbunches; ++i)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
int const bnch = polymost_bunchfront(i,closest); if (bnch < 0) continue;
|
2009-01-09 09:29:17 +00:00
|
|
|
ptempbuf[i] = 1;
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!bnch) { ptempbuf[closest] = 1; closest = i; }
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<numbunches; ++i) //Double-check
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
if (ptempbuf[i]) continue;
|
2015-03-24 00:40:33 +00:00
|
|
|
int const bnch = polymost_bunchfront(i,closest); if (bnch < 0) continue;
|
2009-01-09 09:29:17 +00:00
|
|
|
ptempbuf[i] = 1;
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!bnch) { ptempbuf[closest] = 1; closest = i; i = 0; }
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
polymost_drawalls(closest);
|
|
|
|
|
|
|
|
numbunches--;
|
|
|
|
bunchfirst[closest] = bunchfirst[numbunches];
|
|
|
|
bunchlast[closest] = bunchlast[numbunches];
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glDepthFunc(GL_LEQUAL); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS
|
|
|
|
// glDepthRange(0.0, 1.0); //<- this is more widely supported than glPolygonOffset
|
2019-03-19 17:08:39 +00:00
|
|
|
polymost_identityrotmat();
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:02:51 +00:00
|
|
|
videoEndDrawing();
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
void polymost_drawmaskwall(int32_t damaskwallcnt)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
int const z = maskwall[damaskwallcnt];
|
2016-06-21 00:33:58 +00:00
|
|
|
uwalltype const * const wal = (uwalltype *)&wall[thewall[z]], *wal2 = (uwalltype *)&wall[wal->point2];
|
2015-03-24 00:40:48 +00:00
|
|
|
int32_t const sectnum = thesector[z];
|
2016-06-21 00:33:58 +00:00
|
|
|
usectortype const * const sec = (usectortype *)§or[sectnum];
|
2012-01-26 21:57:51 +00:00
|
|
|
|
|
|
|
// if (wal->nextsector < 0) return;
|
|
|
|
// Without MASKWALL_BAD_ACCESS fix:
|
|
|
|
// wal->nextsector is -1, WGR2 SVN Lochwood Hollow (Til' Death L1) (or trueror1.map)
|
|
|
|
|
2016-06-21 00:33:58 +00:00
|
|
|
usectortype const * const nsec = (usectortype *)§or[wal->nextsector];
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
globalpicnum = wal->overpicnum;
|
|
|
|
if ((uint32_t)globalpicnum >= MAXTILES)
|
|
|
|
globalpicnum = 0;
|
2013-05-15 02:19:14 +00:00
|
|
|
|
2018-11-18 18:13:48 +00:00
|
|
|
globalorientation = (int32_t)wal->cstat;
|
2012-11-15 21:09:53 +00:00
|
|
|
DO_TILE_ANIM(globalpicnum, (int16_t)thewall[z]+16384);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis = globalvisibility;
|
2015-03-24 00:40:48 +00:00
|
|
|
globvis = (sector[sectnum].visibility != 0) ? mulscale4(globvis, (uint8_t)(sector[sectnum].visibility + 16)) : globalvisibility;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis2 = globalvisibility2;
|
|
|
|
globvis2 = (sector[sectnum].visibility != 0) ? mulscale4(globvis2, (uint8_t)(sector[sectnum].visibility + 16)) : globalvisibility2;
|
|
|
|
polymost_setVisibility(globvis2);
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
globalshade = (int32_t)wal->shade;
|
|
|
|
globalpal = (int32_t)((uint8_t)wal->pal);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
vec2f_t s0 = { (float)(wal->x-globalposx), (float)(wal->y-globalposy) };
|
|
|
|
vec2f_t p0 = { s0.y*gcosang - s0.x*gsinang, s0.x*gcosang2 + s0.y*gsinang2 };
|
|
|
|
|
|
|
|
vec2f_t s1 = { (float)(wal2->x-globalposx), (float)(wal2->y-globalposy) };
|
|
|
|
vec2f_t p1 = { s1.y*gcosang - s1.x*gsinang, s1.x*gcosang2 + s1.y*gsinang2 };
|
|
|
|
|
|
|
|
if ((p0.y < SCISDIST) && (p1.y < SCISDIST)) return;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Clip to close parallel-screen plane
|
2015-03-24 00:40:48 +00:00
|
|
|
vec2f_t const op0 = p0;
|
|
|
|
|
|
|
|
float t0 = 0.f;
|
|
|
|
|
|
|
|
if (p0.y < SCISDIST)
|
|
|
|
{
|
|
|
|
t0 = (SCISDIST - p0.y) / (p1.y - p0.y);
|
|
|
|
p0.x = (p1.x - p0.x) * t0 + p0.x;
|
|
|
|
p0.y = SCISDIST;
|
|
|
|
}
|
|
|
|
|
|
|
|
float t1 = 1.f;
|
|
|
|
|
|
|
|
if (p1.y < SCISDIST)
|
|
|
|
{
|
|
|
|
t1 = (SCISDIST - op0.y) / (p1.y - op0.y);
|
|
|
|
p1.x = (p1.x - op0.x) * t1 + op0.x;
|
|
|
|
p1.y = SCISDIST;
|
|
|
|
}
|
|
|
|
|
2017-10-31 00:35:23 +00:00
|
|
|
int32_t m0 = (int32_t)((wal2->x - wal->x) * t0 + wal->x);
|
|
|
|
int32_t m1 = (int32_t)((wal2->y - wal->y) * t0 + wal->y);
|
2015-03-24 00:40:48 +00:00
|
|
|
int32_t cz[4], fz[4];
|
|
|
|
getzsofslope(sectnum, m0, m1, &cz[0], &fz[0]);
|
|
|
|
getzsofslope(wal->nextsector, m0, m1, &cz[1], &fz[1]);
|
2017-10-31 00:35:23 +00:00
|
|
|
m0 = (int32_t)((wal2->x - wal->x) * t1 + wal->x);
|
|
|
|
m1 = (int32_t)((wal2->y - wal->y) * t1 + wal->y);
|
2015-03-24 00:40:48 +00:00
|
|
|
getzsofslope(sectnum, m0, m1, &cz[2], &fz[2]);
|
|
|
|
getzsofslope(wal->nextsector, m0, m1, &cz[3], &fz[3]);
|
|
|
|
|
|
|
|
float ryp0 = 1.f/p0.y;
|
|
|
|
float ryp1 = 1.f/p1.y;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Generate screen coordinates for front side of wall
|
2015-03-24 00:40:48 +00:00
|
|
|
float const x0 = ghalfx*p0.x*ryp0 + ghalfx;
|
|
|
|
float const x1 = ghalfx*p1.x*ryp1 + ghalfx;
|
2006-04-24 19:04:22 +00:00
|
|
|
if (x1 <= x0) return;
|
|
|
|
|
|
|
|
ryp0 *= gyxscale; ryp1 *= gyxscale;
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
xtex.d = (ryp0-ryp1)*gxyaspect / (x0-x1);
|
|
|
|
ytex.d = 0;
|
|
|
|
otex.d = ryp0*gxyaspect - xtex.d*x0;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//gux*x0 + guo = t0*wal->xrepeat*8*yp0
|
|
|
|
//gux*x1 + guo = t1*wal->xrepeat*8*yp1
|
2015-03-24 00:40:33 +00:00
|
|
|
xtex.u = (t0*ryp0 - t1*ryp1)*gxyaspect*(float)wal->xrepeat*8.f / (x0-x1);
|
|
|
|
otex.u = t0*ryp0*gxyaspect*(float)wal->xrepeat*8.f - xtex.u*x0;
|
|
|
|
otex.u += (float)wal->xpanning*otex.d;
|
|
|
|
xtex.u += (float)wal->xpanning*xtex.d;
|
|
|
|
ytex.u = 0;
|
2012-07-08 21:47:14 +00:00
|
|
|
|
2012-07-09 19:00:14 +00:00
|
|
|
// mask
|
2015-03-24 00:40:48 +00:00
|
|
|
calc_ypanning((!(wal->cstat & 4)) ? max(nsec->ceilingz, sec->ceilingz) : min(nsec->floorz, sec->floorz), ryp0, ryp1,
|
|
|
|
x0, x1, wal->ypanning, wal->yrepeat, 0);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
if (wal->cstat&8) //xflip
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
float const t = (float)(wal->xrepeat*8 + wal->xpanning*2);
|
2015-03-24 00:40:33 +00:00
|
|
|
xtex.u = xtex.d*t - xtex.u;
|
|
|
|
ytex.u = ytex.d*t - ytex.u;
|
|
|
|
otex.u = otex.d*t - otex.u;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
if (wal->cstat&256) { xtex.v = -xtex.v; ytex.v = -ytex.v; otex.v = -otex.v; } //yflip
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-12-04 11:52:54 +00:00
|
|
|
int method = DAMETH_MASK | DAMETH_WALL;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (wal->cstat & 128)
|
2016-12-04 22:53:56 +00:00
|
|
|
method = DAMETH_WALL | (((wal->cstat & 512)) ? DAMETH_TRANS2 : DAMETH_TRANS1);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2017-06-25 11:23:47 +00:00
|
|
|
#ifdef NEW_MAP_FORMAT
|
|
|
|
uint8_t const blend = wal->blend;
|
|
|
|
#else
|
2017-06-25 11:23:53 +00:00
|
|
|
uint8_t const blend = wallext[thewall[z]].blend;
|
2017-06-25 11:23:47 +00:00
|
|
|
#endif
|
|
|
|
handle_blend(!!(wal->cstat & 128), blend, !!(wal->cstat & 512));
|
|
|
|
|
|
|
|
drawpoly_alpha = 0.f;
|
|
|
|
drawpoly_blend = blend;
|
|
|
|
|
2017-12-12 05:14:06 +00:00
|
|
|
calc_and_apply_fog(wal->picnum, fogshade(wal->shade, wal->pal), sec->visibility, get_floor_fogpal(sec));
|
2015-03-24 00:40:48 +00:00
|
|
|
|
|
|
|
float const csy[4] = { ((float)(cz[0] - globalposz)) * ryp0 + ghoriz,
|
|
|
|
((float)(cz[1] - globalposz)) * ryp0 + ghoriz,
|
|
|
|
((float)(cz[2] - globalposz)) * ryp1 + ghoriz,
|
|
|
|
((float)(cz[3] - globalposz)) * ryp1 + ghoriz };
|
|
|
|
|
|
|
|
float const fsy[4] = { ((float)(fz[0] - globalposz)) * ryp0 + ghoriz,
|
|
|
|
((float)(fz[1] - globalposz)) * ryp0 + ghoriz,
|
|
|
|
((float)(fz[2] - globalposz)) * ryp1 + ghoriz,
|
|
|
|
((float)(fz[3] - globalposz)) * ryp1 + ghoriz };
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Clip 2 quadrilaterals
|
|
|
|
// /csy3
|
|
|
|
// / |
|
|
|
|
// csy0------/----csy2
|
|
|
|
// | /xxxxxxx|
|
|
|
|
// | /xxxxxxxxx|
|
|
|
|
// csy1/xxxxxxxxxxx|
|
|
|
|
// |xxxxxxxxxxx/fsy3
|
|
|
|
// |xxxxxxxxx/ |
|
|
|
|
// |xxxxxxx/ |
|
|
|
|
// fsy0----/------fsy2
|
|
|
|
// | /
|
|
|
|
// fsy1/
|
|
|
|
|
2019-03-19 17:08:43 +00:00
|
|
|
vec2f_t dpxy[8] = { { x0, csy[1] }, { x1, csy[3] }, { x1, fsy[3] }, { x0, fsy[1] } };
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//Clip to (x0,csy[0])-(x1,csy[2])
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-03-19 17:08:43 +00:00
|
|
|
vec2f_t dp2[8];
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
int n2 = 0;
|
2015-03-24 00:40:33 +00:00
|
|
|
t1 = -((dpxy[0].x - x0) * (csy[2] - csy[0]) - (dpxy[0].y - csy[0]) * (x1 - x0));
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<4; i++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
int j = i + 1;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (j >= 4)
|
2015-03-24 00:40:33 +00:00
|
|
|
j = 0;
|
|
|
|
|
|
|
|
t0 = t1;
|
|
|
|
t1 = -((dpxy[j].x - x0) * (csy[2] - csy[0]) - (dpxy[j].y - csy[0]) * (x1 - x0));
|
|
|
|
|
|
|
|
if (t0 >= 0)
|
|
|
|
dp2[n2++] = dpxy[i];
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2017-11-02 04:25:59 +00:00
|
|
|
if ((t0 >= 0) != (t1 >= 0) && (t0 <= 0) != (t1 <= 0))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
float const r = t0 / (t0 - t1);
|
2015-03-24 00:40:33 +00:00
|
|
|
dp2[n2].x = (dpxy[j].x - dpxy[i].x) * r + dpxy[i].x;
|
|
|
|
dp2[n2].y = (dpxy[j].y - dpxy[i].y) * r + dpxy[i].y;
|
2006-04-24 19:04:22 +00:00
|
|
|
n2++;
|
|
|
|
}
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if (n2 < 3)
|
|
|
|
return;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//Clip to (x1,fsy[2])-(x0,fsy[0])
|
2015-03-24 00:40:33 +00:00
|
|
|
t1 = -((dp2[0].x - x1) * (fsy[0] - fsy[2]) - (dp2[0].y - fsy[2]) * (x0 - x1));
|
2015-10-20 07:15:15 +00:00
|
|
|
int n = 0;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i = 0, j = 1; i < n2; j = ++i + 1)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (j >= n2)
|
|
|
|
j = 0;
|
|
|
|
|
|
|
|
t0 = t1;
|
|
|
|
t1 = -((dp2[j].x - x1) * (fsy[0] - fsy[2]) - (dp2[j].y - fsy[2]) * (x0 - x1));
|
|
|
|
|
|
|
|
if (t0 >= 0)
|
|
|
|
dpxy[n++] = dp2[i];
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2017-11-02 04:25:59 +00:00
|
|
|
if ((t0 >= 0) != (t1 >= 0) && (t0 <= 0) != (t1 <= 0))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
float const r = t0 / (t0 - t1);
|
2015-03-24 00:40:33 +00:00
|
|
|
dpxy[n].x = (dp2[j].x - dp2[i].x) * r + dp2[i].x;
|
|
|
|
dpxy[n].y = (dp2[j].y - dp2[i].y) * r + dp2[i].y;
|
2006-04-24 19:04:22 +00:00
|
|
|
n++;
|
|
|
|
}
|
|
|
|
}
|
2015-03-24 00:40:48 +00:00
|
|
|
|
|
|
|
if (n < 3)
|
|
|
|
return;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2013-03-04 01:23:29 +00:00
|
|
|
pow2xsplit = 0;
|
|
|
|
skyclamphack = 0;
|
2017-06-25 11:23:47 +00:00
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
polymost_updaterotmat();
|
2015-07-08 03:34:20 +00:00
|
|
|
polymost_drawpoly(dpxy, n, method);
|
2019-03-19 17:08:39 +00:00
|
|
|
polymost_identityrotmat();
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2015-01-11 04:56:58 +00:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
uint32_t wrev;
|
|
|
|
uint32_t srev;
|
|
|
|
int16_t wall;
|
|
|
|
int8_t wdist;
|
|
|
|
int8_t filler;
|
|
|
|
} wallspriteinfo_t;
|
|
|
|
|
|
|
|
wallspriteinfo_t wsprinfo[MAXSPRITES];
|
|
|
|
|
2016-10-24 21:30:34 +00:00
|
|
|
void Polymost_prepare_loadboard(void)
|
|
|
|
{
|
|
|
|
Bmemset(wsprinfo, 0, sizeof(wsprinfo));
|
|
|
|
}
|
|
|
|
|
2016-06-21 00:33:58 +00:00
|
|
|
static inline int32_t polymost_findwall(uspritetype const * const tspr, vec2_t const * const tsiz, int32_t * rd)
|
2015-01-11 04:56:58 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t dist = 4, closest = -1;
|
2016-06-21 00:33:58 +00:00
|
|
|
usectortype const * const sect = (usectortype * )§or[tspr->sectnum];
|
2015-01-11 04:56:58 +00:00
|
|
|
vec2_t n;
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=sect->wallptr; i<sect->wallptr + sect->wallnum; i++)
|
2015-01-11 04:56:58 +00:00
|
|
|
{
|
2016-05-13 22:15:28 +00:00
|
|
|
if ((wall[i].nextsector == -1 || ((sector[wall[i].nextsector].ceilingz > (tspr->z - ((tsiz->y * tspr->yrepeat) << 2))) ||
|
|
|
|
sector[wall[i].nextsector].floorz < tspr->z)) && !polymost_getclosestpointonwall((const vec2_t *) tspr, i, &n))
|
2015-01-11 04:56:58 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
int const dst = klabs(tspr->x - n.x) + klabs(tspr->y - n.y);
|
2015-01-11 04:56:58 +00:00
|
|
|
|
|
|
|
if (dst <= dist)
|
|
|
|
{
|
|
|
|
dist = dst;
|
|
|
|
closest = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*rd = dist;
|
2015-10-20 07:15:15 +00:00
|
|
|
|
2015-01-11 04:56:58 +00:00
|
|
|
return closest;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t polymost_lintersect(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
|
|
|
|
int32_t x3, int32_t y3, int32_t x4, int32_t y4)
|
|
|
|
{
|
|
|
|
// p1 to p2 is a line segment
|
|
|
|
int32_t const x21 = x2 - x1, x34 = x3 - x4;
|
|
|
|
int32_t const y21 = y2 - y1, y34 = y3 - y4;
|
|
|
|
int32_t const bot = x21 * y34 - y21 * x34;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if (!bot)
|
|
|
|
return 0;
|
|
|
|
|
2015-01-11 04:56:58 +00:00
|
|
|
int32_t const x31 = x3 - x1, y31 = y3 - y1;
|
|
|
|
int32_t const topt = x31 * y34 - y31 * x34;
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int rv = 1;
|
|
|
|
|
|
|
|
if (bot > 0)
|
2015-01-11 04:56:58 +00:00
|
|
|
{
|
|
|
|
if ((unsigned)topt >= (unsigned)bot)
|
2015-03-24 00:40:33 +00:00
|
|
|
rv = 0;
|
2015-01-11 04:56:58 +00:00
|
|
|
|
|
|
|
int32_t topu = x21 * y31 - y21 * x31;
|
|
|
|
|
|
|
|
if ((unsigned)topu >= (unsigned)bot)
|
2015-03-24 00:40:33 +00:00
|
|
|
rv = 0;
|
2015-01-11 04:56:58 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((unsigned)topt <= (unsigned)bot)
|
2015-03-24 00:40:33 +00:00
|
|
|
rv = 0;
|
2015-01-11 04:56:58 +00:00
|
|
|
|
|
|
|
int32_t topu = x21 * y31 - y21 * x31;
|
|
|
|
|
|
|
|
if ((unsigned)topu <= (unsigned)bot)
|
2015-03-24 00:40:33 +00:00
|
|
|
rv = 0;
|
2015-01-11 04:56:58 +00:00
|
|
|
}
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
return rv;
|
2015-01-11 04:56:58 +00:00
|
|
|
}
|
|
|
|
|
2017-06-09 06:41:45 +00:00
|
|
|
#define TSPR_OFFSET_FACTOR .000008f
|
2017-08-27 10:20:35 +00:00
|
|
|
#define TSPR_OFFSET(tspr) ((TSPR_OFFSET_FACTOR + ((tspr->owner != -1 ? tspr->owner & 63 : 1) * TSPR_OFFSET_FACTOR)) * (float)sepdist(globalposx - tspr->x, globalposy - tspr->y, globalposz - tspr->z) * 0.025f)
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2018-02-16 06:38:34 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
void polymost_drawsprite(int32_t snum)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2016-06-21 00:33:58 +00:00
|
|
|
uspritetype *const tspr = tspriteptr[snum];
|
2014-05-01 22:02:21 +00:00
|
|
|
|
2014-10-25 03:36:34 +00:00
|
|
|
if (EDUKE32_PREDICT_FALSE(bad_tspr(tspr)))
|
2013-04-29 19:24:19 +00:00
|
|
|
return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-06-21 00:33:58 +00:00
|
|
|
const usectortype *sec;
|
2013-03-19 06:23:38 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t spritenum = tspr->owner;
|
2013-03-19 06:23:38 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
DO_TILE_ANIM(tspr->picnum, spritenum + 32768);
|
|
|
|
|
|
|
|
globalpicnum = tspr->picnum;
|
|
|
|
globalshade = tspr->shade;
|
|
|
|
globalpal = tspr->pal;
|
2006-04-24 19:04:22 +00:00
|
|
|
globalorientation = tspr->cstat;
|
2013-05-15 02:19:14 +00:00
|
|
|
globvis = globalvisibility;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if (sector[tspr->sectnum].visibility != 0)
|
|
|
|
globvis = mulscale4(globvis, (uint8_t)(sector[tspr->sectnum].visibility + 16));
|
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis2 = globalvisibility2;
|
|
|
|
if (sector[tspr->sectnum].visibility != 0)
|
|
|
|
globvis2 = mulscale4(globvis2, (uint8_t)(sector[tspr->sectnum].visibility + 16));
|
|
|
|
polymost_setVisibility(globvis2);
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
vec2_t off = { 0, 0 };
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if ((globalorientation & 48) != 48) // only non-voxel sprites should do this
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
int const flag = usehightile && h_xsize[globalpicnum];
|
2016-02-02 00:21:27 +00:00
|
|
|
off.x = (int32_t)tspr->xoffset + (flag ? h_xoffs[globalpicnum] : picanm[globalpicnum].xofs);
|
|
|
|
off.y = (int32_t)tspr->yoffset + (flag ? h_yoffs[globalpicnum] : picanm[globalpicnum].yofs);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-12-04 11:52:54 +00:00
|
|
|
int32_t method = DAMETH_MASK | DAMETH_CLAMPED;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if (tspr->cstat & 2)
|
2016-05-13 22:15:28 +00:00
|
|
|
method = DAMETH_CLAMPED | ((tspr->cstat & 512) ? DAMETH_TRANS2 : DAMETH_TRANS1);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2016-10-09 07:55:23 +00:00
|
|
|
handle_blend(!!(tspr->cstat & 2), tspr->blend, !!(tspr->cstat & 512));
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
drawpoly_alpha = spriteext[spritenum].alpha;
|
2016-10-09 07:55:23 +00:00
|
|
|
drawpoly_blend = tspr->blend;
|
2013-03-04 01:23:29 +00:00
|
|
|
|
2016-06-21 00:33:58 +00:00
|
|
|
sec = (usectortype *)§or[tspr->sectnum];
|
2015-03-24 00:40:48 +00:00
|
|
|
|
2017-12-12 05:14:06 +00:00
|
|
|
calc_and_apply_fog(tspr->picnum, fogshade(globalshade, globalpal), sec->visibility, get_floor_fogpal(sec));
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
while (!(spriteext[spritenum].flags & SPREXT_NOTMD))
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (usemodels && tile2model[Ptile2tile(tspr->picnum, tspr->pal)].modelid >= 0 &&
|
|
|
|
tile2model[Ptile2tile(tspr->picnum, tspr->pal)].framenum >= 0)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2016-05-13 22:15:28 +00:00
|
|
|
if (polymost_mddraw(tspr)) return;
|
2015-03-24 00:40:33 +00:00
|
|
|
break; // else, render as flat sprite
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2012-10-01 17:52:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (usevoxels && (tspr->cstat & 48) != 48 && tiletovox[tspr->picnum] >= 0 && voxmodels[tiletovox[tspr->picnum]])
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2016-05-13 22:15:28 +00:00
|
|
|
if (polymost_voxdraw(voxmodels[tiletovox[tspr->picnum]], tspr)) return;
|
2015-03-24 00:40:33 +00:00
|
|
|
break; // else, render as flat sprite
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2012-10-01 17:52:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if ((tspr->cstat & 48) == 48 && voxmodels[tspr->picnum])
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2014-09-30 04:18:43 +00:00
|
|
|
polymost_voxdraw(voxmodels[tspr->picnum], tspr);
|
2006-04-24 19:04:22 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-03-24 00:40:48 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-10-01 17:52:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2_t pos = *(vec2_t *)tspr;
|
|
|
|
|
|
|
|
if (spriteext[spritenum].flags & SPREXT_AWAY1)
|
2007-12-20 19:14:38 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
pos.x += (sintable[(tspr->ang + 512) & 2047] >> 13);
|
|
|
|
pos.y += (sintable[(tspr->ang) & 2047] >> 13);
|
2007-12-20 19:14:38 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
else if (spriteext[spritenum].flags & SPREXT_AWAY2)
|
2007-12-28 20:04:58 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
pos.x -= (sintable[(tspr->ang + 512) & 2047] >> 13);
|
|
|
|
pos.y -= (sintable[(tspr->ang) & 2047] >> 13);
|
2007-12-28 20:04:58 +00:00
|
|
|
}
|
2012-10-01 17:52:22 +00:00
|
|
|
|
2017-06-24 09:21:13 +00:00
|
|
|
vec2s_t const oldsiz = tilesiz[globalpicnum];
|
|
|
|
vec2_t tsiz = { oldsiz.x, oldsiz.y };
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2011-06-18 13:02:08 +00:00
|
|
|
if (usehightile && h_xsize[globalpicnum])
|
2008-03-27 21:32:23 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
tsiz.x = h_xsize[globalpicnum];
|
|
|
|
tsiz.y = h_ysize[globalpicnum];
|
2008-03-27 21:32:23 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (tsiz.x <= 0 || tsiz.y <= 0)
|
2012-06-13 23:13:36 +00:00
|
|
|
return;
|
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
polymost_updaterotmat();
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
vec2f_t const ftsiz = { (float) tsiz.x, (float) tsiz.y };
|
2014-10-25 03:26:31 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
switch ((globalorientation >> 4) & 3)
|
|
|
|
{
|
|
|
|
case 0: // Face sprite
|
2014-10-25 03:26:31 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
// Project 3D to 2D
|
|
|
|
if (globalorientation & 4)
|
2015-03-24 00:40:48 +00:00
|
|
|
off.x = -off.x;
|
2015-03-24 00:40:33 +00:00
|
|
|
// NOTE: yoff not negated not for y flipping, unlike wall and floor
|
|
|
|
// aligned sprites.
|
2008-01-03 21:54:58 +00:00
|
|
|
|
2015-10-20 07:15:28 +00:00
|
|
|
int const ang = (getangle(tspr->x - globalposx, tspr->y - globalposy) + 1024) & 2047;
|
|
|
|
|
2015-10-21 19:53:57 +00:00
|
|
|
float const foffs = TSPR_OFFSET(tspr);
|
2015-10-20 07:15:28 +00:00
|
|
|
|
2017-02-05 20:58:33 +00:00
|
|
|
vec2f_t const offs = { (float) (sintable[(ang + 512) & 2047] >> 6) * foffs,
|
2015-10-20 07:15:28 +00:00
|
|
|
(float) (sintable[(ang) & 2047] >> 6) * foffs };
|
|
|
|
|
|
|
|
vec2f_t s0 = { (float)(tspr->x - globalposx) + offs.x,
|
2018-02-16 06:38:21 +00:00
|
|
|
(float)(tspr->y - globalposy) + offs.y};
|
2015-10-20 07:15:28 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2f_t p0 = { s0.y * gcosang - s0.x * gsinang, s0.x * gcosang2 + s0.y * gsinang2 };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (p0.y <= SCISDIST)
|
2019-03-19 17:08:39 +00:00
|
|
|
goto _drawsprite_return;
|
2008-01-03 21:54:58 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float const ryp0 = 1.f / p0.y;
|
|
|
|
s0.x = ghalfx * p0.x * ryp0 + ghalfx;
|
|
|
|
s0.y = ((float) (tspr->z - globalposz)) * gyxscale * ryp0 + ghoriz;
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
float const f = ryp0 * fxdimen * (1.0f / 160.f);
|
|
|
|
|
|
|
|
vec2f_t ff = { ((float)tspr->xrepeat) * f,
|
|
|
|
((float)tspr->yrepeat) * f * ((float)yxaspect * (1.0f / 65536.f)) };
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (tsiz.x & 1)
|
2015-03-24 00:40:48 +00:00
|
|
|
s0.x += ff.x * 0.5f;
|
2017-06-23 09:17:12 +00:00
|
|
|
if (globalorientation & 128 && tsiz.y & 1)
|
|
|
|
s0.y += ff.y * 0.5f;
|
2015-03-24 00:40:48 +00:00
|
|
|
|
|
|
|
s0.x -= ff.x * (float) off.x;
|
|
|
|
s0.y -= ff.y * (float) off.y;
|
|
|
|
|
|
|
|
ff.x *= ftsiz.x;
|
|
|
|
ff.y *= ftsiz.y;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vec2f_t pxy[4];
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
pxy[0].x = pxy[3].x = s0.x - ff.x * 0.5f;
|
|
|
|
pxy[1].x = pxy[2].x = s0.x + ff.x * 0.5f;
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!(globalorientation & 128))
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
pxy[0].y = pxy[1].y = s0.y - ff.y;
|
2015-03-24 00:40:33 +00:00
|
|
|
pxy[2].y = pxy[3].y = s0.y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
pxy[0].y = pxy[1].y = s0.y - ff.y * 0.5f;
|
|
|
|
pxy[2].y = pxy[3].y = s0.y + ff.y * 0.5f;
|
2015-03-24 00:40:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
xtex.d = ytex.d = ytex.u = xtex.v = 0;
|
|
|
|
otex.d = ryp0 * gviewxrange;
|
|
|
|
|
|
|
|
if (!(globalorientation & 4))
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
xtex.u = ftsiz.x * otex.d / (pxy[1].x - pxy[0].x + .002f);
|
2015-03-24 00:40:33 +00:00
|
|
|
otex.u = -xtex.u * (pxy[0].x - .001f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
xtex.u = ftsiz.x * otex.d / (pxy[0].x - pxy[1].x - .002f);
|
2015-03-24 00:40:33 +00:00
|
|
|
otex.u = -xtex.u * (pxy[1].x + .001f);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(globalorientation & 8))
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
ytex.v = ftsiz.y * otex.d / (pxy[3].y - pxy[0].y + .002f);
|
2015-03-24 00:40:33 +00:00
|
|
|
otex.v = -ytex.v * (pxy[0].y - .001f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
ytex.v = ftsiz.y * otex.d / (pxy[0].y - pxy[3].y - .002f);
|
2015-03-24 00:40:33 +00:00
|
|
|
otex.v = -ytex.v * (pxy[3].y + .001f);
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// sprite panning
|
|
|
|
if (spriteext[spritenum].xpanning)
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
ytex.u -= ytex.d * ((float) (spriteext[spritenum].xpanning) * (1.0f / 255.f)) * ftsiz.x;
|
|
|
|
otex.u -= otex.d * ((float) (spriteext[spritenum].xpanning) * (1.0f / 255.f)) * ftsiz.x;
|
2015-03-24 00:40:33 +00:00
|
|
|
drawpoly_srepeat = 1;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (spriteext[spritenum].ypanning)
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
ytex.v -= ytex.d * ((float) (spriteext[spritenum].ypanning) * (1.0f / 255.f)) * ftsiz.y;
|
|
|
|
otex.v -= otex.d * ((float) (spriteext[spritenum].ypanning) * (1.0f / 255.f)) * ftsiz.y;
|
2015-03-24 00:40:33 +00:00
|
|
|
drawpoly_trepeat = 1;
|
|
|
|
}
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// Clip sprites to ceilings/floors when no parallaxing and not sloped
|
|
|
|
if (!(sector[tspr->sectnum].ceilingstat & 3))
|
|
|
|
{
|
|
|
|
s0.y = ((float) (sector[tspr->sectnum].ceilingz - globalposz)) * gyxscale * ryp0 + ghoriz;
|
|
|
|
if (pxy[0].y < s0.y)
|
|
|
|
pxy[0].y = pxy[1].y = s0.y;
|
|
|
|
}
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!(sector[tspr->sectnum].floorstat & 3))
|
|
|
|
{
|
|
|
|
s0.y = ((float) (sector[tspr->sectnum].floorz - globalposz)) * gyxscale * ryp0 + ghoriz;
|
|
|
|
if (pxy[2].y > s0.y)
|
|
|
|
pxy[2].y = pxy[3].y = s0.y;
|
|
|
|
}
|
|
|
|
|
2017-06-24 09:21:13 +00:00
|
|
|
tilesiz[globalpicnum].x = tsiz.x;
|
|
|
|
tilesiz[globalpicnum].y = tsiz.y;
|
2015-03-24 00:40:33 +00:00
|
|
|
pow2xsplit = 0;
|
2015-07-08 03:34:20 +00:00
|
|
|
polymost_drawpoly(pxy, 4, method);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
drawpoly_srepeat = 0;
|
|
|
|
drawpoly_trepeat = 0;
|
|
|
|
}
|
2015-03-24 00:40:48 +00:00
|
|
|
break;
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
case 1: // Wall sprite
|
2015-01-11 04:56:58 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
// Project 3D to 2D
|
|
|
|
if (globalorientation & 4)
|
2015-03-24 00:40:48 +00:00
|
|
|
off.x = -off.x;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if (globalorientation & 8)
|
2015-03-24 00:40:48 +00:00
|
|
|
off.y = -off.y;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vec2f_t const extent = { (float)tspr->xrepeat * (float)sintable[(tspr->ang) & 2047] * (1.0f / 65536.f),
|
|
|
|
(float)tspr->xrepeat * (float)sintable[(tspr->ang + 1536) & 2047] * (1.0f / 65536.f) };
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
float f = (float)(tsiz.x >> 1) + (float)off.x;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vec2f_t const vf = { extent.x * f, extent.y * f };
|
2016-06-05 04:46:28 +00:00
|
|
|
|
|
|
|
vec2f_t vec0 = { (float)(pos.x - globalposx) - vf.x,
|
2015-03-24 00:40:33 +00:00
|
|
|
(float)(pos.y - globalposy) - vf.y };
|
2015-01-11 04:56:58 +00:00
|
|
|
|
|
|
|
int32_t const s = tspr->owner;
|
|
|
|
int32_t walldist = 1;
|
|
|
|
int32_t w = (s == -1) ? -1 : wsprinfo[s].wall;
|
|
|
|
|
|
|
|
// find the wall most likely to be what the sprite is supposed to be ornamented against
|
|
|
|
// this is really slow, so cache the result
|
|
|
|
if (s == -1 || !wsprinfo[s].wall || (spritechanged[s] != wsprinfo[s].srev) ||
|
|
|
|
(w != -1 && wallchanged[w] != wsprinfo[s].wrev))
|
|
|
|
{
|
2016-05-13 22:15:28 +00:00
|
|
|
w = polymost_findwall(tspr, &tsiz, &walldist);
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2016-06-21 00:32:47 +00:00
|
|
|
if (s != -1)
|
2015-01-11 04:56:58 +00:00
|
|
|
{
|
|
|
|
wallspriteinfo_t *ws = &wsprinfo[s];
|
|
|
|
ws->wall = w;
|
2016-06-21 00:32:47 +00:00
|
|
|
|
|
|
|
if (w != -1)
|
|
|
|
{
|
|
|
|
ws->wdist = walldist;
|
|
|
|
ws->wrev = wallchanged[w];
|
|
|
|
ws->srev = spritechanged[s];
|
|
|
|
}
|
2015-01-11 04:56:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (s != -1)
|
|
|
|
walldist = wsprinfo[s].wdist;
|
|
|
|
|
|
|
|
// detect if the sprite is either on the wall line or the wall line and sprite intersect
|
|
|
|
if (w != -1)
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2_t v = { /*Blrintf(vf.x)*/(int)vf.x, /*Blrintf(vf.y)*/(int)vf.y };
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2015-10-20 07:15:15 +00:00
|
|
|
if (walldist <= 2 || ((pos.x - v.x) + (pos.x + v.x)) == (wall[w].x + POINT2(w).x) ||
|
2015-03-24 00:40:33 +00:00
|
|
|
((pos.y - v.y) + (pos.y + v.y)) == (wall[w].y + POINT2(w).y) ||
|
|
|
|
polymost_lintersect(pos.x - v.x, pos.y - v.y, pos.x + v.x, pos.y + v.y, wall[w].x, wall[w].y,
|
|
|
|
POINT2(w).x, POINT2(w).y))
|
2015-01-11 04:56:58 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t const ang = getangle(wall[w].x - POINT2(w).x, wall[w].y - POINT2(w).y);
|
2015-10-21 19:53:57 +00:00
|
|
|
float const foffs = TSPR_OFFSET(tspr);
|
2015-10-20 07:15:15 +00:00
|
|
|
vec2f_t const offs = { (float)(sintable[(ang + 1024) & 2047] >> 6) * foffs,
|
|
|
|
(float)(sintable[(ang + 512) & 2047] >> 6) * foffs};
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
vec0.x -= offs.x;
|
|
|
|
vec0.y -= offs.y;
|
2015-01-11 04:56:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2f_t p0 = { vec0.y * gcosang - vec0.x * gsinang,
|
|
|
|
vec0.x * gcosang2 + vec0.y * gsinang2 };
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
vec2f_t const pp = { extent.x * ftsiz.x + vec0.x,
|
|
|
|
extent.y * ftsiz.x + vec0.y };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2f_t p1 = { pp.y * gcosang - pp.x * gsinang,
|
|
|
|
pp.x * gcosang2 + pp.y * gsinang2 };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if ((p0.y <= SCISDIST) && (p1.y <= SCISDIST))
|
2019-03-19 17:08:39 +00:00
|
|
|
goto _drawsprite_return;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// Clip to close parallel-screen plane
|
|
|
|
vec2f_t const op0 = p0;
|
2014-10-25 03:26:31 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float t0 = 0.f, t1 = 1.f;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (p0.y < SCISDIST)
|
|
|
|
{
|
|
|
|
t0 = (SCISDIST - p0.y) / (p1.y - p0.y);
|
|
|
|
p0.x = (p1.x - p0.x) * t0 + p0.x;
|
|
|
|
p0.y = SCISDIST;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (p1.y < SCISDIST)
|
|
|
|
{
|
|
|
|
t1 = (SCISDIST - op0.y) / (p1.y - op0.y);
|
|
|
|
p1.x = (p1.x - op0.x) * t1 + op0.x;
|
|
|
|
p1.y = SCISDIST;
|
|
|
|
}
|
2008-01-03 21:54:58 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
f = 1.f / p0.y;
|
|
|
|
const float ryp0 = f * gyxscale;
|
|
|
|
float sx0 = ghalfx * p0.x * f + ghalfx;
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
f = 1.f / p1.y;
|
|
|
|
const float ryp1 = f * gyxscale;
|
|
|
|
float sx1 = ghalfx * p1.x * f + ghalfx;
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
tspr->z -= ((off.y * tspr->yrepeat) << 2);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
if (globalorientation & 128)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
tspr->z += ((tsiz.y * tspr->yrepeat) << 1);
|
|
|
|
|
|
|
|
if (tsiz.y & 1)
|
|
|
|
tspr->z += (tspr->yrepeat << 1); // Odd yspans
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
xtex.d = (ryp0 - ryp1) * gxyaspect / (sx0 - sx1);
|
|
|
|
ytex.d = 0;
|
|
|
|
otex.d = ryp0 * gxyaspect - xtex.d * sx0;
|
|
|
|
|
|
|
|
if (globalorientation & 4)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
t0 = 1.f - t0;
|
|
|
|
t1 = 1.f - t1;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// sprite panning
|
|
|
|
if (spriteext[spritenum].xpanning)
|
|
|
|
{
|
|
|
|
float const xpan = ((float)(spriteext[spritenum].xpanning) * (1.0f / 255.f));
|
|
|
|
t0 -= xpan;
|
|
|
|
t1 -= xpan;
|
|
|
|
drawpoly_srepeat = 1;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
xtex.u = (t0 * ryp0 - t1 * ryp1) * gxyaspect * ftsiz.x / (sx0 - sx1);
|
2015-03-24 00:40:33 +00:00
|
|
|
ytex.u = 0;
|
2015-03-24 00:40:48 +00:00
|
|
|
otex.u = t0 * ryp0 * gxyaspect * ftsiz.x - xtex.u * sx0;
|
2008-01-03 21:54:58 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
f = ((float) tspr->yrepeat) * ftsiz.y * 4;
|
2008-01-03 21:54:58 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float sc0 = ((float) (tspr->z - globalposz - f)) * ryp0 + ghoriz;
|
|
|
|
float sc1 = ((float) (tspr->z - globalposz - f)) * ryp1 + ghoriz;
|
|
|
|
float sf0 = ((float) (tspr->z - globalposz)) * ryp0 + ghoriz;
|
|
|
|
float sf1 = ((float) (tspr->z - globalposz)) * ryp1 + ghoriz;
|
2008-01-03 21:54:58 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// gvx*sx0 + gvy*sc0 + gvo = 0
|
|
|
|
// gvx*sx1 + gvy*sc1 + gvo = 0
|
|
|
|
// gvx*sx0 + gvy*sf0 + gvo = tsizy*(gdx*sx0 + gdo)
|
2015-03-24 00:40:48 +00:00
|
|
|
f = ftsiz.y * (xtex.d * sx0 + otex.d) / ((sx0 - sx1) * (sc0 - sf0));
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (!(globalorientation & 8))
|
|
|
|
{
|
|
|
|
xtex.v = (sc0 - sc1) * f;
|
|
|
|
ytex.v = (sx1 - sx0) * f;
|
|
|
|
otex.v = -xtex.v * sx0 - ytex.v * sc0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xtex.v = (sf1 - sf0) * f;
|
|
|
|
ytex.v = (sx0 - sx1) * f;
|
|
|
|
otex.v = -xtex.v * sx0 - ytex.v * sf0;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// sprite panning
|
|
|
|
if (spriteext[spritenum].ypanning)
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
float const ypan = ((float)(spriteext[spritenum].ypanning) * (1.0f / 255.f)) * ftsiz.y;
|
2015-03-24 00:40:33 +00:00
|
|
|
xtex.v -= xtex.d * ypan;
|
|
|
|
ytex.v -= ytex.d * ypan;
|
|
|
|
otex.v -= otex.d * ypan;
|
|
|
|
drawpoly_trepeat = 1;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// Clip sprites to ceilings/floors when no parallaxing
|
|
|
|
if (!(sector[tspr->sectnum].ceilingstat & 1))
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
if (sector[tspr->sectnum].ceilingz > tspr->z - (float)((tspr->yrepeat * tsiz.y) << 2))
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
|
|
|
sc0 = (float)(sector[tspr->sectnum].ceilingz - globalposz) * ryp0 + ghoriz;
|
|
|
|
sc1 = (float)(sector[tspr->sectnum].ceilingz - globalposz) * ryp1 + ghoriz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!(sector[tspr->sectnum].floorstat & 1))
|
|
|
|
{
|
|
|
|
if (sector[tspr->sectnum].floorz < tspr->z)
|
|
|
|
{
|
|
|
|
sf0 = (float)(sector[tspr->sectnum].floorz - globalposz) * ryp0 + ghoriz;
|
|
|
|
sf1 = (float)(sector[tspr->sectnum].floorz - globalposz) * ryp1 + ghoriz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sx0 > sx1)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (globalorientation & 64)
|
2019-03-19 17:08:39 +00:00
|
|
|
goto _drawsprite_return; // 1-sided sprite
|
2015-03-24 00:40:48 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
swapfloat(&sx0, &sx1);
|
|
|
|
swapfloat(&sc0, &sc1);
|
|
|
|
swapfloat(&sf0, &sf1);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vec2f_t const pxy[4] = { { sx0, sc0 }, { sx1, sc1 }, { sx1, sf1 }, { sx0, sf0 } };
|
|
|
|
|
2017-06-24 09:21:13 +00:00
|
|
|
tilesiz[globalpicnum].x = tsiz.x;
|
|
|
|
tilesiz[globalpicnum].y = tsiz.y;
|
2015-03-24 00:40:33 +00:00
|
|
|
pow2xsplit = 0;
|
2015-07-08 03:34:20 +00:00
|
|
|
polymost_drawpoly(pxy, 4, method);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
drawpoly_srepeat = 0;
|
|
|
|
drawpoly_trepeat = 0;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
break;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
case 2: // Floor sprite
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis2 = globalhisibility2;
|
|
|
|
if (sector[tspr->sectnum].visibility != 0)
|
|
|
|
globvis2 = mulscale4(globvis2, (uint8_t)(sector[tspr->sectnum].visibility + 16));
|
|
|
|
polymost_setVisibility(globvis2);
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if ((globalorientation & 64) != 0 && (globalposz > tspr->z) == (!(globalorientation & 8)))
|
2019-03-19 17:08:39 +00:00
|
|
|
goto _drawsprite_return;
|
2015-03-24 00:40:33 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((globalorientation & 4) > 0)
|
2015-03-24 00:40:48 +00:00
|
|
|
off.x = -off.x;
|
2015-03-24 00:40:33 +00:00
|
|
|
if ((globalorientation & 8) > 0)
|
2015-03-24 00:40:48 +00:00
|
|
|
off.y = -off.y;
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2017-06-21 13:47:04 +00:00
|
|
|
vec2f_t const p0 = { (float)(((tsiz.x + 1) >> 1) - off.x) * tspr->xrepeat,
|
|
|
|
(float)(((tsiz.y + 1) >> 1) - off.y) * tspr->yrepeat },
|
2015-03-24 00:40:48 +00:00
|
|
|
p1 = { (float)((tsiz.x >> 1) + off.x) * tspr->xrepeat,
|
|
|
|
(float)((tsiz.y >> 1) + off.y) * tspr->yrepeat };
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float const c = sintable[(tspr->ang + 512) & 2047] * (1.0f / 65536.f);
|
|
|
|
float const s = sintable[tspr->ang & 2047] * (1.0f / 65536.f);
|
2015-01-11 04:56:58 +00:00
|
|
|
|
2016-05-13 22:15:28 +00:00
|
|
|
vec2f_t pxy[6];
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// Project 3D to 2D
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j = 0; j < 4; j++)
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
|
|
|
vec2f_t s0 = { (float)(tspr->x - globalposx), (float)(tspr->y - globalposy) };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if ((j + 0) & 2)
|
|
|
|
{
|
|
|
|
s0.y -= s * p0.y;
|
|
|
|
s0.x -= c * p0.y;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s0.y += s * p1.y;
|
|
|
|
s0.x += c * p1.y;
|
|
|
|
}
|
|
|
|
if ((j + 1) & 2)
|
|
|
|
{
|
|
|
|
s0.x -= s * p0.x;
|
|
|
|
s0.y += c * p0.x;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
s0.x += s * p1.x;
|
|
|
|
s0.y -= c * p1.x;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
pxy[j].x = s0.y * gcosang - s0.x * gsinang;
|
|
|
|
pxy[j].y = s0.x * gcosang2 + s0.y * gsinang2;
|
|
|
|
}
|
2014-10-25 03:26:31 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if (tspr->z < globalposz) // if floor sprite is above you, reverse order of points
|
|
|
|
{
|
|
|
|
EDUKE32_STATIC_ASSERT(sizeof(uint64_t) == sizeof(vec2f_t));
|
2008-01-03 21:54:58 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
swap64bit(&pxy[0], &pxy[1]);
|
|
|
|
swap64bit(&pxy[2], &pxy[3]);
|
|
|
|
}
|
2008-01-03 21:54:58 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
// Clip to SCISDIST plane
|
|
|
|
int32_t npoints = 0;
|
|
|
|
vec2f_t p2[6];
|
2008-01-03 21:54:58 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i = 0, j = 1; i < 4; j = ((++i + 1) & 3))
|
2015-03-24 00:40:33 +00:00
|
|
|
{
|
|
|
|
if (pxy[i].y >= SCISDIST)
|
|
|
|
p2[npoints++] = pxy[i];
|
|
|
|
|
|
|
|
if ((pxy[i].y >= SCISDIST) != (pxy[j].y >= SCISDIST))
|
|
|
|
{
|
|
|
|
float const f = (SCISDIST - pxy[i].y) / (pxy[j].y - pxy[i].y);
|
|
|
|
vec2f_t const t = { (pxy[j].x - pxy[i].x) * f + pxy[i].x,
|
|
|
|
(pxy[j].y - pxy[i].y) * f + pxy[i].y };
|
|
|
|
p2[npoints++] = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (npoints < 3)
|
2019-03-19 17:08:39 +00:00
|
|
|
goto _drawsprite_return;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
// Project rotated 3D points to screen
|
|
|
|
|
2015-10-23 23:00:10 +00:00
|
|
|
int fadjust = 0;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-10-23 23:00:10 +00:00
|
|
|
// unfortunately, offsetting by only 1 isn't enough on most Android devices
|
|
|
|
if (tspr->z == sec->ceilingz || tspr->z == sec->ceilingz + 1)
|
|
|
|
tspr->z = sec->ceilingz + 2, fadjust = (tspr->owner & 31);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-10-23 23:00:10 +00:00
|
|
|
if (tspr->z == sec->floorz || tspr->z == sec->floorz - 1)
|
|
|
|
tspr->z = sec->floorz - 2, fadjust = -((tspr->owner & 31));
|
|
|
|
|
|
|
|
float f = (float)(tspr->z - globalposz + fadjust) * gyxscale;
|
2015-04-18 21:59:20 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j = 0; j < npoints; j++)
|
2015-03-24 00:40:48 +00:00
|
|
|
{
|
2015-10-20 07:15:15 +00:00
|
|
|
float const ryp0 = 1.f / p2[j].y;
|
|
|
|
pxy[j].x = ghalfx * p2[j].x * ryp0 + ghalfx;
|
|
|
|
pxy[j].y = f * ryp0 + ghoriz;
|
2015-03-24 00:40:48 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
// gd? Copied from floor rendering code
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
xtex.d = 0;
|
2015-10-23 23:00:10 +00:00
|
|
|
ytex.d = gxyaspect / (double)(tspr->z - globalposz + fadjust);
|
2015-03-24 00:40:48 +00:00
|
|
|
otex.d = -ghoriz * ytex.d;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
// copied&modified from relative alignment
|
|
|
|
vec2f_t const vv = { (float)tspr->x + s * p1.x + c * p1.y, (float)tspr->y + s * p1.y - c * p1.x };
|
|
|
|
vec2f_t ff = { -(p0.x + p1.x) * s, (p0.x + p1.x) * c };
|
|
|
|
|
2015-10-20 07:15:15 +00:00
|
|
|
f = polymost_invsqrt_approximation(ff.x * ff.x + ff.y * ff.y);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
ff.x *= f;
|
|
|
|
ff.y *= f;
|
|
|
|
|
|
|
|
float const ft[4] = { ((float)(globalposy - vv.y)) * ff.y + ((float)(globalposx - vv.x)) * ff.x,
|
2015-03-24 00:40:48 +00:00
|
|
|
((float)(globalposx - vv.x)) * ff.y - ((float)(globalposy - vv.y)) * ff.x,
|
2018-03-07 12:02:03 +00:00
|
|
|
fsinglobalang * ff.y + fcosglobalang * ff.x,
|
|
|
|
fsinglobalang * ff.x - fcosglobalang * ff.y };
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
f = fviewingrange * -(1.f / (65536.f * 262144.f));
|
|
|
|
xtex.u = (float)ft[3] * f;
|
|
|
|
xtex.v = (float)ft[2] * f;
|
2015-03-24 00:40:33 +00:00
|
|
|
ytex.u = ft[0] * ytex.d;
|
|
|
|
ytex.v = ft[1] * ytex.d;
|
|
|
|
otex.u = ft[0] * otex.d;
|
|
|
|
otex.v = ft[1] * otex.d;
|
|
|
|
otex.u += (ft[2] * (1.0f / 262144.f) - xtex.u) * ghalfx;
|
|
|
|
otex.v -= (ft[3] * (1.0f / 262144.f) + xtex.v) * ghalfx;
|
|
|
|
|
|
|
|
f = 4.f / (float)tspr->xrepeat;
|
|
|
|
xtex.u *= f;
|
|
|
|
ytex.u *= f;
|
|
|
|
otex.u *= f;
|
|
|
|
|
|
|
|
f = -4.f / (float)tspr->yrepeat;
|
|
|
|
xtex.v *= f;
|
|
|
|
ytex.v *= f;
|
|
|
|
otex.v *= f;
|
|
|
|
|
|
|
|
if (globalorientation & 4)
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
xtex.u = ftsiz.x * xtex.d - xtex.u;
|
|
|
|
ytex.u = ftsiz.x * ytex.d - ytex.u;
|
|
|
|
otex.u = ftsiz.x * otex.d - otex.u;
|
2015-03-24 00:40:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// sprite panning
|
|
|
|
if (spriteext[spritenum].xpanning)
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
float const f = ((float)(spriteext[spritenum].xpanning) * (1.0f / 255.f)) * ftsiz.x;
|
|
|
|
ytex.u -= ytex.d * f;
|
|
|
|
otex.u -= otex.d * f;
|
2015-03-24 00:40:33 +00:00
|
|
|
drawpoly_srepeat = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spriteext[spritenum].ypanning)
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
float const f = ((float)(spriteext[spritenum].ypanning) * (1.0f / 255.f)) * ftsiz.y;
|
|
|
|
ytex.v -= ytex.d * f;
|
|
|
|
otex.v -= otex.d * f;
|
2015-03-24 00:40:33 +00:00
|
|
|
drawpoly_trepeat = 1;
|
|
|
|
}
|
|
|
|
|
2017-06-24 09:21:13 +00:00
|
|
|
tilesiz[globalpicnum].x = tsiz.x;
|
|
|
|
tilesiz[globalpicnum].y = tsiz.y;
|
2015-03-24 00:40:33 +00:00
|
|
|
pow2xsplit = 0;
|
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
polymost_drawpoly(pxy, npoints, method);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
drawpoly_srepeat = 0;
|
|
|
|
drawpoly_trepeat = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3: // Voxel sprite
|
|
|
|
break;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2019-03-19 17:08:39 +00:00
|
|
|
_drawsprite_return:
|
|
|
|
polymost_identityrotmat();
|
2015-03-24 00:40:33 +00:00
|
|
|
tilesiz[globalpicnum] = oldsiz;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
EDUKE32_STATIC_ASSERT((int)RS_YFLIP == (int)HUDFLAG_FLIPPED);
|
|
|
|
|
2012-08-16 21:48:44 +00:00
|
|
|
//sx,sy center of sprite; screen coords*65536
|
2006-04-24 19:04:22 +00:00
|
|
|
//z zoom*65536. > is zoomed in
|
|
|
|
//a angle (0 is default)
|
|
|
|
//dastat&1 1:translucence
|
|
|
|
//dastat&2 1:auto-scale mode (use 320*200 coordinates)
|
|
|
|
//dastat&4 1:y-flip
|
|
|
|
//dastat&8 1:don't clip to startumost/startdmost
|
|
|
|
//dastat&16 1:force point passed to be top-left corner, 0:Editart center
|
|
|
|
//dastat&32 1:reverse translucence
|
|
|
|
//dastat&64 1:non-masked, 0:masked
|
|
|
|
//dastat&128 1:draw all pages (permanent)
|
|
|
|
//cx1,... clip window (actual screen coords)
|
2014-09-30 04:14:21 +00:00
|
|
|
|
|
|
|
void polymost_dorotatespritemodel(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
|
2016-10-09 07:55:23 +00:00
|
|
|
int8_t dashade, char dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int32_t uniqid)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2014-09-30 04:14:21 +00:00
|
|
|
float d, cosang, sinang, cosang2, sinang2;
|
2006-04-24 19:04:22 +00:00
|
|
|
float m[4][4];
|
2012-08-16 21:48:41 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
const int32_t tilenum = Ptile2tile(picnum, dapalnum);
|
2012-08-16 21:48:44 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (tile2model[tilenum].modelid == -1 || tile2model[tilenum].framenum == -1)
|
|
|
|
return;
|
2012-08-19 12:49:37 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
vec3f_t vec1;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2016-06-21 00:33:58 +00:00
|
|
|
uspritetype tspr;
|
2015-03-24 00:40:48 +00:00
|
|
|
Bmemset(&tspr, 0, sizeof(spritetype));
|
|
|
|
|
|
|
|
hudtyp const * const hud = tile2model[tilenum].hudmem[(dastat&4)>>2];
|
|
|
|
|
|
|
|
if (!hud || hud->flags & HUDFLAG_HIDE)
|
|
|
|
return;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
float const ogchang = gchang; gchang = 1.f;
|
|
|
|
float const ogshang = gshang; gshang = 0.f; d = (float) z*(1.0f/(65536.f*16384.f));
|
|
|
|
float const ogctang = gctang; gctang = (float) sintable[(a+512)&2047]*d;
|
|
|
|
float const ogstang = gstang; gstang = (float) sintable[a&2047]*d;
|
|
|
|
int const ogshade = globalshade; globalshade = dashade;
|
|
|
|
int const ogpal = globalpal; globalpal = (int32_t) ((uint8_t) dapalnum);
|
2019-03-19 17:08:05 +00:00
|
|
|
double const ogxyaspect = gxyaspect; gxyaspect = 1.f;
|
2015-07-08 03:34:20 +00:00
|
|
|
int const oldviewingrange = viewingrange; viewingrange = 65536;
|
2016-10-03 02:43:42 +00:00
|
|
|
float const oldfviewingrange = fviewingrange; fviewingrange = 65536.f;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
polymost_updaterotmat();
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
vec1 = hud->add;
|
2013-11-22 19:26:44 +00:00
|
|
|
|
2011-03-01 05:52:33 +00:00
|
|
|
#ifdef POLYMER
|
2015-03-24 00:40:48 +00:00
|
|
|
if (pr_overridehud) {
|
|
|
|
vec1.x = pr_hudxadd;
|
|
|
|
vec1.y = pr_hudyadd;
|
|
|
|
vec1.z = pr_hudzadd;
|
|
|
|
}
|
2011-03-01 05:52:33 +00:00
|
|
|
#endif
|
2015-03-24 00:40:48 +00:00
|
|
|
if (!(hud->flags & HUDFLAG_NOBOB))
|
|
|
|
{
|
|
|
|
vec2f_t f = { (float)sx * (1.f / 65536.f), (float)sy * (1.f / 65536.f) };
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (dastat & RS_TOPLEFT)
|
|
|
|
{
|
2017-06-24 09:21:13 +00:00
|
|
|
vec2s_t siz = tilesiz[picnum];
|
|
|
|
vec2s_t off = { (int16_t)((siz.x >> 1) + picanm[picnum].xofs), (int16_t)((siz.y >> 1) + picanm[picnum].yofs) };
|
2015-07-08 03:34:20 +00:00
|
|
|
|
|
|
|
d = (float)z * (1.0f / (65536.f * 16384.f));
|
|
|
|
cosang2 = cosang = (float)sintable[(a + 512) & 2047] * d;
|
|
|
|
sinang2 = sinang = (float)sintable[a & 2047] * d;
|
|
|
|
|
|
|
|
if ((dastat & RS_AUTO) || (!(dastat & RS_NOCLIP))) // Don't aspect unscaled perms
|
2015-03-24 00:40:48 +00:00
|
|
|
{
|
2015-07-08 03:34:20 +00:00
|
|
|
d = (float)xyaspect * (1.0f / 65536.f);
|
|
|
|
cosang2 *= d;
|
|
|
|
sinang2 *= d;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-07-08 03:34:20 +00:00
|
|
|
|
2017-06-24 09:21:13 +00:00
|
|
|
vec2f_t const foff = { (float)off.x, (float)off.y };
|
|
|
|
f.x += -foff.x * cosang2 + foff.y * sinang2;
|
|
|
|
f.y += -foff.x * sinang - foff.y * cosang;
|
2015-03-24 00:40:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!(dastat & RS_AUTO))
|
|
|
|
{
|
|
|
|
vec1.x += f.x / ((float)(xdim << 15)) - 1.f; //-1: left of screen, +1: right of screen
|
|
|
|
vec1.y += f.y / ((float)(ydim << 15)) - 1.f; //-1: top of screen, +1: bottom of screen
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vec1.x += f.x * (1.0f / 160.f) - 1.f; //-1: left of screen, +1: right of screen
|
|
|
|
vec1.y += f.y * (1.0f / 100.f) - 1.f; //-1: top of screen, +1: bottom of screen
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tspr.ang = hud->angadd+globalang;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2011-03-01 05:52:33 +00:00
|
|
|
#ifdef POLYMER
|
2015-03-24 00:40:48 +00:00
|
|
|
if (pr_overridehud) {
|
|
|
|
tspr.ang = pr_hudangadd + globalang;
|
|
|
|
}
|
2011-03-01 05:52:33 +00:00
|
|
|
#endif
|
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (dastat & RS_YFLIP) { vec1.x = -vec1.x; vec1.y = -vec1.y; }
|
2011-01-16 02:50:27 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
// In Polymost, we don't care if the model is very big
|
2015-03-24 00:40:33 +00:00
|
|
|
#ifdef POLYMER
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMER)
|
2015-03-24 00:40:48 +00:00
|
|
|
{
|
|
|
|
vec3f_t const vec2 = { fglobalposx + (gcosang * vec1.z - gsinang * vec1.x) * 2560.f,
|
|
|
|
fglobalposy + (gsinang * vec1.z + gcosang * vec1.x) * 2560.f,
|
|
|
|
fglobalposz + (vec1.y * (2560.f * 0.8f)) };
|
|
|
|
*(vec3f_t *)&tspr = vec2;
|
|
|
|
tspr.xrepeat = tspr.yrepeat = 5;
|
|
|
|
}
|
|
|
|
else
|
2015-03-24 00:40:33 +00:00
|
|
|
#endif
|
2015-03-24 00:40:48 +00:00
|
|
|
{
|
|
|
|
tspr.xrepeat = tspr.yrepeat = 32;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
tspr.x = globalposx + Blrintf((gcosang*vec1.z - gsinang*vec1.x)*16384.f);
|
|
|
|
tspr.y = globalposy + Blrintf((gsinang*vec1.z + gcosang*vec1.x)*16384.f);
|
|
|
|
tspr.z = globalposz + Blrintf(vec1.y * (16384.f * 0.8f));
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
tspr.picnum = picnum;
|
|
|
|
tspr.shade = dashade;
|
|
|
|
tspr.pal = dapalnum;
|
|
|
|
tspr.owner = uniqid+MAXSPRITES;
|
|
|
|
// 1 -> 1
|
|
|
|
// 32 -> 32*16 = 512
|
|
|
|
// 4 -> 8
|
|
|
|
tspr.cstat = globalorientation = (dastat&RS_TRANS1) | ((dastat&RS_TRANS2)<<4) | ((dastat&RS_YFLIP)<<1);
|
|
|
|
|
|
|
|
if ((dastat&(RS_AUTO|RS_NOCLIP)) == RS_AUTO)
|
2018-07-14 21:36:44 +00:00
|
|
|
glViewport(windowxy1.x, ydim-(windowxy2.y+1), windowxy2.x-windowxy1.x+1, windowxy2.y-windowxy1.y+1);
|
2015-03-24 00:40:48 +00:00
|
|
|
else
|
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glViewport(0, 0, xdim, ydim);
|
2015-03-24 00:40:48 +00:00
|
|
|
glox1 = -1; //Force fullscreen (glox1=-1 forces it to restore)
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() < REND_POLYMER)
|
2015-03-24 00:40:48 +00:00
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glMatrixMode(GL_PROJECTION);
|
2015-03-24 00:40:48 +00:00
|
|
|
Bmemset(m, 0, sizeof(m));
|
2014-09-30 04:18:43 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if ((dastat&(RS_AUTO|RS_NOCLIP)) == RS_AUTO)
|
|
|
|
{
|
|
|
|
float f = 1.f;
|
|
|
|
int32_t fov = hud->fov;
|
2013-11-22 19:26:46 +00:00
|
|
|
#ifdef POLYMER
|
2015-03-24 00:40:48 +00:00
|
|
|
if (pr_overridehud)
|
|
|
|
fov = pr_hudfov;
|
2013-11-22 19:26:46 +00:00
|
|
|
#endif
|
2015-03-24 00:40:48 +00:00
|
|
|
if (fov != -1)
|
2016-10-03 02:43:48 +00:00
|
|
|
f = 1.f/tanf(((float)fov * 2.56f) * ((.5f * fPI) * (1.0f/2048.f)));
|
2013-11-22 19:26:46 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
m[0][0] = f*fydimen; m[0][2] = 1.f;
|
|
|
|
m[1][1] = f*fxdimen; m[1][2] = 1.f;
|
|
|
|
m[2][2] = 1.f; m[2][3] = fydimen;
|
|
|
|
m[3][2] =-1.f;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m[0][0] = m[2][3] = 1.f;
|
|
|
|
m[1][1] = fxdim/fydim;
|
|
|
|
m[2][2] = 1.0001f;
|
|
|
|
m[3][2] = 1-m[2][2];
|
|
|
|
}
|
2013-11-22 19:26:46 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glLoadMatrixf(&m[0][0]);
|
2013-11-22 19:26:46 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
2015-03-24 00:40:48 +00:00
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (hud->flags & HUDFLAG_NODEPTH)
|
2018-02-16 06:38:21 +00:00
|
|
|
glDisable(GL_DEPTH_TEST);
|
2015-03-24 00:40:48 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
static int32_t onumframes = 0;
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (onumframes != numframes)
|
|
|
|
{
|
|
|
|
onumframes = numframes;
|
2018-02-16 06:38:21 +00:00
|
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
2015-03-24 00:40:48 +00:00
|
|
|
}
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
spriteext[tspr.owner].alpha = daalpha * (1.0f / 255.0f);
|
2016-10-09 07:55:23 +00:00
|
|
|
tspr.blend = dablend;
|
2014-09-30 04:06:05 +00:00
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_setFogEnabled(false);
|
2013-03-25 04:32:24 +00:00
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMOST)
|
2015-03-24 00:40:48 +00:00
|
|
|
polymost_mddraw(&tspr);
|
2011-01-20 21:46:15 +00:00
|
|
|
# ifdef POLYMER
|
2015-03-24 00:40:48 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
int32_t fov;
|
2011-03-01 05:52:33 +00:00
|
|
|
|
2017-07-08 19:42:11 +00:00
|
|
|
tspriteptr[maxspritesonscreen] = &tspr;
|
2010-08-21 07:39:12 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
glEnable(GL_BLEND);
|
2011-01-16 02:50:27 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
spriteext[tspr.owner].roll = a;
|
|
|
|
spriteext[tspr.owner].offset.z = z;
|
2013-11-22 19:26:44 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
fov = hud->fov;
|
2013-11-22 19:26:44 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (fov == -1)
|
|
|
|
fov = pr_fov;
|
2013-11-22 19:26:44 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
if (pr_overridehud)
|
|
|
|
fov = pr_hudfov;
|
2013-11-22 19:26:44 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
polymer_setaspect(fov);
|
2010-08-21 07:39:12 +00:00
|
|
|
|
2017-07-08 19:42:11 +00:00
|
|
|
polymer_drawsprite(maxspritesonscreen);
|
2013-11-22 19:26:44 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
polymer_setaspect(pr_fov);
|
2010-08-21 07:39:12 +00:00
|
|
|
|
2015-03-24 00:40:48 +00:00
|
|
|
spriteext[tspr.owner].offset.z = 0;
|
|
|
|
spriteext[tspr.owner].roll = 0;
|
2010-08-21 07:39:12 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
2015-03-24 00:40:48 +00:00
|
|
|
}
|
2011-01-20 21:46:15 +00:00
|
|
|
# endif
|
2018-03-21 20:41:26 +00:00
|
|
|
if (!nofog) polymost_setFogEnabled(true);
|
2015-03-24 00:40:48 +00:00
|
|
|
|
|
|
|
viewingrange = oldviewingrange;
|
2016-10-03 02:43:42 +00:00
|
|
|
fviewingrange = oldfviewingrange;
|
2015-03-24 00:40:48 +00:00
|
|
|
gxyaspect = ogxyaspect;
|
|
|
|
globalshade = ogshade;
|
|
|
|
globalpal = ogpal;
|
|
|
|
gchang = ogchang;
|
|
|
|
gshang = ogshang;
|
|
|
|
gctang = ogctang;
|
|
|
|
gstang = ogstang;
|
2019-03-19 17:08:39 +00:00
|
|
|
polymost_identityrotmat();
|
2014-09-30 04:14:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
|
2016-10-09 07:55:23 +00:00
|
|
|
int8_t dashade, char dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
|
2014-09-30 04:14:21 +00:00
|
|
|
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, int32_t uniqid)
|
|
|
|
{
|
2015-03-24 00:40:48 +00:00
|
|
|
if (usemodels && tile2model[picnum].hudmem[(dastat&4)>>2])
|
2014-09-30 04:14:21 +00:00
|
|
|
{
|
2016-10-09 07:55:23 +00:00
|
|
|
polymost_dorotatespritemodel(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, uniqid);
|
2014-09-30 04:14:21 +00:00
|
|
|
return;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glViewport(0,0,xdim,ydim); glox1 = -1; //Force fullscreen (glox1=-1 forces it to restore)
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2013-05-15 02:19:14 +00:00
|
|
|
globvis = 0;
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis2 = 0;
|
|
|
|
polymost_setVisibility(globvis2);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
int32_t const ogpicnum = globalpicnum;
|
|
|
|
globalpicnum = picnum;
|
|
|
|
int32_t const ogshade = globalshade;
|
|
|
|
globalshade = dashade;
|
|
|
|
int32_t const ogpal = globalpal;
|
|
|
|
globalpal = (int32_t)((uint8_t)dapalnum);
|
|
|
|
float const oghalfx = ghalfx;
|
|
|
|
ghalfx = fxdim * .5f;
|
|
|
|
float const ogrhalfxdown10 = grhalfxdown10;
|
|
|
|
grhalfxdown10 = 1.f / (ghalfx * 1024.f);
|
|
|
|
float const ogrhalfxdown10x = grhalfxdown10x;
|
|
|
|
grhalfxdown10x = grhalfxdown10;
|
|
|
|
float const oghoriz = ghoriz;
|
|
|
|
ghoriz = fydim * .5f;
|
|
|
|
int32_t const ofoffset = frameoffset;
|
|
|
|
frameoffset = frameplace;
|
|
|
|
float const ogchang = gchang;
|
|
|
|
gchang = 1.f;
|
|
|
|
float const ogshang = gshang;
|
|
|
|
gshang = 0.f;
|
|
|
|
float const ogctang = gctang;
|
|
|
|
gctang = 1.f;
|
|
|
|
float const ogstang = gstang;
|
|
|
|
gstang = 0.f;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2019-03-19 17:08:39 +00:00
|
|
|
polymost_updaterotmat();
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
float m[4][4];
|
|
|
|
|
|
|
|
Bmemset(m,0,sizeof(m));
|
|
|
|
m[0][0] = m[2][3] = 1.0f;
|
|
|
|
m[1][1] = fxdim / fydim;
|
|
|
|
m[2][2] = 1.0001f;
|
|
|
|
m[3][2] = 1 - m[2][2];
|
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glLoadMatrixf(&m[0][0]);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glDisable(GL_DEPTH_TEST);
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
2015-03-24 00:40:48 +00:00
|
|
|
|
|
|
|
#if defined(POLYMER)
|
2016-01-08 01:33:20 +00:00
|
|
|
# ifdef USE_GLEXT
|
2015-03-24 00:40:48 +00:00
|
|
|
const int32_t olddetailmapping = r_detailmapping, oldglowmapping = r_glowmapping;
|
2016-01-08 01:33:20 +00:00
|
|
|
# endif
|
2015-03-24 00:40:48 +00:00
|
|
|
const int32_t oldnormalmapping = pr_normalmapping;
|
|
|
|
#endif
|
|
|
|
|
2015-12-04 11:52:54 +00:00
|
|
|
int32_t method = DAMETH_CLAMPED; //Use OpenGL clamping - dorotatesprite never repeats
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if (!(dastat & RS_NOMASK))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_TRANS1)
|
2015-12-04 11:52:54 +00:00
|
|
|
method |= (dastat & RS_TRANS2) ? DAMETH_TRANS2 : DAMETH_TRANS1;
|
2013-11-22 19:26:52 +00:00
|
|
|
else
|
2015-12-04 11:52:54 +00:00
|
|
|
method |= DAMETH_MASK;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2016-10-09 07:55:23 +00:00
|
|
|
handle_blend(!!(dastat & RS_TRANS1), dablend, !!(dastat & RS_TRANS2));
|
|
|
|
|
2015-12-04 11:52:58 +00:00
|
|
|
#ifdef POLYMER
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMER)
|
2015-12-04 11:52:58 +00:00
|
|
|
{
|
|
|
|
pr_normalmapping = 0;
|
|
|
|
polymer_inb4rotatesprite(picnum, dapalnum, dashade, method);
|
2018-02-16 06:38:37 +00:00
|
|
|
polymost_resetVertexPointers();
|
2016-01-08 01:33:20 +00:00
|
|
|
# ifdef USE_GLEXT
|
2015-12-04 11:52:58 +00:00
|
|
|
r_detailmapping = 0;
|
|
|
|
r_glowmapping = 0;
|
2016-01-08 01:33:20 +00:00
|
|
|
# endif
|
2015-12-04 11:52:58 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
drawpoly_alpha = daalpha * (1.0f / 255.0f);
|
2016-10-09 07:55:23 +00:00
|
|
|
drawpoly_blend = dablend;
|
2013-03-25 04:32:24 +00:00
|
|
|
|
2017-06-24 09:21:13 +00:00
|
|
|
vec2s_t const siz = tilesiz[globalpicnum];
|
|
|
|
vec2s_t ofs = { 0, 0 };
|
2012-08-19 12:49:37 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
if (!(dastat & RS_TOPLEFT))
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
ofs.x = picanm[globalpicnum].xofs + (siz.x>>1);
|
|
|
|
ofs.y = picanm[globalpicnum].yofs + (siz.y>>1);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2012-08-19 12:49:37 +00:00
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if (dastat & RS_YFLIP)
|
2015-03-24 00:40:33 +00:00
|
|
|
ofs.y = siz.y - ofs.y;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t ourxyaspect, temp;
|
|
|
|
dorotspr_handle_bit2(&sx, &sy, &z, dastat, cx1 + cx2, cy1 + cy2, &temp, &ourxyaspect);
|
|
|
|
|
|
|
|
float d = (float)z * (1.0f / (65536.f * 16384.f));
|
|
|
|
float const cosang = (float)sintable[(a + 512) & 2047] * d;
|
|
|
|
float cosang2 = cosang;
|
|
|
|
float const sinang = (float)sintable[a & 2047] * d;
|
|
|
|
float sinang2 = sinang;
|
2011-01-16 02:50:27 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
if ((dastat & RS_AUTO) || (!(dastat & RS_NOCLIP))) // Don't aspect unscaled perms
|
2012-08-19 12:49:37 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
d = (float)ourxyaspect * (1.0f / 65536.f);
|
2012-08-19 12:49:37 +00:00
|
|
|
cosang2 *= d;
|
|
|
|
sinang2 *= d;
|
|
|
|
}
|
|
|
|
|
2017-06-24 09:21:13 +00:00
|
|
|
vec2f_t const fofs = { (float)ofs.x, (float)ofs.y };
|
2018-02-26 11:26:40 +00:00
|
|
|
float const cx = floorf((float)sx * (1.0f / 65536.f) - fofs.x * cosang2 + fofs.y * sinang2);
|
|
|
|
float const cy = floorf((float)sy * (1.0f / 65536.f) - fofs.x * sinang - fofs.y * cosang);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
vec2f_t pxy[8] = { { cx, cy },
|
|
|
|
{ cx + (float)siz.x * cosang2, cy + (float)siz.x * sinang },
|
|
|
|
{ 0, 0 },
|
|
|
|
{ cx - (float)siz.y * sinang2, cy + (float)siz.y * cosang } };
|
|
|
|
|
|
|
|
pxy[2].x = pxy[1].x + pxy[3].x - pxy[0].x;
|
|
|
|
pxy[2].y = pxy[1].y + pxy[3].y - pxy[0].y;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-02-26 11:26:40 +00:00
|
|
|
// Round after calculating pxy[2] so that it is calculated correctly
|
|
|
|
// Rounding pxy[0].x & pxy[0].y is unnecessary so long as pxy[0] can never have fractional values
|
|
|
|
//pxy[0].x = roundf(pxy[0].x); pxy[0].y = roundf(pxy[0].y);
|
|
|
|
pxy[1].x = roundf(pxy[1].x); pxy[1].y = roundf(pxy[1].y);
|
|
|
|
pxy[2].x = roundf(pxy[2].x); pxy[2].y = roundf(pxy[2].y);
|
|
|
|
pxy[3].x = roundf(pxy[3].x); pxy[3].y = roundf(pxy[3].y);
|
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t n = 4;
|
|
|
|
|
|
|
|
xtex.d = 0; ytex.d = 0; otex.d = 1.f;
|
2006-04-24 19:04:22 +00:00
|
|
|
//px[0]*gux + py[0]*guy + guo = 0
|
|
|
|
//px[1]*gux + py[1]*guy + guo = xsiz-.0001
|
|
|
|
//px[3]*gux + py[3]*guy + guo = 0
|
2014-10-25 03:33:26 +00:00
|
|
|
d = 1.f/(pxy[0].x*(pxy[1].y-pxy[3].y) + pxy[1].x*(pxy[3].y-pxy[0].y) + pxy[3].x*(pxy[0].y-pxy[1].y));
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
float const sxd = ((float)siz.x-.0001f)*d;
|
|
|
|
|
|
|
|
xtex.u = (pxy[3].y-pxy[0].y)*sxd;
|
|
|
|
ytex.u = (pxy[0].x-pxy[3].x)*sxd;
|
|
|
|
otex.u = 0 - pxy[0].x*xtex.u - pxy[0].y*ytex.u;
|
|
|
|
|
|
|
|
float const syd = ((float)siz.y-.0001f)*d;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2013-11-22 19:26:52 +00:00
|
|
|
if (!(dastat & RS_YFLIP))
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
|
|
|
//px[0]*gvx + py[0]*gvy + gvo = 0
|
2006-04-24 19:04:22 +00:00
|
|
|
//px[1]*gvx + py[1]*gvy + gvo = 0
|
|
|
|
//px[3]*gvx + py[3]*gvy + gvo = ysiz-.0001
|
2015-03-24 00:40:33 +00:00
|
|
|
xtex.v = (pxy[0].y-pxy[1].y)*syd;
|
|
|
|
ytex.v = (pxy[1].x-pxy[0].x)*syd;
|
|
|
|
otex.v = 0 - pxy[0].x*xtex.v - pxy[0].y*ytex.v;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
else
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
|
|
|
//px[0]*gvx + py[0]*gvy + gvo = ysiz-.0001
|
2006-04-24 19:04:22 +00:00
|
|
|
//px[1]*gvx + py[1]*gvy + gvo = ysiz-.0001
|
|
|
|
//px[3]*gvx + py[3]*gvy + gvo = 0
|
2015-03-24 00:40:33 +00:00
|
|
|
xtex.v = (pxy[1].y-pxy[0].y)*syd;
|
|
|
|
ytex.v = (pxy[0].x-pxy[1].x)*syd;
|
|
|
|
otex.v = (float)siz.y-.0001f - pxy[0].x*xtex.v - pxy[0].y*ytex.v;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cx2++; cy2++;
|
2009-01-09 09:29:17 +00:00
|
|
|
//Clippoly4 (converted from int32_t to double)
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
int32_t nn = z = 0;
|
|
|
|
float px2[8], py2[8];
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
do
|
|
|
|
{
|
2012-08-16 21:48:44 +00:00
|
|
|
int32_t zz = z+1; if (zz == n) zz = 0;
|
2015-03-24 00:40:33 +00:00
|
|
|
float const x1 = pxy[z].x, x2 = pxy[zz].x-x1;
|
|
|
|
if (((float)cx1 <= x1) && (x1 <= (float)cx2)) { px2[nn] = x1; py2[nn] = pxy[z].y; nn++; }
|
|
|
|
float fx = (float)(x2 <= 0 ? cx2 : cx1); d = fx-x1;
|
2014-10-25 03:33:26 +00:00
|
|
|
if ((d < x2) != (d < 0)) { px2[nn] = fx; py2[nn] = (pxy[zz].y-pxy[z].y)*d/x2 + pxy[z].y; nn++; }
|
2015-03-24 00:40:33 +00:00
|
|
|
fx = (float)(x2 <= 0 ? cx1 : cx2); d = fx-x1;
|
2014-10-25 03:33:26 +00:00
|
|
|
if ((d < x2) != (d < 0)) { px2[nn] = fx; py2[nn] = (pxy[zz].y-pxy[z].y)*d/x2 + pxy[z].y; nn++; }
|
2006-04-24 19:04:22 +00:00
|
|
|
z = zz;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (z);
|
2012-08-16 21:48:44 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
if (nn >= 3)
|
|
|
|
{
|
|
|
|
n = z = 0;
|
|
|
|
do
|
|
|
|
{
|
2012-08-16 21:48:44 +00:00
|
|
|
int32_t zz = z+1; if (zz == nn) zz = 0;
|
2016-06-05 04:46:28 +00:00
|
|
|
float const y1 = py2[z], y2 = py2[zz]-y1;
|
2015-03-24 00:40:33 +00:00
|
|
|
if ((cy1 <= y1) && (y1 <= cy2)) { pxy[n].y = y1; pxy[n].x = px2[z]; n++; }
|
|
|
|
float fy = (float)(y2 <= 0 ? cy2 : cy1); d = fy - y1;
|
2014-10-25 03:33:26 +00:00
|
|
|
if ((d < y2) != (d < 0)) { pxy[n].y = fy; pxy[n].x = (px2[zz]-px2[z])*d/y2 + px2[z]; n++; }
|
2015-03-24 00:40:33 +00:00
|
|
|
fy = (float)(y2 <= 0 ? cy1 : cy2); d = fy - y1;
|
2014-10-25 03:33:26 +00:00
|
|
|
if ((d < y2) != (d < 0)) { pxy[n].y = fy; pxy[n].x = (px2[zz]-px2[z])*d/y2 + px2[z]; n++; }
|
2006-04-24 19:04:22 +00:00
|
|
|
z = zz;
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
while (z);
|
2013-03-04 09:10:54 +00:00
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_setFogEnabled(false);
|
2015-07-08 03:34:20 +00:00
|
|
|
pow2xsplit = 0; polymost_drawpoly(pxy, n,method);
|
2018-03-21 20:41:26 +00:00
|
|
|
if (!nofog) polymost_setFogEnabled(true);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
#ifdef POLYMER
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() == REND_POLYMER)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2016-01-08 01:33:20 +00:00
|
|
|
# ifdef USE_GLEXT
|
2015-03-24 00:40:33 +00:00
|
|
|
r_detailmapping = olddetailmapping;
|
|
|
|
r_glowmapping = oldglowmapping;
|
2016-01-08 01:33:20 +00:00
|
|
|
# endif
|
2015-03-24 00:40:33 +00:00
|
|
|
polymer_postrotatesprite();
|
|
|
|
pr_normalmapping = oldnormalmapping;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
#endif
|
2018-02-16 06:38:21 +00:00
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
globalpicnum = ogpicnum;
|
|
|
|
globalshade = ogshade;
|
|
|
|
globalpal = ogpal;
|
|
|
|
ghalfx = oghalfx;
|
|
|
|
grhalfxdown10 = ogrhalfxdown10;
|
|
|
|
grhalfxdown10x = ogrhalfxdown10x;
|
|
|
|
ghoriz = oghoriz;
|
|
|
|
frameoffset = ofoffset;
|
|
|
|
gchang = ogchang;
|
|
|
|
gshang = ogshang;
|
|
|
|
gctang = ogctang;
|
|
|
|
gstang = ogstang;
|
2019-03-19 17:08:39 +00:00
|
|
|
|
|
|
|
polymost_identityrotmat();
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static float trapextx[2];
|
2007-12-12 17:42:14 +00:00
|
|
|
static void drawtrap(float x0, float x1, float y0, float x2, float x3, float y1)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
if (y0 == y1) return;
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
float px[4], py[4];
|
2015-03-24 00:40:33 +00:00
|
|
|
int32_t n = 3;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
px[0] = x0; py[0] = y0; py[2] = y1;
|
2015-03-24 00:40:33 +00:00
|
|
|
if (x0 == x1) { px[1] = x3; py[1] = y1; px[2] = x2; }
|
|
|
|
else if (x2 == x3) { px[1] = x1; py[1] = y0; px[2] = x3; }
|
2006-04-24 19:04:22 +00:00
|
|
|
else { px[1] = x1; py[1] = y0; px[2] = x3; px[3] = x2; py[3] = y1; n = 4; }
|
|
|
|
|
2019-09-16 19:08:42 +00:00
|
|
|
auto data = GLInterface.AllocVertices(n);
|
|
|
|
auto vt = data.second;
|
|
|
|
for (bssize_t i=0; i<n; i++, vt++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
px[i] = min(max(px[i],trapextx[0]),trapextx[1]);
|
2019-09-16 19:08:42 +00:00
|
|
|
vt->SetTexCoord(px[i]*xtex.u + py[i]*ytex.u + otex.u,
|
2015-03-24 00:40:33 +00:00
|
|
|
px[i]*xtex.v + py[i]*ytex.v + otex.v);
|
2019-09-16 19:08:42 +00:00
|
|
|
vt->SetVertex(px[i],py[i]);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2019-09-16 19:08:42 +00:00
|
|
|
GLInterface.Draw(DT_TRIANGLE_FAN, data.first, n);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2013-02-10 16:24:15 +00:00
|
|
|
static void tessectrap(const float *px, const float *py, const int32_t *point2, int32_t numpoints)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
float x0, x1, m0, m1;
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t i, j, k, z, i0, i1, i2, i3, npoints, gap, numrst;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
static int32_t allocpoints = 0, *slist = 0, *npoint2 = 0;
|
|
|
|
typedef struct { float x, y, xi; int32_t i; } raster;
|
2006-04-24 19:04:22 +00:00
|
|
|
static raster *rst = 0;
|
|
|
|
if (numpoints+16 > allocpoints) //16 for safety
|
|
|
|
{
|
|
|
|
allocpoints = numpoints+16;
|
2014-05-30 00:02:19 +00:00
|
|
|
rst = (raster *)Xrealloc(rst,allocpoints*sizeof(raster));
|
|
|
|
slist = (int32_t *)Xrealloc(slist,allocpoints*sizeof(int32_t));
|
|
|
|
npoint2 = (int32_t *)Xrealloc(npoint2,allocpoints*sizeof(int32_t));
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//Remove unnecessary collinear points:
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<numpoints; i++) npoint2[i] = point2[i];
|
2006-04-24 19:04:22 +00:00
|
|
|
npoints = numpoints; z = 0;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=0; i<numpoints; i++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2018-10-25 23:31:05 +00:00
|
|
|
j = npoint2[i]; if ((i < numpoints-1) && (point2[i] < i)) z = 3;
|
2006-04-24 19:04:22 +00:00
|
|
|
if (j < 0) continue;
|
|
|
|
k = npoint2[j];
|
|
|
|
m0 = (px[j]-px[i])*(py[k]-py[j]);
|
|
|
|
m1 = (py[j]-py[i])*(px[k]-px[j]);
|
2007-12-12 17:42:14 +00:00
|
|
|
if (m0 < m1) { z |= 1; continue; }
|
2006-04-24 19:04:22 +00:00
|
|
|
if (m0 > m1) { z |= 2; continue; }
|
|
|
|
npoint2[i] = k; npoint2[j] = -1; npoints--; i--; //collinear
|
|
|
|
}
|
|
|
|
if (!z) return;
|
|
|
|
trapextx[0] = trapextx[1] = px[0];
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=j=0; i<numpoints; i++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
if (npoint2[i] < 0) continue;
|
|
|
|
if (px[i] < trapextx[0]) trapextx[0] = px[i];
|
|
|
|
if (px[i] > trapextx[1]) trapextx[1] = px[i];
|
|
|
|
slist[j++] = i;
|
|
|
|
}
|
|
|
|
if (z != 3) //Simple polygon... early out
|
|
|
|
{
|
2019-09-16 19:08:42 +00:00
|
|
|
auto data = GLInterface.AllocVertices(npoints);
|
|
|
|
auto vt = data.second;
|
|
|
|
|
|
|
|
for (i=0; i<npoints; i++, vt++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
j = slist[i];
|
2019-09-16 19:08:42 +00:00
|
|
|
vt->SetTexCoord(px[j]*xtex.u + py[j]*ytex.u + otex.u,
|
2015-03-24 00:40:33 +00:00
|
|
|
px[j]*xtex.v + py[j]*ytex.v + otex.v);
|
2019-09-16 19:08:42 +00:00
|
|
|
vt->SetVertex(px[j],py[j]);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2019-09-16 19:08:42 +00:00
|
|
|
GLInterface.Draw(DT_TRIANGLE_FAN, data.first, npoints);
|
2006-04-24 19:04:22 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Sort points by y's
|
2009-02-19 16:47:54 +00:00
|
|
|
for (gap=(npoints>>1); gap; gap>>=1)
|
|
|
|
for (i=0; i<npoints-gap; i++)
|
|
|
|
for (j=i; j>=0; j-=gap)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
if (py[npoint2[slist[j]]] <= py[npoint2[slist[j+gap]]]) break;
|
|
|
|
k = slist[j]; slist[j] = slist[j+gap]; slist[j+gap] = k;
|
|
|
|
}
|
|
|
|
|
|
|
|
numrst = 0;
|
2009-02-19 16:47:54 +00:00
|
|
|
for (z=0; z<npoints; z++)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
i0 = slist[z]; i1 = npoint2[i0]; if (py[i0] == py[i1]) continue;
|
|
|
|
i2 = i1; i3 = npoint2[i1];
|
2007-12-12 17:42:14 +00:00
|
|
|
if (py[i1] == py[i3]) { i2 = i3; i3 = npoint2[i3]; }
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
//i0 i3
|
|
|
|
// \ /
|
|
|
|
// i1--i2
|
|
|
|
// / \ ~
|
|
|
|
//i0 i3
|
|
|
|
|
|
|
|
if ((py[i1] < py[i0]) && (py[i2] < py[i3])) //Insert raster
|
|
|
|
{
|
2009-02-19 16:47:54 +00:00
|
|
|
for (i=numrst; i>0; i--)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
if (rst[i-1].xi*(py[i1]-rst[i-1].y) + rst[i-1].x < px[i1]) break;
|
|
|
|
rst[i+1] = rst[i-1];
|
|
|
|
}
|
|
|
|
numrst += 2;
|
|
|
|
|
|
|
|
if (i&1) //split inside area
|
|
|
|
{
|
|
|
|
j = i-1;
|
|
|
|
|
|
|
|
x0 = (py[i1] - rst[j ].y)*rst[j ].xi + rst[j ].x;
|
|
|
|
x1 = (py[i1] - rst[j+1].y)*rst[j+1].xi + rst[j+1].x;
|
|
|
|
drawtrap(rst[j].x,rst[j+1].x,rst[j].y,x0,x1,py[i1]);
|
|
|
|
rst[j ].x = x0; rst[j ].y = py[i1];
|
|
|
|
rst[j+3].x = x1; rst[j+3].y = py[i1];
|
|
|
|
}
|
|
|
|
|
|
|
|
m0 = (px[i0]-px[i1]) / (py[i0]-py[i1]);
|
|
|
|
m1 = (px[i3]-px[i2]) / (py[i3]-py[i2]);
|
|
|
|
j = ((px[i1] > px[i2]) || ((i1 == i2) && (m0 >= m1))) + i;
|
|
|
|
k = (i<<1)+1 - j;
|
|
|
|
rst[j].i = i0; rst[j].xi = m0; rst[j].x = px[i1]; rst[j].y = py[i1];
|
|
|
|
rst[k].i = i3; rst[k].xi = m1; rst[k].x = px[i2]; rst[k].y = py[i2];
|
|
|
|
}
|
|
|
|
else
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
|
|
|
//NOTE:don't count backwards!
|
2009-02-19 16:47:54 +00:00
|
|
|
if (i1 == i2) { for (i=0; i<numrst; i++) if (rst[i].i == i1) break; }
|
|
|
|
else { for (i=0; i<numrst; i++) if ((rst[i].i == i1) || (rst[i].i == i2)) break; }
|
2006-04-24 19:04:22 +00:00
|
|
|
j = i&~1;
|
|
|
|
|
|
|
|
if ((py[i1] > py[i0]) && (py[i2] > py[i3])) //Delete raster
|
|
|
|
{
|
2009-02-19 16:47:54 +00:00
|
|
|
for (; j<=i+1; j+=2)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
|
|
|
x0 = (py[i1] - rst[j ].y)*rst[j ].xi + rst[j ].x;
|
|
|
|
if ((i == j) && (i1 == i2)) x1 = x0; else x1 = (py[i1] - rst[j+1].y)*rst[j+1].xi + rst[j+1].x;
|
|
|
|
drawtrap(rst[j].x,rst[j+1].x,rst[j].y,x0,x1,py[i1]);
|
|
|
|
rst[j ].x = x0; rst[j ].y = py[i1];
|
|
|
|
rst[j+1].x = x1; rst[j+1].y = py[i1];
|
|
|
|
}
|
2009-02-19 16:47:54 +00:00
|
|
|
numrst -= 2; for (; i<numrst; i++) rst[i] = rst[i+2];
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x0 = (py[i1] - rst[j ].y)*rst[j ].xi + rst[j ].x;
|
|
|
|
x1 = (py[i1] - rst[j+1].y)*rst[j+1].xi + rst[j+1].x;
|
|
|
|
drawtrap(rst[j].x,rst[j+1].x,rst[j].y,x0,x1,py[i1]);
|
|
|
|
rst[j ].x = x0; rst[j ].y = py[i1];
|
|
|
|
rst[j+1].x = x1; rst[j+1].y = py[i1];
|
|
|
|
|
|
|
|
if (py[i0] < py[i3]) { rst[i].x = px[i2]; rst[i].y = py[i2]; rst[i].i = i3; }
|
|
|
|
else { rst[i].x = px[i1]; rst[i].y = py[i1]; rst[i].i = i0; }
|
|
|
|
rst[i].xi = (px[rst[i].i] - rst[i].x) / (py[rst[i].i] - py[i1]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
void polymost_fillpolygon(int32_t npoints)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2019-03-19 17:08:39 +00:00
|
|
|
globvis2 = 0;
|
|
|
|
polymost_setVisibility(globvis2);
|
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
globalx1 = mulscale16(globalx1,xyaspect);
|
|
|
|
globaly2 = mulscale16(globaly2,xyaspect);
|
2015-07-08 03:34:20 +00:00
|
|
|
xtex.u = ((float)asm1) * (1.f / 4294967296.f);
|
|
|
|
xtex.v = ((float)asm2) * (1.f / 4294967296.f);
|
|
|
|
ytex.u = ((float)globalx1) * (1.f / 4294967296.f);
|
|
|
|
ytex.v = ((float)globaly2) * (-1.f / 4294967296.f);
|
|
|
|
otex.u = (fxdim * xtex.u + fydim * ytex.u) * -0.5f + fglobalposx * (1.f / 4294967296.f);
|
|
|
|
otex.v = (fxdim * xtex.v + fydim * ytex.v) * -0.5f - fglobalposy * (1.f / 4294967296.f);
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
//Convert int32_t to float (in-place)
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<npoints; ++i)
|
2006-04-24 19:04:22 +00:00
|
|
|
{
|
2014-09-30 04:06:05 +00:00
|
|
|
((float *)rx1)[i] = ((float)rx1[i])*(1.0f/4096.f);
|
|
|
|
((float *)ry1)[i] = ((float)ry1[i])*(1.0f/4096.f);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
if (gloy1 != -1) polymostSet2dView(); //disables blending, texturing, and depth testing
|
2018-02-16 06:38:21 +00:00
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
2018-10-25 23:31:30 +00:00
|
|
|
pthtyp const * const pth = our_texcache_fetch(DAMETH_NOMASK | (videoGetRenderMode() == REND_POLYMOST && r_useindexedcolortextures ? PTH_INDEXED : 0));
|
2018-10-07 05:20:09 +00:00
|
|
|
|
|
|
|
if (pth)
|
2018-03-21 20:41:26 +00:00
|
|
|
{
|
2018-10-07 05:20:09 +00:00
|
|
|
polymost_bindPth(pth);
|
|
|
|
|
|
|
|
if (!(pth->flags & PTH_INDEXED))
|
|
|
|
polymost_usePaletteIndexing(false);
|
2018-03-21 20:41:26 +00:00
|
|
|
}
|
2019-01-22 17:56:37 +00:00
|
|
|
|
2019-03-19 17:09:06 +00:00
|
|
|
polymost_updatePalette();
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-07-08 03:34:20 +00:00
|
|
|
float const f = getshadefactor(globalshade);
|
2014-09-30 04:14:21 +00:00
|
|
|
|
2016-10-09 07:55:23 +00:00
|
|
|
uint8_t const maskprops = (globalorientation>>7)&DAMETH_MASKPROPS;
|
|
|
|
handle_blend(maskprops > DAMETH_MASK, 0, maskprops == DAMETH_TRANS2);
|
|
|
|
if (maskprops > DAMETH_MASK)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glColor4f(f, f, f, float_trans(maskprops, 0));
|
2014-09-30 04:14:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-02-16 06:38:21 +00:00
|
|
|
glDisable(GL_BLEND);
|
|
|
|
glColor3f(f, f, f);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tessectrap((float *)rx1,(float *)ry1,xb1,npoints);
|
2018-03-21 20:41:26 +00:00
|
|
|
|
|
|
|
if (pth && !(pth->flags & PTH_INDEXED))
|
|
|
|
{
|
|
|
|
// restore palette usage if we were just rendering a non-indexed color texture
|
|
|
|
polymost_usePaletteIndexing(true);
|
|
|
|
}
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2012-12-16 19:18:10 +00:00
|
|
|
static int32_t gen_font_glyph_tex(void)
|
|
|
|
{
|
2018-03-21 20:41:26 +00:00
|
|
|
// construct a 256x128 texture for the font glyph matrix
|
2012-12-16 19:18:10 +00:00
|
|
|
|
2019-09-16 16:10:28 +00:00
|
|
|
GetTextureHandle(&polymosttext);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2012-12-16 19:18:10 +00:00
|
|
|
if (!polymosttext) return -1;
|
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
char * const tbuf = (char *)Xmalloc(256*128*4);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
Bmemset(tbuf, 0, 256*128*4);
|
2012-12-16 19:18:10 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
char * cptr = (char *)textfont;
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t h=0; h<256; h++)
|
2012-12-16 19:18:10 +00:00
|
|
|
{
|
2018-03-21 20:41:26 +00:00
|
|
|
char *tptr = tbuf + (h%32)*8*4 + (h/32)*256*8*4;
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=0; i<8; i++)
|
2012-12-16 19:18:10 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j=0; j<8; j++)
|
2012-12-16 19:18:10 +00:00
|
|
|
{
|
2018-03-21 20:41:26 +00:00
|
|
|
if (cptr[h*8+i] & pow2char[7-j])
|
|
|
|
{
|
|
|
|
Bmemset(tptr+4*j, 255, 4);
|
|
|
|
}
|
2012-12-16 19:18:10 +00:00
|
|
|
}
|
2018-03-21 20:41:26 +00:00
|
|
|
tptr += 256*4;
|
2012-12-16 19:18:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cptr = (char *)smalltextfont;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t h=0; h<256; h++)
|
2012-12-16 19:18:10 +00:00
|
|
|
{
|
2018-03-21 20:41:26 +00:00
|
|
|
char *tptr = tbuf + 256*64*4 + (h%32)*8*4 + (h/32)*256*8*4;
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t i=1; i<7; i++)
|
2012-12-16 19:18:10 +00:00
|
|
|
{
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t j=2; j<6; j++)
|
2012-12-16 19:18:10 +00:00
|
|
|
{
|
2018-03-21 20:41:26 +00:00
|
|
|
if (cptr[h*8+i] & pow2char[7-j])
|
|
|
|
{
|
|
|
|
Bmemset(tptr+4*(j-2), 255, 4);
|
|
|
|
}
|
2012-12-16 19:18:10 +00:00
|
|
|
}
|
2018-03-21 20:41:26 +00:00
|
|
|
tptr += 256*4;
|
2012-12-16 19:18:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, polymosttext);
|
2018-03-21 20:41:26 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,256,128,0,GL_RGBA,GL_UNSIGNED_BYTE,(GLvoid *)tbuf);
|
2018-02-16 06:38:21 +00:00
|
|
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
|
2012-12-16 19:18:10 +00:00
|
|
|
Bfree(tbuf);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-05-18 05:14:17 +00:00
|
|
|
int32_t polymost_printext256(int32_t xpos, int32_t ypos, int16_t col, int16_t backcol, const char *name, char fontsize)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
int const arbackcol = (unsigned)backcol < 256 ? backcol : 0;
|
2011-12-09 19:09:29 +00:00
|
|
|
|
|
|
|
// FIXME?
|
|
|
|
if (col < 0)
|
|
|
|
col = 0;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
palette_t p, b;
|
|
|
|
|
2012-11-10 14:11:20 +00:00
|
|
|
bricolor(&p, col);
|
|
|
|
bricolor(&b, arbackcol);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() < REND_POLYMOST || !in3dmode() || (!polymosttext && gen_font_glyph_tex() < 0))
|
2015-03-24 00:40:33 +00:00
|
|
|
return -1;
|
2018-05-08 17:32:16 +00:00
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, polymosttext);
|
|
|
|
polymost_setTexturePosSize({0, 0, 1, 1});
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_usePaletteIndexing(false);
|
|
|
|
|
2018-04-12 21:03:47 +00:00
|
|
|
polymostSet2dView(); // disables blending, texturing, and depth testing
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
glDepthMask(GL_FALSE); // disable writing to the z-buffer
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
// glPushAttrib(GL_POLYGON_BIT|GL_ENABLE_BIT);
|
2014-03-23 23:14:48 +00:00
|
|
|
// XXX: Don't fogify the OSD text in Mapster32 with r_usenewshading >= 2.
|
2018-03-21 20:41:26 +00:00
|
|
|
polymost_setFogEnabled(false);
|
2012-12-16 19:18:13 +00:00
|
|
|
// We want to have readable text in wireframe mode, too:
|
2018-02-16 06:38:21 +00:00
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
2012-12-16 19:18:13 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (backcol >= 0)
|
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
int const c = Bstrlen(name);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glColor4ub(b.r,b.g,b.b,255);
|
2016-06-05 04:46:28 +00:00
|
|
|
|
2019-09-16 19:08:42 +00:00
|
|
|
auto data = GLInterface.AllocVertices(4);
|
|
|
|
auto vt = data.second;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-09-16 19:08:42 +00:00
|
|
|
vt->SetTexCoord(); vt->SetVertex(xpos, ypos); vt++;
|
|
|
|
vt->SetTexCoord(); vt->SetVertex(xpos, ypos + (fontsize ? 6 : 8)); vt++;
|
|
|
|
vt->SetTexCoord(); vt->SetVertex(xpos + (c << (3 - fontsize)), ypos + (fontsize ? 6 : 8)); vt++;
|
|
|
|
vt->SetTexCoord(); vt->SetVertex(xpos+(c<<(3-fontsize)), ypos);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-09-16 19:08:42 +00:00
|
|
|
GLInterface.Draw(DT_TRIANGLE_FAN, data.first, 4);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glColor4ub(p.r,p.g,p.b,255);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
vec2f_t const tc = { fontsize ? (4.f / 256.f) : (8.f / 256.f),
|
|
|
|
fontsize ? (6.f / 128.f) : (8.f / 128.f) };
|
|
|
|
|
|
|
|
|
2016-08-27 01:41:21 +00:00
|
|
|
for (bssize_t c=0; name[c]; ++c)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2008-05-16 19:51:38 +00:00
|
|
|
if (name[c] == '^' && isdigit(name[c+1]))
|
|
|
|
{
|
|
|
|
char smallbuf[8];
|
2015-03-24 00:40:33 +00:00
|
|
|
int bi = 0;
|
|
|
|
|
2012-12-20 12:04:39 +00:00
|
|
|
while (isdigit(name[c+1]) && bi<3)
|
2008-05-16 19:51:38 +00:00
|
|
|
{
|
|
|
|
smallbuf[bi++]=name[c+1];
|
|
|
|
c++;
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
|
|
|
smallbuf[bi++] = 0;
|
|
|
|
|
|
|
|
if (col)
|
2015-12-23 04:05:51 +00:00
|
|
|
{
|
2015-03-24 00:40:33 +00:00
|
|
|
col = Batol(smallbuf);
|
|
|
|
|
2015-12-23 04:05:51 +00:00
|
|
|
if ((unsigned) col >= 256)
|
|
|
|
col = 0;
|
|
|
|
}
|
2008-05-16 19:51:38 +00:00
|
|
|
|
2012-11-10 14:11:20 +00:00
|
|
|
bricolor(&p, col);
|
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glColor4ub(p.r, p.g, p.b, 255);
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2008-05-16 19:51:38 +00:00
|
|
|
continue;
|
|
|
|
}
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2015-03-24 00:40:33 +00:00
|
|
|
vec2f_t const t = { (float)(name[c] % 32) * (1.0f / 32.f),
|
|
|
|
(float)((name[c] / 32) + (fontsize * 8)) * (1.0f / 16.f) };
|
|
|
|
|
2019-09-16 19:08:42 +00:00
|
|
|
auto data = GLInterface.AllocVertices(4);
|
|
|
|
auto vt = data.second;
|
|
|
|
|
|
|
|
vt->SetTexCoord(t.x, t.y);
|
|
|
|
vt->SetVertex(xpos, ypos);
|
|
|
|
vt++;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-09-16 19:08:42 +00:00
|
|
|
vt->SetTexCoord(t.x + tc.x, t.y);
|
|
|
|
vt->SetVertex(xpos + (8 >> fontsize), ypos);
|
|
|
|
vt++;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-09-16 19:08:42 +00:00
|
|
|
vt->SetTexCoord(t.x + tc.x, t.y + tc.y);
|
|
|
|
vt->SetVertex(xpos + (8 >> fontsize), ypos + (fontsize ? 6 : 8));
|
|
|
|
vt++;
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2019-09-16 19:08:42 +00:00
|
|
|
vt->SetTexCoord(t.x, t.y + tc.y);
|
|
|
|
vt->SetVertex(xpos, ypos + (fontsize ? 6 : 8));
|
|
|
|
vt++;
|
|
|
|
|
|
|
|
GLInterface.Draw(DT_TRIANGLE_FAN, data.first, 4);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
xpos += (8>>fontsize);
|
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
glDepthMask(GL_TRUE); // re-enable writing to the z-buffer
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2018-02-16 06:38:21 +00:00
|
|
|
// glPopAttrib();
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2018-03-21 20:41:26 +00:00
|
|
|
if (!nofog) polymost_setFogEnabled(true);
|
|
|
|
|
|
|
|
polymost_usePaletteIndexing(true);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
return 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Console commands by JBF
|
2018-11-18 18:06:15 +00:00
|
|
|
static int32_t gltexturemode(osdcmdptr_t parm)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-01-09 09:29:17 +00:00
|
|
|
int32_t m;
|
2016-01-11 05:05:38 +00:00
|
|
|
char *p;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
if (parm->numparms != 1)
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
OSD_Printf("Current texturing mode is %s\n", glfiltermodes[gltexfiltermode].name);
|
|
|
|
OSD_Printf(" Vaild modes are:\n");
|
2012-10-01 17:52:25 +00:00
|
|
|
for (m = 0; m < NUMGLFILTERMODES; m++)
|
|
|
|
OSD_Printf(" %d - %s\n", m, glfiltermodes[m].name);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
return OSDCMD_OK;
|
|
|
|
}
|
|
|
|
|
2016-01-11 05:05:38 +00:00
|
|
|
m = Bstrtoul(parm->parms[0], &p, 10);
|
2007-12-12 17:42:14 +00:00
|
|
|
if (p == parm->parms[0])
|
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
// string
|
2012-10-01 17:52:25 +00:00
|
|
|
for (m = 0; m < NUMGLFILTERMODES; m++)
|
2007-12-12 17:42:14 +00:00
|
|
|
{
|
2012-10-01 17:52:25 +00:00
|
|
|
if (!Bstrcasecmp(parm->parms[0], glfiltermodes[m].name))
|
|
|
|
break;
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
2012-10-01 17:52:25 +00:00
|
|
|
|
|
|
|
if (m == NUMGLFILTERMODES)
|
|
|
|
m = gltexfiltermode; // no change
|
2007-12-12 17:42:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-10-01 17:52:25 +00:00
|
|
|
m = clamp(m, 0, NUMGLFILTERMODES-1);
|
2006-04-24 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2009-04-29 19:43:51 +00:00
|
|
|
gltexfiltermode = m;
|
|
|
|
gltexapplyprops();
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2007-12-12 17:42:14 +00:00
|
|
|
OSD_Printf("Texture filtering mode changed to %s\n", glfiltermodes[gltexfiltermode].name);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
|
|
|
return OSDCMD_OK;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2018-11-18 18:06:15 +00:00
|
|
|
static int osdcmd_cvar_set_polymost(osdcmdptr_t parm)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2009-04-29 07:47:10 +00:00
|
|
|
int32_t r = osdcmd_cvar_set(parm);
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2009-04-29 20:20:57 +00:00
|
|
|
if (xdim == 0 || ydim == 0 || bpp == 0) // video not set up yet
|
2012-10-14 14:51:29 +00:00
|
|
|
{
|
|
|
|
if (r == OSDCMD_OK)
|
|
|
|
{
|
|
|
|
#ifdef POLYMER
|
|
|
|
if (!Bstrcasecmp(parm->name, "r_pr_maxlightpasses"))
|
|
|
|
pr_maxlightpasses = r_pr_maxlightpasses;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-04-29 07:47:10 +00:00
|
|
|
return r;
|
2012-10-14 14:51:29 +00:00
|
|
|
}
|
2009-04-29 20:20:57 +00:00
|
|
|
|
|
|
|
if (r == OSDCMD_OK)
|
2009-04-29 19:43:51 +00:00
|
|
|
{
|
2009-04-29 20:20:57 +00:00
|
|
|
if (!Bstrcasecmp(parm->name, "r_swapinterval"))
|
2018-04-12 21:02:51 +00:00
|
|
|
vsync = videoSetVsync(vsync);
|
2009-04-29 20:20:57 +00:00
|
|
|
else if (!Bstrcasecmp(parm->name, "r_downsize"))
|
|
|
|
{
|
2013-11-11 20:33:55 +00:00
|
|
|
if (r_downsizevar == -1)
|
|
|
|
r_downsizevar = r_downsize;
|
|
|
|
|
|
|
|
if (in3dmode() && r_downsize != r_downsizevar)
|
2009-04-30 01:07:08 +00:00
|
|
|
{
|
2013-05-15 02:17:17 +00:00
|
|
|
texcache_invalidate();
|
2018-04-12 21:02:51 +00:00
|
|
|
videoResetMode();
|
2018-07-14 21:36:44 +00:00
|
|
|
if (videoSetGameMode(fullscreen,xres,yres,bpp,upscalefactor))
|
2009-04-30 01:07:08 +00:00
|
|
|
OSD_Printf("restartvid: Reset failed...\n");
|
|
|
|
}
|
2013-11-11 20:33:55 +00:00
|
|
|
|
|
|
|
r_downsizevar = r_downsize;
|
2009-04-29 20:20:57 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
else if (!Bstrcasecmp(parm->name, "r_anisotropy"))
|
2009-04-29 20:20:57 +00:00
|
|
|
gltexapplyprops();
|
2015-03-24 00:40:33 +00:00
|
|
|
else if (!Bstrcasecmp(parm->name, "r_texfilter"))
|
2009-04-29 20:20:57 +00:00
|
|
|
gltexturemode(parm);
|
2015-01-11 04:56:58 +00:00
|
|
|
else if (!Bstrcasecmp(parm->name, "r_usenewshading"))
|
2018-02-16 06:38:21 +00:00
|
|
|
glFogi(GL_FOG_MODE, (r_usenewshading < 2) ? GL_EXP2 : GL_LINEAR);
|
2009-06-09 06:19:58 +00:00
|
|
|
#ifdef POLYMER
|
|
|
|
else if (!Bstrcasecmp(parm->name, "r_pr_maxlightpasses"))
|
|
|
|
{
|
|
|
|
if (pr_maxlightpasses != r_pr_maxlightpasses)
|
|
|
|
{
|
2009-06-10 11:12:56 +00:00
|
|
|
polymer_invalidatelights();
|
2009-06-09 08:31:38 +00:00
|
|
|
pr_maxlightpasses = r_pr_maxlightpasses;
|
2009-06-09 06:19:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2009-04-29 19:43:51 +00:00
|
|
|
}
|
2015-03-24 00:40:33 +00:00
|
|
|
|
2009-04-29 07:47:10 +00:00
|
|
|
return r;
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void polymost_initosdfuncs(void)
|
|
|
|
{
|
2009-04-29 06:20:07 +00:00
|
|
|
uint32_t i;
|
|
|
|
|
2017-06-27 02:24:14 +00:00
|
|
|
static osdcvardata_t cvars_polymost[] =
|
2009-04-29 06:20:07 +00:00
|
|
|
{
|
2018-10-10 15:08:08 +00:00
|
|
|
{ "r_enablepolymost2","enable/disable polymost2",(void *) &r_enablepolymost2, CVAR_BOOL, 0, 0 }, //POGO: temporarily disable this variable
|
2018-03-21 20:41:26 +00:00
|
|
|
{ "r_pogoDebug","",(void *) &r_pogoDebug, CVAR_BOOL | CVAR_NOSAVE, 0, 1 },
|
2013-05-17 03:43:20 +00:00
|
|
|
{ "r_animsmoothing","enable/disable model animation smoothing",(void *) &r_animsmoothing, CVAR_BOOL, 0, 1 },
|
|
|
|
{ "r_downsize","controls downsizing factor (quality) for hires textures",(void *) &r_downsize, CVAR_INT|CVAR_FUNCPTR, 0, 5 },
|
|
|
|
{ "r_fullbrights","enable/disable fullbright textures",(void *) &r_fullbrights, CVAR_BOOL, 0, 1 },
|
2015-02-11 05:23:04 +00:00
|
|
|
{ "r_parallaxskyclamping","enable/disable parallaxed floor/ceiling sky texture clamping", (void *) &r_parallaxskyclamping, CVAR_BOOL, 0, 1 },
|
|
|
|
{ "r_parallaxskypanning","enable/disable parallaxed floor/ceiling panning when drawing a parallaxing sky", (void *) &r_parallaxskypanning, CVAR_BOOL, 0, 1 },
|
|
|
|
|
2016-01-08 01:33:20 +00:00
|
|
|
#ifdef USE_GLEXT
|
2015-02-11 05:23:04 +00:00
|
|
|
{ "r_detailmapping","enable/disable detail mapping",(void *) &r_detailmapping, CVAR_BOOL, 0, 1 },
|
2013-05-17 03:43:20 +00:00
|
|
|
{ "r_glowmapping","enable/disable glow mapping",(void *) &r_glowmapping, CVAR_BOOL, 0, 1 },
|
2016-01-08 01:33:20 +00:00
|
|
|
#endif
|
|
|
|
#ifndef EDUKE32_GLES
|
2015-03-24 00:40:33 +00:00
|
|
|
{ "r_polygonmode","debugging feature",(void *) &r_polygonmode, CVAR_INT | CVAR_NOSAVE, 0, 3 },
|
2015-02-11 05:23:04 +00:00
|
|
|
{ "r_texcache","enable/disable OpenGL compressed texture cache",(void *) &glusetexcache, CVAR_INT, 0, 2 },
|
|
|
|
{ "r_memcache","enable/disable texture cache memory cache",(void *) &glusememcache, CVAR_BOOL, 0, 1 },
|
|
|
|
#endif
|
2016-03-28 05:16:14 +00:00
|
|
|
{ "r_texcompr","enable/disable OpenGL texture compression: 0: off 1: hightile only 2: ART and hightile",(void *) &glusetexcompr, CVAR_INT, 0, 2 },
|
2015-02-11 05:23:04 +00:00
|
|
|
|
2013-05-17 03:43:20 +00:00
|
|
|
{ "r_shadescale","multiplier for shading",(void *) &shadescale, CVAR_FLOAT, 0, 10 },
|
|
|
|
{ "r_shadescale_unbounded","enable/disable allowance of complete blackness",(void *) &shadescale_unbounded, CVAR_BOOL, 0, 1 },
|
|
|
|
{ "r_swapinterval","sets the GL swap interval (VSync)",(void *) &vsync, CVAR_INT|CVAR_FUNCPTR, -1, 1 },
|
2014-06-01 11:55:19 +00:00
|
|
|
{
|
|
|
|
"r_npotwallmode", "enable/disable emulation of walls with non-power-of-two height textures (Polymost, r_hightile 0)",
|
2019-03-19 17:08:43 +00:00
|
|
|
(void *) &r_npotwallmode, CVAR_INT, 0, 2
|
2014-06-01 11:55:19 +00:00
|
|
|
},
|
2015-03-24 00:40:33 +00:00
|
|
|
{ "r_anisotropy", "changes the OpenGL texture anisotropy setting", (void *) &glanisotropy, CVAR_INT|CVAR_FUNCPTR, 0, 16 },
|
2013-05-17 03:43:20 +00:00
|
|
|
{ "r_texturemaxsize","changes the maximum OpenGL texture size limit",(void *) &gltexmaxsize, CVAR_INT | CVAR_NOSAVE, 0, 4096 },
|
|
|
|
{ "r_texturemiplevel","changes the highest OpenGL mipmap level used",(void *) &gltexmiplevel, CVAR_INT, 0, 6 },
|
2018-02-16 06:38:05 +00:00
|
|
|
{ "r_texfilter", "changes the texture filtering settings (may require restart)", (void *) &gltexfiltermode, CVAR_INT|CVAR_FUNCPTR, 0, 5 },
|
2018-03-21 20:41:26 +00:00
|
|
|
{ "r_useindexedcolortextures", "enable/disable indexed color texture rendering", (void *) &r_useindexedcolortextures, CVAR_INT, 0, 1 },
|
2014-03-30 20:36:00 +00:00
|
|
|
|
|
|
|
{ "r_usenewshading",
|
2017-11-29 07:29:33 +00:00
|
|
|
"visibility/fog code: 0: orig. Polymost 1: 07/2011 2: linear 12/2012 3: no neg. start 03/2014 4: base constant on shade table 11/2017",
|
|
|
|
(void *) &r_usenewshading, CVAR_INT|CVAR_FUNCPTR, 0, 4
|
2014-03-30 20:36:00 +00:00
|
|
|
},
|
|
|
|
|
2013-08-06 23:51:38 +00:00
|
|
|
{ "r_usetileshades", "enable/disable Polymost tile shade textures", (void *) &r_usetileshades, CVAR_INT | CVAR_INVALIDATEART, 0, 2 },
|
2015-05-26 00:48:04 +00:00
|
|
|
{ "r_projectionhack", "enable/disable projection hack", (void *) &glprojectionhacks, CVAR_INT, 0, 1 },
|
2009-04-29 06:20:07 +00:00
|
|
|
|
|
|
|
|
2014-04-14 16:30:23 +00:00
|
|
|
#ifdef __ANDROID__
|
|
|
|
{ "r_models","enable/disable model rendering",(void *) &usemodels, CVAR_BOOL | CVAR_NOSAVE, 0, 1 },
|
|
|
|
#else
|
2013-05-17 03:43:20 +00:00
|
|
|
{ "r_models","enable/disable model rendering",(void *) &usemodels, CVAR_BOOL, 0, 1 },
|
2014-04-14 16:30:23 +00:00
|
|
|
#endif
|
2015-01-11 04:56:58 +00:00
|
|
|
{ "r_nofog", "enable/disable GL fog", (void *)&nofog, CVAR_BOOL, 0, 1},
|
2013-05-17 03:43:20 +00:00
|
|
|
{ "r_hightile","enable/disable hightile texture rendering",(void *) &usehightile, CVAR_BOOL, 0, 1 },
|
2010-09-06 23:08:35 +00:00
|
|
|
|
2013-05-17 03:43:20 +00:00
|
|
|
{ "r_preview_mouseaim", "toggles mouse aiming preview, use this to calibrate yxaspect in Polymost Mapster32", (void *) &preview_mouseaim, CVAR_BOOL, 0, 1 },
|
2009-04-29 06:20:07 +00:00
|
|
|
};
|
|
|
|
|
2014-03-22 09:25:15 +00:00
|
|
|
for (i=0; i<ARRAY_SIZE(cvars_polymost); i++)
|
2018-10-25 23:31:30 +00:00
|
|
|
OSD_RegisterCvar(&cvars_polymost[i], (cvars_polymost[i].flags & CVAR_FUNCPTR) ? osdcmd_cvar_set_polymost : osdcmd_cvar_set);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 09:29:17 +00:00
|
|
|
void polymost_precache(int32_t dapicnum, int32_t dapalnum, int32_t datype)
|
2006-04-13 20:47:06 +00:00
|
|
|
{
|
2006-04-24 19:04:22 +00:00
|
|
|
// dapicnum and dapalnum are like you'd expect
|
|
|
|
// datype is 0 for a wall/floor/ceiling and 1 for a sprite
|
|
|
|
// basically this just means walls are repeating
|
|
|
|
// while sprites are clamped
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-04-12 21:03:12 +00:00
|
|
|
if (videoGetRenderMode() < REND_POLYMOST) return;
|
2018-10-25 23:31:05 +00:00
|
|
|
if ((dapalnum < (MAXPALOOKUPS - RESERVEDPALS)) && (palookup[dapalnum] == NULL)) return;//dapalnum = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2006-04-24 19:04:22 +00:00
|
|
|
//OSD_Printf("precached %d %d type %d\n", dapicnum, dapalnum, datype);
|
|
|
|
hicprecaching = 1;
|
2015-12-04 11:52:58 +00:00
|
|
|
texcache_fetch(dapicnum, dapalnum, 0, (datype & 1)*(DAMETH_CLAMPED|DAMETH_MASK));
|
2006-04-24 19:04:22 +00:00
|
|
|
hicprecaching = 0;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2010-03-11 23:35:22 +00:00
|
|
|
if (datype == 0 || !usemodels) return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-10-25 23:31:05 +00:00
|
|
|
int const mid = md_tilehasmodel(dapicnum, dapalnum);
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2015-12-23 04:05:51 +00:00
|
|
|
if (mid < 0 || models[mid]->mdnum < 2) return;
|
2006-04-13 20:47:06 +00:00
|
|
|
|
2018-10-25 23:31:05 +00:00
|
|
|
int const surfaces = (models[mid]->mdnum == 3) ? ((md3model_t *)models[mid])->head.numsurfs : 0;
|
2006-04-24 19:04:22 +00:00
|
|
|
|
2018-10-25 23:31:05 +00:00
|
|
|
for (int i = 0; i <= surfaces; i++)
|
|
|
|
mdloadskin((md2model_t *)models[mid], 0, dapalnum, i);
|
2006-04-13 20:47:06 +00:00
|
|
|
}
|
|
|
|
|
2011-09-28 20:30:24 +00:00
|
|
|
#else /* if !defined USE_OPENGL */
|
2008-12-02 10:44:39 +00:00
|
|
|
|
2013-01-08 06:17:10 +00:00
|
|
|
#include "compat.h"
|
|
|
|
|
2008-12-02 10:44:39 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2006-04-13 20:47:06 +00:00
|
|
|
// vim:ts=4:sw=4:
|