2020-01-23 23:12:15 +00:00
// SONIC ROBO BLAST 2
2014-03-15 16:59:03 +00:00
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
2020-01-23 23:12:15 +00:00
// Copyright (C) 1999-2020 by Sonic Team Junior.
2014-03-15 16:59:03 +00:00
//
2020-01-23 23:12:15 +00:00
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
2014-03-15 16:59:03 +00:00
//-----------------------------------------------------------------------------
2020-01-23 23:12:15 +00:00
/// \file hw_main.c
2014-03-15 16:59:03 +00:00
/// \brief hardware renderer, using the standard HardWareRender driver DLL for SRB2
# include <math.h>
# include "../doomstat.h"
# ifdef HWRENDER
# include "hw_glob.h"
# include "hw_light.h"
# include "hw_drv.h"
# include "../i_video.h" // for rendermode == render_glide
# include "../v_video.h"
# include "../p_local.h"
# include "../p_setup.h"
# include "../r_local.h"
2019-10-28 18:28:42 +00:00
# include "../r_patch.h"
2014-03-15 16:59:03 +00:00
# include "../r_bsp.h"
# include "../d_clisrv.h"
# include "../w_wad.h"
# include "../z_zone.h"
# include "../r_splats.h"
# include "../g_game.h"
# include "../st_stuff.h"
# include "../i_system.h"
# include "../m_cheat.h"
2019-11-05 15:10:42 +00:00
# include "../f_finale.h"
2020-01-16 17:37:32 +00:00
# include "../r_things.h" // R_GetShadowZ
2016-01-17 04:10:38 +00:00
# ifdef ESLOPE
# include "../p_slopes.h"
# endif
2014-03-15 16:59:03 +00:00
# include "hw_md2.h"
2017-01-10 18:01:03 +00:00
# ifdef NEWCLIP
# include "hw_clip.h"
# endif
2014-03-15 16:59:03 +00:00
# define R_FAKEFLOORS
2016-10-27 22:41:24 +00:00
# define HWPRECIP
2014-03-15 16:59:03 +00:00
//#define POLYSKY
// ==========================================================================
// the hardware driver object
// ==========================================================================
struct hwdriver_s hwdriver ;
// ==========================================================================
// PROTOS
// ==========================================================================
static void HWR_AddSprites ( sector_t * sec ) ;
static void HWR_ProjectSprite ( mobj_t * thing ) ;
# ifdef HWPRECIP
static void HWR_ProjectPrecipitationSprite ( precipmobj_t * thing ) ;
# endif
2019-12-25 19:22:01 +00:00
void HWR_AddTransparentFloor ( levelflat_t * levelflat , extrasubsector_t * xsub , boolean isceiling , fixed_t fixedheight , INT32 lightlevel , INT32 alpha , sector_t * FOFSector , FBITFIELD blend , boolean fogplane , extracolormap_t * planecolormap ) ;
2019-11-09 01:58:41 +00:00
void HWR_AddTransparentPolyobjectFloor ( levelflat_t * levelflat , polyobj_t * polysector , boolean isceiling , fixed_t fixedheight ,
2014-10-27 20:57:45 +00:00
INT32 lightlevel , INT32 alpha , sector_t * FOFSector , FBITFIELD blend , extracolormap_t * planecolormap ) ;
2019-12-25 19:22:01 +00:00
2014-03-15 16:59:03 +00:00
boolean drawsky = true ;
// ==========================================================================
// VIEW GLOBALS
// ==========================================================================
// Fineangles in the SCREENWIDTH wide window.
# define FIELDOFVIEW ANGLE_90
# define ABS(x) ((x) < 0 ? -(x) : (x))
static angle_t gr_clipangle ;
// The viewangletox[viewangle + FINEANGLES/4] lookup
// maps the visible view angles to screen X coordinates,
// flattening the arc to a flat projection plane.
// There will be many angles mapped to the same X.
static INT32 gr_viewangletox [ FINEANGLES / 2 ] ;
// The xtoviewangleangle[] table maps a screen pixel
// to the lowest viewangle that maps back to x ranges
// from clipangle to -clipangle.
static angle_t gr_xtoviewangle [ MAXVIDWIDTH + 1 ] ;
// ==========================================================================
// GLOBALS
// ==========================================================================
// uncomment to remove the plane rendering
# define DOPLANES
//#define DOWALLS
// test of drawing sky by polygons like in software with visplane, unfortunately
// this doesn't work since we must have z for pixel and z for texture (not like now with z = oow)
//#define POLYSKY
// test change fov when looking up/down but bsp projection messup :(
//#define NOCRAPPYMLOOK
// base values set at SetViewSize
static float gr_basecentery ;
float gr_baseviewwindowy , gr_basewindowcentery ;
float gr_viewwidth , gr_viewheight ; // viewport clipping boundaries (screen coords)
float gr_viewwindowx ;
static float gr_centerx , gr_centery ;
static float gr_viewwindowy ; // top left corner of view window
static float gr_windowcenterx ; // center of view window, for projection
static float gr_windowcentery ;
static float gr_pspritexscale , gr_pspriteyscale ;
static seg_t * gr_curline ;
static side_t * gr_sidedef ;
static line_t * gr_linedef ;
static sector_t * gr_frontsector ;
static sector_t * gr_backsector ;
// --------------------------------------------------------------------------
// STUFF FOR THE PROJECTION CODE
// --------------------------------------------------------------------------
FTransform atransform ;
// duplicates of the main code, set after R_SetupFrame() passed them into sharedstruct,
// copied here for local use
static fixed_t dup_viewx , dup_viewy , dup_viewz ;
static angle_t dup_viewangle ;
static float gr_viewx , gr_viewy , gr_viewz ;
static float gr_viewsin , gr_viewcos ;
// Maybe not necessary with the new T&L code (needs to be checked!)
static float gr_viewludsin , gr_viewludcos ; // look up down kik test
static float gr_fovlud ;
2020-01-23 22:44:46 +00:00
static angle_t gr_aimingangle ;
2020-02-08 20:42:26 +00:00
static void HWR_SetTransformAiming ( FTransform * trans , player_t * player , boolean skybox ) ;
2020-01-23 22:44:46 +00:00
2020-04-18 22:25:28 +00:00
// render stats
int rs_prevframetime = 0 ;
int rs_rendercalltime = 0 ;
int rs_bsptime = 0 ;
int rs_nodetime = 0 ;
int rs_nodesorttime = 0 ;
int rs_nodedrawtime = 0 ;
int rs_spritesorttime = 0 ;
int rs_spritedrawtime = 0 ;
int rs_numdrawnodes = 0 ;
int rs_numbspcalls = 0 ;
int rs_numsprites = 0 ;
int rs_numpolyobjects = 0 ;
//int rs_posttime = 0;
//int rs_swaptime = 0;
2014-03-15 16:59:03 +00:00
// ==========================================================================
2019-12-25 19:22:01 +00:00
// Lighting
2014-03-15 16:59:03 +00:00
// ==========================================================================
2019-12-25 19:22:01 +00:00
void HWR_Lighting ( FSurfaceInfo * Surface , INT32 light_level , extracolormap_t * colormap )
{
RGBA_t poly_color , tint_color , fade_color ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
poly_color . rgba = 0xFFFFFFFF ;
tint_color . rgba = ( colormap ! = NULL ) ? ( UINT32 ) colormap - > rgba : GL_DEFAULTMIX ;
fade_color . rgba = ( colormap ! = NULL ) ? ( UINT32 ) colormap - > fadergba : GL_DEFAULTFOG ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
// Crappy backup coloring if you can't do shaders
if ( ! cv_grshaders . value )
2014-03-15 16:59:03 +00:00
{
2019-12-25 19:22:01 +00:00
// be careful, this may get negative for high lightlevel values.
float tint_alpha , fade_alpha ;
float red , green , blue ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
red = ( float ) poly_color . s . red ;
green = ( float ) poly_color . s . green ;
blue = ( float ) poly_color . s . blue ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
// 48 is just an arbritrary value that looked relatively okay.
tint_alpha = ( float ) ( sqrt ( tint_color . s . alpha ) * 48 ) / 255.0f ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
// 8 is roughly the brightness of the "close" color in Software, and 16 the brightness of the "far" color.
// 8 is too bright for dark levels, and 16 is too dark for bright levels.
// 12 is the compromise value. It doesn't look especially good anywhere, but it's the most balanced.
// (Also, as far as I can tell, fade_color's alpha is actually not used in Software, so we only use light level.)
fade_alpha = ( float ) ( sqrt ( 255 - light_level ) * 12 ) / 255.0f ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
// Clamp the alpha values
tint_alpha = min ( max ( tint_alpha , 0.0f ) , 1.0f ) ;
fade_alpha = min ( max ( fade_alpha , 0.0f ) , 1.0f ) ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
red = ( tint_color . s . red * tint_alpha ) + ( red * ( 1.0f - tint_alpha ) ) ;
green = ( tint_color . s . green * tint_alpha ) + ( green * ( 1.0f - tint_alpha ) ) ;
blue = ( tint_color . s . blue * tint_alpha ) + ( blue * ( 1.0f - tint_alpha ) ) ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
red = ( fade_color . s . red * fade_alpha ) + ( red * ( 1.0f - fade_alpha ) ) ;
green = ( fade_color . s . green * fade_alpha ) + ( green * ( 1.0f - fade_alpha ) ) ;
blue = ( fade_color . s . blue * fade_alpha ) + ( blue * ( 1.0f - fade_alpha ) ) ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
poly_color . s . red = ( UINT8 ) red ;
poly_color . s . green = ( UINT8 ) green ;
poly_color . s . blue = ( UINT8 ) blue ;
2014-03-15 16:59:03 +00:00
}
2019-12-25 19:22:01 +00:00
Surface - > PolyColor . rgba = poly_color . rgba ;
Surface - > TintColor . rgba = tint_color . rgba ;
Surface - > FadeColor . rgba = fade_color . rgba ;
Surface - > LightInfo . light_level = light_level ;
Surface - > LightInfo . fade_start = ( colormap ! = NULL ) ? colormap - > fadestart : 0 ;
Surface - > LightInfo . fade_end = ( colormap ! = NULL ) ? colormap - > fadeend : 31 ;
}
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
UINT8 HWR_FogBlockAlpha ( INT32 light , extracolormap_t * colormap ) // Let's see if this can work
2014-03-15 16:59:03 +00:00
{
2018-03-15 23:58:37 +00:00
RGBA_t realcolor , surfcolor ;
INT32 alpha ;
2014-03-15 16:59:03 +00:00
2020-01-08 01:55:36 +00:00
realcolor . rgba = ( colormap ! = NULL ) ? colormap - > rgba : GL_DEFAULTMIX ;
2019-12-25 19:22:01 +00:00
2020-01-08 01:55:36 +00:00
if ( cv_grshaders . value )
{
surfcolor . s . alpha = ( 255 - light ) ;
}
else
{
light = light - ( 255 - light ) ;
2014-03-24 17:11:45 +00:00
2020-01-08 01:55:36 +00:00
// Don't go out of bounds
if ( light < 0 )
light = 0 ;
else if ( light > 255 )
light = 255 ;
2014-03-15 16:59:03 +00:00
2020-01-08 01:55:36 +00:00
alpha = ( realcolor . s . alpha * 255 ) / 25 ;
2014-03-15 16:59:03 +00:00
2020-01-08 01:55:36 +00:00
// at 255 brightness, alpha is between 0 and 127, at 0 brightness alpha will always be 255
surfcolor . s . alpha = ( alpha * light ) / ( 2 * 256 ) + 255 - light ;
}
2014-03-15 16:59:03 +00:00
return surfcolor . s . alpha ;
}
2020-01-16 21:45:49 +00:00
static FUINT HWR_CalcWallLight ( FUINT lightnum , fixed_t v1x , fixed_t v1y , fixed_t v2x , fixed_t v2y )
{
INT16 finallight = lightnum ;
if ( cv_grfakecontrast . value ! = 0 )
{
const UINT8 contrast = 8 ;
fixed_t extralight = 0 ;
if ( cv_grfakecontrast . value = = 2 ) // Smooth setting
{
extralight = ( - ( contrast < < FRACBITS ) +
FixedDiv ( AngleFixed ( R_PointToAngle2 ( 0 , 0 ,
abs ( v1x - v2x ) ,
abs ( v1y - v2y ) ) ) , 90 < < FRACBITS )
* ( contrast * 2 ) ) > > FRACBITS ;
}
else
{
if ( v1y = = v2y )
extralight = - contrast ;
else if ( v1x = = v2x )
extralight = contrast ;
}
if ( extralight ! = 0 )
{
finallight + = extralight ;
if ( finallight < 0 )
finallight = 0 ;
if ( finallight > 255 )
finallight = 255 ;
}
}
return ( FUINT ) finallight ;
}
static FUINT HWR_CalcSlopeLight ( FUINT lightnum , angle_t dir , fixed_t delta )
{
INT16 finallight = lightnum ;
if ( cv_grfakecontrast . value ! = 0 & & cv_grslopecontrast . value ! = 0 )
{
const UINT8 contrast = 8 ;
fixed_t extralight = 0 ;
if ( cv_grfakecontrast . value = = 2 ) // Smooth setting
{
fixed_t dirmul = abs ( FixedDiv ( AngleFixed ( dir ) - ( 180 < < FRACBITS ) , 180 < < FRACBITS ) ) ;
extralight = - ( contrast < < FRACBITS ) + ( dirmul * ( contrast * 2 ) ) ;
extralight = FixedMul ( extralight , delta * 4 ) > > FRACBITS ;
}
else
{
dir = ( ( dir + ANGLE_45 ) / ANGLE_90 ) * ANGLE_90 ;
if ( dir = = ANGLE_180 )
extralight = - contrast ;
else if ( dir = = 0 )
extralight = contrast ;
if ( delta > = FRACUNIT / 2 )
extralight * = 2 ;
}
if ( extralight ! = 0 )
{
finallight + = extralight ;
if ( finallight < 0 )
finallight = 0 ;
if ( finallight > 255 )
finallight = 255 ;
}
}
return ( FUINT ) finallight ;
}
2014-03-15 16:59:03 +00:00
// ==========================================================================
// FLOOR/CEILING GENERATION FROM SUBSECTORS
// ==========================================================================
# ifdef DOPLANES
// -----------------+
// HWR_RenderPlane : Render a floor or ceiling convex polygon
// -----------------+
2020-04-25 05:10:30 +00:00
static void HWR_RenderPlane ( subsector_t * subsector , extrasubsector_t * xsub , boolean isceiling , fixed_t fixedheight , FBITFIELD PolyFlags , INT32 lightlevel , levelflat_t * levelflat , sector_t * FOFsector , UINT8 alpha , extracolormap_t * planecolormap )
2014-03-15 16:59:03 +00:00
{
polyvertex_t * pv ;
float height ; //constant y for all points on the convex flat polygon
FOutVector * v3d ;
INT32 nrPlaneVerts ; //verts original define of convex flat polygon
INT32 i ;
float flatxref , flatyref ;
2019-11-09 02:42:15 +00:00
float fflatwidth = 64.0f , fflatheight = 64.0f ;
INT32 flatflag = 63 ;
2019-11-09 01:58:41 +00:00
boolean texflat = false ;
2014-03-15 16:59:03 +00:00
size_t len ;
float scrollx = 0.0f , scrolly = 0.0f ;
angle_t angle = 0 ;
FSurfaceInfo Surf ;
fixed_t tempxsow , tempytow ;
2016-01-17 04:10:38 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
pslope_t * slope = NULL ;
2016-01-17 04:10:38 +00:00
# endif
2014-03-15 16:59:03 +00:00
static FOutVector * planeVerts = NULL ;
static UINT16 numAllocedPlaneVerts = 0 ;
// no convex poly were generated for this subsector
if ( ! xsub - > planepoly )
return ;
2016-01-17 04:10:38 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
// Get the slope pointer to simplify future code
if ( FOFsector )
{
2016-07-27 18:56:21 +00:00
if ( FOFsector - > f_slope & & ! isceiling )
2016-01-28 13:56:23 +00:00
slope = FOFsector - > f_slope ;
2016-07-27 18:56:21 +00:00
else if ( FOFsector - > c_slope & & isceiling )
2016-01-28 13:56:23 +00:00
slope = FOFsector - > c_slope ;
}
else
{
2016-07-27 18:56:21 +00:00
if ( gr_frontsector - > f_slope & & ! isceiling )
2016-01-28 13:56:23 +00:00
slope = gr_frontsector - > f_slope ;
2016-07-27 18:56:21 +00:00
else if ( gr_frontsector - > c_slope & & isceiling )
2016-01-28 13:56:23 +00:00
slope = gr_frontsector - > c_slope ;
}
// Set fixedheight to the slope's height from our viewpoint, if we have a slope
if ( slope )
fixedheight = P_GetZAt ( slope , viewx , viewy ) ;
2016-01-17 04:10:38 +00:00
# endif
2014-03-15 16:59:03 +00:00
height = FIXED_TO_FLOAT ( fixedheight ) ;
pv = xsub - > planepoly - > pts ;
nrPlaneVerts = xsub - > planepoly - > numpts ;
if ( nrPlaneVerts < 3 ) //not even a triangle ?
return ;
// Allocate plane-vertex buffer if we need to
if ( ! planeVerts | | nrPlaneVerts > numAllocedPlaneVerts )
{
numAllocedPlaneVerts = ( UINT16 ) nrPlaneVerts ;
Z_Free ( planeVerts ) ;
Z_Malloc ( numAllocedPlaneVerts * sizeof ( FOutVector ) , PU_LEVEL , & planeVerts ) ;
}
2019-11-09 02:42:15 +00:00
// set texture for polygon
if ( levelflat ! = NULL )
2014-03-15 16:59:03 +00:00
{
2019-11-09 02:42:15 +00:00
if ( levelflat - > type = = LEVELFLAT_TEXTURE )
2019-11-09 01:58:41 +00:00
{
2019-11-09 02:42:15 +00:00
fflatwidth = textures [ levelflat - > u . texture . num ] - > width ;
fflatheight = textures [ levelflat - > u . texture . num ] - > height ;
texflat = true ;
2019-11-09 01:58:41 +00:00
}
2019-11-09 02:42:15 +00:00
else if ( levelflat - > type = = LEVELFLAT_FLAT )
{
len = W_LumpLength ( levelflat - > u . flat . lumpnum ) ;
2014-03-15 16:59:03 +00:00
2019-11-09 02:42:15 +00:00
switch ( len )
{
case 4194304 : // 2048x2048 lump
fflatwidth = fflatheight = 2048.0f ;
break ;
case 1048576 : // 1024x1024 lump
fflatwidth = fflatheight = 1024.0f ;
break ;
case 262144 : // 512x512 lump
fflatwidth = fflatheight = 512.0f ;
break ;
case 65536 : // 256x256 lump
fflatwidth = fflatheight = 256.0f ;
break ;
case 16384 : // 128x128 lump
fflatwidth = fflatheight = 128.0f ;
break ;
case 1024 : // 32x32 lump
fflatwidth = fflatheight = 32.0f ;
break ;
default : // 64x64 lump
fflatwidth = fflatheight = 64.0f ;
break ;
}
2019-05-21 03:28:52 +00:00
2019-11-09 02:42:15 +00:00
flatflag = ( ( INT32 ) fflatwidth ) - 1 ;
}
2019-05-26 19:22:33 +00:00
}
2019-11-09 02:42:15 +00:00
else // set no texture
HWD . pfnSetTexture ( NULL ) ;
2019-05-21 03:28:52 +00:00
2014-03-15 16:59:03 +00:00
// reference point for flat texture coord for each vertex around the polygon
2019-05-26 19:22:33 +00:00
flatxref = ( float ) ( ( ( fixed_t ) pv - > x & ( ~ flatflag ) ) / fflatwidth ) ;
flatyref = ( float ) ( ( ( fixed_t ) pv - > y & ( ~ flatflag ) ) / fflatheight ) ;
2014-03-15 16:59:03 +00:00
// transform
if ( FOFsector ! = NULL )
{
2016-07-27 18:56:21 +00:00
if ( ! isceiling ) // it's a floor
2014-03-15 16:59:03 +00:00
{
2019-05-21 03:28:52 +00:00
scrollx = FIXED_TO_FLOAT ( FOFsector - > floor_xoffs ) / fflatwidth ;
scrolly = FIXED_TO_FLOAT ( FOFsector - > floor_yoffs ) / fflatheight ;
2017-03-30 20:57:36 +00:00
angle = FOFsector - > floorpic_angle ;
2014-03-15 16:59:03 +00:00
}
else // it's a ceiling
{
2019-05-21 03:28:52 +00:00
scrollx = FIXED_TO_FLOAT ( FOFsector - > ceiling_xoffs ) / fflatwidth ;
scrolly = FIXED_TO_FLOAT ( FOFsector - > ceiling_yoffs ) / fflatheight ;
2017-03-30 20:57:36 +00:00
angle = FOFsector - > ceilingpic_angle ;
2014-03-15 16:59:03 +00:00
}
}
else if ( gr_frontsector )
{
2016-07-27 18:56:21 +00:00
if ( ! isceiling ) // it's a floor
2014-03-15 16:59:03 +00:00
{
2019-05-21 03:28:52 +00:00
scrollx = FIXED_TO_FLOAT ( gr_frontsector - > floor_xoffs ) / fflatwidth ;
scrolly = FIXED_TO_FLOAT ( gr_frontsector - > floor_yoffs ) / fflatheight ;
2017-03-30 20:57:36 +00:00
angle = gr_frontsector - > floorpic_angle ;
2014-03-15 16:59:03 +00:00
}
else // it's a ceiling
{
2019-05-21 03:28:52 +00:00
scrollx = FIXED_TO_FLOAT ( gr_frontsector - > ceiling_xoffs ) / fflatwidth ;
scrolly = FIXED_TO_FLOAT ( gr_frontsector - > ceiling_yoffs ) / fflatheight ;
2017-03-30 20:57:36 +00:00
angle = gr_frontsector - > ceilingpic_angle ;
2014-03-15 16:59:03 +00:00
}
}
2019-12-25 19:22:01 +00:00
2014-03-15 16:59:03 +00:00
if ( angle ) // Only needs to be done if there's an altered angle
{
2019-12-25 19:22:01 +00:00
angle = ( InvAngle ( angle ) + ANGLE_180 ) > > ANGLETOFINESHIFT ;
// This needs to be done so that it scrolls in a different direction after rotation like software
/*tempxsow = FLOAT_TO_FIXED(scrollx);
tempytow = FLOAT_TO_FIXED ( scrolly ) ;
scrollx = ( FIXED_TO_FLOAT ( FixedMul ( tempxsow , FINECOSINE ( angle ) ) - FixedMul ( tempytow , FINESINE ( angle ) ) ) ) ;
scrolly = ( FIXED_TO_FLOAT ( FixedMul ( tempxsow , FINESINE ( angle ) ) + FixedMul ( tempytow , FINECOSINE ( angle ) ) ) ) ; */
2014-03-15 16:59:03 +00:00
// This needs to be done so everything aligns after rotation
// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
tempxsow = FLOAT_TO_FIXED ( flatxref ) ;
tempytow = FLOAT_TO_FIXED ( flatyref ) ;
flatxref = ( FIXED_TO_FLOAT ( FixedMul ( tempxsow , FINECOSINE ( angle ) ) - FixedMul ( tempytow , FINESINE ( angle ) ) ) ) ;
flatyref = ( FIXED_TO_FLOAT ( FixedMul ( tempxsow , FINESINE ( angle ) ) + FixedMul ( tempytow , FINECOSINE ( angle ) ) ) ) ;
}
2020-03-22 17:13:59 +00:00
# define SETUP3DVERT(vert, vx, vy) {\
/* Hurdler: add scrolling texture on floor/ceiling */ \
if ( texflat ) \
{ \
2020-04-25 05:10:30 +00:00
vert - > s = ( float ) ( ( vx ) / fflatwidth ) + scrollx ; \
vert - > t = - ( float ) ( ( vy ) / fflatheight ) + scrolly ; \
2020-03-22 17:13:59 +00:00
} \
else \
{ \
2020-04-25 05:10:30 +00:00
vert - > s = ( float ) ( ( ( vx ) / fflatwidth ) - flatxref + scrollx ) ; \
vert - > t = ( float ) ( flatyref - ( ( vy ) / fflatheight ) + scrolly ) ; \
2020-03-22 17:13:59 +00:00
} \
\
/* Need to rotate before translate */ \
if ( angle ) /* Only needs to be done if there's an altered angle */ \
{ \
2020-04-25 05:10:30 +00:00
tempxsow = FLOAT_TO_FIXED ( vert - > s ) ; \
tempytow = FLOAT_TO_FIXED ( vert - > t ) ; \
2020-03-22 17:13:59 +00:00
if ( texflat ) \
tempytow = - tempytow ; \
2020-04-25 05:10:30 +00:00
vert - > s = ( FIXED_TO_FLOAT ( FixedMul ( tempxsow , FINECOSINE ( angle ) ) - FixedMul ( tempytow , FINESINE ( angle ) ) ) ) ; \
vert - > t = ( FIXED_TO_FLOAT ( FixedMul ( tempxsow , FINESINE ( angle ) ) + FixedMul ( tempytow , FINECOSINE ( angle ) ) ) ) ; \
2020-03-22 17:13:59 +00:00
} \
\
vert - > x = ( vx ) ; \
vert - > y = height ; \
vert - > z = ( vy ) ; \
\
if ( slope ) \
{ \
fixedheight = P_GetZAt ( slope , FLOAT_TO_FIXED ( ( vx ) ) , FLOAT_TO_FIXED ( ( vy ) ) ) ; \
vert - > y = FIXED_TO_FLOAT ( fixedheight ) ; \
} \
}
2019-12-25 19:22:01 +00:00
2020-03-22 17:13:59 +00:00
for ( i = 0 , v3d = planeVerts ; i < nrPlaneVerts ; i + + , v3d + + , pv + + )
SETUP3DVERT ( v3d , pv - > x , pv - > y ) ;
2014-03-15 16:59:03 +00:00
2020-01-16 21:45:49 +00:00
# ifdef ESLOPE
if ( slope )
lightlevel = HWR_CalcSlopeLight ( lightlevel , R_PointToAngle2 ( 0 , 0 , slope - > normal . x , slope - > normal . y ) , abs ( slope - > zdelta ) ) ;
# endif
2019-12-25 19:22:01 +00:00
HWR_Lighting ( & Surf , lightlevel , planecolormap ) ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
if ( PolyFlags & ( PF_Translucent | PF_Fog ) )
2014-03-15 16:59:03 +00:00
{
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = ( UINT8 ) alpha ;
PolyFlags | = PF_Modulated ;
2014-03-15 16:59:03 +00:00
}
else
2019-12-25 19:22:01 +00:00
PolyFlags | = PF_Masked | PF_Modulated ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
if ( PolyFlags & PF_Fog )
HWD . pfnSetShader ( 6 ) ; // fog shader
else if ( PolyFlags & PF_Ripple )
HWD . pfnSetShader ( 5 ) ; // water shader
2014-03-15 16:59:03 +00:00
else
2019-12-25 19:22:01 +00:00
HWD . pfnSetShader ( 1 ) ; // floor shader
2014-03-15 16:59:03 +00:00
HWD . pfnDrawPolygon ( & Surf , planeVerts , nrPlaneVerts , PolyFlags ) ;
2020-03-22 17:13:59 +00:00
if ( subsector )
{
// Horizon lines
2020-03-22 17:20:26 +00:00
FOutVector horizonpts [ 6 ] ;
2020-03-22 17:13:59 +00:00
float dist , vx , vy ;
2020-03-22 17:52:17 +00:00
float x1 , y1 , xd , yd ;
UINT8 numplanes , j ;
vertex_t v ; // For determining the closest distance from the line to the camera, to split render planes for minimum distortion;
2020-03-23 13:23:36 +00:00
const float renderdist = 27000.0f ; // How far out to properly render the plane
2020-03-22 17:20:26 +00:00
const float farrenderdist = 32768.0f ; // From here, raise plane to horizon level to fill in the line with some texture distortion
2020-03-22 17:13:59 +00:00
seg_t * line = & segs [ subsector - > firstline ] ;
for ( i = 0 ; i < subsector - > numlines ; i + + , line + + )
{
if ( ! line - > glseg & & line - > linedef - > special = = HORIZONSPECIAL & & R_PointOnSegSide ( dup_viewx , dup_viewy , line ) = = 0 )
{
2020-03-22 17:52:17 +00:00
P_ClosestPointOnLine ( viewx , viewy , line - > linedef , & v ) ;
dist = FIXED_TO_FLOAT ( R_PointToDist ( v . x , v . y ) ) ;
x1 = ( ( polyvertex_t * ) line - > pv1 ) - > x ;
y1 = ( ( polyvertex_t * ) line - > pv1 ) - > y ;
xd = ( ( polyvertex_t * ) line - > pv2 ) - > x - x1 ;
yd = ( ( polyvertex_t * ) line - > pv2 ) - > y - y1 ;
// Based on the seg length and the distance from the line, split horizon into multiple poly sets to reduce distortion
dist = sqrtf ( ( xd * xd ) + ( yd * yd ) ) / dist / 16.0f ;
if ( dist > 100.0f )
numplanes = 100 ;
else
numplanes = ( UINT8 ) dist + 1 ;
for ( j = 0 ; j < numplanes ; j + + )
{
// Left side
vx = x1 + xd * j / numplanes ;
vy = y1 + yd * j / numplanes ;
SETUP3DVERT ( ( & horizonpts [ 1 ] ) , vx , vy ) ;
dist = sqrtf ( powf ( vx - gr_viewx , 2 ) + powf ( vy - gr_viewy , 2 ) ) ;
vx = ( vx - gr_viewx ) * renderdist / dist + gr_viewx ;
vy = ( vy - gr_viewy ) * renderdist / dist + gr_viewy ;
SETUP3DVERT ( ( & horizonpts [ 0 ] ) , vx , vy ) ;
// Right side
vx = x1 + xd * ( j + 1 ) / numplanes ;
vy = y1 + yd * ( j + 1 ) / numplanes ;
SETUP3DVERT ( ( & horizonpts [ 2 ] ) , vx , vy ) ;
dist = sqrtf ( powf ( vx - gr_viewx , 2 ) + powf ( vy - gr_viewy , 2 ) ) ;
vx = ( vx - gr_viewx ) * renderdist / dist + gr_viewx ;
vy = ( vy - gr_viewy ) * renderdist / dist + gr_viewy ;
SETUP3DVERT ( ( & horizonpts [ 3 ] ) , vx , vy ) ;
// Horizon fills
vx = ( horizonpts [ 0 ] . x - gr_viewx ) * farrenderdist / renderdist + gr_viewx ;
vy = ( horizonpts [ 0 ] . z - gr_viewy ) * farrenderdist / renderdist + gr_viewy ;
SETUP3DVERT ( ( & horizonpts [ 5 ] ) , vx , vy ) ;
horizonpts [ 5 ] . y = gr_viewz ;
vx = ( horizonpts [ 3 ] . x - gr_viewx ) * farrenderdist / renderdist + gr_viewx ;
vy = ( horizonpts [ 3 ] . z - gr_viewy ) * farrenderdist / renderdist + gr_viewy ;
SETUP3DVERT ( ( & horizonpts [ 4 ] ) , vx , vy ) ;
horizonpts [ 4 ] . y = gr_viewz ;
// Draw
HWD . pfnDrawPolygon ( & Surf , horizonpts , 6 , PolyFlags ) ;
}
2020-03-22 17:13:59 +00:00
}
}
}
2014-03-15 16:59:03 +00:00
# ifdef ALAM_LIGHTING
// add here code for dynamic lighting on planes
HWR_PlaneLighting ( planeVerts , nrPlaneVerts ) ;
# endif
}
# ifdef POLYSKY
// this don't draw anything it only update the z-buffer so there isn't problem with
// wall/things upper that sky (map12)
static void HWR_RenderSkyPlane ( extrasubsector_t * xsub , fixed_t fixedheight )
{
polyvertex_t * pv ;
float height ; //constant y for all points on the convex flat polygon
FOutVector * v3d ;
INT32 nrPlaneVerts ; //verts original define of convex flat polygon
INT32 i ;
// no convex poly were generated for this subsector
if ( ! xsub - > planepoly )
return ;
height = FIXED_TO_FLOAT ( fixedheight ) ;
pv = xsub - > planepoly - > pts ;
nrPlaneVerts = xsub - > planepoly - > numpts ;
if ( nrPlaneVerts < 3 ) // not even a triangle?
return ;
if ( nrPlaneVerts > MAXPLANEVERTICES ) // FIXME: exceeds plVerts size
{
CONS_Debug ( DBG_RENDER , " polygon size of %d exceeds max value of %d vertices \n " , nrPlaneVerts , MAXPLANEVERTICES ) ;
return ;
}
// transform
v3d = planeVerts ;
for ( i = 0 ; i < nrPlaneVerts ; i + + , v3d + + , pv + + )
{
2019-12-25 19:22:01 +00:00
v3d - > s = 0.0f ;
v3d - > t = 0.0f ;
2014-03-15 16:59:03 +00:00
v3d - > x = pv - > x ;
v3d - > y = height ;
v3d - > z = pv - > y ;
}
HWD . pfnDrawPolygon ( NULL , planeVerts , nrPlaneVerts ,
PF_Clip | PF_Invisible | PF_NoTexture | PF_Occlude ) ;
}
# endif //polysky
# endif //doplanes
/*
wallVerts order is :
3 - - 2
| / |
| / |
0 - - 1
*/
# ifdef WALLSPLATS
static void HWR_DrawSegsSplats ( FSurfaceInfo * pSurf )
{
2019-12-25 19:22:01 +00:00
FOutVector wallVerts [ 4 ] ;
2014-03-15 16:59:03 +00:00
wallsplat_t * splat ;
GLPatch_t * gpatch ;
fixed_t i ;
// seg bbox
fixed_t segbbox [ 4 ] ;
M_ClearBox ( segbbox ) ;
M_AddToBox ( segbbox ,
2016-11-07 21:55:56 +00:00
FLOAT_TO_FIXED ( ( ( polyvertex_t * ) gr_curline - > pv1 ) - > x ) ,
FLOAT_TO_FIXED ( ( ( polyvertex_t * ) gr_curline - > pv1 ) - > y ) ) ;
2014-03-15 16:59:03 +00:00
M_AddToBox ( segbbox ,
2016-11-07 21:55:56 +00:00
FLOAT_TO_FIXED ( ( ( polyvertex_t * ) gr_curline - > pv2 ) - > x ) ,
FLOAT_TO_FIXED ( ( ( polyvertex_t * ) gr_curline - > pv2 ) - > y ) ) ;
2014-03-15 16:59:03 +00:00
splat = ( wallsplat_t * ) gr_curline - > linedef - > splats ;
for ( ; splat ; splat = splat - > next )
{
//BP: don't draw splat extern to this seg
// this is quick fix best is explain in logboris.txt at 12-4-2000
if ( ! M_PointInBox ( segbbox , splat - > v1 . x , splat - > v1 . y ) & & ! M_PointInBox ( segbbox , splat - > v2 . x , splat - > v2 . y ) )
continue ;
2019-09-08 21:27:35 +00:00
gpatch = W_CachePatchNum ( splat - > patch , PU_PATCH ) ;
2014-03-15 16:59:03 +00:00
HWR_GetPatch ( gpatch ) ;
wallVerts [ 0 ] . x = wallVerts [ 3 ] . x = FIXED_TO_FLOAT ( splat - > v1 . x ) ;
wallVerts [ 0 ] . z = wallVerts [ 3 ] . z = FIXED_TO_FLOAT ( splat - > v1 . y ) ;
wallVerts [ 2 ] . x = wallVerts [ 1 ] . x = FIXED_TO_FLOAT ( splat - > v2 . x ) ;
wallVerts [ 2 ] . z = wallVerts [ 1 ] . z = FIXED_TO_FLOAT ( splat - > v2 . y ) ;
i = splat - > top ;
if ( splat - > yoffset )
i + = * splat - > yoffset ;
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( i ) + ( gpatch - > height > > 1 ) ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( i ) - ( gpatch - > height > > 1 ) ;
wallVerts [ 3 ] . s = wallVerts [ 3 ] . t = wallVerts [ 2 ] . s = wallVerts [ 0 ] . t = 0.0f ;
wallVerts [ 1 ] . s = wallVerts [ 1 ] . t = wallVerts [ 2 ] . t = wallVerts [ 0 ] . s = 1.0f ;
switch ( splat - > flags & SPLATDRAWMODE_MASK )
{
case SPLATDRAWMODE_OPAQUE :
2019-12-25 19:22:01 +00:00
pSurf . PolyColor . s . alpha = 0xff ;
2014-03-15 16:59:03 +00:00
i = PF_Translucent ;
break ;
case SPLATDRAWMODE_TRANS :
2019-12-25 19:22:01 +00:00
pSurf . PolyColor . s . alpha = 128 ;
2014-03-15 16:59:03 +00:00
i = PF_Translucent ;
break ;
case SPLATDRAWMODE_SHADE :
2019-12-25 19:22:01 +00:00
pSurf . PolyColor . s . alpha = 0xff ;
2014-03-15 16:59:03 +00:00
i = PF_Substractive ;
break ;
}
2019-12-25 19:22:01 +00:00
HWD . pfnSetShader ( 2 ) ; // wall shader
HWD . pfnDrawPolygon ( & pSurf , wallVerts , 4 , i | PF_Modulated | PF_Decal ) ;
2014-03-15 16:59:03 +00:00
}
}
# endif
FBITFIELD HWR_TranstableToAlpha ( INT32 transtablenum , FSurfaceInfo * pSurf )
{
switch ( transtablenum )
{
2019-12-25 19:22:01 +00:00
case tr_trans10 : pSurf - > PolyColor . s . alpha = 0xe6 ; return PF_Translucent ;
case tr_trans20 : pSurf - > PolyColor . s . alpha = 0xcc ; return PF_Translucent ;
case tr_trans30 : pSurf - > PolyColor . s . alpha = 0xb3 ; return PF_Translucent ;
case tr_trans40 : pSurf - > PolyColor . s . alpha = 0x99 ; return PF_Translucent ;
case tr_trans50 : pSurf - > PolyColor . s . alpha = 0x80 ; return PF_Translucent ;
case tr_trans60 : pSurf - > PolyColor . s . alpha = 0x66 ; return PF_Translucent ;
case tr_trans70 : pSurf - > PolyColor . s . alpha = 0x4c ; return PF_Translucent ;
case tr_trans80 : pSurf - > PolyColor . s . alpha = 0x33 ; return PF_Translucent ;
case tr_trans90 : pSurf - > PolyColor . s . alpha = 0x19 ; return PF_Translucent ;
2014-03-15 16:59:03 +00:00
}
return PF_Translucent ;
}
2019-12-25 19:22:01 +00:00
static void HWR_AddTransparentWall ( FOutVector * wallVerts , FSurfaceInfo * pSurf , INT32 texnum , FBITFIELD blend , boolean fogwall , INT32 lightlevel , extracolormap_t * wallcolormap ) ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
// ==========================================================================
// Wall generation from subsector segs
// ==========================================================================
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
//
// HWR_ProjectWall
//
static void HWR_ProjectWall ( FOutVector * wallVerts , FSurfaceInfo * pSurf , FBITFIELD blendmode , INT32 lightlevel , extracolormap_t * wallcolormap )
2014-03-15 16:59:03 +00:00
{
2019-12-25 19:22:01 +00:00
HWR_Lighting ( pSurf , lightlevel , wallcolormap ) ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
HWD . pfnSetShader ( 2 ) ; // wall shader
HWD . pfnDrawPolygon ( pSurf , wallVerts , 4 , blendmode | PF_Modulated | PF_Occlude ) ;
2014-03-15 16:59:03 +00:00
# ifdef WALLSPLATS
if ( gr_curline - > linedef - > splats & & cv_splats . value )
HWR_DrawSegsSplats ( pSurf ) ;
# endif
}
// ==========================================================================
// BSP, CULL, ETC..
// ==========================================================================
// return the frac from the interception of the clipping line
// (in fact a clipping plane that has a constant, so can clip with simple 2d)
// with the wall segment
//
2017-01-10 18:01:03 +00:00
# ifndef NEWCLIP
2014-03-15 16:59:03 +00:00
static float HWR_ClipViewSegment ( INT32 x , polyvertex_t * v1 , polyvertex_t * v2 )
{
float num , den ;
float v1x , v1y , v1dx , v1dy , v2dx , v2dy ;
angle_t pclipangle = gr_xtoviewangle [ x ] ;
// a segment of a polygon
v1x = v1 - > x ;
v1y = v1 - > y ;
v1dx = ( v2 - > x - v1 - > x ) ;
v1dy = ( v2 - > y - v1 - > y ) ;
// the clipping line
pclipangle = pclipangle + dup_viewangle ; //back to normal angle (non-relative)
v2dx = FIXED_TO_FLOAT ( FINECOSINE ( pclipangle > > ANGLETOFINESHIFT ) ) ;
v2dy = FIXED_TO_FLOAT ( FINESINE ( pclipangle > > ANGLETOFINESHIFT ) ) ;
den = v2dy * v1dx - v2dx * v1dy ;
if ( den = = 0 )
return - 1 ; // parallel
// calc the frac along the polygon segment,
//num = (v2x - v1x)*v2dy + (v1y - v2y)*v2dx;
//num = -v1x * v2dy + v1y * v2dx;
num = ( gr_viewx - v1x ) * v2dy + ( v1y - gr_viewy ) * v2dx ;
return num / den ;
}
2017-01-10 18:01:03 +00:00
# endif
2014-03-15 16:59:03 +00:00
//
// HWR_SplitWall
//
2019-12-25 19:22:01 +00:00
static void HWR_SplitWall ( sector_t * sector , FOutVector * wallVerts , INT32 texnum , FSurfaceInfo * Surf , INT32 cutflag , ffloor_t * pfloor )
2014-03-15 16:59:03 +00:00
{
/* SoM: split up and light walls according to the
lightlist . This may also include leaving out parts
of the wall that can ' t be seen */
2016-01-27 06:00:15 +00:00
2014-03-15 16:59:03 +00:00
float realtop , realbot , top , bot ;
float pegt , pegb , pegmul ;
float height = 0.0f , bheight = 0.0f ;
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
float endrealtop , endrealbot , endtop , endbot ;
float endpegt , endpegb , endpegmul ;
float endheight = 0.0f , endbheight = 0.0f ;
2016-01-28 13:56:23 +00:00
// compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly
// use this as a temp var to store P_GetZAt's return value each time
fixed_t temp ;
2016-01-27 06:00:15 +00:00
# endif
2019-12-26 01:09:31 +00:00
fixed_t v1x = FLOAT_TO_FIXED ( wallVerts [ 0 ] . x ) ;
fixed_t v1y = FLOAT_TO_FIXED ( wallVerts [ 0 ] . z ) ; // not a typo
fixed_t v2x = FLOAT_TO_FIXED ( wallVerts [ 1 ] . x ) ;
fixed_t v2y = FLOAT_TO_FIXED ( wallVerts [ 1 ] . z ) ; // not a typo
INT32 solid , i ;
2014-03-15 16:59:03 +00:00
lightlist_t * list = sector - > lightlist ;
2019-12-25 19:22:01 +00:00
const UINT8 alpha = Surf - > PolyColor . s . alpha ;
2019-12-26 01:09:31 +00:00
FUINT lightnum = HWR_CalcWallLight ( sector - > lightlevel , v1x , v1y , v2x , v2y ) ;
2018-03-20 14:20:02 +00:00
extracolormap_t * colormap = NULL ;
2014-03-15 16:59:03 +00:00
2016-01-27 06:00:15 +00:00
realtop = top = wallVerts [ 3 ] . y ;
2014-03-15 16:59:03 +00:00
realbot = bot = wallVerts [ 0 ] . y ;
2016-01-27 06:00:15 +00:00
pegt = wallVerts [ 3 ] . t ;
2014-03-15 16:59:03 +00:00
pegb = wallVerts [ 0 ] . t ;
pegmul = ( pegb - pegt ) / ( top - bot ) ;
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
endrealtop = endtop = wallVerts [ 2 ] . y ;
endrealbot = endbot = wallVerts [ 1 ] . y ;
endpegt = wallVerts [ 2 ] . t ;
endpegb = wallVerts [ 1 ] . t ;
endpegmul = ( endpegb - endpegt ) / ( endtop - endbot ) ;
# endif
2018-03-20 14:20:02 +00:00
for ( i = 0 ; i < sector - > numlights ; i + + )
2014-03-15 16:59:03 +00:00
{
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
2019-12-25 19:22:01 +00:00
if ( endtop < endrealbot )
2016-01-27 06:00:15 +00:00
# endif
2014-03-15 16:59:03 +00:00
if ( top < realbot )
return ;
2018-03-20 14:20:02 +00:00
if ( ! ( list [ i ] . flags & FF_NOSHADE ) )
{
if ( pfloor & & ( pfloor - > flags & FF_FOG ) )
{
2019-12-26 01:09:31 +00:00
lightnum = HWR_CalcWallLight ( pfloor - > master - > frontsector - > lightlevel , v1x , v1y , v2x , v2y ) ;
2018-03-20 14:20:02 +00:00
colormap = pfloor - > master - > frontsector - > extra_colormap ;
}
else
{
2019-12-26 01:09:31 +00:00
lightnum = HWR_CalcWallLight ( * list [ i ] . lightlevel , v1x , v1y , v2x , v2y ) ;
2018-09-12 20:28:55 +00:00
colormap = * list [ i ] . extra_colormap ;
2018-03-20 14:20:02 +00:00
}
}
2014-03-15 16:59:03 +00:00
solid = false ;
2018-03-20 14:20:02 +00:00
if ( ( sector - > lightlist [ i ] . flags & FF_CUTSOLIDS ) & & ! ( cutflag & FF_EXTRA ) )
solid = true ;
else if ( ( sector - > lightlist [ i ] . flags & FF_CUTEXTRA ) & & ( cutflag & FF_EXTRA ) )
2014-03-15 16:59:03 +00:00
{
2018-03-20 14:20:02 +00:00
if ( sector - > lightlist [ i ] . flags & FF_EXTRA )
2014-03-15 16:59:03 +00:00
{
2018-03-20 14:20:02 +00:00
if ( ( sector - > lightlist [ i ] . flags & ( FF_FOG | FF_SWIMMABLE ) ) = = ( cutflag & ( FF_FOG | FF_SWIMMABLE ) ) ) // Only merge with your own types
2014-03-15 16:59:03 +00:00
solid = true ;
}
else
2018-03-20 14:20:02 +00:00
solid = true ;
2014-03-15 16:59:03 +00:00
}
else
solid = false ;
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
if ( list [ i ] . slope )
{
temp = P_GetZAt ( list [ i ] . slope , v1x , v1y ) ;
height = FIXED_TO_FLOAT ( temp ) ;
temp = P_GetZAt ( list [ i ] . slope , v2x , v2y ) ;
endheight = FIXED_TO_FLOAT ( temp ) ;
}
else
height = endheight = FIXED_TO_FLOAT ( list [ i ] . height ) ;
2016-01-27 06:00:15 +00:00
if ( solid )
2016-01-28 13:56:23 +00:00
{
if ( * list [ i ] . caster - > b_slope )
{
temp = P_GetZAt ( * list [ i ] . caster - > b_slope , v1x , v1y ) ;
bheight = FIXED_TO_FLOAT ( temp ) ;
temp = P_GetZAt ( * list [ i ] . caster - > b_slope , v2x , v2y ) ;
endbheight = FIXED_TO_FLOAT ( temp ) ;
}
else
bheight = endbheight = FIXED_TO_FLOAT ( * list [ i ] . caster - > bottomheight ) ;
}
2016-01-27 06:00:15 +00:00
# else
2014-03-15 16:59:03 +00:00
height = FIXED_TO_FLOAT ( list [ i ] . height ) ;
if ( solid )
bheight = FIXED_TO_FLOAT ( * list [ i ] . caster - > bottomheight ) ;
2016-01-27 06:00:15 +00:00
# endif
2014-03-15 16:59:03 +00:00
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
if ( endheight > = endtop )
2016-01-27 06:00:15 +00:00
# endif
2014-03-15 16:59:03 +00:00
if ( height > = top )
{
if ( solid & & top > bheight )
top = bheight ;
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
if ( solid & & endtop > endbheight )
endtop = endbheight ;
2016-01-27 06:00:15 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
2018-03-20 14:20:02 +00:00
# ifdef ESLOPE
if ( i + 1 < sector - > numlights )
{
if ( list [ i + 1 ] . slope )
{
temp = P_GetZAt ( list [ i + 1 ] . slope , v1x , v1y ) ;
bheight = FIXED_TO_FLOAT ( temp ) ;
temp = P_GetZAt ( list [ i + 1 ] . slope , v2x , v2y ) ;
endbheight = FIXED_TO_FLOAT ( temp ) ;
}
else
bheight = endbheight = FIXED_TO_FLOAT ( list [ i + 1 ] . height ) ;
}
else
{
bheight = realbot ;
endbheight = endrealbot ;
}
# else
if ( i + 1 < sector - > numlights )
{
bheight = FIXED_TO_FLOAT ( list [ i + 1 ] . height ) ;
}
else
{
bheight = realbot ;
}
# endif
2018-03-22 00:52:14 +00:00
# ifdef ESLOPE
2018-03-20 14:20:02 +00:00
if ( endbheight > = endtop )
2018-03-22 00:52:14 +00:00
# endif
2018-03-20 14:20:02 +00:00
if ( bheight > = top )
continue ;
2014-03-15 16:59:03 +00:00
//Found a break;
2018-03-20 14:20:02 +00:00
bot = bheight ;
2014-03-15 16:59:03 +00:00
if ( bot < realbot )
bot = realbot ;
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
2018-03-20 14:20:02 +00:00
endbot = endbheight ;
2016-01-27 06:00:15 +00:00
2016-01-28 13:56:23 +00:00
if ( endbot < endrealbot )
endbot = endrealbot ;
2016-01-27 06:00:15 +00:00
# endif
2019-12-25 19:22:01 +00:00
Surf - > PolyColor . s . alpha = alpha ;
2014-03-15 16:59:03 +00:00
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
wallVerts [ 3 ] . t = pegt + ( ( realtop - top ) * pegmul ) ;
wallVerts [ 2 ] . t = endpegt + ( ( endrealtop - endtop ) * endpegmul ) ;
wallVerts [ 0 ] . t = pegt + ( ( realtop - bot ) * pegmul ) ;
wallVerts [ 1 ] . t = endpegt + ( ( endrealtop - endbot ) * endpegmul ) ;
2014-03-15 16:59:03 +00:00
2016-01-27 06:00:15 +00:00
// set top/bottom coords
wallVerts [ 3 ] . y = top ;
wallVerts [ 2 ] . y = endtop ;
wallVerts [ 0 ] . y = bot ;
2016-01-28 13:56:23 +00:00
wallVerts [ 1 ] . y = endbot ;
2016-01-27 06:00:15 +00:00
# else
2014-03-15 16:59:03 +00:00
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = pegt + ( ( realtop - top ) * pegmul ) ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = pegt + ( ( realtop - bot ) * pegmul ) ;
// set top/bottom coords
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = top ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = bot ;
2016-01-27 06:00:15 +00:00
# endif
2014-03-15 16:59:03 +00:00
2018-03-20 14:20:02 +00:00
if ( cutflag & FF_FOG )
HWR_AddTransparentWall ( wallVerts , Surf , texnum , PF_Fog | PF_NoTexture , true , lightnum , colormap ) ;
else if ( cutflag & FF_TRANSLUCENT )
2014-03-15 16:59:03 +00:00
HWR_AddTransparentWall ( wallVerts , Surf , texnum , PF_Translucent , false , lightnum , colormap ) ;
else
HWR_ProjectWall ( wallVerts , Surf , PF_Masked , lightnum , colormap ) ;
2018-03-20 14:20:02 +00:00
top = bot ;
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
2018-03-20 14:20:02 +00:00
endtop = endbot ;
2016-01-27 06:00:15 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
bot = realbot ;
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
endbot = endrealbot ;
if ( endtop < = endrealbot )
2016-01-27 06:00:15 +00:00
# endif
2014-03-15 16:59:03 +00:00
if ( top < = realbot )
return ;
2019-12-25 19:22:01 +00:00
Surf - > PolyColor . s . alpha = alpha ;
2014-03-15 16:59:03 +00:00
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
wallVerts [ 3 ] . t = pegt + ( ( realtop - top ) * pegmul ) ;
wallVerts [ 2 ] . t = endpegt + ( ( endrealtop - endtop ) * endpegmul ) ;
wallVerts [ 0 ] . t = pegt + ( ( realtop - bot ) * pegmul ) ;
wallVerts [ 1 ] . t = endpegt + ( ( endrealtop - endbot ) * endpegmul ) ;
2014-03-15 16:59:03 +00:00
// set top/bottom coords
2016-01-28 13:56:23 +00:00
wallVerts [ 3 ] . y = top ;
wallVerts [ 2 ] . y = endtop ;
wallVerts [ 0 ] . y = bot ;
wallVerts [ 1 ] . y = endbot ;
2016-01-27 06:00:15 +00:00
# else
2019-12-25 19:22:01 +00:00
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = pegt + ( ( realtop - top ) * pegmul ) ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = pegt + ( ( realtop - bot ) * pegmul ) ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
// set top/bottom coords
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = top ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = bot ;
2016-01-27 06:00:15 +00:00
# endif
2014-03-15 16:59:03 +00:00
2018-03-20 14:20:02 +00:00
if ( cutflag & FF_FOG )
HWR_AddTransparentWall ( wallVerts , Surf , texnum , PF_Fog | PF_NoTexture , true , lightnum , colormap ) ;
else if ( cutflag & FF_TRANSLUCENT )
2014-03-15 16:59:03 +00:00
HWR_AddTransparentWall ( wallVerts , Surf , texnum , PF_Translucent , false , lightnum , colormap ) ;
else
HWR_ProjectWall ( wallVerts , Surf , PF_Masked , lightnum , colormap ) ;
}
2018-02-01 22:04:04 +00:00
// HWR_DrawSkyWall
2014-09-08 22:29:05 +00:00
// Draw walls into the depth buffer so that anything behind is culled properly
2019-12-25 19:22:01 +00:00
static void HWR_DrawSkyWall ( FOutVector * wallVerts , FSurfaceInfo * Surf , fixed_t bottom , fixed_t top )
2014-09-08 22:29:05 +00:00
{
HWD . pfnSetTexture ( NULL ) ;
// no texture
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = 0 ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = 0 ;
wallVerts [ 0 ] . s = wallVerts [ 3 ] . s = 0 ;
wallVerts [ 2 ] . s = wallVerts [ 1 ] . s = 0 ;
2019-12-25 19:22:01 +00:00
// set top/bottom coords
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( top ) ; // No real way to find the correct height of this
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( bottom ) ; // worldlow/bottom because it needs to cover up the lower thok barrier wall
HWR_ProjectWall ( wallVerts , Surf , PF_Invisible | PF_NoTexture , 255 , NULL ) ;
2014-09-08 22:29:05 +00:00
// PF_Invisible so it's not drawn into the colour buffer
// PF_NoTexture for no texture
// PF_Occlude is set in HWR_ProjectWall to draw into the depth buffer
}
2014-03-15 16:59:03 +00:00
//
2019-12-25 19:22:01 +00:00
// HWR_ProcessSeg
2014-03-15 16:59:03 +00:00
// A portion or all of a wall segment will be drawn, from startfrac to endfrac,
// where 0 is the start of the segment, 1 the end of the segment
// Anything between means the wall segment has been clipped with solidsegs,
// reducing wall overdraw to a minimum
//
2017-01-10 18:01:03 +00:00
static void HWR_ProcessSeg ( void ) // Sort of like GLWall::Process in GZDoom
2014-03-15 16:59:03 +00:00
{
2019-12-25 19:22:01 +00:00
FOutVector wallVerts [ 4 ] ;
2014-03-15 16:59:03 +00:00
v2d_t vs , ve ; // start, end vertices of 2d line (view from above)
fixed_t worldtop , worldbottom ;
fixed_t worldhigh = 0 , worldlow = 0 ;
2016-01-17 04:10:38 +00:00
# ifdef ESLOPE
fixed_t worldtopslope , worldbottomslope ;
fixed_t worldhighslope = 0 , worldlowslope = 0 ;
fixed_t v1x , v1y , v2x , v2y ;
# endif
2014-03-15 16:59:03 +00:00
GLTexture_t * grTex = NULL ;
float cliplow = 0.0f , cliphigh = 0.0f ;
INT32 gr_midtexture ;
fixed_t h , l ; // 3D sides and 2s middle textures
2016-01-25 05:57:53 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
fixed_t hS , lS ;
2016-01-25 05:57:53 +00:00
# endif
2014-03-15 16:59:03 +00:00
FUINT lightnum = 0 ; // shut up compiler
extracolormap_t * colormap ;
FSurfaceInfo Surf ;
gr_sidedef = gr_curline - > sidedef ;
gr_linedef = gr_curline - > linedef ;
2016-11-07 21:55:56 +00:00
vs . x = ( ( polyvertex_t * ) gr_curline - > pv1 ) - > x ;
vs . y = ( ( polyvertex_t * ) gr_curline - > pv1 ) - > y ;
ve . x = ( ( polyvertex_t * ) gr_curline - > pv2 ) - > x ;
ve . y = ( ( polyvertex_t * ) gr_curline - > pv2 ) - > y ;
2016-01-17 04:10:38 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
v1x = FLOAT_TO_FIXED ( vs . x ) ;
v1y = FLOAT_TO_FIXED ( vs . y ) ;
v2x = FLOAT_TO_FIXED ( ve . x ) ;
v2y = FLOAT_TO_FIXED ( ve . y ) ;
2016-01-17 04:10:38 +00:00
# endif
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
2017-01-12 21:43:37 +00:00
# define SLOPEPARAMS(slope, end1, end2, normalheight) \
if ( slope ) { \
end1 = P_GetZAt ( slope , v1x , v1y ) ; \
end2 = P_GetZAt ( slope , v2x , v2y ) ; \
} else \
end1 = end2 = normalheight ;
SLOPEPARAMS ( gr_frontsector - > c_slope , worldtop , worldtopslope , gr_frontsector - > ceilingheight )
SLOPEPARAMS ( gr_frontsector - > f_slope , worldbottom , worldbottomslope , gr_frontsector - > floorheight )
2016-01-17 04:10:38 +00:00
# else
2017-01-12 21:43:37 +00:00
worldtop = gr_frontsector - > ceilingheight ;
worldbottom = gr_frontsector - > floorheight ;
2016-01-17 04:10:38 +00:00
# endif
2014-03-15 16:59:03 +00:00
// remember vertices ordering
// 3--2
// | /|
// |/ |
// 0--1
// make a wall polygon (with 2 triangles), using the floor/ceiling heights,
// and the 2d map coords of start/end vertices
wallVerts [ 0 ] . x = wallVerts [ 3 ] . x = vs . x ;
wallVerts [ 0 ] . z = wallVerts [ 3 ] . z = vs . y ;
wallVerts [ 2 ] . x = wallVerts [ 1 ] . x = ve . x ;
wallVerts [ 2 ] . z = wallVerts [ 1 ] . z = ve . y ;
2019-12-25 19:22:01 +00:00
// x offset the texture
2014-03-15 16:59:03 +00:00
{
fixed_t texturehpeg = gr_sidedef - > textureoffset + gr_curline - > offset ;
2019-12-25 19:22:01 +00:00
cliplow = ( float ) texturehpeg ;
cliphigh = ( float ) ( texturehpeg + ( gr_curline - > flength * FRACUNIT ) ) ;
2014-03-15 16:59:03 +00:00
}
2019-12-26 01:09:31 +00:00
lightnum = HWR_CalcWallLight ( gr_frontsector - > lightlevel , vs . x , vs . y , ve . x , ve . y ) ;
2014-03-15 16:59:03 +00:00
colormap = gr_frontsector - > extra_colormap ;
if ( gr_frontsector )
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = 255 ;
2014-03-15 16:59:03 +00:00
if ( gr_backsector )
{
2019-12-25 19:22:01 +00:00
INT32 gr_toptexture , gr_bottomtexture ;
2014-03-15 16:59:03 +00:00
// two sided line
2016-01-17 04:10:38 +00:00
2017-01-12 21:43:37 +00:00
# ifdef ESLOPE
SLOPEPARAMS ( gr_backsector - > c_slope , worldhigh , worldhighslope , gr_backsector - > ceilingheight )
SLOPEPARAMS ( gr_backsector - > f_slope , worldlow , worldlowslope , gr_backsector - > floorheight )
# undef SLOPEPARAMS
2016-01-17 04:10:38 +00:00
# else
2017-01-12 21:43:37 +00:00
worldhigh = gr_backsector - > ceilingheight ;
worldlow = gr_backsector - > floorheight ;
2016-01-17 04:10:38 +00:00
# endif
2014-03-15 16:59:03 +00:00
// hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky
2019-12-25 19:22:01 +00:00
if ( gr_frontsector - > ceilingpic = = skyflatnum & &
gr_backsector - > ceilingpic = = skyflatnum )
2018-02-03 19:48:18 +00:00
{
2019-12-25 19:22:01 +00:00
worldtop = worldhigh ;
# ifdef ESLOPE
worldtopslope = worldhighslope ;
# endif
2018-02-03 19:48:18 +00:00
}
2019-12-25 19:22:01 +00:00
gr_toptexture = R_GetTextureNum ( gr_sidedef - > toptexture ) ;
gr_bottomtexture = R_GetTextureNum ( gr_sidedef - > bottomtexture ) ;
2016-12-16 21:38:53 +00:00
2014-03-15 16:59:03 +00:00
// check TOP TEXTURE
2016-01-17 04:10:38 +00:00
if ( (
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
worldhighslope < worldtopslope | |
2016-01-17 04:10:38 +00:00
# endif
worldhigh < worldtop
2016-12-16 21:38:53 +00:00
) & & gr_toptexture )
2014-03-15 16:59:03 +00:00
{
{
fixed_t texturevpegtop ; // top
2016-12-16 21:38:53 +00:00
grTex = HWR_GetTexture ( gr_toptexture ) ;
2014-03-15 16:59:03 +00:00
// PEGGING
if ( gr_linedef - > flags & ML_DONTPEGTOP )
texturevpegtop = 0 ;
2016-01-17 04:10:38 +00:00
# ifdef ESLOPE
else if ( gr_linedef - > flags & ML_EFFECT1 )
2014-03-15 16:59:03 +00:00
texturevpegtop = worldhigh + textureheight [ gr_sidedef - > toptexture ] - worldtop ;
2016-01-17 04:10:38 +00:00
else
texturevpegtop = gr_backsector - > ceilingheight + textureheight [ gr_sidedef - > toptexture ] - gr_frontsector - > ceilingheight ;
# else
else
texturevpegtop = worldhigh + textureheight [ gr_sidedef - > toptexture ] - worldtop ;
# endif
2014-03-15 16:59:03 +00:00
texturevpegtop + = gr_sidedef - > rowoffset ;
2014-03-28 23:28:00 +00:00
// This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway
2016-12-16 21:38:53 +00:00
texturevpegtop % = SHORT ( textures [ gr_toptexture ] - > height ) < < FRACBITS ;
2014-03-28 23:28:00 +00:00
2014-03-15 16:59:03 +00:00
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = texturevpegtop * grTex - > scaleY ;
2016-01-17 04:10:38 +00:00
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = ( texturevpegtop + gr_frontsector - > ceilingheight - gr_backsector - > ceilingheight ) * grTex - > scaleY ;
2014-03-15 16:59:03 +00:00
wallVerts [ 0 ] . s = wallVerts [ 3 ] . s = cliplow * grTex - > scaleX ;
wallVerts [ 2 ] . s = wallVerts [ 1 ] . s = cliphigh * grTex - > scaleX ;
2016-01-17 04:10:38 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
// Adjust t value for sloped walls
if ( ! ( gr_linedef - > flags & ML_EFFECT1 ) )
{
// Unskewed
wallVerts [ 3 ] . t - = ( worldtop - gr_frontsector - > ceilingheight ) * grTex - > scaleY ;
wallVerts [ 2 ] . t - = ( worldtopslope - gr_frontsector - > ceilingheight ) * grTex - > scaleY ;
wallVerts [ 0 ] . t - = ( worldhigh - gr_backsector - > ceilingheight ) * grTex - > scaleY ;
wallVerts [ 1 ] . t - = ( worldhighslope - gr_backsector - > ceilingheight ) * grTex - > scaleY ;
}
else if ( gr_linedef - > flags & ML_DONTPEGTOP )
{
// Skewed by top
wallVerts [ 0 ] . t = ( texturevpegtop + worldtop - worldhigh ) * grTex - > scaleY ;
wallVerts [ 1 ] . t = ( texturevpegtop + worldtopslope - worldhighslope ) * grTex - > scaleY ;
}
else
{
// Skewed by bottom
2016-06-01 18:22:54 +00:00
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = ( texturevpegtop + worldtop - worldhigh ) * grTex - > scaleY ;
wallVerts [ 3 ] . t = wallVerts [ 0 ] . t - ( worldtop - worldhigh ) * grTex - > scaleY ;
wallVerts [ 2 ] . t = wallVerts [ 1 ] . t - ( worldtopslope - worldhighslope ) * grTex - > scaleY ;
2016-01-28 13:56:23 +00:00
}
2016-01-17 04:10:38 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
// set top/bottom coords
2016-01-17 04:10:38 +00:00
# ifdef ESLOPE
wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( worldtop ) ;
wallVerts [ 0 ] . y = FIXED_TO_FLOAT ( worldhigh ) ;
wallVerts [ 2 ] . y = FIXED_TO_FLOAT ( worldtopslope ) ;
wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( worldhighslope ) ;
# else
2014-03-15 16:59:03 +00:00
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( worldtop ) ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( worldhigh ) ;
2016-01-17 04:10:38 +00:00
# endif
2014-03-15 16:59:03 +00:00
if ( gr_frontsector - > numlights )
2018-03-20 14:20:02 +00:00
HWR_SplitWall ( gr_frontsector , wallVerts , gr_toptexture , & Surf , FF_CUTLEVEL , NULL ) ;
2014-03-15 16:59:03 +00:00
else if ( grTex - > mipmap . flags & TF_TRANSPARENT )
2016-12-16 21:38:53 +00:00
HWR_AddTransparentWall ( wallVerts , & Surf , gr_toptexture , PF_Environment , false , lightnum , colormap ) ;
2014-03-15 16:59:03 +00:00
else
HWR_ProjectWall ( wallVerts , & Surf , PF_Masked , lightnum , colormap ) ;
}
// check BOTTOM TEXTURE
2016-01-17 04:10:38 +00:00
if ( (
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
worldlowslope > worldbottomslope | |
2016-01-17 04:10:38 +00:00
# endif
2016-12-16 21:38:53 +00:00
worldlow > worldbottom ) & & gr_bottomtexture ) //only if VISIBLE!!!
2014-03-15 16:59:03 +00:00
{
{
fixed_t texturevpegbottom = 0 ; // bottom
2016-12-16 21:38:53 +00:00
grTex = HWR_GetTexture ( gr_bottomtexture ) ;
2014-03-15 16:59:03 +00:00
// PEGGING
2016-01-24 08:41:30 +00:00
# ifdef ESLOPE
if ( ! ( gr_linedef - > flags & ML_DONTPEGBOTTOM ) )
texturevpegbottom = 0 ;
else if ( gr_linedef - > flags & ML_EFFECT1 )
2016-06-01 17:51:38 +00:00
texturevpegbottom = worldbottom - worldlow ;
2014-03-15 16:59:03 +00:00
else
2016-06-01 17:51:38 +00:00
texturevpegbottom = gr_frontsector - > floorheight - gr_backsector - > floorheight ;
2016-01-24 08:41:30 +00:00
# else
if ( gr_linedef - > flags & ML_DONTPEGBOTTOM )
2016-06-01 17:51:38 +00:00
texturevpegbottom = worldbottom - worldlow ;
2016-01-24 08:41:30 +00:00
else
texturevpegbottom = 0 ;
# endif
2014-03-15 16:59:03 +00:00
texturevpegbottom + = gr_sidedef - > rowoffset ;
2014-03-28 23:28:00 +00:00
// This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway
2016-12-16 21:38:53 +00:00
texturevpegbottom % = SHORT ( textures [ gr_bottomtexture ] - > height ) < < FRACBITS ;
2014-03-28 23:28:00 +00:00
2014-03-15 16:59:03 +00:00
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = texturevpegbottom * grTex - > scaleY ;
2016-01-24 08:41:30 +00:00
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = ( texturevpegbottom + gr_backsector - > floorheight - gr_frontsector - > floorheight ) * grTex - > scaleY ;
2014-03-15 16:59:03 +00:00
wallVerts [ 0 ] . s = wallVerts [ 3 ] . s = cliplow * grTex - > scaleX ;
wallVerts [ 2 ] . s = wallVerts [ 1 ] . s = cliphigh * grTex - > scaleX ;
2016-01-24 08:41:30 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
// Adjust t value for sloped walls
if ( ! ( gr_linedef - > flags & ML_EFFECT1 ) )
{
// Unskewed
wallVerts [ 0 ] . t - = ( worldbottom - gr_frontsector - > floorheight ) * grTex - > scaleY ;
wallVerts [ 1 ] . t - = ( worldbottomslope - gr_frontsector - > floorheight ) * grTex - > scaleY ;
wallVerts [ 3 ] . t - = ( worldlow - gr_backsector - > floorheight ) * grTex - > scaleY ;
wallVerts [ 2 ] . t - = ( worldlowslope - gr_backsector - > floorheight ) * grTex - > scaleY ;
}
else if ( gr_linedef - > flags & ML_DONTPEGBOTTOM )
{
// Skewed by bottom
2016-06-01 17:51:38 +00:00
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = ( texturevpegbottom + worldlow - worldbottom ) * grTex - > scaleY ;
//wallVerts[3].t = wallVerts[0].t - (worldlow - worldbottom) * grTex->scaleY; // no need, [3] is already this
wallVerts [ 2 ] . t = wallVerts [ 1 ] . t - ( worldlowslope - worldbottomslope ) * grTex - > scaleY ;
2016-01-28 13:56:23 +00:00
}
else
{
// Skewed by top
wallVerts [ 0 ] . t = ( texturevpegbottom + worldlow - worldbottom ) * grTex - > scaleY ;
wallVerts [ 1 ] . t = ( texturevpegbottom + worldlowslope - worldbottomslope ) * grTex - > scaleY ;
}
2016-01-24 08:41:30 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
// set top/bottom coords
2016-01-17 04:10:38 +00:00
# ifdef ESLOPE
wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( worldlow ) ;
wallVerts [ 0 ] . y = FIXED_TO_FLOAT ( worldbottom ) ;
wallVerts [ 2 ] . y = FIXED_TO_FLOAT ( worldlowslope ) ;
wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( worldbottomslope ) ;
# else
2014-03-15 16:59:03 +00:00
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( worldlow ) ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( worldbottom ) ;
2016-01-17 04:10:38 +00:00
# endif
2014-03-15 16:59:03 +00:00
if ( gr_frontsector - > numlights )
2018-03-20 14:20:02 +00:00
HWR_SplitWall ( gr_frontsector , wallVerts , gr_bottomtexture , & Surf , FF_CUTLEVEL , NULL ) ;
2014-03-15 16:59:03 +00:00
else if ( grTex - > mipmap . flags & TF_TRANSPARENT )
2016-12-16 21:38:53 +00:00
HWR_AddTransparentWall ( wallVerts , & Surf , gr_bottomtexture , PF_Environment , false , lightnum , colormap ) ;
2014-03-15 16:59:03 +00:00
else
HWR_ProjectWall ( wallVerts , & Surf , PF_Masked , lightnum , colormap ) ;
}
2016-12-16 21:38:53 +00:00
gr_midtexture = R_GetTextureNum ( gr_sidedef - > midtexture ) ;
2014-03-15 16:59:03 +00:00
if ( gr_midtexture )
{
FBITFIELD blendmode ;
sector_t * front , * back ;
fixed_t popentop , popenbottom , polytop , polybottom , lowcut , highcut ;
fixed_t texturevpeg = 0 ;
INT32 repeats ;
if ( gr_linedef - > frontsector - > heightsec ! = - 1 )
front = & sectors [ gr_linedef - > frontsector - > heightsec ] ;
else
front = gr_linedef - > frontsector ;
if ( gr_linedef - > backsector - > heightsec ! = - 1 )
back = & sectors [ gr_linedef - > backsector - > heightsec ] ;
else
back = gr_linedef - > backsector ;
if ( gr_sidedef - > repeatcnt )
repeats = 1 + gr_sidedef - > repeatcnt ;
else if ( gr_linedef - > flags & ML_EFFECT5 )
{
fixed_t high , low ;
if ( front - > ceilingheight > back - > ceilingheight )
high = back - > ceilingheight ;
else
high = front - > ceilingheight ;
if ( front - > floorheight > back - > floorheight )
low = front - > floorheight ;
else
low = back - > floorheight ;
repeats = ( high - low ) / textureheight [ gr_sidedef - > midtexture ] ;
if ( ( high - low ) % textureheight [ gr_sidedef - > midtexture ] )
repeats + + ; // tile an extra time to fill the gap -- Monster Iestyn
}
else
repeats = 1 ;
// SoM: a little note: This code re-arranging will
// fix the bug in Nimrod map02. popentop and popenbottom
// record the limits the texture can be displayed in.
// polytop and polybottom, are the ideal (i.e. unclipped)
// heights of the polygon, and h & l, are the final (clipped)
// poly coords.
# ifdef POLYOBJECTS
// NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to,
// you must use the linedef's backsector to be correct
// From CB
if ( gr_curline - > polyseg )
{
popentop = back - > ceilingheight ;
popenbottom = back - > floorheight ;
}
else
2016-01-27 06:00:15 +00:00
# endif
{
# ifdef ESLOPE
popentop = min ( worldtop , worldhigh ) ;
popenbottom = max ( worldbottom , worldlow ) ;
# else
popentop = min ( front - > ceilingheight , back - > ceilingheight ) ;
popenbottom = max ( front - > floorheight , back - > floorheight ) ;
# endif
2014-03-15 16:59:03 +00:00
}
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
if ( gr_linedef - > flags & ML_EFFECT2 )
{
if ( ! ! ( gr_linedef - > flags & ML_DONTPEGBOTTOM ) ^ ! ! ( gr_linedef - > flags & ML_EFFECT3 ) )
{
polybottom = max ( front - > floorheight , back - > floorheight ) + gr_sidedef - > rowoffset ;
polytop = polybottom + textureheight [ gr_midtexture ] * repeats ;
}
else
{
polytop = min ( front - > ceilingheight , back - > ceilingheight ) + gr_sidedef - > rowoffset ;
polybottom = polytop - textureheight [ gr_midtexture ] * repeats ;
}
}
else if ( ! ! ( gr_linedef - > flags & ML_DONTPEGBOTTOM ) ^ ! ! ( gr_linedef - > flags & ML_EFFECT3 ) )
2016-01-27 06:00:15 +00:00
# else
if ( gr_linedef - > flags & ML_DONTPEGBOTTOM )
# endif
2014-03-15 16:59:03 +00:00
{
polybottom = popenbottom + gr_sidedef - > rowoffset ;
polytop = polybottom + textureheight [ gr_midtexture ] * repeats ;
}
else
{
polytop = popentop + gr_sidedef - > rowoffset ;
polybottom = polytop - textureheight [ gr_midtexture ] * repeats ;
}
// CB
# ifdef POLYOBJECTS
// NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to,
// you must use the linedef's backsector to be correct
if ( gr_curline - > polyseg )
{
lowcut = polybottom ;
highcut = polytop ;
}
# endif
else
{
// The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector
2016-01-27 06:00:15 +00:00
lowcut = popenbottom ;
highcut = popentop ;
2014-03-15 16:59:03 +00:00
}
2016-01-27 06:00:15 +00:00
h = min ( highcut , polytop ) ;
l = max ( polybottom , lowcut ) ;
2014-03-15 16:59:03 +00:00
{
// PEGGING
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
if ( ! ! ( gr_linedef - > flags & ML_DONTPEGBOTTOM ) ^ ! ! ( gr_linedef - > flags & ML_EFFECT3 ) )
2016-01-27 06:00:15 +00:00
# else
2014-03-15 16:59:03 +00:00
if ( gr_linedef - > flags & ML_DONTPEGBOTTOM )
2016-01-27 06:00:15 +00:00
# endif
2014-03-15 16:59:03 +00:00
texturevpeg = textureheight [ gr_sidedef - > midtexture ] * repeats - h + polybottom ;
else
texturevpeg = polytop - h ;
grTex = HWR_GetTexture ( gr_midtexture ) ;
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = texturevpeg * grTex - > scaleY ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = ( h - l + texturevpeg ) * grTex - > scaleY ;
wallVerts [ 0 ] . s = wallVerts [ 3 ] . s = cliplow * grTex - > scaleX ;
wallVerts [ 2 ] . s = wallVerts [ 1 ] . s = cliphigh * grTex - > scaleX ;
}
// set top/bottom coords
// Take the texture peg into account, rather than changing the offsets past
// where the polygon might not be.
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( h ) ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( l ) ;
2016-01-27 06:00:15 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
// Correct to account for slopes
{
fixed_t midtextureslant ;
if ( gr_linedef - > flags & ML_EFFECT2 )
midtextureslant = 0 ;
else if ( ! ! ( gr_linedef - > flags & ML_DONTPEGBOTTOM ) ^ ! ! ( gr_linedef - > flags & ML_EFFECT3 ) )
midtextureslant = worldlow < worldbottom
? worldbottomslope - worldbottom
: worldlowslope - worldlow ;
else
midtextureslant = worldtop < worldhigh
? worldtopslope - worldtop
: worldhighslope - worldhigh ;
polytop + = midtextureslant ;
polybottom + = midtextureslant ;
highcut + = worldtop < worldhigh
? worldtopslope - worldtop
: worldhighslope - worldhigh ;
lowcut + = worldlow < worldbottom
? worldbottomslope - worldbottom
: worldlowslope - worldlow ;
// Texture stuff
h = min ( highcut , polytop ) ;
l = max ( polybottom , lowcut ) ;
{
// PEGGING
if ( ! ! ( gr_linedef - > flags & ML_DONTPEGBOTTOM ) ^ ! ! ( gr_linedef - > flags & ML_EFFECT3 ) )
texturevpeg = textureheight [ gr_sidedef - > midtexture ] * repeats - h + polybottom ;
else
texturevpeg = polytop - h ;
wallVerts [ 2 ] . t = texturevpeg * grTex - > scaleY ;
wallVerts [ 1 ] . t = ( h - l + texturevpeg ) * grTex - > scaleY ;
}
wallVerts [ 2 ] . y = FIXED_TO_FLOAT ( h ) ;
wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( l ) ;
}
2016-01-27 06:00:15 +00:00
# endif
2014-03-15 16:59:03 +00:00
// set alpha for transparent walls (new boom and legacy linedef types)
// ooops ! this do not work at all because render order we should render it in backtofront order
switch ( gr_linedef - > special )
{
case 900 :
blendmode = HWR_TranstableToAlpha ( tr_trans10 , & Surf ) ;
break ;
case 901 :
blendmode = HWR_TranstableToAlpha ( tr_trans20 , & Surf ) ;
break ;
case 902 :
blendmode = HWR_TranstableToAlpha ( tr_trans30 , & Surf ) ;
break ;
case 903 :
blendmode = HWR_TranstableToAlpha ( tr_trans40 , & Surf ) ;
break ;
case 904 :
blendmode = HWR_TranstableToAlpha ( tr_trans50 , & Surf ) ;
break ;
case 905 :
blendmode = HWR_TranstableToAlpha ( tr_trans60 , & Surf ) ;
break ;
case 906 :
blendmode = HWR_TranstableToAlpha ( tr_trans70 , & Surf ) ;
break ;
case 907 :
blendmode = HWR_TranstableToAlpha ( tr_trans80 , & Surf ) ;
break ;
case 908 :
blendmode = HWR_TranstableToAlpha ( tr_trans90 , & Surf ) ;
break ;
// Translucent
case 102 :
case 121 :
case 123 :
case 124 :
case 125 :
case 141 :
case 142 :
case 144 :
case 145 :
case 174 :
case 175 :
case 192 :
case 195 :
case 221 :
case 253 :
case 256 :
blendmode = PF_Translucent ;
break ;
default :
blendmode = PF_Masked ;
break ;
}
2014-08-30 13:10:55 +00:00
# ifdef POLYOBJECTS
if ( gr_curline - > polyseg & & gr_curline - > polyseg - > translucency > 0 )
{
if ( gr_curline - > polyseg - > translucency > = NUMTRANSMAPS ) // wall not drawn
2014-08-30 13:20:07 +00:00
{
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = 0x00 ; // This shouldn't draw anything regardless of blendmode
2014-08-30 13:20:07 +00:00
blendmode = PF_Masked ;
}
2014-08-30 13:36:18 +00:00
else
blendmode = HWR_TranstableToAlpha ( gr_curline - > polyseg - > translucency , & Surf ) ;
2014-08-30 13:10:55 +00:00
}
# endif
2014-03-15 16:59:03 +00:00
if ( gr_frontsector - > numlights )
2014-03-20 20:34:56 +00:00
{
if ( ! ( blendmode & PF_Masked ) )
2018-03-20 14:20:02 +00:00
HWR_SplitWall ( gr_frontsector , wallVerts , gr_midtexture , & Surf , FF_TRANSLUCENT , NULL ) ;
2014-03-20 20:34:56 +00:00
else
2017-09-08 23:41:11 +00:00
{
2018-03-20 14:20:02 +00:00
HWR_SplitWall ( gr_frontsector , wallVerts , gr_midtexture , & Surf , FF_CUTLEVEL , NULL ) ;
2017-09-08 23:41:11 +00:00
}
2014-03-20 20:34:56 +00:00
}
2014-03-15 16:59:03 +00:00
else if ( ! ( blendmode & PF_Masked ) )
HWR_AddTransparentWall ( wallVerts , & Surf , gr_midtexture , blendmode , false , lightnum , colormap ) ;
else
HWR_ProjectWall ( wallVerts , & Surf , blendmode , lightnum , colormap ) ;
}
2014-09-08 22:29:05 +00:00
2019-12-25 19:22:01 +00:00
// Isn't this just the most lovely mess
2014-10-27 20:57:45 +00:00
if ( ! gr_curline - > polyseg ) // Don't do it for polyobjects
2014-09-08 22:29:05 +00:00
{
2019-12-25 19:22:01 +00:00
if ( gr_frontsector - > ceilingpic = = skyflatnum | | gr_backsector - > ceilingpic = = skyflatnum )
2014-10-27 20:57:45 +00:00
{
2019-12-25 19:22:01 +00:00
fixed_t depthwallheight ;
if ( ! gr_sidedef - > toptexture | | ( gr_frontsector - > ceilingpic = = skyflatnum & & gr_backsector - > ceilingpic = = skyflatnum ) ) // when both sectors are sky, the top texture isn't drawn
depthwallheight = gr_frontsector - > ceilingheight < gr_backsector - > ceilingheight ? gr_frontsector - > ceilingheight : gr_backsector - > ceilingheight ;
else
depthwallheight = gr_frontsector - > ceilingheight > gr_backsector - > ceilingheight ? gr_frontsector - > ceilingheight : gr_backsector - > ceilingheight ;
if ( gr_frontsector - > ceilingheight - gr_frontsector - > floorheight < = 0 ) // current sector is a thok barrier
2014-10-27 20:57:45 +00:00
{
2019-12-25 19:22:01 +00:00
if ( gr_backsector - > ceilingheight - gr_backsector - > floorheight < = 0 ) // behind sector is also a thok barrier
{
if ( ! gr_sidedef - > bottomtexture ) // Only extend further down if there's no texture
HWR_DrawSkyWall ( wallVerts , & Surf , worldbottom < worldlow ? worldbottom : worldlow , INT32_MAX ) ;
else
HWR_DrawSkyWall ( wallVerts , & Surf , worldbottom > worldlow ? worldbottom : worldlow , INT32_MAX ) ;
}
// behind sector is not a thok barrier
else if ( gr_backsector - > ceilingheight < = gr_frontsector - > ceilingheight ) // behind sector ceiling is lower or equal to current sector
HWR_DrawSkyWall ( wallVerts , & Surf , depthwallheight , INT32_MAX ) ;
// gr_front/backsector heights need to be used here because of the worldtop being set to worldhigh earlier on
}
else if ( gr_backsector - > ceilingheight - gr_backsector - > floorheight < = 0 ) // behind sector is a thok barrier, current sector is not
{
if ( gr_backsector - > ceilingheight > = gr_frontsector - > ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height
| | gr_backsector - > floorheight < = gr_frontsector - > floorheight // thok barrier ceiling height is equal to or less than current sector floor height
| | gr_backsector - > ceilingpic ! = skyflatnum ) // thok barrier is not a sky
HWR_DrawSkyWall ( wallVerts , & Surf , depthwallheight , INT32_MAX ) ;
}
else // neither sectors are thok barriers
{
if ( ( gr_backsector - > ceilingheight < gr_frontsector - > ceilingheight & & ! gr_sidedef - > toptexture ) // no top texture and sector behind is lower
| | gr_backsector - > ceilingpic ! = skyflatnum ) // behind sector is not a sky
HWR_DrawSkyWall ( wallVerts , & Surf , depthwallheight , INT32_MAX ) ;
2014-09-09 00:59:19 +00:00
}
2014-09-08 22:29:05 +00:00
}
2019-12-25 19:22:01 +00:00
// And now for sky floors!
if ( gr_frontsector - > floorpic = = skyflatnum | | gr_backsector - > floorpic = = skyflatnum )
2018-02-01 22:04:04 +00:00
{
2019-12-25 19:22:01 +00:00
fixed_t depthwallheight ;
if ( ! gr_sidedef - > bottomtexture )
depthwallheight = worldbottom > worldlow ? worldbottom : worldlow ;
else
depthwallheight = worldbottom < worldlow ? worldbottom : worldlow ;
if ( gr_frontsector - > ceilingheight - gr_frontsector - > floorheight < = 0 ) // current sector is a thok barrier
2014-10-27 20:57:45 +00:00
{
2019-12-25 19:22:01 +00:00
if ( gr_backsector - > ceilingheight - gr_backsector - > floorheight < = 0 ) // behind sector is also a thok barrier
{
if ( ! gr_sidedef - > toptexture ) // Only extend up if there's no texture
HWR_DrawSkyWall ( wallVerts , & Surf , INT32_MIN , worldtop > worldhigh ? worldtop : worldhigh ) ;
else
HWR_DrawSkyWall ( wallVerts , & Surf , INT32_MIN , worldtop < worldhigh ? worldtop : worldhigh ) ;
}
// behind sector is not a thok barrier
else if ( gr_backsector - > floorheight > = gr_frontsector - > floorheight ) // behind sector floor is greater or equal to current sector
HWR_DrawSkyWall ( wallVerts , & Surf , INT32_MIN , depthwallheight ) ;
}
else if ( gr_backsector - > ceilingheight - gr_backsector - > floorheight < = 0 ) // behind sector is a thok barrier, current sector is not
{
if ( gr_backsector - > floorheight < = gr_frontsector - > floorheight // thok barrier floor height is equal to or less than current sector floor height
| | gr_backsector - > ceilingheight > = gr_frontsector - > ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height
| | gr_backsector - > floorpic ! = skyflatnum ) // thok barrier is not a sky
HWR_DrawSkyWall ( wallVerts , & Surf , INT32_MIN , depthwallheight ) ;
}
else // neither sectors are thok barriers
{
if ( ( ( gr_backsector - > floorheight > gr_frontsector - > floorheight & & ! gr_sidedef - > bottomtexture ) // no bottom texture and sector behind is higher
| | gr_backsector - > floorpic ! = skyflatnum ) // behind sector is not a sky
& & ABS ( gr_backsector - > floorheight - gr_frontsector - > floorheight ) > FRACUNIT * 3 / 2 ) // don't draw sky walls for VERY thin differences, this makes for horrible looking slopes sometimes!
HWR_DrawSkyWall ( wallVerts , & Surf , INT32_MIN , depthwallheight ) ;
2014-09-09 00:59:19 +00:00
}
2014-09-08 22:29:05 +00:00
}
}
2014-03-15 16:59:03 +00:00
}
else
{
// Single sided line... Deal only with the middletexture (if one exists)
2016-12-16 21:38:53 +00:00
gr_midtexture = R_GetTextureNum ( gr_sidedef - > midtexture ) ;
2019-12-25 19:22:01 +00:00
if ( gr_midtexture & & gr_linedef - > special ! = 41 ) // (Ignore horizon line for OGL)
2014-03-15 16:59:03 +00:00
{
{
fixed_t texturevpeg ;
// PEGGING
2016-01-24 08:41:30 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
if ( ( gr_linedef - > flags & ( ML_DONTPEGBOTTOM | ML_EFFECT2 ) ) = = ( ML_DONTPEGBOTTOM | ML_EFFECT2 ) )
2016-01-24 08:41:30 +00:00
texturevpeg = gr_frontsector - > floorheight + textureheight [ gr_sidedef - > midtexture ] - gr_frontsector - > ceilingheight + gr_sidedef - > rowoffset ;
2016-01-28 13:56:23 +00:00
else
2016-01-24 08:41:30 +00:00
# endif
2014-03-15 16:59:03 +00:00
if ( gr_linedef - > flags & ML_DONTPEGBOTTOM )
texturevpeg = worldbottom + textureheight [ gr_sidedef - > midtexture ] - worldtop + gr_sidedef - > rowoffset ;
else
// top of texture at top
texturevpeg = gr_sidedef - > rowoffset ;
grTex = HWR_GetTexture ( gr_midtexture ) ;
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = texturevpeg * grTex - > scaleY ;
2016-01-24 08:41:30 +00:00
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = ( texturevpeg + gr_frontsector - > ceilingheight - gr_frontsector - > floorheight ) * grTex - > scaleY ;
2014-03-15 16:59:03 +00:00
wallVerts [ 0 ] . s = wallVerts [ 3 ] . s = cliplow * grTex - > scaleX ;
wallVerts [ 2 ] . s = wallVerts [ 1 ] . s = cliphigh * grTex - > scaleX ;
2016-01-24 08:41:30 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
// Texture correction for slopes
if ( gr_linedef - > flags & ML_EFFECT2 ) {
wallVerts [ 3 ] . t + = ( gr_frontsector - > ceilingheight - worldtop ) * grTex - > scaleY ;
wallVerts [ 2 ] . t + = ( gr_frontsector - > ceilingheight - worldtopslope ) * grTex - > scaleY ;
wallVerts [ 0 ] . t + = ( gr_frontsector - > floorheight - worldbottom ) * grTex - > scaleY ;
wallVerts [ 1 ] . t + = ( gr_frontsector - > floorheight - worldbottomslope ) * grTex - > scaleY ;
} else if ( gr_linedef - > flags & ML_DONTPEGBOTTOM ) {
wallVerts [ 3 ] . t = wallVerts [ 0 ] . t + ( worldbottom - worldtop ) * grTex - > scaleY ;
wallVerts [ 2 ] . t = wallVerts [ 1 ] . t + ( worldbottomslope - worldtopslope ) * grTex - > scaleY ;
} else {
wallVerts [ 0 ] . t = wallVerts [ 3 ] . t - ( worldbottom - worldtop ) * grTex - > scaleY ;
wallVerts [ 1 ] . t = wallVerts [ 2 ] . t - ( worldbottomslope - worldtopslope ) * grTex - > scaleY ;
}
2016-01-24 08:41:30 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
2016-01-24 08:41:30 +00:00
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
//Set textures properly on single sided walls that are sloped
2016-01-24 08:41:30 +00:00
wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( worldtop ) ;
wallVerts [ 0 ] . y = FIXED_TO_FLOAT ( worldbottom ) ;
wallVerts [ 2 ] . y = FIXED_TO_FLOAT ( worldtopslope ) ;
wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( worldbottomslope ) ;
# else
2014-03-15 16:59:03 +00:00
// set top/bottom coords
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( worldtop ) ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( worldbottom ) ;
2016-01-24 08:41:30 +00:00
# endif
2019-12-25 19:22:01 +00:00
2014-03-15 16:59:03 +00:00
if ( gr_frontsector - > numlights )
2018-03-20 14:20:02 +00:00
HWR_SplitWall ( gr_frontsector , wallVerts , gr_midtexture , & Surf , FF_CUTLEVEL , NULL ) ;
2019-12-25 19:22:01 +00:00
// I don't think that solid walls can use translucent linedef types...
2014-03-15 16:59:03 +00:00
else
{
if ( grTex - > mipmap . flags & TF_TRANSPARENT )
HWR_AddTransparentWall ( wallVerts , & Surf , gr_midtexture , PF_Environment , false , lightnum , colormap ) ;
else
HWR_ProjectWall ( wallVerts , & Surf , PF_Masked , lightnum , colormap ) ;
}
}
2014-09-08 22:29:05 +00:00
2014-10-27 20:57:45 +00:00
if ( ! gr_curline - > polyseg )
{
if ( gr_frontsector - > ceilingpic = = skyflatnum ) // It's a single-sided line with sky for its sector
2019-12-25 19:22:01 +00:00
HWR_DrawSkyWall ( wallVerts , & Surf , worldtop , INT32_MAX ) ;
2014-10-27 20:57:45 +00:00
if ( gr_frontsector - > floorpic = = skyflatnum )
2019-12-25 19:22:01 +00:00
HWR_DrawSkyWall ( wallVerts , & Surf , INT32_MIN , worldbottom ) ;
2014-10-27 20:57:45 +00:00
}
2014-03-15 16:59:03 +00:00
}
//Hurdler: 3d-floors test
if ( gr_frontsector & & gr_backsector & & gr_frontsector - > tag ! = gr_backsector - > tag & & ( gr_backsector - > ffloors | | gr_frontsector - > ffloors ) )
{
ffloor_t * rover ;
fixed_t highcut = 0 , lowcut = 0 ;
2014-04-17 12:02:34 +00:00
INT32 texnum ;
line_t * newline = NULL ; // Multi-Property FOF
2016-01-24 08:41:30 +00:00
///TODO add slope support (fixing cutoffs, proper wall clipping) - maybe just disable highcut/lowcut if either sector or FOF has a slope
/// to allow fun plane intersecting in OGL? But then people would abuse that and make software look bad. :C
2014-03-15 16:59:03 +00:00
highcut = gr_frontsector - > ceilingheight < gr_backsector - > ceilingheight ? gr_frontsector - > ceilingheight : gr_backsector - > ceilingheight ;
lowcut = gr_frontsector - > floorheight > gr_backsector - > floorheight ? gr_frontsector - > floorheight : gr_backsector - > floorheight ;
if ( gr_backsector - > ffloors )
{
for ( rover = gr_backsector - > ffloors ; rover ; rover = rover - > next )
{
if ( ! ( rover - > flags & FF_EXISTS ) | | ! ( rover - > flags & FF_RENDERSIDES ) | | ( rover - > flags & FF_INVERTSIDES ) )
continue ;
if ( * rover - > topheight < lowcut | | * rover - > bottomheight > highcut )
continue ;
2016-12-16 21:38:53 +00:00
texnum = R_GetTextureNum ( sides [ rover - > master - > sidenum [ 0 ] ] . midtexture ) ;
2014-04-17 12:02:34 +00:00
if ( rover - > master - > flags & ML_TFERLINE )
{
size_t linenum = gr_curline - > linedef - gr_backsector - > lines [ 0 ] ;
newline = rover - > master - > frontsector - > lines [ 0 ] + linenum ;
2016-12-16 21:38:53 +00:00
texnum = R_GetTextureNum ( sides [ newline - > sidenum [ 0 ] ] . midtexture ) ;
2014-04-17 12:02:34 +00:00
}
2014-03-15 16:59:03 +00:00
2016-01-25 05:57:53 +00:00
# ifdef ESLOPE
h = * rover - > t_slope ? P_GetZAt ( * rover - > t_slope , v1x , v1y ) : * rover - > topheight ;
hS = * rover - > t_slope ? P_GetZAt ( * rover - > t_slope , v2x , v2y ) : * rover - > topheight ;
l = * rover - > b_slope ? P_GetZAt ( * rover - > b_slope , v1x , v1y ) : * rover - > bottomheight ;
lS = * rover - > b_slope ? P_GetZAt ( * rover - > b_slope , v2x , v2y ) : * rover - > bottomheight ;
if ( ! ( * rover - > t_slope ) & & ! gr_frontsector - > c_slope & & ! gr_backsector - > c_slope & & h > highcut )
h = hS = highcut ;
if ( ! ( * rover - > b_slope ) & & ! gr_frontsector - > f_slope & & ! gr_backsector - > f_slope & & l < lowcut )
l = lS = lowcut ;
//Hurdler: HW code starts here
//FIXME: check if peging is correct
// set top/bottom coords
2016-01-28 13:56:23 +00:00
wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( h ) ;
wallVerts [ 2 ] . y = FIXED_TO_FLOAT ( hS ) ;
wallVerts [ 0 ] . y = FIXED_TO_FLOAT ( l ) ;
wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( lS ) ;
2016-01-25 05:57:53 +00:00
# else
2014-03-15 16:59:03 +00:00
h = * rover - > topheight ;
l = * rover - > bottomheight ;
if ( h > highcut )
h = highcut ;
if ( l < lowcut )
l = lowcut ;
//Hurdler: HW code starts here
//FIXME: check if peging is correct
// set top/bottom coords
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( h ) ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( l ) ;
2016-01-25 05:57:53 +00:00
# endif
2014-03-15 16:59:03 +00:00
if ( rover - > flags & FF_FOG )
{
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = 0 ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = 0 ;
wallVerts [ 0 ] . s = wallVerts [ 3 ] . s = 0 ;
wallVerts [ 2 ] . s = wallVerts [ 1 ] . s = 0 ;
}
2017-01-12 21:43:37 +00:00
else
2014-03-15 16:59:03 +00:00
{
2018-06-26 20:41:05 +00:00
fixed_t texturevpeg ;
2018-09-28 16:02:02 +00:00
boolean attachtobottom = false ;
# ifdef ESLOPE
boolean slopeskew = false ; // skew FOF walls with slopes?
# endif
2014-04-17 12:02:34 +00:00
2018-06-26 20:41:05 +00:00
// Wow, how was this missing from OpenGL for so long?
// ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software
// -- Monster Iestyn 26/06/18
2014-04-17 12:02:34 +00:00
if ( newline )
{
2018-06-26 20:41:05 +00:00
texturevpeg = sides [ newline - > sidenum [ 0 ] ] . rowoffset ;
2018-09-28 16:02:02 +00:00
attachtobottom = ! ! ( newline - > flags & ML_DONTPEGBOTTOM ) ;
# ifdef ESLOPE
slopeskew = ! ! ( newline - > flags & ML_DONTPEGTOP ) ;
# endif
2014-04-17 12:02:34 +00:00
}
else
{
2018-06-26 20:41:05 +00:00
texturevpeg = sides [ rover - > master - > sidenum [ 0 ] ] . rowoffset ;
2018-09-28 16:02:02 +00:00
attachtobottom = ! ! ( gr_linedef - > flags & ML_DONTPEGBOTTOM ) ;
# ifdef ESLOPE
slopeskew = ! ! ( rover - > master - > flags & ML_DONTPEGTOP ) ;
# endif
2014-04-17 12:02:34 +00:00
}
2018-06-26 20:41:05 +00:00
grTex = HWR_GetTexture ( texnum ) ;
# ifdef ESLOPE
2018-09-28 16:02:02 +00:00
if ( ! slopeskew ) // no skewing
{
if ( attachtobottom )
texturevpeg - = * rover - > topheight - * rover - > bottomheight ;
wallVerts [ 3 ] . t = ( * rover - > topheight - h + texturevpeg ) * grTex - > scaleY ;
wallVerts [ 2 ] . t = ( * rover - > topheight - hS + texturevpeg ) * grTex - > scaleY ;
wallVerts [ 0 ] . t = ( * rover - > topheight - l + texturevpeg ) * grTex - > scaleY ;
wallVerts [ 1 ] . t = ( * rover - > topheight - lS + texturevpeg ) * grTex - > scaleY ;
}
else
{
if ( ! attachtobottom ) // skew by top
{
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = texturevpeg * grTex - > scaleY ;
wallVerts [ 0 ] . t = ( h - l + texturevpeg ) * grTex - > scaleY ;
wallVerts [ 1 ] . t = ( hS - lS + texturevpeg ) * grTex - > scaleY ;
}
else // skew by bottom
{
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = texturevpeg * grTex - > scaleY ;
wallVerts [ 3 ] . t = wallVerts [ 0 ] . t - ( h - l ) * grTex - > scaleY ;
wallVerts [ 2 ] . t = wallVerts [ 1 ] . t - ( hS - lS ) * grTex - > scaleY ;
}
}
2018-06-26 20:41:05 +00:00
# else
2018-09-28 16:02:02 +00:00
if ( attachtobottom )
texturevpeg - = * rover - > topheight - * rover - > bottomheight ;
2018-06-26 20:41:05 +00:00
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = ( * rover - > topheight - h + texturevpeg ) * grTex - > scaleY ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = ( * rover - > topheight - l + texturevpeg ) * grTex - > scaleY ;
2016-01-25 05:57:53 +00:00
# endif
2014-03-15 16:59:03 +00:00
wallVerts [ 0 ] . s = wallVerts [ 3 ] . s = cliplow * grTex - > scaleX ;
wallVerts [ 2 ] . s = wallVerts [ 1 ] . s = cliphigh * grTex - > scaleX ;
}
if ( rover - > flags & FF_FOG )
{
FBITFIELD blendmode ;
2018-03-15 23:58:37 +00:00
blendmode = PF_Fog | PF_NoTexture ;
2014-03-15 16:59:03 +00:00
2019-12-26 01:09:31 +00:00
lightnum = HWR_CalcWallLight ( rover - > master - > frontsector - > lightlevel , vs . x , vs . y , ve . x , ve . y ) ;
2014-03-15 16:59:03 +00:00
colormap = rover - > master - > frontsector - > extra_colormap ;
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = HWR_FogBlockAlpha ( rover - > master - > frontsector - > lightlevel , rover - > master - > frontsector - > extra_colormap ) ;
2014-03-15 16:59:03 +00:00
if ( gr_frontsector - > numlights )
2018-03-20 14:20:02 +00:00
HWR_SplitWall ( gr_frontsector , wallVerts , 0 , & Surf , rover - > flags , rover ) ;
2014-03-15 16:59:03 +00:00
else
HWR_AddTransparentWall ( wallVerts , & Surf , 0 , blendmode , true , lightnum , colormap ) ;
}
else
{
FBITFIELD blendmode = PF_Masked ;
2017-09-08 23:41:11 +00:00
if ( rover - > flags & FF_TRANSLUCENT & & rover - > alpha < 256 )
2014-03-15 16:59:03 +00:00
{
blendmode = PF_Translucent ;
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = ( UINT8 ) rover - > alpha - 1 > 255 ? 255 : rover - > alpha - 1 ;
2014-03-15 16:59:03 +00:00
}
if ( gr_frontsector - > numlights )
2018-03-20 14:20:02 +00:00
HWR_SplitWall ( gr_frontsector , wallVerts , texnum , & Surf , rover - > flags , rover ) ;
2014-03-15 16:59:03 +00:00
else
{
if ( blendmode ! = PF_Masked )
2014-04-17 12:02:34 +00:00
HWR_AddTransparentWall ( wallVerts , & Surf , texnum , blendmode , false , lightnum , colormap ) ;
2014-03-15 16:59:03 +00:00
else
HWR_ProjectWall ( wallVerts , & Surf , PF_Masked , lightnum , colormap ) ;
}
}
}
}
if ( gr_frontsector - > ffloors ) // Putting this seperate should allow 2 FOF sectors to be connected without too many errors? I think?
{
for ( rover = gr_frontsector - > ffloors ; rover ; rover = rover - > next )
{
if ( ! ( rover - > flags & FF_EXISTS ) | | ! ( rover - > flags & FF_RENDERSIDES ) | | ! ( rover - > flags & FF_ALLSIDES ) )
continue ;
if ( * rover - > topheight < lowcut | | * rover - > bottomheight > highcut )
continue ;
2016-12-16 21:38:53 +00:00
texnum = R_GetTextureNum ( sides [ rover - > master - > sidenum [ 0 ] ] . midtexture ) ;
2014-04-17 12:02:34 +00:00
if ( rover - > master - > flags & ML_TFERLINE )
{
size_t linenum = gr_curline - > linedef - gr_backsector - > lines [ 0 ] ;
newline = rover - > master - > frontsector - > lines [ 0 ] + linenum ;
2016-12-16 21:38:53 +00:00
texnum = R_GetTextureNum ( sides [ newline - > sidenum [ 0 ] ] . midtexture ) ;
2014-04-17 12:02:34 +00:00
}
2016-01-25 05:57:53 +00:00
# ifdef ESLOPE //backsides
h = * rover - > t_slope ? P_GetZAt ( * rover - > t_slope , v1x , v1y ) : * rover - > topheight ;
hS = * rover - > t_slope ? P_GetZAt ( * rover - > t_slope , v2x , v2y ) : * rover - > topheight ;
l = * rover - > b_slope ? P_GetZAt ( * rover - > b_slope , v1x , v1y ) : * rover - > bottomheight ;
lS = * rover - > b_slope ? P_GetZAt ( * rover - > b_slope , v2x , v2y ) : * rover - > bottomheight ;
if ( ! ( * rover - > t_slope ) & & ! gr_frontsector - > c_slope & & ! gr_backsector - > c_slope & & h > highcut )
h = hS = highcut ;
if ( ! ( * rover - > b_slope ) & & ! gr_frontsector - > f_slope & & ! gr_backsector - > f_slope & & l < lowcut )
l = lS = lowcut ;
//Hurdler: HW code starts here
//FIXME: check if peging is correct
// set top/bottom coords
2014-04-17 12:02:34 +00:00
2016-01-28 13:56:23 +00:00
wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( h ) ;
wallVerts [ 2 ] . y = FIXED_TO_FLOAT ( hS ) ;
wallVerts [ 0 ] . y = FIXED_TO_FLOAT ( l ) ;
wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( lS ) ;
2016-01-25 05:57:53 +00:00
# else
2014-03-15 16:59:03 +00:00
h = * rover - > topheight ;
l = * rover - > bottomheight ;
if ( h > highcut )
h = highcut ;
if ( l < lowcut )
l = lowcut ;
//Hurdler: HW code starts here
//FIXME: check if peging is correct
// set top/bottom coords
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = FIXED_TO_FLOAT ( h ) ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = FIXED_TO_FLOAT ( l ) ;
2016-01-25 05:57:53 +00:00
# endif
2014-03-15 16:59:03 +00:00
if ( rover - > flags & FF_FOG )
{
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = 0 ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = 0 ;
wallVerts [ 0 ] . s = wallVerts [ 3 ] . s = 0 ;
wallVerts [ 2 ] . s = wallVerts [ 1 ] . s = 0 ;
}
2017-01-12 21:43:37 +00:00
else
2014-03-15 16:59:03 +00:00
{
2014-04-17 12:02:34 +00:00
grTex = HWR_GetTexture ( texnum ) ;
if ( newline )
{
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = ( * rover - > topheight - h + sides [ newline - > sidenum [ 0 ] ] . rowoffset ) * grTex - > scaleY ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = ( h - l + ( * rover - > topheight - h + sides [ newline - > sidenum [ 0 ] ] . rowoffset ) ) * grTex - > scaleY ;
}
else
{
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = ( * rover - > topheight - h + sides [ rover - > master - > sidenum [ 0 ] ] . rowoffset ) * grTex - > scaleY ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = ( h - l + ( * rover - > topheight - h + sides [ rover - > master - > sidenum [ 0 ] ] . rowoffset ) ) * grTex - > scaleY ;
}
2014-03-15 16:59:03 +00:00
wallVerts [ 0 ] . s = wallVerts [ 3 ] . s = cliplow * grTex - > scaleX ;
wallVerts [ 2 ] . s = wallVerts [ 1 ] . s = cliphigh * grTex - > scaleX ;
}
if ( rover - > flags & FF_FOG )
{
FBITFIELD blendmode ;
2018-03-15 23:58:37 +00:00
blendmode = PF_Fog | PF_NoTexture ;
2014-03-15 16:59:03 +00:00
2019-12-26 01:09:31 +00:00
lightnum = HWR_CalcWallLight ( rover - > master - > frontsector - > lightlevel , vs . x , vs . y , ve . x , ve . y ) ;
2014-03-15 16:59:03 +00:00
colormap = rover - > master - > frontsector - > extra_colormap ;
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = HWR_FogBlockAlpha ( rover - > master - > frontsector - > lightlevel , rover - > master - > frontsector - > extra_colormap ) ;
2014-03-15 16:59:03 +00:00
if ( gr_backsector - > numlights )
2018-03-20 14:20:02 +00:00
HWR_SplitWall ( gr_backsector , wallVerts , 0 , & Surf , rover - > flags , rover ) ;
2014-03-15 16:59:03 +00:00
else
HWR_AddTransparentWall ( wallVerts , & Surf , 0 , blendmode , true , lightnum , colormap ) ;
}
else
{
FBITFIELD blendmode = PF_Masked ;
2017-09-08 23:41:11 +00:00
if ( rover - > flags & FF_TRANSLUCENT & & rover - > alpha < 256 )
2014-03-15 16:59:03 +00:00
{
blendmode = PF_Translucent ;
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = ( UINT8 ) rover - > alpha - 1 > 255 ? 255 : rover - > alpha - 1 ;
2014-03-15 16:59:03 +00:00
}
if ( gr_backsector - > numlights )
2018-03-20 14:20:02 +00:00
HWR_SplitWall ( gr_backsector , wallVerts , texnum , & Surf , rover - > flags , rover ) ;
2014-03-15 16:59:03 +00:00
else
{
if ( blendmode ! = PF_Masked )
2014-04-17 12:02:34 +00:00
HWR_AddTransparentWall ( wallVerts , & Surf , texnum , blendmode , false , lightnum , colormap ) ;
2014-03-15 16:59:03 +00:00
else
HWR_ProjectWall ( wallVerts , & Surf , PF_Masked , lightnum , colormap ) ;
}
}
}
}
}
//Hurdler: end of 3d-floors test
}
2017-01-10 18:01:03 +00:00
// From PrBoom:
//
// e6y: Check whether the player can look beyond this line
//
# ifdef NEWCLIP
2017-01-10 20:07:02 +00:00
boolean checkforemptylines = true ;
2017-01-10 18:01:03 +00:00
// Don't modify anything here, just check
// Kalaron: Modified for sloped linedefs
static boolean CheckClip ( seg_t * seg , sector_t * afrontsector , sector_t * abacksector )
{
fixed_t frontf1 , frontf2 , frontc1 , frontc2 ; // front floor/ceiling ends
fixed_t backf1 , backf2 , backc1 , backc2 ; // back floor ceiling ends
2018-02-07 17:46:01 +00:00
boolean bothceilingssky = false , bothfloorssky = false ;
if ( abacksector - > ceilingpic = = skyflatnum & & afrontsector - > ceilingpic = = skyflatnum )
bothceilingssky = true ;
if ( abacksector - > floorpic = = skyflatnum & & afrontsector - > floorpic = = skyflatnum )
bothfloorssky = true ;
2017-01-10 18:01:03 +00:00
// GZDoom method of sloped line clipping
# ifdef ESLOPE
if ( afrontsector - > f_slope | | afrontsector - > c_slope | | abacksector - > f_slope | | abacksector - > c_slope )
{
fixed_t v1x , v1y , v2x , v2y ; // the seg's vertexes as fixed_t
v1x = FLOAT_TO_FIXED ( ( ( polyvertex_t * ) gr_curline - > pv1 ) - > x ) ;
v1y = FLOAT_TO_FIXED ( ( ( polyvertex_t * ) gr_curline - > pv1 ) - > y ) ;
v2x = FLOAT_TO_FIXED ( ( ( polyvertex_t * ) gr_curline - > pv2 ) - > x ) ;
v2y = FLOAT_TO_FIXED ( ( ( polyvertex_t * ) gr_curline - > pv2 ) - > y ) ;
# define SLOPEPARAMS(slope, end1, end2, normalheight) \
if ( slope ) { \
end1 = P_GetZAt ( slope , v1x , v1y ) ; \
end2 = P_GetZAt ( slope , v2x , v2y ) ; \
} else \
end1 = end2 = normalheight ;
SLOPEPARAMS ( afrontsector - > f_slope , frontf1 , frontf2 , afrontsector - > floorheight )
SLOPEPARAMS ( afrontsector - > c_slope , frontc1 , frontc2 , afrontsector - > ceilingheight )
SLOPEPARAMS ( abacksector - > f_slope , backf1 , backf2 , abacksector - > floorheight )
SLOPEPARAMS ( abacksector - > c_slope , backc1 , backc2 , abacksector - > ceilingheight )
# undef SLOPEPARAMS
}
else
# endif
{
frontf1 = frontf2 = afrontsector - > floorheight ;
frontc1 = frontc2 = afrontsector - > ceilingheight ;
backf1 = backf2 = abacksector - > floorheight ;
backc1 = backc2 = abacksector - > ceilingheight ;
}
2018-02-01 22:04:04 +00:00
// properly render skies (consider door "open" if both ceilings are sky)
2018-02-03 19:48:18 +00:00
// same for floors
2018-02-07 17:46:01 +00:00
if ( ! bothceilingssky & & ! bothfloorssky )
2017-01-10 18:01:03 +00:00
{
2018-02-01 22:04:04 +00:00
// now check for closed sectors!
2018-02-03 18:30:49 +00:00
if ( ( backc1 < = frontf1 & & backc2 < = frontf2 )
| | ( backf1 > = frontc1 & & backf2 > = frontc2 ) )
2018-02-01 22:04:04 +00:00
{
checkforemptylines = false ;
return true ;
2017-01-10 18:01:03 +00:00
}
2018-02-01 22:04:04 +00:00
if ( backc1 < = backf1 & & backc2 < = backf2 )
2017-01-10 18:01:03 +00:00
{
2018-02-01 22:04:04 +00:00
// preserve a kind of transparent door/lift special effect:
if ( ( ( backc1 > = frontc1 & & backc2 > = frontc2 ) | | seg - > sidedef - > toptexture )
& & ( ( backf1 < = frontf1 & & backf2 < = frontf2 ) | | seg - > sidedef - > bottomtexture ) )
{
checkforemptylines = false ;
return true ;
}
2017-01-10 18:01:03 +00:00
}
}
2018-02-07 17:46:01 +00:00
if ( ! bothceilingssky ) {
if ( backc1 ! = frontc1 | | backc2 ! = frontc2 )
{
checkforemptylines = false ;
return false ;
}
}
if ( ! bothfloorssky ) {
if ( backf1 ! = frontf1 | | backf2 ! = frontf2 )
2017-01-10 20:07:02 +00:00
{
checkforemptylines = false ;
return false ;
}
2018-02-07 17:46:01 +00:00
}
2017-01-10 18:01:03 +00:00
return false ;
}
# else
2014-03-15 16:59:03 +00:00
//Hurdler: just like in r_bsp.c
# if 1
# define MAXSEGS MAXVIDWIDTH / 2+1
# else
//Alam_GBC: Or not (may cause overflow)
# define MAXSEGS 128
# endif
// hw_newend is one past the last valid seg
static cliprange_t * hw_newend ;
static cliprange_t gr_solidsegs [ MAXSEGS ] ;
2019-12-12 20:30:19 +00:00
// needs fix: walls are incorrectly clipped one column less
static consvar_t cv_grclipwalls = { " gr_clipwalls " , " Off " , 0 , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2014-03-15 16:59:03 +00:00
static void printsolidsegs ( void )
{
cliprange_t * start ;
2019-12-12 19:53:31 +00:00
if ( ! hw_newend )
2014-03-15 16:59:03 +00:00
return ;
for ( start = gr_solidsegs ; start ! = hw_newend ; start + + )
{
CONS_Debug ( DBG_RENDER , " %d-%d| " , start - > first , start - > last ) ;
}
CONS_Debug ( DBG_RENDER , " \n \n " ) ;
}
//
//
//
static void HWR_ClipSolidWallSegment ( INT32 first , INT32 last )
{
cliprange_t * next , * start ;
float lowfrac , highfrac ;
boolean poorhack = false ;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = gr_solidsegs ;
while ( start - > last < first - 1 )
start + + ;
if ( first < start - > first )
{
if ( last < start - > first - 1 )
{
// Post is entirely visible (above start),
// so insert a new clippost.
HWR_StoreWallRange ( first , last ) ;
next = hw_newend ;
hw_newend + + ;
while ( next ! = start )
{
* next = * ( next - 1 ) ;
next - - ;
}
next - > first = first ;
next - > last = last ;
printsolidsegs ( ) ;
return ;
}
// There is a fragment above *start.
if ( ! cv_grclipwalls . value )
{
if ( ! poorhack ) HWR_StoreWallRange ( first , last ) ;
poorhack = true ;
}
else
{
2016-11-07 21:55:56 +00:00
highfrac = HWR_ClipViewSegment ( start - > first + 1 , ( polyvertex_t * ) gr_curline - > pv1 , ( polyvertex_t * ) gr_curline - > pv2 ) ;
2014-03-15 16:59:03 +00:00
HWR_StoreWallRange ( 0 , highfrac ) ;
}
// Now adjust the clip size.
start - > first = first ;
}
// Bottom contained in start?
if ( last < = start - > last )
{
printsolidsegs ( ) ;
return ;
}
next = start ;
while ( last > = ( next + 1 ) - > first - 1 )
{
// There is a fragment between two posts.
if ( ! cv_grclipwalls . value )
{
if ( ! poorhack ) HWR_StoreWallRange ( first , last ) ;
poorhack = true ;
}
else
{
2016-11-07 21:55:56 +00:00
lowfrac = HWR_ClipViewSegment ( next - > last - 1 , ( polyvertex_t * ) gr_curline - > pv1 , ( polyvertex_t * ) gr_curline - > pv2 ) ;
highfrac = HWR_ClipViewSegment ( ( next + 1 ) - > first + 1 , ( polyvertex_t * ) gr_curline - > pv1 , ( polyvertex_t * ) gr_curline - > pv2 ) ;
2014-03-15 16:59:03 +00:00
HWR_StoreWallRange ( lowfrac , highfrac ) ;
}
next + + ;
if ( last < = next - > last )
{
// Bottom is contained in next.
// Adjust the clip size.
start - > last = next - > last ;
goto crunch ;
}
}
if ( first = = next - > first + 1 ) // 1 line texture
{
if ( ! cv_grclipwalls . value )
{
if ( ! poorhack ) HWR_StoreWallRange ( first , last ) ;
poorhack = true ;
}
else
HWR_StoreWallRange ( 0 , 1 ) ;
}
else
{
// There is a fragment after *next.
if ( ! cv_grclipwalls . value )
{
if ( ! poorhack ) HWR_StoreWallRange ( first , last ) ;
poorhack = true ;
}
else
{
2016-11-07 21:55:56 +00:00
lowfrac = HWR_ClipViewSegment ( next - > last - 1 , ( polyvertex_t * ) gr_curline - > pv1 , ( polyvertex_t * ) gr_curline - > pv2 ) ;
2014-03-15 16:59:03 +00:00
HWR_StoreWallRange ( lowfrac , 1 ) ;
}
}
// Adjust the clip size.
start - > last = last ;
// Remove start+1 to next from the clip list,
// because start now covers their area.
crunch :
if ( next = = start )
{
printsolidsegs ( ) ;
// Post just extended past the bottom of one post.
return ;
}
while ( next + + ! = hw_newend )
{
// Remove a post.
* + + start = * next ;
}
hw_newend = start ;
printsolidsegs ( ) ;
}
//
// handle LineDefs with upper and lower texture (windows)
//
static void HWR_ClipPassWallSegment ( INT32 first , INT32 last )
{
cliprange_t * start ;
float lowfrac , highfrac ;
//to allow noclipwalls but still solidseg reject of non-visible walls
boolean poorhack = false ;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = gr_solidsegs ;
while ( start - > last < first - 1 )
start + + ;
if ( first < start - > first )
{
if ( last < start - > first - 1 )
{
// Post is entirely visible (above start).
HWR_StoreWallRange ( 0 , 1 ) ;
return ;
}
// There is a fragment above *start.
if ( ! cv_grclipwalls . value )
{ //20/08/99: Changed by Hurdler (taken from faB's code)
if ( ! poorhack ) HWR_StoreWallRange ( 0 , 1 ) ;
poorhack = true ;
}
else
{
highfrac = HWR_ClipViewSegment ( min ( start - > first + 1 ,
2016-11-07 21:55:56 +00:00
start - > last ) , ( polyvertex_t * ) gr_curline - > pv1 ,
( polyvertex_t * ) gr_curline - > pv2 ) ;
2014-03-15 16:59:03 +00:00
HWR_StoreWallRange ( 0 , highfrac ) ;
}
}
// Bottom contained in start?
if ( last < = start - > last )
return ;
while ( last > = ( start + 1 ) - > first - 1 )
{
// There is a fragment between two posts.
if ( ! cv_grclipwalls . value )
{
if ( ! poorhack ) HWR_StoreWallRange ( 0 , 1 ) ;
poorhack = true ;
}
else
{
2016-11-07 21:55:56 +00:00
lowfrac = HWR_ClipViewSegment ( max ( start - > last - 1 , start - > first ) , ( polyvertex_t * ) gr_curline - > pv1 , ( polyvertex_t * ) gr_curline - > pv2 ) ;
highfrac = HWR_ClipViewSegment ( min ( ( start + 1 ) - > first + 1 , ( start + 1 ) - > last ) , ( polyvertex_t * ) gr_curline - > pv1 , ( polyvertex_t * ) gr_curline - > pv2 ) ;
2014-03-15 16:59:03 +00:00
HWR_StoreWallRange ( lowfrac , highfrac ) ;
}
start + + ;
if ( last < = start - > last )
return ;
}
if ( first = = start - > first + 1 ) // 1 line texture
{
if ( ! cv_grclipwalls . value )
{
if ( ! poorhack ) HWR_StoreWallRange ( 0 , 1 ) ;
poorhack = true ;
}
else
HWR_StoreWallRange ( 0 , 1 ) ;
}
else
{
// There is a fragment after *next.
if ( ! cv_grclipwalls . value )
{
if ( ! poorhack ) HWR_StoreWallRange ( 0 , 1 ) ;
poorhack = true ;
}
else
{
lowfrac = HWR_ClipViewSegment ( max ( start - > last - 1 ,
2016-11-07 21:55:56 +00:00
start - > first ) , ( polyvertex_t * ) gr_curline - > pv1 ,
( polyvertex_t * ) gr_curline - > pv2 ) ;
2014-03-15 16:59:03 +00:00
HWR_StoreWallRange ( lowfrac , 1 ) ;
}
}
}
// --------------------------------------------------------------------------
// HWR_ClipToSolidSegs check if it is hide by wall (solidsegs)
// --------------------------------------------------------------------------
static boolean HWR_ClipToSolidSegs ( INT32 first , INT32 last )
{
cliprange_t * start ;
// Find the first range that touches the range
// (adjacent pixels are touching).
start = gr_solidsegs ;
while ( start - > last < first - 1 )
start + + ;
if ( first < start - > first )
return true ;
// Bottom contained in start?
if ( last < = start - > last )
return false ;
return true ;
}
//
// HWR_ClearClipSegs
//
static void HWR_ClearClipSegs ( void )
{
gr_solidsegs [ 0 ] . first = - 0x7fffffff ;
gr_solidsegs [ 0 ] . last = - 1 ;
gr_solidsegs [ 1 ] . first = vid . width ; //viewwidth;
gr_solidsegs [ 1 ] . last = 0x7fffffff ;
hw_newend = gr_solidsegs + 2 ;
}
2017-01-10 18:01:03 +00:00
# endif // NEWCLIP
2014-03-15 16:59:03 +00:00
// -----------------+
// HWR_AddLine : Clips the given segment and adds any visible pieces to the line list.
// Notes : gr_cursectorlight is set to the current subsector -> sector -> light value
// : (it may be mixed with the wall's own flat colour in the future ...)
// -----------------+
static void HWR_AddLine ( seg_t * line )
{
angle_t angle1 , angle2 ;
2017-01-10 18:01:03 +00:00
# ifndef NEWCLIP
INT32 x1 , x2 ;
2014-03-15 16:59:03 +00:00
angle_t span , tspan ;
2018-02-07 17:46:01 +00:00
boolean bothceilingssky = false , bothfloorssky = false ;
2017-01-10 18:01:03 +00:00
# endif
2014-03-15 16:59:03 +00:00
// SoM: Backsector needs to be run through R_FakeFlat
2018-03-29 22:28:54 +00:00
static sector_t tempsec ;
2014-03-15 16:59:03 +00:00
2016-12-21 22:31:09 +00:00
fixed_t v1x , v1y , v2x , v2y ; // the seg's vertexes as fixed_t
2017-01-10 18:01:03 +00:00
# ifdef POLYOBJECTS
2014-03-15 16:59:03 +00:00
if ( line - > polyseg & & ! ( line - > polyseg - > flags & POF_RENDERSIDES ) )
return ;
2017-01-10 18:01:03 +00:00
# endif
2014-03-15 16:59:03 +00:00
gr_curline = line ;
2016-12-21 22:31:09 +00:00
v1x = FLOAT_TO_FIXED ( ( ( polyvertex_t * ) gr_curline - > pv1 ) - > x ) ;
v1y = FLOAT_TO_FIXED ( ( ( polyvertex_t * ) gr_curline - > pv1 ) - > y ) ;
v2x = FLOAT_TO_FIXED ( ( ( polyvertex_t * ) gr_curline - > pv2 ) - > x ) ;
v2y = FLOAT_TO_FIXED ( ( ( polyvertex_t * ) gr_curline - > pv2 ) - > y ) ;
2014-03-15 16:59:03 +00:00
// OPTIMIZE: quickly reject orthogonal back sides.
2016-12-21 22:31:09 +00:00
angle1 = R_PointToAngle ( v1x , v1y ) ;
angle2 = R_PointToAngle ( v2x , v2y ) ;
2014-03-15 16:59:03 +00:00
2017-01-10 18:01:03 +00:00
# ifdef NEWCLIP
// PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle!
if ( angle2 - angle1 < ANGLE_180 )
return ;
// PrBoom: use REAL clipping math YAYYYYYYY!!!
if ( ! gld_clipper_SafeCheckRange ( angle2 , angle1 ) )
{
return ;
}
2017-01-10 20:07:02 +00:00
checkforemptylines = true ;
2017-01-10 18:01:03 +00:00
# else
2014-03-15 16:59:03 +00:00
// Clip to view edges.
span = angle1 - angle2 ;
// backface culling : span is < ANGLE_180 if ang1 > ang2 : the seg is facing
if ( span > = ANGLE_180 )
return ;
// Global angle needed by segcalc.
//rw_angle1 = angle1;
angle1 - = dup_viewangle ;
angle2 - = dup_viewangle ;
tspan = angle1 + gr_clipangle ;
if ( tspan > 2 * gr_clipangle )
{
tspan - = 2 * gr_clipangle ;
// Totally off the left edge?
if ( tspan > = span )
return ;
angle1 = gr_clipangle ;
}
tspan = gr_clipangle - angle2 ;
if ( tspan > 2 * gr_clipangle )
{
tspan - = 2 * gr_clipangle ;
// Totally off the left edge?
if ( tspan > = span )
return ;
angle2 = ( angle_t ) - ( signed ) gr_clipangle ;
}
#if 0
{
float fx1 , fx2 , fy1 , fy2 ;
//BP: test with a better projection than viewangletox[R_PointToAngle(angle)]
// do not enable this at release 4 mul and 2 div
2016-11-07 21:55:56 +00:00
fx1 = ( ( polyvertex_t * ) ( line - > pv1 ) ) - > x - gr_viewx ;
fy1 = ( ( polyvertex_t * ) ( line - > pv1 ) ) - > y - gr_viewy ;
2014-03-15 16:59:03 +00:00
fy2 = ( fx1 * gr_viewcos + fy1 * gr_viewsin ) ;
if ( fy2 < 0 )
// the point is back
fx1 = 0 ;
else
fx1 = gr_windowcenterx + ( fx1 * gr_viewsin - fy1 * gr_viewcos ) * gr_centerx / fy2 ;
2016-11-07 21:55:56 +00:00
fx2 = ( ( polyvertex_t * ) ( line - > pv2 ) ) - > x - gr_viewx ;
fy2 = ( ( polyvertex_t * ) ( line - > pv2 ) ) - > y - gr_viewy ;
2014-03-15 16:59:03 +00:00
fy1 = ( fx2 * gr_viewcos + fy2 * gr_viewsin ) ;
if ( fy1 < 0 )
// the point is back
fx2 = vid . width ;
else
fx2 = gr_windowcenterx + ( fx2 * gr_viewsin - fy2 * gr_viewcos ) * gr_centerx / fy1 ;
x1 = fx1 + 0.5f ;
x2 = fx2 + 0.5f ;
}
# else
// The seg is in the view range,
// but not necessarily visible.
angle1 = ( angle1 + ANGLE_90 ) > > ANGLETOFINESHIFT ;
angle2 = ( angle2 + ANGLE_90 ) > > ANGLETOFINESHIFT ;
x1 = gr_viewangletox [ angle1 ] ;
x2 = gr_viewangletox [ angle2 ] ;
# endif
// Does not cross a pixel?
// if (x1 == x2)
/* {
// BP: HERE IS THE MAIN PROBLEM !
//CONS_Debug(DBG_RENDER, "tineline\n");
return ;
}
*/
2017-01-10 18:01:03 +00:00
# endif
2014-03-15 16:59:03 +00:00
gr_backsector = line - > backsector ;
2017-01-10 18:01:03 +00:00
# ifdef NEWCLIP
if ( ! line - > backsector )
{
gld_clipper_SafeAddClipRange ( angle2 , angle1 ) ;
}
else
{
2018-02-07 17:46:01 +00:00
boolean bothceilingssky = false , bothfloorssky = false ;
2017-01-10 18:01:03 +00:00
gr_backsector = R_FakeFlat ( gr_backsector , & tempsec , NULL , NULL , true ) ;
2018-02-07 17:46:01 +00:00
if ( gr_backsector - > ceilingpic = = skyflatnum & & gr_frontsector - > ceilingpic = = skyflatnum )
bothceilingssky = true ;
if ( gr_backsector - > floorpic = = skyflatnum & & gr_frontsector - > floorpic = = skyflatnum )
bothfloorssky = true ;
if ( bothceilingssky & & bothfloorssky ) // everything's sky? let's save us a bit of time then
{
if (
# ifdef POLYOBJECTS
! line - > polyseg & &
# endif
! line - > sidedef - > midtexture
& & ( ( ! gr_frontsector - > ffloors & & ! gr_backsector - > ffloors )
| | ( gr_frontsector - > tag = = gr_backsector - > tag ) ) )
return ; // line is empty, don't even bother
// treat like wide open window instead
HWR_ProcessSeg ( ) ; // Doesn't need arguments because they're defined globally :D
return ;
}
2017-01-10 18:01:03 +00:00
if ( CheckClip ( line , gr_frontsector , gr_backsector ) )
{
gld_clipper_SafeAddClipRange ( angle2 , angle1 ) ;
2017-01-10 20:07:02 +00:00
checkforemptylines = false ;
2017-01-10 18:01:03 +00:00
}
2017-01-10 20:07:02 +00:00
// Reject empty lines used for triggers and special events.
// Identical floor and ceiling on both sides,
// identical light levels on both sides,
// and no middle texture.
if ( checkforemptylines & & R_IsEmptyLine ( line , gr_frontsector , gr_backsector ) )
return ;
2017-01-10 18:01:03 +00:00
}
HWR_ProcessSeg ( ) ; // Doesn't need arguments because they're defined globally :D
return ;
# else
2014-03-15 16:59:03 +00:00
// Single sided line?
if ( ! gr_backsector )
goto clipsolid ;
gr_backsector = R_FakeFlat ( gr_backsector , & tempsec , NULL , NULL , true ) ;
2018-02-07 17:46:01 +00:00
if ( gr_backsector - > ceilingpic = = skyflatnum & & gr_frontsector - > ceilingpic = = skyflatnum )
bothceilingssky = true ;
if ( gr_backsector - > floorpic = = skyflatnum & & gr_frontsector - > floorpic = = skyflatnum )
bothfloorssky = true ;
if ( bothceilingssky & & bothfloorssky ) // everything's sky? let's save us a bit of time then
{
if (
# ifdef POLYOBJECTS
! line - > polyseg & &
# endif
! line - > sidedef - > midtexture
& & ( ( ! gr_frontsector - > ffloors & & ! gr_backsector - > ffloors )
| | ( gr_frontsector - > tag = = gr_backsector - > tag ) ) )
return ; // line is empty, don't even bother
goto clippass ; // treat like wide open window instead
}
2016-06-04 17:31:21 +00:00
# ifdef ESLOPE
if ( gr_frontsector - > f_slope | | gr_frontsector - > c_slope | | gr_backsector - > f_slope | | gr_backsector - > c_slope )
{
fixed_t frontf1 , frontf2 , frontc1 , frontc2 ; // front floor/ceiling ends
fixed_t backf1 , backf2 , backc1 , backc2 ; // back floor ceiling ends
# define SLOPEPARAMS(slope, end1, end2, normalheight) \
if ( slope ) { \
end1 = P_GetZAt ( slope , v1x , v1y ) ; \
end2 = P_GetZAt ( slope , v2x , v2y ) ; \
} else \
end1 = end2 = normalheight ;
SLOPEPARAMS ( gr_frontsector - > f_slope , frontf1 , frontf2 , gr_frontsector - > floorheight )
SLOPEPARAMS ( gr_frontsector - > c_slope , frontc1 , frontc2 , gr_frontsector - > ceilingheight )
SLOPEPARAMS ( gr_backsector - > f_slope , backf1 , backf2 , gr_backsector - > floorheight )
SLOPEPARAMS ( gr_backsector - > c_slope , backc1 , backc2 , gr_backsector - > ceilingheight )
# undef SLOPEPARAMS
2018-02-03 19:48:18 +00:00
// if both ceilings are skies, consider it always "open"
// same for floors
2018-02-07 17:46:01 +00:00
if ( ! bothceilingssky & & ! bothfloorssky )
2016-06-04 17:31:21 +00:00
{
2018-02-01 22:04:04 +00:00
// Closed door.
if ( ( backc1 < = frontf1 & & backc2 < = frontf2 )
| | ( backf1 > = frontc1 & & backf2 > = frontc2 ) )
{
goto clipsolid ;
}
2014-03-15 16:59:03 +00:00
2018-02-01 22:04:04 +00:00
// Check for automap fix.
if ( backc1 < = backf1 & & backc2 < = backf2
& & ( ( backc1 > = frontc1 & & backc2 > = frontc2 ) | | gr_curline - > sidedef - > toptexture )
2018-02-03 18:30:49 +00:00
& & ( ( backf1 < = frontf1 & & backf2 > = frontf2 ) | | gr_curline - > sidedef - > bottomtexture ) )
2018-02-01 22:04:04 +00:00
goto clipsolid ;
}
2016-12-21 22:31:09 +00:00
2016-06-04 17:31:21 +00:00
// Window.
2018-02-07 17:46:01 +00:00
if ( ! bothceilingssky ) // ceilings are always the "same" when sky
if ( backc1 ! = frontc1 | | backc2 ! = frontc2 )
goto clippass ;
if ( ! bothfloorssky ) // floors are always the "same" when sky
if ( backf1 ! = frontf1 | | backf2 ! = frontf2 )
goto clippass ;
2016-06-04 17:31:21 +00:00
}
else
# endif
{
2018-02-03 19:48:18 +00:00
// if both ceilings are skies, consider it always "open"
// same for floors
2018-02-07 17:46:01 +00:00
if ( ! bothceilingssky & & ! bothfloorssky )
2018-02-01 22:04:04 +00:00
{
// Closed door.
if ( gr_backsector - > ceilingheight < = gr_frontsector - > floorheight | |
gr_backsector - > floorheight > = gr_frontsector - > ceilingheight )
goto clipsolid ;
// Check for automap fix.
if ( gr_backsector - > ceilingheight < = gr_backsector - > floorheight
& & ( ( gr_backsector - > ceilingheight > = gr_frontsector - > ceilingheight ) | | gr_curline - > sidedef - > toptexture )
2018-02-03 18:30:49 +00:00
& & ( ( gr_backsector - > floorheight < = gr_backsector - > floorheight ) | | gr_curline - > sidedef - > bottomtexture ) )
2018-02-01 22:04:04 +00:00
goto clipsolid ;
}
2016-12-21 22:31:09 +00:00
2016-06-04 17:31:21 +00:00
// Window.
2018-02-07 17:46:01 +00:00
if ( ! bothceilingssky ) // ceilings are always the "same" when sky
if ( gr_backsector - > ceilingheight ! = gr_frontsector - > ceilingheight )
goto clippass ;
if ( ! bothfloorssky ) // floors are always the "same" when sky
if ( gr_backsector - > floorheight ! = gr_frontsector - > floorheight )
goto clippass ;
2016-06-04 17:31:21 +00:00
}
2014-03-15 16:59:03 +00:00
// Reject empty lines used for triggers and special events.
// Identical floor and ceiling on both sides,
// identical light levels on both sides,
// and no middle texture.
2017-05-31 16:17:08 +00:00
if ( R_IsEmptyLine ( gr_curline , gr_frontsector , gr_backsector ) )
2014-03-15 16:59:03 +00:00
return ;
clippass :
if ( x1 = = x2 )
{ x2 + + ; x1 - = 2 ; }
HWR_ClipPassWallSegment ( x1 , x2 - 1 ) ;
return ;
clipsolid :
if ( x1 = = x2 )
goto clippass ;
HWR_ClipSolidWallSegment ( x1 , x2 - 1 ) ;
2017-01-10 18:01:03 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
// HWR_CheckBBox
// Checks BSP node/subtree bounding box.
// Returns true
// if some part of the bbox might be visible.
//
// modified to use local variables
static boolean HWR_CheckBBox ( fixed_t * bspcoord )
{
2017-01-10 18:01:03 +00:00
INT32 boxpos ;
2014-03-15 16:59:03 +00:00
fixed_t px1 , py1 , px2 , py2 ;
2017-01-10 18:01:03 +00:00
angle_t angle1 , angle2 ;
# ifndef NEWCLIP
INT32 sx1 , sx2 ;
angle_t span , tspan ;
# endif
2014-03-15 16:59:03 +00:00
// Find the corners of the box
// that define the edges from current viewpoint.
if ( dup_viewx < = bspcoord [ BOXLEFT ] )
boxpos = 0 ;
else if ( dup_viewx < bspcoord [ BOXRIGHT ] )
boxpos = 1 ;
else
boxpos = 2 ;
if ( dup_viewy > = bspcoord [ BOXTOP ] )
boxpos | = 0 ;
else if ( dup_viewy > bspcoord [ BOXBOTTOM ] )
boxpos | = 1 < < 2 ;
else
boxpos | = 2 < < 2 ;
if ( boxpos = = 5 )
return true ;
px1 = bspcoord [ checkcoord [ boxpos ] [ 0 ] ] ;
py1 = bspcoord [ checkcoord [ boxpos ] [ 1 ] ] ;
px2 = bspcoord [ checkcoord [ boxpos ] [ 2 ] ] ;
py2 = bspcoord [ checkcoord [ boxpos ] [ 3 ] ] ;
2017-01-10 18:01:03 +00:00
# ifdef NEWCLIP
angle1 = R_PointToAngle ( px1 , py1 ) ;
angle2 = R_PointToAngle ( px2 , py2 ) ;
return gld_clipper_SafeCheckRange ( angle2 , angle1 ) ;
# else
2014-03-15 16:59:03 +00:00
// check clip list for an open space
2018-05-26 12:13:37 +00:00
angle1 = R_PointToAngle2 ( dup_viewx > > 1 , dup_viewy > > 1 , px1 > > 1 , py1 > > 1 ) - dup_viewangle ;
angle2 = R_PointToAngle2 ( dup_viewx > > 1 , dup_viewy > > 1 , px2 > > 1 , py2 > > 1 ) - dup_viewangle ;
2014-03-15 16:59:03 +00:00
span = angle1 - angle2 ;
// Sitting on a line?
if ( span > = ANGLE_180 )
return true ;
tspan = angle1 + gr_clipangle ;
if ( tspan > 2 * gr_clipangle )
{
tspan - = 2 * gr_clipangle ;
// Totally off the left edge?
if ( tspan > = span )
return false ;
angle1 = gr_clipangle ;
}
tspan = gr_clipangle - angle2 ;
if ( tspan > 2 * gr_clipangle )
{
tspan - = 2 * gr_clipangle ;
// Totally off the left edge?
if ( tspan > = span )
return false ;
angle2 = ( angle_t ) - ( signed ) gr_clipangle ;
}
// Find the first clippost
// that touches the source post
// (adjacent pixels are touching).
angle1 = ( angle1 + ANGLE_90 ) > > ANGLETOFINESHIFT ;
angle2 = ( angle2 + ANGLE_90 ) > > ANGLETOFINESHIFT ;
sx1 = gr_viewangletox [ angle1 ] ;
sx2 = gr_viewangletox [ angle2 ] ;
// Does not cross a pixel.
if ( sx1 = = sx2 )
return false ;
return HWR_ClipToSolidSegs ( sx1 , sx2 - 1 ) ;
2017-01-10 18:01:03 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
# ifdef POLYOBJECTS
//
// HWR_AddPolyObjectSegs
//
// haleyjd 02/19/06
// Adds all segs in all polyobjects in the given subsector.
// Modified for hardware rendering.
//
static inline void HWR_AddPolyObjectSegs ( void )
{
size_t i , j ;
seg_t * gr_fakeline = Z_Calloc ( sizeof ( seg_t ) , PU_STATIC , NULL ) ;
polyvertex_t * pv1 = Z_Calloc ( sizeof ( polyvertex_t ) , PU_STATIC , NULL ) ;
polyvertex_t * pv2 = Z_Calloc ( sizeof ( polyvertex_t ) , PU_STATIC , NULL ) ;
// Sort through all the polyobjects
for ( i = 0 ; i < numpolys ; + + i )
{
// Render the polyobject's lines
for ( j = 0 ; j < po_ptrs [ i ] - > segCount ; + + j )
{
// Copy the info of a polyobject's seg, then convert it to OpenGL floating point
M_Memcpy ( gr_fakeline , po_ptrs [ i ] - > segs [ j ] , sizeof ( seg_t ) ) ;
// Now convert the line to float and add it to be rendered
pv1 - > x = FIXED_TO_FLOAT ( gr_fakeline - > v1 - > x ) ;
pv1 - > y = FIXED_TO_FLOAT ( gr_fakeline - > v1 - > y ) ;
pv2 - > x = FIXED_TO_FLOAT ( gr_fakeline - > v2 - > x ) ;
pv2 - > y = FIXED_TO_FLOAT ( gr_fakeline - > v2 - > y ) ;
2016-11-07 21:55:56 +00:00
gr_fakeline - > pv1 = pv1 ;
gr_fakeline - > pv2 = pv2 ;
2014-03-15 16:59:03 +00:00
HWR_AddLine ( gr_fakeline ) ;
}
}
// Free temporary data no longer needed
Z_Free ( pv2 ) ;
Z_Free ( pv1 ) ;
Z_Free ( gr_fakeline ) ;
}
2014-10-27 20:57:45 +00:00
# ifdef POLYOBJECTS_PLANES
2016-07-27 18:56:21 +00:00
static void HWR_RenderPolyObjectPlane ( polyobj_t * polysector , boolean isceiling , fixed_t fixedheight ,
2019-11-09 01:58:41 +00:00
FBITFIELD blendmode , UINT8 lightlevel , levelflat_t * levelflat , sector_t * FOFsector ,
2014-10-27 20:57:45 +00:00
UINT8 alpha , extracolormap_t * planecolormap )
{
float height ; //constant y for all points on the convex flat polygon
FOutVector * v3d ;
INT32 i ;
float flatxref , flatyref ;
2019-11-09 02:42:15 +00:00
float fflatwidth = 64.0f , fflatheight = 64.0f ;
INT32 flatflag = 63 ;
2019-11-09 01:58:41 +00:00
boolean texflat = false ;
2014-10-27 20:57:45 +00:00
size_t len ;
float scrollx = 0.0f , scrolly = 0.0f ;
angle_t angle = 0 ;
FSurfaceInfo Surf ;
2019-12-25 19:22:01 +00:00
fixed_t tempxs , tempyt ;
2014-10-27 20:57:45 +00:00
size_t nrPlaneVerts ;
static FOutVector * planeVerts = NULL ;
static UINT16 numAllocedPlaneVerts = 0 ;
nrPlaneVerts = polysector - > numVertices ;
height = FIXED_TO_FLOAT ( fixedheight ) ;
if ( nrPlaneVerts < 3 ) //not even a triangle ?
return ;
2019-07-09 20:43:38 +00:00
if ( nrPlaneVerts > ( size_t ) UINT16_MAX ) // FIXME: exceeds plVerts size
2014-10-27 20:57:45 +00:00
{
2015-01-10 22:27:24 +00:00
CONS_Debug ( DBG_RENDER , " polygon size of %s exceeds max value of %d vertices \n " , sizeu1 ( nrPlaneVerts ) , UINT16_MAX ) ;
2014-10-27 20:57:45 +00:00
return ;
}
// Allocate plane-vertex buffer if we need to
if ( ! planeVerts | | nrPlaneVerts > numAllocedPlaneVerts )
{
numAllocedPlaneVerts = ( UINT16 ) nrPlaneVerts ;
Z_Free ( planeVerts ) ;
Z_Malloc ( numAllocedPlaneVerts * sizeof ( FOutVector ) , PU_LEVEL , & planeVerts ) ;
}
2019-11-09 02:42:15 +00:00
// set texture for polygon
if ( levelflat ! = NULL )
2014-10-27 20:57:45 +00:00
{
2019-11-09 02:42:15 +00:00
if ( levelflat - > type = = LEVELFLAT_TEXTURE )
2019-11-09 01:58:41 +00:00
{
2019-11-09 02:42:15 +00:00
fflatwidth = textures [ levelflat - > u . texture . num ] - > width ;
fflatheight = textures [ levelflat - > u . texture . num ] - > height ;
texflat = true ;
2019-11-09 01:58:41 +00:00
}
2019-11-09 02:42:15 +00:00
else if ( levelflat - > type = = LEVELFLAT_FLAT )
{
len = W_LumpLength ( levelflat - > u . flat . lumpnum ) ;
2014-10-27 20:57:45 +00:00
2019-11-09 02:42:15 +00:00
switch ( len )
{
case 4194304 : // 2048x2048 lump
fflatwidth = fflatheight = 2048.0f ;
break ;
case 1048576 : // 1024x1024 lump
fflatwidth = fflatheight = 1024.0f ;
break ;
case 262144 : // 512x512 lump
fflatwidth = fflatheight = 512.0f ;
break ;
case 65536 : // 256x256 lump
fflatwidth = fflatheight = 256.0f ;
break ;
case 16384 : // 128x128 lump
fflatwidth = fflatheight = 128.0f ;
break ;
case 1024 : // 32x32 lump
fflatwidth = fflatheight = 32.0f ;
break ;
default : // 64x64 lump
fflatwidth = fflatheight = 64.0f ;
break ;
}
2019-05-21 03:28:52 +00:00
2019-11-09 02:42:15 +00:00
flatflag = ( ( INT32 ) fflatwidth ) - 1 ;
}
2019-05-26 21:16:13 +00:00
}
2019-11-09 02:42:15 +00:00
else // set no texture
HWD . pfnSetTexture ( NULL ) ;
2019-05-21 03:28:52 +00:00
2014-10-27 20:57:45 +00:00
// reference point for flat texture coord for each vertex around the polygon
2019-05-26 21:16:13 +00:00
flatxref = ( float ) ( ( polysector - > origVerts [ 0 ] . x & ( ~ flatflag ) ) / fflatwidth ) ;
flatyref = ( float ) ( ( polysector - > origVerts [ 0 ] . y & ( ~ flatflag ) ) / fflatheight ) ;
2014-10-27 20:57:45 +00:00
// transform
v3d = planeVerts ;
if ( FOFsector ! = NULL )
{
2016-07-27 18:56:21 +00:00
if ( ! isceiling ) // it's a floor
2014-10-27 20:57:45 +00:00
{
2019-05-21 03:28:52 +00:00
scrollx = FIXED_TO_FLOAT ( FOFsector - > floor_xoffs ) / fflatwidth ;
scrolly = FIXED_TO_FLOAT ( FOFsector - > floor_yoffs ) / fflatheight ;
2014-10-27 20:57:45 +00:00
angle = FOFsector - > floorpic_angle > > ANGLETOFINESHIFT ;
}
else // it's a ceiling
{
2019-05-21 03:28:52 +00:00
scrollx = FIXED_TO_FLOAT ( FOFsector - > ceiling_xoffs ) / fflatwidth ;
scrolly = FIXED_TO_FLOAT ( FOFsector - > ceiling_yoffs ) / fflatheight ;
2014-10-27 20:57:45 +00:00
angle = FOFsector - > ceilingpic_angle > > ANGLETOFINESHIFT ;
}
}
else if ( gr_frontsector )
{
2016-07-27 18:56:21 +00:00
if ( ! isceiling ) // it's a floor
2014-10-27 20:57:45 +00:00
{
2019-05-21 03:28:52 +00:00
scrollx = FIXED_TO_FLOAT ( gr_frontsector - > floor_xoffs ) / fflatwidth ;
scrolly = FIXED_TO_FLOAT ( gr_frontsector - > floor_yoffs ) / fflatheight ;
2014-10-27 20:57:45 +00:00
angle = gr_frontsector - > floorpic_angle > > ANGLETOFINESHIFT ;
}
else // it's a ceiling
{
2019-05-21 03:28:52 +00:00
scrollx = FIXED_TO_FLOAT ( gr_frontsector - > ceiling_xoffs ) / fflatwidth ;
scrolly = FIXED_TO_FLOAT ( gr_frontsector - > ceiling_yoffs ) / fflatheight ;
2014-10-27 20:57:45 +00:00
angle = gr_frontsector - > ceilingpic_angle > > ANGLETOFINESHIFT ;
}
}
if ( angle ) // Only needs to be done if there's an altered angle
{
// This needs to be done so that it scrolls in a different direction after rotation like software
2019-12-25 19:22:01 +00:00
tempxs = FLOAT_TO_FIXED ( scrollx ) ;
tempyt = FLOAT_TO_FIXED ( scrolly ) ;
scrollx = ( FIXED_TO_FLOAT ( FixedMul ( tempxs , FINECOSINE ( angle ) ) - FixedMul ( tempyt , FINESINE ( angle ) ) ) ) ;
scrolly = ( FIXED_TO_FLOAT ( FixedMul ( tempxs , FINESINE ( angle ) ) + FixedMul ( tempyt , FINECOSINE ( angle ) ) ) ) ;
2014-10-27 20:57:45 +00:00
// This needs to be done so everything aligns after rotation
// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
2019-12-25 19:22:01 +00:00
tempxs = FLOAT_TO_FIXED ( flatxref ) ;
tempyt = FLOAT_TO_FIXED ( flatyref ) ;
flatxref = ( FIXED_TO_FLOAT ( FixedMul ( tempxs , FINECOSINE ( angle ) ) - FixedMul ( tempyt , FINESINE ( angle ) ) ) ) ;
flatyref = ( FIXED_TO_FLOAT ( FixedMul ( tempxs , FINESINE ( angle ) ) + FixedMul ( tempyt , FINECOSINE ( angle ) ) ) ) ;
2014-10-27 20:57:45 +00:00
}
2014-11-02 04:15:05 +00:00
for ( i = 0 ; i < ( INT32 ) nrPlaneVerts ; i + + , v3d + + )
2014-10-27 20:57:45 +00:00
{
2019-05-26 21:16:13 +00:00
// Go from the polysector's original vertex locations
// Means the flat is offset based on the original vertex locations
if ( texflat )
{
2019-12-25 19:22:01 +00:00
v3d - > s = ( float ) ( FIXED_TO_FLOAT ( polysector - > origVerts [ i ] . x ) / fflatwidth ) + scrollx ;
v3d - > t = - ( float ) ( FIXED_TO_FLOAT ( polysector - > origVerts [ i ] . y ) / fflatheight ) + scrolly ;
2019-05-26 21:16:13 +00:00
}
else
{
2019-12-25 19:22:01 +00:00
v3d - > s = ( float ) ( ( FIXED_TO_FLOAT ( polysector - > origVerts [ i ] . x ) / fflatwidth ) - flatxref + scrollx ) ;
v3d - > t = ( float ) ( flatyref - ( FIXED_TO_FLOAT ( polysector - > origVerts [ i ] . y ) / fflatheight ) + scrolly ) ;
2019-05-26 21:16:13 +00:00
}
2014-10-27 20:57:45 +00:00
// Need to rotate before translate
if ( angle ) // Only needs to be done if there's an altered angle
{
2019-12-25 19:22:01 +00:00
tempxs = FLOAT_TO_FIXED ( v3d - > s ) ;
tempyt = FLOAT_TO_FIXED ( v3d - > t ) ;
2019-05-26 21:16:13 +00:00
if ( texflat )
2019-12-25 19:22:01 +00:00
tempyt = - tempyt ;
v3d - > s = ( FIXED_TO_FLOAT ( FixedMul ( tempxs , FINECOSINE ( angle ) ) - FixedMul ( tempyt , FINESINE ( angle ) ) ) ) ;
v3d - > t = ( FIXED_TO_FLOAT ( - FixedMul ( tempxs , FINESINE ( angle ) ) - FixedMul ( tempyt , FINECOSINE ( angle ) ) ) ) ;
2014-10-27 20:57:45 +00:00
}
2014-11-14 22:19:44 +00:00
v3d - > x = FIXED_TO_FLOAT ( polysector - > vertices [ i ] - > x ) ;
2014-10-27 20:57:45 +00:00
v3d - > y = height ;
2014-11-14 22:19:44 +00:00
v3d - > z = FIXED_TO_FLOAT ( polysector - > vertices [ i ] - > y ) ;
2014-10-27 20:57:45 +00:00
}
2019-12-25 19:22:01 +00:00
HWR_Lighting ( & Surf , lightlevel , planecolormap ) ;
2014-10-27 20:57:45 +00:00
if ( blendmode & PF_Translucent )
{
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = ( UINT8 ) alpha ;
2014-10-27 20:57:45 +00:00
blendmode | = PF_Modulated | PF_Occlude | PF_Clip ;
}
else
blendmode | = PF_Masked | PF_Modulated | PF_Clip ;
2019-12-25 19:22:01 +00:00
HWD . pfnSetShader ( 1 ) ; // floor shader
2014-10-27 20:57:45 +00:00
HWD . pfnDrawPolygon ( & Surf , planeVerts , nrPlaneVerts , blendmode ) ;
}
static void HWR_AddPolyObjectPlanes ( void )
{
size_t i ;
2014-11-02 03:52:17 +00:00
sector_t * polyobjsector ;
2019-08-22 21:30:36 +00:00
INT32 light = 0 ;
2014-10-27 20:57:45 +00:00
// Polyobject Planes need their own function for drawing because they don't have extrasubsectors by themselves
// It should be okay because polyobjects should always be convex anyway
for ( i = 0 ; i < numpolys ; i + + )
{
polyobjsector = po_ptrs [ i ] - > lines [ 0 ] - > backsector ; // the in-level polyobject sector
if ( ! ( po_ptrs [ i ] - > flags & POF_RENDERPLANES ) ) // Only render planes when you should
continue ;
if ( po_ptrs [ i ] - > translucency > = NUMTRANSMAPS )
continue ;
if ( polyobjsector - > floorheight < = gr_frontsector - > ceilingheight
& & polyobjsector - > floorheight > = gr_frontsector - > floorheight
& & ( viewz < polyobjsector - > floorheight ) )
{
2019-08-22 21:30:36 +00:00
light = R_GetPlaneLight ( gr_frontsector , polyobjsector - > floorheight , true ) ;
2014-10-27 20:57:45 +00:00
if ( po_ptrs [ i ] - > translucency > 0 )
{
FSurfaceInfo Surf ;
2019-08-22 21:30:36 +00:00
FBITFIELD blendmode ;
memset ( & Surf , 0x00 , sizeof ( Surf ) ) ;
blendmode = HWR_TranstableToAlpha ( po_ptrs [ i ] - > translucency , & Surf ) ;
2019-11-09 01:58:41 +00:00
HWR_AddTransparentPolyobjectFloor ( & levelflats [ polyobjsector - > floorpic ] , po_ptrs [ i ] , false , polyobjsector - > floorheight ,
2019-12-25 19:22:01 +00:00
( light = = - 1 ? gr_frontsector - > lightlevel : * gr_frontsector - > lightlist [ light ] . lightlevel ) , Surf . PolyColor . s . alpha , polyobjsector , blendmode , ( light = = - 1 ? gr_frontsector - > extra_colormap : * gr_frontsector - > lightlist [ light ] . extra_colormap ) ) ;
2014-10-27 20:57:45 +00:00
}
else
{
2019-11-09 02:42:15 +00:00
HWR_GetLevelFlat ( & levelflats [ polyobjsector - > floorpic ] ) ;
2016-07-27 18:56:21 +00:00
HWR_RenderPolyObjectPlane ( po_ptrs [ i ] , false , polyobjsector - > floorheight , PF_Occlude ,
2019-11-09 01:58:41 +00:00
( light = = - 1 ? gr_frontsector - > lightlevel : * gr_frontsector - > lightlist [ light ] . lightlevel ) , & levelflats [ polyobjsector - > floorpic ] ,
2019-08-22 21:30:36 +00:00
polyobjsector , 255 , ( light = = - 1 ? gr_frontsector - > extra_colormap : * gr_frontsector - > lightlist [ light ] . extra_colormap ) ) ;
2014-10-27 20:57:45 +00:00
}
}
if ( polyobjsector - > ceilingheight > = gr_frontsector - > floorheight
& & polyobjsector - > ceilingheight < = gr_frontsector - > ceilingheight
& & ( viewz > polyobjsector - > ceilingheight ) )
{
2019-08-22 21:30:36 +00:00
light = R_GetPlaneLight ( gr_frontsector , polyobjsector - > ceilingheight , true ) ;
2014-10-27 20:57:45 +00:00
if ( po_ptrs [ i ] - > translucency > 0 )
{
FSurfaceInfo Surf ;
2016-05-27 05:28:21 +00:00
FBITFIELD blendmode ;
2016-05-27 05:19:16 +00:00
memset ( & Surf , 0x00 , sizeof ( Surf ) ) ;
2016-05-27 05:28:21 +00:00
blendmode = HWR_TranstableToAlpha ( po_ptrs [ i ] - > translucency , & Surf ) ;
2019-11-09 01:58:41 +00:00
HWR_AddTransparentPolyobjectFloor ( & levelflats [ polyobjsector - > ceilingpic ] , po_ptrs [ i ] , true , polyobjsector - > ceilingheight ,
2019-12-25 19:22:01 +00:00
( light = = - 1 ? gr_frontsector - > lightlevel : * gr_frontsector - > lightlist [ light ] . lightlevel ) , Surf . PolyColor . s . alpha , polyobjsector , blendmode , ( light = = - 1 ? gr_frontsector - > extra_colormap : * gr_frontsector - > lightlist [ light ] . extra_colormap ) ) ;
2014-10-27 20:57:45 +00:00
}
else
{
2019-11-09 02:42:15 +00:00
HWR_GetLevelFlat ( & levelflats [ polyobjsector - > ceilingpic ] ) ;
2016-07-27 18:56:21 +00:00
HWR_RenderPolyObjectPlane ( po_ptrs [ i ] , true , polyobjsector - > ceilingheight , PF_Occlude ,
2019-12-08 07:15:25 +00:00
( light = = - 1 ? gr_frontsector - > lightlevel : * gr_frontsector - > lightlist [ light ] . lightlevel ) , & levelflats [ polyobjsector - > ceilingpic ] ,
2019-08-22 21:30:36 +00:00
polyobjsector , 255 , ( light = = - 1 ? gr_frontsector - > extra_colormap : * gr_frontsector - > lightlist [ light ] . extra_colormap ) ) ;
2014-10-27 20:57:45 +00:00
}
}
}
}
# endif
2014-03-15 16:59:03 +00:00
# endif
// -----------------+
// HWR_Subsector : Determine floor/ceiling planes.
// : Add sprites of things in sector.
// : Draw one or more line segments.
// Notes : Sets gr_cursectorlight to the light of the parent sector, to modulate wall textures
// -----------------+
static void HWR_Subsector ( size_t num )
{
INT16 count ;
seg_t * line ;
subsector_t * sub ;
2018-03-29 22:28:54 +00:00
static sector_t tempsec ; //SoM: 4/7/2000
2014-03-15 16:59:03 +00:00
INT32 floorlightlevel ;
INT32 ceilinglightlevel ;
INT32 locFloorHeight , locCeilingHeight ;
2016-01-28 13:56:23 +00:00
INT32 cullFloorHeight , cullCeilingHeight ;
2014-03-15 16:59:03 +00:00
INT32 light = 0 ;
extracolormap_t * floorcolormap ;
extracolormap_t * ceilingcolormap ;
# ifdef PARANOIA //no risk while developing, enough debugging nights!
if ( num > = addsubsector )
I_Error ( " HWR_Subsector: ss %s with numss = %s, addss = %s \n " ,
sizeu1 ( num ) , sizeu2 ( numsubsectors ) , sizeu3 ( addsubsector ) ) ;
/*if (num >= numsubsectors)
I_Error ( " HWR_Subsector: ss %i with numss = %i " ,
num ,
numsubsectors ) ; */
# endif
if ( num < numsubsectors )
{
// subsector
sub = & subsectors [ num ] ;
// sector
gr_frontsector = sub - > sector ;
// how many linedefs
count = sub - > numlines ;
// first line seg
line = & segs [ sub - > firstline ] ;
}
else
{
// there are no segs but only planes
sub = & subsectors [ 0 ] ;
gr_frontsector = sub - > sector ;
count = 0 ;
line = NULL ;
}
//SoM: 4/7/2000: Test to make Boom water work in Hardware mode.
gr_frontsector = R_FakeFlat ( gr_frontsector , & tempsec , & floorlightlevel ,
& ceilinglightlevel , false ) ;
//FIXME: Use floorlightlevel and ceilinglightlevel insted of lightlevel.
floorcolormap = ceilingcolormap = gr_frontsector - > extra_colormap ;
// ------------------------------------------------------------------------
// sector lighting, DISABLED because it's done in HWR_StoreWallRange
// ------------------------------------------------------------------------
/// \todo store a RGBA instead of just intensity, allow coloured sector lighting
//light = (FUBYTE)(sub->sector->lightlevel & 0xFF) / 255.0f;
//gr_cursectorlight.red = light;
//gr_cursectorlight.green = light;
//gr_cursectorlight.blue = light;
//gr_cursectorlight.alpha = light;
// ----- for special tricks with HW renderer -----
if ( gr_frontsector - > pseudoSector )
{
2016-01-24 08:41:30 +00:00
cullFloorHeight = locFloorHeight = gr_frontsector - > virtualFloorheight ;
cullCeilingHeight = locCeilingHeight = gr_frontsector - > virtualCeilingheight ;
2014-03-15 16:59:03 +00:00
}
else if ( gr_frontsector - > virtualFloor )
{
2016-01-28 13:56:23 +00:00
///@TODO Is this whole virtualFloor mess even useful? I don't think it even triggers ever.
2016-01-24 08:41:30 +00:00
cullFloorHeight = locFloorHeight = gr_frontsector - > virtualFloorheight ;
2014-03-15 16:59:03 +00:00
if ( gr_frontsector - > virtualCeiling )
2016-01-24 08:41:30 +00:00
cullCeilingHeight = locCeilingHeight = gr_frontsector - > virtualCeilingheight ;
2014-03-15 16:59:03 +00:00
else
2016-01-24 08:41:30 +00:00
cullCeilingHeight = locCeilingHeight = gr_frontsector - > ceilingheight ;
2014-03-15 16:59:03 +00:00
}
else if ( gr_frontsector - > virtualCeiling )
{
2016-01-24 08:41:30 +00:00
cullCeilingHeight = locCeilingHeight = gr_frontsector - > virtualCeilingheight ;
cullFloorHeight = locFloorHeight = gr_frontsector - > floorheight ;
2014-03-15 16:59:03 +00:00
}
else
{
2016-01-24 08:41:30 +00:00
cullFloorHeight = locFloorHeight = gr_frontsector - > floorheight ;
cullCeilingHeight = locCeilingHeight = gr_frontsector - > ceilingheight ;
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
if ( gr_frontsector - > f_slope )
{
cullFloorHeight = P_GetZAt ( gr_frontsector - > f_slope , viewx , viewy ) ;
locFloorHeight = P_GetZAt ( gr_frontsector - > f_slope , gr_frontsector - > soundorg . x , gr_frontsector - > soundorg . y ) ;
}
2016-01-24 08:41:30 +00:00
2016-01-28 13:56:23 +00:00
if ( gr_frontsector - > c_slope )
{
cullCeilingHeight = P_GetZAt ( gr_frontsector - > c_slope , viewx , viewy ) ;
locCeilingHeight = P_GetZAt ( gr_frontsector - > c_slope , gr_frontsector - > soundorg . x , gr_frontsector - > soundorg . y ) ;
}
2016-01-24 08:41:30 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
// ----- end special tricks -----
if ( gr_frontsector - > ffloors )
{
if ( gr_frontsector - > moved )
{
gr_frontsector - > numlights = sub - > sector - > numlights = 0 ;
R_Prep3DFloors ( gr_frontsector ) ;
sub - > sector - > lightlist = gr_frontsector - > lightlist ;
sub - > sector - > numlights = gr_frontsector - > numlights ;
sub - > sector - > moved = gr_frontsector - > moved = false ;
}
light = R_GetPlaneLight ( gr_frontsector , locFloorHeight , false ) ;
if ( gr_frontsector - > floorlightsec = = - 1 )
floorlightlevel = * gr_frontsector - > lightlist [ light ] . lightlevel ;
2018-09-12 20:28:55 +00:00
floorcolormap = * gr_frontsector - > lightlist [ light ] . extra_colormap ;
2014-03-15 16:59:03 +00:00
light = R_GetPlaneLight ( gr_frontsector , locCeilingHeight , false ) ;
if ( gr_frontsector - > ceilinglightsec = = - 1 )
ceilinglightlevel = * gr_frontsector - > lightlist [ light ] . lightlevel ;
2018-09-12 20:28:55 +00:00
ceilingcolormap = * gr_frontsector - > lightlist [ light ] . extra_colormap ;
2014-03-15 16:59:03 +00:00
}
sub - > sector - > extra_colormap = gr_frontsector - > extra_colormap ;
// render floor ?
# ifdef DOPLANES
// yeah, easy backface cull! :)
2016-01-24 08:41:30 +00:00
if ( cullFloorHeight < dup_viewz )
2014-03-15 16:59:03 +00:00
{
if ( gr_frontsector - > floorpic ! = skyflatnum )
{
if ( sub - > validcount ! = validcount )
{
2019-11-09 02:42:15 +00:00
HWR_GetLevelFlat ( & levelflats [ gr_frontsector - > floorpic ] ) ;
2020-03-22 17:13:59 +00:00
HWR_RenderPlane ( sub , & extrasubsectors [ num ] , false ,
2016-01-28 13:56:23 +00:00
// Hack to make things continue to work around slopes.
locFloorHeight = = cullFloorHeight ? locFloorHeight : gr_frontsector - > floorheight ,
// We now return you to your regularly scheduled rendering.
2019-12-25 19:22:01 +00:00
PF_Occlude , floorlightlevel , & levelflats [ gr_frontsector - > floorpic ] , NULL , 255 , floorcolormap ) ;
2014-03-15 16:59:03 +00:00
}
}
else
{
# ifdef POLYSKY
HWR_RenderSkyPlane ( & extrasubsectors [ num ] , locFloorHeight ) ;
# endif
}
}
2016-01-24 08:41:30 +00:00
if ( cullCeilingHeight > dup_viewz )
2014-03-15 16:59:03 +00:00
{
if ( gr_frontsector - > ceilingpic ! = skyflatnum )
{
if ( sub - > validcount ! = validcount )
{
2019-11-09 02:42:15 +00:00
HWR_GetLevelFlat ( & levelflats [ gr_frontsector - > ceilingpic ] ) ;
2020-03-22 17:13:59 +00:00
HWR_RenderPlane ( sub , & extrasubsectors [ num ] , true ,
2016-01-28 13:56:23 +00:00
// Hack to make things continue to work around slopes.
locCeilingHeight = = cullCeilingHeight ? locCeilingHeight : gr_frontsector - > ceilingheight ,
// We now return you to your regularly scheduled rendering.
2019-12-25 19:22:01 +00:00
PF_Occlude , ceilinglightlevel , & levelflats [ gr_frontsector - > ceilingpic ] , NULL , 255 , ceilingcolormap ) ;
2014-03-15 16:59:03 +00:00
}
}
else
{
# ifdef POLYSKY
HWR_RenderSkyPlane ( & extrasubsectors [ num ] , locCeilingHeight ) ;
# endif
}
}
# ifndef POLYSKY
// Moved here because before, when above the ceiling and the floor does not have the sky flat, it doesn't draw the sky
if ( gr_frontsector - > ceilingpic = = skyflatnum | | gr_frontsector - > floorpic = = skyflatnum )
drawsky = true ;
# endif
# ifdef R_FAKEFLOORS
if ( gr_frontsector - > ffloors )
{
/// \todo fix light, xoffs, yoffs, extracolormap ?
ffloor_t * rover ;
for ( rover = gr_frontsector - > ffloors ;
rover ; rover = rover - > next )
{
2016-01-28 13:56:23 +00:00
fixed_t cullHeight , centerHeight ;
2016-01-25 05:57:53 +00:00
// bottom plane
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
if ( * rover - > b_slope )
{
cullHeight = P_GetZAt ( * rover - > b_slope , viewx , viewy ) ;
centerHeight = P_GetZAt ( * rover - > b_slope , gr_frontsector - > soundorg . x , gr_frontsector - > soundorg . y ) ;
}
else
2016-01-25 05:57:53 +00:00
# endif
cullHeight = centerHeight = * rover - > bottomheight ;
2014-03-15 16:59:03 +00:00
if ( ! ( rover - > flags & FF_EXISTS ) | | ! ( rover - > flags & FF_RENDERPLANES ) )
continue ;
if ( sub - > validcount = = validcount )
continue ;
2016-01-25 05:57:53 +00:00
if ( centerHeight < = locCeilingHeight & &
centerHeight > = locFloorHeight & &
( ( dup_viewz < cullHeight & & ! ( rover - > flags & FF_INVERTPLANES ) ) | |
( dup_viewz > cullHeight & & ( rover - > flags & FF_BOTHPLANES | | rover - > flags & FF_INVERTPLANES ) ) ) )
2014-03-15 16:59:03 +00:00
{
if ( rover - > flags & FF_FOG )
{
UINT8 alpha ;
2016-01-25 05:57:53 +00:00
light = R_GetPlaneLight ( gr_frontsector , centerHeight , dup_viewz < cullHeight ? true : false ) ;
2019-12-25 19:22:01 +00:00
alpha = HWR_FogBlockAlpha ( * gr_frontsector - > lightlist [ light ] . lightlevel , rover - > master - > frontsector - > extra_colormap ) ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
HWR_AddTransparentFloor ( 0 ,
2014-03-15 16:59:03 +00:00
& extrasubsectors [ num ] ,
2016-07-27 18:56:21 +00:00
false ,
2014-03-15 16:59:03 +00:00
* rover - > bottomheight ,
* gr_frontsector - > lightlist [ light ] . lightlevel ,
2018-03-15 23:58:37 +00:00
alpha , rover - > master - > frontsector , PF_Fog | PF_NoTexture ,
2014-03-15 16:59:03 +00:00
true , rover - > master - > frontsector - > extra_colormap ) ;
}
2017-09-08 23:41:11 +00:00
else if ( rover - > flags & FF_TRANSLUCENT & & rover - > alpha < 256 ) // SoM: Flags are more efficient
2014-03-15 16:59:03 +00:00
{
2016-01-25 05:57:53 +00:00
light = R_GetPlaneLight ( gr_frontsector , centerHeight , dup_viewz < cullHeight ? true : false ) ;
2019-12-25 19:22:01 +00:00
2019-11-09 01:58:41 +00:00
HWR_AddTransparentFloor ( & levelflats [ * rover - > bottompic ] ,
2014-03-15 16:59:03 +00:00
& extrasubsectors [ num ] ,
2016-07-27 18:56:21 +00:00
false ,
2014-03-15 16:59:03 +00:00
* rover - > bottomheight ,
* gr_frontsector - > lightlist [ light ] . lightlevel ,
2019-12-25 19:22:01 +00:00
rover - > alpha - 1 > 255 ? 255 : rover - > alpha - 1 , rover - > master - > frontsector , ( rover - > flags & FF_RIPPLE ? PF_Ripple : 0 ) | PF_Translucent ,
2018-09-12 20:28:55 +00:00
false , * gr_frontsector - > lightlist [ light ] . extra_colormap ) ;
2014-03-15 16:59:03 +00:00
}
else
{
2019-11-09 02:42:15 +00:00
HWR_GetLevelFlat ( & levelflats [ * rover - > bottompic ] ) ;
2016-01-25 05:57:53 +00:00
light = R_GetPlaneLight ( gr_frontsector , centerHeight , dup_viewz < cullHeight ? true : false ) ;
2020-04-25 05:10:30 +00:00
HWR_RenderPlane ( sub , & extrasubsectors [ num ] , false , * rover - > bottomheight , ( rover - > flags & FF_RIPPLE ? PF_Ripple : 0 ) | PF_Occlude , * gr_frontsector - > lightlist [ light ] . lightlevel , & levelflats [ * rover - > bottompic ] ,
2019-12-25 19:22:01 +00:00
rover - > master - > frontsector , 255 , * gr_frontsector - > lightlist [ light ] . extra_colormap ) ;
2014-03-15 16:59:03 +00:00
}
}
2016-01-25 05:57:53 +00:00
// top plane
# ifdef ESLOPE
2016-01-28 13:56:23 +00:00
if ( * rover - > t_slope )
{
cullHeight = P_GetZAt ( * rover - > t_slope , viewx , viewy ) ;
centerHeight = P_GetZAt ( * rover - > t_slope , gr_frontsector - > soundorg . x , gr_frontsector - > soundorg . y ) ;
}
else
2016-01-25 05:57:53 +00:00
# endif
cullHeight = centerHeight = * rover - > topheight ;
if ( centerHeight > = locFloorHeight & &
centerHeight < = locCeilingHeight & &
( ( dup_viewz > cullHeight & & ! ( rover - > flags & FF_INVERTPLANES ) ) | |
( dup_viewz < cullHeight & & ( rover - > flags & FF_BOTHPLANES | | rover - > flags & FF_INVERTPLANES ) ) ) )
2014-03-15 16:59:03 +00:00
{
if ( rover - > flags & FF_FOG )
{
UINT8 alpha ;
2016-01-25 05:57:53 +00:00
light = R_GetPlaneLight ( gr_frontsector , centerHeight , dup_viewz < cullHeight ? true : false ) ;
2019-12-25 19:22:01 +00:00
alpha = HWR_FogBlockAlpha ( * gr_frontsector - > lightlist [ light ] . lightlevel , rover - > master - > frontsector - > extra_colormap ) ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
HWR_AddTransparentFloor ( 0 ,
2014-03-15 16:59:03 +00:00
& extrasubsectors [ num ] ,
2016-07-27 18:56:21 +00:00
true ,
2014-03-15 16:59:03 +00:00
* rover - > topheight ,
* gr_frontsector - > lightlist [ light ] . lightlevel ,
2018-03-15 23:58:37 +00:00
alpha , rover - > master - > frontsector , PF_Fog | PF_NoTexture ,
2014-03-15 16:59:03 +00:00
true , rover - > master - > frontsector - > extra_colormap ) ;
}
2017-09-08 23:41:11 +00:00
else if ( rover - > flags & FF_TRANSLUCENT & & rover - > alpha < 256 )
2014-03-15 16:59:03 +00:00
{
2016-01-25 05:57:53 +00:00
light = R_GetPlaneLight ( gr_frontsector , centerHeight , dup_viewz < cullHeight ? true : false ) ;
2019-12-25 19:22:01 +00:00
2019-11-09 01:58:41 +00:00
HWR_AddTransparentFloor ( & levelflats [ * rover - > toppic ] ,
2014-03-15 16:59:03 +00:00
& extrasubsectors [ num ] ,
2016-07-27 18:56:21 +00:00
true ,
2014-03-15 16:59:03 +00:00
* rover - > topheight ,
* gr_frontsector - > lightlist [ light ] . lightlevel ,
2019-12-25 19:22:01 +00:00
rover - > alpha - 1 > 255 ? 255 : rover - > alpha - 1 , rover - > master - > frontsector , ( rover - > flags & FF_RIPPLE ? PF_Ripple : 0 ) | PF_Translucent ,
2018-09-12 20:28:55 +00:00
false , * gr_frontsector - > lightlist [ light ] . extra_colormap ) ;
2014-03-15 16:59:03 +00:00
}
else
{
2019-11-09 02:42:15 +00:00
HWR_GetLevelFlat ( & levelflats [ * rover - > toppic ] ) ;
2016-01-25 05:57:53 +00:00
light = R_GetPlaneLight ( gr_frontsector , centerHeight , dup_viewz < cullHeight ? true : false ) ;
2020-04-25 05:10:30 +00:00
HWR_RenderPlane ( sub , & extrasubsectors [ num ] , true , * rover - > topheight , ( rover - > flags & FF_RIPPLE ? PF_Ripple : 0 ) | PF_Occlude , * gr_frontsector - > lightlist [ light ] . lightlevel , & levelflats [ * rover - > toppic ] ,
2019-12-25 19:22:01 +00:00
rover - > master - > frontsector , 255 , * gr_frontsector - > lightlist [ light ] . extra_colormap ) ;
2014-03-15 16:59:03 +00:00
}
}
}
}
# endif
# endif //doplanes
# ifdef POLYOBJECTS
// Draw all the polyobjects in this subsector
if ( sub - > polyList )
{
polyobj_t * po = sub - > polyList ;
numpolys = 0 ;
// Count all the polyobjects, reset the list, and recount them
while ( po )
{
+ + numpolys ;
po = ( polyobj_t * ) ( po - > link . next ) ;
}
2020-04-18 22:25:28 +00:00
// for render stats
rs_numpolyobjects + = numpolys ;
2014-03-15 16:59:03 +00:00
// Sort polyobjects
R_SortPolyObjects ( sub ) ;
// Draw polyobject lines.
HWR_AddPolyObjectSegs ( ) ;
2014-10-27 20:57:45 +00:00
# ifdef POLYOBJECTS_PLANES
if ( sub - > validcount ! = validcount ) // This validcount situation seems to let us know that the floors have already been drawn.
{
// Draw polyobject planes
HWR_AddPolyObjectPlanes ( ) ;
}
# endif
2014-03-15 16:59:03 +00:00
}
# endif
// Hurder ici se passe les choses INT32<33> essantes!
// on vient de tracer le sol et le plafond
// on trace <20> pr<70> ent d'abord les sprites et ensuite les murs
// hurdler: faux: on ajoute seulement les sprites, le murs sont trac<61> d'abord
if ( line )
{
// draw sprites first, coz they are clipped to the solidsegs of
// subsectors more 'in front'
HWR_AddSprites ( gr_frontsector ) ;
//Hurdler: at this point validcount must be the same, but is not because
// gr_frontsector doesn't point anymore to sub->sector due to
// the call gr_frontsector = R_FakeFlat(...)
// if it's not done, the sprite is drawn more than once,
// what looks really bad with translucency or dynamic light,
// without talking about the overdraw of course.
sub - > sector - > validcount = validcount ; /// \todo fix that in a better way
while ( count - - )
{
2020-01-06 13:40:59 +00:00
if ( ! line - > glseg
2017-06-03 16:47:46 +00:00
# ifdef POLYOBJECTS
2020-01-06 14:58:05 +00:00
& & ! line - > polyseg // ignore segs that belong to polyobjects
2017-06-03 16:47:46 +00:00
# endif
2020-01-06 14:58:05 +00:00
)
{
2014-03-15 16:59:03 +00:00
HWR_AddLine ( line ) ;
2020-01-06 14:58:05 +00:00
}
line + + ;
2014-03-15 16:59:03 +00:00
}
}
sub - > validcount = validcount ;
}
//
// Renders all subsectors below a given node,
// traversing subtree recursively.
// Just call with BSP root.
# ifdef coolhack
//t;b;l;r
static fixed_t hackbbox [ 4 ] ;
//BOXTOP,
//BOXBOTTOM,
//BOXLEFT,
//BOXRIGHT
static boolean HWR_CheckHackBBox ( fixed_t * bb )
{
if ( bb [ BOXTOP ] < hackbbox [ BOXBOTTOM ] ) //y up
return false ;
if ( bb [ BOXBOTTOM ] > hackbbox [ BOXTOP ] )
return false ;
if ( bb [ BOXLEFT ] > hackbbox [ BOXRIGHT ] )
return false ;
if ( bb [ BOXRIGHT ] < hackbbox [ BOXLEFT ] )
return false ;
return true ;
}
# endif
// BP: big hack for a test in lighning ref : 1249753487AB
fixed_t * hwbbox ;
static void HWR_RenderBSPNode ( INT32 bspnum )
{
/*//GZDoom code
if ( bspnum = = - 1 )
{
HWR_Subsector ( subsectors ) ;
return ;
}
while ( ! ( ( size_t ) bspnum & ( ~ NF_SUBSECTOR ) ) ) // Keep going until found a subsector
{
node_t * bsp = & nodes [ bspnum ] ;
// Decide which side the view point is on
INT32 side = R_PointOnSide ( dup_viewx , dup_viewy , bsp ) ;
2020-01-23 22:17:05 +00:00
// Recursively divide front space (toward the viewer)
2014-03-15 16:59:03 +00:00
HWR_RenderBSPNode ( bsp - > children [ side ] ) ;
// Possibly divide back space (away from viewer)
side ^ = 1 ;
if ( ! HWR_CheckBBox ( bsp - > bbox [ side ] ) )
return ;
bspnum = bsp - > children [ side ] ;
}
HWR_Subsector ( bspnum - 1 ) ;
*/
node_t * bsp = & nodes [ bspnum ] ;
// Decide which side the view point is on
INT32 side ;
2020-04-18 22:25:28 +00:00
rs_numbspcalls + + ;
2014-03-15 16:59:03 +00:00
// Found a subsector?
if ( bspnum & NF_SUBSECTOR )
{
if ( bspnum = = - 1 )
{
//*(gr_drawsubsector_p++) = 0;
HWR_Subsector ( 0 ) ;
}
else
{
//*(gr_drawsubsector_p++) = bspnum&(~NF_SUBSECTOR);
HWR_Subsector ( bspnum & ( ~ NF_SUBSECTOR ) ) ;
}
return ;
}
// Decide which side the view point is on.
side = R_PointOnSide ( dup_viewx , dup_viewy , bsp ) ;
// BP: big hack for a test in lighning ref : 1249753487AB
hwbbox = bsp - > bbox [ side ] ;
// Recursively divide front space.
HWR_RenderBSPNode ( bsp - > children [ side ] ) ;
// Possibly divide back space.
if ( HWR_CheckBBox ( bsp - > bbox [ side ^ 1 ] ) )
{
// BP: big hack for a test in lighning ref : 1249753487AB
hwbbox = bsp - > bbox [ side ^ 1 ] ;
HWR_RenderBSPNode ( bsp - > children [ side ^ 1 ] ) ;
}
}
/*
//
// Clear 'stack' of subsectors to draw
//
static void HWR_ClearDrawSubsectors ( void )
{
gr_drawsubsector_p = gr_drawsubsectors ;
}
//
// Draw subsectors pushed on the drawsubsectors 'stack', back to front
//
static void HWR_RenderSubsectors ( void )
{
while ( gr_drawsubsector_p > gr_drawsubsectors )
{
HWR_RenderBSPNode (
lastsubsec - > nextsubsec = bspnum & ( ~ NF_SUBSECTOR ) ;
}
}
*/
// ==========================================================================
// FROM R_MAIN.C
// ==========================================================================
//BP : exactely the same as R_InitTextureMapping
void HWR_InitTextureMapping ( void )
{
angle_t i ;
INT32 x ;
INT32 t ;
fixed_t focallength ;
fixed_t grcenterx ;
fixed_t grcenterxfrac ;
INT32 grviewwidth ;
# define clipanglefov (FIELDOFVIEW>>ANGLETOFINESHIFT)
grviewwidth = vid . width ;
grcenterx = grviewwidth / 2 ;
grcenterxfrac = grcenterx < < FRACBITS ;
// Use tangent table to generate viewangletox:
// viewangletox will give the next greatest x
// after the view angle.
//
// Calc focallength
// so FIELDOFVIEW angles covers SCREENWIDTH.
focallength = FixedDiv ( grcenterxfrac ,
FINETANGENT ( FINEANGLES / 4 + clipanglefov / 2 ) ) ;
for ( i = 0 ; i < FINEANGLES / 2 ; i + + )
{
if ( FINETANGENT ( i ) > FRACUNIT * 2 )
t = - 1 ;
else if ( FINETANGENT ( i ) < - FRACUNIT * 2 )
t = grviewwidth + 1 ;
else
{
t = FixedMul ( FINETANGENT ( i ) , focallength ) ;
t = ( grcenterxfrac - t + FRACUNIT - 1 ) > > FRACBITS ;
if ( t < - 1 )
t = - 1 ;
else if ( t > grviewwidth + 1 )
t = grviewwidth + 1 ;
}
gr_viewangletox [ i ] = t ;
}
// Scan viewangletox[] to generate xtoviewangle[]:
// xtoviewangle will give the smallest view angle
// that maps to x.
for ( x = 0 ; x < = grviewwidth ; x + + )
{
i = 0 ;
while ( gr_viewangletox [ i ] > x )
i + + ;
gr_xtoviewangle [ x ] = ( i < < ANGLETOFINESHIFT ) - ANGLE_90 ;
}
// Take out the fencepost cases from viewangletox.
for ( i = 0 ; i < FINEANGLES / 2 ; i + + )
{
if ( gr_viewangletox [ i ] = = - 1 )
gr_viewangletox [ i ] = 0 ;
else if ( gr_viewangletox [ i ] = = grviewwidth + 1 )
gr_viewangletox [ i ] = grviewwidth ;
}
gr_clipangle = gr_xtoviewangle [ 0 ] ;
}
// ==========================================================================
// gr_things.c
// ==========================================================================
// sprites are drawn after all wall and planes are rendered, so that
// sprite translucency effects apply on the rendered view (instead of the background sky!!)
static UINT32 gr_visspritecount ;
static gr_vissprite_t * gr_visspritechunks [ MAXVISSPRITES > > VISSPRITECHUNKBITS ] = { NULL } ;
// --------------------------------------------------------------------------
// HWR_ClearSprites
// Called at frame start.
// --------------------------------------------------------------------------
static void HWR_ClearSprites ( void )
{
gr_visspritecount = 0 ;
}
// --------------------------------------------------------------------------
// HWR_NewVisSprite
// --------------------------------------------------------------------------
static gr_vissprite_t gr_overflowsprite ;
static gr_vissprite_t * HWR_GetVisSprite ( UINT32 num )
{
UINT32 chunk = num > > VISSPRITECHUNKBITS ;
// Allocate chunk if necessary
if ( ! gr_visspritechunks [ chunk ] )
Z_Malloc ( sizeof ( gr_vissprite_t ) * VISSPRITESPERCHUNK , PU_LEVEL , & gr_visspritechunks [ chunk ] ) ;
return gr_visspritechunks [ chunk ] + ( num & VISSPRITEINDEXMASK ) ;
}
static gr_vissprite_t * HWR_NewVisSprite ( void )
{
if ( gr_visspritecount = = MAXVISSPRITES )
return & gr_overflowsprite ;
return HWR_GetVisSprite ( gr_visspritecount + + ) ;
}
2014-11-12 00:55:07 +00:00
//
// HWR_DoCulling
// Hardware version of R_DoCulling
// (see r_main.c)
static boolean HWR_DoCulling ( line_t * cullheight , line_t * viewcullheight , float vz , float bottomh , float toph )
{
float cullplane ;
if ( ! cullheight )
return false ;
cullplane = FIXED_TO_FLOAT ( cullheight - > frontsector - > floorheight ) ;
if ( cullheight - > flags & ML_NOCLIMB ) // Group culling
{
if ( ! viewcullheight )
return false ;
// Make sure this is part of the same group
if ( viewcullheight - > frontsector = = cullheight - > frontsector )
{
// OK, we can cull
if ( vz > cullplane & & toph < cullplane ) // Cull if below plane
return true ;
if ( bottomh > cullplane & & vz < = cullplane ) // Cull if above plane
return true ;
}
}
else // Quick culling
{
if ( vz > cullplane & & toph < cullplane ) // Cull if below plane
return true ;
if ( bottomh > cullplane & & vz < = cullplane ) // Cull if above plane
return true ;
}
return false ;
}
2020-02-02 03:58:11 +00:00
static void HWR_DrawDropShadow ( mobj_t * thing , fixed_t scale )
2015-01-02 15:14:22 +00:00
{
2020-01-16 17:37:32 +00:00
GLPatch_t * gpatch ;
FOutVector shadowVerts [ 4 ] ;
2015-01-02 15:14:22 +00:00
FSurfaceInfo sSurf ;
2020-01-16 17:37:32 +00:00
float fscale ; float fx ; float fy ; float offset ;
extracolormap_t * colormap = NULL ;
UINT8 i ;
2015-01-02 15:14:22 +00:00
2020-01-16 17:37:32 +00:00
INT32 light ;
fixed_t scalemul ;
UINT16 alpha ;
fixed_t floordiff ;
fixed_t floorz ;
fixed_t slopez ;
pslope_t * floorslope ;
2015-01-02 15:14:22 +00:00
2020-01-16 17:37:32 +00:00
floorz = R_GetShadowZ ( thing , & floorslope ) ;
2015-01-02 15:14:22 +00:00
2020-01-16 17:37:32 +00:00
//if (abs(floorz - gr_viewz) / tz > 4) return; // Prevent stretchy shadows and possible crashes
2015-01-02 15:14:22 +00:00
2020-01-16 17:37:32 +00:00
floordiff = abs ( thing - > z - floorz ) ;
2015-01-02 15:14:22 +00:00
2020-01-16 17:37:32 +00:00
alpha = floordiff / ( 4 * FRACUNIT ) + 75 ;
if ( alpha > = 255 ) return ;
alpha = 255 - alpha ;
2018-03-21 19:45:37 +00:00
2020-01-16 17:37:32 +00:00
gpatch = ( GLPatch_t * ) W_CachePatchName ( " DSHADOW " , PU_CACHE ) ;
if ( ! ( gpatch & & gpatch - > mipmap - > grInfo . format ) ) return ;
HWR_GetPatch ( gpatch ) ;
scalemul = FixedMul ( FRACUNIT - floordiff / 640 , scale ) ;
scalemul = FixedMul ( scalemul , ( thing - > radius * 2 ) / gpatch - > height ) ;
fscale = FIXED_TO_FLOAT ( scalemul ) ;
fx = FIXED_TO_FLOAT ( thing - > x ) ;
fy = FIXED_TO_FLOAT ( thing - > y ) ;
2015-01-02 15:14:22 +00:00
// 3--2
// | /|
// |/ |
// 0--1
2020-01-16 17:37:32 +00:00
if ( thing & & fabsf ( fscale - 1.0f ) > 1.0E-36 f )
offset = ( gpatch - > height / 2 ) * fscale ;
else
offset = ( float ) ( gpatch - > height / 2 ) ;
2015-01-02 15:14:22 +00:00
2020-02-02 03:58:11 +00:00
shadowVerts [ 2 ] . x = shadowVerts [ 3 ] . x = fx + offset ;
shadowVerts [ 1 ] . x = shadowVerts [ 0 ] . x = fx - offset ;
shadowVerts [ 1 ] . z = shadowVerts [ 2 ] . z = fy - offset ;
shadowVerts [ 0 ] . z = shadowVerts [ 3 ] . z = fy + offset ;
for ( i = 0 ; i < 4 ; i + + )
{
float oldx = shadowVerts [ i ] . x ;
float oldy = shadowVerts [ i ] . z ;
shadowVerts [ i ] . x = fx + ( ( oldx - fx ) * gr_viewcos ) - ( ( oldy - fy ) * gr_viewsin ) ;
shadowVerts [ i ] . z = fy + ( ( oldx - fx ) * gr_viewsin ) + ( ( oldy - fy ) * gr_viewcos ) ;
}
2015-01-02 15:14:22 +00:00
2020-01-16 17:37:32 +00:00
if ( floorslope )
2015-01-02 15:14:22 +00:00
{
2020-01-16 17:37:32 +00:00
for ( i = 0 ; i < 4 ; i + + )
{
slopez = P_GetZAt ( floorslope , FLOAT_TO_FIXED ( shadowVerts [ i ] . x ) , FLOAT_TO_FIXED ( shadowVerts [ i ] . z ) ) ;
shadowVerts [ i ] . y = FIXED_TO_FLOAT ( slopez ) + 0.05f ;
}
2015-01-02 15:14:22 +00:00
}
else
{
2020-01-16 17:37:32 +00:00
for ( i = 0 ; i < 4 ; i + + )
shadowVerts [ i ] . y = FIXED_TO_FLOAT ( floorz ) + 0.05f ;
2015-01-02 15:14:22 +00:00
}
2020-02-02 03:58:11 +00:00
shadowVerts [ 0 ] . s = shadowVerts [ 3 ] . s = 0 ;
shadowVerts [ 2 ] . s = shadowVerts [ 1 ] . s = gpatch - > max_s ;
2015-01-02 15:14:22 +00:00
2020-02-02 03:58:11 +00:00
shadowVerts [ 3 ] . t = shadowVerts [ 2 ] . t = 0 ;
shadowVerts [ 0 ] . t = shadowVerts [ 1 ] . t = gpatch - > max_t ;
2015-01-02 15:14:22 +00:00
2020-01-16 17:37:32 +00:00
if ( thing - > subsector - > sector - > numlights )
2015-01-02 15:14:22 +00:00
{
2020-01-16 17:37:32 +00:00
light = R_GetPlaneLight ( thing - > subsector - > sector , floorz , false ) ; // Always use the light at the top instead of whatever I was doing before
if ( * thing - > subsector - > sector - > lightlist [ light ] . extra_colormap )
colormap = * thing - > subsector - > sector - > lightlist [ light ] . extra_colormap ;
2015-01-02 15:14:22 +00:00
}
else
{
2020-01-16 17:37:32 +00:00
if ( thing - > subsector - > sector - > extra_colormap )
colormap = thing - > subsector - > sector - > extra_colormap ;
2015-01-02 15:14:22 +00:00
}
2020-01-16 17:37:32 +00:00
2020-02-02 03:58:11 +00:00
HWR_Lighting ( & sSurf , 0 , colormap ) ;
2020-01-16 19:55:55 +00:00
sSurf . PolyColor . s . alpha = alpha ;
2020-01-16 17:37:32 +00:00
2020-01-16 19:55:55 +00:00
HWD . pfnSetShader ( 3 ) ; // sprite shader
2020-01-16 17:37:32 +00:00
HWD . pfnDrawPolygon ( & sSurf , shadowVerts , 4 , PF_Translucent | PF_Modulated | PF_Clip ) ;
2015-01-02 15:14:22 +00:00
}
2019-04-30 22:08:01 +00:00
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
static void HWR_RotateSpritePolyToAim ( gr_vissprite_t * spr , FOutVector * wallVerts )
{
2019-05-06 19:24:26 +00:00
if ( cv_grspritebillboarding . value
& & spr & & spr - > mobj & & ! ( spr - > mobj - > frame & FF_PAPERSPRITE )
& & wallVerts )
2019-04-30 22:08:01 +00:00
{
float basey = FIXED_TO_FLOAT ( spr - > mobj - > z ) ;
float lowy = wallVerts [ 0 ] . y ;
if ( P_MobjFlip ( spr - > mobj ) = = - 1 )
{
basey = FIXED_TO_FLOAT ( spr - > mobj - > z + spr - > mobj - > height ) ;
}
// Rotate sprites to fully billboard with the camera
// X, Y, AND Z need to be manipulated for the polys to rotate around the
// origin, because of how the origin setting works I believe that should
// be mobj->z or mobj->z + mobj->height
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = ( spr - > ty - basey ) * gr_viewludsin + basey ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = ( lowy - basey ) * gr_viewludsin + basey ;
// translate back to be around 0 before translating back
wallVerts [ 3 ] . x + = ( ( spr - > ty - basey ) * gr_viewludcos ) * gr_viewcos ;
wallVerts [ 2 ] . x + = ( ( spr - > ty - basey ) * gr_viewludcos ) * gr_viewcos ;
wallVerts [ 0 ] . x + = ( ( lowy - basey ) * gr_viewludcos ) * gr_viewcos ;
wallVerts [ 1 ] . x + = ( ( lowy - basey ) * gr_viewludcos ) * gr_viewcos ;
wallVerts [ 3 ] . z + = ( ( spr - > ty - basey ) * gr_viewludcos ) * gr_viewsin ;
wallVerts [ 2 ] . z + = ( ( spr - > ty - basey ) * gr_viewludcos ) * gr_viewsin ;
wallVerts [ 0 ] . z + = ( ( lowy - basey ) * gr_viewludcos ) * gr_viewsin ;
wallVerts [ 1 ] . z + = ( ( lowy - basey ) * gr_viewludcos ) * gr_viewsin ;
}
}
2018-03-22 00:52:14 +00:00
static void HWR_SplitSprite ( gr_vissprite_t * spr )
{
float this_scale = 1.0f ;
FOutVector wallVerts [ 4 ] ;
2019-04-30 22:08:01 +00:00
FOutVector baseWallVerts [ 4 ] ; // This is what the verts should end up as
2018-03-22 00:52:14 +00:00
GLPatch_t * gpatch ;
FSurfaceInfo Surf ;
const boolean hires = ( spr - > mobj & & spr - > mobj - > skin & & ( ( skin_t * ) spr - > mobj - > skin ) - > flags & SF_HIRES ) ;
extracolormap_t * colormap ;
FUINT lightlevel ;
FBITFIELD blend = 0 ;
UINT8 alpha ;
INT32 i ;
float realtop , realbot , top , bot ;
2019-12-25 19:22:01 +00:00
float ttop , tbot , tmult ;
2018-03-22 00:52:14 +00:00
float bheight ;
2019-04-30 22:08:01 +00:00
float realheight , heightmult ;
2018-03-22 00:52:14 +00:00
const sector_t * sector = spr - > mobj - > subsector - > sector ;
const lightlist_t * list = sector - > lightlist ;
# ifdef ESLOPE
float endrealtop , endrealbot , endtop , endbot ;
float endbheight ;
2019-04-30 22:08:01 +00:00
float endrealheight ;
2018-03-22 00:52:14 +00:00
fixed_t temp ;
fixed_t v1x , v1y , v2x , v2y ;
# endif
this_scale = FIXED_TO_FLOAT ( spr - > mobj - > scale ) ;
if ( hires )
this_scale = this_scale * FIXED_TO_FLOAT ( ( ( skin_t * ) spr - > mobj - > skin ) - > highresscale ) ;
2019-08-18 17:16:48 +00:00
gpatch = spr - > gpatch ; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE);
2018-03-22 00:52:14 +00:00
// cache the patch in the graphics card memory
//12/12/99: Hurdler: same comment as above (for md2)
//Hurdler: 25/04/2000: now support colormap in hardware mode
HWR_GetMappedPatch ( gpatch , spr - > colormap ) ;
2019-04-30 22:08:01 +00:00
baseWallVerts [ 0 ] . x = baseWallVerts [ 3 ] . x = spr - > x1 ;
baseWallVerts [ 2 ] . x = baseWallVerts [ 1 ] . x = spr - > x2 ;
baseWallVerts [ 0 ] . z = baseWallVerts [ 3 ] . z = spr - > z1 ;
baseWallVerts [ 1 ] . z = baseWallVerts [ 2 ] . z = spr - > z2 ;
2018-03-22 00:52:14 +00:00
2019-04-30 22:08:01 +00:00
baseWallVerts [ 2 ] . y = baseWallVerts [ 3 ] . y = spr - > ty ;
2018-12-15 00:33:40 +00:00
if ( spr - > mobj & & fabsf ( this_scale - 1.0f ) > 1.0E-36 f )
2019-04-30 22:08:01 +00:00
baseWallVerts [ 0 ] . y = baseWallVerts [ 1 ] . y = spr - > ty - gpatch - > height * this_scale ;
2018-03-22 00:52:14 +00:00
else
2019-04-30 22:08:01 +00:00
baseWallVerts [ 0 ] . y = baseWallVerts [ 1 ] . y = spr - > ty - gpatch - > height ;
2018-03-22 00:52:14 +00:00
v1x = FLOAT_TO_FIXED ( spr - > x1 ) ;
v1y = FLOAT_TO_FIXED ( spr - > z1 ) ;
v2x = FLOAT_TO_FIXED ( spr - > x2 ) ;
v2y = FLOAT_TO_FIXED ( spr - > z2 ) ;
if ( spr - > flip )
{
2019-12-25 19:22:01 +00:00
baseWallVerts [ 0 ] . s = baseWallVerts [ 3 ] . s = gpatch - > max_s ;
baseWallVerts [ 2 ] . s = baseWallVerts [ 1 ] . s = 0 ;
2019-04-30 22:08:01 +00:00
}
else
{
2019-12-25 19:22:01 +00:00
baseWallVerts [ 0 ] . s = baseWallVerts [ 3 ] . s = 0 ;
baseWallVerts [ 2 ] . s = baseWallVerts [ 1 ] . s = gpatch - > max_s ;
2018-03-22 00:52:14 +00:00
}
// flip the texture coords (look familiar?)
if ( spr - > vflip )
{
2019-12-25 19:22:01 +00:00
baseWallVerts [ 3 ] . t = baseWallVerts [ 2 ] . t = gpatch - > max_t ;
baseWallVerts [ 0 ] . t = baseWallVerts [ 1 ] . t = 0 ;
2019-04-30 22:08:01 +00:00
}
else
{
2019-12-25 19:22:01 +00:00
baseWallVerts [ 3 ] . t = baseWallVerts [ 2 ] . t = 0 ;
baseWallVerts [ 0 ] . t = baseWallVerts [ 1 ] . t = gpatch - > max_t ;
2018-03-22 00:52:14 +00:00
}
2020-01-23 22:17:05 +00:00
// if it has a dispoffset, push it a little towards the camera
2018-12-18 21:37:01 +00:00
if ( spr - > dispoffset ) {
2018-12-18 21:59:59 +00:00
float co = - gr_viewcos * ( 0.05f * spr - > dispoffset ) ;
float si = - gr_viewsin * ( 0.05f * spr - > dispoffset ) ;
2019-04-30 22:08:01 +00:00
baseWallVerts [ 0 ] . z = baseWallVerts [ 3 ] . z = baseWallVerts [ 0 ] . z + si ;
baseWallVerts [ 1 ] . z = baseWallVerts [ 2 ] . z = baseWallVerts [ 1 ] . z + si ;
baseWallVerts [ 0 ] . x = baseWallVerts [ 3 ] . x = baseWallVerts [ 0 ] . x + co ;
baseWallVerts [ 1 ] . x = baseWallVerts [ 2 ] . x = baseWallVerts [ 1 ] . x + co ;
2018-12-18 21:37:01 +00:00
}
2018-12-18 21:59:59 +00:00
2019-04-30 22:08:01 +00:00
// Let dispoffset work first since this adjust each vertex
HWR_RotateSpritePolyToAim ( spr , baseWallVerts ) ;
realtop = top = baseWallVerts [ 3 ] . y ;
realbot = bot = baseWallVerts [ 0 ] . y ;
2019-12-25 19:22:01 +00:00
ttop = baseWallVerts [ 3 ] . t ;
tbot = baseWallVerts [ 0 ] . t ;
tmult = ( tbot - ttop ) / ( top - bot ) ;
2018-03-22 00:52:14 +00:00
# ifdef ESLOPE
2019-04-30 22:08:01 +00:00
endrealtop = endtop = baseWallVerts [ 2 ] . y ;
endrealbot = endbot = baseWallVerts [ 1 ] . y ;
2018-03-22 00:52:14 +00:00
# endif
2019-04-30 22:08:01 +00:00
// copy the contents of baseWallVerts into the drawn wallVerts array
// baseWallVerts is used to know the final shape to easily get the vertex
// co-ordinates
memcpy ( wallVerts , baseWallVerts , sizeof ( baseWallVerts ) ) ;
2018-03-22 00:52:14 +00:00
if ( ! cv_translucency . value ) // translucency disabled
{
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = 0xFF ;
2018-03-22 00:52:14 +00:00
blend = PF_Translucent | PF_Occlude ;
}
else if ( spr - > mobj - > flags2 & MF2_SHADOW )
{
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = 0x40 ;
2018-03-22 00:52:14 +00:00
blend = PF_Translucent ;
}
else if ( spr - > mobj - > frame & FF_TRANSMASK )
blend = HWR_TranstableToAlpha ( ( spr - > mobj - > frame & FF_TRANSMASK ) > > FF_TRANSSHIFT , & Surf ) ;
else
{
// BP: i agree that is little better in environement but it don't
// work properly under glide nor with fogcolor to ffffff :(
// Hurdler: PF_Environement would be cool, but we need to fix
// the issue with the fog before
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = 0xFF ;
2018-03-22 00:52:14 +00:00
blend = PF_Translucent | PF_Occlude ;
}
2019-12-25 19:22:01 +00:00
alpha = Surf . PolyColor . s . alpha ;
2018-03-22 00:52:14 +00:00
// Start with the lightlevel and colormap from the top of the sprite
lightlevel = * list [ sector - > numlights - 1 ] . lightlevel ;
2018-09-12 20:28:55 +00:00
colormap = * list [ sector - > numlights - 1 ] . extra_colormap ;
2018-03-22 00:52:14 +00:00
i = 0 ;
temp = FLOAT_TO_FIXED ( realtop ) ;
2018-05-16 20:04:57 +00:00
if ( spr - > mobj - > frame & FF_FULLBRIGHT )
lightlevel = 255 ;
2018-03-22 00:52:14 +00:00
# ifdef ESLOPE
for ( i = 1 ; i < sector - > numlights ; i + + )
{
fixed_t h = sector - > lightlist [ i ] . slope ? P_GetZAt ( sector - > lightlist [ i ] . slope , spr - > mobj - > x , spr - > mobj - > y )
: sector - > lightlist [ i ] . height ;
if ( h < = temp )
{
2018-05-16 20:04:57 +00:00
if ( ! ( spr - > mobj - > frame & FF_FULLBRIGHT ) )
2020-03-08 03:41:52 +00:00
lightlevel = * list [ i - 1 ] . lightlevel > 255 ? 255 : * list [ i - 1 ] . lightlevel ;
2018-09-12 20:28:55 +00:00
colormap = * list [ i - 1 ] . extra_colormap ;
2018-03-22 00:52:14 +00:00
break ;
}
}
# else
i = R_GetPlaneLight ( sector , temp , false ) ;
2018-05-16 20:04:57 +00:00
if ( ! ( spr - > mobj - > frame & FF_FULLBRIGHT ) )
2020-03-08 03:41:52 +00:00
lightlevel = * list [ i ] . lightlevel > 255 ? 255 : * list [ i ] . lightlevel ;
2018-09-12 20:28:55 +00:00
colormap = * list [ i ] . extra_colormap ;
2018-03-22 00:52:14 +00:00
# endif
for ( i = 0 ; i < sector - > numlights ; i + + )
{
# ifdef ESLOPE
if ( endtop < endrealbot )
# endif
if ( top < realbot )
return ;
// even if we aren't changing colormap or lightlevel, we still need to continue drawing down the sprite
if ( ! ( list [ i ] . flags & FF_NOSHADE ) & & ( list [ i ] . flags & FF_CUTSPRITES ) )
{
2018-05-16 20:04:57 +00:00
if ( ! ( spr - > mobj - > frame & FF_FULLBRIGHT ) )
2020-03-08 03:41:52 +00:00
lightlevel = * list [ i ] . lightlevel > 255 ? 255 : * list [ i ] . lightlevel ;
2018-09-12 20:28:55 +00:00
colormap = * list [ i ] . extra_colormap ;
2018-03-22 00:52:14 +00:00
}
# ifdef ESLOPE
if ( i + 1 < sector - > numlights )
{
if ( list [ i + 1 ] . slope )
{
temp = P_GetZAt ( list [ i + 1 ] . slope , v1x , v1y ) ;
bheight = FIXED_TO_FLOAT ( temp ) ;
temp = P_GetZAt ( list [ i + 1 ] . slope , v2x , v2y ) ;
endbheight = FIXED_TO_FLOAT ( temp ) ;
}
else
bheight = endbheight = FIXED_TO_FLOAT ( list [ i + 1 ] . height ) ;
}
else
{
bheight = realbot ;
endbheight = endrealbot ;
}
# else
if ( i + 1 < sector - > numlights )
{
bheight = FIXED_TO_FLOAT ( list [ i + 1 ] . height ) ;
}
else
{
bheight = realbot ;
}
# endif
# ifdef ESLOPE
if ( endbheight > = endtop )
# endif
if ( bheight > = top )
continue ;
bot = bheight ;
if ( bot < realbot )
bot = realbot ;
# ifdef ESLOPE
endbot = endbheight ;
if ( endbot < endrealbot )
endbot = endrealbot ;
# endif
# ifdef ESLOPE
2019-12-25 19:22:01 +00:00
wallVerts [ 3 ] . t = ttop + ( ( realtop - top ) * tmult ) ;
wallVerts [ 2 ] . t = ttop + ( ( endrealtop - endtop ) * tmult ) ;
wallVerts [ 0 ] . t = ttop + ( ( realtop - bot ) * tmult ) ;
wallVerts [ 1 ] . t = ttop + ( ( endrealtop - endbot ) * tmult ) ;
2018-03-22 00:52:14 +00:00
wallVerts [ 3 ] . y = top ;
wallVerts [ 2 ] . y = endtop ;
wallVerts [ 0 ] . y = bot ;
wallVerts [ 1 ] . y = endbot ;
2019-04-30 22:08:01 +00:00
// The x and y only need to be adjusted in the case that it's not a papersprite
2019-05-06 19:24:26 +00:00
if ( cv_grspritebillboarding . value
& & spr - > mobj & & ! ( spr - > mobj - > frame & FF_PAPERSPRITE ) )
2019-04-30 22:08:01 +00:00
{
// Get the x and z of the vertices so billboarding draws correctly
realheight = realbot - realtop ;
endrealheight = endrealbot - endrealtop ;
heightmult = ( realtop - top ) / realheight ;
wallVerts [ 3 ] . x = baseWallVerts [ 3 ] . x + ( baseWallVerts [ 3 ] . x - baseWallVerts [ 0 ] . x ) * heightmult ;
wallVerts [ 3 ] . z = baseWallVerts [ 3 ] . z + ( baseWallVerts [ 3 ] . z - baseWallVerts [ 0 ] . z ) * heightmult ;
heightmult = ( endrealtop - endtop ) / endrealheight ;
wallVerts [ 2 ] . x = baseWallVerts [ 2 ] . x + ( baseWallVerts [ 2 ] . x - baseWallVerts [ 1 ] . x ) * heightmult ;
wallVerts [ 2 ] . z = baseWallVerts [ 2 ] . z + ( baseWallVerts [ 2 ] . z - baseWallVerts [ 1 ] . z ) * heightmult ;
heightmult = ( realtop - bot ) / realheight ;
wallVerts [ 0 ] . x = baseWallVerts [ 3 ] . x + ( baseWallVerts [ 3 ] . x - baseWallVerts [ 0 ] . x ) * heightmult ;
wallVerts [ 0 ] . z = baseWallVerts [ 3 ] . z + ( baseWallVerts [ 3 ] . z - baseWallVerts [ 0 ] . z ) * heightmult ;
heightmult = ( endrealtop - endbot ) / endrealheight ;
wallVerts [ 1 ] . x = baseWallVerts [ 2 ] . x + ( baseWallVerts [ 2 ] . x - baseWallVerts [ 1 ] . x ) * heightmult ;
wallVerts [ 1 ] . z = baseWallVerts [ 2 ] . z + ( baseWallVerts [ 2 ] . z - baseWallVerts [ 1 ] . z ) * heightmult ;
}
2018-03-22 00:52:14 +00:00
# else
2019-12-25 19:22:01 +00:00
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = ttop + ( ( realtop - top ) * tmult ) ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = ttop + ( ( realtop - bot ) * tmult ) ;
2018-03-22 00:52:14 +00:00
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = top ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = bot ;
2019-04-30 22:08:01 +00:00
// The x and y only need to be adjusted in the case that it's not a papersprite
2019-05-06 19:24:26 +00:00
if ( cv_grspritebillboarding . value
& & spr - > mobj & & ! ( spr - > mobj - > frame & FF_PAPERSPRITE ) )
2019-04-30 22:08:01 +00:00
{
// Get the x and z of the vertices so billboarding draws correctly
realheight = realbot - realtop ;
heightmult = ( realtop - top ) / realheight ;
wallVerts [ 3 ] . x = baseWallVerts [ 3 ] . x + ( baseWallVerts [ 3 ] . x - baseWallVerts [ 0 ] . x ) * heightmult ;
wallVerts [ 3 ] . z = baseWallVerts [ 3 ] . z + ( baseWallVerts [ 3 ] . z - baseWallVerts [ 0 ] . z ) * heightmult ;
wallVerts [ 2 ] . x = baseWallVerts [ 2 ] . x + ( baseWallVerts [ 2 ] . x - baseWallVerts [ 1 ] . x ) * heightmult ;
wallVerts [ 2 ] . z = baseWallVerts [ 2 ] . z + ( baseWallVerts [ 2 ] . z - baseWallVerts [ 1 ] . z ) * heightmult ;
heightmult = ( realtop - bot ) / realheight ;
wallVerts [ 0 ] . x = baseWallVerts [ 3 ] . x + ( baseWallVerts [ 3 ] . x - baseWallVerts [ 0 ] . x ) * heightmult ;
wallVerts [ 0 ] . z = baseWallVerts [ 3 ] . z + ( baseWallVerts [ 3 ] . z - baseWallVerts [ 0 ] . z ) * heightmult ;
wallVerts [ 1 ] . x = baseWallVerts [ 2 ] . x + ( baseWallVerts [ 2 ] . x - baseWallVerts [ 1 ] . x ) * heightmult ;
wallVerts [ 1 ] . z = baseWallVerts [ 2 ] . z + ( baseWallVerts [ 2 ] . z - baseWallVerts [ 1 ] . z ) * heightmult ;
}
2018-03-22 00:52:14 +00:00
# endif
2019-12-25 19:22:01 +00:00
HWR_Lighting ( & Surf , lightlevel , colormap ) ;
2018-03-22 00:52:14 +00:00
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = alpha ;
2018-03-22 00:52:14 +00:00
2019-12-25 19:22:01 +00:00
HWD . pfnSetShader ( 3 ) ; // sprite shader
2018-03-22 00:52:14 +00:00
HWD . pfnDrawPolygon ( & Surf , wallVerts , 4 , blend | PF_Modulated | PF_Clip ) ;
top = bot ;
# ifdef ESLOPE
endtop = endbot ;
# endif
}
bot = realbot ;
# ifdef ESLOPE
endbot = endrealbot ;
if ( endtop < = endrealbot )
# endif
if ( top < = realbot )
return ;
// If we're ever down here, somehow the above loop hasn't draw all the light levels of sprite
# ifdef ESLOPE
2019-12-25 19:22:01 +00:00
wallVerts [ 3 ] . t = ttop + ( ( realtop - top ) * tmult ) ;
wallVerts [ 2 ] . t = ttop + ( ( endrealtop - endtop ) * tmult ) ;
wallVerts [ 0 ] . t = ttop + ( ( realtop - bot ) * tmult ) ;
wallVerts [ 1 ] . t = ttop + ( ( endrealtop - endbot ) * tmult ) ;
2018-03-22 00:52:14 +00:00
wallVerts [ 3 ] . y = top ;
wallVerts [ 2 ] . y = endtop ;
wallVerts [ 0 ] . y = bot ;
wallVerts [ 1 ] . y = endbot ;
# else
2019-12-25 19:22:01 +00:00
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = ttop + ( ( realtop - top ) * tmult ) ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = ttop + ( ( realtop - bot ) * tmult ) ;
2018-03-22 00:52:14 +00:00
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = top ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = bot ;
# endif
2019-12-25 19:22:01 +00:00
HWR_Lighting ( & Surf , lightlevel , colormap ) ;
2018-03-22 00:52:14 +00:00
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = alpha ;
2018-03-22 00:52:14 +00:00
2019-12-25 19:22:01 +00:00
HWD . pfnSetShader ( 3 ) ; // sprite shader
2018-03-22 00:52:14 +00:00
HWD . pfnDrawPolygon ( & Surf , wallVerts , 4 , blend | PF_Modulated | PF_Clip ) ;
}
2014-03-15 16:59:03 +00:00
// -----------------+
// HWR_DrawSprite : Draw flat sprites
// : (monsters, bonuses, weapons, lights, ...)
// Returns :
// -----------------+
static void HWR_DrawSprite ( gr_vissprite_t * spr )
{
2018-03-21 19:45:37 +00:00
float this_scale = 1.0f ;
2014-03-15 16:59:03 +00:00
FOutVector wallVerts [ 4 ] ;
GLPatch_t * gpatch ; // sprite patch converted to hardware
FSurfaceInfo Surf ;
const boolean hires = ( spr - > mobj & & spr - > mobj - > skin & & ( ( skin_t * ) spr - > mobj - > skin ) - > flags & SF_HIRES ) ;
2016-12-13 21:02:23 +00:00
//const boolean papersprite = (spr->mobj && (spr->mobj->frame & FF_PAPERSPRITE));
2014-03-15 16:59:03 +00:00
if ( spr - > mobj )
this_scale = FIXED_TO_FLOAT ( spr - > mobj - > scale ) ;
if ( hires )
this_scale = this_scale * FIXED_TO_FLOAT ( ( ( skin_t * ) spr - > mobj - > skin ) - > highresscale ) ;
if ( ! spr - > mobj )
return ;
if ( ! spr - > mobj - > subsector )
return ;
2018-03-22 00:52:14 +00:00
if ( spr - > mobj - > subsector - > sector - > numlights )
{
HWR_SplitSprite ( spr ) ;
return ;
}
2014-03-15 16:59:03 +00:00
// cache sprite graphics
//12/12/99: Hurdler:
// OK, I don't change anything for MD2 support because I want to be
// sure to do it the right way. So actually, we keep normal sprite
// in memory and we add the md2 model if it exists for that sprite
2019-08-18 17:16:48 +00:00
gpatch = spr - > gpatch ; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE);
2014-03-15 16:59:03 +00:00
# ifdef ALAM_LIGHTING
if ( ! ( spr - > mobj - > flags2 & MF2_DEBRIS ) & & ( spr - > mobj - > sprite ! = SPR_PLAY | |
( spr - > mobj - > player & & spr - > mobj - > player - > powers [ pw_super ] ) ) )
HWR_DL_AddLight ( spr , gpatch ) ;
# endif
// create the sprite billboard
//
// 3--2
// | /|
// |/ |
// 0--1
// these were already scaled in HWR_ProjectSprite
wallVerts [ 0 ] . x = wallVerts [ 3 ] . x = spr - > x1 ;
wallVerts [ 2 ] . x = wallVerts [ 1 ] . x = spr - > x2 ;
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = spr - > ty ;
2018-12-15 00:33:40 +00:00
if ( spr - > mobj & & fabsf ( this_scale - 1.0f ) > 1.0E-36 f )
2014-03-15 16:59:03 +00:00
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = spr - > ty - gpatch - > height * this_scale ;
else
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = spr - > ty - gpatch - > height ;
// make a wall polygon (with 2 triangles), using the floor/ceiling heights,
// and the 2d map coords of start/end vertices
2016-12-13 21:02:23 +00:00
wallVerts [ 0 ] . z = wallVerts [ 3 ] . z = spr - > z1 ;
2018-03-21 19:45:37 +00:00
wallVerts [ 1 ] . z = wallVerts [ 2 ] . z = spr - > z2 ;
2014-03-15 16:59:03 +00:00
if ( spr - > flip )
{
2019-12-25 19:22:01 +00:00
wallVerts [ 0 ] . s = wallVerts [ 3 ] . s = gpatch - > max_s ;
wallVerts [ 2 ] . s = wallVerts [ 1 ] . s = 0 ;
2014-03-15 16:59:03 +00:00
} else {
2019-12-25 19:22:01 +00:00
wallVerts [ 0 ] . s = wallVerts [ 3 ] . s = 0 ;
wallVerts [ 2 ] . s = wallVerts [ 1 ] . s = gpatch - > max_s ;
2014-03-15 16:59:03 +00:00
}
// flip the texture coords (look familiar?)
if ( spr - > vflip )
{
2019-12-25 19:22:01 +00:00
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = gpatch - > max_t ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = 0 ;
2014-03-15 16:59:03 +00:00
} else {
2019-12-25 19:22:01 +00:00
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = 0 ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = gpatch - > max_t ;
2014-03-15 16:59:03 +00:00
}
// cache the patch in the graphics card memory
//12/12/99: Hurdler: same comment as above (for md2)
//Hurdler: 25/04/2000: now support colormap in hardware mode
HWR_GetMappedPatch ( gpatch , spr - > colormap ) ;
2018-12-18 21:37:01 +00:00
// if it has a dispoffset, push it a little towards the camera
if ( spr - > dispoffset ) {
2018-12-18 21:59:59 +00:00
float co = - gr_viewcos * ( 0.05f * spr - > dispoffset ) ;
float si = - gr_viewsin * ( 0.05f * spr - > dispoffset ) ;
2018-12-18 21:37:01 +00:00
wallVerts [ 0 ] . z = wallVerts [ 3 ] . z = wallVerts [ 0 ] . z + si ;
wallVerts [ 1 ] . z = wallVerts [ 2 ] . z = wallVerts [ 1 ] . z + si ;
wallVerts [ 0 ] . x = wallVerts [ 3 ] . x = wallVerts [ 0 ] . x + co ;
wallVerts [ 1 ] . x = wallVerts [ 2 ] . x = wallVerts [ 1 ] . x + co ;
}
2018-12-18 21:59:59 +00:00
2019-04-30 22:08:01 +00:00
// Let dispoffset work first since this adjust each vertex
HWR_RotateSpritePolyToAim ( spr , wallVerts ) ;
2014-03-15 16:59:03 +00:00
// This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black.
// sprite lighting by modulating the RGB components
/// \todo coloured
// colormap test
{
sector_t * sector = spr - > mobj - > subsector - > sector ;
2015-01-28 15:16:50 +00:00
UINT8 lightlevel = 255 ;
2014-03-15 16:59:03 +00:00
extracolormap_t * colormap = sector - > extra_colormap ;
2018-03-22 00:52:14 +00:00
if ( ! ( spr - > mobj - > frame & FF_FULLBRIGHT ) )
2020-03-08 03:41:52 +00:00
lightlevel = sector - > lightlevel > 255 ? 255 : sector - > lightlevel ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
HWR_Lighting ( & Surf , lightlevel , colormap ) ;
2014-03-15 16:59:03 +00:00
}
{
FBITFIELD blend = 0 ;
2015-01-02 15:14:22 +00:00
if ( ! cv_translucency . value ) // translucency disabled
{
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = 0xFF ;
2015-01-02 15:14:22 +00:00
blend = PF_Translucent | PF_Occlude ;
}
else if ( spr - > mobj - > flags2 & MF2_SHADOW )
2014-03-15 16:59:03 +00:00
{
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = 0x40 ;
2014-03-15 16:59:03 +00:00
blend = PF_Translucent ;
}
else if ( spr - > mobj - > frame & FF_TRANSMASK )
blend = HWR_TranstableToAlpha ( ( spr - > mobj - > frame & FF_TRANSMASK ) > > FF_TRANSSHIFT , & Surf ) ;
else
{
// BP: i agree that is little better in environement but it don't
// work properly under glide nor with fogcolor to ffffff :(
// Hurdler: PF_Environement would be cool, but we need to fix
// the issue with the fog before
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = 0xFF ;
2014-03-15 16:59:03 +00:00
blend = PF_Translucent | PF_Occlude ;
}
2019-12-25 19:22:01 +00:00
HWD . pfnSetShader ( 3 ) ; // sprite shader
2014-03-15 16:59:03 +00:00
HWD . pfnDrawPolygon ( & Surf , wallVerts , 4 , blend | PF_Modulated | PF_Clip ) ;
}
}
# ifdef HWPRECIP
// Sprite drawer for precipitation
static inline void HWR_DrawPrecipitationSprite ( gr_vissprite_t * spr )
{
FBITFIELD blend = 0 ;
FOutVector wallVerts [ 4 ] ;
GLPatch_t * gpatch ; // sprite patch converted to hardware
FSurfaceInfo Surf ;
if ( ! spr - > mobj )
return ;
if ( ! spr - > mobj - > subsector )
return ;
// cache sprite graphics
2019-08-18 17:16:48 +00:00
gpatch = spr - > gpatch ; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE);
2014-03-15 16:59:03 +00:00
// create the sprite billboard
//
// 3--2
// | /|
// |/ |
// 0--1
wallVerts [ 0 ] . x = wallVerts [ 3 ] . x = spr - > x1 ;
wallVerts [ 2 ] . x = wallVerts [ 1 ] . x = spr - > x2 ;
wallVerts [ 2 ] . y = wallVerts [ 3 ] . y = spr - > ty ;
wallVerts [ 0 ] . y = wallVerts [ 1 ] . y = spr - > ty - gpatch - > height ;
// make a wall polygon (with 2 triangles), using the floor/ceiling heights,
// and the 2d map coords of start/end vertices
2018-03-21 19:45:37 +00:00
wallVerts [ 0 ] . z = wallVerts [ 3 ] . z = spr - > z1 ;
wallVerts [ 1 ] . z = wallVerts [ 2 ] . z = spr - > z2 ;
2014-03-15 16:59:03 +00:00
2019-04-30 22:08:01 +00:00
// Let dispoffset work first since this adjust each vertex
HWR_RotateSpritePolyToAim ( spr , wallVerts ) ;
2019-12-25 19:22:01 +00:00
wallVerts [ 0 ] . s = wallVerts [ 3 ] . s = 0 ;
wallVerts [ 2 ] . s = wallVerts [ 1 ] . s = gpatch - > max_s ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
wallVerts [ 3 ] . t = wallVerts [ 2 ] . t = 0 ;
wallVerts [ 0 ] . t = wallVerts [ 1 ] . t = gpatch - > max_t ;
2014-03-15 16:59:03 +00:00
// cache the patch in the graphics card memory
//12/12/99: Hurdler: same comment as above (for md2)
//Hurdler: 25/04/2000: now support colormap in hardware mode
HWR_GetMappedPatch ( gpatch , spr - > colormap ) ;
2016-10-27 22:41:24 +00:00
// colormap test
2014-03-15 16:59:03 +00:00
{
2016-10-27 22:41:24 +00:00
sector_t * sector = spr - > mobj - > subsector - > sector ;
UINT8 lightlevel = 255 ;
extracolormap_t * colormap = sector - > extra_colormap ;
2014-03-15 16:59:03 +00:00
2016-10-27 22:41:24 +00:00
if ( sector - > numlights )
{
INT32 light ;
light = R_GetPlaneLight ( sector , spr - > mobj - > z + spr - > mobj - > height , false ) ; // Always use the light at the top instead of whatever I was doing before
if ( ! ( spr - > mobj - > frame & FF_FULLBRIGHT ) )
2020-03-08 03:41:52 +00:00
lightlevel = * sector - > lightlist [ light ] . lightlevel > 255 ? 255 : * sector - > lightlist [ light ] . lightlevel ;
2016-10-27 22:41:24 +00:00
2018-09-12 20:28:55 +00:00
if ( * sector - > lightlist [ light ] . extra_colormap )
colormap = * sector - > lightlist [ light ] . extra_colormap ;
2016-10-27 22:41:24 +00:00
}
2014-03-15 16:59:03 +00:00
else
2016-10-27 22:41:24 +00:00
{
if ( ! ( spr - > mobj - > frame & FF_FULLBRIGHT ) )
2020-03-08 03:41:52 +00:00
lightlevel = sector - > lightlevel > 255 ? 255 : sector - > lightlevel ;
2016-10-27 22:41:24 +00:00
if ( sector - > extra_colormap )
colormap = sector - > extra_colormap ;
}
2019-12-25 19:22:01 +00:00
HWR_Lighting ( & Surf , lightlevel , colormap ) ;
2016-10-27 22:41:24 +00:00
}
2014-03-15 16:59:03 +00:00
if ( spr - > mobj - > flags2 & MF2_SHADOW )
{
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = 0x40 ;
2014-03-15 16:59:03 +00:00
blend = PF_Translucent ;
}
else if ( spr - > mobj - > frame & FF_TRANSMASK )
blend = HWR_TranstableToAlpha ( ( spr - > mobj - > frame & FF_TRANSMASK ) > > FF_TRANSSHIFT , & Surf ) ;
else
{
// BP: i agree that is little better in environement but it don't
// work properly under glide nor with fogcolor to ffffff :(
// Hurdler: PF_Environement would be cool, but we need to fix
// the issue with the fog before
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = 0xFF ;
2014-03-15 16:59:03 +00:00
blend = PF_Translucent | PF_Occlude ;
}
2019-12-25 19:22:01 +00:00
HWD . pfnSetShader ( 3 ) ; // sprite shader
2014-03-15 16:59:03 +00:00
HWD . pfnDrawPolygon ( & Surf , wallVerts , 4 , blend | PF_Modulated | PF_Clip ) ;
}
# endif
// --------------------------------------------------------------------------
// Sort vissprites by distance
// --------------------------------------------------------------------------
static gr_vissprite_t gr_vsprsortedhead ;
static void HWR_SortVisSprites ( void )
{
UINT32 i ;
gr_vissprite_t * ds , * dsprev , * dsnext , * dsfirst ;
gr_vissprite_t * best = NULL ;
gr_vissprite_t unsorted ;
2016-12-23 00:42:00 +00:00
float bestdist = 0.0f ;
INT32 bestdispoffset = 0 ;
2014-03-15 16:59:03 +00:00
if ( ! gr_visspritecount )
return ;
dsfirst = HWR_GetVisSprite ( 0 ) ;
for ( i = 0 , dsnext = dsfirst , ds = NULL ; i < gr_visspritecount ; i + + )
{
dsprev = ds ;
ds = dsnext ;
if ( i < gr_visspritecount - 1 ) dsnext = HWR_GetVisSprite ( i + 1 ) ;
ds - > next = dsnext ;
ds - > prev = dsprev ;
}
// Fix first and last. ds still points to the last one after the loop
dsfirst - > prev = & unsorted ;
unsorted . next = dsfirst ;
2016-06-13 14:07:10 +00:00
if ( ds )
ds - > next = & unsorted ;
2014-03-15 16:59:03 +00:00
unsorted . prev = ds ;
// pull the vissprites out by scale
gr_vsprsortedhead . next = gr_vsprsortedhead . prev = & gr_vsprsortedhead ;
for ( i = 0 ; i < gr_visspritecount ; i + + )
{
2016-02-22 05:02:09 +00:00
best = NULL ;
2014-03-15 16:59:03 +00:00
for ( ds = unsorted . next ; ds ! = & unsorted ; ds = ds - > next )
{
2016-02-22 05:02:09 +00:00
if ( ! best | | ds - > tz > bestdist )
2014-03-15 16:59:03 +00:00
{
bestdist = ds - > tz ;
2015-11-23 17:01:10 +00:00
bestdispoffset = ds - > dispoffset ;
best = ds ;
}
// order visprites of same scale by dispoffset, smallest first
2018-12-15 00:33:40 +00:00
else if ( fabsf ( ds - > tz - bestdist ) < 1.0E-36 f & & ds - > dispoffset < bestdispoffset )
2015-11-23 17:01:10 +00:00
{
bestdispoffset = ds - > dispoffset ;
2014-03-15 16:59:03 +00:00
best = ds ;
}
}
2016-06-13 14:07:10 +00:00
if ( best )
{
best - > next - > prev = best - > prev ;
best - > prev - > next = best - > next ;
best - > next = & gr_vsprsortedhead ;
best - > prev = gr_vsprsortedhead . prev ;
}
2014-03-15 16:59:03 +00:00
gr_vsprsortedhead . prev - > next = best ;
gr_vsprsortedhead . prev = best ;
}
2018-03-09 09:58:10 +00:00
// Sryder: Oh boy, while it's nice having ALL the sprites sorted properly, it fails when we bring MD2's into the
// mix and they want to be translucent. So let's place all the translucent sprites and MD2's AFTER
// everything else, but still ordered of course, the depth buffer can handle the opaque ones plenty fine.
// We just need to move all translucent ones to the end in order
// TODO: Fully sort all sprites and MD2s with walls and floors, this part will be unnecessary after that
best = gr_vsprsortedhead . next ;
for ( i = 0 ; i < gr_visspritecount ; i + + )
{
if ( ( best - > mobj - > flags2 & MF2_SHADOW ) | | ( best - > mobj - > frame & FF_TRANSMASK ) )
{
if ( best = = gr_vsprsortedhead . next )
{
gr_vsprsortedhead . next = best - > next ;
}
best - > prev - > next = best - > next ;
best - > next - > prev = best - > prev ;
best - > prev = gr_vsprsortedhead . prev ;
gr_vsprsortedhead . prev - > next = best ;
gr_vsprsortedhead . prev = best ;
ds = best ;
best = best - > next ;
ds - > next = & gr_vsprsortedhead ;
}
else
best = best - > next ;
}
2014-03-15 16:59:03 +00:00
}
// A drawnode is something that points to a 3D floor, 3D side, or masked
// middle texture. This is used for sorting with sprites.
typedef struct
{
2019-12-25 19:22:01 +00:00
FOutVector wallVerts [ 4 ] ;
2014-03-15 16:59:03 +00:00
FSurfaceInfo Surf ;
INT32 texnum ;
FBITFIELD blend ;
INT32 drawcount ;
boolean fogwall ;
INT32 lightlevel ;
extracolormap_t * wallcolormap ; // Doing the lighting in HWR_RenderWall now for correct fog after sorting
} wallinfo_t ;
static wallinfo_t * wallinfo = NULL ;
static size_t numwalls = 0 ; // a list of transparent walls to be drawn
2019-12-25 19:22:01 +00:00
void HWR_RenderWall ( FOutVector * wallVerts , FSurfaceInfo * pSurf , FBITFIELD blend , boolean fogwall , INT32 lightlevel , extracolormap_t * wallcolormap ) ;
2014-03-15 16:59:03 +00:00
# define MAX_TRANSPARENTWALL 256
typedef struct
{
extrasubsector_t * xsub ;
2016-07-27 18:56:21 +00:00
boolean isceiling ;
2014-03-15 16:59:03 +00:00
fixed_t fixedheight ;
INT32 lightlevel ;
2019-11-09 01:58:41 +00:00
levelflat_t * levelflat ;
2014-03-15 16:59:03 +00:00
INT32 alpha ;
sector_t * FOFSector ;
FBITFIELD blend ;
boolean fogplane ;
extracolormap_t * planecolormap ;
INT32 drawcount ;
} planeinfo_t ;
static size_t numplanes = 0 ; // a list of transparent floors to be drawn
static planeinfo_t * planeinfo = NULL ;
2014-10-27 20:57:45 +00:00
typedef struct
{
polyobj_t * polysector ;
2016-07-27 18:56:21 +00:00
boolean isceiling ;
2014-10-27 20:57:45 +00:00
fixed_t fixedheight ;
INT32 lightlevel ;
2019-11-09 01:58:41 +00:00
levelflat_t * levelflat ;
2014-10-27 20:57:45 +00:00
INT32 alpha ;
sector_t * FOFSector ;
FBITFIELD blend ;
extracolormap_t * planecolormap ;
INT32 drawcount ;
} polyplaneinfo_t ;
static size_t numpolyplanes = 0 ; // a list of transparent poyobject floors to be drawn
static polyplaneinfo_t * polyplaneinfo = NULL ;
2014-03-15 16:59:03 +00:00
//Hurdler: 3D water sutffs
typedef struct gr_drawnode_s
{
planeinfo_t * plane ;
2014-10-27 20:57:45 +00:00
polyplaneinfo_t * polyplane ;
2014-03-15 16:59:03 +00:00
wallinfo_t * wall ;
gr_vissprite_t * sprite ;
// struct gr_drawnode_s *next;
// struct gr_drawnode_s *prev;
} gr_drawnode_t ;
static INT32 drawcount = 0 ;
# define MAX_TRANSPARENTFLOOR 512
// This will likely turn into a copy of HWR_Add3DWater and replace it.
2019-12-25 19:22:01 +00:00
void HWR_AddTransparentFloor ( levelflat_t * levelflat , extrasubsector_t * xsub , boolean isceiling , fixed_t fixedheight , INT32 lightlevel , INT32 alpha , sector_t * FOFSector , FBITFIELD blend , boolean fogplane , extracolormap_t * planecolormap )
2014-03-15 16:59:03 +00:00
{
static size_t allocedplanes = 0 ;
// Force realloc if buffer has been freed
if ( ! planeinfo )
allocedplanes = 0 ;
if ( allocedplanes < numplanes + 1 )
{
allocedplanes + = MAX_TRANSPARENTFLOOR ;
Z_Realloc ( planeinfo , allocedplanes * sizeof ( * planeinfo ) , PU_LEVEL , & planeinfo ) ;
}
2016-07-27 18:56:21 +00:00
planeinfo [ numplanes ] . isceiling = isceiling ;
2014-03-15 16:59:03 +00:00
planeinfo [ numplanes ] . fixedheight = fixedheight ;
2020-02-16 19:19:24 +00:00
planeinfo [ numplanes ] . lightlevel = ( planecolormap & & ( planecolormap - > flags & CMF_FOG ) ) ? lightlevel : 255 ;
2019-11-09 01:58:41 +00:00
planeinfo [ numplanes ] . levelflat = levelflat ;
2014-03-15 16:59:03 +00:00
planeinfo [ numplanes ] . xsub = xsub ;
planeinfo [ numplanes ] . alpha = alpha ;
planeinfo [ numplanes ] . FOFSector = FOFSector ;
planeinfo [ numplanes ] . blend = blend ;
planeinfo [ numplanes ] . fogplane = fogplane ;
planeinfo [ numplanes ] . planecolormap = planecolormap ;
planeinfo [ numplanes ] . drawcount = drawcount + + ;
2016-07-27 18:56:21 +00:00
2014-03-15 16:59:03 +00:00
numplanes + + ;
}
2014-10-27 20:57:45 +00:00
// Adding this for now until I can create extrasubsector info for polyobjects
// When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane
2019-12-25 19:22:01 +00:00
void HWR_AddTransparentPolyobjectFloor ( levelflat_t * levelflat , polyobj_t * polysector , boolean isceiling , fixed_t fixedheight , INT32 lightlevel , INT32 alpha , sector_t * FOFSector , FBITFIELD blend , extracolormap_t * planecolormap )
2014-10-27 20:57:45 +00:00
{
static size_t allocedpolyplanes = 0 ;
// Force realloc if buffer has been freed
if ( ! polyplaneinfo )
allocedpolyplanes = 0 ;
if ( allocedpolyplanes < numpolyplanes + 1 )
{
allocedpolyplanes + = MAX_TRANSPARENTFLOOR ;
Z_Realloc ( polyplaneinfo , allocedpolyplanes * sizeof ( * polyplaneinfo ) , PU_LEVEL , & polyplaneinfo ) ;
}
2016-07-27 18:56:21 +00:00
polyplaneinfo [ numpolyplanes ] . isceiling = isceiling ;
2014-10-27 20:57:45 +00:00
polyplaneinfo [ numpolyplanes ] . fixedheight = fixedheight ;
2020-02-16 19:19:24 +00:00
polyplaneinfo [ numpolyplanes ] . lightlevel = ( planecolormap & & ( planecolormap - > flags & CMF_FOG ) ) ? lightlevel : 255 ;
2019-11-09 01:58:41 +00:00
polyplaneinfo [ numpolyplanes ] . levelflat = levelflat ;
2014-10-27 20:57:45 +00:00
polyplaneinfo [ numpolyplanes ] . polysector = polysector ;
polyplaneinfo [ numpolyplanes ] . alpha = alpha ;
polyplaneinfo [ numpolyplanes ] . FOFSector = FOFSector ;
polyplaneinfo [ numpolyplanes ] . blend = blend ;
polyplaneinfo [ numpolyplanes ] . planecolormap = planecolormap ;
polyplaneinfo [ numpolyplanes ] . drawcount = drawcount + + ;
numpolyplanes + + ;
}
2014-03-15 16:59:03 +00:00
//
// HWR_CreateDrawNodes
// Creates and sorts a list of drawnodes for the scene being rendered.
static void HWR_CreateDrawNodes ( void )
{
UINT32 i = 0 , p = 0 , prev = 0 , loop ;
const fixed_t pviewz = dup_viewz ;
// Dump EVERYTHING into a huge drawnode list. Then we'll sort it!
// Could this be optimized into _AddTransparentWall/_AddTransparentPlane?
// Hell yes! But sort algorithm must be modified to use a linked list.
gr_drawnode_t * sortnode = Z_Calloc ( ( sizeof ( planeinfo_t ) * numplanes )
2014-10-27 20:57:45 +00:00
+ ( sizeof ( polyplaneinfo_t ) * numpolyplanes )
2014-03-15 16:59:03 +00:00
+ ( sizeof ( wallinfo_t ) * numwalls )
, PU_STATIC , NULL ) ;
// todo:
// However, in reality we shouldn't be re-copying and shifting all this information
// that is already lying around. This should all be in some sort of linked list or lists.
2014-10-27 20:57:45 +00:00
size_t * sortindex = Z_Calloc ( sizeof ( size_t ) * ( numplanes + numpolyplanes + numwalls ) , PU_STATIC , NULL ) ;
2014-03-15 16:59:03 +00:00
// If true, swap the draw order.
boolean shift = false ;
2020-04-18 22:25:28 +00:00
rs_nodesorttime = I_GetTimeMicros ( ) ;
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < numplanes ; i + + , p + + )
{
sortnode [ p ] . plane = & planeinfo [ i ] ;
sortindex [ p ] = p ;
}
2014-10-27 20:57:45 +00:00
for ( i = 0 ; i < numpolyplanes ; i + + , p + + )
{
sortnode [ p ] . polyplane = & polyplaneinfo [ i ] ;
sortindex [ p ] = p ;
}
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < numwalls ; i + + , p + + )
{
sortnode [ p ] . wall = & wallinfo [ i ] ;
sortindex [ p ] = p ;
}
2020-04-18 22:25:28 +00:00
rs_numdrawnodes = p ;
2014-03-15 16:59:03 +00:00
// p is the number of stuff to sort
// Add the 3D floors, thicksides, and masked textures...
// Instead of going through drawsegs, we need to iterate
// through the lists of masked textures and
// translucent ffloors being drawn.
// This is a bubble sort! Wahoo!
// Stuff is sorted:
// sortnode[sortindex[0]] = farthest away
// sortnode[sortindex[p-1]] = closest
// "i" should be closer. "prev" should be further.
// The lower drawcount is, the further it is from the screen.
for ( loop = 0 ; loop < p ; loop + + )
{
for ( i = 1 ; i < p ; i + + )
{
prev = i - 1 ;
if ( sortnode [ sortindex [ i ] ] . plane )
{
// What are we comparing it with?
if ( sortnode [ sortindex [ prev ] ] . plane )
{
// Plane (i) is further away than plane (prev)
if ( ABS ( sortnode [ sortindex [ i ] ] . plane - > fixedheight - pviewz ) > ABS ( sortnode [ sortindex [ prev ] ] . plane - > fixedheight - pviewz ) )
shift = true ;
}
2014-10-27 20:57:45 +00:00
if ( sortnode [ sortindex [ prev ] ] . polyplane )
{
// Plane (i) is further away than polyplane (prev)
if ( ABS ( sortnode [ sortindex [ i ] ] . plane - > fixedheight - pviewz ) > ABS ( sortnode [ sortindex [ prev ] ] . polyplane - > fixedheight - pviewz ) )
shift = true ;
}
2014-03-15 16:59:03 +00:00
else if ( sortnode [ sortindex [ prev ] ] . wall )
{
// Plane (i) is further than wall (prev)
if ( sortnode [ sortindex [ i ] ] . plane - > drawcount > sortnode [ sortindex [ prev ] ] . wall - > drawcount )
shift = true ;
}
}
2014-10-27 20:57:45 +00:00
else if ( sortnode [ sortindex [ i ] ] . polyplane )
{
// What are we comparing it with?
if ( sortnode [ sortindex [ prev ] ] . plane )
{
// Plane (i) is further away than plane (prev)
if ( ABS ( sortnode [ sortindex [ i ] ] . polyplane - > fixedheight - pviewz ) > ABS ( sortnode [ sortindex [ prev ] ] . plane - > fixedheight - pviewz ) )
shift = true ;
}
if ( sortnode [ sortindex [ prev ] ] . polyplane )
{
// Plane (i) is further away than polyplane (prev)
if ( ABS ( sortnode [ sortindex [ i ] ] . polyplane - > fixedheight - pviewz ) > ABS ( sortnode [ sortindex [ prev ] ] . polyplane - > fixedheight - pviewz ) )
shift = true ;
}
else if ( sortnode [ sortindex [ prev ] ] . wall )
{
// Plane (i) is further than wall (prev)
if ( sortnode [ sortindex [ i ] ] . polyplane - > drawcount > sortnode [ sortindex [ prev ] ] . wall - > drawcount )
shift = true ;
}
}
2014-03-15 16:59:03 +00:00
else if ( sortnode [ sortindex [ i ] ] . wall )
{
// What are we comparing it with?
if ( sortnode [ sortindex [ prev ] ] . plane )
{
// Wall (i) is further than plane(prev)
if ( sortnode [ sortindex [ i ] ] . wall - > drawcount > sortnode [ sortindex [ prev ] ] . plane - > drawcount )
shift = true ;
}
2014-10-27 20:57:45 +00:00
if ( sortnode [ sortindex [ prev ] ] . polyplane )
{
// Wall (i) is further than polyplane(prev)
if ( sortnode [ sortindex [ i ] ] . wall - > drawcount > sortnode [ sortindex [ prev ] ] . polyplane - > drawcount )
shift = true ;
}
2014-03-15 16:59:03 +00:00
else if ( sortnode [ sortindex [ prev ] ] . wall )
{
// Wall (i) is further than wall (prev)
if ( sortnode [ sortindex [ i ] ] . wall - > drawcount > sortnode [ sortindex [ prev ] ] . wall - > drawcount )
shift = true ;
}
}
if ( shift )
{
size_t temp ;
temp = sortindex [ prev ] ;
sortindex [ prev ] = sortindex [ i ] ;
sortindex [ i ] = temp ;
shift = false ;
}
} //i++
} // loop++
2020-04-18 22:25:28 +00:00
rs_nodesorttime = I_GetTimeMicros ( ) - rs_nodesorttime ;
rs_nodedrawtime = I_GetTimeMicros ( ) ;
2014-03-15 16:59:03 +00:00
// Okay! Let's draw it all! Woo!
2019-12-25 19:22:01 +00:00
HWD . pfnSetTransform ( & atransform ) ;
HWD . pfnSetShader ( 0 ) ;
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < p ; i + + )
{
if ( sortnode [ sortindex [ i ] ] . plane )
{
// We aren't traversing the BSP tree, so make gr_frontsector null to avoid crashes.
gr_frontsector = NULL ;
if ( ! ( sortnode [ sortindex [ i ] ] . plane - > blend & PF_NoTexture ) )
2019-11-09 02:42:15 +00:00
HWR_GetLevelFlat ( sortnode [ sortindex [ i ] ] . plane - > levelflat ) ;
2016-07-27 18:56:21 +00:00
HWR_RenderPlane ( NULL , sortnode [ sortindex [ i ] ] . plane - > xsub , sortnode [ sortindex [ i ] ] . plane - > isceiling , sortnode [ sortindex [ i ] ] . plane - > fixedheight , sortnode [ sortindex [ i ] ] . plane - > blend , sortnode [ sortindex [ i ] ] . plane - > lightlevel ,
2019-12-25 19:22:01 +00:00
sortnode [ sortindex [ i ] ] . plane - > levelflat , sortnode [ sortindex [ i ] ] . plane - > FOFSector , sortnode [ sortindex [ i ] ] . plane - > alpha , sortnode [ sortindex [ i ] ] . plane - > planecolormap ) ;
2014-03-15 16:59:03 +00:00
}
2014-10-27 20:57:45 +00:00
else if ( sortnode [ sortindex [ i ] ] . polyplane )
{
// We aren't traversing the BSP tree, so make gr_frontsector null to avoid crashes.
gr_frontsector = NULL ;
if ( ! ( sortnode [ sortindex [ i ] ] . polyplane - > blend & PF_NoTexture ) )
2019-11-09 02:42:15 +00:00
HWR_GetLevelFlat ( sortnode [ sortindex [ i ] ] . polyplane - > levelflat ) ;
2016-07-27 18:56:21 +00:00
HWR_RenderPolyObjectPlane ( sortnode [ sortindex [ i ] ] . polyplane - > polysector , sortnode [ sortindex [ i ] ] . polyplane - > isceiling , sortnode [ sortindex [ i ] ] . polyplane - > fixedheight , sortnode [ sortindex [ i ] ] . polyplane - > blend , sortnode [ sortindex [ i ] ] . polyplane - > lightlevel ,
2019-11-09 01:58:41 +00:00
sortnode [ sortindex [ i ] ] . polyplane - > levelflat , sortnode [ sortindex [ i ] ] . polyplane - > FOFSector , sortnode [ sortindex [ i ] ] . polyplane - > alpha , sortnode [ sortindex [ i ] ] . polyplane - > planecolormap ) ;
2014-10-27 20:57:45 +00:00
}
2014-03-15 16:59:03 +00:00
else if ( sortnode [ sortindex [ i ] ] . wall )
{
if ( ! ( sortnode [ sortindex [ i ] ] . wall - > blend & PF_NoTexture ) )
HWR_GetTexture ( sortnode [ sortindex [ i ] ] . wall - > texnum ) ;
HWR_RenderWall ( sortnode [ sortindex [ i ] ] . wall - > wallVerts , & sortnode [ sortindex [ i ] ] . wall - > Surf , sortnode [ sortindex [ i ] ] . wall - > blend , sortnode [ sortindex [ i ] ] . wall - > fogwall ,
sortnode [ sortindex [ i ] ] . wall - > lightlevel , sortnode [ sortindex [ i ] ] . wall - > wallcolormap ) ;
}
}
2020-04-18 22:25:28 +00:00
rs_nodedrawtime = I_GetTimeMicros ( ) - rs_nodedrawtime ;
2014-03-15 16:59:03 +00:00
numwalls = 0 ;
numplanes = 0 ;
2014-10-27 20:57:45 +00:00
numpolyplanes = 0 ;
2014-03-15 16:59:03 +00:00
// No mem leaks, please.
Z_Free ( sortnode ) ;
Z_Free ( sortindex ) ;
}
// --------------------------------------------------------------------------
// Draw all vissprites
// --------------------------------------------------------------------------
2019-12-25 19:22:01 +00:00
2017-09-07 23:56:58 +00:00
// added the stransform so they can be switched as drawing happenes so MD2s and sprites are sorted correctly with each other
2014-03-15 16:59:03 +00:00
static void HWR_DrawSprites ( void )
{
if ( gr_visspritecount > 0 )
{
gr_vissprite_t * spr ;
2020-01-24 01:02:18 +00:00
HWD . pfnSetSpecialState ( HWD_SET_MODEL_LIGHTING , cv_grmodellighting . value ) ;
2014-03-15 16:59:03 +00:00
// draw all vissprites back to front
for ( spr = gr_vsprsortedhead . next ;
spr ! = & gr_vsprsortedhead ;
spr = spr - > next )
{
# ifdef HWPRECIP
if ( spr - > precip )
HWR_DrawPrecipitationSprite ( spr ) ;
else
# endif
2020-01-16 17:37:32 +00:00
{
2020-01-18 03:20:04 +00:00
if ( spr - > mobj & & spr - > mobj - > shadowscale & & cv_shadow . value )
2020-01-16 17:37:32 +00:00
{
2020-02-02 03:58:11 +00:00
HWR_DrawDropShadow ( spr - > mobj , spr - > mobj - > shadowscale ) ;
2020-01-16 17:37:32 +00:00
}
2014-03-19 23:40:02 +00:00
if ( spr - > mobj & & spr - > mobj - > skin & & spr - > mobj - > sprite = = SPR_PLAY )
2014-03-15 16:59:03 +00:00
{
2019-09-03 02:29:16 +00:00
if ( ! cv_grmodels . value | | md2_playermodels [ ( skin_t * ) spr - > mobj - > skin - skins ] . notfound | | md2_playermodels [ ( skin_t * ) spr - > mobj - > skin - skins ] . scale < 0.0f )
2014-03-15 16:59:03 +00:00
HWR_DrawSprite ( spr ) ;
2017-09-07 23:56:58 +00:00
else
2019-12-13 01:53:19 +00:00
{
if ( ! HWR_DrawModel ( spr ) )
HWR_DrawSprite ( spr ) ;
}
2014-03-15 16:59:03 +00:00
}
2017-09-07 23:56:58 +00:00
else
2014-03-15 16:59:03 +00:00
{
2019-09-03 02:29:16 +00:00
if ( ! cv_grmodels . value | | md2_models [ spr - > mobj - > sprite ] . notfound | | md2_models [ spr - > mobj - > sprite ] . scale < 0.0f )
2017-09-07 23:56:58 +00:00
HWR_DrawSprite ( spr ) ;
else
2019-12-13 01:53:19 +00:00
{
if ( ! HWR_DrawModel ( spr ) )
HWR_DrawSprite ( spr ) ;
}
2014-03-15 16:59:03 +00:00
}
2020-01-16 17:37:32 +00:00
}
2014-03-15 16:59:03 +00:00
}
2020-01-24 01:02:18 +00:00
HWD . pfnSetSpecialState ( HWD_SET_MODEL_LIGHTING , 0 ) ;
2014-03-15 16:59:03 +00:00
}
}
// --------------------------------------------------------------------------
// HWR_AddSprites
// During BSP traversal, this adds sprites by sector.
// --------------------------------------------------------------------------
static UINT8 sectorlight ;
static void HWR_AddSprites ( sector_t * sec )
{
mobj_t * thing ;
# ifdef HWPRECIP
precipmobj_t * precipthing ;
# endif
2020-01-18 04:45:55 +00:00
fixed_t limit_dist , hoop_limit_dist ;
2014-03-15 16:59:03 +00:00
// BSP is traversed by subsector.
// A sector might have been split into several
// subsectors during BSP building.
// Thus we check whether its already added.
if ( sec - > validcount = = validcount )
return ;
// Well, now it will be done.
sec - > validcount = validcount ;
// sprite lighting
2014-03-24 16:11:25 +00:00
sectorlight = sec - > lightlevel & 0xff ;
2014-03-15 16:59:03 +00:00
// Handle all things in sector.
// If a limit exists, handle things a tiny bit different.
2019-10-11 19:02:11 +00:00
limit_dist = ( fixed_t ) ( cv_drawdist . value ) < < FRACBITS ;
hoop_limit_dist = ( fixed_t ) ( cv_drawdist_nights . value ) < < FRACBITS ;
2020-01-18 04:45:55 +00:00
for ( thing = sec - > thinglist ; thing ; thing = thing - > snext )
2014-03-15 16:59:03 +00:00
{
2020-01-18 04:45:55 +00:00
if ( R_ThingVisibleWithinDist ( thing , limit_dist , hoop_limit_dist ) )
2018-10-07 14:00:58 +00:00
HWR_ProjectSprite ( thing ) ;
2014-03-15 16:59:03 +00:00
}
# ifdef HWPRECIP
2019-06-18 12:33:35 +00:00
// no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off
2014-03-15 16:59:03 +00:00
if ( ( limit_dist = ( fixed_t ) cv_drawdist_precip . value < < FRACBITS ) )
{
for ( precipthing = sec - > preciplist ; precipthing ; precipthing = precipthing - > snext )
{
2020-01-18 04:45:55 +00:00
if ( R_PrecipThingVisible ( precipthing , limit_dist ) )
HWR_ProjectPrecipitationSprite ( precipthing ) ;
2014-03-15 16:59:03 +00:00
}
}
# endif
}
// --------------------------------------------------------------------------
// HWR_ProjectSprite
// Generates a vissprite for a thing if it might be visible.
// --------------------------------------------------------------------------
// BP why not use xtoviexangle/viewangletox like in bsp ?....
static void HWR_ProjectSprite ( mobj_t * thing )
{
gr_vissprite_t * vis ;
float tr_x , tr_y ;
2018-03-21 19:45:37 +00:00
float tz ;
2014-03-15 16:59:03 +00:00
float x1 , x2 ;
2018-03-21 19:45:37 +00:00
float rightsin , rightcos ;
2014-03-15 16:59:03 +00:00
float this_scale ;
float gz , gzt ;
spritedef_t * sprdef ;
spriteframe_t * sprframe ;
2019-09-29 15:13:51 +00:00
spriteinfo_t * sprinfo ;
2020-01-09 04:52:34 +00:00
md2_t * md2 ;
2014-03-15 16:59:03 +00:00
size_t lumpoff ;
unsigned rot ;
2020-01-08 20:49:14 +00:00
UINT16 flip ;
2016-09-24 13:23:00 +00:00
boolean vflip = ( ! ( thing - > eflags & MFE_VERTICALFLIP ) ! = ! ( thing - > frame & FF_VERTICALFLIP ) ) ;
2014-03-15 16:59:03 +00:00
angle_t ang ;
INT32 heightsec , phs ;
2016-12-13 21:02:23 +00:00
const boolean papersprite = ( thing - > frame & FF_PAPERSPRITE ) ;
2018-04-06 17:42:07 +00:00
angle_t mobjangle = ( thing - > player ? thing - > player - > drawangle : thing - > angle ) ;
2016-12-13 21:02:23 +00:00
float z1 , z2 ;
2014-03-15 16:59:03 +00:00
2019-08-18 17:16:48 +00:00
fixed_t spr_width , spr_height ;
fixed_t spr_offset , spr_topoffset ;
# ifdef ROTSPRITE
patch_t * rotsprite = NULL ;
2019-12-27 00:27:30 +00:00
INT32 rollangle = 0 ;
2019-08-18 17:16:48 +00:00
# endif
2014-03-15 16:59:03 +00:00
if ( ! thing )
return ;
2019-08-18 17:16:48 +00:00
this_scale = FIXED_TO_FLOAT ( thing - > scale ) ;
2014-03-15 16:59:03 +00:00
// transform the origin point
tr_x = FIXED_TO_FLOAT ( thing - > x ) - gr_viewx ;
tr_y = FIXED_TO_FLOAT ( thing - > y ) - gr_viewy ;
// rotation around vertical axis
tz = ( tr_x * gr_viewcos ) + ( tr_y * gr_viewsin ) ;
// thing is behind view plane?
2020-01-09 04:52:34 +00:00
if ( tz < ZCLIP_PLANE & & ! papersprite )
{
if ( cv_grmodels . value ) //Yellow: Only MD2's dont disappear
{
if ( thing - > skin & & thing - > sprite = = SPR_PLAY )
md2 = & md2_playermodels [ ( ( skin_t * ) thing - > skin - skins ) ] ;
else
md2 = & md2_models [ thing - > sprite ] ;
if ( md2 - > notfound | | md2 - > scale < 0.0f )
return ;
}
else
return ;
}
2014-03-15 16:59:03 +00:00
2018-03-21 19:45:37 +00:00
// The above can stay as it works for cutting sprites that are too close
tr_x = FIXED_TO_FLOAT ( thing - > x ) ;
tr_y = FIXED_TO_FLOAT ( thing - > y ) ;
2014-03-15 16:59:03 +00:00
// decide which patch to use for sprite relative to player
# ifdef RANGECHECK
if ( ( unsigned ) thing - > sprite > = numsprites )
I_Error ( " HWR_ProjectSprite: invalid sprite number %i " , thing - > sprite ) ;
# endif
rot = thing - > frame & FF_FRAMEMASK ;
//Fab : 02-08-98: 'skin' override spritedef currently used for skin
if ( thing - > skin & & thing - > sprite = = SPR_PLAY )
2019-09-29 15:13:51 +00:00
{
2015-01-22 15:23:45 +00:00
sprdef = & ( ( skin_t * ) thing - > skin ) - > sprites [ thing - > sprite2 ] ;
2019-09-29 15:13:51 +00:00
sprinfo = & ( ( skin_t * ) thing - > skin ) - > sprinfo [ thing - > sprite2 ] ;
}
2014-03-15 16:59:03 +00:00
else
2019-09-29 15:13:51 +00:00
{
2014-03-15 16:59:03 +00:00
sprdef = & sprites [ thing - > sprite ] ;
2019-09-29 15:13:51 +00:00
sprinfo = NULL ;
}
2014-03-15 16:59:03 +00:00
if ( rot > = sprdef - > numframes )
{
2015-02-15 17:15:55 +00:00
CONS_Alert ( CONS_ERROR , M_GetText ( " HWR_ProjectSprite: invalid sprite frame %s/%s for %s \n " ) ,
2014-03-15 16:59:03 +00:00
sizeu1 ( rot ) , sizeu2 ( sprdef - > numframes ) , sprnames [ thing - > sprite ] ) ;
thing - > sprite = states [ S_UNKNOWN ] . sprite ;
thing - > frame = states [ S_UNKNOWN ] . frame ;
2015-02-18 23:42:01 +00:00
sprdef = & sprites [ thing - > sprite ] ;
2019-09-29 15:13:51 +00:00
sprinfo = NULL ;
2014-03-15 16:59:03 +00:00
rot = thing - > frame & FF_FRAMEMASK ;
thing - > state - > sprite = thing - > sprite ;
thing - > state - > frame = thing - > frame ;
}
sprframe = & sprdef - > spriteframes [ rot ] ;
# ifdef PARANOIA
if ( ! sprframe )
I_Error ( " sprframes NULL for sprite %d \n " , thing - > sprite ) ;
# endif
2018-06-11 18:53:16 +00:00
ang = R_PointToAngle ( thing - > x , thing - > y ) - mobjangle ;
2016-12-13 21:02:23 +00:00
2016-07-18 23:04:00 +00:00
if ( sprframe - > rotate = = SRF_SINGLE )
2014-03-15 16:59:03 +00:00
{
// use single rotation for all views
rot = 0 ; //Fab: for vis->patch below
lumpoff = sprframe - > lumpid [ 0 ] ; //Fab: see note above
flip = sprframe - > flip ; // Will only be 0x00 or 0xFF
2018-06-09 17:47:42 +00:00
2018-06-09 21:58:03 +00:00
if ( papersprite & & ang < ANGLE_180 )
2020-01-08 20:49:14 +00:00
flip ^ = 0xFFFF ;
2014-03-15 16:59:03 +00:00
}
2016-07-18 23:04:00 +00:00
else
{
// choose a different rotation based on player view
2016-08-06 23:21:16 +00:00
if ( ( sprframe - > rotate & SRF_RIGHT ) & & ( ang < ANGLE_180 ) ) // See from right
2016-07-18 23:04:00 +00:00
rot = 6 ; // F7 slot
2016-08-06 23:21:16 +00:00
else if ( ( sprframe - > rotate & SRF_LEFT ) & & ( ang > = ANGLE_180 ) ) // See from left
2016-07-18 23:04:00 +00:00
rot = 2 ; // F3 slot
2020-01-08 20:49:14 +00:00
else if ( sprframe - > rotate & SRF_3DGE ) // 16-angle mode
{
rot = ( ang + ANGLE_180 + ANGLE_11hh ) > > 28 ;
rot = ( ( rot & 1 ) < < 3 ) | ( rot > > 1 ) ;
}
2016-07-18 23:04:00 +00:00
else // Normal behaviour
rot = ( ang + ANGLE_202h ) > > 29 ;
//Fab: lumpid is the index for spritewidth,spriteoffset... tables
lumpoff = sprframe - > lumpid [ rot ] ;
flip = sprframe - > flip & ( 1 < < rot ) ;
2018-06-09 21:58:03 +00:00
if ( papersprite & & ang < ANGLE_180 )
2020-01-08 20:49:14 +00:00
flip ^ = ( 1 < < rot ) ;
2016-07-18 23:04:00 +00:00
}
2014-03-15 16:59:03 +00:00
if ( thing - > skin & & ( ( skin_t * ) thing - > skin ) - > flags & SF_HIRES )
this_scale = this_scale * FIXED_TO_FLOAT ( ( ( skin_t * ) thing - > skin ) - > highresscale ) ;
2019-08-18 17:16:48 +00:00
spr_width = spritecachedinfo [ lumpoff ] . width ;
spr_height = spritecachedinfo [ lumpoff ] . height ;
spr_offset = spritecachedinfo [ lumpoff ] . offset ;
spr_topoffset = spritecachedinfo [ lumpoff ] . topoffset ;
# ifdef ROTSPRITE
2019-12-27 00:27:30 +00:00
if ( thing - > rollangle )
2019-08-18 17:16:48 +00:00
{
2019-12-27 00:27:30 +00:00
rollangle = R_GetRollAngle ( thing - > rollangle ) ;
2020-01-08 20:49:14 +00:00
if ( ! ( sprframe - > rotsprite . cached & ( 1 < < rot ) ) )
2019-09-29 17:12:53 +00:00
R_CacheRotSprite ( thing - > sprite , ( thing - > frame & FF_FRAMEMASK ) , sprinfo , sprframe , rot , flip ) ;
2019-08-18 17:16:48 +00:00
rotsprite = sprframe - > rotsprite . patch [ rot ] [ rollangle ] ;
if ( rotsprite ! = NULL )
{
spr_width = rotsprite - > width < < FRACBITS ;
spr_height = rotsprite - > height < < FRACBITS ;
spr_offset = rotsprite - > leftoffset < < FRACBITS ;
spr_topoffset = rotsprite - > topoffset < < FRACBITS ;
// flip -> rotate, not rotate -> flip
flip = 0 ;
}
}
# endif
2018-06-09 17:47:42 +00:00
if ( papersprite )
2018-04-06 17:42:07 +00:00
{
2018-06-11 18:53:16 +00:00
rightsin = FIXED_TO_FLOAT ( FINESINE ( ( mobjangle ) > > ANGLETOFINESHIFT ) ) ;
rightcos = FIXED_TO_FLOAT ( FINECOSINE ( ( mobjangle ) > > ANGLETOFINESHIFT ) ) ;
2018-04-06 17:42:07 +00:00
}
2014-03-15 16:59:03 +00:00
else
2018-04-06 17:42:07 +00:00
{
rightsin = FIXED_TO_FLOAT ( FINESINE ( ( viewangle + ANGLE_90 ) > > ANGLETOFINESHIFT ) ) ;
rightcos = FIXED_TO_FLOAT ( FINECOSINE ( ( viewangle + ANGLE_90 ) > > ANGLETOFINESHIFT ) ) ;
}
2014-03-15 16:59:03 +00:00
if ( flip )
2018-03-21 19:45:37 +00:00
{
2019-08-18 17:16:48 +00:00
x1 = ( FIXED_TO_FLOAT ( spr_width - spr_offset ) * this_scale ) ;
x2 = ( FIXED_TO_FLOAT ( spr_offset ) * this_scale ) ;
2018-03-21 19:45:37 +00:00
}
2014-03-15 16:59:03 +00:00
else
2018-03-21 19:45:37 +00:00
{
2019-08-18 17:16:48 +00:00
x1 = ( FIXED_TO_FLOAT ( spr_offset ) * this_scale ) ;
x2 = ( FIXED_TO_FLOAT ( spr_width - spr_offset ) * this_scale ) ;
2018-03-21 19:45:37 +00:00
}
2017-05-13 11:49:30 +00:00
2018-04-06 17:42:07 +00:00
// test if too close
/*
if ( papersprite )
{
z1 = tz - x1 * angle_scalez ;
z2 = tz + x2 * angle_scalez ;
2017-05-13 11:49:30 +00:00
2018-04-06 17:42:07 +00:00
if ( max ( z1 , z2 ) < ZCLIP_PLANE )
return ;
}
*/
2016-12-13 21:02:23 +00:00
2018-03-21 19:45:37 +00:00
z1 = tr_y + x1 * rightsin ;
z2 = tr_y - x2 * rightsin ;
x1 = tr_x + x1 * rightcos ;
x2 = tr_x - x2 * rightcos ;
2014-03-15 16:59:03 +00:00
2016-09-24 13:23:00 +00:00
if ( vflip )
2014-03-15 16:59:03 +00:00
{
2019-08-18 17:16:48 +00:00
gz = FIXED_TO_FLOAT ( thing - > z + thing - > height ) - FIXED_TO_FLOAT ( spr_topoffset ) * this_scale ;
gzt = gz + FIXED_TO_FLOAT ( spr_height ) * this_scale ;
2014-03-15 16:59:03 +00:00
}
else
{
2019-08-18 17:16:48 +00:00
gzt = FIXED_TO_FLOAT ( thing - > z ) + FIXED_TO_FLOAT ( spr_topoffset ) * this_scale ;
gz = gzt - FIXED_TO_FLOAT ( spr_height ) * this_scale ;
2014-03-15 16:59:03 +00:00
}
if ( thing - > subsector - > sector - > cullheight )
{
2014-11-12 00:55:07 +00:00
if ( HWR_DoCulling ( thing - > subsector - > sector - > cullheight , viewsector - > cullheight , gr_viewz , gz , gzt ) )
return ;
2014-03-15 16:59:03 +00:00
}
heightsec = thing - > subsector - > sector - > heightsec ;
2018-06-23 17:47:32 +00:00
if ( viewplayer - > mo & & viewplayer - > mo - > subsector )
phs = viewplayer - > mo - > subsector - > sector - > heightsec ;
else
phs = - 1 ;
2014-03-15 16:59:03 +00:00
if ( heightsec ! = - 1 & & phs ! = - 1 ) // only clip things which are in special sectors
{
if ( gr_viewz < FIXED_TO_FLOAT ( sectors [ phs ] . floorheight ) ?
FIXED_TO_FLOAT ( thing - > z ) > = FIXED_TO_FLOAT ( sectors [ heightsec ] . floorheight ) :
gzt < FIXED_TO_FLOAT ( sectors [ heightsec ] . floorheight ) )
return ;
if ( gr_viewz > FIXED_TO_FLOAT ( sectors [ phs ] . ceilingheight ) ?
gzt < FIXED_TO_FLOAT ( sectors [ heightsec ] . ceilingheight ) & & gr_viewz > = FIXED_TO_FLOAT ( sectors [ heightsec ] . ceilingheight ) :
FIXED_TO_FLOAT ( thing - > z ) > = FIXED_TO_FLOAT ( sectors [ heightsec ] . ceilingheight ) )
return ;
}
2019-10-06 15:31:13 +00:00
if ( ( thing - > flags2 & MF2_LINKDRAW ) & & thing - > tracer )
{
// bodge support - not nearly as comprehensive as r_things.c, but better than nothing
2020-01-18 04:56:32 +00:00
if ( ! R_ThingVisible ( thing - > tracer ) )
2019-10-06 15:31:13 +00:00
return ;
}
2014-03-15 16:59:03 +00:00
// store information in a vissprite
vis = HWR_NewVisSprite ( ) ;
vis - > x1 = x1 ;
vis - > x2 = x2 ;
2018-03-21 19:45:37 +00:00
vis - > tz = tz ; // Keep tz for the simple sprite sorting that happens
2015-11-23 17:01:10 +00:00
vis - > dispoffset = thing - > info - > dispoffset ; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST
2019-08-18 17:16:48 +00:00
//vis->patchlumpnum = sprframe->lumppat[rot];
# ifdef ROTSPRITE
if ( rotsprite )
vis - > gpatch = ( GLPatch_t * ) rotsprite ;
else
# endif
vis - > gpatch = ( GLPatch_t * ) W_CachePatchNum ( sprframe - > lumppat [ rot ] , PU_CACHE ) ;
2014-03-15 16:59:03 +00:00
vis - > flip = flip ;
vis - > mobj = thing ;
2016-12-13 21:02:23 +00:00
vis - > z1 = z1 ;
vis - > z2 = z2 ;
2014-03-15 16:59:03 +00:00
//Hurdler: 25/04/2000: now support colormap in hardware mode
2019-10-06 15:31:13 +00:00
if ( ( vis - > mobj - > flags & ( MF_ENEMY | MF_BOSS ) ) & & ( vis - > mobj - > flags2 & MF2_FRET ) & & ! ( vis - > mobj - > flags & MF_GRENADEBOUNCE ) & & ( leveltime & 1 ) ) // Bosses "flash"
2014-03-15 16:59:03 +00:00
{
2019-07-02 23:58:02 +00:00
if ( vis - > mobj - > type = = MT_CYBRAKDEMON | | vis - > mobj - > colorized )
2014-03-15 16:59:03 +00:00
vis - > colormap = R_GetTranslationColormap ( TC_ALLWHITE , 0 , GTC_CACHE ) ;
else if ( vis - > mobj - > type = = MT_METALSONIC_BATTLE )
vis - > colormap = R_GetTranslationColormap ( TC_METALSONIC , 0 , GTC_CACHE ) ;
else
vis - > colormap = R_GetTranslationColormap ( TC_BOSS , 0 , GTC_CACHE ) ;
}
else if ( thing - > color )
{
// New colormap stuff for skins Tails 06-07-2002
2019-06-18 16:55:57 +00:00
if ( thing - > colorized )
vis - > colormap = R_GetTranslationColormap ( TC_RAINBOW , thing - > color , GTC_CACHE ) ;
2019-11-04 13:11:04 +00:00
else if ( thing - > player & & thing - > player - > dashmode > = DASHMODE_THRESHOLD
& & ( thing - > player - > charflags & SF_DASHMODE )
& & ( ( leveltime / 2 ) & 1 ) )
{
if ( thing - > player - > charflags & SF_MACHINE )
vis - > colormap = R_GetTranslationColormap ( TC_DASHMODE , 0 , GTC_CACHE ) ;
else
vis - > colormap = R_GetTranslationColormap ( TC_RAINBOW , thing - > color , GTC_CACHE ) ;
}
2019-06-18 16:55:57 +00:00
else if ( thing - > skin & & thing - > sprite = = SPR_PLAY ) // This thing is a player!
2014-03-15 16:59:03 +00:00
{
size_t skinnum = ( skin_t * ) thing - > skin - skins ;
vis - > colormap = R_GetTranslationColormap ( ( INT32 ) skinnum , thing - > color , GTC_CACHE ) ;
}
else
vis - > colormap = R_GetTranslationColormap ( TC_DEFAULT , vis - > mobj - > color ? vis - > mobj - > color : SKINCOLOR_CYAN , GTC_CACHE ) ;
}
else
vis - > colormap = colormaps ;
// set top/bottom coords
2018-03-21 19:45:37 +00:00
vis - > ty = gzt ;
2014-03-15 16:59:03 +00:00
//CONS_Debug(DBG_RENDER, "------------------\nH: sprite : %d\nH: frame : %x\nH: type : %d\nH: sname : %s\n\n",
// thing->sprite, thing->frame, thing->type, sprnames[thing->sprite]);
2016-09-24 13:23:00 +00:00
vis - > vflip = vflip ;
2014-03-15 16:59:03 +00:00
vis - > precip = false ;
}
# ifdef HWPRECIP
// Precipitation projector for hardware mode
static void HWR_ProjectPrecipitationSprite ( precipmobj_t * thing )
{
gr_vissprite_t * vis ;
float tr_x , tr_y ;
2018-03-21 19:45:37 +00:00
float tz ;
2014-03-15 16:59:03 +00:00
float x1 , x2 ;
2018-03-21 19:45:37 +00:00
float z1 , z2 ;
float rightsin , rightcos ;
2014-03-15 16:59:03 +00:00
spritedef_t * sprdef ;
spriteframe_t * sprframe ;
size_t lumpoff ;
unsigned rot = 0 ;
UINT8 flip ;
// transform the origin point
tr_x = FIXED_TO_FLOAT ( thing - > x ) - gr_viewx ;
tr_y = FIXED_TO_FLOAT ( thing - > y ) - gr_viewy ;
// rotation around vertical axis
tz = ( tr_x * gr_viewcos ) + ( tr_y * gr_viewsin ) ;
// thing is behind view plane?
if ( tz < ZCLIP_PLANE )
return ;
2018-03-21 19:45:37 +00:00
tr_x = FIXED_TO_FLOAT ( thing - > x ) ;
tr_y = FIXED_TO_FLOAT ( thing - > y ) ;
2014-03-15 16:59:03 +00:00
// decide which patch to use for sprite relative to player
if ( ( unsigned ) thing - > sprite > = numsprites )
# ifdef RANGECHECK
I_Error ( " HWR_ProjectPrecipitationSprite: invalid sprite number %i " ,
thing - > sprite ) ;
# else
return ;
# endif
sprdef = & sprites [ thing - > sprite ] ;
if ( ( size_t ) ( thing - > frame & FF_FRAMEMASK ) > = sprdef - > numframes )
# ifdef RANGECHECK
I_Error ( " HWR_ProjectPrecipitationSprite: invalid sprite frame %i : %i for %s " ,
thing - > sprite , thing - > frame , sprnames [ thing - > sprite ] ) ;
# else
return ;
# endif
sprframe = & sprdef - > spriteframes [ thing - > frame & FF_FRAMEMASK ] ;
// use single rotation for all views
lumpoff = sprframe - > lumpid [ 0 ] ;
flip = sprframe - > flip ; // Will only be 0x00 or 0xFF
2018-03-21 19:45:37 +00:00
rightsin = FIXED_TO_FLOAT ( FINESINE ( ( viewangle + ANGLE_90 ) > > ANGLETOFINESHIFT ) ) ;
rightcos = FIXED_TO_FLOAT ( FINECOSINE ( ( viewangle + ANGLE_90 ) > > ANGLETOFINESHIFT ) ) ;
if ( flip )
{
x1 = FIXED_TO_FLOAT ( spritecachedinfo [ lumpoff ] . width - spritecachedinfo [ lumpoff ] . offset ) ;
x2 = FIXED_TO_FLOAT ( spritecachedinfo [ lumpoff ] . offset ) ;
}
else
{
x1 = FIXED_TO_FLOAT ( spritecachedinfo [ lumpoff ] . offset ) ;
x2 = FIXED_TO_FLOAT ( spritecachedinfo [ lumpoff ] . width - spritecachedinfo [ lumpoff ] . offset ) ;
}
2014-03-15 16:59:03 +00:00
2018-03-21 19:45:37 +00:00
z1 = tr_y + x1 * rightsin ;
z2 = tr_y - x2 * rightsin ;
x1 = tr_x + x1 * rightcos ;
x2 = tr_x - x2 * rightcos ;
2014-03-15 16:59:03 +00:00
//
// store information in a vissprite
//
vis = HWR_NewVisSprite ( ) ;
vis - > x1 = x1 ;
2016-10-27 22:41:24 +00:00
vis - > x2 = x2 ;
2018-03-21 19:45:37 +00:00
vis - > z1 = z1 ;
vis - > z2 = z2 ;
2014-03-15 16:59:03 +00:00
vis - > tz = tz ;
2015-11-23 17:01:10 +00:00
vis - > dispoffset = 0 ; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST
2019-08-18 17:16:48 +00:00
//vis->patchlumpnum = sprframe->lumppat[rot];
vis - > gpatch = ( GLPatch_t * ) W_CachePatchNum ( sprframe - > lumppat [ rot ] , PU_CACHE ) ;
2014-03-15 16:59:03 +00:00
vis - > flip = flip ;
vis - > mobj = ( mobj_t * ) thing ;
vis - > colormap = colormaps ;
// set top/bottom coords
2018-03-21 19:45:37 +00:00
vis - > ty = FIXED_TO_FLOAT ( thing - > z + spritecachedinfo [ lumpoff ] . topoffset ) ;
2014-03-15 16:59:03 +00:00
vis - > precip = true ;
2019-06-18 12:33:35 +00:00
// okay... this is a hack, but weather isn't networked, so it should be ok
if ( ! ( thing - > precipflags & PCF_THUNK ) )
{
if ( thing - > precipflags & PCF_RAIN )
P_RainThinker ( thing ) ;
else
P_SnowThinker ( thing ) ;
thing - > precipflags | = PCF_THUNK ;
}
2014-03-15 16:59:03 +00:00
}
# endif
// ==========================================================================
//
// ==========================================================================
2019-09-18 02:38:04 +00:00
static void HWR_DrawSkyBackground ( player_t * player )
2014-03-15 16:59:03 +00:00
{
2019-09-18 02:38:04 +00:00
if ( cv_grskydome . value )
{
2019-12-08 05:27:51 +00:00
FTransform dometransform ;
2019-12-31 17:21:46 +00:00
const float fpov = FIXED_TO_FLOAT ( cv_fov . value + player - > fovadd ) ;
2019-09-18 02:38:04 +00:00
postimg_t * type ;
2014-03-15 16:59:03 +00:00
2019-09-18 02:38:04 +00:00
if ( splitscreen & & player = = & players [ secondarydisplayplayer ] )
type = & postimgtype2 ;
else
type = & postimgtype ;
2014-03-15 16:59:03 +00:00
2019-12-08 05:27:51 +00:00
memset ( & dometransform , 0x00 , sizeof ( FTransform ) ) ;
2018-11-10 19:19:41 +00:00
2019-09-18 02:38:04 +00:00
//04/01/2000: Hurdler: added for T&L
// It should replace all other gr_viewxxx when finished
2020-02-08 20:42:26 +00:00
HWR_SetTransformAiming ( & dometransform , player , false ) ;
2019-12-08 05:27:51 +00:00
dometransform . angley = ( float ) ( ( viewangle - ANGLE_270 ) > > ANGLETOFINESHIFT ) * ( 360.0f / ( float ) FINEANGLES ) ;
2014-03-15 16:59:03 +00:00
2019-09-18 02:38:04 +00:00
if ( * type = = postimg_flip )
2019-12-08 05:27:51 +00:00
dometransform . flip = true ;
2019-09-18 02:38:04 +00:00
else
2019-12-08 05:27:51 +00:00
dometransform . flip = false ;
2014-03-15 16:59:03 +00:00
2019-12-08 05:27:51 +00:00
dometransform . scalex = 1 ;
dometransform . scaley = ( float ) vid . width / vid . height ;
dometransform . scalez = 1 ;
dometransform . fovxangle = fpov ; // Tails
dometransform . fovyangle = fpov ; // Tails
2020-01-18 03:55:16 +00:00
if ( player - > viewrollangle ! = 0 )
{
fixed_t rol = AngleFixed ( player - > viewrollangle ) ;
dometransform . rollangle = FIXED_TO_FLOAT ( rol ) ;
dometransform . roll = true ;
}
2019-12-08 05:27:51 +00:00
dometransform . splitscreen = splitscreen ;
2014-03-20 20:13:15 +00:00
2019-09-18 02:38:04 +00:00
HWR_GetTexture ( texturetranslation [ skytexture ] ) ;
2019-12-08 05:27:51 +00:00
HWD . pfnRenderSkyDome ( skytexture , textures [ skytexture ] - > width , textures [ skytexture ] - > height , dometransform ) ;
2019-09-18 02:38:04 +00:00
}
else
{
FOutVector v [ 4 ] ;
angle_t angle ;
float dimensionmultiply ;
float aspectratio ;
float angleturn ;
2014-03-15 16:59:03 +00:00
2019-09-18 02:38:04 +00:00
HWR_GetTexture ( texturetranslation [ skytexture ] ) ;
aspectratio = ( float ) vid . width / ( float ) vid . height ;
2014-03-15 16:59:03 +00:00
2019-09-18 02:38:04 +00:00
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
// because it's called just after clearing the screen
// and thus, the near clipping plane is set to 3.99
// Sryder: Just use the near clipping plane value then
2014-03-15 16:59:03 +00:00
2019-09-18 02:38:04 +00:00
// 3--2
// | /|
// |/ |
// 0--1
v [ 0 ] . x = v [ 3 ] . x = - ZCLIP_PLANE - 1 ;
v [ 1 ] . x = v [ 2 ] . x = ZCLIP_PLANE + 1 ;
v [ 0 ] . y = v [ 1 ] . y = - ZCLIP_PLANE - 1 ;
v [ 2 ] . y = v [ 3 ] . y = ZCLIP_PLANE + 1 ;
2014-03-20 20:13:15 +00:00
2019-09-18 02:38:04 +00:00
v [ 0 ] . z = v [ 1 ] . z = v [ 2 ] . z = v [ 3 ] . z = ZCLIP_PLANE + 1 ;
2018-11-10 19:19:41 +00:00
2019-09-18 02:38:04 +00:00
// X
2014-09-07 23:55:32 +00:00
2019-09-18 02:38:04 +00:00
// NOTE: This doesn't work right with texture widths greater than 1024
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
2014-03-15 16:59:03 +00:00
2019-09-18 02:38:04 +00:00
angle = ( dup_viewangle + gr_xtoviewangle [ 0 ] ) ;
2018-11-10 19:19:41 +00:00
2019-09-18 02:38:04 +00:00
dimensionmultiply = ( ( float ) textures [ texturetranslation [ skytexture ] ] - > width / 256.0f ) ;
2019-12-25 19:22:01 +00:00
v [ 0 ] . s = v [ 3 ] . s = ( - 1.0f * angle ) / ( ( ANGLE_90 - 1 ) * dimensionmultiply ) ; // left
v [ 2 ] . s = v [ 1 ] . s = v [ 0 ] . s + ( 1.0f / dimensionmultiply ) ; // right (or left + 1.0f)
2019-09-18 02:38:04 +00:00
// use +angle and -1.0f above instead if you wanted old backwards behavior
2014-03-15 16:59:03 +00:00
2019-09-18 02:38:04 +00:00
// Y
angle = aimingangle ;
dimensionmultiply = ( ( float ) textures [ texturetranslation [ skytexture ] ] - > height / ( 128.0f * aspectratio ) ) ;
if ( splitscreen )
{
dimensionmultiply * = 2 ;
angle * = 2 ;
}
// Middle of the sky should always be at angle 0
// need to keep correct aspect ratio with X
if ( atransform . flip )
{
// During vertical flip the sky should be flipped and it's y movement should also be flipped obviously
2019-12-25 19:22:01 +00:00
v [ 3 ] . t = v [ 2 ] . t = - ( 0.5f - ( 0.5f / dimensionmultiply ) ) ; // top
v [ 0 ] . t = v [ 1 ] . t = v [ 3 ] . t - ( 1.0f / dimensionmultiply ) ; // bottom (or top - 1.0f)
2019-09-18 02:38:04 +00:00
}
else
{
2019-12-25 19:22:01 +00:00
v [ 0 ] . t = v [ 1 ] . t = - ( 0.5f - ( 0.5f / dimensionmultiply ) ) ; // bottom
v [ 3 ] . t = v [ 2 ] . t = v [ 0 ] . t - ( 1.0f / dimensionmultiply ) ; // top (or bottom - 1.0f)
2019-09-18 02:38:04 +00:00
}
angleturn = ( ( ( float ) ANGLE_45 - 1.0f ) * aspectratio ) * dimensionmultiply ;
if ( angle > ANGLE_180 ) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa
{
angle = InvAngle ( angle ) ;
2019-12-25 19:22:01 +00:00
v [ 3 ] . t = v [ 2 ] . t + = ( ( float ) angle / angleturn ) ;
v [ 0 ] . t = v [ 1 ] . t + = ( ( float ) angle / angleturn ) ;
2019-09-18 02:38:04 +00:00
}
else
{
2019-12-25 19:22:01 +00:00
v [ 3 ] . t = v [ 2 ] . t - = ( ( float ) angle / angleturn ) ;
v [ 0 ] . t = v [ 1 ] . t - = ( ( float ) angle / angleturn ) ;
2019-09-18 02:38:04 +00:00
}
2019-12-25 19:22:01 +00:00
HWD . pfnSetShader ( 7 ) ; // sky shader
2019-09-18 02:38:04 +00:00
HWD . pfnDrawPolygon ( NULL , v , 4 , 0 ) ;
2019-12-25 19:22:01 +00:00
HWD . pfnSetShader ( 0 ) ;
2019-09-18 02:38:04 +00:00
}
2014-03-15 16:59:03 +00:00
}
// -----------------+
// HWR_ClearView : clear the viewwindow, with maximum z value
// -----------------+
static inline void HWR_ClearView ( void )
{
// 3--2
// | /|
// |/ |
// 0--1
/// \bug faB - enable depth mask, disable color mask
HWD . pfnGClipRect ( ( INT32 ) gr_viewwindowx ,
( INT32 ) gr_viewwindowy ,
( INT32 ) ( gr_viewwindowx + gr_viewwidth ) ,
( INT32 ) ( gr_viewwindowy + gr_viewheight ) ,
2018-03-06 03:48:15 +00:00
ZCLIP_PLANE ) ;
2014-03-15 16:59:03 +00:00
HWD . pfnClearBuffer ( false , true , 0 ) ;
//disable clip window - set to full size
// rem by Hurdler
// HWD.pfnGClipRect(0, 0, vid.width, vid.height);
}
// -----------------+
// HWR_SetViewSize : set projection and scaling values
// -----------------+
void HWR_SetViewSize ( void )
{
// setup view size
gr_viewwidth = ( float ) vid . width ;
gr_viewheight = ( float ) vid . height ;
if ( splitscreen )
gr_viewheight / = 2 ;
gr_centerx = gr_viewwidth / 2 ;
gr_basecentery = gr_viewheight / 2 ; //note: this is (gr_centerx * gr_viewheight / gr_viewwidth)
gr_viewwindowx = ( vid . width - gr_viewwidth ) / 2 ;
gr_windowcenterx = ( float ) ( vid . width / 2 ) ;
2018-12-15 00:33:40 +00:00
if ( fabsf ( gr_viewwidth - vid . width ) < 1.0E-36 f )
2014-03-15 16:59:03 +00:00
{
gr_baseviewwindowy = 0 ;
gr_basewindowcentery = gr_viewheight / 2 ; // window top left corner at 0,0
}
else
{
gr_baseviewwindowy = ( vid . height - gr_viewheight ) / 2 ;
gr_basewindowcentery = ( float ) ( vid . height / 2 ) ;
}
gr_pspritexscale = gr_viewwidth / BASEVIDWIDTH ;
gr_pspriteyscale = ( ( vid . height * gr_pspritexscale * BASEVIDWIDTH ) / BASEVIDHEIGHT ) / vid . width ;
2018-03-07 05:19:06 +00:00
HWD . pfnFlushScreenTextures ( ) ;
2014-03-15 16:59:03 +00:00
}
2020-01-23 22:44:46 +00:00
// Set view aiming, for the sky dome, the skybox,
// and the normal view, all with a single function.
2020-02-08 20:42:26 +00:00
static void HWR_SetTransformAiming ( FTransform * trans , player_t * player , boolean skybox )
2020-01-23 22:44:46 +00:00
{
2020-02-08 20:42:26 +00:00
// 1 = always on
// 2 = chasecam only
2020-02-08 21:08:56 +00:00
if ( cv_grshearing . value = = 1 | | ( cv_grshearing . value = = 2 & & R_IsViewpointThirdPerson ( player , skybox ) ) )
2020-01-23 22:44:46 +00:00
{
fixed_t fixedaiming = AIMINGTODY ( aimingangle ) ;
trans - > viewaiming = FIXED_TO_FLOAT ( fixedaiming ) ;
trans - > shearing = true ;
gr_aimingangle = 0 ;
}
else
{
trans - > shearing = false ;
gr_aimingangle = aimingangle ;
}
2020-02-08 20:42:26 +00:00
2020-01-23 22:44:46 +00:00
trans - > anglex = ( float ) ( gr_aimingangle > > ANGLETOFINESHIFT ) * ( 360.0f / ( float ) FINEANGLES ) ;
}
2014-03-20 20:13:15 +00:00
// ==========================================================================
// Same as rendering the player view, but from the skybox object
// ==========================================================================
void HWR_RenderSkyboxView ( INT32 viewnumber , player_t * player )
{
2019-12-31 17:21:46 +00:00
const float fpov = FIXED_TO_FLOAT ( cv_fov . value + player - > fovadd ) ;
2014-08-27 03:56:30 +00:00
postimg_t * type ;
if ( splitscreen & & player = = & players [ secondarydisplayplayer ] )
type = & postimgtype2 ;
else
type = & postimgtype ;
2014-03-20 20:13:15 +00:00
{
// do we really need to save player (is it not the same)?
player_t * saved_player = stplyr ;
stplyr = player ;
ST_doPaletteStuff ( ) ;
stplyr = saved_player ;
# ifdef ALAM_LIGHTING
HWR_SetLights ( viewnumber ) ;
# endif
}
// note: sets viewangle, viewx, viewy, viewz
R_SkyboxFrame ( player ) ;
// copy view cam position for local use
dup_viewx = viewx ;
dup_viewy = viewy ;
dup_viewz = viewz ;
dup_viewangle = viewangle ;
// set window position
gr_centery = gr_basecentery ;
gr_viewwindowy = gr_baseviewwindowy ;
gr_windowcentery = gr_basewindowcentery ;
if ( splitscreen & & viewnumber = = 1 )
{
gr_viewwindowy + = ( vid . height / 2 ) ;
gr_windowcentery + = ( vid . height / 2 ) ;
}
// check for new console commands.
NetUpdate ( ) ;
gr_viewx = FIXED_TO_FLOAT ( dup_viewx ) ;
gr_viewy = FIXED_TO_FLOAT ( dup_viewy ) ;
gr_viewz = FIXED_TO_FLOAT ( dup_viewz ) ;
gr_viewsin = FIXED_TO_FLOAT ( viewsin ) ;
gr_viewcos = FIXED_TO_FLOAT ( viewcos ) ;
//04/01/2000: Hurdler: added for T&L
// It should replace all other gr_viewxxx when finished
2019-12-08 02:55:28 +00:00
memset ( & atransform , 0x00 , sizeof ( FTransform ) ) ;
2020-02-08 20:42:26 +00:00
HWR_SetTransformAiming ( & atransform , player , true ) ;
2014-03-20 20:13:15 +00:00
atransform . angley = ( float ) ( viewangle > > ANGLETOFINESHIFT ) * ( 360.0f / ( float ) FINEANGLES ) ;
2014-04-07 16:08:04 +00:00
2020-01-23 22:44:46 +00:00
gr_viewludsin = FIXED_TO_FLOAT ( FINECOSINE ( gr_aimingangle > > ANGLETOFINESHIFT ) ) ;
gr_viewludcos = FIXED_TO_FLOAT ( - FINESINE ( gr_aimingangle > > ANGLETOFINESHIFT ) ) ;
2014-08-27 03:56:30 +00:00
if ( * type = = postimg_flip )
2014-04-07 16:08:04 +00:00
atransform . flip = true ;
else
atransform . flip = false ;
2014-03-20 20:13:15 +00:00
atransform . x = gr_viewx ; // FIXED_TO_FLOAT(viewx)
atransform . y = gr_viewy ; // FIXED_TO_FLOAT(viewy)
atransform . z = gr_viewz ; // FIXED_TO_FLOAT(viewz)
atransform . scalex = 1 ;
2018-03-22 01:10:53 +00:00
atransform . scaley = ( float ) vid . width / vid . height ;
2014-03-20 20:13:15 +00:00
atransform . scalez = 1 ;
2019-12-25 19:22:01 +00:00
2014-03-20 20:13:15 +00:00
atransform . fovxangle = fpov ; // Tails
atransform . fovyangle = fpov ; // Tails
2020-01-18 03:55:16 +00:00
if ( player - > viewrollangle ! = 0 )
{
fixed_t rol = AngleFixed ( player - > viewrollangle ) ;
atransform . rollangle = FIXED_TO_FLOAT ( rol ) ;
atransform . roll = true ;
}
2014-03-20 20:13:15 +00:00
atransform . splitscreen = splitscreen ;
gr_fovlud = ( float ) ( 1.0 l / tan ( ( double ) ( fpov * M_PIl / 360l ) ) ) ;
//------------------------------------------------------------------------
HWR_ClearView ( ) ;
if ( drawsky )
2019-09-18 02:38:04 +00:00
HWR_DrawSkyBackground ( player ) ;
2014-03-20 20:13:15 +00:00
//Hurdler: it doesn't work in splitscreen mode
drawsky = splitscreen ;
HWR_ClearSprites ( ) ;
drawcount = 0 ;
2019-12-25 19:22:01 +00:00
2017-01-10 18:01:03 +00:00
# ifdef NEWCLIP
if ( rendermode = = render_opengl )
{
2019-12-25 19:22:01 +00:00
angle_t a1 = gld_FrustumAngle ( gr_aimingangle ) ;
2017-01-10 18:01:03 +00:00
gld_clipper_Clear ( ) ;
gld_clipper_SafeAddClipRange ( viewangle + a1 , viewangle - a1 ) ;
# ifdef HAVE_SPHEREFRUSTRUM
gld_FrustrumSetup ( ) ;
# endif
}
# else
2014-03-20 20:13:15 +00:00
HWR_ClearClipSegs ( ) ;
2017-01-10 18:01:03 +00:00
# endif
2014-03-20 20:13:15 +00:00
//04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes
HWD . pfnSetTransform ( & atransform ) ;
2019-12-25 19:22:01 +00:00
// Reset the shader state.
HWD . pfnSetSpecialState ( HWD_SET_SHADERS , cv_grshaders . value ) ;
HWD . pfnSetShader ( 0 ) ;
2014-03-20 20:13:15 +00:00
validcount + + ;
HWR_RenderBSPNode ( ( INT32 ) numnodes - 1 ) ;
2017-01-10 18:01:03 +00:00
# ifndef NEWCLIP
2014-03-20 20:13:15 +00:00
// Make a viewangle int so we can render things based on mouselook
if ( player = = & players [ consoleplayer ] )
viewangle = localaiming ;
else if ( splitscreen & & player = = & players [ secondarydisplayplayer ] )
viewangle = localaiming2 ;
// Handle stuff when you are looking farther up or down.
2020-01-23 22:44:46 +00:00
if ( ( gr_aimingangle | | cv_fov . value + player - > fovadd > 90 * FRACUNIT ) )
2014-03-20 20:13:15 +00:00
{
dup_viewangle + = ANGLE_90 ;
HWR_ClearClipSegs ( ) ;
HWR_RenderBSPNode ( ( INT32 ) numnodes - 1 ) ; //left
dup_viewangle + = ANGLE_90 ;
2020-01-23 22:44:46 +00:00
if ( ( ( INT32 ) gr_aimingangle > ANGLE_45 | | ( INT32 ) gr_aimingangle < - ANGLE_45 ) )
2014-03-20 20:13:15 +00:00
{
HWR_ClearClipSegs ( ) ;
HWR_RenderBSPNode ( ( INT32 ) numnodes - 1 ) ; //back
}
dup_viewangle + = ANGLE_90 ;
HWR_ClearClipSegs ( ) ;
HWR_RenderBSPNode ( ( INT32 ) numnodes - 1 ) ; //right
dup_viewangle + = ANGLE_90 ;
}
2017-01-10 18:01:03 +00:00
# endif
2014-03-20 20:13:15 +00:00
// Check for new console commands.
NetUpdate ( ) ;
# ifdef ALAM_LIGHTING
//14/11/99: Hurdler: moved here because it doesn't work with
// subsector, see other comments;
HWR_ResetLights ( ) ;
# endif
// Draw MD2 and sprites
HWR_SortVisSprites ( ) ;
HWR_DrawSprites ( ) ;
2019-12-25 19:22:01 +00:00
2014-03-20 20:13:15 +00:00
# ifdef NEWCORONAS
//Hurdler: they must be drawn before translucent planes, what about gl fog?
HWR_DrawCoronas ( ) ;
# endif
2014-10-27 20:57:45 +00:00
if ( numplanes | | numpolyplanes | | numwalls ) //Hurdler: render 3D water and transparent walls after everything
2014-03-20 20:13:15 +00:00
{
HWR_CreateDrawNodes ( ) ;
}
HWD . pfnSetTransform ( NULL ) ;
2019-12-25 19:22:01 +00:00
HWD . pfnUnSetShader ( ) ;
2014-03-20 20:13:15 +00:00
// Check for new console commands.
NetUpdate ( ) ;
// added by Hurdler for correct splitscreen
// moved here by hurdler so it works with the new near clipping plane
HWD . pfnGClipRect ( 0 , 0 , vid . width , vid . height , NZCLIP_PLANE ) ;
}
2014-03-15 16:59:03 +00:00
// ==========================================================================
//
// ==========================================================================
void HWR_RenderPlayerView ( INT32 viewnumber , player_t * player )
{
2019-12-31 17:21:46 +00:00
const float fpov = FIXED_TO_FLOAT ( cv_fov . value + player - > fovadd ) ;
2014-08-27 03:56:30 +00:00
postimg_t * type ;
2014-03-15 16:59:03 +00:00
2014-03-20 20:13:15 +00:00
const boolean skybox = ( skyboxmo [ 0 ] & & cv_skybox . value ) ; // True if there's a skybox object and skyboxes are on
2014-03-22 17:17:40 +00:00
FRGBAFloat ClearColor ;
2014-08-27 03:56:30 +00:00
if ( splitscreen & & player = = & players [ secondarydisplayplayer ] )
type = & postimgtype2 ;
else
type = & postimgtype ;
2014-03-22 17:17:40 +00:00
ClearColor . red = 0.0f ;
ClearColor . green = 0.0f ;
ClearColor . blue = 0.0f ;
ClearColor . alpha = 1.0f ;
2020-01-24 00:25:54 +00:00
if ( cv_grshaders . value )
HWD . pfnSetShaderInfo ( HWD_SHADERINFO_LEVELTIME , ( INT32 ) leveltime ) ; // The water surface shader needs the leveltime.
2014-03-30 23:07:55 +00:00
if ( viewnumber = = 0 ) // Only do it if it's the first screen being rendered
HWD . pfnClearBuffer ( true , false , & ClearColor ) ; // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs.
2014-03-22 17:17:40 +00:00
2014-03-20 20:13:15 +00:00
if ( skybox & & drawsky ) // If there's a skybox and we should be drawing the sky, draw the skybox
HWR_RenderSkyboxView ( viewnumber , player ) ; // This is drawn before everything else so it is placed behind
2014-03-15 16:59:03 +00:00
{
// do we really need to save player (is it not the same)?
player_t * saved_player = stplyr ;
stplyr = player ;
ST_doPaletteStuff ( ) ;
stplyr = saved_player ;
# ifdef ALAM_LIGHTING
HWR_SetLights ( viewnumber ) ;
# endif
}
// note: sets viewangle, viewx, viewy, viewz
2019-06-01 19:26:25 +00:00
R_SetupFrame ( player ) ;
2018-12-28 04:05:06 +00:00
framecount + + ; // timedemo
2014-03-15 16:59:03 +00:00
// copy view cam position for local use
dup_viewx = viewx ;
dup_viewy = viewy ;
dup_viewz = viewz ;
dup_viewangle = viewangle ;
// set window position
gr_centery = gr_basecentery ;
gr_viewwindowy = gr_baseviewwindowy ;
gr_windowcentery = gr_basewindowcentery ;
if ( splitscreen & & viewnumber = = 1 )
{
gr_viewwindowy + = ( vid . height / 2 ) ;
gr_windowcentery + = ( vid . height / 2 ) ;
}
// check for new console commands.
NetUpdate ( ) ;
gr_viewx = FIXED_TO_FLOAT ( dup_viewx ) ;
gr_viewy = FIXED_TO_FLOAT ( dup_viewy ) ;
gr_viewz = FIXED_TO_FLOAT ( dup_viewz ) ;
gr_viewsin = FIXED_TO_FLOAT ( viewsin ) ;
gr_viewcos = FIXED_TO_FLOAT ( viewcos ) ;
//04/01/2000: Hurdler: added for T&L
// It should replace all other gr_viewxxx when finished
2019-12-08 02:55:28 +00:00
memset ( & atransform , 0x00 , sizeof ( FTransform ) ) ;
2020-02-08 20:42:26 +00:00
HWR_SetTransformAiming ( & atransform , player , false ) ;
2014-03-15 16:59:03 +00:00
atransform . angley = ( float ) ( viewangle > > ANGLETOFINESHIFT ) * ( 360.0f / ( float ) FINEANGLES ) ;
2014-04-07 16:08:04 +00:00
2020-01-23 22:44:46 +00:00
gr_viewludsin = FIXED_TO_FLOAT ( FINECOSINE ( gr_aimingangle > > ANGLETOFINESHIFT ) ) ;
gr_viewludcos = FIXED_TO_FLOAT ( - FINESINE ( gr_aimingangle > > ANGLETOFINESHIFT ) ) ;
2014-08-27 03:56:30 +00:00
if ( * type = = postimg_flip )
2014-04-07 16:08:04 +00:00
atransform . flip = true ;
else
atransform . flip = false ;
2014-03-15 16:59:03 +00:00
atransform . x = gr_viewx ; // FIXED_TO_FLOAT(viewx)
atransform . y = gr_viewy ; // FIXED_TO_FLOAT(viewy)
atransform . z = gr_viewz ; // FIXED_TO_FLOAT(viewz)
atransform . scalex = 1 ;
2018-03-22 01:10:53 +00:00
atransform . scaley = ( float ) vid . width / vid . height ;
2014-03-15 16:59:03 +00:00
atransform . scalez = 1 ;
2019-12-25 19:22:01 +00:00
2014-03-15 16:59:03 +00:00
atransform . fovxangle = fpov ; // Tails
atransform . fovyangle = fpov ; // Tails
2020-01-18 03:55:16 +00:00
if ( player - > viewrollangle ! = 0 )
{
fixed_t rol = AngleFixed ( player - > viewrollangle ) ;
atransform . rollangle = FIXED_TO_FLOAT ( rol ) ;
atransform . roll = true ;
}
2014-03-15 16:59:03 +00:00
atransform . splitscreen = splitscreen ;
gr_fovlud = ( float ) ( 1.0 l / tan ( ( double ) ( fpov * M_PIl / 360l ) ) ) ;
//------------------------------------------------------------------------
2014-03-22 17:17:40 +00:00
HWR_ClearView ( ) ; // Clears the depth buffer and resets the view I believe
2014-03-15 16:59:03 +00:00
2014-03-20 20:13:15 +00:00
if ( ! skybox & & drawsky ) // Don't draw the regular sky if there's a skybox
2019-09-18 02:38:04 +00:00
HWR_DrawSkyBackground ( player ) ;
2014-03-15 16:59:03 +00:00
//Hurdler: it doesn't work in splitscreen mode
drawsky = splitscreen ;
HWR_ClearSprites ( ) ;
drawcount = 0 ;
2019-12-25 19:22:01 +00:00
2017-01-10 18:01:03 +00:00
# ifdef NEWCLIP
if ( rendermode = = render_opengl )
{
2019-12-25 19:22:01 +00:00
angle_t a1 = gld_FrustumAngle ( gr_aimingangle ) ;
2017-01-10 18:01:03 +00:00
gld_clipper_Clear ( ) ;
gld_clipper_SafeAddClipRange ( viewangle + a1 , viewangle - a1 ) ;
# ifdef HAVE_SPHEREFRUSTRUM
gld_FrustrumSetup ( ) ;
# endif
}
# else
2014-03-15 16:59:03 +00:00
HWR_ClearClipSegs ( ) ;
2017-01-10 18:01:03 +00:00
# endif
2014-03-15 16:59:03 +00:00
//04/01/2000: Hurdler: added for T&L
// Actually it only works on Walls and Planes
HWD . pfnSetTransform ( & atransform ) ;
2019-12-25 19:22:01 +00:00
// Reset the shader state.
HWD . pfnSetSpecialState ( HWD_SET_SHADERS , cv_grshaders . value ) ;
HWD . pfnSetShader ( 0 ) ;
2020-04-18 22:25:28 +00:00
rs_numbspcalls = 0 ;
rs_numpolyobjects = 0 ;
rs_bsptime = I_GetTimeMicros ( ) ;
2014-03-15 16:59:03 +00:00
validcount + + ;
HWR_RenderBSPNode ( ( INT32 ) numnodes - 1 ) ;
2017-01-10 18:01:03 +00:00
# ifndef NEWCLIP
2014-03-15 16:59:03 +00:00
// Make a viewangle int so we can render things based on mouselook
if ( player = = & players [ consoleplayer ] )
viewangle = localaiming ;
else if ( splitscreen & & player = = & players [ secondarydisplayplayer ] )
viewangle = localaiming2 ;
// Handle stuff when you are looking farther up or down.
2020-01-23 22:44:46 +00:00
if ( ( gr_aimingangle | | cv_fov . value + player - > fovadd > 90 * FRACUNIT ) )
2014-03-15 16:59:03 +00:00
{
dup_viewangle + = ANGLE_90 ;
HWR_ClearClipSegs ( ) ;
HWR_RenderBSPNode ( ( INT32 ) numnodes - 1 ) ; //left
dup_viewangle + = ANGLE_90 ;
2020-01-23 22:44:46 +00:00
if ( ( ( INT32 ) gr_aimingangle > ANGLE_45 | | ( INT32 ) gr_aimingangle < - ANGLE_45 ) )
2014-03-15 16:59:03 +00:00
{
HWR_ClearClipSegs ( ) ;
HWR_RenderBSPNode ( ( INT32 ) numnodes - 1 ) ; //back
}
dup_viewangle + = ANGLE_90 ;
HWR_ClearClipSegs ( ) ;
HWR_RenderBSPNode ( ( INT32 ) numnodes - 1 ) ; //right
dup_viewangle + = ANGLE_90 ;
}
2017-01-10 18:01:03 +00:00
# endif
2014-03-15 16:59:03 +00:00
2020-04-18 22:25:28 +00:00
rs_bsptime = I_GetTimeMicros ( ) - rs_bsptime ;
2014-03-15 16:59:03 +00:00
// Check for new console commands.
NetUpdate ( ) ;
# ifdef ALAM_LIGHTING
//14/11/99: Hurdler: moved here because it doesn't work with
// subsector, see other comments;
HWR_ResetLights ( ) ;
# endif
// Draw MD2 and sprites
2020-04-18 22:25:28 +00:00
rs_numsprites = gr_visspritecount ;
rs_spritesorttime = I_GetTimeMicros ( ) ;
2014-03-15 16:59:03 +00:00
HWR_SortVisSprites ( ) ;
2020-04-18 22:25:28 +00:00
rs_spritesorttime = I_GetTimeMicros ( ) - rs_spritesorttime ;
rs_spritedrawtime = I_GetTimeMicros ( ) ;
2014-03-15 16:59:03 +00:00
HWR_DrawSprites ( ) ;
2020-04-18 22:25:28 +00:00
rs_spritedrawtime = I_GetTimeMicros ( ) - rs_spritedrawtime ;
2019-12-25 19:22:01 +00:00
2014-03-15 16:59:03 +00:00
# ifdef NEWCORONAS
//Hurdler: they must be drawn before translucent planes, what about gl fog?
HWR_DrawCoronas ( ) ;
# endif
2020-04-18 22:25:28 +00:00
rs_numdrawnodes = 0 ;
rs_nodesorttime = 0 ;
rs_nodedrawtime = 0 ;
2014-10-27 20:57:45 +00:00
if ( numplanes | | numpolyplanes | | numwalls ) //Hurdler: render 3D water and transparent walls after everything
2014-03-15 16:59:03 +00:00
{
HWR_CreateDrawNodes ( ) ;
}
HWD . pfnSetTransform ( NULL ) ;
2019-12-25 19:22:01 +00:00
HWD . pfnUnSetShader ( ) ;
2014-03-15 16:59:03 +00:00
HWR_DoPostProcessor ( player ) ;
// Check for new console commands.
NetUpdate ( ) ;
// added by Hurdler for correct splitscreen
// moved here by hurdler so it works with the new near clipping plane
HWD . pfnGClipRect ( 0 , 0 , vid . width , vid . height , NZCLIP_PLANE ) ;
}
// ==========================================================================
// 3D ENGINE COMMANDS
// ==========================================================================
2019-12-12 20:30:19 +00:00
static CV_PossibleValue_t grmodelinterpolation_cons_t [ ] = { { 0 , " Off " } , { 1 , " Sometimes " } , { 2 , " Always " } , { 0 , NULL } } ;
2019-12-26 01:09:31 +00:00
static CV_PossibleValue_t grfakecontrast_cons_t [ ] = { { 0 , " Off " } , { 1 , " On " } , { 2 , " Smooth " } , { 0 , NULL } } ;
2020-02-08 20:42:26 +00:00
static CV_PossibleValue_t grshearing_cons_t [ ] = { { 0 , " Off " } , { 1 , " On " } , { 2 , " Third-person " } , { 0 , NULL } } ;
2019-12-12 20:30:19 +00:00
static void CV_grfiltermode_OnChange ( void ) ;
static void CV_granisotropic_OnChange ( void ) ;
static CV_PossibleValue_t grfiltermode_cons_t [ ] = { { HWD_SET_TEXTUREFILTER_POINTSAMPLED , " Nearest " } ,
{ HWD_SET_TEXTUREFILTER_BILINEAR , " Bilinear " } , { HWD_SET_TEXTUREFILTER_TRILINEAR , " Trilinear " } ,
{ HWD_SET_TEXTUREFILTER_MIXED1 , " Linear_Nearest " } ,
{ HWD_SET_TEXTUREFILTER_MIXED2 , " Nearest_Linear " } ,
{ HWD_SET_TEXTUREFILTER_MIXED3 , " Nearest_Mipmap " } ,
{ 0 , NULL } } ;
CV_PossibleValue_t granisotropicmode_cons_t [ ] = { { 1 , " MIN " } , { 16 , " MAX " } , { 0 , NULL } } ;
2019-12-25 19:22:01 +00:00
consvar_t cv_grshaders = { " gr_shaders " , " On " , CV_SAVE , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2019-12-31 17:21:46 +00:00
consvar_t cv_fovchange = { " gr_fovchange " , " Off " , CV_SAVE , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2019-12-12 20:30:19 +00:00
# ifdef ALAM_LIGHTING
consvar_t cv_grdynamiclighting = { " gr_dynamiclighting " , " On " , CV_SAVE , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
consvar_t cv_grstaticlighting = { " gr_staticlighting " , " On " , CV_SAVE , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
consvar_t cv_grcoronas = { " gr_coronas " , " On " , CV_SAVE , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2019-12-12 20:37:55 +00:00
consvar_t cv_grcoronasize = { " gr_coronasize " , " 1 " , CV_SAVE | CV_FLOAT , 0 , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2019-12-12 20:30:19 +00:00
# endif
consvar_t cv_grmodels = { " gr_models " , " Off " , CV_SAVE , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
consvar_t cv_grmodelinterpolation = { " gr_modelinterpolation " , " Sometimes " , CV_SAVE , grmodelinterpolation_cons_t , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2020-01-24 01:02:18 +00:00
consvar_t cv_grmodellighting = { " gr_modellighting " , " Off " , CV_SAVE , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2019-12-12 20:30:19 +00:00
2020-02-17 15:30:02 +00:00
consvar_t cv_grshearing = { " gr_shearing " , " Off " , CV_SAVE , grshearing_cons_t , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2019-12-13 00:52:59 +00:00
consvar_t cv_grspritebillboarding = { " gr_spritebillboarding " , " Off " , CV_SAVE , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2019-12-12 20:30:19 +00:00
consvar_t cv_grskydome = { " gr_skydome " , " On " , CV_SAVE , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2019-12-26 01:09:31 +00:00
consvar_t cv_grfakecontrast = { " gr_fakecontrast " , " Smooth " , CV_SAVE , grfakecontrast_cons_t , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2020-01-16 21:45:49 +00:00
consvar_t cv_grslopecontrast = { " gr_slopecontrast " , " Off " , CV_SAVE , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2019-12-12 20:30:19 +00:00
2019-12-12 20:37:55 +00:00
consvar_t cv_grfiltermode = { " gr_filtermode " , " Nearest " , CV_SAVE | CV_CALL , grfiltermode_cons_t ,
2019-12-12 20:30:19 +00:00
CV_grfiltermode_OnChange , 0 , NULL , NULL , 0 , 0 , NULL } ;
2019-12-12 21:28:05 +00:00
consvar_t cv_granisotropicmode = { " gr_anisotropicmode " , " 1 " , CV_CALL , granisotropicmode_cons_t ,
2019-12-12 20:30:19 +00:00
CV_granisotropic_OnChange , 0 , NULL , NULL , 0 , 0 , NULL } ;
consvar_t cv_grcorrecttricks = { " gr_correcttricks " , " Off " , 0 , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
consvar_t cv_grsolvetjoin = { " gr_solvetjoin " , " On " , 0 , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2020-04-18 22:25:28 +00:00
// render stats
// for now have it in here in the hw code
// could have it somewhere else since renderstats could also be a software rendering thing
consvar_t cv_renderstats = { " renderstats " , " Off " , 0 , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2019-12-12 20:30:19 +00:00
static void CV_grfiltermode_OnChange ( void )
{
if ( rendermode = = render_opengl )
HWD . pfnSetSpecialState ( HWD_SET_TEXTUREFILTERMODE , cv_grfiltermode . value ) ;
}
static void CV_granisotropic_OnChange ( void )
{
if ( rendermode = = render_opengl )
HWD . pfnSetSpecialState ( HWD_SET_TEXTUREANISOTROPICMODE , cv_granisotropicmode . value ) ;
}
2014-03-15 16:59:03 +00:00
//added by Hurdler: console varibale that are saved
void HWR_AddCommands ( void )
{
2019-12-31 17:21:46 +00:00
CV_RegisterVar ( & cv_fovchange ) ;
2019-12-12 20:30:19 +00:00
# ifdef ALAM_LIGHTING
CV_RegisterVar ( & cv_grstaticlighting ) ;
CV_RegisterVar ( & cv_grdynamiclighting ) ;
CV_RegisterVar ( & cv_grcoronasize ) ;
CV_RegisterVar ( & cv_grcoronas ) ;
# endif
2019-12-12 20:48:29 +00:00
CV_RegisterVar ( & cv_grmodellighting ) ;
2019-12-12 20:30:19 +00:00
CV_RegisterVar ( & cv_grmodelinterpolation ) ;
CV_RegisterVar ( & cv_grmodels ) ;
2019-12-12 20:48:29 +00:00
2019-12-12 20:30:19 +00:00
CV_RegisterVar ( & cv_grskydome ) ;
CV_RegisterVar ( & cv_grspritebillboarding ) ;
2019-12-26 01:09:31 +00:00
CV_RegisterVar ( & cv_grfakecontrast ) ;
2019-12-25 19:22:01 +00:00
CV_RegisterVar ( & cv_grshearing ) ;
CV_RegisterVar ( & cv_grshaders ) ;
2014-03-15 16:59:03 +00:00
CV_RegisterVar ( & cv_grfiltermode ) ;
CV_RegisterVar ( & cv_grcorrecttricks ) ;
CV_RegisterVar ( & cv_grsolvetjoin ) ;
2020-04-18 22:25:28 +00:00
CV_RegisterVar ( & cv_renderstats ) ;
2014-03-15 16:59:03 +00:00
2017-01-10 18:01:03 +00:00
# ifndef NEWCLIP
2014-03-15 16:59:03 +00:00
CV_RegisterVar ( & cv_grclipwalls ) ;
2017-01-10 18:01:03 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
2019-12-12 21:28:05 +00:00
void HWR_AddSessionCommands ( void )
{
2019-12-17 19:12:44 +00:00
static boolean alreadycalled = false ;
if ( alreadycalled )
return ;
2014-03-15 16:59:03 +00:00
2019-12-12 21:28:05 +00:00
CV_RegisterVar ( & cv_granisotropicmode ) ;
2014-03-15 16:59:03 +00:00
2019-12-17 19:12:44 +00:00
alreadycalled = true ;
2019-12-12 21:28:05 +00:00
}
2014-03-15 16:59:03 +00:00
// --------------------------------------------------------------------------
// Setup the hardware renderer
// --------------------------------------------------------------------------
void HWR_Startup ( void )
{
static boolean startupdone = false ;
// do this once
if ( ! startupdone )
{
2020-01-27 05:15:34 +00:00
INT32 i ;
2019-11-05 13:28:19 +00:00
CONS_Printf ( " HWR_Startup()... \n " ) ;
2020-01-27 05:15:34 +00:00
2014-03-15 16:59:03 +00:00
HWR_InitPolyPool ( ) ;
2019-12-12 21:28:05 +00:00
HWR_AddSessionCommands ( ) ;
2014-03-15 16:59:03 +00:00
HWR_InitTextureCache ( ) ;
2019-11-05 13:28:19 +00:00
HWR_InitModels ( ) ;
2014-03-15 16:59:03 +00:00
# ifdef ALAM_LIGHTING
HWR_InitLight ( ) ;
# endif
2020-01-27 05:15:34 +00:00
// read every custom shader
for ( i = 0 ; i < numwadfiles ; i + + )
HWR_ReadShaders ( i , ( wadfiles [ i ] - > type = = RET_PK3 ) ) ;
HWR_LoadShaders ( ) ;
2014-03-15 16:59:03 +00:00
}
if ( rendermode = = render_opengl )
2017-09-29 21:48:14 +00:00
textureformat = patchformat = GR_RGBA ;
2014-03-15 16:59:03 +00:00
startupdone = true ;
}
2019-12-17 19:12:44 +00:00
// --------------------------------------------------------------------------
// Called after switching to the hardware renderer
// --------------------------------------------------------------------------
void HWR_Switch ( void )
{
// Set special states from CVARs
HWD . pfnSetSpecialState ( HWD_SET_TEXTUREFILTERMODE , cv_grfiltermode . value ) ;
HWD . pfnSetSpecialState ( HWD_SET_TEXTUREANISOTROPICMODE , cv_granisotropicmode . value ) ;
}
2014-03-15 16:59:03 +00:00
// --------------------------------------------------------------------------
// Free resources allocated by the hardware renderer
// --------------------------------------------------------------------------
void HWR_Shutdown ( void )
{
CONS_Printf ( " HWR_Shutdown() \n " ) ;
HWR_FreeExtraSubsectors ( ) ;
HWR_FreePolyPool ( ) ;
HWR_FreeTextureCache ( ) ;
2018-03-07 05:19:06 +00:00
HWD . pfnFlushScreenTextures ( ) ;
2014-03-15 16:59:03 +00:00
}
void transform ( float * cx , float * cy , float * cz )
{
float tr_x , tr_y ;
// translation
tr_x = * cx - gr_viewx ;
tr_y = * cz - gr_viewy ;
// *cy = *cy;
// rotation around vertical y axis
* cx = ( tr_x * gr_viewsin ) - ( tr_y * gr_viewcos ) ;
tr_x = ( tr_x * gr_viewcos ) + ( tr_y * gr_viewsin ) ;
//look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
tr_y = * cy - gr_viewz ;
* cy = ( tr_x * gr_viewludcos ) + ( tr_y * gr_viewludsin ) ;
* cz = ( tr_x * gr_viewludsin ) - ( tr_y * gr_viewludcos ) ;
//scale y before frustum so that frustum can be scaled to screen height
* cy * = ORIGINAL_ASPECT * gr_fovlud ;
* cx * = gr_fovlud ;
}
2019-12-25 19:22:01 +00:00
void HWR_AddTransparentWall ( FOutVector * wallVerts , FSurfaceInfo * pSurf , INT32 texnum , FBITFIELD blend , boolean fogwall , INT32 lightlevel , extracolormap_t * wallcolormap )
2014-03-15 16:59:03 +00:00
{
static size_t allocedwalls = 0 ;
// Force realloc if buffer has been freed
if ( ! wallinfo )
allocedwalls = 0 ;
if ( allocedwalls < numwalls + 1 )
{
allocedwalls + = MAX_TRANSPARENTWALL ;
Z_Realloc ( wallinfo , allocedwalls * sizeof ( * wallinfo ) , PU_LEVEL , & wallinfo ) ;
}
M_Memcpy ( wallinfo [ numwalls ] . wallVerts , wallVerts , sizeof ( wallinfo [ numwalls ] . wallVerts ) ) ;
M_Memcpy ( & wallinfo [ numwalls ] . Surf , pSurf , sizeof ( FSurfaceInfo ) ) ;
wallinfo [ numwalls ] . texnum = texnum ;
wallinfo [ numwalls ] . blend = blend ;
wallinfo [ numwalls ] . drawcount = drawcount + + ;
wallinfo [ numwalls ] . fogwall = fogwall ;
wallinfo [ numwalls ] . lightlevel = lightlevel ;
wallinfo [ numwalls ] . wallcolormap = wallcolormap ;
numwalls + + ;
}
2019-11-09 02:42:15 +00:00
2019-12-25 19:22:01 +00:00
void HWR_RenderWall ( FOutVector * wallVerts , FSurfaceInfo * pSurf , FBITFIELD blend , boolean fogwall , INT32 lightlevel , extracolormap_t * wallcolormap )
2014-03-15 16:59:03 +00:00
{
2019-12-25 19:22:01 +00:00
FBITFIELD blendmode = blend ;
UINT8 alpha = pSurf - > PolyColor . s . alpha ; // retain the alpha
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
// Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting
HWR_Lighting ( pSurf , lightlevel , wallcolormap ) ;
2019-11-09 02:42:15 +00:00
2019-12-25 19:22:01 +00:00
pSurf - > PolyColor . s . alpha = alpha ; // put the alpha back after lighting
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
HWD . pfnSetShader ( 2 ) ; // wall shader
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
if ( blend & PF_Environment )
blendmode | = PF_Occlude ; // PF_Occlude must be used for solid objects
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
if ( fogwall )
2014-03-15 16:59:03 +00:00
{
2019-12-25 19:22:01 +00:00
blendmode | = PF_Fog ;
HWD . pfnSetShader ( 6 ) ; // fog shader
2014-03-15 16:59:03 +00:00
}
2019-12-25 19:22:01 +00:00
blendmode | = PF_Modulated ; // No PF_Occlude means overlapping (incorrect) transparency
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
HWD . pfnDrawPolygon ( pSurf , wallVerts , 4 , blendmode ) ;
2014-03-15 16:59:03 +00:00
# ifdef WALLSPLATS
if ( gr_curline - > linedef - > splats & & cv_splats . value )
HWR_DrawSegsSplats ( pSurf ) ;
# endif
}
INT32 HWR_GetTextureUsed ( void )
{
return HWD . pfnGetTextureUsed ( ) ;
}
void HWR_DoPostProcessor ( player_t * player )
{
2014-08-27 03:56:30 +00:00
postimg_t * type ;
2019-12-25 19:22:01 +00:00
HWD . pfnUnSetShader ( ) ;
2014-08-27 03:56:30 +00:00
if ( splitscreen & & player = = & players [ secondarydisplayplayer ] )
type = & postimgtype2 ;
else
type = & postimgtype ;
2014-03-15 16:59:03 +00:00
// Armageddon Blast Flash!
// Could this even be considered postprocessor?
if ( player - > flashcount )
{
FOutVector v [ 4 ] ;
FSurfaceInfo Surf ;
2014-03-23 00:04:35 +00:00
v [ 0 ] . x = v [ 2 ] . y = v [ 3 ] . x = v [ 3 ] . y = - 4.0f ;
v [ 0 ] . y = v [ 1 ] . x = v [ 1 ] . y = v [ 2 ] . x = 4.0f ;
v [ 0 ] . z = v [ 1 ] . z = v [ 2 ] . z = v [ 3 ] . z = 4.0f ; // 4.0 because of the same reason as with the sky, just after the screen is cleared so near clipping plane is 3.99
// This won't change if the flash palettes are changed unfortunately, but it works for its purpose
if ( player - > flashpal = = PAL_NUKE )
{
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . red = 0xff ;
Surf . PolyColor . s . green = Surf . PolyColor . s . blue = 0x7F ; // The nuke palette is kind of pink-ish
2014-03-23 00:04:35 +00:00
}
else
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . red = Surf . PolyColor . s . green = Surf . PolyColor . s . blue = 0xff ;
2014-03-15 16:59:03 +00:00
2019-12-25 19:22:01 +00:00
Surf . PolyColor . s . alpha = 0xc0 ; // match software mode
2014-03-15 16:59:03 +00:00
HWD . pfnDrawPolygon ( & Surf , v , 4 , PF_Modulated | PF_Additive | PF_NoTexture | PF_NoDepthTest | PF_Clip | PF_NoZClip ) ;
}
// Capture the screen for intermission and screen waving
if ( gamestate ! = GS_INTERMISSION )
HWD . pfnMakeScreenTexture ( ) ;
if ( splitscreen ) // Not supported in splitscreen - someone want to add support?
return ;
// Drunken vision! WooOOooo~
2014-08-27 03:56:30 +00:00
if ( * type = = postimg_water | | * type = = postimg_heat )
2014-03-15 16:59:03 +00:00
{
// 10 by 10 grid. 2 coordinates (xy)
float v [ SCREENVERTS ] [ SCREENVERTS ] [ 2 ] ;
static double disStart = 0 ;
UINT8 x , y ;
INT32 WAVELENGTH ;
INT32 AMPLITUDE ;
INT32 FREQUENCY ;
// Modifies the wave.
2014-08-27 03:56:30 +00:00
if ( * type = = postimg_water )
2014-03-15 16:59:03 +00:00
{
WAVELENGTH = 20 ; // Lower is longer
AMPLITUDE = 20 ; // Lower is bigger
FREQUENCY = 16 ; // Lower is faster
}
else
{
WAVELENGTH = 10 ; // Lower is longer
AMPLITUDE = 30 ; // Lower is bigger
FREQUENCY = 4 ; // Lower is faster
}
for ( x = 0 ; x < SCREENVERTS ; x + + )
{
for ( y = 0 ; y < SCREENVERTS ; y + + )
{
// Change X position based on its Y position.
v [ x ] [ y ] [ 0 ] = ( x / ( ( float ) ( SCREENVERTS - 1.0f ) / 9.0f ) ) - 4.5f + ( float ) sin ( ( disStart + ( y * WAVELENGTH ) ) / FREQUENCY ) / AMPLITUDE ;
v [ x ] [ y ] [ 1 ] = ( y / ( ( float ) ( SCREENVERTS - 1.0f ) / 9.0f ) ) - 4.5f ;
}
}
HWD . pfnPostImgRedraw ( v ) ;
2020-01-24 00:25:54 +00:00
if ( ! ( paused | | P_AutoPause ( ) ) )
disStart + = 1 ;
2014-03-15 16:59:03 +00:00
2014-04-07 16:08:04 +00:00
// Capture the screen again for screen waving on the intermission
if ( gamestate ! = GS_INTERMISSION )
HWD . pfnMakeScreenTexture ( ) ;
2014-03-15 16:59:03 +00:00
}
2014-04-07 16:08:04 +00:00
// Flipping of the screen isn't done here anymore
2014-03-15 16:59:03 +00:00
}
void HWR_StartScreenWipe ( void )
{
//CONS_Debug(DBG_RENDER, "In HWR_StartScreenWipe()\n");
HWD . pfnStartScreenWipe ( ) ;
}
void HWR_EndScreenWipe ( void )
{
//CONS_Debug(DBG_RENDER, "In HWR_EndScreenWipe()\n");
HWD . pfnEndScreenWipe ( ) ;
}
void HWR_DrawIntermissionBG ( void )
{
HWD . pfnDrawIntermissionBG ( ) ;
}
2019-11-05 15:10:42 +00:00
//
// hwr mode wipes
//
static lumpnum_t wipelumpnum ;
2019-11-15 22:40:58 +00:00
// puts wipe lumpname in wipename[9]
2019-11-05 15:31:50 +00:00
static boolean HWR_WipeCheck ( UINT8 wipenum , UINT8 scrnnum )
2014-03-15 16:59:03 +00:00
{
2019-11-15 22:40:58 +00:00
static char lumpname [ 9 ] = " FADEmmss " ;
2014-09-04 00:35:29 +00:00
size_t lsize ;
2019-11-05 15:10:42 +00:00
// not a valid wipe number
if ( wipenum > 99 | | scrnnum > 99 )
return false ; // shouldn't end up here really, the loop should've stopped running beforehand
2014-09-04 00:35:29 +00:00
2019-11-05 15:10:42 +00:00
// puts the numbers into the wipename
2019-11-15 22:40:58 +00:00
lumpname [ 4 ] = ' 0 ' + ( wipenum / 10 ) ;
lumpname [ 5 ] = ' 0 ' + ( wipenum % 10 ) ;
lumpname [ 6 ] = ' 0 ' + ( scrnnum / 10 ) ;
lumpname [ 7 ] = ' 0 ' + ( scrnnum % 10 ) ;
2019-11-15 22:09:02 +00:00
wipelumpnum = W_CheckNumForName ( lumpname ) ;
2014-09-04 00:35:29 +00:00
2019-11-05 15:10:42 +00:00
// again, shouldn't be here really
if ( wipelumpnum = = LUMPERROR )
return false ;
2014-09-04 00:35:29 +00:00
2019-11-05 15:10:42 +00:00
lsize = W_LumpLength ( wipelumpnum ) ;
2014-09-04 00:35:29 +00:00
if ( ! ( lsize = = 256000 | | lsize = = 64000 | | lsize = = 16000 | | lsize = = 4000 ) )
{
2019-11-15 22:09:02 +00:00
CONS_Alert ( CONS_WARNING , " Fade mask lump %s of incorrect size, ignored \n " , lumpname ) ;
2019-11-05 15:10:42 +00:00
return false ; // again, shouldn't get here if it is a bad size
2014-09-04 00:35:29 +00:00
}
2019-11-05 15:10:42 +00:00
return true ;
}
2014-03-15 16:59:03 +00:00
2019-11-05 15:10:42 +00:00
void HWR_DoWipe ( UINT8 wipenum , UINT8 scrnnum )
{
2019-11-05 15:31:50 +00:00
if ( ! HWR_WipeCheck ( wipenum , scrnnum ) )
2019-11-05 15:10:42 +00:00
return ;
HWR_GetFadeMask ( wipelumpnum ) ;
2018-12-27 20:23:33 +00:00
HWD . pfnDoScreenWipe ( ) ;
2014-03-15 16:59:03 +00:00
}
2019-11-05 15:10:42 +00:00
void HWR_DoTintedWipe ( UINT8 wipenum , UINT8 scrnnum )
2019-09-10 02:31:48 +00:00
{
2019-11-05 15:31:50 +00:00
// It does the same thing
HWR_DoWipe ( wipenum , scrnnum ) ;
2019-11-05 15:10:42 +00:00
}
2019-10-29 02:14:00 +00:00
2014-11-14 00:06:38 +00:00
void HWR_MakeScreenFinalTexture ( void )
{
HWD . pfnMakeScreenFinalTexture ( ) ;
}
void HWR_DrawScreenFinalTexture ( int width , int height )
{
HWD . pfnDrawScreenFinalTexture ( width , height ) ;
}
2019-12-25 19:22:01 +00:00
// jimita 18032019
typedef struct
{
char type [ 16 ] ;
INT32 id ;
} shaderxlat_t ;
static inline UINT16 HWR_CheckShader ( UINT16 wadnum )
{
UINT16 i ;
lumpinfo_t * lump_p ;
lump_p = wadfiles [ wadnum ] - > lumpinfo ;
for ( i = 0 ; i < wadfiles [ wadnum ] - > numlumps ; i + + , lump_p + + )
if ( memcmp ( lump_p - > name , " SHADERS " , 7 ) = = 0 )
return i ;
return INT16_MAX ;
}
2020-01-27 05:15:34 +00:00
void HWR_LoadShaders ( void )
{
HWD . pfnInitCustomShaders ( ) ;
}
void HWR_ReadShaders ( UINT16 wadnum , boolean PK3 )
2019-12-25 19:22:01 +00:00
{
UINT16 lump ;
char * shaderdef , * line ;
char * stoken ;
char * value ;
size_t size ;
int linenum = 1 ;
int shadertype = 0 ;
int i ;
# define SHADER_TYPES 7
shaderxlat_t shaderxlat [ SHADER_TYPES ] =
{
{ " Flat " , 1 } ,
{ " WallTexture " , 2 } ,
{ " Sprite " , 3 } ,
{ " Model " , 4 } ,
{ " WaterRipple " , 5 } ,
{ " Fog " , 6 } ,
{ " Sky " , 7 } ,
} ;
lump = HWR_CheckShader ( wadnum ) ;
if ( lump = = INT16_MAX )
return ;
shaderdef = W_CacheLumpNumPwad ( wadnum , lump , PU_CACHE ) ;
size = W_LumpLengthPwad ( wadnum , lump ) ;
line = Z_Malloc ( size + 1 , PU_STATIC , NULL ) ;
M_Memcpy ( line , shaderdef , size ) ;
line [ size ] = ' \0 ' ;
stoken = strtok ( line , " \r \n " ) ;
while ( stoken )
{
if ( ( stoken [ 0 ] = = ' / ' & & stoken [ 1 ] = = ' / ' )
| | ( stoken [ 0 ] = = ' # ' ) ) // skip comments
{
stoken = strtok ( NULL , " \r \n " ) ;
goto skip_field ;
}
if ( ! stricmp ( stoken , " GLSL " ) )
{
value = strtok ( NULL , " \r \n " ) ;
if ( ! value )
{
2020-01-27 05:15:34 +00:00
CONS_Alert ( CONS_WARNING , " HWR_ReadShaders: Missing shader type (file %s, line %d) \n " , wadfiles [ wadnum ] - > filename , linenum ) ;
2019-12-25 19:22:01 +00:00
stoken = strtok ( NULL , " \r \n " ) ; // skip end of line
goto skip_lump ;
}
if ( ! stricmp ( value , " VERTEX " ) )
shadertype = 1 ;
else if ( ! stricmp ( value , " FRAGMENT " ) )
shadertype = 2 ;
skip_lump :
stoken = strtok ( NULL , " \r \n " ) ;
linenum + + ;
}
else
{
value = strtok ( NULL , " \r \n = " ) ;
if ( ! value )
{
2020-01-27 05:15:34 +00:00
CONS_Alert ( CONS_WARNING , " HWR_ReadShaders: Missing shader target (file %s, line %d) \n " , wadfiles [ wadnum ] - > filename , linenum ) ;
2019-12-25 19:22:01 +00:00
stoken = strtok ( NULL , " \r \n " ) ; // skip end of line
goto skip_field ;
}
if ( ! shadertype )
{
2020-01-27 05:15:34 +00:00
CONS_Alert ( CONS_ERROR , " HWR_ReadShaders: Missing shader type (file %s, line %d) \n " , wadfiles [ wadnum ] - > filename , linenum ) ;
2019-12-25 19:22:01 +00:00
Z_Free ( line ) ;
return ;
}
for ( i = 0 ; i < SHADER_TYPES ; i + + )
{
if ( ! stricmp ( shaderxlat [ i ] . type , stoken ) )
{
size_t shader_size ;
char * shader_source ;
char * shader_lumpname ;
UINT16 shader_lumpnum ;
if ( PK3 )
{
shader_lumpname = Z_Malloc ( strlen ( value ) + 12 , PU_STATIC , NULL ) ;
strcpy ( shader_lumpname , " Shaders/sh_ " ) ;
strcat ( shader_lumpname , value ) ;
shader_lumpnum = W_CheckNumForFullNamePK3 ( shader_lumpname , wadnum , 0 ) ;
}
else
{
shader_lumpname = Z_Malloc ( strlen ( value ) + 4 , PU_STATIC , NULL ) ;
strcpy ( shader_lumpname , " SH_ " ) ;
strcat ( shader_lumpname , value ) ;
shader_lumpnum = W_CheckNumForNamePwad ( shader_lumpname , wadnum , 0 ) ;
}
if ( shader_lumpnum = = INT16_MAX )
{
2020-01-27 05:15:34 +00:00
CONS_Alert ( CONS_ERROR , " HWR_ReadShaders: Missing shader source %s (file %s, line %d) \n " , shader_lumpname , wadfiles [ wadnum ] - > filename , linenum ) ;
2019-12-25 19:22:01 +00:00
Z_Free ( shader_lumpname ) ;
continue ;
}
shader_size = W_LumpLengthPwad ( wadnum , shader_lumpnum ) ;
shader_source = Z_Malloc ( shader_size , PU_STATIC , NULL ) ;
W_ReadLumpPwad ( wadnum , shader_lumpnum , shader_source ) ;
HWD . pfnLoadCustomShader ( shaderxlat [ i ] . id , shader_source , shader_size , ( shadertype = = 2 ) ) ;
Z_Free ( shader_source ) ;
Z_Free ( shader_lumpname ) ;
}
}
skip_field :
stoken = strtok ( NULL , " \r \n = " ) ;
linenum + + ;
}
}
Z_Free ( line ) ;
return ;
}
2014-03-15 16:59:03 +00:00
# endif // HWRENDER