- float version of clipmove's slope sprite collector.

This could be simplified quite a bit by leveraging the info returned by GetFlatSpritePosition.
This commit is contained in:
Christoph Oelckers 2022-10-23 21:19:09 +02:00
parent ede7a7ac12
commit ea530cbc49
3 changed files with 58 additions and 69 deletions

View file

@ -248,17 +248,12 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect,
TSectIterator<DCoreActor> it(dasect); TSectIterator<DCoreActor> it(dasect);
while (auto actor = it.Next()) while (auto actor = it.Next())
{ {
const int32_t cstat = actor->spr.cstat; int cstat = actor->spr.cstat;
if (actor->spr.cstat2 & CSTAT2_SPRITE_NOFIND) continue; if (actor->spr.cstat2 & CSTAT2_SPRITE_NOFIND) continue;
if ((cstat&dasprclipmask) == 0) if ((cstat & dasprclipmask) == 0)
continue; continue;
auto p1 = actor->int_pos().vec2;
CollisionBase obj;
obj.setSprite(actor);
switch (cstat & (CSTAT_SPRITE_ALIGNMENT_MASK)) switch (cstat & (CSTAT_SPRITE_ALIGNMENT_MASK))
{ {
case CSTAT_SPRITE_ALIGNMENT_FACING: case CSTAT_SPRITE_ALIGNMENT_FACING:
@ -274,63 +269,7 @@ CollisionBase clipmove_(vec3_t * const pos, int * const sectnum, int32_t xvect,
break; break;
case CSTAT_SPRITE_ALIGNMENT_SLOPE: case CSTAT_SPRITE_ALIGNMENT_SLOPE:
{ processClipSlopeSprite(clip, actor);
if (!processClipFloorSprite(clip, actor)) continue;
int heinum = spriteGetSlope(actor);
if (heinum == 0) continue;
// the rest is for slope sprites only.
auto tex = TexMan.GetGameTexture(actor->spr.spritetexture());
const int32_t cosang = bcos(actor->int_ang());
const int32_t sinang = bsin(actor->int_ang());
vec2_t const span = { (int)tex->GetDisplayWidth(), (int)tex->GetDisplayHeight() };
vec2_t const repeat = { int(actor->spr.scale.X * scaletoint), int(actor->spr.scale.Y * scaletoint) };
vec2_t adjofs = { (int)tex->GetDisplayLeftOffset(), (int)tex->GetDisplayTopOffset() };
if (actor->spr.cstat & CSTAT_SPRITE_XFLIP)
adjofs.X = -adjofs.X;
if (actor->spr.cstat & CSTAT_SPRITE_YFLIP)
adjofs.Y = -adjofs.Y;
int32_t const centerx = ((span.X >> 1) + adjofs.X) * repeat.X;
int32_t const centery = ((span.Y >> 1) + adjofs.Y) * repeat.Y;
int32_t const rspanx = span.X * repeat.X;
int32_t const rspany = span.Y * repeat.Y;
int32_t const ratio = ksqrt(heinum * heinum + SLOPEVAL_FACTOR * SLOPEVAL_FACTOR);
int32_t zz[3] = { pos->Z, pos->Z + flordist, pos->Z - ceildist };
for (int k = 0; k < 3; k++)
{
int32_t jj = DivScale(actor->int_pos().Z - zz[k], heinum, 18);
int32_t jj2 = MulScale(jj, ratio, 12);
if (jj2 > (centery << 8) || jj2 < ((centery - rspany) << 8))
continue;
int32_t x1 = actor->int_pos().X + MulScale(sinang, centerx, 16) + MulScale(jj, cosang, 24);
int32_t y1 = actor->int_pos().Y - MulScale(cosang, centerx, 16) + MulScale(jj, sinang, 24);
int32_t x2 = x1 - MulScale(sinang, rspanx, 16);
int32_t y2 = y1 + MulScale(cosang, rspanx, 16);
vec2_t const v = { MulScale(bcos(actor->int_ang() - 256), walldist, 14),
MulScale(bsin(actor->int_ang() - 256), walldist, 14) };
if (clipinsideboxline(cent.X, cent.Y, x1, y1, x2, y2, rad) != 0)
{
if ((x1 - pos->X) * (y2 - pos->Y) >= (x2 - pos->X) * (y1 - pos->Y))
{
addclipline(x1 + v.X, y1 + v.Y, x2 + v.Y, y2 - v.X, obj, false);
}
else
{
if ((cstat & CSTAT_SPRITE_ONE_SIDE) != 0)
continue;
addclipline(x2 - v.X, y2 - v.Y, x1 - v.Y, y1 + v.X, obj, false);
}
}
}
break;
}
} }
} }
} while (clipsectcnt < clipsectnum || clipspritecnt < clipspritenum); } while (clipsectcnt < clipsectnum || clipspritecnt < clipspritenum);

