Merge commit 'fd0e9824b60a8cae288102551f0f3134a221cf3c' into whaven

# Conflicts:
#	source/build/include/build.h
#	source/build/src/engine.cpp
#	source/build/src/engine_priv.h
This commit is contained in:
Christoph Oelckers 2021-03-26 15:35:19 +01:00
commit 3e17f3cb97
59 changed files with 1478 additions and 1635 deletions

View file

@ -48,11 +48,6 @@ enum
MAXVOXMIPS = 5,
MAXXDIM = 7680,
MAXYDIM = 3200,
MINXDIM = 640,
MINYDIM = 480,
MAXWALLSB = ((MAXWALLS >> 2) + (MAXWALLS >> 3)),
MAXVOXELS = 1024,
@ -101,24 +96,11 @@ enum {
};
enum {
SPR_XFLIP = 4,
SPR_YFLIP = 8,
SPR_WALL = 16,
SPR_FLOOR = 32,
SPR_ALIGN_MASK = 32+16,
};
#include "buildtypes.h"
using usectortype = sectortype;
using uwalltype = walltype;
using uspritetype = spritetype;
using uspriteptr_t = uspritetype const *;
using uwallptr_t = uwalltype const *;
using usectorptr_t = usectortype const *;
using uspriteptr_t = spritetype const *;
using uwallptr_t = walltype const *;
using usectorptr_t = sectortype const *;
using tspriteptr_t = tspritetype *;
@ -151,17 +133,11 @@ typedef struct {
#define SPREXT_TSPRACCESS 16
#define SPREXT_TEMPINVISIBLE 32
#define NEG_ALPHA_TO_BLEND(alpha, blend, orientation) do { \
if ((alpha) < 0) { (blend) = -(alpha); (alpha) = 0; (orientation) |= RS_TRANS1; } \
} while (0)
// using the clipdist field
enum
{
TSPR_FLAGS_MDHACK = 1u<<0u,
TSPR_FLAGS_DRAW_LAST = 1u<<1u,
TSPR_FLAGS_NO_SHADOW = 1u<<2u,
TSPR_FLAGS_INVISIBLE_WITH_SHADOW = 1u<<3u,
};
EXTERN int32_t guniqhudid;
@ -177,57 +153,44 @@ struct usermaphack_t
EXTERN spriteext_t *spriteext;
EXTERN spritesmooth_t *spritesmooth;
// Wrapper that makes an array of pointers look like an array of references. (Refactoring helper.)
template<class T, int size>
class ReferenceArray
{
T* data[size];
public:
T& operator[](size_t index)
{
assert(index < size);
return *data[index];
}
void set(int pos, T* spr)
{
data[pos] = spr;
}
};
EXTERN sectortype *sector;
EXTERN walltype *wall;
EXTERN spritetype *sprite;
EXTERN tspriteptr_t tsprite;
EXTERN int leveltimer;
extern sectortype sectorbackup[MAXSECTORS];
extern walltype wallbackup[MAXWALLS];
extern bool inpreparemirror;
static inline tspriteptr_t renderMakeTSpriteFromSprite(tspriteptr_t const tspr, uint16_t const spritenum)
inline tspriteptr_t renderAddNewTSprite()
{
auto const spr = &sprite[spritenum];
*tspr = *spr;
tspr->clipdist = 0;
tspr->owner = spritenum;
auto tspr = &tsprite[spritesortcnt++];
*tspr = {};
return tspr;
}
static inline tspriteptr_t renderAddTSpriteFromSprite(uint16_t const spritenum)
inline tspriteptr_t renderAddTSpriteFromSprite(uint16_t const spritenum)
{
return renderMakeTSpriteFromSprite(&tsprite[spritesortcnt++], spritenum);
auto tspr = &tsprite[spritesortcnt++];
auto const spr = &sprite[spritenum];
*tspr = *spr;
tspr->clipdist = 0;
tspr->owner = spritenum;
return tspr;
}
// returns: 0=continue sprite collecting;
// 1=break out of sprite collecting;
inline int32_t renderAddTsprite(int16_t z, int16_t sectnum)
{
if (spritesortcnt >= MAXSPRITESONSCREEN) return 1;
renderAddTSpriteFromSprite(z);
return 0;
}
EXTERN int16_t maskwall[MAXWALLSB], maskwallcnt;
EXTERN int16_t thewall[MAXWALLSB];
EXTERN tspriteptr_t tspriteptr[MAXSPRITESONSCREEN + 1];
EXTERN int32_t xdim, ydim;
EXTERN int32_t yxaspect, viewingrange;
@ -238,19 +201,8 @@ EXTERN int32_t display_mirror;
EXTERN int32_t randomseed;
EXTERN int16_t numshades;
EXTERN uint8_t paletteloaded;
// Return type is int because this gets passed to variadic functions where structs may produce undefined behavior.
inline int shadeToLight(int shade)
{
shade = clamp(shade, 0, numshades-1);
int light = Scale(numshades-1-shade, 255, numshades-1);
return PalEntry(255,light,light,light);
}
EXTERN int32_t maxspritesonscreen;
enum {
PALETTE_MAIN = 1<<0,
PALETTE_SHADE = 1<<1,
@ -385,22 +337,8 @@ SPRITE VARIABLES:
be in some sector, and must have some kind of status that you define.
TILE VARIABLES:
NUMTILES - the number of tiles found TILES.DAT.
TIMING VARIABLES:
NUMFRAMES - The number of times the draw3dscreen function was called
since the engine was initialized. This helps to determine frame
rate. (Frame rate = numframes * 120 / I_GetBuildTime().)
OTHER VARIABLES:
STARTUMOST[320] is an array of the highest y-coordinates on each column
that my engine is allowed to write to. You need to set it only
once.
STARTDMOST[320] is an array of the lowest y-coordinates on each column
that my engine is allowed to write to. You need to set it only
once.
SINTABLE[2048] is a sin table with 2048 angles rather than the
normal 360 angles for higher precision. Also since SINTABLE is in
all integers, the range is multiplied by 16383, so instead of the
@ -444,34 +382,14 @@ void renderSetAspect(int32_t daxrange, int32_t daaspect);
void plotpixel(int32_t x, int32_t y, char col);
FCanvasTexture *renderSetTarget(int16_t tilenume);
void renderRestoreTarget();
void renderPrepareMirror(int32_t dax, int32_t day, int32_t daz, fixed_t daang, fixed_t dahoriz, int16_t dawall,
int32_t *tposx, int32_t *tposy, fixed_t *tang);
void renderCompleteMirror(void);
int32_t renderDrawRoomsQ16(int32_t daposx, int32_t daposy, int32_t daposz, fixed_t daang, fixed_t dahoriz, int16_t dacursectnum);
void renderDrawMasks(void);
void setVideoMode();
void videoInit();
void videoClearViewableArea(int32_t dacol);
void videoClearScreen(int32_t dacol);
void renderDrawMapView(int32_t dax, int32_t day, int32_t zoome, int16_t ang);
void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FGameTexture *pic = nullptr, int basepal = 0);
class F2DDrawer;
void twod_rotatesprite(F2DDrawer* twod, int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t clipx1, int32_t clipy1, int32_t clipx2, int32_t clipy2, FGameTexture* pic = nullptr, int basepal = 0);
////////// specialized rotatesprite wrappers for (very) often used cases //////////
static FORCE_INLINE void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FGameTexture* pic = nullptr, int basepal = 0)
{
rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, cx1, cy1, cx2, cy2, pic, basepal);
}
void getzrange(const vec3_t *pos, int16_t sectnum, int32_t *ceilz, int32_t *ceilhit, int32_t *florz,
int32_t *florhit, int32_t walldist, uint32_t cliptype) ATTRIBUTE((nonnull(1,3,4,5,6)));
@ -519,13 +437,12 @@ void updatesectorneighbor(int32_t const x, int32_t const y, int16_t * const sect
void updatesectorneighborz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum, int32_t initialMaxDistance = INITIALUPDATESECTORDIST, int32_t maxDistance = MAXUPDATESECTORDIST) ATTRIBUTE((nonnull(4)));
int findwallbetweensectors(int sect1, int sect2);
static FORCE_INLINE int sectoradjacent(int sect1, int sect2) { return findwallbetweensectors(sect1, sect2) != -1; }
inline int sectoradjacent(int sect1, int sect2) { return findwallbetweensectors(sect1, sect2) != -1; }
int32_t getsectordist(vec2_t const in, int const sectnum, vec2_t * const out = nullptr);
extern const int16_t *chsecptr_onextwall;
int32_t checksectorpointer(int16_t i, int16_t sectnum);
#if !KRANDDEBUG
static FORCE_INLINE int32_t krand(void)
inline int32_t krand(void)
{
randomseed = (randomseed * 1664525ul) + 221297ul;
return ((uint32_t) randomseed)>>16;
@ -542,12 +459,12 @@ inline int32_t ksqrt(uint32_t num)
int32_t getangle(int32_t xvect, int32_t yvect);
fixed_t gethiq16angle(int32_t xvect, int32_t yvect);
static FORCE_INLINE constexpr uint32_t uhypsq(int32_t const dx, int32_t const dy)
inline constexpr uint32_t uhypsq(int32_t const dx, int32_t const dy)
{
return (uint32_t)dx*dx + (uint32_t)dy*dy;
}
static FORCE_INLINE int32_t logapproach(int32_t const val, int32_t const targetval)
inline int32_t logapproach(int32_t const val, int32_t const targetval)
{
int32_t const dif = targetval - val;
return (dif>>1) ? val + (dif>>1) : targetval;
@ -576,36 +493,36 @@ void yax_getzsofslope(int sectNum, int playerX, int playerY, int32_t* pCeilZ, in
int32_t yax_getceilzofslope(int const sectnum, vec2_t const vect);
int32_t yax_getflorzofslope(int const sectnum, vec2_t const vect);
static FORCE_INLINE int32_t getceilzofslope(int16_t sectnum, int32_t dax, int32_t day)
inline int32_t getceilzofslope(int16_t sectnum, int32_t dax, int32_t day)
{
return getceilzofslopeptr((usectorptr_t)&sector[sectnum], dax, day);
}
static FORCE_INLINE int32_t getflorzofslope(int16_t sectnum, int32_t dax, int32_t day)
inline int32_t getflorzofslope(int16_t sectnum, int32_t dax, int32_t day)
{
return getflorzofslopeptr((usectorptr_t)&sector[sectnum], dax, day);
}
static FORCE_INLINE void getzsofslope(int16_t sectnum, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz)
inline void getzsofslope(int16_t sectnum, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz)
{
getzsofslopeptr((usectorptr_t)&sector[sectnum], dax, day, ceilz, florz);
}
static FORCE_INLINE void getcorrectzsofslope(int16_t sectnum, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz)
inline void getcorrectzsofslope(int16_t sectnum, int32_t dax, int32_t day, int32_t *ceilz, int32_t *florz)
{
vec2_t closest = { dax, day };
getsectordist(closest, sectnum, &closest);
getzsofslopeptr((usectorptr_t)&sector[sectnum], closest.x, closest.y, ceilz, florz);
}
static FORCE_INLINE int32_t getcorrectceilzofslope(int16_t sectnum, int32_t dax, int32_t day)
inline int32_t getcorrectceilzofslope(int16_t sectnum, int32_t dax, int32_t day)
{
vec2_t closest = { dax, day };
getsectordist(closest, sectnum, &closest);
return getceilzofslopeptr((usectorptr_t)&sector[sectnum], closest.x, closest.y);
}
static FORCE_INLINE int32_t getcorrectflorzofslope(int16_t sectnum, int32_t dax, int32_t day)
inline int32_t getcorrectflorzofslope(int16_t sectnum, int32_t dax, int32_t day)
{
vec2_t closest = { dax, day };
getsectordist(closest, sectnum, &closest);
@ -614,12 +531,12 @@ static FORCE_INLINE int32_t getcorrectflorzofslope(int16_t sectnum, int32_t dax,
// Is <wal> a red wall in a safe fashion, i.e. only if consistency invariant
// ".nextsector >= 0 iff .nextwall >= 0" holds.
static FORCE_INLINE int32_t redwallp(uwallptr_t wal)
inline int32_t redwallp(uwallptr_t wal)
{
return (wal->nextwall >= 0 && wal->nextsector >= 0);
}
static FORCE_INLINE int32_t E_SpriteIsValid(const int32_t i)
inline int32_t E_SpriteIsValid(const int32_t i)
{
return ((unsigned)i < MAXSPRITES && sprite[i].statnum != MAXSTATUS);
}
@ -662,23 +579,13 @@ inline void setspritepos(int spnum, int x, int y, int z)
int32_t setspritez(int16_t spritenum, const vec3_t *) ATTRIBUTE((nonnull(2)));
int32_t spriteheightofsptr(uspriteptr_t spr, int32_t *height, int32_t alsotileyofs);
static FORCE_INLINE int32_t spriteheightofs(int16_t i, int32_t *height, int32_t alsotileyofs)
inline int32_t spriteheightofs(int16_t i, int32_t *height, int32_t alsotileyofs)
{
return spriteheightofsptr((uspriteptr_t)&sprite[i], height, alsotileyofs);
}
int videoCaptureScreen();
// PLAG: line utility functions
typedef struct s_equation
{
float a, b, c;
} _equation;
#ifdef USE_OPENGL
void renderSetRollAngle(float rolla);
#endif
void PrecacheHardwareTextures(int nTile);
void Polymost_Startup();
@ -721,7 +628,7 @@ typedef struct
int16_t framenum; // calculate the number from the name when declaring
int16_t nexttile;
uint16_t smoothduration;
hudtyp *hudmem[2];
hudtyp hudmem[2];
int8_t skinnum;
char pal;
} tile2model_t;
@ -731,13 +638,13 @@ typedef struct
EXTERN int32_t mdinited;
EXTERN tile2model_t tile2model[MAXTILES+EXTRATILES];
static FORCE_INLINE int32_t md_tilehasmodel(int32_t const tilenume, int32_t const pal)
inline int32_t md_tilehasmodel(int32_t const tilenume, int32_t const pal)
{
return mdinited ? tile2model[Ptile2tile(tilenume,pal)].modelid : -1;
}
#endif // defined USE_OPENGL
static FORCE_INLINE int tilehasmodelorvoxel(int const tilenume, int pal)
inline int tilehasmodelorvoxel(int const tilenume, int pal)
{
UNREFERENCED_PARAMETER(pal);
return
@ -766,7 +673,7 @@ extern int skiptile;
static vec2_t const zerovec = { 0, 0 };
static FORCE_INLINE int inside_p(int32_t const x, int32_t const y, int const sectnum) { return (sectnum >= 0 && inside(x, y, sectnum) == 1); }
inline int inside_p(int32_t const x, int32_t const y, int const sectnum) { return (sectnum >= 0 && inside(x, y, sectnum) == 1); }
#define SET_AND_RETURN(Lval, Rval) \
do \
@ -878,7 +785,7 @@ inline void tileUpdatePicnum(int* const tileptr, int const obj, int stat)
inline void setgotpic(int32_t tilenume)
{
gotpic[tilenume >> 3] |= pow2char[tilenume & 7];
gotpic[tilenume >> 3] |= 1 << (tilenume & 7);
}

View file

@ -67,7 +67,7 @@ struct sectortype
uint8_t dirty;
float ceilingxpan_, ceilingypan_, floorxpan_, floorypan_;
uint8_t portalflags;
uint8_t portalnum;
int8_t portalnum;
int ceilingxpan() const { return int(ceilingxpan_); }
int ceilingypan() const { return int(ceilingypan_); }
@ -255,6 +255,7 @@ struct spritetype
};
int16_t extra;
int16_t detail;
int time;
#if 0
// make sure we do not accidentally copy this

View file

@ -27,26 +27,6 @@
#endif
#ifndef MAY_ALIAS
# ifdef _MSC_VER
# define MAY_ALIAS
# else
# define MAY_ALIAS __attribute__((may_alias))
# endif
#endif
#ifndef FORCE_INLINE
# ifdef _MSC_VER
# define FORCE_INLINE __forceinline
# else
# ifdef __GNUC__
# define FORCE_INLINE inline __attribute__((always_inline))
# else
# define FORCE_INLINE inline
# endif
# endif
#endif
# define fallthrough__ [[fallthrough]]
////////// Architecture detection //////////
@ -91,17 +71,12 @@
#include "engineerrors.h"
////////// DEPRECATED: Standard library prefixing //////////
typedef intptr_t ssize_t;
typedef ssize_t bssize_t;
typedef intptr_t bssize_t;
#define BMAX_PATH 256
////////// Metaprogramming structs //////////
using std::enable_if_t;
using native_t = intptr_t;
typedef struct {
@ -121,44 +96,14 @@ typedef struct {
static_assert(sizeof(vec3f_t) == sizeof(float) * 3);
typedef struct {
union { double x; double d; };
union { double y; double u; };
union { double z; double v; };
} vec3d_t;
static_assert(sizeof(vec3d_t) == sizeof(double) * 3);
////////// Language tricks that depend on size_t //////////
#include "basics.h"
////////// Pointer management //////////
#define DO_FREE_AND_NULL(var) do { \
Xfree(var); (var) = NULL; \
} while (0)
////////// Abstract data operations //////////
using std::min;
using std::max;
////////// Bitfield manipulation //////////
// This once was a static array, requiring a memory acces where a shift would suffice.
// Revert the above to a real bit shift through some C++ operator magic. That saves me from reverting all the code that uses this construct.
// Note: Only occurs 25 times in the code, should be removed for good.
static struct
{
constexpr uint8_t operator[](int index) const { return 1 << index; };
} pow2char;
static FORCE_INLINE void bitmap_set(uint8_t *const ptr, int const n) { ptr[n>>3] |= 1 << (n&7); }
static FORCE_INLINE char bitmap_test(uint8_t const *const ptr, int const n) { return ptr[n>>3] & (1 << (n&7)); }
inline void bitmap_set(uint8_t *const ptr, int const n) { ptr[n>>3] |= 1 << (n&7); }
inline char bitmap_test(uint8_t const *const ptr, int const n) { return ptr[n>>3] & (1 << (n&7)); }
////////// Utility functions //////////
@ -183,13 +128,4 @@ void bfirst_search_try(T *const list, uint8_t *const bitmap, T *const eltnumptr,
}
}
////////// PANICKING ALLOCATION WRAPPERS //////////
#define Xstrdup(s) (strdup(s))
#define Xmalloc(size) (M_Malloc(size))
#define Xcalloc(nmemb, size) (M_Calloc(nmemb, size))
#define Xrealloc(ptr, size) (M_Realloc(ptr, size))
#define Xfree(ptr) (M_Free(ptr))
#endif // compat_h_

View file

@ -212,10 +212,6 @@ void voxfree(voxmodel_t *m);
voxmodel_t *voxload(int lumpnum);
int32_t polymost_voxdraw(voxmodel_t *m, tspriteptr_t const tspr);
int md3postload_polymer(md3model_t* m);
//int32_t md_thinoutmodel(int32_t modelid, uint8_t *usedframebitmap);
EXTERN void md_freevbos(void);
#endif // defined USE_OPENGL
enum {

View file

@ -25,9 +25,9 @@ void polymost_completeMirror();
void polymost_precache(int32_t dapicnum, int32_t dapalnum, int32_t datype);
void polymost_deletesprite(int num);
int32_t polymost_maskWallHasTranslucency(uwalltype const * const wall);
int32_t polymost_spriteHasTranslucency(tspritetype const * const tspr);
int32_t polymost_spriteIsModelOrVoxel(tspritetype const * const tspr);
int32_t polymost_maskWallHasTranslucency(walltype const * const wall);
int32_t polymost_spriteHasTranslucency(spritetype const * const tspr);
int32_t polymost_spriteIsModelOrVoxel(spritetype const * const tspr);
void polymost_glreset(void);
void polymost_scansector(int32_t sectnum);
@ -36,6 +36,23 @@ extern float curpolygonoffset;
}
void renderPrepareMirror(int32_t dax, int32_t day, int32_t daz, fixed_t daang, fixed_t dahoriz, int16_t dawall,
int32_t* tposx, int32_t* tposy, fixed_t* tang);
void renderCompleteMirror(void);
int32_t renderDrawRoomsQ16(int32_t daposx, int32_t daposy, int32_t daposz, fixed_t daang, fixed_t dahoriz, int16_t dacursectnum);
void renderDrawMasks(void);
// PLAG: line utility functions
typedef struct s_equation
{
float a, b, c;
} _equation;
void renderSetRollAngle(float rolla);
// these are defined in engine.cpp.
extern int16_t globalpicnum;
extern float fcosglobalang, fsinglobalang;

View file

@ -27,41 +27,9 @@ static uint8_t clipignore[(MAXCLIPNUM+7)>>3];
int32_t quickloadboard=0;
static int32_t numclipmaps;
static int32_t numclipsects; // number in sectq[]
static int16_t *sectoidx;
static int16_t *sectq; // [numsectors]
static int16_t pictoidx[MAXTILES]; // maps tile num to clipinfo[] index
static int16_t *tempictoidx;
static usectortype *loadsector;
static uwalltype *loadwall, *loadwallinv;
static uspritetype *loadsprite;
vec2_t hitscangoal = { (1<<29)-1, (1<<29)-1 };
int32_t hitallsprites = 0;
void engineInitClipMaps()
{
numclipmaps = 0;
numclipsects = 0;
DO_FREE_AND_NULL(sectq);
DO_FREE_AND_NULL(sectoidx);
DO_FREE_AND_NULL(tempictoidx);
DO_FREE_AND_NULL(loadsector);
DO_FREE_AND_NULL(loadwall);
DO_FREE_AND_NULL(loadwallinv);
DO_FREE_AND_NULL(loadsprite);
// two's complement trick, -1 = 0xff
memset(&pictoidx, -1, sizeof(pictoidx));
numsectors = 0;
numwalls = 0;
}
////////// CLIPMOVE //////////
int32_t clipmoveboxtracenum = 3;
@ -157,14 +125,14 @@ static void addclipline(int32_t dax1, int32_t day1, int32_t dax2, int32_t day2,
clipit[clipnum].x2 = dax2; clipit[clipnum].y2 = day2;
clipobjectval[clipnum] = daoval;
uint32_t const mask = pow2char[clipnum&7];
uint32_t const mask = (1 << (clipnum&7));
uint8_t &value = clipignore[clipnum>>3];
value = (value & ~mask) | (-nofix & mask);
clipnum++;
}
static FORCE_INLINE void clipmove_tweak_pos(const vec3_t *pos, int32_t gx, int32_t gy, int32_t x1, int32_t y1, int32_t x2,
inline void clipmove_tweak_pos(const vec3_t *pos, int32_t gx, int32_t gy, int32_t x1, int32_t y1, int32_t x2,
int32_t y2, int32_t *daxptr, int32_t *dayptr)
{
int32_t daz;
@ -530,7 +498,7 @@ int32_t clipmove(vec3_t * const pos, int16_t * const sectnum, int32_t xvect, int
if (clipyou)
{
int16_t const objtype = curspr ? (int16_t)(curspr - (uspritetype *)sprite) + 49152 : (int16_t)j + 32768;
int16_t const objtype = curspr ? (int16_t)(curspr - sprite) + 49152 : (int16_t)j + 32768;
//Add 2 boxes at endpoints
int32_t bsz = walldist; if (diff.x < 0) bsz = -bsz;
@ -1214,22 +1182,22 @@ static int32_t hitscan_trysector(const vec3_t *sv, usectorptr_t sec, hitdata_t *
{
if (tmp==NULL)
{
if (inside(x1,y1,sec-(usectortype *)sector) == 1)
if (inside(x1,y1,sec-sector) == 1)
{
hit_set(hit, sec-(usectortype *)sector, -1, -1, x1, y1, z1);
hit_set(hit, sec-sector, -1, -1, x1, y1, z1);
hitscan_hitsectcf = (how+1)>>1;
}
}
else
{
const int32_t curidx=(int32_t)tmp[0];
auto const curspr=(uspritetype *)tmp[1];
auto const curspr=(spritetype *)tmp[1];
const int32_t thislastsec = tmp[2];
if (!thislastsec)
{
if (inside(x1,y1,sec-(usectortype *)sector) == 1)
hit_set(hit, curspr->sectnum, -1, curspr-(uspritetype *)sprite, x1, y1, z1);
if (inside(x1,y1,sec-sector) == 1)
hit_set(hit, curspr->sectnum, -1, curspr-sprite, x1, y1, z1);
}
}
}

View file

@ -210,8 +210,6 @@ enum scripttoken_t
};
static int32_t lastmodelid = -1, lastvoxid = -1, modelskin = -1, lastmodelskin = -1, seenframe = 0;
static char *faketilebuffer = NULL;
static int32_t faketilebuffersiz = 0;
static const char *skyfaces[6] =
{
@ -1282,7 +1280,7 @@ static int32_t defsparser(scriptfile *script)
break;
default:
if (framei >= 0 && framei<1024)
usedframebitmap[framei>>3] |= pow2char[framei&7];
usedframebitmap[framei>>3] |= (1 << (framei&7));
}
model_ok &= happy;
}
@ -1637,7 +1635,7 @@ static int32_t defsparser(scriptfile *script)
}
case T_ROTATE:
voxrotate[lastvoxid>>3] |= pow2char[lastvoxid&7];
voxrotate[lastvoxid>>3] |= (1 << (lastvoxid&7));
break;
}
}
@ -3196,9 +3194,6 @@ int32_t loaddefinitionsfile(const char *fn, bool loadadds)
if (script)
scriptfile_close(script);
DO_FREE_AND_NULL(faketilebuffer);
faketilebuffersiz = 0;
if (!script) return -1;
Printf(PRINT_NONOTIFY, "\n");

View file

@ -1,4 +1,5 @@
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// "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.
//
@ -40,8 +41,6 @@
#include "gl_renderer.h"
#endif
float rollang;
int32_t r_rortexture = 0;
int32_t r_rortexturerange = 0;
int32_t r_rorphase = 0;
@ -58,7 +57,7 @@ int16_t pskybits_override = -1;
static TArray<TArray<uint8_t>> voxelmemory;
int16_t tiletovox[MAXTILES];
char *voxfilenames[MAXVOXELS];
int voxlumps[MAXVOXELS];
char g_haveVoxels;
//#define kloadvoxel loadvoxel
@ -82,7 +81,7 @@ int32_t showfirstwall=0;
int32_t showheightindicators=1;
int32_t circlewall=-1;
static fixed_t global100horiz; // (-100..300)-scale horiz (the one passed to drawrooms)
fixed_t global100horiz; // (-100..300)-scale horiz (the one passed to drawrooms)
static FString printcoords(void)
{
@ -140,12 +139,6 @@ static void getclosestpointonwall_internal(vec2_t const p, int32_t const dawall,
*closest = { (int32_t)(w.x + ((d.x * i) >> 30)), (int32_t)(w.y + ((d.y * i) >> 30)) };
}
int16_t bunchp2[MAXWALLSB], thesector[MAXWALLSB];
int16_t bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB];
static vec3_t spritesxyz[MAXSPRITESONSCREEN+1];
int32_t xdimen = -1, xdimenscale, xdimscale;
float fxdimen = -1.f;
int32_t ydimen;
@ -168,35 +161,17 @@ int16_t globalpicnum;
static int32_t globaly1, globalx2;
int16_t sectorborder[256];
int16_t pointhighlight=-1, linehighlight=-1, highlightcnt=0;
static_assert(MAXWALLSB < INT16_MAX);
int16_t numscans, numbunches;
static int16_t numhits;
bool inpreparemirror = 0;
static int32_t mirrorsx1, mirrorsy1, mirrorsx2, mirrorsy2;
//
// Internal Engine Functions
//
// returns: 0=continue sprite collecting;
// 1=break out of sprite collecting;
int32_t renderAddTsprite(int16_t z, int16_t sectnum)
{
auto const spr = (uspriteptr_t)&sprite[z];
if (spritesortcnt >= maxspritesonscreen)
return 1;
renderAddTSpriteFromSprite(z);
return 0;
}
//
// animateoffs (internal)
@ -232,21 +207,6 @@ int32_t animateoffs(int const tilenum, int fakevar)
return offs;
}
static void renderDrawSprite(int32_t snum)
{
Polymost::polymost_drawsprite(snum);
}
//
// drawmaskwall (internal)
//
static void renderDrawMaskedWall(int16_t damaskwallcnt)
{
Polymost::polymost_drawmaskwall(damaskwallcnt); return;
}
static int32_t engineLoadTables(void)
{
static char tablesloaded = 0;
@ -281,16 +241,10 @@ static int32_t engineLoadTables(void)
////////// SPRITE LIST MANIPULATION FUNCTIONS //////////
#ifdef NETCODE_DISABLE
# define LISTFN_STATIC static
#else
# define LISTFN_STATIC
#endif
///// sector lists of sprites /////
// insert sprite at the head of sector list, change .sectnum
LISTFN_STATIC void do_insertsprite_at_headofsect(int16_t spritenum, int16_t sectnum)
static void do_insertsprite_at_headofsect(int16_t spritenum, int16_t sectnum)
{
int16_t const ohead = headspritesect[sectnum];
@ -304,7 +258,7 @@ LISTFN_STATIC void do_insertsprite_at_headofsect(int16_t spritenum, int16_t sect
}
// remove sprite 'deleteme' from its sector list
LISTFN_STATIC void do_deletespritesect(int16_t deleteme)
static void do_deletespritesect(int16_t deleteme)
{
int32_t const sectnum = sprite[deleteme].sectnum;
int32_t const prev = prevspritesect[deleteme];
@ -321,7 +275,7 @@ LISTFN_STATIC void do_deletespritesect(int16_t deleteme)
///// now, status lists /////
// insert sprite at head of status list, change .statnum
LISTFN_STATIC void do_insertsprite_at_headofstat(int16_t spritenum, int16_t statnum)
static void do_insertsprite_at_headofstat(int16_t spritenum, int16_t statnum)
{
int16_t const ohead = headspritestat[statnum];
@ -335,7 +289,7 @@ LISTFN_STATIC void do_insertsprite_at_headofstat(int16_t spritenum, int16_t stat
}
// insertspritestat (internal)
LISTFN_STATIC int32_t insertspritestat(int16_t statnum)
static int32_t insertspritestat(int16_t statnum)
{
if ((statnum >= MAXSTATUS) || (headspritestat[MAXSTATUS] == -1))
return -1; //list full
@ -356,7 +310,7 @@ LISTFN_STATIC int32_t insertspritestat(int16_t statnum)
}
// remove sprite 'deleteme' from its status list
LISTFN_STATIC void do_deletespritestat(int16_t deleteme)
static void do_deletespritestat(int16_t deleteme)
{
int32_t const sectnum = sprite[deleteme].statnum;
int32_t const prev = prevspritestat[deleteme];
@ -390,6 +344,7 @@ int32_t insertsprite(int16_t sectnum, int16_t statnum)
Numsprites++;
}
sprite[newspritenum].time = leveltimer++;
return newspritenum;
}
@ -735,40 +690,20 @@ int32_t engineInit(void)
g_visibility = 512;
parallaxvisibility = 512;
maxspritesonscreen = MAXSPRITESONSCREEN;
GPalette.Init(MAXPALOOKUPS + 1); // one slot for each translation, plus a separate one for the base palettes.
gi->loadPalette();
#ifdef USE_OPENGL
if (!mdinited) mdinit();
#endif
return 0;
}
//
// uninitengine
//
void engineUnInit(void)
{
Polymost::polymost_glreset();
freeallmodels();
# ifdef POLYMER
polymer_uninit();
# endif
TileFiles.CloseAll();
}
//
// initspritelists
//
void (*initspritelists_replace)(void) = NULL;
void initspritelists(void)
{
leveltimer = 0;
if (initspritelists_replace)
{
initspritelists_replace();
@ -818,463 +753,6 @@ void initspritelists(void)
}
void set_globalang(fixed_t const ang)
{
globalang = FixedToInt(ang)&2047;
qglobalang = ang & 0x7FFFFFF;
float const f_ang = FixedToFloat(ang);
float const fcosang = bcosf(f_ang);
float const fsinang = bsinf(f_ang);
#ifdef USE_OPENGL
fcosglobalang = fcosang;
fsinglobalang = fsinang;
#endif
cosglobalang = (int)fcosang;
singlobalang = (int)fsinang;
cosviewingrangeglobalang = MulScale(cosglobalang,viewingrange, 16);
sinviewingrangeglobalang = MulScale(singlobalang,viewingrange, 16);
}
//
// drawrooms
//
EXTERN_CVAR(Int, gl_fogmode)
CVAR(Bool, testnewrenderer, true, 0)
int32_t renderDrawRoomsQ16(int32_t daposx, int32_t daposy, int32_t daposz,
fixed_t daang, fixed_t dahoriz, int16_t dacursectnum)
{
checkRotatedWalls();
if (gl_fogmode == 1) gl_fogmode = 2; // only radial fog works with Build's screwed up coordinate system.
// Update starting sector number (common to classic and Polymost).
// ADJUST_GLOBALCURSECTNUM.
if (dacursectnum >= MAXSECTORS)
dacursectnum -= MAXSECTORS;
else
{
int i = dacursectnum;
updatesector(daposx, daposy, &dacursectnum);
if (dacursectnum < 0) dacursectnum = 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 (dacursectnum < 0)
return 0;
}
set_globalpos(daposx, daposy, daposz);
set_globalang(daang);
global100horiz = dahoriz;
memset(gotsector, 0, sizeof(gotsector));
qglobalhoriz = MulScale(dahoriz, DivScale(xdimenscale, viewingrange, 16), 16) + IntToFixed(ydimen >> 1);
globalcursectnum = dacursectnum;
Polymost::polymost_drawrooms();
return inpreparemirror;
}
// UTILITY TYPES AND FUNCTIONS FOR DRAWMASKS OCCLUSION TREE
// typedef struct s_maskleaf
// {
// int32_t index;
// _point2d p1, p2;
// _equation maskeq, p1eq, p2eq;
// struct s_maskleaf* branch[MAXWALLSB];
// int32_t drawing;
// } _maskleaf;
//
// _maskleaf maskleaves[MAXWALLSB];
// returns equation of a line given two points
static inline _equation equation(float const x1, float const y1, float const x2, float const y2)
{
const float f = x2-x1;
// vertical
if (f == 0.f)
return { 1, 0, -x1 };
else
{
float const ff = (y2 - y1) / f;
return { ff, -1, (y1 - (ff * x1)) };
}
}
static inline int32_t sameside(const _equation *eq, const vec2f_t *p1, const vec2f_t *p2)
{
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;
}
static inline int comparetsprites(int const k, int const l)
{
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;
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 (abs(spritesxyz[k].z-globalposz) != abs(spritesxyz[l].z-globalposz))
return abs(spritesxyz[k].z-globalposz)-abs(spritesxyz[l].z-globalposz);
return 0;
}
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;
std::swap(tspriteptr[l],tspriteptr[l+gap]);
std::swap(spritesxyz[l].x,spritesxyz[l+gap].x);
std::swap(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 = tileTopOffset(s->picnum) + s->yoffset;
int32_t yspan = (tileHeight(s->picnum) * s->yrepeat << 2);
spritesxyz[k].z -= (yoff*s->yrepeat)<<2;
if (!(s->cstat&128))
spritesxyz[k].z -= (yspan>>1);
if (abs(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++)
if (comparetsprites(k, l) < 0)
{
std::swap(tspriteptr[k], tspriteptr[l]);
vec3_t tv3 = spritesxyz[k];
spritesxyz[k] = spritesxyz[l];
spritesxyz[l] = tv3;
}
}
i = j;
}
}
//
// drawmasks
//
void renderDrawMasks(void)
{
# define debugmask_add(dispidx, idx) do {} while (0)
int32_t i = spritesortcnt-1;
int32_t numSprites = spritesortcnt;
spritesortcnt = 0;
int32_t back = i;
for (; i >= 0; --i)
{
if (Polymost::polymost_spriteHasTranslucency(&tsprite[i]))
{
tspriteptr[spritesortcnt] = &tsprite[i];
++spritesortcnt;
} else
{
tspriteptr[back] = &tsprite[i];
--back;
}
}
for (i=numSprites-1; i>=0; --i)
{
const int32_t xs = tspriteptr[i]->x-globalposx, ys = tspriteptr[i]->y-globalposy;
const int32_t yp = DMulScale(xs,cosviewingrangeglobalang,ys,sinviewingrangeglobalang, 6);
const int32_t modelp = spriteIsModelOrVoxel(tspriteptr[i]);
if (yp > (4<<8))
{
const int32_t xp = DMulScale(ys,cosglobalang,-xs,singlobalang, 6);
if (MulScale(labs(xp+yp),xdimen, 24) >= yp)
goto killsprite;
spritesxyz[i].x = Scale(xp+yp,xdimen<<7,yp);
}
else if ((tspriteptr[i]->cstat&48) == 0)
{
killsprite:
if (!modelp)
{
//Delete face sprite if on wrong side!
if (i >= spritesortcnt)
{
--numSprites;
if (i != numSprites)
{
tspriteptr[i] = tspriteptr[numSprites];
spritesxyz[i].x = spritesxyz[numSprites].x;
spritesxyz[i].y = spritesxyz[numSprites].y;
}
}
else
{
--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;
}
}
continue;
}
}
spritesxyz[i].y = yp;
}
sortsprites(0, spritesortcnt);
sortsprites(spritesortcnt, numSprites);
renderBeginScene();
GLInterface.EnableBlend(false);
GLInterface.EnableAlphaTest(true);
GLInterface.SetDepthBias(-2, -256);
if (spritesortcnt < numSprites)
{
i = spritesortcnt;
for (bssize_t i = spritesortcnt; i < numSprites;)
{
int32_t py = spritesxyz[i].y;
int32_t pcstat = tspriteptr[i]->cstat & 48;
int32_t pangle = tspriteptr[i]->ang;
int j = i + 1;
if (!spriteIsModelOrVoxel(tspriteptr[i]))
{
while (j < numSprites && py == spritesxyz[j].y && pcstat == (tspriteptr[j]->cstat & 48) && (pcstat != 16 || pangle == tspriteptr[j]->ang)
&& !spriteIsModelOrVoxel(tspriteptr[j]))
{
j++;
}
}
if (j - i == 1)
{
debugmask_add(i | 32768, tspriteptr[i]->owner);
renderDrawSprite(i);
tspriteptr[i] = NULL;
}
else
{
GLInterface.SetDepthMask(false);
for (bssize_t k = j-1; k >= i; k--)
{
debugmask_add(k | 32768, tspriteptr[k]->owner);
renderDrawSprite(k);
}
GLInterface.SetDepthMask(true);
GLInterface.SetColorMask(false);
for (bssize_t k = j-1; k >= i; k--)
{
renderDrawSprite(k);
tspriteptr[k] = NULL;
}
GLInterface.SetColorMask(true);
}
i = j;
}
}
int32_t numMaskWalls = maskwallcnt;
maskwallcnt = 0;
for (i = 0; i < numMaskWalls; i++)
{
if (Polymost::polymost_maskWallHasTranslucency((uwalltype *) &wall[thewall[maskwall[i]]]))
{
maskwall[maskwallcnt] = maskwall[i];
maskwallcnt++;
}
else
renderDrawMaskedWall(i);
}
GLInterface.EnableBlend(true);
GLInterface.EnableAlphaTest(true);
GLInterface.SetDepthMask(false);
vec2f_t pos;
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
const int32_t w = thewall[maskwall[maskwallcnt-1]];
maskwallcnt--;
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 };
_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);
i = spritesortcnt;
while (i)
{
i--;
if (tspriteptr[i] != NULL)
{
vec2f_t spr;
auto const tspr = tspriteptr[i];
spr.x = (float)tspr->x;
spr.y = (float)tspr->y;
if (!sameside(&maskeq, &spr, &pos))
{
// Sprite and camera are on different sides of the
// masked wall.
// 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);
int32_t ok = (inleft && inright);
if (!ok)
{
// If not, check if any of the border points are...
vec2_t pp[4];
int32_t numpts, jj;
const _equation pineq = inleft ? p1eq : p2eq;
if ((tspr->cstat & 48) == 32)
{
numpts = 4;
GetFlatSpritePosition(tspr, tspr->pos.vec2, pp);
}
else
{
const int32_t oang = tspr->ang;
numpts = 2;
// Consider face sprites as wall sprites with camera ang.
// XXX: factor 4/5 needed?
if ((tspr->cstat & 48) != 16)
tspriteptr[i]->ang = globalang;
GetWallSpritePosition(tspr, tspr->pos.vec2, pp);
if ((tspr->cstat & 48) != 16)
tspriteptr[i]->ang = oang;
}
for (jj=0; jj<numpts; jj++)
{
spr.x = (float)pp[jj].x;
spr.y = (float)pp[jj].y;
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;
}
}
}
if (ok)
{
debugmask_add(i | 32768, tspr->owner);
renderDrawSprite(i);
tspriteptr[i] = NULL;
}
}
}
}
debugmask_add(maskwall[maskwallcnt], thewall[maskwall[maskwallcnt]]);
renderDrawMaskedWall(maskwallcnt);
}
while (spritesortcnt)
{
--spritesortcnt;
if (tspriteptr[spritesortcnt] != NULL)
{
debugmask_add(i | 32768, tspriteptr[i]->owner);
renderDrawSprite(spritesortcnt);
tspriteptr[spritesortcnt] = NULL;
}
}
renderFinishScene();
GLInterface.SetDepthMask(true);
GLInterface.SetDepthBias(0, 0);
}
//
// qloadkvx
@ -1307,16 +785,13 @@ int32_t qloadkvx(int32_t voxindex, const char *filename)
}
#ifdef USE_OPENGL
if (voxmodels[voxindex])
{
voxfree(voxmodels[voxindex]);
voxmodels[voxindex] = NULL;
}
Xfree(voxfilenames[voxindex]);
voxfilenames[voxindex] = Xstrdup(filename);
#endif
voxlumps[voxindex] = fileSystem.FindFile(filename);
g_haveVoxels = 1;
@ -1325,21 +800,18 @@ int32_t qloadkvx(int32_t voxindex, const char *filename)
void vox_undefine(int32_t const tile)
{
ssize_t voxindex = tiletovox[tile];
int 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
voxscale[voxindex] = 65536;
voxrotate[voxindex>>3] &= ~pow2char[voxindex&7];
voxrotate[voxindex>>3] &= ~(1 << (voxindex&7));
tiletovox[tile] = -1;
// TODO: nextvoxid
@ -1683,7 +1155,7 @@ int32_t cansee(int32_t x1, int32_t y1, int32_t z1, int16_t sect1, int32_t x2, in
if (x1 == x2 && y1 == y2)
return (sect1 == sect2);
sectbitmap[sect1>>3] |= pow2char[sect1&7];
sectbitmap[sect1>>3] |= (1 << (sect1&7));
clipsectorlist[0] = sect1; danum = 1;
for (dacnt=0; dacnt<danum; dacnt++)
@ -1731,16 +1203,16 @@ int32_t cansee(int32_t x1, int32_t y1, int32_t z1, int16_t sect1, int32_t x2, in
if (z <= cfz[0] || z >= cfz[1])
return 0;
if (!(sectbitmap[nexts>>3] & pow2char[nexts&7]))
if (!(sectbitmap[nexts>>3] & (1 << (nexts&7))))
{
sectbitmap[nexts>>3] |= pow2char[nexts&7];
sectbitmap[nexts>>3] |= (1 << (nexts&7));
clipsectorlist[danum++] = nexts;
}
}
}
if (sectbitmap[sect2>>3] & pow2char[sect2&7])
if (sectbitmap[sect2>>3] & (1<<(sect2&7)))
return 1;
return 0;
@ -1876,7 +1348,7 @@ void dragpoint(int16_t pointhighlight, int32_t dax, int32_t day, uint8_t flags)
sector[wall[w].sector].dirty = 255;
wall[w].x = dax;
wall[w].y = day;
walbitmap[w>>3] |= pow2char[w&7];
walbitmap[w>>3] |= (1<<(w&7));
if (!clockwise) //search points CCW
{
@ -1906,7 +1378,7 @@ void dragpoint(int16_t pointhighlight, int32_t dax, int32_t day, uint8_t flags)
break;
}
if ((walbitmap[w>>3] & pow2char[w&7]))
if ((walbitmap[w>>3] & (1<<(w&7))))
{
if (clockwise)
break;
@ -2033,35 +1505,10 @@ int findwallbetweensectors(int sect1, int sect2)
//
void updatesector(int32_t const x, int32_t const y, int16_t * const sectnum)
{
#if 0
if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE)
{
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
#endif
{
int16_t sect = *sectnum;
updatesectorneighbor(x, y, &sect, INITIALUPDATESECTORDIST, MAXUPDATESECTORDIST);
if (sect != -1)
SET_AND_RETURN(*sectnum, sect);
}
int16_t sect = *sectnum;
updatesectorneighbor(x, y, &sect, INITIALUPDATESECTORDIST, MAXUPDATESECTORDIST);
if (sect != -1)
SET_AND_RETURN(*sectnum, sect);
// we need to support passing in a sectnum of -1, unfortunately
@ -2077,7 +1524,6 @@ void updatesector(int32_t const x, int32_t const y, int16_t * const sectnum)
// as starting sector and the 'initial' z check is skipped
// (not initial anymore because it follows the sector updating due to TROR)
// NOTE: This comes from Duke, therefore it's GPL!
void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int16_t * const sectnum)
{
if (enginecompatibility_mode != ENGINECOMPATIBILITY_NONE)
@ -2100,7 +1546,7 @@ void updatesectorz(int32_t const x, int32_t const y, int32_t const z, int16_t *
if (inside_p(x, y, *sectnum))
return;
uwalltype const * wal = (uwalltype *)&wall[sector[*sectnum].wallptr];
walltype const * wal = &wall[sector[*sectnum].wallptr];
int wallsleft = sector[*sectnum].wallnum;
do
{
@ -2226,22 +1672,6 @@ void rotatepoint(vec2_t const pivot, vec2_t p, int16_t const daang, vec2_t * con
p2->y = DMulScale(p.y, dacos, p.x, dasin, 14) + pivot.y;
}
void videoSetCorrectedAspect()
{
// 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;
x = xdim;
y = ydim;
vr = DivScale(x*3, y*4, 16);
renderSetAspect(vr, yx);
}
//
// setview
//
@ -2256,32 +1686,11 @@ void videoSetViewableArea(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
ydimen = (y2-y1)+1;
fxdimen = (float) xdimen;
#ifdef USE_OPENGL
fydimen = (float) ydimen;
#endif
videoSetCorrectedAspect();
}
//
// setaspect
//
void renderSetAspect(int32_t daxrange, int32_t daaspect)
{
if (daxrange == 65536) daxrange--; // This doesn't work correctly with 65536. All other values are fine. No idea where this is evaluated wrong.
viewingrange = daxrange;
viewingrangerecip = DivScale(1,daxrange, 32);
#ifdef USE_OPENGL
fviewingrange = (float) daxrange;
#endif
yxaspect = daaspect;
xyaspect = DivScale(1,yxaspect, 32);
xdimenscale = Scale(xdimen,yxaspect,320);
xdimscale = Scale(320,xyaspect,xdimen);
}
#include "v_2ddrawer.h"
@ -2355,41 +1764,6 @@ void renderRestoreTarget()
}
//
// preparemirror
//
void renderPrepareMirror(int32_t dax, int32_t day, int32_t daz, fixed_t daang, fixed_t dahoriz, int16_t dawall,
int32_t *tposx, int32_t *tposy, fixed_t *tang)
{
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;
const int32_t j = dx*dx + dy*dy;
if (j == 0)
return;
int i = ((dax-x)*dx + (day-y)*dy)<<1;
*tposx = (x<<1) + Scale(dx,i,j) - dax;
*tposy = (y<<1) + Scale(dy,i,j) - day;
*tang = ((gethiq16angle(dx, dy) << 1) - daang) & 0x7FFFFFF;
inpreparemirror = 1;
Polymost::polymost_prepareMirror(dax, day, daz, daang, dahoriz, dawall);
}
//
// completemirror
//
void renderCompleteMirror(void)
{
Polymost::polymost_completeMirror();
inpreparemirror = 0;
}
int32_t getceilzofslopeptr(usectorptr_t sec, int32_t dax, int32_t day)
{
if (!(sec->ceilingstat&2))
@ -2493,15 +1867,3 @@ void alignflorslope(int16_t dasect, int32_t x, int32_t y, int32_t z)
}
//
// setrollangle
//
#ifdef USE_OPENGL
void renderSetRollAngle(float rolla)
{
Polymost::gtang = rolla * BAngRadian;
rollang = rolla * (BAngRadian * 180 / pi::pif());
}
#endif

View file

@ -13,10 +13,7 @@
#ifndef ENGINE_PRIV_H
#define ENGINE_PRIV_H
extern int16_t thesector[MAXWALLSB], thewall[MAXWALLSB];
extern int16_t bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB];
extern int16_t maskwall[MAXWALLSB], maskwallcnt;
extern tspriteptr_t tspriteptr[MAXSPRITESONSCREEN + 1];
extern int32_t globalpal, globalfloorpal;
extern int32_t xdimen, xdimenscale, xdimscale, ydimen;
extern float fxdimen;
extern int32_t globalposx, globalposy, globalposz;
@ -31,20 +28,11 @@ extern int16_t globalpicnum;
extern int32_t globalorientation;
extern int16_t sectorborder[256];
extern int32_t hitallsprites;
extern int16_t bunchp2[MAXWALLSB];
extern int16_t numscans, numbunches;
// int32_t wallmost(int16_t *mostbuf, int32_t w, int32_t sectnum, char dastat);
void set_globalang(fixed_t const ang);
int32_t animateoffs(int tilenum, int fakevar);
static FORCE_INLINE int32_t bad_tspr(tspriteptr_t tspr)
inline int32_t bad_tspr(tspriteptr_t tspr)
{
// NOTE: tspr->owner >= MAXSPRITES (could be model) has to be handled by
// caller.

View file

@ -98,27 +98,23 @@ void freeallmodels()
if (models)
{
for (i=0; i<nextmodelid; i++) mdfree(models[i]);
DO_FREE_AND_NULL(models);
M_Free(models);
models = nullptr;
nummodelsalloced = 0;
nextmodelid = 0;
}
memset(tile2model,-1,sizeof(tile2model));
for (i=0; i<MAXTILES; i++)
memset(tile2model[i].hudmem, 0, sizeof(tile2model[i].hudmem));
curextra=MAXTILES;
if (vertlist)
{
DO_FREE_AND_NULL(vertlist);
M_Free(vertlist);
vertlist = nullptr;
allocmodelverts = maxmodelverts = 0;
allocmodeltris = maxmodeltris = 0;
}
#ifdef POLYMER
DO_FREE_AND_NULL(tribuf);
#endif
}
void mdinit()
@ -135,7 +131,7 @@ int32_t md_loadmodel(const char *fn)
if (nextmodelid >= nummodelsalloced)
{
ml = (mdmodel_t **)Xrealloc(models,(nummodelsalloced+MODELALLOCGROUP)*sizeof(void *));
ml = (mdmodel_t **)M_Realloc(models,(nummodelsalloced+MODELALLOCGROUP)*sizeof(void *));
models = ml; nummodelsalloced += MODELALLOCGROUP;
}
@ -247,7 +243,7 @@ int32_t md_defineanimation(int32_t modelid, const char *framestart, const char *
ma.fpssc = fpssc;
ma.flags = flags;
map = (mdanim_t *)Xmalloc(sizeof(mdanim_t));
map = (mdanim_t *)M_Malloc(sizeof(mdanim_t));
memcpy(map, &ma, sizeof(ma));
@ -257,110 +253,6 @@ int32_t md_defineanimation(int32_t modelid, const char *framestart, const char *
return 0;
}
#if 0
// FIXME: CURRENTLY DISABLED: interpolation may access frames we consider 'unused'?
int32_t md_thinoutmodel(int32_t modelid, uint8_t *usedframebitmap)
{
md3model_t *m;
md3surf_t *s;
mdanim_t *anm;
int32_t i, surfi, sub, usedframes;
static int16_t otonframe[1024];
if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1;
m = (md3model_t *)models[modelid];
if (m->mdnum != 3) return -2;
for (anm=m->animations; anm; anm=anm->next)
{
if (anm->endframe <= anm->startframe)
{
// Printf("backward anim %d-%d\n", anm->startframe, anm->endframe);
return -3;
}
for (i=anm->startframe; i<anm->endframe; i++)
usedframebitmap[i>>3] |= pow2char[i&7];
}
sub = 0;
for (i=0; i<m->numframes; i++)
{
if (!(usedframebitmap[i>>3]&pow2char[i&7]))
{
sub++;
otonframe[i] = -1;
continue;
}
otonframe[i] = i-sub;
}
usedframes = m->numframes - sub;
if (usedframes==0 || usedframes==m->numframes)
return usedframes;
//// THIN OUT! ////
for (i=0; i<m->numframes; i++)
{
if (otonframe[i]>=0 && otonframe[i] != i)
{
if (m->muladdframes)
memcpy(&m->muladdframes[2*otonframe[i]], &m->muladdframes[2*i], 2*sizeof(vec3f_t));
memcpy(&m->head.frames[otonframe[i]], &m->head.frames[i], sizeof(md3frame_t));
}
}
for (surfi=0; surfi < m->head.numsurfs; surfi++)
{
s = &m->head.surfs[surfi];
for (i=0; i<m->numframes; i++)
if (otonframe[i]>=0 && otonframe[i] != i)
memcpy(&s->xyzn[otonframe[i]*s->numverts], &s->xyzn[i*s->numverts], s->numverts*sizeof(md3xyzn_t));
}
////// tweak frame indices in various places
for (anm=m->animations; anm; anm=anm->next)
{
if (otonframe[anm->startframe]==-1 || otonframe[anm->endframe-1]==-1)
Printf("md %d WTF: anm %d %d\n", modelid, anm->startframe, anm->endframe);
anm->startframe = otonframe[anm->startframe];
anm->endframe = otonframe[anm->endframe-1];
}
for (i=0; i<MAXTILES+EXTRATILES; i++)
if (tile2model[i].modelid == modelid)
{
if (otonframe[tile2model[i].framenum]==-1)
Printf("md %d WTF: tile %d, fr %d\n", modelid, i, tile2model[i].framenum);
tile2model[i].framenum = otonframe[tile2model[i].framenum];
}
////// realloc & change "numframes" everywhere
if (m->muladdframes)
m->muladdframes = Xrealloc(m->muladdframes, 2*sizeof(vec3f_t)*usedframes);
m->head.frames = Xrealloc(m->head.frames, sizeof(md3frame_t)*usedframes);
for (surfi=0; surfi < m->head.numsurfs; surfi++)
{
m->head.surfs[surfi].numframes = usedframes;
// CAN'T do that because xyzn is offset from a larger block when loaded from md3:
// m->head.surfs[surfi].xyzn = Xrealloc(m->head.surfs[surfi].xyzn, s->numverts*usedframes*sizeof(md3xyzn_t));
}
m->head.numframes = usedframes;
m->numframes = usedframes;
////////////
return usedframes;
}
#endif
int32_t md_defineskin(int32_t modelid, const char *skinfn, int32_t palnum, int32_t skinnum, int32_t surfnum, float param, float specpower, float specfactor, int32_t flags)
{
mdskinmap_t *sk, *skl;
@ -382,7 +274,7 @@ int32_t md_defineskin(int32_t modelid, const char *skinfn, int32_t palnum, int32
break;
if (!sk)
{
sk = (mdskinmap_t *)Xcalloc(1,sizeof(mdskinmap_t));
sk = (mdskinmap_t *)M_Calloc(1,sizeof(mdskinmap_t));
if (!skl) m->skinmap = sk;
else skl->next = sk;
@ -411,9 +303,7 @@ int32_t md_definehud(int32_t modelid, int32_t tilex, vec3f_t add, int32_t angadd
if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1;
if ((uint32_t)tilex >= (uint32_t)MAXTILES) return -2;
tile2model[tilex].hudmem[(flags>>2)&1] = (hudtyp *)Xmalloc(sizeof(hudtyp));
hudtyp * const hud = tile2model[tilex].hudmem[(flags>>2)&1];
hudtyp * const hud = &tile2model[tilex].hudmem[(flags>>2)&1];
hud->add = add;
hud->angadd = ((int16_t)angadd)|2048;
@ -430,8 +320,6 @@ int32_t md_undefinetile(int32_t tile)
tile2model[tile].modelid = -1;
tile2model[tile].nexttile = -1;
DO_FREE_AND_NULL(tile2model[tile].hudmem[0]);
DO_FREE_AND_NULL(tile2model[tile].hudmem[1]);
return 0;
}
@ -447,8 +335,6 @@ int32_t md_undefinemodel(int32_t modelid)
if (tile2model[i].modelid == modelid)
{
tile2model[i].modelid = -1;
DO_FREE_AND_NULL(tile2model[i].hudmem[0]);
DO_FREE_AND_NULL(tile2model[i].hudmem[1]);
}
if (models)
@ -670,7 +556,7 @@ static md2model_t *md2load(FileReader & fil, const char *filnam)
int32_t ournumskins, ournumglcmds;
m = (md2model_t *)Xcalloc(1,sizeof(md2model_t));
m = (md2model_t *)M_Calloc(1,sizeof(md2model_t));
m->mdnum = 2; m->scale = .01f;
fil.Read((char *)&head,sizeof(md2head_t));
@ -686,7 +572,7 @@ static md2model_t *md2load(FileReader & fil, const char *filnam)
head.ofseof = LittleLong(head.ofseof);
#endif
if ((head.id != IDP2_MAGIC) || (head.vers != 8)) { Xfree(m); return 0; } //"IDP2"
if ((head.id != IDP2_MAGIC) || (head.vers != 8)) { M_Free(m); return 0; } //"IDP2"
ournumskins = head.numskins ? head.numskins : 1;
ournumglcmds = head.numglcmds ? head.numglcmds : 1;
@ -697,29 +583,29 @@ static md2model_t *md2load(FileReader & fil, const char *filnam)
m->numglcmds = head.numglcmds;
m->framebytes = head.framebytes;
m->frames = (char *)Xmalloc(m->numframes*m->framebytes);
m->glcmds = (int32_t *)Xmalloc(ournumglcmds*sizeof(int32_t));
m->tris = (md2tri_t *)Xmalloc(head.numtris*sizeof(md2tri_t));
m->uv = (md2uv_t *)Xmalloc(head.numuv*sizeof(md2uv_t));
m->frames = (char *)M_Malloc(m->numframes*m->framebytes);
m->glcmds = (int32_t *)M_Malloc(ournumglcmds*sizeof(int32_t));
m->tris = (md2tri_t *)M_Malloc(head.numtris*sizeof(md2tri_t));
m->uv = (md2uv_t *)M_Malloc(head.numuv*sizeof(md2uv_t));
fil.Seek(head.ofsframes,FileReader::SeekSet);
if (fil.Read((char *)m->frames,m->numframes*m->framebytes) != m->numframes*m->framebytes)
{ Xfree(m->uv); Xfree(m->tris); Xfree(m->glcmds); Xfree(m->frames); Xfree(m); return 0; }
{ M_Free(m->uv); M_Free(m->tris); M_Free(m->glcmds); M_Free(m->frames); M_Free(m); return 0; }
if (m->numglcmds > 0)
{
fil.Seek(head.ofsglcmds,FileReader::SeekSet);
if (fil.Read((char *)m->glcmds,m->numglcmds*sizeof(int32_t)) != (int32_t)(m->numglcmds*sizeof(int32_t)))
{ Xfree(m->uv); Xfree(m->tris); Xfree(m->glcmds); Xfree(m->frames); Xfree(m); return 0; }
{ M_Free(m->uv); M_Free(m->tris); M_Free(m->glcmds); M_Free(m->frames); M_Free(m); return 0; }
}
fil.Seek(head.ofstris,FileReader::SeekSet);
if (fil.Read((char *)m->tris,head.numtris*sizeof(md2tri_t)) != (int32_t)(head.numtris*sizeof(md2tri_t)))
{ Xfree(m->uv); Xfree(m->tris); Xfree(m->glcmds); Xfree(m->frames); Xfree(m); return 0; }
{ M_Free(m->uv); M_Free(m->tris); M_Free(m->glcmds); M_Free(m->frames); M_Free(m); return 0; }
fil.Seek(head.ofsuv,FileReader::SeekSet);
if (fil.Read((char *)m->uv,head.numuv*sizeof(md2uv_t)) != (int32_t)(head.numuv*sizeof(md2uv_t)))
{ Xfree(m->uv); Xfree(m->tris); Xfree(m->glcmds); Xfree(m->frames); Xfree(m); return 0; }
{ M_Free(m->uv); M_Free(m->tris); M_Free(m->glcmds); M_Free(m->frames); M_Free(m); return 0; }
#if B_BIG_ENDIAN != 0
{
@ -761,15 +647,15 @@ static md2model_t *md2load(FileReader & fil, const char *filnam)
if ((st[i] == '/') || (st[i] == '\\')) { i++; break; }
if (i<0) i=0;
st[i] = 0;
m->basepath = (char *)Xmalloc(i+1);
m->basepath = (char *)M_Malloc(i+1);
strcpy(m->basepath, st);
m->skinfn = (char *)Xmalloc(ournumskins*64);
m->skinfn = (char *)M_Malloc(ournumskins*64);
if (m->numskins > 0)
{
fil.Seek(head.ofsskins,FileReader::SeekSet);
if (fil.Read(m->skinfn,64*m->numskins) != 64*m->numskins)
{ Xfree(m->glcmds); Xfree(m->frames); Xfree(m); return 0; }
{ M_Free(m->glcmds); M_Free(m->frames); M_Free(m); return 0; }
}
maxmodelverts = max(maxmodelverts, m->numverts);
@ -779,7 +665,7 @@ static md2model_t *md2load(FileReader & fil, const char *filnam)
// the MD2 is now loaded internally - let's begin the MD3 conversion process
//Printf("Beginning md3 conversion.\n");
m3 = (md3model_t *)Xcalloc(1, sizeof(md3model_t));
m3 = (md3model_t *)M_Calloc(1, sizeof(md3model_t));
m3->mdnum = 3; m3->texture = nullptr; m3->scale = m->scale;
m3->head.id = IDP3_MAGIC; m3->head.vers = 15;
@ -792,8 +678,8 @@ static md2model_t *md2load(FileReader & fil, const char *filnam)
m3->numskins = m3->head.numskins;
m3->numframes = m3->head.numframes;
m3->head.frames = (md3frame_t *)Xcalloc(m3->head.numframes, sizeof(md3frame_t));
m3->muladdframes = (vec3f_t *)Xcalloc(m->numframes * 2, sizeof(vec3f_t));
m3->head.frames = (md3frame_t *)M_Calloc(m3->head.numframes, sizeof(md3frame_t));
m3->muladdframes = (vec3f_t *)M_Calloc(m->numframes * 2, sizeof(vec3f_t));
f = (md2frame_t *)(m->frames);
@ -811,7 +697,7 @@ static md2model_t *md2load(FileReader & fil, const char *filnam)
m3->head.tags = NULL;
m3->head.surfs = (md3surf_t *)Xcalloc(1, sizeof(md3surf_t));
m3->head.surfs = (md3surf_t *)M_Calloc(1, sizeof(md3surf_t));
s = m3->head.surfs;
// model converting
@ -828,9 +714,9 @@ static md2model_t *md2load(FileReader & fil, const char *filnam)
s->shaders = NULL;
s->tris = (md3tri_t *)Xcalloc(head.numtris, sizeof(md3tri_t));
s->uv = (md3uv_t *)Xcalloc(s->numverts, sizeof(md3uv_t));
s->xyzn = (md3xyzn_t *)Xcalloc(s->numverts * m->numframes, sizeof(md3xyzn_t));
s->tris = (md3tri_t *)M_Calloc(head.numtris, sizeof(md3tri_t));
s->uv = (md3uv_t *)M_Calloc(s->numverts, sizeof(md3uv_t));
s->xyzn = (md3xyzn_t *)M_Calloc(s->numverts * m->numframes, sizeof(md3xyzn_t));
//memoryusage += (s->numverts * m->numframes * sizeof(md3xyzn_t));
//Printf("Current model geometry memory usage : %i.\n", memoryusage);
@ -875,7 +761,7 @@ static md2model_t *md2load(FileReader & fil, const char *filnam)
{
mdskinmap_t *sk;
sk = (mdskinmap_t *)Xcalloc(1,sizeof(mdskinmap_t));
sk = (mdskinmap_t *)M_Calloc(1,sizeof(mdskinmap_t));
sk->palette = 0;
sk->skinnum = 0;
sk->surfnum = 0;
@ -892,12 +778,12 @@ static md2model_t *md2load(FileReader & fil, const char *filnam)
m3->skinmap = sk;
}
m3->indexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * s->numtris);
m3->vindexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * s->numtris * 3);
m3->maxdepths = (float *)Xmalloc(sizeof(float) * s->numtris);
m3->indexes = (uint16_t *)M_Malloc(sizeof(uint16_t) * s->numtris);
m3->vindexes = (uint16_t *)M_Malloc(sizeof(uint16_t) * s->numtris * 3);
m3->maxdepths = (float *)M_Malloc(sizeof(float) * s->numtris);
// die MD2 ! DIE !
Xfree(m->skinfn); Xfree(m->basepath); Xfree(m->uv); Xfree(m->tris); Xfree(m->glcmds); Xfree(m->frames); Xfree(m);
M_Free(m->skinfn); M_Free(m->basepath); M_Free(m->uv); M_Free(m->tris); M_Free(m->glcmds); M_Free(m->frames); M_Free(m);
return ((md2model_t *)m3);
}
@ -949,7 +835,7 @@ static md3model_t *md3load(FileReader & fil)
md3model_t *m;
md3surf_t *s;
m = (md3model_t *)Xcalloc(1,sizeof(md3model_t));
m = (md3model_t *)M_Calloc(1,sizeof(md3model_t));
m->mdnum = 3; m->texture = nullptr; m->scale = .01f;
m->muladdframes = NULL;
@ -965,7 +851,7 @@ static md3model_t *md3load(FileReader & fil)
m->head.eof = LittleLong(m->head.eof);
#endif
if ((m->head.id != IDP3_MAGIC) && (m->head.vers != 15)) { Xfree(m); return 0; } //"IDP3"
if ((m->head.id != IDP3_MAGIC) && (m->head.vers != 15)) { M_Free(m); return 0; } //"IDP3"
m->numskins = m->head.numskins; //<- dead code?
m->numframes = m->head.numframes;
@ -973,19 +859,19 @@ static md3model_t *md3load(FileReader & fil)
ofsurf = m->head.ofssurfs;
fil.Seek(m->head.ofsframes,FileReader::SeekSet); i = m->head.numframes*sizeof(md3frame_t);
m->head.frames = (md3frame_t *)Xmalloc(i);
m->head.frames = (md3frame_t *)M_Malloc(i);
fil.Read(m->head.frames,i);
if (m->head.numtags == 0) m->head.tags = NULL;
else
{
fil.Seek(m->head.ofstags,FileReader::SeekSet); i = m->head.numtags*sizeof(md3tag_t);
m->head.tags = (md3tag_t *)Xmalloc(i);
m->head.tags = (md3tag_t *)M_Malloc(i);
fil.Read(m->head.tags,i);
}
fil.Seek(m->head.ofssurfs,FileReader::SeekSet);
m->head.surfs = (md3surf_t *)Xcalloc(m->head.numsurfs, sizeof(md3surf_t));
m->head.surfs = (md3surf_t *)M_Calloc(m->head.numsurfs, sizeof(md3surf_t));
// NOTE: We assume that NULL is represented by all-zeros.
// surfs[0].geometry is for POLYMER_MD_PROCESS_CHECK (else: crashes).
// surfs[i].geometry is for FREE_SURFS_GEOMETRY.
@ -1038,7 +924,7 @@ static md3model_t *md3load(FileReader & fil)
//memoryusage += (s->numverts * s->numframes * sizeof(md3xyzn_t));
//Printf("Current model geometry memory usage : %i.\n", memoryusage);
s->tris = (md3tri_t *)Xmalloc((leng[0] + leng[1]) + (leng[2] + leng[3]));
s->tris = (md3tri_t *)M_Malloc((leng[0] + leng[1]) + (leng[2] + leng[3]));
s->shaders = (md3shader_t *)(((intptr_t)s->tris)+leng[0]);
s->uv = (md3uv_t *)(((intptr_t)s->shaders)+leng[1]);
@ -1081,9 +967,9 @@ static md3model_t *md3load(FileReader & fil)
ofsurf += s->ofsend;
}
m->indexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * maxtrispersurf);
m->vindexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * maxtrispersurf * 3);
m->maxdepths = (float *)Xmalloc(sizeof(float) * maxtrispersurf);
m->indexes = (uint16_t *)M_Malloc(sizeof(uint16_t) * maxtrispersurf);
m->vindexes = (uint16_t *)M_Malloc(sizeof(uint16_t) * maxtrispersurf * 3);
m->maxdepths = (float *)M_Malloc(sizeof(float) * maxtrispersurf);
return m;
}
@ -1556,12 +1442,12 @@ static void md3free(md3model_t *m)
for (anim=m->animations; anim; anim=nanim)
{
nanim = anim->next;
Xfree(anim);
M_Free(anim);
}
for (sk=m->skinmap; sk; sk=nsk)
{
nsk = sk->next;
Xfree(sk);
M_Free(sk);
}
if (m->head.surfs)
@ -1569,21 +1455,21 @@ static void md3free(md3model_t *m)
for (bssize_t surfi=m->head.numsurfs-1; surfi>=0; surfi--)
{
md3surf_t *s = &m->head.surfs[surfi];
Xfree(s->tris);
Xfree(s->geometry); // FREE_SURFS_GEOMETRY
M_Free(s->tris);
M_Free(s->geometry); // FREE_SURFS_GEOMETRY
}
Xfree(m->head.surfs);
M_Free(m->head.surfs);
}
Xfree(m->head.tags);
Xfree(m->head.frames);
M_Free(m->head.tags);
M_Free(m->head.frames);
Xfree(m->muladdframes);
M_Free(m->muladdframes);
Xfree(m->indexes);
Xfree(m->vindexes);
Xfree(m->maxdepths);
M_Free(m->indexes);
M_Free(m->vindexes);
M_Free(m->maxdepths);
Xfree(m);
M_Free(m);
}
//---------------------------------------- MD3 LIBRARY ENDS ----------------------------------------
@ -1639,7 +1525,7 @@ int32_t polymost_mddraw(tspriteptr_t tspr)
{
if (maxmodelverts > allocmodelverts)
{
vertlist = (vec3f_t *) Xrealloc(vertlist, sizeof(vec3f_t)*maxmodelverts);
vertlist = (vec3f_t *) M_Realloc(vertlist, sizeof(vec3f_t)*maxmodelverts);
allocmodelverts = maxmodelverts;
}

View file

@ -22,6 +22,19 @@ Ken Silverman's official web site: http://www.advsys.net/ken
#include "texturemanager.h"
#include "hw_renderstate.h"
#include "printf.h"
#include "gamefuncs.h"
#include "hw_drawinfo.h"
typedef struct {
union { double x; double d; };
union { double y; double u; };
union { double z; double v; };
} vec3d_t;
static_assert(sizeof(vec3d_t) == sizeof(double) * 3);
int skiptile = -1;
FGameTexture* GetSkyTexture(int basetile, int lognumtiles, const int16_t* tilemap);
@ -38,6 +51,19 @@ CVARD(Float, hw_shadescale, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "multiplier
// For testing - will be removed later.
CVAR(Int, skytile, 0, 0)
CVAR(Bool, testnewrenderer, true, 0)
extern fixed_t global100horiz; // (-100..300)-scale horiz (the one passed to drawrooms)
static vec3_t spritesxyz[MAXSPRITESONSCREEN + 1];
static int16_t thewall[MAXWALLSB];
static int16_t bunchp2[MAXWALLSB], thesector[MAXWALLSB];
static int16_t bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB];
static int16_t numscans, numbunches;
static int16_t maskwall[MAXWALLSB], maskwallcnt;
static int16_t sectorborder[256];
static tspriteptr_t tspriteptr[MAXSPRITESONSCREEN + 1];
namespace Polymost
{
@ -108,6 +134,27 @@ void polymost_outputGLDebugMessage(uint8_t severity, const char* format, ...)
{
}
static void set_globalang(fixed_t const ang)
{
globalang = FixedToInt(ang) & 2047;
qglobalang = ang & 0x7FFFFFF;
float const f_ang = FixedToFloat(ang);
float const fcosang = bcosf(f_ang);
float const fsinang = bsinf(f_ang);
#ifdef USE_OPENGL
fcosglobalang = fcosang;
fsinglobalang = fsinang;
#endif
cosglobalang = (int)fcosang;
singlobalang = (int)fsinang;
cosviewingrangeglobalang = MulScale(cosglobalang, viewingrange, 16);
sinviewingrangeglobalang = MulScale(singlobalang, viewingrange, 16);
}
static inline float polymost_invsqrt_approximation(float x)
{
// this is the comment
@ -121,7 +168,7 @@ static float sectorVisibility(int sectnum)
return v? ((uint8_t)(v + 16)) / 16.f : 1.f;
}
template <typename T> static FORCE_INLINE void tileUpdatePicnum(T* const tileptr, int const obj)
static void tileUpdatePicnum(short* const tileptr, int const obj)
{
auto& tile = *tileptr;
@ -216,7 +263,7 @@ static int32_t pow2xsplit = 0, skyzbufferhack = 0, flatskyrender = 0;
static float drawpoly_alpha = 0.f;
static uint8_t drawpoly_blend = 0;
int32_t polymost_maskWallHasTranslucency(uwalltype const * const wall)
int32_t polymost_maskWallHasTranslucency(walltype const * const wall)
{
if (wall->cstat & CSTAT_WALL_TRANSLUCENT)
return true;
@ -224,7 +271,7 @@ int32_t polymost_maskWallHasTranslucency(uwalltype const * const wall)
return checkTranslucentReplacement(tileGetTexture(wall->picnum)->GetID(), wall->pal);
}
int32_t polymost_spriteHasTranslucency(tspritetype const * const tspr)
int32_t polymost_spriteHasTranslucency(spritetype const * const tspr)
{
if ((tspr->cstat & CSTAT_SPRITE_TRANSLUCENT) || (tspr->clipdist & TSPR_FLAGS_DRAW_LAST) ||
((unsigned)tspr->owner < MAXSPRITES && spriteext[tspr->owner].alpha))
@ -1771,7 +1818,7 @@ static void polymost_drawalls(int32_t const bunch)
domostpolymethod = DAMETH_NOMASK;
if (nextsectnum >= 0)
if ((!(gotsector[nextsectnum>>3]&pow2char[nextsectnum&7])) && testvisiblemost(x0,x1))
if ((!(gotsector[nextsectnum>>3]& (1<<(nextsectnum&7)))) && testvisiblemost(x0,x1))
polymost_scansector(nextsectnum);
}
}
@ -1872,7 +1919,7 @@ void polymost_scansector(int32_t sectnum)
}
}
gotsector[sectnum>>3] |= pow2char[sectnum&7];
gotsector[sectnum>>3] |= 1<<(sectnum&7);
int const bunchfrst = numbunches;
int const onumscans = numscans;
@ -1895,7 +1942,7 @@ void polymost_scansector(int32_t sectnum)
int const nextsectnum = wal->nextsector; //Scan close sectors
if (nextsectnum >= 0 && !(wal->cstat&32) && sectorbordercnt < countof(sectorborder))
if ((gotsector[nextsectnum>>3]&pow2char[nextsectnum&7]) == 0)
if ((gotsector[nextsectnum>>3]&(1<<(nextsectnum&7))) == 0)
{
double const d = fp1.X* fp2.Y - fp2.X * fp1.Y;
DVector2 const p1 = fp2 - fp1;
@ -1905,7 +1952,7 @@ void polymost_scansector(int32_t sectnum)
if (d*d < (p1.LengthSquared()) * 256.f)
{
sectorborder[sectorbordercnt++] = nextsectnum;
gotsector[nextsectnum>>3] |= pow2char[nextsectnum&7];
gotsector[nextsectnum>>3] |= 1<<(nextsectnum&7);
}
}
@ -2570,7 +2617,7 @@ void polymost_deletesprite(int num)
static inline int32_t polymost_findwall(tspritetype const * const tspr, vec2_t const * const tsiz, int32_t * rd)
{
int32_t dist = 4, closest = -1;
auto const sect = (usectortype * )&sector[tspr->sectnum];
auto const sect = &sector[tspr->sectnum];
vec2_t n;
for (bssize_t i=sect->wallptr; i<sect->wallptr + sect->wallnum; i++)
@ -3200,6 +3247,8 @@ _drawsprite_return:
;
}
//////////////////////////////////
static_assert((int)RS_YFLIP == (int)HUDFLAG_FLIPPED);
void polymost_precache(int32_t dapicnum, int32_t dapalnum, int32_t datype)
@ -3209,9 +3258,9 @@ void polymost_precache(int32_t dapicnum, int32_t dapalnum, int32_t datype)
// basically this just means walls are repeating
// while sprites are clamped
if ((dapalnum < (MAXPALOOKUPS - RESERVEDPALS)) && (!lookups.checkTable(dapalnum))) return;//dapalnum = 0;
if ((dapalnum < (MAXPALOOKUPS - RESERVEDPALS)) && (!lookups.checkTable(dapalnum))) return;//dapalnum = 0;
//Printf("precached %d %d type %d\n", dapicnum, dapalnum, datype);
//Printf("precached %d %d type %d\n", dapicnum, dapalnum, datype);
hicprecaching = 1;
int palid = TRANSLATION(Translation_Remap + curbasepal, dapalnum);
auto tex = tileGetTexture(dapicnum);
@ -3225,17 +3274,492 @@ void polymost_precache(int32_t dapicnum, int32_t dapalnum, int32_t datype)
if (mid < 0 || models[mid]->mdnum < 2) return;
int const surfaces = (models[mid]->mdnum == 3) ? ((md3model_t *)models[mid])->head.numsurfs : 0;
int const surfaces = (models[mid]->mdnum == 3) ? ((md3model_t*)models[mid])->head.numsurfs : 0;
for (int i = 0; i <= surfaces; i++)
{
auto tex = mdloadskin((md2model_t *)models[mid], 0, dapalnum, i, nullptr);
{
auto tex = mdloadskin((md2model_t*)models[mid], 0, dapalnum, i, nullptr);
int palid = TRANSLATION(Translation_Remap + curbasepal, dapalnum);
if (tex) GLInterface.SetTexture(tex, palid, CLAMP_NONE);
}
}
}
}
//
// preparemirror
//
void renderPrepareMirror(int32_t dax, int32_t day, int32_t daz, fixed_t daang, fixed_t dahoriz, int16_t dawall,
int32_t* tposx, int32_t* tposy, fixed_t* tang)
{
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;
const int32_t j = dx * dx + dy * dy;
if (j == 0)
return;
int i = ((dax - x) * dx + (day - y) * dy) << 1;
*tposx = (x << 1) + Scale(dx, i, j) - dax;
*tposy = (y << 1) + Scale(dy, i, j) - day;
*tang = ((gethiq16angle(dx, dy) << 1) - daang) & 0x7FFFFFF;
inpreparemirror = 1;
Polymost::polymost_prepareMirror(dax, day, daz, daang, dahoriz, dawall);
}
//
// completemirror
//
void renderCompleteMirror(void)
{
Polymost::polymost_completeMirror();
inpreparemirror = 0;
}
//
// drawrooms
//
EXTERN_CVAR(Int, gl_fogmode)
int32_t renderDrawRoomsQ16(int32_t daposx, int32_t daposy, int32_t daposz,
fixed_t daang, fixed_t dahoriz, int16_t dacursectnum)
{
checkRotatedWalls();
if (gl_fogmode == 1) gl_fogmode = 2; // only radial fog works with Build's screwed up coordinate system.
// Update starting sector number (common to classic and Polymost).
// ADJUST_GLOBALCURSECTNUM.
if (dacursectnum >= MAXSECTORS)
dacursectnum -= MAXSECTORS;
else
{
int i = dacursectnum;
updatesector(daposx, daposy, &dacursectnum);
if (dacursectnum < 0) dacursectnum = 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 (dacursectnum < 0)
return 0;
}
set_globalpos(daposx, daposy, daposz);
Polymost::set_globalang(daang);
global100horiz = dahoriz;
memset(gotsector, 0, sizeof(gotsector));
qglobalhoriz = MulScale(dahoriz, DivScale(xdimenscale, viewingrange, 16), 16) + IntToFixed(ydimen >> 1);
globalcursectnum = dacursectnum;
Polymost::polymost_drawrooms();
return inpreparemirror;
}
// UTILITY TYPES AND FUNCTIONS FOR DRAWMASKS OCCLUSION TREE
// typedef struct s_maskleaf
// {
// int32_t index;
// _point2d p1, p2;
// _equation maskeq, p1eq, p2eq;
// struct s_maskleaf* branch[MAXWALLSB];
// int32_t drawing;
// } _maskleaf;
//
// _maskleaf maskleaves[MAXWALLSB];
// returns equation of a line given two points
static inline _equation equation(float const x1, float const y1, float const x2, float const y2)
{
const float f = x2 - x1;
// vertical
if (f == 0.f)
return { 1, 0, -x1 };
else
{
float const ff = (y2 - y1) / f;
return { ff, -1, (y1 - (ff * x1)) };
}
}
static inline int32_t sameside(const _equation* eq, const vec2f_t* p1, const vec2f_t* p2)
{
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;
}
static inline int comparetsprites(int const k, int const l)
{
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;
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 (abs(spritesxyz[k].z - globalposz) != abs(spritesxyz[l].z - globalposz))
return abs(spritesxyz[k].z - globalposz) - abs(spritesxyz[l].z - globalposz);
return 0;
}
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;
std::swap(tspriteptr[l], tspriteptr[l + gap]);
std::swap(spritesxyz[l].x, spritesxyz[l + gap].x);
std::swap(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 = tileTopOffset(s->picnum) + s->yoffset;
int32_t yspan = (tileHeight(s->picnum) * s->yrepeat << 2);
spritesxyz[k].z -= (yoff * s->yrepeat) << 2;
if (!(s->cstat & 128))
spritesxyz[k].z -= (yspan >> 1);
if (abs(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++)
if (comparetsprites(k, l) < 0)
{
std::swap(tspriteptr[k], tspriteptr[l]);
vec3_t tv3 = spritesxyz[k];
spritesxyz[k] = spritesxyz[l];
spritesxyz[l] = tv3;
}
}
i = j;
}
}
//
// drawmasks
//
void renderDrawMasks(void)
{
# define debugmask_add(dispidx, idx) do {} while (0)
int32_t i = spritesortcnt - 1;
int32_t numSprites = spritesortcnt;
spritesortcnt = 0;
int32_t back = i;
for (; i >= 0; --i)
{
if (Polymost::polymost_spriteHasTranslucency(&tsprite[i]))
{
tspriteptr[spritesortcnt] = &tsprite[i];
++spritesortcnt;
}
else
{
tspriteptr[back] = &tsprite[i];
--back;
}
}
for (i = numSprites - 1; i >= 0; --i)
{
const int32_t xs = tspriteptr[i]->x - globalposx, ys = tspriteptr[i]->y - globalposy;
const int32_t yp = DMulScale(xs, cosviewingrangeglobalang, ys, sinviewingrangeglobalang, 6);
const int32_t modelp = spriteIsModelOrVoxel(tspriteptr[i]);
if (yp > (4 << 8))
{
const int32_t xp = DMulScale(ys, cosglobalang, -xs, singlobalang, 6);
if (MulScale(labs(xp + yp), xdimen, 24) >= yp)
goto killsprite;
spritesxyz[i].x = Scale(xp + yp, xdimen << 7, yp);
}
else if ((tspriteptr[i]->cstat & 48) == 0)
{
killsprite:
if (!modelp)
{
//Delete face sprite if on wrong side!
if (i >= spritesortcnt)
{
--numSprites;
if (i != numSprites)
{
tspriteptr[i] = tspriteptr[numSprites];
spritesxyz[i].x = spritesxyz[numSprites].x;
spritesxyz[i].y = spritesxyz[numSprites].y;
}
}
else
{
--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;
}
}
continue;
}
}
spritesxyz[i].y = yp;
}
sortsprites(0, spritesortcnt);
sortsprites(spritesortcnt, numSprites);
renderBeginScene();
GLInterface.EnableBlend(false);
GLInterface.EnableAlphaTest(true);
GLInterface.SetDepthBias(-2, -256);
if (spritesortcnt < numSprites)
{
i = spritesortcnt;
for (bssize_t i = spritesortcnt; i < numSprites;)
{
int32_t py = spritesxyz[i].y;
int32_t pcstat = tspriteptr[i]->cstat & 48;
int32_t pangle = tspriteptr[i]->ang;
int j = i + 1;
if (!spriteIsModelOrVoxel(tspriteptr[i]))
{
while (j < numSprites && py == spritesxyz[j].y && pcstat == (tspriteptr[j]->cstat & 48) && (pcstat != 16 || pangle == tspriteptr[j]->ang)
&& !spriteIsModelOrVoxel(tspriteptr[j]))
{
j++;
}
}
if (j - i == 1)
{
debugmask_add(i | 32768, tspriteptr[i]->owner);
Polymost::polymost_drawsprite(i);
tspriteptr[i] = NULL;
}
else
{
GLInterface.SetDepthMask(false);
for (bssize_t k = j - 1; k >= i; k--)
{
debugmask_add(k | 32768, tspriteptr[k]->owner);
Polymost::polymost_drawsprite(k);
}
GLInterface.SetDepthMask(true);
GLInterface.SetColorMask(false);
for (bssize_t k = j - 1; k >= i; k--)
{
Polymost::polymost_drawsprite(k);
tspriteptr[k] = NULL;
}
GLInterface.SetColorMask(true);
}
i = j;
}
}
int32_t numMaskWalls = maskwallcnt;
maskwallcnt = 0;
for (i = 0; i < numMaskWalls; i++)
{
if (Polymost::polymost_maskWallHasTranslucency(&wall[thewall[maskwall[i]]]))
{
maskwall[maskwallcnt] = maskwall[i];
maskwallcnt++;
}
else
Polymost::polymost_drawmaskwall(i);
}
GLInterface.EnableBlend(true);
GLInterface.EnableAlphaTest(true);
GLInterface.SetDepthMask(false);
vec2f_t pos;
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
const int32_t w = thewall[maskwall[maskwallcnt - 1]];
maskwallcnt--;
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 };
_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);
i = spritesortcnt;
while (i)
{
i--;
if (tspriteptr[i] != NULL)
{
vec2f_t spr;
auto const tspr = tspriteptr[i];
spr.x = (float)tspr->x;
spr.y = (float)tspr->y;
if (!sameside(&maskeq, &spr, &pos))
{
// Sprite and camera are on different sides of the
// masked wall.
// 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);
int32_t ok = (inleft && inright);
if (!ok)
{
// If not, check if any of the border points are...
vec2_t pp[4];
int32_t numpts, jj;
const _equation pineq = inleft ? p1eq : p2eq;
if ((tspr->cstat & 48) == 32)
{
numpts = 4;
GetFlatSpritePosition(tspr, tspr->pos.vec2, pp);
}
else
{
const int32_t oang = tspr->ang;
numpts = 2;
// Consider face sprites as wall sprites with camera ang.
// XXX: factor 4/5 needed?
if ((tspr->cstat & 48) != 16)
tspriteptr[i]->ang = globalang;
GetWallSpritePosition(tspr, tspr->pos.vec2, pp);
if ((tspr->cstat & 48) != 16)
tspriteptr[i]->ang = oang;
}
for (jj = 0; jj < numpts; jj++)
{
spr.x = (float)pp[jj].x;
spr.y = (float)pp[jj].y;
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;
}
}
}
if (ok)
{
debugmask_add(i | 32768, tspr->owner);
Polymost::polymost_drawsprite(i);
tspriteptr[i] = NULL;
}
}
}
}
debugmask_add(maskwall[maskwallcnt], thewall[maskwall[maskwallcnt]]);
Polymost::polymost_drawmaskwall(maskwallcnt);
}
while (spritesortcnt)
{
--spritesortcnt;
if (tspriteptr[spritesortcnt] != NULL)
{
debugmask_add(i | 32768, tspriteptr[i]->owner);
Polymost::polymost_drawsprite(spritesortcnt);
tspriteptr[spritesortcnt] = NULL;
}
}
renderFinishScene();
GLInterface.SetDepthMask(true);
GLInterface.SetDepthBias(0, 0);
}
void PrecacheHardwareTextures(int nTile)
{
// PRECACHE
@ -3243,3 +3767,45 @@ void PrecacheHardwareTextures(int nTile)
Polymost::polymost_precache(nTile, 0, 1);
}
//
// setrollangle
//
void renderSetRollAngle(float rolla)
{
Polymost::gtang = rolla * BAngRadian;
}
void videoSetCorrectedAspect()
{
// 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;
x = xdim;
y = ydim;
vr = DivScale(x * 3, y * 4, 16);
renderSetAspect(vr, yx);
}
//
// setaspect
//
void renderSetAspect(int32_t daxrange, int32_t daaspect)
{
if (daxrange == 65536) daxrange--; // This doesn't work correctly with 65536. All other values are fine. No idea where this is evaluated wrong.
viewingrange = daxrange;
viewingrangerecip = DivScale(1, daxrange, 32);
fviewingrange = (float)daxrange;
yxaspect = daaspect;
xyaspect = DivScale(1, yxaspect, 32);
xdimenscale = Scale(xdimen, yxaspect, 320);
xdimscale = Scale(320, xyaspect, xdimen);
}

View file

@ -22,10 +22,7 @@ using namespace Polymost;
void voxfree(voxmodel_t *m)
{
if (!m)
return;
Xfree(m);
if (m) delete m;
}
voxmodel_t *voxload(int lumpnum)
@ -33,8 +30,8 @@ voxmodel_t *voxload(int lumpnum)
FVoxel* voxel = R_LoadKVX(lumpnum);
if (voxel != nullptr)
{
voxmodel_t* vm = (voxmodel_t*)Xmalloc(sizeof(voxmodel_t));
memset(vm, 0, sizeof(voxmodel_t));
voxmodel_t* vm = new voxmodel_t;
*vm = {};
auto pivot = voxel->Mips[0].Pivot;
vm->mdnum = 1; //VOXel model id
vm->scale = vm->bscale = 1.f;
@ -53,7 +50,6 @@ voxmodel_t *voxload(int lumpnum)
}
//Draw voxel model as perfect cubes
// Note: This is a hopeless mess that totally forfeits any chance of using a vertex buffer with its messy coordinate adjustments. :(
int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr)
{
float f, g, k0, zoff;
@ -193,7 +189,7 @@ int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr)
return 1;
}
extern char* voxfilenames[MAXVOXELS];
extern int voxlumps[MAXVOXELS];
void (*PolymostProcessVoxels_Callback)(void) = NULL;
void PolymostProcessVoxels(void)
{
@ -207,17 +203,16 @@ void PolymostProcessVoxels(void)
Printf(PRINT_NONOTIFY, "Generating voxel models for Polymost. This may take a while...\n");
for (bssize_t i = 0; i < MAXVOXELS; i++)
for (int i = 0; i < MAXVOXELS; i++)
{
if (voxfilenames[i])
int lumpnum = voxlumps[i];
if (lumpnum > 0)
{
int lumpnum = fileSystem.FindFile(voxfilenames[i]);
if (lumpnum >= 0)
{
voxmodels[i] = voxload(lumpnum);
voxmodels[i] = voxload(lumpnum);
if (voxmodels[i])
voxmodels[i]->scale = voxscale[i] * (1.f / 65536.f);
}
DO_FREE_AND_NULL(voxfilenames[i]);
else
Printf("Unable to load voxel from %s\n", fileSystem.GetFileFullPath(lumpnum));
}
}
}

