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 "osd.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"
2018-11-18 18:09:48 +00:00
2011-03-04 08:50:58 +00:00
# ifdef USE_OPENGL
2018-11-18 18:09:48 +00:00
# include "hightile.h"
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
2015-02-07 17:29:10 +00:00
//////////
// Compilation switches for optional/extended engine features
2014-09-30 04:06:32 +00:00
# if !defined(__arm__) && !defined(GEKKO)
2015-02-07 17:29:10 +00:00
# define HIGH_PRECISION_SPRITE
# endif
# if !defined EDUKE32_TOUCH_DEVICES && !defined GEKKO && !defined __OPENDINGUX__
// Handle absolute z difference of floor/ceiling to camera >= 1<<24.
2015-02-19 17:41:53 +00:00
// Also: higher precision view-relative x and y for drawvox().
2015-02-07 17:29:10 +00:00
# define CLASSIC_Z_DIFF_64
2014-09-30 04:06:32 +00:00
# endif
2012-12-23 13:59:56 +00:00
# define MULTI_COLUMN_VLINE
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
2013-07-04 19:38:37 +00:00
// Handle nonpow2-ysize walls the old way?
2019-04-18 17:25:38 +00:00
static FORCE_INLINE int32_t oldnonpow2 ( void )
2013-06-01 20:09:39 +00:00
{
# if !defined CLASSIC_NONPOW2_YSIZE_WALLS
return 1 ;
# else
2013-07-04 19:38:37 +00:00
return ( g_loadedMapVersion < 10 ) ;
2013-06-01 20:09:39 +00:00
# endif
}
2020-01-28 21:41:07 +00:00
bool playing_rr ;
bool playing_blood ;
int32_t rendmode = 0 ;
int32_t glrendmode = REND_POLYMOST ;
int32_t r_scenebrightness = 0 ;
int32_t r_rortexture = 0 ;
int32_t r_rortexturerange = 0 ;
int32_t r_rorphase = 0 ;
int32_t mdtims , omdtims ;
uint8_t alphahackarray [ MAXTILES ] ;
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
char britable [ 16 ] [ 256 ] ; // JBF 20040207: full 8bit precision
2008-12-02 10:44:39 +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 ;
//i = tabledivide64((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-12-25 15:33:02 +00:00
# if !defined YAX_ENABLE
# warning Non-TROR builds are supported only for debugging. Expect savegame breakage etc...
# endif
2011-03-13 11:59:32 +00:00
# ifdef YAX_ENABLE
// all references to floor/ceiling bunchnums should be through the
// get/set functions!
2011-09-04 19:44:07 +00:00
int32_t g_nodraw = 0 ;
2011-05-22 21:52:22 +00:00
int32_t scansector_retfast = 0 ;
2019-03-19 17:07:53 +00:00
int32_t scansector_collectsprites = 1 ;
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
int32_t yax_globalcf = - 1 , yax_nomaskpass = 0 , yax_nomaskdidit ; // engine internal
int32_t r_tror_nomaskpass = 1 ; // cvar
2011-09-15 17:02:12 +00:00
int32_t yax_globallev = YAX_MAXDRAWS ;
int32_t yax_globalbunch = - 1 ;
2019-03-19 17:07:53 +00:00
int32_t yax_polymostclearzbuffer = 1 ;
2011-05-07 18:23:34 +00:00
// duplicated tsprites
// [i]:
// i==MAXDRAWS: base level
// i<MAXDRAWS: MAXDRAWS-i-1 is level towards ceiling
// i>MAXDRAWS: i-MAXDRAWS-1 is level towards floor
static int16_t yax_spritesortcnt [ 1 + 2 * YAX_MAXDRAWS ] ;
2011-09-28 20:30:41 +00:00
static uint16_t yax_tsprite [ 1 + 2 * YAX_MAXDRAWS ] [ MAXSPRITESONSCREEN ] ;
static uint8_t yax_tsprfrombunch [ 1 + 2 * YAX_MAXDRAWS ] [ MAXSPRITESONSCREEN ] ;
2011-04-28 21:28:33 +00:00
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
// drawn sectors
2019-04-18 17:24:43 +00:00
uint8_t yax_gotsector [ ( MAXSECTORS + 7 ) > > 3 ] ; // engine internal
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
2013-04-09 17:35:11 +00:00
# if !defined NEW_MAP_FORMAT
// Game-time YAX data structures, V7-V9 map formats.
2011-05-12 23:31:13 +00:00
int16_t yax_bunchnum [ MAXSECTORS ] [ 2 ] ;
int16_t yax_nextwall [ MAXWALLS ] [ 2 ] ;
2011-04-11 22:28:58 +00:00
2017-02-25 08:15:53 +00:00
static FORCE_INLINE int32_t yax_islockededge ( int32_t line , int32_t cf )
2011-04-11 22:28:58 +00:00
{
return ! ! ( wall [ line ] . cstat & ( YAX_NEXTWALLBIT ( cf ) ) ) ;
}
2011-03-13 11:59:32 +00:00
2012-02-16 19:25:18 +00:00
# define YAX_PTRBUNCHNUM(Ptr, Sect, Cf) (*(&Ptr[Sect].ceilingxpanning + 8*Cf))
# define YAX_BUNCHNUM(Sect, Cf) YAX_PTRBUNCHNUM(sector, Sect, Cf)
2011-04-11 22:28:58 +00:00
//// bunch getters/setters
2011-03-02 21:21:47 +00:00
int16_t yax_getbunch ( int16_t i , int16_t cf )
{
2011-03-13 11:59:32 +00:00
if ( editstatus = = 0 )
return yax_bunchnum [ i ] [ cf ] ;
2016-06-21 00:34:18 +00:00
return ( * ( & sector [ i ] . ceilingstat + cf ) & YAX_BIT ) ? YAX_BUNCHNUM ( i , cf ) : - 1 ;
2011-03-02 21:21:47 +00:00
}
2013-04-09 17:35:11 +00:00
# endif
2011-03-13 11:59:32 +00:00
2011-11-26 22:39:50 +00:00
// bunchnum: -1: also clear yax-nextwalls (forward and reverse)
// -2: don't clear reverse yax-nextwalls
// -3: don't clear either forward or reverse yax-nextwalls
2011-03-02 21:21:47 +00:00
void yax_setbunch ( int16_t i , int16_t cf , int16_t bunchnum )
{
2011-03-13 11:59:32 +00:00
if ( editstatus = = 0 )
2011-04-11 22:28:58 +00:00
{
2011-03-13 11:59:32 +00:00
yax_bunchnum [ i ] [ cf ] = bunchnum ;
2011-04-11 22:28:58 +00:00
return ;
}
2011-03-13 11:59:32 +00:00
2011-11-26 22:39:50 +00:00
if ( bunchnum < 0 )
2011-03-02 21:21:47 +00:00
{
2011-11-26 22:39:50 +00:00
if ( bunchnum > - 3 )
2011-04-22 22:48:06 +00:00
{
2011-11-26 22:39:50 +00:00
// TODO: for in-game too?
2016-08-27 01:41:21 +00:00
for ( bssize_t ynw , j = sector [ i ] . wallptr ; j < sector [ i ] . wallptr + sector [ i ] . wallnum ; j + + )
2011-05-22 21:52:22 +00:00
{
2011-11-26 22:39:50 +00:00
ynw = yax_getnextwall ( j , cf ) ;
if ( ynw > = 0 )
{
if ( bunchnum > - 2 )
yax_setnextwall ( ynw , ! cf , - 1 ) ;
yax_setnextwall ( j , cf , - 1 ) ;
}
2011-05-22 21:52:22 +00:00
}
2011-04-22 22:48:06 +00:00
}
2011-03-02 21:21:47 +00:00
* ( & sector [ i ] . ceilingstat + cf ) & = ~ YAX_BIT ;
2014-01-28 19:03:47 +00:00
// NOTE: Don't reset xpanning-as-index, since we can be called from
// e.g. Mapster32's "Inner loop made into new sector" functionality.
2011-03-02 21:21:47 +00:00
return ;
}
* ( & sector [ i ] . ceilingstat + cf ) | = YAX_BIT ;
YAX_BUNCHNUM ( i , cf ) = bunchnum ;
}
2011-03-13 11:59:32 +00:00
void yax_setbunches ( int16_t i , int16_t cb , int16_t fb )
{
yax_setbunch ( i , YAX_CEILING , cb ) ;
yax_setbunch ( i , YAX_FLOOR , fb ) ;
}
2013-04-09 17:35:11 +00:00
# if !defined NEW_MAP_FORMAT
2011-04-11 22:28:58 +00:00
//// nextwall getters/setters
int16_t yax_getnextwall ( int16_t wal , int16_t cf )
{
if ( editstatus = = 0 )
return yax_nextwall [ wal ] [ cf ] ;
2016-06-21 00:34:18 +00:00
return yax_islockededge ( wal , cf ) ? YAX_NEXTWALL ( wal , cf ) : - 1 ;
2011-04-11 22:28:58 +00:00
}
// unchecked!
void yax_setnextwall ( int16_t wal , int16_t cf , int16_t thenextwall )
{
if ( editstatus = = 0 )
{
yax_nextwall [ wal ] [ cf ] = thenextwall ;
return ;
}
if ( thenextwall > = 0 )
2011-04-14 20:48:08 +00:00
{
2011-04-11 22:28:58 +00:00
wall [ wal ] . cstat | = YAX_NEXTWALLBIT ( cf ) ;
2011-04-14 20:48:08 +00:00
YAX_NEXTWALL ( wal , cf ) = thenextwall ;
}
2011-04-11 22:28:58 +00:00
else
2011-04-14 20:48:08 +00:00
{
2011-04-11 22:28:58 +00:00
wall [ wal ] . cstat & = ~ YAX_NEXTWALLBIT ( cf ) ;
2012-08-26 22:10:40 +00:00
YAX_NEXTWALL ( wal , cf ) = YAX_NEXTWALLDEFAULT ( cf ) ;
2011-04-14 20:48:08 +00:00
}
2011-04-11 22:28:58 +00:00
}
2013-04-09 17:35:11 +00:00
# endif
2011-04-11 22:28:58 +00:00
2011-09-15 17:02:12 +00:00
// make one step in the vertical direction, and if the wall we arrive at
// is red, return its nextsector.
int16_t yax_vnextsec ( int16_t line , int16_t cf )
{
2015-02-11 05:21:53 +00:00
int16_t const ynw = yax_getnextwall ( line , cf ) ;
return ( ynw < 0 ) ? - 1 : wall [ ynw ] . nextsector ;
2011-09-15 17:02:12 +00:00
}
2011-05-15 22:37:24 +00:00
//// in-struct --> array transfer (only resetstat==0); list construction
2011-05-12 23:31:13 +00:00
// resetstat: 0: reset and read data from structs and construct linked lists etc.
// 1: only reset
// 2: read data from game-time arrays and construct linked lists etc.
void yax_update ( int32_t resetstat )
2011-03-23 17:41:01 +00:00
{
2013-04-09 17:35:11 +00:00
int32_t i ;
# if !defined NEW_MAP_FORMAT
int32_t j ;
const int32_t oeditstatus = editstatus ;
# endif
int16_t cb , fb ;
2011-03-23 17:41:01 +00:00
2011-05-15 22:37:24 +00:00
if ( resetstat ! = 2 )
numyaxbunches = 0 ;
2011-03-23 17:41:01 +00:00
for ( i = 0 ; i < MAXSECTORS ; i + + )
{
2013-04-09 17:35:11 +00:00
# if !defined NEW_MAP_FORMAT
2011-05-12 23:31:13 +00:00
if ( resetstat ! = 2 | | i > = numsectors )
yax_bunchnum [ i ] [ 0 ] = yax_bunchnum [ i ] [ 1 ] = - 1 ;
2013-04-09 17:35:11 +00:00
# endif
2011-03-23 17:41:01 +00:00
nextsectbunch [ 0 ] [ i ] = nextsectbunch [ 1 ] [ i ] = - 1 ;
}
for ( i = 0 ; i < YAX_MAXBUNCHES ; i + + )
headsectbunch [ 0 ] [ i ] = headsectbunch [ 1 ] [ i ] = - 1 ;
2013-04-09 17:35:11 +00:00
# if !defined NEW_MAP_FORMAT
2011-04-11 22:28:58 +00:00
for ( i = 0 ; i < MAXWALLS ; i + + )
2011-05-12 23:31:13 +00:00
if ( resetstat ! = 2 | | i > = numwalls )
yax_nextwall [ i ] [ 0 ] = yax_nextwall [ i ] [ 1 ] = - 1 ;
2013-04-09 17:35:11 +00:00
# endif
2011-03-23 17:41:01 +00:00
2011-05-12 23:31:13 +00:00
if ( resetstat = = 1 )
2011-03-23 17:41:01 +00:00
return ;
2013-04-09 17:35:11 +00:00
// Constuct singly linked list of sectors-of-bunch.
2012-02-16 19:25:18 +00:00
2013-04-09 17:35:11 +00:00
# if !defined NEW_MAP_FORMAT
// Read bunchnums directly from the sector struct in yax_[gs]etbunch{es}!
2012-02-16 19:25:18 +00:00
editstatus = ( resetstat = = 0 ) ;
2013-04-09 17:35:11 +00:00
// NOTE: Use oeditstatus to check for in-gamedness from here on!
# endif
2011-05-15 22:37:24 +00:00
if ( resetstat = = 0 )
{
// make bunchnums consecutive
uint8_t * const havebunch = ( uint8_t * ) tempbuf ;
2019-07-19 01:49:19 +00:00
uint8_t * const bunchmap = havebunch + ( ( YAX_MAXBUNCHES + 7 ) > > 3 ) ;
2011-05-15 22:37:24 +00:00
int32_t dasub = 0 ;
2019-07-19 01:49:19 +00:00
Bmemset ( havebunch , 0 , ( YAX_MAXBUNCHES + 7 ) > > 3 ) ;
2011-05-15 22:37:24 +00:00
for ( i = 0 ; i < numsectors ; i + + )
{
yax_getbunches ( i , & cb , & fb ) ;
if ( cb > = 0 )
2019-08-04 02:51:50 +00:00
havebunch [ cb > > 3 ] | = pow2char [ cb & 7 ] ;
2011-05-15 22:37:24 +00:00
if ( fb > = 0 )
2019-08-04 02:51:50 +00:00
havebunch [ fb > > 3 ] | = pow2char [ fb & 7 ] ;
2011-05-15 22:37:24 +00:00
}
for ( i = 0 ; i < YAX_MAXBUNCHES ; i + + )
{
2019-08-04 02:51:50 +00:00
if ( ( havebunch [ i > > 3 ] & pow2char [ i & 7 ] ) = = 0 )
2011-05-15 22:37:24 +00:00
{
bunchmap [ i ] = 255 ;
dasub + + ;
continue ;
}
bunchmap [ i ] = i - dasub ;
}
for ( i = 0 ; i < numsectors ; i + + )
{
yax_getbunches ( i , & cb , & fb ) ;
if ( cb > = 0 )
yax_setbunch ( i , YAX_CEILING , bunchmap [ cb ] ) ;
2011-10-03 17:43:16 +00:00
if ( fb > = 0 )
2011-05-15 22:37:24 +00:00
yax_setbunch ( i , YAX_FLOOR , bunchmap [ fb ] ) ;
}
}
2013-04-09 17:35:11 +00:00
// In-struct --> array transfer (resetstat==0 and !defined NEW_MAP_FORMAT)
// and list construction.
2011-03-23 17:41:01 +00:00
for ( i = numsectors - 1 ; i > = 0 ; i - - )
{
yax_getbunches ( i , & cb , & fb ) ;
2013-04-09 17:35:11 +00:00
# if !defined NEW_MAP_FORMAT
2011-05-12 23:31:13 +00:00
if ( resetstat = = 0 )
{
yax_bunchnum [ i ] [ 0 ] = cb ;
yax_bunchnum [ i ] [ 1 ] = fb ;
}
2013-04-09 17:35:11 +00:00
# endif
2011-03-23 17:41:01 +00:00
if ( cb > = 0 )
{
2013-04-09 17:35:11 +00:00
# if !defined NEW_MAP_FORMAT
2011-05-12 23:31:13 +00:00
if ( resetstat = = 0 )
for ( j = sector [ i ] . wallptr ; j < sector [ i ] . wallptr + sector [ i ] . wallnum ; j + + )
{
if ( yax_islockededge ( j , YAX_CEILING ) )
2012-02-16 19:25:18 +00:00
{
2011-05-12 23:31:13 +00:00
yax_nextwall [ j ] [ 0 ] = YAX_NEXTWALL ( j , 0 ) ;
2012-02-16 19:25:18 +00:00
if ( oeditstatus = = 0 )
YAX_NEXTWALL ( j , 0 ) = 0 ; // reset lotag!
}
2011-05-12 23:31:13 +00:00
}
2013-04-09 17:35:11 +00:00
# endif
2011-03-23 17:41:01 +00:00
if ( headsectbunch [ 0 ] [ cb ] = = - 1 )
{
headsectbunch [ 0 ] [ cb ] = i ;
// not duplicated in floors, since every extended ceiling
// must have a corresponding floor:
2011-05-12 23:31:13 +00:00
if ( resetstat = = 0 )
numyaxbunches + + ;
2011-03-23 17:41:01 +00:00
}
else
{
2013-04-09 17:35:11 +00:00
int32_t tmpsect = headsectbunch [ 0 ] [ cb ] ;
2011-03-23 17:41:01 +00:00
headsectbunch [ 0 ] [ cb ] = i ;
nextsectbunch [ 0 ] [ i ] = tmpsect ;
}
}
if ( fb > = 0 )
{
2013-04-09 17:35:11 +00:00
# if !defined NEW_MAP_FORMAT
2011-05-12 23:31:13 +00:00
if ( resetstat = = 0 )
for ( j = sector [ i ] . wallptr ; j < sector [ i ] . wallptr + sector [ i ] . wallnum ; j + + )
{
if ( yax_islockededge ( j , YAX_FLOOR ) )
2012-02-16 19:25:18 +00:00
{
2011-05-12 23:31:13 +00:00
yax_nextwall [ j ] [ 1 ] = YAX_NEXTWALL ( j , 1 ) ;
2012-02-16 19:25:18 +00:00
if ( oeditstatus = = 0 )
YAX_NEXTWALL ( j , 1 ) = - 1 ; // reset extra!
}
2011-05-12 23:31:13 +00:00
}
2013-04-09 17:35:11 +00:00
# endif
2011-03-23 17:41:01 +00:00
if ( headsectbunch [ 1 ] [ fb ] = = - 1 )
headsectbunch [ 1 ] [ fb ] = i ;
else
{
2013-04-09 17:35:11 +00:00
int32_t tmpsect = headsectbunch [ 1 ] [ fb ] ;
2011-03-23 17:41:01 +00:00
headsectbunch [ 1 ] [ fb ] = i ;
nextsectbunch [ 1 ] [ i ] = tmpsect ;
}
}
}
2012-02-16 19:25:18 +00:00
2013-04-09 17:35:11 +00:00
# if !defined NEW_MAP_FORMAT
2011-03-23 17:41:01 +00:00
editstatus = oeditstatus ;
2013-06-01 20:09:39 +00:00
# else
2014-03-10 20:08:27 +00:00
mapversion = get_mapversion ( ) ;
2013-04-09 17:35:11 +00:00
# endif
2011-03-23 17:41:01 +00:00
}
2011-04-22 22:48:06 +00:00
2012-10-01 17:52:18 +00:00
int32_t yax_getneighborsect ( int32_t x , int32_t y , int32_t sectnum , int32_t cf )
2011-04-22 22:48:06 +00:00
{
int16_t bunchnum = yax_getbunch ( sectnum , cf ) ;
if ( bunchnum < 0 )
return - 1 ;
2016-08-27 01:41:21 +00:00
for ( bssize_t SECTORS_OF_BUNCH ( bunchnum , ! cf , i ) )
2011-04-22 22:48:06 +00:00
if ( inside ( x , y , i ) = = 1 )
return i ;
return - 1 ;
}
2011-05-15 22:37:24 +00:00
// indexed as a list:
static int16_t bunches [ 2 ] [ YAX_MAXBUNCHES ] ;
// indexed with bunchnums directly:
static int16_t bunchsec [ YAX_MAXBUNCHES ] , bunchdist [ YAX_MAXBUNCHES ] ;
2011-05-12 23:31:13 +00:00
2019-07-19 01:49:19 +00:00
uint8_t haveymost [ ( YAX_MAXBUNCHES + 7 ) > > 3 ] ;
2011-05-15 22:37:24 +00:00
static inline int32_t yax_walldist ( int32_t w )
{
2019-04-18 17:24:30 +00:00
vec2_t closest ;
getclosestpointonwall_internal ( { globalposx , globalposy } , w , & closest ) ;
return klabs ( closest . x - globalposx ) + klabs ( closest . y - globalposy ) ;
2011-04-22 22:48:06 +00:00
}
2011-05-15 22:37:24 +00:00
// calculate distances to bunches and best start-drawing sectors
static void yax_scanbunches ( int32_t bbeg , int32_t numhere , const uint8_t * lastgotsector )
2011-04-22 22:48:06 +00:00
{
2011-05-15 23:16:37 +00:00
int32_t bnchcnt , bunchnum , j , k ;
2011-05-15 22:37:24 +00:00
int32_t startwall , endwall ;
2011-04-22 22:48:06 +00:00
2011-05-15 23:16:37 +00:00
UNREFERENCED_PARAMETER ( lastgotsector ) ;
2011-05-15 22:37:24 +00:00
scansector_retfast = 1 ;
scansector_collectsprites = 0 ;
2011-05-12 23:31:13 +00:00
2011-05-15 22:37:24 +00:00
for ( bnchcnt = bbeg ; bnchcnt < bbeg + numhere ; bnchcnt + + )
2011-05-07 18:23:34 +00:00
{
2011-05-15 22:37:24 +00:00
int32_t walldist , bestsec = - 1 ;
int32_t bestwalldist = INT32_MAX , bestbestdist = INT32_MAX ;
bunchnum = bunches [ yax_globalcf ] [ bnchcnt ] ;
2011-04-22 22:48:06 +00:00
2011-05-15 22:37:24 +00:00
for ( SECTORS_OF_BUNCH ( bunchnum , ! yax_globalcf , k ) )
2011-05-07 18:23:34 +00:00
{
2011-05-15 22:37:24 +00:00
int32_t checkthisec = 0 ;
if ( inside ( globalposx , globalposy , k ) = = 1 )
{
bestsec = k ;
bestbestdist = 0 ;
break ;
}
2011-05-12 23:31:13 +00:00
startwall = sector [ k ] . wallptr ;
endwall = startwall + sector [ k ] . wallnum ;
for ( j = startwall ; j < endwall ; j + + )
{
/*
2011-05-15 22:37:24 +00:00
if ( ( w = yax_getnextwall ( j , ! yax_globalcf ) ) > = 0 )
if ( ( ns = wall [ w ] . nextsector ) > = 0 )
2019-08-04 02:51:50 +00:00
if ( ( lastgotsector [ ns > > 3 ] & pow2char [ ns & 7 ] ) = = 0 )
2011-05-15 22:37:24 +00:00
continue ;
2011-05-12 23:31:13 +00:00
*/
walldist = yax_walldist ( j ) ;
if ( walldist < bestwalldist )
{
2011-05-15 22:37:24 +00:00
checkthisec = 1 ;
2011-05-12 23:31:13 +00:00
bestwalldist = walldist ;
}
}
2011-05-15 22:37:24 +00:00
if ( checkthisec )
2011-05-12 23:31:13 +00:00
{
numscans = numbunches = 0 ;
2020-03-29 12:55:09 +00:00
polymost_scansector ( k ) ;
2011-05-12 23:31:13 +00:00
if ( numbunches > 0 )
2011-05-15 22:37:24 +00:00
{
2011-05-12 23:31:13 +00:00
bestsec = k ;
2011-05-15 22:37:24 +00:00
bestbestdist = bestwalldist ;
}
2011-05-12 23:31:13 +00:00
}
2011-05-07 18:23:34 +00:00
}
2011-05-12 23:31:13 +00:00
2011-05-15 22:37:24 +00:00
bunchsec [ bunchnum ] = bestsec ;
bunchdist [ bunchnum ] = bestbestdist ;
2011-05-07 18:23:34 +00:00
}
2011-05-15 22:37:24 +00:00
scansector_collectsprites = 1 ;
scansector_retfast = 0 ;
}
2013-09-21 13:38:44 +00:00
static int yax_cmpbunches ( const void * b1 , const void * b2 )
2011-05-15 22:37:24 +00:00
{
2015-05-03 07:03:48 +00:00
return ( bunchdist [ B_UNBUF16 ( b2 ) ] - bunchdist [ B_UNBUF16 ( b1 ) ] ) ;
2011-05-07 18:23:34 +00:00
}
2011-04-22 22:48:06 +00:00
2012-02-16 19:25:42 +00:00
void yax_tweakpicnums ( int32_t bunchnum , int32_t cf , int32_t restore )
2011-05-07 18:23:34 +00:00
{
2012-02-16 19:25:18 +00:00
// for polymer, this is called before polymer_drawrooms() with restore==0
// and after polymer_drawmasks() with restore==1
2011-05-23 22:42:39 +00:00
int32_t i , dastat ;
2012-02-16 19:25:42 +00:00
static int16_t opicnum [ 2 ] [ MAXSECTORS ] ;
2011-04-22 22:48:06 +00:00
2011-05-15 22:37:24 +00:00
for ( SECTORS_OF_BUNCH ( bunchnum , cf , i ) )
2011-05-18 22:44:09 +00:00
{
2011-05-23 22:42:39 +00:00
dastat = ( SECTORFLD ( i , stat , cf ) & ( 128 + 256 ) ) ;
2011-10-02 22:38:09 +00:00
2012-02-16 19:25:18 +00:00
// only consider non-masked ceilings/floors
2011-10-02 22:38:09 +00:00
if ( dastat = = 0 | | ( restore = = 1 & & opicnum [ cf ] [ i ] & 0x8000 ) )
2011-05-07 18:23:34 +00:00
{
if ( ! restore )
{
opicnum [ cf ] [ i ] = SECTORFLD ( i , picnum , cf ) ;
if ( editstatus & & showinvisibility )
2011-05-23 22:42:39 +00:00
SECTORFLD ( i , picnum , cf ) = MAXTILES - 1 ;
2011-10-02 22:38:09 +00:00
else //if ((dastat&(128+256))==0)
2019-10-10 22:34:27 +00:00
SECTORFLD ( i , picnum , cf ) = playing_blood ? MAXTILES - 2 : 13 ; //FOF;
2011-05-07 18:23:34 +00:00
}
else
{
SECTORFLD ( i , picnum , cf ) = opicnum [ cf ] [ i ] ;
}
}
2011-05-18 22:44:09 +00:00
}
2011-05-07 18:23:34 +00:00
}
2011-04-22 22:48:06 +00:00
2011-09-28 20:30:41 +00:00
static void yax_copytsprites ( )
2011-05-07 18:23:34 +00:00
{
2011-09-28 20:30:41 +00:00
int32_t i , spritenum , gotthrough , sectnum ;
2011-05-07 18:23:34 +00:00
int32_t sortcnt = yax_spritesortcnt [ yax_globallev ] ;
2019-04-18 17:25:24 +00:00
uspriteptr_t spr ;
2011-05-07 18:23:34 +00:00
for ( i = 0 ; i < sortcnt ; i + + )
2011-04-22 22:48:06 +00:00
{
2011-05-07 18:23:34 +00:00
spritenum = yax_tsprite [ yax_globallev ] [ i ] ;
2011-09-28 20:30:41 +00:00
gotthrough = spritenum & ( MAXSPRITES | ( MAXSPRITES < < 1 ) ) ;
2011-05-07 18:23:34 +00:00
spritenum & = MAXSPRITES - 1 ;
2019-04-18 17:25:24 +00:00
spr = ( uspriteptr_t ) & sprite [ spritenum ] ;
2011-05-07 18:23:34 +00:00
sectnum = spr - > sectnum ;
2011-09-28 20:30:41 +00:00
if ( gotthrough = = ( MAXSPRITES | ( MAXSPRITES < < 1 ) ) )
2011-04-22 22:48:06 +00:00
{
2011-09-28 20:30:41 +00:00
if ( yax_globalbunch ! = yax_tsprfrombunch [ yax_globallev ] [ i ] )
2011-05-07 18:23:34 +00:00
continue ;
2011-04-22 22:48:06 +00:00
}
2011-09-28 20:30:41 +00:00
else
{
int32_t cf = - 1 ;
if ( gotthrough = = MAXSPRITES )
cf = YAX_CEILING ; // sprite got here through the ceiling of lower sector
else if ( gotthrough = = ( MAXSPRITES < < 1 ) )
cf = YAX_FLOOR ; // sprite got here through the floor of upper sector
if ( cf ! = - 1 )
{
if ( ( yax_globallev - YAX_MAXDRAWS ) * ( - 1 + 2 * cf ) > 0 )
if ( yax_getbunch ( sectnum , cf ) ! = yax_globalbunch )
continue ;
2012-10-01 17:52:18 +00:00
sectnum = yax_getneighborsect ( spr - > x , spr - > y , sectnum , cf ) ;
2011-09-28 20:30:41 +00:00
if ( sectnum < 0 )
continue ;
}
}
2011-05-07 18:23:34 +00:00
2017-07-08 19:42:11 +00:00
if ( spritesortcnt > = maxspritesonscreen )
2011-05-12 23:31:13 +00:00
break ;
2019-12-26 06:27:58 +00:00
tspriteptr_t tsp = renderAddTSpriteFromSprite ( spritenum ) ;
tsp - > sectnum = sectnum ; // potentially tweak sectnum!
2011-05-07 18:23:34 +00:00
}
}
2011-05-22 21:52:22 +00:00
2011-05-07 18:23:34 +00:00
void yax_preparedrawrooms ( void )
{
2018-04-12 21:03:12 +00:00
if ( videoGetRenderMode ( ) = = REND_POLYMER | | numyaxbunches = = 0 )
2011-05-07 18:23:34 +00:00
return ;
g_nodraw = 1 ;
2020-03-29 14:59:49 +00:00
memset ( yax_spritesortcnt , 0 , sizeof ( yax_spritesortcnt ) ) ;
memset ( haveymost , 0 , ( numyaxbunches + 7 ) > > 3 ) ;
2011-05-15 22:37:24 +00:00
2011-05-07 18:23:34 +00:00
}
2019-06-29 17:48:05 +00:00
void yax_drawrooms ( void ( * SpriteAnimFunc ) ( int32_t , int32_t , int32_t , int32_t , int32_t ) ,
2012-08-13 18:25:37 +00:00
int16_t sectnum , int32_t didmirror , int32_t smoothr )
2011-05-07 18:23:34 +00:00
{
2019-07-19 01:49:19 +00:00
static uint8_t havebunch [ ( YAX_MAXBUNCHES + 7 ) > > 3 ] ;
2011-05-07 18:23:34 +00:00
2018-03-07 04:21:05 +00:00
const fix16_t horiz = global100horiz ;
2012-08-13 18:25:37 +00:00
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
int32_t i , j , k , lev , cf , nmp ;
2011-05-07 18:23:34 +00:00
int32_t bnchcnt , bnchnum [ 2 ] = { 0 , 0 } , maxlev [ 2 ] ;
int16_t ourbunch [ 2 ] = { - 1 , - 1 } , osectnum = sectnum ;
int32_t bnchbeg [ YAX_MAXDRAWS ] [ 2 ] , bnchend [ YAX_MAXDRAWS ] [ 2 ] ;
int32_t bbeg , numhere ;
// original (1st-draw) and accumulated ('per-level') gotsector bitmaps
2019-04-18 17:24:43 +00:00
static uint8_t ogotsector [ ( MAXSECTORS + 7 ) > > 3 ] , lgotsector [ ( MAXSECTORS + 7 ) > > 3 ] ;
2011-05-12 23:31:13 +00:00
# ifdef YAX_DEBUG
2011-09-15 17:05:00 +00:00
uint64_t t ;
2011-05-12 23:31:13 +00:00
# endif
2011-05-07 18:23:34 +00:00
2018-04-12 21:03:12 +00:00
if ( videoGetRenderMode ( ) = = REND_POLYMER | | numyaxbunches = = 0 )
2011-05-07 18:23:34 +00:00
{
return ;
2011-04-22 22:48:06 +00:00
}
2011-05-07 18:23:34 +00:00
// if we're here, there was just a drawrooms() call with g_nodraw=1
Bmemcpy ( ogotsector , gotsector , ( numsectors + 7 ) > > 3 ) ;
2011-04-22 22:48:06 +00:00
2011-05-07 18:23:34 +00:00
if ( sectnum > = 0 )
yax_getbunches ( sectnum , & ourbunch [ 0 ] , & ourbunch [ 1 ] ) ;
Bmemset ( & havebunch , 0 , ( numyaxbunches + 7 ) > > 3 ) ;
// first scan all bunches above, then all below...
2011-04-22 22:48:06 +00:00
for ( cf = 0 ; cf < 2 ; cf + + )
{
2011-05-07 18:23:34 +00:00
yax_globalcf = cf ;
2011-04-22 22:48:06 +00:00
2011-05-07 18:23:34 +00:00
if ( cf = = 1 )
{
sectnum = osectnum ;
Bmemcpy ( gotsector , ogotsector , ( numsectors + 7 ) > > 3 ) ;
}
2011-04-22 22:48:06 +00:00
2011-05-07 18:23:34 +00:00
for ( lev = 0 ; /*lev<YAX_MAXDRAWS*/ ; lev + + )
2011-04-22 22:48:06 +00:00
{
2011-05-07 18:23:34 +00:00
yax_globallev = YAX_MAXDRAWS + ( - 1 + 2 * cf ) * ( lev + 1 ) ;
bbeg = bnchbeg [ lev ] [ cf ] = bnchend [ lev ] [ cf ] = bnchnum [ cf ] ;
numhere = 0 ;
2011-04-22 22:48:06 +00:00
2011-05-07 18:23:34 +00:00
for ( i = 0 ; i < numsectors ; i + + )
2011-04-22 22:48:06 +00:00
{
2019-08-04 02:51:50 +00:00
if ( ! ( gotsector [ i > > 3 ] & pow2char [ i & 7 ] ) )
2011-04-22 22:48:06 +00:00
continue ;
2011-05-07 18:23:34 +00:00
j = yax_getbunch ( i , cf ) ;
2019-08-04 02:51:50 +00:00
if ( j > = 0 & & ! ( havebunch [ j > > 3 ] & pow2char [ j & 7 ] ) )
2011-04-28 21:28:33 +00:00
{
2011-05-12 23:31:13 +00:00
if ( ( SECTORFLD ( i , stat , cf ) & 2 ) | |
2019-08-01 06:49:50 +00:00
( cf = = 0 & & globalposz > = sector [ i ] . ceilingz ) | |
( cf = = 1 & & globalposz < = sector [ i ] . floorz ) )
2011-05-12 23:31:13 +00:00
{
2019-08-04 02:51:50 +00:00
havebunch [ j > > 3 ] | = pow2char [ j & 7 ] ;
2011-05-12 23:31:13 +00:00
bunches [ cf ] [ bnchnum [ cf ] + + ] = j ;
bnchend [ lev ] [ cf ] + + ;
numhere + + ;
}
2011-04-28 21:28:33 +00:00
}
}
2011-04-22 22:48:06 +00:00
2011-05-07 18:23:34 +00:00
if ( numhere > 0 )
2011-04-28 21:28:33 +00:00
{
2011-05-07 18:23:34 +00:00
// found bunches -- need to fake-draw
2011-05-15 22:37:24 +00:00
yax_scanbunches ( bbeg , numhere , ( uint8_t * ) gotsector ) ;
2011-05-07 18:23:34 +00:00
2013-09-21 13:38:44 +00:00
qsort ( & bunches [ cf ] [ bbeg ] , numhere , sizeof ( int16_t ) , & yax_cmpbunches ) ;
2011-05-07 18:23:34 +00:00
2011-05-15 22:37:24 +00:00
if ( numhere > 1 & & lev ! = YAX_MAXDRAWS - 1 )
2019-09-03 04:09:20 +00:00
Bmemset ( lgotsector , 0 , sizeof ( lgotsector ) ) ;
2011-05-15 22:37:24 +00:00
2011-05-07 18:23:34 +00:00
for ( bnchcnt = bbeg ; bnchcnt < bbeg + numhere ; bnchcnt + + )
2011-04-22 22:48:06 +00:00
{
2011-05-07 18:23:34 +00:00
j = bunches [ cf ] [ bnchcnt ] ; // the actual bunchnum...
2011-05-15 22:37:24 +00:00
yax_globalbunch = j ;
2011-05-12 23:31:13 +00:00
# ifdef YAX_DEBUG
2018-04-12 21:02:51 +00:00
t = timerGetTicksU64 ( ) ;
2011-05-12 23:31:13 +00:00
# endif
2011-05-15 22:37:24 +00:00
k = bunchsec [ j ] ;
2011-05-07 18:23:34 +00:00
if ( k < 0 )
{
2011-05-15 22:37:24 +00:00
yaxprintf ( " %s, l %d: skipped bunch %d \n " , cf ? " v " : " ^ " , lev , j ) ;
2011-05-07 18:23:34 +00:00
continue ;
}
if ( lev ! = YAX_MAXDRAWS - 1 )
{
2011-09-28 20:30:41 +00:00
# ifdef YAX_DEBUG
int32_t odsprcnt = yax_spritesortcnt [ yax_globallev ] ;
# endif
2011-05-07 18:23:34 +00:00
// +MAXSECTORS: force
2018-04-12 21:03:47 +00:00
renderDrawRoomsQ16 ( globalposx , globalposy , globalposz , qglobalang , horiz , k + MAXSECTORS ) ;
2011-05-07 18:23:34 +00:00
if ( numhere > 1 )
for ( i = 0 ; i < ( numsectors + 7 ) > > 3 ; i + + )
lgotsector [ i ] | = gotsector [ i ] ;
2011-09-28 20:30:41 +00:00
yaxdebug ( " l%d: faked (bn %2d) sec %4d,%3d dspr, ob=[%2d,%2d], sn=%4d, %.3f ms " ,
yax_globallev - YAX_MAXDRAWS , j , k , yax_spritesortcnt [ yax_globallev ] - odsprcnt ,
2011-09-15 17:05:00 +00:00
ourbunch [ 0 ] , ourbunch [ 1 ] , sectnum ,
2018-04-12 21:02:51 +00:00
( double ) ( 1000 * ( timerGetTicksU64 ( ) - t ) ) / u64tickspersec ) ;
2011-05-12 23:31:13 +00:00
}
if ( ourbunch [ cf ] = = j )
{
ourbunch [ cf ] = yax_getbunch ( k , cf ) ;
sectnum = k ;
2011-05-07 18:23:34 +00:00
}
}
2011-04-22 22:48:06 +00:00
2011-05-07 18:23:34 +00:00
if ( numhere > 1 & & lev ! = YAX_MAXDRAWS - 1 )
Bmemcpy ( gotsector , lgotsector , ( numsectors + 7 ) > > 3 ) ;
}
2011-04-22 22:48:06 +00:00
2011-05-07 18:23:34 +00:00
if ( numhere = = 0 | | lev = = YAX_MAXDRAWS - 1 )
{
// no new bunches or max level reached
maxlev [ cf ] = lev - ( numhere = = 0 ) ;
break ;
}
2011-04-22 22:48:06 +00:00
}
}
2011-05-15 22:37:24 +00:00
// yax_globalcf = -1;
2011-04-22 22:48:06 +00:00
2011-05-07 18:23:34 +00:00
// now comes the real drawing!
g_nodraw = 0 ;
scansector_collectsprites = 0 ;
2019-03-19 17:07:53 +00:00
# ifdef USE_OPENGL
if ( videoGetRenderMode ( ) = = REND_POLYMOST )
{
2020-01-02 22:56:35 +00:00
GLInterface . ClearScreen ( 0 , true ) ;
2019-10-04 19:13:04 +00:00
yax_polymostclearzbuffer = 0 ;
2019-03-19 17:07:53 +00:00
}
# endif
2011-05-07 18:23:34 +00:00
for ( cf = 0 ; cf < 2 ; cf + + )
{
2011-05-15 22:37:24 +00:00
yax_globalcf = cf ;
2011-05-07 18:23:34 +00:00
for ( lev = maxlev [ cf ] ; lev > = 0 ; lev - - )
2011-04-22 22:48:06 +00:00
{
2011-05-07 18:23:34 +00:00
yax_globallev = YAX_MAXDRAWS + ( - 1 + 2 * cf ) * ( lev + 1 ) ;
2011-05-12 23:31:13 +00:00
scansector_collectsprites = ( lev = = YAX_MAXDRAWS - 1 ) ;
2011-04-22 22:48:06 +00:00
2011-05-07 18:23:34 +00:00
for ( bnchcnt = bnchbeg [ lev ] [ cf ] ; bnchcnt < bnchend [ lev ] [ cf ] ; bnchcnt + + )
{
j = bunches [ cf ] [ bnchcnt ] ; // the actual bunchnum...
2011-05-15 22:37:24 +00:00
k = bunchsec [ j ] ; // best start-drawing sector
yax_globalbunch = j ;
2011-05-12 23:31:13 +00:00
# ifdef YAX_DEBUG
2018-04-12 21:02:51 +00:00
t = timerGetTicksU64 ( ) ;
2011-05-12 23:31:13 +00:00
# endif
2011-05-07 18:23:34 +00:00
yax_tweakpicnums ( j , cf , 0 ) ;
if ( k < 0 )
continue ;
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
yax_nomaskdidit = 0 ;
for ( nmp = r_tror_nomaskpass ; nmp > = 0 ; nmp - - )
{
yax_nomaskpass = nmp ;
2018-04-12 21:03:47 +00:00
renderDrawRoomsQ16 ( globalposx , globalposy , globalposz , qglobalang , horiz , k + MAXSECTORS ) ; // +MAXSECTORS: force
2011-05-07 18:23:34 +00:00
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
if ( nmp = = 1 )
{
2011-09-28 20:30:41 +00:00
yaxdebug ( " nm1 l%d: DRAWN (bn %2d) sec %4d, %.3f ms " ,
yax_globallev - YAX_MAXDRAWS , j , k ,
2018-04-12 21:02:51 +00:00
( double ) ( 1000 * ( timerGetTicksU64 ( ) - t ) ) / u64tickspersec ) ;
2011-09-28 20:30:41 +00:00
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
if ( ! yax_nomaskdidit )
{
yax_nomaskpass = 0 ;
break ; // no need to draw the same stuff twice
}
Bmemcpy ( yax_gotsector , gotsector , ( numsectors + 7 ) > > 3 ) ;
}
}
2011-09-28 20:30:41 +00:00
if ( ! scansector_collectsprites )
spritesortcnt = 0 ;
yax_copytsprites ( ) ;
yaxdebug ( " nm0 l%d: DRAWN (bn %2d) sec %4d,%3d tspr, %.3f ms " ,
yax_globallev - YAX_MAXDRAWS , j , k , spritesortcnt ,
2018-04-12 21:02:51 +00:00
( double ) ( 1000 * ( timerGetTicksU64 ( ) - t ) ) / u64tickspersec ) ;
2011-05-07 18:23:34 +00:00
2019-06-29 17:48:05 +00:00
SpriteAnimFunc ( globalposx , globalposy , globalposz , globalang , smoothr ) ;
2018-04-12 21:03:47 +00:00
renderDrawMasks ( ) ;
2011-05-07 18:23:34 +00:00
}
if ( lev < maxlev [ cf ] )
for ( bnchcnt = bnchbeg [ lev + 1 ] [ cf ] ; bnchcnt < bnchend [ lev + 1 ] [ cf ] ; bnchcnt + + )
yax_tweakpicnums ( bunches [ cf ] [ bnchcnt ] , cf , 1 ) ; // restore picnums
2011-04-22 22:48:06 +00:00
}
}
2011-05-07 18:23:34 +00:00
2011-05-12 23:31:13 +00:00
# ifdef YAX_DEBUG
2018-04-12 21:02:51 +00:00
t = timerGetTicksU64 ( ) ;
2011-05-12 23:31:13 +00:00
# endif
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
yax_globalcf = - 1 ;
2011-05-15 22:37:24 +00:00
yax_globalbunch = - 1 ;
2011-05-07 18:23:34 +00:00
yax_globallev = YAX_MAXDRAWS ;
2011-05-12 23:31:13 +00:00
scansector_collectsprites = 0 ;
2011-05-07 18:23:34 +00:00
// draw base level
2018-04-12 21:03:47 +00:00
renderDrawRoomsQ16 ( globalposx , globalposy , globalposz , qglobalang , horiz ,
2012-07-06 15:36:46 +00:00
osectnum + MAXSECTORS * didmirror ) ;
2011-09-28 20:30:41 +00:00
// if (scansector_collectsprites)
// spritesortcnt = 0;
yax_copytsprites ( ) ;
yaxdebug ( " DRAWN base level sec %d,%3d tspr, %.3f ms " , osectnum ,
2018-04-12 21:02:51 +00:00
spritesortcnt , ( double ) ( 1000 * ( timerGetTicksU64 ( ) - t ) ) / u64tickspersec ) ;
2011-05-07 18:23:34 +00:00
scansector_collectsprites = 1 ;
for ( cf = 0 ; cf < 2 ; cf + + )
if ( maxlev [ cf ] > = 0 )
for ( bnchcnt = bnchbeg [ 0 ] [ cf ] ; bnchcnt < bnchend [ 0 ] [ cf ] ; bnchcnt + + )
yax_tweakpicnums ( bunches [ cf ] [ bnchcnt ] , cf , 1 ) ; // restore picnums
# ifdef ENGINE_SCREENSHOT_DEBUG
engine_screenshot = 0 ;
# endif
2011-05-15 22:37:24 +00:00
2019-03-19 17:07:53 +00:00
# ifdef USE_OPENGL
if ( videoGetRenderMode ( ) = = REND_POLYMOST )
yax_polymostclearzbuffer = 1 ;
# endif
2011-04-22 22:48:06 +00:00
}
2012-03-22 22:46:23 +00:00
# endif // defined YAX_ENABLE
2011-03-02 21:21:47 +00:00
2013-05-01 17:42:05 +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 ;
# ifdef YAX_ENABLE
int16_t cb [ 2 ] , fb [ 2 ] ;
# endif
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
# ifdef YAX_ENABLE
yax_getbunches ( sectnum , & cb [ 0 ] , & fb [ 0 ] ) ;
yax_getbunches ( j , & cb [ 1 ] , & fb [ 1 ] ) ;
2011-04-14 20:48:08 +00:00
2011-06-04 00:06:08 +00:00
if ( ( cb [ 0 ] > = 0 & & cb [ 0 ] = = cb [ 1 ] ) | | ( fb [ 0 ] > = 0 & & fb [ 0 ] = = fb [ 1 ] ) )
2011-04-14 20:48:08 +00:00
{
2011-06-04 00:06:08 +00:00
tmpscore = INT32_MAX ;
2011-04-14 20:48:08 +00:00
}
2011-06-04 00:06:08 +00:00
else
# endif
{
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 )
# ifdef YAX_ENABLE
2011-09-30 13:52:02 +00:00
// for walls with TROR neighbors, be conservative in case if score <=0
// (meaning that no wall area is mutually visible) -- it could be that
// another sector is a better candidate later on
2011-06-04 00:06:08 +00:00
if ( ( yax_getnextwall ( i , 0 ) < 0 & & yax_getnextwall ( i , 1 ) < 0 ) | | bestwallscore > 0 )
# endif
{
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
static int32_t yb1 [ MAXWALLSB ] , xb2 [ MAXWALLSB ] , yb2 [ MAXWALLSB ] ;
int32_t rx1 [ MAXWALLSB ] , ry1 [ MAXWALLSB ] ;
static int32_t rx2 [ MAXWALLSB ] , ry2 [ 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
2009-01-09 09:29:17 +00:00
static int32_t nrx1 [ 8 ] , nry1 [ 8 ] , nrx2 [ 8 ] , nry2 [ 8 ] ; // JBF 20031206: Thanks Ken
2006-04-13 20:47:06 +00:00
2016-06-21 00:33:30 +00:00
int32_t rxi [ 8 ] , ryi [ 8 ] ;
static int32_t rzi [ 8 ] , rxi2 [ 8 ] , ryi2 [ 8 ] , rzi2 [ 8 ] ;
2020-03-29 14:59:49 +00:00
static int32_t xsi [ 8 ] , ysi [ 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 ;
2013-05-15 02:19:14 +00:00
static int32_t globaluclip , globaldclip ;
int32_t globvis , globalvisibility ;
int32_t globalhisibility , globalpisibility , globalcisibility ;
2019-03-19 17:08:39 +00:00
# ifdef USE_OPENGL
int32_t globvis2 , globalvisibility2 , globalhisibility2 , globalpisibility2 , globalcisibility2 ;
# endif
2012-01-26 21:58:08 +00:00
//char globparaceilclip, globparaflorclip;
2006-04-13 20:47:06 +00:00
2012-01-26 21:58:08 +00:00
int32_t xyaspect ;
static 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 ;
static int16_t globalshiftval ;
2013-02-14 16:02:12 +00:00
# ifdef HIGH_PRECISION_SPRITE
static int64_t globalzd ;
# else
static int32_t globalzd ;
# endif
static int32_t globalyscale ;
2011-04-14 20:48:08 +00:00
static int32_t globalxspan , globalyspan , globalispow2 = 1 ; // true if texture has power-of-two x and y size
2012-01-26 21:58:08 +00:00
static intptr_t globalbufplc ;
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
2019-12-26 13:04:53 +00:00
# ifdef GAMENAME
char apptitle [ 256 ] = GAMENAME ;
2019-08-08 01:48:55 +00:00
# else
2006-04-13 20:47:06 +00:00
char apptitle [ 256 ] = " Build Engine " ;
2019-08-08 01:48:55 +00:00
# endif
2011-01-27 06:35:52 +00:00
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 ] ;
2011-05-22 21:52:22 +00:00
# ifdef YAX_ENABLE
if ( g_nodraw = = 0 )
{
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
if ( numyaxbunches = = 0 )
{
2011-05-22 21:52:22 +00:00
# endif
2017-07-08 19:42:11 +00:00
if ( spritesortcnt > = maxspritesonscreen )
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
return 1 ;
2019-12-26 06:27:58 +00:00
renderAddTSpriteFromSprite ( z ) ;
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
2011-05-22 21:52:22 +00:00
# ifdef YAX_ENABLE
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
}
2011-05-22 21:52:22 +00:00
}
else
Support for drawing 'island sectors' for TROR/classic (and with limited
functionality, Polymost).
The new feature can be enabled/disabled with the 'r_tror_nomaskpass' cvar.
The basic idea is that when drawing lower or upper levels, a first pass
is performed that ignores all red walls for which the TROR nextwall link
'towards' the viewer arrives at a red wall. Thus, in the worst case, there
can be up to twice as many rendering passes now (when it is discovered that
the no-mask-pass isn't different that what would be drawn with the ordinary
one, the latter is skipped, since we've already drawn all needed geometry).
Hovever, this kind of multi-pass splitting is only suitable for simple scenes,
like the upper subway in the TROR test map. In particular, multiple islands
shouldn't 'see' each other.
Two issues are worth mentioning: first, care needs to be taken for translucent
ceilings or floors, since drawing them twice isn't the same as drawing them
once. This is done for classic, but not for Polymost. Second, sprites (which
are always drawn _after_ the geometry for a given pass) are still clipped to
the geometry of the ordinary pass, resulting in their disappearance from
certain angles.
--
Additionaly, a change made it into this commit that fixes redundant collection
of sprites in TROR:classic/Polymost.
git-svn-id: https://svn.eduke32.com/eduke32@2024 1a8010ca-5511-0410-912e-c29ae57300e0
2011-09-15 17:04:14 +00:00
if ( yax_nomaskpass = = 0 )
2011-05-22 21:52:22 +00:00
{
2015-07-17 00:12:40 +00:00
int16_t * sortcnt = & yax_spritesortcnt [ yax_globallev ] ;
2017-07-08 19:42:11 +00:00
if ( * sortcnt > = maxspritesonscreen )
2011-12-17 18:51:29 +00:00
return 1 ;
2011-05-22 21:52:22 +00:00
yax_tsprite [ yax_globallev ] [ * sortcnt ] = z ;
2011-09-28 20:30:41 +00:00
if ( yax_globalbunch > = 0 )
{
yax_tsprite [ yax_globallev ] [ * sortcnt ] | = ( MAXSPRITES | ( MAXSPRITES < < 1 ) ) ;
yax_tsprfrombunch [ yax_globallev ] [ * sortcnt ] = yax_globalbunch ;
}
2011-05-22 21:52:22 +00:00
( * sortcnt ) + + ;
// now check whether the tsprite needs duplication into another level
if ( ( spr - > cstat & 48 ) = = 32 )
return 0 ;
2015-07-17 00:12:40 +00:00
int16_t cb , fb ;
2011-05-22 21:52:22 +00:00
yax_getbunches ( sectnum , & cb , & fb ) ;
if ( cb < 0 & & fb < 0 )
return 0 ;
2015-07-17 00:12:40 +00:00
int32_t spheight ;
int16_t spzofs = spriteheightofs ( z , & spheight , 1 ) ;
2011-05-22 21:52:22 +00:00
// TODO: get*zofslope?
if ( cb > = 0 & & spr - > z + spzofs - spheight < sector [ sectnum ] . ceilingz )
{
sortcnt = & yax_spritesortcnt [ yax_globallev - 1 ] ;
2017-07-08 19:42:11 +00:00
if ( * sortcnt < maxspritesonscreen )
2011-05-22 21:52:22 +00:00
{
yax_tsprite [ yax_globallev - 1 ] [ * sortcnt ] = z | MAXSPRITES ;
( * sortcnt ) + + ;
}
}
if ( fb > = 0 & & spr - > z + spzofs > sector [ sectnum ] . floorz )
{
sortcnt = & yax_spritesortcnt [ yax_globallev + 1 ] ;
2017-07-08 19:42:11 +00:00
if ( * sortcnt < maxspritesonscreen )
2011-05-22 21:52:22 +00:00
{
yax_tsprite [ yax_globallev + 1 ] [ * sortcnt ] = z | ( MAXSPRITES < < 1 ) ;
( * sortcnt ) + + ;
}
}
}
# endif
return 0 ;
}
2019-04-18 17:25:38 +00:00
static FORCE_INLINE vec2_t get_rel_coords ( int32_t const x , int32_t const y )
2015-01-04 18:45:00 +00:00
{
2019-04-18 17:25:38 +00:00
return { dmulscale6 ( y , cosglobalang , - x , singlobalang ) ,
dmulscale6 ( x , cosviewingrangeglobalang , y , sinviewingrangeglobalang ) } ;
2015-01-04 18:45:00 +00:00
}
// Note: the returned y coordinates are not actually screen coordinates, but
// potentially clipped player-relative y coordinates.
2018-10-07 05:22:17 +00:00
static int get_screen_coords ( const vec2_t & p1 , const vec2_t & p2 ,
2015-01-04 18:45:00 +00:00
int32_t * sx1ptr , int32_t * sy1ptr ,
int32_t * sx2ptr , int32_t * sy2ptr )
{
int32_t sx1 , sy1 , sx2 , sy2 ;
// First point.
if ( p1 . x > = - p1 . y )
{
if ( p1 . x > p1 . y | | p1 . y = = 0 )
return 0 ;
sx1 = halfxdimen + scale ( p1 . x , halfxdimen , p1 . y )
+ ( p1 . x > = 0 ) ; // Fix for SIGNED divide
if ( sx1 > = xdimen )
sx1 = xdimen - 1 ;
sy1 = p1 . y ;
}
else
{
if ( p2 . x < - p2 . y )
return 0 ;
sx1 = 0 ;
int32_t tempint = ( p1 . x + p1 . y ) - ( p2 . x + p2 . y ) ;
if ( tempint = = 0 )
return 0 ;
sy1 = p1 . y + scale ( p2 . y - p1 . y , p1 . x + p1 . y , tempint ) ;
}
if ( sy1 < 256 )
return 0 ;
// Second point.
if ( p2 . x < = p2 . y )
{
if ( p2 . x < - p2 . y | | p2 . y = = 0 )
return 0 ;
sx2 = halfxdimen + scale ( p2 . x , halfxdimen , p2 . y ) - 1
+ ( p2 . x > = 0 ) ; // Fix for SIGNED divide
if ( sx2 > = xdimen )
sx2 = xdimen - 1 ;
sy2 = p2 . y ;
}
else
{
if ( p1 . x > p1 . y )
return 0 ;
sx2 = xdimen - 1 ;
2018-10-10 19:14:51 +00:00
int32_t const tempint = ( p1 . y - p1 . x ) + ( p2 . x - p2 . y ) ;
2015-01-04 18:45:00 +00:00
sy2 = p1 . y + scale ( p2 . y - p1 . y , p1 . y - p1 . x , tempint ) ;
}
if ( sy2 < 256 | | sx1 > sx2 )
return 0 ;
* sx1ptr = sx1 ; * sy1ptr = sy1 ;
* sx2ptr = sx2 ; * sy2ptr = sy2 ;
return 1 ;
}
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 )
{
globalxshift = ( 8 - ( picsiz [ globalpicnum ] & 15 ) ) ;
globalyshift = ( 8 - ( picsiz [ globalpicnum ] > > 4 ) ) ;
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
}
}
//
// loadtables (internal)
//
2009-02-19 09:39:19 +00:00
static inline void calcbritable ( void )
2006-04-13 20:47:06 +00:00
{
2014-09-30 04:18:43 +00:00
int32_t i , j ;
float a , b ;
2009-02-19 16:47:54 +00:00
for ( i = 0 ; i < 16 ; i + + )
2007-12-12 17:42:14 +00:00
{
2014-09-30 04:18:43 +00:00
a = 8.f / ( ( float ) i + 8.f ) ;
b = 255.f / powf ( 255.f , a ) ;
2009-02-19 16:47:54 +00:00
for ( j = 0 ; j < 256 ; j + + ) // JBF 20040207: full 8bit precision
2014-09-30 04:18:43 +00:00
britable [ i ] [ j ] = ( uint8_t ) ( powf ( ( float ) j , a ) * b ) ;
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 ] ;
2012-09-02 14:08:43 +00:00
calcbritable ( ) ;
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 ;
2012-03-13 20:05:51 +00:00
int32_t deletesprite ( int16_t 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 ;
}
2019-04-05 17:45:19 +00:00
t = tabledivide64 ( t < < 24L , rayLengthSquared ) ;
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
int64_t t = tabledivide64 ( ( ( int64_t ) originDiffCrossLineVec ) < < 24L , rayCrossLineVec ) ;
// 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
Inreased debugging level for catching oob accesses to 'main' arrays.
If enabled, this makes the following arrays be allocated statically:
spriteext, spritesmooth, sector, wall, sprite, tsprite, while
necessarily disabling the clipshape feature (because it relies on
setting sector/wall to different malloc'd block temporarily).
To compile, pass DEBUGANYWAY=1 in addition to RELEASE=0 to 'make',
and it's really only useful with CC=clang, of course.
git-svn-id: https://svn.eduke32.com/eduke32@2270 1a8010ca-5511-0410-912e-c29ae57300e0
2012-01-19 23:17:34 +00:00
# ifdef HAVE_CLIPSHAPE_FEATURE
2018-04-12 21:03:47 +00:00
engineInitClipMaps ( ) ;
Inreased debugging level for catching oob accesses to 'main' arrays.
If enabled, this makes the following arrays be allocated statically:
spriteext, spritesmooth, sector, wall, sprite, tsprite, while
necessarily disabling the clipshape feature (because it relies on
setting sector/wall to different malloc'd block temporarily).
To compile, pass DEBUGANYWAY=1 in addition to RELEASE=0 to 'make',
and it's really only useful with CC=clang, of course.
git-svn-id: https://svn.eduke32.com/eduke32@2270 1a8010ca-5511-0410-912e-c29ae57300e0
2012-01-19 23:17:34 +00:00
# endif
2006-07-24 02:47:47 +00:00
preinitcalled = 1 ;
return 0 ;
2006-07-07 18:41:05 +00:00
}
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 ;
2018-04-12 21:03:12 +00:00
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
if ( ! ( paletteloaded & PALETTE_SHADE ) )
2020-01-25 09:56:30 +00:00
I_FatalError ( " No shade table found. " ) ;
2016-12-26 06:01:32 +00:00
if ( ! ( paletteloaded & PALETTE_TRANSLUC ) )
2020-01-25 09:56:30 +00:00
I_FatalError ( " No translucency table found. " ) ;
2016-12-26 06:01:32 +00:00
2018-04-12 21:03:12 +00:00
palettePostLoadTables ( ) ;
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
void paletteFreeAll ( ) ;
2018-04-12 21:03:47 +00:00
void engineUnInit ( void )
2006-04-13 20:47:06 +00:00
{
2011-03-04 08:50:58 +00:00
# ifdef USE_OPENGL
2006-04-13 20:47:06 +00:00
polymost_glreset ( ) ;
hicinit ( ) ;
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
2006-04-13 20:47:06 +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
2020-04-12 05:44:55 +00:00
paletteFreeAll ( ) ;
2015-09-23 17:55:02 +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
globaluclip = ( 0 - globalhoriz ) * xdimscale ;
globaldclip = ( ydimen - globalhoriz ) * xdimscale ;
i = mulscale16 ( xdimenscale , viewingrangerecip ) ;
globalpisibility = mulscale16 ( parallaxvisibility , i ) ;
2020-03-29 13:54:02 +00:00
globalvisibility = g_visibility * xdimen ;
globalvisibility2 = mulscale16 ( g_visibility , i ) ;
2011-07-24 18:40:10 +00:00
2006-04-13 20:47:06 +00:00
globalhisibility = mulscale16 ( globalvisibility , xyaspect ) ;
globalcisibility = mulscale8 ( globalhisibility , 320 ) ;
2019-03-19 17:08:39 +00:00
# ifdef USE_OPENGL
globalhisibility2 = mulscale16 ( globalvisibility2 , xyaspect ) ;
globalcisibility2 = mulscale8 ( globalhisibility2 , 320 ) ;
# endif
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
# ifdef YAX_ENABLE
| | yax_globallev = = YAX_MAXDRAWS
# endif
)
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
#if 0
2006-08-31 01:56:43 +00:00
// returns the intersection point between two lines
2006-08-29 01:58:59 +00:00
_point2d intersection ( _equation eq1 , _equation eq2 )
{
_point2d ret ;
float det ;
det = ( float ) ( 1 ) / ( eq1 . a * eq2 . b - eq2 . a * eq1 . b ) ;
ret . x = ( ( eq1 . b * eq2 . c - eq2 . b * eq1 . c ) * det ) ;
ret . y = ( ( eq2 . a * eq1 . c - eq1 . a * eq2 . c ) * det ) ;
2016-06-21 00:34:41 +00:00
return ret ;
2006-08-29 01:58:59 +00:00
}
// check if a point that's on the line is within the segment boundaries
2009-01-09 09:29:17 +00:00
int32_t pointonmask ( _point2d point , _maskleaf * wall )
2006-08-29 01:58:59 +00:00
{
if ( ( min ( wall - > p1 . x , wall - > p2 . x ) < = point . x ) & & ( point . x < = max ( wall - > p1 . x , wall - > p2 . x ) ) & & ( min ( wall - > p1 . y , wall - > p2 . y ) < = point . y ) & & ( point . y < = max ( wall - > p1 . y , wall - > p2 . y ) ) )
2016-06-21 00:34:41 +00:00
return 1 ;
return 0 ;
2006-08-29 01:58:59 +00:00
}
// returns 1 if wall2 is hidden by wall1
2009-01-09 09:29:17 +00:00
int32_t wallobstructswall ( _maskleaf * wall1 , _maskleaf * wall2 )
2006-08-29 01:58:59 +00:00
{
_point2d cross ;
cross = intersection ( wall2 - > p1eq , wall1 - > maskeq ) ;
if ( pointonmask ( cross , wall1 ) )
2016-06-21 00:34:41 +00:00
return 1 ;
2006-08-29 01:58:59 +00:00
cross = intersection ( wall2 - > p2eq , wall1 - > maskeq ) ;
if ( pointonmask ( cross , wall1 ) )
2016-06-21 00:34:41 +00:00
return 1 ;
2006-08-29 01:58:59 +00:00
cross = intersection ( wall1 - > p1eq , wall2 - > maskeq ) ;
if ( pointonmask ( cross , wall2 ) )
2016-06-21 00:34:41 +00:00
return 1 ;
2006-08-29 01:58:59 +00:00
cross = intersection ( wall1 - > p2eq , wall2 - > maskeq ) ;
if ( pointonmask ( cross , wall2 ) )
2016-06-21 00:34:41 +00:00
return 1 ;
2006-08-29 01:58:59 +00:00
2016-06-21 00:34:41 +00:00
return 0 ;
2006-08-29 01:58:59 +00:00
}
// recursive mask drawing function
2009-02-19 09:39:19 +00:00
static inline void drawmaskleaf ( _maskleaf * wall )
2006-08-29 01:58:59 +00:00
{
2009-01-09 09:29:17 +00:00
int32_t i ;
2006-08-29 01:58:59 +00:00
wall - > drawing = 1 ;
i = 0 ;
while ( wall - > branch [ i ] ! = NULL )
{
if ( wall - > branch [ i ] - > drawing = = 0 )
{
2020-04-11 21:45:45 +00:00
//Printf("Drawing parent of %i : mask %i\n", wall->index, wall->branch[i]->index);
2006-08-29 01:58:59 +00:00
drawmaskleaf ( wall - > branch [ i ] ) ;
}
i + + ;
}
2020-04-11 21:45:45 +00:00
//Printf("Drawing mask %i\n", wall->index);
2006-08-29 01:58:59 +00:00
drawmaskwall ( wall - > index ) ;
}
2011-05-02 16:58:11 +00:00
# endif
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 )
{
int32_t yoff = picanm [ s - > picnum ] . yofs + s - > yoffset ;
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 ) ;
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 ) ;
2019-10-05 10:28:08 +00:00
GLInterface . SetClamp ( 1 + 2 ) ;
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
int32_t py = spritesxyz [ spritesortcnt ] . y ;
int32_t pcstat = tspriteptr [ spritesortcnt ] - > cstat & 48 ;
int32_t pangle = tspriteptr [ spritesortcnt ] - > ang ;
i = spritesortcnt ;
for ( bssize_t j = spritesortcnt + 1 ; j < = numSprites ; j + + )
2006-04-13 20:47:06 +00:00
{
2019-09-25 20:33:22 +00:00
if ( j < numSprites )
2015-10-21 19:54:14 +00:00
{
2020-02-02 19:00:37 +00:00
if ( py = = spritesxyz [ j ] . y & & pcstat = = ( tspriteptr [ j ] - > cstat & 48 ) & & ( pcstat ! = 16 | | pangle = = tspriteptr [ j ] - > ang )
& & ! polymost_spriteIsModelOrVoxel ( tspriteptr [ j ] ) )
2019-09-25 20:33:22 +00:00
continue ;
py = spritesxyz [ j ] . y ;
pcstat = ( tspriteptr [ j ] - > cstat & 48 ) ;
pangle = tspriteptr [ j ] - > ang ;
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
2019-10-05 10:28:08 +00:00
GLInterface . SetClamp ( 0 ) ;
2019-07-13 21:26:10 +00:00
int32_t numMaskWalls = maskwallcnt ;
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
2019-07-12 08:44:40 +00:00
# ifdef USE_OPENGL
if ( videoGetRenderMode ( ) = = REND_POLYMOST )
2019-10-05 10:28:08 +00:00
GLInterface . SetClamp ( 1 + 2 ) ;
2019-07-12 08:44:40 +00:00
# endif
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 ] ] ) ;
2019-07-12 08:44:40 +00:00
# ifdef USE_OPENGL
if ( videoGetRenderMode ( ) = = REND_POLYMOST )
2019-10-05 10:28:08 +00:00
GLInterface . SetClamp ( 0 ) ;
2019-07-12 08:44:40 +00:00
# endif
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-07-12 08:44:40 +00:00
# ifdef USE_OPENGL
if ( videoGetRenderMode ( ) = = REND_POLYMOST )
2019-10-05 10:28:08 +00:00
GLInterface . SetClamp ( 1 + 2 ) ;
2019-07-12 08:44:40 +00:00
# endif
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
}
# ifdef USE_OPENGL
2018-04-12 21:03:12 +00:00
if ( videoGetRenderMode ( ) = = REND_POLYMOST )
2019-07-12 08:44:40 +00:00
{
2019-10-04 17:17:55 +00:00
GLInterface . SetDepthMask ( true ) ;
2019-10-05 10:28:08 +00:00
GLInterface . SetClamp ( 0 ) ;
2020-02-06 17:43:27 +00:00
GLInterface . SetDepthBias ( 0 , 0 ) ;
2019-07-12 08:44:40 +00:00
}
2015-10-21 19:54:14 +00:00
# endif
2006-12-31 06:32:04 +00:00
}
2006-04-13 20:47:06 +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 ) ;
2019-12-31 18:50:27 +00:00
twod - > 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
{
2012-03-22 22:45:41 +00:00
# ifdef YAX_ENABLE
if ( yax_getbunch ( s , YAX_FLOOR ) > = 0 & & ( sector [ s ] . floorstat & ( 256 + 128 ) ) = = 0 )
continue ;
# endif
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 ) ;
globvis = globalhisibility ;
2012-12-14 19:28:05 +00:00
if ( sec - > visibility ! = 0 ) globvis = mulscale4 ( globvis , ( uint8_t ) ( sec - > visibility + 16 ) ) ;
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
globvis = globalhisibility ;
2012-12-14 19:28:05 +00:00
if ( sec - > visibility ! = 0 ) globvis = mulscale4 ( globvis , ( uint8_t ) ( sec - > visibility + 16 ) ) ;
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 ;
2014-10-25 03:29:21 +00:00
i = ox * ox + oy * oy ; if ( i = = 0 ) continue ; i = tabledivide32_noinline ( 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 ;
2014-10-25 03:29:21 +00:00
i = ox * ox + oy * oy ; if ( i = = 0 ) continue ; i = tabledivide32_noinline ( 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
ox = picsiz [ globalpicnum ] ; oy = ( ( ox > > 4 ) & 15 ) ; ox & = 15 ;
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 ) ) ;
2019-08-01 06:50:42 +00:00
Bmemset ( editwall , 0 , sizeof ( editwall ) ) ;
2019-06-25 11:28:14 +00:00
# ifdef USE_STRUCT_TRACKERS
2015-01-11 04:56:58 +00:00
Bmemset ( sectorchanged , 0 , sizeof ( sectorchanged ) ) ;
Bmemset ( spritechanged , 0 , sizeof ( spritechanged ) ) ;
Bmemset ( wallchanged , 0 , sizeof ( wallchanged ) ) ;
2018-03-17 03:26:01 +00:00
# endif
2012-10-01 17:52:37 +00:00
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 )
2019-09-18 22:19:02 +00:00
{
// If I understand this correctly, both of these essentially do the same thing...
if ( ! playing_rr ) sprite [ i ] . cstat & = ~ 48 ;
else sprite [ i ] . cstat | = 32768 ;
}
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 ) ;
# ifdef HAVE_CLIPSHAPE_FEATURE
if ( ! quickloadboard )
# endif
{
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 ) ;
2011-04-28 21:28:33 +00:00
# ifdef YAX_ENABLE
2013-05-06 19:43:42 +00:00
ok | = ( mapversion = = 9 ) ;
2011-04-28 21:28:33 +00:00
# endif
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 ;
2011-04-09 13:27:08 +00:00
# ifdef YAX_ENABLE
2011-04-28 21:28:33 +00:00
yax_update ( mapversion < 9 ) ;
2011-04-09 13:27:08 +00:00
# endif
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
{
2019-11-01 21:17:15 +00:00
#if 0 // No, no! This is absolutely unacceptable. I won't support mods that require this kind of access.
2013-05-06 19:43:38 +00:00
char fn [ BMAX_PATH ] ;
2013-04-25 17:48:37 +00:00
Bstrcpy ( fn , filename ) ;
2013-05-06 19:43:38 +00:00
append_ext_UNSAFE ( fn , " .cfg " ) ;
2013-04-29 15:13:48 +00:00
OSD_Exec ( fn ) ;
2019-11-01 21:17:15 +00:00
# endif
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
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
2014-10-29 17:04:28 +00:00
# define YSAVES ((xdim*MAXSPRITES)>>7)
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
}
//
// 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 ( ) ;
FStat : : PrintStat ( ) ;
C_DrawConsole ( ) ;
recursion = false ;
}
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
2018-04-06 01:42:47 +00:00
for ( native_t i = 0 ; i < Numsprites ; + + 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 + + ;
}
//
// 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
}
2017-01-23 11:20:03 +00:00
int32_t LUNATIC_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-04-17 13:21:22 +00:00
fix16_t LUNATIC_FASTCALL gethiq16angle ( int32_t xvect , int32_t yvect )
{
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
}
2013-02-16 18:53:15 +00:00
# ifdef LUNATIC
int32_t Mulscale ( int32_t a , int32_t b , int32_t sh )
{
return mulscale ( a , b , sh ) ;
}
# endif
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
2014-09-30 04:14:21 +00:00
hei = ( tilesiz [ picnum ] . y * 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 )
zofs - = picanm [ picnum ] . yofs * 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 ] ;
2011-07-01 17:15:07 +00:00
# ifdef YAX_ENABLE
int16_t pendingsectnum ;
vec3_t pendingvec ;
2013-03-24 18:55:18 +00:00
// Negative sectnums can happen, for example if the player is using noclip.
// MAXSECTORS can happen from C-CON, e.g. canseespr with a sprite not in
// the game world.
if ( ( unsigned ) sect1 > = MAXSECTORS | | ( unsigned ) sect2 > = MAXSECTORS )
2012-02-14 23:13:38 +00:00
return 0 ;
2011-07-01 17:15:07 +00:00
Bmemset ( & pendingvec , 0 , sizeof ( vec3_t ) ) ; // compiler-happy
2011-10-30 19:46:51 +00:00
# endif
2019-09-03 04:09:20 +00:00
Bmemset ( sectbitmap , 0 , sizeof ( sectbitmap ) ) ;
2011-07-01 17:15:07 +00:00
# ifdef YAX_ENABLE
restart_grand :
# endif
2012-11-17 19:46:47 +00:00
if ( x1 = = x2 & & y1 = = y2 )
return ( sect1 = = sect2 ) ;
2006-04-13 20:47:06 +00:00
2011-12-25 15:33:02 +00:00
# ifdef YAX_ENABLE
2011-07-01 17:15:07 +00:00
pendingsectnum = - 1 ;
2011-12-25 15:33:02 +00:00
# endif
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 ;
2011-07-01 17:15:07 +00:00
# ifdef YAX_ENABLE
2012-11-17 19:46:47 +00:00
int32_t cfz1 [ 2 ] , cfz2 [ 2 ] ; // both wrt dasectnum
int16_t bn [ 2 ] ;
2011-07-01 17:15:07 +00:00
yax_getbunches ( dasectnum , & bn [ 0 ] , & bn [ 1 ] ) ;
getzsofslope ( dasectnum , x1 , y1 , & cfz1 [ 0 ] , & cfz1 [ 1 ] ) ;
getzsofslope ( dasectnum , x2 , y2 , & cfz2 [ 0 ] , & cfz2 [ 1 ] ) ;
# endif
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 )
{
2011-12-25 15:33:02 +00:00
# ifdef YAX_ENABLE
2011-07-01 17:15:07 +00:00
if ( t > = bot )
{
int32_t cf , frac , ns ;
for ( cf = 0 ; cf < 2 ; cf + + )
{
if ( ( cf = = 0 & & bn [ 0 ] > = 0 & & z1 > cfz1 [ 0 ] & & cfz2 [ 0 ] > z2 ) | |
( cf = = 1 & & bn [ 1 ] > = 0 & & z1 < cfz1 [ 1 ] & & cfz2 [ 1 ] < z2 ) )
{
if ( ( cfz1 [ cf ] - cfz2 [ cf ] ) - ( z1 - z2 ) = = 0 )
continue ;
frac = divscale24 ( z1 - cfz1 [ cf ] , ( z1 - z2 ) - ( cfz1 [ cf ] - cfz2 [ cf ] ) ) ;
if ( ( unsigned ) frac > = ( 1 < < 24 ) )
continue ;
x = x1 + mulscale24 ( x21 , frac ) ;
y = y1 + mulscale24 ( y21 , frac ) ;
2012-10-01 17:52:18 +00:00
ns = yax_getneighborsect ( x , y , dasectnum , cf ) ;
2011-07-01 17:15:07 +00:00
if ( ns < 0 )
continue ;
2019-08-04 02:51:50 +00:00
if ( ! ( sectbitmap [ ns > > 3 ] & pow2char [ ns & 7 ] ) & & pendingsectnum = = - 1 )
2011-07-01 17:15:07 +00:00
{
2019-08-04 02:51:50 +00:00
sectbitmap [ ns > > 3 ] | = pow2char [ ns & 7 ] ;
2011-07-01 17:15:07 +00:00
pendingsectnum = ns ;
pendingvec . x = x ;
pendingvec . y = y ;
pendingvec . z = z1 + mulscale24 ( z21 , frac ) ;
}
}
}
}
# endif
continue ;
}
2006-04-13 20:47:06 +00:00
nexts = wal - > nextsector ;
2011-07-01 17:15:07 +00:00
# ifdef YAX_ENABLE
if ( bn [ 0 ] < 0 & & bn [ 1 ] < 0 )
# endif
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
{
# ifdef YAX_ENABLE
int32_t cf , frac ;
// XXX: Is this any good?
for ( cf = 0 ; cf < 2 ; cf + + )
if ( ( cf = = 0 & & bn [ 0 ] > = 0 & & z < = cfz [ 0 ] & & z1 > = cfz1 [ 0 ] ) | |
( cf = = 1 & & bn [ 1 ] > = 0 & & z > = cfz [ 1 ] & & z1 < = cfz1 [ 1 ] ) )
{
if ( ( cfz1 [ cf ] - cfz [ cf ] ) - ( z1 - z ) = = 0 )
continue ;
2006-04-13 20:47:06 +00:00
2011-07-01 17:15:07 +00:00
frac = divscale24 ( z1 - cfz1 [ cf ] , ( z1 - z ) - ( cfz1 [ cf ] - cfz [ cf ] ) ) ;
t = mulscale24 ( t , frac ) ;
if ( ( unsigned ) t < ( 1 < < 24 ) )
{
x = x1 + mulscale24 ( x21 , t ) ;
y = y1 + mulscale24 ( y21 , t ) ;
2012-10-01 17:52:18 +00:00
nexts = yax_getneighborsect ( x , y , dasectnum , cf ) ;
2011-07-01 17:15:07 +00:00
if ( nexts > = 0 )
goto add_nextsector ;
}
}
2016-06-05 04:46:28 +00:00
2011-07-01 17:15:07 +00:00
# endif
2013-04-15 10:48:09 +00:00
return 0 ;
2011-07-01 17:15:07 +00:00
}
# ifdef YAX_ENABLE
2013-04-15 10:48:09 +00:00
if ( nexts < 0 | | ( wal - > cstat & 32 ) )
2011-07-01 17:15:07 +00:00
return 0 ;
# endif
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
add_nextsector :
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 ;
}
}
# ifdef YAX_ENABLE
if ( pendingsectnum > = 0 )
{
sect1 = pendingsectnum ;
x1 = pendingvec . x ;
y1 = pendingvec . y ;
z1 = pendingvec . z ;
goto restart_grand ;
2006-04-13 20:47:06 +00:00
}
2011-07-01 17:15:07 +00:00
# endif
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 )
{
2012-11-17 19:46:47 +00:00
int32_t j , tmpcf ;
2011-04-14 20:48:08 +00:00
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
for ( YAX_ITER_WALLS ( w , j , tmpcf ) )
{
2019-08-04 02:51:50 +00:00
if ( ( walbitmap [ j > > 3 ] & pow2char [ j & 7 ] ) = = 0 )
2011-04-14 20:48:08 +00:00
{
2019-08-04 02:51:50 +00:00
walbitmap [ j > > 3 ] | = pow2char [ j & 7 ] ;
2011-04-14 20:48:08 +00:00
yaxwalls [ numyaxwalls + + ] = j ;
}
}
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
}
}
if ( editstatus )
{
2012-11-17 19:46:47 +00:00
int32_t w ;
// TODO: extern a separate bitmap instead?
2011-04-14 20:48:08 +00:00
for ( w = 0 ; w < numwalls ; w + + )
2019-08-04 02:51:50 +00:00
if ( walbitmap [ w > > 3 ] & pow2char [ w & 7 ] )
2013-01-16 20:38:41 +00:00
{
2019-08-01 06:50:42 +00:00
editwall [ w > > 3 ] | = 1 < < ( w & 7 ) ;
2013-01-16 20:38:41 +00:00
if ( flags & 2 )
2019-08-01 06:50:42 +00:00
{
int wn = lastwall ( w ) ;
editwall [ wn > > 3 ] | = 1 < < ( wn & 7 ) ;
}
2013-01-16 20:38:41 +00:00
}
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)
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 ) ;
# ifdef YAX_ENABLE
if ( z < cz )
{
int const next = yax_getneighborsect ( x , y , * sectnum , YAX_CEILING ) ;
if ( next > = 0 & & z > = getceilzofslope ( next , x , y ) )
SET_AND_RETURN ( * sectnum , next ) ;
}
if ( z > fz )
{
int const next = yax_getneighborsect ( x , y , * sectnum , YAX_FLOOR ) ;
if ( next > = 0 & & z < = getflorzofslope ( next , x , y ) )
SET_AND_RETURN ( * sectnum , next ) ;
}
# endif
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
# ifdef YAX_ENABLE
2019-04-18 17:25:11 +00:00
if ( z < cz )
{
int const next = yax_getneighborsect ( x , y , correctedsectnum , YAX_CEILING ) ;
if ( next > = 0 & & z > = getceilzofslope ( next , x , y ) )
SET_AND_RETURN ( * sectnum , next ) ;
}
2019-04-06 06:38:00 +00:00
2019-04-18 17:25:11 +00:00
if ( z > fz )
{
int const next = yax_getneighborsect ( x , y , correctedsectnum , YAX_FLOOR ) ;
if ( next > = 0 & & z < = getflorzofslope ( next , x , y ) )
SET_AND_RETURN ( * sectnum , next ) ;
}
2019-04-06 06:38:00 +00:00
# endif
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
{
2018-04-12 21:03:12 +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
//
// rotatesprite
//
2013-03-25 04:32:24 +00:00
void rotatesprite_ ( int32_t sx , int32_t sy , int32_t z , int16_t a , int16_t picnum ,
2019-09-22 21:15:46 +00:00
int8_t dashade , uint8_t dapalnum , int32_t dastat , uint8_t daalpha , uint8_t dablend ,
2020-05-23 12:36:35 +00:00
int32_t cx1 , int32_t cy1 , int32_t cx2 , int32_t cy2 , FTexture * tex , int basepal )
2006-04-13 20:47:06 +00:00
{
2020-04-12 05:46:53 +00:00
if ( ! tex & & ( unsigned ) picnum > = MAXTILES )
2012-03-25 22:01:21 +00:00
return ;
2006-04-13 20:47:06 +00:00
if ( ( cx1 > cx2 ) | | ( cy1 > cy2 ) ) return ;
if ( z < = 16 ) return ;
2019-12-29 14:46:48 +00:00
if ( r_rotatespritenowidescreen )
2007-12-12 17:42:14 +00:00
{
2019-12-29 14:46:48 +00:00
dastat | = RS_STRETCH ;
dastat & = ~ RS_ALIGN_MASK ;
2006-04-13 20:47:06 +00:00
}
2020-04-12 05:46:53 +00:00
if ( ! tex )
2019-12-30 11:23:26 +00:00
{
2020-04-12 05:46:53 +00:00
tileUpdatePicnum ( & picnum , ( int16_t ) 0xc000 ) ;
if ( ( tilesiz [ picnum ] . x < = 0 ) | | ( tilesiz [ picnum ] . y < = 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 ;
}
2019-12-30 11:23:26 +00:00
}
2020-04-12 05:46:53 +00:00
2019-12-29 14:46:48 +00:00
// We must store all calls in the 2D drawer so that the backend can operate on a clean 3D view.
2020-05-23 12:36:35 +00:00
twod - > rotatesprite ( sx , sy , z , a , picnum , dashade , dapalnum , dastat , daalpha , dablend , cx1 , cy1 , cx2 , cy2 , tex , basepal ) ;
2006-04-13 20:47:06 +00:00
2019-12-29 14:46:48 +00:00
// RS_PERM code was removed because the current backend supports only one page that needs to be redrawn each frame in which case the perm list was skipped anyway.
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
//
2018-04-12 21:03:47 +00:00
void renderSetTarget ( int16_t tilenume , int32_t xsiz , int32_t ysiz )
2006-04-13 20:47:06 +00:00
{
2020-03-29 12:01:46 +00:00
if ( setviewcnt > 0 )
2019-04-18 17:24:37 +00:00
return ;
2019-08-07 16:18:57 +00:00
if ( xsiz < = 0 | |
ysiz < = 0 )
return ;
2019-04-18 17:24:37 +00:00
2020-03-29 12:01:46 +00:00
OpenGLRenderer : : GLRenderer - > StartOffscreen ( ) ;
OpenGLRenderer : : GLRenderer - > BindToFrameBuffer ( TileFiles . tiles [ tilenume ] ) ;
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-03-29 12:01:46 +00:00
xdim = ysiz * 4 ;
ydim = xsiz * 4 ;
videoSetViewableArea ( 0 , 0 , ysiz * 4 - 1 , xsiz * 4 - 1 ) ;
2018-04-12 21:03:47 +00:00
renderSetAspect ( 65536 , 65536 ) ;
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
OpenGLRenderer : : GLRenderer - > EndOffscreen ( ) ;
2006-04-13 20:47:06 +00:00
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
}
2018-04-02 22:00:23 +00:00
int32_t sectorofwall_noquick ( 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 ;
2011-02-10 23:15:02 +00:00
2018-04-02 22:00:23 +00:00
return 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
}
2019-09-17 03:20:38 +00:00
# ifdef YAX_ENABLE
void yax_getzsofslope ( int sectNum , int playerX , int playerY , int32_t * pCeilZ , int32_t * pFloorZ )
{
int didCeiling = 0 ;
int didFloor = 0 ;
int testSector = 0 ;
if ( ( sector [ sectNum ] . ceilingstat & 512 ) = = 0 )
{
testSector = yax_getneighborsect ( playerX , playerY , sectNum , YAX_CEILING ) ;
if ( testSector > = 0 )
{
ceiling :
* pCeilZ = getcorrectceilzofslope ( testSector , playerX , playerY ) ;
didCeiling = 1 ;
}
}
if ( ( sector [ sectNum ] . floorstat & 512 ) = = 0 )
{
testSector = yax_getneighborsect ( playerX , playerY , sectNum , YAX_FLOOR ) ;
if ( testSector > = 0 )
{
floor :
* pFloorZ = getcorrectflorzofslope ( testSector , playerX , playerY ) ;
didFloor = 1 ;
}
}
testSector = sectNum ;
if ( ! didCeiling )
goto ceiling ;
else if ( ! didFloor )
goto floor ;
}
2020-05-13 23:55:58 +00:00
int32_t yax_getceilzofslope ( int const sectnum , vec2_t const vect )
{
if ( ( sector [ sectnum ] . ceilingstat & 512 ) = = 0 )
{
int const nsect = yax_getneighborsect ( vect . x , vect . y , sectnum , YAX_CEILING ) ;
if ( nsect > = 0 )
return getcorrectceilzofslope ( nsect , vect . x , vect . y ) ;
}
return getcorrectceilzofslope ( sectnum , vect . x , vect . y ) ;
}
int32_t yax_getflorzofslope ( int const sectnum , vec2_t const vect )
{
if ( ( sector [ sectnum ] . floorstat & 512 ) = = 0 )
{
int const nsect = yax_getneighborsect ( vect . x , vect . y , sectnum , YAX_FLOOR ) ;
if ( nsect > = 0 )
return getcorrectflorzofslope ( nsect , vect . x , vect . y ) ;
}
return getcorrectflorzofslope ( sectnum , vect . x , vect . y ) ;
}
2019-09-17 03:20:38 +00:00
# endif
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 ;
}
//
// loopnumofsector
//
2009-01-09 09:29:17 +00:00
int32_t loopnumofsector ( int16_t sectnum , int16_t wallnum )
2006-04-13 20:47:06 +00:00
{
2013-04-12 11:59:26 +00:00
int32_t numloops = 0 ;
const int32_t startwall = sector [ sectnum ] . wallptr ;
const int32_t endwall = startwall + sector [ sectnum ] . wallnum ;
2006-04-13 20:47:06 +00:00
2016-08-27 01:41:21 +00:00
for ( bssize_t i = startwall ; i < endwall ; i + + )
2006-04-13 20:47:06 +00:00
{
2013-04-12 11:59:26 +00:00
if ( i = = wallnum )
return numloops ;
if ( wall [ i ] . point2 < i )
numloops + + ;
2006-04-13 20:47:06 +00:00
}
2013-04-12 11:59:26 +00:00
return - 1 ;
2006-04-13 20:47:06 +00:00
}
//
// setfirstwall
//
2009-01-09 09:29:17 +00:00
void setfirstwall ( int16_t sectnum , int16_t newfirstwall )
2006-04-13 20:47:06 +00:00
{
2013-04-12 11:59:26 +00:00
int32_t i , j , numwallsofloop ;
int32_t dagoalloop ;
2016-06-21 00:33:58 +00:00
uwalltype * tmpwall ;
2006-04-13 20:47:06 +00:00
2013-04-12 11:59:26 +00:00
const int32_t startwall = sector [ sectnum ] . wallptr ;
const int32_t danumwalls = sector [ sectnum ] . wallnum ;
const int32_t endwall = startwall + danumwalls ;
2010-09-30 23:05:40 +00:00
2013-04-12 11:59:26 +00:00
if ( newfirstwall < startwall | | newfirstwall > = startwall + danumwalls )
return ;
2010-09-30 23:05:40 +00:00
2016-06-21 00:33:58 +00:00
tmpwall = ( uwalltype * ) Xmalloc ( danumwalls * sizeof ( walltype ) ) ;
2010-09-30 23:05:40 +00:00
Bmemcpy ( tmpwall , & wall [ startwall ] , danumwalls * sizeof ( walltype ) ) ;
2006-04-13 20:47:06 +00:00
numwallsofloop = 0 ;
i = newfirstwall ;
do
{
numwallsofloop + + ;
i = wall [ i ] . point2 ;
2007-12-12 17:42:14 +00:00
}
while ( i ! = newfirstwall ) ;
2006-04-13 20:47:06 +00:00
2006-04-24 19:04:22 +00:00
//Put correct loop at beginning
2006-04-13 20:47:06 +00:00
dagoalloop = loopnumofsector ( sectnum , newfirstwall ) ;
if ( dagoalloop > 0 )
{
j = 0 ;
2011-09-30 13:52:02 +00:00
while ( loopnumofsector ( sectnum , j + startwall ) ! = dagoalloop )
j + + ;
2009-02-19 16:47:54 +00:00
for ( i = 0 ; i < danumwalls ; i + + )
2006-04-13 20:47:06 +00:00
{
2013-04-12 11:59:26 +00:00
int32_t k = i + j ;
if ( k > = danumwalls ) k - = danumwalls ;
2010-09-30 23:05:40 +00:00
Bmemcpy ( & wall [ startwall + i ] , & tmpwall [ k ] , sizeof ( walltype ) ) ;
2006-04-13 20:47:06 +00:00
wall [ startwall + i ] . point2 + = danumwalls - startwall - j ;
if ( wall [ startwall + i ] . point2 > = danumwalls )
wall [ startwall + i ] . point2 - = danumwalls ;
wall [ startwall + i ] . point2 + = startwall ;
}
2011-09-30 13:52:02 +00:00
2006-04-13 20:47:06 +00:00
newfirstwall + = danumwalls - j ;
2011-09-30 13:52:02 +00:00
if ( newfirstwall > = startwall + danumwalls )
newfirstwall - = danumwalls ;
2006-04-13 20:47:06 +00:00
}
2009-02-19 16:47:54 +00:00
for ( i = 0 ; i < numwallsofloop ; i + + )
2010-09-30 23:05:40 +00:00
Bmemcpy ( & tmpwall [ i ] , & wall [ i + startwall ] , sizeof ( walltype ) ) ;
2009-02-19 16:47:54 +00:00
for ( i = 0 ; i < numwallsofloop ; i + + )
2006-04-13 20:47:06 +00:00
{
2013-04-12 11:59:26 +00:00
int32_t k = i + newfirstwall - startwall ;
2006-04-13 20:47:06 +00:00
if ( k > = numwallsofloop ) k - = numwallsofloop ;
2010-09-30 23:05:40 +00:00
Bmemcpy ( & wall [ startwall + i ] , & tmpwall [ k ] , sizeof ( walltype ) ) ;
2006-04-13 20:47:06 +00:00
wall [ startwall + i ] . point2 + = numwallsofloop - newfirstwall ;
if ( wall [ startwall + i ] . point2 > = numwallsofloop )
wall [ startwall + i ] . point2 - = numwallsofloop ;
wall [ startwall + i ] . point2 + = startwall ;
}
2009-02-19 16:47:54 +00:00
for ( i = startwall ; i < endwall ; i + + )
2011-09-30 13:52:02 +00:00
if ( wall [ i ] . nextwall > = 0 )
wall [ wall [ i ] . nextwall ] . nextwall = i ;
2011-04-11 22:28:58 +00:00
# ifdef YAX_ENABLE
2016-06-21 00:34:18 +00:00
int16_t cb , fb ;
yax_getbunches ( sectnum , & cb , & fb ) ;
2011-04-11 22:28:58 +00:00
2016-06-21 00:34:18 +00:00
if ( cb > = 0 | | fb > = 0 )
{
for ( i = startwall ; i < endwall ; i + + )
2011-04-11 22:28:58 +00:00
{
2016-06-21 00:34:18 +00:00
j = yax_getnextwall ( i , YAX_CEILING ) ;
if ( j > = 0 )
yax_setnextwall ( j , YAX_FLOOR , i ) ;
2011-04-11 22:28:58 +00:00
2016-06-21 00:34:18 +00:00
j = yax_getnextwall ( i , YAX_FLOOR ) ;
if ( j > = 0 )
yax_setnextwall ( j , YAX_CEILING , i ) ;
2011-04-11 22:28:58 +00:00
}
}
# endif
2010-09-30 23:05:40 +00:00
2019-06-25 11:29:08 +00:00
Xfree ( tmpwall ) ;
2006-04-13 20:47:06 +00:00
}
2006-04-24 19:04:22 +00:00
2006-04-13 20:47:06 +00:00
//
// 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