View file

@ -1403,14 +1403,13 @@ void processClipWallSprite(MoveClipper& clip, DCoreActor* actor)
} }
} }
//========================================================================== //==========================================================================
// //
// //
// //
//========================================================================== //==========================================================================
bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor) bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor, DVector2* points, double* heights)
{ {
int heinum = spriteGetSlope(actor); int heinum = spriteGetSlope(actor);
double sprz = spriteGetZOfSlopef(&actor->spr, actor->spr.pos.XY(), heinum); double sprz = spriteGetZOfSlopef(&actor->spr, actor->spr.pos.XY(), heinum);
@ -1422,8 +1421,9 @@ bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor)
if ((clip.pos.Z > sprz) == ((actor->spr.cstat & CSTAT_SPRITE_YFLIP) == 0)) return false; if ((clip.pos.Z > sprz) == ((actor->spr.cstat & CSTAT_SPRITE_YFLIP) == 0)) return false;
} }
DVector2 points[4]; DVector2 opoints[4];
GetFlatSpritePosition(actor, actor->spr.pos.XY(), points, nullptr); if (!points) points = opoints;
GetFlatSpritePosition(actor, actor->spr.pos.XY(), points, heights);
auto offset = (actor->spr.Angles.Yaw - DAngle45).ToVector() * clip.walldist; auto offset = (actor->spr.Angles.Yaw - DAngle45).ToVector() * clip.walldist;
@ -1464,6 +1464,55 @@ bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor)
// //
//========================================================================== //==========================================================================
void processClipSlopeSprite(MoveClipper& clip, DCoreActor* actor)
{
auto spos = actor->spr.pos;
DVector2 points[4];
double heights[4];
DVector2 lpoints[2];
if (!processClipFloorSprite(clip, actor, points, heights)) return;
int heinum = spriteGetSlope(actor);
if (heinum == 0) return;
double zz[3] = { clip.pos.Z, clip.pos.Z + clip.floordist, clip.pos.Z - clip.ceilingdist };
CollisionBase objtype;
objtype.setSprite(actor);
for (int k = 0; k < 3; k++)
{
double factor = (zz[k] - heights[0]) / (heights[1] - heights[0]);
if (factor < 0 || factor > 1) continue; // sprite never hits the desired height.
auto dist = (points[1] - points[0]) * factor;
lpoints[0] = points[0] + dist;
lpoints[1] = points[3] + dist;
// The rest is just the same as the main part of the wall sprite collector.
if (IsCloseToLine(clip.center, lpoints[0], lpoints[1], clip.movedist) == EClose::Outside) continue; // out of reach
auto offset = (actor->spr.angle - DAngle45).ToVector() * clip.walldist;
auto d = lpoints[1] - lpoints[0];
if (PointOnLineSide(clip.center.X, clip.center.Y, lpoints[0].X, lpoints[0].Y, d.X, d.Y) <= 0)
{
// in front
addClipLine(clip, lpoints[0] + offset, lpoints[1] + offset.Rotated90CW(), objtype);
}
else if (!(actor->spr.cstat & CSTAT_SPRITE_ONE_SIDE))
{
// behind
addClipLine(clip, lpoints[0] - offset, lpoints[1] + offset.Rotated90CCW(), objtype);
}
}
}
//==========================================================================
//
//
//
//==========================================================================
int FindBestSector(const DVector3& pos) int FindBestSector(const DVector3& pos)
{ {
int bestnum = -1; int bestnum = -1;

View file

@ -261,7 +261,8 @@ void processClipWalls(MoveClipper& clip, sectortype* sec);
void processClipFaceSprite(MoveClipper& clip, DCoreActor* actor); void processClipFaceSprite(MoveClipper& clip, DCoreActor* actor);
void processClipWallSprite(MoveClipper& clip, DCoreActor* actor); void processClipWallSprite(MoveClipper& clip, DCoreActor* actor);
bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor); bool processClipFloorSprite(MoveClipper& clip, DCoreActor* actor, DVector2* points = nullptr, double* heights = nullptr);
void processClipSlopeSprite(MoveClipper& clip, DCoreActor* actor);
int FindBestSector(const DVector3& pos); int FindBestSector(const DVector3& pos);