View file

@ -2,6 +2,7 @@
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#define MAXWIDTH 12000
#define MAXHEIGHT 5000
@ -101,3 +102,6 @@ enum EStateUseFlags
SUF_WEAPON = 4,
SUF_ITEM = 8,
};
using std::min;
using std::max;

View file

@ -73,6 +73,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "automap.h"
#include "v_draw.h"
#include "gi.h"
#include "gamefuncs.h"
CVAR(Bool, autoloadlights, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR(Bool, autoloadbrightmaps, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
@ -226,10 +227,11 @@ static IntRect System_GetSceneRect()
{
// Special handling so the view with a visible status bar displays properly
int height = windowxy2.y - windowxy1.y + 1, width = windowxy2.x - windowxy1.x + 1;
int bottomspace = screen->GetHeight() - windowxy2.y;
IntRect mSceneViewport;
mSceneViewport.left = windowxy1.x;
mSceneViewport.top = windowxy1.y;
mSceneViewport.top = (bottomspace - windowxy1.y/2);
mSceneViewport.width = width;
mSceneViewport.height = height;
return mSceneViewport;
@ -579,7 +581,7 @@ int GameMain()
TileFiles.CloseAll(); // delete the texture data before shutting down graphics.
GLInterface.Deinit();
I_ShutdownGraphics();
engineUnInit();
freeallmodels();
if (gi)
{
delete gi;

View file

@ -262,7 +262,7 @@ void GetFlatSpritePosition(const spritetype* spr, vec2_t pos, vec2_t* out)
//==========================================================================
//
// Check if some walls are set to be rotated textures.
// Check if some walls are set to use rotated textures.
// Ideally this should just have been done with texture rotation,
// but the effects on the render code would be too severe due to the alignment mess.
//

View file

@ -98,4 +98,14 @@ inline int sectorofwall(int wallNum)
return -1;
}
extern int numshades;
// Return type is int because this gets passed to variadic functions where structs may produce undefined behavior.
inline int shadeToLight(int shade)
{
shade = clamp(shade, 0, numshades - 1);
int light = Scale(numshades - 1 - shade, 255, numshades - 1);
return PalEntry(255, light, light, light);
}

View file

@ -11,6 +11,7 @@ bool System_WantGuiCapture(); // During playing this tells us whether the game m
#include "inputstate.h"
class FSerializer;
struct FRenderViewpoint;
struct GameStats
{
@ -101,7 +102,7 @@ struct GameInterface
virtual int chaseCamX(binangle ang) { return 0; }
virtual int chaseCamY(binangle ang) { return 0; }
virtual int chaseCamZ(fixedhoriz horiz) { return 0; }
virtual void processSprites(int viewx, int viewy, int viewz, binangle viewang, double smoothRatio) {}
virtual void processSprites(int viewx, int viewy, int viewz, binangle viewang, double smoothRatio) = 0;
virtual FString statFPS()
{

View file

@ -375,6 +375,9 @@ static void insertAllSprites(const char* filename, const vec3_t* pos, int16_t* c
void engineLoadBoard(const char* filename, int flags, vec3_t* pos, int16_t* ang, int16_t* cursectnum)
{
inputState.ClearAllInput();
memset(sector, 0, sizeof(*sector) * MAXSECTORS);
memset(wall, 0, sizeof(*wall) * MAXWALLS);
memset(sprite, 0, sizeof(*sector) * MAXSPRITES);
FileReader fr = fileSystem.OpenFileReader(filename);
if (!fr.isOpen()) I_Error("Unable to open map %s", filename);

View file

@ -48,6 +48,7 @@
#include "../../glbackend/glbackend.h"
LookupTableInfo lookups;
int numshades;
//==========================================================================
//
@ -136,7 +137,6 @@ void paletteLoadFromDisk(void)
void LookupTableInfo::postLoadTables(void)
{
globalpal = 0;
GPalette.GenerateGlobalBrightmapFromColormap(getTable(0), numshades);
// Try to detect fullbright translations. Unfortunately this cannot be used to detect fade strength because of loss of color precision in the palette map.

View file

@ -165,7 +165,7 @@ inline void videoclearFade()
void videoTintBlood(int32_t r, int32_t g, int32_t b);
extern int32_t globalpal, globalfloorpal;
extern int numshades;
extern void paletteLoadFromDisk(void);

View file

@ -171,17 +171,18 @@ void RenderViewpoint(FRenderViewpoint& mainvp, IntRect* bounds, float fov, float
//
//===========================================================================
FRenderViewpoint SetupView(spritetype* cam, const vec3_t& position, int sectnum, fixed_t q16angle, fixed_t q16horizon, float rollang)
FRenderViewpoint SetupViewpoint(spritetype* cam, const vec3_t& position, int sectnum, binangle angle, fixedhoriz horizon, lookangle rollang)
{
FRenderViewpoint r_viewpoint{};
r_viewpoint.CameraSprite = cam;
r_viewpoint.SectNum = sectnum;
r_viewpoint.SectNums = nullptr;
r_viewpoint.SectCount = sectnum;
r_viewpoint.Pos = { position.x / 16.f, position.y / -16.f, position.z / -256.f };
r_viewpoint.HWAngles.Yaw = -90.f + q16ang(q16angle).asdeg();
r_viewpoint.HWAngles.Pitch = -HorizToPitch(q16horizon);
r_viewpoint.HWAngles.Roll = -rollang;
r_viewpoint.HWAngles.Yaw = -90.f + angle.asdeg();
r_viewpoint.HWAngles.Pitch = -horizon.aspitch();
r_viewpoint.HWAngles.Roll = -rollang.asdeg();
r_viewpoint.FieldOfView = (float)r_fov;
r_viewpoint.RotAngle = q16ang(q16angle).asbam();
r_viewpoint.RotAngle = angle.asbam();
return r_viewpoint;
}
@ -263,7 +264,7 @@ static void CheckTimer(FRenderState &state, uint64_t ShaderStartTime)
}
void render_drawrooms(spritetype* playersprite, const vec3_t& position, int sectnum, fixed_t q16angle, fixed_t q16horizon, float rollang)
void render_drawrooms(spritetype* playersprite, const vec3_t& position, int sectnum, binangle angle, fixedhoriz horizon, lookangle rollang)
{
checkRotatedWalls();
@ -278,7 +279,7 @@ void render_drawrooms(spritetype* playersprite, const vec3_t& position, int sect
RenderState->SetVertexBuffer(screen->mVertexData);
screen->mVertexData->Reset();
FRenderViewpoint r_viewpoint = SetupView(playersprite, position, sectnum, q16angle, q16horizon, rollang);
FRenderViewpoint r_viewpoint = SetupViewpoint(playersprite, position, sectnum, angle, horizon, rollang);
iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0;
checkBenchActive();

View file

@ -3,7 +3,7 @@
class FSerializer;
void render_drawrooms(spritetype* playersprite, const vec3_t& position, int sectnum, fixed_t q16angle, fixed_t q16horizon, float rollang);
void render_drawrooms(spritetype* playersprite, const vec3_t& position, int sectnum, binangle angle, fixedhoriz horizon, lookangle rollang);
struct PortalDesc
{
@ -26,7 +26,7 @@ inline int portalAdd(int type, int target, int dx = 0, int dy = 0, int dz = 0)
{
auto& pt = allPortals[allPortals.Reserve(1)];
pt.type = type;
pt.targets.Push(target);
if (target >= 0) pt.targets.Push(target);
pt.dx = dx;
pt.dy = dy;
pt.dz = dz;
@ -50,7 +50,7 @@ inline void mergePortals()
{
auto& pt2 = allPortals[j];
if (pt1.type != pt2.type || pt1.dx != pt2.dx || pt1.dy != pt2.dy || pt1.dz != pt2.dz) continue;
for (unsigned s = 0; s < pt1.targets.Size(); s++)
for (unsigned s = 0; s < pt1.targets.Size() && pt2.targets.Size(); s++)
{
for (unsigned t = 0; t < pt2.targets.Size(); t++)
{
@ -63,9 +63,9 @@ inline void mergePortals()
{
//Printf("Merged %d and %d\n", i, j);
if (sector[n].portalnum == j) sector[n].portalnum = i;
didsomething = true;
break;
}
didsomething = true;
break;
}
}
}

View file

@ -38,6 +38,7 @@
#include "hw_drawstructs.h"
#include "automap.h"
#include "gamefuncs.h"
#include "hw_portal.h"
//==========================================================================
@ -52,8 +53,13 @@ void BunchDrawer::Init(HWDrawInfo *_di, Clipper* c, vec2_t& view)
clipper = c;
viewx = view.x * (1/ 16.f);
viewy = view.y * -(1/ 16.f);
iview = view;
StartScene();
clipper->SetViewpoint(view);
gcosang = bamang(di->Viewpoint.RotAngle).fcos();
gsinang = bamang(di->Viewpoint.RotAngle).fsin();
for (int i = 0; i < numwalls; i++)
{
// Precalculate the clip angles to avoid doing this repeatedly during level traversal.
@ -119,15 +125,6 @@ void BunchDrawer::DeleteBunch(int index)
bool BunchDrawer::CheckClip(walltype* wal)
{
#ifdef _DEBUG
if (wal - wall == 843 || wal - wall == 847)
{
int a = 0;
}
#endif
auto pt2 = &wall[wal->point2];
sectortype* backsector = &sector[wal->nextsector];
sectortype* frontsector = &sector[wall[wal->nextwall].nextsector];
@ -427,16 +424,41 @@ void BunchDrawer::ProcessSector(int sectnum)
if (gotsector[sectnum]) return;
gotsector.Set(sectnum);
Bsp.Clock();
auto sect = &sector[sectnum];
bool inbunch;
binangle startangle;
SetupSprite.Clock();
int z;
SectIterator it(sectnum);
while ((z = it.NextIndex()) >= 0)
{
auto const spr = (uspriteptr_t)&sprite[z];
if ((spr->cstat & CSTAT_SPRITE_INVISIBLE) || spr->xrepeat == 0 || spr->yrepeat == 0) // skip invisible sprites
continue;
int sx = spr->x - iview.x, sy = spr->y - int(iview.y);
// this checks if the sprite is it behind the camera, which will not work if the pitch is high enough to necessitate a FOV of more than 180°.
//if ((spr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) || (hw_models && tile2model[spr->picnum].modelid >= 0) || ((sx * gcosang) + (sy * gsinang) > 0))
{
if ((spr->cstat & (CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_ALIGNMENT_MASK)) != (CSTAT_SPRITE_ONE_SIDED | CSTAT_SPRITE_ALIGNMENT_WALL) ||
(r_voxels && tiletovox[spr->picnum] >= 0 && voxmodels[tiletovox[spr->picnum]]) ||
DMulScale(bcos(spr->ang), -sx, bsin(spr->ang), -sy, 6) > 0)
if (renderAddTsprite(z, sectnum))
break;
}
}
SetupSprite.Unclock();
SetupFlat.Clock();
HWFlat flat;
flat.ProcessSector(di, &sector[sectnum]);
SetupFlat.Unclock();
Bsp.Clock();
//Todo: process subsectors
inbunch = false;
@ -491,9 +513,10 @@ void BunchDrawer::ProcessSector(int sectnum)
//
//==========================================================================
void BunchDrawer::RenderScene(int viewsector)
void BunchDrawer::RenderScene(const int* viewsectors, unsigned sectcount)
{
ProcessSector(viewsector);
for(unsigned i=0;i<sectcount;i++)
ProcessSector(viewsectors[i]);
while (Bunches.Size() > 0)
{
int closest = FindClosestBunch();

View file

@ -24,6 +24,8 @@ class BunchDrawer
TArray<FBunch> Bunches;
TArray<int> CompareData;
double viewx, viewy;
vec2_t iview;
float gcosang, gsinang;
FixedBitArray<MAXSECTORS> gotsector;
private:
@ -50,5 +52,5 @@ private:
public:
void Init(HWDrawInfo* _di, Clipper* c, vec2_t& view);
void RenderScene(int viewsector);
void RenderScene(const int* viewsectors, unsigned sectcount);
};

View file

@ -39,6 +39,7 @@
#include "hw_clipper.h"
#include "v_draw.h"
#include "gamecvars.h"
#include "gamestruct.h"
EXTERN_CVAR(Float, r_visibility)
CVAR(Bool, gl_bandedswlight, false, CVAR_ARCHIVE)
@ -306,9 +307,18 @@ void HWDrawInfo::CreateScene()
screen->mVertexData->Map();
screen->mLights->Map();
spritesortcnt = 0;
vec2_t view = { int(vp.Pos.X * 16), int(vp.Pos.Y * -16) };
mDrawer.Init(this, mClipper, view);
mDrawer.RenderScene(vp.SectNum);
if (vp.SectNums)
mDrawer.RenderScene(vp.SectNums, vp.SectCount);
else
mDrawer.RenderScene(&vp.SectCount, 1);
SetupSprite.Clock();
gi->processSprites(view.x, view.y, vp.Pos.Z * -256, bamang(vp.RotAngle), vp.TicFrac * 65536);
SetupSprite.Unclock();
screen->mLights->Unmap();
screen->mVertexData->Unmap();

View file

@ -40,7 +40,8 @@ struct FRenderViewpoint
FRotator HWAngles;
FAngle FieldOfView;
angle_t RotAngle;
int SectNum;
int* SectNums;
int SectCount;
double TicFrac;
};
//==========================================================================

View file

@ -32,6 +32,7 @@
#include "flatvertices.h"
#include "hw_clock.h"
#include "texturemanager.h"
#include "gamestruct.h"
EXTERN_CVAR(Int, r_mirror_recursions)
EXTERN_CVAR(Bool, gl_portals)
@ -398,6 +399,7 @@ void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestenci
void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper)
{
auto outer_di = di->outer;
#if 0 // todo: fixme or remove - Unlike for Doom this won't be of great benefit with Build's rendering approach.
// This requires maximum precision, so convert everything to double.
DAngle angleOffset = deltaangle(DAngle(outer_di->Viewpoint.HWAngles.Yaw.Degrees), DAngle(di->Viewpoint.HWAngles.Yaw.Degrees));
@ -418,6 +420,7 @@ void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper)
clipper->SafeRemoveClipRange(startang, endang);
}
}
#endif
// and finally clip it to the visible area
angle_t a1 = di->FrustumAngle();
@ -554,7 +557,9 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe
int newy = int((y << 1) + Scale(dy, i, j) - view.y);
int newan = ((gethiq16angle(dx, dy) << 1) - bamang(vp.RotAngle).asq16()) & 0x7FFFFFF;
vp.RotAngle = q16ang(newan).asbam();
vp.SectNum = line->sector;
vp.SectNums = nullptr;
vp.SectCount = line->sector;
vp.Pos.X = newx / 16.f;
vp.Pos.Y = newy / -16.f;
@ -636,7 +641,8 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl
int origx = vp.Pos.X * 16;
int origy = vp.Pos.Y * -16;
vp.SectNum = line->sector;
vp.SectNums = nullptr;
vp.SectCount = line->sector;
vp.Pos.X = npos.X;
vp.Pos.Y = npos.Y;
@ -689,7 +695,8 @@ bool HWLineToSpritePortal::Setup(HWDrawInfo* di, FRenderState& rstate, Clipper*
int origx = vp.Pos.X * 16;
int origy = vp.Pos.Y * -16;
vp.SectNum = camera->sectnum;
vp.SectNums = nullptr;
vp.SectCount = camera->sectnum;
vp.Pos.X = npos.X;
vp.Pos.Y = npos.Y;
@ -798,16 +805,23 @@ bool HWSkyboxPortal::AllowSSAO() { return false; } // [MK] sector skyboxes don't
//-----------------------------------------------------------------------------
bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
{
auto state = mState;
// TODO: Handle recursion more intelligently
auto& state = mState;
if (state->renderdepth > r_mirror_recursions)
{
return false;
}
auto portal = origin;
auto &vp = di->Viewpoint;
vp.Pos += DVector3(portal->dx / 16., portal->dy / -16., portal->dz / -256.);
//vp.ActorPos += origin->mDisplacement;
//vp.ViewActor = nullptr;
vp.SectNums = portal->targets.Data();
vp.SectCount = portal->targets.Size();
type = origin->type;
state->insectorportal = true;
// avoid recursions!
screen->instack[origin->type == PORTAL_SECTOR_CEILING ? 1 : 0]++;
screen->instack[type == PORTAL_SECTOR_CEILING ? 1 : 0]++;
di->SetupView(rstate, vp.Pos.X, vp.Pos.Y, vp.Pos.Z, !!(state->MirrorFlag & 1), !!(state->PlaneMirrorFlag & 1));
//SetupCoverage(di);
@ -819,7 +833,8 @@ bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c
void HWSectorStackPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
{
screen->instack[origin->type == PORTAL_SECTOR_CEILING ? 1 : 0]--;
screen->instack[type == PORTAL_SECTOR_CEILING ? 1 : 0]--;
mState->insectorportal = false;
}
const char *HWSectorStackPortal::GetName() { return "Sectorstack"; }
@ -829,7 +844,7 @@ const char *HWSectorStackPortal::GetName() { return "Sectorstack"; }
//-----------------------------------------------------------------------------
//
//
// Plane Mirror Portal
// Plane Mirror Portal (currently not needed, Witchaven 2 is the only Build game using such a feature)
//
//
//-----------------------------------------------------------------------------

View file

@ -182,6 +182,7 @@ struct FPortalSceneState
int PlaneMirrorMode = 0;
bool inskybox = 0;
bool insectorportal = false;
UniqueList<HWSkyInfo> UniqueSkies;
UniqueList<HWHorizonInfo> UniqueHorizons;
@ -350,6 +351,7 @@ public:
struct HWSectorStackPortal : public HWScenePortalBase
{
TArray<sectortype *> sectors;
int type = -1;
protected:
bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) override;
void Shutdown(HWDrawInfo *di, FRenderState &rstate) override;

View file

@ -81,13 +81,13 @@ void HWWall::SkyPlane(HWDrawInfo *di, sectortype *sector, int plane, bool allowr
{
int ptype;
if (sector->portalflags == PORTAL_SECTOR_CEILING || sector->portalflags == PORTAL_SECTOR_FLOOR)
if ((sector->portalflags == PORTAL_SECTOR_CEILING && plane == plane_ceiling) || (sector->portalflags == PORTAL_SECTOR_FLOOR && plane == plane_floor))
{
if (screen->instack[1 - plane] || allPortals.Size() == 0) return;
if (screen->instack[1 - plane] || sector->portalnum >= (int)allPortals.Size()) return;
portal = &allPortals[sector->portalnum];
PutPortal(di, PORTALTYPE_SECTORSTACK, plane);
}
else if (sector->portalflags == PORTAL_SECTOR_CEILING_REFLECT || sector->portalflags == PORTAL_SECTOR_FLOOR_REFLECT)
else if ((sector->portalflags == PORTAL_SECTOR_CEILING_REFLECT && plane == plane_ceiling) || (sector->portalflags == PORTAL_SECTOR_FLOOR_REFLECT && plane == plane_floor))
{
ptype = PORTALTYPE_PLANEMIRROR;
if (plane == plane_ceiling && (sector->ceilingstat & CSTAT_SECTOR_SLOPE)) return;
@ -115,7 +115,7 @@ void HWWall::SkyPlane(HWDrawInfo *di, sectortype *sector, int plane, bool allowr
void HWWall::SkyNormal(HWDrawInfo* di, sectortype* fs, FVector2& v1, FVector2& v2, float fch1, float fch2, float ffh1, float ffh2)
{
if (fs->ceilingstat & CSTAT_SECTOR_SKY)
if ((fs->ceilingstat & CSTAT_SECTOR_SKY) || fs->portalflags == PORTAL_SECTOR_CEILING || fs->portalflags == PORTAL_SECTOR_CEILING_REFLECT)
{
ztop[0] = ztop[1] = 32768.0f;
zbottom[0] = fch1;
@ -123,7 +123,7 @@ void HWWall::SkyNormal(HWDrawInfo* di, sectortype* fs, FVector2& v1, FVector2& v
SkyPlane(di, fs, plane_ceiling, true);
}
if (fs->floorstat & CSTAT_SECTOR_SKY)
if ((fs->floorstat & CSTAT_SECTOR_SKY) || fs->portalflags == PORTAL_SECTOR_FLOOR || fs->portalflags == PORTAL_SECTOR_FLOOR_REFLECT)
{
ztop[0] = ffh1;
ztop[1] = ffh2;

View file

@ -496,6 +496,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, spritetype &c, spritet
("hitag", c.hitag, def->hitag)
("extra", c.extra, def->extra)
("detail", c.detail, def->detail)
("time", c.time, def->time)
.EndObject();
}
return arc;

View file

@ -917,10 +917,10 @@ bool AddINIFile(const char* pzFile, bool bForce = false)
if (findfrompath(pzFile, &pzFN)) return false; // failed to resolve the filename
if (!FileExists(pzFN))
{
Xfree(pzFN);
M_Free(pzFN);
return false;
} // failed to stat the file
Xfree(pzFN);
M_Free(pzFN);
IniFile* pTempIni = new IniFile(pzFile);
if (!pTempIni->FindSection("Episode1"))
{

View file

@ -632,7 +632,7 @@ void artSetupMapArt(const char* filename)
}
for (bssize_t i = 0; i < MAXARTFILES_TOTAL - MAXARTFILES_BASE; i++)
for (int i = 0; i < MAXARTFILES_TOTAL - MAXARTFILES_BASE; i++)
{
FStringf fullname("%s_%02d.art", filename, i);
TileFiles.LoadArtFile(fullname, filename);

View file

@ -126,7 +126,7 @@ static tspritetype *viewAddEffect(int nTSprite, VIEW_EFFECT nViewEffect)
{
assert(nViewEffect >= 0 && nViewEffect < kViewEffectMax);
auto pTSprite = &tsprite[nTSprite];
if (gDetail < effectDetail[nViewEffect] || nTSprite >= maxspritesonscreen) return NULL;
if (gDetail < effectDetail[nViewEffect] || nTSprite >= MAXSPRITESONSCREEN) return NULL;
switch (nViewEffect)
{
case VIEW_EFFECT_18:
@ -220,7 +220,7 @@ static tspritetype *viewAddEffect(int nTSprite, VIEW_EFFECT nViewEffect)
{
nAng = (nAng+1024)&2047;
}
for (int i = 0; i < 5 && spritesortcnt < maxspritesonscreen; i++)
for (int i = 0; i < 5 && spritesortcnt < MAXSPRITESONSCREEN; i++)
{
int nSector = pTSprite->sectnum;
auto pNSprite = viewInsertTSprite<tspritetype>(nSector, 32767, NULL);
@ -433,7 +433,7 @@ void viewProcessSprites(int32_t cX, int32_t cY, int32_t cZ, int32_t cA, int32_t
{
// shift before interpolating to increase precision.
int myclock = (PlayClock<<3) + MulScale(4<<3, smoothratio, 16);
assert(spritesortcnt <= maxspritesonscreen);
assert(spritesortcnt <= MAXSPRITESONSCREEN);
gCameraAng = cA;
int nViewSprites = spritesortcnt;
for (int nTSprite = spritesortcnt-1; nTSprite >= 0; nTSprite--)
@ -633,7 +633,7 @@ void viewProcessSprites(int32_t cX, int32_t cY, int32_t cZ, int32_t cA, int32_t
pTSprite->xrepeat = pTSprite->yrepeat = 0;
}
}
if (spritesortcnt >= maxspritesonscreen) continue;
if (spritesortcnt >= MAXSPRITESONSCREEN) continue;
if (pTXSprite && pTXSprite->burnTime > 0)
{
pTSprite->shade = ClipRange(pTSprite->shade-16-QRandom(8), -128, 127);

View file

@ -112,7 +112,6 @@ void StartLevel(MapRecord* level)
}
}
memset(xsprite, 0, sizeof(xsprite));
memset(sprite, 0, kMaxSprites * sizeof(spritetype));
//drawLoadingScreen();
dbLoadMap(currentLevel->fileName, (int*)&startpos.x, (int*)&startpos.y, (int*)&startpos.z, &startang, &startsectnum, nullptr);
SECRET_SetMapName(currentLevel->DisplayName(), currentLevel->name);

View file

@ -201,6 +201,7 @@ int InsertSprite(int nSector, int nStat)
Numsprites++;
sprite[nSprite].time = leveltimer++;
return nSprite;
}
@ -512,6 +513,10 @@ void dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, shor
gModernMap = false;
#endif
memset(sector, 0, sizeof(*sector) * MAXSECTORS);
memset(wall, 0, sizeof(*wall) * MAXWALLS);
memset(sprite, 0, sizeof(*sector) * MAXSPRITES);
#ifdef USE_OPENGL
Polymost::Polymost_prepare_loadboard();
#endif

View file

@ -157,7 +157,6 @@ void hudDraw(PLAYER *gView, int nSectnum, double bobx, double boby, double zDelt
{
DoLensEffect();
viewingRange = viewingrange;
yxAspect = yxaspect;
r otatesprite(IntToFixed(280), IntToFixed(35), 53248, 512, 4077, v10, v14, 512 + 6, gViewX0, gViewY0, gViewX1, gViewY1);
r otatesprite(IntToFixed(280), IntToFixed(35), 53248, 0, 1683, v10, 0, 512 + 35, gViewX0, gViewY0, gViewX1, gViewY1);
}

View file

@ -136,7 +136,7 @@ void InitMirrors(void)
mirror[mirrorcnt].link = i;
sector[j].ceilingpicnum = 4080+mirrorcnt;
sector[j].portalflags = PORTAL_SECTOR_CEILING;
sector[i].portalnum = portalAdd(PORTAL_SECTOR_CEILING, j, mirror[mirrorcnt].dx, mirror[mirrorcnt].dy, mirror[mirrorcnt].dz);
sector[j].portalnum = portalAdd(PORTAL_SECTOR_CEILING, i, mirror[mirrorcnt].dx, mirror[mirrorcnt].dy, mirror[mirrorcnt].dz);
mirrorcnt++;
}
}

View file

@ -772,10 +772,10 @@ void viewDrawScreen(bool sceneonly)
if (testnewrenderer)
{
fixed_t deliriumPitchI = interpolate(IntToFixed(deliriumPitchO), IntToFixed(deliriumPitch), gInterpolate);
fixedhoriz deliriumPitchI = q16horiz(interpolate(IntToFixed(deliriumPitchO), IntToFixed(deliriumPitch), gInterpolate));
int bakCstat = gView->pSprite->cstat;
gView->pSprite->cstat |= (gViewPos == 0) ? CSTAT_SPRITE_INVISIBLE : CSTAT_SPRITE_TRANSLUCENT | CSTAT_SPRITE_TRANSLUCENT_INVERT;
render_drawrooms(gView->pSprite, { cX, cY, cZ }, nSectnum, cA.asq16(), cH.asq16() + deliriumPitchI, rotscrnang.asbuildf());
render_drawrooms(gView->pSprite, { cX, cY, cZ }, nSectnum, cA, cH + deliriumPitchI, rotscrnang);
gView->pSprite->cstat = bakCstat;
}
else
@ -868,8 +868,6 @@ bool GameInterface::DrawAutomapPlayer(int x, int y, int z, int a, double const s
// [MR]: Confirm that this is correct as math doesn't match the variable names.
int nCos = z * -bsin(a);
int nSin = z * -bcos(a);
int nCos2 = MulScale(nCos, yxaspect, 16);
int nSin2 = MulScale(nSin, yxaspect, 16);
int nPSprite = gView->pSprite->index;
for (int i = connecthead; i >= 0; i = connectpoint2[i])
@ -886,7 +884,7 @@ bool GameInterface::DrawAutomapPlayer(int x, int y, int z, int a, double const s
GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, (pSprite->clipdist << 2) + 16, CLIPMASK0, PARALLAXCLIP_CEILING | PARALLAXCLIP_FLOOR);
int nTop, nBottom;
GetSpriteExtents(pSprite, &nTop, &nBottom);
int nScale = MulScale((pSprite->yrepeat + ((floorZ - nBottom) >> 8)) * z, yxaspect, 16);
int nScale = (pSprite->yrepeat + ((floorZ - nBottom) >> 8)) * z;
nScale = ClipRange(nScale, 8000, 65536 << 1);
// Players on automap
double x = xdim / 2. + x1 / double(1 << 12);

View file

@ -41,6 +41,7 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
#include "mapinfo.h"
#include "c_dispatch.h"
#include "gamestate.h"
#include "gamefuncs.h"
BEGIN_DUKE_NS

View file

@ -39,6 +39,7 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
#include "texturemanager.h"
#include "c_dispatch.h"
#include "gamestate.h"
#include "gamefuncs.h"
BEGIN_DUKE_NS

View file

@ -65,6 +65,7 @@ struct GameInterface : public ::GameInterface
int chaseCamX(binangle ang) { return -ang.bcos(-4); }
int chaseCamY(binangle ang) { return -ang.bsin(-4); }
int chaseCamZ(fixedhoriz horiz) { return horiz.asq16() >> 9; }
void processSprites(int viewx, int viewy, int viewz, binangle viewang, double smoothRatio) override;
};

View file

@ -399,15 +399,13 @@ bool GameInterface::DrawAutomapPlayer(int cposx, int cposy, int czoom, int cang,
int i, j, k, l, x1, y1, x2, y2, x3, y3, x4, y4, ox, oy, xoff, yoff;
int dax, day, cosang, sinang, xspan, yspan, sprx, spry;
int xrepeat, yrepeat, tilenum, daang;
int xvect, yvect, xvect2, yvect2;
int xvect, yvect;
int p;
PalEntry col;
spritetype* spr;
xvect = -bsin(cang) * czoom;
yvect = -bcos(cang) * czoom;
xvect2 = MulScale(xvect, yxaspect, 16);
yvect2 = MulScale(yvect, yxaspect, 16);
//Draw sprites
auto pactor = ps[screenpeek].GetActor();
@ -435,15 +433,15 @@ bool GameInterface::DrawAutomapPlayer(int cposx, int cposy, int czoom, int cang,
ox = sprx - cposx;
oy = spry - cposy;
x1 = DMulScale(ox, xvect, -oy, yvect, 16);
y1 = DMulScale(oy, xvect2, ox, yvect2, 16);
y1 = DMulScale(oy, xvect, ox, yvect, 16);
ox = bcos(spr->ang, -7);
oy = bsin(spr->ang, -7);
x2 = DMulScale(ox, xvect, -oy, yvect, 16);
y2 = DMulScale(oy, xvect, ox, yvect, 16);
x3 = MulScale(x2, yxaspect, 16);
y3 = MulScale(y2, yxaspect, 16);
x3 = x2;
y3 = y2;
drawlinergb(x1 - x2 + (xdim << 11), y1 - y3 + (ydim << 11),
x1 + x2 + (xdim << 11), y1 + y3 + (ydim << 11), col);
@ -475,12 +473,12 @@ bool GameInterface::DrawAutomapPlayer(int cposx, int cposy, int czoom, int cang,
ox = x1 - cposx;
oy = y1 - cposy;
x1 = DMulScale(ox, xvect, -oy, yvect, 16);
y1 = DMulScale(oy, xvect2, ox, yvect2, 16);
y1 = DMulScale(oy, xvect, ox, yvect, 16);
ox = x2 - cposx;
oy = y2 - cposy;
x2 = DMulScale(ox, xvect, -oy, yvect, 16);
y2 = DMulScale(oy, xvect2, ox, yvect2, 16);
y2 = DMulScale(oy, xvect, ox, yvect, 16);
drawlinergb(x1 + (xdim << 11), y1 + (ydim << 11),
x2 + (xdim << 11), y2 + (ydim << 11), col);
@ -521,22 +519,22 @@ bool GameInterface::DrawAutomapPlayer(int cposx, int cposy, int czoom, int cang,
ox = x1 - cposx;
oy = y1 - cposy;
x1 = DMulScale(ox, xvect, -oy, yvect, 16);
y1 = DMulScale(oy, xvect2, ox, yvect2, 16);
y1 = DMulScale(oy, xvect, ox, yvect, 16);
ox = x2 - cposx;
oy = y2 - cposy;
x2 = DMulScale(ox, xvect, -oy, yvect, 16);
y2 = DMulScale(oy, xvect2, ox, yvect2, 16);
y2 = DMulScale(oy, xvect, ox, yvect, 16);
ox = x3 - cposx;
oy = y3 - cposy;
x3 = DMulScale(ox, xvect, -oy, yvect, 16);
y3 = DMulScale(oy, xvect2, ox, yvect2, 16);
y3 = DMulScale(oy, xvect, ox, yvect, 16);
ox = x4 - cposx;
oy = y4 - cposy;
x4 = DMulScale(ox, xvect, -oy, yvect, 16);
y4 = DMulScale(oy, xvect2, ox, yvect2, 16);
y4 = DMulScale(oy, xvect, ox, yvect, 16);
drawlinergb(x1 + (xdim << 11), y1 + (ydim << 11),
x2 + (xdim << 11), y2 + (ydim << 11), col);
@ -571,7 +569,7 @@ bool GameInterface::DrawAutomapPlayer(int cposx, int cposy, int czoom, int cang,
i = TILE_APLAYERTOP;
j = abs(pp.truefz - pp.posz) >> 8;
j = MulScale(czoom * (pspr->yrepeat + j), yxaspect, 16);
j = czoom * (pspr->yrepeat + j);
if (j < 22000) j = 22000;
else if (j > (65536 << 1)) j = (65536 << 1);

View file

@ -924,7 +924,7 @@ static void SpawnPortals()
if (findwallbetweensectors(i, t) >= 0)
{
sector[i].portalflags = PORTAL_SECTOR_FLOOR;
sector[i].portalnum = uint8_t(&pt - allPortals.Data());
sector[i].portalnum = uint8_t(1 ^ (&pt - allPortals.Data()));
pt.targets.Push(i);
goto nexti;
}
@ -943,7 +943,7 @@ static void SpawnPortals()
if (findwallbetweensectors(i, t) >= 0)
{
sector[i].portalflags = PORTAL_SECTOR_CEILING;
sector[i].portalnum = uint8_t(&pt - allPortals.Data());
sector[i].portalnum = uint8_t(1 ^ (&pt - allPortals.Data()));
pt.targets.Push(i);
goto nexti;
}

View file

@ -82,7 +82,7 @@ void renderView(spritetype* playersprite, int sectnum, int x, int y, int z, bina
}
else
{
render_drawrooms(playersprite, { x, y, z }, sectnum, a.asq16(), h.asq16(), rotscrnang.asbuildf());
render_drawrooms(playersprite, { x, y, z }, sectnum, a, h, rotscrnang);
}
}
@ -125,7 +125,7 @@ void animatecamsprite(double smoothratio)
}
else
{
render_drawrooms(camera, camera->pos, camera->sectnum, ang.asq16(), IntToFixed(camera->shade), 0);
render_drawrooms(camera, camera->pos, camera->sectnum, ang, buildhoriz(camera->shade), buildlook(0));
}
display_mirror = 0;
renderDrawMasks();
@ -414,6 +414,10 @@ bool GameInterface::GenerateSavePic()
return true;
}
void GameInterface::processSprites(int viewx, int viewy, int viewz, binangle viewang, double smoothRatio)
{
fi.animatesprites(viewx, viewy, viewz, int(smoothRatio));
}
END_DUKE_NS

View file

@ -38,6 +38,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "v_draw.h"
#include "m_random.h"
#include "gstrings.h"
#include "gamefuncs.h"
#include <string>

View file

@ -255,6 +255,7 @@ struct GameInterface : ::GameInterface
int chaseCamX(binangle ang) { return -ang.bcos() / 12; }
int chaseCamY(binangle ang) { return -ang.bsin() / 12; }
int chaseCamZ(fixedhoriz horiz) { return horiz.asq16() / 384; }
void processSprites(int viewx, int viewy, int viewz, binangle viewang, double smoothRatio) override;
::GameStats getStats() override;
};

View file

@ -77,8 +77,6 @@ bool GameInterface::DrawAutomapPlayer(int x, int y, int z, int a, double const s
// [MR]: Confirm that this is correct as math doesn't match the variable names.
int nCos = z * -bsin(a);
int nSin = z * -bcos(a);
int nCos2 = MulScale(nCos, yxaspect, 16);
int nSin2 = MulScale(nSin, yxaspect, 16);
for (int i = connecthead; i >= 0; i = connectpoint2[i])
{
@ -94,7 +92,7 @@ bool GameInterface::DrawAutomapPlayer(int x, int y, int z, int a, double const s
getzrange_old(pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, &ceilZ, &ceilHit, &floorZ, &floorHit, (pSprite->clipdist << 2) + 16, CLIPMASK0);
int nTop, nBottom;
GetSpriteExtents(pSprite, &nTop, &nBottom);
int nScale = MulScale((pSprite->yrepeat + ((floorZ - nBottom) >> 8)) * z, yxaspect, 16);
int nScale = (pSprite->yrepeat + ((floorZ - nBottom) >> 8)) * z;
nScale = clamp(nScale, 8000, 65536 << 1);
// Players on automap
double x = xdim / 2. + x1 / double(1 << 12);

View file

@ -66,7 +66,7 @@ short enemy;
short nEnemyPal = 0;
// NOTE - not to be confused with Ken's analyzesprites()
static void analyzesprites(double const smoothratio)
static void analyzesprites(int x, int y, int z, double const smoothratio)
{
tspritetype *pTSprite;
@ -90,11 +90,6 @@ static void analyzesprites(double const smoothratio)
besttarget = -1;
int x = pPlayerSprite->x;
int y = pPlayerSprite->y;
int z = pPlayerSprite->z - (GetSpriteHeight(nPlayerSprite) / 2);
short nSector = pPlayerSprite->sectnum;
int nAngle = (2048 - pPlayerSprite->ang) & kAngleMask;
@ -362,12 +357,12 @@ void DrawView(double smoothRatio, bool sceneonly)
{
renderSetRollAngle(rotscrnang.asbuildf());
renderDrawRoomsQ16(nCamerax, nCameray, viewz, nCameraa.asq16(), nCamerapan.asq16(), nSector);
analyzesprites(smoothRatio);
analyzesprites(nCamerax, nCameray, viewz, smoothRatio);
renderDrawMasks();
}
else
{
render_drawrooms(nullptr, { nCamerax, nCameray, viewz }, nSector, nCameraa.asq16(), nCamerapan.asq16(), rotscrnang.asbuildf());
render_drawrooms(nullptr, { nCamerax, nCameray, viewz }, nSector, nCameraa, nCamerapan, rotscrnang);
}
if (HavePLURemap())
@ -467,6 +462,12 @@ bool GameInterface::GenerateSavePic()
return true;
}
void GameInterface::processSprites(int viewx, int viewy, int viewz, binangle viewang, double smoothRatio)
{
analyzesprites(viewx, viewy, viewz, smoothRatio);
}
void NoClip()
{
}

View file

@ -1,310 +1,7 @@
BEGIN_SW_NS
short GlobStackSect[2];
void
GetUpperLowerSector(short match, int x, int y, short* upper, short* lower)
{
int i;
short sectorlist[16];
int sln = 0;
int SpriteNum;
SPRITEp sp;
// keep a list of the last stacked sectors the view was in and
// check those fisrt
sln = 0;
for (i = 0; i < (int)SIZ(GlobStackSect); i++)
{
// will not hurt if GlobStackSect is invalid - inside checks for this
if (inside(x, y, GlobStackSect[i]) == 1)
{
bool found = false;
SectIterator it(GlobStackSect[i]);
while ((SpriteNum = it.NextIndex()) >= 0)
{
sp = &sprite[SpriteNum];
if (sp->statnum == STAT_FAF &&
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
&& sp->lotag == match)
{
found = true;
}
}
if (!found)
continue;
sectorlist[sln] = GlobStackSect[i];
sln++;
}
}
// didn't find it yet so test ALL sectors
if (sln < 2)
{
sln = 0;
for (i = numsectors - 1; i >= 0; i--)
{
if (inside(x, y, (short)i) == 1)
{
bool found = false;
SectIterator it(i);
while ((SpriteNum = it.NextIndex()) >= 0)
{
sp = &sprite[SpriteNum];
if (sp->statnum == STAT_FAF &&
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
&& sp->lotag == match)
{
found = true;
}
}
if (!found)
continue;
if (sln < (int)SIZ(GlobStackSect))
GlobStackSect[sln] = i;
if (sln < (int)SIZ(sectorlist))
sectorlist[sln] = i;
sln++;
}
}
}
// might not find ANYTHING if not tagged right
if (sln == 0)
{
*upper = -1;
*lower = -1;
return;
}
// Map rooms have NOT been dragged on top of each other
else if (sln == 1)
{
*lower = sectorlist[0];
*upper = sectorlist[0];
return;
}
// Map rooms HAVE been dragged on top of each other
// inside will somtimes find that you are in two different sectors if the x,y
// is exactly on a sector line.
else if (sln > 2)
{
//DSPRINTF(ds, "TOO MANY SECTORS FOUND: x=%d, y=%d, match=%d, num sectors %d, %d, %d, %d, %d, %d", x, y, match, sln, sectorlist[0], sectorlist[1], sectorlist[2], sectorlist[3], sectorlist[4]);
MONO_PRINT(ds);
// try again moving the x,y pos around until you only get two sectors
GetUpperLowerSector(match, x - 1, y, upper, lower);
}
if (sln == 2)
{
if (sector[sectorlist[0]].floorz < sector[sectorlist[1]].floorz)
{
// swap
// make sectorlist[0] the LOW sector
short hold;
hold = sectorlist[0];
sectorlist[0] = sectorlist[1];
sectorlist[1] = hold;
}
*lower = sectorlist[0];
*upper = sectorlist[1];
}
}
bool
FindCeilingView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
{
int xoff = 0;
int yoff = 0;
int i;
SPRITEp sp = NULL;
int pix_diff;
int newz;
save.zcount = 0;
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
StatIterator it(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->hitag == VIEW_THRU_CEILING && sp->lotag == match)
{
xoff = *x - sp->x;
yoff = *y - sp->y;
break;
}
}
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// determine x,y position
if (sp->hitag == VIEW_THRU_FLOOR)
{
short upper, lower;
*x = sp->x + xoff;
*y = sp->y + yoff;
// get new sector
GetUpperLowerSector(match, *x, *y, &upper, &lower);
*sectnum = upper;
break;
}
}
}
if (*sectnum < 0)
return false;
ASSERT(sp);
ASSERT(sp->hitag == VIEW_THRU_FLOOR);
pix_diff = labs(z - sector[sp->sectnum].floorz) >> 8;
newz = sector[sp->sectnum].floorz + ((pix_diff / 128) + 1) * Z(128);
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// move lower levels ceilings up for the correct view
if (sp->hitag == VIEW_LEVEL2)
{
// save it off
save.sectnum[save.zcount] = sp->sectnum;
save.zval[save.zcount] = sector[sp->sectnum].floorz;
save.pic[save.zcount] = sector[sp->sectnum].floorpicnum;
save.slope[save.zcount] = sector[sp->sectnum].floorheinum;
sector[sp->sectnum].floorz = newz;
// don't change FAF_MIRROR_PIC - ConnectArea
if (sector[sp->sectnum].floorpicnum != FAF_MIRROR_PIC)
sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC + 1;
sector[sp->sectnum].floorheinum = 0;
save.zcount++;
PRODUCTION_ASSERT(save.zcount < ZMAX);
}
}
}
return true;
}
bool
FindFloorView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
{
int xoff = 0;
int yoff = 0;
int i;
SPRITEp sp = NULL;
int newz;
int pix_diff;
save.zcount = 0;
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
StatIterator it(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->hitag == VIEW_THRU_FLOOR && sp->lotag == match)
{
xoff = *x - sp->x;
yoff = *y - sp->y;
break;
}
}
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// determine x,y position
if (sp->hitag == VIEW_THRU_CEILING)
{
short upper, lower;
*x = sp->x + xoff;
*y = sp->y + yoff;
// get new sector
GetUpperLowerSector(match, *x, *y, &upper, &lower);
*sectnum = lower;
break;
}
}
}
if (*sectnum < 0)
return false;
ASSERT(sp);
ASSERT(sp->hitag == VIEW_THRU_CEILING);
// move ceiling multiple of 128 so that the wall tile will line up
pix_diff = labs(z - sector[sp->sectnum].ceilingz) >> 8;
newz = sector[sp->sectnum].ceilingz - ((pix_diff / 128) + 1) * Z(128);
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// move upper levels floors down for the correct view
if (sp->hitag == VIEW_LEVEL1)
{
// save it off
save.sectnum[save.zcount] = sp->sectnum;
save.zval[save.zcount] = sector[sp->sectnum].ceilingz;
save.pic[save.zcount] = sector[sp->sectnum].ceilingpicnum;
save.slope[save.zcount] = sector[sp->sectnum].ceilingheinum;
sector[sp->sectnum].ceilingz = newz;
// don't change FAF_MIRROR_PIC - ConnectArea
if (sector[sp->sectnum].ceilingpicnum != FAF_MIRROR_PIC)
sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC + 1;
sector[sp->sectnum].ceilingheinum = 0;
save.zcount++;
PRODUCTION_ASSERT(save.zcount < ZMAX);
}
}
}
return true;
}
bool FindCeilingView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum);
bool FindFloorView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum);
short
@ -480,7 +177,7 @@ void polymost_drawscreen(PLAYERp pp, int tx, int ty, int tz, binangle tang, fixe
if (!FAF_DebugView)
FAF_DrawRooms(tx, ty, tz, tang.asq16(), thoriz.asq16(), tsectnum);
analyzesprites(tx, ty, tz, false);
analyzesprites(tx, ty, tz, tang.asbuild());
post_analyzesprites();
renderDrawMasks();
@ -626,7 +323,7 @@ void JS_DrawMirrors(PLAYERp pp, int tx, int ty, int tz, fixed_t tpq16ang, fixed
renderDrawRoomsQ16(tposx, tposy, tz, (tang), tpq16horiz, mirror[cnt].mirrorsector + MAXSECTORS);
analyzesprites(tposx, tposy, tz, true);
analyzesprites(tposx, tposy, tz, tang >> 16);
renderDrawMasks();
renderCompleteMirror(); // Reverse screen x-wise in this

View file

@ -71,7 +71,7 @@ extern short f_c;
extern ParentalStruct aVoxelArray[MAXTILES];
int ConnectCopySprite(uspritetype const * tsp);
int ConnectCopySprite(spritetype const * tsp);
void PreDrawStackedWater(void);
void SW_InitMultiPsky(void)
@ -265,7 +265,7 @@ DoShadowFindGroundPoint(tspriteptr_t sp)
}
void
DoShadows(tspriteptr_t tsp, int viewz, bool mirror)
DoShadows(tspriteptr_t tsp, int viewz, int camang)
{
tspriteptr_t New = &tsprite[spritesortcnt];
USERp tu = User[tsp->owner];
@ -553,7 +553,7 @@ void DoStarView(tspriteptr_t tsp, USERp tu, int viewz)
}
void
analyzesprites(int viewx, int viewy, int viewz, bool mirror)
analyzesprites(int viewx, int viewy, int viewz, int camang)
{
int tSpriteNum;
short SpriteNum;
@ -645,7 +645,7 @@ analyzesprites(int viewx, int viewy, int viewz, bool mirror)
if (r_shadows && TEST(tu->Flags, SPR_SHADOW))
{
DoShadows(tsp, viewz, mirror);
DoShadows(tsp, viewz, camang);
}
//#define UK_VERSION 1
@ -794,8 +794,7 @@ analyzesprites(int viewx, int viewy, int viewz, bool mirror)
if (OverlapDraw && FAF_ConnectArea(tsp->sectnum) && tsp->owner >= 0)
{
static_assert(sizeof(uspritetype) == sizeof(tspritetype)); // see TSPRITE_SIZE
ConnectCopySprite((uspriteptr_t)tsp);
ConnectCopySprite(tsp);
}
//
@ -902,7 +901,6 @@ post_analyzesprites(void)
{
if (tu->ID == FIREBALL_FLAMES && tu->Attach >= 0)
{
//uspritetype * const atsp = &sprite[tu->Attach];
tspriteptr_t const atsp = get_tsprite(tu->Attach);
if (!atsp)
@ -1096,34 +1094,6 @@ void PrintSpriteInfo(PLAYERp pp)
}
void SpriteSortList2D(int tx, int ty)
{
SPRITEp sp;
int i;
int dist,a,b,c;
spritesortcnt = 0;
for (i = 0; i < MAXSPRITES; i++)
{
if (sprite[i].statnum < MAXSTATUS)
{
sp = &sprite[i];
if (!TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE) &&
(sp->xrepeat > 0) && (sp->yrepeat > 0) &&
(spritesortcnt < MAXSPRITESONSCREEN))
{
DISTANCE(tx,ty,sp->x,sp->y,dist,a,b,c);
if (dist < 22000)
{
renderAddTSpriteFromSprite(i);
}
}
}
}
}
void DrawCrosshair(PLAYERp pp)
{
extern bool CameraTestMode;
@ -1281,7 +1251,7 @@ PostDraw(void)
}
}
int CopySprite(uspritetype const * tsp, short newsector)
int CopySprite(spritetype const * tsp, short newsector)
{
short New;
SPRITEp sp;
@ -1310,7 +1280,7 @@ int CopySprite(uspritetype const * tsp, short newsector)
return New;
}
int ConnectCopySprite(uspritetype const * tsp)
int ConnectCopySprite(spritetype const * tsp)
{
short newsector;
int testz;
@ -1375,7 +1345,7 @@ void PreDrawStackedWater(void)
sp = &sprite[i];
u = User[i];
New = ConnectCopySprite((uspritetype const *)sp);
New = ConnectCopySprite((spritetype const *)sp);
if (New >= 0)
{
// spawn a user
@ -1596,7 +1566,7 @@ drawscreen(PLAYERp pp, double smoothratio)
else
{
UpdateWallPortalState();
render_drawrooms(pp->SpriteP, { tx, ty, tz }, tsectnum, tang.asq16(), thoriz.asq16(), trotscrnang.asbuildf());
render_drawrooms(pp->SpriteP, { tx, ty, tz }, tsectnum, tang, thoriz, trotscrnang);
}
@ -1706,7 +1676,7 @@ bool GameInterface::DrawAutomapPlayer(int cposx, int cposy, int czoom, int cang,
int i, j, k, l, x1, y1, x2, y2, x3, y3, x4, y4, ox, oy, xoff, yoff;
int dax, day, cosang, sinang, xspan, yspan, sprx, spry;
int xrepeat, yrepeat, z1, z2, startwall, endwall, tilenum, daang;
int xvect, yvect, xvect2, yvect2;
int xvect, yvect;
walltype* wal, * wal2;
spritetype* spr;
short p;
@ -1716,8 +1686,6 @@ bool GameInterface::DrawAutomapPlayer(int cposx, int cposy, int czoom, int cang,
xvect = -bsin(cang) * czoom;
yvect = -bcos(cang) * czoom;
xvect2 = MulScale(xvect, yxaspect, 16);
yvect2 = MulScale(yvect, yxaspect, 16);
// Draw sprites
@ -1784,7 +1752,7 @@ bool GameInterface::DrawAutomapPlayer(int cposx, int cposy, int czoom, int cang,
double xd = ((x1 << 4) + (xdim << 15)) / 65536.;
double yd = ((y1 << 4) + (ydim << 15)) / 65536.;
double sc = MulScale(czoom * (spr->yrepeat), yxaspect, 16) / 32768.;
double sc = czoom * (spr->yrepeat) / 32768.;
if (spnum >= 0)
{
DrawTexture(twod, tileGetTexture(1196 + pspr_ndx[myconnectindex], true), xd, yd, DTA_ScaleX, sc, DTA_ScaleY, sc, DTA_Rotate, daang * (-360. / 2048),
@ -1815,12 +1783,12 @@ bool GameInterface::DrawAutomapPlayer(int cposx, int cposy, int czoom, int cang,
ox = x1 - cposx;
oy = y1 - cposy;
x1 = MulScale(ox, xvect, 16) - MulScale(oy, yvect, 16);
y1 = MulScale(oy, xvect2, 16) + MulScale(ox, yvect2, 16);
y1 = MulScale(oy, xvect, 16) + MulScale(ox, yvect, 16);
ox = x2 - cposx;
oy = y2 - cposy;
x2 = MulScale(ox, xvect, 16) - MulScale(oy, yvect, 16);
y2 = MulScale(oy, xvect2, 16) + MulScale(ox, yvect2, 16);
y2 = MulScale(oy, xvect, 16) + MulScale(ox, yvect, 16);
drawlinergb(x1 + (xdim << 11), y1 + (ydim << 11),
x2 + (xdim << 11), y2 + (ydim << 11), col);
@ -1863,22 +1831,22 @@ bool GameInterface::DrawAutomapPlayer(int cposx, int cposy, int czoom, int cang,
ox = x1 - cposx;
oy = y1 - cposy;
x1 = MulScale(ox, xvect, 16) - MulScale(oy, yvect, 16);
y1 = MulScale(oy, xvect2, 16) + MulScale(ox, yvect2, 16);
y1 = MulScale(oy, xvect, 16) + MulScale(ox, yvect, 16);
ox = x2 - cposx;
oy = y2 - cposy;
x2 = MulScale(ox, xvect, 16) - MulScale(oy, yvect, 16);
y2 = MulScale(oy, xvect2, 16) + MulScale(ox, yvect2, 16);
y2 = MulScale(oy, xvect, 16) + MulScale(ox, yvect, 16);
ox = x3 - cposx;
oy = y3 - cposy;
x3 = MulScale(ox, xvect, 16) - MulScale(oy, yvect, 16);
y3 = MulScale(oy, xvect2, 16) + MulScale(ox, yvect2, 16);
y3 = MulScale(oy, xvect, 16) + MulScale(ox, yvect, 16);
ox = x4 - cposx;
oy = y4 - cposy;
x4 = MulScale(ox, xvect, 16) - MulScale(oy, yvect, 16);
y4 = MulScale(oy, xvect2, 16) + MulScale(ox, yvect2, 16);
y4 = MulScale(oy, xvect, 16) + MulScale(ox, yvect, 16);
drawlinergb(x1 + (xdim << 11), y1 + (ydim << 11),
x2 + (xdim << 11), y2 + (ydim << 11), col);
@ -1901,6 +1869,12 @@ bool GameInterface::DrawAutomapPlayer(int cposx, int cposy, int czoom, int cang,
return true;
}
void GameInterface::processSprites(int viewx, int viewy, int viewz, binangle viewang, double smoothRatio)
{
analyzesprites(viewx, viewy, viewz, viewang.asbuild());
post_analyzesprites();
}
END_SW_NS

View file

@ -407,8 +407,8 @@ void InitLevel(MapRecord *maprec)
PlaceActorsOnTracks();
PostSetupSectorObject();
SetupMirrorTiles();
SetupSectorPortals();
initlava();
CollectPortals();
// reset NewGame
NewGame = false;

View file

@ -1967,23 +1967,16 @@ int DoPickTarget(SPRITEp sp, uint32_t max_delta_ang, int skip_targets);
void change_sprite_stat(short, short);
void SetOwner(short, short);
void SetAttach(short, short);
void analyzesprites(int,int,int,bool);
void analyzesprites(int,int,int,int);
void ChangeState(short SpriteNum, STATEp statep);
void CollectPortals();
void UpdateSectorFAF_Connect(short SpriteNum, int newz);
#if 0
bool FAF_ConnectCeiling(short sectnum);
bool FAF_ConnectFloor(short sectnum);
#else
#define FAF_PLACE_MIRROR_PIC 341
#define FAF_MIRROR_PIC 2356
#define FAF_ConnectCeiling(sectnum) (sector[(sectnum)].ceilingpicnum == FAF_MIRROR_PIC)
#define FAF_ConnectFloor(sectnum) (sector[(sectnum)].floorpicnum == FAF_MIRROR_PIC)
#define FAF_ConnectArea(sectnum) (FAF_ConnectCeiling(sectnum) || FAF_ConnectFloor(sectnum))
#endif
//void updatesectorz(int, int, int, short *);
void FAF_ConnectPlayerCeiling(PLAYERp pp);
void FAF_ConnectPlayerFloor(PLAYERp pp);
bool PlayerCeilingHit(PLAYERp pp, int zlimit);
bool PlayerFloorHit(PLAYERp pp, int zlimit);
@ -2135,7 +2128,6 @@ void DrawOverlapRoom(int tx,int ty,int tz,fixed_t tq16ang,fixed_t tq16horiz,shor
void SetupMirrorTiles(void); // rooms.c
bool FAF_Sector(short sectnum); // rooms.c
int GetZadjustment(short sectnum,short hitag); // rooms.c
void SetupSectorPortals();
void InitSetup(void); // setup.c
@ -2256,6 +2248,7 @@ struct GameInterface : ::GameInterface
int chaseCamX(binangle ang) { return -ang.bcos(-3); }
int chaseCamY(binangle ang) { return -ang.bsin(-3); }
int chaseCamZ(fixedhoriz horiz) { return horiz.asq16() >> 8; }
void processSprites(int viewx, int viewy, int viewz, binangle viewang, double smoothRatio) override;
GameStats getStats() override;

View file

@ -464,7 +464,7 @@ void JS_InitMirrors(void)
// Draw a 3d screen to a specific tile
/////////////////////////////////////////////////////
void drawroomstotile(int daposx, int daposy, int daposz,
fixed_t daq16ang, fixed_t daq16horiz, short dacursectnum, short tilenume)
binangle ang, fixedhoriz horiz, short dacursectnum, short tilenume)
{
TileFiles.MakeCanvas(tilenume, tileWidth(tilenume), tileHeight(tilenume));
@ -475,13 +475,13 @@ void drawroomstotile(int daposx, int daposy, int daposz,
{
if (!testnewrenderer)
{
renderDrawRoomsQ16(daposx, daposy, daposz, daq16ang, daq16horiz, dacursectnum);
analyzesprites(daposx, daposy, daposz, false);
renderDrawRoomsQ16(daposx, daposy, daposz, ang.asq16(), horiz.asq16(), dacursectnum);
analyzesprites(daposx, daposy, daposz, ang.asbuild());
renderDrawMasks();
}
else
{
render_drawrooms(nullptr, { daposx, daposy, daposz }, dacursectnum, daq16ang, daq16horiz, 0);
render_drawrooms(nullptr, { daposx, daposy, daposz }, dacursectnum, ang, horiz, buildlook(0));
}
});
@ -721,11 +721,11 @@ void JS_DrawCameras(PLAYERp pp, int tx, int ty, int tz)
if (TEST_BOOL11(sp) && numplayers > 1)
{
drawroomstotile(cp->posx, cp->posy, cp->posz, cp->angle.ang.asq16(), cp->horizon.horiz.asq16(), cp->cursectnum, mirror[cnt].campic);
drawroomstotile(cp->posx, cp->posy, cp->posz, cp->angle.ang, cp->horizon.horiz, cp->cursectnum, mirror[cnt].campic);
}
else
{
drawroomstotile(sp->x, sp->y, sp->z, IntToFixed(SP_TAG5(sp)), IntToFixed(camhoriz), sp->sectnum, mirror[cnt].campic);
drawroomstotile(sp->x, sp->y, sp->z, buildang(SP_TAG5(sp)), buildhoriz(camhoriz), sp->sectnum, mirror[cnt].campic);
}
}
}

View file

@ -29,6 +29,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
#include "names2.h"
#include "panel.h"
#include "misc.h"
#include "hw_drawinfo.h"
BEGIN_SW_NS
@ -678,50 +679,521 @@ SetupMirrorTiles(void)
}
}
short GlobStackSect[2];
void SetupSectorPortals()
void
GetUpperLowerSector(short match, int x, int y, short *upper, short *lower)
{
TArray<int> foundf, foundc;
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
StatIterator it(STAT_FAF);
int i;
while ((i = it.NextIndex()) >= 0)
short sectorlist[16];
int sln = 0;
int SpriteNum;
SPRITEp sp;
#if 0
// keep a list of the last stacked sectors the view was in and
// check those fisrt
sln = 0;
for (i = 0; i < (int)SIZ(GlobStackSect); i++)
{
auto sp = &sprite[i];
if (sp->hitag == VIEW_THRU_CEILING) foundc.Push(i);
if (sp->hitag == VIEW_THRU_FLOOR) foundf.Push(i);
}
portalClear();
while (foundf.Size())
{
auto spf = &sprite[foundf[0]];
auto cindex = foundc.FindEx([=](int i) { return spf->lotag == sprite[i].lotag; });
if (cindex != foundc.Size())
// will not hurt if GlobStackSect is invalid - inside checks for this
if (inside(x, y, GlobStackSect[i]) == 1)
{
auto spc = &sprite[foundf[cindex]];
sector[spf->sectnum].portalflags = PORTAL_SECTOR_FLOOR;
sector[spf->sectnum].portalnum = portalAdd(PORTAL_SECTOR_FLOOR, spc->sectnum, spc->x - spf->x, spc->y - spf->y, 0);
bool found = false;
sector[spc->sectnum].portalflags = PORTAL_SECTOR_CEILING;
sector[spc->sectnum].portalnum = portalAdd(PORTAL_SECTOR_CEILING, spf->sectnum, spf->x - spc->x, spf->y - spc->y, 0);
SectIterator it(GlobStackSect[i]);
while ((SpriteNum = it.NextIndex()) >= 0)
{
sp = &sprite[SpriteNum];
//Printf("Portal with tag %d\n", sprite[foundf[0]].lotag);
foundf.Delete(0);
foundc.Delete(cindex);
}
else
{
//Printf("Floor portal %d without partner\n", sprite[foundf[0]].lotag);
foundf.Delete(0);
if (sp->statnum == STAT_FAF &&
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
&& sp->lotag == match)
{
found = true;
}
}
if (!found)
continue;
sectorlist[sln] = GlobStackSect[i];
sln++;
}
}
for (auto c : foundc)
#endif
// didn't find it yet so test ALL sectors
if (sln < 2)
{
//Printf("Ceiling portal %d without partner\n", sprite[c].lotag);
sln = 0;
for (i = 0; i < numsectors; i++)// - 1; i >= 0; i--)
{
if (inside(x, y, (short) i) == 1)
{
bool found = false;
SectIterator it(i);
while ((SpriteNum = it.NextIndex()) >= 0)
{
sp = &sprite[SpriteNum];
if (sp->statnum == STAT_FAF &&
(sp->hitag >= VIEW_LEVEL1 && sp->hitag <= VIEW_LEVEL6)
&& sp->lotag == match)
{
found = true;
}
}
if (!found)
continue;
if (sln < (int)SIZ(GlobStackSect))
GlobStackSect[sln] = i;
if (sln < (int)SIZ(sectorlist))
sectorlist[sln] = i;
sln++;
}
}
}
// might not find ANYTHING if not tagged right
if (sln == 0)
{
*upper = -1;
*lower = -1;
return;
}
// Map rooms have NOT been dragged on top of each other
else if (sln == 1)
{
*lower = sectorlist[0];
*upper = sectorlist[0];
return;
}
// Map rooms HAVE been dragged on top of each other
// inside will somtimes find that you are in two different sectors if the x,y
// is exactly on a sector line.
else if (sln > 2)
{
//DSPRINTF(ds, "TOO MANY SECTORS FOUND: x=%d, y=%d, match=%d, num sectors %d, %d, %d, %d, %d, %d", x, y, match, sln, sectorlist[0], sectorlist[1], sectorlist[2], sectorlist[3], sectorlist[4]);
MONO_PRINT(ds);
// try again moving the x,y pos around until you only get two sectors
GetUpperLowerSector(match, x - 1, y, upper, lower);
}
if (sln == 2)
{
if (sector[sectorlist[0]].floorz < sector[sectorlist[1]].floorz)
{
// swap
// make sectorlist[0] the LOW sector
short hold;
hold = sectorlist[0];
sectorlist[0] = sectorlist[1];
sectorlist[1] = hold;
}
*lower = sectorlist[0];
*upper = sectorlist[1];
}
}
bool
FindCeilingView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
{
int xoff = 0;
int yoff = 0;
int i;
SPRITEp sp = NULL;
int pix_diff;
int newz;
save.zcount = 0;
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
StatIterator it(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->hitag == VIEW_THRU_CEILING && sp->lotag == match)
{
xoff = *x - sp->x;
yoff = *y - sp->y;
break;
}
}
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// determine x,y position
if (sp->hitag == VIEW_THRU_FLOOR)
{
short upper, lower;
*x = sp->x + xoff;
*y = sp->y + yoff;
// get new sector
GetUpperLowerSector(match, *x, *y, &upper, &lower);
*sectnum = upper;
break;
}
}
}
if (*sectnum < 0)
return false;
ASSERT(sp);
ASSERT(sp->hitag == VIEW_THRU_FLOOR);
pix_diff = labs(z - sector[sp->sectnum].floorz) >> 8;
newz = sector[sp->sectnum].floorz + ((pix_diff / 128) + 1) * Z(128);
if (!testnewrenderer)
{
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// move lower levels ceilings up for the correct view
if (sp->hitag == VIEW_LEVEL2)
{
// save it off
save.sectnum[save.zcount] = sp->sectnum;
save.zval[save.zcount] = sector[sp->sectnum].floorz;
save.pic[save.zcount] = sector[sp->sectnum].floorpicnum;
save.slope[save.zcount] = sector[sp->sectnum].floorheinum;
sector[sp->sectnum].floorz = newz;
// don't change FAF_MIRROR_PIC - ConnectArea
if (sector[sp->sectnum].floorpicnum != FAF_MIRROR_PIC)
sector[sp->sectnum].floorpicnum = FAF_MIRROR_PIC + 1;
sector[sp->sectnum].floorheinum = 0;
save.zcount++;
PRODUCTION_ASSERT(save.zcount < ZMAX);
}
}
}
}
return true;
}
bool
FindFloorView(short match, int32_t* x, int32_t* y, int32_t z, int16_t* sectnum)
{
int xoff = 0;
int yoff = 0;
int i;
SPRITEp sp = NULL;
int newz;
int pix_diff;
save.zcount = 0;
// Search Stat List For closest ceiling view sprite
// Get the match, xoff, yoff from this point
StatIterator it(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->hitag == VIEW_THRU_FLOOR && sp->lotag == match)
{
xoff = *x - sp->x;
yoff = *y - sp->y;
break;
}
}
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// determine x,y position
if (sp->hitag == VIEW_THRU_CEILING)
{
short upper, lower;
*x = sp->x + xoff;
*y = sp->y + yoff;
// get new sector
GetUpperLowerSector(match, *x, *y, &upper, &lower);
*sectnum = lower;
break;
}
}
}
if (*sectnum < 0)
return false;
ASSERT(sp);
ASSERT(sp->hitag == VIEW_THRU_CEILING);
// move ceiling multiple of 128 so that the wall tile will line up
pix_diff = labs(z - sector[sp->sectnum].ceilingz) >> 8;
newz = sector[sp->sectnum].ceilingz - ((pix_diff / 128) + 1) * Z(128);
if (!testnewrenderer)
{
it.Reset(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->lotag == match)
{
// move upper levels floors down for the correct view
if (sp->hitag == VIEW_LEVEL1)
{
// save it off
save.sectnum[save.zcount] = sp->sectnum;
save.zval[save.zcount] = sector[sp->sectnum].ceilingz;
save.pic[save.zcount] = sector[sp->sectnum].ceilingpicnum;
save.slope[save.zcount] = sector[sp->sectnum].ceilingheinum;
sector[sp->sectnum].ceilingz = newz;
// don't change FAF_MIRROR_PIC - ConnectArea
if (sector[sp->sectnum].ceilingpicnum != FAF_MIRROR_PIC)
sector[sp->sectnum].ceilingpicnum = FAF_MIRROR_PIC + 1;
sector[sp->sectnum].ceilingheinum = 0;
save.zcount++;
PRODUCTION_ASSERT(save.zcount < ZMAX);
}
}
}
}
return true;
}
short
FindViewSectorInScene(short cursectnum, short level)
{
int i;
SPRITEp sp;
short match;
StatIterator it(STAT_FAF);
while ((i = it.NextIndex()) >= 0)
{
sp = &sprite[i];
if (sp->hitag == level)
{
if (cursectnum == sp->sectnum)
{
// ignore case if sprite is pointing up
if (sp->ang == 1536)
continue;
// only gets to here is sprite is pointing down
// found a potential match
match = sp->lotag;
return match;
}
}
}
return -1;
}
struct PortalGroup
{
TArray<int> sectors;
int othersector = -1;
vec3_t offset = { 0,0,0 };
};
// This is very messy because some portals are linked outside the actual portal sectors, so we have to use the complicated original linking logic to find the connection. :?
void CollectPortals()
{
int t = testnewrenderer;
testnewrenderer = true;
TArray<PortalGroup> floorportals;
TArray<PortalGroup> ceilingportals;
FixedBitArray<MAXSECTORS> floordone, ceilingdone;
floordone.Zero();
ceilingdone.Zero();
for (int i = 0; i < numsectors; i++)
{
if (sector[i].floorpicnum == FAF_MIRROR_PIC && !floordone[i])
{
auto& fp = floorportals[floorportals.Reserve(1)];
fp.sectors.Push(i);
floordone.Set(i);
for (unsigned ii = 0; ii < fp.sectors.Size(); ii++)
{
auto sec = &sector[fp.sectors[ii]];
for (int w = 0; w < sec->wallnum; w++)
{
auto ns = wall[sec->wallptr + w].nextsector;
if (ns < 0 || floordone[ns] || sector[ns].floorpicnum != FAF_MIRROR_PIC) continue;
fp.sectors.Push(ns);
floordone.Set(ns);
}
}
}
if (sector[i].ceilingpicnum == FAF_MIRROR_PIC && !ceilingdone[i])
{
auto& fp = ceilingportals[ceilingportals.Reserve(1)];
fp.sectors.Push(i);
ceilingdone.Set(i);
for (unsigned ii = 0; ii < fp.sectors.Size(); ii++)
{
auto sec = &sector[fp.sectors[ii]];
for (int w = 0; w < sec->wallnum; w++)
{
auto ns = wall[sec->wallptr + w].nextsector;
if (ns < 0 || ceilingdone[ns] || sector[ns].ceilingpicnum != FAF_MIRROR_PIC) continue;
fp.sectors.Push(ns);
ceilingdone.Set(ns);
}
}
}
}
// now try to find connections.
for (auto& fp : ceilingportals)
{
// pick one sprite out of the sectors, repeat until we get a valid connection
for (auto sec : fp.sectors)
{
SectIterator it(sec);
int spr;
while ((spr = it.NextIndex()) >= 0)
{
int tx = sprite[spr].x;
int ty = sprite[spr].y;
int tz = sprite[spr].z;
int16_t tsectnum = sec;
int match = FindViewSectorInScene(tsectnum, VIEW_LEVEL1);
if (match != -1)
{
FindCeilingView(match, &tx, &ty, tz, &tsectnum);
if (tsectnum >= 0 && sector[tsectnum].floorpicnum == FAF_MIRROR_PIC)
{
// got something!
fp.othersector = tsectnum;
fp.offset = { tx, ty, tz };
fp.offset -= sprite[spr].pos;
goto nextfg;
}
}
}
}
nextfg:;
}
for (auto& fp : floorportals)
{
for (auto sec : fp.sectors)
{
SectIterator it(sec);
int spr;
while ((spr = it.NextIndex()) >= 0)
{
int tx = sprite[spr].x;
int ty = sprite[spr].y;
int tz = sprite[spr].z;
int16_t tsectnum = sec;
int match = FindViewSectorInScene(tsectnum, VIEW_LEVEL2);
if (match != -1)
{
FindFloorView(match, &tx, &ty, tz, &tsectnum);
if (tsectnum >= 0 && sector[tsectnum].ceilingpicnum == FAF_MIRROR_PIC)
{
// got something!
fp.othersector = tsectnum;
fp.offset = { tx, ty, tz };
fp.offset -= sprite[spr].pos;
goto nextcg;
}
}
}
}
nextcg:;
}
for (auto& pt : floorportals)
{
if (pt.othersector > -1)
{
auto findother = [&](int other) -> PortalGroup*
{
for (auto& pt2 : ceilingportals)
{
if (pt2.sectors.Find(other) != pt2.sectors.Size()) return &pt2;
}
return nullptr;
};
auto pt2 = findother(pt.othersector);
if (pt2)
{
int pnum = portalAdd(PORTAL_SECTOR_FLOOR, -1, pt.offset.x, pt.offset.y, 0);
allPortals[pnum].targets = pt2->sectors; // do not move! We still need the original.
for (auto sec : pt.sectors)
{
sector[sec].portalflags = PORTAL_SECTOR_FLOOR;
sector[sec].portalnum = pnum;
}
}
}
}
for (auto& pt : ceilingportals)
{
if (pt.othersector > -1)
{
auto findother = [&](int other) -> PortalGroup*
{
for (auto& pt2 : floorportals)
{
if (pt2.sectors.Find(other) != pt2.sectors.Size()) return &pt2;
}
return nullptr;
};
auto pt2 = findother(pt.othersector);
if (pt2)
{
int pnum = portalAdd(PORTAL_SECTOR_FLOOR, -1, pt.offset.x, pt.offset.y, 0);
allPortals[pnum].targets = std::move(pt2->sectors);
for (auto sec : pt.sectors)
{
sector[sec].portalflags = PORTAL_SECTOR_CEILING;
sector[sec].portalnum = pnum;
}
}
}
}
testnewrenderer = false;
}
END_SW_NS

View file

@ -44,7 +44,7 @@ typedef struct
} saveable_module;
template <typename T>
constexpr enable_if_t<!std::is_pointer<T>::value, size_t> SAVE_SIZEOF(T const & obj) noexcept
constexpr std::enable_if_t<!std::is_pointer<T>::value, size_t> SAVE_SIZEOF(T const & obj) noexcept
{
return sizeof(obj);
}

View file

@ -639,7 +639,7 @@ TrackSetup(void)
if (t->NumPoints == 0)
{
int i;
auto const sp = (uspritetype const *)&sprite[StatIterator::First(STAT_TRACK+ndx)];
auto const sp = (spritetype const *)&sprite[StatIterator::First(STAT_TRACK+ndx)];
Printf("WARNING: Did not find first point of Track Number %d, x %d, y %d\n", ndx, sp->x, sp->y);
StatIterator it(STAT_TRACK + ndx);
while ((i = it.NextIndex()) >= 0)

View file

@ -10,10 +10,11 @@ EXTERN_CVAR(Bool, testnewrenderer)
BEGIN_WH_NS
int curpnum;
void drawscreen(int num, double dasmoothratio, bool sceneonly)
{
curpnum = num;
PLAYER& plr = player[num];
int cposx = plr.x;
@ -90,7 +91,6 @@ void drawscreen(int num, double dasmoothratio, bool sceneonly)
cposz = floorz - lz;
// do screen rotation.
renderSetRollAngle(crotscrnang.asbam() / (double)(BAMUNIT));
if (!testnewrenderer)
{
@ -101,7 +101,7 @@ void drawscreen(int num, double dasmoothratio, bool sceneonly)
}
else
{
render_drawrooms(nullptr, { cposx, cposy, cposz }, plr.sector, cang.asq16(), choriz.asq16(), crotscrnang.asbuildf());
render_drawrooms(nullptr, { cposx, cposy, cposz }, plr.sector, cang, choriz, crotscrnang);
}
if (!sceneonly)
@ -118,6 +118,12 @@ void drawscreen(int num, double dasmoothratio, bool sceneonly)
}
}
void GameInterface::processSprites(int viewx, int viewy, int viewz, binangle viewang, double smoothRatio)
{
PLAYER& plr = player[curpnum];
analyzesprites(plr, (int)smoothRatio);
}
void GameInterface::Render()
{
double const smoothRatio = playrunning() ? I_GetTimeFrac() * MaxSmoothRatio : MaxSmoothRatio;

View file

@ -535,6 +535,7 @@ struct GameInterface : public ::GameInterface
int chaseCamX(binangle ang) { return -ang.bcos() / 12; }
int chaseCamY(binangle ang) { return -ang.bsin() / 12; }
int chaseCamZ(fixedhoriz horiz) { return horiz.asq16() / 384; }
void processSprites(int viewx, int viewy, int viewz, binangle viewang, double smoothRatio) override;
};

View file

@ -50,6 +50,7 @@
#include "hw_cvars.h"
#include "gamestruct.h"
#include "gl_models.h"
#include "gamefuncs.h"
CVARD(Bool, hw_hightile, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "enable/disable hightile texture rendering")
bool hw_int_useindexedcolortextures;