- overhauled getzrangepoint to use backend utilities

This commit is contained in:
Christoph Oelckers 2022-09-06 20:19:55 +02:00
parent b2fd1fdaa4
commit ca8b9e9793
5 changed files with 55 additions and 96 deletions

View file

@ -558,7 +558,7 @@ static void renderDrawMapView(const DVector2& cpos, const DVector2& cangvect, co
{ {
if (!gFullMap && !(actor->spr.cstat2 & CSTAT2_SPRITE_MAPPED)) continue; if (!gFullMap && !(actor->spr.cstat2 & CSTAT2_SPRITE_MAPPED)) continue;
DVector2 pp[4]; DVector2 pp[4];
GetFlatSpritePosition(actor, actor->spr.pos.XY(), pp, true); GetFlatSpritePosition(actor, actor->spr.pos.XY(), pp, nullptr, true);
for (unsigned j = 0; j < 4; j++) for (unsigned j = 0; j < 4; j++)
{ {

View file

@ -371,9 +371,9 @@ void TGetFlatSpritePosition(const spritetypebase* spr, const DVector2& pos, DVec
} }
void GetFlatSpritePosition(DCoreActor* actor, const DVector2& pos, DVector2* out, bool render) void GetFlatSpritePosition(DCoreActor* actor, const DVector2& pos, DVector2* out, double* outz, bool render)
{ {
TGetFlatSpritePosition(&actor->spr, pos, out, nullptr, spriteGetSlope(actor), render); TGetFlatSpritePosition(&actor->spr, pos, out, outz, spriteGetSlope(actor), render);
} }
void GetFlatSpritePosition(const tspritetype* spr, const DVector2& pos, DVector2* out, double* outz, bool render) void GetFlatSpritePosition(const tspritetype* spr, const DVector2& pos, DVector2* out, double* outz, bool render)
@ -528,6 +528,39 @@ int inside(double x, double y, const sectortype* sect)
return -1; return -1;
} }
//==========================================================================
//
//
//
//==========================================================================
int insidePoly(double x, double y, const DVector2* points, int count)
{
int64_t acc = 1;
for (int i = 0; i < count; i++)
{
int j = (i + 1) % count;
// Perform the checks here in 48.16 fixed point.
// Doing it directly with floats and multiplications does not work reliably.
// Unfortunately, due to the conversions, this is a bit slower. :(
int64_t xs = int64_t(0x10000 * (points[i].X - x));
int64_t ys = int64_t(0x10000 * (points[i].Y - y));
int64_t xe = int64_t(0x10000 * (points[j].X - x));
int64_t ye = int64_t(0x10000 * (points[j].Y - y));
if ((ys ^ ye) < 0)
{
int64_t val;
if ((xs ^ xe) >= 0) val = xs;
else val = ((xs * ye) - xe * ys) ^ ye;
acc ^= val;
}
}
return acc < 0;
}
//========================================================================== //==========================================================================
// //
// find the closest neighboring sector plane in the given direction. // find the closest neighboring sector plane in the given direction.

View file

@ -267,7 +267,7 @@ int getslopeval(sectortype* sect, int x, int y, int z, int planez);
void setWallSectors(); void setWallSectors();
void GetWallSpritePosition(const spritetypebase* spr, const DVector2& pos, DVector2* out, bool render = false); void GetWallSpritePosition(const spritetypebase* spr, const DVector2& pos, DVector2* out, bool render = false);
void GetFlatSpritePosition(DCoreActor* spr, const DVector2& pos, DVector2* out, bool render = false); void GetFlatSpritePosition(DCoreActor* spr, const DVector2& pos, DVector2* out, double* outz = nullptr, bool render = false);
void GetFlatSpritePosition(const tspritetype* spr, const DVector2& pos, DVector2* out, double* outz, bool render = false); void GetFlatSpritePosition(const tspritetype* spr, const DVector2& pos, DVector2* out, double* outz, bool render = false);
enum class EClose enum class EClose
@ -284,6 +284,7 @@ bool sectorsConnected(int sect1, int sect2);
[[deprecated]] void dragpoint(walltype* wal, int newx, int newy); [[deprecated]] void dragpoint(walltype* wal, int newx, int newy);
void dragpoint(walltype* wal, const DVector2& pos); void dragpoint(walltype* wal, const DVector2& pos);
int32_t inside(double x, double y, const sectortype* sect); int32_t inside(double x, double y, const sectortype* sect);
int insidePoly(double x, double y, const DVector2* points, int count);
void getcorrectzsofslope(int sectnum, int dax, int day, int* ceilz, int* florz); void getcorrectzsofslope(int sectnum, int dax, int day, int* ceilz, int* florz);
int getceilzofslopeptr(const sectortype* sec, int dax, int day); int getceilzofslopeptr(const sectortype* sec, int dax, int day);
int getflorzofslopeptr(const sectortype* sec, int dax, int day); int getflorzofslopeptr(const sectortype* sec, int dax, int day);

View file

@ -1635,15 +1635,7 @@ short AnimSetVelAdj(short anim_ndx, double vel_adj);
void EnemyDefaults(DSWActor* actor, ACTOR_ACTION_SET* action, PERSONALITY* person); void EnemyDefaults(DSWActor* actor, ACTOR_ACTION_SET* action, PERSONALITY* person);
void getzrangepoint(int x, int y, int z, sectortype* sect, int32_t* ceilz, Collision* ceilhit, int32_t* florz, Collision* florhit); void getzrangepoint(const DVector3& pos, sectortype* sect, double* hiz, Collision* ceilhit, double* loz, Collision* florhit);
inline void getzrangepoint(const DVector3& pos, sectortype* sect, double* hiz, Collision* ceilhit, double* loz, Collision* florhit)
{
int32_t hi, lo;
getzrangepoint(int(pos.X * worldtoint), int(pos.Y * worldtoint), int(pos.Z * zworldtoint), sect, &hi, ceilhit, &lo, florhit);
*hiz = hi * zinttoworld;
*loz = lo * zinttoworld;
}
Collision move_sprite(DSWActor* actor, const DVector3& change, double ceildist, double flordist, uint32_t cliptype, int numtics); Collision move_sprite(DSWActor* actor, const DVector3& change, double ceildist, double flordist, uint32_t cliptype, int numtics);
Collision move_missile(DSWActor* actor, const DVector3& change, double ceildist, double flordist, uint32_t cliptype, int numtics); Collision move_missile(DSWActor* actor, const DVector3& change, double ceildist, double flordist, uint32_t cliptype, int numtics);

View file

@ -4417,25 +4417,22 @@ bool SpriteOverlapZ(DSWActor* actor_a, DSWActor* actor_b, double z_overlap)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void getzrangepoint(int x, int y, int z, sectortype* sect, void getzrangepoint(const DVector3& pos, sectortype* sect,
int32_t* ceilz, Collision* ceilhit, int32_t* florz, Collision* florhit) double* ceil_z, Collision* ceilhit, double* flor_z, Collision* florhit)
{ {
int j, k, l, dax, day, daz, xspan, yspan, xoff, yoff;
int x1, y1, x2, y2, x3, y3, x4, y4, cosang, sinang, tilenum;
short cstat; short cstat;
uint8_t clipyou;
if (sect == nullptr) if (sect == nullptr)
{ {
*ceilz = 0x80000000; *ceil_z = 0x800000;
*florz = 0x7fffffff; *flor_z = 0x7fffff;
florhit->invalidate(); florhit->invalidate();
return; return;
} }
// Initialize z's and hits to the current sector's top&bottom // Initialize z's and hits to the current sector's top&bottom
getzsofslopeptr(sect, x, y, ceilz, florz); getzsofslopeptr(sect, pos, ceil_z, flor_z);
ceilhit->setSector(sect); ceilhit->setSector(sect);
florhit->setSector(sect); florhit->setSector(sect);
@ -4447,94 +4444,30 @@ void getzrangepoint(int x, int y, int z, sectortype* sect,
if ((cstat & (CSTAT_SPRITE_ALIGNMENT_MASK | CSTAT_SPRITE_BLOCK)) != (CSTAT_SPRITE_ALIGNMENT_FLOOR|CSTAT_SPRITE_BLOCK)) if ((cstat & (CSTAT_SPRITE_ALIGNMENT_MASK | CSTAT_SPRITE_BLOCK)) != (CSTAT_SPRITE_ALIGNMENT_FLOOR|CSTAT_SPRITE_BLOCK))
continue; // Only check blocking floor sprites continue; // Only check blocking floor sprites
daz = itActor->int_pos().Z; double fdaz = itActor->spr.pos.Z; // todo: consider slope sprites here.
// Only check if sprite's 2-sided or your on the 1-sided side // Only check if sprite's 2-sided or your on the 1-sided side
if (((cstat & CSTAT_SPRITE_ONE_SIDE) != 0) && ((z > daz) == ((cstat & CSTAT_SPRITE_YFLIP) == 0))) if (((cstat & CSTAT_SPRITE_ONE_SIDE) != 0) && ((pos.Z > fdaz) == ((cstat & CSTAT_SPRITE_YFLIP) == 0)))
continue; continue;
// Calculate and store centering offset information into xoff&yoff DVector2 out[4];
tilenum = itActor->spr.picnum; GetFlatSpritePosition(itActor, itActor->spr.pos.XY(), out);
xoff = (int)tileLeftOffset(tilenum) + (int)itActor->spr.xoffset; if (!insidePoly(pos.X, pos.Y, out, 4)) continue;
yoff = (int)tileTopOffset(tilenum) + (int)itActor->spr.yoffset;
if (cstat & CSTAT_SPRITE_XFLIP)
xoff = -xoff;
if (cstat & CSTAT_SPRITE_YFLIP)
yoff = -yoff;
// Calculate all 4 points of the floor sprite.
// (x1,y1),(x2,y2),(x3,y3),(x4,y4)
// These points will already have (x,y) subtracted from them
// [MR] Note, formula here appears identical to that of `DrawAutomapAlignmentFloor()`.
// Consider looking there when refactoring.
cosang = bcos(itActor->int_ang());
sinang = bsin(itActor->int_ang());
xspan = tileWidth(tilenum);
dax = ((xspan >> 1) + xoff) * itActor->spr.xrepeat;
yspan = tileHeight(tilenum);
day = ((yspan >> 1) + yoff) * itActor->spr.yrepeat;
x1 = itActor->int_pos().X + DMulScale(sinang, dax, cosang, day, 16) - x;
y1 = itActor->int_pos().Y + DMulScale(sinang, day, -cosang, dax, 16) - y;
l = xspan * itActor->spr.xrepeat;
x2 = x1 - MulScale(sinang, l, 16);
y2 = y1 + MulScale(cosang, l, 16);
l = yspan * itActor->spr.yrepeat;
k = -MulScale(cosang, l, 16);
x3 = x2 + k;
x4 = x1 + k;
k = -MulScale(sinang, l, 16);
y3 = y2 + k;
y4 = y1 + k;
// Check to see if point (0,0) is inside the 4 points by seeing if
// the number of lines crossed as a line is shot outward is odd
clipyou = 0;
if ((y1 ^ y2) < 0) // If y1 and y2 have different signs
// (- / +)
{
if ((x1 ^ x2) < 0)
clipyou ^= (x1 * y2 < x2 * y1) ^ (y1 < y2);
else if (x1 >= 0)
clipyou ^= 1;
}
if ((y2 ^ y3) < 0)
{
if ((x2 ^ x3) < 0)
clipyou ^= (x2 * y3 < x3 * y2) ^ (y2 < y3);
else if (x2 >= 0)
clipyou ^= 1;
}
if ((y3 ^ y4) < 0)
{
if ((x3 ^ x4) < 0)
clipyou ^= (x3 * y4 < x4 * y3) ^ (y3 < y4);
else if (x3 >= 0)
clipyou ^= 1;
}
if ((y4 ^ y1) < 0)
{
if ((x4 ^ x1) < 0)
clipyou ^= (x4 * y1 < x1 * y4) ^ (y4 < y1);
else if (x4 >= 0)
clipyou ^= 1;
}
if (clipyou == 0)
continue; // Point is not inside, don't clip
// Clipping time! // Clipping time!
if (z > daz) if (pos.Z > fdaz)
{ {
if (daz > *ceilz) if (fdaz > *ceil_z)
{ {
*ceilz = daz; *ceil_z = fdaz;
ceilhit->setSprite(itActor); ceilhit->setSprite(itActor);
} }
} }
else else
{ {
if (daz < *florz) if (fdaz < *flor_z)
{ {
*florz = daz; *flor_z = fdaz;
florhit->setSprite(itActor); florhit->setSprite(itActor);
} }
} }