- let the clipper work exclusively on Build coordinates.

This commit is contained in:
Christoph Oelckers 2021-03-22 23:40:25 +01:00
parent 096ce5e025
commit 0c7f05a416
11 changed files with 103 additions and 126 deletions

View file

@ -21,6 +21,7 @@ static_assert('\xff' == 255, "Char must be unsigned!");
#include "compat.h"
#include "palette.h"
#include "binaryangle.h"
//Make all variables in BUILD.H defined in the ENGINE,
//and externed in GAME
@ -35,7 +36,6 @@ EXTERN int16_t sintable[2048];
#include "buildtiles.h"
#include "c_cvars.h"
#include "cmdlib.h"
#include "binaryangle.h"
#include "mathutil.h"
typedef int64_t coord_t;

View file

@ -118,7 +118,7 @@ struct walltype
int16_t hitag;
int16_t extra;
float xpan_, ypan_;
angle_t clipangle;
binangle clipangle;
uint8_t portalflags;
uint16_t portalnum;

View file

@ -40,8 +40,8 @@
#include "m_fixed.h"
#include "xs_Float.h" // needed for reliably overflowing float->int conversions.
#include "serializer.h"
#include "build.h"
#include "math/cmath.h"
#include "templates.h"
class FSerializer;
@ -61,6 +61,7 @@ enum
constexpr double BAngRadian = pi::pi() * (1. / 1024.);
constexpr double BRadAngScale = 1. / BAngRadian;
extern int16_t sintable[2048];
//---------------------------------------------------------------------------
//
@ -345,7 +346,6 @@ public:
{
return binangle(value >> shift);
}
};
inline constexpr binangle bamang(uint32_t v) { return binangle(v); }

View file

@ -1,8 +1,8 @@
#pragma once
#include "gamecontrol.h"
#include "buildtypes.h"
#include "binaryangle.h"
#include "build.h"
extern int cameradist, cameraclock;

View file

@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "gameinput.h"
#include "gamestruct.h"
#include "serializer.h"
#include "build.h"
CVARD(Bool, invertmousex, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "invert horizontal mouse movement")
CVARD(Bool, invertmouse, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "invert vertical mouse movement")

View file

@ -54,12 +54,12 @@ void BunchDrawer::Init(HWDrawInfo *_di, Clipper* c, vec2_t& view)
viewx = view.x * (1/ 16.f);
viewy = view.y * -(1/ 16.f);
StartScene();
clipper->SetViewpoint(DVector2(viewx, viewy));
clipper->SetViewpoint(view);
for (int i = 0; i < numwalls; i++)
{
// Precalculate the clip angles to avoid doing this repeatedly during level traversal.
// Reverse the orientation so that startangle and endangle are properly ordered.
wall[i].clipangle = 0 - clipper->PointToPseudoAngle(wall[i].x * (1 / 16.f), wall[i].y * (-1 / 16.f));
wall[i].clipangle = clipper->PointToAngle(wall[i].pos);
}
}
@ -84,7 +84,7 @@ void BunchDrawer::StartScene()
//
//==========================================================================
void BunchDrawer::StartBunch(int sectnum, int linenum, angle_t startan, angle_t endan)
void BunchDrawer::StartBunch(int sectnum, int linenum, binangle startan, binangle endan)
{
FBunch* bunch = &Bunches[LastBunch = Bunches.Reserve(1)];
@ -100,7 +100,7 @@ void BunchDrawer::StartBunch(int sectnum, int linenum, angle_t startan, angle_t
//
//==========================================================================
void BunchDrawer::AddLineToBunch(int line, int newan)
void BunchDrawer::AddLineToBunch(int line, binangle newan)
{
Bunches[LastBunch].endline++;
Bunches[LastBunch].endangle = newan;
@ -186,14 +186,13 @@ bool BunchDrawer::CheckClip(walltype* wal)
int BunchDrawer::ClipLine(int line)
{
angle_t startAngle, endAngle;
auto wal = &wall[line];
startAngle = wal->clipangle;
endAngle = wall[wal->point2].clipangle;
auto startAngle = wal->clipangle;
auto endAngle = wall[wal->point2].clipangle;
// Back side, i.e. backface culling - read: endAngle >= startAngle!
if (startAngle - endAngle < ANGLE_180)
if (startAngle.asbam() - endAngle.asbam() < ANGLE_180)
{
return CL_Skip;
}
@ -325,9 +324,9 @@ int BunchDrawer::WallInFront(int wall1, int wall2)
int BunchDrawer::BunchInFront(FBunch* b1, FBunch* b2)
{
angle_t anglecheck, endang;
binangle anglecheck, endang;
if (b2->startangle - b1->startangle < b1->endangle - b1->startangle)
if (b2->startangle.asbam() - b1->startangle.asbam() < b1->endangle.asbam() - b1->startangle.asbam())
{
// we have an overlap at b2->startangle
anglecheck = b2->startangle - b1->startangle;
@ -336,7 +335,7 @@ int BunchDrawer::BunchInFront(FBunch* b1, FBunch* b2)
for (int i = b1->startline; i <= b1->endline; i++)
{
endang = wall[wall[i].point2].clipangle - b1->startangle;
if (endang > anglecheck)
if (endang.asbam() > anglecheck.asbam())
{
// found a line
int ret = WallInFront(b2->startline, i);
@ -344,7 +343,7 @@ int BunchDrawer::BunchInFront(FBunch* b1, FBunch* b2)
}
}
}
else if (b1->startangle - b2->startangle < b2->endangle - b2->startangle)
else if (b1->startangle.asbam() - b2->startangle.asbam() < b2->endangle.asbam() - b2->startangle.asbam())
{
// we have an overlap at b1->startangle
anglecheck = b1->startangle - b2->startangle;
@ -353,7 +352,7 @@ int BunchDrawer::BunchInFront(FBunch* b1, FBunch* b2)
for (int i = b2->startline; i <= b2->endline; i++)
{
endang = wall[wall[i].point2].clipangle - b2->startangle;
if (endang > anglecheck)
if (endang.asbam() > anglecheck.asbam())
{
// found a line
int ret = WallInFront(i, b1->startline);
@ -434,7 +433,7 @@ void BunchDrawer::ProcessSector(int sectnum)
auto sect = &sector[sectnum];
bool inbunch;
angle_t startangle;
binangle startangle;
SetupFlat.Clock();
HWFlat flat;
@ -452,10 +451,10 @@ void BunchDrawer::ProcessSector(int sectnum)
DVector2 start = { WallStartX(thiswall), WallStartY(thiswall) };
DVector2 end = { WallStartX(thiswall->point2), WallStartY(thiswall->point2) };
#endif
angle_t ang1 = thiswall->clipangle;
angle_t ang2 = wall[thiswall->point2].clipangle;
binangle ang1 = thiswall->clipangle;
binangle ang2 = wall[thiswall->point2].clipangle;
if (ang1 - ang2 < ANGLE_180)
if (ang1.asbam() - ang2.asbam() < ANGLE_180)
{
// Backside
inbunch = false;
@ -465,7 +464,7 @@ void BunchDrawer::ProcessSector(int sectnum)
// is it visible?
inbunch = false;
}
else if (!inbunch || ang2 - startangle >= ANGLE_180)
else if (!inbunch || ang2.asbam() - startangle.asbam() >= ANGLE_180)
{
// don't let a bunch span more than 180° to avoid problems.
// This limitation ensures that the combined range of 2

View file

@ -11,8 +11,8 @@ struct FBunch
int sectnum;
int startline;
int endline;
angle_t startangle; // in pseudo angles for the clipper
angle_t endangle;
binangle startangle; // in pseudo angles for the clipper
binangle endangle;
};
class BunchDrawer
@ -37,8 +37,8 @@ private:
void StartScene();
void StartBunch(int sectnum, int linenum, angle_t startan, angle_t endan);
void AddLineToBunch(int line, int newan);
void StartBunch(int sectnum, int linenum, binangle startan, binangle endan);
void AddLineToBunch(int line, binangle newan);
void DeleteBunch(int index);
bool CheckClip(walltype* wal);
int ClipLine(int line);

View file

@ -37,6 +37,7 @@
#include "hw_clipper.h"
#include "basics.h"
#include "build.h"
unsigned Clipper::starttime;
@ -78,7 +79,7 @@ void Clipper::Clear()
ClipNode *temp;
blocked = false;
while (node != NULL)
while (node != nullptr)
{
temp = node;
node = node->next;
@ -86,15 +87,15 @@ void Clipper::Clear()
}
node = silhouette;
while (node != NULL)
while (node != nullptr)
{
temp = node;
node = node->next;
Free(temp);
}
cliphead = NULL;
silhouette = NULL;
cliphead = nullptr;
silhouette = nullptr;
starttime++;
}
@ -107,14 +108,14 @@ void Clipper::Clear()
void Clipper::SetSilhouette()
{
ClipNode *node = cliphead;
ClipNode *last = NULL;
ClipNode *last = nullptr;
while (node != NULL)
while (node != nullptr)
{
ClipNode *snode = NewRange(node->start, node->end);
if (silhouette == NULL) silhouette = snode;
if (silhouette == nullptr) silhouette = snode;
snode->prev = last;
if (last != NULL) last->next = snode;
if (last != nullptr) last->next = snode;
last = snode;
node = node->next;
}
@ -126,16 +127,16 @@ void Clipper::SetSilhouette()
//
//-----------------------------------------------------------------------------
bool Clipper::IsRangeVisible(angle_t startAngle, angle_t endAngle)
bool Clipper::IsRangeVisible(binangle startAngle, binangle endAngle)
{
ClipNode *ci;
ci = cliphead;
if (endAngle==0 && ci && ci->start==0) return false;
if (endAngle.asbam()==0 && ci && ci->start==0) return false;
while (ci != NULL && ci->start < endAngle)
while (ci != nullptr && ci->start < endAngle.asbam())
{
if (startAngle >= ci->start && endAngle <= ci->end)
if (startAngle.asbam() >= ci->start && endAngle.asbam() <= ci->end)
{
return false;
}
@ -151,15 +152,16 @@ bool Clipper::IsRangeVisible(angle_t startAngle, angle_t endAngle)
//
//-----------------------------------------------------------------------------
void Clipper::AddClipRange(angle_t start, angle_t end)
void Clipper::AddClipRange(binangle start_, binangle end_)
{
auto start = start_.asbam(), end = end_.asbam();
ClipNode *node, *temp, *prevNode;
if (cliphead)
{
//check to see if range contains any old ranges
node = cliphead;
while (node != NULL && node->start < end)
while (node != nullptr && node->start < end)
{
if (node->start >= start && node->end <= end)
{
@ -179,7 +181,7 @@ void Clipper::AddClipRange(angle_t start, angle_t end)
//check to see if range overlaps a range (or possibly 2)
node = cliphead;
while (node != NULL && node->start <= end)
while (node != nullptr && node->start <= end)
{
if (node->end >= start)
{
@ -210,17 +212,17 @@ void Clipper::AddClipRange(angle_t start, angle_t end)
//just add range
node = cliphead;
prevNode = NULL;
prevNode = nullptr;
temp = NewRange(start, end);
while (node != NULL && node->start < end)
while (node != nullptr && node->start < end)
{
prevNode = node;
node = node->next;
}
temp->next = node;
if (node == NULL)
if (node == nullptr)
{
temp->prev = prevNode;
if (prevNode) prevNode->next = temp;
@ -256,24 +258,25 @@ void Clipper::AddClipRange(angle_t start, angle_t end)
//
//-----------------------------------------------------------------------------
void Clipper::RemoveClipRange(angle_t start, angle_t end)
void Clipper::RemoveClipRange(binangle start_, binangle end_)
{
auto start = start_.asbam(), end = end_.asbam();
ClipNode *node;
if (silhouette)
{
node = silhouette;
while (node != NULL && node->end <= start)
while (node != nullptr && node->end <= start)
{
node = node->next;
}
if (node != NULL && node->start <= start)
if (node != nullptr && node->start <= start)
{
if (node->end >= end) return;
start = node->end;
node = node->next;
}
while (node != NULL && node->start < end)
while (node != nullptr && node->start < end)
{
DoRemoveClipRange(start, node->start);
start = node->end;
@ -298,7 +301,7 @@ void Clipper::DoRemoveClipRange(angle_t start, angle_t end)
{
//check to see if range contains any old ranges
node = cliphead;
while (node != NULL && node->start < end)
while (node != nullptr && node->start < end)
{
if (node->start >= start && node->end <= end)
{
@ -314,7 +317,7 @@ void Clipper::DoRemoveClipRange(angle_t start, angle_t end)
//check to see if range overlaps a range (or possibly 2)
node = cliphead;
while (node != NULL)
while (node != nullptr)
{
if (node->start >= start && node->start <= end)
{
@ -341,25 +344,6 @@ void Clipper::DoRemoveClipRange(angle_t start, angle_t end)
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
angle_t Clipper::AngleToPseudo(angle_t ang)
{
double vecx = cos(ang * M_PI / ANGLE_180);
double vecy = sin(ang * M_PI / ANGLE_180);
double result = vecy / (fabs(vecx) + fabs(vecy));
if (vecx < 0)
{
result = 2.f - result;
}
return xs_Fix<30>::ToFix(result);
}
//-----------------------------------------------------------------------------
//
// ! Returns the pseudoangle between the line p1 to (infinity, p1.y) and the
@ -373,24 +357,27 @@ angle_t Clipper::AngleToPseudo(angle_t ang)
//
//-----------------------------------------------------------------------------
angle_t Clipper::PointToPseudoAngle(double x, double y)
binangle Clipper::PointToAngle(const vec2_t& pos)
{
double vecx = x - viewpoint.X;
double vecy = y - viewpoint.Y;
vec2_t vec = pos - viewpoint;
#if 0
if (vecx == 0 && vecy == 0)
if (vec.x == 0 && vec.y == 0)
{
return 0;
}
else
{
double result = vecy / (fabs(vecx) + fabs(vecy));
if (vecx < 0)
double result = vec.y / double(abs(vec.x) + fabs(vec.y));
if (vec.x < 0)
{
result = 2. - result;
}
return xs_Fix<30>::ToFix(result);
return bamang(xs_Fix<30>::ToFix(result));
}
#else
return q16ang(gethiq16angle(vec.x, vec.y));
#endif
}

View file

@ -5,6 +5,8 @@
#include "memarena.h"
#include "basics.h"
#include "vectors.h"
#include "binaryangle.h"
#include "intvec.h"
class ClipNode
{
@ -29,21 +31,20 @@ class Clipper
ClipNode * clipnodes = nullptr;
ClipNode * cliphead = nullptr;
ClipNode * silhouette = nullptr; // will be preserved even when RemoveClipRange is called
DVector2 viewpoint;
vec2_t viewpoint;
bool blocked = false;
bool IsRangeVisible(angle_t startangle, angle_t endangle);
bool IsRangeVisible(binangle startangle, binangle endangle);
void RemoveRange(ClipNode * cn);
void AddClipRange(angle_t startangle, angle_t endangle);
void RemoveClipRange(angle_t startangle, angle_t endangle);
void DoRemoveClipRange(angle_t start, angle_t end);
void AddClipRange(binangle startangle, binangle endangle);
void RemoveClipRange(binangle startangle, binangle endangle);
public:
Clipper();
void Clear();
static angle_t AngleToPseudo(angle_t ang);
static binangle AngleToPseudo(binangle ang);
void Free(ClipNode *node)
{
@ -51,6 +52,7 @@ public:
freelist = node;
}
private:
ClipNode * GetNew()
{
if (freelist)
@ -71,31 +73,35 @@ public:
c->next = c->prev = NULL;
return c;
}
void DoRemoveClipRange(angle_t start, angle_t end);
public:
void SetViewpoint(const DVector2 &vp)
void SetViewpoint(const vec2_t &vp)
{
viewpoint = vp;
}
void SetSilhouette();
bool SafeCheckRange(angle_t startAngle, angle_t endAngle)
bool SafeCheckRange(binangle startAngle, binangle endAngle)
{
if(startAngle > endAngle)
if(startAngle.asbam() > endAngle.asbam())
{
return (IsRangeVisible(startAngle, ANGLE_MAX) || IsRangeVisible(0, endAngle));
return (IsRangeVisible(startAngle, bamang(ANGLE_MAX)) || IsRangeVisible(bamang(0), endAngle));
}
return IsRangeVisible(startAngle, endAngle);
}
void SafeAddClipRange(angle_t startangle, angle_t endangle)
void SafeAddClipRange(binangle startangle, binangle endangle)
{
if(startangle > endangle)
if(startangle.asbam() > endangle.asbam())
{
// The range has to added in two parts.
AddClipRange(startangle, ANGLE_MAX);
AddClipRange(0, endangle);
AddClipRange(startangle, bamang(ANGLE_MAX));
AddClipRange(bamang(0), endangle);
}
else
{
@ -104,26 +110,20 @@ public:
}
}
void SafeAddClipRange(const DVector2& v1, const DVector2& v2)
void SafeAddClipRange(const vec2_t& v1, const vec2_t& v2)
{
angle_t a2 = PointToPseudoAngle(v1.X, v1.Y);
angle_t a1 = PointToPseudoAngle(v2.X, v2.Y);
binangle a2 = PointToAngle(v1);
binangle a1 = PointToAngle(v2);
SafeAddClipRange(a1,a2);
}
void SafeAddClipRangeRealAngles(angle_t startangle, angle_t endangle)
void SafeRemoveClipRange(binangle startangle, binangle endangle)
{
SafeAddClipRange(AngleToPseudo(startangle), AngleToPseudo(endangle));
}
void SafeRemoveClipRange(angle_t startangle, angle_t endangle)
{
if(startangle > endangle)
if(startangle.asbam() > endangle.asbam())
{
// The range has to added in two parts.
RemoveClipRange(startangle, ANGLE_MAX);
RemoveClipRange(0, endangle);
RemoveClipRange(startangle, bamang(ANGLE_MAX));
RemoveClipRange(bamang(0), endangle);
}
else
{
@ -132,11 +132,6 @@ public:
}
}
void SafeRemoveClipRangeRealAngles(angle_t startangle, angle_t endangle)
{
SafeRemoveClipRange(AngleToPseudo(startangle), AngleToPseudo(endangle));
}
void SetBlocked(bool on)
{
blocked = on;
@ -147,12 +142,7 @@ public:
return blocked;
}
angle_t PointToPseudoAngle(double x, double y);
inline angle_t GetClipAngle(const DVector2& v)
{
return PointToPseudoAngle(v.X, v.Y);
}
binangle PointToAngle(const vec2_t& point);
};

View file

@ -117,7 +117,7 @@ HWDrawInfo *HWDrawInfo::StartDrawInfo(HWDrawInfo *parent, FRenderViewpoint &pare
static Clipper staticClipper; // Since all scenes are processed sequentially we only need one clipper.
static HWDrawInfo * gl_drawinfo; // This is a linked list of all active DrawInfos and needed to free the memory arena after the last one goes out of scope.
void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uniforms)
void HWDrawInfo::StartScene(FRenderViewpoint& parentvp, HWViewpointUniforms* uniforms)
{
staticClipper.Clear();
mClipper = &staticClipper;
@ -143,7 +143,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni
VPUniforms.mClipLine.X = -10000000.0f;
VPUniforms.mShadowmapFilter = gl_shadowmap_filter;
}
mClipper->SetViewpoint(Viewpoint.Pos.XY());
mClipper->SetViewpoint({viewx, viewy});
ClearBuffers();
@ -294,7 +294,7 @@ void HWDrawInfo::CreateScene()
const auto& vp = Viewpoint;
angle_t a1 = FrustumAngle();
mClipper->SafeAddClipRangeRealAngles(vp.RotAngle + a1, vp.RotAngle - a1);
mClipper->SafeAddClipRange(bamang(vp.RotAngle + a1), bamang(vp.RotAngle - a1));
// reset the portal manager
portalState.StartFrame();

View file

@ -404,21 +404,21 @@ void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper)
clipper->Clear();
// Set the clipper to the minimal visible area
clipper->SafeAddClipRange(0, 0xffffffff);
clipper->SafeAddClipRange(bamang(0), bamang(0xffffffff));
for (unsigned int i = 0; i < lines.Size(); i++)
{
DAngle startAngle = (DVector2(lines[i].glseg.x2, lines[i].glseg.y2) - outer_di->Viewpoint.Pos).Angle() + angleOffset;
DAngle endAngle = (DVector2(lines[i].glseg.x1, lines[i].glseg.y1) - outer_di->Viewpoint.Pos).Angle() + angleOffset;
binangle startang = lines[i].seg->clipangle;
binangle endang = wall[lines[i].seg->point2].clipangle;
if (deltaangle(endAngle, startAngle) < 0)
if (endang.asbam() - startang.asbam() >= ANGLE_180)
{
clipper->SafeRemoveClipRangeRealAngles(startAngle.BAMs(), endAngle.BAMs());
clipper->SafeRemoveClipRange(startang, endang);
}
}
// and finally clip it to the visible area
angle_t a1 = di->FrustumAngle();
if (a1 < ANGLE_180) clipper->SafeAddClipRangeRealAngles(di->Viewpoint.HWAngles.Yaw.BAMs() + a1, di->Viewpoint.HWAngles.Yaw.BAMs() - a1);
if (a1 < ANGLE_180) clipper->SafeAddClipRange(bamang(di->Viewpoint.RotAngle + a1), bamang(di->Viewpoint.RotAngle - a1));
// lock the parts that have just been clipped out.
//clipper->SetSilhouette();
@ -595,9 +595,9 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe
clipper->Clear();
angle_t af = di->FrustumAngle();
if (af < ANGLE_180) clipper->SafeAddClipRangeRealAngles(vp.HWAngles.Yaw.BAMs() + af, vp.HWAngles.Yaw.BAMs() - af);
if (af < ANGLE_180) clipper->SafeAddClipRange(bamang(vp.RotAngle + af), bamang(vp.RotAngle - af));
clipper->SafeAddClipRange(pos1, pos2);
clipper->SafeAddClipRange(line->clipangle, wall[line->point2].clipangle);
return true;
}