mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-01 16:41:09 +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();
|
ClearBuffers();
|
||||||
SetSceneViewport();
|
SetSceneViewport();
|
||||||
SetupPerspectiveMatrix();
|
SetupPerspectiveMatrix();
|
||||||
MainPortal.SetViewpoint(WorldToClip, GetNextStencilValue());
|
MainPortal.SetViewpoint(WorldToClip, Vec4f(0.0f), GetNextStencilValue());
|
||||||
MainPortal.Render(0);
|
MainPortal.Render(0);
|
||||||
Skydome.Render(WorldToClip);
|
Skydome.Render(WorldToClip);
|
||||||
MainPortal.RenderTranslucent(0);
|
MainPortal.RenderTranslucent(0);
|
||||||
|
|
|
@ -28,11 +28,12 @@
|
||||||
#include "r_poly_cull.h"
|
#include "r_poly_cull.h"
|
||||||
#include "r_poly.h"
|
#include "r_poly.h"
|
||||||
|
|
||||||
void PolyCull::CullScene(const TriMatrix &worldToClip)
|
void PolyCull::CullScene(const TriMatrix &worldToClip, const Vec4f &portalClipPlane)
|
||||||
{
|
{
|
||||||
ClearSolidSegments();
|
ClearSolidSegments();
|
||||||
PvsSectors.clear();
|
PvsSectors.clear();
|
||||||
frustumPlanes = FrustumPlanes(worldToClip);
|
frustumPlanes = FrustumPlanes(worldToClip);
|
||||||
|
PortalClipPlane = portalClipPlane;
|
||||||
|
|
||||||
// Cull front to back
|
// Cull front to back
|
||||||
MaxCeilingHeight = 0.0;
|
MaxCeilingHeight = 0.0;
|
||||||
|
@ -174,6 +175,11 @@ bool PolyCull::CheckBBox(float *bspcoord)
|
||||||
if (result == IntersectionTest::outside)
|
if (result == IntersectionTest::outside)
|
||||||
return false;
|
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:
|
// Occlusion test using solid segments:
|
||||||
|
|
||||||
static const int lines[4][4] =
|
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;
|
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:
|
// Transform to 2D view space:
|
||||||
x1 = x1 - ViewPos.X;
|
x1 = x1 - ViewPos.X;
|
||||||
y1 = y1 - ViewPos.Y;
|
y1 = y1 - ViewPos.Y;
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
class PolyCull
|
class PolyCull
|
||||||
{
|
{
|
||||||
public:
|
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;
|
bool GetSegmentRangeForLine(double x1, double y1, double x2, double y2, int &sx1, int &sx2) const;
|
||||||
void MarkSegmentCulled(int x1, int x2);
|
void MarkSegmentCulled(int x1, int x2);
|
||||||
|
@ -59,4 +59,5 @@ private:
|
||||||
const int SolidCullScale = 3000;
|
const int SolidCullScale = 3000;
|
||||||
|
|
||||||
FrustumPlanes frustumPlanes;
|
FrustumPlanes frustumPlanes;
|
||||||
|
Vec4f PortalClipPlane;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
class Vec3f;
|
||||||
|
|
||||||
class Vec4f
|
class Vec4f
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -33,6 +35,7 @@ public:
|
||||||
Vec4f(const Vec4f &) = default;
|
Vec4f(const Vec4f &) = default;
|
||||||
Vec4f(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) { }
|
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(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 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; }
|
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;
|
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
|
class Vec3f
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -75,6 +81,9 @@ public:
|
||||||
float x, y, z;
|
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); }
|
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 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;
|
typedef TriMatrix Mat4f;
|
||||||
|
|
||||||
class AxisAlignedBoundingBox
|
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;
|
WorldToClip = worldToClip;
|
||||||
StencilValue = stencilValue;
|
StencilValue = stencilValue;
|
||||||
|
PortalPlane = portalPlane;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPolyPortal::Render(int portalDepth)
|
void RenderPolyPortal::Render(int portalDepth)
|
||||||
{
|
{
|
||||||
ClearBuffers();
|
ClearBuffers();
|
||||||
Cull.CullScene(WorldToClip);
|
Cull.CullScene(WorldToClip, PortalPlane);
|
||||||
RenderSectors();
|
RenderSectors();
|
||||||
RenderPortals(portalDepth);
|
RenderPortals(portalDepth);
|
||||||
}
|
}
|
||||||
|
@ -340,7 +341,7 @@ void PolyDrawSectorPortal::Render(int portalDepth)
|
||||||
TriMatrix::translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z);
|
TriMatrix::translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z);
|
||||||
TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView;
|
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);
|
RenderPortal.Render(portalDepth);
|
||||||
|
|
||||||
RestoreGlobals();
|
RestoreGlobals();
|
||||||
|
@ -440,7 +441,14 @@ void PolyDrawLinePortal::Render(int portalDepth)
|
||||||
TriMatrix::translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z);
|
TriMatrix::translate((float)-ViewPos.X, (float)-ViewPos.Y, (float)-ViewPos.Z);
|
||||||
TriMatrix worldToClip = TriMatrix::perspective(fovy, ratio, 5.0f, 65535.0f) * worldToView;
|
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);
|
RenderPortal.Render(portalDepth);
|
||||||
|
|
||||||
RestoreGlobals();
|
RestoreGlobals();
|
||||||
|
|
|
@ -83,7 +83,7 @@ class RenderPolyPortal
|
||||||
public:
|
public:
|
||||||
RenderPolyPortal();
|
RenderPolyPortal();
|
||||||
~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 Render(int portalDepth);
|
||||||
void RenderTranslucent(int portalDepth);
|
void RenderTranslucent(int portalDepth);
|
||||||
|
|
||||||
|
@ -99,6 +99,7 @@ private:
|
||||||
SpriteRange GetSpritesForSector(sector_t *sector);
|
SpriteRange GetSpritesForSector(sector_t *sector);
|
||||||
|
|
||||||
TriMatrix WorldToClip;
|
TriMatrix WorldToClip;
|
||||||
|
Vec4f PortalPlane;
|
||||||
uint32_t StencilValue = 0;
|
uint32_t StencilValue = 0;
|
||||||
PolyCull Cull;
|
PolyCull Cull;
|
||||||
uint32_t NextSubsectorDepth = 0;
|
uint32_t NextSubsectorDepth = 0;
|
||||||
|
|
Loading…
Reference in a new issue