mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 21:11:39 +00:00
Fixed odd merge bugs
This commit is contained in:
parent
a520d35d89
commit
31cad858d9
3 changed files with 464 additions and 0 deletions
|
@ -951,6 +951,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE
|
|||
p_xlat.cpp
|
||||
parsecontext.cpp
|
||||
po_man.cpp
|
||||
portal.cpp
|
||||
r_swrenderer.cpp
|
||||
r_utility.cpp
|
||||
r_3dfloors.cpp
|
||||
|
|
390
src/portal.cpp
Normal file
390
src/portal.cpp
Normal file
|
@ -0,0 +1,390 @@
|
|||
#include "portal.h"
|
||||
#include "p_local.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "r_bsp.h"
|
||||
#include "r_segs.h"
|
||||
#include "c_cvars.h"
|
||||
#include "m_bbox.h"
|
||||
|
||||
// simulation recurions maximum
|
||||
CVAR(Int, sv_portal_recursions, 4, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
||||
|
||||
PortalDrawseg* CurrentPortal = NULL;
|
||||
int CurrentPortalUniq = 0;
|
||||
|
||||
// [ZZ] lots of floats here to avoid overflowing a lot
|
||||
bool R_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)
|
||||
{
|
||||
float xx = FIXED2FLOAT(o2x) - FIXED2FLOAT(o1x);
|
||||
float xy = FIXED2FLOAT(o2y) - FIXED2FLOAT(o1y);
|
||||
|
||||
float d1x = FIXED2FLOAT(p1x) - FIXED2FLOAT(o1x);
|
||||
float d1y = FIXED2FLOAT(p1y) - FIXED2FLOAT(o1y);
|
||||
|
||||
if (d1x > d1y)
|
||||
{
|
||||
d1y = d1y / d1x * 32767.0f;
|
||||
d1x = 32767.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
d1x = d1x / d1y * 32767.0f;
|
||||
d1y = 32767.0;
|
||||
}
|
||||
|
||||
float d2x = FIXED2FLOAT(p2x) - FIXED2FLOAT(o2x);
|
||||
float d2y = FIXED2FLOAT(p2y) - FIXED2FLOAT(o2y);
|
||||
|
||||
float cross = d1x*d2y - d1y*d2x;
|
||||
if (fabs(cross) < 1e-8)
|
||||
return false;
|
||||
|
||||
float t1 = (xx * d2y - xy * d2x)/cross;
|
||||
rx = o1x + FLOAT2FIXED(d1x * t1);
|
||||
ry = o1y + FLOAT2FIXED(d1y * t1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool P_ClipLineToPortal(line_t* line, line_t* portal, fixed_t viewx, fixed_t viewy, bool partial, bool samebehind)
|
||||
{
|
||||
// we do this only if simple check doesn't clip away the line
|
||||
bool behind1 = !!P_PointOnLineSide(line->v1->x, line->v1->y, portal);
|
||||
bool behind2 = !!P_PointOnLineSide(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)
|
||||
return true;
|
||||
|
||||
if ((behind1 || behind2) && partial)
|
||||
{
|
||||
fixed_t v1x = line->v1->x;
|
||||
fixed_t v1y = line->v1->y;
|
||||
fixed_t v2x = line->v2->x;
|
||||
fixed_t v2y = line->v2->y;
|
||||
|
||||
fixed_t check1X = viewx;
|
||||
fixed_t check1Y = viewy;
|
||||
|
||||
fixed_t check2X = portal->v2->x;
|
||||
fixed_t check2Y = portal->v2->y;
|
||||
|
||||
fixed_t in1x = v1x;
|
||||
fixed_t in1y = v1y;
|
||||
|
||||
bool i1 = R_IntersectLines(check1X, check1Y, check2X, check2Y, v1x, v1y, v2x, v2y, in1x, in1y);
|
||||
|
||||
check2X = portal->v1->x;
|
||||
check2Y = portal->v1->y;
|
||||
|
||||
fixed_t in2x = v2x;
|
||||
fixed_t in2y = v2y;
|
||||
|
||||
bool i2 = R_IntersectLines(check1X, check1Y, check2X, check2Y, v1x, v1y, v2x, v2y, in2x, in2y);
|
||||
|
||||
//if (log) Printf("intersection = %d [at %.2f, %.2f]; %d [at %.2f, %.2f]\n", i1, FIXED2FLOAT(in1x), FIXED2FLOAT(in1y), i2, FIXED2FLOAT(in2x), FIXED2FLOAT(in2y));
|
||||
|
||||
// now, to cull the shitty line that obstructs the view, we check if any of intersected points are on behind of the portal :)
|
||||
behind1 = !!P_PointOnLineSide(in1x, in1y, portal);
|
||||
behind2 = !!P_PointOnLineSide(in2x, in2y, portal);
|
||||
|
||||
if (behind1 && behind2)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool P_CheckPortal(line_t* line)
|
||||
{
|
||||
if (line->special == Line_Mirror)
|
||||
{
|
||||
line->portal = true;
|
||||
line->portal_mirror = true;
|
||||
line->portal_passive = true;
|
||||
line->portal_dst = line;
|
||||
}
|
||||
else if (line->special == Line_SetPortal ||
|
||||
line->special == Line_SetVisualPortal)
|
||||
{
|
||||
// portal destination is special argument #0
|
||||
line_t* dst = NULL;
|
||||
|
||||
if (line->args[0] > 0)
|
||||
{
|
||||
int linenum = -1;
|
||||
|
||||
for (int i = 0; i < numlines; i++)
|
||||
{
|
||||
if (&lines[i] == line)
|
||||
continue;
|
||||
if (lines[i].id == line->args[0])
|
||||
{
|
||||
dst = &lines[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dst)
|
||||
{
|
||||
line->portal = true;
|
||||
line->portal_mirror = false;
|
||||
line->portal_passive = (line->special == Line_SetVisualPortal);
|
||||
line->portal_dst = dst;
|
||||
}
|
||||
else
|
||||
{
|
||||
line->portal = false;
|
||||
line->portal_mirror = false;
|
||||
line->portal_passive = false;
|
||||
line->portal_dst = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
line->portal = false;
|
||||
line->portal_mirror = false;
|
||||
line->portal_passive = false;
|
||||
line->portal_dst = NULL;
|
||||
}
|
||||
|
||||
return (line->portal);
|
||||
}
|
||||
|
||||
void P_TranslatePortalXY(line_t* src, line_t* dst, fixed_t& x, fixed_t& y)
|
||||
{
|
||||
if (!src || !dst)
|
||||
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.
|
||||
angle_t angle =
|
||||
R_PointToAngle2(0, 0, dst->dx, dst->dy) -
|
||||
R_PointToAngle2(0, 0, src->dx, src->dy);
|
||||
|
||||
angle += ANGLE_180;
|
||||
|
||||
// Sine, cosine of angle adjustment
|
||||
fixed_t s = finesine[angle>>ANGLETOFINESHIFT];
|
||||
fixed_t c = finecosine[angle>>ANGLETOFINESHIFT];
|
||||
|
||||
fixed_t tx, ty;
|
||||
|
||||
nposx = x - src->v1->x;
|
||||
nposy = y - src->v1->y;
|
||||
|
||||
// Rotate position along normal to match exit linedef
|
||||
tx = FixedMul(nposx, c) - FixedMul(nposy, s);
|
||||
ty = FixedMul(nposy, c) + FixedMul(nposx, s);
|
||||
|
||||
tx += dst->v2->x;
|
||||
ty += dst->v2->y;
|
||||
|
||||
x = tx;
|
||||
y = ty;
|
||||
}
|
||||
|
||||
void P_TranslatePortalVXVY(line_t* src, line_t* dst, fixed_t& vx, fixed_t& vy)
|
||||
{
|
||||
angle_t angle =
|
||||
R_PointToAngle2(0, 0, dst->dx, dst->dy) -
|
||||
R_PointToAngle2(0, 0, src->dx, src->dy);
|
||||
|
||||
angle += ANGLE_180;
|
||||
|
||||
// Sine, cosine of angle adjustment
|
||||
fixed_t s = finesine[angle>>ANGLETOFINESHIFT];
|
||||
fixed_t c = finecosine[angle>>ANGLETOFINESHIFT];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void P_TranslatePortalAngle(line_t* src, line_t* dst, 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_t xangle =
|
||||
R_PointToAngle2(0, 0, dst->dx, dst->dy) -
|
||||
R_PointToAngle2(0, 0, src->dx, src->dy);
|
||||
|
||||
xangle += ANGLE_180;
|
||||
angle += xangle;
|
||||
}
|
||||
|
||||
void P_TranslatePortalZ(line_t* src, line_t* dst, fixed_t& z)
|
||||
{
|
||||
// args[2] = 0 - no teleport
|
||||
// args[2] = 1 - adjust by floor difference
|
||||
// args[2] = 2 - adjust by ceiling difference
|
||||
|
||||
if (src->args[2] == 1)
|
||||
{
|
||||
z = z - src->frontsector->floorplane.ZatPoint(src->v1->x, src->v1->y) + dst->frontsector->floorplane.ZatPoint(dst->v2->x, dst->v2->y);
|
||||
}
|
||||
else if (src->args[2] == 2)
|
||||
{
|
||||
z = z - src->frontsector->ceilingplane.ZatPoint(src->v1->x, src->v1->y) + dst->frontsector->ceilingplane.ZatPoint(dst->v2->x, dst->v2->y);
|
||||
}
|
||||
}
|
||||
|
||||
// calculate shortest distance from a point (x,y) to a linedef
|
||||
fixed_t P_PointLineDistance(line_t* line, fixed_t x, fixed_t y)
|
||||
{
|
||||
angle_t angle = R_PointToAngle2(0, 0, line->dx, line->dy);
|
||||
angle += ANGLE_180;
|
||||
|
||||
fixed_t dx = line->v1->x - x;
|
||||
fixed_t dy = line->v1->y - y;
|
||||
|
||||
fixed_t s = finesine[angle>>ANGLETOFINESHIFT];
|
||||
fixed_t c = finecosine[angle>>ANGLETOFINESHIFT];
|
||||
|
||||
fixed_t d2x = FixedMul(dx, c) - FixedMul(dy, s);
|
||||
|
||||
return abs(d2x);
|
||||
}
|
||||
|
||||
void P_NormalizeVXVY(fixed_t& vx, fixed_t& vy)
|
||||
{
|
||||
float _vx = FIXED2FLOAT(vx);
|
||||
float _vy = FIXED2FLOAT(vy);
|
||||
float len = sqrt(_vx*_vx+_vy*_vy);
|
||||
vx = FLOAT2FIXED(_vx/len);
|
||||
vy = FLOAT2FIXED(_vy/len);
|
||||
}
|
||||
|
||||
// portal tracer code
|
||||
PortalTracer::PortalTracer(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy)
|
||||
{
|
||||
this->startx = startx;
|
||||
this->starty = starty;
|
||||
this->endx = endx;
|
||||
this->endy = endy;
|
||||
intx = endx;
|
||||
inty = endy;
|
||||
intxIn = intx;
|
||||
intyIn = inty;
|
||||
z = 0;
|
||||
angle = 0;
|
||||
depth = 0;
|
||||
frac = 0;
|
||||
in = NULL;
|
||||
out = NULL;
|
||||
vx = 0;
|
||||
vy = 0;
|
||||
}
|
||||
|
||||
bool PortalTracer::TraceStep()
|
||||
{
|
||||
if (depth > sv_portal_recursions)
|
||||
return false;
|
||||
|
||||
this->in = NULL;
|
||||
this->out = NULL;
|
||||
this->vx = 0;
|
||||
this->vy = 0;
|
||||
|
||||
int oDepth = depth;
|
||||
|
||||
fixed_t dirx = endx-startx;
|
||||
fixed_t diry = endy-starty;
|
||||
P_NormalizeVXVY(dirx, diry);
|
||||
|
||||
dirx = 0;
|
||||
diry = 0;
|
||||
|
||||
FPathTraverse it(startx-dirx, starty-diry, endx+dirx, endy+diry, PT_ADDLINES | PT_COMPATIBLE);
|
||||
|
||||
intercept_t *in;
|
||||
while ((in = it.Next()))
|
||||
{
|
||||
line_t* li;
|
||||
|
||||
if (in->isaline)
|
||||
{
|
||||
li = in->d.line;
|
||||
|
||||
if (li->portal && !li->portal_passive)
|
||||
{
|
||||
if (P_PointOnLineSide(startx-dirx, starty-diry, li))
|
||||
continue; // we're at the back side of this line
|
||||
|
||||
line_t* out = li->portal_dst;
|
||||
|
||||
this->in = li;
|
||||
this->out = out;
|
||||
|
||||
// we only know that we crossed it, but we also need to know WHERE we crossed it
|
||||
fixed_t vx = it.Trace().dx;
|
||||
fixed_t vy = it.Trace().dy;
|
||||
|
||||
fixed_t x = it.Trace().x + FixedMul(vx, in->frac);
|
||||
fixed_t y = it.Trace().y + FixedMul(vy, in->frac);
|
||||
|
||||
P_NormalizeVXVY(vx, vy);
|
||||
|
||||
this->vx = vx;
|
||||
this->vy = vy;
|
||||
|
||||
// teleport our trace
|
||||
|
||||
if (!out->backsector)
|
||||
{
|
||||
intx = x + vx;
|
||||
inty = y + vy;
|
||||
}
|
||||
else
|
||||
{
|
||||
intx = x - vx;
|
||||
inty = y - vy;
|
||||
}
|
||||
|
||||
//P_TranslateCoordinatesAndAngle(li, out, startx, starty, noangle);
|
||||
//P_TranslateCoordinatesAndAngle(li, out, endx, endy, angle);
|
||||
//if (hdeltaZ)
|
||||
// P_TranslateZ(li, out, deltaZ);
|
||||
//P_TranslateCoordinatesAndAngle(li, out, vx, vy, noangle);
|
||||
|
||||
P_TranslatePortalXY(li, out, startx, starty);
|
||||
P_TranslatePortalVXVY(li, out, this->vx, this->vy);
|
||||
intxIn = intx;
|
||||
intyIn = inty;
|
||||
P_TranslatePortalXY(li, out, intx, inty);
|
||||
P_TranslatePortalXY(li, out, endx, endy);
|
||||
P_TranslatePortalAngle(li, out, angle);
|
||||
P_TranslatePortalZ(li, out, z);
|
||||
frac += in->frac;
|
||||
depth++;
|
||||
break; // breaks to outer loop
|
||||
}
|
||||
|
||||
if (!(li->flags & ML_TWOSIDED) || (li->flags & ML_BLOCKEVERYTHING))
|
||||
return false; // stop tracing, 2D blocking line
|
||||
}
|
||||
}
|
||||
|
||||
//Printf("returning %d; vx = %.2f; vy = %.2f\n", (oDepth != depth), FIXED2FLOAT(this->vx), FIXED2FLOAT(this->vy));
|
||||
|
||||
return (oDepth != depth); // if a portal has been found, return false
|
||||
}
|
||||
|
73
src/portal.h
Normal file
73
src/portal.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
#ifndef _PORTALS_H_
|
||||
#define _PORTALS_H_
|
||||
|
||||
#include "basictypes.h"
|
||||
#include "v_video.h"
|
||||
#include "r_defs.h"
|
||||
#include "actor.h"
|
||||
#include "p_local.h"
|
||||
#include "m_bbox.h"
|
||||
|
||||
/* portal structure, this is used in r_ code in order to store drawsegs with portals (and mirrors) */
|
||||
struct PortalDrawseg
|
||||
{
|
||||
line_t* src; // source line (the one drawn) this doesn't change over render loops
|
||||
line_t* dst; // destination line (the one that the portal is linked with, equals 'src' for mirrors)
|
||||
|
||||
int x1; // drawseg x1
|
||||
int x2; // drawseg x2
|
||||
|
||||
int len;
|
||||
TArray<short> ceilingclip;
|
||||
TArray<short> floorclip;
|
||||
|
||||
bool mirror; // true if this is a mirror (src should equal dst)
|
||||
};
|
||||
|
||||
extern PortalDrawseg* CurrentPortal;
|
||||
extern int CurrentPortalUniq;
|
||||
|
||||
/* 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);
|
||||
bool P_CheckPortal(line_t* line);
|
||||
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_NormalizeVXVY(fixed_t& vx, fixed_t& vy);
|
||||
|
||||
// basically, this is a teleporting tracer function,
|
||||
// which can be used by itself (to calculate portal-aware offsets, say, for projectiles)
|
||||
// or to teleport normal tracers (like hitscan, railgun, autoaim tracers)
|
||||
class PortalTracer
|
||||
{
|
||||
public:
|
||||
PortalTracer(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy);
|
||||
|
||||
// trace to next portal
|
||||
bool TraceStep();
|
||||
// trace to last available portal on the path
|
||||
void TraceAll() { while (TraceStep()) continue; }
|
||||
|
||||
int depth;
|
||||
fixed_t startx;
|
||||
fixed_t starty;
|
||||
fixed_t intx;
|
||||
fixed_t inty;
|
||||
fixed_t intxIn;
|
||||
fixed_t intyIn;
|
||||
fixed_t endx;
|
||||
fixed_t endy;
|
||||
angle_t angle;
|
||||
fixed_t z;
|
||||
fixed_t frac;
|
||||
line_t* in;
|
||||
line_t* out;
|
||||
fixed_t vx;
|
||||
fixed_t vy;
|
||||
};
|
||||
|
||||
/* new code */
|
||||
fixed_t P_PointLineDistance(line_t* line, fixed_t x, fixed_t y);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue