Cull lines not visible from the camera
This commit is contained in:
parent
4de06b3175
commit
2121047fa2
4 changed files with 162 additions and 3 deletions
|
|
@ -35,6 +35,7 @@
|
|||
#include "hw_drawinfo.h"
|
||||
#include "hw_cvars.h"
|
||||
#include "hw_drawcontext.h"
|
||||
#include "hw_visibleset.h"
|
||||
#include "r_utility.h"
|
||||
#include "texturemanager.h"
|
||||
|
||||
|
|
@ -46,7 +47,7 @@ extern thread_local bool isWorkerThread;
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool hw_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsector)
|
||||
bool hw_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsector, CameraFrustum* frustum)
|
||||
{
|
||||
line_t *linedef = sidedef->linedef;
|
||||
double bs_floorheight1;
|
||||
|
|
@ -155,6 +156,25 @@ bool hw_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsecto
|
|||
return true;
|
||||
}
|
||||
|
||||
if (frustum)
|
||||
{
|
||||
// Is the line visible by the camera's clip frustum?
|
||||
DVector3 p0(linedef->v1->fX(), std::min(bs_ceilingheight1, fs_ceilingheight1), linedef->v1->fY());
|
||||
DVector3 p1(linedef->v2->fX(), std::min(bs_ceilingheight2, fs_ceilingheight2), linedef->v2->fY());
|
||||
DVector3 p2(linedef->v1->fX(), std::max(bs_floorheight1, fs_floorheight1), linedef->v1->fY());
|
||||
DVector3 p3(linedef->v2->fX(), std::max(bs_floorheight2, fs_floorheight2), linedef->v2->fY());
|
||||
DVector3 aabbMin = p0;
|
||||
DVector3 aabbMax = p0;
|
||||
aabbMin.X = std::min(aabbMin.X, p1.X); aabbMin.Y = std::min(aabbMin.Y, p1.Y); aabbMin.Z = std::min(aabbMin.Z, p1.Z);
|
||||
aabbMax.X = std::max(aabbMax.X, p1.X); aabbMax.Y = std::max(aabbMax.Y, p1.Y); aabbMax.Z = std::max(aabbMax.Z, p1.Z);
|
||||
aabbMin.X = std::min(aabbMin.X, p2.X); aabbMin.Y = std::min(aabbMin.Y, p2.Y); aabbMin.Z = std::min(aabbMin.Z, p2.Z);
|
||||
aabbMax.X = std::max(aabbMax.X, p2.X); aabbMax.Y = std::max(aabbMax.Y, p2.Y); aabbMax.Z = std::max(aabbMax.Z, p2.Z);
|
||||
aabbMin.X = std::min(aabbMin.X, p3.X); aabbMin.Y = std::min(aabbMin.Y, p3.Y); aabbMin.Z = std::min(aabbMin.Z, p3.Z);
|
||||
aabbMax.X = std::max(aabbMax.X, p3.X); aabbMax.Y = std::max(aabbMax.Y, p3.Y); aabbMax.Z = std::max(aabbMax.Z, p3.Z);
|
||||
if (!frustum->IsAABBVisible(aabbMin, aabbMax))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@ enum area_t : int
|
|||
area_default
|
||||
};
|
||||
|
||||
struct CameraFrustum;
|
||||
|
||||
// Global functions.
|
||||
bool hw_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsector);
|
||||
bool hw_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsector, CameraFrustum* frustum = nullptr);
|
||||
void hw_ClearFakeFlat(HWDrawContext* drawctx);
|
||||
sector_t * hw_FakeFlat(HWDrawContext* drawctx, sector_t * sec, area_t in_area, bool back, sector_t *localcopy = nullptr);
|
||||
area_t hw_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, sector_t *backsector);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ void HWVisibleSet::FindPVS(HWDrawInfo* di, int sliceIndex, int sliceCount)
|
|||
in_area = di->in_area;
|
||||
mClipPortal = di->mClipPortal;
|
||||
|
||||
VSMatrix m = di->VPUniforms.mProjectionMatrix;
|
||||
m.multMatrix(di->VPUniforms.mViewMatrix);
|
||||
ClipFrustum.Set(m);
|
||||
|
||||
CurrentMapSections = &di->CurrentMapSections;
|
||||
no_renderflags = TArrayView<uint8_t>(di->no_renderflags.data(), di->no_renderflags.size());
|
||||
|
||||
|
|
@ -381,7 +385,7 @@ void HWVisibleSet::AddLine(seg_t* seg, bool portalclip)
|
|||
|
||||
backsector = hw_FakeFlat(&drawctx, seg->backsector, in_area, true);
|
||||
|
||||
if (hw_CheckClip(seg->sidedef, currentsector, backsector))
|
||||
if (hw_CheckClip(seg->sidedef, currentsector, backsector, &ClipFrustum))
|
||||
{
|
||||
clipper.SafeAddClipRange(startAngle, endAngle);
|
||||
}
|
||||
|
|
@ -653,3 +657,91 @@ void HWVisibleSetThreads::WorkerMain(int sliceIndex)
|
|||
WorkCondvar.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CameraFrustum::Set(const VSMatrix& worldToProjection)
|
||||
{
|
||||
Planes[0] = LeftFrustum(worldToProjection);
|
||||
Planes[1] = TopFrustum(worldToProjection);
|
||||
Planes[2] = RightFrustum(worldToProjection);
|
||||
Planes[3] = BottomFrustum(worldToProjection);
|
||||
Planes[4] = NearFrustum(worldToProjection);
|
||||
Planes[5] = FarFrustum(worldToProjection);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
AbsPlaneNormals[i] = Planes[i].XYZ();
|
||||
AbsPlaneNormals[i].X = std::abs(AbsPlaneNormals[i].X);
|
||||
AbsPlaneNormals[i].Y = std::abs(AbsPlaneNormals[i].Y);
|
||||
AbsPlaneNormals[i].Z = std::abs(AbsPlaneNormals[i].Z);
|
||||
}
|
||||
}
|
||||
|
||||
DVector4 CameraFrustum::LeftFrustum(const VSMatrix& matrix)
|
||||
{
|
||||
return Normalize(DVector4(
|
||||
matrix.mMatrix[3 + 0 * 4] + matrix.mMatrix[0 + 0 * 4],
|
||||
matrix.mMatrix[3 + 1 * 4] + matrix.mMatrix[0 + 1 * 4],
|
||||
matrix.mMatrix[3 + 2 * 4] + matrix.mMatrix[0 + 2 * 4],
|
||||
matrix.mMatrix[3 + 3 * 4] + matrix.mMatrix[0 + 3 * 4]));
|
||||
}
|
||||
|
||||
DVector4 CameraFrustum::RightFrustum(const VSMatrix& matrix)
|
||||
{
|
||||
return Normalize(DVector4(
|
||||
matrix.mMatrix[3 + 0 * 4] - matrix.mMatrix[0 + 0 * 4],
|
||||
matrix.mMatrix[3 + 1 * 4] - matrix.mMatrix[0 + 1 * 4],
|
||||
matrix.mMatrix[3 + 2 * 4] - matrix.mMatrix[0 + 2 * 4],
|
||||
matrix.mMatrix[3 + 3 * 4] - matrix.mMatrix[0 + 3 * 4]));
|
||||
}
|
||||
|
||||
DVector4 CameraFrustum::TopFrustum(const VSMatrix& matrix)
|
||||
{
|
||||
return Normalize(DVector4(
|
||||
matrix.mMatrix[3 + 0 * 4] - matrix.mMatrix[1 + 0 * 4],
|
||||
matrix.mMatrix[3 + 1 * 4] - matrix.mMatrix[1 + 1 * 4],
|
||||
matrix.mMatrix[3 + 2 * 4] - matrix.mMatrix[1 + 2 * 4],
|
||||
matrix.mMatrix[3 + 3 * 4] - matrix.mMatrix[1 + 3 * 4]));
|
||||
}
|
||||
|
||||
DVector4 CameraFrustum::BottomFrustum(const VSMatrix& matrix)
|
||||
{
|
||||
return Normalize(DVector4(
|
||||
matrix.mMatrix[3 + 0 * 4] + matrix.mMatrix[1 + 0 * 4],
|
||||
matrix.mMatrix[3 + 1 * 4] + matrix.mMatrix[1 + 1 * 4],
|
||||
matrix.mMatrix[3 + 2 * 4] + matrix.mMatrix[1 + 2 * 4],
|
||||
matrix.mMatrix[3 + 3 * 4] + matrix.mMatrix[1 + 3 * 4]));
|
||||
}
|
||||
|
||||
DVector4 CameraFrustum::NearFrustum(const VSMatrix& matrix)
|
||||
{
|
||||
return Normalize(DVector4(
|
||||
matrix.mMatrix[3 + 0 * 4] + matrix.mMatrix[2 + 0 * 4],
|
||||
matrix.mMatrix[3 + 1 * 4] + matrix.mMatrix[2 + 1 * 4],
|
||||
matrix.mMatrix[3 + 2 * 4] + matrix.mMatrix[2 + 2 * 4],
|
||||
matrix.mMatrix[3 + 3 * 4] + matrix.mMatrix[2 + 3 * 4]));
|
||||
}
|
||||
|
||||
DVector4 CameraFrustum::FarFrustum(const VSMatrix& matrix)
|
||||
{
|
||||
return Normalize(DVector4(
|
||||
matrix.mMatrix[3 + 0 * 4] - matrix.mMatrix[2 + 0 * 4],
|
||||
matrix.mMatrix[3 + 1 * 4] - matrix.mMatrix[2 + 1 * 4],
|
||||
matrix.mMatrix[3 + 2 * 4] - matrix.mMatrix[2 + 2 * 4],
|
||||
matrix.mMatrix[3 + 3 * 4] - matrix.mMatrix[2 + 3 * 4]));
|
||||
}
|
||||
|
||||
DVector4 CameraFrustum::Normalize(DVector4 v)
|
||||
{
|
||||
double length = std::sqrt(v.XYZ() | v.XYZ());
|
||||
if (length > DBL_EPSILON)
|
||||
{
|
||||
double rcpLength = 1.0 / length;
|
||||
v.X *= rcpLength;
|
||||
v.Y *= rcpLength;
|
||||
v.Z *= rcpLength;
|
||||
v.W *= rcpLength;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,50 @@ class Clipper;
|
|||
class HWPortal;
|
||||
struct HWDrawInfo;
|
||||
|
||||
struct CameraFrustum
|
||||
{
|
||||
void Set(const VSMatrix& worldToProjection);
|
||||
|
||||
bool IsSphereVisible(const DVector3& point, double radius) const
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if ((Planes[i].XYZ() | point) < -radius)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsAABBVisible(const DVector3& aabbMin, const DVector3& aabbMax) const
|
||||
{
|
||||
DVector3 aabbCenter = (aabbMin + aabbMax) * 0.5;
|
||||
DVector3 aabbExtents = (aabbMax - aabbMin) * 0.5;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
double distance = Planes[i] | DVector4(aabbCenter, 1.0);
|
||||
double radius = AbsPlaneNormals[i] | aabbExtents;
|
||||
bool outside = distance < -radius;
|
||||
//bool inside = distance > radius;
|
||||
//bool intersect = distance > -radius && distance < radius;
|
||||
if (outside)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static DVector4 LeftFrustum(const VSMatrix& matrix);
|
||||
static DVector4 RightFrustum(const VSMatrix& matrix);
|
||||
static DVector4 TopFrustum(const VSMatrix& matrix);
|
||||
static DVector4 BottomFrustum(const VSMatrix& matrix);
|
||||
static DVector4 NearFrustum(const VSMatrix& matrix);
|
||||
static DVector4 FarFrustum(const VSMatrix& matrix);
|
||||
static DVector4 Normalize(DVector4 v);
|
||||
|
||||
DVector3 AbsPlaneNormals[6];
|
||||
DVector4 Planes[6];
|
||||
};
|
||||
|
||||
class HWVisibleSet
|
||||
{
|
||||
public:
|
||||
|
|
@ -77,6 +121,7 @@ private:
|
|||
HWDrawContext drawctx;
|
||||
FLevelLocals* Level = nullptr;
|
||||
FRenderViewpoint Viewpoint;
|
||||
CameraFrustum ClipFrustum;
|
||||
TArrayView<uint8_t> no_renderflags;
|
||||
BitArray* CurrentMapSections = nullptr;
|
||||
TArray<uint8_t> section_renderflags;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue