raze/source/core/rendering/scene/hw_clipper.h
2021-04-10 10:56:11 +02:00

173 lines
3.1 KiB
C++

#ifndef __GL_CLIPPER
#define __GL_CLIPPER
#include "xs_Float.h"
#include "memarena.h"
#include "basics.h"
#include "vectors.h"
#include "binaryangle.h"
#include "intvec.h"
class ClipNode
{
friend class Clipper;
ClipNode *prev, *next;
angle_t start, end;
bool operator== (const ClipNode &other)
{
return other.start == start && other.end == end;
}
};
class Clipper
{
static unsigned starttime;
FMemArena nodearena;
ClipNode * freelist = nullptr;
ClipNode * clipnodes = nullptr;
ClipNode * cliphead = nullptr;
ClipNode * silhouette = nullptr; // will be preserved even when RemoveClipRange is called
vec2_t viewpoint;
bool blocked = false;
bool IsRangeVisible(binangle startangle, binangle endangle);
void RemoveRange(ClipNode * cn);
void AddClipRange(binangle startangle, binangle endangle);
void RemoveClipRange(binangle startangle, binangle endangle);
public:
Clipper();
void Clear();
static binangle AngleToPseudo(binangle ang);
void Free(ClipNode *node)
{
node->next = freelist;
freelist = node;
}
private:
ClipNode * GetNew()
{
if (freelist)
{
ClipNode * p = freelist;
freelist = p->next;
return p;
}
else return (ClipNode*)nodearena.Alloc(sizeof(ClipNode));
}
ClipNode * NewRange(angle_t start, angle_t end)
{
ClipNode * c = GetNew();
c->start = start;
c->end = end;
c->next = c->prev = NULL;
return c;
}
void DoRemoveClipRange(angle_t start, angle_t end);
public:
void SetViewpoint(const vec2_t &vp)
{
viewpoint = vp;
}
void SetSilhouette();
bool SafeCheckRange(binangle startAngle, binangle endAngle)
{
if(startAngle.asbam() > endAngle.asbam())
{
return (IsRangeVisible(startAngle, bamang(ANGLE_MAX)) || IsRangeVisible(bamang(0), endAngle));
}
return IsRangeVisible(startAngle, endAngle);
}
void SafeAddClipRange(binangle startangle, binangle endangle)
{
if(startangle.asbam() > endangle.asbam())
{
// The range has to added in two parts.
AddClipRange(startangle, bamang(ANGLE_MAX));
AddClipRange(bamang(0), endangle);
}
else
{
// Add the range as usual.
AddClipRange(startangle, endangle);
}
}
void SafeAddClipRange(const vec2_t& v1, const vec2_t& v2)
{
binangle a2 = PointToAngle(v1);
binangle a1 = PointToAngle(v2);
SafeAddClipRange(a1,a2);
}
void SafeRemoveClipRange(binangle startangle, binangle endangle)
{
if(startangle.asbam() > endangle.asbam())
{
// The range has to added in two parts.
RemoveClipRange(startangle, bamang(ANGLE_MAX));
RemoveClipRange(bamang(0), endangle);
}
else
{
// Add the range as usual.
RemoveClipRange(startangle, endangle);
}
}
void SetBlocked(bool on)
{
blocked = on;
}
bool IsBlocked() const
{
return blocked;
}
void DumpClipper();
binangle PointToAngle(const vec2_t& pos)
{
vec2_t vec = pos - viewpoint;
#if 0
if (vec.x == 0 && vec.y == 0)
{
return bamang(0);
}
else
{
double result = vec.y / double(abs(vec.x) + fabs(vec.y));
if (vec.x < 0)
{
result = 2. - result;
}
return bamang(xs_Fix<30>::ToFix(result));
}
#else
return bvectangbam(vec.x, vec.y);
#endif
}
};
#endif