matrix: rewrite projections to dx style

This commit is contained in:
BlackMATov
2021-01-29 08:58:39 +07:00
parent 0b1955ce49
commit 0e5692bdd0
2 changed files with 126 additions and 94 deletions

View File

@@ -582,93 +582,91 @@ namespace vmath_hpp
// orthographic
template < typename T >
[[nodiscard]] mat<T, 4> orthographic_lh_zo(T left, T right, T bottom, T top, T znear, T zfar) {
[[nodiscard]] mat<T, 4> orthographic_lh(T width, T height, T znear, T zfar) {
/// REFERENCE:
/// https://en.wikipedia.org/wiki/Orthographic_projection
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixortholh
const T sx = T(2) * rcp(right - left);
const T sy = T(2) * rcp(top - bottom);
const T sz = T(1) * rcp(zfar - znear);
const T rwidth = rcp(width);
const T rheight = rcp(height);
const T frange = rcp(zfar - znear);
const T tx = - (right + left) * rcp(right - left);
const T ty = - (top + bottom) * rcp(top - bottom);
const T tz = - znear * rcp(zfar - znear);
const T sx = T(2) * rwidth;
const T sy = T(2) * rheight;
const T sz = frange;
const T tz = -frange * znear;
return {
sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, sz, 0,
tx, ty, tz, 1};
0, 0, tz, 1};
}
template < typename T >
[[nodiscard]] mat<T, 4> orthographic_lh_no(T left, T right, T bottom, T top, T znear, T zfar) {
[[nodiscard]] mat<T, 4> orthographic_rh(T width, T height, T znear, T zfar) {
/// REFERENCE:
/// https://en.wikipedia.org/wiki/Orthographic_projection
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthorh
const T sx = T(2) * rcp(right - left);
const T sy = T(2) * rcp(top - bottom);
const T sz = T(2) * rcp(zfar - znear);
const T rwidth = rcp(width);
const T rheight = rcp(height);
const T frange = rcp(znear - zfar);
const T tx = - (right + left) * rcp(right - left);
const T ty = - (top + bottom) * rcp(top - bottom);
const T tz = - (zfar + znear) * rcp(zfar - znear);
const T sx = T(2) * rwidth;
const T sy = T(2) * rheight;
const T sz = frange;
const T tz = frange * znear;
return {
sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, sz, 0,
tx, ty, tz, 1};
0, 0, tz, 1};
}
template < typename T >
[[nodiscard]] mat<T, 4> orthographic_rh_zo(T left, T right, T bottom, T top, T znear, T zfar) {
[[nodiscard]] mat<T, 4> orthographic_lh(T left, T right, T bottom, T top, T znear, T zfar) {
/// REFERENCE:
/// https://en.wikipedia.org/wiki/Orthographic_projection
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterlh
const T sx = T(2) * rcp(right - left);
const T sy = T(2) * rcp(top - bottom);
const T sz = -T(1) * rcp(zfar - znear);
const T tx = - (right + left) * rcp(right - left);
const T ty = - (top + bottom) * rcp(top - bottom);
const T tz = - znear * rcp(zfar - znear);
const T rwidth = rcp(right - left);
const T rheight = rcp(top - bottom);
const T frange = rcp(zfar - znear);
return {
sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, sz, 0,
tx, ty, tz, 1};
T(2) * rwidth, 0, 0, 0,
0, T(2) * rheight, 0, 0,
0, 0, frange, 0,
-(left + right) * rwidth, -(top + bottom) * rheight, -frange * znear, 1};
}
template < typename T >
[[nodiscard]] mat<T, 4> orthographic_rh_no(T left, T right, T bottom, T top, T znear, T zfar) {
[[nodiscard]] mat<T, 4> orthographic_rh(T left, T right, T bottom, T top, T znear, T zfar) {
/// REFERENCE:
/// https://en.wikipedia.org/wiki/Orthographic_projection
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterrh
const T sx = T(2) * rcp(right - left);
const T sy = T(2) * rcp(top - bottom);
const T sz = -T(2) * rcp(zfar - znear);
const T tx = - (right + left) * rcp(right - left);
const T ty = - (top + bottom) * rcp(top - bottom);
const T tz = - (zfar + znear) * rcp(zfar - znear);
const T rwidth = rcp(right - left);
const T rheight = rcp(top - bottom);
const T frange = rcp(znear - zfar);
return {
sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, sz, 0,
tx, ty, tz, 1};
T(2) * rwidth, 0, 0, 0,
0, T(2) * rheight, 0, 0,
0, 0, frange, 0,
-(left + right) * rwidth, -(top + bottom) * rheight, frange * znear, 1};
}
// perspective
template < typename T >
[[nodiscard]] mat<T, 4> perspective_lh_zo(T fov, T aspect, T znear, T zfar) {
const T sy = rcp(tan(fov * T(0.5)));
const T sx = sy / aspect;
const T sz = zfar / (zfar - znear);
const T tz = (znear * zfar) / (znear - zfar);
[[nodiscard]] mat<T, 4> perspective_lh(T width, T height, T znear, T zfar) {
/// REFERENCE:
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivelh
const T sx = T(2) * znear * rcp(width);
const T sy = T(2) * znear * rcp(height);
const T sz = zfar * rcp(zfar - znear);
const T tz = (znear * zfar) * rcp(znear - zfar);
return {
sx, 0, 0, 0,
0, sy, 0, 0,
@@ -677,24 +675,15 @@ namespace vmath_hpp
}
template < typename T >
[[nodiscard]] mat<T, 4> perspective_lh_no(T fov, T aspect, T znear, T zfar) {
const T sy = rcp(tan(fov * T(0.5)));
const T sx = sy / aspect;
const T sz = (zfar + znear) / (zfar - znear);
const T tz = (T(2) * znear * zfar) / (znear - zfar);
return {
sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, sz, 1,
0, 0, tz, 0};
}
[[nodiscard]] mat<T, 4> perspective_rh(T width, T height, T znear, T zfar) {
/// REFERENCE:
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectiverh
const T sx = T(2) * znear * rcp(width);
const T sy = T(2) * znear * rcp(height);
const T sz = zfar * rcp(znear - zfar);
const T tz = (znear * zfar) * rcp(znear - zfar);
template < typename T >
[[nodiscard]] mat<T, 4> perspective_rh_zo(T fov, T aspect, T znear, T zfar) {
const T sy = rcp(tan(fov * T(0.5)));
const T sx = sy / aspect;
const T sz = zfar / (znear - zfar);
const T tz = (znear * zfar) / (znear - zfar);
return {
sx, 0, 0, 0,
0, sy, 0, 0,
@@ -703,11 +692,65 @@ namespace vmath_hpp
}
template < typename T >
[[nodiscard]] mat<T, 4> perspective_rh_no(T fov, T aspect, T znear, T zfar) {
const T sy = rcp(tan(fov * T(0.5)));
const T sx = sy / aspect;
const T sz = (zfar + znear) / (znear - zfar);
const T tz = (T(2) * znear * zfar) / (znear - zfar);
[[nodiscard]] mat<T, 4> perspective_lh(T left, T right, T bottom, T top, T znear, T zfar) {
/// REFERENCE:
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectiveoffcenterlh
const T znear2 = T(2) * znear;
const T rwidth = rcp(right - left);
const T rheight = rcp(top - bottom);
const T frange = zfar * rcp(zfar - znear);
return {
znear2 * rwidth, 0, 0, 0,
0, znear2 * rheight, 0, 0,
-(left + right) * rwidth, -(top + bottom) * rheight, frange, 1,
0, 0, -frange * znear, 0};
}
template < typename T >
[[nodiscard]] mat<T, 4> perspective_rh(T left, T right, T bottom, T top, T znear, T zfar) {
/// REFERENCE:
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectiveoffcenterrh
const T znear2 = T(2) * znear;
const T rwidth = rcp(right - left);
const T rheight = rcp(top - bottom);
const T frange = zfar * rcp(znear - zfar);
return {
znear2 * rwidth, 0, 0, 0,
0, znear2 * rheight, 0, 0,
(left + right) * rwidth, (top + bottom) * rheight, frange, -1,
0, 0, frange * znear, 0};
}
template < typename T >
[[nodiscard]] mat<T, 4> perspective_fov_lh(T fovy, T aspect, T znear, T zfar) {
/// REFERENCE:
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovlh
const T sy = rcp(tan(fovy * T(0.5)));
const T sx = sy * rcp(aspect);
const T sz = zfar * rcp(zfar - znear);
const T tz = (znear * zfar) * rcp(znear - zfar);
return {
sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, sz, 1,
0, 0, tz, 0};
}
template < typename T >
[[nodiscard]] mat<T, 4> perspective_fov_rh(T fovy, T aspect, T znear, T zfar) {
/// REFERENCE:
/// https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovrh
const T sy = rcp(tan(fovy * T(0.5)));
const T sx = sy * rcp(aspect);
const T sz = zfar * rcp(znear - zfar);
const T tz = (znear * zfar) * rcp(znear - zfar);
return {
sx, 0, 0, 0,
0, sy, 0, 0,

View File

@@ -263,38 +263,27 @@ TEST_CASE("vmath/ext") {
SECTION("matrix orthographic") {
REQUIRE(all(approx(
orthographic_lh_no(100.f, 800.f, 50.f, 640.f, 5.f, 10.f),
orthographic_lh_zo(100.f, 800.f, 50.f, 640.f, 5.f, 10.f) * scale(1.f,1.f,2.f) * translate(0.f,0.f,-1.f))));
orthographic_lh(800.f, 600.f, 5.f, 10.f),
scale(1.f,1.f,-1.f) * orthographic_rh(800.f, 600.f, 5.f, 10.f))));
REQUIRE(all(approx(
orthographic_rh_no(100.f, 800.f, 50.f, 640.f, 5.f, 10.f),
orthographic_rh_zo(100.f, 800.f, 50.f, 640.f, 5.f, 10.f) * scale(1.f,1.f,2.f) * translate(0.f,0.f,-1.f))));
REQUIRE(all(approx(
orthographic_lh_no(100.f, 800.f, 50.f, 640.f, 5.f, 10.f),
scale(1.f,1.f,-1.f) * orthographic_rh_no(100.f, 800.f, 50.f, 640.f, 5.f, 10.f))));
REQUIRE(all(approx(
orthographic_lh_zo(100.f, 800.f, 50.f, 640.f, 5.f, 10.f),
scale(1.f,1.f,-1.f) * orthographic_rh_zo(100.f, 800.f, 50.f, 640.f, 5.f, 10.f))));
orthographic_lh(100.f, 800.f, 50.f, 640.f, 5.f, 10.f),
scale(1.f,1.f,-1.f) * orthographic_rh(100.f, 800.f, 50.f, 640.f, 5.f, 10.f))));
}
SECTION("matrix perspective") {
REQUIRE(all(approx(
perspective_lh_no(1.5f, 1.3f, 0.f, 10.f),
perspective_lh_zo(1.5f, 1.3f, 0.f, 10.f) * scale(1.f,1.f,2.f) * translate(0.f,0.f,-1.f))));
perspective_lh(800.f, 600.f, 5.f, 10.f),
scale(1.f,1.f,-1.f) * perspective_rh(800.f, 600.f, 5.f, 10.f))));
REQUIRE(all(approx(
perspective_rh_no(1.5f, 1.3f, 0.f, 10.f),
perspective_rh_zo(1.5f, 1.3f, 0.f, 10.f) * scale(1.f,1.f,2.f) * translate(0.f,0.f,-1.f))));
perspective_fov_lh(1.5f, 1.3f, 0.f, 10.f),
scale(1.f,1.f,-1.f) * perspective_fov_rh(1.5f, 1.3f, 0.f, 10.f))));
REQUIRE(all(approx(
perspective_lh_no(1.5f, 1.3f, 0.f, 10.f),
scale(1.f,1.f,-1.f) * perspective_rh_no(1.5f, 1.3f, 0.f, 10.f))));
REQUIRE(all(approx(
perspective_lh_zo(1.5f, 1.3f, 0.f, 10.f),
scale(1.f,1.f,-1.f) * perspective_rh_zo(1.5f, 1.3f, 0.f, 10.f))));
perspective_lh(100.f, 800.f, 50.f, 600.f, 5.f, 10.f),
scale(1.f,1.f,-1.f) * perspective_rh(100.f, 800.f, 50.f, 600.f, 5.f, 10.f))));
}
SECTION("matrix look_at") {