raze/source/core/rendering/scene/hw_clipper.h
Christoph Oelckers be08a2f800 - clipper rework
* let the clipper work on relative angles to simplify the math.
* properly initialize the initial visible range and preserve it for multiple invocations.
* track the maximum visible angular range per sector. While possibly not sufficient to handle every edge case imaginable it has low overhead and is still useful to eliminate obvious cases that do not need more complex checks. It is enough to fix the blue door in Duke E3L4.
* removed unused elements of the clipper.
2021-04-24 12:08:38 +02:00

115 lines
2 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;
int start, end;
bool operator== (const ClipNode &other)
{
return other.start == start && other.end == end;
}
};
class Clipper
{
FMemArena nodearena;
ClipNode * freelist = nullptr;
ClipNode * clipnodes = nullptr;
ClipNode * cliphead = nullptr;
vec2_t viewpoint;
void RemoveRange(ClipNode* cn);
binangle visibleStart, visibleEnd;
public:
bool IsRangeVisible(int startangle, int endangle);
void AddClipRange(int startangle, int endangle);
void RemoveClipRange(int startangle, int endangle);
public:
void Clear(binangle rangestart);
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(int start, int end)
{
ClipNode * c = GetNew();
c->start = start;
c->end = end;
c->next = c->prev = NULL;
return c;
}
public:
void SetViewpoint(const vec2_t &vp)
{
viewpoint = vp;
}
void SetVisibleRange(angle_t a1, angle_t a2)
{
if (a2 != 0xffffffff)
{
visibleStart = bamang(a1 - a2);
visibleEnd = bamang(a1 + a2);
}
else visibleStart = visibleEnd = bamang(0);
}
void RestrictVisibleRange(binangle a1, binangle a2)
{
if (visibleStart == visibleEnd)
{
visibleStart = a1;
visibleEnd = a2;
}
else
{
if (a1.asbam() - visibleStart.asbam() < visibleEnd.asbam() - visibleStart.asbam()) visibleStart = a1;
if (a2.asbam() - visibleStart.asbam() < visibleEnd.asbam() - visibleStart.asbam()) visibleStart = a2;
}
}
void DumpClipper();
binangle PointToAngle(const vec2_t& pos)
{
vec2_t vec = pos - viewpoint;
return bvectangbam(vec.x, vec.y);
}
};
#endif