2014-03-15 16:59:03 +00:00
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
2023-03-31 12:53:31 +00:00
// Copyright (C) 1999-2023 by Sonic Team Junior.
2014-03-15 16:59:03 +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.
//-----------------------------------------------------------------------------
/// \file r_plane.c
/// \brief Here is a core component: drawing the floors and ceilings,
/// while maintaining a per column clipping list only.
/// Moreover, the sky areas have to be determined.
# include "doomdef.h"
# include "console.h"
2022-11-13 15:15:15 +00:00
# include "m_easing.h" // For Easing_InOutSine, used in R_UpdatePlaneRipple
2014-03-15 16:59:03 +00:00
# include "g_game.h"
2018-12-14 17:08:25 +00:00
# include "p_setup.h" // levelflats
# include "p_slopes.h"
2014-03-15 16:59:03 +00:00
# include "r_data.h"
2020-01-07 15:35:10 +00:00
# include "r_textures.h"
2014-03-15 16:59:03 +00:00
# include "r_local.h"
# include "r_state.h"
# include "r_splats.h" // faB(21jan):testing
# include "r_sky.h"
2019-06-01 19:26:25 +00:00
# include "r_portal.h"
2014-03-15 16:59:03 +00:00
# include "v_video.h"
# include "w_wad.h"
# include "z_zone.h"
# include "p_tick.h"
//
// opening
//
//SoM: 3/23/2000: Use Boom visplane hashing.
2019-06-07 11:10:12 +00:00
visplane_t * visplanes [ MAXVISPLANES ] ;
2014-03-15 16:59:03 +00:00
static visplane_t * freetail ;
static visplane_t * * freehead = & freetail ;
visplane_t * floorplane ;
visplane_t * ceilingplane ;
static visplane_t * currentplane ;
2018-12-14 17:08:25 +00:00
visffloor_t ffloor [ MAXFFLOORS ] ;
2014-03-15 16:59:03 +00:00
INT32 numffloors ;
//SoM: 3/23/2000: Boom visplane hashing routine.
# define visplane_hash(picnum,lightlevel,height) \
2020-10-17 11:35:28 +00:00
( ( unsigned ) ( ( picnum ) * 3 + ( lightlevel ) + ( height ) * 7 ) & VISPLANEHASHMASK )
2014-03-15 16:59:03 +00:00
//SoM: 3/23/2000: Use boom opening limit removal
size_t maxopenings ;
INT16 * openings , * lastopening ; /// \todo free leak
//
// Clip values are the solid pixel bounding the range.
// floorclip starts out SCREENHEIGHT
// ceilingclip starts out -1
//
INT16 floorclip [ MAXVIDWIDTH ] , ceilingclip [ MAXVIDWIDTH ] ;
fixed_t frontscale [ MAXVIDWIDTH ] ;
//
// spanstart holds the start of a plane span
// initialized to 0 at start
//
static INT32 spanstart [ MAXVIDHEIGHT ] ;
//
// texture mapping
//
2015-05-14 02:41:54 +00:00
lighttable_t * * planezlight ;
2014-03-15 16:59:03 +00:00
static fixed_t planeheight ;
//added : 10-02-98: yslopetab is what yslope used to be,
// yslope points somewhere into yslopetab,
// now (viewheight/2) slopes are calculated above and
// below the original viewheight for mouselook
// (this is to calculate yslopes only when really needed)
// (when mouselookin', yslope is moving into yslopetab)
// Check R_SetupFrame, R_SetViewSize for more...
2018-12-14 17:08:25 +00:00
fixed_t yslopetab [ MAXVIDHEIGHT * 16 ] ;
2014-03-15 16:59:03 +00:00
fixed_t * yslope ;
fixed_t cachedheight [ MAXVIDHEIGHT ] ;
fixed_t cacheddistance [ MAXVIDHEIGHT ] ;
fixed_t cachedxstep [ MAXVIDHEIGHT ] ;
fixed_t cachedystep [ MAXVIDHEIGHT ] ;
static fixed_t xoffs , yoffs ;
2021-04-14 13:55:52 +00:00
static floatv3_t ds_slope_origin , ds_slope_u , ds_slope_v ;
2014-03-15 16:59:03 +00:00
//
// R_InitPlanes
// Only at game startup.
//
void R_InitPlanes ( void )
{
// FIXME: unused
}
//
2020-11-05 03:00:08 +00:00
// Water ripple effect
2019-12-14 22:50:40 +00:00
// Needs the height of the plane, and the vertical position of the span.
2020-11-05 02:46:34 +00:00
// Sets planeripple.xfrac and planeripple.yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted.
2014-03-15 16:59:03 +00:00
//
2018-12-14 17:08:25 +00:00
2021-08-26 16:22:32 +00:00
static struct
2020-11-05 02:46:34 +00:00
{
INT32 offset ;
fixed_t xfrac , yfrac ;
boolean active ;
} planeripple ;
2019-12-11 15:36:54 +00:00
2021-04-27 22:01:09 +00:00
// ripples da water texture
static fixed_t R_CalculateRippleOffset ( INT32 y )
2019-12-11 15:36:54 +00:00
{
2021-04-27 22:01:09 +00:00
fixed_t distance = FixedMul ( planeheight , yslope [ y ] ) ;
2020-11-05 02:46:34 +00:00
const INT32 yay = ( planeripple . offset + ( distance > > 9 ) ) & 8191 ;
2021-04-27 22:01:09 +00:00
return FixedDiv ( FINESINE ( yay ) , ( 1 < < 12 ) + ( distance > > 11 ) ) ;
}
2020-11-05 02:46:34 +00:00
2021-04-27 22:01:09 +00:00
static void R_CalculatePlaneRipple ( angle_t angle )
{
angle > > = ANGLETOFINESHIFT ;
angle = ( angle + 2048 ) & 8191 ; // 90 degrees
planeripple . xfrac = FixedMul ( FINECOSINE ( angle ) , ds_bgofs ) ;
planeripple . yfrac = FixedMul ( FINESINE ( angle ) , ds_bgofs ) ;
2020-11-05 02:46:34 +00:00
}
static void R_UpdatePlaneRipple ( void )
{
2022-11-13 15:15:15 +00:00
// ds_waterofs oscillates between 0 and 16384 every other tic
// Now that frame interpolation is a thing, HOW does it oscillate?
// The difference between linear interpolation and a sine wave is miniscule here,
// but a sine wave is ever so slightly smoother and sleeker
ds_waterofs = Easing_InOutSine ( ( ( leveltime & 1 ) * FRACUNIT ) + rendertimefrac , 16384 , 0 ) ;
// Meanwhile, planeripple.offset just counts up, so it gets simple linear interpolation
planeripple . offset = ( ( leveltime - 1 ) * 140 ) + ( ( rendertimefrac * 140 ) / FRACUNIT ) ;
2019-12-11 15:36:54 +00:00
}
2014-03-15 16:59:03 +00:00
2021-04-27 22:01:09 +00:00
static void R_MapPlane ( INT32 y , INT32 x1 , INT32 x2 )
2014-03-15 16:59:03 +00:00
{
2018-12-14 17:08:25 +00:00
angle_t angle , planecos , planesin ;
2020-11-05 02:46:34 +00:00
fixed_t distance = 0 , span ;
2014-03-15 16:59:03 +00:00
size_t pindex ;
# ifdef RANGECHECK
if ( x2 < x1 | | x1 < 0 | | x2 > = viewwidth | | y > viewheight )
I_Error ( " R_MapPlane: %d, %d at %d " , x1 , x2 , y ) ;
# endif
2020-11-05 02:46:34 +00:00
if ( x1 > = vid . width )
x1 = vid . width - 1 ;
2014-03-15 16:59:03 +00:00
2021-04-27 22:01:09 +00:00
angle = ( currentplane - > viewangle + currentplane - > plangle ) > > ANGLETOFINESHIFT ;
planecos = FINECOSINE ( angle ) ;
planesin = FINESINE ( angle ) ;
if ( planeheight ! = cachedheight [ y ] )
2014-03-15 16:59:03 +00:00
{
2021-04-27 22:01:09 +00:00
cachedheight [ y ] = planeheight ;
cacheddistance [ y ] = distance = FixedMul ( planeheight , yslope [ y ] ) ;
span = abs ( centery - y ) ;
2018-12-14 17:08:25 +00:00
2021-08-26 16:22:32 +00:00
if ( span ) // Don't divide by zero
2018-12-14 17:08:25 +00:00
{
2021-04-27 22:01:09 +00:00
ds_xstep = FixedMul ( planesin , planeheight ) / span ;
ds_ystep = FixedMul ( planecos , planeheight ) / span ;
2020-11-05 02:46:34 +00:00
}
else
2021-08-26 16:22:32 +00:00
ds_xstep = ds_ystep = FRACUNIT ;
2014-03-15 16:59:03 +00:00
2021-04-27 22:01:09 +00:00
cachedxstep [ y ] = ds_xstep ;
cachedystep [ y ] = ds_ystep ;
}
else
{
distance = cacheddistance [ y ] ;
ds_xstep = cachedxstep [ y ] ;
ds_ystep = cachedystep [ y ] ;
2020-11-05 02:46:34 +00:00
}
2014-03-15 16:59:03 +00:00
2021-08-26 16:22:32 +00:00
// [RH] Instead of using the xtoviewangle array, I calculated the fractional values
// at the middle of the screen, then used the calculated ds_xstep and ds_ystep
// to step from those to the proper texture coordinate to start drawing at.
// That way, the texture coordinate is always calculated by its position
// on the screen and not by its position relative to the edge of the visplane.
2021-04-27 22:01:09 +00:00
ds_xfrac = xoffs + FixedMul ( planecos , distance ) + ( x1 - centerx ) * ds_xstep ;
ds_yfrac = yoffs - FixedMul ( planesin , distance ) + ( x1 - centerx ) * ds_ystep ;
2020-11-05 03:00:08 +00:00
// Water ripple effect
2020-11-05 02:46:34 +00:00
if ( planeripple . active )
2014-03-15 16:59:03 +00:00
{
2021-04-27 22:01:09 +00:00
ds_bgofs = R_CalculateRippleOffset ( y ) ;
2014-03-15 16:59:03 +00:00
2021-04-27 22:01:09 +00:00
R_CalculatePlaneRipple ( currentplane - > viewangle + currentplane - > plangle ) ;
ds_xfrac + = planeripple . xfrac ;
ds_yfrac + = planeripple . yfrac ;
ds_bgofs > > = FRACBITS ;
2019-12-10 20:01:19 +00:00
2020-11-05 02:46:34 +00:00
if ( ( y + ds_bgofs ) > = viewheight )
2019-05-21 03:28:52 +00:00
ds_bgofs = viewheight - y - 1 ;
2020-11-05 02:46:34 +00:00
if ( ( y + ds_bgofs ) < 0 )
2019-05-21 03:28:52 +00:00
ds_bgofs = - y ;
2014-03-15 16:59:03 +00:00
}
2021-04-27 22:01:09 +00:00
pindex = distance > > LIGHTZSHIFT ;
if ( pindex > = MAXLIGHTZ )
pindex = MAXLIGHTZ - 1 ;
2014-03-15 16:59:03 +00:00
2021-04-27 22:01:09 +00:00
ds_colormap = planezlight [ pindex ] ;
2014-03-15 16:59:03 +00:00
if ( currentplane - > extra_colormap )
ds_colormap = currentplane - > extra_colormap - > colormap + ( ds_colormap - colormaps ) ;
ds_y = y ;
ds_x1 = x1 ;
ds_x2 = x2 ;
spanfunc ( ) ;
2021-04-27 22:01:09 +00:00
}
2014-03-15 16:59:03 +00:00
2021-04-27 22:01:09 +00:00
static void R_MapTiltedPlane ( INT32 y , INT32 x1 , INT32 x2 )
{
# ifdef RANGECHECK
if ( x2 < x1 | | x1 < 0 | | x2 > = viewwidth | | y > viewheight )
I_Error ( " R_MapTiltedPlane: %d, %d at %d " , x1 , x2 , y ) ;
2014-03-15 16:59:03 +00:00
# endif
2021-04-27 22:01:09 +00:00
if ( x1 > = vid . width )
x1 = vid . width - 1 ;
// Water ripple effect
if ( planeripple . active )
{
ds_bgofs = R_CalculateRippleOffset ( y ) ;
ds_sup = & ds_su [ y ] ;
ds_svp = & ds_sv [ y ] ;
ds_szp = & ds_sz [ y ] ;
ds_bgofs > > = FRACBITS ;
if ( ( y + ds_bgofs ) > = viewheight )
ds_bgofs = viewheight - y - 1 ;
if ( ( y + ds_bgofs ) < 0 )
ds_bgofs = - y ;
}
if ( currentplane - > extra_colormap )
ds_colormap = currentplane - > extra_colormap - > colormap ;
else
ds_colormap = colormaps ;
ds_y = y ;
ds_x1 = x1 ;
ds_x2 = x2 ;
spanfunc ( ) ;
2014-03-15 16:59:03 +00:00
}
2021-10-12 17:10:48 +00:00
static void R_MapFogPlane ( INT32 y , INT32 x1 , INT32 x2 )
{
fixed_t distance ;
size_t pindex ;
# ifdef RANGECHECK
if ( x2 < x1 | | x1 < 0 | | x2 > = viewwidth | | y > viewheight )
I_Error ( " R_MapFogPlane: %d, %d at %d " , x1 , x2 , y ) ;
# endif
if ( x1 > = vid . width )
x1 = vid . width - 1 ;
if ( planeheight ! = cachedheight [ y ] )
distance = FixedMul ( planeheight , yslope [ y ] ) ;
else
distance = cacheddistance [ y ] ;
pindex = distance > > LIGHTZSHIFT ;
if ( pindex > = MAXLIGHTZ )
pindex = MAXLIGHTZ - 1 ;
ds_colormap = planezlight [ pindex ] ;
if ( currentplane - > extra_colormap )
ds_colormap = currentplane - > extra_colormap - > colormap + ( ds_colormap - colormaps ) ;
ds_y = y ;
ds_x1 = x1 ;
ds_x2 = x2 ;
spanfunc ( ) ;
}
static void R_MapTiltedFogPlane ( INT32 y , INT32 x1 , INT32 x2 )
{
# ifdef RANGECHECK
if ( x2 < x1 | | x1 < 0 | | x2 > = viewwidth | | y > viewheight )
I_Error ( " R_MapTiltedFogPlane: %d, %d at %d " , x1 , x2 , y ) ;
# endif
if ( x1 > = vid . width )
x1 = vid . width - 1 ;
if ( currentplane - > extra_colormap )
ds_colormap = currentplane - > extra_colormap - > colormap ;
else
ds_colormap = colormaps ;
ds_y = y ;
ds_x1 = x1 ;
ds_x2 = x2 ;
spanfunc ( ) ;
}
2019-06-09 20:48:54 +00:00
void R_ClearFFloorClips ( void )
{
INT32 i , p ;
// opening / clipping determination
for ( i = 0 ; i < viewwidth ; i + + )
{
for ( p = 0 ; p < MAXFFLOORS ; p + + )
{
ffloor [ p ] . f_clip [ i ] = ( INT16 ) viewheight ;
ffloor [ p ] . c_clip [ i ] = - 1 ;
}
}
numffloors = 0 ;
}
2014-03-15 16:59:03 +00:00
//
// R_ClearPlanes
// At begining of frame.
//
void R_ClearPlanes ( void )
{
INT32 i , p ;
// opening / clipping determination
for ( i = 0 ; i < viewwidth ; i + + )
{
floorclip [ i ] = ( INT16 ) viewheight ;
2018-12-14 17:08:25 +00:00
ceilingclip [ i ] = - 1 ;
2014-03-15 16:59:03 +00:00
frontscale [ i ] = INT32_MAX ;
for ( p = 0 ; p < MAXFFLOORS ; p + + )
{
ffloor [ p ] . f_clip [ i ] = ( INT16 ) viewheight ;
2018-12-14 17:08:25 +00:00
ffloor [ p ] . c_clip [ i ] = - 1 ;
2014-03-15 16:59:03 +00:00
}
}
for ( i = 0 ; i < MAXVISPLANES ; i + + )
for ( * freehead = visplanes [ i ] , visplanes [ i ] = NULL ;
freehead & & * freehead ; )
{
freehead = & ( * freehead ) - > next ;
}
lastopening = openings ;
// texture calculation
memset ( cachedheight , 0 , sizeof ( cachedheight ) ) ;
}
static visplane_t * new_visplane ( unsigned hash )
{
visplane_t * check = freetail ;
if ( ! check )
{
2021-10-11 04:20:11 +00:00
check = malloc ( sizeof ( * check ) ) ;
2014-03-15 16:59:03 +00:00
if ( check = = NULL ) I_Error ( " %s: Out of memory " , " new_visplane " ) ; // FIXME: ugly
}
else
{
freetail = freetail - > next ;
if ( ! freetail )
freehead = & freetail ;
}
check - > next = visplanes [ hash ] ;
visplanes [ hash ] = check ;
return check ;
}
//
// R_FindPlane: Seek a visplane having the identical values:
// Same height, same flattexture, same lightlevel.
// If not, allocates another of them.
//
visplane_t * R_FindPlane ( fixed_t height , INT32 picnum , INT32 lightlevel ,
fixed_t xoff , fixed_t yoff , angle_t plangle , extracolormap_t * planecolormap ,
2020-05-02 10:08:31 +00:00
ffloor_t * pfloor , polyobj_t * polyobj , pslope_t * slope )
2014-03-15 16:59:03 +00:00
{
visplane_t * check ;
unsigned hash ;
2020-03-20 17:55:29 +00:00
if ( ! slope ) // Don't mess with this right now if a slope is involved
2014-03-15 16:59:03 +00:00
{
xoff + = viewx ;
yoff - = viewy ;
2017-03-30 20:57:36 +00:00
if ( plangle ! = 0 )
{
// Add the view offset, rotated by the plane angle.
2021-05-17 00:43:52 +00:00
float ang = ANG2RAD ( plangle ) ;
float x = FixedToFloat ( xoff ) ;
float y = FixedToFloat ( yoff ) ;
xoff = FloatToFixed ( x * cos ( ang ) + y * sin ( ang ) ) ;
yoff = FloatToFixed ( - x * sin ( ang ) + y * cos ( ang ) ) ;
2017-03-30 20:57:36 +00:00
}
2014-03-15 16:59:03 +00:00
}
2017-08-07 19:33:24 +00:00
if ( polyobj )
{
if ( polyobj - > angle ! = 0 )
{
2021-06-03 14:01:09 +00:00
float ang = ANG2RAD ( polyobj - > angle ) ;
float x = FixedToFloat ( polyobj - > centerPt . x ) ;
float y = FixedToFloat ( polyobj - > centerPt . y ) ;
xoff - = FloatToFixed ( x * cos ( ang ) + y * sin ( ang ) ) ;
yoff - = FloatToFixed ( x * sin ( ang ) - y * cos ( ang ) ) ;
2017-08-07 19:33:24 +00:00
}
else
{
xoff - = polyobj - > centerPt . x ;
yoff + = polyobj - > centerPt . y ;
}
}
2014-03-15 16:59:03 +00:00
// This appears to fix the Nimbus Ruins sky bug.
if ( picnum = = skyflatnum & & pfloor )
{
height = 0 ; // all skies map together
lightlevel = 0 ;
}
2020-10-17 11:35:28 +00:00
if ( ! pfloor )
2014-03-15 16:59:03 +00:00
{
2020-10-17 11:35:28 +00:00
hash = visplane_hash ( picnum , lightlevel , height ) ;
for ( check = visplanes [ hash ] ; check ; check = check - > next )
2014-03-15 16:59:03 +00:00
{
2020-10-17 11:35:28 +00:00
if ( polyobj ! = check - > polyobj )
continue ;
if ( height = = check - > height & & picnum = = check - > picnum
& & lightlevel = = check - > lightlevel
& & xoff = = check - > xoffs & & yoff = = check - > yoffs
& & planecolormap = = check - > extra_colormap
& & check - > viewx = = viewx & & check - > viewy = = viewy & & check - > viewz = = viewz
& & check - > viewangle = = viewangle
& & check - > plangle = = plangle
& & check - > slope = = slope )
{
return check ;
}
2014-03-15 16:59:03 +00:00
}
}
2020-10-17 11:35:28 +00:00
else
{
hash = MAXVISPLANES - 1 ;
}
2014-03-15 16:59:03 +00:00
check = new_visplane ( hash ) ;
check - > height = height ;
check - > picnum = picnum ;
check - > lightlevel = lightlevel ;
check - > minx = vid . width ;
check - > maxx = - 1 ;
check - > xoffs = xoff ;
check - > yoffs = yoff ;
check - > extra_colormap = planecolormap ;
check - > ffloor = pfloor ;
2016-04-04 19:49:01 +00:00
check - > viewx = viewx ;
check - > viewy = viewy ;
2014-03-15 16:59:03 +00:00
check - > viewz = viewz ;
2016-04-04 20:46:51 +00:00
check - > viewangle = viewangle ;
2014-03-15 16:59:03 +00:00
check - > plangle = plangle ;
2016-10-09 20:48:25 +00:00
check - > polyobj = polyobj ;
2015-04-20 07:10:14 +00:00
check - > slope = slope ;
2014-03-15 16:59:03 +00:00
memset ( check - > top , 0xff , sizeof ( check - > top ) ) ;
memset ( check - > bottom , 0x00 , sizeof ( check - > bottom ) ) ;
return check ;
}
//
// R_CheckPlane: return same visplane or alloc a new one if needed
//
visplane_t * R_CheckPlane ( visplane_t * pl , INT32 start , INT32 stop )
{
INT32 intrl , intrh ;
INT32 unionl , unionh ;
INT32 x ;
if ( start < pl - > minx )
{
intrl = pl - > minx ;
unionl = start ;
}
else
{
unionl = pl - > minx ;
intrl = start ;
}
if ( stop > pl - > maxx )
{
intrh = pl - > maxx ;
unionh = stop ;
}
else
{
unionh = pl - > maxx ;
intrh = stop ;
}
// 0xff is not equal to -1 with shorts...
for ( x = intrl ; x < = intrh ; x + + )
if ( pl - > top [ x ] ! = 0xffff | | pl - > bottom [ x ] ! = 0x0000 )
break ;
if ( x > intrh ) /* Can use existing plane; extend range */
{
pl - > minx = unionl ;
pl - > maxx = unionh ;
}
else /* Cannot use existing plane; create a new one */
{
2020-10-17 11:35:28 +00:00
visplane_t * new_pl ;
if ( pl - > ffloor )
{
new_pl = new_visplane ( MAXVISPLANES - 1 ) ;
}
else
{
unsigned hash =
visplane_hash ( pl - > picnum , pl - > lightlevel , pl - > height ) ;
new_pl = new_visplane ( hash ) ;
}
2014-03-15 16:59:03 +00:00
new_pl - > height = pl - > height ;
new_pl - > picnum = pl - > picnum ;
new_pl - > lightlevel = pl - > lightlevel ;
new_pl - > xoffs = pl - > xoffs ;
new_pl - > yoffs = pl - > yoffs ;
new_pl - > extra_colormap = pl - > extra_colormap ;
new_pl - > ffloor = pl - > ffloor ;
2016-04-04 19:49:01 +00:00
new_pl - > viewx = pl - > viewx ;
new_pl - > viewy = pl - > viewy ;
2014-03-15 16:59:03 +00:00
new_pl - > viewz = pl - > viewz ;
new_pl - > viewangle = pl - > viewangle ;
new_pl - > plangle = pl - > plangle ;
new_pl - > polyobj = pl - > polyobj ;
2015-04-20 07:10:14 +00:00
new_pl - > slope = pl - > slope ;
2014-03-15 16:59:03 +00:00
pl = new_pl ;
pl - > minx = start ;
pl - > maxx = stop ;
memset ( pl - > top , 0xff , sizeof pl - > top ) ;
memset ( pl - > bottom , 0x00 , sizeof pl - > bottom ) ;
}
return pl ;
}
//
// R_ExpandPlane
//
2021-08-26 16:22:32 +00:00
// This function basically expands the visplane.
2014-03-15 16:59:03 +00:00
// The reason for this is that when creating 3D floor planes, there is no
// need to create new ones with R_CheckPlane, because 3D floor planes
// are created by subsector and there is no way a subsector can graphically
// overlap.
void R_ExpandPlane ( visplane_t * pl , INT32 start , INT32 stop )
{
// Don't expand polyobject planes here - we do that on our own.
if ( pl - > polyobj )
return ;
2018-02-07 18:11:32 +00:00
if ( pl - > minx > start ) pl - > minx = start ;
if ( pl - > maxx < stop ) pl - > maxx = stop ;
2014-03-15 16:59:03 +00:00
}
2021-08-26 16:22:32 +00:00
static void R_MakeSpans ( void ( * mapfunc ) ( INT32 , INT32 , INT32 ) , INT32 x , INT32 t1 , INT32 b1 , INT32 t2 , INT32 b2 )
2021-04-27 22:01:09 +00:00
{
// Alam: from r_splats's R_RasterizeFloorSplat
if ( t1 > = vid . height ) t1 = vid . height - 1 ;
if ( b1 > = vid . height ) b1 = vid . height - 1 ;
if ( t2 > = vid . height ) t2 = vid . height - 1 ;
if ( b2 > = vid . height ) b2 = vid . height - 1 ;
if ( x - 1 > = vid . width ) x = vid . width ;
while ( t1 < t2 & & t1 < = b1 )
{
2021-08-26 16:22:32 +00:00
mapfunc ( t1 , spanstart [ t1 ] , x - 1 ) ;
2021-04-27 22:01:09 +00:00
t1 + + ;
}
while ( b1 > b2 & & b1 > = t1 )
{
2021-08-26 16:22:32 +00:00
mapfunc ( b1 , spanstart [ b1 ] , x - 1 ) ;
2021-04-27 22:01:09 +00:00
b1 - - ;
}
while ( t2 < t1 & & t2 < = b2 )
spanstart [ t2 + + ] = x ;
while ( b2 > b1 & & b2 > = t2 )
spanstart [ b2 - - ] = x ;
}
2014-03-15 16:59:03 +00:00
void R_DrawPlanes ( void )
{
visplane_t * pl ;
INT32 i ;
2020-11-05 03:00:08 +00:00
R_UpdatePlaneRipple ( ) ;
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < MAXVISPLANES ; i + + , pl + + )
{
for ( pl = visplanes [ i ] ; pl ; pl = pl - > next )
{
2020-05-02 10:08:31 +00:00
if ( pl - > ffloor ! = NULL | | pl - > polyobj ! = NULL )
2014-03-15 16:59:03 +00:00
continue ;
R_DrawSinglePlane ( pl ) ;
}
}
}
2018-01-27 19:18:17 +00:00
// R_DrawSkyPlane
//
// Draws the sky within the plane's top/bottom bounds
// Note: this uses column drawers instead of span drawers, since the sky is always a texture
//
static void R_DrawSkyPlane ( visplane_t * pl )
{
INT32 x ;
INT32 angle ;
// Reset column drawer function (note: couldn't we just call walldrawerfunc directly?)
// (that is, unless we'll need to switch drawers in future for some reason)
2019-12-13 15:26:47 +00:00
colfunc = colfuncs [ BASEDRAWFUNC ] ;
2018-01-27 19:18:17 +00:00
// use correct aspect ratio scale
dc_iscale = skyscale ;
// Sky is always drawn full bright,
// i.e. colormaps[0] is used.
// Because of this hack, sky is not affected
// by sector colormaps (INVUL inverse mapping is not implemented in SRB2 so is irrelevant).
dc_colormap = colormaps ;
dc_texturemid = skytexturemid ;
dc_texheight = textureheight [ skytexture ]
> > FRACBITS ;
for ( x = pl - > minx ; x < = pl - > maxx ; x + + )
{
dc_yl = pl - > top [ x ] ;
dc_yh = pl - > bottom [ x ] ;
if ( dc_yl < = dc_yh )
{
angle = ( pl - > viewangle + xtoviewangle [ x ] ) > > ANGLETOSKYSHIFT ;
dc_iscale = FixedMul ( skyscale , FINECOSINE ( xtoviewangle [ x ] > > ANGLETOFINESHIFT ) ) ;
dc_x = x ;
2023-07-30 23:56:28 +00:00
dc_source = R_GetColumn ( texturetranslation [ skytexture ] , - angle ) - > pixels ; // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18
2019-12-13 15:26:47 +00:00
colfunc ( ) ;
2018-01-27 19:18:17 +00:00
}
}
}
2021-04-28 01:59:06 +00:00
// Returns the height of the sloped plane at (x, y) as a 32.16 fixed_t
static INT64 R_GetSlopeZAt ( const pslope_t * slope , fixed_t x , fixed_t y )
2019-12-10 20:01:19 +00:00
{
2021-04-29 01:00:20 +00:00
INT64 x64 = ( ( INT64 ) x - ( INT64 ) slope - > o . x ) ;
INT64 y64 = ( ( INT64 ) y - ( INT64 ) slope - > o . y ) ;
2019-12-10 20:01:19 +00:00
2021-04-29 01:00:20 +00:00
x64 = ( x64 * ( INT64 ) slope - > d . x ) / FRACUNIT ;
y64 = ( y64 * ( INT64 ) slope - > d . y ) / FRACUNIT ;
2019-12-10 20:01:19 +00:00
2021-04-29 01:00:20 +00:00
return ( INT64 ) slope - > o . z + ( ( x64 + y64 ) * ( INT64 ) slope - > zdelta ) / FRACUNIT ;
2021-04-27 23:32:41 +00:00
}
2021-04-14 14:34:36 +00:00
// Sets the texture origin vector of the sloped plane.
2021-04-14 13:55:52 +00:00
static void R_SetSlopePlaneOrigin ( pslope_t * slope , fixed_t xpos , fixed_t ypos , fixed_t zpos , fixed_t xoff , fixed_t yoff , fixed_t angle )
2019-12-10 20:01:19 +00:00
{
2021-04-14 13:55:52 +00:00
floatv3_t * p = & ds_slope_origin ;
2019-12-10 20:01:19 +00:00
2021-04-29 22:24:37 +00:00
INT64 vx = ( INT64 ) xpos + ( INT64 ) xoff ;
INT64 vy = ( INT64 ) ypos - ( INT64 ) yoff ;
float vxf = vx / ( float ) FRACUNIT ;
float vyf = vy / ( float ) FRACUNIT ;
2021-04-14 13:55:52 +00:00
float ang = ANG2RAD ( ANGLE_270 - angle ) ;
2019-12-10 20:01:19 +00:00
// p is the texture origin in view space
// Don't add in the offsets at this stage, because doing so can result in
// errors if the flat is rotated.
2021-04-29 22:24:37 +00:00
p - > x = vxf * cos ( ang ) - vyf * sin ( ang ) ;
p - > z = vxf * sin ( ang ) + vyf * cos ( ang ) ;
2021-04-28 01:59:06 +00:00
p - > y = ( R_GetSlopeZAt ( slope , - xoff , yoff ) - zpos ) / ( float ) FRACUNIT ;
2021-04-14 13:55:52 +00:00
}
2021-04-14 14:34:36 +00:00
// This function calculates all of the vectors necessary for drawing a sloped plane.
2021-04-14 13:55:52 +00:00
void R_SetSlopePlane ( pslope_t * slope , fixed_t xpos , fixed_t ypos , fixed_t zpos , fixed_t xoff , fixed_t yoff , angle_t angle , angle_t plangle )
{
// Potentially override other stuff for now cus we're mean. :< But draw a slope plane!
// I copied ZDoom's code and adapted it to SRB2... -Red
floatv3_t * m = & ds_slope_v , * n = & ds_slope_u ;
2021-04-27 22:01:09 +00:00
fixed_t height , temp ;
2021-04-14 13:55:52 +00:00
float ang ;
R_SetSlopePlaneOrigin ( slope , xpos , ypos , zpos , xoff , yoff , angle ) ;
2021-04-27 22:01:09 +00:00
height = P_GetSlopeZAt ( slope , xpos , ypos ) ;
zeroheight = FixedToFloat ( height - zpos ) ;
2019-12-10 20:01:19 +00:00
// m is the v direction vector in view space
2021-04-14 13:55:52 +00:00
ang = ANG2RAD ( ANGLE_180 - ( angle + plangle ) ) ;
m - > x = cos ( ang ) ;
m - > z = sin ( ang ) ;
2019-12-10 20:01:19 +00:00
// n is the u direction vector in view space
2021-04-14 13:55:52 +00:00
n - > x = sin ( ang ) ;
n - > z = - cos ( ang ) ;
2021-04-28 01:54:56 +00:00
plangle > > = ANGLETOFINESHIFT ;
temp = P_GetSlopeZAt ( slope , xpos + FINESINE ( plangle ) , ypos + FINECOSINE ( plangle ) ) ;
2021-04-27 22:01:09 +00:00
m - > y = FixedToFloat ( temp - height ) ;
2021-04-28 01:54:56 +00:00
temp = P_GetSlopeZAt ( slope , xpos + FINECOSINE ( plangle ) , ypos - FINESINE ( plangle ) ) ;
2021-04-27 22:01:09 +00:00
n - > y = FixedToFloat ( temp - height ) ;
2021-04-14 13:55:52 +00:00
}
2019-12-10 20:01:19 +00:00
2021-04-14 14:34:36 +00:00
// This function calculates all of the vectors necessary for drawing a sloped and scaled plane.
void R_SetScaledSlopePlane ( pslope_t * slope , fixed_t xpos , fixed_t ypos , fixed_t zpos , fixed_t xs , fixed_t ys , fixed_t xoff , fixed_t yoff , angle_t angle , angle_t plangle )
2021-04-14 13:55:52 +00:00
{
floatv3_t * m = & ds_slope_v , * n = & ds_slope_u ;
2021-04-27 22:01:09 +00:00
fixed_t height , temp ;
2019-12-10 20:01:19 +00:00
2021-04-14 13:55:52 +00:00
float xscale = FixedToFloat ( xs ) ;
float yscale = FixedToFloat ( ys ) ;
float ang ;
2019-12-10 20:01:19 +00:00
2021-04-14 13:55:52 +00:00
R_SetSlopePlaneOrigin ( slope , xpos , ypos , zpos , xoff , yoff , angle ) ;
2021-04-27 22:01:09 +00:00
height = P_GetSlopeZAt ( slope , xpos , ypos ) ;
zeroheight = FixedToFloat ( height - zpos ) ;
2019-12-10 20:01:19 +00:00
2021-04-14 13:55:52 +00:00
// m is the v direction vector in view space
ang = ANG2RAD ( ANGLE_180 - ( angle + plangle ) ) ;
m - > x = yscale * cos ( ang ) ;
m - > z = yscale * sin ( ang ) ;
// n is the u direction vector in view space
n - > x = xscale * sin ( ang ) ;
n - > z = - xscale * cos ( ang ) ;
ang = ANG2RAD ( plangle ) ;
temp = P_GetSlopeZAt ( slope , xpos + FloatToFixed ( yscale * sin ( ang ) ) , ypos + FloatToFixed ( yscale * cos ( ang ) ) ) ;
2021-04-27 22:01:09 +00:00
m - > y = FixedToFloat ( temp - height ) ;
2021-04-14 13:55:52 +00:00
temp = P_GetSlopeZAt ( slope , xpos + FloatToFixed ( xscale * cos ( ang ) ) , ypos - FloatToFixed ( xscale * sin ( ang ) ) ) ;
2021-04-27 22:01:09 +00:00
n - > y = FixedToFloat ( temp - height ) ;
2021-04-14 13:55:52 +00:00
}
void R_CalculateSlopeVectors ( void )
{
2021-04-14 14:34:36 +00:00
float sfmult = 65536.f ;
2019-12-10 20:01:19 +00:00
// Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using.
# define CROSS(d, v1, v2) \
2020-10-14 01:42:07 +00:00
d - > x = ( v1 . y * v2 . z ) - ( v1 . z * v2 . y ) ; \
d - > y = ( v1 . z * v2 . x ) - ( v1 . x * v2 . z ) ; \
d - > z = ( v1 . x * v2 . y ) - ( v1 . y * v2 . x )
2021-04-14 13:55:52 +00:00
CROSS ( ds_sup , ds_slope_origin , ds_slope_v ) ;
CROSS ( ds_svp , ds_slope_origin , ds_slope_u ) ;
CROSS ( ds_szp , ds_slope_v , ds_slope_u ) ;
2019-12-10 20:01:19 +00:00
# undef CROSS
2020-10-14 01:42:07 +00:00
ds_sup - > z * = focallengthf ;
ds_svp - > z * = focallengthf ;
ds_szp - > z * = focallengthf ;
2019-12-10 20:01:19 +00:00
2022-11-16 01:40:54 +00:00
if ( ds_solidcolor )
return ;
2019-12-10 20:01:19 +00:00
// Premultiply the texture vectors with the scale factors
if ( ds_powersoftwo )
2021-04-14 14:34:36 +00:00
sfmult * = ( 1 < < nflatshiftup ) ;
ds_sup - > x * = sfmult ;
ds_sup - > y * = sfmult ;
ds_sup - > z * = sfmult ;
ds_svp - > x * = sfmult ;
ds_svp - > y * = sfmult ;
ds_svp - > z * = sfmult ;
2019-12-10 20:01:19 +00:00
}
2020-11-23 15:53:59 +00:00
void R_SetTiltedSpan ( INT32 span )
2020-10-14 01:42:07 +00:00
{
2020-11-05 02:46:34 +00:00
if ( ds_su = = NULL )
ds_su = Z_Malloc ( sizeof ( * ds_su ) * vid . height , PU_STATIC , NULL ) ;
if ( ds_sv = = NULL )
ds_sv = Z_Malloc ( sizeof ( * ds_sv ) * vid . height , PU_STATIC , NULL ) ;
if ( ds_sz = = NULL )
ds_sz = Z_Malloc ( sizeof ( * ds_sz ) * vid . height , PU_STATIC , NULL ) ;
2020-11-23 15:53:59 +00:00
ds_sup = & ds_su [ span ] ;
ds_svp = & ds_sv [ span ] ;
ds_szp = & ds_sz [ span ] ;
}
2020-11-05 02:46:34 +00:00
2021-04-14 13:55:52 +00:00
static void R_SetSlopePlaneVectors ( visplane_t * pl , INT32 y , fixed_t xoff , fixed_t yoff )
2020-11-23 15:53:59 +00:00
{
R_SetTiltedSpan ( y ) ;
2021-04-14 13:55:52 +00:00
R_SetSlopePlane ( pl - > slope , pl - > viewx , pl - > viewy , pl - > viewz , xoff , yoff , pl - > viewangle , pl - > plangle ) ;
R_CalculateSlopeVectors ( ) ;
2020-10-14 01:42:07 +00:00
}
2021-04-29 01:15:05 +00:00
static inline void R_AdjustSlopeCoordinates ( vector3_t * origin )
2021-04-27 01:17:03 +00:00
{
const fixed_t modmask = ( ( 1 < < ( 32 - nflatshiftup ) ) - 1 ) ;
2021-04-29 01:15:05 +00:00
fixed_t ox = ( origin - > x & modmask ) ;
fixed_t oy = - ( origin - > y & modmask ) ;
2021-04-27 01:17:03 +00:00
2021-04-29 01:15:05 +00:00
xoffs & = modmask ;
yoffs & = modmask ;
2021-04-28 01:59:06 +00:00
2021-04-29 01:15:05 +00:00
xoffs - = ( origin - > x - ox ) ;
yoffs + = ( origin - > y + oy ) ;
2021-04-27 01:17:03 +00:00
}
2021-04-29 01:15:05 +00:00
static inline void R_AdjustSlopeCoordinatesNPO2 ( vector3_t * origin )
2021-04-27 01:17:03 +00:00
{
const fixed_t modmaskw = ( ds_flatwidth < < FRACBITS ) ;
const fixed_t modmaskh = ( ds_flatheight < < FRACBITS ) ;
2021-04-29 01:15:05 +00:00
fixed_t ox = ( origin - > x % modmaskw ) ;
fixed_t oy = - ( origin - > y % modmaskh ) ;
2021-04-27 01:17:03 +00:00
2021-04-29 01:15:05 +00:00
xoffs % = modmaskw ;
yoffs % = modmaskh ;
2021-04-28 01:59:06 +00:00
2021-04-29 01:15:05 +00:00
xoffs - = ( origin - > x - ox ) ;
yoffs + = ( origin - > y + oy ) ;
2020-10-14 01:42:07 +00:00
}
2014-03-15 16:59:03 +00:00
void R_DrawSinglePlane ( visplane_t * pl )
{
INT32 light = 0 ;
2021-08-26 16:22:32 +00:00
INT32 x , stop ;
2014-03-15 16:59:03 +00:00
ffloor_t * rover ;
2021-10-12 17:10:48 +00:00
boolean fog = false ;
INT32 spanfunctype = BASEDRAWFUNC ;
2022-11-16 01:40:54 +00:00
void ( * mapfunc ) ( INT32 , INT32 , INT32 ) ;
2014-03-15 16:59:03 +00:00
if ( ! ( pl - > minx < = pl - > maxx ) )
return ;
2018-01-27 19:18:17 +00:00
// sky flat
if ( pl - > picnum = = skyflatnum )
{
R_DrawSkyPlane ( pl ) ;
return ;
}
2020-11-05 02:46:34 +00:00
planeripple . active = false ;
2014-11-12 00:55:07 +00:00
2020-06-03 17:41:47 +00:00
if ( pl - > polyobj )
2019-12-13 16:11:56 +00:00
{
2014-11-12 00:55:07 +00:00
// Hacked up support for alpha value in software mode Tails 09-24-2002 (sidenote: ported to polys 10-15-2014, there was no time travel involved -Red)
if ( pl - > polyobj - > translucency > = 10 )
return ; // Don't even draw it
2015-10-12 14:10:43 +00:00
else if ( pl - > polyobj - > translucency > 0 )
2020-06-03 17:41:47 +00:00
{
spanfunctype = ( pl - > polyobj - > flags & POF_SPLAT ) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS ;
2020-10-27 03:03:41 +00:00
ds_transmap = R_GetTranslucencyTable ( pl - > polyobj - > translucency ) ;
2020-06-03 17:41:47 +00:00
}
else if ( pl - > polyobj - > flags & POF_SPLAT ) // Opaque, but allow transparent flat pixels
2019-12-13 16:11:56 +00:00
spanfunctype = SPANDRAWFUNC_SPLAT ;
2014-11-12 00:55:07 +00:00
2020-06-03 17:41:47 +00:00
if ( pl - > polyobj - > translucency = = 0 | | ( pl - > extra_colormap & & ( pl - > extra_colormap - > flags & CMF_FOG ) ) )
2014-11-12 00:55:07 +00:00
light = ( pl - > lightlevel > > LIGHTSEGSHIFT ) ;
else
2016-01-14 16:39:31 +00:00
light = LIGHTLEVELS - 1 ;
2020-05-02 10:08:31 +00:00
}
else
2014-03-15 16:59:03 +00:00
{
2020-05-02 10:08:31 +00:00
if ( pl - > ffloor )
2014-03-15 16:59:03 +00:00
{
2020-05-02 10:08:31 +00:00
// Don't draw planes that shouldn't be drawn.
for ( rover = pl - > ffloor - > target - > ffloors ; rover ; rover = rover - > next )
2014-03-15 16:59:03 +00:00
{
2022-07-31 10:04:42 +00:00
if ( ( pl - > ffloor - > fofflags & FOF_CUTEXTRA ) & & ( rover - > fofflags & FOF_EXTRA ) )
2014-03-15 16:59:03 +00:00
{
2022-07-31 10:04:42 +00:00
if ( pl - > ffloor - > fofflags & FOF_EXTRA )
2020-05-02 10:08:31 +00:00
{
// The plane is from an extra 3D floor... Check the flags so
// there are no undesired cuts.
2022-07-31 10:04:42 +00:00
if ( ( ( pl - > ffloor - > fofflags & ( FOF_FOG | FOF_SWIMMABLE ) ) = = ( rover - > fofflags & ( FOF_FOG | FOF_SWIMMABLE ) ) )
2020-05-02 10:08:31 +00:00
& & pl - > height < * rover - > topheight
& & pl - > height > * rover - > bottomheight )
return ;
}
2014-03-15 16:59:03 +00:00
}
}
2022-07-31 10:04:42 +00:00
if ( pl - > ffloor - > fofflags & FOF_TRANSLUCENT )
2020-05-02 10:08:31 +00:00
{
2022-07-31 10:04:42 +00:00
spanfunctype = ( pl - > ffloor - > fofflags & FOF_SPLAT ) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS ;
2020-05-02 10:08:31 +00:00
// Hacked up support for alpha value in software mode Tails 09-24-2002
2021-11-19 18:01:41 +00:00
// ...unhacked by toaster 04-01-2021, re-hacked a little by sphere 19-11-2021
{
INT32 trans = ( 10 * ( ( 256 + 12 ) - pl - > ffloor - > alpha ) ) / 255 ;
if ( trans > = 10 )
return ; // Don't even draw it
if ( pl - > ffloor - > blend ) // additive, (reverse) subtractive, modulative
ds_transmap = R_GetBlendTable ( pl - > ffloor - > blend , trans ) ;
2022-01-02 19:44:24 +00:00
else if ( ! ( ds_transmap = R_GetTranslucencyTable ( trans ) ) | | trans = = 0 )
2021-11-19 18:01:41 +00:00
spanfunctype = SPANDRAWFUNC_SPLAT ; // Opaque, but allow transparent flat pixels
}
2020-05-02 10:08:31 +00:00
if ( ( spanfunctype = = SPANDRAWFUNC_SPLAT ) | | ( pl - > extra_colormap & & ( pl - > extra_colormap - > flags & CMF_FOG ) ) )
light = ( pl - > lightlevel > > LIGHTSEGSHIFT ) ;
else
light = LIGHTLEVELS - 1 ;
}
2022-07-31 10:04:42 +00:00
else if ( pl - > ffloor - > fofflags & FOF_FOG )
2020-05-02 10:08:31 +00:00
{
2021-10-12 17:10:48 +00:00
fog = true ;
2020-05-02 10:08:31 +00:00
spanfunctype = SPANDRAWFUNC_FOG ;
2014-03-15 16:59:03 +00:00
light = ( pl - > lightlevel > > LIGHTSEGSHIFT ) ;
2020-05-02 10:08:31 +00:00
}
else light = ( pl - > lightlevel > > LIGHTSEGSHIFT ) ;
2014-03-15 16:59:03 +00:00
2022-11-16 01:40:54 +00:00
if ( pl - > ffloor - > fofflags & FOF_RIPPLE & & ! fog )
2014-03-15 16:59:03 +00:00
{
2020-11-05 02:46:34 +00:00
planeripple . active = true ;
2020-05-02 10:08:31 +00:00
if ( spanfunctype = = SPANDRAWFUNC_TRANS )
{
// Copy the current scene, ugh
2021-10-12 17:10:48 +00:00
INT32 top = pl - > high - 8 ;
INT32 bottom = pl - > low + 8 ;
2014-03-15 16:59:03 +00:00
2020-05-02 10:08:31 +00:00
if ( top < 0 )
top = 0 ;
if ( bottom > vid . height )
bottom = vid . height ;
2014-03-15 16:59:03 +00:00
2021-10-12 17:10:48 +00:00
spanfunctype = SPANDRAWFUNC_WATER ;
2020-05-02 10:08:31 +00:00
// Only copy the part of the screen we need
VID_BlitLinearScreen ( ( splitscreen & & viewplayer = = & players [ secondarydisplayplayer ] ) ? screens [ 0 ] + ( top + ( vid . height > > 1 ) ) * vid . width : screens [ 0 ] + ( ( top ) * vid . width ) , screens [ 1 ] + ( ( top ) * vid . width ) ,
vid . width , bottom - top ,
vid . width , vid . width ) ;
}
2014-03-15 16:59:03 +00:00
}
}
2020-05-02 10:08:31 +00:00
else
light = ( pl - > lightlevel > > LIGHTSEGSHIFT ) ;
2014-03-15 16:59:03 +00:00
}
2022-11-16 01:40:54 +00:00
ds_powersoftwo = ds_solidcolor = false ;
2014-03-15 16:59:03 +00:00
2022-11-16 01:40:54 +00:00
if ( fog )
{
// Since all fog planes do is apply a colormap, it's not required
// to know any information about their textures.
mapfunc = R_MapFogPlane ;
}
else
2019-10-21 03:21:22 +00:00
{
2021-10-12 17:10:48 +00:00
levelflat_t * levelflat = & levelflats [ pl - > picnum ] ;
/* :james: */
switch ( levelflat - > type )
{
case LEVELFLAT_NONE :
2020-01-07 16:27:59 +00:00
return ;
2021-10-12 17:10:48 +00:00
case LEVELFLAT_FLAT :
ds_source = ( UINT8 * ) R_GetFlat ( levelflat - > u . flat . lumpnum ) ;
2022-11-16 01:40:54 +00:00
R_SetFlatVars ( W_LumpLength ( levelflat - > u . flat . lumpnum ) ) ;
if ( R_CheckSolidColorFlat ( ) )
ds_solidcolor = true ;
else
ds_powersoftwo = true ;
2021-10-12 17:10:48 +00:00
break ;
default :
ds_source = ( UINT8 * ) R_GetLevelFlat ( levelflat ) ;
if ( ! ds_source )
return ;
2022-11-16 01:40:54 +00:00
else if ( R_CheckSolidColorFlat ( ) )
ds_solidcolor = true ;
else if ( R_CheckPowersOfTwo ( ) )
{
R_SetFlatVars ( ds_flatwidth * ds_flatheight ) ;
ds_powersoftwo = true ;
}
2021-10-12 17:10:48 +00:00
}
2014-03-15 16:59:03 +00:00
2022-11-16 01:40:54 +00:00
// Don't mess with angle on slopes! We'll handle this ourselves later
if ( ! pl - > slope & & viewangle ! = pl - > viewangle + pl - > plangle )
2021-10-12 17:10:48 +00:00
{
memset ( cachedheight , 0 , sizeof ( cachedheight ) ) ;
viewangle = pl - > viewangle + pl - > plangle ;
}
2022-11-16 01:40:54 +00:00
mapfunc = R_MapPlane ;
if ( ds_solidcolor )
{
switch ( spanfunctype )
{
case SPANDRAWFUNC_WATER :
spanfunctype = SPANDRAWFUNC_WATERSOLID ;
break ;
case SPANDRAWFUNC_TRANS :
spanfunctype = SPANDRAWFUNC_TRANSSOLID ;
break ;
default :
spanfunctype = SPANDRAWFUNC_SOLID ;
break ;
}
}
2020-10-12 03:13:22 +00:00
}
xoffs = pl - > xoffs ;
yoffs = pl - > yoffs ;
2015-05-14 02:41:54 +00:00
if ( light > = LIGHTLEVELS )
light = LIGHTLEVELS - 1 ;
if ( light < 0 )
light = 0 ;
2019-12-10 20:01:19 +00:00
if ( pl - > slope )
{
2021-10-12 17:10:48 +00:00
if ( fog )
mapfunc = R_MapTiltedFogPlane ;
else
2017-03-30 20:57:36 +00:00
{
2021-10-12 17:10:48 +00:00
mapfunc = R_MapTiltedPlane ;
2022-11-16 01:40:54 +00:00
if ( ! pl - > plangle & & ! ds_solidcolor )
2021-10-12 17:10:48 +00:00
{
if ( ds_powersoftwo )
R_AdjustSlopeCoordinates ( & pl - > slope - > o ) ;
else
R_AdjustSlopeCoordinatesNPO2 ( & pl - > slope - > o ) ;
}
2017-03-30 20:57:36 +00:00
}
2015-05-23 21:27:15 +00:00
2020-11-05 02:46:34 +00:00
if ( planeripple . active )
2019-06-25 17:40:00 +00:00
{
2021-04-27 22:01:09 +00:00
planeheight = abs ( P_GetSlopeZAt ( pl - > slope , pl - > viewx , pl - > viewy ) - pl - > viewz ) ;
2015-05-23 06:19:38 +00:00
2019-12-10 20:01:19 +00:00
R_PlaneBounds ( pl ) ;
2015-04-20 07:10:14 +00:00
2020-11-05 02:46:34 +00:00
for ( x = pl - > high ; x < pl - > low ; x + + )
2019-12-10 20:01:19 +00:00
{
2021-04-27 22:01:09 +00:00
ds_bgofs = R_CalculateRippleOffset ( x ) ;
R_CalculatePlaneRipple ( pl - > viewangle + pl - > plangle ) ;
2021-04-14 13:55:52 +00:00
R_SetSlopePlaneVectors ( pl , x , ( xoffs + planeripple . xfrac ) , ( yoffs + planeripple . yfrac ) ) ;
2019-12-10 20:01:19 +00:00
}
2019-09-12 17:32:31 +00:00
}
else
2021-04-14 13:55:52 +00:00
R_SetSlopePlaneVectors ( pl , 0 , xoffs , yoffs ) ;
2015-04-20 07:10:14 +00:00
2020-11-05 02:46:34 +00:00
switch ( spanfunctype )
{
case SPANDRAWFUNC_WATER :
spanfunctype = SPANDRAWFUNC_TILTEDWATER ;
break ;
case SPANDRAWFUNC_TRANS :
spanfunctype = SPANDRAWFUNC_TILTEDTRANS ;
break ;
case SPANDRAWFUNC_SPLAT :
spanfunctype = SPANDRAWFUNC_TILTEDSPLAT ;
break ;
2022-11-16 01:40:54 +00:00
case SPANDRAWFUNC_SOLID :
spanfunctype = SPANDRAWFUNC_TILTEDSOLID ;
break ;
case SPANDRAWFUNC_TRANSSOLID :
spanfunctype = SPANDRAWFUNC_TILTEDTRANSSOLID ;
break ;
case SPANDRAWFUNC_WATERSOLID :
spanfunctype = SPANDRAWFUNC_TILTEDWATERSOLID ;
break ;
2021-10-12 17:10:48 +00:00
case SPANDRAWFUNC_FOG :
spanfunctype = SPANDRAWFUNC_TILTEDFOG ;
break ;
2020-11-05 02:46:34 +00:00
default :
spanfunctype = SPANDRAWFUNC_TILTED ;
break ;
}
2015-04-20 07:10:14 +00:00
2015-05-14 02:41:54 +00:00
planezlight = scalelight [ light ] ;
2020-03-20 17:55:29 +00:00
}
else
2021-04-27 22:01:09 +00:00
{
planeheight = abs ( pl - > height - pl - > viewz ) ;
2020-03-20 17:55:29 +00:00
planezlight = zlight [ light ] ;
2021-04-27 22:01:09 +00:00
}
2014-03-15 16:59:03 +00:00
2022-11-16 01:40:54 +00:00
// Set the span drawer
2019-12-13 16:11:56 +00:00
if ( ! ds_powersoftwo )
{
if ( spanfuncs_npo2 [ spanfunctype ] )
spanfunc = spanfuncs_npo2 [ spanfunctype ] ;
else
spanfunc = spanfuncs [ spanfunctype ] ;
}
else
spanfunc = spanfuncs [ spanfunctype ] ;
2014-03-15 16:59:03 +00:00
// set the maximum value for unsigned
pl - > top [ pl - > maxx + 1 ] = 0xffff ;
pl - > top [ pl - > minx - 1 ] = 0xffff ;
pl - > bottom [ pl - > maxx + 1 ] = 0x0000 ;
pl - > bottom [ pl - > minx - 1 ] = 0x0000 ;
2022-11-16 01:40:54 +00:00
currentplane = pl ;
2014-03-15 16:59:03 +00:00
stop = pl - > maxx + 1 ;
2021-08-26 16:22:32 +00:00
for ( x = pl - > minx ; x < = stop ; x + + )
R_MakeSpans ( mapfunc , x , pl - > top [ x - 1 ] , pl - > bottom [ x - 1 ] , pl - > top [ x ] , pl - > bottom [ x ] ) ;
2014-03-15 16:59:03 +00:00
}
void R_PlaneBounds ( visplane_t * plane )
{
INT32 i ;
INT32 hi , low ;
hi = plane - > top [ plane - > minx ] ;
low = plane - > bottom [ plane - > minx ] ;
for ( i = plane - > minx + 1 ; i < = plane - > maxx ; i + + )
{
if ( plane - > top [ i ] < hi )
hi = plane - > top [ i ] ;
if ( plane - > bottom [ i ] > low )
low = plane - > bottom [ i ] ;
}
plane - > high = hi ;
plane - > low = low ;
}