mirror of
https://github.com/ZDoom/Raze.git
synced 2025-02-21 02:51:46 +00:00
Merge commit '88706e8e1320b782702e3da7c1293b3791aa97d7' into whaven
This commit is contained in:
commit
8f07ccd295
22 changed files with 449 additions and 282 deletions
|
@ -1117,6 +1117,7 @@ set (PCH_SOURCES
|
|||
core/savegamehelp.cpp
|
||||
core/quotes.cpp
|
||||
core/screenshot.cpp
|
||||
core/sectorgeometry.cpp
|
||||
core/raze_music.cpp
|
||||
core/raze_sound.cpp
|
||||
core/palette.cpp
|
||||
|
|
|
@ -622,7 +622,6 @@ static FORCE_INLINE int32_t E_SpriteIsValid(const int32_t i)
|
|||
|
||||
void alignceilslope(int16_t dasect, int32_t x, int32_t y, int32_t z);
|
||||
void alignflorslope(int16_t dasect, int32_t x, int32_t y, int32_t z);
|
||||
int32_t sectorofwall(int16_t wallNum);
|
||||
void setslope(int32_t sectnum, int32_t cf, int16_t slope);
|
||||
|
||||
int32_t lintersect(int32_t originX, int32_t originY, int32_t originZ,
|
||||
|
@ -862,7 +861,6 @@ void markTileForPrecache(int tilenum, int palnum);
|
|||
void precacheMarkedTiles();
|
||||
|
||||
extern int32_t(*animateoffs_replace)(int const tilenum, int fakevar);
|
||||
extern int32_t(*getpalookup_replace)(int32_t davis, int32_t dashade);
|
||||
extern void(*initspritelists_replace)(void);
|
||||
extern int32_t(*insertsprite_replace)(int16_t sectnum, int16_t statnum);
|
||||
extern int32_t(*deletesprite_replace)(int16_t spritenum);
|
||||
|
|
|
@ -51,6 +51,7 @@ struct sectortype
|
|||
int16_t hitag;
|
||||
int16_t extra;
|
||||
|
||||
uint8_t dirty;
|
||||
float ceilingxpan_, ceilingypan_, floorxpan_, floorypan_;
|
||||
|
||||
int ceilingxpan() const { return int(ceilingxpan_); }
|
||||
|
@ -91,7 +92,7 @@ struct walltype
|
|||
};
|
||||
vec2_t pos;
|
||||
};
|
||||
int16_t point2, nextwall, nextsector;
|
||||
int16_t point2, nextwall, sector, nextsector;
|
||||
uint16_t cstat;
|
||||
int16_t picnum, overpicnum;
|
||||
int8_t shade;
|
||||
|
|
|
@ -508,7 +508,7 @@ int32_t clipmove(vec3_t * const pos, int16_t * const sectnum, int32_t xvect, int
|
|||
{
|
||||
clipyou = 1;
|
||||
}
|
||||
else if (editstatus == 0)
|
||||
else
|
||||
{
|
||||
clipmove_tweak_pos(pos, diff.x, diff.y, p1.x, p1.y, p2.x, p2.y, &v.x, &v.y);
|
||||
clipyou = cliptestsector(dasect, wal->nextsector, flordist, ceildist, v, pos->z);
|
||||
|
@ -990,11 +990,8 @@ void getzrange(const vec3_t *pos, int16_t sectnum,
|
|||
if (wall[j].cstat&dawalclipmask) continue; // XXX?
|
||||
auto const sec = (usectorptr_t)§or[k];
|
||||
|
||||
if (editstatus == 0)
|
||||
{
|
||||
if (((sec->ceilingstat&1) == 0) && (pos->z <= sec->ceilingz+(3<<8))) continue;
|
||||
if (((sec->floorstat&1) == 0) && (pos->z >= sec->floorz-(3<<8))) continue;
|
||||
}
|
||||
if (((sec->ceilingstat&1) == 0) && (pos->z <= sec->ceilingz+(3<<8))) continue;
|
||||
if (((sec->floorstat&1) == 0) && (pos->z >= sec->floorz-(3<<8))) continue;
|
||||
|
||||
if (bitmap_test(clipsectormap, k) == 0)
|
||||
addclipsect(k);
|
||||
|
|
|
@ -73,7 +73,6 @@ int32_t globalflags;
|
|||
static int8_t tempbuf[MAXWALLS];
|
||||
|
||||
// referenced from asm
|
||||
int32_t reciptable[2048];
|
||||
intptr_t asm1, asm2;
|
||||
int32_t globalx1, globaly2, globalx3, globaly3;
|
||||
|
||||
|
@ -87,7 +86,6 @@ int32_t showfirstwall=0;
|
|||
int32_t showheightindicators=1;
|
||||
int32_t circlewall=-1;
|
||||
|
||||
int16_t editstatus = 0;
|
||||
static fixed_t global100horiz; // (-100..300)-scale horiz (the one passed to drawrooms)
|
||||
|
||||
static FString printcoords(void)
|
||||
|
@ -118,8 +116,6 @@ ADD_STAT(printcoords)
|
|||
return printcoords();
|
||||
}
|
||||
|
||||
int32_t(*getpalookup_replace)(int32_t davis, int32_t dashade) = NULL;
|
||||
|
||||
// adapted from build.c
|
||||
static void getclosestpointonwall_internal(vec2_t const p, int32_t const dawall, vec2_t *const closest)
|
||||
{
|
||||
|
@ -149,7 +145,6 @@ static void getclosestpointonwall_internal(vec2_t const p, int32_t const dawall,
|
|||
}
|
||||
|
||||
int32_t xb1[MAXWALLSB]; // Polymost uses this as a temp array
|
||||
static int32_t xb2[MAXWALLSB];
|
||||
int32_t rx1[MAXWALLSB], ry1[MAXWALLSB];
|
||||
int16_t bunchp2[MAXWALLSB], thesector[MAXWALLSB];
|
||||
|
||||
|
@ -158,7 +153,7 @@ int16_t bunchfirst[MAXWALLSB], bunchlast[MAXWALLSB];
|
|||
|
||||
static vec3_t spritesxyz[MAXSPRITESONSCREEN+1];
|
||||
|
||||
int32_t xdimen = -1, xdimenrecip, halfxdimen, xdimenscale, xdimscale;
|
||||
int32_t xdimen = -1, xdimenscale, xdimscale;
|
||||
float fxdimen = -1.f;
|
||||
int32_t ydimen;
|
||||
|
||||
|
@ -191,18 +186,6 @@ static_assert(MAXWALLSB < INT16_MAX);
|
|||
int16_t numscans, numbunches;
|
||||
static int16_t numhits;
|
||||
|
||||
int16_t searchit;
|
||||
int16_t searchsector, searchwall, searchstat; //search output
|
||||
|
||||
// SEARCHBOTTOMWALL:
|
||||
// When aiming at a the bottom part of a 2-sided wall whose bottom part
|
||||
// is swapped (.cstat&2), searchbottomwall equals that wall's .nextwall. In all
|
||||
// other cases (when aiming at a wall), searchbottomwall equals searchwall.
|
||||
//
|
||||
// SEARCHISBOTTOM:
|
||||
// When aiming at a 2-sided wall, 1 if aiming at the bottom part, 0 else
|
||||
int16_t searchbottomwall, searchisbottom;
|
||||
|
||||
bool inpreparemirror = 0;
|
||||
static int32_t mirrorsx1, mirrorsy1, mirrorsx2, mirrorsy2;
|
||||
|
||||
|
@ -319,9 +302,6 @@ static int32_t engineLoadTables(void)
|
|||
{
|
||||
int32_t i;
|
||||
|
||||
for (i=0; i<2048; i++)
|
||||
reciptable[i] = DivScale(2048, i+2048, 30);
|
||||
|
||||
for (i=0; i<=512; i++)
|
||||
sintable[i] = bsinf(i);
|
||||
for (i=513; i<1024; i++)
|
||||
|
@ -799,8 +779,6 @@ int32_t engineInit(void)
|
|||
|
||||
paletteloaded = 0;
|
||||
|
||||
searchit = 0; searchstat = -1;
|
||||
|
||||
g_visibility = 512;
|
||||
parallaxvisibility = 512;
|
||||
|
||||
|
@ -2607,6 +2585,7 @@ void dragpoint(int16_t pointhighlight, int32_t dax, int32_t day, uint8_t flags)
|
|||
|
||||
while (1)
|
||||
{
|
||||
sector[wall[w].sector].dirty = 255;
|
||||
wall[w].x = dax;
|
||||
wall[w].y = day;
|
||||
walbitmap[w>>3] |= pow2char[w&7];
|
||||
|
@ -2985,8 +2964,7 @@ void videoSetViewableArea(int32_t x1, int32_t y1, int32_t x2, int32_t y2)
|
|||
windowxy2.x = x2;
|
||||
windowxy2.y = y2;
|
||||
|
||||
xdimen = (x2-x1)+1; halfxdimen = (xdimen>>1);
|
||||
xdimenrecip = DivScale(1L,xdimen, 32);
|
||||
xdimen = (x2-x1)+1;
|
||||
ydimen = (y2-y1)+1;
|
||||
|
||||
fxdimen = (float) xdimen;
|
||||
|
@ -3124,36 +3102,6 @@ void renderCompleteMirror(void)
|
|||
}
|
||||
|
||||
|
||||
//
|
||||
// sectorofwall
|
||||
//
|
||||
static int32_t sectorofwall_internal(int16_t wallNum)
|
||||
{
|
||||
native_t gap = numsectors>>1, sectNum = gap;
|
||||
|
||||
while (gap > 1)
|
||||
{
|
||||
gap >>= 1;
|
||||
native_t const n = !!(sector[sectNum].wallptr < wallNum);
|
||||
sectNum += (n ^ (n - 1)) * gap;
|
||||
}
|
||||
while (sector[sectNum].wallptr > wallNum) sectNum--;
|
||||
while (sector[sectNum].wallptr + sector[sectNum].wallnum <= wallNum) sectNum++;
|
||||
|
||||
return sectNum;
|
||||
}
|
||||
|
||||
int32_t sectorofwall(int16_t wallNum)
|
||||
{
|
||||
if ((unsigned)wallNum < (unsigned)numwalls)
|
||||
{
|
||||
native_t const w = wall[wallNum].nextwall;
|
||||
return ((unsigned)w < MAXWALLS) ? wall[w].nextsector : sectorofwall_internal(wallNum);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int32_t getceilzofslopeptr(usectorptr_t sec, int32_t dax, int32_t day)
|
||||
{
|
||||
if (!(sec->ceilingstat&2))
|
||||
|
|
|
@ -39,7 +39,7 @@ 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 xdimen, xdimenrecip, halfxdimen, xdimenscale, xdimscale, ydimen;
|
||||
extern int32_t xdimen, xdimenscale, xdimscale, ydimen;
|
||||
extern float fxdimen;
|
||||
extern int32_t globalposx, globalposy, globalposz;
|
||||
extern fixed_t qglobalhoriz, qglobalang;
|
||||
|
@ -53,12 +53,6 @@ extern int16_t globalpicnum;
|
|||
|
||||
extern int32_t globalorientation;
|
||||
|
||||
extern int16_t editstatus;
|
||||
|
||||
extern int16_t searchit;
|
||||
extern int16_t searchsector, searchwall, searchstat;
|
||||
extern int16_t searchbottomwall, searchisbottom;
|
||||
|
||||
extern int16_t sectorborder[256];
|
||||
extern int32_t hitallsprites;
|
||||
|
||||
|
@ -67,7 +61,6 @@ extern int32_t rx1[MAXWALLSB], ry1[MAXWALLSB];
|
|||
extern int16_t bunchp2[MAXWALLSB];
|
||||
extern int16_t numscans, numbunches;
|
||||
extern int32_t rxi[8], ryi[8];
|
||||
extern int32_t reciptable[2048];
|
||||
|
||||
|
||||
// int32_t wallmost(int16_t *mostbuf, int32_t w, int32_t sectnum, char dastat);
|
||||
|
@ -84,18 +77,6 @@ static FORCE_INLINE int32_t bad_tspr(tspriteptr_t tspr)
|
|||
return (tspr->owner < 0 || (unsigned)tspr->picnum >= MAXTILES);
|
||||
}
|
||||
|
||||
//
|
||||
// getpalookup (internal)
|
||||
//
|
||||
static FORCE_INLINE int32_t getpalookup(int32_t davis, int32_t dashade)
|
||||
{
|
||||
if (getpalookup_replace)
|
||||
return getpalookup_replace(davis, dashade);
|
||||
return min(max(dashade + (davis >> 8), 0), numshades - 1);
|
||||
}
|
||||
|
||||
static FORCE_INLINE int32_t getpalookupsh(int32_t davis) { return getpalookup(davis, globalshade) << 8; }
|
||||
|
||||
static FORCE_INLINE void setgotpic(int32_t tilenume)
|
||||
{
|
||||
gotpic[tilenume>>3] |= pow2char[tilenume&7];
|
||||
|
|
|
@ -915,16 +915,6 @@ skip: ;
|
|||
#endif
|
||||
}
|
||||
|
||||
// Moved in from pragmas.h
|
||||
static inline int32_t krecipasm(int32_t i)
|
||||
{
|
||||
// Ken did this
|
||||
union { int32_t i; float f; } x;
|
||||
x.f = (float)i;
|
||||
i = x.i;
|
||||
return ((reciptable[(i >> 12) & 2047] >> (((i - 0x3f800000) >> 23) & 31)) ^ (i >> 31));
|
||||
}
|
||||
|
||||
// variables that are set to ceiling- or floor-members, depending
|
||||
// on which one is processed right now
|
||||
static int32_t global_cf_z;
|
||||
|
@ -956,14 +946,14 @@ static void polymost_internal_nonparallaxed(vec2f_t n0, vec2f_t n1, float ryp0,
|
|||
wall[wall[sec->wallptr].point2].y - wall[sec->wallptr].y };
|
||||
float r;
|
||||
|
||||
int length = ksqrt(uhypsq(xy.x, xy.y));
|
||||
if (globalorientation & 2)
|
||||
{
|
||||
int i = krecipasm(ksqrt(uhypsq(xy.x,xy.y)));
|
||||
r = i * (1.f/1073741824.f);
|
||||
r = 1.f / length;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = ksqrt(uhypsq(xy.x,xy.y)); if (i == 0) i = 1024; else i = 1048576 / i;
|
||||
int i; if (length == 0) i = 1024; else i = 1048576 / length; // consider integer truncation
|
||||
r = i * (1.f/1048576.f);
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ bool spriteIsModelOrVoxel(const spritetype * tspr)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void PlanesAtPoint(usectorptr_t sec, float dax, float day, float* pceilz, float* pflorz)
|
||||
void PlanesAtPoint(const sectortype* sec, float dax, float day, float* pceilz, float* pflorz)
|
||||
{
|
||||
float ceilz = float(sec->ceilingz);
|
||||
float florz = float(sec->floorz);
|
||||
|
@ -200,25 +200,3 @@ void PlanesAtPoint(usectorptr_t sec, float dax, float day, float* pceilz, float*
|
|||
if (pceilz) *pceilz = ceilz * -(1.f / 256.f);
|
||||
if (pflorz) *pflorz = florz * -(1.f / 256.f);
|
||||
}
|
||||
|
||||
// variant that allows to pass precalculated info for the first line in. For cases where multiple points in a sector need to be checked.
|
||||
void PlanesAtPoint(usectorptr_t sec, PlaneParam *pp, float dax, float day, float* pceilz, float* pflorz)
|
||||
{
|
||||
float ceilz = float(sec->ceilingz);
|
||||
float florz = float(sec->floorz);
|
||||
|
||||
if (((sec->ceilingstat | sec->floorstat) & CSTAT_SECTOR_SLOPE) == CSTAT_SECTOR_SLOPE)
|
||||
{
|
||||
if (pp->length != 0)
|
||||
{
|
||||
auto wal = &wall[sec->wallptr];
|
||||
float const j = (pp->dx * (day - wal->y) - pp->dy * (dax - wal->x)) * (1.f / 8.f);
|
||||
if (sec->ceilingstat & CSTAT_SECTOR_SLOPE) ceilz += (sec->ceilingheinum * j) / pp->length;
|
||||
if (sec->floorstat & CSTAT_SECTOR_SLOPE) florz += (sec->floorheinum * j) / pp->length;
|
||||
}
|
||||
}
|
||||
// Scale to render coordinates.
|
||||
if (pceilz) *pceilz = ceilz * -(1.f / 256.f);
|
||||
if (pflorz) *pflorz = florz * -(1.f / 256.f);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,15 +8,8 @@ extern int cameradist, cameraclock;
|
|||
|
||||
bool calcChaseCamPos(int* px, int* py, int* pz, spritetype* pspr, short *psectnum, binangle ang, fixedhoriz horiz, double const smoothratio);
|
||||
bool spriteIsModelOrVoxel(const spritetype* tspr);
|
||||
void PlanesAtPoint(usectorptr_t sec, float dax, float day, float* ceilz, float* florz);
|
||||
|
||||
struct PlaneParam
|
||||
{
|
||||
float dx, dy;
|
||||
int length;
|
||||
};
|
||||
|
||||
void PlanesAtPoint(usectorptr_t sec, PlaneParam* pp, float dax, float day, float* ceilz, float* florz);
|
||||
void PlanesAtPoint(const sectortype* sec, float dax, float day, float* ceilz, float* florz);
|
||||
void setWallSectors();
|
||||
|
||||
// y is negated so that the orientation is the same as in GZDoom, in order to use its utilities.
|
||||
// The render code should NOT use Build coordinates for anything!
|
||||
|
@ -76,3 +69,10 @@ inline double PointOnLineSide(double x, double y, double linex, double liney, do
|
|||
return (x - linex) * deltay - (y - liney) * deltax;
|
||||
}
|
||||
|
||||
inline int sectorofwall(int wallNum)
|
||||
{
|
||||
if ((unsigned)wallNum < (unsigned)numwalls) return wall[wallNum].sector;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -72,8 +72,8 @@ void Set(int index, int type, double val)
|
|||
case Interp_Sect_CeilingPanX: sector[index].ceilingxpan_ = float(val); break;
|
||||
case Interp_Sect_CeilingPanY: sector[index].ceilingypan_ = float(val); break;
|
||||
|
||||
case Interp_Wall_X: wall[index].x = xs_CRoundToInt(val); break;
|
||||
case Interp_Wall_Y: wall[index].y = xs_CRoundToInt(val); break;
|
||||
case Interp_Wall_X: wall[index].x = xs_CRoundToInt(val); sector[wall[index].sector].dirty = 255; break;
|
||||
case Interp_Wall_Y: wall[index].y = xs_CRoundToInt(val); sector[wall[index].sector].dirty = 255; break;
|
||||
case Interp_Wall_PanX: wall[index].xpan_ = float(val); break;
|
||||
case Interp_Wall_PanY: wall[index].ypan_ = float(val); break;
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
#include "inputstate.h"
|
||||
#include "md4.h"
|
||||
#include "gamecontrol.h"
|
||||
#include "gamefuncs.h"
|
||||
#include "sectorgeometry.h"
|
||||
|
||||
|
||||
static void ReadSectorV7(FileReader& fr, sectortype& sect)
|
||||
|
@ -444,6 +446,7 @@ void engineLoadBoard(const char* filename, int flags, vec3_t* pos, int16_t* ang,
|
|||
unsigned char md4[16];
|
||||
md4once(buffer.Data(), buffer.Size(), md4);
|
||||
G_LoadMapHack(filename, md4);
|
||||
setWallSectors();
|
||||
|
||||
memcpy(wallbackup, wall, sizeof(wallbackup));
|
||||
memcpy(sectorbackup, sector, sizeof(sectorbackup));
|
||||
|
@ -468,4 +471,18 @@ void loadMapBackup(const char* filename)
|
|||
engineLoadBoard(filename, 0, &pos, &scratch, &scratch);
|
||||
initspritelists();
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the sector reference for each wall. We need this for the triangulation cache.
|
||||
void setWallSectors()
|
||||
{
|
||||
for (int i = 0; i < numsectors; i++)
|
||||
{
|
||||
sector[i].dirty = 255;
|
||||
for (int w = 0; w < sector[i].wallnum; w++)
|
||||
{
|
||||
wall[sector[i].wallptr + w].sector = i;
|
||||
}
|
||||
}
|
||||
sectorGeometry.SetSize(numsectors);
|
||||
}
|
|
@ -185,7 +185,7 @@ FRenderViewpoint SetupView(vec3_t& position, int sectnum, fixed_t q16angle, fixe
|
|||
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.Roll = -rollang;
|
||||
r_viewpoint.FieldOfView = (float)r_fov;
|
||||
r_viewpoint.RotAngle = q16ang(q16angle).asbam();
|
||||
return r_viewpoint;
|
||||
|
|
|
@ -35,8 +35,7 @@
|
|||
#include "hw_lightbuffer.h"
|
||||
#include "hw_drawstructs.h"
|
||||
#include "hw_renderstate.h"
|
||||
#include "texturemanager.h"
|
||||
#include "earcut.hpp"
|
||||
#include "sectorgeometry.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
CVAR(Int, gl_breaksec, -1, 0)
|
||||
|
@ -92,115 +91,26 @@ void HWFlat::SetupLights(HWDrawInfo *di, FLightNode * node, FDynLightData &light
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// CalcPlane fixme - this should be stored in the sector, not be recalculated each frame.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FVector3 CalcNormal(sectortype* sector, int plane)
|
||||
{
|
||||
FVector3 pt[3];
|
||||
|
||||
auto wal = &wall[sector->wallptr];
|
||||
auto wal2 = &wall[wal->point2];
|
||||
|
||||
pt[0] = { (float)WallStartX(wal), (float)WallStartY(wal), 0 };
|
||||
pt[1] = { (float)WallEndX(wal), (float)WallEndY(wal), 0 };
|
||||
PlanesAtPoint(sector, wal->x, wal->y, plane ? &pt[0].Z : nullptr, plane? nullptr : &pt[0].Z);
|
||||
PlanesAtPoint(sector, wal2->x, wal2->y, plane ? &pt[1].Z : nullptr, plane ? nullptr : &pt[1].Z);
|
||||
|
||||
if (pt[0].X == pt[1].X)
|
||||
{
|
||||
if (pt[0].Y == pt[1].Y) return { 0.f, 0.f, plane ? -1.f : 1.f };
|
||||
pt[2].X = pt[0].X + 4;
|
||||
pt[2].Y = pt[0].Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
pt[2].X = pt[0].X;
|
||||
pt[2].Y = pt[0].Y + 4;
|
||||
}
|
||||
PlanesAtPoint(sector, pt[2].X * 16, pt[2].Y * 16, plane ? &pt[2].Z : nullptr, plane ? nullptr : &pt[2].Z);
|
||||
|
||||
auto normal = (pt[2] - pt[0]) ^ (pt[1] - pt[0]);
|
||||
|
||||
if ((pt[2].Z < 0 && !plane) || (pt[2].Z > 0 && plane)) return -pt[2];
|
||||
return pt[2];
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// this should be buffered later.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void HWFlat::MakeVertices()
|
||||
{
|
||||
int numvertices = sec->wallnum;
|
||||
|
||||
TArray<FVector3> points(numvertices, true);
|
||||
using Point = std::pair<float, float>;
|
||||
std::vector<std::vector<Point>> polygon;
|
||||
std::vector<Point>* curPoly;
|
||||
|
||||
polygon.resize(1);
|
||||
curPoly = &polygon.back();
|
||||
|
||||
for (int i = 0; i < numvertices; i++)
|
||||
{
|
||||
auto wal = &wall[sec->wallptr + i];
|
||||
|
||||
float X = WallStartX(wal);
|
||||
float Y = WallStartY(wal);
|
||||
curPoly->push_back(std::make_pair(X, Y));
|
||||
if (wal->point2 != sec->wallptr+i+1 && i < numvertices - 1)
|
||||
{
|
||||
polygon.resize(polygon.size() + 1);
|
||||
curPoly = &polygon.back();
|
||||
}
|
||||
}
|
||||
// Now make sure that the outer boundary is the first polygon by picking a point that's as much to the outside as possible.
|
||||
int outer = 0;
|
||||
float minx = FLT_MAX;
|
||||
float miny = FLT_MAX;
|
||||
for (size_t a = 0; a < polygon.size(); a++)
|
||||
{
|
||||
for (auto& pt : polygon[a])
|
||||
{
|
||||
if (pt.first < minx || (pt.first == minx && pt.second < miny))
|
||||
{
|
||||
minx = pt.first;
|
||||
miny = pt.second;
|
||||
outer = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (outer != 0) std::swap(polygon[0], polygon[outer]);
|
||||
auto indices = mapbox::earcut(polygon);
|
||||
|
||||
int p = 0;
|
||||
for (size_t a = 0; a < polygon.size(); a++)
|
||||
{
|
||||
for (auto& pt : polygon[a])
|
||||
{
|
||||
float planez;
|
||||
PlanesAtPoint(sec, (pt.first * 16), (pt.second * -16), plane ? &planez : nullptr, !plane ? &planez : nullptr);
|
||||
FVector3 point = { pt.first, pt.second, planez };
|
||||
points[p++] = point;
|
||||
}
|
||||
}
|
||||
|
||||
auto ret = screen->mVertexData->AllocVertices(indices.size());
|
||||
auto mesh = sectorGeometry.get(sec - sector, plane);
|
||||
if (!mesh) return;
|
||||
auto ret = screen->mVertexData->AllocVertices(mesh->vertices.Size());
|
||||
auto vp = ret.first;
|
||||
for (auto i : indices)
|
||||
for (unsigned i = 0; i < mesh->vertices.Size(); i++)
|
||||
{
|
||||
auto& pt = points[i];
|
||||
auto& pt = mesh->vertices[i];
|
||||
auto& uv = mesh->texcoords[i];
|
||||
vp->SetVertex(pt.X, pt.Z, pt.Y);
|
||||
vp->SetTexCoord(pt.X / 64.f, pt.Y / 64.f); // todo: align
|
||||
vp->SetTexCoord(uv.X, uv.Y);
|
||||
vp++;
|
||||
}
|
||||
vertindex = ret.second;
|
||||
vertcount = indices.size();
|
||||
vertcount = mesh->vertices.Size();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -222,7 +132,8 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent)
|
|||
}
|
||||
#endif
|
||||
|
||||
state.SetNormal(CalcNormal(sector, plane));
|
||||
auto mesh = sectorGeometry.get(sec - sector, plane);
|
||||
state.SetNormal(mesh->normal);
|
||||
|
||||
// Fog must be done before the texture so that the texture selector can override it.
|
||||
bool foggy = (GlobalMapFog || (fade & 0xffffff));
|
||||
|
@ -275,6 +186,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent)
|
|||
|
||||
void HWFlat::PutFlat(HWDrawInfo *di, int whichplane)
|
||||
{
|
||||
plane = whichplane;
|
||||
if (!screen->BuffersArePersistent()) // should be made static buffer content later (when the logic is working)
|
||||
{
|
||||
#if 0
|
||||
|
@ -285,7 +197,6 @@ void HWFlat::PutFlat(HWDrawInfo *di, int whichplane)
|
|||
#endif
|
||||
MakeVertices();
|
||||
}
|
||||
plane = whichplane;
|
||||
di->AddFlat(this);
|
||||
rendered_flats++;
|
||||
}
|
||||
|
|
|
@ -615,34 +615,6 @@ bool HWWall::DoHorizon(HWDrawInfo* di, walltype* seg, sectortype* fs, DVector2&
|
|||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Build math sucks. This would be easier if NPOT was handled properly.
|
||||
// Panning is calculated in NPOT dimensions only, the next largest one
|
||||
// to the texture height applies, so the panning needs to be scaled accordingly.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static float GetYPanning(float curypanning, FGameTexture* tex/*, bool aligned*/)
|
||||
{
|
||||
// get next largest POT size.
|
||||
int th = tex->GetTexelHeight();
|
||||
int pow2size = 1 << sizeToBits(th);
|
||||
if (pow2size < th) pow2size *= 2;
|
||||
|
||||
/* crap for lack of NPOT emulation. Should not be needed anymore
|
||||
if (aligned)
|
||||
{
|
||||
float yoffs = (pow2size - th) * (255.0f / pow2size);
|
||||
if (curypanning > 256 - yoffs)
|
||||
curypanning -= yoffs;
|
||||
}
|
||||
*/
|
||||
|
||||
// scale the panning factor and scale to texture coordinates.
|
||||
return pow2size * curypanning / (256.0f * th);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -721,7 +693,7 @@ void HWWall::CheckTexturePosition()
|
|||
|
||||
// clamp texture coordinates to a reasonable range.
|
||||
// Extremely large values can cause visual problems
|
||||
if (tcs[UPLFT].v > tcs[LOLFT].v || tcs[UPRGT].v > tcs[LORGT].v)
|
||||
if (tcs[UPLFT].v < tcs[LOLFT].v || tcs[UPRGT].v < tcs[LORGT].v)
|
||||
{
|
||||
if (tcs[UPLFT].v < tcs[UPRGT].v)
|
||||
{
|
||||
|
@ -775,7 +747,6 @@ void HWWall::CheckTexturePosition()
|
|||
void HWWall::DoTexture(HWDrawInfo* di, walltype* wal, walltype* refwall, float refheight, float topleft, float topright, float bottomleft, float bottomright)
|
||||
{
|
||||
auto glsave = glseg;
|
||||
float ypanning = wal->ypan_ ? GetYPanning(wal->ypan_, texture) : 0;
|
||||
SetWallCoordinates(wal, topleft, topright, bottomleft, bottomright);
|
||||
|
||||
bool xflipped = (wal->cstat & CSTAT_WALL_XFLIP);
|
||||
|
@ -784,8 +755,12 @@ void HWWall::DoTexture(HWDrawInfo* di, walltype* wal, walltype* refwall, float r
|
|||
|
||||
float tw = texture->GetTexelWidth();
|
||||
float th = texture->GetTexelHeight();
|
||||
tcs[LOLFT].u = tcs[UPLFT].u = ((leftdist * 8.f * wal->xrepeat) + wal->xpan_) / tw;
|
||||
tcs[LORGT].u = tcs[UPRGT].u = ((rightdist * 8.f * wal->xrepeat) + wal->xpan_) / tw;
|
||||
int pow2size = 1 << sizeToBits(th);
|
||||
if (pow2size < th) pow2size *= 2;
|
||||
float ypanning = refwall->ypan_ ? pow2size * refwall->ypan_ / (256.0f * th) : 0;
|
||||
|
||||
tcs[LOLFT].u = tcs[UPLFT].u = ((leftdist * 8.f * wal->xrepeat) + refwall->xpan_) / tw;
|
||||
tcs[LORGT].u = tcs[UPRGT].u = ((rightdist * 8.f * wal->xrepeat) + refwall->xpan_) / tw;
|
||||
|
||||
auto setv = [=](float hl, float hr, float frac) -> float
|
||||
{
|
||||
|
@ -799,7 +774,7 @@ void HWWall::DoTexture(HWDrawInfo* di, walltype* wal, walltype* refwall, float r
|
|||
tcs[LOLFT].v = setv(bottomleft, bottomright, glseg.fracleft);
|
||||
tcs[UPRGT].v = setv(topleft, topright, glseg.fracright);
|
||||
tcs[LORGT].v = setv(bottomleft, bottomright, glseg.fracright);
|
||||
CheckTexturePosition();
|
||||
if (th == pow2size) CheckTexturePosition(); // for NPOT textures this adjustment can break things.
|
||||
bool trans = type == RENDERWALL_M2S && (wal->cstat & CSTAT_WALL_TRANSLUCENT);
|
||||
if (trans)
|
||||
{
|
||||
|
@ -807,6 +782,7 @@ void HWWall::DoTexture(HWDrawInfo* di, walltype* wal, walltype* refwall, float r
|
|||
alpha = GetAlphaFromBlend((wal->cstat & CSTAT_WALL_TRANS_FLIP) ? DAMETH_TRANS2 : DAMETH_TRANS1, 0);
|
||||
}
|
||||
PutWall(di, trans);
|
||||
flags = 0;
|
||||
glseg = glsave;
|
||||
}
|
||||
|
||||
|
@ -851,7 +827,7 @@ void HWWall::DoUpperTexture(HWDrawInfo* di, walltype* wal, sectortype* frontsect
|
|||
// get the alignment reference position.
|
||||
int refheight = (wal->cstat & CSTAT_WALL_ALIGN_BOTTOM) ? frontsector->ceilingz : backsector->ceilingz;
|
||||
|
||||
type = RENDERWALL_BOTTOM;
|
||||
type = RENDERWALL_TOP;
|
||||
DoTexture(di, wal, wal, refheight, topleft, topright, bottomleft, bottomright);
|
||||
}
|
||||
|
||||
|
@ -867,7 +843,7 @@ void HWWall::DoLowerTexture(HWDrawInfo* di, walltype* wal, sectortype* frontsect
|
|||
// get the alignment reference position.
|
||||
int refheight;
|
||||
auto refwall = (wal->cstat & CSTAT_WALL_BOTTOM_SWAP) ? &wall[wal->nextwall] : wal;
|
||||
refheight = (wal->cstat & CSTAT_WALL_ALIGN_BOTTOM) ? frontsector->ceilingz : backsector->floorz;
|
||||
refheight = (refwall->cstat & CSTAT_WALL_ALIGN_BOTTOM) ? frontsector->ceilingz : backsector->floorz;
|
||||
|
||||
shade = refwall->shade;
|
||||
palette = refwall->pal;
|
||||
|
@ -942,7 +918,7 @@ void HWWall::Process(HWDrawInfo *di, walltype *wal, sectortype* frontsector, sec
|
|||
PlanesAtPoint(frontsector, p2wall->x, p2wall->y, &fch2, &ffh2);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (wal - wall == 3810)
|
||||
if (wal - wall == 7591)
|
||||
{
|
||||
int a = 0;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "gamestate.h"
|
||||
#include "razemenu.h"
|
||||
#include "interpolate.h"
|
||||
#include "gamefuncs.h"
|
||||
|
||||
|
||||
sectortype sectorbackup[MAXSECTORS];
|
||||
|
@ -670,6 +671,10 @@ void SerializeMap(FSerializer& arc)
|
|||
if (prevspritestat[i] == -2) prevspritestat[i] = i - 1;
|
||||
if (prevspritesect[i] == -2) prevspritesect[i] = i - 1;
|
||||
}
|
||||
if (arc.isReading())
|
||||
{
|
||||
setWallSectors();
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
|
325
source/core/sectorgeometry.cpp
Normal file
325
source/core/sectorgeometry.cpp
Normal file
|
@ -0,0 +1,325 @@
|
|||
/*
|
||||
** sectorgeometry.cpp
|
||||
**
|
||||
** caches the triangle meshes used for rendering sector planes.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2021 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
**
|
||||
*/
|
||||
|
||||
#include "sectorgeometry.h"
|
||||
#include "build.h"
|
||||
#include "gamefuncs.h"
|
||||
#include "texturemanager.h"
|
||||
#include "earcut.hpp"
|
||||
|
||||
SectorGeometry sectorGeometry;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CalcPlane fixme - this should be stored in the sector, not be recalculated each frame.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FVector3 CalcNormal(sectortype* sector, int plane)
|
||||
{
|
||||
FVector3 pt[3];
|
||||
|
||||
auto wal = &wall[sector->wallptr];
|
||||
auto wal2 = &wall[wal->point2];
|
||||
|
||||
pt[0] = { (float)WallStartX(wal), (float)WallStartY(wal), 0 };
|
||||
pt[1] = { (float)WallEndX(wal), (float)WallEndY(wal), 0 };
|
||||
PlanesAtPoint(sector, wal->x, wal->y, plane ? &pt[0].Z : nullptr, plane? nullptr : &pt[0].Z);
|
||||
PlanesAtPoint(sector, wal2->x, wal2->y, plane ? &pt[1].Z : nullptr, plane ? nullptr : &pt[1].Z);
|
||||
|
||||
if (pt[0].X == pt[1].X)
|
||||
{
|
||||
if (pt[0].Y == pt[1].Y) return { 0.f, 0.f, plane ? -1.f : 1.f };
|
||||
pt[2].X = pt[0].X + 4;
|
||||
pt[2].Y = pt[0].Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
pt[2].X = pt[0].X;
|
||||
pt[2].Y = pt[0].Y + 4;
|
||||
}
|
||||
PlanesAtPoint(sector, pt[2].X * 16, pt[2].Y * 16, plane ? &pt[2].Z : nullptr, plane ? nullptr : &pt[2].Z);
|
||||
|
||||
auto normal = (pt[2] - pt[0]) ^ (pt[1] - pt[0]);
|
||||
|
||||
if ((pt[2].Z < 0 && !plane) || (pt[2].Z > 0 && plane)) return -pt[2];
|
||||
return pt[2];
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// The math used here to calculate texture positioning was derived from
|
||||
// Polymer but required several fixes for correctness.
|
||||
//
|
||||
//==========================================================================
|
||||
class UVCalculator
|
||||
{
|
||||
sectortype* sect;
|
||||
int myplane;
|
||||
int stat;
|
||||
float z1;
|
||||
int ix1;
|
||||
int iy1;
|
||||
int ix2;
|
||||
int iy2;
|
||||
float sinalign, cosalign;
|
||||
FGameTexture* tex;
|
||||
float xpanning, ypanning;
|
||||
float xscaled, yscaled;
|
||||
|
||||
public:
|
||||
|
||||
// Moved in from pragmas.h
|
||||
UVCalculator(sectortype* sec, int plane, FGameTexture* tx)
|
||||
{
|
||||
float xpan, ypan;
|
||||
|
||||
sect = sec;
|
||||
tex = tx;
|
||||
myplane = plane;
|
||||
|
||||
auto firstwall = &wall[sec->wallptr];
|
||||
ix1 = firstwall->x;
|
||||
iy1 = firstwall->y;
|
||||
ix2 = wall[firstwall->point2].x;
|
||||
iy2 = wall[firstwall->point2].y;
|
||||
|
||||
if (plane == 0)
|
||||
{
|
||||
stat = sec->floorstat;
|
||||
xpan = sec->floorxpan_;
|
||||
ypan = sec->floorypan_;
|
||||
PlanesAtPoint(sec, ix1, iy1, nullptr, &z1);
|
||||
}
|
||||
else
|
||||
{
|
||||
stat = sec->ceilingstat;
|
||||
xpan = sec->ceilingxpan_;
|
||||
ypan = sec->ceilingypan_;
|
||||
PlanesAtPoint(sec, ix1, iy1, &z1, nullptr);
|
||||
}
|
||||
|
||||
DVector2 dv = { double(ix2 - ix1), -double(iy2 - iy1) };
|
||||
auto vang = dv.Angle() - 90.;
|
||||
|
||||
cosalign = vang.Cos();
|
||||
sinalign = vang.Sin();
|
||||
|
||||
int pow2width = 1 << sizeToBits(tx->GetTexelWidth());
|
||||
if (pow2width < tx->GetTexelWidth()) pow2width *= 2;
|
||||
|
||||
int pow2height = 1 << sizeToBits(tx->GetTexelHeight());
|
||||
if (pow2height < tx->GetTexelHeight()) pow2height *= 2;
|
||||
|
||||
xpanning = pow2width * xpan / (256.f * tx->GetTexelWidth());
|
||||
ypanning = pow2height * ypan / (256.f * tx->GetTexelHeight());
|
||||
|
||||
float scalefactor = (stat & CSTAT_SECTOR_TEXHALF) ? 8.0f : 16.0f;
|
||||
|
||||
if ((stat & (CSTAT_SECTOR_SLOPE | CSTAT_SECTOR_ALIGN)) == (CSTAT_SECTOR_ALIGN))
|
||||
{
|
||||
// This is necessary to adjust for some imprecisions in the math.
|
||||
// To calculate the inverse Build performs an integer division with significant loss of precision
|
||||
// that can cause the texture to be shifted by multiple pixels.
|
||||
// The code below calculates the amount of this deviation so that it can be added back to the formula.
|
||||
int len = ksqrt(uhypsq(ix2 - ix1, iy2 - iy1));
|
||||
if (len != 0)
|
||||
{
|
||||
int i = 1048576 / len;
|
||||
scalefactor *= 1048576.f / (i * len);
|
||||
}
|
||||
}
|
||||
|
||||
xscaled = scalefactor * tx->GetTexelWidth();
|
||||
yscaled = scalefactor * tx->GetTexelHeight();
|
||||
}
|
||||
|
||||
FVector2 GetUV(int x, int y, float z)
|
||||
{
|
||||
float tv, tu;
|
||||
|
||||
if (stat & CSTAT_SECTOR_ALIGN)
|
||||
{
|
||||
float dx = (float)(x - ix1);
|
||||
float dy = (float)(y - iy1);
|
||||
|
||||
tu = -(dx * sinalign + dy * cosalign);
|
||||
tv = (dx * cosalign - dy * sinalign);
|
||||
|
||||
if (stat & CSTAT_SECTOR_SLOPE)
|
||||
{
|
||||
float dz = (z - z1) * 16;
|
||||
float newtv = sqrt(tv * tv + dz * dz);
|
||||
tv = tv < 0 ? -newtv : newtv;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tu = x;
|
||||
tv = -y;
|
||||
}
|
||||
|
||||
if (stat & CSTAT_SECTOR_SWAPXY)
|
||||
std::swap(tu, tv);
|
||||
|
||||
if (stat & CSTAT_SECTOR_XFLIP) tu = -tu;
|
||||
if (stat & CSTAT_SECTOR_YFLIP) tv = -tv;
|
||||
|
||||
|
||||
|
||||
return { tu / xscaled + xpanning, tv / yscaled + ypanning };
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SectorGeometry::MakeVertices(unsigned int secnum, int plane)
|
||||
{
|
||||
auto sec = §or[secnum];
|
||||
int numvertices = sec->wallnum;
|
||||
|
||||
TArray<FVector3> points(numvertices, true);
|
||||
using Point = std::pair<float, float>;
|
||||
std::vector<std::vector<Point>> polygon;
|
||||
std::vector<Point>* curPoly;
|
||||
|
||||
polygon.resize(1);
|
||||
curPoly = &polygon.back();
|
||||
|
||||
for (int i = 0; i < numvertices; i++)
|
||||
{
|
||||
auto wal = &wall[sec->wallptr + i];
|
||||
|
||||
float X = WallStartX(wal);
|
||||
float Y = WallStartY(wal);
|
||||
curPoly->push_back(std::make_pair(X, Y));
|
||||
if (wal->point2 != sec->wallptr+i+1 && i < numvertices - 1)
|
||||
{
|
||||
polygon.resize(polygon.size() + 1);
|
||||
curPoly = &polygon.back();
|
||||
}
|
||||
}
|
||||
// Now make sure that the outer boundary is the first polygon by picking a point that's as much to the outside as possible.
|
||||
int outer = 0;
|
||||
float minx = FLT_MAX;
|
||||
float miny = FLT_MAX;
|
||||
for (size_t a = 0; a < polygon.size(); a++)
|
||||
{
|
||||
for (auto& pt : polygon[a])
|
||||
{
|
||||
if (pt.first < minx || (pt.first == minx && pt.second < miny))
|
||||
{
|
||||
minx = pt.first;
|
||||
miny = pt.second;
|
||||
outer = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (outer != 0) std::swap(polygon[0], polygon[outer]);
|
||||
auto indices = mapbox::earcut(polygon);
|
||||
|
||||
int p = 0;
|
||||
for (size_t a = 0; a < polygon.size(); a++)
|
||||
{
|
||||
for (auto& pt : polygon[a])
|
||||
{
|
||||
float planez;
|
||||
PlanesAtPoint(sec, (pt.first * 16), (pt.second * -16), plane ? &planez : nullptr, !plane ? &planez : nullptr);
|
||||
FVector3 point = { pt.first, pt.second, planez };
|
||||
points[p++] = point;
|
||||
}
|
||||
}
|
||||
|
||||
auto& entry = data[secnum].planes[plane];
|
||||
entry.vertices.Resize(indices.size());
|
||||
entry.texcoords.Resize(indices.size());
|
||||
entry.normal = CalcNormal(sec, plane);
|
||||
|
||||
auto texture = tileGetTexture(plane ? sec->ceilingpicnum : sec->floorpicnum);
|
||||
|
||||
UVCalculator uvcalc(sec, plane, texture);
|
||||
|
||||
for(unsigned i = 0; i < entry.vertices.Size(); i++)
|
||||
{
|
||||
auto& pt = points[indices[i]];
|
||||
entry.vertices[i] = pt;
|
||||
entry.texcoords[i] = uvcalc.GetUV(int(pt.X * 16), int(pt.Y * -16), pt.Z);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void SectorGeometry::ValidateSector(unsigned int secnum, int plane)
|
||||
{
|
||||
auto sec = §or[secnum];
|
||||
auto compare = &data[secnum].compare;
|
||||
if (plane == 0)
|
||||
{
|
||||
if (sec->floorheinum == compare->floorheinum &&
|
||||
sec->floorpicnum == compare->floorpicnum &&
|
||||
((sec->floorstat ^ compare->floorstat) & (CSTAT_SECTOR_ALIGN | CSTAT_SECTOR_YFLIP | CSTAT_SECTOR_XFLIP | CSTAT_SECTOR_TEXHALF | CSTAT_SECTOR_SWAPXY)) == 0 &&
|
||||
sec->floorxpan_ == compare->floorxpan_ &&
|
||||
sec->floorypan_ == compare->floorypan_ &&
|
||||
sec->floorz == compare->floorz &&
|
||||
!(sec->dirty & 1) && data[secnum].planes[plane].vertices.Size() ) return;
|
||||
|
||||
sec->dirty &= ~1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sec->ceilingheinum == compare->ceilingheinum &&
|
||||
sec->ceilingpicnum == compare->ceilingpicnum &&
|
||||
((sec->ceilingstat ^ compare->ceilingstat) & (CSTAT_SECTOR_ALIGN | CSTAT_SECTOR_YFLIP | CSTAT_SECTOR_XFLIP | CSTAT_SECTOR_TEXHALF | CSTAT_SECTOR_SWAPXY)) == 0 &&
|
||||
sec->ceilingxpan_ == compare->ceilingxpan_ &&
|
||||
sec->ceilingypan_ == compare->ceilingypan_ &&
|
||||
sec->ceilingz == compare->ceilingz &&
|
||||
!(sec->dirty & 2) && data[secnum].planes[plane].vertices.Size()) return;
|
||||
|
||||
sec->dirty &= ~2;
|
||||
}
|
||||
*compare = *sec;
|
||||
MakeVertices(secnum, plane);
|
||||
}
|
44
source/core/sectorgeometry.h
Normal file
44
source/core/sectorgeometry.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
|
||||
#include "tarray.h"
|
||||
#include "vectors.h"
|
||||
#include "build.h"
|
||||
|
||||
struct SectorGeometryPlane
|
||||
{
|
||||
TArray<FVector3> vertices;
|
||||
TArray<FVector2> texcoords;
|
||||
FVector3 normal{};
|
||||
};
|
||||
|
||||
struct SectorGeometryData
|
||||
{
|
||||
SectorGeometryPlane planes[2];
|
||||
sectortype compare{};
|
||||
};
|
||||
|
||||
class SectorGeometry
|
||||
{
|
||||
TArray<SectorGeometryData> data;
|
||||
|
||||
void ValidateSector(unsigned sectnum, int plane);
|
||||
void MakeVertices(unsigned sectnum, int plane);
|
||||
|
||||
public:
|
||||
SectorGeometryPlane* get(unsigned sectnum, int plane)
|
||||
{
|
||||
if (sectnum >= data.Size()) return nullptr;
|
||||
ValidateSector(sectnum, plane);
|
||||
return &data[sectnum].planes[plane];
|
||||
}
|
||||
|
||||
void SetSize(unsigned sectcount)
|
||||
{
|
||||
data.Clear(); // delete old content
|
||||
data.Resize(sectcount);
|
||||
}
|
||||
};
|
||||
|
||||
extern SectorGeometry sectorGeometry;
|
||||
|
||||
|
|
@ -31,6 +31,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "md4.h"
|
||||
#include "automap.h"
|
||||
#include "raze_sound.h"
|
||||
#include "gamefuncs.h"
|
||||
|
||||
#include "blood.h"
|
||||
|
||||
|
@ -1058,6 +1059,7 @@ void dbLoadMap(const char *pPath, int *pX, int *pY, int *pZ, short *pAngle, shor
|
|||
}
|
||||
}
|
||||
|
||||
setWallSectors();
|
||||
memcpy(wallbackup, wall, sizeof(wallbackup));
|
||||
memcpy(sectorbackup, sector, sizeof(sectorbackup));
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ void sub_5571C(char mode);
|
|||
void sub_557C4(int x, int y, int interpolation);
|
||||
void DrawMirrors(int x, int y, int z, fixed_t a, fixed_t horiz, int smooth, int viewPlayer);
|
||||
int qanimateoffs(int a1, int a2);
|
||||
int32_t qgetpalookup(int32_t a1, int32_t a2);
|
||||
void HookReplaceFunctions();
|
||||
|
||||
struct QAV;
|
||||
|
|
|
@ -62,14 +62,6 @@ int qanimateoffs(int a1, int a2)
|
|||
return offset;
|
||||
}
|
||||
|
||||
int32_t qgetpalookup(int32_t a1, int32_t a2)
|
||||
{
|
||||
if (gFogMode)
|
||||
return ClipHigh(a1 >> 8, 15) * 16 + ClipRange(a2, 0, 15);
|
||||
else
|
||||
return ClipRange((a1 >> 8) + a2, 0, 63);
|
||||
}
|
||||
|
||||
void qinitspritelists();
|
||||
int32_t qinsertsprite(int16_t nSector, int16_t nStat);
|
||||
int32_t qdeletesprite(int16_t nSprite);
|
||||
|
@ -79,7 +71,6 @@ int32_t qchangespritestat(int16_t nSprite, int16_t nStatus);
|
|||
void HookReplaceFunctions(void)
|
||||
{
|
||||
animateoffs_replace = qanimateoffs;
|
||||
getpalookup_replace = qgetpalookup;
|
||||
initspritelists_replace = qinitspritelists;
|
||||
insertsprite_replace = qinsertsprite;
|
||||
deletesprite_replace = qdeletesprite;
|
||||
|
|
|
@ -794,6 +794,7 @@ void PathSound(int nSector, int nSound)
|
|||
|
||||
void DragPoint(int nWall, int x, int y)
|
||||
{
|
||||
sector[wall[nWall].sector].dirty = 255;
|
||||
viewInterpolateWall(nWall, &wall[nWall]);
|
||||
wall[nWall].x = x;
|
||||
wall[nWall].y = y;
|
||||
|
@ -805,6 +806,7 @@ void DragPoint(int nWall, int x, int y)
|
|||
if (wall[vb].nextwall >= 0)
|
||||
{
|
||||
vb = wall[wall[vb].nextwall].point2;
|
||||
sector[wall[vb].sector].dirty = 255;
|
||||
viewInterpolateWall(vb, &wall[vb]);
|
||||
wall[vb].x = x;
|
||||
wall[vb].y = y;
|
||||
|
@ -817,6 +819,7 @@ void DragPoint(int nWall, int x, int y)
|
|||
if (wall[lastwall(vb)].nextwall >= 0)
|
||||
{
|
||||
vb = wall[lastwall(vb)].nextwall;
|
||||
sector[wall[vb].sector].dirty = 255;
|
||||
viewInterpolateWall(vb, &wall[vb]);
|
||||
wall[vb].x = x;
|
||||
wall[vb].y = y;
|
||||
|
|
|
@ -977,7 +977,7 @@ void DoWall(char bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, s
|
|||
else SetGameVarID((int)lVar2, wall[iWall].overpicnum, sActor, sPlayer);
|
||||
break;
|
||||
case WALL_SHADE:
|
||||
if (bSet) wall[iWall].x = lValue;
|
||||
if (bSet) wall[iWall].shade = lValue;
|
||||
else SetGameVarID((int)lVar2, wall[iWall].shade, sActor, sPlayer);
|
||||
break;
|
||||
case WALL_PAL:
|
||||
|
@ -1009,8 +1009,8 @@ void DoWall(char bSet, int lVar1, int lLabelID, int lVar2, DDukeActor* sActor, s
|
|||
else SetGameVarID((int)lVar2, wall[iWall].hitag, sActor, sPlayer);
|
||||
break;
|
||||
case WALL_EXTRA:
|
||||
if (bSet) wall[iWall].x = lValue;
|
||||
else SetGameVarID((int)lVar2, wall[iWall].x, sActor, sPlayer);
|
||||
if (bSet) wall[iWall].extra = lValue;
|
||||
else SetGameVarID((int)lVar2, wall[iWall].extra, sActor, sPlayer);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue