mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
- redid P_ClipLineToPortal with revised visibility rules:
* any line completely parallel to the portal is rejected * any line with one end on the same straight line than the portal is solely decided by the other vertex. * any line with both ends behind the portal cannot be visible inside, so there's no need to check for an intersection with the view range. * due to the above P_IntersectLines could be removed as it was redundant. * for any line that does intersect with the portal straight, do a reverse check: If both ends of the portal lie on the other side of the line than the viewpoint, the line is between viewpoint and portal and needs to be rejected. This fixes nearly all the phantom wall glitches in the demo map.
This commit is contained in:
parent
14a0567343
commit
ec258c9588
1 changed files with 37 additions and 61 deletions
102
src/portal.cpp
102
src/portal.cpp
|
@ -468,47 +468,6 @@ void P_ClearPortals()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// Calculate the intersection between two lines.
|
|
||||||
// [ZZ] lots of floats here to avoid overflowing a lot
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
bool P_IntersectLines(fixed_t o1x, fixed_t o1y, fixed_t p1x, fixed_t p1y,
|
|
||||||
fixed_t o2x, fixed_t o2y, fixed_t p2x, fixed_t p2y,
|
|
||||||
fixed_t& rx, fixed_t& ry)
|
|
||||||
{
|
|
||||||
double xx = FIXED2DBL(o2x) - FIXED2DBL(o1x);
|
|
||||||
double xy = FIXED2DBL(o2y) - FIXED2DBL(o1y);
|
|
||||||
|
|
||||||
double d1x = FIXED2DBL(p1x) - FIXED2DBL(o1x);
|
|
||||||
double d1y = FIXED2DBL(p1y) - FIXED2DBL(o1y);
|
|
||||||
|
|
||||||
if (d1x > d1y)
|
|
||||||
{
|
|
||||||
d1y = d1y / d1x * 32767.0f;
|
|
||||||
d1x = 32767.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d1x = d1x / d1y * 32767.0f;
|
|
||||||
d1y = 32767.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double d2x = FIXED2DBL(p2x) - FIXED2DBL(o2x);
|
|
||||||
double d2y = FIXED2DBL(p2y) - FIXED2DBL(o2y);
|
|
||||||
|
|
||||||
double cross = d1x*d2y - d1y*d2x;
|
|
||||||
if (fabs(cross) < 1e-8)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
double t1 = (xx * d2y - xy * d2x)/cross;
|
|
||||||
rx = o1x + FLOAT2FIXED(d1x * t1);
|
|
||||||
ry = o1y + FLOAT2FIXED(d1y * t1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int P_PointOnLineSideExplicit (fixed_t x, fixed_t y, fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
|
inline int P_PointOnLineSideExplicit (fixed_t x, fixed_t y, fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
|
||||||
{
|
{
|
||||||
return DMulScale32 (y-y1, x2-x1, x1-x, y2-y1) > 0;
|
return DMulScale32 (y-y1, x2-x1, x1-x, y2-y1) > 0;
|
||||||
|
@ -517,36 +476,53 @@ inline int P_PointOnLineSideExplicit (fixed_t x, fixed_t y, fixed_t x1, fixed_t
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// check if this line is between portal and the viewer. clip away if it is.
|
// check if this line is between portal and the viewer. clip away if it is.
|
||||||
// (this may need some fixing)
|
|
||||||
//
|
//
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
bool P_ClipLineToPortal(line_t* line, line_t* portal, fixed_t viewx, fixed_t viewy, bool partial, bool samebehind)
|
inline int P_GetLineSide(fixed_t x, fixed_t y, const line_t *line)
|
||||||
{
|
{
|
||||||
bool behind1 = !!P_PointOnLineSidePrecise(line->v1->x, line->v1->y, portal);
|
return DMulScale32(y - line->v1->y, line->dx, line->v1->x - x, line->dy);
|
||||||
bool behind2 = !!P_PointOnLineSidePrecise(line->v2->x, line->v2->y, portal);
|
|
||||||
|
|
||||||
// [ZZ] update 16.12.2014: if a vertex equals to one of portal's vertices, it's treated as being behind the portal.
|
|
||||||
// this is required in order to clip away diagonal lines around the portal (example: 1-sided triangle shape with a mirror on it's side)
|
|
||||||
if ((line->v1->x == portal->v1->x && line->v1->y == portal->v1->y) ||
|
|
||||||
(line->v1->x == portal->v2->x && line->v1->y == portal->v2->y))
|
|
||||||
behind1 = samebehind;
|
|
||||||
if ((line->v2->x == portal->v1->x && line->v2->y == portal->v1->y) ||
|
|
||||||
(line->v2->x == portal->v2->x && line->v2->y == portal->v2->y))
|
|
||||||
behind2 = samebehind;
|
|
||||||
|
|
||||||
if (behind1 && behind2)
|
|
||||||
{
|
|
||||||
// line is behind the portal plane. now check if it's in front of two view plane borders (i.e. if it will get in the way of rendering)
|
|
||||||
fixed_t dummyx, dummyy;
|
|
||||||
bool infront1 = P_IntersectLines(line->v1->x, line->v1->y, line->v2->x, line->v2->y, viewx, viewy, portal->v1->x, portal->v1->y, dummyx, dummyy);
|
|
||||||
bool infront2 = P_IntersectLines(line->v1->x, line->v1->y, line->v2->x, line->v2->y, viewx, viewy, portal->v2->x, portal->v2->y, dummyx, dummyy);
|
|
||||||
if (infront1 && infront2)
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool P_ClipLineToPortal(line_t* line, line_t* portal, fixed_t viewx, fixed_t viewy, bool partial, bool samebehind)
|
||||||
|
{
|
||||||
|
int behind1 = P_GetLineSide(line->v1->x, line->v1->y, portal);
|
||||||
|
int behind2 = P_GetLineSide(line->v2->x, line->v2->y, portal);
|
||||||
|
|
||||||
|
if (behind1 == 0 && behind2 == 0)
|
||||||
|
{
|
||||||
|
// The line is parallel to the portal and cannot possibly be visible.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If one point lies on the same straight line than the portal, the other vertex will determine sidedness alone.
|
||||||
|
else if (behind2 == 0) behind2 = behind1;
|
||||||
|
else if (behind1 == 0) behind1 = behind2;
|
||||||
|
|
||||||
|
if (behind1 > 0 && behind2 > 0)
|
||||||
|
{
|
||||||
|
// The line is behind the portal, i.e. between viewer and portal line, and must be rejected
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (behind1 < 0 && behind2 < 0)
|
||||||
|
{
|
||||||
|
// The line is in front of the portal, i.e. the portal is between viewer and line. This line must not be rejected
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The line intersects with the portal straight, so we need to do another check to see how both ends of the portal lie in relation to the viewer.
|
||||||
|
int viewside = P_PointOnLineSidePrecise(viewx, viewy, line);
|
||||||
|
int p1side = P_GetLineSide(portal->v1->x, portal->v1->y, line);
|
||||||
|
int p2side = P_GetLineSide(portal->v2->x, portal->v2->y, line);
|
||||||
|
// Do the same handling of points on the portal straight than above.
|
||||||
|
if (p1side == 0) p1side = p2side;
|
||||||
|
else if (p2side == 0) p2side = p1side;
|
||||||
|
p1side = p1side > 0;
|
||||||
|
p2side = p2side > 0;
|
||||||
|
// If the portal is on the other side of the line than the viewpoint, there is no possibility to see this line inside the portal.
|
||||||
|
return (p1side == p2side && viewside != p1side);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in a new issue