mirror of
https://github.com/DrBeef/Raze.git
synced 2025-02-20 18:52:43 +00:00
- replaced try_facespr_intersect with something independently written.
This commit is contained in:
parent
9ce30d7963
commit
9c564db015
6 changed files with 63 additions and 51 deletions
|
@ -1092,47 +1092,6 @@ void getzrange(const vec3_t& pos, sectortype* sect, int32_t* ceilz, CollisionBas
|
|||
|
||||
}
|
||||
|
||||
|
||||
// intp: point of currently best (closest) intersection
|
||||
int32_t try_facespr_intersect(DCoreActor* actor, vec3_t const in,
|
||||
int32_t vx, int32_t vy, int32_t vz,
|
||||
vec3_t * const intp, int32_t strictly_smaller_than_p)
|
||||
{
|
||||
vec3_t const sprpos = actor->int_pos();
|
||||
|
||||
int32_t const topt = vx * (sprpos.X - in.X) + vy * (sprpos.Y - in.Y);
|
||||
|
||||
if (topt <= 0) return 0;
|
||||
|
||||
int32_t const bot = vx * vx + vy * vy;
|
||||
|
||||
if (!bot) return 0;
|
||||
|
||||
vec3_t newpos = { 0, 0, in.Z + Scale(vz, topt, bot) };
|
||||
int32_t siz;
|
||||
int32_t const z1 = sprpos.Z + actor->GetOffsetAndHeight(siz);
|
||||
|
||||
if (newpos.Z < z1 - siz || newpos.Z > z1)
|
||||
return 0;
|
||||
|
||||
int32_t const topu = vx * (sprpos.Y - in.Y) - vy * (sprpos.X - in.X);
|
||||
vec2_t const off = { Scale(vx, topu, bot), Scale(vy, topu, bot) };
|
||||
int32_t const dist = off.X * off.X + off.Y * off.Y;
|
||||
|
||||
siz = tileWidth(actor->spr.picnum) * actor->spr.xrepeat;
|
||||
|
||||
if (dist > MulScale(siz, siz, 7)) return 0;
|
||||
|
||||
newpos.vec2 = { in.X + Scale(vx, topt, bot), in.Y + Scale(vy, topt, bot) };
|
||||
|
||||
if (abs(newpos.X - in.X) + abs(newpos.Y - in.Y) + strictly_smaller_than_p >
|
||||
abs(intp->X - in.X) + abs(intp->Y - in.Y))
|
||||
return 0;
|
||||
|
||||
*intp = newpos;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void hit_set(HitInfoBase *hit, sectortype* sect, walltype* wal, DCoreActor* actor, int32_t x, int32_t y, int32_t z)
|
||||
{
|
||||
hit->hitSector = sect;
|
||||
|
@ -1287,10 +1246,11 @@ int hitscan(const vec3_t& start, const sectortype* startsect, const vec3_t& dire
|
|||
{
|
||||
case 0:
|
||||
{
|
||||
auto v = hitinfo.int_hitpos();
|
||||
if (try_facespr_intersect(actor, *sv, vx, vy, vz, &v, 0))
|
||||
auto v = hitinfo.hitpos;
|
||||
if (intersectSprite(actor, DVector3(sv->X * inttoworld, sv->Y * inttoworld, sv->Z * zinttoworld),
|
||||
DVector3(vx * inttoworld, vy * inttoworld, vz * zinttoworld), v, 0) )
|
||||
{
|
||||
hit_set(&hitinfo, sec, nullptr, actor, v.X, v.Y, v.Z);
|
||||
hit_set(&hitinfo, sec, nullptr, actor, v.X * worldtoint, v.Y * worldtoint, v.Z * zworldtoint);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -128,8 +128,11 @@ void neartag(const vec3_t& sv, sectortype* sect, int ange, HitInfoBase& result,
|
|||
|
||||
if (((tagsearch&1) && actor->spr.lotag) || ((tagsearch&2) && actor->spr.hitag))
|
||||
{
|
||||
if (try_facespr_intersect(actor, sv, vx, vy, 0, &hitv, 1))
|
||||
DVector3 v;
|
||||
if (intersectSprite(actor, DVector3(sv.X * inttoworld, sv.Y * inttoworld, sv.Z * zinttoworld),
|
||||
DVector3(vx * inttoworld, vy * inttoworld, 0), v, 1 / 256.))
|
||||
{
|
||||
vec3_t hitv(v.X * worldtoint, v.Y * worldtoint, v.Z * zworldtoint);
|
||||
result.hitActor = actor;
|
||||
result.hitpos.X = DMulScale(hitv.X-sv.X, bcos(ange), hitv.Y-sv.Y, bsin(ange), 14) * inttoworld;
|
||||
}
|
||||
|
|
|
@ -488,6 +488,13 @@ int DCoreActor::GetOffsetAndHeight(int& height)
|
|||
return zofs - tileTopOffset(spr.picnum) * yrepeat;
|
||||
}
|
||||
|
||||
double DCoreActor::GetOffsetAndHeight(double& height)
|
||||
{
|
||||
double yrepeat = spr.yrepeat * REPEAT_SCALE;
|
||||
height = tileHeight(spr.picnum) * yrepeat;
|
||||
double zofs = (spr.cstat & CSTAT_SPRITE_YCENTER) ? height * 0.5 : 0;
|
||||
return zofs - tileTopOffset(spr.picnum) * yrepeat;
|
||||
}
|
||||
|
||||
|
||||
DEFINE_FIELD_NAMED(DCoreActor, spr.sectp, sector)
|
||||
|
|
|
@ -60,6 +60,7 @@ public:
|
|||
void OnDestroy() override;
|
||||
size_t PropagateMark() override;
|
||||
int GetOffsetAndHeight(int& height);
|
||||
double GetOffsetAndHeight(double& height);
|
||||
|
||||
bool exists() const
|
||||
{
|
||||
|
|
|
@ -585,6 +585,46 @@ bool cansee(const DVector3& start, sectortype* sect1, const DVector3& end, secto
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool intersectSprite(DCoreActor* actor, const DVector3& start, const DVector3& direction, DVector3& result, double displacement)
|
||||
{
|
||||
auto end = start + direction;
|
||||
if (direction.isZero()) return false;
|
||||
|
||||
// use dot product to check if the sprite is behind us (or ourselves if the result is 0)
|
||||
auto dotprod = direction.XY().dot(actor->spr.pos.XY() - start.XY());
|
||||
if (dotprod <= 0) return false;
|
||||
|
||||
// get point on trace that is closest to the sprite
|
||||
auto point = NearestPointOnLine(actor->spr.pos.X, actor->spr.pos.Y, start.X, start.Y, end.X, end.Y);
|
||||
|
||||
// This is somewhat smaller than the sprite's actual size, but that's how it was
|
||||
auto sprwidth = tileWidth(actor->spr.picnum) * actor->spr.xrepeat * (REPEAT_SCALE * 0.25) + displacement;
|
||||
|
||||
// Using proper distance here, Build originally used the sum of x- and y-distance
|
||||
if ((point - actor->spr.pos).LengthSquared() > sprwidth * sprwidth) return false; // too far away
|
||||
|
||||
double DVector2::* c = point.X == actor->spr.pos.X ? &DVector2::Y : &DVector2::X;
|
||||
double newz = start.Z + (direction.Z) * (point.*c - start.XY().*c) / direction.XY().*c;
|
||||
|
||||
double siz;
|
||||
double const hitz = actor->spr.pos.Z + actor->GetOffsetAndHeight(siz);
|
||||
|
||||
if (newz < hitz - siz || newz > hitz)
|
||||
return 0;
|
||||
|
||||
result.XY() = point;
|
||||
result.Z = newz;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -262,6 +262,7 @@ void loaddefinitionsfile(const char* fn, bool cumulative = false, bool maingrp =
|
|||
bool calcChaseCamPos(DVector3& ppos, DCoreActor* pspr, sectortype** psectnum, DAngle ang, fixedhoriz horiz, double const interpfrac);
|
||||
int getslopeval(sectortype* sect, const DVector3& pos, double bazez);
|
||||
bool cansee(const DVector3& start, sectortype* sect1, const DVector3& end, sectortype* sect2);
|
||||
bool intersectSprite(DCoreActor* actor, const DVector3& start, const DVector3& end, DVector3& result, double displacement);
|
||||
|
||||
|
||||
|
||||
|
@ -493,13 +494,8 @@ inline double SquareDist(double lx1, double ly1, double lx2, double ly2)
|
|||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
inline DVector2 NearestPointOnWall(double px, double py, const walltype* wal, bool clamp = true)
|
||||
inline DVector2 NearestPointOnLine(double px, double py, double lx1, double ly1, double lx2, double ly2, bool clamp = true)
|
||||
{
|
||||
double lx1 = wal->pos.X;
|
||||
double ly1 = wal->pos.Y;
|
||||
double lx2 = wal->point2Wall()->pos.X;
|
||||
double ly2 = wal->point2Wall()->pos.Y;
|
||||
|
||||
double wall_length = SquareDist(lx1, ly1, lx2, ly2);
|
||||
|
||||
if (wall_length == 0) return { lx1, ly1 };
|
||||
|
@ -515,6 +511,11 @@ inline DVector2 NearestPointOnWall(double px, double py, const walltype* wal, bo
|
|||
return { xx, yy };
|
||||
}
|
||||
|
||||
inline DVector2 NearestPointOnWall(double px, double py, const walltype* wal, bool clamp = true)
|
||||
{
|
||||
return NearestPointOnLine(px, py, wal->pos.X, wal->pos.Y, wal->point2Wall()->pos.X, wal->point2Wall()->pos.Y, clamp);
|
||||
}
|
||||
|
||||
inline double SquareDistToWall(double px, double py, const walltype* wal, DVector2* point = nullptr)
|
||||
{
|
||||
auto pt = NearestPointOnWall(px, py, wal);
|
||||
|
|
Loading…
Reference in a new issue