diff --git a/src/p_map.cpp b/src/p_map.cpp index 0fe73229cb..0151d48039 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1041,8 +1041,8 @@ static bool PIT_CheckPortal(FMultiBlockLinesIterator &mit, FMultiBlockLinesItera line_t *lp = cres.line->getPortalDestination(); fixed_t zofs = 0; - P_TranslatePortalXY(cres.line, lp, cres.position.x, cres.position.y); - P_TranslatePortalZ(cres.line, lp, zofs); + P_TranslatePortalXY(cres.line, cres.position.x, cres.position.y); + P_TranslatePortalZ(cres.line, zofs); // fudge a bit with the portal line so that this gets included in the checks that normally only get run on two-sided lines sector_t *sec = lp->backsector; @@ -2325,14 +2325,13 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, } else if (!portalcrossed) { - line_t *out = port->mDestination; fixedvec3 pos = { tm.x, tm.y, thing->Z() }; fixedvec3 oldthingpos = thing->Pos(); fixedvec2 thingpos = oldthingpos; - P_TranslatePortalXY(ld, out, pos.x, pos.y); - P_TranslatePortalXY(ld, out, thingpos.x, thingpos.y); - P_TranslatePortalZ(ld, out, pos.z); + P_TranslatePortalXY(ld, pos.x, pos.y); + P_TranslatePortalXY(ld, thingpos.x, thingpos.y); + P_TranslatePortalZ(ld, pos.z); thing->SetXYZ(thingpos.x, thingpos.y, pos.z); if (!P_CheckPosition(thing, pos.x, pos.y, true)) // check if some actor blocks us on the other side. (No line checks, because of the mess that'd create.) { @@ -2342,8 +2341,8 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, } thing->UnlinkFromWorld(); thing->SetXYZ(pos); - P_TranslatePortalVXVY(ld, out, thing->velx, thing->vely); - P_TranslatePortalAngle(ld, out, thing->angle); + P_TranslatePortalVXVY(ld, thing->velx, thing->vely); + P_TranslatePortalAngle(ld, thing->angle); thing->LinkToWorld(); P_FindFloorCeiling(thing); thing->ClearInterpolation(); @@ -2355,7 +2354,6 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, { divline_t dl1 = { besthit.oldrefpos.x,besthit. oldrefpos.y, besthit.refpos.x - besthit.oldrefpos.x, besthit.refpos.y - besthit.oldrefpos.y }; fixedvec3a hit = { dl1.x + FixedMul(dl1.dx, bestfrac), dl1.y + FixedMul(dl1.dy, bestfrac), 0, 0 }; - line_t *out = port->mDestination; R_AddInterpolationPoint(hit); if (port->mType == PORTT_LINKED) @@ -2365,10 +2363,10 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, } else { - P_TranslatePortalXY(ld, out, hit.x, hit.y); - P_TranslatePortalZ(ld, out, hit.z); + P_TranslatePortalXY(ld, hit.x, hit.y); + P_TranslatePortalZ(ld, hit.z); players[consoleplayer].viewz += hit.z; // needs to be done here because otherwise the renderer will not catch the change. - P_TranslatePortalAngle(ld, out, hit.angle); + P_TranslatePortalAngle(ld, hit.angle); } R_AddInterpolationPoint(hit); } @@ -3700,7 +3698,6 @@ struct aim_t aim_t newtrace = Clone(); FLinePortal *port = li->getPortal(); - line_t *dest = port->mDestination; newtrace.toppitch = toppitch; newtrace.bottompitch = bottompitch; @@ -3708,9 +3705,9 @@ struct aim_t newtrace.unlinked = (port->mType != PORTT_LINKED); newtrace.startpos = startpos; newtrace.aimtrace = aimtrace; - P_TranslatePortalXY(li, dest, newtrace.startpos.x, newtrace.startpos.y); - P_TranslatePortalZ(li, dest, newtrace.startpos.z); - P_TranslatePortalVXVY(li, dest, newtrace.aimtrace.x, newtrace.aimtrace.y); + P_TranslatePortalXY(li, newtrace.startpos.x, newtrace.startpos.y); + P_TranslatePortalZ(li, newtrace.startpos.z); + P_TranslatePortalVXVY(li, newtrace.aimtrace.x, newtrace.aimtrace.y); newtrace.startfrac = frac + FixedDiv(FRACUNIT, attackrange); // this is to skip the transition line to the portal which would produce a bogus opening @@ -3718,7 +3715,7 @@ struct aim_t fixed_t y = newtrace.startpos.y + FixedMul(newtrace.aimtrace.y, newtrace.startfrac); newtrace.lastsector = P_PointInSector(x, y); - P_TranslatePortalZ(li, dest, limitz); + P_TranslatePortalZ(li, limitz); Printf("-----Entering line portal from sector %d to sector %d\n", lastsector->sectornum, newtrace.lastsector->sectornum); newtrace.AimTraverse(); SetResult(linetarget, newtrace.linetarget); diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 2a8c0efda1..c6453285eb 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -1660,14 +1660,13 @@ int FPathTraverse::PortalRelocate(intercept_t *in, int flags, fixedvec3 *optpos) fixed_t hity = trace.y; fixed_t endx = trace.x + trace.dx; fixed_t endy = trace.y + trace.dy; - line_t *out = in->d.line->getPortalDestination(); - - P_TranslatePortalXY(in->d.line, out, hitx, hity); - P_TranslatePortalXY(in->d.line, out, endx, endy); + + P_TranslatePortalXY(in->d.line, hitx, hity); + P_TranslatePortalXY(in->d.line, endx, endy); if (optpos != NULL) { - P_TranslatePortalXY(in->d.line, out, optpos->x, optpos->y); - P_TranslatePortalZ(in->d.line, out, optpos->z); + P_TranslatePortalXY(in->d.line, optpos->x, optpos->y); + P_TranslatePortalZ(in->d.line, optpos->z); } intercepts.Resize(intercept_index); init(hitx, hity, endx, endy, flags, in->frac); diff --git a/src/portal.cpp b/src/portal.cpp index 01afb0bc48..f9c3cec2a6 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -265,9 +265,17 @@ void P_SpawnLinePortal(line_t* line) if (port->mDestination != NULL) { port->mDefFlags = port->mType == PORTT_VISUAL ? PORTF_VISIBLE : port->mType == PORTT_TELEPORT ? PORTF_TYPETELEPORT : PORTF_TYPEINTERACTIVE; - - } + + // Get the angle between the two linedefs, for rotating + // orientation and velocity. Rotate 180 degrees, and flip + // the position across the exit linedef, if reversed. + + double angle = atan2(dst->dy, dst->dx) - atan2(line->dy, line->dx) + M_PI; + port->mSinRot = FLOAT2FIXED(sin(angle)); + port->mCosRot = FLOAT2FIXED(cos(angle)); + port->mAngleDiff = RAD2ANGLE(angle); + } else if (line->args[2] == PORTT_LINKEDEE && line->args[0] == 0) { @@ -546,30 +554,22 @@ bool P_ClipLineToPortal(line_t* line, line_t* portal, fixed_t viewx, fixed_t vie // //============================================================================ -void P_TranslatePortalXY(line_t* src, line_t* dst, fixed_t& x, fixed_t& y) +void P_TranslatePortalXY(line_t* src, fixed_t& x, fixed_t& y) { - if (!src || !dst) - return; + if (!src) return; + FLinePortal *port = src->getPortal(); + if (!port) return; - fixed_t nposx, nposy; // offsets from line - - // Get the angle between the two linedefs, for rotating - // orientation and velocity. Rotate 180 degrees, and flip - // the position across the exit linedef, if reversed. - - double angle = atan2(dst->dy, dst->dx) - atan2(src->dy, src->dx) + M_PI; - fixed_t s = FLOAT2FIXED(sin(angle)); - fixed_t c = FLOAT2FIXED(cos(angle)); - - nposx = x - src->v1->x; - nposy = y - src->v1->y; + // offsets from line + fixed_t nposx = x - src->v1->x; + fixed_t nposy = y - src->v1->y; // Rotate position along normal to match exit linedef - fixed_t tx = FixedMul(nposx, c) - FixedMul(nposy, s); - fixed_t ty = FixedMul(nposy, c) + FixedMul(nposx, s); + fixed_t tx = FixedMul(nposx, port->mCosRot) - FixedMul(nposy, port->mSinRot); + fixed_t ty = FixedMul(nposy, port->mCosRot) + FixedMul(nposx, port->mSinRot); - tx += dst->v2->x; - ty += dst->v2->y; + tx += port->mDestination->v2->x; + ty += port->mDestination->v2->y; x = tx; y = ty; @@ -581,16 +581,16 @@ void P_TranslatePortalXY(line_t* src, line_t* dst, fixed_t& x, fixed_t& y) // //============================================================================ -void P_TranslatePortalVXVY(line_t* src, line_t* dst, fixed_t& vx, fixed_t& vy) +void P_TranslatePortalVXVY(line_t* src, fixed_t& vx, fixed_t& vy) { - double angle = atan2(dst->dy, dst->dx) - atan2(src->dy, src->dx) + M_PI; - fixed_t s = FLOAT2FIXED(sin(angle)); - fixed_t c = FLOAT2FIXED(cos(angle)); + if (!src) return; + FLinePortal *port = src->getPortal(); + if (!port) return; fixed_t orig_velx = vx; fixed_t orig_vely = vy; - vx = FixedMul(orig_velx, c) - FixedMul(orig_vely, s); - vy = FixedMul(orig_vely, c) + FixedMul(orig_velx, s); + vx = FixedMul(orig_velx, port->mCosRot) - FixedMul(orig_vely, port->mSinRot); + vy = FixedMul(orig_vely, port->mCosRot) + FixedMul(orig_velx, port->mSinRot); } //============================================================================ @@ -599,15 +599,12 @@ void P_TranslatePortalVXVY(line_t* src, line_t* dst, fixed_t& vx, fixed_t& vy) // //============================================================================ -void P_TranslatePortalAngle(line_t* src, line_t* dst, angle_t& angle) +void P_TranslatePortalAngle(line_t* src, angle_t& angle) { - if (!src || !dst) - return; - - // Get the angle between the two linedefs, for rotating - // orientation and velocity. Rotate 180 degrees, and flip - // the position across the exit linedef, if reversed. - angle += RAD2ANGLE(atan2(dst->dy, dst->dx) - atan2(src->dy, src->dx)) + ANGLE_180; + if (!src) return; + FLinePortal *port = src->getPortal(); + if (!port) return; + angle += port->mAngleDiff; } //============================================================================ @@ -616,12 +613,14 @@ void P_TranslatePortalAngle(line_t* src, line_t* dst, angle_t& angle) // //============================================================================ -void P_TranslatePortalZ(line_t* src, line_t* dst, fixed_t& z) +void P_TranslatePortalZ(line_t* src, fixed_t& z) { // args[2] = 0 - no adjustment // args[2] = 1 - adjust by floor difference // args[2] = 2 - adjust by ceiling difference + // This cannot be precalculated because heights may change. + line_t *dst = src->getPortalDestination(); switch (src->getPortalAlignment()) { case PORG_FLOOR: @@ -704,7 +703,6 @@ fixedvec2 P_GetOffsetPosition(fixed_t x, fixed_t y, fixed_t dx, fixed_t dy) // hit a portal line. line_t *line = in->d.line; FLinePortal *port = line->getPortal(); - line_t* out = port->mDestination; // Teleport portals are intentionally ignored since skipping this stuff is their entire reason for existence. if (port->mFlags & PORTF_INTERACTIVE) @@ -723,8 +721,8 @@ fixedvec2 P_GetOffsetPosition(fixed_t x, fixed_t y, fixed_t dx, fixed_t dy) { // interactive ones are more complex because the vector may be rotated. // Note: There is no z-translation here, there's just too much code in the engine that wouldn't be able to handle interactive portals with a height difference. - P_TranslatePortalXY(line, out, hit.x, hit.y); - P_TranslatePortalXY(line, out, dest.x, dest.y); + P_TranslatePortalXY(line, hit.x, hit.y); + P_TranslatePortalXY(line, dest.x, dest.y); } // update the fields, end this trace and restart from the new position dx = dest.x - hit.x; diff --git a/src/portal.h b/src/portal.h index 127a9ec3ba..b8a5d3ba38 100644 --- a/src/portal.h +++ b/src/portal.h @@ -173,6 +173,9 @@ struct FLinePortal BYTE mFlags; BYTE mDefFlags; BYTE mAlign; + angle_t mAngleDiff; + fixed_t mSinRot; + fixed_t mCosRot; }; extern TArray linePortals; @@ -192,10 +195,10 @@ inline int P_NumPortalGroups() /* code ported from prototype */ bool P_ClipLineToPortal(line_t* line, line_t* portal, fixed_t viewx, fixed_t viewy, bool partial = true, bool samebehind = true); -void P_TranslatePortalXY(line_t* src, line_t* dst, fixed_t& x, fixed_t& y); -void P_TranslatePortalVXVY(line_t* src, line_t* dst, fixed_t& vx, fixed_t& vy); -void P_TranslatePortalAngle(line_t* src, line_t* dst, angle_t& angle); -void P_TranslatePortalZ(line_t* src, line_t* dst, fixed_t& z); +void P_TranslatePortalXY(line_t* src, fixed_t& x, fixed_t& y); +void P_TranslatePortalVXVY(line_t* src, fixed_t& vx, fixed_t& vy); +void P_TranslatePortalAngle(line_t* src, angle_t& angle); +void P_TranslatePortalZ(line_t* src, fixed_t& z); void P_NormalizeVXVY(fixed_t& vx, fixed_t& vy); fixed_t P_PointLineDistance(line_t* line, fixed_t x, fixed_t y); fixedvec2 P_GetOffsetPosition(fixed_t x, fixed_t y, fixed_t dx, fixed_t dy); diff --git a/src/r_main.cpp b/src/r_main.cpp index 12dd3916bd..c445787a07 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -732,9 +732,9 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) } else { - P_TranslatePortalXY(pds->src, pds->dst, viewx, viewy); - P_TranslatePortalZ(pds->src, pds->dst, viewz); - P_TranslatePortalAngle(pds->src, pds->dst, viewangle); + P_TranslatePortalXY(pds->src, viewx, viewy); + P_TranslatePortalZ(pds->src, viewz); + P_TranslatePortalAngle(pds->src, viewangle); } viewsin = finesine[viewangle>>ANGLETOFINESHIFT];