2006-04-13 20:47:06 +00:00
// "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.
//
// This file has been modified from Ken Silverman's original release
2012-03-12 04:47:04 +00:00
// by Jonathon Fowler (jf@jonof.id.au)
2018-11-05 07:28:01 +00:00
// by the EDuke32 team (development@voidpoint.com)
2006-04-13 20:47:06 +00:00
2018-11-18 18:09:48 +00:00
# define engine_c_
2006-04-13 20:47:06 +00:00
2020-03-29 12:01:46 +00:00
# include "gl_load.h"
2018-11-18 18:09:48 +00:00
# include "baselayer.h"
2006-04-13 20:47:06 +00:00
# include "build.h"
2019-12-17 22:25:07 +00:00
2020-01-28 09:31:59 +00:00
# include "imagehelpers.h"
2019-09-19 21:02:57 +00:00
# include "common.h"
2018-11-18 18:09:48 +00:00
# include "compat.h"
# include "engine_priv.h"
# include "palette.h"
# include "pragmas.h"
2008-11-25 13:06:36 +00:00
# include "scriptfile.h"
2019-10-23 16:36:48 +00:00
# include "gamecvars.h"
2019-11-06 22:40:10 +00:00
# include "c_console.h"
# include "v_2ddrawer.h"
2019-11-08 22:02:52 +00:00
# include "v_draw.h"
2019-11-10 09:01:31 +00:00
# include "stats.h"
2019-11-21 21:31:46 +00:00
# include "menu.h"
2019-12-26 13:04:53 +00:00
# include "version.h"
2020-05-25 15:11:32 +00:00
# include "earcut.hpp"
2018-11-18 18:09:48 +00:00
2011-03-04 08:50:58 +00:00
# ifdef USE_OPENGL
2011-10-02 07:18:17 +00:00
# include "mdsprite.h"
2008-12-02 10:44:39 +00:00
# include "polymost.h"
2019-12-23 18:37:40 +00:00
# include "v_video.h"
2019-10-04 16:12:03 +00:00
# include "../../glbackend/glbackend.h"
2020-03-29 12:01:46 +00:00
# include "gl_renderer.h"
2008-05-10 01:29:37 +00:00
# endif
2006-04-13 20:47:06 +00:00
2010-08-26 15:24:12 +00:00
2013-06-01 20:09:39 +00:00
int32_t mapversion = 7 ; // JBF 20040211: default mapversion to 7
2013-06-28 14:07:44 +00:00
int32_t g_loadedMapVersion = - 1 ; // -1: none (e.g. started new)
2013-06-01 20:09:39 +00:00
2020-01-28 21:41:07 +00:00
int32_t rendmode = 0 ;
int32_t glrendmode = REND_POLYMOST ;
int32_t r_rortexture = 0 ;
int32_t r_rortexturerange = 0 ;
int32_t r_rorphase = 0 ;
int32_t mdtims , omdtims ;
2020-01-28 21:54:57 +00:00
int32_t polymostcenterhoriz = 100 ;
float fcosglobalang , fsinglobalang ;
float fxdim , fydim , fydimen , fviewingrange ;
2020-01-28 21:41:07 +00:00
2018-02-15 03:49:23 +00:00
uint8_t globalr = 255 , globalg = 255 , globalb = 255 ;
2015-05-19 22:05:20 +00:00
int16_t pskybits_override = - 1 ;
2019-10-20 23:17:26 +00:00
// This was on the cache but is permanently allocated, so put it into something static. This needs some rethinking anyway
static TArray < TArray < uint8_t > > voxelmemory ;
2019-09-19 20:02:45 +00:00
void ( * loadvoxel_replace ) ( int32_t voxindex ) = NULL ;
2012-01-19 21:57:46 +00:00
int16_t tiletovox [ MAXTILES ] ;
2014-12-26 17:29:53 +00:00
# ifdef USE_OPENGL
2019-12-23 18:37:40 +00:00
char * voxfilenames [ MAXVOXELS ] ;
2014-12-26 17:29:53 +00:00
# endif
2019-08-13 02:53:38 +00:00
char g_haveVoxels ;
2011-10-17 18:42:10 +00:00
//#define kloadvoxel loadvoxel
2006-04-13 20:47:06 +00:00
2011-06-18 13:02:08 +00:00
int32_t novoxmips = 1 ;
2006-04-13 20:47:06 +00:00
2006-04-24 19:04:22 +00:00
//These variables need to be copied into BUILD
2006-04-13 20:47:06 +00:00
# define MAXXSIZ 256
# define MAXYSIZ 256
# define MAXZSIZ 255
2019-10-20 23:17:26 +00:00
2009-01-09 09:29:17 +00:00
int32_t voxscale [ MAXVOXELS ] ;
2006-04-13 20:47:06 +00:00
2017-06-23 03:58:36 +00:00
static int32_t beforedrawrooms = 1 ;
2006-04-13 20:47:06 +00:00
2009-01-09 09:29:17 +00:00
static int32_t oxdimen = - 1 , oviewingrange = - 1 , oxyaspect = - 1 ;
2006-04-13 20:47:06 +00:00
2010-10-17 14:49:39 +00:00
// r_usenewaspect is the cvar, newaspect_enable to trigger the new behaviour in the code
2019-11-09 18:15:03 +00:00
CVAR ( Bool , r_usenewaspect , true , CVAR_ARCHIVE | CVAR_GLOBALCONFIG ) ;
int32_t newaspect_enable = 0 ;
2010-10-17 14:49:39 +00:00
2019-07-06 16:30:18 +00:00
int32_t r_fpgrouscan = 1 ;
2015-03-09 20:32:36 +00:00
int32_t globalflags ;
2009-01-09 09:29:17 +00:00
static int8_t tempbuf [ MAXWALLS ] ;
2006-04-13 20:47:06 +00:00
2012-11-15 14:28:11 +00:00
// referenced from asm
2020-03-29 14:59:49 +00:00
int32_t reciptable [ 2048 ] ;
2020-04-12 05:44:55 +00:00
intptr_t asm1 , asm2 ;
2012-11-15 14:28:11 +00:00
int32_t globalx1 , globaly2 , globalx3 , globaly3 ;
2012-09-02 14:10:55 +00:00
static int32_t no_radarang2 = 0 ;
2019-06-25 11:29:42 +00:00
static int16_t radarang [ 1280 ] ;
2019-12-24 17:53:29 +00:00
static int32_t qradarang [ 10240 ] ;
2012-11-05 02:49:08 +00:00
2019-09-22 19:26:07 +00:00
uint16_t ATTRIBUTE ( ( used ) ) sqrtable [ 4096 ] , ATTRIBUTE ( ( used ) ) shlookup [ 4096 + 256 ] , ATTRIBUTE ( ( used ) ) sqrtable_old [ 2048 ] ;
2012-11-05 02:49:08 +00:00
2006-04-13 20:47:06 +00:00
static char kensmessage [ 128 ] ;
2011-02-21 23:08:21 +00:00
const char * engineerrstr = " No error " ;
2006-04-13 20:47:06 +00:00
2009-11-18 01:17:56 +00:00
int32_t showfirstwall = 0 ;
2013-08-12 15:18:05 +00:00
int32_t showheightindicators = 1 ;
2009-11-18 01:17:56 +00:00
int32_t circlewall = - 1 ;
2011-03-13 11:59:32 +00:00
int16_t editstatus = 0 ;
2018-03-07 04:21:05 +00:00
static fix16_t global100horiz ; // (-100..300)-scale horiz (the one passed to drawrooms)
2011-03-13 11:59:32 +00:00
2019-09-19 21:02:57 +00:00
int32_t ( * getpalookup_replace ) ( int32_t davis , int32_t dashade ) = NULL ;
2019-04-18 17:24:30 +00:00
// adapted from build.c
2019-08-27 06:52:42 +00:00
static void getclosestpointonwall_internal ( vec2_t const p , int32_t const dawall , vec2_t * const closest )
2019-04-18 17:24:30 +00:00
{
2019-06-25 11:28:25 +00:00
vec2_t const w = wall [ dawall ] . pos ;
vec2_t const w2 = wall [ wall [ dawall ] . point2 ] . pos ;
2019-04-18 17:24:30 +00:00
vec2_t const d = { w2 . x - w . x , w2 . y - w . y } ;
int64_t i = d . x * ( ( int64_t ) p . x - w . x ) + d . y * ( ( int64_t ) p . y - w . y ) ;
if ( i < = 0 )
{
* closest = w ;
return ;
}
int64_t const j = ( int64_t ) d . x * d . x + ( int64_t ) d . y * d . y ;
if ( i > = j )
{
* closest = w2 ;
return ;
}
2020-01-07 23:06:24 +00:00
i = ( ( i < < 15 ) / j ) < < 15 ;
2019-04-18 17:24:30 +00:00
* closest = { ( int32_t ) ( w . x + ( ( d . x * i ) > > 30 ) ) , ( int32_t ) ( w . y + ( ( d . y * i ) > > 30 ) ) } ;
}
2011-03-02 21:21:47 +00:00
2011-05-07 18:23:34 +00:00
2019-09-21 20:53:00 +00:00
void faketimerhandler ( )
{
}
2011-05-07 18:23:34 +00:00
2011-04-14 20:48:08 +00:00
//
// setslope
//
void setslope ( int32_t sectnum , int32_t cf , int16_t slope )
{
if ( slope = = 0 )
{
SECTORFLD ( sectnum , stat , cf ) & = ~ 2 ;
SECTORFLD ( sectnum , heinum , cf ) = 0 ;
}
else
{
SECTORFLD ( sectnum , stat , cf ) | = 2 ;
SECTORFLD ( sectnum , heinum , cf ) = slope ;
}
}
2011-05-15 22:37:24 +00:00
# define WALLS_ARE_CONSISTENT(k) ((wall[k].x == x2 && wall[k].y == y2) \
& & ( ( wall [ wall [ k ] . point2 ] ) . x = = x1 & & ( wall [ wall [ k ] . point2 ] ) . y = = y1 ) )
2011-06-04 00:06:08 +00:00
static int32_t getscore ( int32_t w1c , int32_t w1f , int32_t w2c , int32_t w2f )
{
if ( w1c > w1f )
swaplong ( & w1c , & w1f ) ;
if ( w2c > w2f )
swaplong ( & w2c , & w2f ) ;
// now: c <= f for each "wall-vline"
2015-02-11 05:21:53 +00:00
int32_t maxceil = max ( w1c , w2c ) ;
int32_t minflor = min ( w1f , w2f ) ;
2011-06-04 00:06:08 +00:00
return minflor - maxceil ;
}
2011-05-15 22:37:24 +00:00
const int16_t * chsecptr_onextwall = NULL ;
2010-10-28 20:17:22 +00:00
2011-01-16 00:23:39 +00:00
int32_t checksectorpointer ( int16_t i , int16_t sectnum )
{
2011-09-30 13:52:02 +00:00
int32_t startsec , endsec ;
2011-01-16 00:23:39 +00:00
int32_t j , k , startwall , endwall , x1 , y1 , x2 , y2 , numnewwalls = 0 ;
2011-06-04 00:06:08 +00:00
int32_t bestnextwall = - 1 , bestnextsec = - 1 , bestwallscore = INT32_MIN ;
int32_t cz [ 4 ] , fz [ 4 ] , tmp [ 2 ] , tmpscore = 0 ;
2011-01-16 00:23:39 +00:00
x1 = wall [ i ] . x ;
y1 = wall [ i ] . y ;
x2 = ( wall [ wall [ i ] . point2 ] ) . x ;
y2 = ( wall [ wall [ i ] . point2 ] ) . y ;
2011-04-14 20:48:08 +00:00
k = wall [ i ] . nextwall ;
if ( k > = 0 ) //Check for early exit
2011-01-16 00:23:39 +00:00
{
2011-05-15 22:37:24 +00:00
if ( WALLS_ARE_CONSISTENT ( k ) )
return 0 ;
2011-04-14 20:48:08 +00:00
wall [ k ] . nextwall = wall [ k ] . nextsector = - 1 ;
2011-01-16 00:23:39 +00:00
}
2011-09-30 13:52:02 +00:00
if ( ( unsigned ) wall [ i ] . nextsector < ( unsigned ) numsectors & & wall [ i ] . nextwall < 0 )
{
// if we have a nextsector but no nextwall, take this as a hint
// to search only the walls of that sector
startsec = wall [ i ] . nextsector ;
endsec = startsec + 1 ;
}
else
{
startsec = 0 ;
endsec = numsectors ;
}
2011-04-14 20:48:08 +00:00
wall [ i ] . nextsector = wall [ i ] . nextwall = - 1 ;
2011-05-15 22:37:24 +00:00
if ( chsecptr_onextwall & & ( k = chsecptr_onextwall [ i ] ) > = 0 & & wall [ k ] . nextwall < 0 )
{
2011-06-04 00:06:08 +00:00
// old next wall found
2011-05-15 22:37:24 +00:00
if ( WALLS_ARE_CONSISTENT ( k ) )
{
j = sectorofwall ( k ) ;
wall [ i ] . nextsector = j ;
wall [ i ] . nextwall = k ;
wall [ k ] . nextsector = sectnum ;
wall [ k ] . nextwall = i ;
return 1 ;
}
}
2011-09-30 13:52:02 +00:00
for ( j = startsec ; j < endsec ; j + + )
2011-01-16 00:23:39 +00:00
{
2011-05-02 16:58:11 +00:00
if ( j = = sectnum )
continue ;
2011-01-16 00:23:39 +00:00
startwall = sector [ j ] . wallptr ;
2011-05-15 22:37:24 +00:00
endwall = startwall + sector [ j ] . wallnum ;
for ( k = startwall ; k < endwall ; k + + )
2011-01-16 00:23:39 +00:00
{
2011-05-15 22:37:24 +00:00
if ( ! WALLS_ARE_CONSISTENT ( k ) )
2011-04-14 20:48:08 +00:00
continue ;
// Don't create link if the other side is connected to another wall.
// The nextwall relation should be definitely one-to-one at all times!
if ( wall [ k ] . nextwall > = 0 & & wall [ k ] . nextwall ! = i )
continue ;
2011-06-04 00:06:08 +00:00
{
getzsofslope ( sectnum , x1 , y1 , & cz [ 0 ] , & fz [ 0 ] ) ;
getzsofslope ( sectnum , x2 , y2 , & cz [ 1 ] , & fz [ 1 ] ) ;
getzsofslope ( j , x1 , y1 , & cz [ 2 ] , & fz [ 2 ] ) ;
getzsofslope ( j , x2 , y2 , & cz [ 3 ] , & fz [ 3 ] ) ;
2011-04-14 20:48:08 +00:00
2011-06-04 00:06:08 +00:00
tmp [ 0 ] = getscore ( cz [ 0 ] , fz [ 0 ] , cz [ 2 ] , fz [ 2 ] ) ;
tmp [ 1 ] = getscore ( cz [ 1 ] , fz [ 1 ] , cz [ 3 ] , fz [ 3 ] ) ;
if ( ( tmp [ 0 ] ^ tmp [ 1 ] ) > = 0 )
tmpscore = tmp [ 0 ] + tmp [ 1 ] ;
else
tmpscore = max ( tmp [ 0 ] , tmp [ 1 ] ) ;
}
if ( bestnextwall = = - 1 | | tmpscore > bestwallscore )
{
bestwallscore = tmpscore ;
bestnextwall = k ;
bestnextsec = j ;
}
numnewwalls + + ;
2011-01-16 00:23:39 +00:00
}
}
2011-05-15 22:37:24 +00:00
2011-06-04 00:06:08 +00:00
// sectnum -2 means dry run
if ( bestnextwall > = 0 & & sectnum ! = - 2 )
{
2020-04-11 21:45:45 +00:00
// Printf("w%d new nw=%d (score %d)\n", i, bestnextwall, bestwallscore)
2011-06-04 00:06:08 +00:00
wall [ i ] . nextsector = bestnextsec ;
wall [ i ] . nextwall = bestnextwall ;
wall [ bestnextwall ] . nextsector = sectnum ;
wall [ bestnextwall ] . nextwall = i ;
}
2011-05-15 22:37:24 +00:00
return numnewwalls ;
2011-01-16 00:23:39 +00:00
}
2011-05-15 22:37:24 +00:00
# undef WALLS_ARE_CONSISTENT
2016-06-21 00:33:30 +00:00
int32_t xb1 [ MAXWALLSB ] ; // Polymost uses this as a temp array
2020-07-14 15:35:19 +00:00
static int32_t xb2 [ MAXWALLSB ] ;
2016-06-21 00:33:30 +00:00
int32_t rx1 [ MAXWALLSB ] , ry1 [ MAXWALLSB ] ;
int16_t bunchp2 [ MAXWALLSB ] , thesector [ MAXWALLSB ] ;
2011-01-16 00:23:39 +00:00
2016-06-21 00:33:30 +00:00
int16_t bunchfirst [ MAXWALLSB ] , bunchlast [ MAXWALLSB ] ;
2006-04-13 20:47:06 +00:00
2014-10-29 17:04:28 +00:00
2014-10-29 17:04:43 +00:00
static vec3_t spritesxyz [ MAXSPRITESONSCREEN + 1 ] ;
2006-04-13 20:47:06 +00:00
2009-01-09 09:29:17 +00:00
int32_t xdimen = - 1 , xdimenrecip , halfxdimen , xdimenscale , xdimscale ;
2014-11-28 08:14:00 +00:00
float fxdimen = - 1.f ;
2011-09-15 17:02:52 +00:00
int32_t ydimen ;
2006-04-13 20:47:06 +00:00
2016-06-21 00:33:30 +00:00
int32_t rxi [ 8 ] , ryi [ 8 ] ;
2006-04-13 20:47:06 +00:00
2009-01-09 09:29:17 +00:00
int32_t globalposx , globalposy , globalposz , globalhoriz ;
2018-03-07 04:21:05 +00:00
fix16_t qglobalhoriz ;
2014-10-25 03:32:26 +00:00
float fglobalposx , fglobalposy , fglobalposz ;
2009-01-09 09:29:17 +00:00
int16_t globalang , globalcursectnum ;
2018-03-07 04:21:18 +00:00
fix16_t qglobalang ;
2009-01-09 09:29:17 +00:00
int32_t globalpal , cosglobalang , singlobalang ;
int32_t cosviewingrangeglobalang , sinviewingrangeglobalang ;
2006-04-13 20:47:06 +00:00
2012-01-26 21:58:08 +00:00
int32_t xyaspect ;
2020-07-03 07:38:42 +00:00
int32_t viewingrangerecip ;
2006-04-13 20:47:06 +00:00
2012-01-26 21:58:08 +00:00
static char globalxshift , globalyshift ;
static int32_t globalxpanning , globalypanning ;
int32_t globalshade , globalorientation ;
int16_t globalpicnum ;
2020-07-14 15:35:19 +00:00
2012-01-26 21:58:08 +00:00
2014-04-05 11:28:06 +00:00
static int32_t globaly1 , globalx2 ;
2006-04-13 20:47:06 +00:00
2014-04-21 17:00:54 +00:00
int16_t sectorborder [ 256 ] ;
2012-01-20 13:24:15 +00:00
int32_t ydim16 , qsetmode = 0 ;
2011-03-13 11:59:32 +00:00
int16_t pointhighlight = - 1 , linehighlight = - 1 , highlightcnt = 0 ;
2012-01-26 21:58:08 +00:00
2009-01-09 09:29:17 +00:00
int32_t halfxdim16 , midydim16 ;
2006-04-13 20:47:06 +00:00
2014-04-19 22:42:22 +00:00
EDUKE32_STATIC_ASSERT ( MAXWALLSB < INT16_MAX ) ;
2012-01-26 21:58:08 +00:00
int16_t numscans , numbunches ;
static int16_t numhits ;
2006-04-13 20:47:06 +00:00
2009-01-09 09:29:17 +00:00
int16_t searchit ;
int32_t searchx = - 1 , searchy ; //search input
int16_t searchsector , searchwall , searchstat ; //search output
2010-09-06 23:08:35 +00:00
2011-03-17 23:37:38 +00:00
// SEARCHBOTTOMWALL:
// When aiming at a the bottom part of a 2-sided wall whose bottom part
// is swapped (.cstat&2), searchbottomwall equals that wall's .nextwall. In all
// other cases (when aiming at a wall), searchbottomwall equals searchwall.
//
// SEARCHISBOTTOM:
// When aiming at a 2-sided wall, 1 if aiming at the bottom part, 0 else
int16_t searchbottomwall , searchisbottom ;
2010-09-06 23:08:35 +00:00
2019-06-25 18:35:05 +00:00
char inpreparemirror = 0 ;
2009-01-09 09:29:17 +00:00
static int32_t mirrorsx1 , mirrorsy1 , mirrorsx2 , mirrorsy2 ;
2006-04-13 20:47:06 +00:00
2019-04-18 17:24:37 +00:00
# define MAXSETVIEW 4
2006-04-13 20:47:06 +00:00
//
// Internal Engine Functions
//
2011-06-18 13:02:08 +00:00
// returns: 0=continue sprite collecting;
// 1=break out of sprite collecting;
2018-04-12 21:04:00 +00:00
int32_t renderAddTsprite ( int16_t z , int16_t sectnum )
2011-05-22 21:52:22 +00:00
{
2019-04-18 17:25:24 +00:00
auto const spr = ( uspriteptr_t ) & sprite [ z ] ;
2020-07-14 14:06:14 +00:00
if ( spritesortcnt > = maxspritesonscreen )
return 1 ;
2011-05-22 21:52:22 +00:00
2020-07-14 14:06:14 +00:00
renderAddTSpriteFromSprite ( z ) ;
2011-05-22 21:52:22 +00:00
return 0 ;
}
2015-01-04 18:45:00 +00:00
2006-04-13 20:47:06 +00:00
//
// wallfront (internal)
//
2009-01-09 09:29:17 +00:00
int32_t wallfront ( int32_t l1 , int32_t l2 )
2006-04-13 20:47:06 +00:00
{
2019-06-25 11:28:25 +00:00
vec2_t const l1vect = wall [ thewall [ l1 ] ] . pos ;
vec2_t const l1p2vect = wall [ wall [ thewall [ l1 ] ] . point2 ] . pos ;
vec2_t const l2vect = wall [ thewall [ l2 ] ] . pos ;
vec2_t const l2p2vect = wall [ wall [ thewall [ l2 ] ] . point2 ] . pos ;
2015-03-24 00:40:48 +00:00
vec2_t d = { l1p2vect . x - l1vect . x , l1p2vect . y - l1vect . y } ;
int32_t t1 = dmulscale2 ( l2vect . x - l1vect . x , d . y , - d . x , l2vect . y - l1vect . y ) ; //p1(l2) vs. l1
int32_t t2 = dmulscale2 ( l2p2vect . x - l1vect . x , d . y , - d . x , l2p2vect . y - l1vect . y ) ; //p2(l2) vs. l1
2014-10-25 03:34:25 +00:00
if ( t1 = = 0 ) { if ( t2 = = 0 ) return - 1 ; t1 = t2 ; }
if ( t2 = = 0 ) t2 = t1 ;
2006-04-13 20:47:06 +00:00
2014-10-25 03:34:25 +00:00
if ( ( t1 ^ t2 ) > = 0 ) //pos vs. l1
2015-03-24 00:40:48 +00:00
return ( dmulscale2 ( globalposx - l1vect . x , d . y , - d . x , globalposy - l1vect . y ) ^ t1 ) > = 0 ;
2006-04-13 20:47:06 +00:00
2015-03-24 00:40:48 +00:00
d . x = l2p2vect . x - l2vect . x ;
d . y = l2p2vect . y - l2vect . y ;
2014-10-25 03:34:25 +00:00
2015-03-24 00:40:48 +00:00
t1 = dmulscale2 ( l1vect . x - l2vect . x , d . y , - d . x , l1vect . y - l2vect . y ) ; //p1(l1) vs. l2
t2 = dmulscale2 ( l1p2vect . x - l2vect . x , d . y , - d . x , l1p2vect . y - l2vect . y ) ; //p2(l1) vs. l2
2006-04-13 20:47:06 +00:00
2014-10-25 03:34:25 +00:00
if ( t1 = = 0 ) { if ( t2 = = 0 ) return - 1 ; t1 = t2 ; }
2006-04-13 20:47:06 +00:00
if ( t2 = = 0 ) t2 = t1 ;
2014-10-25 03:34:25 +00:00
if ( ( t1 ^ t2 ) > = 0 ) //pos vs. l2
2015-03-24 00:40:48 +00:00
return ( dmulscale2 ( globalposx - l2vect . x , d . y , - d . x , globalposy - l2vect . y ) ^ t1 ) < 0 ;
2014-10-25 03:34:25 +00:00
return - 2 ;
}
2006-04-13 20:47:06 +00:00
//
// spritewallfront (internal)
//
2019-12-26 06:27:48 +00:00
static inline int32_t spritewallfront ( tspritetype const * const s , int32_t w )
2006-04-13 20:47:06 +00:00
{
2019-04-18 17:25:24 +00:00
auto const wal = ( uwallptr_t ) & wall [ w ] ;
auto const wal2 = ( uwallptr_t ) & wall [ wal - > point2 ] ;
2015-03-24 00:40:48 +00:00
const vec2_t v = { wal - > x , wal - > y } ;
2006-04-13 20:47:06 +00:00
2015-03-24 00:40:48 +00:00
return dmulscale32 ( wal2 - > x - v . x , s - > y - v . y , - ( s - > x - v . x ) , wal2 - > y - v . y ) > = 0 ;
2006-04-13 20:47:06 +00:00
}
//
// bunchfront (internal)
//
2009-02-02 01:49:14 +00:00
static inline int32_t bunchfront ( int32_t b1 , int32_t b2 )
2006-04-13 20:47:06 +00:00
{
2015-03-24 00:40:48 +00:00
int b1f = bunchfirst [ b1 ] ;
int const x1b1 = xb1 [ b1f ] ;
int const x2b2 = xb2 [ bunchlast [ b2 ] ] + 1 ;
2006-04-13 20:47:06 +00:00
2015-03-24 00:40:48 +00:00
if ( x1b1 > = x2b2 )
2016-06-21 00:34:41 +00:00
return - 1 ;
2015-03-24 00:40:48 +00:00
int b2f = bunchfirst [ b2 ] ;
int const x1b2 = xb1 [ b2f ] ;
int const x2b1 = xb2 [ bunchlast [ b1 ] ] + 1 ;
if ( x1b2 > = x2b1 )
2016-06-21 00:34:41 +00:00
return - 1 ;
2006-04-13 20:47:06 +00:00
if ( x1b1 > = x1b2 )
{
2016-01-12 10:31:12 +00:00
for ( ; xb2 [ b2f ] < x1b1 ; b2f = bunchp2 [ b2f ] ) { }
2015-03-24 00:40:48 +00:00
return wallfront ( b1f , b2f ) ;
2006-04-13 20:47:06 +00:00
}
2015-03-24 00:40:48 +00:00
2016-01-12 10:31:12 +00:00
for ( ; xb2 [ b1f ] < x1b2 ; b1f = bunchp2 [ b1f ] ) { }
2015-03-24 00:40:48 +00:00
return wallfront ( b1f , b2f ) ;
2006-04-13 20:47:06 +00:00
}
2020-03-29 12:55:09 +00:00
//
// animateoffs (internal)
//
int32_t ( * animateoffs_replace ) ( int const tilenum , int fakevar ) = NULL ;
int32_t animateoffs ( int const tilenum , int fakevar )
{
if ( animateoffs_replace )
{
return animateoffs_replace ( tilenum , fakevar ) ;
}
int const animnum = picanm [ tilenum ] . num ;
2006-04-13 20:47:06 +00:00
2020-03-29 12:55:09 +00:00
if ( animnum < = 0 )
return 0 ;
2006-04-13 20:47:06 +00:00
2020-03-29 12:55:09 +00:00
int const i = ( int ) totalclocklock > > ( picanm [ tilenum ] . sf & PICANM_ANIMSPEED_MASK ) ;
int offs = 0 ;
switch ( picanm [ tilenum ] . sf & PICANM_ANIMTYPE_MASK )
{
case PICANM_ANIMTYPE_OSC :
2006-04-13 20:47:06 +00:00
{
2020-03-29 12:55:09 +00:00
int k = ( i % ( animnum < < 1 ) ) ;
offs = ( k < animnum ) ? k : ( animnum < < 1 ) - k ;
}
break ;
case PICANM_ANIMTYPE_FWD : offs = i % ( animnum + 1 ) ; break ;
case PICANM_ANIMTYPE_BACK : offs = - ( i % ( animnum + 1 ) ) ; break ;
}
2006-04-13 20:47:06 +00:00
2020-03-29 12:55:09 +00:00
return offs ;
}
2014-12-05 23:12:36 +00:00
2006-04-13 20:47:06 +00:00
2020-03-29 12:55:09 +00:00
// globalpicnum --> globalxshift, globalyshift
static void calc_globalshifts ( void )
{
2020-05-23 22:27:24 +00:00
globalxshift = ( 8 - widthBits ( globalpicnum ) ) ;
globalyshift = ( 8 - heightBits ( globalpicnum ) ) ;
2020-03-29 12:55:09 +00:00
if ( globalorientation & 8 ) { globalxshift + + ; globalyshift + + ; }
// PK: the following can happen for large (>= 512) tile sizes.
// NOTE that global[xy]shift are unsigned chars.
if ( globalxshift > 31 ) globalxshift = 0 ;
if ( globalyshift > 31 ) globalyshift = 0 ;
2006-04-13 20:47:06 +00:00
}
2018-04-12 21:04:00 +00:00
static void renderDrawSprite ( int32_t snum )
2013-02-10 16:24:04 +00:00
{
2020-03-29 12:55:09 +00:00
polymost_drawsprite ( snum ) ;
2013-02-10 16:24:04 +00:00
}
2006-04-13 20:47:06 +00:00
//
// drawmaskwall (internal)
//
2018-04-12 21:04:00 +00:00
static void renderDrawMaskedWall ( int16_t damaskwallcnt )
2006-04-13 20:47:06 +00:00
{
2020-03-29 12:55:09 +00:00
if ( videoGetRenderMode ( ) = = REND_POLYMOST )
{
polymost_drawmaskwall ( damaskwallcnt ) ; return ;
2006-04-13 20:47:06 +00:00
}
}
2016-10-23 19:47:36 +00:00
static uint32_t msqrtasm ( uint32_t c )
{
uint32_t a = 0x40000000l , b = 0x20000000l ;
do
{
if ( c > = a )
{
c - = a ;
a + = b * 4 ;
}
a - = b ;
a > > = 1 ;
b > > = 2 ;
} while ( b ) ;
if ( c > = a )
a + + ;
return a > > 1 ;
}
2006-04-13 20:47:06 +00:00
//
// initksqrt (internal)
//
2009-02-19 09:39:19 +00:00
static inline void initksqrt ( void )
2006-04-13 20:47:06 +00:00
{
2009-01-09 09:29:17 +00:00
int32_t i , j , k ;
2019-09-22 19:26:07 +00:00
uint32_t root , num ;
int32_t temp ;
2006-04-13 20:47:06 +00:00
j = 1 ; k = 0 ;
2009-02-19 16:47:54 +00:00
for ( i = 0 ; i < 4096 ; i + + )
2006-04-13 20:47:06 +00:00
{
if ( i > = j ) { j < < = 2 ; k + + ; }
2009-01-09 09:29:17 +00:00
sqrtable [ i ] = ( uint16_t ) ( msqrtasm ( ( i < < 18 ) + 131072 ) < < 1 ) ;
2006-04-13 20:47:06 +00:00
shlookup [ i ] = ( k < < 1 ) + ( ( 10 - k ) < < 8 ) ;
if ( i < 256 ) shlookup [ i + 4096 ] = ( ( k + 6 ) < < 1 ) + ( ( 10 - ( k + 6 ) ) < < 8 ) ;
}
2019-09-22 19:26:07 +00:00
for ( i = 0 ; i < 2048 ; i + + )
{
root = 128 ;
num = i < < 20 ;
do
{
temp = root ;
root = ( root + num / root ) > > 1 ;
} while ( ( temp - root + 1 ) > 2 ) ;
temp = root * root - num ;
while ( klabs ( int32_t ( temp - 2 * root + 1 ) ) < klabs ( temp ) )
{
temp + = - ( 2 * root ) + 1 ;
root - - ;
}
while ( klabs ( int32_t ( temp + 2 * root + 1 ) ) < klabs ( temp ) )
{
temp + = 2 * root + 1 ;
root + + ;
}
sqrtable_old [ i ] = root ;
}
2006-04-13 20:47:06 +00:00
}
//
// dosetaspect
//
static void dosetaspect ( void )
{
2012-09-02 14:10:55 +00:00
int32_t i , j ;
2006-04-13 20:47:06 +00:00
if ( xyaspect ! = oxyaspect )
{
oxyaspect = xyaspect ;
j = xyaspect * 320 ;
}
2012-09-02 14:10:55 +00:00
if ( xdimen ! = oxdimen | | viewingrange ! = oviewingrange )
2006-04-13 20:47:06 +00:00
{
2012-09-02 14:10:55 +00:00
int32_t k , x , xinc ;
no_radarang2 = 0 ;
2006-04-13 20:47:06 +00:00
oviewingrange = viewingrange ;
2012-09-02 14:10:55 +00:00
2019-06-25 11:29:42 +00:00
xinc = mulscale32 ( viewingrange * 2560 , xdimenrecip ) ;
x = ( 5120 < < 16 ) - mulscale1 ( xinc , xdimen ) ;
2012-09-02 14:10:55 +00:00
2009-02-19 16:47:54 +00:00
for ( i = 0 ; i < xdimen ; i + + )
2006-04-13 20:47:06 +00:00
{
j = ( x & 65535 ) ; k = ( x > > 16 ) ; x + = xinc ;
2012-09-02 14:10:55 +00:00
2019-06-25 11:29:42 +00:00
if ( k < 0 | | k > = ( int32_t ) ARRAY_SIZE ( qradarang ) - 1 )
2012-09-02 14:10:55 +00:00
{
no_radarang2 = 1 ;
break ;
}
if ( j ! = 0 )
2019-06-25 11:29:42 +00:00
j = mulscale16 ( qradarang [ k + 1 ] - qradarang [ k ] , j ) ;
2014-08-23 09:00:36 +00:00
}
2012-09-02 14:10:55 +00:00
2014-10-25 03:29:21 +00:00
oxdimen = xdimen ;
2006-04-13 20:47:06 +00:00
}
}
2018-04-12 21:03:47 +00:00
static int32_t engineLoadTables ( void )
2006-04-13 20:47:06 +00:00
{
2012-09-02 14:08:43 +00:00
static char tablesloaded = 0 ;
2006-04-13 20:47:06 +00:00
if ( tablesloaded = = 0 )
{
2012-09-02 14:08:43 +00:00
int32_t i ;
2006-04-13 20:47:06 +00:00
initksqrt ( ) ;
2012-03-22 22:48:06 +00:00
for ( i = 0 ; i < 2048 ; i + + )
reciptable [ i ] = divscale30 ( 2048 , i + 2048 ) ;
2006-04-13 20:47:06 +00:00
2012-09-02 14:08:43 +00:00
for ( i = 0 ; i < = 512 ; i + + )
2020-04-04 19:41:57 +00:00
sintable [ i ] = ( int16_t ) ( 16384.f * sinf ( ( float ) i * BANG2RAD ) + 0.0001f ) ;
2012-09-02 14:08:43 +00:00
for ( i = 513 ; i < 1024 ; i + + )
sintable [ i ] = sintable [ 1024 - i ] ;
for ( i = 1024 ; i < 2048 ; i + + )
sintable [ i ] = - sintable [ i - 1024 ] ;
2006-04-13 20:47:06 +00:00
2012-09-02 14:08:43 +00:00
for ( i = 0 ; i < 640 ; i + + )
2020-04-04 19:41:57 +00:00
radarang [ i ] = ( int16_t ) ( atanf ( ( ( float ) ( 640 - i ) - 0.5f ) * ( 1.f / 160.f ) ) * ( - 64.f * ( 1.f / BANG2RAD ) ) + 0.0001f ) ;
2012-09-02 14:08:43 +00:00
for ( i = 0 ; i < 640 ; i + + )
radarang [ 1279 - i ] = - radarang [ i ] ;
2019-06-25 11:29:42 +00:00
for ( i = 0 ; i < 5120 ; i + + )
2019-09-08 13:51:07 +00:00
qradarang [ i ] = fix16_from_float ( atanf ( ( ( float ) ( 5120 - i ) - 0.5f ) * ( 1.f / 1280.f ) ) * ( - 64.f * ( 1.f / BANG2RAD ) ) ) ;
2019-06-25 11:29:42 +00:00
for ( i = 0 ; i < 5120 ; i + + )
qradarang [ 10239 - i ] = - qradarang [ i ] ;
2006-04-13 20:47:06 +00:00
tablesloaded = 1 ;
}
return 0 ;
}
2012-03-13 20:06:07 +00:00
////////// SPRITE LIST MANIPULATION FUNCTIONS //////////
2013-12-31 11:51:54 +00:00
# ifdef NETCODE_DISABLE
# define LISTFN_STATIC static
# else
# define LISTFN_STATIC
# endif
2012-03-13 20:07:17 +00:00
///// sector lists of sprites /////
2012-03-13 20:06:07 +00:00
// insert sprite at the head of sector list, change .sectnum
2013-12-31 11:51:54 +00:00
LISTFN_STATIC void do_insertsprite_at_headofsect ( int16_t spritenum , int16_t sectnum )
2012-03-13 20:06:07 +00:00
{
2016-06-21 00:33:39 +00:00
int16_t const ohead = headspritesect [ sectnum ] ;
2012-03-13 20:06:07 +00:00
prevspritesect [ spritenum ] = - 1 ;
nextspritesect [ spritenum ] = ohead ;
if ( ohead > = 0 )
prevspritesect [ ohead ] = spritenum ;
headspritesect [ sectnum ] = spritenum ;
sprite [ spritenum ] . sectnum = sectnum ;
}
// remove sprite 'deleteme' from its sector list
2013-12-31 11:51:54 +00:00
LISTFN_STATIC void do_deletespritesect ( int16_t deleteme )
2012-03-13 20:06:07 +00:00
{
2016-06-21 00:33:39 +00:00
int32_t const sectnum = sprite [ deleteme ] . sectnum ;
int32_t const prev = prevspritesect [ deleteme ] ;
int32_t const next = nextspritesect [ deleteme ] ;
2012-03-13 20:06:07 +00:00
if ( headspritesect [ sectnum ] = = deleteme )
headspritesect [ sectnum ] = next ;
if ( prev > = 0 )
nextspritesect [ prev ] = next ;
if ( next > = 0 )
prevspritesect [ next ] = prev ;
}
2012-03-14 22:29:45 +00:00
///// now, status lists /////
2012-03-13 20:06:07 +00:00
2012-03-13 20:07:17 +00:00
// insert sprite at head of status list, change .statnum
2013-12-31 11:51:54 +00:00
LISTFN_STATIC void do_insertsprite_at_headofstat ( int16_t spritenum , int16_t statnum )
2012-03-13 20:06:07 +00:00
{
2016-06-21 00:33:39 +00:00
int16_t const ohead = headspritestat [ statnum ] ;
2012-03-13 20:06:07 +00:00
prevspritestat [ spritenum ] = - 1 ;
nextspritestat [ spritenum ] = ohead ;
if ( ohead > = 0 )
prevspritestat [ ohead ] = spritenum ;
headspritestat [ statnum ] = spritenum ;
sprite [ spritenum ] . statnum = statnum ;
}
2006-04-13 20:47:06 +00:00
// insertspritestat (internal)
2013-12-31 11:51:54 +00:00
LISTFN_STATIC int32_t insertspritestat ( int16_t statnum )
2006-04-13 20:47:06 +00:00
{
if ( ( statnum > = MAXSTATUS ) | | ( headspritestat [ MAXSTATUS ] = = - 1 ) )
2016-06-21 00:33:39 +00:00
return - 1 ; //list full
2006-04-13 20:47:06 +00:00
2012-03-13 20:04:56 +00:00
// remove one sprite from the statnum-freelist
2016-06-21 00:33:39 +00:00
int16_t const blanktouse = headspritestat [ MAXSTATUS ] ;
2006-04-13 20:47:06 +00:00
headspritestat [ MAXSTATUS ] = nextspritestat [ blanktouse ] ;
2012-03-13 20:04:56 +00:00
2012-03-13 20:06:07 +00:00
// make back-link of the new freelist head point to nil
2006-04-13 20:47:06 +00:00
if ( headspritestat [ MAXSTATUS ] > = 0 )
prevspritestat [ headspritestat [ MAXSTATUS ] ] = - 1 ;
2019-09-22 19:26:07 +00:00
else if ( enginecompatibility_mode = = ENGINECOMPATIBILITY_NONE )
2012-03-13 20:07:17 +00:00
tailspritefree = - 1 ;
2006-04-13 20:47:06 +00:00
2012-03-13 20:06:07 +00:00
do_insertsprite_at_headofstat ( blanktouse , statnum ) ;
2006-04-13 20:47:06 +00:00
2016-06-21 00:33:39 +00:00
return blanktouse ;
2006-04-13 20:47:06 +00:00
}
2012-03-13 20:06:07 +00:00
// remove sprite 'deleteme' from its status list
2018-12-08 00:40:39 +00:00
LISTFN_STATIC void do_deletespritestat ( int16_t deleteme )
2006-04-13 20:47:06 +00:00
{
2016-06-21 00:33:39 +00:00
int32_t const sectnum = sprite [ deleteme ] . statnum ;
int32_t const prev = prevspritestat [ deleteme ] ;
int32_t const next = nextspritestat [ deleteme ] ;
2012-03-13 20:06:07 +00:00
if ( headspritestat [ sectnum ] = = deleteme )
headspritestat [ sectnum ] = next ;
if ( prev > = 0 )
nextspritestat [ prev ] = next ;
if ( next > = 0 )
prevspritestat [ next ] = prev ;
2006-04-13 20:47:06 +00:00
}
2012-03-13 20:05:51 +00:00
//
// insertsprite
//
2019-09-19 20:02:45 +00:00
int32_t ( * insertsprite_replace ) ( int16_t sectnum , int16_t statnum ) = NULL ;
2012-03-13 20:05:51 +00:00
int32_t insertsprite ( int16_t sectnum , int16_t statnum )
{
2019-09-19 20:02:45 +00:00
if ( insertsprite_replace )
return insertsprite_replace ( sectnum , statnum ) ;
2012-03-14 22:30:57 +00:00
// TODO: guard against bad sectnum?
2016-06-21 00:33:39 +00:00
int32_t const newspritenum = insertspritestat ( statnum ) ;
2012-03-14 22:29:45 +00:00
if ( newspritenum > = 0 )
2012-03-14 22:30:24 +00:00
{
2012-03-26 22:04:44 +00:00
Bassert ( ( unsigned ) sectnum < MAXSECTORS ) ;
2012-03-14 22:30:57 +00:00
2012-03-14 22:29:45 +00:00
do_insertsprite_at_headofsect ( newspritenum , sectnum ) ;
2012-03-14 22:30:24 +00:00
Numsprites + + ;
}
2012-03-14 22:29:45 +00:00
return newspritenum ;
2012-03-13 20:05:51 +00:00
}
//
// deletesprite
//
2019-09-19 20:02:45 +00:00
int32_t ( * deletesprite_replace ) ( int16_t spritenum ) = NULL ;
2020-07-14 11:51:03 +00:00
void polymost_deletesprite ( int num ) ;
2012-03-13 20:05:51 +00:00
int32_t deletesprite ( int16_t spritenum )
{
2020-07-14 11:51:03 +00:00
polymost_deletesprite ( spritenum ) ;
2019-09-19 20:02:45 +00:00
if ( deletesprite_replace )
return deletesprite_replace ( spritenum ) ;
2012-03-26 22:04:44 +00:00
Bassert ( ( sprite [ spritenum ] . statnum = = MAXSTATUS )
= = ( sprite [ spritenum ] . sectnum = = MAXSECTORS ) ) ;
2012-03-13 20:07:17 +00:00
if ( sprite [ spritenum ] . statnum = = MAXSTATUS )
2016-06-21 00:33:39 +00:00
return - 1 ; // already not in the world
2012-03-13 20:07:17 +00:00
do_deletespritestat ( spritenum ) ;
do_deletespritesect ( spritenum ) ;
2012-03-14 22:29:45 +00:00
// (dummy) insert at tail of sector freelist, compat
// for code that checks .sectnum==MAXSECTOR
2012-03-13 20:07:17 +00:00
sprite [ spritenum ] . sectnum = MAXSECTORS ;
// insert at tail of status freelist
2019-09-22 19:26:07 +00:00
if ( enginecompatibility_mode ! = ENGINECOMPATIBILITY_NONE )
2019-09-21 11:02:17 +00:00
do_insertsprite_at_headofstat ( spritenum , MAXSTATUS ) ;
2012-03-13 20:07:17 +00:00
else
2019-09-21 11:02:17 +00:00
{
prevspritestat [ spritenum ] = tailspritefree ;
nextspritestat [ spritenum ] = - 1 ;
if ( tailspritefree > = 0 )
nextspritestat [ tailspritefree ] = spritenum ;
else
headspritestat [ MAXSTATUS ] = spritenum ;
sprite [ spritenum ] . statnum = MAXSTATUS ;
2012-03-13 20:07:17 +00:00
2019-09-21 11:02:17 +00:00
tailspritefree = spritenum ;
}
2012-03-14 22:30:24 +00:00
Numsprites - - ;
2012-03-13 20:07:17 +00:00
return 0 ;
2012-03-13 20:05:51 +00:00
}
2012-03-13 20:06:22 +00:00
//
// changespritesect
//
2019-09-19 20:02:45 +00:00
int32_t ( * changespritesect_replace ) ( int16_t spritenum , int16_t newsectnum ) = NULL ;
2012-03-13 20:06:22 +00:00
int32_t changespritesect ( int16_t spritenum , int16_t newsectnum )
{
2019-09-19 20:02:45 +00:00
if ( changespritesect_replace )
return changespritesect_replace ( spritenum , newsectnum ) ;
2013-02-10 16:24:27 +00:00
// XXX: NOTE: MAXSECTORS is allowed
2016-06-21 00:33:39 +00:00
if ( ( newsectnum < 0 | | newsectnum > MAXSECTORS ) | | ( sprite [ spritenum ] . sectnum = = MAXSECTORS ) )
return - 1 ;
2013-02-10 16:24:27 +00:00
if ( sprite [ spritenum ] . sectnum = = newsectnum )
2016-06-21 00:33:39 +00:00
return 0 ;
2012-03-13 20:06:22 +00:00
2012-03-13 20:06:52 +00:00
do_deletespritesect ( spritenum ) ;
do_insertsprite_at_headofsect ( spritenum , newsectnum ) ;
2012-03-13 20:06:22 +00:00
2016-06-21 00:33:39 +00:00
return 0 ;
2012-03-13 20:06:22 +00:00
}
//
// changespritestat
//
2019-09-19 20:02:45 +00:00
int32_t ( * changespritestat_replace ) ( int16_t spritenum , int16_t newstatnum ) = NULL ;
2012-03-13 20:06:22 +00:00
int32_t changespritestat ( int16_t spritenum , int16_t newstatnum )
{
2019-09-19 20:02:45 +00:00
if ( changespritestat_replace )
return changespritestat_replace ( spritenum , newstatnum ) ;
2013-02-10 16:24:27 +00:00
// XXX: NOTE: MAXSTATUS is allowed
2016-06-21 00:33:39 +00:00
if ( ( newstatnum < 0 | | newstatnum > MAXSTATUS ) | | ( sprite [ spritenum ] . statnum = = MAXSTATUS ) )
return - 1 ; // can't set the statnum of a sprite not in the world
2013-02-10 16:24:27 +00:00
if ( sprite [ spritenum ] . statnum = = newstatnum )
2016-06-21 00:33:39 +00:00
return 0 ; // sprite already has desired statnum
2012-03-13 20:06:22 +00:00
2012-03-13 20:06:52 +00:00
do_deletespritestat ( spritenum ) ;
do_insertsprite_at_headofstat ( spritenum , newstatnum ) ;
2012-03-13 20:06:22 +00:00
2016-06-21 00:34:41 +00:00
return 0 ;
2012-03-13 20:06:22 +00:00
}
2006-04-13 20:47:06 +00:00
//
// lintersect (internal)
//
2019-04-05 17:45:16 +00:00
int32_t lintersect ( const int32_t originX , const int32_t originY , const int32_t originZ ,
const int32_t destX , const int32_t destY , const int32_t destZ ,
const int32_t lineStartX , const int32_t lineStartY , const int32_t lineEndX , const int32_t lineEndY ,
int32_t * intersectionX , int32_t * intersectionY , int32_t * intersectionZ )
2007-12-12 17:42:14 +00:00
{
2019-04-05 17:45:16 +00:00
const vec2_t ray = { destX - originX ,
destY - originY } ;
const vec2_t lineVec = { lineEndX - lineStartX ,
lineEndY - lineStartY } ;
const vec2_t originDiff = { lineStartX - originX ,
lineStartY - originY } ;
2015-01-11 04:56:58 +00:00
2019-04-05 17:45:16 +00:00
const int32_t rayCrossLineVec = ray . x * lineVec . y - ray . y * lineVec . x ;
const int32_t originDiffCrossRay = originDiff . x * ray . y - originDiff . y * ray . x ;
2015-01-11 04:56:58 +00:00
2019-04-05 17:45:16 +00:00
if ( rayCrossLineVec = = 0 )
2018-05-15 16:45:34 +00:00
{
2019-09-22 19:26:07 +00:00
if ( originDiffCrossRay ! = 0 | | enginecompatibility_mode ! = ENGINECOMPATIBILITY_NONE )
2019-04-05 17:45:16 +00:00
{
// line segments are parallel
return 0 ;
}
2018-12-15 01:40:31 +00:00
2019-04-05 17:45:16 +00:00
// line segments are collinear
const int32_t rayLengthSquared = ray . x * ray . x + ray . y * ray . y ;
const int32_t rayDotOriginDiff = ray . x * originDiff . x + ray . y * originDiff . y ;
const int32_t rayDotLineEndDiff = rayDotOriginDiff + ray . x * lineVec . x + ray . y * lineVec . y ;
2019-04-05 17:45:19 +00:00
int64_t t = min ( rayDotOriginDiff , rayDotLineEndDiff ) ;
2019-04-05 17:45:16 +00:00
if ( rayDotOriginDiff < 0 )
{
if ( rayDotLineEndDiff < 0 )
return 0 ;
2018-12-15 01:40:31 +00:00
2019-04-05 17:45:16 +00:00
t = 0 ;
}
else if ( rayDotOriginDiff > rayLengthSquared )
{
if ( rayDotLineEndDiff > rayLengthSquared )
return 0 ;
2018-12-15 01:40:31 +00:00
2019-04-05 17:45:16 +00:00
t = rayDotLineEndDiff ;
}
2020-07-14 18:21:16 +00:00
t = ( t < < 24 ) / rayLengthSquared ;
2019-04-05 17:45:19 +00:00
2019-04-05 17:45:16 +00:00
* intersectionX = originX + mulscale24 ( ray . x , t ) ;
* intersectionY = originY + mulscale24 ( ray . y , t ) ;
* intersectionZ = originZ + mulscale24 ( destZ - originZ , t ) ;
2018-12-15 01:40:31 +00:00
2019-04-05 17:45:16 +00:00
return 1 ;
2018-05-15 16:45:34 +00:00
}
2018-12-15 01:40:31 +00:00
2019-04-05 17:45:16 +00:00
const int32_t originDiffCrossLineVec = originDiff . x * lineVec . y - originDiff . y * lineVec . x ;
static const int32_t signBit = 1u < < 31u ;
2019-04-05 17:45:19 +00:00
// Any point on either line can be expressed as p+t*r and q+u*s
// The two line segments intersect when we can find a t & u such that p+t*r = q+u*s
// If the point is outside of the bounds of the line segment, we know we don't have an intersection.
2019-04-05 17:45:16 +00:00
// t is < 0 if (originDiffCrossLineVec^rayCrossLineVec) & signBit)
// u is < 0 if (originDiffCrossRay^rayCrossLineVec) & signBit
2019-04-05 20:41:04 +00:00
// t is > 1 if klabs(originDiffCrossLineVec) > klabs(rayCrossLineVec)
// u is > 1 if klabs(originDiffCrossRay) > klabs(rayCrossLineVec)
2019-04-05 17:45:19 +00:00
// where int32_t u = tabledivide64(((int64_t) originDiffCrossRay) << 24L, rayCrossLineVec);
if ( ( ( originDiffCrossLineVec ^ rayCrossLineVec ) & signBit ) | |
( ( originDiffCrossRay ^ rayCrossLineVec ) & signBit ) | |
2019-04-05 20:41:04 +00:00
klabs ( originDiffCrossLineVec ) > klabs ( rayCrossLineVec ) | |
klabs ( originDiffCrossRay ) > klabs ( rayCrossLineVec ) )
2019-04-05 17:45:16 +00:00
{
// line segments do not overlap
return 0 ;
}
2019-04-05 17:45:19 +00:00
2020-07-14 18:21:16 +00:00
int64_t t = ( int64_t ( originDiffCrossLineVec ) < < 24 ) / rayCrossLineVec ;
2019-04-05 17:45:19 +00:00
// For sake of completeness/readability, alternative to the above approach for an early out & avoidance of an extra division:
2019-04-05 17:45:16 +00:00
* intersectionX = originX + mulscale24 ( ray . x , t ) ;
* intersectionY = originY + mulscale24 ( ray . y , t ) ;
* intersectionZ = originZ + mulscale24 ( destZ - originZ , t ) ;
2006-04-13 20:47:06 +00:00
2015-01-11 04:56:58 +00:00
return 1 ;
2010-09-27 21:52:04 +00:00
}
2006-04-13 20:47:06 +00:00
//
// rintersect (internal)
//
2012-10-14 20:41:34 +00:00
// returns: -1 if didn't intersect, coefficient (x3--x4 fraction)<<16 else
2019-07-29 11:12:06 +00:00
int32_t rintersect_old ( int32_t x1 , int32_t y1 , int32_t z1 ,
int32_t vx , int32_t vy , int32_t vz ,
int32_t x3 , int32_t y3 , int32_t x4 , int32_t y4 ,
int32_t * intx , int32_t * inty , int32_t * intz )
{
//p1 towards p2 is a ray
int32_t const x34 = x3 - x4 , y34 = y3 - y4 ;
int32_t const x31 = x3 - x1 , y31 = y3 - y1 ;
int32_t const bot = vx * y34 - vy * x34 ;
int32_t const topt = x31 * y34 - y31 * x34 ;
if ( bot = = 0 )
return - 1 ;
int32_t const topu = vx * y31 - vy * x31 ;
if ( bot > 0 & & ( topt < 0 | | topu < 0 | | topu > = bot ) )
return - 1 ;
else if ( bot < 0 & & ( topt > 0 | | topu > 0 | | topu < = bot ) )
return - 1 ;
int32_t t = divscale16 ( topt , bot ) ;
* intx = x1 + mulscale16 ( vx , t ) ;
* inty = y1 + mulscale16 ( vy , t ) ;
* intz = z1 + mulscale16 ( vz , t ) ;
t = divscale16 ( topu , bot ) ;
return t ;
}
2016-06-21 00:33:30 +00:00
int32_t rintersect ( int32_t x1 , int32_t y1 , int32_t z1 ,
2019-06-25 11:28:40 +00:00
int32_t vx , int32_t vy , int32_t vz ,
2016-06-21 00:33:30 +00:00
int32_t x3 , int32_t y3 , int32_t x4 , int32_t y4 ,
int32_t * intx , int32_t * inty , int32_t * intz )
2007-12-12 17:42:14 +00:00
{
//p1 towards p2 is a ray
2012-06-13 23:13:39 +00:00
2019-09-22 19:26:07 +00:00
if ( enginecompatibility_mode ! = ENGINECOMPATIBILITY_NONE )
2019-07-29 11:12:06 +00:00
return rintersect_old ( x1 , y1 , z1 , vx , vy , vz , x3 , y3 , x4 , y4 , intx , inty , intz ) ;
2019-06-25 11:28:40 +00:00
int64_t const x34 = x3 - x4 , y34 = y3 - y4 ;
int64_t const x31 = x3 - x1 , y31 = y3 - y1 ;
int64_t const bot = vx * y34 - vy * x34 ;
int64_t const topt = x31 * y34 - y31 * x34 ;
2013-03-24 18:55:40 +00:00
if ( bot = = 0 )
return - 1 ;
2012-06-13 23:13:39 +00:00
2019-06-25 11:28:40 +00:00
int64_t const topu = vx * y31 - vy * x31 ;
if ( bot > 0 & & ( topt < 0 | | topu < 0 | | topu > = bot ) )
return - 1 ;
else if ( bot < 0 & & ( topt > 0 | | topu > 0 | | topu < = bot ) )
return - 1 ;
2020-04-05 21:58:58 +00:00
int64_t t = ( topt < < 16 ) / bot ;
2012-06-13 23:13:39 +00:00
* intx = x1 + ( ( vx * t ) > > 16 ) ;
* inty = y1 + ( ( vy * t ) > > 16 ) ;
* intz = z1 + ( ( vz * t ) > > 16 ) ;
2020-04-05 21:58:58 +00:00
t = ( topu < < 16 ) / bot ;
2019-06-25 11:28:40 +00:00
2012-10-14 20:41:34 +00:00
Bassert ( ( unsigned ) t < 65536 ) ;
return t ;
2006-04-13 20:47:06 +00:00
}
2010-09-27 21:52:04 +00:00
int32_t rayintersect ( int32_t x1 , int32_t y1 , int32_t z1 , int32_t vx , int32_t vy , int32_t vz , int32_t x3 ,
int32_t y3 , int32_t x4 , int32_t y4 , int32_t * intx , int32_t * inty , int32_t * intz )
{
2012-10-14 20:41:34 +00:00
return ( rintersect ( x1 , y1 , z1 , vx , vy , vz , x3 , y3 , x4 , y4 , intx , inty , intz ) ! = - 1 ) ;
2010-09-27 21:52:04 +00:00
}
2006-04-13 20:47:06 +00:00
2015-05-27 08:47:34 +00:00
//
// multi-pskies
//
2018-04-12 21:03:47 +00:00
psky_t * tileSetupSky ( int32_t const tilenum )
2015-05-27 08:47:34 +00:00
{
2016-08-27 01:41:21 +00:00
for ( bssize_t i = 0 ; i < pskynummultis ; i + + )
2015-05-27 08:47:34 +00:00
if ( multipskytile [ i ] = = tilenum )
return & multipsky [ i ] ;
2006-04-13 20:47:06 +00:00
2015-05-27 08:47:34 +00:00
int32_t const newPskyID = pskynummultis + + ;
multipsky = ( psky_t * ) Xrealloc ( multipsky , pskynummultis * sizeof ( psky_t ) ) ;
multipskytile = ( int32_t * ) Xrealloc ( multipskytile , pskynummultis * sizeof ( int32_t ) ) ;
psky_t * const newPsky = & multipsky [ newPskyID ] ;
Bmemset ( newPsky , 0 , sizeof ( psky_t ) ) ;
multipskytile [ newPskyID ] = tilenum ;
2017-11-29 07:29:48 +00:00
newPsky - > yscale = 65536 ;
2015-05-27 08:47:34 +00:00
return newPsky ;
}
2006-04-13 20:47:06 +00:00
2006-07-07 18:41:05 +00:00
//
// preinitengine
//
2009-01-09 09:29:17 +00:00
static int32_t preinitcalled = 0 ;
2008-05-31 01:57:14 +00:00
2019-06-25 11:29:23 +00:00
# if !defined DEBUG_MAIN_ARRAYS
2009-01-10 07:38:50 +00:00
static spriteext_t spriteext_s [ MAXSPRITES + MAXUNIQHUDID ] ;
static spritesmooth_t spritesmooth_s [ MAXSPRITES + MAXUNIQHUDID ] ;
2011-02-25 22:49:56 +00:00
static sectortype sector_s [ MAXSECTORS + M32_FIXME_SECTORS ] ;
static walltype wall_s [ MAXWALLS + M32_FIXME_WALLS ] ;
2017-06-25 11:23:53 +00:00
# ifndef NEW_MAP_FORMAT
static wallext_t wallext_s [ MAXWALLS ] ;
# endif
2008-08-03 11:45:15 +00:00
static spritetype sprite_s [ MAXSPRITES ] ;
2019-04-18 17:25:24 +00:00
static tspritetype tsprite_s [ MAXSPRITESONSCREEN ] ;
2008-05-31 01:57:14 +00:00
# endif
2018-04-12 21:03:47 +00:00
int32_t enginePreInit ( void )
2006-07-07 18:41:05 +00:00
{
2019-11-04 00:18:38 +00:00
polymost_initosdfuncs ( ) ;
2017-12-09 02:56:12 +00:00
initdivtables ( ) ;
2007-09-06 10:43:42 +00:00
2019-06-25 11:29:23 +00:00
# if !defined DEBUG_MAIN_ARRAYS
2008-05-31 01:57:14 +00:00
sector = sector_s ;
wall = wall_s ;
2017-06-25 11:23:53 +00:00
# ifndef NEW_MAP_FORMAT
wallext = wallext_s ;
# endif
2008-05-31 01:57:14 +00:00
sprite = sprite_s ;
tsprite = tsprite_s ;
spriteext = spriteext_s ;
spritesmooth = spritesmooth_s ;
# endif
2007-09-06 10:43:42 +00:00
2006-07-07 18:41:05 +00:00
2006-07-24 02:47:47 +00:00
preinitcalled = 1 ;
return 0 ;
2006-07-07 18:41:05 +00:00
}
2020-05-23 12:40:54 +00:00
void ( * paletteLoadFromDisk_replace ) ( void ) = NULL ; // replacement hook for Blood.
2006-04-13 20:47:06 +00:00
//
// initengine
//
2018-04-12 21:03:47 +00:00
int32_t engineInit ( void )
2006-04-13 20:47:06 +00:00
{
2019-10-21 17:36:54 +00:00
int32_t i ;
2007-09-06 10:43:42 +00:00
2007-12-12 17:42:14 +00:00
if ( ! preinitcalled )
{
2018-04-12 21:03:47 +00:00
i = enginePreInit ( ) ;
2006-07-24 02:47:47 +00:00
if ( i ) return i ;
}
2018-04-12 21:03:47 +00:00
if ( engineLoadTables ( ) )
2012-03-22 22:46:39 +00:00
return 1 ;
2006-04-13 20:47:06 +00:00
xyaspect = - 1 ;
2019-01-30 00:19:56 +00:00
rotatesprite_y_offset = 0 ;
rotatesprite_yxaspect = 65536 ;
2006-04-13 20:47:06 +00:00
showinvisibility = 0 ;
2019-10-20 23:17:26 +00:00
voxelmemory . Reset ( ) ;
2009-02-19 16:47:54 +00:00
for ( i = 0 ; i < MAXTILES ; i + + )
2006-04-13 20:47:06 +00:00
tiletovox [ i ] = - 1 ;
2020-03-29 14:59:49 +00:00
for ( auto & v : voxscale ) v = 65536 ;
memset ( voxrotate , 0 , sizeof ( voxrotate ) ) ;
2006-04-13 20:47:06 +00:00
paletteloaded = 0 ;
searchit = 0 ; searchstat = - 1 ;
totalclock = 0 ;
2012-12-14 19:28:05 +00:00
g_visibility = 512 ;
2006-04-13 20:47:06 +00:00
parallaxvisibility = 512 ;
2017-07-08 19:42:11 +00:00
maxspritesonscreen = MAXSPRITESONSCREEN ;
2020-05-23 16:58:57 +00:00
GPalette . Init ( MAXPALOOKUPS + 1 ) ; // one slot for each translation, plus a separate one for the base palettes.
2020-05-23 12:40:54 +00:00
if ( paletteLoadFromDisk_replace )
{
paletteLoadFromDisk_replace ( ) ;
}
else
{
paletteLoadFromDisk ( ) ;
}
2012-03-22 22:46:39 +00:00
2011-03-04 08:50:58 +00:00
# ifdef USE_OPENGL
2006-04-13 20:47:06 +00:00
if ( ! mdinited ) mdinit ( ) ;
# endif
2006-04-24 19:04:22 +00:00
return 0 ;
2006-04-13 20:47:06 +00:00
}
2016-12-26 06:01:32 +00:00
//
// E_PostInit
//
2018-04-12 21:03:47 +00:00
int32_t enginePostInit ( void )
2016-12-26 06:01:32 +00:00
{
if ( ! ( paletteloaded & PALETTE_MAIN ) )
2020-01-25 09:56:30 +00:00
I_FatalError ( " No palette found. " ) ;
2016-12-26 06:01:32 +00:00
2020-05-01 11:13:46 +00:00
V_LoadTranslations ( ) ; // loading the translations must be delayed until the palettes have been fully set up.
2020-05-27 20:19:02 +00:00
lookups . postLoadTables ( ) ;
2020-05-24 08:30:09 +00:00
TileFiles . SetupReverseTileMap ( ) ;
2020-05-30 18:55:29 +00:00
TileFiles . PostLoadSetup ( ) ;
2016-12-26 06:01:32 +00:00
return 0 ;
}
2006-04-13 20:47:06 +00:00
//
// uninitengine
//
2020-04-12 05:44:55 +00:00
2018-04-12 21:03:47 +00:00
void engineUnInit ( void )
2006-04-13 20:47:06 +00:00
{
polymost_glreset ( ) ;
freeallmodels ( ) ;
2012-01-10 23:44:35 +00:00
# ifdef POLYMER
2009-05-22 23:49:25 +00:00
polymer_uninit ( ) ;
2012-01-10 23:44:35 +00:00
# endif
2017-06-27 11:01:22 +00:00
2019-10-15 21:56:29 +00:00
TileFiles . CloseAll ( ) ;
2019-10-15 21:18:52 +00:00
2016-08-27 01:41:21 +00:00
for ( bssize_t i = 0 ; i < num_usermaphacks ; i + + )
2015-01-08 15:14:00 +00:00
{
2019-06-25 11:29:08 +00:00
Xfree ( usermaphacks [ i ] . mhkfile ) ;
Xfree ( usermaphacks [ i ] . title ) ;
2015-01-08 15:14:00 +00:00
}
2015-09-23 17:55:31 +00:00
DO_FREE_AND_NULL ( usermaphacks ) ;
num_usermaphacks = 0 ;
2015-05-27 08:47:34 +00:00
DO_FREE_AND_NULL ( multipsky ) ;
DO_FREE_AND_NULL ( multipskytile ) ;
pskynummultis = 0 ;
2006-04-13 20:47:06 +00:00
}
//
// initspritelists
//
2019-09-19 20:02:45 +00:00
void ( * initspritelists_replace ) ( void ) = NULL ;
2006-04-13 20:47:06 +00:00
void initspritelists ( void )
{
2019-09-19 20:02:45 +00:00
if ( initspritelists_replace )
{
initspritelists_replace ( ) ;
return ;
}
2009-01-09 09:29:17 +00:00
int32_t i ;
2006-04-13 20:47:06 +00:00
2012-03-22 22:48:06 +00:00
// initial list state for statnum lists:
2012-03-13 20:04:56 +00:00
//
2012-03-22 22:48:06 +00:00
// statnum 0: nil
// statnum 1: nil
2012-03-13 20:04:56 +00:00
// . . .
2012-03-22 22:48:06 +00:00
// statnum MAXSTATUS-1: nil
// "statnum MAXSTATUS": nil <- 0 <-> 1 <-> 2 <-> ... <-> MAXSPRITES-1 -> nil
2012-03-13 20:04:56 +00:00
//
2012-03-22 22:48:06 +00:00
// That is, the dummy MAXSTATUS statnum has all sprites.
2012-03-13 20:04:56 +00:00
2009-02-19 16:47:54 +00:00
for ( i = 0 ; i < MAXSECTORS ; i + + ) //Init doubly-linked sprite sector lists
2006-04-13 20:47:06 +00:00
headspritesect [ i ] = - 1 ;
headspritesect [ MAXSECTORS ] = 0 ;
2012-03-13 20:06:37 +00:00
2009-02-19 16:47:54 +00:00
for ( i = 0 ; i < MAXSPRITES ; i + + )
2006-04-13 20:47:06 +00:00
{
prevspritesect [ i ] = i - 1 ;
nextspritesect [ i ] = i + 1 ;
sprite [ i ] . sectnum = MAXSECTORS ;
}
prevspritesect [ 0 ] = - 1 ;
nextspritesect [ MAXSPRITES - 1 ] = - 1 ;
2009-02-19 16:47:54 +00:00
for ( i = 0 ; i < MAXSTATUS ; i + + ) //Init doubly-linked sprite status lists
2006-04-13 20:47:06 +00:00
headspritestat [ i ] = - 1 ;
headspritestat [ MAXSTATUS ] = 0 ;
2012-03-13 20:06:37 +00:00
2009-02-19 16:47:54 +00:00
for ( i = 0 ; i < MAXSPRITES ; i + + )
2006-04-13 20:47:06 +00:00
{
prevspritestat [ i ] = i - 1 ;
nextspritestat [ i ] = i + 1 ;
sprite [ i ] . statnum = MAXSTATUS ;
}
prevspritestat [ 0 ] = - 1 ;
nextspritestat [ MAXSPRITES - 1 ] = - 1 ;
2012-03-13 20:07:17 +00:00
tailspritefree = MAXSPRITES - 1 ;
2012-03-14 22:30:24 +00:00
Numsprites = 0 ;
2006-04-13 20:47:06 +00:00
}
2019-04-18 17:24:10 +00:00
void set_globalang ( fix16_t const ang )
2013-02-10 16:24:11 +00:00
{
2018-03-07 04:21:18 +00:00
globalang = fix16_to_int ( ang ) & 2047 ;
qglobalang = ang & 0x7FFFFFF ;
float const f_ang = fix16_to_float ( ang ) ;
float const f_ang_radians = f_ang * M_PI * ( 1.f / 1024.f ) ;
2019-06-25 11:29:42 +00:00
float const fcosang = cosf ( f_ang_radians ) * 16384.f ;
float const fsinang = sinf ( f_ang_radians ) * 16384.f ;
# ifdef USE_OPENGL
fcosglobalang = fcosang ;
fsinglobalang = fsinang ;
2016-10-03 02:43:42 +00:00
# endif
2019-06-25 11:29:42 +00:00
cosglobalang = ( int ) fcosang ;
singlobalang = ( int ) fsinang ;
2018-03-07 04:21:18 +00:00
2013-02-10 16:24:11 +00:00
cosviewingrangeglobalang = mulscale16 ( cosglobalang , viewingrange ) ;
sinviewingrangeglobalang = mulscale16 ( singlobalang , viewingrange ) ;
}
2006-04-13 20:47:06 +00:00
//
// drawrooms
//
2018-04-12 21:03:47 +00:00
int32_t renderDrawRoomsQ16 ( int32_t daposx , int32_t daposy , int32_t daposz ,
fix16_t daang , fix16_t dahoriz , int16_t dacursectnum )
2006-04-13 20:47:06 +00:00
{
2020-03-29 12:55:09 +00:00
int32_t i ;
2006-04-13 20:47:06 +00:00
beforedrawrooms = 0 ;
2014-10-25 03:32:26 +00:00
set_globalpos ( daposx , daposy , daposz ) ;
2018-03-07 04:21:18 +00:00
set_globalang ( daang ) ;
2018-03-07 12:02:03 +00:00
2012-08-13 18:25:37 +00:00
global100horiz = dahoriz ;
2012-03-04 20:14:48 +00:00
// xdimenscale is scale(xdimen,yxaspect,320);
// normalization by viewingrange so that center-of-aim doesn't depend on it
2018-03-07 04:21:05 +00:00
qglobalhoriz = mulscale16 ( dahoriz - F16 ( 100 ) , divscale16 ( xdimenscale , viewingrange ) ) + fix16_from_int ( ydimen > > 1 ) ;
2019-06-25 11:29:42 +00:00
globalhoriz = fix16_to_int ( qglobalhoriz ) ;
2006-04-13 20:47:06 +00:00
globalcursectnum = dacursectnum ;
2015-03-08 23:39:51 +00:00
totalclocklock = totalclock ;
2006-04-13 20:47:06 +00:00
if ( ( xyaspect ! = oxyaspect ) | | ( xdimen ! = oxdimen ) | | ( viewingrange ! = oviewingrange ) )
dosetaspect ( ) ;
2019-09-03 04:09:20 +00:00
Bmemset ( gotsector , 0 , sizeof ( gotsector ) ) ;
2006-04-13 20:47:06 +00:00
2018-04-12 21:03:12 +00:00
if ( videoGetRenderMode ( ) ! = REND_CLASSIC
2011-09-15 17:02:52 +00:00
)
2006-04-13 20:47:06 +00:00
{
2011-09-15 17:02:52 +00:00
i = xdimen - 1 ;
2007-12-12 17:42:14 +00:00
}
2006-04-23 06:44:19 +00:00
2019-06-26 13:20:03 +00:00
for ( int i = 0 ; i < numwalls ; + + i )
2018-11-18 18:13:48 +00:00
{
2019-06-26 13:20:03 +00:00
if ( wall [ i ] . cstat & CSTAT_WALL_ROTATE_90 )
2018-11-18 18:13:48 +00:00
{
2019-06-26 13:20:03 +00:00
auto & w = wall [ i ] ;
2019-10-15 21:56:29 +00:00
auto & tile = RotTile ( w . picnum + animateoffs ( w . picnum , 16384 ) ) ;
2019-09-19 21:02:57 +00:00
2019-06-26 13:20:03 +00:00
if ( tile . newtile = = - 1 & & tile . owner = = - 1 )
{
2019-10-15 21:56:29 +00:00
auto owner = w . picnum + animateoffs ( w . picnum , 16384 ) ;
tile . newtile = TileFiles . tileCreateRotated ( owner ) ;
2019-06-26 13:20:03 +00:00
Bassert ( tile . newtile ! = - 1 ) ;
2018-11-18 18:13:48 +00:00
2019-10-15 21:56:29 +00:00
RotTile ( tile . newtile ) . owner = w . picnum + animateoffs ( w . picnum , 16384 ) ;
2018-11-18 18:13:48 +00:00
}
}
}
2015-02-22 12:43:02 +00:00
// Update starting sector number (common to classic and Polymost).
2015-08-01 08:41:14 +00:00
// ADJUST_GLOBALCURSECTNUM.
2015-02-22 12:43:02 +00:00
if ( globalcursectnum > = MAXSECTORS )
globalcursectnum - = MAXSECTORS ;
else
{
i = globalcursectnum ;
2019-04-06 06:38:10 +00:00
updatesector ( globalposx , globalposy , & globalcursectnum ) ;
2015-02-22 12:43:02 +00:00
if ( globalcursectnum < 0 ) globalcursectnum = i ;
// PK 20110123: I'm not sure what the line above is supposed to do, but 'i'
// *can* be negative, so let's just quit here in that case...
if ( globalcursectnum < 0 )
return 0 ;
}
2007-01-06 01:29:45 +00:00
polymost_drawrooms ( ) ;
2013-05-17 03:44:09 +00:00
2019-06-25 18:35:05 +00:00
return inpreparemirror ;
2006-04-13 20:47:06 +00:00
}
2006-08-29 01:58:59 +00:00
// UTILITY TYPES AND FUNCTIONS FOR DRAWMASKS OCCLUSION TREE
2009-03-03 14:01:14 +00:00
// typedef struct s_maskleaf
// {
// int32_t index;
// _point2d p1, p2;
// _equation maskeq, p1eq, p2eq;
// struct s_maskleaf* branch[MAXWALLSB];
// int32_t drawing;
// } _maskleaf;
2009-06-24 08:20:10 +00:00
//
2009-03-03 14:01:14 +00:00
// _maskleaf maskleaves[MAXWALLSB];
2006-08-29 01:58:59 +00:00
// returns equation of a line given two points
2019-04-18 17:24:10 +00:00
static inline _equation equation ( float const x1 , float const y1 , float const x2 , float const y2 )
2006-08-29 01:58:59 +00:00
{
2014-10-25 03:30:38 +00:00
const float f = x2 - x1 ;
2006-08-29 01:58:59 +00:00
2014-10-25 03:30:38 +00:00
// vertical
if ( f = = 0.f )
2019-04-18 17:24:34 +00:00
return { 1 , 0 , - x1 } ;
else
2006-08-29 01:58:59 +00:00
{
2019-04-18 17:24:34 +00:00
float const ff = ( y2 - y1 ) / f ;
return { ff , - 1 , ( y1 - ( ff * x1 ) ) } ;
2006-08-29 01:58:59 +00:00
}
}
2019-04-18 17:24:10 +00:00
int32_t wallvisible ( int32_t const x , int32_t const y , int16_t const wallnum )
2007-12-12 17:42:14 +00:00
{
// 1 if wall is in front of player 0 otherwise
2019-04-18 17:25:24 +00:00
auto w1 = ( uwallptr_t ) & wall [ wallnum ] ;
auto w2 = ( uwallptr_t ) & wall [ w1 - > point2 ] ;
2007-07-01 06:32:03 +00:00
2019-04-18 17:24:10 +00:00
int32_t const a1 = getangle ( w1 - > x - x , w1 - > y - y ) ;
int32_t const a2 = getangle ( w2 - > x - x , w2 - > y - y ) ;
2007-07-01 06:32:03 +00:00
2016-06-21 00:33:39 +00:00
return ( ( ( a2 + ( 2048 - a1 ) ) & 2047 ) < = 1024 ) ;
2007-07-01 06:32:03 +00:00
}
2011-05-02 16:58:11 +00:00
2006-08-29 01:58:59 +00:00
2014-10-25 03:30:38 +00:00
static inline int32_t sameside ( const _equation * eq , const vec2f_t * p1 , const vec2f_t * p2 )
2006-08-29 01:58:59 +00:00
{
2014-10-25 03:30:38 +00:00
const float sign1 = ( eq - > a * p1 - > x ) + ( eq - > b * p1 - > y ) + eq - > c ;
const float sign2 = ( eq - > a * p2 - > x ) + ( eq - > b * p2 - > y ) + eq - > c ;
return ( sign1 * sign2 ) > 0.f ;
2006-08-29 01:58:59 +00:00
}
2006-04-13 20:47:06 +00:00
2014-01-24 21:39:02 +00:00
// x1, y1: in/out
// rest x/y: out
2018-10-16 06:09:09 +00:00
2014-01-24 21:39:02 +00:00
2014-01-19 20:17:14 +00:00
# ifdef DEBUG_MASK_DRAWING
int32_t g_maskDrawMode = 0 ;
# endif
2006-12-31 06:32:04 +00:00
2019-09-25 20:57:14 +00:00
static inline int comparetsprites ( int const k , int const l )
{
# ifdef USE_OPENGL
if ( videoGetRenderMode ( ) = = REND_POLYMOST )
{
if ( ( tspriteptr [ k ] - > cstat & 48 ) ! = ( tspriteptr [ l ] - > cstat & 48 ) )
return ( tspriteptr [ k ] - > cstat & 48 ) - ( tspriteptr [ l ] - > cstat & 48 ) ;
if ( ( tspriteptr [ k ] - > cstat & 48 ) = = 16 & & tspriteptr [ k ] - > ang ! = tspriteptr [ l ] - > ang )
return tspriteptr [ k ] - > ang - tspriteptr [ l ] - > ang ;
}
# endif
if ( tspriteptr [ k ] - > statnum ! = tspriteptr [ l ] - > statnum )
return tspriteptr [ k ] - > statnum - tspriteptr [ l ] - > statnum ;
if ( tspriteptr [ k ] - > x = = tspriteptr [ l ] - > x & &
tspriteptr [ k ] - > y = = tspriteptr [ l ] - > y & &
tspriteptr [ k ] - > z = = tspriteptr [ l ] - > z & &
( tspriteptr [ k ] - > cstat & 48 ) = = ( tspriteptr [ l ] - > cstat & 48 ) & &
tspriteptr [ k ] - > owner ! = tspriteptr [ l ] - > owner )
return tspriteptr [ k ] - > owner - tspriteptr [ l ] - > owner ;
if ( klabs ( spritesxyz [ k ] . z - globalposz ) ! = klabs ( spritesxyz [ l ] . z - globalposz ) )
return klabs ( spritesxyz [ k ] . z - globalposz ) - klabs ( spritesxyz [ l ] . z - globalposz ) ;
return 0 ;
}
2019-09-25 20:33:22 +00:00
static void sortsprites ( int const start , int const end )
{
int32_t i , gap , y , ys ;
if ( start > = end )
return ;
gap = 1 ; while ( gap < end - start ) gap = ( gap < < 1 ) + 1 ;
for ( gap > > = 1 ; gap > 0 ; gap > > = 1 ) //Sort sprite list
for ( i = start ; i < end - gap ; i + + )
for ( bssize_t l = i ; l > = start ; l - = gap )
{
if ( spritesxyz [ l ] . y < = spritesxyz [ l + gap ] . y ) break ;
swapptr ( & tspriteptr [ l ] , & tspriteptr [ l + gap ] ) ;
swaplong ( & spritesxyz [ l ] . x , & spritesxyz [ l + gap ] . x ) ;
swaplong ( & spritesxyz [ l ] . y , & spritesxyz [ l + gap ] . y ) ;
}
ys = spritesxyz [ start ] . y ; i = start ;
for ( bssize_t j = start + 1 ; j < = end ; j + + )
{
if ( j < end )
{
y = spritesxyz [ j ] . y ;
if ( y = = ys )
continue ;
ys = y ;
}
if ( j > i + 1 )
{
for ( bssize_t k = i ; k < j ; k + + )
{
auto const s = tspriteptr [ k ] ;
spritesxyz [ k ] . z = s - > z ;
if ( ( s - > cstat & 48 ) ! = 32 )
{
2020-05-24 10:31:38 +00:00
int32_t yoff = tileTopOffset ( s - > picnum ) + s - > yoffset ;
2019-09-25 20:33:22 +00:00
int32_t yspan = ( tilesiz [ s - > picnum ] . y * s - > yrepeat < < 2 ) ;
spritesxyz [ k ] . z - = ( yoff * s - > yrepeat ) < < 2 ;
if ( ! ( s - > cstat & 128 ) )
spritesxyz [ k ] . z - = ( yspan > > 1 ) ;
if ( klabs ( spritesxyz [ k ] . z - globalposz ) < ( yspan > > 1 ) )
spritesxyz [ k ] . z = globalposz ;
}
}
for ( bssize_t k = i + 1 ; k < j ; k + + )
for ( bssize_t l = i ; l < k ; l + + )
2019-09-25 20:57:14 +00:00
if ( comparetsprites ( k , l ) < 0 )
2019-09-25 20:33:22 +00:00
{
swapptr ( & tspriteptr [ k ] , & tspriteptr [ l ] ) ;
vec3_t tv3 = spritesxyz [ k ] ;
spritesxyz [ k ] = spritesxyz [ l ] ;
spritesxyz [ l ] = tv3 ;
}
}
i = j ;
}
}
2006-04-13 20:47:06 +00:00
//
// drawmasks
//
2018-04-12 21:03:47 +00:00
void renderDrawMasks ( void )
2006-04-13 20:47:06 +00:00
{
2014-01-19 20:17:14 +00:00
# define debugmask_add(dispidx, idx) do {} while (0)
2019-04-19 21:45:22 +00:00
int32_t i = spritesortcnt - 1 ;
int32_t numSprites = spritesortcnt ;
2012-11-25 13:19:02 +00:00
2019-09-08 01:01:22 +00:00
# ifdef USE_OPENGL
2019-04-19 21:45:22 +00:00
if ( videoGetRenderMode ( ) = = REND_POLYMOST )
{
spritesortcnt = 0 ;
int32_t back = i ;
for ( ; i > = 0 ; - - i )
{
if ( polymost_spriteHasTranslucency ( & tsprite [ i ] ) )
{
tspriteptr [ spritesortcnt ] = & tsprite [ i ] ;
+ + spritesortcnt ;
} else
{
tspriteptr [ back ] = & tsprite [ i ] ;
- - back ;
}
}
} else
2019-09-08 01:01:22 +00:00
# endif
2019-04-19 21:45:22 +00:00
{
for ( ; i > = 0 ; - - i )
{
tspriteptr [ i ] = & tsprite [ i ] ;
}
}
2006-04-13 20:47:06 +00:00
2019-09-25 20:33:22 +00:00
for ( i = numSprites - 1 ; i > = 0 ; - - i )
2006-04-24 19:04:22 +00:00
{
2012-11-25 13:19:02 +00:00
const int32_t xs = tspriteptr [ i ] - > x - globalposx , ys = tspriteptr [ i ] - > y - globalposy ;
const int32_t yp = dmulscale6 ( xs , cosviewingrangeglobalang , ys , sinviewingrangeglobalang ) ;
2011-05-22 21:52:22 +00:00
# ifdef USE_OPENGL
2020-02-02 19:00:37 +00:00
const int32_t modelp = polymost_spriteIsModelOrVoxel ( tspriteptr [ i ] ) ;
2011-05-22 21:52:22 +00:00
# endif
2014-09-30 04:06:32 +00:00
2006-04-24 19:04:22 +00:00
if ( yp > ( 4 < < 8 ) )
{
2012-11-25 13:19:02 +00:00
const int32_t xp = dmulscale6 ( ys , cosglobalang , - xs , singlobalang ) ;
if ( mulscale24 ( labs ( xp + yp ) , xdimen ) > = yp )
goto killsprite ;
2014-10-29 17:04:43 +00:00
spritesxyz [ i ] . x = scale ( xp + yp , xdimen < < 7 , yp ) ;
2006-04-24 19:04:22 +00:00
}
else if ( ( tspriteptr [ i ] - > cstat & 48 ) = = 0 )
{
2011-05-07 18:23:34 +00:00
killsprite :
2014-01-30 16:13:53 +00:00
# ifdef USE_OPENGL
2011-05-22 21:52:22 +00:00
if ( ! modelp )
2014-01-30 16:13:53 +00:00
# endif
2011-05-22 21:52:22 +00:00
{
2019-04-19 21:45:22 +00:00
//Delete face sprite if on wrong side!
2019-09-25 20:33:22 +00:00
if ( i > = spritesortcnt )
{
- - numSprites ;
if ( i ! = numSprites )
{
tspriteptr [ i ] = tspriteptr [ numSprites ] ;
spritesxyz [ i ] . x = spritesxyz [ numSprites ] . x ;
spritesxyz [ i ] . y = spritesxyz [ numSprites ] . y ;
}
}
else
2012-11-25 13:19:02 +00:00
{
2019-09-25 20:33:22 +00:00
- - numSprites ;
- - spritesortcnt ;
if ( i ! = numSprites )
{
tspriteptr [ i ] = tspriteptr [ spritesortcnt ] ;
spritesxyz [ i ] . x = spritesxyz [ spritesortcnt ] . x ;
spritesxyz [ i ] . y = spritesxyz [ spritesortcnt ] . y ;
tspriteptr [ spritesortcnt ] = tspriteptr [ numSprites ] ;
spritesxyz [ spritesortcnt ] . x = spritesxyz [ numSprites ] . x ;
spritesxyz [ spritesortcnt ] . y = spritesxyz [ numSprites ] . y ;
}
2012-11-25 13:19:02 +00:00
}
2011-05-22 21:52:22 +00:00
continue ;
}
2006-04-24 19:04:22 +00:00
}
2014-10-29 17:04:43 +00:00
spritesxyz [ i ] . y = yp ;
2006-04-24 19:04:22 +00:00
}
2006-04-13 20:47:06 +00:00
2019-09-25 20:33:22 +00:00
sortsprites ( 0 , spritesortcnt ) ;
sortsprites ( spritesortcnt , numSprites ) ;
2020-06-04 16:46:44 +00:00
renderBeginScene ( ) ;
2013-04-21 19:55:38 +00:00
2019-09-25 20:33:22 +00:00
# ifdef USE_OPENGL
if ( videoGetRenderMode ( ) = = REND_POLYMOST )
2015-10-21 19:54:14 +00:00
{
2019-10-04 16:12:03 +00:00
GLInterface . EnableBlend ( false ) ;
GLInterface . EnableAlphaTest ( true ) ;
2020-02-06 17:43:27 +00:00
GLInterface . SetDepthBias ( - 2 , - 256 ) ;
2012-11-25 13:19:02 +00:00
2019-09-25 20:33:22 +00:00
if ( spritesortcnt < numSprites )
2015-10-21 19:54:14 +00:00
{
2019-09-25 20:33:22 +00:00
i = spritesortcnt ;
2020-05-27 09:46:38 +00:00
for ( bssize_t i = spritesortcnt ; i < numSprites ; )
2006-04-13 20:47:06 +00:00
{
2020-05-27 09:46:38 +00:00
int32_t py = spritesxyz [ i ] . y ;
int32_t pcstat = tspriteptr [ i ] - > cstat & 48 ;
int32_t pangle = tspriteptr [ i ] - > ang ;
int j = i + 1 ;
if ( ! polymost_spriteIsModelOrVoxel ( tspriteptr [ i ] ) )
2015-10-21 19:54:14 +00:00
{
2020-05-27 09:46:38 +00:00
while ( j < numSprites & & py = = spritesxyz [ j ] . y & & pcstat = = ( tspriteptr [ j ] - > cstat & 48 ) & & ( pcstat ! = 16 | | pangle = = tspriteptr [ j ] - > ang )
2020-02-02 19:00:37 +00:00
& & ! polymost_spriteIsModelOrVoxel ( tspriteptr [ j ] ) )
2020-05-27 09:46:38 +00:00
{
j + + ;
}
2007-12-12 17:42:14 +00:00
}
2019-09-25 20:33:22 +00:00
if ( j - i = = 1 )
{
debugmask_add ( i | 32768 , tspriteptr [ i ] - > owner ) ;
renderDrawSprite ( i ) ;
tspriteptr [ i ] = NULL ;
}
else
{
2019-10-04 17:17:55 +00:00
GLInterface . SetDepthMask ( false ) ;
2014-10-29 17:04:43 +00:00
2019-09-25 20:33:22 +00:00
for ( bssize_t k = j - 1 ; k > = i ; k - - )
2015-10-21 19:54:14 +00:00
{
2019-09-25 20:33:22 +00:00
debugmask_add ( k | 32768 , tspriteptr [ k ] - > owner ) ;
renderDrawSprite ( k ) ;
2015-10-21 19:54:14 +00:00
}
2015-10-20 07:15:25 +00:00
2019-10-04 17:17:55 +00:00
GLInterface . SetDepthMask ( true ) ;
2019-09-25 20:33:22 +00:00
2019-10-04 17:17:55 +00:00
GLInterface . SetColorMask ( false ) ;
2019-09-25 20:33:22 +00:00
for ( bssize_t k = j - 1 ; k > = i ; k - - )
2015-10-21 19:54:14 +00:00
{
2019-09-25 20:33:22 +00:00
renderDrawSprite ( k ) ;
tspriteptr [ k ] = NULL ;
2015-10-21 19:54:14 +00:00
}
2006-04-13 20:47:06 +00:00
2019-10-04 17:17:55 +00:00
GLInterface . SetColorMask ( true ) ;
2006-04-13 20:47:06 +00:00
2019-09-25 20:33:22 +00:00
}
i = j ;
2019-04-19 21:45:22 +00:00
}
}
2006-04-13 20:47:06 +00:00
2020-06-12 20:32:49 +00:00
int32_t numMaskWalls = maskwallcnt ;
2019-07-13 21:26:10 +00:00
maskwallcnt = 0 ;
for ( i = 0 ; i < numMaskWalls ; i + + )
2012-11-25 13:19:02 +00:00
{
2019-07-13 21:26:10 +00:00
if ( polymost_maskWallHasTranslucency ( ( uwalltype * ) & wall [ thewall [ maskwall [ i ] ] ] ) )
2019-04-19 21:45:22 +00:00
{
2019-07-13 21:26:10 +00:00
maskwall [ maskwallcnt ] = maskwall [ i ] ;
maskwallcnt + + ;
2019-04-19 21:45:22 +00:00
}
else
2019-07-13 21:26:10 +00:00
renderDrawMaskedWall ( i ) ;
2012-11-25 13:19:02 +00:00
}
2019-04-30 11:12:16 +00:00
2019-10-04 16:12:03 +00:00
GLInterface . EnableBlend ( true ) ;
GLInterface . EnableAlphaTest ( true ) ;
2019-10-04 17:17:55 +00:00
GLInterface . SetDepthMask ( false ) ;
2020-02-06 17:43:27 +00:00
}
2019-04-19 21:45:22 +00:00
# endif
2015-10-21 19:54:14 +00:00
vec2f_t pos ;
2006-08-29 01:58:59 +00:00
2015-10-21 19:54:14 +00:00
pos . x = fglobalposx ;
pos . y = fglobalposy ;
// CAUTION: maskwallcnt and spritesortcnt may be zero!
// Writing e.g. "while (maskwallcnt--)" is wrong!
while ( maskwallcnt )
{
// PLAG: sorting stuff
2018-04-12 21:03:12 +00:00
const int32_t w = ( videoGetRenderMode ( ) = = REND_POLYMER ) ?
2015-10-21 19:54:14 +00:00
maskwall [ maskwallcnt - 1 ] : thewall [ maskwall [ maskwallcnt - 1 ] ] ;
2013-04-21 19:55:38 +00:00
2015-10-21 19:54:14 +00:00
maskwallcnt - - ;
2013-04-22 10:35:48 +00:00
2017-06-09 06:41:23 +00:00
vec2f_t dot = { ( float ) wall [ w ] . x , ( float ) wall [ w ] . y } ;
vec2f_t dot2 = { ( float ) wall [ wall [ w ] . point2 ] . x , ( float ) wall [ wall [ w ] . point2 ] . y } ;
vec2f_t middle = { ( dot . x + dot2 . x ) * .5f , ( dot . y + dot2 . y ) * .5f } ;
2006-08-29 01:58:59 +00:00
2017-06-09 06:41:23 +00:00
_equation maskeq = equation ( dot . x , dot . y , dot2 . x , dot2 . y ) ;
_equation p1eq = equation ( pos . x , pos . y , dot . x , dot . y ) ;
_equation p2eq = equation ( pos . x , pos . y , dot2 . x , dot2 . y ) ;
2006-08-29 01:58:59 +00:00
2015-10-21 19:54:14 +00:00
i = spritesortcnt ;
while ( i )
{
i - - ;
2019-04-19 21:45:22 +00:00
if ( tspriteptr [ i ] ! = NULL )
2006-08-29 01:58:59 +00:00
{
2015-10-21 19:54:14 +00:00
vec2f_t spr ;
2019-04-18 17:24:10 +00:00
auto const tspr = tspriteptr [ i ] ;
2012-11-25 13:19:02 +00:00
2015-10-21 19:54:14 +00:00
spr . x = ( float ) tspr - > x ;
spr . y = ( float ) tspr - > y ;
2007-12-12 17:42:14 +00:00
2015-10-21 19:54:14 +00:00
if ( ! sameside ( & maskeq , & spr , & pos ) )
{
// Sprite and camera are on different sides of the
// masked wall.
2014-01-24 21:39:02 +00:00
2015-10-21 19:54:14 +00:00
// Check if the sprite is inside the 'cone' given by
// the rays from the camera to the two wall-points.
const int32_t inleft = sameside ( & p1eq , & middle , & spr ) ;
const int32_t inright = sameside ( & p2eq , & middle , & spr ) ;
2014-01-24 21:39:02 +00:00
2015-10-21 19:54:14 +00:00
int32_t ok = ( inleft & & inright ) ;
2014-01-24 21:39:02 +00:00
2015-10-21 19:54:14 +00:00
if ( ! ok )
{
// If not, check if any of the border points are...
int32_t xx [ 4 ] = { tspr - > x } ;
int32_t yy [ 4 ] = { tspr - > y } ;
int32_t numpts , jj ;
2014-01-24 21:39:02 +00:00
2015-10-21 19:54:14 +00:00
const _equation pineq = inleft ? p1eq : p2eq ;
2014-01-24 21:39:02 +00:00
2015-10-21 19:54:14 +00:00
if ( ( tspr - > cstat & 48 ) = = 32 )
{
numpts = 4 ;
get_floorspr_points ( tspr , 0 , 0 ,
& xx [ 0 ] , & xx [ 1 ] , & xx [ 2 ] , & xx [ 3 ] ,
& yy [ 0 ] , & yy [ 1 ] , & yy [ 2 ] , & yy [ 3 ] ) ;
}
else
{
const int32_t oang = tspr - > ang ;
numpts = 2 ;
2014-01-24 21:39:02 +00:00
2015-10-21 19:54:14 +00:00
// Consider face sprites as wall sprites with camera ang.
// XXX: factor 4/5 needed?
if ( ( tspr - > cstat & 48 ) ! = 16 )
tspriteptr [ i ] - > ang = globalang ;
2014-01-24 21:39:02 +00:00
2019-12-26 06:27:48 +00:00
get_wallspr_points ( tspr , & xx [ 0 ] , & xx [ 1 ] , & yy [ 0 ] , & yy [ 1 ] ) ;
2014-01-24 21:39:02 +00:00
2020-02-22 15:56:20 +00:00
if ( ( tspr - > cstat & 48 ) ! = 16 )
2015-10-21 19:54:14 +00:00
tspriteptr [ i ] - > ang = oang ;
2014-01-24 21:39:02 +00:00
}
2015-10-21 19:54:14 +00:00
for ( jj = 0 ; jj < numpts ; jj + + )
2014-01-24 21:39:02 +00:00
{
2015-10-21 19:54:14 +00:00
spr . x = ( float ) xx [ jj ] ;
spr . y = ( float ) yy [ jj ] ;
if ( ! sameside ( & maskeq , & spr , & pos ) ) // behind the maskwall,
if ( ( sameside ( & p1eq , & middle , & spr ) & & // inside the 'cone',
sameside ( & p2eq , & middle , & spr ) )
| | ! sameside ( & pineq , & middle , & spr ) ) // or on the other outside.
{
ok = 1 ;
break ;
}
2014-01-24 21:39:02 +00:00
}
2007-12-12 17:42:14 +00:00
}
2015-10-21 19:54:14 +00:00
if ( ok )
{
debugmask_add ( i | 32768 , tspr - > owner ) ;
2018-04-12 21:04:00 +00:00
renderDrawSprite ( i ) ;
2016-09-09 03:12:23 +00:00
2015-10-21 19:54:14 +00:00
tspriteptr [ i ] = NULL ;
}
2006-08-29 01:58:59 +00:00
}
}
2015-10-21 19:54:14 +00:00
}
debugmask_add ( maskwall [ maskwallcnt ] , thewall [ maskwall [ maskwallcnt ] ] ) ;
2018-04-12 21:04:00 +00:00
renderDrawMaskedWall ( maskwallcnt ) ;
2015-10-21 19:54:14 +00:00
}
2013-04-21 19:55:38 +00:00
2019-04-19 21:45:22 +00:00
while ( spritesortcnt )
{
- - spritesortcnt ;
if ( tspriteptr [ spritesortcnt ] ! = NULL )
2015-10-21 19:54:14 +00:00
{
debugmask_add ( i | 32768 , tspriteptr [ i ] - > owner ) ;
2019-04-19 21:45:22 +00:00
renderDrawSprite ( spritesortcnt ) ;
tspriteptr [ spritesortcnt ] = NULL ;
2006-04-13 20:47:06 +00:00
}
2015-10-21 19:54:14 +00:00
}
2020-06-04 16:46:44 +00:00
renderFinishScene ( ) ;
GLInterface . SetDepthMask ( true ) ;
2020-06-12 20:32:49 +00:00
GLInterface . SetDepthBias ( 0 , 0 ) ;
2006-12-31 06:32:04 +00:00
}
2006-04-13 20:47:06 +00:00
2019-12-31 14:41:12 +00:00
2020-05-25 15:11:32 +00:00
//==========================================================================
//
//
//
//==========================================================================
void FillPolygon ( int * rx1 , int * ry1 , int * xb1 , int32_t npoints , int picnum , int palette , int shade , int props , const FVector2 & xtex , const FVector2 & ytex , const FVector2 & otex ,
int clipx1 , int clipy1 , int clipx2 , int clipy2 )
{
//Convert int32_t to float (in-place)
TArray < FVector4 > points ( npoints , true ) ;
using Point = std : : pair < float , float > ;
std : : vector < std : : vector < Point > > polygon ;
std : : vector < Point > * curPoly ;
polygon . resize ( 1 ) ;
curPoly = & polygon . back ( ) ;
for ( bssize_t i = 0 ; i < npoints ; + + i )
{
auto X = ( ( float ) rx1 [ i ] ) * ( 1.0f / 4096.f ) ;
auto Y = ( ( float ) ry1 [ i ] ) * ( 1.0f / 4096.f ) ;
curPoly - > push_back ( std : : make_pair ( X , Y ) ) ;
if ( xb1 [ i ] < i & & i < npoints - 1 )
{
polygon . resize ( polygon . size ( ) + 1 ) ;
curPoly = & polygon . back ( ) ;
}
}
// Now make sure that the outer boundary is the first polygon by picking a point that's as much to the outside as possible.
int outer = 0 ;
float minx = FLT_MAX ;
float miny = FLT_MAX ;
for ( size_t a = 0 ; a < polygon . size ( ) ; a + + )
{
for ( auto & pt : polygon [ a ] )
{
if ( pt . first < minx | | ( pt . first = = minx & & pt . second < miny ) )
{
minx = pt . first ;
miny = pt . second ;
outer = a ;
}
}
}
if ( outer ! = 0 ) std : : swap ( polygon [ 0 ] , polygon [ outer ] ) ;
auto indices = mapbox : : earcut ( polygon ) ;
int p = 0 ;
for ( size_t a = 0 ; a < polygon . size ( ) ; a + + )
{
for ( auto & pt : polygon [ a ] )
{
FVector4 point = { pt . first , pt . second , float ( pt . first * xtex . X + pt . second * ytex . X + otex . X ) , float ( pt . first * xtex . Y + pt . second * ytex . Y + otex . Y ) } ;
points [ p + + ] = point ;
}
}
int maskprops = ( props > > 7 ) & DAMETH_MASKPROPS ;
FRenderStyle rs = LegacyRenderStyles [ STYLE_Translucent ] ;
double alpha = 1. ;
if ( maskprops > DAMETH_MASK )
{
rs = GetRenderStyle ( 0 , maskprops = = DAMETH_TRANS2 ) ;
alpha = GetAlphaFromBlend ( maskprops , 0 ) ;
}
int translation = TRANSLATION ( Translation_Remap + curbasepal , palette ) ;
int light = clamp ( scale ( ( numshades - shade ) , 255 , numshades ) , 0 , 255 ) ;
PalEntry pe = PalEntry ( uint8_t ( alpha * 255 ) , light , light , light ) ;
twod - > AddPoly ( tileGetTexture ( picnum ) , points . Data ( ) , points . Size ( ) , indices . data ( ) , indices . size ( ) , translation , pe , rs , clipx1 , clipy1 , clipx2 , clipy2 ) ;
}
void drawlinergb ( int32_t x1 , int32_t y1 , int32_t x2 , int32_t y2 , PalEntry p )
{
twod - > AddLine ( x1 / 4096.f , y1 / 4096.f , x2 / 4096.f , y2 / 4096.f , windowxy1 . x , windowxy1 . y , windowxy2 . x , windowxy2 . y , p ) ;
}
void drawlinergb ( int32_t x1 , int32_t y1 , int32_t x2 , int32_t y2 , palette_t p )
{
drawlinergb ( x1 , y1 , x2 , y2 , PalEntry ( p . r , p . g , p . b ) ) ;
}
void renderDrawLine ( int32_t x1 , int32_t y1 , int32_t x2 , int32_t y2 , uint8_t col )
{
drawlinergb ( x1 , y1 , x2 , y2 , GPalette . BaseColors [ GPalette . Remap [ col ] ] ) ;
}
//==========================================================================
//
//
//
//==========================================================================
# include "build.h"
# include "../src/engine_priv.h"
//sx,sy center of sprite; screen coords*65536
//z zoom*65536. > is zoomed in
//a angle (0 is default)
//dastat&1 1:translucence
//dastat&2 1:auto-scale mode (use 320*200 coordinates)
//dastat&4 1:y-flip
//dastat&8 1:don't clip to startumost/startdmost
//dastat&16 1:force point passed to be top-left corner, 0:Editart center
//dastat&32 1:reverse translucence
//dastat&64 1:non-masked, 0:masked
//dastat&128 1:draw all pages (permanent - no longer used)
//cx1,... clip window (actual screen coords)
//==========================================================================
//
// INTERNAL helper function for classic/polymost dorotatesprite
// sxptr, sxptr, z: in/out
// ret_yxaspect, ret_xyaspect: out
//
//==========================================================================
static int32_t dorotspr_handle_bit2 ( int32_t * sxptr , int32_t * syptr , int32_t * z , int32_t dastat , int32_t cx1_plus_cx2 , int32_t cy1_plus_cy2 )
{
if ( ( dastat & RS_AUTO ) = = 0 )
{
if ( ! ( dastat & RS_STRETCH ) & & 4 * ydim < = 3 * xdim )
{
return ( 10 < < 16 ) / 12 ;
}
else
{
return xyaspect ;
}
}
else
{
// dastat&2: Auto window size scaling
const int32_t oxdim = xdim ;
const int32_t oydim = ydim ;
int32_t xdim = oxdim ; // SHADOWS global
int32_t ydim = oydim ;
int32_t zoomsc , sx = * sxptr , sy = * syptr ;
int32_t ouryxaspect = yxaspect , ourxyaspect = xyaspect ;
sy + = rotatesprite_y_offset ;
if ( ! ( dastat & RS_STRETCH ) & & 4 * ydim < = 3 * xdim )
{
if ( ( dastat & RS_ALIGN_MASK ) & & ( dastat & RS_ALIGN_MASK ) ! = RS_ALIGN_MASK )
sx + = NEGATE_ON_CONDITION ( scale ( 120 < < 16 , xdim , ydim ) - ( 160 < < 16 ) , ! ( dastat & RS_ALIGN_R ) ) ;
if ( ( dastat & RS_ALIGN_MASK ) = = RS_ALIGN_MASK )
ydim = scale ( xdim , 3 , 4 ) ;
else
xdim = scale ( ydim , 4 , 3 ) ;
ouryxaspect = ( 12 < < 16 ) / 10 ;
ourxyaspect = ( 10 < < 16 ) / 12 ;
}
ouryxaspect = mulscale16 ( ouryxaspect , rotatesprite_yxaspect ) ;
ourxyaspect = divscale16 ( ourxyaspect , rotatesprite_yxaspect ) ;
// screen center to s[xy], 320<<16 coords.
const int32_t normxofs = sx - ( 320 < < 15 ) , normyofs = sy - ( 200 < < 15 ) ;
// nasty hacks go here
if ( ! ( dastat & RS_NOCLIP ) )
{
const int32_t twice_midcx = cx1_plus_cx2 + 2 ;
// screen x center to sx1, scaled to viewport
const int32_t scaledxofs = scale ( normxofs , scale ( xdimen , xdim , oxdim ) , 320 ) ;
sx = ( ( twice_midcx ) < < 15 ) + scaledxofs ;
zoomsc = xdimenscale ; //= scale(xdimen,yxaspect,320);
zoomsc = mulscale16 ( zoomsc , rotatesprite_yxaspect ) ;
if ( ( dastat & RS_ALIGN_MASK ) = = RS_ALIGN_MASK )
zoomsc = scale ( zoomsc , ydim , oydim ) ;
sy = ( ( cy1_plus_cy2 + 2 ) < < 15 ) + mulscale16 ( normyofs , zoomsc ) ;
}
else
{
//If not clipping to startmosts, & auto-scaling on, as a
//hard-coded bonus, scale to full screen instead
sx = ( xdim < < 15 ) + 32768 + scale ( normxofs , xdim , 320 ) ;
zoomsc = scale ( xdim , ouryxaspect , 320 ) ;
sy = ( ydim < < 15 ) + 32768 + mulscale16 ( normyofs , zoomsc ) ;
if ( ( dastat & RS_ALIGN_MASK ) = = RS_ALIGN_MASK )
sy + = ( oydim - ydim ) < < 15 ;
else
sx + = ( oxdim - xdim ) < < 15 ;
if ( dastat & RS_CENTERORIGIN )
sx + = oxdim < < 15 ;
}
* sxptr = sx ;
* syptr = sy ;
* z = mulscale16 ( * z , zoomsc ) ;
return ourxyaspect ;
}
}
//==========================================================================
//
//
//
//==========================================================================
2020-05-19 22:35:52 +00:00
void twod_rotatesprite ( F2DDrawer * twod , int32_t sx , int32_t sy , int32_t z , int16_t a , int16_t picnum ,
2020-05-25 15:11:32 +00:00
int8_t dashade , uint8_t dapalnum , int32_t dastat , uint8_t daalpha , uint8_t dablend ,
2020-05-25 21:59:07 +00:00
int32_t clipx1 , int32_t clipy1 , int32_t clipx2 , int32_t clipy2 , FGameTexture * pic , int basepal )
2020-05-25 15:11:32 +00:00
{
2020-05-19 22:35:52 +00:00
// todo: re-add
#if 0
if ( ! tex & & ( dastat & RS_MODELSUBST ) )
{
tileUpdatePicnum ( & picnum , ( int16_t ) 0xc000 ) ;
if ( ( tileWidth ( picnum ) < = 0 ) | | ( tileHeight ( picnum ) < = 0 ) ) return ;
if ( hw_models & & tile2model [ picnum ] . hudmem [ ( dastat & 4 ) > > 2 ] )
{
polymost_dorotatespritemodel ( sx , sy , z , a , picnum , dashade , dapalnum , dastat , daalpha , dablend , guniqhudid ) ;
return ;
}
}
2020-05-21 09:59:52 +00:00
else
2020-05-19 22:35:52 +00:00
# endif
2020-05-21 09:59:52 +00:00
if ( ! pic ) tileUpdatePicnum ( & picnum , 0 ) ;
2020-05-19 22:35:52 +00:00
2020-05-25 15:11:32 +00:00
F2DDrawer : : RenderCommand dg = { } ;
int method = 0 ;
dg . mType = F2DDrawer : : DrawTypeTriangles ;
if ( clipx1 > 0 | | clipy1 > 0 | | clipx2 < screen - > GetWidth ( ) - 1 | | clipy2 < screen - > GetHeight ( ) - 1 )
{
dg . mScissor [ 0 ] = clipx1 ;
dg . mScissor [ 1 ] = clipy1 ;
dg . mScissor [ 2 ] = clipx2 + 1 ;
dg . mScissor [ 3 ] = clipy2 + 1 ;
dg . mFlags | = F2DDrawer : : DTF_Scissor ;
}
if ( ! ( dastat & RS_NOMASK ) )
{
if ( dastat & RS_TRANS1 )
method | = ( dastat & RS_TRANS2 ) ? DAMETH_TRANS2 : DAMETH_TRANS1 ;
else
method | = DAMETH_MASK ;
dg . mRenderStyle = GetRenderStyle ( dablend , ( dastat & RS_TRANS2 ) ? 1 : 0 ) ;
}
else
{
dg . mRenderStyle = LegacyRenderStyles [ STYLE_Normal ] ;
}
dg . mTexture = pic ? pic : tileGetTexture ( picnum ) ;
2020-05-30 18:55:29 +00:00
if ( ! dg . mTexture | | ! dg . mTexture - > isValid ( ) ) return ; // empty tile.
2020-06-07 11:50:41 +00:00
// todo: check for hires replacements.
// The weapon drawer needs to use the global base palette.
if ( twod = = & twodpsp ) dg . mTranslationId = TRANSLATION ( Translation_Remap + curbasepal , dapalnum ) ;
else if ( basepal = = 0 & & dapalnum = = 0 & & pic ) dg . mTranslationId = 0 ;
2020-05-30 18:55:29 +00:00
else dg . mTranslationId = TRANSLATION ( Translation_Remap + basepal , dapalnum ) ;
2020-05-25 15:11:32 +00:00
dg . mVertCount = 4 ;
dg . mVertIndex = ( int ) twod - > mVertices . Reserve ( 4 ) ;
auto ptr = & twod - > mVertices [ dg . mVertIndex ] ;
float drawpoly_alpha = daalpha * ( 1.0f / 255.0f ) ;
float alpha = GetAlphaFromBlend ( method , dablend ) * ( 1.f - drawpoly_alpha ) ; // Hmmm...
2020-06-07 12:50:12 +00:00
PalEntry p ;
if ( ! hw_useindexedcolortextures )
{
int light = clamp ( scale ( ( numshades - dashade ) , 255 , numshades ) , 0 , 255 ) ;
p = PalEntry ( ( uint8_t ) ( alpha * 255 ) , light , light , light ) ;
}
else
{
p = PalEntry ( ( uint8_t ) ( alpha * 255 ) , 255 , 255 , 255 ) ;
dg . mLightLevel = clamp ( dashade , 0 , numshades ) ;
}
2020-05-25 15:11:32 +00:00
2020-05-25 21:59:07 +00:00
vec2_t const siz = { ( int ) dg . mTexture - > GetDisplayWidth ( ) , ( int ) dg . mTexture - > GetDisplayHeight ( ) } ;
2020-05-25 15:11:32 +00:00
vec2_16_t ofs = { 0 , 0 } ;
if ( ! ( dastat & RS_TOPLEFT ) )
{
2020-05-27 21:30:36 +00:00
if ( ! pic & & ! ( dastat & RS_CENTER ) )
2020-05-25 15:11:32 +00:00
{
ofs = { int16_t ( tileLeftOffset ( picnum ) + ( siz . x > > 1 ) ) ,
int16_t ( tileTopOffset ( picnum ) + ( siz . y > > 1 ) ) } ;
}
else
{
ofs = { int16_t ( ( siz . x > > 1 ) ) ,
int16_t ( ( siz . y > > 1 ) ) } ;
}
}
if ( dastat & RS_YFLIP )
ofs . y = siz . y - ofs . y ;
int32_t aspectcorrect = dorotspr_handle_bit2 ( & sx , & sy , & z , dastat , clipx1 + clipx2 , clipy1 + clipy2 ) ;
int32_t cosang = mulscale14 ( sintable [ ( a + 512 ) & 2047 ] , z ) ;
int32_t cosang2 = cosang ;
int32_t sinang = mulscale14 ( sintable [ a & 2047 ] , z ) ;
int32_t sinang2 = sinang ;
if ( ( dastat & RS_AUTO ) | | ( ! ( dastat & RS_NOCLIP ) ) ) // Don't aspect unscaled perms
{
cosang2 = mulscale16 ( cosang2 , aspectcorrect ) ;
sinang2 = mulscale16 ( sinang2 , aspectcorrect ) ;
}
int cx0 = sx - ofs . x * cosang2 + ofs . y * sinang2 ;
int cy0 = sy - ofs . x * sinang - ofs . y * cosang ;
int cx1 = cx0 + siz . x * cosang2 ;
int cy1 = cy0 + siz . x * sinang ;
int cx3 = cx0 - siz . y * sinang2 ;
int cy3 = cy0 + siz . y * cosang ;
int cx2 = cx1 + cx3 - cx0 ;
int cy2 = cy1 + cy3 - cy0 ;
float y = ( dastat & RS_YFLIP ) ? 1.f : 0.f ;
ptr - > Set ( cx0 / 65536.f , cy0 / 65536.f , 0.f , 0.f , y , p ) ; ptr + + ;
ptr - > Set ( cx1 / 65536.f , cy1 / 65536.f , 0.f , 1.f , y , p ) ; ptr + + ;
ptr - > Set ( cx2 / 65536.f , cy2 / 65536.f , 0.f , 1.f , 1.f - y , p ) ; ptr + + ;
ptr - > Set ( cx3 / 65536.f , cy3 / 65536.f , 0.f , 0.f , 1.f - y , p ) ; ptr + + ;
dg . mIndexIndex = twod - > mIndices . Size ( ) ;
dg . mIndexCount + = 6 ;
twod - > AddIndices ( dg . mVertIndex , 6 , 0 , 1 , 2 , 0 , 2 , 3 ) ;
twod - > AddCommand ( & dg ) ;
}
2020-05-19 22:35:52 +00:00
void rotatesprite_ ( int32_t sx , int32_t sy , int32_t z , int16_t a , int16_t picnum ,
int8_t dashade , uint8_t dapalnum , int32_t dastat , uint8_t daalpha , uint8_t dablend ,
int32_t cx1 , int32_t cy1 , int32_t cx2 , int32_t cy2 , FGameTexture * tex , int basepal )
{
if ( ! tex & & ( unsigned ) picnum > = MAXTILES )
return ;
if ( ( cx1 > cx2 ) | | ( cy1 > cy2 ) ) return ;
if ( z < = 16 ) return ;
// We must store all calls in the 2D drawer so that the backend can operate on a clean 3D view.
twod_rotatesprite ( twod , sx , sy , z , a , picnum , dashade , dapalnum , dastat , daalpha , dablend , cx1 , cy1 , cx2 , cy2 , tex , basepal ) ;
}
2020-05-25 15:11:32 +00:00
2019-12-31 14:41:12 +00:00
//
// fillpolygon (internal)
//
static void renderFillPolygon ( int32_t npoints )
{
// fix for bad next-point (xb1) values...
for ( int z = 0 ; z < npoints ; z + + )
if ( ( unsigned ) xb1 [ z ] > = ( unsigned ) npoints )
xb1 [ z ] = 0 ;
2019-12-31 16:23:29 +00:00
FVector2 xtex , ytex , otex ;
int x1 = mulscale16 ( globalx1 , xyaspect ) ;
int y2 = mulscale16 ( globaly2 , xyaspect ) ;
xtex . X = ( ( float ) asm1 ) * ( 1.f / 4294967296.f ) ;
xtex . Y = ( ( float ) asm2 ) * ( 1.f / 4294967296.f ) ;
ytex . X = ( ( float ) x1 ) * ( 1.f / 4294967296.f ) ;
ytex . Y = ( ( float ) y2 ) * ( - 1.f / 4294967296.f ) ;
otex . X = ( fxdim * xtex . X + fydim * ytex . X ) * - 0.5f + fglobalposx * ( 1.f / 4294967296.f ) ;
otex . Y = ( fxdim * xtex . Y + fydim * ytex . Y ) * - 0.5f - fglobalposy * ( 1.f / 4294967296.f ) ;
2020-05-25 15:11:32 +00:00
FillPolygon ( rx1 , ry1 , xb1 , npoints , globalpicnum , globalpal , globalshade , globalorientation , xtex , ytex , otex , windowxy1 . x , windowxy1 . y , windowxy2 . x , windowxy2 . y ) ;
2019-12-31 14:41:12 +00:00
}
2006-04-13 20:47:06 +00:00
//
// drawmapview
//
2018-04-12 21:03:47 +00:00
void renderDrawMapView ( int32_t dax , int32_t day , int32_t zoome , int16_t ang )
2006-04-13 20:47:06 +00:00
{
2012-11-17 19:46:50 +00:00
int32_t i , j , k , l ;
2015-07-17 00:12:40 +00:00
int32_t x , y ;
int32_t s , ox , oy ;
2010-06-22 21:50:01 +00:00
2015-07-17 00:12:40 +00:00
int32_t const oyxaspect = yxaspect , oviewingrange = viewingrange ;
2010-10-17 14:49:39 +00:00
2018-04-12 21:03:47 +00:00
renderSetAspect ( 65536 , divscale16 ( ( 320 * 5 ) / 8 , 200 ) ) ;
2006-04-13 20:47:06 +00:00
beforedrawrooms = 0 ;
2019-09-03 04:09:20 +00:00
Bmemset ( gotsector , 0 , sizeof ( gotsector ) ) ;
2006-04-13 20:47:06 +00:00
2017-02-05 20:58:33 +00:00
vec2_t const c1 = { ( windowxy1 . x < < 12 ) , ( windowxy1 . y < < 12 ) } ;
vec2_t const c2 = { ( ( windowxy2 . x + 1 ) < < 12 ) - 1 , ( ( windowxy2 . y + 1 ) < < 12 ) - 1 } ;
2009-09-09 07:19:14 +00:00
2006-04-13 20:47:06 +00:00
zoome < < = 8 ;
2009-09-09 07:19:14 +00:00
2015-07-17 00:12:40 +00:00
vec2_t const bakgvect = { divscale28 ( sintable [ ( 1536 - ang ) & 2047 ] , zoome ) ,
divscale28 ( sintable [ ( 2048 - ang ) & 2047 ] , zoome ) } ;
vec2_t const vect = { mulscale8 ( sintable [ ( 2048 - ang ) & 2047 ] , zoome ) , mulscale8 ( sintable [ ( 1536 - ang ) & 2047 ] , zoome ) } ;
vec2_t const vect2 = { mulscale16 ( vect . x , yxaspect ) , mulscale16 ( vect . y , yxaspect ) } ;
2006-04-13 20:47:06 +00:00
2015-07-17 00:12:40 +00:00
int32_t sortnum = 0 ;
2006-04-13 20:47:06 +00:00
2019-04-18 17:25:24 +00:00
usectorptr_t sec ;
2015-07-17 00:12:40 +00:00
2019-04-18 17:25:24 +00:00
for ( s = 0 , sec = ( usectorptr_t ) & sector [ s ] ; s < numsectors ; s + + , sec + + )
2020-03-07 09:04:29 +00:00
if ( gFullMap | | show2dsector [ s ] )
2006-04-13 20:47:06 +00:00
{
2015-07-17 00:12:40 +00:00
int32_t npoints = 0 ; i = 0 ;
int32_t startwall = sec - > wallptr ;
2006-04-13 20:47:06 +00:00
j = startwall ; l = 0 ;
2019-04-18 17:25:24 +00:00
uwallptr_t wal ;
2015-07-17 00:12:40 +00:00
int32_t w ;
2019-04-18 17:25:24 +00:00
for ( w = sec - > wallnum , wal = ( uwallptr_t ) & wall [ startwall ] ; w > 0 ; w - - , wal + + , j + + )
2006-04-13 20:47:06 +00:00
{
k = lastwall ( j ) ;
if ( ( k > j ) & & ( npoints > 0 ) ) { xb1 [ npoints - 1 ] = l ; l = npoints ; } //overwrite point2
2006-04-24 19:04:22 +00:00
//wall[k].x wal->x wall[wal->point2].x
//wall[k].y wal->y wall[wal->point2].y
2006-04-13 20:47:06 +00:00
if ( ! dmulscale1 ( wal - > x - wall [ k ] . x , wall [ wal - > point2 ] . y - wal - > y , - ( wal - > y - wall [ k ] . y ) , wall [ wal - > point2 ] . x - wal - > x ) ) continue ;
ox = wal - > x - dax ; oy = wal - > y - day ;
2015-07-17 00:12:40 +00:00
x = dmulscale16 ( ox , vect . x , - oy , vect . y ) + ( xdim < < 11 ) ;
y = dmulscale16 ( oy , vect2 . x , ox , vect2 . y ) + ( ydim < < 11 ) ;
i | = getclipmask ( x - c1 . x , c2 . x - x , y - c1 . y , c2 . y - y ) ;
2006-04-13 20:47:06 +00:00
rx1 [ npoints ] = x ;
ry1 [ npoints ] = y ;
xb1 [ npoints ] = npoints + 1 ;
npoints + + ;
}
if ( npoints > 0 ) xb1 [ npoints - 1 ] = l ; //overwrite point2
2015-07-17 00:12:40 +00:00
2017-02-05 20:58:33 +00:00
vec2_t bak = { rx1 [ 0 ] , mulscale16 ( ry1 [ 0 ] - ( ydim < < 11 ) , xyaspect ) + ( ydim < < 11 ) } ;
2015-07-17 00:12:40 +00:00
2006-04-13 20:47:06 +00:00
2006-04-24 19:04:22 +00:00
//Collect floor sprites to draw
2009-02-19 16:47:54 +00:00
for ( i = headspritesect [ s ] ; i > = 0 ; i = nextspritesect [ i ] )
2019-08-16 12:05:29 +00:00
{
if ( sprite [ i ] . cstat & 32768 )
continue ;
if ( ( sprite [ i ] . cstat & 48 ) = = 32 )
2006-04-13 20:47:06 +00:00
{
2019-08-16 12:05:29 +00:00
if ( ( sprite [ i ] . cstat & ( 64 + 8 ) ) = = ( 64 + 8 ) )
continue ;
2006-04-13 20:47:06 +00:00
tsprite [ sortnum + + ] . owner = i ;
}
2019-08-16 12:05:29 +00:00
}
2006-04-13 20:47:06 +00:00
gotsector [ s > > 3 ] | = pow2char [ s & 7 ] ;
2009-01-09 09:29:17 +00:00
globalorientation = ( int32_t ) sec - > floorstat ;
2006-04-13 20:47:06 +00:00
if ( ( globalorientation & 1 ) ! = 0 ) continue ;
2006-04-23 08:23:40 +00:00
globalpal = sec - > floorpal ;
2006-04-13 20:47:06 +00:00
globalpicnum = sec - > floorpicnum ;
if ( ( unsigned ) globalpicnum > = ( unsigned ) MAXTILES ) globalpicnum = 0 ;
2019-06-25 11:30:22 +00:00
tileUpdatePicnum ( & globalpicnum , s ) ;
2006-04-13 20:47:06 +00:00
setgotpic ( globalpicnum ) ;
2014-09-30 04:14:21 +00:00
if ( ( tilesiz [ globalpicnum ] . x < = 0 ) | | ( tilesiz [ globalpicnum ] . y < = 0 ) ) continue ;
2019-10-11 21:31:59 +00:00
2019-10-15 21:18:52 +00:00
globalshade = max ( min < int > ( sec - > floorshade , numshades - 1 ) , 0 ) ;
2006-04-13 20:47:06 +00:00
if ( ( globalorientation & 64 ) = = 0 )
{
2014-10-25 03:32:26 +00:00
set_globalpos ( dax , day , globalposz ) ;
2015-07-17 00:12:40 +00:00
globalx1 = bakgvect . x ; globaly1 = bakgvect . y ;
globalx2 = bakgvect . x ; globaly2 = bakgvect . y ;
2006-04-13 20:47:06 +00:00
}
else
{
ox = wall [ wall [ startwall ] . point2 ] . x - wall [ startwall ] . x ;
oy = wall [ wall [ startwall ] . point2 ] . y - wall [ startwall ] . y ;
2012-07-01 22:11:14 +00:00
i = nsqrtasm ( uhypsq ( ox , oy ) ) ; if ( i = = 0 ) continue ;
2006-04-13 20:47:06 +00:00
i = 1048576 / i ;
2015-07-17 00:12:40 +00:00
globalx1 = mulscale10 ( dmulscale10 ( ox , bakgvect . x , oy , bakgvect . y ) , i ) ;
globaly1 = mulscale10 ( dmulscale10 ( ox , bakgvect . y , - oy , bakgvect . x ) , i ) ;
ox = ( bak . x > > 4 ) - ( xdim < < 7 ) ; oy = ( bak . y > > 4 ) - ( ydim < < 7 ) ;
2014-10-25 03:32:26 +00:00
globalposx = dmulscale28 ( - oy , globalx1 , - ox , globaly1 ) ;
globalposy = dmulscale28 ( - ox , globalx1 , oy , globaly1 ) ;
2006-04-13 20:47:06 +00:00
globalx2 = - globalx1 ;
globaly2 = - globaly1 ;
2015-07-17 00:12:40 +00:00
int32_t const daslope = sector [ s ] . floorheinum ;
2006-04-13 20:47:06 +00:00
i = nsqrtasm ( daslope * daslope + 16777216 ) ;
2014-10-25 03:32:26 +00:00
set_globalpos ( globalposx , mulscale12 ( globalposy , i ) , globalposz ) ;
2006-04-13 20:47:06 +00:00
globalx2 = mulscale12 ( globalx2 , i ) ;
globaly2 = mulscale12 ( globaly2 , i ) ;
}
2012-12-14 19:28:14 +00:00
calc_globalshifts ( ) ;
2006-04-13 20:47:06 +00:00
if ( ( globalorientation & 0x4 ) > 0 )
{
i = globalposx ; globalposx = - globalposy ; globalposy = - i ;
i = globalx2 ; globalx2 = globaly1 ; globaly1 = i ;
i = globalx1 ; globalx1 = - globaly2 ; globaly2 = - i ;
}
if ( ( globalorientation & 0x10 ) > 0 ) globalx1 = - globalx1 , globaly1 = - globaly1 , globalposx = - globalposx ;
if ( ( globalorientation & 0x20 ) > 0 ) globalx2 = - globalx2 , globaly2 = - globaly2 , globalposy = - globalposy ;
asm1 = ( globaly1 < < globalxshift ) ;
asm2 = ( globalx2 < < globalyshift ) ;
globalx1 < < = globalxshift ;
globaly2 < < = globalyshift ;
2014-10-25 03:32:26 +00:00
set_globalpos ( ( ( int64_t ) globalposx < < ( 20 + globalxshift ) ) + ( ( ( uint32_t ) sec - > floorxpanning ) < < 24 ) ,
( ( int64_t ) globalposy < < ( 20 + globalyshift ) ) - ( ( ( uint32_t ) sec - > floorypanning ) < < 24 ) ,
globalposz ) ;
2018-04-12 21:04:00 +00:00
renderFillPolygon ( npoints ) ;
2006-04-13 20:47:06 +00:00
}
2006-04-24 19:04:22 +00:00
//Sort sprite list
2015-07-17 00:12:40 +00:00
int32_t gap = 1 ;
while ( gap < sortnum ) gap = ( gap < < 1 ) + 1 ;
2009-02-19 16:47:54 +00:00
for ( gap > > = 1 ; gap > 0 ; gap > > = 1 )
for ( i = 0 ; i < sortnum - gap ; i + + )
for ( j = i ; j > = 0 ; j - = gap )
2006-04-13 20:47:06 +00:00
{
if ( sprite [ tsprite [ j ] . owner ] . z < = sprite [ tsprite [ j + gap ] . owner ] . z ) break ;
swapshort ( & tsprite [ j ] . owner , & tsprite [ j + gap ] . owner ) ;
}
2009-02-19 16:47:54 +00:00
for ( s = sortnum - 1 ; s > = 0 ; s - - )
2006-04-13 20:47:06 +00:00
{
2019-04-18 17:24:10 +00:00
auto const spr = ( uspritetype * ) & sprite [ tsprite [ s ] . owner ] ;
2006-04-13 20:47:06 +00:00
if ( ( spr - > cstat & 48 ) = = 32 )
{
2014-12-05 23:12:36 +00:00
const int32_t xspan = tilesiz [ spr - > picnum ] . x ;
2012-11-17 19:46:50 +00:00
2015-07-17 00:12:40 +00:00
int32_t npoints = 0 ;
2017-02-05 20:58:33 +00:00
vec2_t v1 = { spr - > x , spr - > y } , v2 , v3 , v4 ;
2006-04-13 20:47:06 +00:00
2015-07-17 00:12:40 +00:00
get_floorspr_points ( spr , 0 , 0 , & v1 . x , & v2 . x , & v3 . x , & v4 . x ,
& v1 . y , & v2 . y , & v3 . y , & v4 . y ) ;
2006-04-13 20:47:06 +00:00
xb1 [ 0 ] = 1 ; xb1 [ 1 ] = 2 ; xb1 [ 2 ] = 3 ; xb1 [ 3 ] = 0 ;
npoints = 4 ;
i = 0 ;
2015-07-17 00:12:40 +00:00
ox = v1 . x - dax ; oy = v1 . y - day ;
x = dmulscale16 ( ox , vect . x , - oy , vect . y ) + ( xdim < < 11 ) ;
y = dmulscale16 ( oy , vect2 . x , ox , vect2 . y ) + ( ydim < < 11 ) ;
i | = getclipmask ( x - c1 . x , c2 . x - x , y - c1 . y , c2 . y - y ) ;
2006-04-13 20:47:06 +00:00
rx1 [ 0 ] = x ; ry1 [ 0 ] = y ;
2015-07-17 00:12:40 +00:00
ox = v2 . x - dax ; oy = v2 . y - day ;
x = dmulscale16 ( ox , vect . x , - oy , vect . y ) + ( xdim < < 11 ) ;
y = dmulscale16 ( oy , vect2 . x , ox , vect2 . y ) + ( ydim < < 11 ) ;
i | = getclipmask ( x - c1 . x , c2 . x - x , y - c1 . y , c2 . y - y ) ;
2006-04-13 20:47:06 +00:00
rx1 [ 1 ] = x ; ry1 [ 1 ] = y ;
2015-07-17 00:12:40 +00:00
ox = v3 . x - dax ; oy = v3 . y - day ;
x = dmulscale16 ( ox , vect . x , - oy , vect . y ) + ( xdim < < 11 ) ;
y = dmulscale16 ( oy , vect2 . x , ox , vect2 . y ) + ( ydim < < 11 ) ;
i | = getclipmask ( x - c1 . x , c2 . x - x , y - c1 . y , c2 . y - y ) ;
2006-04-13 20:47:06 +00:00
rx1 [ 2 ] = x ; ry1 [ 2 ] = y ;
x = rx1 [ 0 ] + rx1 [ 2 ] - rx1 [ 1 ] ;
y = ry1 [ 0 ] + ry1 [ 2 ] - ry1 [ 1 ] ;
2015-07-17 00:12:40 +00:00
i | = getclipmask ( x - c1 . x , c2 . x - x , y - c1 . y , c2 . y - y ) ;
2006-04-13 20:47:06 +00:00
rx1 [ 3 ] = x ; ry1 [ 3 ] = y ;
2015-07-17 00:12:40 +00:00
vec2_t bak = { rx1 [ 0 ] , mulscale16 ( ry1 [ 0 ] - ( ydim < < 11 ) , xyaspect ) + ( ydim < < 11 ) } ;
2006-04-13 20:47:06 +00:00
globalpicnum = spr - > picnum ;
2010-01-18 11:40:40 +00:00
globalpal = spr - > pal ; // GL needs this, software doesn't
2006-04-13 20:47:06 +00:00
if ( ( unsigned ) globalpicnum > = ( unsigned ) MAXTILES ) globalpicnum = 0 ;
2019-06-25 11:30:22 +00:00
tileUpdatePicnum ( & globalpicnum , s ) ;
2006-04-13 20:47:06 +00:00
setgotpic ( globalpicnum ) ;
2014-09-30 04:14:21 +00:00
if ( ( tilesiz [ globalpicnum ] . x < = 0 ) | | ( tilesiz [ globalpicnum ] . y < = 0 ) ) continue ;
2019-10-11 21:31:59 +00:00
2006-04-13 20:47:06 +00:00
if ( ( sector [ spr - > sectnum ] . ceilingstat & 1 ) > 0 )
2009-01-09 09:29:17 +00:00
globalshade = ( ( int32_t ) sector [ spr - > sectnum ] . ceilingshade ) ;
2006-04-13 20:47:06 +00:00
else
2009-01-09 09:29:17 +00:00
globalshade = ( ( int32_t ) sector [ spr - > sectnum ] . floorshade ) ;
2012-03-20 18:32:00 +00:00
globalshade = max ( min ( globalshade + spr - > shade + 6 , numshades - 1 ) , 0 ) ;
2006-04-13 20:47:06 +00:00
2006-04-24 19:04:22 +00:00
//relative alignment stuff
2015-07-17 00:12:40 +00:00
ox = v2 . x - v1 . x ; oy = v2 . y - v1 . y ;
2020-07-14 18:21:16 +00:00
i = ox * ox + oy * oy ; if ( i = = 0 ) continue ; i = 65536 * 16384 / i ;
2015-07-17 00:12:40 +00:00
globalx1 = mulscale10 ( dmulscale10 ( ox , bakgvect . x , oy , bakgvect . y ) , i ) ;
globaly1 = mulscale10 ( dmulscale10 ( ox , bakgvect . y , - oy , bakgvect . x ) , i ) ;
ox = v1 . y - v4 . y ; oy = v4 . x - v1 . x ;
2020-07-14 18:21:16 +00:00
i = ox * ox + oy * oy ; if ( i = = 0 ) continue ; i = 65536 * 16384 / i ;
2015-07-17 00:12:40 +00:00
globalx2 = mulscale10 ( dmulscale10 ( ox , bakgvect . x , oy , bakgvect . y ) , i ) ;
globaly2 = mulscale10 ( dmulscale10 ( ox , bakgvect . y , - oy , bakgvect . x ) , i ) ;
2006-04-13 20:47:06 +00:00
2020-05-23 22:27:24 +00:00
ox = widthBits ( globalpicnum ) ;
oy = heightBits ( globalpicnum ) ;
2006-04-13 20:47:06 +00:00
if ( pow2long [ ox ] ! = xspan )
{
ox + + ;
globalx1 = mulscale ( globalx1 , xspan , ox ) ;
globaly1 = mulscale ( globaly1 , xspan , ox ) ;
}
2015-07-17 00:12:40 +00:00
bak . x = ( bak . x > > 4 ) - ( xdim < < 7 ) ; bak . y = ( bak . y > > 4 ) - ( ydim < < 7 ) ;
globalposx = dmulscale28 ( - bak . y , globalx1 , - bak . x , globaly1 ) ;
globalposy = dmulscale28 ( bak . x , globalx2 , - bak . y , globaly2 ) ;
2006-04-13 20:47:06 +00:00
if ( ( spr - > cstat & 0x4 ) > 0 ) globalx1 = - globalx1 , globaly1 = - globaly1 , globalposx = - globalposx ;
asm1 = ( globaly1 < < 2 ) ; globalx1 < < = 2 ; globalposx < < = ( 20 + 2 ) ;
asm2 = ( globalx2 < < 2 ) ; globaly2 < < = 2 ; globalposy < < = ( 20 + 2 ) ;
2014-10-25 03:32:26 +00:00
set_globalpos ( globalposx , globalposy , globalposz ) ;
2012-03-13 20:06:37 +00:00
// so polymost can get the translucency. ignored in software mode:
globalorientation = ( ( spr - > cstat & 2 ) < < 7 ) | ( ( spr - > cstat & 512 ) > > 2 ) ;
2018-04-12 21:04:00 +00:00
renderFillPolygon ( npoints ) ;
2006-04-13 20:47:06 +00:00
}
}
2010-10-17 14:49:39 +00:00
if ( r_usenewaspect )
2018-04-12 21:03:47 +00:00
renderSetAspect ( oviewingrange , oyxaspect ) ;
2010-10-17 14:49:39 +00:00
else
2018-04-12 21:03:47 +00:00
renderSetAspect ( 65536 , divscale16 ( ydim * 320 , xdim * 200 ) ) ;
2006-04-13 20:47:06 +00:00
}
2012-10-01 17:52:37 +00:00
//////////////////// LOADING AND SAVING ROUTINES ////////////////////
2017-02-25 08:15:53 +00:00
static FORCE_INLINE int32_t have_maptext ( void )
2013-05-06 19:43:42 +00:00
{
return ( mapversion > = 10 ) ;
}
2019-11-01 21:17:15 +00:00
static void enginePrepareLoadBoard ( FileReader & fr , vec3_t * dapos , int16_t * daang , int16_t * dacursectnum )
2012-10-01 17:52:37 +00:00
{
initspritelists ( ) ;
2020-03-07 09:04:29 +00:00
show2dsector . Zero ( ) ;
2012-10-01 17:52:37 +00:00
Bmemset ( show2dsprite , 0 , sizeof ( show2dsprite ) ) ;
Bmemset ( show2dwall , 0 , sizeof ( show2dwall ) ) ;
2016-10-24 21:30:34 +00:00
# ifdef USE_OPENGL
2016-10-25 05:43:46 +00:00
Polymost_prepare_loadboard ( ) ;
2016-10-24 21:30:34 +00:00
# endif
2013-05-06 19:43:42 +00:00
if ( ! have_maptext ( ) )
{
2019-11-01 21:17:15 +00:00
fr . Read ( & dapos - > x , 4 ) ; dapos - > x = B_LITTLE32 ( dapos - > x ) ;
fr . Read ( & dapos - > y , 4 ) ; dapos - > y = B_LITTLE32 ( dapos - > y ) ;
fr . Read ( & dapos - > z , 4 ) ; dapos - > z = B_LITTLE32 ( dapos - > z ) ;
fr . Read ( daang , 2 ) ; * daang = B_LITTLE16 ( * daang ) & 2047 ;
fr . Read ( dacursectnum , 2 ) ; * dacursectnum = B_LITTLE16 ( * dacursectnum ) ;
2013-05-06 19:43:42 +00:00
}
2012-10-01 17:52:37 +00:00
}
2018-04-12 21:03:47 +00:00
static int32_t engineFinishLoadBoard ( const vec3_t * dapos , int16_t * dacursectnum , int16_t numsprites , char myflags )
2012-10-01 17:52:37 +00:00
{
2013-04-21 19:55:22 +00:00
int32_t i , realnumsprites = numsprites , numremoved ;
2012-10-01 17:52:37 +00:00
2013-01-08 06:17:10 +00:00
# if !defined USE_OPENGL || !defined POLYMER
UNREFERENCED_PARAMETER ( myflags ) ;
# endif
2012-10-01 17:52:37 +00:00
for ( i = 0 ; i < numsprites ; i + + )
{
2013-04-21 19:55:18 +00:00
int32_t removeit = 0 ;
2012-10-01 17:52:37 +00:00
if ( ( sprite [ i ] . cstat & 48 ) = = 48 )
2020-07-14 15:35:19 +00:00
sprite [ i ] . cstat & = ~ 48 ;
2012-10-01 17:52:37 +00:00
2013-04-21 19:55:18 +00:00
if ( sprite [ i ] . statnum = = MAXSTATUS )
{
// Sprite was removed in loadboard() -> check_sprite(). Insert it
// for now, because we must maintain the sprite numbering.
sprite [ i ] . statnum = sprite [ i ] . sectnum = 0 ;
removeit = 1 ;
}
2012-10-01 17:52:37 +00:00
insertsprite ( sprite [ i ] . sectnum , sprite [ i ] . statnum ) ;
2013-04-21 19:55:18 +00:00
if ( removeit )
{
// Flag .statnum==MAXSTATUS, temporarily creating an inconsistency
// with sprite list.
sprite [ i ] . statnum = MAXSTATUS ;
realnumsprites - - ;
}
2012-10-01 17:52:37 +00:00
}
2013-04-21 19:55:18 +00:00
if ( numsprites ! = realnumsprites )
{
for ( i = 0 ; i < numsprites ; i + + )
if ( sprite [ i ] . statnum = = MAXSTATUS )
{
// Now remove it for real!
sprite [ i ] . statnum = 0 ;
deletesprite ( i ) ;
}
}
2013-04-21 19:55:22 +00:00
numremoved = ( numsprites - realnumsprites ) ;
2013-04-21 19:55:18 +00:00
numsprites = realnumsprites ;
Bassert ( numsprites = = Numsprites ) ;
2012-10-01 17:52:37 +00:00
//Must be after loading sectors, etc!
updatesector ( dapos - > x , dapos - > y , dacursectnum ) ;
{
Bmemset ( spriteext , 0 , sizeof ( spriteext_t ) * MAXSPRITES ) ;
2017-06-25 11:23:53 +00:00
# ifndef NEW_MAP_FORMAT
Bmemset ( wallext , 0 , sizeof ( wallext_t ) * MAXWALLS ) ;
# endif
2012-10-01 17:52:37 +00:00
# ifdef USE_OPENGL
Bmemset ( spritesmooth , 0 , sizeof ( spritesmooth_t ) * ( MAXSPRITES + MAXUNIQHUDID ) ) ;
# ifdef POLYMER
2018-04-12 21:03:12 +00:00
if ( videoGetRenderMode ( ) = = REND_POLYMER )
2012-10-01 17:52:37 +00:00
{
if ( ( myflags & 4 ) = = 0 )
polymer_loadboard ( ) ;
}
# endif
# endif
}
guniqhudid = 0 ;
2013-04-21 19:55:22 +00:00
return numremoved ;
2012-10-01 17:52:37 +00:00
}
# define MYMAXSECTORS() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXSECTORSV7 : MAXSECTORSV8)
# define MYMAXWALLS() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXWALLSV7 : MAXWALLSV8)
# define MYMAXSPRITES() (MAXSECTORS==MAXSECTORSV7 || mapversion <= 7 ? MAXSPRITESV7 : MAXSPRITESV8)
2013-04-21 19:55:18 +00:00
// Sprite checking
static void remove_sprite ( int32_t i )
{
Bmemset ( & sprite [ i ] , 0 , sizeof ( spritetype ) ) ;
sprite [ i ] . statnum = MAXSTATUS ;
sprite [ i ] . sectnum = MAXSECTORS ;
}
// This is only to be run after reading the sprite array!
2012-10-01 17:52:37 +00:00
static void check_sprite ( int32_t i )
{
2013-04-21 19:55:18 +00:00
if ( ( unsigned ) sprite [ i ] . statnum > = MAXSTATUS )
2012-10-01 17:52:37 +00:00
{
2020-04-11 21:45:45 +00:00
Printf ( " Map error: sprite #%d (%d,%d) with illegal statnum (%d) REMOVED. \n " ,
2013-04-21 19:55:18 +00:00
i , TrackerCast ( sprite [ i ] . x ) , TrackerCast ( sprite [ i ] . y ) , TrackerCast ( sprite [ i ] . statnum ) ) ;
remove_sprite ( i ) ;
}
else if ( ( unsigned ) sprite [ i ] . picnum > = MAXTILES )
{
2020-04-11 21:45:45 +00:00
Printf ( " Map error: sprite #%d (%d,%d) with illegal picnum (%d) REMOVED. \n " ,
2012-11-26 08:26:04 +00:00
i , TrackerCast ( sprite [ i ] . x ) , TrackerCast ( sprite [ i ] . y ) , TrackerCast ( sprite [ i ] . sectnum ) ) ;
2013-04-21 19:55:18 +00:00
remove_sprite ( i ) ;
}
else if ( ( unsigned ) sprite [ i ] . sectnum > = ( unsigned ) numsectors )
{
const int32_t osectnum = sprite [ i ] . sectnum ;
2012-10-01 17:52:37 +00:00
2013-04-21 19:55:18 +00:00
sprite [ i ] . sectnum = - 1 ;
2012-10-01 17:52:37 +00:00
updatesector ( sprite [ i ] . x , sprite [ i ] . y , & sprite [ i ] . sectnum ) ;
if ( sprite [ i ] . sectnum < 0 )
2013-04-21 19:55:18 +00:00
remove_sprite ( i ) ;
2012-10-01 17:52:37 +00:00
2020-04-11 21:45:45 +00:00
Printf ( " Map error: sprite #%d (%d,%d) with illegal sector (%d) " ,
2013-04-21 19:55:18 +00:00
i , TrackerCast ( sprite [ i ] . x ) , TrackerCast ( sprite [ i ] . y ) , osectnum ) ;
2012-10-01 17:52:37 +00:00
2013-04-21 19:55:18 +00:00
if ( sprite [ i ] . statnum ! = MAXSTATUS )
2020-04-11 21:45:45 +00:00
Printf ( " changed to sector %d. \n " , TrackerCast ( sprite [ i ] . sectnum ) ) ;
2013-04-21 19:55:18 +00:00
else
2020-04-11 21:45:45 +00:00
Printf ( " REMOVED. \n " ) ;
2012-10-01 17:52:37 +00:00
}
}
2015-01-08 15:14:00 +00:00
# include "md4.h"
2019-06-28 16:03:47 +00:00
int32_t ( * loadboard_replace ) ( const char * filename , char flags , vec3_t * dapos , int16_t * daang , int16_t * dacursectnum ) = NULL ;
2011-01-16 00:23:39 +00:00
// flags: 1, 2: former parameter "fromwhere"
// 4: don't call polymer_loadboard
2013-12-24 09:44:23 +00:00
// 8: don't autoexec <mapname>.cfg
// returns: on success, number of removed sprites
// -1: file not found
2012-05-25 18:39:19 +00:00
// -2: invalid version
2013-05-06 19:43:42 +00:00
// -3: invalid number of sectors, walls or sprites
// <= -4: map-text error
2018-04-12 21:03:47 +00:00
int32_t engineLoadBoard ( const char * filename , char flags , vec3_t * dapos , int16_t * daang , int16_t * dacursectnum )
2006-04-13 20:47:06 +00:00
{
2019-06-28 16:03:47 +00:00
if ( loadboard_replace )
return loadboard_replace ( filename , flags , dapos , daang , dacursectnum ) ;
2019-09-21 11:02:17 +00:00
int32_t i ;
2012-10-01 17:52:37 +00:00
int16_t numsprites ;
2013-04-09 17:35:11 +00:00
const char myflags = flags & ( ~ 3 ) ;
2011-01-16 00:23:39 +00:00
flags & = 3 ;
2006-04-13 20:47:06 +00:00
2020-04-11 21:54:33 +00:00
FileReader fr = fileSystem . OpenFileReader ( filename ) ;
2019-11-01 21:17:15 +00:00
if ( ! fr . isOpen ( ) )
2013-05-06 19:43:42 +00:00
{ mapversion = 7 ; return - 1 ; }
2006-04-13 20:47:06 +00:00
2019-11-01 21:17:15 +00:00
if ( fr . Read ( & mapversion , 4 ) ! = 4 )
2017-12-18 23:36:05 +00:00
{
2013-05-06 19:43:42 +00:00
return - 2 ;
2017-12-18 23:36:05 +00:00
}
2012-05-25 18:39:19 +00:00
{
2013-05-06 19:43:42 +00:00
int32_t ok = 0 ;
# ifdef NEW_MAP_FORMAT
// Check for map-text first.
if ( ! Bmemcmp ( & mapversion , " --ED " , 4 ) )
{
mapversion = 10 ;
ok = 1 ;
}
else
# endif
{
// Not map-text. We expect a little-endian version int now.
mapversion = B_LITTLE32 ( mapversion ) ;
2012-05-25 18:39:19 +00:00
# if MAXSECTORS==MAXSECTORSV8
2013-05-06 19:43:42 +00:00
// v8 engine
ok | = ( mapversion = = 8 ) ;
2012-05-25 18:39:19 +00:00
# endif
2013-05-06 19:43:42 +00:00
ok | = ( mapversion = = 7 ) ;
}
if ( ! ok )
{
return - 2 ;
}
2012-05-25 18:39:19 +00:00
}
2006-04-13 20:47:06 +00:00
2019-11-01 21:17:15 +00:00
enginePrepareLoadBoard ( fr , dapos , daang , dacursectnum ) ;
2013-05-06 19:43:42 +00:00
2013-04-09 17:35:11 +00:00
////////// Read sectors //////////
2019-11-01 21:17:15 +00:00
fr . Read ( & numsectors , 2 ) ; numsectors = B_LITTLE16 ( numsectors ) ;
2018-11-18 18:11:50 +00:00
if ( ( unsigned ) numsectors > = MYMAXSECTORS ( ) + 1 )
{
error :
numsectors = 0 ;
numwalls = 0 ;
numsprites = 0 ;
return - 3 ;
}
2013-04-09 17:35:11 +00:00
2019-11-01 21:17:15 +00:00
fr . Read ( sector , sizeof ( sectortypev7 ) * numsectors ) ;
2013-04-09 17:35:11 +00:00
2007-12-12 17:42:14 +00:00
for ( i = numsectors - 1 ; i > = 0 ; i - - )
{
2006-04-13 20:47:06 +00:00
sector [ i ] . wallptr = B_LITTLE16 ( sector [ i ] . wallptr ) ;
sector [ i ] . wallnum = B_LITTLE16 ( sector [ i ] . wallnum ) ;
sector [ i ] . ceilingz = B_LITTLE32 ( sector [ i ] . ceilingz ) ;
sector [ i ] . floorz = B_LITTLE32 ( sector [ i ] . floorz ) ;
sector [ i ] . ceilingstat = B_LITTLE16 ( sector [ i ] . ceilingstat ) ;
sector [ i ] . floorstat = B_LITTLE16 ( sector [ i ] . floorstat ) ;
sector [ i ] . ceilingpicnum = B_LITTLE16 ( sector [ i ] . ceilingpicnum ) ;
sector [ i ] . ceilingheinum = B_LITTLE16 ( sector [ i ] . ceilingheinum ) ;
sector [ i ] . floorpicnum = B_LITTLE16 ( sector [ i ] . floorpicnum ) ;
sector [ i ] . floorheinum = B_LITTLE16 ( sector [ i ] . floorheinum ) ;
sector [ i ] . lotag = B_LITTLE16 ( sector [ i ] . lotag ) ;
sector [ i ] . hitag = B_LITTLE16 ( sector [ i ] . hitag ) ;
sector [ i ] . extra = B_LITTLE16 ( sector [ i ] . extra ) ;
}
2013-04-09 17:35:11 +00:00
////////// Read walls //////////
2019-11-01 21:17:15 +00:00
fr . Read ( & numwalls , 2 ) ; numwalls = B_LITTLE16 ( numwalls ) ;
2018-11-18 18:11:50 +00:00
if ( ( unsigned ) numwalls > = MYMAXWALLS ( ) + 1 ) goto error ;
2013-04-09 17:35:11 +00:00
2019-11-01 21:17:15 +00:00
fr . Read ( wall , sizeof ( walltypev7 ) * numwalls ) ;
2013-04-09 17:35:11 +00:00
2007-12-12 17:42:14 +00:00
for ( i = numwalls - 1 ; i > = 0 ; i - - )
{
2006-04-13 20:47:06 +00:00
wall [ i ] . x = B_LITTLE32 ( wall [ i ] . x ) ;
wall [ i ] . y = B_LITTLE32 ( wall [ i ] . y ) ;
wall [ i ] . point2 = B_LITTLE16 ( wall [ i ] . point2 ) ;
wall [ i ] . nextwall = B_LITTLE16 ( wall [ i ] . nextwall ) ;
wall [ i ] . nextsector = B_LITTLE16 ( wall [ i ] . nextsector ) ;
wall [ i ] . cstat = B_LITTLE16 ( wall [ i ] . cstat ) ;
wall [ i ] . picnum = B_LITTLE16 ( wall [ i ] . picnum ) ;
wall [ i ] . overpicnum = B_LITTLE16 ( wall [ i ] . overpicnum ) ;
wall [ i ] . lotag = B_LITTLE16 ( wall [ i ] . lotag ) ;
wall [ i ] . hitag = B_LITTLE16 ( wall [ i ] . hitag ) ;
wall [ i ] . extra = B_LITTLE16 ( wall [ i ] . extra ) ;
}
2013-04-09 17:35:11 +00:00
////////// Read sprites //////////
2019-11-01 21:17:15 +00:00
fr . Read ( & numsprites , 2 ) ; numsprites = B_LITTLE16 ( numsprites ) ;
2018-11-18 18:11:50 +00:00
if ( ( unsigned ) numsprites > = MYMAXSPRITES ( ) + 1 ) goto error ;
2013-04-09 17:35:11 +00:00
2019-11-01 21:17:15 +00:00
fr . Read ( sprite , sizeof ( spritetype ) * numsprites ) ;
2015-01-08 15:14:00 +00:00
2019-11-01 21:17:15 +00:00
fr . Seek ( 0 , FileReader : : SeekSet ) ;
int32_t boardsize = fr . GetLength ( ) ;
2015-01-08 15:14:00 +00:00
uint8_t * fullboard = ( uint8_t * ) Xmalloc ( boardsize ) ;
2019-11-01 21:17:15 +00:00
fr . Read ( fullboard , boardsize ) ;
2015-01-18 20:31:37 +00:00
md4once ( fullboard , boardsize , g_loadedMapHack . md4 ) ;
2019-06-25 11:29:08 +00:00
Xfree ( fullboard ) ;
2015-01-08 15:14:00 +00:00
2013-04-21 19:55:18 +00:00
// Done reading file.
2019-08-01 06:50:46 +00:00
if ( ! have_maptext ( ) )
2007-12-12 17:42:14 +00:00
{
2019-08-01 06:50:46 +00:00
for ( i = numsprites - 1 ; i > = 0 ; i - - )
2013-05-06 19:43:42 +00:00
{
sprite [ i ] . x = B_LITTLE32 ( sprite [ i ] . x ) ;
sprite [ i ] . y = B_LITTLE32 ( sprite [ i ] . y ) ;
sprite [ i ] . z = B_LITTLE32 ( sprite [ i ] . z ) ;
sprite [ i ] . cstat = B_LITTLE16 ( sprite [ i ] . cstat ) ;
sprite [ i ] . picnum = B_LITTLE16 ( sprite [ i ] . picnum ) ;
sprite [ i ] . sectnum = B_LITTLE16 ( sprite [ i ] . sectnum ) ;
sprite [ i ] . statnum = B_LITTLE16 ( sprite [ i ] . statnum ) ;
sprite [ i ] . ang = B_LITTLE16 ( sprite [ i ] . ang ) ;
sprite [ i ] . owner = B_LITTLE16 ( sprite [ i ] . owner ) ;
sprite [ i ] . xvel = B_LITTLE16 ( sprite [ i ] . xvel ) ;
sprite [ i ] . yvel = B_LITTLE16 ( sprite [ i ] . yvel ) ;
sprite [ i ] . zvel = B_LITTLE16 ( sprite [ i ] . zvel ) ;
sprite [ i ] . lotag = B_LITTLE16 ( sprite [ i ] . lotag ) ;
sprite [ i ] . hitag = B_LITTLE16 ( sprite [ i ] . hitag ) ;
sprite [ i ] . extra = B_LITTLE16 ( sprite [ i ] . extra ) ;
2008-02-06 03:49:35 +00:00
2019-08-01 06:50:46 +00:00
check_sprite ( i ) ;
}
}
else
{
for ( i = numsprites - 1 ; i > = 0 ; i - - )
check_sprite ( i ) ;
2012-10-01 17:52:37 +00:00
}
2012-03-14 22:30:57 +00:00
2013-06-28 14:07:44 +00:00
// Back up the map version of the *loaded* map. Must be before yax_update().
g_loadedMapVersion = mapversion ;
2006-09-29 21:36:12 +00:00
2013-12-24 09:44:23 +00:00
if ( ( myflags & 8 ) = = 0 )
2013-04-25 17:48:37 +00:00
{
2014-01-12 14:54:36 +00:00
// Per-map ART
2018-04-12 21:03:30 +00:00
artSetupMapArt ( filename ) ;
2013-04-25 17:48:37 +00:00
}
2020-04-11 21:45:45 +00:00
// Printf("Loaded map \"%s\" (md4sum: %08x%08x%08x%08x)\n", filename, B_BIG32(*((int32_t*)&md4out[0])), B_BIG32(*((int32_t*)&md4out[4])), B_BIG32(*((int32_t*)&md4out[8])), B_BIG32(*((int32_t*)&md4out[12])));
2015-01-08 15:14:00 +00:00
2018-04-12 21:03:47 +00:00
return engineFinishLoadBoard ( dapos , dacursectnum , numsprites , myflags ) ;
2006-04-13 20:47:06 +00:00
}
//
// loadboardv5/6
//
2013-04-25 21:10:22 +00:00
# include "engine_oldmap.h"
2006-04-13 20:47:06 +00:00
// Powerslave uses v6
2009-02-19 09:39:19 +00:00
// Witchaven 1 and TekWar and LameDuke use v5
2018-04-12 21:03:47 +00:00
int32_t engineLoadBoardV5V6 ( const char * filename , char fromwhere , vec3_t * dapos , int16_t * daang , int16_t * dacursectnum )
2006-04-13 20:47:06 +00:00
{
2019-03-01 08:51:50 +00:00
int32_t i ;
2012-10-01 17:52:37 +00:00
int16_t numsprites ;
2006-04-13 20:47:06 +00:00
struct sectortypev5 v5sect ;
struct walltypev5 v5wall ;
struct spritetypev5 v5spr ;
struct sectortypev6 v6sect ;
struct walltypev6 v6wall ;
struct spritetypev6 v6spr ;
2020-04-11 21:54:33 +00:00
FileReader fr = fileSystem . OpenFileReader ( filename ) ;
2019-11-01 21:17:15 +00:00
if ( ! fr . isOpen ( ) )
2016-06-21 00:34:41 +00:00
{ mapversion = 5L ; return - 1 ; }
2006-04-13 20:47:06 +00:00
2019-11-01 21:17:15 +00:00
fr . Read ( & mapversion , 4 ) ; mapversion = B_LITTLE32 ( mapversion ) ;
if ( mapversion ! = 5L & & mapversion ! = 6L ) { return - 2 ; }
2006-04-13 20:47:06 +00:00
2019-11-01 21:17:15 +00:00
enginePrepareLoadBoard ( fr , dapos , daang , dacursectnum ) ;
2006-04-13 20:47:06 +00:00
2019-11-01 21:17:15 +00:00
fr . Read ( & numsectors , 2 ) ; numsectors = B_LITTLE16 ( numsectors ) ;
if ( numsectors > MAXSECTORS ) { return - 1 ; }
2007-12-12 17:42:14 +00:00
for ( i = 0 ; i < numsectors ; i + + )
{
switch ( mapversion )
{
2006-11-13 23:12:47 +00:00
case 5 :
2019-11-01 21:17:15 +00:00
fr . Read ( & v5sect , sizeof ( struct sectortypev5 ) ) ;
2006-04-24 19:04:22 +00:00
v5sect . wallptr = B_LITTLE16 ( v5sect . wallptr ) ;
v5sect . wallnum = B_LITTLE16 ( v5sect . wallnum ) ;
v5sect . ceilingpicnum = B_LITTLE16 ( v5sect . ceilingpicnum ) ;
v5sect . floorpicnum = B_LITTLE16 ( v5sect . floorpicnum ) ;
v5sect . ceilingheinum = B_LITTLE16 ( v5sect . ceilingheinum ) ;
v5sect . floorheinum = B_LITTLE16 ( v5sect . floorheinum ) ;
v5sect . ceilingz = B_LITTLE32 ( v5sect . ceilingz ) ;
v5sect . floorz = B_LITTLE32 ( v5sect . floorz ) ;
v5sect . lotag = B_LITTLE16 ( v5sect . lotag ) ;
v5sect . hitag = B_LITTLE16 ( v5sect . hitag ) ;
v5sect . extra = B_LITTLE16 ( v5sect . extra ) ;
break ;
2006-11-13 23:12:47 +00:00
case 6 :
2019-11-01 21:17:15 +00:00
fr . Read ( & v6sect , sizeof ( struct sectortypev6 ) ) ;
2006-04-24 19:04:22 +00:00
v6sect . wallptr = B_LITTLE16 ( v6sect . wallptr ) ;
v6sect . wallnum = B_LITTLE16 ( v6sect . wallnum ) ;
v6sect . ceilingpicnum = B_LITTLE16 ( v6sect . ceilingpicnum ) ;
v6sect . floorpicnum = B_LITTLE16 ( v6sect . floorpicnum ) ;
v6sect . ceilingheinum = B_LITTLE16 ( v6sect . ceilingheinum ) ;
v6sect . floorheinum = B_LITTLE16 ( v6sect . floorheinum ) ;
v6sect . ceilingz = B_LITTLE32 ( v6sect . ceilingz ) ;
v6sect . floorz = B_LITTLE32 ( v6sect . floorz ) ;
v6sect . lotag = B_LITTLE16 ( v6sect . lotag ) ;
v6sect . hitag = B_LITTLE16 ( v6sect . hitag ) ;
v6sect . extra = B_LITTLE16 ( v6sect . extra ) ;
break ;
2006-04-13 20:47:06 +00:00
}
2012-10-01 17:52:37 +00:00
2007-12-12 17:42:14 +00:00
switch ( mapversion )
{
2006-11-13 23:12:47 +00:00
case 5 :
2012-02-18 17:55:27 +00:00
convertv5sectv6 ( & v5sect , & v6sect ) ;
2017-07-18 20:53:41 +00:00
fallthrough__ ;
2006-11-13 23:12:47 +00:00
case 6 :
2012-02-18 17:55:27 +00:00
convertv6sectv7 ( & v6sect , & sector [ i ] ) ;
2017-07-18 20:53:41 +00:00
break ;
2006-04-13 20:47:06 +00:00
}
}
2019-11-01 21:17:15 +00:00
fr . Read ( & numwalls , 2 ) ; numwalls = B_LITTLE16 ( numwalls ) ;
if ( numwalls > MAXWALLS ) { return - 1 ; }
2007-12-12 17:42:14 +00:00
for ( i = 0 ; i < numwalls ; i + + )
{
switch ( mapversion )
{
2006-11-13 23:12:47 +00:00
case 5 :
2019-11-01 21:17:15 +00:00
fr . Read ( & v5wall , sizeof ( struct walltypev5 ) ) ;
2006-04-24 19:04:22 +00:00
v5wall . x = B_LITTLE32 ( v5wall . x ) ;
v5wall . y = B_LITTLE32 ( v5wall . y ) ;
v5wall . point2 = B_LITTLE16 ( v5wall . point2 ) ;
v5wall . picnum = B_LITTLE16 ( v5wall . picnum ) ;
v5wall . overpicnum = B_LITTLE16 ( v5wall . overpicnum ) ;
v5wall . cstat = B_LITTLE16 ( v5wall . cstat ) ;
v5wall . nextsector1 = B_LITTLE16 ( v5wall . nextsector1 ) ;
v5wall . nextwall1 = B_LITTLE16 ( v5wall . nextwall1 ) ;
v5wall . nextsector2 = B_LITTLE16 ( v5wall . nextsector2 ) ;
v5wall . nextwall2 = B_LITTLE16 ( v5wall . nextwall2 ) ;
v5wall . lotag = B_LITTLE16 ( v5wall . lotag ) ;
v5wall . hitag = B_LITTLE16 ( v5wall . hitag ) ;
v5wall . extra = B_LITTLE16 ( v5wall . extra ) ;
break ;
2006-11-13 23:12:47 +00:00
case 6 :
2019-11-01 21:17:15 +00:00
fr . Read ( & v6wall , sizeof ( struct walltypev6 ) ) ;
2006-04-24 19:04:22 +00:00
v6wall . x = B_LITTLE32 ( v6wall . x ) ;
v6wall . y = B_LITTLE32 ( v6wall . y ) ;
v6wall . point2 = B_LITTLE16 ( v6wall . point2 ) ;
v6wall . nextsector = B_LITTLE16 ( v6wall . nextsector ) ;
v6wall . nextwall = B_LITTLE16 ( v6wall . nextwall ) ;
v6wall . picnum = B_LITTLE16 ( v6wall . picnum ) ;
v6wall . overpicnum = B_LITTLE16 ( v6wall . overpicnum ) ;
v6wall . cstat = B_LITTLE16 ( v6wall . cstat ) ;
v6wall . lotag = B_LITTLE16 ( v6wall . lotag ) ;
v6wall . hitag = B_LITTLE16 ( v6wall . hitag ) ;
v6wall . extra = B_LITTLE16 ( v6wall . extra ) ;
break ;
2006-04-13 20:47:06 +00:00
}
2012-10-01 17:52:37 +00:00
2007-12-12 17:42:14 +00:00
switch ( mapversion )
{
2006-11-13 23:12:47 +00:00
case 5 :
2012-02-18 17:55:27 +00:00
convertv5wallv6 ( & v5wall , & v6wall , i ) ;
2017-07-18 20:53:41 +00:00
fallthrough__ ;
2006-11-13 23:12:47 +00:00
case 6 :
2012-02-18 17:55:27 +00:00
convertv6wallv7 ( & v6wall , & wall [ i ] ) ;
2017-07-18 20:53:41 +00:00
break ;
2006-04-13 20:47:06 +00:00
}
}
2019-11-01 21:17:15 +00:00
fr . Read ( & numsprites , 2 ) ; numsprites = B_LITTLE16 ( numsprites ) ;
if ( numsprites > MAXSPRITES ) { return - 1 ; }
2007-12-12 17:42:14 +00:00
for ( i = 0 ; i < numsprites ; i + + )
{
switch ( mapversion )
{
2006-11-13 23:12:47 +00:00
case 5 :
2019-11-01 21:17:15 +00:00
fr . Read ( & v5spr , sizeof ( struct spritetypev5 ) ) ;
2006-04-24 19:04:22 +00:00
v5spr . x = B_LITTLE32 ( v5spr . x ) ;
v5spr . y = B_LITTLE32 ( v5spr . y ) ;
v5spr . z = B_LITTLE32 ( v5spr . z ) ;
v5spr . picnum = B_LITTLE16 ( v5spr . picnum ) ;
v5spr . ang = B_LITTLE16 ( v5spr . ang ) ;
v5spr . xvel = B_LITTLE16 ( v5spr . xvel ) ;
v5spr . yvel = B_LITTLE16 ( v5spr . yvel ) ;
v5spr . zvel = B_LITTLE16 ( v5spr . zvel ) ;
v5spr . owner = B_LITTLE16 ( v5spr . owner ) ;
v5spr . sectnum = B_LITTLE16 ( v5spr . sectnum ) ;
v5spr . statnum = B_LITTLE16 ( v5spr . statnum ) ;
v5spr . lotag = B_LITTLE16 ( v5spr . lotag ) ;
v5spr . hitag = B_LITTLE16 ( v5spr . hitag ) ;
v5spr . extra = B_LITTLE16 ( v5spr . extra ) ;
break ;
2006-11-13 23:12:47 +00:00
case 6 :
2019-11-01 21:17:15 +00:00
fr . Read ( & v6spr , sizeof ( struct spritetypev6 ) ) ;
2006-04-24 19:04:22 +00:00
v6spr . x = B_LITTLE32 ( v6spr . x ) ;
v6spr . y = B_LITTLE32 ( v6spr . y ) ;
v6spr . z = B_LITTLE32 ( v6spr . z ) ;
v6spr . cstat = B_LITTLE16 ( v6spr . cstat ) ;
v6spr . picnum = B_LITTLE16 ( v6spr . picnum ) ;
v6spr . ang = B_LITTLE16 ( v6spr . ang ) ;
v6spr . xvel = B_LITTLE16 ( v6spr . xvel ) ;
v6spr . yvel = B_LITTLE16 ( v6spr . yvel ) ;
v6spr . zvel = B_LITTLE16 ( v6spr . zvel ) ;
v6spr . owner = B_LITTLE16 ( v6spr . owner ) ;
v6spr . sectnum = B_LITTLE16 ( v6spr . sectnum ) ;
v6spr . statnum = B_LITTLE16 ( v6spr . statnum ) ;
v6spr . lotag = B_LITTLE16 ( v6spr . lotag ) ;
v6spr . hitag = B_LITTLE16 ( v6spr . hitag ) ;
v6spr . extra = B_LITTLE16 ( v6spr . extra ) ;
break ;
2006-04-13 20:47:06 +00:00
}
2012-10-01 17:52:37 +00:00
2007-12-12 17:42:14 +00:00
switch ( mapversion )
{
2006-11-13 23:12:47 +00:00
case 5 :
2012-02-18 17:55:27 +00:00
convertv5sprv6 ( & v5spr , & v6spr ) ;
2017-07-18 20:53:41 +00:00
fallthrough__ ;
2006-11-13 23:12:47 +00:00
case 6 :
2012-02-18 17:55:27 +00:00
convertv6sprv7 ( & v6spr , & sprite [ i ] ) ;
2017-07-18 20:53:41 +00:00
break ;
2006-04-13 20:47:06 +00:00
}
2012-10-01 17:52:37 +00:00
check_sprite ( i ) ;
2006-04-13 20:47:06 +00:00
}
2012-10-01 17:52:37 +00:00
// Done reading file.
2006-04-13 20:47:06 +00:00
2020-06-12 20:01:08 +00:00
g_loadedMapVersion = mapversion ;
2018-04-12 21:03:47 +00:00
return engineFinishLoadBoard ( dapos , dacursectnum , numsprites , 0 ) ;
2006-04-13 20:47:06 +00:00
}
2013-04-25 21:10:22 +00:00
2006-04-13 20:47:06 +00:00
//
// setgamemode
//
// JBF: davidoption now functions as a windowed-mode flag (0 == windowed, 1 == fullscreen)
2018-07-14 21:36:44 +00:00
int32_t videoSetGameMode ( char davidoption , int32_t daupscaledxdim , int32_t daupscaledydim , int32_t dabpp , int32_t daupscalefactor )
2006-04-13 20:47:06 +00:00
{
2012-12-14 19:28:17 +00:00
int32_t j ;
2006-04-13 20:47:06 +00:00
2019-12-23 18:37:40 +00:00
if ( dabpp ! = 32 ) return - 1 ; // block software mode.
2018-07-14 21:36:44 +00:00
daupscaledxdim = max ( 320 , daupscaledxdim ) ;
daupscaledydim = max ( 200 , daupscaledydim ) ;
2011-07-01 12:22:12 +00:00
2020-01-01 11:36:48 +00:00
if ( in3dmode ( ) & &
2019-12-23 18:37:40 +00:00
( xres = = daupscaledxdim ) & & ( yres = = daupscaledydim ) & & ( bpp = = dabpp ) )
2016-06-21 00:34:41 +00:00
return 0 ;
2006-04-24 19:04:22 +00:00
2012-03-13 20:06:37 +00:00
Bstrcpy ( kensmessage , " !!!! BUILD engine&tools programmed by Ken Silverman of E.G. RI. "
" (c) Copyright 1995 Ken Silverman. Summary: BUILD = Ken. !!!! " ) ;
2008-08-26 19:50:34 +00:00
2006-04-13 20:47:06 +00:00
j = bpp ;
2010-08-14 21:32:28 +00:00
2019-12-23 18:37:40 +00:00
rendmode = REND_POLYMOST ;
2006-04-13 20:47:06 +00:00
2019-12-23 18:37:40 +00:00
upscalefactor = 1 ;
xdim = daupscaledxdim ;
ydim = daupscaledydim ;
2019-11-08 22:02:52 +00:00
V_UpdateModeSize ( xdim , ydim ) ;
2019-12-29 14:46:48 +00:00
numpages = 1 ; // We have only one page, no exceptions.
2006-04-13 20:47:06 +00:00
2014-10-25 03:27:35 +00:00
# ifdef USE_OPENGL
2018-07-14 21:36:44 +00:00
fxdim = ( float ) xdim ;
fydim = ( float ) ydim ;
2014-10-25 03:27:35 +00:00
# endif
2014-10-29 17:04:28 +00:00
2012-05-26 21:58:31 +00:00
j = ydim * 4 ; //Leave room for horizlookup&horizlookup2
2006-04-13 20:47:06 +00:00
//Force drawrooms to call dosetaspect & recalculate stuff
oxyaspect = oxdimen = oviewingrange = - 1 ;
2018-04-12 21:02:51 +00:00
videoSetViewableArea ( 0L , 0L , xdim - 1 , ydim - 1 ) ;
videoClearScreen ( 0L ) ;
2006-04-13 20:47:06 +00:00
2007-12-12 17:42:14 +00:00
if ( searchx < 0 ) { searchx = halfxdimen ; searchy = ( ydimen > > 1 ) ; }
2006-04-13 20:47:06 +00:00
qsetmode = 200 ;
2016-06-21 00:34:41 +00:00
return 0 ;
2006-04-13 20:47:06 +00:00
}
2020-06-11 16:40:53 +00:00
void DrawFullscreenBlends ( ) ;
2006-04-13 20:47:06 +00:00
//
// nextpage
//
2018-04-12 21:02:51 +00:00
void videoNextPage ( void )
2006-04-13 20:47:06 +00:00
{
2019-11-24 16:52:54 +00:00
static bool recursion ;
2006-04-13 20:47:06 +00:00
2019-11-24 16:52:54 +00:00
if ( ! recursion )
{
2019-11-30 18:23:54 +00:00
// This protection is needed because the menu can call scripts from inside its drawers and the scripts can call the busy-looping Screen_Play script event
2019-11-24 16:52:54 +00:00
// which calls videoNextPage for page flipping again. In this loop the UI drawers may not get called again.
// Ideally this stuff should be moved out of videoNextPage so that all those busy loops won't call UI overlays at all.
recursion = true ;
M_Drawer ( ) ;
2020-05-25 15:11:32 +00:00
FStat : : PrintStat ( twod ) ;
2019-11-24 16:52:54 +00:00
C_DrawConsole ( ) ;
recursion = false ;
}
2020-06-11 16:40:53 +00:00
// Handle the final 2D overlays.
DrawFullscreenBlends ( ) ;
DrawRateStuff ( ) ;
2019-11-24 16:52:54 +00:00
2018-04-06 01:42:47 +00:00
if ( in3dmode ( ) )
2006-04-13 20:47:06 +00:00
{
2019-12-29 14:46:48 +00:00
g_beforeSwapTime = timerGetHiTicks ( ) ;
2019-11-10 10:42:25 +00:00
2019-11-06 22:40:10 +00:00
videoShowFrame ( 0 ) ;
2006-04-13 20:47:06 +00:00
}
2011-03-04 08:50:58 +00:00
# ifdef USE_OPENGL
2018-04-06 01:42:47 +00:00
omdtims = mdtims ;
2018-04-12 21:02:51 +00:00
mdtims = timerGetTicks ( ) ;
2008-02-02 16:38:30 +00:00
2020-06-08 19:47:09 +00:00
for ( native_t i = 0 ; i < MAXSPRITES + MAXUNIQHUDID ; + + i )
2015-03-24 00:40:18 +00:00
if ( ( mdpause & & spriteext [ i ] . mdanimtims ) | | ( spriteext [ i ] . flags & SPREXT_NOMDANIM ) )
spriteext [ i ] . mdanimtims + = mdtims - omdtims ;
2006-04-13 20:47:06 +00:00
# endif
beforedrawrooms = 1 ;
numframes + + ;
2020-04-28 20:55:37 +00:00
twod - > SetSize ( screen - > GetWidth ( ) , screen - > GetHeight ( ) ) ;
twodpsp . SetSize ( screen - > GetWidth ( ) , screen - > GetHeight ( ) ) ;
2006-04-13 20:47:06 +00:00
}
//
// qloadkvx
//
2019-10-20 23:17:26 +00:00
2011-01-16 00:23:39 +00:00
int32_t qloadkvx ( int32_t voxindex , const char * filename )
2006-04-13 20:47:06 +00:00
{
2019-12-22 10:20:26 +00:00
if ( ( unsigned ) voxindex > = MAXVOXELS )
return - 1 ;
2020-04-11 21:54:33 +00:00
auto fil = fileSystem . OpenFileReader ( filename ) ;
2019-10-20 23:17:26 +00:00
if ( ! fil . isOpen ( ) )
2014-12-26 17:29:48 +00:00
return - 1 ;
2006-04-13 20:47:06 +00:00
2014-12-26 17:29:48 +00:00
int32_t lengcnt = 0 ;
2019-10-20 23:17:26 +00:00
const int32_t lengtot = fil . GetLength ( ) ;
2006-04-13 20:47:06 +00:00
2016-08-27 01:41:21 +00:00
for ( bssize_t i = 0 ; i < MAXVOXMIPS ; i + + )
2006-04-13 20:47:06 +00:00
{
2019-10-20 23:17:26 +00:00
int32_t dasiz = fil . ReadInt32 ( ) ;
2014-12-26 17:29:48 +00:00
2019-10-20 23:17:26 +00:00
voxelmemory . Reserve ( 1 ) ;
voxelmemory . Last ( ) = fil . Read ( dasiz ) ;
2019-10-21 17:36:54 +00:00
voxoff [ voxindex ] [ i ] = ( intptr_t ) voxelmemory . Last ( ) . Data ( ) ;
2006-04-13 20:47:06 +00:00
lengcnt + = dasiz + 4 ;
2014-12-26 17:29:48 +00:00
if ( lengcnt > = lengtot - 768 )
break ;
2006-04-13 20:47:06 +00:00
}
2014-12-26 17:29:48 +00:00
2006-04-13 20:47:06 +00:00
2011-03-04 08:50:58 +00:00
# ifdef USE_OPENGL
2007-12-12 17:42:14 +00:00
if ( voxmodels [ voxindex ] )
{
2006-04-13 20:47:06 +00:00
voxfree ( voxmodels [ voxindex ] ) ;
voxmodels [ voxindex ] = NULL ;
}
2014-12-26 17:29:48 +00:00
2019-06-25 11:29:08 +00:00
Xfree ( voxfilenames [ voxindex ] ) ;
2018-10-25 23:28:56 +00:00
voxfilenames [ voxindex ] = Xstrdup ( filename ) ;
2006-04-13 20:47:06 +00:00
# endif
2014-12-26 17:29:48 +00:00
2019-08-13 02:53:38 +00:00
g_haveVoxels = 1 ;
2006-04-13 20:47:06 +00:00
return 0 ;
}
2016-10-25 05:43:50 +00:00
void vox_undefine ( int32_t const tile )
{
ssize_t voxindex = tiletovox [ tile ] ;
if ( voxindex < 0 )
return ;
# ifdef USE_OPENGL
if ( voxmodels [ voxindex ] )
{
voxfree ( voxmodels [ voxindex ] ) ;
voxmodels [ voxindex ] = NULL ;
}
DO_FREE_AND_NULL ( voxfilenames [ voxindex ] ) ;
# endif
for ( ssize_t j = 0 ; j < MAXVOXMIPS ; + + j )
{
// CACHE1D_FREE
voxoff [ voxindex ] [ j ] = 0 ;
}
voxscale [ voxindex ] = 65536 ;
2019-09-17 05:07:28 +00:00
voxrotate [ voxindex > > 3 ] & = ~ pow2char [ voxindex & 7 ] ;
2016-10-25 05:43:50 +00:00
tiletovox [ tile ] = - 1 ;
// TODO: nextvoxid
}
2019-12-25 07:57:58 +00:00
void vox_deinit ( )
{
for ( auto & vox : voxmodels )
{
voxfree ( vox ) ;
vox = nullptr ;
}
}
2006-04-13 20:47:06 +00:00
//
// inside
//
2013-06-22 11:31:16 +00:00
// See http://fabiensanglard.net/duke3d/build_engine_internals.php,
// "Inside details" for the idea behind the algorithm.
2019-09-22 19:26:07 +00:00
int32_t inside_ps ( int32_t x , int32_t y , int16_t sectnum )
{
if ( sectnum > = 0 & & sectnum < numsectors )
{
int32_t cnt = 0 ;
auto wal = ( uwallptr_t ) & wall [ sector [ sectnum ] . wallptr ] ;
int wallsleft = sector [ sectnum ] . wallnum ;
do
{
vec2_t v1 = { wal - > x - x , wal - > y - y } ;
auto const & wal2 = * ( uwallptr_t ) & wall [ wal - > point2 ] ;
vec2_t v2 = { wal2 . x - x , wal2 . y - y } ;
if ( ( v1 . y ^ v2 . y ) < 0 )
cnt ^ = ( ( ( v1 . x ^ v2 . x ) < 0 ) ? ( v1 . x * v2 . y < v2 . x * v1 . y ) ^ ( v1 . y < v2 . y ) : ( v1 . x > = 0 ) ) ;
wal + + ;
}
while ( - - wallsleft ) ;
return cnt ;
}
2019-09-21 11:02:17 +00:00
2019-09-22 19:26:07 +00:00
return - 1 ;
}
2019-09-21 11:02:17 +00:00
int32_t inside_old ( int32_t x , int32_t y , int16_t sectnum )
{
if ( sectnum > = 0 & & sectnum < numsectors )
{
uint32_t cnt = 0 ;
auto wal = ( uwallptr_t ) & wall [ sector [ sectnum ] . wallptr ] ;
int wallsleft = sector [ sectnum ] . wallnum ;
do
{
// Get the x and y components of the [tested point]-->[wall
// point{1,2}] vectors.
vec2_t v1 = { wal - > x - x , wal - > y - y } ;
auto const & wal2 = * ( uwallptr_t ) & wall [ wal - > point2 ] ;
vec2_t v2 = { wal2 . x - x , wal2 . y - y } ;
// If their signs differ[*], ...
//
// [*] where '-' corresponds to <0 and '+' corresponds to >=0.
// Equivalently, the branch is taken iff
// y1 != y2 AND y_m <= y < y_M,
// where y_m := min(y1, y2) and y_M := max(y1, y2).
if ( ( v1 . y ^ v2 . y ) < 0 )
cnt ^ = ( ( ( v1 . x ^ v2 . x ) > = 0 ) ? v1 . x : ( v1 . x * v2 . y - v2 . x * v1 . y ) ^ v2 . y ) ;
wal + + ;
}
while ( - - wallsleft ) ;
return cnt > > 31 ;
}
return - 1 ;
}
2009-01-09 09:29:17 +00:00
int32_t inside ( int32_t x , int32_t y , int16_t sectnum )
2006-04-13 20:47:06 +00:00
{
2019-09-22 19:26:07 +00:00
switch ( enginecompatibility_mode )
{
case ENGINECOMPATIBILITY_NONE :
break ;
case ENGINECOMPATIBILITY_19950829 :
return inside_ps ( x , y , sectnum ) ;
default :
2019-09-21 11:02:17 +00:00
return inside_old ( x , y , sectnum ) ;
2019-09-22 19:26:07 +00:00
}
2019-04-18 17:23:35 +00:00
if ( ( unsigned ) sectnum < ( unsigned ) numsectors )
2006-04-13 20:47:06 +00:00
{
2013-06-22 11:31:16 +00:00
uint32_t cnt1 = 0 , cnt2 = 0 ;
2019-04-18 17:25:24 +00:00
auto wal = ( uwallptr_t ) & wall [ sector [ sectnum ] . wallptr ] ;
int wallsleft = sector [ sectnum ] . wallnum ;
2013-06-22 11:31:15 +00:00
do
2006-04-13 20:47:06 +00:00
{
2013-06-22 11:31:16 +00:00
// Get the x and y components of the [tested point]-->[wall
// point{1,2}] vectors.
2016-06-21 00:33:30 +00:00
vec2_t v1 = { wal - > x - x , wal - > y - y } ;
2019-04-18 17:25:24 +00:00
auto const & wal2 = * ( uwallptr_t ) & wall [ wal - > point2 ] ;
2019-04-18 17:23:35 +00:00
vec2_t v2 = { wal2 . x - x , wal2 . y - y } ;
2013-06-22 11:31:16 +00:00
// First, test if the point is EXACTLY_ON_WALL_POINT.
2016-06-21 00:33:30 +00:00
if ( ( v1 . x | v1 . y ) = = 0 | | ( v2 . x | v2 . y ) = = 0 )
2013-06-22 11:31:16 +00:00
return 1 ;
2013-06-22 11:31:15 +00:00
// If their signs differ[*], ...
//
// [*] where '-' corresponds to <0 and '+' corresponds to >=0.
// Equivalently, the branch is taken iff
2013-06-28 14:07:33 +00:00
// y1 != y2 AND y_m <= y < y_M,
2013-06-22 11:31:15 +00:00
// where y_m := min(y1, y2) and y_M := max(y1, y2).
2016-06-21 00:33:30 +00:00
if ( ( v1 . y ^ v2 . y ) < 0 )
cnt1 ^ = ( ( ( v1 . x ^ v2 . x ) > = 0 ) ? v1 . x : ( v1 . x * v2 . y - v2 . x * v1 . y ) ^ v2 . y ) ;
2013-06-22 11:31:16 +00:00
2016-06-21 00:33:30 +00:00
v1 . y - - ;
v2 . y - - ;
2013-06-22 11:31:16 +00:00
// Now, do the same comparisons, but with the interval half-open on
// the other side! That is, take the branch iff
2013-06-28 14:07:33 +00:00
// y1 != y2 AND y_m < y <= y_M,
2013-06-22 11:31:16 +00:00
// For a rectangular sector, without EXACTLY_ON_WALL_POINT, this
// would still leave the lower left and upper right points
// "outside" the sector.
2016-06-21 00:33:30 +00:00
if ( ( v1 . y ^ v2 . y ) < 0 )
2013-06-22 11:31:16 +00:00
{
2016-06-21 00:33:30 +00:00
v1 . x - - ;
v2 . x - - ;
2013-06-22 11:31:15 +00:00
2016-06-21 00:33:30 +00:00
cnt2 ^ = ( ( ( v1 . x ^ v2 . x ) > = 0 ) ? v1 . x : ( v1 . x * v2 . y - v2 . x * v1 . y ) ^ v2 . y ) ;
2013-06-22 11:31:15 +00:00
}
2016-06-21 00:34:29 +00:00
wal + + ;
2006-04-13 20:47:06 +00:00
}
2016-06-21 00:34:29 +00:00
while ( - - wallsleft ) ;
2013-06-22 11:31:15 +00:00
2013-06-22 11:31:16 +00:00
return ( cnt1 | cnt2 ) > > 31 ;
2007-12-12 17:42:14 +00:00
}
2013-06-22 11:31:15 +00:00
return - 1 ;
2006-04-13 20:47:06 +00:00
}
2020-05-17 18:47:27 +00:00
int32_t __fastcall getangle ( int32_t xvect , int32_t yvect )
2012-09-02 14:12:01 +00:00
{
2015-01-11 04:56:58 +00:00
int32_t rv ;
if ( ( xvect | yvect ) = = 0 )
rv = 0 ;
else if ( xvect = = 0 )
rv = 512 + ( ( yvect < 0 ) < < 10 ) ;
else if ( yvect = = 0 )
rv = ( ( xvect < 0 ) < < 10 ) ;
else if ( xvect = = yvect )
rv = 256 + ( ( xvect < 0 ) < < 10 ) ;
else if ( xvect = = - yvect )
rv = 768 + ( ( xvect > 0 ) < < 10 ) ;
else if ( klabs ( xvect ) > klabs ( yvect ) )
rv = ( ( radarang [ 640 + scale ( 160 , yvect , xvect ) ] > > 6 ) + ( ( xvect < 0 ) < < 10 ) ) & 2047 ;
else rv = ( ( radarang [ 640 - scale ( 160 , xvect , yvect ) ] > > 6 ) + 512 + ( ( yvect < 0 ) < < 10 ) ) & 2047 ;
return rv ;
2012-09-02 14:12:01 +00:00
}
2006-04-13 20:47:06 +00:00
2020-05-17 18:47:27 +00:00
fix16_t __fastcall gethiq16angle ( int32_t xvect , int32_t yvect )
2020-04-17 13:21:22 +00:00
{
fix16_t rv ;
if ( ( xvect | yvect ) = = 0 )
rv = 0 ;
else if ( xvect = = 0 )
rv = fix16_from_int ( 512 + ( ( yvect < 0 ) < < 10 ) ) ;
else if ( yvect = = 0 )
rv = fix16_from_int ( ( ( xvect < 0 ) < < 10 ) ) ;
else if ( xvect = = yvect )
rv = fix16_from_int ( 256 + ( ( xvect < 0 ) < < 10 ) ) ;
else if ( xvect = = - yvect )
rv = fix16_from_int ( 768 + ( ( xvect > 0 ) < < 10 ) ) ;
else if ( klabs ( xvect ) > klabs ( yvect ) )
rv = ( ( qradarang [ 5120 + scale ( 1280 , yvect , xvect ) ] > > 6 ) + fix16_from_int ( ( ( xvect < 0 ) < < 10 ) ) ) & 0x7FFFFFF ;
else rv = ( ( qradarang [ 5120 - scale ( 1280 , xvect , yvect ) ] > > 6 ) + fix16_from_int ( 512 + ( ( yvect < 0 ) < < 10 ) ) ) & 0x7FFFFFF ;
return rv ;
}
2006-04-13 20:47:06 +00:00
//
// ksqrt
//
2012-07-01 22:11:14 +00:00
int32_t ksqrt ( uint32_t num )
2006-04-13 20:47:06 +00:00
{
2020-03-03 03:18:10 +00:00
if ( enginecompatibility_mode = = ENGINECOMPATIBILITY_19950829 )
return ksqrtasm_old ( num ) ;
2013-04-12 11:59:26 +00:00
return nsqrtasm ( num ) ;
2006-04-13 20:47:06 +00:00
}
2012-11-17 19:46:43 +00:00
// Gets the BUILD unit height and z offset of a sprite.
// Returns the z offset, 'height' may be NULL.
2019-04-18 17:25:24 +00:00
int32_t spriteheightofsptr ( uspriteptr_t spr , int32_t * height , int32_t alsotileyofs )
2011-03-02 21:21:47 +00:00
{
2012-11-17 19:46:43 +00:00
int32_t hei , zofs = 0 ;
2012-11-25 13:18:57 +00:00
const int32_t picnum = spr - > picnum , yrepeat = spr - > yrepeat ;
2011-03-23 17:41:01 +00:00
2020-05-23 22:27:24 +00:00
hei = ( tileHeight ( picnum ) * yrepeat ) < < 2 ;
2019-03-19 17:08:12 +00:00
if ( height ! = NULL )
* height = hei ;
2011-03-02 21:21:47 +00:00
2012-11-25 13:18:57 +00:00
if ( spr - > cstat & 128 )
2012-11-17 19:46:43 +00:00
zofs = hei > > 1 ;
2011-09-04 19:44:51 +00:00
2012-11-17 19:46:43 +00:00
// NOTE: a positive per-tile yoffset translates the sprite into the
// negative world z direction (i.e. upward).
if ( alsotileyofs )
2020-05-24 10:31:38 +00:00
zofs - = tileTopOffset ( picnum ) * yrepeat < < 2 ;
2012-11-17 19:46:37 +00:00
2012-11-17 19:46:43 +00:00
return zofs ;
2011-03-02 21:21:47 +00:00
}
2006-04-13 20:47:06 +00:00
//
// setsprite
//
2012-11-05 02:49:08 +00:00
int32_t setsprite ( int16_t spritenum , const vec3_t * newpos )
2006-04-13 20:47:06 +00:00
{
2009-01-19 00:58:39 +00:00
int16_t tempsectnum = sprite [ spritenum ] . sectnum ;
2006-04-13 20:47:06 +00:00
2017-06-23 03:58:48 +00:00
if ( ( void const * ) newpos ! = ( void * ) & sprite [ spritenum ] )
2019-08-13 14:44:00 +00:00
sprite [ spritenum ] . pos = * newpos ;
2006-04-13 20:47:06 +00:00
2012-11-05 02:49:08 +00:00
updatesector ( newpos - > x , newpos - > y , & tempsectnum ) ;
2007-08-16 23:25:24 +00:00
2006-04-13 20:47:06 +00:00
if ( tempsectnum < 0 )
2016-06-21 00:34:41 +00:00
return - 1 ;
2006-04-13 20:47:06 +00:00
if ( tempsectnum ! = sprite [ spritenum ] . sectnum )
changespritesect ( spritenum , tempsectnum ) ;
2016-06-21 00:34:41 +00:00
return 0 ;
2006-04-13 20:47:06 +00:00
}
2012-11-05 02:49:08 +00:00
int32_t setspritez ( int16_t spritenum , const vec3_t * newpos )
2007-08-16 23:25:24 +00:00
{
2009-01-19 00:58:39 +00:00
int16_t tempsectnum = sprite [ spritenum ] . sectnum ;
2007-08-16 23:25:24 +00:00
2016-01-11 05:05:38 +00:00
if ( ( void const * ) newpos ! = ( void * ) & sprite [ spritenum ] )
2019-08-13 14:44:00 +00:00
sprite [ spritenum ] . pos = * newpos ;
2007-08-16 23:25:24 +00:00
2012-11-05 02:49:08 +00:00
updatesectorz ( newpos - > x , newpos - > y , newpos - > z , & tempsectnum ) ;
2007-08-16 23:25:24 +00:00
if ( tempsectnum < 0 )
2016-06-21 00:34:41 +00:00
return - 1 ;
2007-08-16 23:25:24 +00:00
if ( tempsectnum ! = sprite [ spritenum ] . sectnum )
changespritesect ( spritenum , tempsectnum ) ;
2016-06-21 00:34:41 +00:00
return 0 ;
2007-08-16 23:25:24 +00:00
}
2006-04-13 20:47:06 +00:00
//
// nextsectorneighborz
//
2012-08-26 22:15:02 +00:00
// -1: ceiling or up
// 1: floor or down
2014-03-25 21:04:33 +00:00
int32_t nextsectorneighborz ( int16_t sectnum , int32_t refz , int16_t topbottom , int16_t direction )
2006-04-13 20:47:06 +00:00
{
2012-08-26 22:15:02 +00:00
int32_t nextz = ( direction = = 1 ) ? INT32_MAX : INT32_MIN ;
int32_t sectortouse = - 1 ;
2006-04-13 20:47:06 +00:00
2019-04-18 17:25:24 +00:00
auto wal = ( uwallptr_t ) & wall [ sector [ sectnum ] . wallptr ] ;
2012-08-26 22:15:02 +00:00
int32_t i = sector [ sectnum ] . wallnum ;
2006-04-13 20:47:06 +00:00
do
{
2012-08-26 22:15:02 +00:00
const int32_t ns = wal - > nextsector ;
if ( ns > = 0 )
2006-04-13 20:47:06 +00:00
{
2014-01-31 21:12:56 +00:00
const int32_t testz = ( topbottom = = 1 ) ?
2012-08-26 22:15:02 +00:00
sector [ ns ] . floorz : sector [ ns ] . ceilingz ;
2014-01-31 21:12:56 +00:00
const int32_t update = ( direction = = 1 ) ?
2014-03-25 21:04:33 +00:00
( nextz > testz & & testz > refz ) :
( nextz < testz & & testz < refz ) ;
2012-08-26 22:15:02 +00:00
2014-01-31 21:12:56 +00:00
if ( update )
2006-04-13 20:47:06 +00:00
{
2012-08-26 22:15:02 +00:00
nextz = testz ;
2014-01-31 21:12:56 +00:00
sectortouse = ns ;
2006-04-13 20:47:06 +00:00
}
}
2012-08-26 22:15:02 +00:00
2006-04-13 20:47:06 +00:00
wal + + ;
i - - ;
2007-12-12 17:42:14 +00:00
}
while ( i ! = 0 ) ;
2006-04-13 20:47:06 +00:00
2014-01-31 21:12:56 +00:00
return sectortouse ;
2006-04-13 20:47:06 +00:00
}
//
// cansee
//
2019-09-22 19:26:07 +00:00
int32_t cansee_old ( int32_t xs , int32_t ys , int32_t zs , int16_t sectnums , int32_t xe , int32_t ye , int32_t ze , int16_t sectnume )
{
sectortype * sec , * nsec ;
walltype * wal , * wal2 ;
int32_t intx , inty , intz , i , cnt , nextsector , dasectnum , dacnt , danum ;
if ( ( xs = = xe ) & & ( ys = = ye ) & & ( sectnums = = sectnume ) ) return 1 ;
clipsectorlist [ 0 ] = sectnums ; danum = 1 ;
for ( dacnt = 0 ; dacnt < danum ; dacnt + + )
{
dasectnum = clipsectorlist [ dacnt ] ; sec = & sector [ dasectnum ] ;
for ( cnt = sec - > wallnum , wal = & wall [ sec - > wallptr ] ; cnt > 0 ; cnt - - , wal + + )
{
wal2 = & wall [ wal - > point2 ] ;
if ( lintersect ( xs , ys , zs , xe , ye , ze , wal - > x , wal - > y , wal2 - > x , wal2 - > y , & intx , & inty , & intz ) ! = 0 )
{
nextsector = wal - > nextsector ; if ( nextsector < 0 ) return 0 ;
if ( intz < = sec - > ceilingz ) return 0 ;
if ( intz > = sec - > floorz ) return 0 ;
nsec = & sector [ nextsector ] ;
if ( intz < = nsec - > ceilingz ) return 0 ;
if ( intz > = nsec - > floorz ) return 0 ;
for ( i = danum - 1 ; i > = 0 ; i - - )
if ( clipsectorlist [ i ] = = nextsector ) break ;
if ( i < 0 ) clipsectorlist [ danum + + ] = nextsector ;
}
}
if ( clipsectorlist [ dacnt ] = = sectnume )
return 1 ;
}
return 0 ;
}
2009-01-09 09:29:17 +00:00
int32_t cansee ( int32_t x1 , int32_t y1 , int32_t z1 , int16_t sect1 , int32_t x2 , int32_t y2 , int32_t z2 , int16_t sect2 )
2006-04-13 20:47:06 +00:00
{
2019-09-22 19:26:07 +00:00
if ( enginecompatibility_mode = = ENGINECOMPATIBILITY_19950829 )
2019-11-07 05:15:12 +00:00
return cansee_old ( x1 , y1 , z1 , sect1 , x2 , y2 , z2 , sect2 ) ;
2012-11-17 19:46:47 +00:00
int32_t dacnt , danum ;
const int32_t x21 = x2 - x1 , y21 = y2 - y1 , z21 = z2 - z1 ;
2006-04-13 20:47:06 +00:00
2019-04-18 17:24:43 +00:00
static uint8_t sectbitmap [ ( MAXSECTORS + 7 ) > > 3 ] ;
2019-09-03 04:09:20 +00:00
Bmemset ( sectbitmap , 0 , sizeof ( sectbitmap ) ) ;
2012-11-17 19:46:47 +00:00
if ( x1 = = x2 & & y1 = = y2 )
return ( sect1 = = sect2 ) ;
2006-04-13 20:47:06 +00:00
2019-08-04 02:51:50 +00:00
sectbitmap [ sect1 > > 3 ] | = pow2char [ sect1 & 7 ] ;
2006-04-13 20:47:06 +00:00
clipsectorlist [ 0 ] = sect1 ; danum = 1 ;
2011-07-01 17:15:07 +00:00
2009-02-19 16:47:54 +00:00
for ( dacnt = 0 ; dacnt < danum ; dacnt + + )
2006-04-13 20:47:06 +00:00
{
2012-11-17 19:46:47 +00:00
const int32_t dasectnum = clipsectorlist [ dacnt ] ;
2019-04-18 17:25:24 +00:00
auto const sec = ( usectorptr_t ) & sector [ dasectnum ] ;
uwallptr_t wal ;
2016-08-27 01:41:21 +00:00
bssize_t cnt ;
2019-04-18 17:25:24 +00:00
for ( cnt = sec - > wallnum , wal = ( uwallptr_t ) & wall [ sec - > wallptr ] ; cnt > 0 ; cnt - - , wal + + )
2006-04-13 20:47:06 +00:00
{
2019-04-18 17:25:24 +00:00
auto const wal2 = ( uwallptr_t ) & wall [ wal - > point2 ] ;
2012-11-17 19:46:47 +00:00
const int32_t x31 = wal - > x - x1 , x34 = wal - > x - wal2 - > x ;
const int32_t y31 = wal - > y - y1 , y34 = wal - > y - wal2 - > y ;
int32_t x , y , z , nexts , t , bot ;
int32_t cfz [ 2 ] ;
2006-04-13 20:47:06 +00:00
bot = y21 * x34 - x21 * y34 ; if ( bot < = 0 ) continue ;
2012-06-13 23:13:39 +00:00
// XXX: OVERFLOW
2006-04-13 20:47:06 +00:00
t = y21 * x31 - x21 * y31 ; if ( ( unsigned ) t > = ( unsigned ) bot ) continue ;
2011-07-01 17:15:07 +00:00
t = y31 * x34 - x31 * y34 ;
if ( ( unsigned ) t > = ( unsigned ) bot )
{
continue ;
}
2006-04-13 20:47:06 +00:00
nexts = wal - > nextsector ;
2011-07-01 17:15:07 +00:00
2013-04-15 10:48:09 +00:00
if ( nexts < 0 | | wal - > cstat & 32 )
return 0 ;
2006-04-13 20:47:06 +00:00
t = divscale24 ( t , bot ) ;
x = x1 + mulscale24 ( x21 , t ) ;
y = y1 + mulscale24 ( y21 , t ) ;
z = z1 + mulscale24 ( z21 , t ) ;
2013-04-15 10:48:09 +00:00
getzsofslope ( dasectnum , x , y , & cfz [ 0 ] , & cfz [ 1 ] ) ;
2011-07-01 17:15:07 +00:00
2013-04-12 11:59:22 +00:00
if ( z < = cfz [ 0 ] | | z > = cfz [ 1 ] )
2011-07-01 17:15:07 +00:00
{
2013-04-15 10:48:09 +00:00
return 0 ;
2011-07-01 17:15:07 +00:00
}
2013-04-15 10:48:09 +00:00
getzsofslope ( nexts , x , y , & cfz [ 0 ] , & cfz [ 1 ] ) ;
if ( z < = cfz [ 0 ] | | z > = cfz [ 1 ] )
return 0 ;
2011-07-01 17:15:07 +00:00
2019-08-04 02:51:50 +00:00
if ( ! ( sectbitmap [ nexts > > 3 ] & pow2char [ nexts & 7 ] ) )
2011-07-01 17:15:07 +00:00
{
2019-08-04 02:51:50 +00:00
sectbitmap [ nexts > > 3 ] | = pow2char [ nexts & 7 ] ;
2011-07-01 17:15:07 +00:00
clipsectorlist [ danum + + ] = nexts ;
}
}
2006-04-13 20:47:06 +00:00
}
2011-07-01 17:15:07 +00:00
2019-08-04 02:51:50 +00:00
if ( sectbitmap [ sect2 > > 3 ] & pow2char [ sect2 & 7 ] )
2011-07-01 17:15:07 +00:00
return 1 ;
2013-04-15 10:48:09 +00:00
return 0 ;
2006-04-13 20:47:06 +00:00
}
//
// neartag
//
2014-01-31 21:13:00 +00:00
void neartag ( int32_t xs , int32_t ys , int32_t zs , int16_t sectnum , int16_t ange ,
int16_t * neartagsector , int16_t * neartagwall , int16_t * neartagsprite , int32_t * neartaghitdist , /* out */
int32_t neartagrange , uint8_t tagsearch ,
2012-02-20 19:54:24 +00:00
int32_t ( * blacklist_sprite_func ) ( int32_t ) )
2006-04-13 20:47:06 +00:00
{
2012-11-17 19:46:47 +00:00
int16_t tempshortcnt , tempshortnum ;
const int32_t vx = mulscale14 ( sintable [ ( ange + 2560 ) & 2047 ] , neartagrange ) ;
const int32_t vy = mulscale14 ( sintable [ ( ange + 2048 ) & 2047 ] , neartagrange ) ;
2012-11-25 13:18:57 +00:00
vec3_t hitv = { xs + vx , ys + vy , 0 } ;
const vec3_t sv = { xs , ys , zs } ;
2006-04-13 20:47:06 +00:00
* neartagsector = - 1 ; * neartagwall = - 1 ; * neartagsprite = - 1 ;
* neartaghitdist = 0 ;
2012-11-17 19:46:47 +00:00
if ( sectnum < 0 | | ( tagsearch & 3 ) = = 0 )
return ;
2006-04-13 20:47:06 +00:00
clipsectorlist [ 0 ] = sectnum ;
tempshortcnt = 0 ; tempshortnum = 1 ;
do
{
2012-11-17 19:46:47 +00:00
const int32_t dasector = clipsectorlist [ tempshortcnt ] ;
const int32_t startwall = sector [ dasector ] . wallptr ;
const int32_t endwall = startwall + sector [ dasector ] . wallnum - 1 ;
2019-04-18 17:25:24 +00:00
uwallptr_t wal ;
2012-11-17 19:46:47 +00:00
int32_t z ;
2006-04-13 20:47:06 +00:00
2019-04-18 17:25:24 +00:00
for ( z = startwall , wal = ( uwallptr_t ) & wall [ startwall ] ; z < = endwall ; z + + , wal + + )
2006-04-13 20:47:06 +00:00
{
2019-04-18 17:25:24 +00:00
auto const wal2 = ( uwallptr_t ) & wall [ wal - > point2 ] ;
2012-11-17 19:46:47 +00:00
const int32_t nextsector = wal - > nextsector ;
2006-04-13 20:47:06 +00:00
2012-11-17 19:46:47 +00:00
const int32_t x1 = wal - > x , y1 = wal - > y , x2 = wal2 - > x , y2 = wal2 - > y ;
int32_t intx , inty , intz , good = 0 ;
2006-04-13 20:47:06 +00:00
if ( nextsector > = 0 )
{
if ( ( tagsearch & 1 ) & & sector [ nextsector ] . lotag ) good | = 1 ;
if ( ( tagsearch & 2 ) & & sector [ nextsector ] . hitag ) good | = 1 ;
}
2012-11-17 19:46:47 +00:00
2006-04-13 20:47:06 +00:00
if ( ( tagsearch & 1 ) & & wal - > lotag ) good | = 2 ;
if ( ( tagsearch & 2 ) & & wal - > hitag ) good | = 2 ;
if ( ( good = = 0 ) & & ( nextsector < 0 ) ) continue ;
2014-08-23 10:28:18 +00:00
if ( ( coord_t ) ( x1 - xs ) * ( y2 - ys ) < ( coord_t ) ( x2 - xs ) * ( y1 - ys ) ) continue ;
2006-04-13 20:47:06 +00:00
2012-11-25 13:18:57 +00:00
if ( lintersect ( xs , ys , zs , hitv . x , hitv . y , hitv . z , x1 , y1 , x2 , y2 , & intx , & inty , & intz ) = = 1 )
2006-04-13 20:47:06 +00:00
{
if ( good ! = 0 )
{
if ( good & 1 ) * neartagsector = nextsector ;
if ( good & 2 ) * neartagwall = z ;
* neartaghitdist = dmulscale14 ( intx - xs , sintable [ ( ange + 2560 ) & 2047 ] , inty - ys , sintable [ ( ange + 2048 ) & 2047 ] ) ;
2012-11-25 13:18:57 +00:00
hitv . x = intx ; hitv . y = inty ; hitv . z = intz ;
2006-04-13 20:47:06 +00:00
}
2012-11-17 19:46:47 +00:00
2006-04-13 20:47:06 +00:00
if ( nextsector > = 0 )
{
2012-11-17 19:46:47 +00:00
int32_t zz ;
2009-02-19 16:47:54 +00:00
for ( zz = tempshortnum - 1 ; zz > = 0 ; zz - - )
2006-04-13 20:47:06 +00:00
if ( clipsectorlist [ zz ] = = nextsector ) break ;
if ( zz < 0 ) clipsectorlist [ tempshortnum + + ] = nextsector ;
}
}
}
2011-03-04 08:50:58 +00:00
tempshortcnt + + ;
2012-11-17 19:46:47 +00:00
if ( tagsearch & 4 )
continue ; // skip sprite search
2011-03-04 08:50:58 +00:00
2009-02-19 16:47:54 +00:00
for ( z = headspritesect [ dasector ] ; z > = 0 ; z = nextspritesect [ z ] )
2006-04-13 20:47:06 +00:00
{
2019-04-18 17:25:24 +00:00
auto const spr = ( uspriteptr_t ) & sprite [ z ] ;
2012-11-17 19:46:47 +00:00
2012-02-20 19:54:24 +00:00
if ( blacklist_sprite_func & & blacklist_sprite_func ( z ) )
continue ;
2012-11-25 13:18:57 +00:00
if ( ( ( tagsearch & 1 ) & & spr - > lotag ) | | ( ( tagsearch & 2 ) & & spr - > hitag ) )
2006-04-13 20:47:06 +00:00
{
2019-08-09 09:28:27 +00:00
if ( try_facespr_intersect ( spr , sv , vx , vy , 0 , & hitv , 1 ) )
2006-04-13 20:47:06 +00:00
{
2012-11-25 13:18:57 +00:00
* neartagsprite = z ;
* neartaghitdist = dmulscale14 ( hitv . x - xs , sintable [ ( ange + 2560 ) & 2047 ] ,
hitv . y - ys , sintable [ ( ange + 2048 ) & 2047 ] ) ;
2006-04-13 20:47:06 +00:00
}
}
}
2007-12-12 17:42:14 +00:00
}
while ( tempshortcnt < tempshortnum ) ;
2006-04-13 20:47:06 +00:00
}
//
// dragpoint
//
2013-01-16 20:38:41 +00:00
// flags:
// 1: don't reset walbitmap[] (the bitmap of already dragged vertices)
// 2: In the editor, do wall[].cstat |= (1<<14) also for the lastwall().
void dragpoint ( int16_t pointhighlight , int32_t dax , int32_t day , uint8_t flags )
2011-04-14 20:48:08 +00:00
{
2012-11-17 19:46:47 +00:00
int32_t i , numyaxwalls = 0 ;
2011-04-14 20:48:08 +00:00
static int16_t yaxwalls [ MAXWALLS ] ;
2012-11-17 19:46:47 +00:00
uint8_t * const walbitmap = ( uint8_t * ) tempbuf ;
2011-04-14 20:48:08 +00:00
2013-01-16 20:38:41 +00:00
if ( ( flags & 1 ) = = 0 )
2011-05-29 12:30:38 +00:00
Bmemset ( walbitmap , 0 , ( numwalls + 7 ) > > 3 ) ;
2011-04-14 20:48:08 +00:00
yaxwalls [ numyaxwalls + + ] = pointhighlight ;
for ( i = 0 ; i < numyaxwalls ; i + + )
{
2012-11-17 19:46:47 +00:00
int32_t clockwise = 0 ;
int32_t w = yaxwalls [ i ] ;
const int32_t tmpstartwall = w ;
2011-10-03 17:43:51 +00:00
2016-08-27 01:41:21 +00:00
bssize_t cnt = MAXWALLS ;
2011-04-14 20:48:08 +00:00
while ( 1 )
{
wall [ w ] . x = dax ;
wall [ w ] . y = day ;
2019-08-04 02:51:50 +00:00
walbitmap [ w > > 3 ] | = pow2char [ w & 7 ] ;
2011-04-14 20:48:08 +00:00
2011-11-01 22:01:35 +00:00
if ( ! clockwise ) //search points CCW
2011-04-14 20:48:08 +00:00
{
if ( wall [ w ] . nextwall > = 0 )
w = wall [ wall [ w ] . nextwall ] . point2 ;
else
2011-10-03 17:43:51 +00:00
{
w = tmpstartwall ;
2011-04-14 20:48:08 +00:00
clockwise = 1 ;
2011-10-03 17:43:51 +00:00
}
2011-04-14 20:48:08 +00:00
}
2011-11-01 22:01:35 +00:00
cnt - - ;
if ( cnt = = 0 )
{
2020-04-11 21:45:45 +00:00
Printf ( " dragpoint %d: infloop! \n " , pointhighlight ) ;
2011-11-01 22:01:35 +00:00
i = numyaxwalls ;
break ;
}
if ( clockwise )
2011-04-14 20:48:08 +00:00
{
2012-11-17 19:46:47 +00:00
int32_t thelastwall = lastwall ( w ) ;
2011-04-14 20:48:08 +00:00
if ( wall [ thelastwall ] . nextwall > = 0 )
w = wall [ thelastwall ] . nextwall ;
else
break ;
}
2019-08-04 02:51:50 +00:00
if ( ( walbitmap [ w > > 3 ] & pow2char [ w & 7 ] ) )
2011-11-01 22:01:35 +00:00
{
if ( clockwise )
break ;
w = tmpstartwall ;
clockwise = 1 ;
continue ;
}
2011-04-14 20:48:08 +00:00
}
}
}
2006-04-13 20:47:06 +00:00
//
// lastwall
//
2009-01-09 09:29:17 +00:00
int32_t lastwall ( int16_t point )
2006-04-13 20:47:06 +00:00
{
2012-11-17 19:46:47 +00:00
if ( point > 0 & & wall [ point - 1 ] . point2 = = point )
return point - 1 ;
2006-04-13 20:47:06 +00:00
2019-04-10 09:30:49 +00:00
int i = point , cnt = numwalls ;
2006-04-13 20:47:06 +00:00
do
{
2015-07-11 23:07:47 +00:00
int const j = wall [ i ] . point2 ;
if ( j = = point )
{
point = i ;
break ;
}
2006-04-13 20:47:06 +00:00
i = j ;
2007-12-12 17:42:14 +00:00
}
2015-07-11 23:07:47 +00:00
while ( - - cnt ) ;
2012-11-17 19:46:47 +00:00
2015-07-11 23:07:47 +00:00
return point ;
2006-04-13 20:47:06 +00:00
}
2016-06-21 00:33:30 +00:00
////////// UPDATESECTOR* FAMILY OF FUNCTIONS //////////
/* Different "is inside" predicates.
* NOTE : The redundant bound checks are expected to be optimized away in the
* inlined code . */
2010-10-28 20:17:22 +00:00
2019-12-07 23:49:56 +00:00
static FORCE_INLINE CONSTEXPR int inside_exclude_p ( int32_t const x , int32_t const y , int const sectnum , const uint8_t * excludesectbitmap )
2010-10-28 20:17:22 +00:00
{
2019-04-06 06:37:42 +00:00
return ( sectnum > = 0 & & ! bitmap_test ( excludesectbitmap , sectnum ) & & inside_p ( x , y , sectnum ) ) ;
2016-06-21 00:33:30 +00:00
}
2013-04-12 11:59:22 +00:00
2016-06-21 00:33:30 +00:00
/* NOTE: no bound check */
2019-12-07 23:49:56 +00:00
static inline int inside_z_p ( int32_t const x , int32_t const y , int32_t const z , int const sectnum )
2016-06-21 00:33:30 +00:00
{
int32_t cz , fz ;
2019-04-06 06:37:42 +00:00
getzsofslope ( sectnum , x , y , & cz , & fz ) ;
return ( z > = cz & & z < = fz & & inside_p ( x , y , sectnum ) ) ;
2016-06-21 00:33:30 +00:00
}
2012-10-01 17:52:09 +00:00
2019-08-27 06:52:42 +00:00
int32_t getwalldist ( vec2_t const in , int const wallnum )
2019-04-18 17:24:30 +00:00
{
vec2_t closest ;
2019-04-19 08:31:47 +00:00
getclosestpointonwall_internal ( in , wallnum , & closest ) ;
return klabs ( closest . x - in . x ) + klabs ( closest . y - in . y ) ;
2019-04-18 17:24:30 +00:00
}
2019-08-27 06:52:42 +00:00
int32_t getwalldist ( vec2_t const in , int const wallnum , vec2_t * const out )
2019-08-04 02:51:59 +00:00
{
getclosestpointonwall_internal ( in , wallnum , out ) ;
return klabs ( out - > x - in . x ) + klabs ( out - > y - in . y ) ;
}
2019-08-27 06:52:42 +00:00
int32_t getsectordist ( vec2_t const in , int const sectnum , vec2_t * const out /*= nullptr*/ )
2019-04-18 17:24:30 +00:00
{
2019-04-19 08:31:47 +00:00
if ( inside_p ( in . x , in . y , sectnum ) )
{
if ( out )
* out = in ;
2019-04-18 17:24:30 +00:00
return 0 ;
2019-04-19 08:31:47 +00:00
}
2019-04-18 17:24:30 +00:00
int32_t distance = INT32_MAX ;
2019-04-18 17:25:24 +00:00
auto const sec = ( usectorptr_t ) & sector [ sectnum ] ;
2019-04-18 17:24:30 +00:00
int const startwall = sec - > wallptr ;
int const endwall = sec - > wallptr + sec - > wallnum ;
2019-04-18 17:25:24 +00:00
auto uwal = ( uwallptr_t ) & wall [ startwall ] ;
2019-04-19 08:31:47 +00:00
vec2_t closest = { } ;
2019-04-18 17:24:30 +00:00
for ( int j = startwall ; j < endwall ; j + + , uwal + + )
{
2019-04-19 08:31:47 +00:00
vec2_t p ;
int32_t const walldist = getwalldist ( in , j , & p ) ;
if ( walldist < distance )
{
distance = walldist ;
closest = p ;
}
2019-04-18 17:24:30 +00:00
}
2019-04-19 08:31:47 +00:00
if ( out )
* out = closest ;
2019-04-18 17:24:30 +00:00
return distance ;
}
2019-04-19 08:31:42 +00:00
int findwallbetweensectors ( int sect1 , int sect2 )
2019-04-18 17:24:05 +00:00
{
if ( sector [ sect1 ] . wallnum > sector [ sect2 ] . wallnum )
swaplong ( & sect1 , & sect2 ) ;
2019-04-19 08:31:42 +00:00
auto const sec = ( usectorptr_t ) & sector [ sect1 ] ;
int const last = sec - > wallptr + sec - > wallnum ;
2019-04-18 17:24:05 +00:00
2019-04-19 08:31:42 +00:00
for ( int i = sec - > wallptr ; i < last ; i + + )
if ( wall [ i ] . nextsector = = sect2 )
return i ;
return - 1 ;
2019-04-18 17:24:05 +00:00
}
2006-04-13 20:47:06 +00:00
//
// updatesector[z]
//
2019-04-06 06:37:42 +00:00
void updatesector ( int32_t const x , int32_t const y , int16_t * const sectnum )
2006-04-13 20:47:06 +00:00
{
2020-04-21 23:05:52 +00:00
#if 0
2019-09-22 19:26:07 +00:00
if ( enginecompatibility_mode ! = ENGINECOMPATIBILITY_NONE )
2019-07-29 15:12:01 +00:00
{
if ( inside_p ( x , y , * sectnum ) )
return ;
if ( ( unsigned ) * sectnum < ( unsigned ) numsectors )
{
const uwalltype * wal = ( uwalltype * ) & wall [ sector [ * sectnum ] . wallptr ] ;
int wallsleft = sector [ * sectnum ] . wallnum ;
do
{
int const next = wal - > nextsector ;
if ( inside_p ( x , y , next ) )
SET_AND_RETURN ( * sectnum , next ) ;
wal + + ;
}
while ( - - wallsleft ) ;
}
}
else
2020-04-21 23:05:52 +00:00
# endif
2019-07-29 15:12:01 +00:00
{
int16_t sect = * sectnum ;
updatesectorneighbor ( x , y , & sect , INITIALUPDATESECTORDIST , MAXUPDATESECTORDIST ) ;
if ( sect ! = - 1 )
SET_AND_RETURN ( * sectnum , sect ) ;
}
2012-01-14 14:48:30 +00:00
2019-04-18 17:25:11 +00:00
// we need to support passing in a sectnum of -1, unfortunately
for ( int i = numsectors - 1 ; i > = 0 ; - - i )
if ( inside_p ( x , y , i ) )
SET_AND_RETURN ( * sectnum , i ) ;
2012-01-14 14:48:30 +00:00
* sectnum = - 1 ;
}
2019-04-06 06:37:42 +00:00
void updatesectorexclude ( int32_t const x , int32_t const y , int16_t * const sectnum , const uint8_t * const excludesectbitmap )
2010-11-27 22:12:24 +00:00
{
2012-10-01 17:52:09 +00:00
if ( inside_exclude_p ( x , y , * sectnum , excludesectbitmap ) )
2010-11-27 22:12:24 +00:00
return ;
2012-10-01 17:52:09 +00:00
if ( * sectnum > = 0 & & * sectnum < numsectors )
2010-11-27 22:12:24 +00:00
{
2019-04-18 17:25:24 +00:00
auto wal = ( uwallptr_t ) & wall [ sector [ * sectnum ] . wallptr ] ;
2016-06-21 00:34:29 +00:00
int wallsleft = sector [ * sectnum ] . wallnum ;
2012-10-01 17:52:09 +00:00
2010-11-27 22:12:24 +00:00
do
{
2016-06-21 00:34:29 +00:00
int const next = wal - > nextsector ;
if ( inside_exclude_p ( x , y , next , excludesectbitmap ) )
SET_AND_RETURN ( * sectnum , next ) ;
wal + + ;
2010-11-27 22:12:24 +00:00
}
2016-06-21 00:34:29 +00:00
while ( - - wallsleft ) ;
2010-11-27 22:12:24 +00:00
}
2016-08-27 01:41:21 +00:00
for ( bssize_t i = numsectors - 1 ; i > = 0 ; - - i )
2012-10-01 17:52:09 +00:00
if ( inside_exclude_p ( x , y , i , excludesectbitmap ) )
SET_AND_RETURN ( * sectnum , i ) ;
2010-11-27 22:12:24 +00:00
* sectnum = - 1 ;
}
2011-09-01 18:38:13 +00:00
// new: if *sectnum >= MAXSECTORS, *sectnum-=MAXSECTORS is considered instead
// as starting sector and the 'initial' z check is skipped
// (not initial anymore because it follows the sector updating due to TROR)
2020-05-16 10:47:01 +00:00
// NOTE: This comes from Duke, therefore it's GPL!
2019-04-06 06:38:10 +00:00
void updatesectorz ( int32_t const x , int32_t const y , int32_t const z , int16_t * const sectnum )
2019-07-19 01:46:32 +00:00
{
2019-09-22 19:26:07 +00:00
if ( enginecompatibility_mode ! = ENGINECOMPATIBILITY_NONE )
2019-07-29 15:12:01 +00:00
{
if ( ( uint32_t ) ( * sectnum ) < 2 * MAXSECTORS )
{
int32_t nofirstzcheck = 0 ;
if ( * sectnum > = MAXSECTORS )
{
* sectnum - = MAXSECTORS ;
nofirstzcheck = 1 ;
}
// this block used to be outside the "if" and caused crashes in Polymost Mapster32
int32_t cz , fz ;
getzsofslope ( * sectnum , x , y , & cz , & fz ) ;
if ( nofirstzcheck | | ( z > = cz & & z < = fz ) )
if ( inside_p ( x , y , * sectnum ) )
return ;
uwalltype const * wal = ( uwalltype * ) & wall [ sector [ * sectnum ] . wallptr ] ;
int wallsleft = sector [ * sectnum ] . wallnum ;
do
{
// YAX: TODO: check neighboring sectors here too?
int const next = wal - > nextsector ;
if ( next > = 0 & & inside_z_p ( x , y , z , next ) )
SET_AND_RETURN ( * sectnum , next ) ;
wal + + ;
}
while ( - - wallsleft ) ;
}
}
else
{
int16_t sect = * sectnum ;
updatesectorneighborz ( x , y , z , & sect , INITIALUPDATESECTORDIST , MAXUPDATESECTORDIST ) ;
if ( sect ! = - 1 )
SET_AND_RETURN ( * sectnum , sect ) ;
}
2019-07-19 01:46:32 +00:00
// we need to support passing in a sectnum of -1, unfortunately
for ( int i = numsectors - 1 ; i > = 0 ; - - i )
if ( inside_z_p ( x , y , z , i ) )
SET_AND_RETURN ( * sectnum , i ) ;
* sectnum = - 1 ;
}
2019-07-19 03:14:53 +00:00
void updatesectorneighbor ( int32_t const x , int32_t const y , int16_t * const sectnum , int32_t initialMaxDistance /*= INITIALUPDATESECTORDIST*/ , int32_t maxDistance /*= MAXUPDATESECTORDIST*/ )
2019-07-19 01:46:32 +00:00
{
int const initialsectnum = * sectnum ;
if ( ( unsigned ) initialsectnum < ( unsigned ) numsectors & & getsectordist ( { x , y } , initialsectnum ) < = initialMaxDistance )
{
if ( inside_p ( x , y , initialsectnum ) )
return ;
static int16_t sectlist [ MAXSECTORS ] ;
static uint8_t sectbitmap [ ( MAXSECTORS + 7 ) > > 3 ] ;
int16_t nsecs ;
bfirst_search_init ( sectlist , sectbitmap , & nsecs , MAXSECTORS , initialsectnum ) ;
for ( int sectcnt = 0 ; sectcnt < nsecs ; sectcnt + + )
{
int const listsectnum = sectlist [ sectcnt ] ;
if ( inside_p ( x , y , listsectnum ) )
SET_AND_RETURN ( * sectnum , listsectnum ) ;
auto const sec = & sector [ listsectnum ] ;
int const startwall = sec - > wallptr ;
int const endwall = sec - > wallptr + sec - > wallnum ;
auto uwal = ( uwallptr_t ) & wall [ startwall ] ;
for ( int j = startwall ; j < endwall ; j + + , uwal + + )
if ( uwal - > nextsector > = 0 & & getsectordist ( { x , y } , uwal - > nextsector ) < = maxDistance )
bfirst_search_try ( sectlist , sectbitmap , & nsecs , uwal - > nextsector ) ;
}
}
* sectnum = - 1 ;
}
2019-07-19 03:14:53 +00:00
void updatesectorneighborz ( int32_t const x , int32_t const y , int32_t const z , int16_t * const sectnum , int32_t initialMaxDistance /*= 0*/ , int32_t maxDistance /*= 0*/ )
2019-04-06 06:38:00 +00:00
{
bool nofirstzcheck = false ;
2019-04-20 21:57:02 +00:00
if ( * sectnum > = MAXSECTORS & & * sectnum - MAXSECTORS < numsectors )
2019-04-06 06:38:00 +00:00
{
2019-04-18 17:25:11 +00:00
* sectnum - = MAXSECTORS ;
nofirstzcheck = true ;
}
2019-04-06 06:38:00 +00:00
2019-04-20 21:57:02 +00:00
uint32_t const correctedsectnum = ( unsigned ) * sectnum ;
2019-04-06 06:38:00 +00:00
2019-07-19 01:46:32 +00:00
if ( correctedsectnum < ( unsigned ) numsectors & & getsectordist ( { x , y } , correctedsectnum ) < = initialMaxDistance )
2019-04-18 17:25:11 +00:00
{
int32_t cz , fz ;
getzsofslope ( correctedsectnum , x , y , & cz , & fz ) ;
2019-04-06 06:38:00 +00:00
2019-04-20 21:57:02 +00:00
if ( ( nofirstzcheck | | ( z > = cz & & z < = fz ) ) & & inside_p ( x , y , * sectnum ) )
2019-04-06 06:38:00 +00:00
return ;
2019-04-18 17:25:11 +00:00
static int16_t sectlist [ MAXSECTORS ] ;
static uint8_t sectbitmap [ ( MAXSECTORS + 7 ) > > 3 ] ;
2019-05-19 03:52:54 +00:00
int16_t nsecs ;
2019-04-06 06:38:00 +00:00
2019-04-18 17:25:11 +00:00
bfirst_search_init ( sectlist , sectbitmap , & nsecs , MAXSECTORS , correctedsectnum ) ;
2019-04-06 06:38:00 +00:00
2019-04-18 17:25:11 +00:00
for ( int sectcnt = 0 ; sectcnt < nsecs ; sectcnt + + )
{
int const listsectnum = sectlist [ sectcnt ] ;
if ( inside_z_p ( x , y , z , listsectnum ) )
SET_AND_RETURN ( * sectnum , listsectnum ) ;
2019-04-06 06:38:00 +00:00
2019-04-18 17:25:11 +00:00
auto const sec = & sector [ listsectnum ] ;
int const startwall = sec - > wallptr ;
int const endwall = sec - > wallptr + sec - > wallnum ;
2019-04-18 17:25:24 +00:00
auto uwal = ( uwallptr_t ) & wall [ startwall ] ;
2019-04-06 06:38:00 +00:00
2019-04-18 17:25:11 +00:00
for ( int j = startwall ; j < endwall ; j + + , uwal + + )
2019-07-19 01:46:32 +00:00
if ( uwal - > nextsector > = 0 & & getsectordist ( { x , y } , uwal - > nextsector ) < = maxDistance )
2019-04-18 17:25:11 +00:00
bfirst_search_try ( sectlist , sectbitmap , & nsecs , uwal - > nextsector ) ;
}
2019-04-06 06:38:00 +00:00
}
* sectnum = - 1 ;
}
2006-04-13 20:47:06 +00:00
//
// rotatepoint
//
2019-04-18 17:24:10 +00:00
void rotatepoint ( vec2_t const pivot , vec2_t p , int16_t const daang , vec2_t * const p2 )
2006-04-13 20:47:06 +00:00
{
2015-05-26 00:47:54 +00:00
int const dacos = sintable [ ( daang + 2560 ) & 2047 ] ;
int const dasin = sintable [ ( daang + 2048 ) & 2047 ] ;
p . x - = pivot . x ;
p . y - = pivot . y ;
p2 - > x = dmulscale14 ( p . x , dacos , - p . y , dasin ) + pivot . x ;
p2 - > y = dmulscale14 ( p . y , dacos , p . x , dasin ) + pivot . y ;
2006-04-13 20:47:06 +00:00
}
2012-08-16 21:48:56 +00:00
int32_t setaspect_new_use_dimen = 0 ;
2018-04-12 21:02:51 +00:00
void videoSetCorrectedAspect ( )
2010-10-17 14:49:39 +00:00
{
2020-07-05 19:21:39 +00:00
if ( /*r_usenewaspect &&*/ newaspect_enable & & videoGetRenderMode ( ) ! = REND_POLYMER )
2010-10-17 14:49:39 +00:00
{
2019-02-18 22:02:33 +00:00
// In DOS the game world is displayed with an aspect of 1.28 instead 1.333,
// meaning we have to stretch it by a factor of 1.25 instead of 1.2
// to get perfect squares
int32_t yx = ( 65536 * 5 ) / 4 ;
int32_t vr , y , x ;
2010-10-17 14:49:39 +00:00
2012-08-16 21:48:56 +00:00
const int32_t xd = setaspect_new_use_dimen ? xdimen : xdim ;
const int32_t yd = setaspect_new_use_dimen ? ydimen : ydim ;
2020-01-01 11:36:48 +00:00
x = xd ;
y = yd ;
2010-10-17 14:49:39 +00:00
2012-04-09 19:22:31 +00:00
vr = divscale16 ( x * 3 , y * 4 ) ;
2010-10-17 14:49:39 +00:00
2018-04-12 21:03:47 +00:00
renderSetAspect ( vr , yx ) ;
2010-10-17 14:49:39 +00:00
}
else
2018-04-12 21:03:47 +00:00
renderSetAspect ( 65536 , divscale16 ( ydim * 320 , xdim * 200 ) ) ;
2010-10-17 14:49:39 +00:00
}
2006-04-13 20:47:06 +00:00
//
// setview
//
2018-04-12 21:02:51 +00:00
void videoSetViewableArea ( int32_t x1 , int32_t y1 , int32_t x2 , int32_t y2 )
2006-04-13 20:47:06 +00:00
{
2019-12-31 18:02:55 +00:00
windowxy1 . x = x1 ;
windowxy1 . y = y1 ;
windowxy2 . x = x2 ;
windowxy2 . y = y2 ;
2006-04-13 20:47:06 +00:00
xdimen = ( x2 - x1 ) + 1 ; halfxdimen = ( xdimen > > 1 ) ;
xdimenrecip = divscale32 ( 1L , xdimen ) ;
ydimen = ( y2 - y1 ) + 1 ;
2014-10-25 03:27:35 +00:00
fxdimen = ( float ) xdimen ;
2014-11-28 08:14:00 +00:00
# ifdef USE_OPENGL
2014-10-25 03:27:35 +00:00
fydimen = ( float ) ydimen ;
# endif
2018-04-12 21:02:51 +00:00
videoSetCorrectedAspect ( ) ;
2006-04-13 20:47:06 +00:00
}
//
// setaspect
//
2018-04-12 21:03:47 +00:00
void renderSetAspect ( int32_t daxrange , int32_t daaspect )
2006-04-13 20:47:06 +00:00
{
2020-01-25 10:56:13 +00:00
if ( daxrange = = 65536 ) daxrange - - ; // This doesn't work correctly with 65536. All other values are fine. No idea where this is evaluated wrong.
2006-04-13 20:47:06 +00:00
viewingrange = daxrange ;
2011-10-17 18:41:38 +00:00
viewingrangerecip = divscale32 ( 1 , daxrange ) ;
2016-10-03 02:43:42 +00:00
# ifdef USE_OPENGL
fviewingrange = ( float ) daxrange ;
# endif
2006-04-13 20:47:06 +00:00
yxaspect = daaspect ;
xyaspect = divscale32 ( 1 , yxaspect ) ;
xdimenscale = scale ( xdimen , yxaspect , 320 ) ;
xdimscale = scale ( 320 , xyaspect , xdimen ) ;
}
2019-11-21 18:30:27 +00:00
# include "v_2ddrawer.h"
2006-04-13 20:47:06 +00:00
2020-01-01 11:01:26 +00:00
2006-04-13 20:47:06 +00:00
//
// clearview
//
2018-04-12 21:02:51 +00:00
void videoClearViewableArea ( int32_t dacol )
2006-04-13 20:47:06 +00:00
{
2020-04-12 05:44:55 +00:00
GLInterface . ClearScreen ( dacol , false ) ;
2006-04-13 20:47:06 +00:00
}
//
// clearallviews
//
2018-04-12 21:02:51 +00:00
void videoClearScreen ( int32_t dacol )
2006-04-13 20:47:06 +00:00
{
2020-04-12 05:44:55 +00:00
GLInterface . ClearScreen ( dacol | PalEntry ( 255 , 0 , 0 , 0 ) ) ;
2006-04-13 20:47:06 +00:00
}
2006-04-24 19:04:22 +00:00
//MUST USE RESTOREFORDRAWROOMS AFTER DRAWING
2006-04-13 20:47:06 +00:00
2020-03-29 12:01:46 +00:00
static int32_t setviewcnt = 0 ; // interface layers use this now
static int32_t bakxsiz , bakysiz ;
static vec2_t bakwindowxy1 , bakwindowxy2 ;
2006-04-13 20:47:06 +00:00
//
// setviewtotile
//
2020-06-14 19:57:21 +00:00
FCanvasTexture * renderSetTarget ( int16_t tilenume )
2006-04-13 20:47:06 +00:00
{
2020-06-14 19:57:21 +00:00
auto tex = tileGetTexture ( tilenume ) ;
if ( ! tex | | ! tex - > isHardwareCanvas ( ) ) return nullptr ;
auto canvas = static_cast < FCanvasTexture * > ( tex - > GetTexture ( ) ) ;
if ( ! canvas ) return nullptr ;
int xsiz = tex - > GetTexelWidth ( ) , ysiz = tex - > GetTexelHeight ( ) ;
if ( setviewcnt > 0 | | xsiz < = 0 | | ysiz < = 0 )
return nullptr ;
2014-09-30 04:06:32 +00:00
2020-03-29 12:01:46 +00:00
//DRAWROOMS TO TILE BACKUP&SET CODE
bakxsiz = xdim ; bakysiz = ydim ;
bakwindowxy1 = windowxy1 ;
bakwindowxy2 = windowxy2 ;
2014-09-30 04:06:32 +00:00
2006-04-13 20:47:06 +00:00
setviewcnt + + ;
2020-06-14 19:57:21 +00:00
xdim = ysiz ;
ydim = xsiz ;
videoSetViewableArea ( 0 , 0 , ysiz - 1 , xsiz - 1 ) ;
2018-04-12 21:03:47 +00:00
renderSetAspect ( 65536 , 65536 ) ;
2020-06-14 19:57:21 +00:00
return canvas ;
2006-04-13 20:47:06 +00:00
}
//
// setviewback
//
2020-03-29 12:01:46 +00:00
void renderRestoreTarget ( )
2006-04-13 20:47:06 +00:00
{
if ( setviewcnt < = 0 ) return ;
setviewcnt - - ;
2020-03-29 12:01:46 +00:00
xdim = bakxsiz ;
ydim = bakysiz ;
videoSetViewableArea ( bakwindowxy1 . x , bakwindowxy1 . y ,
bakwindowxy2 . x , bakwindowxy2 . y ) ;
2012-12-14 19:28:17 +00:00
2006-04-13 20:47:06 +00:00
}
//
// preparemirror
//
2019-06-25 18:35:16 +00:00
void renderPrepareMirror ( int32_t dax , int32_t day , int32_t daz , fix16_t daang , fix16_t dahoriz , int16_t dawall ,
2018-04-12 21:03:47 +00:00
int32_t * tposx , int32_t * tposy , fix16_t * tang )
2006-04-13 20:47:06 +00:00
{
2013-05-01 17:41:59 +00:00
const int32_t x = wall [ dawall ] . x , dx = wall [ wall [ dawall ] . point2 ] . x - x ;
const int32_t y = wall [ dawall ] . y , dy = wall [ wall [ dawall ] . point2 ] . y - y ;
2006-04-13 20:47:06 +00:00
2013-05-01 17:41:59 +00:00
const int32_t j = dx * dx + dy * dy ;
if ( j = = 0 )
return ;
2016-06-21 00:33:39 +00:00
int i = ( ( dax - x ) * dx + ( day - y ) * dy ) < < 1 ;
2008-03-22 10:23:57 +00:00
2006-04-13 20:47:06 +00:00
* tposx = ( x < < 1 ) + scale ( dx , i , j ) - dax ;
* tposy = ( y < < 1 ) + scale ( dy , i , j ) - day ;
2018-03-07 04:21:18 +00:00
* tang = ( fix16_from_int ( getangle ( dx , dy ) < < 1 ) - daang ) & 0x7FFFFFF ;
2006-04-13 20:47:06 +00:00
inpreparemirror = 1 ;
2019-06-25 18:35:16 +00:00
# ifdef USE_OPENGL
2019-07-19 01:49:34 +00:00
if ( videoGetRenderMode ( ) = = REND_POLYMOST )
2019-06-25 18:35:16 +00:00
polymost_prepareMirror ( dax , day , daz , daang , dahoriz , dawall ) ;
# endif
2006-04-13 20:47:06 +00:00
}
2019-09-21 11:02:17 +00:00
2006-04-13 20:47:06 +00:00
//
// completemirror
//
2018-04-12 21:03:47 +00:00
void renderCompleteMirror ( void )
2006-04-13 20:47:06 +00:00
{
2020-03-29 12:55:09 +00:00
polymost_completeMirror ( ) ;
2019-06-25 18:35:05 +00:00
inpreparemirror = 0 ;
2006-04-13 20:47:06 +00:00
}
//
// sectorofwall
//
2018-04-02 22:00:23 +00:00
static int32_t sectorofwall_internal ( int16_t wallNum )
2006-04-13 20:47:06 +00:00
{
2018-04-02 22:00:23 +00:00
native_t gap = numsectors > > 1 , sectNum = gap ;
2006-04-13 20:47:06 +00:00
while ( gap > 1 )
{
gap > > = 1 ;
2018-04-02 22:00:23 +00:00
native_t const n = ! ! ( sector [ sectNum ] . wallptr < wallNum ) ;
sectNum + = ( n ^ ( n - 1 ) ) * gap ;
2006-04-13 20:47:06 +00:00
}
2018-04-02 22:00:23 +00:00
while ( sector [ sectNum ] . wallptr > wallNum ) sectNum - - ;
while ( sector [ sectNum ] . wallptr + sector [ sectNum ] . wallnum < = wallNum ) sectNum + + ;
2013-04-12 11:59:26 +00:00
2018-04-02 22:00:23 +00:00
return sectNum ;
2006-04-13 20:47:06 +00:00
}
2018-04-02 22:00:23 +00:00
int32_t sectorofwall ( int16_t wallNum )
2011-02-10 23:15:02 +00:00
{
2018-04-02 22:00:23 +00:00
if ( EDUKE32_PREDICT_FALSE ( ( unsigned ) wallNum > = ( unsigned ) numwalls ) )
2013-04-12 11:59:26 +00:00
return - 1 ;
2018-04-02 22:00:23 +00:00
native_t const w = wall [ wallNum ] . nextwall ;
2011-02-10 23:15:02 +00:00
2018-04-02 22:00:23 +00:00
return ( ( unsigned ) w < MAXWALLS ) ? wall [ w ] . nextsector : sectorofwall_internal ( wallNum ) ;
2011-02-10 23:15:02 +00:00
}
2006-04-13 20:47:06 +00:00
2019-04-18 17:25:24 +00:00
int32_t getceilzofslopeptr ( usectorptr_t sec , int32_t dax , int32_t day )
2006-04-13 20:47:06 +00:00
{
2013-04-12 11:59:26 +00:00
if ( ! ( sec - > ceilingstat & 2 ) )
return sec - > ceilingz ;
2009-06-07 03:13:55 +00:00
2019-04-18 17:25:24 +00:00
auto const wal = ( uwallptr_t ) & wall [ sec - > wallptr ] ;
auto const wal2 = ( uwallptr_t ) & wall [ wal - > point2 ] ;
2009-06-07 03:13:55 +00:00
2016-06-21 00:34:18 +00:00
vec2_t const w = * ( vec2_t const * ) wal ;
2019-04-18 17:23:53 +00:00
vec2_t const d = { wal2 - > x - w . x , wal2 - > y - w . y } ;
2013-04-12 11:59:26 +00:00
2016-06-21 00:34:29 +00:00
int const i = nsqrtasm ( uhypsq ( d . x , d . y ) ) < < 5 ;
2016-06-21 00:33:30 +00:00
if ( i = = 0 ) return sec - > ceilingz ;
2013-04-12 11:59:26 +00:00
2016-06-21 00:34:29 +00:00
int const j = dmulscale3 ( d . x , day - w . y , - d . y , dax - w . x ) ;
2019-09-22 19:26:07 +00:00
int const shift = enginecompatibility_mode ! = ENGINECOMPATIBILITY_NONE ? 0 : 1 ;
2019-09-21 11:02:17 +00:00
return sec - > ceilingz + ( scale ( sec - > ceilingheinum , j > > shift , i ) < < shift ) ;
2006-04-13 20:47:06 +00:00
}
2019-04-18 17:25:24 +00:00
int32_t getflorzofslopeptr ( usectorptr_t sec , int32_t dax , int32_t day )
2006-04-13 20:47:06 +00:00
{
2013-04-12 11:59:26 +00:00
if ( ! ( sec - > floorstat & 2 ) )
return sec - > floorz ;
2009-06-07 03:13:55 +00:00
2019-04-18 17:25:24 +00:00
auto const wal = ( uwallptr_t ) & wall [ sec - > wallptr ] ;
auto const wal2 = ( uwallptr_t ) & wall [ wal - > point2 ] ;
2009-06-07 03:13:55 +00:00
2016-06-21 00:34:18 +00:00
vec2_t const w = * ( vec2_t const * ) wal ;
2019-04-18 17:23:53 +00:00
vec2_t const d = { wal2 - > x - w . x , wal2 - > y - w . y } ;
2013-04-12 11:59:26 +00:00
2016-06-21 00:34:29 +00:00
int const i = nsqrtasm ( uhypsq ( d . x , d . y ) ) < < 5 ;
2016-06-21 00:33:30 +00:00
if ( i = = 0 ) return sec - > floorz ;
2013-04-12 11:59:26 +00:00
2016-06-21 00:34:29 +00:00
int const j = dmulscale3 ( d . x , day - w . y , - d . y , dax - w . x ) ;
2019-09-22 19:26:07 +00:00
int const shift = enginecompatibility_mode ! = ENGINECOMPATIBILITY_NONE ? 0 : 1 ;
2019-09-21 11:02:17 +00:00
return sec - > floorz + ( scale ( sec - > floorheinum , j > > shift , i ) < < shift ) ;
2006-04-13 20:47:06 +00:00
}
2019-04-18 17:25:24 +00:00
void getzsofslopeptr ( usectorptr_t sec , int32_t dax , int32_t day , int32_t * ceilz , int32_t * florz )
2006-04-13 20:47:06 +00:00
{
* ceilz = sec - > ceilingz ; * florz = sec - > floorz ;
2013-04-12 11:59:26 +00:00
2016-06-21 00:33:30 +00:00
if ( ( ( sec - > ceilingstat | sec - > floorstat ) & 2 ) ! = 2 )
return ;
2013-04-12 11:59:26 +00:00
2019-04-18 17:25:24 +00:00
auto const wal = ( uwallptr_t ) & wall [ sec - > wallptr ] ;
auto const wal2 = ( uwallptr_t ) & wall [ wal - > point2 ] ;
2019-04-18 17:23:53 +00:00
vec2_t const d = { wal2 - > x - wal - > x , wal2 - > y - wal - > y } ;
2013-04-12 11:59:26 +00:00
2016-06-21 00:34:29 +00:00
int const i = nsqrtasm ( uhypsq ( d . x , d . y ) ) < < 5 ;
2016-06-21 00:33:30 +00:00
if ( i = = 0 ) return ;
2016-06-21 00:34:29 +00:00
int const j = dmulscale3 ( d . x , day - wal - > y , - d . y , dax - wal - > x ) ;
2019-09-22 19:26:07 +00:00
int const shift = enginecompatibility_mode ! = ENGINECOMPATIBILITY_NONE ? 0 : 1 ;
2016-06-21 00:33:30 +00:00
if ( sec - > ceilingstat & 2 )
2019-09-21 11:02:17 +00:00
* ceilz + = scale ( sec - > ceilingheinum , j > > shift , i ) < < shift ;
2016-06-21 00:33:30 +00:00
if ( sec - > floorstat & 2 )
2019-09-21 11:02:17 +00:00
* florz + = scale ( sec - > floorheinum , j > > shift , i ) < < shift ;
2006-04-13 20:47:06 +00:00
}
//
// alignceilslope
//
2009-01-09 09:29:17 +00:00
void alignceilslope ( int16_t dasect , int32_t x , int32_t y , int32_t z )
2006-04-13 20:47:06 +00:00
{
2019-04-18 17:25:24 +00:00
auto const wal = ( uwallptr_t ) & wall [ sector [ dasect ] . wallptr ] ;
2013-04-12 11:59:26 +00:00
const int32_t dax = wall [ wal - > point2 ] . x - wal - > x ;
const int32_t day = wall [ wal - > point2 ] . y - wal - > y ;
2006-04-13 20:47:06 +00:00
2013-04-12 11:59:26 +00:00
const int32_t i = ( y - wal - > y ) * dax - ( x - wal - > x ) * day ;
if ( i = = 0 )
return ;
2006-04-13 20:47:06 +00:00
sector [ dasect ] . ceilingheinum = scale ( ( z - sector [ dasect ] . ceilingz ) < < 8 ,
2012-07-01 22:11:14 +00:00
nsqrtasm ( uhypsq ( dax , day ) ) , i ) ;
2013-04-12 11:59:26 +00:00
if ( sector [ dasect ] . ceilingheinum = = 0 )
sector [ dasect ] . ceilingstat & = ~ 2 ;
2006-04-13 20:47:06 +00:00
else sector [ dasect ] . ceilingstat | = 2 ;
}
//
// alignflorslope
//
2009-01-09 09:29:17 +00:00
void alignflorslope ( int16_t dasect , int32_t x , int32_t y , int32_t z )
2006-04-13 20:47:06 +00:00
{
2019-04-18 17:25:24 +00:00
auto const wal = ( uwallptr_t ) & wall [ sector [ dasect ] . wallptr ] ;
2013-04-12 11:59:26 +00:00
const int32_t dax = wall [ wal - > point2 ] . x - wal - > x ;
const int32_t day = wall [ wal - > point2 ] . y - wal - > y ;
2006-04-13 20:47:06 +00:00
2013-04-12 11:59:26 +00:00
const int32_t i = ( y - wal - > y ) * dax - ( x - wal - > x ) * day ;
if ( i = = 0 )
return ;
2006-04-13 20:47:06 +00:00
sector [ dasect ] . floorheinum = scale ( ( z - sector [ dasect ] . floorz ) < < 8 ,
2012-07-01 22:11:14 +00:00
nsqrtasm ( uhypsq ( dax , day ) ) , i ) ;
2013-04-12 11:59:26 +00:00
if ( sector [ dasect ] . floorheinum = = 0 )
sector [ dasect ] . floorstat & = ~ 2 ;
2006-04-13 20:47:06 +00:00
else sector [ dasect ] . floorstat | = 2 ;
}
//
// setrendermode
//
2018-04-12 21:03:47 +00:00
int32_t videoSetRenderMode ( int32_t renderer )
2006-04-13 20:47:06 +00:00
{
2008-07-24 11:16:20 +00:00
UNREFERENCED_PARAMETER ( renderer ) ;
2014-12-26 17:29:52 +00:00
2011-03-04 08:50:58 +00:00
# ifdef USE_OPENGL
2009-08-09 05:32:17 +00:00
2020-03-29 12:55:09 +00:00
renderer = REND_POLYMOST ;
2006-08-29 01:58:59 +00:00
2006-04-13 20:47:06 +00:00
rendmode = renderer ;
2018-04-12 21:03:12 +00:00
if ( videoGetRenderMode ( ) > = REND_POLYMOST )
2009-03-27 21:54:55 +00:00
glrendmode = rendmode ;
2018-03-21 20:41:26 +00:00
2006-04-13 20:47:06 +00:00
# endif
return 0 ;
}
//
// setrollangle
//
2011-03-04 08:50:58 +00:00
# ifdef USE_OPENGL
2020-05-13 04:42:47 +00:00
void renderSetRollAngle ( float rolla )
2006-04-13 20:47:06 +00:00
{
2020-05-13 04:42:47 +00:00
gtang = rolla * ( fPI * ( 1.f / 1024.f ) ) ;
2006-04-13 20:47:06 +00:00
}
2008-07-24 11:16:20 +00:00
# endif