2016-03-01 15:47:10 +00:00
// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// DESCRIPTION:
// All the clipping: columns, horizontal spans, sky columns.
//
// This file contains some code from the Build Engine.
//
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// Ken Silverman's official web site: "http://www.advsys.net/ken"
// See the included license file "BUILDLIC.TXT" for license info.
//
//-----------------------------------------------------------------------------
# include <stdlib.h>
# include <stddef.h>
# include "templates.h"
# include "i_system.h"
# include "doomdef.h"
# include "doomstat.h"
# include "doomdata.h"
# include "p_lnspec.h"
# include "r_local.h"
# include "r_sky.h"
# include "v_video.h"
# include "m_swap.h"
# include "w_wad.h"
# include "stats.h"
# include "a_sharedglobal.h"
# include "d_net.h"
# include "g_level.h"
# include "r_bsp.h"
# include "r_plane.h"
# include "r_segs.h"
# include "r_3dfloors.h"
# include "v_palette.h"
# include "r_data/colormaps.h"
# define WALLYREPEAT 8
CVAR ( Bool , r_np2 , true , 0 )
//CVAR (Int, ty, 8, 0)
//CVAR (Int, tx, 8, 0)
# define HEIGHTBITS 12
# define HEIGHTSHIFT (FRACBITS-HEIGHTBITS)
2016-04-14 17:40:14 +00:00
extern double globaluclip , globaldclip ;
2016-03-01 15:47:10 +00:00
PortalDrawseg * CurrentPortal = NULL ;
int CurrentPortalUniq = 0 ;
bool CurrentPortalInSkybox = false ;
// OPTIMIZE: closed two sided lines as single sided
// killough 1/6/98: replaced globals with statics where appropriate
static bool segtextured ; // True if any of the segs textures might be visible.
bool markfloor ; // False if the back side is the same plane.
bool markceiling ;
FTexture * toptexture ;
FTexture * bottomtexture ;
FTexture * midtexture ;
fixed_t rw_offset_top ;
fixed_t rw_offset_mid ;
fixed_t rw_offset_bottom ;
int wallshade ;
short walltop [ MAXWIDTH ] ; // [RH] record max extents of wall
short wallbottom [ MAXWIDTH ] ;
short wallupper [ MAXWIDTH ] ;
short walllower [ MAXWIDTH ] ;
fixed_t swall [ MAXWIDTH ] ;
fixed_t lwall [ MAXWIDTH ] ;
2016-04-14 17:40:14 +00:00
double lwallscale ;
2016-03-01 15:47:10 +00:00
//
// regular wall
//
extern fixed_t rw_backcz1 , rw_backcz2 ;
extern fixed_t rw_backfz1 , rw_backfz2 ;
extern fixed_t rw_frontcz1 , rw_frontcz2 ;
extern fixed_t rw_frontfz1 , rw_frontfz2 ;
int rw_ceilstat , rw_floorstat ;
bool rw_mustmarkfloor , rw_mustmarkceiling ;
bool rw_prepped ;
bool rw_markportal ;
bool rw_havehigh ;
bool rw_havelow ;
2016-04-15 00:14:04 +00:00
float rw_light ; // [RH] Scale lights with viewsize adjustments
float rw_lightstep ;
float rw_lightleft ;
2016-03-01 15:47:10 +00:00
2016-04-14 17:40:14 +00:00
static double rw_frontlowertop ;
2016-03-01 15:47:10 +00:00
static int rw_x ;
static int rw_stopx ;
fixed_t rw_offset ;
static fixed_t rw_scalestep ;
static fixed_t rw_midtexturemid ;
static fixed_t rw_toptexturemid ;
static fixed_t rw_bottomtexturemid ;
2016-04-14 17:40:14 +00:00
static double rw_midtexturescalex ;
static double rw_midtexturescaley ;
static double rw_toptexturescalex ;
static double rw_toptexturescaley ;
static double rw_bottomtexturescalex ;
static double rw_bottomtexturescaley ;
2016-03-01 15:47:10 +00:00
FTexture * rw_pic ;
static fixed_t * maskedtexturecol ;
static void R_RenderDecal ( side_t * wall , DBaseDecal * first , drawseg_t * clipper , int pass ) ;
static void WallSpriteColumn ( void ( * drawfunc ) ( const BYTE * column , const FTexture : : Span * spans ) ) ;
void wallscan_np2 ( int x1 , int x2 , short * uwal , short * dwal , fixed_t * swal , fixed_t * lwal , fixed_t yrepeat , fixed_t top , fixed_t bot , bool mask ) ;
static void wallscan_np2_ds ( drawseg_t * ds , int x1 , int x2 , short * uwal , short * dwal , fixed_t * swal , fixed_t * lwal , fixed_t yrepeat ) ;
static void call_wallscan ( int x1 , int x2 , short * uwal , short * dwal , fixed_t * swal , fixed_t * lwal , fixed_t yrepeat , bool mask ) ;
//=============================================================================
//
// CVAR r_fogboundary
//
// If true, makes fog look more "real" by shading the walls separating two
// sectors with different fog.
//=============================================================================
CVAR ( Bool , r_fogboundary , true , 0 )
inline bool IsFogBoundary ( sector_t * front , sector_t * back )
{
return r_fogboundary & & fixedcolormap = = NULL & & front - > ColorMap - > Fade & &
front - > ColorMap - > Fade ! = back - > ColorMap - > Fade & &
( front - > GetTexture ( sector_t : : ceiling ) ! = skyflatnum | | back - > GetTexture ( sector_t : : ceiling ) ! = skyflatnum ) ;
}
//=============================================================================
//
// CVAR r_drawmirrors
//
// Set to false to disable rendering of mirrors
//=============================================================================
CVAR ( Bool , r_drawmirrors , true , 0 )
//
// R_RenderMaskedSegRange
//
fixed_t * MaskedSWall ;
fixed_t MaskedScaleY ;
static void BlastMaskedColumn ( void ( * blastfunc ) ( const BYTE * pixels , const FTexture : : Span * spans ) , FTexture * tex )
{
// calculate lighting
if ( fixedcolormap = = NULL & & fixedlightlev < 0 )
{
dc_colormap = basecolormap - > Maps + ( GETPALOOKUP ( rw_light , wallshade ) < < COLORMAPSHIFT ) ;
}
dc_iscale = MulScale18 ( MaskedSWall [ dc_x ] , MaskedScaleY ) ;
if ( sprflipvert )
2016-04-14 17:40:14 +00:00
sprtopscreen = FLOAT2FIXED ( CenterY ) + FixedMul ( dc_texturemid , spryscale ) ;
2016-03-01 15:47:10 +00:00
else
2016-04-14 17:40:14 +00:00
sprtopscreen = FLOAT2FIXED ( CenterY ) - FixedMul ( dc_texturemid , spryscale ) ;
2016-03-01 15:47:10 +00:00
// killough 1/25/98: here's where Medusa came in, because
// it implicitly assumed that the column was all one patch.
// Originally, Doom did not construct complete columns for
// multipatched textures, so there were no header or trailer
// bytes in the column referred to below, which explains
// the Medusa effect. The fix is to construct true columns
// when forming multipatched textures (see r_data.c).
// draw the texture
const FTexture : : Span * spans ;
const BYTE * pixels = tex - > GetColumn ( maskedtexturecol [ dc_x ] > > FRACBITS , & spans ) ;
blastfunc ( pixels , spans ) ;
rw_light + = rw_lightstep ;
spryscale + = rw_scalestep ;
}
// Clip a midtexture to the floor and ceiling of the sector in front of it.
void ClipMidtex ( int x1 , int x2 )
{
short most [ MAXWIDTH ] ;
WallMost ( most , curline - > frontsector - > ceilingplane , & WallC ) ;
for ( int i = x1 ; i < x2 ; + + i )
{
if ( wallupper [ i ] < most [ i ] )
wallupper [ i ] = most [ i ] ;
}
WallMost ( most , curline - > frontsector - > floorplane , & WallC ) ;
for ( int i = x1 ; i < x2 ; + + i )
{
if ( walllower [ i ] > most [ i ] )
walllower [ i ] = most [ i ] ;
}
}
void R_RenderFakeWallRange ( drawseg_t * ds , int x1 , int x2 ) ;
void R_RenderMaskedSegRange ( drawseg_t * ds , int x1 , int x2 )
{
FTexture * tex ;
int i ;
sector_t tempsec ; // killough 4/13/98
2016-04-14 17:40:14 +00:00
double texheight , texheightscale ;
2016-03-01 15:47:10 +00:00
bool notrelevant = false ;
fixed_t rowoffset ;
const sector_t * sec ;
sprflipvert = false ;
curline = ds - > curline ;
// killough 4/11/98: draw translucent 2s normal textures
// [RH] modified because we don't use user-definable translucency maps
ESPSResult drawmode ;
drawmode = R_SetPatchStyle ( LegacyRenderStyles [ curline - > linedef - > flags & ML_ADDTRANS ? STYLE_Add : STYLE_Translucent ] ,
2016-03-21 11:18:46 +00:00
MIN < fixed_t > ( curline - > linedef - > Alpha , OPAQUE ) , 0 , 0 ) ;
2016-03-01 15:47:10 +00:00
if ( ( drawmode = = DontDraw & & ! ds - > bFogBoundary & & ! ds - > bFakeBoundary ) )
{
return ;
}
NetUpdate ( ) ;
frontsector = curline - > frontsector ;
backsector = curline - > backsector ;
tex = TexMan ( curline - > sidedef - > GetTexture ( side_t : : mid ) , true ) ;
if ( i_compatflags & COMPATF_MASKEDMIDTEX )
{
tex = tex - > GetRawTexture ( ) ;
}
// killough 4/13/98: get correct lightlevel for 2s normal textures
sec = R_FakeFlat ( frontsector , & tempsec , NULL , NULL , false ) ;
basecolormap = sec - > ColorMap ; // [RH] Set basecolormap
wallshade = ds - > shade ;
rw_lightstep = ds - > lightstep ;
rw_light = ds - > light + ( x1 - ds - > x1 ) * rw_lightstep ;
if ( fixedlightlev < 0 )
{
if ( ! ( fake3D & FAKE3D_CLIPTOP ) )
{
2016-04-14 17:40:14 +00:00
sclipTop = sec - > ceilingplane . ZatPoint ( ViewPos ) ;
2016-03-01 15:47:10 +00:00
}
for ( i = frontsector - > e - > XFloor . lightlist . Size ( ) - 1 ; i > = 0 ; i - - )
{
if ( sclipTop < = frontsector - > e - > XFloor . lightlist [ i ] . plane . Zat0 ( ) )
{
lightlist_t * lit = & frontsector - > e - > XFloor . lightlist [ i ] ;
basecolormap = lit - > extra_colormap ;
wallshade = LIGHT2SHADE ( curline - > sidedef - > GetLightLevel ( foggy , * lit - > p_lightlevel , lit - > lightsource ! = NULL ) + r_actualextralight ) ;
break ;
}
}
}
mfloorclip = openings + ds - > sprbottomclip - ds - > x1 ;
mceilingclip = openings + ds - > sprtopclip - ds - > x1 ;
// [RH] Draw fog partition
if ( ds - > bFogBoundary )
{
R_DrawFogBoundary ( x1 , x2 , mceilingclip , mfloorclip ) ;
if ( ds - > maskedtexturecol = = - 1 )
{
goto clearfog ;
}
}
if ( ( ds - > bFakeBoundary & & ! ( ds - > bFakeBoundary & 4 ) ) | | drawmode = = DontDraw )
{
goto clearfog ;
}
MaskedSWall = ( fixed_t * ) ( openings + ds - > swall ) - ds - > x1 ;
MaskedScaleY = ds - > yrepeat ;
maskedtexturecol = ( fixed_t * ) ( openings + ds - > maskedtexturecol ) - ds - > x1 ;
spryscale = ds - > iscale + ds - > iscalestep * ( x1 - ds - > x1 ) ;
rw_scalestep = ds - > iscalestep ;
if ( fixedlightlev > = 0 )
dc_colormap = basecolormap - > Maps + fixedlightlev ;
else if ( fixedcolormap ! = NULL )
dc_colormap = fixedcolormap ;
// find positioning
2016-04-14 17:40:14 +00:00
texheight = tex - > GetScaledHeightDouble ( ) ;
texheightscale = fabs ( curline - > sidedef - > GetTextureYScaleF ( side_t : : mid ) ) ;
if ( texheightscale ! = 1 )
2016-03-01 15:47:10 +00:00
{
2016-04-14 17:40:14 +00:00
texheight = texheight / texheightscale ;
2016-03-01 15:47:10 +00:00
}
if ( curline - > linedef - > flags & ML_DONTPEGBOTTOM )
{
2016-04-14 17:40:14 +00:00
dc_texturemid = FLOAT2FIXED ( MAX ( frontsector - > GetPlaneTexZF ( sector_t : : floor ) , backsector - > GetPlaneTexZF ( sector_t : : floor ) ) + texheight ) ;
2016-03-01 15:47:10 +00:00
}
else
{
2016-04-14 17:40:14 +00:00
dc_texturemid = FLOAT2FIXED ( MIN ( frontsector - > GetPlaneTexZF ( sector_t : : ceiling ) , backsector - > GetPlaneTexZF ( sector_t : : ceiling ) ) ) ;
2016-03-01 15:47:10 +00:00
}
rowoffset = curline - > sidedef - > GetTextureYOffset ( side_t : : mid ) ;
if ( ! ( curline - > linedef - > flags & ML_WRAP_MIDTEX ) & &
! ( curline - > sidedef - > Flags & WALLF_WRAP_MIDTEX ) )
{ // Texture does not wrap vertically.
2016-04-14 17:40:14 +00:00
double textop ;
2016-03-01 15:47:10 +00:00
if ( MaskedScaleY < 0 )
{
MaskedScaleY = - MaskedScaleY ;
sprflipvert = true ;
}
if ( tex - > bWorldPanning )
{
// rowoffset is added before the MulScale3 so that the masked texture will
// still be positioned in world units rather than texels.
2016-04-14 17:40:14 +00:00
dc_texturemid + = rowoffset - FLOAT2FIXED ( ViewPos . Z ) ;
textop = FIXED2FLOAT ( dc_texturemid ) ;
2016-03-01 15:47:10 +00:00
dc_texturemid = MulScale16 ( dc_texturemid , MaskedScaleY ) ;
}
else
{
// rowoffset is added outside the multiply so that it positions the texture
// by texels instead of world units.
2016-04-14 17:40:14 +00:00
textop = FIXED2FLOAT ( dc_texturemid + SafeDivScale16 ( rowoffset , MaskedScaleY ) ) - ViewPos . Z ;
dc_texturemid = MulScale16 ( dc_texturemid - FLOAT2FIXED ( ViewPos . Z ) , MaskedScaleY ) + rowoffset ;
2016-03-01 15:47:10 +00:00
}
if ( sprflipvert )
{
MaskedScaleY = - MaskedScaleY ;
dc_texturemid - = tex - > GetHeight ( ) < < FRACBITS ;
}
// [RH] Don't bother drawing segs that are completely offscreen
2016-04-14 17:40:14 +00:00
if ( globaldclip * ds - > sz1 < - textop & & globaldclip * ds - > sz2 < - textop )
2016-03-01 15:47:10 +00:00
{ // Texture top is below the bottom of the screen
goto clearfog ;
}
2016-04-14 17:40:14 +00:00
if ( globaluclip * ds - > sz1 > texheight - textop & & globaluclip * ds - > sz2 > texheight - textop )
2016-03-01 15:47:10 +00:00
{ // Texture bottom is above the top of the screen
goto clearfog ;
}
2016-04-14 17:40:14 +00:00
if ( ( fake3D & FAKE3D_CLIPBOTTOM ) & & textop < sclipBottom - ViewPos . Z )
2016-03-01 15:47:10 +00:00
{
notrelevant = true ;
goto clearfog ;
}
2016-04-14 17:40:14 +00:00
if ( ( fake3D & FAKE3D_CLIPTOP ) & & textop - texheight > sclipTop - ViewPos . Z )
2016-03-01 15:47:10 +00:00
{
notrelevant = true ;
goto clearfog ;
}
WallC . sz1 = ds - > sz1 ;
WallC . sz2 = ds - > sz2 ;
WallC . sx1 = ds - > sx1 ;
WallC . sx2 = ds - > sx2 ;
if ( fake3D & FAKE3D_CLIPTOP )
{
2016-04-14 17:40:14 +00:00
OWallMost ( wallupper , textop < sclipTop - ViewPos . Z ? textop : sclipTop - ViewPos . Z , & WallC ) ;
2016-03-01 15:47:10 +00:00
}
else
{
OWallMost ( wallupper , textop , & WallC ) ;
}
if ( fake3D & FAKE3D_CLIPBOTTOM )
{
2016-04-14 17:40:14 +00:00
OWallMost ( walllower , textop - texheight > sclipBottom - ViewPos . Z ? textop - texheight : sclipBottom - ViewPos . Z , & WallC ) ;
2016-03-01 15:47:10 +00:00
}
else
{
OWallMost ( walllower , textop - texheight , & WallC ) ;
}
for ( i = x1 ; i < x2 ; i + + )
{
if ( wallupper [ i ] < mceilingclip [ i ] )
wallupper [ i ] = mceilingclip [ i ] ;
}
for ( i = x1 ; i < x2 ; i + + )
{
if ( walllower [ i ] > mfloorclip [ i ] )
walllower [ i ] = mfloorclip [ i ] ;
}
if ( CurrentSkybox )
{ // Midtex clipping doesn't work properly with skyboxes, since you're normally below the floor
// or above the ceiling, so the appropriate end won't be clipped automatically when adding
// this drawseg.
if ( ( curline - > linedef - > flags & ML_CLIP_MIDTEX ) | |
( curline - > sidedef - > Flags & WALLF_CLIP_MIDTEX ) )
{
ClipMidtex ( x1 , x2 ) ;
}
}
mfloorclip = walllower ;
mceilingclip = wallupper ;
// draw the columns one at a time
if ( drawmode = = DoDraw0 )
{
for ( dc_x = x1 ; dc_x < x2 ; + + dc_x )
{
BlastMaskedColumn ( R_DrawMaskedColumn , tex ) ;
}
}
else
{
// [RH] Draw up to four columns at once
int stop = x2 & ~ 3 ;
if ( x1 > = x2 )
goto clearfog ;
dc_x = x1 ;
while ( ( dc_x < stop ) & & ( dc_x & 3 ) )
{
BlastMaskedColumn ( R_DrawMaskedColumn , tex ) ;
dc_x + + ;
}
while ( dc_x < stop )
{
rt_initcols ( ) ;
BlastMaskedColumn ( R_DrawMaskedColumnHoriz , tex ) ; dc_x + + ;
BlastMaskedColumn ( R_DrawMaskedColumnHoriz , tex ) ; dc_x + + ;
BlastMaskedColumn ( R_DrawMaskedColumnHoriz , tex ) ; dc_x + + ;
BlastMaskedColumn ( R_DrawMaskedColumnHoriz , tex ) ;
rt_draw4cols ( dc_x - 3 ) ;
dc_x + + ;
}
while ( dc_x < x2 )
{
BlastMaskedColumn ( R_DrawMaskedColumn , tex ) ;
dc_x + + ;
}
}
}
else
{ // Texture does wrap vertically.
if ( tex - > bWorldPanning )
{
// rowoffset is added before the MulScale3 so that the masked texture will
// still be positioned in world units rather than texels.
2016-04-14 17:40:14 +00:00
dc_texturemid + = rowoffset - FLOAT2FIXED ( ViewPos . Z ) ;
2016-03-01 15:47:10 +00:00
dc_texturemid = MulScale16 ( dc_texturemid , MaskedScaleY ) ;
}
else
{
// rowoffset is added outside the multiply so that it positions the texture
// by texels instead of world units.
2016-04-14 17:40:14 +00:00
dc_texturemid = MulScale16 ( dc_texturemid - FLOAT2FIXED ( ViewPos . Z ) , MaskedScaleY ) + rowoffset ;
2016-03-01 15:47:10 +00:00
}
WallC . sz1 = ds - > sz1 ;
WallC . sz2 = ds - > sz2 ;
WallC . sx1 = ds - > sx1 ;
WallC . sx2 = ds - > sx2 ;
if ( CurrentSkybox )
{ // Midtex clipping doesn't work properly with skyboxes, since you're normally below the floor
// or above the ceiling, so the appropriate end won't be clipped automatically when adding
// this drawseg.
if ( ( curline - > linedef - > flags & ML_CLIP_MIDTEX ) | |
( curline - > sidedef - > Flags & WALLF_CLIP_MIDTEX ) )
{
ClipMidtex ( x1 , x2 ) ;
}
}
if ( fake3D & FAKE3D_CLIPTOP )
{
2016-04-14 17:40:14 +00:00
OWallMost ( wallupper , sclipTop - ViewPos . Z , & WallC ) ;
2016-03-01 15:47:10 +00:00
for ( i = x1 ; i < x2 ; i + + )
{
if ( wallupper [ i ] < mceilingclip [ i ] )
wallupper [ i ] = mceilingclip [ i ] ;
}
mceilingclip = wallupper ;
}
if ( fake3D & FAKE3D_CLIPBOTTOM )
{
2016-04-14 17:40:14 +00:00
OWallMost ( walllower , sclipBottom - ViewPos . Z , & WallC ) ;
2016-03-01 15:47:10 +00:00
for ( i = x1 ; i < x2 ; i + + )
{
if ( walllower [ i ] > mfloorclip [ i ] )
walllower [ i ] = mfloorclip [ i ] ;
}
mfloorclip = walllower ;
}
rw_offset = 0 ;
rw_pic = tex ;
wallscan_np2_ds ( ds , x1 , x2 , mceilingclip , mfloorclip , MaskedSWall , maskedtexturecol , ds - > yrepeat ) ;
}
clearfog :
R_FinishSetPatchStyle ( ) ;
if ( ds - > bFakeBoundary & 3 )
{
R_RenderFakeWallRange ( ds , x1 , x2 ) ;
}
if ( ! notrelevant )
{
if ( fake3D & FAKE3D_REFRESHCLIP )
{
assert ( ds - > bkup > = 0 ) ;
memcpy ( openings + ds - > sprtopclip , openings + ds - > bkup , ( ds - > x2 - ds - > x1 ) * 2 ) ;
}
else
{
clearbufshort ( openings + ds - > sprtopclip - ds - > x1 + x1 , x2 - x1 , viewheight ) ;
}
}
return ;
}
// kg3D - render one fake wall
void R_RenderFakeWall ( drawseg_t * ds , int x1 , int x2 , F3DFloor * rover )
{
int i ;
2016-04-14 17:40:14 +00:00
fixed_t xscale ;
double yscale ;
2016-03-01 15:47:10 +00:00
fixed_t Alpha = Scale ( rover - > alpha , OPAQUE , 255 ) ;
ESPSResult drawmode ;
drawmode = R_SetPatchStyle ( LegacyRenderStyles [ rover - > flags & FF_ADDITIVETRANS ? STYLE_Add : STYLE_Translucent ] ,
Alpha , 0 , 0 ) ;
if ( drawmode = = DontDraw ) {
R_FinishSetPatchStyle ( ) ;
return ;
}
rw_lightstep = ds - > lightstep ;
rw_light = ds - > light + ( x1 - ds - > x1 ) * rw_lightstep ;
mfloorclip = openings + ds - > sprbottomclip - ds - > x1 ;
mceilingclip = openings + ds - > sprtopclip - ds - > x1 ;
spryscale = ds - > iscale + ds - > iscalestep * ( x1 - ds - > x1 ) ;
rw_scalestep = ds - > iscalestep ;
MaskedSWall = ( fixed_t * ) ( openings + ds - > swall ) - ds - > x1 ;
// find positioning
side_t * scaledside ;
side_t : : ETexpart scaledpart ;
if ( rover - > flags & FF_UPPERTEXTURE )
{
scaledside = curline - > sidedef ;
scaledpart = side_t : : top ;
}
else if ( rover - > flags & FF_LOWERTEXTURE )
{
scaledside = curline - > sidedef ;
scaledpart = side_t : : bottom ;
}
else
{
scaledside = rover - > master - > sidedef [ 0 ] ;
scaledpart = side_t : : mid ;
}
2016-03-26 12:37:44 +00:00
xscale = fixed_t ( rw_pic - > Scale . X * scaledside - > GetTextureXScale ( scaledpart ) ) ;
2016-04-14 17:40:14 +00:00
yscale = rw_pic - > Scale . Y * scaledside - > GetTextureYScale ( scaledpart ) ;
2016-03-01 15:47:10 +00:00
fixed_t rowoffset = curline - > sidedef - > GetTextureYOffset ( side_t : : mid ) + rover - > master - > sidedef [ 0 ] - > GetTextureYOffset ( side_t : : mid ) ;
2016-04-14 17:40:14 +00:00
double planez = rover - > model - > GetPlaneTexZF ( sector_t : : ceiling ) ;
2016-03-01 15:47:10 +00:00
rw_offset = curline - > sidedef - > GetTextureXOffset ( side_t : : mid ) + rover - > master - > sidedef [ 0 ] - > GetTextureXOffset ( side_t : : mid ) ;
if ( rowoffset < 0 )
{
rowoffset + = rw_pic - > GetHeight ( ) < < FRACBITS ;
}
2016-04-14 17:40:14 +00:00
dc_texturemid = FLOAT2FIXED ( ( planez - ViewPos . Z ) * yscale ) ;
2016-03-01 15:47:10 +00:00
if ( rw_pic - > bWorldPanning )
{
// rowoffset is added before the MulScale3 so that the masked texture will
// still be positioned in world units rather than texels.
2016-04-14 17:40:14 +00:00
dc_texturemid + = xs_FloorToInt ( rowoffset * yscale ) ;
rw_offset = MulScale16 ( rw_offset , xscale ) ; ///Is this really supposed to be xscale and not yscale?
2016-03-01 15:47:10 +00:00
}
else
{
// rowoffset is added outside the multiply so that it positions the texture
// by texels instead of world units.
2016-04-14 17:40:14 +00:00
dc_texturemid + = rowoffset ;
2016-03-01 15:47:10 +00:00
}
if ( fixedlightlev > = 0 )
dc_colormap = basecolormap - > Maps + fixedlightlev ;
else if ( fixedcolormap ! = NULL )
dc_colormap = fixedcolormap ;
WallC . sz1 = ds - > sz1 ;
WallC . sz2 = ds - > sz2 ;
WallC . sx1 = ds - > sx1 ;
WallC . sx2 = ds - > sx2 ;
2016-04-14 17:40:14 +00:00
WallC . tleft . X = ds - > cx ;
WallC . tleft . Y = ds - > cy ;
WallC . tright . X = ds - > cx + ds - > cdx ;
WallC . tright . Y = ds - > cy + ds - > cdy ;
2016-03-01 15:47:10 +00:00
WallT = ds - > tmapvals ;
2016-04-14 17:40:14 +00:00
OWallMost ( wallupper , sclipTop - ViewPos . Z , & WallC ) ;
OWallMost ( walllower , sclipBottom - ViewPos . Z , & WallC ) ;
2016-03-01 15:47:10 +00:00
for ( i = x1 ; i < x2 ; i + + )
{
if ( wallupper [ i ] < mceilingclip [ i ] )
wallupper [ i ] = mceilingclip [ i ] ;
}
for ( i = x1 ; i < x2 ; i + + )
{
if ( walllower [ i ] > mfloorclip [ i ] )
walllower [ i ] = mfloorclip [ i ] ;
}
PrepLWall ( lwall , curline - > sidedef - > TexelLength * xscale , ds - > sx1 , ds - > sx2 ) ;
2016-04-14 17:40:14 +00:00
wallscan_np2_ds ( ds , x1 , x2 , wallupper , walllower , MaskedSWall , lwall , FLOAT2FIXED ( yscale ) ) ;
2016-03-01 15:47:10 +00:00
R_FinishSetPatchStyle ( ) ;
}
// kg3D - walls of fake floors
void R_RenderFakeWallRange ( drawseg_t * ds , int x1 , int x2 )
{
FTexture * const DONT_DRAW = ( ( FTexture * ) ( intptr_t ) - 1 ) ;
int i , j ;
F3DFloor * rover , * fover = NULL ;
int passed , last ;
fixed_t floorheight ;
fixed_t ceilingheight ;
sprflipvert = false ;
curline = ds - > curline ;
frontsector = curline - > frontsector ;
backsector = curline - > backsector ;
if ( backsector = = NULL )
{
return ;
}
if ( ( ds - > bFakeBoundary & 3 ) = = 2 )
{
sector_t * sec = backsector ;
backsector = frontsector ;
frontsector = sec ;
}
2016-03-30 14:30:22 +00:00
floorheight = FLOAT2FIXED ( backsector - > CenterFloor ( ) ) ;
ceilingheight = FLOAT2FIXED ( backsector - > CenterCeiling ( ) ) ;
2016-03-01 15:47:10 +00:00
// maybe fix clipheights
if ( ! ( fake3D & FAKE3D_CLIPBOTTOM ) ) sclipBottom = floorheight ;
if ( ! ( fake3D & FAKE3D_CLIPTOP ) ) sclipTop = ceilingheight ;
// maybe not visible
2016-03-30 14:30:22 +00:00
if ( sclipBottom > = FLOAT2FIXED ( frontsector - > CenterCeiling ( ) ) ) return ;
if ( sclipTop < = FLOAT2FIXED ( frontsector - > CenterFloor ( ) ) ) return ;
2016-03-01 15:47:10 +00:00
if ( fake3D & FAKE3D_DOWN2UP )
{ // bottom to viewz
last = 0 ;
for ( i = backsector - > e - > XFloor . ffloors . Size ( ) - 1 ; i > = 0 ; i - - )
{
rover = backsector - > e - > XFloor . ffloors [ i ] ;
if ( ! ( rover - > flags & FF_EXISTS ) ) continue ;
// visible?
passed = 0 ;
2016-03-29 10:40:41 +00:00
if ( ! ( rover - > flags & FF_RENDERSIDES ) | | rover - > top . plane - > isSlope ( ) | | rover - > bottom . plane - > isSlope ( ) | |
2016-03-01 15:47:10 +00:00
rover - > top . plane - > Zat0 ( ) < = sclipBottom | |
rover - > bottom . plane - > Zat0 ( ) > = ceilingheight | |
rover - > top . plane - > Zat0 ( ) < = floorheight )
{
if ( ! i )
{
passed = 1 ;
}
else
{
continue ;
}
}
rw_pic = NULL ;
if ( rover - > bottom . plane - > Zat0 ( ) > = sclipTop | | passed )
{
if ( last )
{
break ;
}
// maybe wall from inside rendering?
fover = NULL ;
for ( j = frontsector - > e - > XFloor . ffloors . Size ( ) - 1 ; j > = 0 ; j - - )
{
fover = frontsector - > e - > XFloor . ffloors [ j ] ;
if ( fover - > model = = rover - > model )
{ // never
fover = NULL ;
break ;
}
if ( ! ( fover - > flags & FF_EXISTS ) ) continue ;
if ( ! ( fover - > flags & FF_RENDERSIDES ) ) continue ;
// no sloped walls, it's bugged
2016-03-29 10:40:41 +00:00
if ( fover - > top . plane - > isSlope ( ) | | fover - > bottom . plane - > isSlope ( ) ) continue ;
2016-03-01 15:47:10 +00:00
// visible?
if ( fover - > top . plane - > Zat0 ( ) < = sclipBottom ) continue ; // no
if ( fover - > bottom . plane - > Zat0 ( ) > = sclipTop )
{ // no, last possible
fover = NULL ;
break ;
}
// it is, render inside?
if ( ! ( fover - > flags & ( FF_BOTHPLANES | FF_INVERTPLANES ) ) )
{ // no
fover = NULL ;
}
break ;
}
// nothing
if ( ! fover | | j = = - 1 )
{
break ;
}
// correct texture
if ( fover - > flags & rover - > flags & FF_SWIMMABLE )
{ // don't ever draw (but treat as something has been found)
rw_pic = DONT_DRAW ;
}
else if ( fover - > flags & FF_UPPERTEXTURE )
{
rw_pic = TexMan ( curline - > sidedef - > GetTexture ( side_t : : top ) , true ) ;
}
else if ( fover - > flags & FF_LOWERTEXTURE )
{
rw_pic = TexMan ( curline - > sidedef - > GetTexture ( side_t : : bottom ) , true ) ;
}
else
{
rw_pic = TexMan ( fover - > master - > sidedef [ 0 ] - > GetTexture ( side_t : : mid ) , true ) ;
}
}
else if ( frontsector - > e - > XFloor . ffloors . Size ( ) )
{
// maybe not visible?
fover = NULL ;
for ( j = frontsector - > e - > XFloor . ffloors . Size ( ) - 1 ; j > = 0 ; j - - )
{
fover = frontsector - > e - > XFloor . ffloors [ j ] ;
if ( fover - > model = = rover - > model ) // never
{
break ;
}
if ( ! ( fover - > flags & FF_EXISTS ) ) continue ;
if ( ! ( fover - > flags & FF_RENDERSIDES ) ) continue ;
// no sloped walls, it's bugged
2016-03-29 10:40:41 +00:00
if ( fover - > top . plane - > isSlope ( ) | | fover - > bottom . plane - > isSlope ( ) ) continue ;
2016-03-01 15:47:10 +00:00
// visible?
if ( fover - > top . plane - > Zat0 ( ) < = sclipBottom ) continue ; // no
if ( fover - > bottom . plane - > Zat0 ( ) > = sclipTop )
{ // visible, last possible
fover = NULL ;
break ;
}
if ( ( fover - > flags & FF_SOLID ) = = ( rover - > flags & FF_SOLID ) & &
! ( ! ( fover - > flags & FF_SOLID ) & & ( fover - > alpha = = 255 | | rover - > alpha = = 255 ) )
)
{
break ;
}
if ( fover - > flags & rover - > flags & FF_SWIMMABLE )
{ // don't ever draw (but treat as something has been found)
rw_pic = DONT_DRAW ;
}
fover = NULL ; // visible
break ;
}
if ( fover & & j ! = - 1 )
{
fover = NULL ;
last = 1 ;
continue ; // not visible
}
}
if ( ! rw_pic )
{
fover = NULL ;
if ( rover - > flags & FF_UPPERTEXTURE )
{
rw_pic = TexMan ( curline - > sidedef - > GetTexture ( side_t : : top ) , true ) ;
}
else if ( rover - > flags & FF_LOWERTEXTURE )
{
rw_pic = TexMan ( curline - > sidedef - > GetTexture ( side_t : : bottom ) , true ) ;
}
else
{
rw_pic = TexMan ( rover - > master - > sidedef [ 0 ] - > GetTexture ( side_t : : mid ) , true ) ;
}
}
// correct colors now
basecolormap = frontsector - > ColorMap ;
wallshade = ds - > shade ;
if ( fixedlightlev < 0 )
{
if ( ( ds - > bFakeBoundary & 3 ) = = 2 )
{
for ( j = backsector - > e - > XFloor . lightlist . Size ( ) - 1 ; j > = 0 ; j - - )
{
if ( sclipTop < = backsector - > e - > XFloor . lightlist [ j ] . plane . Zat0 ( ) )
{
lightlist_t * lit = & backsector - > e - > XFloor . lightlist [ j ] ;
basecolormap = lit - > extra_colormap ;
wallshade = LIGHT2SHADE ( curline - > sidedef - > GetLightLevel ( foggy , * lit - > p_lightlevel , lit - > lightsource ! = NULL ) + r_actualextralight ) ;
break ;
}
}
}
else
{
for ( j = frontsector - > e - > XFloor . lightlist . Size ( ) - 1 ; j > = 0 ; j - - )
{
if ( sclipTop < = frontsector - > e - > XFloor . lightlist [ j ] . plane . Zat0 ( ) )
{
lightlist_t * lit = & frontsector - > e - > XFloor . lightlist [ j ] ;
basecolormap = lit - > extra_colormap ;
wallshade = LIGHT2SHADE ( curline - > sidedef - > GetLightLevel ( foggy , * lit - > p_lightlevel , lit - > lightsource ! = NULL ) + r_actualextralight ) ;
break ;
}
}
}
}
if ( rw_pic ! = DONT_DRAW )
{
R_RenderFakeWall ( ds , x1 , x2 , fover ? fover : rover ) ;
}
else rw_pic = NULL ;
break ;
}
}
else
{ // top to viewz
for ( i = 0 ; i < ( int ) backsector - > e - > XFloor . ffloors . Size ( ) ; i + + )
{
rover = backsector - > e - > XFloor . ffloors [ i ] ;
if ( ! ( rover - > flags & FF_EXISTS ) ) continue ;
// visible?
passed = 0 ;
if ( ! ( rover - > flags & FF_RENDERSIDES ) | |
2016-03-29 10:40:41 +00:00
rover - > top . plane - > isSlope ( ) | | rover - > bottom . plane - > isSlope ( ) | |
2016-03-01 15:47:10 +00:00
rover - > bottom . plane - > Zat0 ( ) > = sclipTop | |
rover - > top . plane - > Zat0 ( ) < = floorheight | |
rover - > bottom . plane - > Zat0 ( ) > = ceilingheight )
{
if ( ( unsigned ) i = = backsector - > e - > XFloor . ffloors . Size ( ) - 1 )
{
passed = 1 ;
}
else
{
continue ;
}
}
rw_pic = NULL ;
if ( rover - > top . plane - > Zat0 ( ) < = sclipBottom | | passed )
{ // maybe wall from inside rendering?
fover = NULL ;
for ( j = 0 ; j < ( int ) frontsector - > e - > XFloor . ffloors . Size ( ) ; j + + )
{
fover = frontsector - > e - > XFloor . ffloors [ j ] ;
if ( fover - > model = = rover - > model )
{ // never
fover = NULL ;
break ;
}
if ( ! ( fover - > flags & FF_EXISTS ) ) continue ;
if ( ! ( fover - > flags & FF_RENDERSIDES ) ) continue ;
// no sloped walls, it's bugged
2016-03-29 10:40:41 +00:00
if ( fover - > top . plane - > isSlope ( ) | | fover - > bottom . plane - > isSlope ( ) ) continue ;
2016-03-01 15:47:10 +00:00
// visible?
if ( fover - > bottom . plane - > Zat0 ( ) > = sclipTop ) continue ; // no
if ( fover - > top . plane - > Zat0 ( ) < = sclipBottom )
{ // no, last possible
fover = NULL ;
break ;
}
// it is, render inside?
if ( ! ( fover - > flags & ( FF_BOTHPLANES | FF_INVERTPLANES ) ) )
{ // no
fover = NULL ;
}
break ;
}
// nothing
if ( ! fover | | ( unsigned ) j = = frontsector - > e - > XFloor . ffloors . Size ( ) )
{
break ;
}
// correct texture
if ( fover - > flags & rover - > flags & FF_SWIMMABLE )
{
rw_pic = DONT_DRAW ; // don't ever draw (but treat as something has been found)
}
else if ( fover - > flags & FF_UPPERTEXTURE )
{
rw_pic = TexMan ( curline - > sidedef - > GetTexture ( side_t : : top ) , true ) ;
}
else if ( fover - > flags & FF_LOWERTEXTURE )
{
rw_pic = TexMan ( curline - > sidedef - > GetTexture ( side_t : : bottom ) , true ) ;
}
else
{
rw_pic = TexMan ( fover - > master - > sidedef [ 0 ] - > GetTexture ( side_t : : mid ) , true ) ;
}
}
else if ( frontsector - > e - > XFloor . ffloors . Size ( ) )
{ // maybe not visible?
fover = NULL ;
for ( j = 0 ; j < ( int ) frontsector - > e - > XFloor . ffloors . Size ( ) ; j + + )
{
fover = frontsector - > e - > XFloor . ffloors [ j ] ;
if ( fover - > model = = rover - > model )
{ // never
break ;
}
if ( ! ( fover - > flags & FF_EXISTS ) ) continue ;
if ( ! ( fover - > flags & FF_RENDERSIDES ) ) continue ;
// no sloped walls, its bugged
2016-03-29 10:40:41 +00:00
if ( fover - > top . plane - > isSlope ( ) | | fover - > bottom . plane - > isSlope ( ) ) continue ;
2016-03-01 15:47:10 +00:00
// visible?
if ( fover - > bottom . plane - > Zat0 ( ) > = sclipTop ) continue ; // no
if ( fover - > top . plane - > Zat0 ( ) < = sclipBottom )
{ // visible, last possible
fover = NULL ;
break ;
}
if ( ( fover - > flags & FF_SOLID ) = = ( rover - > flags & FF_SOLID ) & &
! ( ! ( rover - > flags & FF_SOLID ) & & ( fover - > alpha = = 255 | | rover - > alpha = = 255 ) )
)
{
break ;
}
if ( fover - > flags & rover - > flags & FF_SWIMMABLE )
{ // don't ever draw (but treat as something has been found)
rw_pic = DONT_DRAW ;
}
fover = NULL ; // visible
break ;
}
if ( fover & & ( unsigned ) j ! = frontsector - > e - > XFloor . ffloors . Size ( ) )
{ // not visible
break ;
}
}
if ( rw_pic = = NULL )
{
fover = NULL ;
if ( rover - > flags & FF_UPPERTEXTURE )
{
rw_pic = TexMan ( curline - > sidedef - > GetTexture ( side_t : : top ) , true ) ;
}
else if ( rover - > flags & FF_LOWERTEXTURE )
{
rw_pic = TexMan ( curline - > sidedef - > GetTexture ( side_t : : bottom ) , true ) ;
}
else
{
rw_pic = TexMan ( rover - > master - > sidedef [ 0 ] - > GetTexture ( side_t : : mid ) , true ) ;
}
}
// correct colors now
basecolormap = frontsector - > ColorMap ;
wallshade = ds - > shade ;
if ( fixedlightlev < 0 )
{
if ( ( ds - > bFakeBoundary & 3 ) = = 2 )
{
for ( j = backsector - > e - > XFloor . lightlist . Size ( ) - 1 ; j > = 0 ; j - - )
{
if ( sclipTop < = backsector - > e - > XFloor . lightlist [ j ] . plane . Zat0 ( ) )
{
lightlist_t * lit = & backsector - > e - > XFloor . lightlist [ j ] ;
basecolormap = lit - > extra_colormap ;
wallshade = LIGHT2SHADE ( curline - > sidedef - > GetLightLevel ( foggy , * lit - > p_lightlevel , lit - > lightsource ! = NULL ) + r_actualextralight ) ;
break ;
}
}
}
else
{
for ( j = frontsector - > e - > XFloor . lightlist . Size ( ) - 1 ; j > = 0 ; j - - )
{
if ( sclipTop < = frontsector - > e - > XFloor . lightlist [ j ] . plane . Zat0 ( ) )
{
lightlist_t * lit = & frontsector - > e - > XFloor . lightlist [ j ] ;
basecolormap = lit - > extra_colormap ;
wallshade = LIGHT2SHADE ( curline - > sidedef - > GetLightLevel ( foggy , * lit - > p_lightlevel , lit - > lightsource ! = NULL ) + r_actualextralight ) ;
break ;
}
}
}
}
if ( rw_pic ! = DONT_DRAW )
{
R_RenderFakeWall ( ds , x1 , x2 , fover ? fover : rover ) ;
}
else
{
rw_pic = NULL ;
}
break ;
}
}
return ;
}
// prevlineasm1 is like vlineasm1 but skips the loop if only drawing one pixel
inline fixed_t prevline1 ( fixed_t vince , BYTE * colormap , int count , fixed_t vplce , const BYTE * bufplce , BYTE * dest )
{
dc_iscale = vince ;
dc_colormap = colormap ;
dc_count = count ;
dc_texturefrac = vplce ;
dc_source = bufplce ;
dc_dest = dest ;
return doprevline1 ( ) ;
}
void wallscan ( int x1 , int x2 , short * uwal , short * dwal , fixed_t * swal , fixed_t * lwal ,
fixed_t yrepeat , const BYTE * ( * getcol ) ( FTexture * tex , int x ) )
{
int x , shiftval ;
int y1ve [ 4 ] , y2ve [ 4 ] , u4 , d4 , z ;
char bad ;
2016-04-15 00:14:04 +00:00
float light = rw_light - rw_lightstep ;
2016-03-01 15:47:10 +00:00
SDWORD texturemid , xoffset ;
BYTE * basecolormapdata ;
// This function also gets used to draw skies. Unlike BUILD, skies are
// drawn by visplane instead of by bunch, so these checks are invalid.
//if ((uwal[x1] > viewheight) && (uwal[x2] > viewheight)) return;
//if ((dwal[x1] < 0) && (dwal[x2] < 0)) return;
if ( rw_pic - > UseType = = FTexture : : TEX_Null )
{
return ;
}
//extern cycle_t WallScanCycles;
//clock (WallScanCycles);
rw_pic - > GetHeight ( ) ; // Make sure texture size is loaded
shiftval = rw_pic - > HeightBits ;
setupvline ( 32 - shiftval ) ;
yrepeat > > = 2 + shiftval ;
texturemid = dc_texturemid < < ( 16 - shiftval ) ;
xoffset = rw_offset ;
basecolormapdata = basecolormap - > Maps ;
2016-04-14 17:40:14 +00:00
fixed_t centeryfrac = FLOAT2FIXED ( CenterY ) ;
2016-03-01 15:47:10 +00:00
x = x1 ;
//while ((umost[x] > dmost[x]) && (x < x2)) x++;
bool fixed = ( fixedcolormap ! = NULL | | fixedlightlev > = 0 ) ;
if ( fixed )
{
palookupoffse [ 0 ] = dc_colormap ;
palookupoffse [ 1 ] = dc_colormap ;
palookupoffse [ 2 ] = dc_colormap ;
palookupoffse [ 3 ] = dc_colormap ;
}
for ( ; ( x < x2 ) & & ( x & 3 ) ; + + x )
{
light + = rw_lightstep ;
y1ve [ 0 ] = uwal [ x ] ; //max(uwal[x],umost[x]);
y2ve [ 0 ] = dwal [ x ] ; //min(dwal[x],dmost[x]);
if ( y2ve [ 0 ] < = y1ve [ 0 ] ) continue ;
assert ( y1ve [ 0 ] < viewheight ) ;
assert ( y2ve [ 0 ] < = viewheight ) ;
if ( ! fixed )
{ // calculate lighting
dc_colormap = basecolormapdata + ( GETPALOOKUP ( light , wallshade ) < < COLORMAPSHIFT ) ;
}
dc_source = getcol ( rw_pic , ( lwal [ x ] + xoffset ) > > FRACBITS ) ;
dc_dest = ylookup [ y1ve [ 0 ] ] + x + dc_destorg ;
dc_iscale = swal [ x ] * yrepeat ;
dc_count = y2ve [ 0 ] - y1ve [ 0 ] ;
dc_texturefrac = texturemid + FixedMul ( dc_iscale , ( y1ve [ 0 ] < < FRACBITS ) - centeryfrac + FRACUNIT ) ;
dovline1 ( ) ;
}
for ( ; x < x2 - 3 ; x + = 4 )
{
bad = 0 ;
for ( z = 3 ; z > = 0 ; - - z )
{
y1ve [ z ] = uwal [ x + z ] ; //max(uwal[x+z],umost[x+z]);
y2ve [ z ] = dwal [ x + z ] ; //min(dwal[x+z],dmost[x+z])-1;
if ( y2ve [ z ] < = y1ve [ z ] ) { bad + = 1 < < z ; continue ; }
assert ( y1ve [ z ] < viewheight ) ;
assert ( y2ve [ z ] < = viewheight ) ;
bufplce [ z ] = getcol ( rw_pic , ( lwal [ x + z ] + xoffset ) > > FRACBITS ) ;
vince [ z ] = swal [ x + z ] * yrepeat ;
vplce [ z ] = texturemid + FixedMul ( vince [ z ] , ( y1ve [ z ] < < FRACBITS ) - centeryfrac + FRACUNIT ) ;
}
if ( bad = = 15 )
{
2016-04-15 00:14:04 +00:00
light + = rw_lightstep * 4 ;
2016-03-01 15:47:10 +00:00
continue ;
}
if ( ! fixed )
{
for ( z = 0 ; z < 4 ; + + z )
{
light + = rw_lightstep ;
palookupoffse [ z ] = basecolormapdata + ( GETPALOOKUP ( light , wallshade ) < < COLORMAPSHIFT ) ;
}
}
u4 = MAX ( MAX ( y1ve [ 0 ] , y1ve [ 1 ] ) , MAX ( y1ve [ 2 ] , y1ve [ 3 ] ) ) ;
d4 = MIN ( MIN ( y2ve [ 0 ] , y2ve [ 1 ] ) , MIN ( y2ve [ 2 ] , y2ve [ 3 ] ) ) ;
if ( ( bad ! = 0 ) | | ( u4 > = d4 ) )
{
for ( z = 0 ; z < 4 ; + + z )
{
if ( ! ( bad & 1 ) )
{
prevline1 ( vince [ z ] , palookupoffse [ z ] , y2ve [ z ] - y1ve [ z ] , vplce [ z ] , bufplce [ z ] , ylookup [ y1ve [ z ] ] + x + z + dc_destorg ) ;
}
bad > > = 1 ;
}
continue ;
}
for ( z = 0 ; z < 4 ; + + z )
{
if ( u4 > y1ve [ z ] )
{
vplce [ z ] = prevline1 ( vince [ z ] , palookupoffse [ z ] , u4 - y1ve [ z ] , vplce [ z ] , bufplce [ z ] , ylookup [ y1ve [ z ] ] + x + z + dc_destorg ) ;
}
}
if ( d4 > u4 )
{
dc_count = d4 - u4 ;
dc_dest = ylookup [ u4 ] + x + dc_destorg ;
dovline4 ( ) ;
}
BYTE * i = x + ylookup [ d4 ] + dc_destorg ;
for ( z = 0 ; z < 4 ; + + z )
{
if ( y2ve [ z ] > d4 )
{
prevline1 ( vince [ z ] , palookupoffse [ 0 ] , y2ve [ z ] - d4 , vplce [ z ] , bufplce [ z ] , i + z ) ;
}
}
}
for ( ; x < x2 ; x + + )
{
light + = rw_lightstep ;
y1ve [ 0 ] = uwal [ x ] ; //max(uwal[x],umost[x]);
y2ve [ 0 ] = dwal [ x ] ; //min(dwal[x],dmost[x]);
if ( y2ve [ 0 ] < = y1ve [ 0 ] ) continue ;
assert ( y1ve [ 0 ] < viewheight ) ;
assert ( y2ve [ 0 ] < = viewheight ) ;
if ( ! fixed )
{ // calculate lighting
dc_colormap = basecolormapdata + ( GETPALOOKUP ( light , wallshade ) < < COLORMAPSHIFT ) ;
}
dc_source = getcol ( rw_pic , ( lwal [ x ] + xoffset ) > > FRACBITS ) ;
dc_dest = ylookup [ y1ve [ 0 ] ] + x + dc_destorg ;
dc_iscale = swal [ x ] * yrepeat ;
dc_count = y2ve [ 0 ] - y1ve [ 0 ] ;
dc_texturefrac = texturemid + FixedMul ( dc_iscale , ( y1ve [ 0 ] < < FRACBITS ) - centeryfrac + FRACUNIT ) ;
dovline1 ( ) ;
}
//unclock (WallScanCycles);
NetUpdate ( ) ;
}
void wallscan_striped ( int x1 , int x2 , short * uwal , short * dwal , fixed_t * swal , fixed_t * lwal , fixed_t yrepeat )
{
FDynamicColormap * startcolormap = basecolormap ;
int startshade = wallshade ;
bool fogginess = foggy ;
short most1 [ MAXWIDTH ] , most2 [ MAXWIDTH ] , most3 [ MAXWIDTH ] ;
short * up , * down ;
up = uwal ;
down = most1 ;
assert ( WallC . sx1 < = x1 ) ;
assert ( WallC . sx2 > = x2 ) ;
// kg3D - fake floors instead of zdoom light list
for ( unsigned int i = 0 ; i < frontsector - > e - > XFloor . lightlist . Size ( ) ; i + + )
{
int j = WallMost ( most3 , frontsector - > e - > XFloor . lightlist [ i ] . plane , & WallC ) ;
if ( j ! = 3 )
{
for ( int j = x1 ; j < x2 ; + + j )
{
down [ j ] = clamp ( most3 [ j ] , up [ j ] , dwal [ j ] ) ;
}
wallscan ( x1 , x2 , up , down , swal , lwal , yrepeat ) ;
up = down ;
down = ( down = = most1 ) ? most2 : most1 ;
}
lightlist_t * lit = & frontsector - > e - > XFloor . lightlist [ i ] ;
basecolormap = lit - > extra_colormap ;
wallshade = LIGHT2SHADE ( curline - > sidedef - > GetLightLevel ( fogginess ,
* lit - > p_lightlevel , lit - > lightsource ! = NULL ) + r_actualextralight ) ;
}
wallscan ( x1 , x2 , up , dwal , swal , lwal , yrepeat ) ;
basecolormap = startcolormap ;
wallshade = startshade ;
}
static void call_wallscan ( int x1 , int x2 , short * uwal , short * dwal , fixed_t * swal , fixed_t * lwal , fixed_t yrepeat , bool mask )
{
if ( mask )
{
if ( colfunc = = basecolfunc )
{
maskwallscan ( x1 , x2 , uwal , dwal , swal , lwal , yrepeat ) ;
}
else
{
transmaskwallscan ( x1 , x2 , uwal , dwal , swal , lwal , yrepeat ) ;
}
}
else
{
if ( fixedcolormap ! = NULL | | fixedlightlev > = 0 | | ! ( frontsector - > e & & frontsector - > e - > XFloor . lightlist . Size ( ) ) )
{
wallscan ( x1 , x2 , uwal , dwal , swal , lwal , yrepeat ) ;
}
else
{
wallscan_striped ( x1 , x2 , uwal , dwal , swal , lwal , yrepeat ) ;
}
}
}
//=============================================================================
//
// wallscan_np2
//
// This is a wrapper around wallscan that helps it tile textures whose heights
// are not powers of 2. It divides the wall into texture-sized strips and calls
// wallscan for each of those. Since only one repetition of the texture fits
// in each strip, wallscan will not tile.
//
//=============================================================================
2016-04-14 17:40:14 +00:00
void wallscan_np2 ( int x1 , int x2 , short * uwal , short * dwal , fixed_t * swal , fixed_t * lwal , fixed_t yrepeat , fixed_t itop , fixed_t ibot , bool mask )
2016-03-01 15:47:10 +00:00
{
if ( ! r_np2 )
{
call_wallscan ( x1 , x2 , uwal , dwal , swal , lwal , yrepeat , mask ) ;
}
else
{
short most1 [ MAXWIDTH ] , most2 [ MAXWIDTH ] , most3 [ MAXWIDTH ] ;
short * up , * down ;
fixed_t texheight = rw_pic - > GetHeight ( ) < < FRACBITS ;
2016-04-14 17:40:14 +00:00
double scaledtexheight = FIXED2FLOAT ( FixedDiv ( texheight , yrepeat ) ) ;
double partition ;
double top = FIXED2FLOAT ( itop ) ;
double bot = FIXED2FLOAT ( ibot ) ;
2016-03-01 15:47:10 +00:00
if ( yrepeat > = 0 )
{ // normal orientation: draw strips from top to bottom
2016-04-14 17:40:14 +00:00
partition = top - fmod ( top - FIXED2FLOAT ( FixedDiv ( dc_texturemid , yrepeat ) ) - ViewPos . Z , scaledtexheight ) ;
if ( partition = = top )
{
partition - = scaledtexheight ;
}
2016-03-01 15:47:10 +00:00
up = uwal ;
down = most1 ;
2016-04-14 17:40:14 +00:00
dc_texturemid = xs_RoundToInt ( ( partition - ViewPos . Z ) * yrepeat + texheight ) ;
2016-03-01 15:47:10 +00:00
while ( partition > bot )
{
2016-04-14 17:40:14 +00:00
int j = OWallMost ( most3 , partition - ViewPos . Z , & WallC ) ;
2016-03-01 15:47:10 +00:00
if ( j ! = 3 )
{
for ( int j = x1 ; j < x2 ; + + j )
{
down [ j ] = clamp ( most3 [ j ] , up [ j ] , dwal [ j ] ) ;
}
call_wallscan ( x1 , x2 , up , down , swal , lwal , yrepeat , mask ) ;
up = down ;
down = ( down = = most1 ) ? most2 : most1 ;
}
partition - = scaledtexheight ;
dc_texturemid - = texheight ;
}
call_wallscan ( x1 , x2 , up , dwal , swal , lwal , yrepeat , mask ) ;
}
else
{ // upside down: draw strips from bottom to top
2016-04-14 17:40:14 +00:00
partition = bot - fmod ( bot - FIXED2FLOAT ( FixedDiv ( dc_texturemid , yrepeat ) ) - ViewPos . Z , scaledtexheight ) ;
2016-03-01 15:47:10 +00:00
up = most1 ;
down = dwal ;
2016-04-14 17:40:14 +00:00
dc_texturemid = xs_RoundToInt ( ( partition - ViewPos . Z ) * yrepeat + texheight ) ;
2016-03-01 15:47:10 +00:00
while ( partition < top )
{
2016-04-14 17:40:14 +00:00
int j = OWallMost ( most3 , partition - ViewPos . Z , & WallC ) ;
2016-03-01 15:47:10 +00:00
if ( j ! = 12 )
{
for ( int j = x1 ; j < x2 ; + + j )
{
up [ j ] = clamp ( most3 [ j ] , uwal [ j ] , down [ j ] ) ;
}
call_wallscan ( x1 , x2 , up , down , swal , lwal , yrepeat , mask ) ;
down = up ;
up = ( up = = most1 ) ? most2 : most1 ;
}
partition - = scaledtexheight ;
dc_texturemid - = texheight ;
}
call_wallscan ( x1 , x2 , uwal , down , swal , lwal , yrepeat , mask ) ;
}
}
}
static void wallscan_np2_ds ( drawseg_t * ds , int x1 , int x2 , short * uwal , short * dwal , fixed_t * swal , fixed_t * lwal , fixed_t yrepeat )
{
if ( rw_pic - > GetHeight ( ) ! = 1 < < rw_pic - > HeightBits )
{
2016-04-14 17:40:14 +00:00
double frontcz1 = ds - > curline - > frontsector - > ceilingplane . ZatPoint ( ds - > curline - > v1 ) ;
double frontfz1 = ds - > curline - > frontsector - > floorplane . ZatPoint ( ds - > curline - > v1 ) ;
double frontcz2 = ds - > curline - > frontsector - > ceilingplane . ZatPoint ( ds - > curline - > v2 ) ;
double frontfz2 = ds - > curline - > frontsector - > floorplane . ZatPoint ( ds - > curline - > v2 ) ;
double top = MAX ( frontcz1 , frontcz2 ) ;
double bot = MIN ( frontfz1 , frontfz2 ) ;
2016-03-01 15:47:10 +00:00
if ( fake3D & FAKE3D_CLIPTOP )
{
top = MIN ( top , sclipTop ) ;
}
if ( fake3D & FAKE3D_CLIPBOTTOM )
{
bot = MAX ( bot , sclipBottom ) ;
}
2016-04-14 17:40:14 +00:00
wallscan_np2 ( x1 , x2 , uwal , dwal , swal , lwal , yrepeat , FLOAT2FIXED ( top ) , FLOAT2FIXED ( bot ) , true ) ;
2016-03-01 15:47:10 +00:00
}
else
{
call_wallscan ( x1 , x2 , uwal , dwal , swal , lwal , yrepeat , true ) ;
}
}
inline fixed_t mvline1 ( fixed_t vince , BYTE * colormap , int count , fixed_t vplce , const BYTE * bufplce , BYTE * dest )
{
dc_iscale = vince ;
dc_colormap = colormap ;
dc_count = count ;
dc_texturefrac = vplce ;
dc_source = bufplce ;
dc_dest = dest ;
return domvline1 ( ) ;
}
void maskwallscan ( int x1 , int x2 , short * uwal , short * dwal , fixed_t * swal , fixed_t * lwal ,
fixed_t yrepeat , const BYTE * ( * getcol ) ( FTexture * tex , int x ) )
{
int x , shiftval ;
BYTE * p ;
int y1ve [ 4 ] , y2ve [ 4 ] , u4 , d4 , startx , dax , z ;
char bad ;
2016-04-15 00:14:04 +00:00
float light = rw_light - rw_lightstep ;
2016-03-01 15:47:10 +00:00
SDWORD texturemid , xoffset ;
BYTE * basecolormapdata ;
if ( rw_pic - > UseType = = FTexture : : TEX_Null )
{
return ;
}
if ( ! rw_pic - > bMasked )
{ // Textures that aren't masked can use the faster wallscan.
wallscan ( x1 , x2 , uwal , dwal , swal , lwal , yrepeat , getcol ) ;
return ;
}
//extern cycle_t WallScanCycles;
//clock (WallScanCycles);
rw_pic - > GetHeight ( ) ; // Make sure texture size is loaded
shiftval = rw_pic - > HeightBits ;
setupmvline ( 32 - shiftval ) ;
yrepeat > > = 2 + shiftval ;
texturemid = dc_texturemid < < ( 16 - shiftval ) ;
xoffset = rw_offset ;
basecolormapdata = basecolormap - > Maps ;
2016-04-14 17:40:14 +00:00
fixed_t centeryfrac = FLOAT2FIXED ( CenterY ) ;
2016-03-01 15:47:10 +00:00
x = startx = x1 ;
p = x + dc_destorg ;
bool fixed = ( fixedcolormap ! = NULL | | fixedlightlev > = 0 ) ;
if ( fixed )
{
palookupoffse [ 0 ] = dc_colormap ;
palookupoffse [ 1 ] = dc_colormap ;
palookupoffse [ 2 ] = dc_colormap ;
palookupoffse [ 3 ] = dc_colormap ;
}
for ( ; ( x < x2 ) & & ( ( size_t ) p & 3 ) ; + + x , + + p )
{
light + = rw_lightstep ;
y1ve [ 0 ] = uwal [ x ] ; //max(uwal[x],umost[x]);
y2ve [ 0 ] = dwal [ x ] ; //min(dwal[x],dmost[x]);
if ( y2ve [ 0 ] < = y1ve [ 0 ] ) continue ;
if ( ! fixed )
{ // calculate lighting
dc_colormap = basecolormapdata + ( GETPALOOKUP ( light , wallshade ) < < COLORMAPSHIFT ) ;
}
dc_source = getcol ( rw_pic , ( lwal [ x ] + xoffset ) > > FRACBITS ) ;
dc_dest = ylookup [ y1ve [ 0 ] ] + p ;
dc_iscale = swal [ x ] * yrepeat ;
dc_count = y2ve [ 0 ] - y1ve [ 0 ] ;
dc_texturefrac = texturemid + FixedMul ( dc_iscale , ( y1ve [ 0 ] < < FRACBITS ) - centeryfrac + FRACUNIT ) ;
domvline1 ( ) ;
}
for ( ; x < x2 - 3 ; x + = 4 , p + = 4 )
{
bad = 0 ;
for ( z = 3 , dax = x + 3 ; z > = 0 ; - - z , - - dax )
{
y1ve [ z ] = uwal [ dax ] ;
y2ve [ z ] = dwal [ dax ] ;
if ( y2ve [ z ] < = y1ve [ z ] ) { bad + = 1 < < z ; continue ; }
bufplce [ z ] = getcol ( rw_pic , ( lwal [ dax ] + xoffset ) > > FRACBITS ) ;
vince [ z ] = swal [ dax ] * yrepeat ;
vplce [ z ] = texturemid + FixedMul ( vince [ z ] , ( y1ve [ z ] < < FRACBITS ) - centeryfrac + FRACUNIT ) ;
}
if ( bad = = 15 )
{
2016-04-15 00:14:04 +00:00
light + = rw_lightstep * 4 ;
2016-03-01 15:47:10 +00:00
continue ;
}
if ( ! fixed )
{
for ( z = 0 ; z < 4 ; + + z )
{
light + = rw_lightstep ;
palookupoffse [ z ] = basecolormapdata + ( GETPALOOKUP ( light , wallshade ) < < COLORMAPSHIFT ) ;
}
}
u4 = MAX ( MAX ( y1ve [ 0 ] , y1ve [ 1 ] ) , MAX ( y1ve [ 2 ] , y1ve [ 3 ] ) ) ;
d4 = MIN ( MIN ( y2ve [ 0 ] , y2ve [ 1 ] ) , MIN ( y2ve [ 2 ] , y2ve [ 3 ] ) ) ;
if ( ( bad ! = 0 ) | | ( u4 > = d4 ) )
{
for ( z = 0 ; z < 4 ; + + z )
{
if ( ! ( bad & 1 ) )
{
mvline1 ( vince [ z ] , palookupoffse [ z ] , y2ve [ z ] - y1ve [ z ] , vplce [ z ] , bufplce [ z ] , ylookup [ y1ve [ z ] ] + p + z ) ;
}
bad > > = 1 ;
}
continue ;
}
for ( z = 0 ; z < 4 ; + + z )
{
if ( u4 > y1ve [ z ] )
{
vplce [ z ] = mvline1 ( vince [ z ] , palookupoffse [ z ] , u4 - y1ve [ z ] , vplce [ z ] , bufplce [ z ] , ylookup [ y1ve [ z ] ] + p + z ) ;
}
}
if ( d4 > u4 )
{
dc_count = d4 - u4 ;
dc_dest = ylookup [ u4 ] + p ;
domvline4 ( ) ;
}
BYTE * i = p + ylookup [ d4 ] ;
for ( z = 0 ; z < 4 ; + + z )
{
if ( y2ve [ z ] > d4 )
{
mvline1 ( vince [ z ] , palookupoffse [ 0 ] , y2ve [ z ] - d4 , vplce [ z ] , bufplce [ z ] , i + z ) ;
}
}
}
for ( ; x < x2 ; + + x , + + p )
{
light + = rw_lightstep ;
y1ve [ 0 ] = uwal [ x ] ;
y2ve [ 0 ] = dwal [ x ] ;
if ( y2ve [ 0 ] < = y1ve [ 0 ] ) continue ;
if ( ! fixed )
{ // calculate lighting
dc_colormap = basecolormapdata + ( GETPALOOKUP ( light , wallshade ) < < COLORMAPSHIFT ) ;
}
dc_source = getcol ( rw_pic , ( lwal [ x ] + xoffset ) > > FRACBITS ) ;
dc_dest = ylookup [ y1ve [ 0 ] ] + p ;
dc_iscale = swal [ x ] * yrepeat ;
dc_count = y2ve [ 0 ] - y1ve [ 0 ] ;
dc_texturefrac = texturemid + FixedMul ( dc_iscale , ( y1ve [ 0 ] < < FRACBITS ) - centeryfrac + FRACUNIT ) ;
domvline1 ( ) ;
}
//unclock(WallScanCycles);
NetUpdate ( ) ;
}
inline void preptmvline1 ( fixed_t vince , BYTE * colormap , int count , fixed_t vplce , const BYTE * bufplce , BYTE * dest )
{
dc_iscale = vince ;
dc_colormap = colormap ;
dc_count = count ;
dc_texturefrac = vplce ;
dc_source = bufplce ;
dc_dest = dest ;
}
void transmaskwallscan ( int x1 , int x2 , short * uwal , short * dwal , fixed_t * swal , fixed_t * lwal ,
fixed_t yrepeat , const BYTE * ( * getcol ) ( FTexture * tex , int x ) )
{
fixed_t ( * tmvline1 ) ( ) ;
void ( * tmvline4 ) ( ) ;
int x , shiftval ;
BYTE * p ;
int y1ve [ 4 ] , y2ve [ 4 ] , u4 , d4 , startx , dax , z ;
char bad ;
2016-04-15 00:14:04 +00:00
float light = rw_light - rw_lightstep ;
2016-03-01 15:47:10 +00:00
SDWORD texturemid , xoffset ;
BYTE * basecolormapdata ;
if ( rw_pic - > UseType = = FTexture : : TEX_Null )
{
return ;
}
if ( ! R_GetTransMaskDrawers ( & tmvline1 , & tmvline4 ) )
{
// The current translucency is unsupported, so draw with regular maskwallscan instead.
maskwallscan ( x1 , x2 , uwal , dwal , swal , lwal , yrepeat , getcol ) ;
return ;
}
//extern cycle_t WallScanCycles;
//clock (WallScanCycles);
rw_pic - > GetHeight ( ) ; // Make sure texture size is loaded
shiftval = rw_pic - > HeightBits ;
setuptmvline ( 32 - shiftval ) ;
yrepeat > > = 2 + shiftval ;
texturemid = dc_texturemid < < ( 16 - shiftval ) ;
xoffset = rw_offset ;
basecolormapdata = basecolormap - > Maps ;
2016-04-14 17:40:14 +00:00
fixed_t centeryfrac = FLOAT2FIXED ( CenterY ) ;
2016-03-01 15:47:10 +00:00
x = startx = x1 ;
p = x + dc_destorg ;
bool fixed = ( fixedcolormap ! = NULL | | fixedlightlev > = 0 ) ;
if ( fixed )
{
palookupoffse [ 0 ] = dc_colormap ;
palookupoffse [ 1 ] = dc_colormap ;
palookupoffse [ 2 ] = dc_colormap ;
palookupoffse [ 3 ] = dc_colormap ;
}
for ( ; ( x < x2 ) & & ( ( size_t ) p & 3 ) ; + + x , + + p )
{
light + = rw_lightstep ;
y1ve [ 0 ] = uwal [ x ] ; //max(uwal[x],umost[x]);
y2ve [ 0 ] = dwal [ x ] ; //min(dwal[x],dmost[x]);
if ( y2ve [ 0 ] < = y1ve [ 0 ] ) continue ;
if ( ! fixed )
{ // calculate lighting
dc_colormap = basecolormapdata + ( GETPALOOKUP ( light , wallshade ) < < COLORMAPSHIFT ) ;
}
dc_source = getcol ( rw_pic , ( lwal [ x ] + xoffset ) > > FRACBITS ) ;
dc_dest = ylookup [ y1ve [ 0 ] ] + p ;
dc_iscale = swal [ x ] * yrepeat ;
dc_count = y2ve [ 0 ] - y1ve [ 0 ] ;
dc_texturefrac = texturemid + FixedMul ( dc_iscale , ( y1ve [ 0 ] < < FRACBITS ) - centeryfrac + FRACUNIT ) ;
tmvline1 ( ) ;
}
for ( ; x < x2 - 3 ; x + = 4 , p + = 4 )
{
bad = 0 ;
for ( z = 3 , dax = x + 3 ; z > = 0 ; - - z , - - dax )
{
y1ve [ z ] = uwal [ dax ] ;
y2ve [ z ] = dwal [ dax ] ;
if ( y2ve [ z ] < = y1ve [ z ] ) { bad + = 1 < < z ; continue ; }
bufplce [ z ] = getcol ( rw_pic , ( lwal [ dax ] + xoffset ) > > FRACBITS ) ;
vince [ z ] = swal [ dax ] * yrepeat ;
vplce [ z ] = texturemid + FixedMul ( vince [ z ] , ( y1ve [ z ] < < FRACBITS ) - centeryfrac + FRACUNIT ) ;
}
if ( bad = = 15 )
{
2016-04-15 00:14:04 +00:00
light + = rw_lightstep * 4 ;
2016-03-01 15:47:10 +00:00
continue ;
}
if ( ! fixed )
{
for ( z = 0 ; z < 4 ; + + z )
{
light + = rw_lightstep ;
palookupoffse [ z ] = basecolormapdata + ( GETPALOOKUP ( light , wallshade ) < < COLORMAPSHIFT ) ;
}
}
u4 = MAX ( MAX ( y1ve [ 0 ] , y1ve [ 1 ] ) , MAX ( y1ve [ 2 ] , y1ve [ 3 ] ) ) ;
d4 = MIN ( MIN ( y2ve [ 0 ] , y2ve [ 1 ] ) , MIN ( y2ve [ 2 ] , y2ve [ 3 ] ) ) ;
if ( ( bad ! = 0 ) | | ( u4 > = d4 ) )
{
for ( z = 0 ; z < 4 ; + + z )
{
if ( ! ( bad & 1 ) )
{
preptmvline1 ( vince [ z ] , palookupoffse [ z ] , y2ve [ z ] - y1ve [ z ] , vplce [ z ] , bufplce [ z ] , ylookup [ y1ve [ z ] ] + p + z ) ;
tmvline1 ( ) ;
}
bad > > = 1 ;
}
continue ;
}
for ( z = 0 ; z < 4 ; + + z )
{
if ( u4 > y1ve [ z ] )
{
preptmvline1 ( vince [ z ] , palookupoffse [ z ] , u4 - y1ve [ z ] , vplce [ z ] , bufplce [ z ] , ylookup [ y1ve [ z ] ] + p + z ) ;
vplce [ z ] = tmvline1 ( ) ;
}
}
if ( d4 > u4 )
{
dc_count = d4 - u4 ;
dc_dest = ylookup [ u4 ] + p ;
tmvline4 ( ) ;
}
BYTE * i = p + ylookup [ d4 ] ;
for ( z = 0 ; z < 4 ; + + z )
{
if ( y2ve [ z ] > d4 )
{
preptmvline1 ( vince [ z ] , palookupoffse [ 0 ] , y2ve [ z ] - d4 , vplce [ z ] , bufplce [ z ] , i + z ) ;
tmvline1 ( ) ;
}
}
}
for ( ; x < x2 ; + + x , + + p )
{
light + = rw_lightstep ;
y1ve [ 0 ] = uwal [ x ] ;
y2ve [ 0 ] = dwal [ x ] ;
if ( y2ve [ 0 ] < = y1ve [ 0 ] ) continue ;
if ( ! fixed )
{ // calculate lighting
dc_colormap = basecolormapdata + ( GETPALOOKUP ( light , wallshade ) < < COLORMAPSHIFT ) ;
}
dc_source = getcol ( rw_pic , ( lwal [ x ] + xoffset ) > > FRACBITS ) ;
dc_dest = ylookup [ y1ve [ 0 ] ] + p ;
dc_iscale = swal [ x ] * yrepeat ;
dc_count = y2ve [ 0 ] - y1ve [ 0 ] ;
dc_texturefrac = texturemid + FixedMul ( dc_iscale , ( y1ve [ 0 ] < < FRACBITS ) - centeryfrac + FRACUNIT ) ;
tmvline1 ( ) ;
}
//unclock(WallScanCycles);
NetUpdate ( ) ;
}
//
// R_RenderSegLoop
// Draws zero, one, or two textures for walls.
// Can draw or mark the starting pixel of floor and ceiling textures.
// CALLED: CORE LOOPING ROUTINE.
//
// [RH] Rewrote this to use Build's wallscan, so it's quite far
// removed from the original Doom routine.
//
void R_RenderSegLoop ( )
{
int x1 = rw_x ;
int x2 = rw_stopx ;
int x ;
2016-04-14 17:40:14 +00:00
double xscale ;
fixed_t yscale ;
2016-03-01 15:47:10 +00:00
fixed_t xoffset = rw_offset ;
if ( fixedlightlev > = 0 )
dc_colormap = basecolormap - > Maps + fixedlightlev ;
else if ( fixedcolormap ! = NULL )
dc_colormap = fixedcolormap ;
// clip wall to the floor and ceiling
for ( x = x1 ; x < x2 ; + + x )
{
if ( walltop [ x ] < ceilingclip [ x ] )
{
walltop [ x ] = ceilingclip [ x ] ;
}
if ( wallbottom [ x ] > floorclip [ x ] )
{
wallbottom [ x ] = floorclip [ x ] ;
}
}
// mark ceiling areas
if ( markceiling )
{
for ( x = x1 ; x < x2 ; + + x )
{
short top = ( fakeFloor & & fake3D & 2 ) ? fakeFloor - > ceilingclip [ x ] : ceilingclip [ x ] ;
short bottom = MIN ( walltop [ x ] , floorclip [ x ] ) ;
if ( top < bottom )
{
ceilingplane - > top [ x ] = top ;
ceilingplane - > bottom [ x ] = bottom ;
}
}
}
// mark floor areas
if ( markfloor )
{
for ( x = x1 ; x < x2 ; + + x )
{
short top = MAX ( wallbottom [ x ] , ceilingclip [ x ] ) ;
short bottom = ( fakeFloor & & fake3D & 1 ) ? fakeFloor - > floorclip [ x ] : floorclip [ x ] ;
if ( top < bottom )
{
assert ( bottom < = viewheight ) ;
floorplane - > top [ x ] = top ;
floorplane - > bottom [ x ] = bottom ;
}
}
}
// kg3D - fake planes clipping
if ( fake3D & FAKE3D_REFRESHCLIP )
{
if ( fake3D & FAKE3D_CLIPBOTFRONT )
{
memcpy ( fakeFloor - > floorclip + x1 , wallbottom + x1 , ( x2 - x1 ) * sizeof ( short ) ) ;
}
else
{
for ( x = x1 ; x < x2 ; + + x )
{
walllower [ x ] = MIN ( MAX ( walllower [ x ] , ceilingclip [ x ] ) , wallbottom [ x ] ) ;
}
memcpy ( fakeFloor - > floorclip + x1 , walllower + x1 , ( x2 - x1 ) * sizeof ( short ) ) ;
}
if ( fake3D & FAKE3D_CLIPTOPFRONT )
{
memcpy ( fakeFloor - > ceilingclip + x1 , walltop + x1 , ( x2 - x1 ) * sizeof ( short ) ) ;
}
else
{
for ( x = x1 ; x < x2 ; + + x )
{
wallupper [ x ] = MAX ( MIN ( wallupper [ x ] , floorclip [ x ] ) , walltop [ x ] ) ;
}
memcpy ( fakeFloor - > ceilingclip + x1 , wallupper + x1 , ( x2 - x1 ) * sizeof ( short ) ) ;
}
}
if ( fake3D & 7 ) return ;
// draw the wall tiers
if ( midtexture )
{ // one sided line
if ( midtexture - > UseType ! = FTexture : : TEX_Null & & viewactive )
{
dc_texturemid = rw_midtexturemid ;
rw_pic = midtexture ;
2016-04-14 17:40:14 +00:00
xscale = rw_pic - > Scale . X * rw_midtexturescalex ;
yscale = FLOAT2FIXED ( rw_pic - > Scale . Y * rw_midtexturescaley ) ;
2016-03-01 15:47:10 +00:00
if ( xscale ! = lwallscale )
{
PrepLWall ( lwall , curline - > sidedef - > TexelLength * xscale , WallC . sx1 , WallC . sx2 ) ;
lwallscale = xscale ;
}
if ( midtexture - > bWorldPanning )
{
2016-04-14 17:40:14 +00:00
rw_offset = xs_RoundToInt ( rw_offset_mid * xscale ) ;
2016-03-01 15:47:10 +00:00
}
else
{
rw_offset = rw_offset_mid ;
}
if ( xscale < 0 )
{
rw_offset = - rw_offset ;
}
if ( rw_pic - > GetHeight ( ) ! = 1 < < rw_pic - > HeightBits )
{
wallscan_np2 ( x1 , x2 , walltop , wallbottom , swall , lwall , yscale , MAX ( rw_frontcz1 , rw_frontcz2 ) , MIN ( rw_frontfz1 , rw_frontfz2 ) , false ) ;
}
else
{
call_wallscan ( x1 , x2 , walltop , wallbottom , swall , lwall , yscale , false ) ;
}
}
clearbufshort ( ceilingclip + x1 , x2 - x1 , viewheight ) ;
clearbufshort ( floorclip + x1 , x2 - x1 , 0xffff ) ;
}
else
{ // two sided line
if ( toptexture ! = NULL & & toptexture - > UseType ! = FTexture : : TEX_Null )
{ // top wall
for ( x = x1 ; x < x2 ; + + x )
{
wallupper [ x ] = MAX ( MIN ( wallupper [ x ] , floorclip [ x ] ) , walltop [ x ] ) ;
}
if ( viewactive )
{
dc_texturemid = rw_toptexturemid ;
rw_pic = toptexture ;
2016-04-14 17:40:14 +00:00
xscale = rw_pic - > Scale . X * rw_toptexturescalex ;
yscale = FLOAT2FIXED ( rw_pic - > Scale . Y * rw_toptexturescaley ) ;
2016-03-01 15:47:10 +00:00
if ( xscale ! = lwallscale )
{
PrepLWall ( lwall , curline - > sidedef - > TexelLength * xscale , WallC . sx1 , WallC . sx2 ) ;
lwallscale = xscale ;
}
if ( toptexture - > bWorldPanning )
{
2016-04-14 17:40:14 +00:00
rw_offset = xs_RoundToInt ( rw_offset_top * xscale ) ;
2016-03-01 15:47:10 +00:00
}
else
{
rw_offset = rw_offset_top ;
}
if ( xscale < 0 )
{
rw_offset = - rw_offset ;
}
if ( rw_pic - > GetHeight ( ) ! = 1 < < rw_pic - > HeightBits )
{
wallscan_np2 ( x1 , x2 , walltop , wallupper , swall , lwall , yscale , MAX ( rw_frontcz1 , rw_frontcz2 ) , MIN ( rw_backcz1 , rw_backcz2 ) , false ) ;
}
else
{
call_wallscan ( x1 , x2 , walltop , wallupper , swall , lwall , yscale , false ) ;
}
}
memcpy ( ceilingclip + x1 , wallupper + x1 , ( x2 - x1 ) * sizeof ( short ) ) ;
}
else if ( markceiling )
{ // no top wall
memcpy ( ceilingclip + x1 , walltop + x1 , ( x2 - x1 ) * sizeof ( short ) ) ;
}
if ( bottomtexture ! = NULL & & bottomtexture - > UseType ! = FTexture : : TEX_Null )
{ // bottom wall
for ( x = x1 ; x < x2 ; + + x )
{
walllower [ x ] = MIN ( MAX ( walllower [ x ] , ceilingclip [ x ] ) , wallbottom [ x ] ) ;
}
if ( viewactive )
{
dc_texturemid = rw_bottomtexturemid ;
rw_pic = bottomtexture ;
2016-04-14 17:40:14 +00:00
xscale = rw_pic - > Scale . X * rw_bottomtexturescalex ;
yscale = FLOAT2FIXED ( rw_pic - > Scale . Y * rw_bottomtexturescaley ) ;
2016-03-01 15:47:10 +00:00
if ( xscale ! = lwallscale )
{
PrepLWall ( lwall , curline - > sidedef - > TexelLength * xscale , WallC . sx1 , WallC . sx2 ) ;
lwallscale = xscale ;
}
if ( bottomtexture - > bWorldPanning )
{
2016-04-14 17:40:14 +00:00
rw_offset = xs_RoundToInt ( rw_offset_bottom * xscale ) ;
2016-03-01 15:47:10 +00:00
}
else
{
rw_offset = rw_offset_bottom ;
}
if ( xscale < 0 )
{
rw_offset = - rw_offset ;
}
if ( rw_pic - > GetHeight ( ) ! = 1 < < rw_pic - > HeightBits )
{
wallscan_np2 ( x1 , x2 , walllower , wallbottom , swall , lwall , yscale , MAX ( rw_backfz1 , rw_backfz2 ) , MIN ( rw_frontfz1 , rw_frontfz2 ) , false ) ;
}
else
{
call_wallscan ( x1 , x2 , walllower , wallbottom , swall , lwall , yscale , false ) ;
}
}
memcpy ( floorclip + x1 , walllower + x1 , ( x2 - x1 ) * sizeof ( short ) ) ;
}
else if ( markfloor )
{ // no bottom wall
memcpy ( floorclip + x1 , wallbottom + x1 , ( x2 - x1 ) * sizeof ( short ) ) ;
}
}
rw_offset = xoffset ;
}
void R_NewWall ( bool needlights )
{
2016-04-14 17:40:14 +00:00
fixed_t rowoffset ;
double yrepeat ;
2016-03-01 15:47:10 +00:00
rw_markportal = false ;
sidedef = curline - > sidedef ;
linedef = curline - > linedef ;
// mark the segment as visible for auto map
if ( ! r_dontmaplines ) linedef - > flags | = ML_MAPPED ;
midtexture = toptexture = bottomtexture = 0 ;
if ( sidedef = = linedef - > sidedef [ 0 ] & &
( linedef - > isVisualPortal ( ) | | ( linedef - > special = = Line_Mirror & & r_drawmirrors ) ) ) // [ZZ] compatibility with r_drawmirrors cvar that existed way before portals
{
markfloor = markceiling = true ; // act like an one-sided wall here (todo: check how does this work with transparency)
rw_markportal = true ;
}
else if ( backsector = = NULL )
{
// single sided line
// a single sided line is terminal, so it must mark ends
markfloor = markceiling = true ;
// [RH] Horizon lines do not need to be textured
if ( linedef - > special ! = Line_Horizon )
{
midtexture = TexMan ( sidedef - > GetTexture ( side_t : : mid ) , true ) ;
rw_offset_mid = sidedef - > GetTextureXOffset ( side_t : : mid ) ;
rowoffset = sidedef - > GetTextureYOffset ( side_t : : mid ) ;
2016-04-14 17:40:14 +00:00
rw_midtexturescalex = FIXED2DBL ( sidedef - > GetTextureXScale ( side_t : : mid ) ) ;
rw_midtexturescaley = FIXED2DBL ( sidedef - > GetTextureYScale ( side_t : : mid ) ) ;
yrepeat = midtexture - > Scale . Y * rw_midtexturescaley ;
2016-03-01 15:47:10 +00:00
if ( yrepeat > = 0 )
{ // normal orientation
if ( linedef - > flags & ML_DONTPEGBOTTOM )
{ // bottom of texture at bottom
2016-04-14 17:40:14 +00:00
rw_midtexturemid = FLOAT2FIXED ( ( frontsector - > GetPlaneTexZF ( sector_t : : floor ) - ViewPos . Z ) * yrepeat + midtexture - > GetHeight ( ) ) ;
2016-03-01 15:47:10 +00:00
}
else
{ // top of texture at top
2016-04-14 17:40:14 +00:00
rw_midtexturemid = FLOAT2FIXED ( ( frontsector - > GetPlaneTexZF ( sector_t : : ceiling ) - ViewPos . Z ) * yrepeat ) ;
2016-03-01 15:47:10 +00:00
if ( rowoffset < 0 & & midtexture ! = NULL )
{
rowoffset + = midtexture - > GetHeight ( ) < < FRACBITS ;
}
}
}
else
{ // upside down
rowoffset = - rowoffset ;
if ( linedef - > flags & ML_DONTPEGBOTTOM )
{ // top of texture at bottom
2016-04-14 17:40:14 +00:00
rw_midtexturemid = FLOAT2FIXED ( ( frontsector - > GetPlaneTexZF ( sector_t : : floor ) - ViewPos . Z ) * yrepeat ) ;
2016-03-01 15:47:10 +00:00
}
else
{ // bottom of texture at top
2016-04-14 17:40:14 +00:00
rw_midtexturemid = FLOAT2FIXED ( ( frontsector - > GetPlaneTexZ ( sector_t : : ceiling ) - ViewPos . Z ) * yrepeat + midtexture - > GetHeight ( ) ) ;
2016-03-01 15:47:10 +00:00
}
}
if ( midtexture - > bWorldPanning )
{
2016-04-14 17:40:14 +00:00
rw_midtexturemid + = xs_FloorToInt ( rowoffset * yrepeat ) ;
2016-03-01 15:47:10 +00:00
}
else
{
// rowoffset is added outside the multiply so that it positions the texture
// by texels instead of world units.
rw_midtexturemid + = rowoffset ;
}
}
}
else
{ // two-sided line
// hack to allow height changes in outdoor areas
2016-04-14 17:40:14 +00:00
rw_frontlowertop = frontsector - > GetPlaneTexZF ( sector_t : : ceiling ) ;
2016-03-01 15:47:10 +00:00
if ( frontsector - > GetTexture ( sector_t : : ceiling ) = = skyflatnum & &
backsector - > GetTexture ( sector_t : : ceiling ) = = skyflatnum )
{
if ( rw_havehigh )
{ // front ceiling is above back ceiling
memcpy ( & walltop [ WallC . sx1 ] , & wallupper [ WallC . sx1 ] , ( WallC . sx2 - WallC . sx1 ) * sizeof ( walltop [ 0 ] ) ) ;
rw_havehigh = false ;
}
else if ( rw_havelow & & frontsector - > ceilingplane ! = backsector - > ceilingplane )
{ // back ceiling is above front ceiling
// The check for rw_havelow is not Doom-compliant, but it avoids HoM that
// would otherwise occur because there is space made available for this
// wall but nothing to draw for it.
// Recalculate walltop so that the wall is clipped by the back sector's
// ceiling instead of the front sector's ceiling.
WallMost ( walltop , backsector - > ceilingplane , & WallC ) ;
}
// Putting sky ceilings on the front and back of a line alters the way unpegged
// positioning works.
2016-04-14 17:40:14 +00:00
rw_frontlowertop = backsector - > GetPlaneTexZF ( sector_t : : ceiling ) ;
2016-03-01 15:47:10 +00:00
}
if ( ( rw_backcz1 < = rw_frontfz1 & & rw_backcz2 < = rw_frontfz2 ) | |
( rw_backfz1 > = rw_frontcz1 & & rw_backfz2 > = rw_frontcz2 ) )
{
// closed door
markceiling = markfloor = true ;
}
else
{
markfloor = rw_mustmarkfloor
| | backsector - > floorplane ! = frontsector - > floorplane
| | backsector - > lightlevel ! = frontsector - > lightlevel
| | backsector - > GetTexture ( sector_t : : floor ) ! = frontsector - > GetTexture ( sector_t : : floor )
// killough 3/7/98: Add checks for (x,y) offsets
| | backsector - > GetXOffset ( sector_t : : floor ) ! = frontsector - > GetXOffset ( sector_t : : floor )
| | backsector - > GetYOffset ( sector_t : : floor ) ! = frontsector - > GetYOffset ( sector_t : : floor )
| | backsector - > GetAlpha ( sector_t : : floor ) ! = frontsector - > GetAlpha ( sector_t : : floor )
// killough 4/15/98: prevent 2s normals
// from bleeding through deep water
| | frontsector - > heightsec
| | backsector - > GetPlaneLight ( sector_t : : floor ) ! = frontsector - > GetPlaneLight ( sector_t : : floor )
| | backsector - > GetFlags ( sector_t : : floor ) ! = frontsector - > GetFlags ( sector_t : : floor )
// [RH] Add checks for colormaps
| | backsector - > ColorMap ! = frontsector - > ColorMap
| | backsector - > GetXScale ( sector_t : : floor ) ! = frontsector - > GetXScale ( sector_t : : floor )
| | backsector - > GetYScale ( sector_t : : floor ) ! = frontsector - > GetYScale ( sector_t : : floor )
| | backsector - > GetAngle ( sector_t : : floor ) ! = frontsector - > GetAngle ( sector_t : : floor )
// kg3D - add fake lights
| | ( frontsector - > e & & frontsector - > e - > XFloor . lightlist . Size ( ) )
| | ( backsector - > e & & backsector - > e - > XFloor . lightlist . Size ( ) )
| | ( sidedef - > GetTexture ( side_t : : mid ) . isValid ( ) & &
( ( linedef - > flags & ( ML_CLIP_MIDTEX | ML_WRAP_MIDTEX ) ) | |
( sidedef - > Flags & ( WALLF_CLIP_MIDTEX | WALLF_WRAP_MIDTEX ) ) ) )
;
markceiling = ( frontsector - > GetTexture ( sector_t : : ceiling ) ! = skyflatnum | |
backsector - > GetTexture ( sector_t : : ceiling ) ! = skyflatnum ) & &
( rw_mustmarkceiling
| | backsector - > ceilingplane ! = frontsector - > ceilingplane
| | backsector - > lightlevel ! = frontsector - > lightlevel
| | backsector - > GetTexture ( sector_t : : ceiling ) ! = frontsector - > GetTexture ( sector_t : : ceiling )
// killough 3/7/98: Add checks for (x,y) offsets
| | backsector - > GetXOffset ( sector_t : : ceiling ) ! = frontsector - > GetXOffset ( sector_t : : ceiling )
| | backsector - > GetYOffset ( sector_t : : ceiling ) ! = frontsector - > GetYOffset ( sector_t : : ceiling )
| | backsector - > GetAlpha ( sector_t : : ceiling ) ! = frontsector - > GetAlpha ( sector_t : : ceiling )
// killough 4/15/98: prevent 2s normals
// from bleeding through fake ceilings
| | ( frontsector - > heightsec & & frontsector - > GetTexture ( sector_t : : ceiling ) ! = skyflatnum )
| | backsector - > GetPlaneLight ( sector_t : : ceiling ) ! = frontsector - > GetPlaneLight ( sector_t : : ceiling )
| | backsector - > GetFlags ( sector_t : : ceiling ) ! = frontsector - > GetFlags ( sector_t : : ceiling )
// [RH] Add check for colormaps
| | backsector - > ColorMap ! = frontsector - > ColorMap
| | backsector - > GetXScale ( sector_t : : ceiling ) ! = frontsector - > GetXScale ( sector_t : : ceiling )
| | backsector - > GetYScale ( sector_t : : ceiling ) ! = frontsector - > GetYScale ( sector_t : : ceiling )
| | backsector - > GetAngle ( sector_t : : ceiling ) ! = frontsector - > GetAngle ( sector_t : : ceiling )
// kg3D - add fake lights
| | ( frontsector - > e & & frontsector - > e - > XFloor . lightlist . Size ( ) )
| | ( backsector - > e & & backsector - > e - > XFloor . lightlist . Size ( ) )
| | ( sidedef - > GetTexture ( side_t : : mid ) . isValid ( ) & &
( ( linedef - > flags & ( ML_CLIP_MIDTEX | ML_WRAP_MIDTEX ) ) | |
( sidedef - > Flags & ( WALLF_CLIP_MIDTEX | WALLF_WRAP_MIDTEX ) ) ) )
) ;
}
if ( rw_havehigh )
{ // top texture
toptexture = TexMan ( sidedef - > GetTexture ( side_t : : top ) , true ) ;
rw_offset_top = sidedef - > GetTextureXOffset ( side_t : : top ) ;
rowoffset = sidedef - > GetTextureYOffset ( side_t : : top ) ;
2016-04-14 17:40:14 +00:00
rw_toptexturescalex = FIXED2DBL ( sidedef - > GetTextureXScale ( side_t : : top ) ) ;
rw_toptexturescaley = FIXED2DBL ( sidedef - > GetTextureYScale ( side_t : : top ) ) ;
yrepeat = toptexture - > Scale . Y * rw_toptexturescaley ;
2016-03-01 15:47:10 +00:00
if ( yrepeat > = 0 )
{ // normal orientation
if ( linedef - > flags & ML_DONTPEGTOP )
{ // top of texture at top
2016-04-14 17:40:14 +00:00
rw_toptexturemid = FLOAT2FIXED ( ( frontsector - > GetPlaneTexZF ( sector_t : : ceiling ) - ViewPos . Z ) * yrepeat ) ;
2016-03-01 15:47:10 +00:00
if ( rowoffset < 0 & & toptexture ! = NULL )
{
rowoffset + = toptexture - > GetHeight ( ) < < FRACBITS ;
}
}
else
{ // bottom of texture at bottom
2016-04-14 17:40:14 +00:00
rw_toptexturemid = FLOAT2FIXED ( ( backsector - > GetPlaneTexZF ( sector_t : : ceiling ) - ViewPos . Z ) * yrepeat + toptexture - > GetHeight ( ) ) ;
2016-03-01 15:47:10 +00:00
}
}
else
{ // upside down
rowoffset = - rowoffset ;
if ( linedef - > flags & ML_DONTPEGTOP )
{ // bottom of texture at top
2016-04-14 17:40:14 +00:00
rw_toptexturemid = FLOAT2FIXED ( ( frontsector - > GetPlaneTexZF ( sector_t : : ceiling ) - ViewPos . Z ) * yrepeat + toptexture - > GetHeight ( ) ) ;
2016-03-01 15:47:10 +00:00
}
else
{ // top of texture at bottom
2016-04-14 17:40:14 +00:00
rw_toptexturemid = FLOAT2FIXED ( ( backsector - > GetPlaneTexZF ( sector_t : : ceiling ) - ViewPos . Z ) * yrepeat ) ;
2016-03-01 15:47:10 +00:00
}
}
if ( toptexture - > bWorldPanning )
{
2016-04-14 17:40:14 +00:00
rw_toptexturemid + = xs_FloorToInt ( rowoffset * yrepeat ) ;
2016-03-01 15:47:10 +00:00
}
else
{
rw_toptexturemid + = rowoffset ;
}
}
if ( rw_havelow )
{ // bottom texture
bottomtexture = TexMan ( sidedef - > GetTexture ( side_t : : bottom ) , true ) ;
rw_offset_bottom = sidedef - > GetTextureXOffset ( side_t : : bottom ) ;
rowoffset = sidedef - > GetTextureYOffset ( side_t : : bottom ) ;
2016-04-14 17:40:14 +00:00
rw_bottomtexturescalex = FIXED2DBL ( sidedef - > GetTextureXScale ( side_t : : bottom ) ) ;
rw_bottomtexturescaley = FIXED2DBL ( sidedef - > GetTextureYScale ( side_t : : bottom ) ) ;
2016-03-26 12:37:44 +00:00
yrepeat = fixed_t ( bottomtexture - > Scale . Y * rw_bottomtexturescaley ) ;
2016-03-01 15:47:10 +00:00
if ( yrepeat > = 0 )
{ // normal orientation
if ( linedef - > flags & ML_DONTPEGBOTTOM )
{ // bottom of texture at bottom
2016-04-14 17:40:14 +00:00
rw_bottomtexturemid = FLOAT2FIXED ( ( rw_frontlowertop - ViewPos . Z ) * yrepeat ) ;
2016-03-01 15:47:10 +00:00
}
else
{ // top of texture at top
2016-04-14 17:40:14 +00:00
rw_bottomtexturemid = FLOAT2FIXED ( ( backsector - > GetPlaneTexZF ( sector_t : : floor ) - ViewPos . Z ) * yrepeat ) ;
2016-03-01 15:47:10 +00:00
if ( rowoffset < 0 & & bottomtexture ! = NULL )
{
rowoffset + = bottomtexture - > GetHeight ( ) < < FRACBITS ;
}
}
}
else
{ // upside down
rowoffset = - rowoffset ;
if ( linedef - > flags & ML_DONTPEGBOTTOM )
{ // top of texture at bottom
2016-04-14 17:40:14 +00:00
rw_bottomtexturemid = FLOAT2FIXED ( ( rw_frontlowertop - ViewPos . Z ) * yrepeat ) ;
2016-03-01 15:47:10 +00:00
}
else
{ // bottom of texture at top
2016-04-14 17:40:14 +00:00
rw_bottomtexturemid = FLOAT2FIXED ( ( backsector - > GetPlaneTexZ ( sector_t : : floor ) - ViewPos . Z ) * yrepeat + bottomtexture - > GetHeight ( ) ) ;
2016-03-01 15:47:10 +00:00
}
}
if ( bottomtexture - > bWorldPanning )
{
2016-04-14 17:40:14 +00:00
rw_bottomtexturemid + = xs_FloorToInt ( rowoffset * yrepeat ) ;
2016-03-01 15:47:10 +00:00
}
else
{
rw_bottomtexturemid + = rowoffset ;
}
}
}
// if a floor / ceiling plane is on the wrong side of the view plane,
// it is definitely invisible and doesn't need to be marked.
// killough 3/7/98: add deep water check
if ( frontsector - > GetHeightSec ( ) = = NULL )
{
int planeside ;
2016-04-14 17:40:14 +00:00
planeside = frontsector - > floorplane . PointOnSide ( ViewPos ) ;
2016-03-30 07:41:46 +00:00
if ( frontsector - > floorplane . fC ( ) < 0 ) // 3D floors have the floor backwards
2016-03-01 15:47:10 +00:00
planeside = - planeside ;
if ( planeside < = 0 ) // above view plane
markfloor = false ;
if ( frontsector - > GetTexture ( sector_t : : ceiling ) ! = skyflatnum )
{
2016-04-14 17:40:14 +00:00
planeside = frontsector - > ceilingplane . PointOnSide ( ViewPos ) ;
2016-03-30 07:41:46 +00:00
if ( frontsector - > ceilingplane . fC ( ) > 0 ) // 3D floors have the ceiling backwards
2016-03-01 15:47:10 +00:00
planeside = - planeside ;
if ( planeside < = 0 ) // below view plane
markceiling = false ;
}
}
FTexture * midtex = TexMan ( sidedef - > GetTexture ( side_t : : mid ) , true ) ;
segtextured = midtex ! = NULL | | toptexture ! = NULL | | bottomtexture ! = NULL ;
// calculate light table
if ( needlights & & ( segtextured | | ( backsector & & IsFogBoundary ( frontsector , backsector ) ) ) )
{
lwallscale =
2016-04-14 17:40:14 +00:00
midtex ? ( midtex - > Scale . X * sidedef - > GetTextureXScale ( side_t : : mid ) / 65536.0 ) :
toptexture ? ( toptexture - > Scale . X * sidedef - > GetTextureXScale ( side_t : : top ) / 65536.0 ) :
bottomtexture ? ( bottomtexture - > Scale . X * sidedef - > GetTextureXScale ( side_t : : bottom ) / 65536.0 ) :
2016-03-01 15:47:10 +00:00
FRACUNIT ;
PrepWall ( swall , lwall , sidedef - > TexelLength * lwallscale , WallC . sx1 , WallC . sx2 ) ;
if ( fixedcolormap = = NULL & & fixedlightlev < 0 )
{
wallshade = LIGHT2SHADE ( curline - > sidedef - > GetLightLevel ( foggy , frontsector - > lightlevel )
+ r_actualextralight ) ;
GlobVis = r_WallVisibility ;
2016-04-15 00:14:04 +00:00
rw_lightleft = float ( GlobVis / WallC . sz1 ) ;
rw_lightstep = float ( ( GlobVis / WallC . sz2 - rw_lightleft ) / ( WallC . sx2 - WallC . sx1 ) ) ;
2016-03-01 15:47:10 +00:00
}
else
{
2016-04-15 00:14:04 +00:00
rw_lightleft = 1 ;
2016-03-01 15:47:10 +00:00
rw_lightstep = 0 ;
}
}
}
//
// R_CheckDrawSegs
//
void R_CheckDrawSegs ( )
{
if ( ds_p = = & drawsegs [ MaxDrawSegs ] )
{ // [RH] Grab some more drawsegs
size_t newdrawsegs = MaxDrawSegs ? MaxDrawSegs * 2 : 32 ;
ptrdiff_t firstofs = firstdrawseg - drawsegs ;
drawsegs = ( drawseg_t * ) M_Realloc ( drawsegs , newdrawsegs * sizeof ( drawseg_t ) ) ;
firstdrawseg = drawsegs + firstofs ;
ds_p = drawsegs + MaxDrawSegs ;
MaxDrawSegs = newdrawsegs ;
DPrintf ( " MaxDrawSegs increased to %zu \n " , MaxDrawSegs ) ;
}
}
//
// R_CheckOpenings
//
ptrdiff_t R_NewOpening ( ptrdiff_t len )
{
ptrdiff_t res = lastopening ;
lastopening + = len ;
if ( ( size_t ) lastopening > maxopenings )
{
do
maxopenings = maxopenings ? maxopenings * 2 : 16384 ;
while ( ( size_t ) lastopening > maxopenings ) ;
openings = ( short * ) M_Realloc ( openings , maxopenings * sizeof ( * openings ) ) ;
DPrintf ( " MaxOpenings increased to %zu \n " , maxopenings ) ;
}
return res ;
}
//
// R_StoreWallRange
// A wall segment will be drawn between start and stop pixels (inclusive).
//
void R_StoreWallRange ( int start , int stop )
{
int i ;
bool maskedtexture = false ;
# ifdef RANGECHECK
if ( start > = viewwidth | | start > = stop )
I_FatalError ( " Bad R_StoreWallRange: %i to %i " , start , stop ) ;
# endif
// don't overflow and crash
R_CheckDrawSegs ( ) ;
if ( ! rw_prepped )
{
rw_prepped = true ;
R_NewWall ( true ) ;
}
rw_offset = sidedef - > GetTextureXOffset ( side_t : : mid ) ;
rw_light = rw_lightleft + rw_lightstep * ( start - WallC . sx1 ) ;
ds_p - > CurrentPortalUniq = CurrentPortalUniq ;
ds_p - > sx1 = WallC . sx1 ;
ds_p - > sx2 = WallC . sx2 ;
ds_p - > sz1 = WallC . sz1 ;
ds_p - > sz2 = WallC . sz2 ;
2016-04-14 17:40:14 +00:00
ds_p - > cx = WallC . tleft . X ; ;
ds_p - > cy = WallC . tleft . Y ;
ds_p - > cdx = WallC . tright . X - WallC . tleft . X ;
ds_p - > cdy = WallC . tright . Y - WallC . tleft . Y ;
2016-03-01 15:47:10 +00:00
ds_p - > tmapvals = WallT ;
2016-04-14 17:40:14 +00:00
ds_p - > siz1 = 1 / WallC . sz1 ;
ds_p - > siz2 = 1 / WallC . sz2 ;
2016-03-01 15:47:10 +00:00
ds_p - > x1 = rw_x = start ;
ds_p - > x2 = stop ;
ds_p - > curline = curline ;
rw_stopx = stop ;
ds_p - > bFogBoundary = false ;
ds_p - > bFakeBoundary = false ;
if ( fake3D & 7 ) ds_p - > fake = 1 ;
else ds_p - > fake = 0 ;
// killough 1/6/98, 2/1/98: remove limit on openings
ds_p - > sprtopclip = ds_p - > sprbottomclip = ds_p - > maskedtexturecol = ds_p - > bkup = ds_p - > swall = - 1 ;
if ( rw_markportal )
{
ds_p - > silhouette = SIL_BOTH ;
}
else if ( backsector = = NULL )
{
ds_p - > sprtopclip = R_NewOpening ( stop - start ) ;
ds_p - > sprbottomclip = R_NewOpening ( stop - start ) ;
clearbufshort ( openings + ds_p - > sprtopclip , stop - start , viewheight ) ;
memset ( openings + ds_p - > sprbottomclip , - 1 , ( stop - start ) * sizeof ( short ) ) ;
ds_p - > silhouette = SIL_BOTH ;
}
else
{
// two sided line
ds_p - > silhouette = 0 ;
if ( rw_frontfz1 > rw_backfz1 | | rw_frontfz2 > rw_backfz2 | |
2016-04-14 17:40:14 +00:00
backsector - > floorplane . PointOnSide ( ViewPos ) < 0 )
2016-03-01 15:47:10 +00:00
{
ds_p - > silhouette = SIL_BOTTOM ;
}
if ( rw_frontcz1 < rw_backcz1 | | rw_frontcz2 < rw_backcz2 | |
2016-04-14 17:40:14 +00:00
backsector - > ceilingplane . PointOnSide ( ViewPos ) < 0 )
2016-03-01 15:47:10 +00:00
{
ds_p - > silhouette | = SIL_TOP ;
}
// killough 1/17/98: this test is required if the fix
// for the automap bug (r_bsp.c) is used, or else some
// sprites will be displayed behind closed doors. That
// fix prevents lines behind closed doors with dropoffs
// from being displayed on the automap.
//
// killough 4/7/98: make doorclosed external variable
{
extern int doorclosed ; // killough 1/17/98, 2/8/98, 4/7/98
if ( doorclosed | | ( rw_backcz1 < = rw_frontfz1 & & rw_backcz2 < = rw_frontfz2 ) )
{
ds_p - > sprbottomclip = R_NewOpening ( stop - start ) ;
memset ( openings + ds_p - > sprbottomclip , - 1 , ( stop - start ) * sizeof ( short ) ) ;
ds_p - > silhouette | = SIL_BOTTOM ;
}
if ( doorclosed | | ( rw_backfz1 > = rw_frontcz1 & & rw_backfz2 > = rw_frontcz2 ) )
{ // killough 1/17/98, 2/8/98
ds_p - > sprtopclip = R_NewOpening ( stop - start ) ;
clearbufshort ( openings + ds_p - > sprtopclip , stop - start , viewheight ) ;
ds_p - > silhouette | = SIL_TOP ;
}
}
if ( ! ds_p - > fake & & r_3dfloors & & backsector - > e & & backsector - > e - > XFloor . ffloors . Size ( ) ) {
for ( i = 0 ; i < ( int ) backsector - > e - > XFloor . ffloors . Size ( ) ; i + + ) {
F3DFloor * rover = backsector - > e - > XFloor . ffloors [ i ] ;
if ( rover - > flags & FF_RENDERSIDES & & ( ! ( rover - > flags & FF_INVERTSIDES ) | | rover - > flags & FF_ALLSIDES ) ) {
ds_p - > bFakeBoundary | = 1 ;
break ;
}
}
}
if ( ! ds_p - > fake & & r_3dfloors & & frontsector - > e & & frontsector - > e - > XFloor . ffloors . Size ( ) ) {
for ( i = 0 ; i < ( int ) frontsector - > e - > XFloor . ffloors . Size ( ) ; i + + ) {
F3DFloor * rover = frontsector - > e - > XFloor . ffloors [ i ] ;
if ( rover - > flags & FF_RENDERSIDES & & ( rover - > flags & FF_ALLSIDES | | rover - > flags & FF_INVERTSIDES ) ) {
ds_p - > bFakeBoundary | = 2 ;
break ;
}
}
}
// kg3D - no for fakes
if ( ! ds_p - > fake )
// allocate space for masked texture tables, if needed
// [RH] Don't just allocate the space; fill it in too.
if ( ( TexMan ( sidedef - > GetTexture ( side_t : : mid ) , true ) - > UseType ! = FTexture : : TEX_Null | | ds_p - > bFakeBoundary | | IsFogBoundary ( frontsector , backsector ) ) & &
( rw_ceilstat ! = 12 | | ! sidedef - > GetTexture ( side_t : : top ) . isValid ( ) ) & &
( rw_floorstat ! = 3 | | ! sidedef - > GetTexture ( side_t : : bottom ) . isValid ( ) ) & &
( WallC . sz1 > = TOO_CLOSE_Z & & WallC . sz2 > = TOO_CLOSE_Z ) )
{
fixed_t * swal ;
fixed_t * lwal ;
int i ;
maskedtexture = true ;
// kg3D - backup for mid and fake walls
ds_p - > bkup = R_NewOpening ( stop - start ) ;
memcpy ( openings + ds_p - > bkup , & ceilingclip [ start ] , sizeof ( short ) * ( stop - start ) ) ;
ds_p - > bFogBoundary = IsFogBoundary ( frontsector , backsector ) ;
if ( sidedef - > GetTexture ( side_t : : mid ) . isValid ( ) | | ds_p - > bFakeBoundary )
{
if ( sidedef - > GetTexture ( side_t : : mid ) . isValid ( ) )
ds_p - > bFakeBoundary | = 4 ; // it is also mid texture
ds_p - > maskedtexturecol = R_NewOpening ( ( stop - start ) * 2 ) ;
ds_p - > swall = R_NewOpening ( ( stop - start ) * 2 ) ;
lwal = ( fixed_t * ) ( openings + ds_p - > maskedtexturecol ) ;
swal = ( fixed_t * ) ( openings + ds_p - > swall ) ;
FTexture * pic = TexMan ( sidedef - > GetTexture ( side_t : : mid ) , true ) ;
2016-03-26 12:37:44 +00:00
fixed_t yrepeat = int ( pic - > Scale . X * sidedef - > GetTextureYScale ( side_t : : mid ) ) ;
2016-03-01 15:47:10 +00:00
fixed_t xoffset = sidedef - > GetTextureXOffset ( side_t : : mid ) ;
if ( pic - > bWorldPanning )
{
2016-04-14 17:40:14 +00:00
xoffset = xs_RoundToInt ( xoffset * lwallscale ) ;
2016-03-01 15:47:10 +00:00
}
for ( i = start ; i < stop ; i + + )
{
* lwal + + = lwall [ i ] + xoffset ;
* swal + + = swall [ i ] ;
}
fixed_t istart = MulScale18 ( * ( ( fixed_t * ) ( openings + ds_p - > swall ) ) , yrepeat ) ;
fixed_t iend = MulScale18 ( * ( swal - 1 ) , yrepeat ) ;
if ( istart < 3 & & istart > = 0 ) istart = 3 ;
if ( istart > - 3 & & istart < 0 ) istart = - 3 ;
if ( iend < 3 & & iend > = 0 ) iend = 3 ;
if ( iend > - 3 & & iend < 0 ) iend = - 3 ;
istart = DivScale32 ( 1 , istart ) ;
iend = DivScale32 ( 1 , iend ) ;
ds_p - > yrepeat = yrepeat ;
ds_p - > iscale = istart ;
if ( stop - start > 0 )
{
ds_p - > iscalestep = ( iend - istart ) / ( stop - start ) ;
}
else
{
ds_p - > iscalestep = 0 ;
}
}
ds_p - > light = rw_light ;
ds_p - > lightstep = rw_lightstep ;
// Masked midtextures should get the light level from the sector they reference,
// not from the current subsector, which is what the current wallshade value
// comes from. We make an exeption for polyobjects, however, since their "home"
// sector should be whichever one they move into.
if ( curline - > sidedef - > Flags & WALLF_POLYOBJ )
{
ds_p - > shade = wallshade ;
}
else
{
ds_p - > shade = LIGHT2SHADE ( curline - > sidedef - > GetLightLevel ( foggy , curline - > frontsector - > lightlevel )
+ r_actualextralight ) ;
}
if ( ds_p - > bFogBoundary | | ds_p - > maskedtexturecol ! = - 1 )
{
size_t drawsegnum = ds_p - drawsegs ;
InterestingDrawsegs . Push ( drawsegnum ) ;
}
}
}
// render it
if ( markceiling )
{
if ( ceilingplane )
{ // killough 4/11/98: add NULL ptr checks
ceilingplane = R_CheckPlane ( ceilingplane , start , stop ) ;
}
else
{
markceiling = false ;
}
}
if ( markfloor )
{
if ( floorplane )
{ // killough 4/11/98: add NULL ptr checks
floorplane = R_CheckPlane ( floorplane , start , stop ) ;
}
else
{
markfloor = false ;
}
}
R_RenderSegLoop ( ) ;
if ( fake3D & 7 ) {
ds_p + + ;
return ;
}
// save sprite clipping info
if ( ( ( ds_p - > silhouette & SIL_TOP ) | | maskedtexture ) & & ds_p - > sprtopclip = = - 1 )
{
ds_p - > sprtopclip = R_NewOpening ( stop - start ) ;
memcpy ( openings + ds_p - > sprtopclip , & ceilingclip [ start ] , sizeof ( short ) * ( stop - start ) ) ;
}
if ( ( ( ds_p - > silhouette & SIL_BOTTOM ) | | maskedtexture ) & & ds_p - > sprbottomclip = = - 1 )
{
ds_p - > sprbottomclip = R_NewOpening ( stop - start ) ;
memcpy ( openings + ds_p - > sprbottomclip , & floorclip [ start ] , sizeof ( short ) * ( stop - start ) ) ;
}
if ( maskedtexture & & curline - > sidedef - > GetTexture ( side_t : : mid ) . isValid ( ) )
{
ds_p - > silhouette | = SIL_TOP | SIL_BOTTOM ;
}
// [RH] Draw any decals bound to the seg
// [ZZ] Only if not an active mirror
if ( ! rw_markportal )
{
for ( DBaseDecal * decal = curline - > sidedef - > AttachedDecals ; decal ! = NULL ; decal = decal - > WallNext )
{
R_RenderDecal ( curline - > sidedef , decal , ds_p , 0 ) ;
}
}
if ( rw_markportal )
{
PortalDrawseg pds ;
pds . src = curline - > linedef ;
pds . dst = curline - > linedef - > special = = Line_Mirror ? curline - > linedef : curline - > linedef - > getPortalDestination ( ) ;
pds . x1 = ds_p - > x1 ;
pds . x2 = ds_p - > x2 ;
pds . len = pds . x2 - pds . x1 ;
pds . ceilingclip . Resize ( pds . len ) ;
memcpy ( & pds . ceilingclip [ 0 ] , openings + ds_p - > sprtopclip , pds . len * sizeof ( * openings ) ) ;
pds . floorclip . Resize ( pds . len ) ;
memcpy ( & pds . floorclip [ 0 ] , openings + ds_p - > sprbottomclip , pds . len * sizeof ( * openings ) ) ;
for ( int i = 0 ; i < pds . x2 - pds . x1 ; i + + )
{
if ( pds . ceilingclip [ i ] < 0 )
pds . ceilingclip [ i ] = 0 ;
2016-03-09 01:53:37 +00:00
if ( pds . ceilingclip [ i ] > = viewheight )
pds . ceilingclip [ i ] = viewheight - 1 ;
2016-03-01 15:47:10 +00:00
if ( pds . floorclip [ i ] < 0 )
pds . floorclip [ i ] = 0 ;
2016-03-09 01:53:37 +00:00
if ( pds . floorclip [ i ] > = viewheight )
pds . floorclip [ i ] = viewheight - 1 ;
2016-03-01 15:47:10 +00:00
}
pds . mirror = curline - > linedef - > special = = Line_Mirror ;
WallPortals . Push ( pds ) ;
}
ds_p + + ;
}
2016-04-14 17:40:14 +00:00
int OWallMost ( short * mostbuf , double z , const FWallCoords * wallc )
2016-03-01 15:47:10 +00:00
{
2016-04-14 17:40:14 +00:00
int bad , ix1 , ix2 ;
double y , iy1 , iy2 ;
double s1 , s2 , s3 , s4 ;
2016-03-01 15:47:10 +00:00
2016-04-14 17:40:14 +00:00
z = - z ;
s1 = globaluclip * wallc - > sz1 ; s2 = globaluclip * wallc - > sz2 ;
s3 = globaldclip * wallc - > sz1 ; s4 = globaldclip * wallc - > sz2 ;
2016-03-01 15:47:10 +00:00
bad = ( z < s1 ) + ( ( z < s2 ) < < 1 ) + ( ( z > s3 ) < < 2 ) + ( ( z > s4 ) < < 3 ) ;
# if 1
if ( ( bad & 3 ) = = 3 )
{
memset ( & mostbuf [ wallc - > sx1 ] , 0 , ( wallc - > sx2 - wallc - > sx1 ) * sizeof ( mostbuf [ 0 ] ) ) ;
return bad ;
}
if ( ( bad & 12 ) = = 12 )
{
clearbufshort ( & mostbuf [ wallc - > sx1 ] , wallc - > sx2 - wallc - > sx1 , viewheight ) ;
return bad ;
}
# endif
ix1 = wallc - > sx1 ; iy1 = wallc - > sz1 ;
ix2 = wallc - > sx2 ; iy2 = wallc - > sz2 ;
# if 1
if ( bad & 3 )
{
2016-04-14 17:40:14 +00:00
double t = ( z - s1 ) / ( s2 - s1 ) ;
double inty = wallc - > sz1 + t * ( wallc - > sz2 - wallc - > sz1 ) ;
int xcross = xs_RoundToInt ( wallc - > sx1 + ( t * wallc - > sz2 * ( wallc - > sx2 - wallc - > sx1 ) ) / inty ) ;
2016-03-01 15:47:10 +00:00
if ( ( bad & 3 ) = = 2 )
{
if ( wallc - > sx1 < = xcross ) { iy2 = inty ; ix2 = xcross ; }
if ( wallc - > sx2 > xcross ) memset ( & mostbuf [ xcross ] , 0 , ( wallc - > sx2 - xcross ) * sizeof ( mostbuf [ 0 ] ) ) ;
}
else
{
if ( xcross < = wallc - > sx2 ) { iy1 = inty ; ix1 = xcross ; }
if ( xcross > wallc - > sx1 ) memset ( & mostbuf [ wallc - > sx1 ] , 0 , ( xcross - wallc - > sx1 ) * sizeof ( mostbuf [ 0 ] ) ) ;
}
}
if ( bad & 12 )
{
2016-04-14 17:40:14 +00:00
double t = ( z - s3 ) / ( s4 - s3 ) ;
double inty = wallc - > sz1 + t * ( wallc - > sz2 - wallc - > sz1 ) ;
int xcross = xs_RoundToInt ( wallc - > sx1 + ( t * wallc - > sz2 * ( wallc - > sx2 - wallc - > sx1 ) ) / inty ) ;
2016-03-01 15:47:10 +00:00
if ( ( bad & 12 ) = = 8 )
{
if ( wallc - > sx1 < = xcross ) { iy2 = inty ; ix2 = xcross ; }
if ( wallc - > sx2 > xcross ) clearbufshort ( & mostbuf [ xcross ] , wallc - > sx2 - xcross , viewheight ) ;
}
else
{
if ( xcross < = wallc - > sx2 ) { iy1 = inty ; ix1 = xcross ; }
if ( xcross > wallc - > sx1 ) clearbufshort ( & mostbuf [ wallc - > sx1 ] , xcross - wallc - > sx1 , viewheight ) ;
}
}
2016-04-14 17:40:14 +00:00
y = z * InvZtoScale / iy1 ;
2016-03-01 15:47:10 +00:00
if ( ix2 = = ix1 )
{
2016-04-14 17:40:14 +00:00
mostbuf [ ix1 ] = ( short ) xs_RoundToInt ( y + CenterY ) ;
2016-03-01 15:47:10 +00:00
}
else
{
2016-04-14 17:40:14 +00:00
fixed_t yinc = FLOAT2FIXED ( ( ( z * InvZtoScale / iy2 ) - y ) / ( ix2 - ix1 ) ) ;
qinterpolatedown16short ( & mostbuf [ ix1 ] , ix2 - ix1 , FLOAT2FIXED ( y + CenterY ) , yinc ) ;
2016-03-01 15:47:10 +00:00
}
# else
double max = viewheight ;
double zz = z / 65536.0 ;
#if 0
double z1 = zz * InvZtoScale / wallc - > sz1 ;
double z2 = zz * InvZtoScale / wallc - > sz2 - z1 ;
z2 / = ( wallc - > sx2 - wallc - > sx1 ) ;
z1 + = centeryfrac / 65536.0 ;
for ( int x = wallc - > sx1 ; x < wallc - > sx2 ; + + x )
{
mostbuf [ x ] = xs_RoundToInt ( clamp ( z1 , 0.0 , max ) ) ;
z1 + = z2 ;
}
# else
double top , bot , i ;
i = wallc - > sx1 - centerx ;
top = WallT . UoverZorg + WallT . UoverZstep * i ;
bot = WallT . InvZorg + WallT . InvZstep * i ;
double cy = centeryfrac / 65536.0 ;
for ( int x = wallc - > sx1 ; x < wallc - > sx2 ; x + + )
{
double frac = top / bot ;
double scale = frac * WallT . DepthScale + WallT . DepthOrg ;
mostbuf [ x ] = xs_RoundToInt ( clamp ( zz / scale + cy , 0.0 , max ) ) ;
top + = WallT . UoverZstep ;
bot + = WallT . InvZstep ;
}
# endif
# endif
return bad ;
}
int WallMost ( short * mostbuf , const secplane_t & plane , const FWallCoords * wallc )
{
2016-03-29 10:40:41 +00:00
if ( ! plane . isSlope ( ) )
2016-03-01 15:47:10 +00:00
{
2016-04-14 17:40:14 +00:00
return OWallMost ( mostbuf , plane . Zat0 ( ) - ViewPos . Z , wallc ) ;
2016-03-01 15:47:10 +00:00
}
2016-04-14 17:40:14 +00:00
double x , y , den , z1 , z2 , oz1 , oz2 ;
double s1 , s2 , s3 , s4 ;
int bad , ix1 , ix2 ;
double iy1 , iy2 ;
2016-03-01 15:47:10 +00:00
if ( MirrorFlags & RF_XFLIP )
{
2016-04-14 17:40:14 +00:00
x = curline - > v2 - > fX ( ) ;
y = curline - > v2 - > fY ( ) ;
if ( wallc - > sx1 = = 0 & & 0 ! = ( den = wallc - > tleft . X - wallc - > tright . X + wallc - > tleft . Y - wallc - > tright . Y ) )
2016-03-01 15:47:10 +00:00
{
2016-04-14 17:40:14 +00:00
double frac = ( wallc - > tleft . Y + wallc - > tleft . X ) / den ;
x - = frac * ( x - curline - > v1 - > fX ( ) ) ;
y - = frac * ( y - curline - > v1 - > fY ( ) ) ;
2016-03-01 15:47:10 +00:00
}
2016-04-14 17:40:14 +00:00
z1 = ViewPos . Z - plane . ZatPoint ( x , y ) ;
2016-03-01 15:47:10 +00:00
if ( wallc - > sx2 > wallc - > sx1 + 1 )
{
2016-04-14 17:40:14 +00:00
x = curline - > v1 - > fX ( ) ;
y = curline - > v1 - > fY ( ) ;
if ( wallc - > sx2 = = viewwidth & & 0 ! = ( den = wallc - > tleft . X - wallc - > tright . X - wallc - > tleft . Y + wallc - > tright . Y ) )
2016-03-01 15:47:10 +00:00
{
2016-04-14 17:40:14 +00:00
double frac = ( wallc - > tright . Y - wallc - > tright . X ) / den ;
x + = frac * ( curline - > v2 - > fX ( ) - x ) ;
y + = frac * ( curline - > v2 - > fY ( ) - y ) ;
2016-03-01 15:47:10 +00:00
}
2016-04-14 17:40:14 +00:00
z2 = ViewPos . Z - plane . ZatPoint ( x , y ) ;
2016-03-01 15:47:10 +00:00
}
else
{
z2 = z1 ;
}
}
else
{
2016-04-14 17:40:14 +00:00
x = curline - > v1 - > fX ( ) ;
y = curline - > v1 - > fY ( ) ;
if ( wallc - > sx1 = = 0 & & 0 ! = ( den = wallc - > tleft . X - wallc - > tright . X + wallc - > tleft . Y - wallc - > tright . Y ) )
2016-03-01 15:47:10 +00:00
{
2016-04-14 17:40:14 +00:00
double frac = ( wallc - > tleft . Y + wallc - > tleft . X ) / den ;
x + = frac * ( curline - > v2 - > fX ( ) - x ) ;
y + = frac * ( curline - > v2 - > fY ( ) - y ) ;
2016-03-01 15:47:10 +00:00
}
2016-04-14 17:40:14 +00:00
z1 = ViewPos . Z - plane . ZatPoint ( x , y ) ;
2016-03-01 15:47:10 +00:00
if ( wallc - > sx2 > wallc - > sx1 + 1 )
{
2016-04-14 17:40:14 +00:00
x = curline - > v2 - > fX ( ) ;
y = curline - > v2 - > fY ( ) ;
if ( wallc - > sx2 = = viewwidth & & 0 ! = ( den = wallc - > tleft . X - wallc - > tright . X - wallc - > tleft . Y + wallc - > tright . Y ) )
2016-03-01 15:47:10 +00:00
{
2016-04-14 17:40:14 +00:00
double frac = ( wallc - > tright . Y - wallc - > tright . X ) / den ;
x - = frac * ( x - curline - > v1 - > fX ( ) ) ;
y - = frac * ( y - curline - > v1 - > fY ( ) ) ;
2016-03-01 15:47:10 +00:00
}
2016-04-14 17:40:14 +00:00
z2 = ViewPos . Z - plane . ZatPoint ( x , y ) ;
2016-03-01 15:47:10 +00:00
}
else
{
z2 = z1 ;
}
}
2016-04-14 17:40:14 +00:00
s1 = globaluclip * wallc - > sz1 ; s2 = globaluclip * wallc - > sz2 ;
s3 = globaldclip * wallc - > sz1 ; s4 = globaldclip * wallc - > sz2 ;
2016-03-01 15:47:10 +00:00
bad = ( z1 < s1 ) + ( ( z2 < s2 ) < < 1 ) + ( ( z1 > s3 ) < < 2 ) + ( ( z2 > s4 ) < < 3 ) ;
ix1 = wallc - > sx1 ; ix2 = wallc - > sx2 ;
iy1 = wallc - > sz1 ; iy2 = wallc - > sz2 ;
oz1 = z1 ; oz2 = z2 ;
if ( ( bad & 3 ) = = 3 )
{
memset ( & mostbuf [ ix1 ] , - 1 , ( ix2 - ix1 ) * sizeof ( mostbuf [ 0 ] ) ) ;
return bad ;
}
if ( ( bad & 12 ) = = 12 )
{
clearbufshort ( & mostbuf [ ix1 ] , ix2 - ix1 , viewheight ) ;
return bad ;
}
if ( bad & 3 )
{
//inty = intz / (globaluclip>>16)
2016-04-14 17:40:14 +00:00
double t = ( oz1 - s1 ) / ( s2 - s1 + oz1 - oz2 ) ;
double inty = wallc - > sz1 + t * ( wallc - > sz2 - wallc - > sz1 ) ;
double intz = oz1 + t * ( oz2 - oz1 ) ;
int xcross = wallc - > sx1 + xs_RoundToInt ( ( t * wallc - > sz2 * ( wallc - > sx2 - wallc - > sx1 ) ) / inty ) ;
2016-03-01 15:47:10 +00:00
//t = divscale30((x1<<4)-xcross*yb1[w],xcross*(yb2[w]-yb1[w])-((x2-x1)<<4));
//inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
//intz = z1 + mulscale30(z2-z1,t);
if ( ( bad & 3 ) = = 2 )
{
if ( wallc - > sx1 < = xcross ) { z2 = intz ; iy2 = inty ; ix2 = xcross ; }
memset ( & mostbuf [ xcross ] , 0 , ( wallc - > sx2 - xcross ) * sizeof ( mostbuf [ 0 ] ) ) ;
}
else
{
if ( xcross < = wallc - > sx2 ) { z1 = intz ; iy1 = inty ; ix1 = xcross ; }
memset ( & mostbuf [ wallc - > sx1 ] , 0 , ( xcross - wallc - > sx1 ) * sizeof ( mostbuf [ 0 ] ) ) ;
}
}
if ( bad & 12 )
{
//inty = intz / (globaldclip>>16)
2016-04-14 17:40:14 +00:00
double t = ( oz1 - s3 ) / ( s4 - s3 + oz1 - oz2 ) ;
double inty = wallc - > sz1 + t * ( wallc - > sz2 - wallc - > sz1 ) ;
double intz = oz1 + t * ( oz2 - oz1 ) ;
int xcross = wallc - > sx1 + xs_RoundToInt ( ( t * wallc - > sz2 * ( wallc - > sx2 - wallc - > sx1 ) ) / inty ) ;
2016-03-01 15:47:10 +00:00
//t = divscale30((x1<<4)-xcross*yb1[w],xcross*(yb2[w]-yb1[w])-((x2-x1)<<4));
//inty = yb1[w] + mulscale30(yb2[w]-yb1[w],t);
//intz = z1 + mulscale30(z2-z1,t);
if ( ( bad & 12 ) = = 8 )
{
if ( wallc - > sx1 < = xcross ) { z2 = intz ; iy2 = inty ; ix2 = xcross ; }
if ( wallc - > sx2 > xcross ) clearbufshort ( & mostbuf [ xcross ] , wallc - > sx2 - xcross , viewheight ) ;
}
else
{
if ( xcross < = wallc - > sx2 ) { z1 = intz ; iy1 = inty ; ix1 = xcross ; }
if ( xcross > wallc - > sx1 ) clearbufshort ( & mostbuf [ wallc - > sx1 ] , xcross - wallc - > sx1 , viewheight ) ;
}
}
2016-04-14 17:40:14 +00:00
y = z1 * InvZtoScale / iy1 ;
2016-03-01 15:47:10 +00:00
if ( ix2 = = ix1 )
{
2016-04-14 17:40:14 +00:00
mostbuf [ ix1 ] = ( short ) xs_RoundToInt ( y / 65536.0 + CenterY ) ;
2016-03-01 15:47:10 +00:00
}
else
{
2016-04-14 17:40:14 +00:00
fixed_t yinc = FLOAT2FIXED ( ( ( z2 * InvZtoScale / iy2 ) - y ) / ( ix2 - ix1 ) ) ;
qinterpolatedown16short ( & mostbuf [ ix1 ] , ix2 - ix1 , FLOAT2FIXED ( y / 65536.0 + CenterY ) , yinc ) ;
2016-03-01 15:47:10 +00:00
}
return bad ;
}
static void PrepWallRoundFix ( fixed_t * lwall , fixed_t walxrepeat , int x1 , int x2 )
{
// fix for rounding errors
walxrepeat = abs ( walxrepeat ) ;
fixed_t fix = ( MirrorFlags & RF_XFLIP ) ? walxrepeat - 1 : 0 ;
int x ;
if ( x1 > 0 )
{
for ( x = x1 ; x < x2 ; x + + )
{
if ( ( unsigned ) lwall [ x ] > = ( unsigned ) walxrepeat )
{
lwall [ x ] = fix ;
}
else
{
break ;
}
}
}
fix = walxrepeat - 1 - fix ;
for ( x = x2 - 1 ; x > = x1 ; x - - )
{
if ( ( unsigned ) lwall [ x ] > = ( unsigned ) walxrepeat )
{
lwall [ x ] = fix ;
}
else
{
break ;
}
}
}
2016-04-14 17:40:14 +00:00
void PrepWall ( fixed_t * swall , fixed_t * lwall , double walxrepeat , int x1 , int x2 )
2016-03-01 15:47:10 +00:00
{ // swall = scale, lwall = texturecolumn
double top , bot , i ;
2016-04-14 17:40:14 +00:00
double xrepeat = fabs ( walxrepeat * 65536 ) ;
2016-03-01 15:47:10 +00:00
double depth_scale = WallT . InvZstep * WallTMapScale2 ;
double depth_org = - WallT . UoverZstep * WallTMapScale2 ;
i = x1 - centerx ;
top = WallT . UoverZorg + WallT . UoverZstep * i ;
bot = WallT . InvZorg + WallT . InvZstep * i ;
for ( int x = x1 ; x < x2 ; x + + )
{
double frac = top / bot ;
if ( walxrepeat < 0 )
{
lwall [ x ] = xs_RoundToInt ( xrepeat - frac * xrepeat ) ;
}
else
{
lwall [ x ] = xs_RoundToInt ( frac * xrepeat ) ;
}
swall [ x ] = xs_RoundToInt ( frac * depth_scale + depth_org ) ;
top + = WallT . UoverZstep ;
bot + = WallT . InvZstep ;
}
2016-04-14 17:40:14 +00:00
PrepWallRoundFix ( lwall , FLOAT2FIXED ( walxrepeat ) , x1 , x2 ) ;
2016-03-01 15:47:10 +00:00
}
2016-04-14 17:40:14 +00:00
void PrepLWall ( fixed_t * lwall , double walxrepeat , int x1 , int x2 )
2016-03-01 15:47:10 +00:00
{ // lwall = texturecolumn
double top , bot , i ;
2016-04-14 17:40:14 +00:00
double xrepeat = fabs ( walxrepeat * 65536 ) ;
double topstep , botstep ;
2016-03-01 15:47:10 +00:00
i = x1 - centerx ;
top = WallT . UoverZorg + WallT . UoverZstep * i ;
bot = WallT . InvZorg + WallT . InvZstep * i ;
top * = xrepeat ;
topstep = WallT . UoverZstep * xrepeat ;
2016-04-14 17:40:14 +00:00
botstep = WallT . InvZstep ;
2016-03-01 15:47:10 +00:00
for ( int x = x1 ; x < x2 ; x + + )
{
if ( walxrepeat < 0 )
{
lwall [ x ] = xs_RoundToInt ( xrepeat - top / bot ) ;
}
else
{
lwall [ x ] = xs_RoundToInt ( top / bot ) ;
}
top + = topstep ;
2016-04-14 17:40:14 +00:00
bot + = botstep ;
2016-03-01 15:47:10 +00:00
}
2016-04-14 17:40:14 +00:00
PrepWallRoundFix ( lwall , FLOAT2FIXED ( walxrepeat ) , x1 , x2 ) ;
2016-03-01 15:47:10 +00:00
}
// pass = 0: when seg is first drawn
// = 1: drawing masked textures (including sprites)
// Currently, only pass = 0 is done or used
static void R_RenderDecal ( side_t * wall , DBaseDecal * decal , drawseg_t * clipper , int pass )
{
2016-04-14 17:40:14 +00:00
DVector2 decal_left , decal_right , decal_pos ;
2016-03-01 15:47:10 +00:00
int x1 , x2 ;
fixed_t xscale , yscale ;
fixed_t topoff ;
BYTE flipx ;
2016-03-22 21:07:38 +00:00
double zpos ;
2016-03-01 15:47:10 +00:00
int needrepeat = 0 ;
sector_t * front , * back ;
bool calclighting ;
bool rereadcolormap ;
FDynamicColormap * usecolormap ;
if ( decal - > RenderFlags & RF_INVISIBLE | | ! viewactive | | ! decal - > PicNum . isValid ( ) )
return ;
// Determine actor z
zpos = decal - > Z ;
front = curline - > frontsector ;
back = ( curline - > backsector ! = NULL ) ? curline - > backsector : curline - > frontsector ;
switch ( decal - > RenderFlags & RF_RELMASK )
{
default :
zpos = decal - > Z ;
break ;
case RF_RELUPPER :
if ( curline - > linedef - > flags & ML_DONTPEGTOP )
{
2016-03-22 21:07:38 +00:00
zpos = decal - > Z + front - > GetPlaneTexZF ( sector_t : : ceiling ) ;
2016-03-01 15:47:10 +00:00
}
else
{
2016-03-22 21:07:38 +00:00
zpos = decal - > Z + back - > GetPlaneTexZF ( sector_t : : ceiling ) ;
2016-03-01 15:47:10 +00:00
}
break ;
case RF_RELLOWER :
if ( curline - > linedef - > flags & ML_DONTPEGBOTTOM )
{
2016-03-22 21:07:38 +00:00
zpos = decal - > Z + front - > GetPlaneTexZF ( sector_t : : ceiling ) ;
2016-03-01 15:47:10 +00:00
}
else
{
2016-03-22 21:07:38 +00:00
zpos = decal - > Z + back - > GetPlaneTexZF ( sector_t : : floor ) ;
2016-03-01 15:47:10 +00:00
}
break ;
case RF_RELMID :
if ( curline - > linedef - > flags & ML_DONTPEGBOTTOM )
{
2016-03-22 21:07:38 +00:00
zpos = decal - > Z + front - > GetPlaneTexZF ( sector_t : : floor ) ;
2016-03-01 15:47:10 +00:00
}
else
{
2016-03-22 21:07:38 +00:00
zpos = decal - > Z + front - > GetPlaneTexZF ( sector_t : : ceiling ) ;
2016-03-01 15:47:10 +00:00
}
}
2016-03-22 21:07:38 +00:00
xscale = FLOAT2FIXED ( decal - > ScaleX ) ;
yscale = FLOAT2FIXED ( decal - > ScaleY ) ;
2016-03-01 15:47:10 +00:00
WallSpriteTile = TexMan ( decal - > PicNum , true ) ;
flipx = ( BYTE ) ( decal - > RenderFlags & RF_XFLIP ) ;
if ( WallSpriteTile = = NULL | | WallSpriteTile - > UseType = = FTexture : : TEX_Null )
{
return ;
}
// Determine left and right edges of sprite. Since this sprite is bound
// to a wall, we use the wall's angle instead of the decal's. This is
// pretty much the same as what R_AddLine() does.
FWallCoords savecoord = WallC ;
x2 = WallSpriteTile - > GetWidth ( ) ;
x1 = WallSpriteTile - > LeftOffset ;
x2 = x2 - x1 ;
x1 * = xscale ;
x2 * = xscale ;
2016-03-22 21:07:38 +00:00
double dcx , dcy ;
decal - > GetXY ( wall , dcx , dcy ) ;
2016-04-14 17:40:14 +00:00
decal_pos = { dcx , dcy } ;
DVector2 angvec = ( curline - > v2 - > fPos ( ) - curline - > v1 - > fPos ( ) ) . Unit ( ) ;
2016-03-01 15:47:10 +00:00
2016-04-14 17:40:14 +00:00
decal_left = decal_pos - x1 * angvec - ViewPos ;
decal_right = decal_pos + x2 * angvec - ViewPos ;
2016-03-01 15:47:10 +00:00
2016-04-14 17:40:14 +00:00
if ( WallC . Init ( decal_left , decal_right , TOO_CLOSE_Z ) )
2016-03-01 15:47:10 +00:00
goto done ;
x1 = WallC . sx1 ;
x2 = WallC . sx2 ;
if ( x1 > = clipper - > x2 | | x2 < = clipper - > x1 )
goto done ;
WallT . InitFromWallCoords ( & WallC ) ;
// Get the top and bottom clipping arrays
switch ( decal - > RenderFlags & RF_CLIPMASK )
{
case RF_CLIPFULL :
if ( curline - > backsector = = NULL )
{
if ( pass ! = 0 )
{
goto done ;
}
mceilingclip = walltop ;
mfloorclip = wallbottom ;
}
else if ( pass = = 0 )
{
mceilingclip = walltop ;
mfloorclip = ceilingclip ;
needrepeat = 1 ;
}
else
{
mceilingclip = openings + clipper - > sprtopclip - clipper - > x1 ;
mfloorclip = openings + clipper - > sprbottomclip - clipper - > x1 ;
}
break ;
case RF_CLIPUPPER :
if ( pass ! = 0 )
{
goto done ;
}
mceilingclip = walltop ;
mfloorclip = ceilingclip ;
break ;
case RF_CLIPMID :
if ( curline - > backsector ! = NULL & & pass ! = 2 )
{
goto done ;
}
mceilingclip = openings + clipper - > sprtopclip - clipper - > x1 ;
mfloorclip = openings + clipper - > sprbottomclip - clipper - > x1 ;
break ;
case RF_CLIPLOWER :
if ( pass ! = 0 )
{
goto done ;
}
mceilingclip = floorclip ;
mfloorclip = wallbottom ;
break ;
}
topoff = WallSpriteTile - > TopOffset < < FRACBITS ;
2016-04-14 17:40:14 +00:00
dc_texturemid = topoff + xs_ToInt ( ( zpos - ViewPos . Z ) * 65536 / yscale ) ;
2016-03-01 15:47:10 +00:00
// Clip sprite to drawseg
x1 = MAX < int > ( clipper - > x1 , x1 ) ;
x2 = MIN < int > ( clipper - > x2 , x2 ) ;
if ( x1 > = x2 )
{
goto done ;
}
PrepWall ( swall , lwall , WallSpriteTile - > GetWidth ( ) < < FRACBITS , x1 , x2 ) ;
if ( flipx )
{
int i ;
int right = ( WallSpriteTile - > GetWidth ( ) < < FRACBITS ) - 1 ;
for ( i = x1 ; i < x2 ; i + + )
{
lwall [ i ] = right - lwall [ i ] ;
}
}
// Prepare lighting
calclighting = false ;
usecolormap = basecolormap ;
rereadcolormap = true ;
// Decals that are added to the scene must fade to black.
if ( decal - > RenderStyle = = LegacyRenderStyles [ STYLE_Add ] & & usecolormap - > Fade ! = 0 )
{
usecolormap = GetSpecialLights ( usecolormap - > Color , 0 , usecolormap - > Desaturate ) ;
rereadcolormap = false ;
}
rw_light = rw_lightleft + ( x1 - WallC . sx1 ) * rw_lightstep ;
if ( fixedlightlev > = 0 )
dc_colormap = usecolormap - > Maps + fixedlightlev ;
else if ( fixedcolormap ! = NULL )
dc_colormap = fixedcolormap ;
else if ( ! foggy & & ( decal - > RenderFlags & RF_FULLBRIGHT ) )
dc_colormap = usecolormap - > Maps ;
else
calclighting = true ;
// Draw it
if ( decal - > RenderFlags & RF_YFLIP )
{
sprflipvert = true ;
yscale = - yscale ;
dc_texturemid = dc_texturemid - ( WallSpriteTile - > GetHeight ( ) < < FRACBITS ) ;
}
else
{
sprflipvert = false ;
}
// rw_offset is used as the texture's vertical scale
rw_offset = SafeDivScale30 ( 1 , yscale ) ;
do
{
dc_x = x1 ;
ESPSResult mode ;
2016-03-22 21:07:38 +00:00
mode = R_SetPatchStyle ( decal - > RenderStyle , ( float ) decal - > Alpha , decal - > Translation , decal - > AlphaColor ) ;
2016-03-01 15:47:10 +00:00
// R_SetPatchStyle can modify basecolormap.
if ( rereadcolormap )
{
usecolormap = basecolormap ;
}
if ( mode = = DontDraw )
{
needrepeat = 0 ;
}
else
{
int stop4 ;
if ( mode = = DoDraw0 )
{ // 1 column at a time
stop4 = dc_x ;
}
else // DoDraw1
{ // up to 4 columns at a time
stop4 = x2 & ~ 3 ;
}
while ( ( dc_x < stop4 ) & & ( dc_x & 3 ) )
{
if ( calclighting )
{ // calculate lighting
dc_colormap = usecolormap - > Maps + ( GETPALOOKUP ( rw_light , wallshade ) < < COLORMAPSHIFT ) ;
}
R_WallSpriteColumn ( R_DrawMaskedColumn ) ;
dc_x + + ;
}
while ( dc_x < stop4 )
{
if ( calclighting )
{ // calculate lighting
dc_colormap = usecolormap - > Maps + ( GETPALOOKUP ( rw_light , wallshade ) < < COLORMAPSHIFT ) ;
}
rt_initcols ( ) ;
for ( int zz = 4 ; zz ; - - zz )
{
R_WallSpriteColumn ( R_DrawMaskedColumnHoriz ) ;
dc_x + + ;
}
rt_draw4cols ( dc_x - 4 ) ;
}
while ( dc_x < x2 )
{
if ( calclighting )
{ // calculate lighting
dc_colormap = usecolormap - > Maps + ( GETPALOOKUP ( rw_light , wallshade ) < < COLORMAPSHIFT ) ;
}
R_WallSpriteColumn ( R_DrawMaskedColumn ) ;
dc_x + + ;
}
}
// If this sprite is RF_CLIPFULL on a two-sided line, needrepeat will
// be set 1 if we need to draw on the lower wall. In all other cases,
// needrepeat will be 0, and the while will fail.
mceilingclip = floorclip ;
mfloorclip = wallbottom ;
R_FinishSetPatchStyle ( ) ;
} while ( needrepeat - - ) ;
colfunc = basecolfunc ;
hcolfunc_post1 = rt_map1col ;
hcolfunc_post4 = rt_map4cols ;
R_FinishSetPatchStyle ( ) ;
done :
WallC = savecoord ;
}