mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-25 21:41:30 +00:00
Add portal plane clipping
This commit is contained in:
parent
70181f4146
commit
8bbb63e913
6 changed files with 39 additions and 8 deletions
|
@ -44,7 +44,7 @@ void RenderPolyScene::Render()
|
|||
ClearBuffers();
|
||||
SetSceneViewport();
|
||||
SetupPerspectiveMatrix();
|
||||
MainPortal.SetViewpoint(WorldToClip, GetNextStencilValue());
|
||||
MainPortal.SetViewpoint(WorldToClip, Vec4f(0.0f), GetNextStencilValue());
|
||||
MainPortal.Render(0);
|
||||
Skydome.Render(WorldToClip);
|
||||
MainPortal.RenderTranslucent(0);
|
||||
|
|
|
@ -28,11 +28,12 @@
|
|||
#include "r_poly_cull.h"
|
||||
#include "r_poly.h"
|
||||
|
||||
void PolyCull::CullScene(const TriMatrix &worldToClip)
|
||||
void PolyCull::CullScene(const TriMatrix &worldToClip, const Vec4f &portalClipPlane)
|
||||
{
|
||||
ClearSolidSegments();
|
||||
PvsSectors.clear();
|
||||
frustumPlanes = FrustumPlanes(worldToClip);
|
||||
PortalClipPlane = portalClipPlane;
|
||||
|
||||
// Cull front to back
|
||||
MaxCeilingHeight = 0.0;
|
||||
|
@ -174,6 +175,11 @@ bool PolyCull::CheckBBox(float *bspcoord)
|
|||
if (result == IntersectionTest::outside)
|
||||
return false;
|
||||
|
||||
// Skip if its in front of the portal:
|
||||
|
||||
if (PortalClipPlane != Vec4f(0.0f) && IntersectionTest::plane_aabb(PortalClipPlane, aabb) == IntersectionTest::outside)
|
||||
return false;
|
||||
|
||||
// Occlusion test using solid segments:
|
||||
|
||||
static const int lines[4][4] =
|
||||
|
@ -219,6 +225,10 @@ bool PolyCull::GetSegmentRangeForLine(double x1, double y1, double x2, double y2
|
|||
{
|
||||
double znear = 5.0;
|
||||
|
||||
// Cull if entirely behind the portal clip plane (tbd: should we clip the segment?)
|
||||
if (Vec4f::dot(PortalClipPlane, Vec4f((float)x1, (float)y1, 0.0f, 1.0f)) < 0.0f && Vec4f::dot(PortalClipPlane, Vec4f((float)x2, (float)y2, 0.0f, 1.0f)) < 0.0f)
|
||||
return false;
|
||||
|
||||
// Transform to 2D view space:
|
||||
x1 = x1 - ViewPos.X;
|
||||
y1 = y1 - ViewPos.Y;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
class PolyCull
|
||||
{
|
||||
public:
|
||||
void CullScene(const TriMatrix &worldToClip);
|
||||
void CullScene(const TriMatrix &worldToClip, const Vec4f &portalClipPlane);
|
||||
|
||||
bool GetSegmentRangeForLine(double x1, double y1, double x2, double y2, int &sx1, int &sx2) const;
|
||||
void MarkSegmentCulled(int x1, int x2);
|
||||
|
@ -59,4 +59,5 @@ private:
|
|||
const int SolidCullScale = 3000;
|
||||
|
||||
FrustumPlanes frustumPlanes;
|
||||
Vec4f PortalClipPlane;
|
||||
};
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
class Vec3f;
|
||||
|
||||
class Vec4f
|
||||
{
|
||||
public:
|
||||
|
@ -33,6 +35,7 @@ public:
|
|||
Vec4f(const Vec4f &) = default;
|
||||
Vec4f(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { }
|
||||
Vec4f(float v) : x(v), y(v), z(v), w(v) { }
|
||||
Vec4f(const Vec3f &xyz, float w);
|
||||
|
||||
static float dot(const Vec4f &a, const Vec4f &b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; }
|
||||
static float dot3(const Vec4f &a, const Vec4f &b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
|
||||
|
@ -51,6 +54,9 @@ public:
|
|||
float x, y, z, w;
|
||||
};
|
||||
|
||||
inline bool operator==(const Vec4f &a, const Vec4f &b) { return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; }
|
||||
inline bool operator!=(const Vec4f &a, const Vec4f &b) { return a.x != b.x || a.y != b.y || a.z != b.z || a.w == b.w; }
|
||||
|
||||
class Vec3f
|
||||
{
|
||||
public:
|
||||
|
@ -75,6 +81,9 @@ public:
|
|||
float x, y, z;
|
||||
};
|
||||
|
||||
inline bool operator==(const Vec3f &a, const Vec3f &b) { return a.x == b.x && a.y == b.y && a.z == b.z; }
|
||||
inline bool operator!=(const Vec3f &a, const Vec3f &b) { return a.x != b.x || a.y != b.y || a.z != b.z; }
|
||||
|
||||
inline Vec3f operator+(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x + b.x, a.y + b.y, a.z + b.z); }
|
||||
inline Vec3f operator-(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x - b.x, a.y - b.y, a.z - b.z); }
|
||||
inline Vec3f operator*(const Vec3f &a, const Vec3f &b) { return Vec3f(a.x * b.x, a.y * b.y, a.z * b.z); }
|
||||
|
@ -90,6 +99,8 @@ inline Vec3f operator-(float a, const Vec3f &b) { return Vec3f(a - b.x, a - b.y,
|
|||
inline Vec3f operator*(float a, const Vec3f &b) { return Vec3f(a * b.x, a * b.y, a * b.z); }
|
||||
inline Vec3f operator/(float a, const Vec3f &b) { return Vec3f(a / b.x, a / b.y, a / b.z); }
|
||||
|
||||
inline Vec4f::Vec4f(const Vec3f &xyz, float w) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) { }
|
||||
|
||||
typedef TriMatrix Mat4f;
|
||||
|
||||
class AxisAlignedBoundingBox
|
||||
|
|
|
@ -45,16 +45,17 @@ RenderPolyPortal::~RenderPolyPortal()
|
|||
{
|
||||
}
|
||||
|
||||
void RenderPolyPortal::SetViewpoint(const TriMatrix &worldToClip, uint32_t stencilValue)
|
||||
void RenderPolyPortal::SetViewpoint(const TriMatrix &worldToClip, const Vec4f &portalPlane, uint32_t stencilValue)
|
||||
{
|
||||
WorldToClip = worldToClip;
|
||||
StencilValue = stencilValue;
|
||||
PortalPlane = portalPlane;
|
||||
}
|
||||
|
||||
void RenderPolyPortal::Render(int portalDepth)
|
||||
{
|
||||
ClearBuffers();
|
||||
Cull.CullScene(WorldToClip);
|
||||
Cull.CullScene(WorldToClip, PortalPlane);
|
||||
RenderSectors();
|
||||
RenderPortals(portalDepth);
|
||||
}
|
||||
|
@ -340,7 +341,7 @@ void PolyDrawSectorPortal::Render(int portalDepth)
|
|||
TriMatrix::translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z);
|
||||
TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView;
|
||||
|
||||
RenderPortal.SetViewpoint(worldToClip, StencilValue);
|
||||
RenderPortal.SetViewpoint(worldToClip, Vec4f(0.0f), StencilValue);
|
||||
RenderPortal.Render(portalDepth);
|
||||
|
||||
RestoreGlobals();
|
||||
|
@ -440,7 +441,14 @@ void PolyDrawLinePortal::Render(int portalDepth)
|
|||
TriMatrix::translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z);
|
||||
TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView;
|
||||
|
||||
RenderPortal.SetViewpoint(worldToClip, StencilValue);
|
||||
// Calculate plane clipping
|
||||
DVector2 planePos = Portal->mDestination->v1->fPos();
|
||||
DVector2 planeNormal = (Portal->mDestination->v2->fPos() - Portal->mDestination->v1->fPos()).Rotated90CW();
|
||||
planeNormal.MakeUnit();
|
||||
double planeD = -(planeNormal | (planePos + planeNormal * 5.0));
|
||||
Vec4f portalPlane((float)planeNormal.X, (float)planeNormal.Y, 0.0f, (float)planeD);
|
||||
|
||||
RenderPortal.SetViewpoint(worldToClip, portalPlane, StencilValue);
|
||||
RenderPortal.Render(portalDepth);
|
||||
|
||||
RestoreGlobals();
|
||||
|
|
|
@ -83,7 +83,7 @@ class RenderPolyPortal
|
|||
public:
|
||||
RenderPolyPortal();
|
||||
~RenderPolyPortal();
|
||||
void SetViewpoint(const TriMatrix &worldToClip, uint32_t stencilValue);
|
||||
void SetViewpoint(const TriMatrix &worldToClip, const Vec4f &portalPlane, uint32_t stencilValue);
|
||||
void Render(int portalDepth);
|
||||
void RenderTranslucent(int portalDepth);
|
||||
|
||||
|
@ -99,6 +99,7 @@ private:
|
|||
SpriteRange GetSpritesForSector(sector_t *sector);
|
||||
|
||||
TriMatrix WorldToClip;
|
||||
Vec4f PortalPlane;
|
||||
uint32_t StencilValue = 0;
|
||||
PolyCull Cull;
|
||||
uint32_t NextSubsectorDepth = 0;
|
||||
|
|
Loading…
Reference in a new issue