/*---{fips-meta:file-header:public}-------------------------------------*\ | o _______ __ _______ _ ______ __ o | | | ___|__|.-----.| __|| | | |.-----.--| |.-----. | | | ___| || _ ||__ ||_| | ---|| _ | _ || -__| | | |___| |__|| __||_______| |______||_____|_____||_____| | | FipS' CODE |__| > > > > > > > > > > > > > > > > > > > > > > | | (c) 2004-12 +++ Filip Stoklas, aka FipS, http://www.4FipS.com +++ | | o THIS CODE IS FREE - LICENSED UNDER THE MIT LICENSE o | \*----------------------------------------------------------------------*/ namespace fs { namespace math { template inline Matrix4 make_ortho(T left, T right, T bottom, T top, T znear, T zfar) { // from OpenGL spec PDF: can be rewritten as: // / 2/(r-l) 0 0 -(r+l)/(r-l) \ / 2/(r-l) 0 0 (r+l)/(l-r) \ // | 0 2/(t-b) 0 -(t+b)/(t-b) | => | 0 2/(t-b) 0 (t+b)/(b-t) | // | 0 0 -2/(f-n) -(f+n)/(f-n) | | 0 0 2/(n-f) (f+n)/(n-f) | // \ 0 0 0 1 / \ 0 0 0 1 / // invalid for: l=r, b=t, or n=f FS_ASSERT(left != right); FS_ASSERT(bottom != top); FS_ASSERT(znear != zfar); const T p_fn = zfar + znear; const T m_nf = znear - zfar; // ~ -m_fn const T p_rl = right + left; const T m_rl = right - left; const T p_tb = top + bottom; const T m_tb = top - bottom; const T m_lr = -m_rl; const T m_bt = -m_tb; return Matrix4( T(2)/m_rl, T(0), T(0), p_rl/m_lr, T(0), T(2)/m_tb, T(0), p_tb/m_bt, T(0), T(0), T(2)/m_nf, p_fn/m_nf, T(0), T(0), T(0), T(1) ); } template inline Matrix4 make_frustum(T left, T right, T bottom, T top, T znear, T zfar) { // from OpenGL spec PDF: can be rewritten as: // / 2n/(r-l) 0 (r+l)/(r-l) 0 \ / 2n/(r-l) 0 (r+l)/(r-l) 0 \ // | 0 2n/(t-b) (t+b)/(t-b) 0 | => | 0 2n/(t-b) (t+b)/(t-b) 0 | // | 0 0 -(f+n)/(f-n) -2fn/(f-n) | | 0 0 (f+n)/(n-f) 2fn/(n-f) | // \ 0 0 -1 0 / \ 0 0 -1 0 / // invalid for: n<=0, f<=0, l=r, b=t, or n=f FS_ASSERT(znear > T(0)); FS_ASSERT(zfar > T(0)); FS_ASSERT(left != right); FS_ASSERT(bottom != top); FS_ASSERT(znear != zfar); const T x_2n = znear + znear; const T x_2nf = T(2) * znear * zfar; const T p_fn = zfar + znear; const T m_nf = znear - zfar; // ~ -m_fn const T p_rl = right + left; const T m_rl = right - left; const T p_tb = top + bottom; const T m_tb = top - bottom; return Matrix4( x_2n/m_rl, T(0), p_rl/m_rl, T(0), T(0), x_2n/m_tb, p_tb/m_tb, T(0), T(0), T(0), p_fn/m_nf, x_2nf/m_nf, T(0), T(0), T(-1), T(0) ); } template inline Matrix4 make_perspective(T fovy_deg, T aspect, T znear, T zfar) { // from OpenGL spec PDF: can be rewritten as: // / c/a 0 0 0 \ / c/a 0 0 0 \ // | 0 c 0 0 | ==> | 0 c 0 0 | // | 0 0 -(f+n)/(f-n) -2nf/(f+n) | | 0 0 (f+n)/(n-f) 2nf/(n-f) | // \ 0 0 -1 0 / \ 0 0 -1 0 / FS_ASSERT(znear > T(0)); FS_ASSERT(zfar > T(0)); FS_ASSERT(aspect != T(0)); FS_ASSERT(znear != zfar); const T half_fovy_rad = T(M_PI) * fovy_deg / T(360); const auto si_co = sin_cos(half_fovy_rad); const T si = si_co.first; const T co = si_co.second; FS_ASSERT(si != T(0)); const T c = co / si; // cotangent const T a = aspect; const T x_2nf = T(2) * znear * zfar; const T p_fn = zfar + znear; const T m_nf = znear - zfar; return Matrix4( c/a, T(0), T(0), T(0), T(0), c, T(0), T(0), T(0), T(0), p_fn/m_nf, x_2nf/m_nf, T(0), T(0), T(-1), T(0) ); } }} // namespace fs::math