mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-10 23:01:59 +00:00
- fixed a few incorrect uses of AngleTo function.
- added portal offsetting to all AproxDistance, AngleTo and Vec*To members of AActor. - optimized displacement retrieval so that the most common case with no offset retrieves a constant null-vector which can be optimized away fully by the compiler. - early out in P_GetOffsetPosition if there's no portal lines nearby, so that the common case can skip the traverser completely even on maps with line portals.
This commit is contained in:
parent
fd78686679
commit
eafd2519b4
10 changed files with 92 additions and 70 deletions
55
src/actor.h
55
src/actor.h
|
@ -818,22 +818,28 @@ public:
|
|||
return ( abs(X() - other->X()) < blockdist && abs(Y() - other->Y()) < blockdist);
|
||||
}
|
||||
|
||||
// 'absolute' is reserved for a linked portal implementation which needs
|
||||
// to distinguish between portal-aware and portal-unaware distance calculation.
|
||||
fixed_t AproxDistance(AActor *other, bool absolute = false)
|
||||
{
|
||||
return P_AproxDistance(X() - other->X(), Y() - other->Y());
|
||||
}
|
||||
|
||||
// same with 'ref' here.
|
||||
fixed_t AproxDistance(fixed_t otherx, fixed_t othery, AActor *ref = NULL)
|
||||
fixed_t AproxDistance(fixed_t otherx, fixed_t othery)
|
||||
{
|
||||
return P_AproxDistance(X() - otherx, Y() - othery);
|
||||
}
|
||||
|
||||
fixed_t AngleTo(fixed_t otherx, fixed_t othery)
|
||||
{
|
||||
return R_PointToAngle2(X(), Y(), otherx, othery);
|
||||
}
|
||||
|
||||
// 'absolute' is reserved for a linked portal implementation which needs
|
||||
// to distinguish between portal-aware and portal-unaware distance calculation.
|
||||
fixed_t AproxDistance(AActor *other, bool absolute = false)
|
||||
{
|
||||
fixedvec3 otherpos = absolute ? other->Pos() : other->PosRelative(this);
|
||||
return P_AproxDistance(X() - otherpos.x, Y() - otherpos.y);
|
||||
}
|
||||
|
||||
fixed_t AproxDistance(AActor *other, fixed_t xadd, fixed_t yadd, bool absolute = false)
|
||||
{
|
||||
return P_AproxDistance(X() - other->X() + xadd, Y() - other->Y() + yadd);
|
||||
fixedvec3 otherpos = absolute ? other->Pos() : other->PosRelative(this);
|
||||
return P_AproxDistance(X() - otherpos.x + xadd, Y() - otherpos.y + yadd);
|
||||
}
|
||||
|
||||
fixed_t AproxDistance3D(AActor *other, bool absolute = false)
|
||||
|
@ -844,18 +850,21 @@ public:
|
|||
// more precise, but slower version, being used in a few places
|
||||
fixed_t Distance2D(AActor *other, bool absolute = false)
|
||||
{
|
||||
return xs_RoundToInt(TVector2<double>(X() - other->X(), Y() - other->Y()).Length());
|
||||
fixedvec3 otherpos = absolute ? other->Pos() : other->PosRelative(this);
|
||||
return xs_RoundToInt(TVector2<double>(X() - otherpos.x, Y() - otherpos.y).Length());
|
||||
}
|
||||
|
||||
// a full 3D version of the above
|
||||
fixed_t Distance3D(AActor *other, bool absolute = false)
|
||||
{
|
||||
return xs_RoundToInt(TVector3<double>(X() - other->X(), Y() - other->Y(), Z() - other->Z()).Length());
|
||||
fixedvec3 otherpos = absolute ? other->Pos() : other->PosRelative(this);
|
||||
return xs_RoundToInt(TVector3<double>(X() - otherpos.x, Y() - otherpos.y, Z() - otherpos.z).Length());
|
||||
}
|
||||
|
||||
angle_t AngleTo(AActor *other, bool absolute = false) const
|
||||
angle_t AngleTo(AActor *other, bool absolute = false)
|
||||
{
|
||||
return R_PointToAngle2(X(), Y(), other->X(), other->Y());
|
||||
fixedvec3 otherpos = absolute ? other->Pos() : other->PosRelative(this);
|
||||
return R_PointToAngle2(X(), Y(), otherpos.x, otherpos.y);
|
||||
}
|
||||
|
||||
angle_t AngleTo(AActor *other, fixed_t oxofs, fixed_t oyofs, bool absolute = false) const
|
||||
|
@ -863,25 +872,17 @@ public:
|
|||
return R_PointToAngle2(X(), Y(), other->X() + oxofs, other->Y() + oyofs);
|
||||
}
|
||||
|
||||
fixed_t AngleTo(fixed_t otherx, fixed_t othery, AActor *ref = NULL)
|
||||
{
|
||||
return R_PointToAngle2(X(), Y(), otherx, othery);
|
||||
}
|
||||
|
||||
fixed_t AngleXYTo(fixed_t myx, fixed_t myy, AActor *other, bool absolute = false)
|
||||
{
|
||||
return R_PointToAngle2(myx, myy, other->X(), other->Y());
|
||||
}
|
||||
|
||||
fixedvec2 Vec2To(AActor *other) const
|
||||
{
|
||||
fixedvec2 ret = { other->X() - X(), other->Y() - Y() };
|
||||
fixedvec3 otherpos = other->PosRelative(this);
|
||||
fixedvec2 ret = { otherpos.x - X(), otherpos.y - Y() };
|
||||
return ret;
|
||||
}
|
||||
|
||||
fixedvec3 Vec3To(AActor *other) const
|
||||
{
|
||||
fixedvec3 ret = { other->X() - X(), other->Y() - Y(), other->Z() - Z() };
|
||||
fixedvec3 otherpos = other->PosRelative(this);
|
||||
fixedvec3 ret = { otherpos.x - X(), otherpos.y - Y(), otherpos.z - Z() };
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1190,7 +1191,7 @@ public:
|
|||
return __pos;
|
||||
}
|
||||
|
||||
fixedvec3 PosRelative(AActor *other) const;
|
||||
fixedvec3 PosRelative(const AActor *other) const;
|
||||
fixedvec3 PosRelative(sector_t *sec) const;
|
||||
fixedvec3 PosRelative(line_t *line) const;
|
||||
|
||||
|
|
|
@ -513,7 +513,7 @@ AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
|
|||
z -= source->floorclip;
|
||||
th = Spawn (type, x, y, z, ALLOW_REPLACE);
|
||||
th->target = source; // Originator
|
||||
an = source->AngleXYTo(x, y, dest);
|
||||
an = th->AngleTo(dest);
|
||||
if (dest->flags & MF_SHADOW)
|
||||
{ // Invisible target
|
||||
an += pr_kmissile.Random2()<<21;
|
||||
|
@ -522,7 +522,7 @@ AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
|
|||
an >>= ANGLETOFINESHIFT;
|
||||
th->velx = FixedMul (th->Speed, finecosine[an]);
|
||||
th->vely = FixedMul (th->Speed, finesine[an]);
|
||||
dist = dest->AproxDistance (x, y, source) / th->Speed;
|
||||
dist = dest->AproxDistance (th) / th->Speed;
|
||||
if (dist < 1)
|
||||
{
|
||||
dist = 1;
|
||||
|
|
|
@ -856,7 +856,7 @@ bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
|
|||
|
||||
void FMultiBlockLinesIterator::startIteratorForGroup(int group)
|
||||
{
|
||||
offset = Displacements(basegroup, group);
|
||||
offset = Displacements.getOffset(basegroup, group);
|
||||
offset.x += checkpoint.x;
|
||||
offset.y += checkpoint.y;
|
||||
bbox.setBox(offset.x, offset.y, checkpoint.z);
|
||||
|
@ -1088,7 +1088,7 @@ bool FMultiBlockThingsIterator::Next(FMultiBlockThingsIterator::CheckResult *ite
|
|||
if (thing != NULL)
|
||||
{
|
||||
item->thing = thing;
|
||||
item->position = checkpoint + Displacements(basegroup, thing->Sector->PortalGroup);
|
||||
item->position = checkpoint + Displacements.getOffset(basegroup, thing->Sector->PortalGroup);
|
||||
item->portalflags = portalflags;
|
||||
return true;
|
||||
}
|
||||
|
@ -1127,7 +1127,7 @@ bool FMultiBlockThingsIterator::Next(FMultiBlockThingsIterator::CheckResult *ite
|
|||
|
||||
void FMultiBlockThingsIterator::startIteratorForGroup(int group)
|
||||
{
|
||||
fixedvec2 offset = Displacements(basegroup, group);
|
||||
fixedvec2 offset = Displacements.getOffset(basegroup, group);
|
||||
offset.x += checkpoint.x;
|
||||
offset.y += checkpoint.y;
|
||||
bbox.setBox(offset.x, offset.y, checkpoint.z);
|
||||
|
|
|
@ -897,9 +897,9 @@ fixed_t sector_t::HighestCeilingAt(fixed_t x, fixed_t y, sector_t **resultsec)
|
|||
// Continue until we find a blocking portal or a portal below where we actually are.
|
||||
while (!check->PortalBlocksMovement(ceiling) && planeheight < check->SkyBoxes[ceiling]->threshold)
|
||||
{
|
||||
FDisplacement &disp = check->CeilingDisplacement();
|
||||
x += disp.pos.x;
|
||||
y += disp.pos.y;
|
||||
fixedvec2 pos = check->CeilingDisplacement();
|
||||
x += pos.x;
|
||||
y += pos.y;
|
||||
planeheight = check->SkyBoxes[ceiling]->threshold;
|
||||
check = P_PointInSector(x, y);
|
||||
}
|
||||
|
@ -921,9 +921,9 @@ fixed_t sector_t::LowestFloorAt(fixed_t x, fixed_t y, sector_t **resultsec)
|
|||
// Continue until we find a blocking portal or a portal above where we actually are.
|
||||
while (!check->PortalBlocksMovement(floor) && planeheight > check->SkyBoxes[floor]->threshold)
|
||||
{
|
||||
FDisplacement &disp = check->FloorDisplacement();
|
||||
x += disp.pos.x;
|
||||
y += disp.pos.y;
|
||||
fixedvec2 pos = check->FloorDisplacement();
|
||||
x += pos.x;
|
||||
y += pos.y;
|
||||
planeheight = check->SkyBoxes[floor]->threshold;
|
||||
check = P_PointInSector(x, y);
|
||||
}
|
||||
|
@ -960,9 +960,9 @@ fixed_t sector_t::NextHighestCeilingAt(fixed_t x, fixed_t y, fixed_t z, int flag
|
|||
}
|
||||
else
|
||||
{
|
||||
FDisplacement &disp = sec->CeilingDisplacement();
|
||||
x += disp.pos.x;
|
||||
y += disp.pos.y;
|
||||
fixedvec2 pos = sec->CeilingDisplacement();
|
||||
x += pos.x;
|
||||
y += pos.y;
|
||||
planeheight = sec->SkyBoxes[ceiling]->threshold;
|
||||
sec = P_PointInSector(x, y);
|
||||
}
|
||||
|
@ -1003,9 +1003,9 @@ fixed_t sector_t::NextLowestFloorAt(fixed_t x, fixed_t y, fixed_t z, int flags,
|
|||
}
|
||||
else
|
||||
{
|
||||
FDisplacement &disp = sec->FloorDisplacement();
|
||||
x += disp.pos.x;
|
||||
y += disp.pos.y;
|
||||
fixedvec2 pos = sec->FloorDisplacement();
|
||||
x += pos.x;
|
||||
y += pos.y;
|
||||
planeheight = sec->SkyBoxes[floor]->threshold;
|
||||
sec = P_PointInSector(x, y);
|
||||
}
|
||||
|
|
|
@ -786,7 +786,7 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
|
|||
if (flags & WARPF_WARPINTERPOLATION)
|
||||
{
|
||||
// This just translates the movement but doesn't change the vector
|
||||
fixedvec3 displacedold = old + Displacements(oldpgroup, caller->Sector->PortalGroup);
|
||||
fixedvec3 displacedold = old + Displacements.getOffset(oldpgroup, caller->Sector->PortalGroup);
|
||||
caller->PrevX += caller->X() - displacedold.x;
|
||||
caller->PrevY += caller->Y() - displacedold.y;
|
||||
caller->PrevZ += caller->Z() - displacedold.z;
|
||||
|
@ -795,8 +795,8 @@ int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs,
|
|||
else if (flags & WARPF_COPYINTERPOLATION)
|
||||
{
|
||||
// Map both positions of the reference actor to the current portal group
|
||||
fixedvec3 displacedold = old + Displacements(reference->PrevPortalGroup, caller->Sector->PortalGroup);
|
||||
fixedvec3 displacedref = old + Displacements(reference->Sector->PortalGroup, caller->Sector->PortalGroup);
|
||||
fixedvec3 displacedold = old + Displacements.getOffset(reference->PrevPortalGroup, caller->Sector->PortalGroup);
|
||||
fixedvec3 displacedref = old + Displacements.getOffset(reference->Sector->PortalGroup, caller->Sector->PortalGroup);
|
||||
caller->PrevX = caller->X() + displacedold.x - displacedref.x;
|
||||
caller->PrevY = caller->Y() + displacedold.y - displacedref.y;
|
||||
caller->PrevZ = caller->Z() + displacedold.z - displacedref.z;
|
||||
|
|
|
@ -121,6 +121,11 @@ static void BuildBlockmap()
|
|||
{
|
||||
PortalBlockmap.containsLines = true;
|
||||
block.portallines.Push(ld);
|
||||
block.neighborContainsLines = true;
|
||||
if (x > 0) PortalBlockmap(x - 1, y).neighborContainsLines = true;
|
||||
if (y > 0) PortalBlockmap(x, y - 1).neighborContainsLines = true;
|
||||
if (x < PortalBlockmap.dx - 1) PortalBlockmap(x + 1, y).neighborContainsLines = true;
|
||||
if (y < PortalBlockmap.dy - 1) PortalBlockmap(x, y + 1).neighborContainsLines = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -691,10 +696,18 @@ void P_NormalizeVXVY(fixed_t& vx, fixed_t& vy)
|
|||
|
||||
fixedvec2 P_GetOffsetPosition(AActor *actor, fixed_t dx, fixed_t dy)
|
||||
{
|
||||
fixedvec3 dest = { actor->X() + dx, actor->Y() + dy };
|
||||
fixedvec2 dest = { actor->X() + dx, actor->Y() + dy };
|
||||
if (PortalBlockmap.containsLines)
|
||||
{
|
||||
fixed_t actx = actor->X(), acty = actor->Y();
|
||||
// Try some easily discoverable early-out first. If we know that the trace cannot possibly find a portal, this saves us from calling the traverser completely for vast parts of the map.
|
||||
if (dx < 128 * FRACUNIT && dy < 128 * FRACUNIT)
|
||||
{
|
||||
fixed_t blockx = GetSafeBlockX(actx - bmaporgx);
|
||||
fixed_t blocky = GetSafeBlockX(acty - bmaporgy);
|
||||
if (blockx < 0 || blocky < 0 || blockx >= bmapwidth || blocky >= bmapheight || !PortalBlockmap(blockx, blocky).neighborContainsLines) return dest;
|
||||
}
|
||||
|
||||
FLinePortalTraverse it;
|
||||
bool repeat;
|
||||
do
|
||||
|
@ -1159,9 +1172,9 @@ bool P_CollectConnectedGroups(int startgroup, const fixedvec3 &position, fixed_t
|
|||
while (!wsec->PortalBlocksMovement(sector_t::ceiling) && upperz > wsec->SkyBoxes[sector_t::ceiling]->threshold)
|
||||
{
|
||||
sector_t *othersec = wsec->SkyBoxes[sector_t::ceiling]->Sector;
|
||||
FDisplacement &disp = Displacements(startgroup, othersec->PortalGroup);
|
||||
fixed_t dx = position.x + disp.pos.x;
|
||||
fixed_t dy = position.y + disp.pos.y;
|
||||
fixedvec2 pos = Displacements.getOffset(startgroup, othersec->PortalGroup);
|
||||
fixed_t dx = position.x + pos.x;
|
||||
fixed_t dy = position.y + pos.y;
|
||||
processMask.setBit(othersec->PortalGroup);
|
||||
out.Add(othersec->PortalGroup|FPortalGroupArray::UPPER);
|
||||
wsec = P_PointInSector(dx, dy); // get upper sector at the exact spot we want to check and repeat
|
||||
|
@ -1171,9 +1184,9 @@ bool P_CollectConnectedGroups(int startgroup, const fixedvec3 &position, fixed_t
|
|||
while (!wsec->PortalBlocksMovement(sector_t::floor) && position.z < wsec->SkyBoxes[sector_t::floor]->threshold)
|
||||
{
|
||||
sector_t *othersec = wsec->SkyBoxes[sector_t::floor]->Sector;
|
||||
FDisplacement &disp = Displacements(startgroup, othersec->PortalGroup);
|
||||
fixed_t dx = position.x + disp.pos.x;
|
||||
fixed_t dy = position.y + disp.pos.y;
|
||||
fixedvec2 pos = Displacements.getOffset(startgroup, othersec->PortalGroup);
|
||||
fixed_t dx = position.x + pos.x;
|
||||
fixed_t dy = position.y + pos.y;
|
||||
processMask.setBit(othersec->PortalGroup|FPortalGroupArray::LOWER);
|
||||
out.Add(othersec->PortalGroup);
|
||||
wsec = P_PointInSector(dx, dy); // get lower sector at the exact spot we want to check and repeat
|
||||
|
|
18
src/portal.h
18
src/portal.h
|
@ -30,10 +30,6 @@ struct FDisplacement
|
|||
bool isSet;
|
||||
BYTE indirect; // just for illustration.
|
||||
|
||||
operator fixedvec2()
|
||||
{
|
||||
return pos;
|
||||
}
|
||||
};
|
||||
|
||||
struct FDisplacementTable
|
||||
|
@ -55,9 +51,15 @@ struct FDisplacementTable
|
|||
|
||||
FDisplacement &operator()(int x, int y)
|
||||
{
|
||||
if (x == y) return data[0]; // shortcut for the most common case
|
||||
return data[x + size*y];
|
||||
}
|
||||
|
||||
fixedvec2 getOffset(int x, int y) const
|
||||
{
|
||||
static const fixedvec2 nulvec = { 0,0 };
|
||||
if (x == y) return nulvec; // shortcut for the most common case
|
||||
return data[x + size*y].pos;
|
||||
}
|
||||
};
|
||||
|
||||
extern FDisplacementTable Displacements;
|
||||
|
@ -72,7 +74,13 @@ extern FDisplacementTable Displacements;
|
|||
|
||||
struct FPortalBlock
|
||||
{
|
||||
bool neighborContainsLines; // this is for skipping the traverser and exiting early if we can quickly decide that there's no portals nearby.
|
||||
TArray<line_t*> portallines;
|
||||
|
||||
FPortalBlock()
|
||||
{
|
||||
neighborContainsLines = false;
|
||||
}
|
||||
};
|
||||
|
||||
struct FPortalBlockmap
|
||||
|
|
18
src/r_defs.h
18
src/r_defs.h
|
@ -785,14 +785,14 @@ struct sector_t
|
|||
}
|
||||
|
||||
// These may only be called if the portal has been validated
|
||||
FDisplacement &FloorDisplacement()
|
||||
fixedvec2 FloorDisplacement()
|
||||
{
|
||||
return Displacements(PortalGroup, SkyBoxes[sector_t::floor]->Sector->PortalGroup);
|
||||
return Displacements.getOffset(PortalGroup, SkyBoxes[sector_t::floor]->Sector->PortalGroup);
|
||||
}
|
||||
|
||||
FDisplacement &CeilingDisplacement()
|
||||
fixedvec2 CeilingDisplacement()
|
||||
{
|
||||
return Displacements(PortalGroup, SkyBoxes[sector_t::ceiling]->Sector->PortalGroup);
|
||||
return Displacements.getOffset(PortalGroup, SkyBoxes[sector_t::ceiling]->Sector->PortalGroup);
|
||||
}
|
||||
|
||||
int GetTerrain(int pos) const;
|
||||
|
@ -1263,24 +1263,24 @@ inline sector_t *P_PointInSector(fixed_t x, fixed_t y)
|
|||
return P_PointInSubsector(x, y)->sector;
|
||||
}
|
||||
|
||||
inline fixedvec3 AActor::PosRelative(AActor *other) const
|
||||
inline fixedvec3 AActor::PosRelative(const AActor *other) const
|
||||
{
|
||||
return __pos + Displacements(Sector->PortalGroup, other->Sector->PortalGroup);
|
||||
return __pos + Displacements.getOffset(Sector->PortalGroup, other->Sector->PortalGroup);
|
||||
}
|
||||
|
||||
inline fixedvec3 AActor::PosRelative(sector_t *sec) const
|
||||
{
|
||||
return __pos + Displacements(Sector->PortalGroup, sec->PortalGroup);
|
||||
return __pos + Displacements.getOffset(Sector->PortalGroup, sec->PortalGroup);
|
||||
}
|
||||
|
||||
inline fixedvec3 AActor::PosRelative(line_t *line) const
|
||||
{
|
||||
return __pos + Displacements(Sector->PortalGroup, line->frontsector->PortalGroup);
|
||||
return __pos + Displacements.getOffset(Sector->PortalGroup, line->frontsector->PortalGroup);
|
||||
}
|
||||
|
||||
inline fixedvec3 PosRelative(const fixedvec3 &pos, line_t *line, sector_t *refsec = NULL)
|
||||
{
|
||||
return pos + Displacements(refsec->PortalGroup, line->frontsector->PortalGroup);
|
||||
return pos + Displacements.getOffset(refsec->PortalGroup, line->frontsector->PortalGroup);
|
||||
}
|
||||
|
||||
inline void AActor::ClearInterpolation()
|
||||
|
|
|
@ -583,7 +583,7 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi
|
|||
}
|
||||
int oldgroup = R_PointInSubsector(iview->oviewx, iview->oviewy)->sector->PortalGroup;
|
||||
int newgroup = R_PointInSubsector(iview->nviewx, iview->nviewy)->sector->PortalGroup;
|
||||
fixedvec2 disp = Displacements(oldgroup, newgroup);
|
||||
fixedvec2 disp = Displacements.getOffset(oldgroup, newgroup);
|
||||
viewx = iview->oviewx + FixedMul (frac, iview->nviewx - iview->oviewx - disp.x);
|
||||
viewy = iview->oviewy + FixedMul (frac, iview->nviewy - iview->oviewy - disp.y);
|
||||
viewz = iview->oviewz + FixedMul (frac, iview->nviewz - iview->oviewz);
|
||||
|
|
|
@ -5181,7 +5181,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_WolfAttack)
|
|||
if (spawnblood)
|
||||
{
|
||||
P_SpawnBlood(bloodpos, angle, newdam > 0 ? newdam : damage, self->target);
|
||||
P_TraceBleed(newdam > 0 ? newdam : damage, self->target, self->AngleTo(dx, dy, self->target), 0);
|
||||
P_TraceBleed(newdam > 0 ? newdam : damage, self->target, self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue