Skip to content

Commit 96917d5

Browse files
MathLib: fixed GetNearFarClipPlanes for orthographic matrices
Also, enable SetNearFarClipPlanes for both perspective and orthographics projections
1 parent d3c9457 commit 96917d5

File tree

2 files changed

+99
-42
lines changed

2 files changed

+99
-42
lines changed

Common/interface/BasicMath.hpp

Lines changed: 62 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,46 +1716,74 @@ template <class T> struct Matrix4x4
17161716
// See https://github.com/DiligentGraphics/DiligentCore/blob/master/doc/CoordinateSystem.md
17171717
void SetNearFarClipPlanes(T zNear, T zFar, bool NegativeOneToOneZ)
17181718
{
1719-
if (NegativeOneToOneZ)
1719+
if (_44 == 0)
17201720
{
1721-
// https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
1722-
// http://www.terathon.com/gdc07_lengyel.pdf
1723-
// Note that OpenGL uses right-handed coordinate system, where
1724-
// camera is looking in negative z direction:
1725-
// OO
1726-
// |__|<--------------------
1727-
// -z +z
1728-
// Consequently, OpenGL projection matrix given by these two
1729-
// references inverts z axis.
1730-
1731-
// We do not need to do this, because we use DX coordinate
1732-
// system for the camera space. Thus we need to invert the
1733-
// sign of the values in the third column in the matrix
1734-
// from the references:
1735-
1736-
_33 = -(-(zFar + zNear) / (zFar - zNear));
1737-
_43 = -2 * zNear * zFar / (zFar - zNear);
1738-
_34 = -(-1);
1721+
// Perspective projection
1722+
if (NegativeOneToOneZ)
1723+
{
1724+
// https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
1725+
// http://www.terathon.com/gdc07_lengyel.pdf
1726+
// Note that OpenGL uses right-handed coordinate system, where
1727+
// camera is looking in negative z direction:
1728+
// OO
1729+
// |__|<--------------------
1730+
// -z +z
1731+
// Consequently, OpenGL projection matrix given by these two
1732+
// references inverts z axis.
1733+
1734+
// We do not need to do this, because we use DX coordinate
1735+
// system for the camera space. Thus we need to invert the
1736+
// sign of the values in the third column in the matrix
1737+
// from the references:
1738+
1739+
_33 = -(-(zFar + zNear) / (zFar - zNear));
1740+
_43 = -2 * zNear * zFar / (zFar - zNear);
1741+
_34 = -(-1);
1742+
}
1743+
else
1744+
{
1745+
_33 = zFar / (zFar - zNear);
1746+
_43 = -zNear * zFar / (zFar - zNear);
1747+
_34 = 1;
1748+
}
17391749
}
17401750
else
17411751
{
1742-
_33 = zFar / (zFar - zNear);
1743-
_43 = -zNear * zFar / (zFar - zNear);
1744-
_34 = 1;
1752+
// Orthographic projection
1753+
_33 = (NegativeOneToOneZ ? 2 : 1) / (zFar - zNear);
1754+
_43 = (NegativeOneToOneZ ? zNear + zFar : zNear) / (zNear - zFar);
17451755
}
17461756
}
17471757

17481758
void GetNearFarClipPlanes(T& zNear, T& zFar, bool NegativeOneToOneZ) const
17491759
{
1750-
if (NegativeOneToOneZ)
1760+
if (_44 == 0)
17511761
{
1752-
zNear = _43 / (-1 - _33);
1753-
zFar = _43 / (+1 - _33);
1762+
// Perspective projection
1763+
if (NegativeOneToOneZ)
1764+
{
1765+
zNear = _43 / (-1 - _33);
1766+
zFar = _43 / (+1 - _33);
1767+
}
1768+
else
1769+
{
1770+
zNear = -_43 / _33;
1771+
zFar = _33 / (_33 - 1) * zNear;
1772+
}
17541773
}
17551774
else
17561775
{
1757-
zNear = -_43 / _33;
1758-
zFar = _33 / (_33 - 1) * zNear;
1776+
// Orthographic projection
1777+
if (NegativeOneToOneZ)
1778+
{
1779+
zNear = (-1 - _43) / _33;
1780+
zFar = (+1 - _43) / _33;
1781+
}
1782+
else
1783+
{
1784+
zNear = -_43 / _33;
1785+
zFar = (1 - _43) / _33;
1786+
}
17591787
}
17601788
}
17611789

@@ -1774,17 +1802,17 @@ template <class T> struct Matrix4x4
17741802

17751803
static Matrix4x4 OrthoOffCenter(T left, T right, T bottom, T top, T zNear, T zFar, bool NegativeOneToOneZ) // Left-handed ortho projection
17761804
{
1777-
auto _22 = (NegativeOneToOneZ ? 2 : 1) / (zFar - zNear);
1778-
auto _32 = (NegativeOneToOneZ ? zNear + zFar : zNear) / (zNear - zFar);
17791805
// clang-format off
1780-
return Matrix4x4
1806+
Matrix4x4 Proj
17811807
{
1782-
2 / (right - left), 0, 0, 0,
1783-
0, 2 / (top - bottom), 0, 0,
1784-
0, 0, _22, 0,
1785-
(left + right)/(left - right), (top + bottom) / (bottom - top), _32, 1
1808+
2 / (right - left), 0, 0, 0,
1809+
0, 2 / (top - bottom), 0, 0,
1810+
0, 0, 0, 0,
1811+
(left + right)/(left - right), (top + bottom) / (bottom - top), 0, 1
17861812
};
17871813
// clang-format on
1814+
Proj.SetNearFarClipPlanes(zNear, zFar, NegativeOneToOneZ);
1815+
return Proj;
17881816
}
17891817

17901818
static Matrix4x4 Ortho(T width, T height, T zNear, T zFar, bool NegativeOneToOneZ) // Left-handed ortho projection

Tests/DiligentCoreTest/src/Common/MathLibTest.cpp

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,37 +1074,66 @@ TEST(Common_BasicMath, OrthoProjection)
10741074
{
10751075
float4x4 OrthoProj = float4x4::Ortho(2.f, 4.f, -4.f, 12.f, false);
10761076

1077-
auto c0 = float3{-1.f, -2.f, -4.f} * OrthoProj;
1078-
auto c1 = float3{+1.f, +2.f, +12.f} * OrthoProj;
1077+
float3 c0 = float3{-1.f, -2.f, -4.f} * OrthoProj;
1078+
float3 c1 = float3{+1.f, +2.f, +12.f} * OrthoProj;
10791079
EXPECT_EQ(c0, float3(-1, -1, 0));
10801080
EXPECT_EQ(c1, float3(+1, +1, +1));
1081+
1082+
float Near = 0, Far = 0;
1083+
OrthoProj.GetNearFarClipPlanes(Near, Far, false);
1084+
EXPECT_FLOAT_EQ(Near, -4);
1085+
EXPECT_FLOAT_EQ(Far, 12);
1086+
1087+
OrthoProj.SetNearFarClipPlanes(2, 34, false);
1088+
OrthoProj.GetNearFarClipPlanes(Near, Far, false);
1089+
EXPECT_FLOAT_EQ(Near, 2);
1090+
EXPECT_FLOAT_EQ(Far, 34);
10811091
}
10821092

10831093
{
10841094
float4x4 OrthoProj = float4x4::Ortho(2.f, 4.f, -4.f, 12.f, true);
10851095

1086-
auto c0 = float3(-1.f, -2.f, -4.f) * OrthoProj;
1087-
auto c1 = float3(+1.f, +2.f, +12.f) * OrthoProj;
1096+
float3 c0 = float3(-1.f, -2.f, -4.f) * OrthoProj;
1097+
float3 c1 = float3(+1.f, +2.f, +12.f) * OrthoProj;
10881098
EXPECT_EQ(c0, float3(-1, -1, -1));
10891099
EXPECT_EQ(c1, float3(+1, +1, +1));
1100+
1101+
float Near = 0, Far = 0;
1102+
OrthoProj.GetNearFarClipPlanes(Near, Far, true);
1103+
EXPECT_FLOAT_EQ(Near, -4);
1104+
EXPECT_FLOAT_EQ(Far, 12);
1105+
1106+
OrthoProj.SetNearFarClipPlanes(2, 34, true);
1107+
OrthoProj.GetNearFarClipPlanes(Near, Far, true);
1108+
EXPECT_FLOAT_EQ(Near, 2);
1109+
EXPECT_FLOAT_EQ(Far, 34);
10901110
}
10911111

10921112
{
10931113
float4x4 OrthoProj = float4x4::OrthoOffCenter(-2.f, 6.f, -4.f, +12.f, -6.f, 10.f, false);
10941114

1095-
auto c0 = float3{-2.f, -4.f, -6.f} * OrthoProj;
1096-
auto c1 = float3{+6.f, +12.f, +10.f} * OrthoProj;
1115+
float3 c0 = float3{-2.f, -4.f, -6.f} * OrthoProj;
1116+
float3 c1 = float3{+6.f, +12.f, +10.f} * OrthoProj;
10971117
EXPECT_EQ(c0, float3(-1, -1, 0));
10981118
EXPECT_EQ(c1, float3(+1, +1, +1));
1119+
1120+
float Near = 0, Far = 0;
1121+
OrthoProj.GetNearFarClipPlanes(Near, Far, false);
1122+
EXPECT_FLOAT_EQ(Near, -6);
1123+
EXPECT_FLOAT_EQ(Far, 10);
10991124
}
11001125

11011126
{
11021127
float4x4 OrthoProj = float4x4::OrthoOffCenter(-2.f, 6.f, -4.f, +12.f, -6.f, 10.f, true);
11031128

1104-
auto c0 = float3{-2.f, -4.f, -6.f} * OrthoProj;
1105-
auto c1 = float3{+6.f, +12.f, +10.f} * OrthoProj;
1129+
float3 c0 = float3{-2.f, -4.f, -6.f} * OrthoProj;
1130+
float3 c1 = float3{+6.f, +12.f, +10.f} * OrthoProj;
11061131
EXPECT_EQ(c0, float3(-1, -1, -1));
11071132
EXPECT_EQ(c1, float3(+1, +1, +1));
1133+
1134+
float Near = 0, Far = 0;
1135+
OrthoProj.GetNearFarClipPlanes(Near, Far, true);
1136+
EXPECT_FLOAT_EQ(Near, -6);
11081137
}
11091138
}
11101139

0 commit comments

Comments
 (0)