// L============================================================================= // L This software is distributed under the MIT license. // L Copyright 2021 Péter Kardos // L============================================================================= #pragma once #include "../Matrix/MatrixImpl.hpp" #include "../Vector.hpp" #include "IdentityBuilder.hpp" namespace mathter { template class OrthographicBuilder { static_assert(!std::is_integral_v); using VectorT = Vector; public: OrthographicBuilder(const VectorT& minBounds, const VectorT& maxBounds, T projNearPlane, T projFarPlane) : minBounds(minBounds), maxBounds(maxBounds), projNearPlane(projNearPlane), projFarPlane(projFarPlane) {} OrthographicBuilder& operator=(const OrthographicBuilder&) = delete; template operator Matrix() const { Matrix m; Set(m); return m; } template operator Matrix() const { Matrix m; Set(m); return m; } template operator Matrix() const { Matrix m; Set(m); return m; } private: template void Set(Matrix& m) const { using VectorT = Vector; VectorT volumeSize = maxBounds - minBounds; VectorT scale = T(2) / volumeSize; scale[scale.Dimension() - 1] *= T(0.5) * (projFarPlane - projNearPlane); VectorT offset = -(maxBounds + minBounds) / T(2) * scale; offset[offset.Dimension() - 1] += (projFarPlane + projNearPlane) / 2; m = Identity(); for (int i = 0; i < scale.Dimension(); ++i) { m(i, i) = scale(i); (Order == eMatrixOrder::FOLLOW_VECTOR ? m(scale.Dimension(), i) : m(i, scale.Dimension())) = offset(i); } } const Vector minBounds, maxBounds; T projNearPlane, projFarPlane; }; /// Creates an orthographics projection matrix. The volume before projection /// is an axis-aligned hypercube and it is projected onto a unit hypercube. /// The "left" corner of the hypercube. /// The "right" corner of the hypercube. /// The lower bound of the last axis of the projected volume (Z axis in 3D). /// The upper bound of the last axis of the projected volume (Z axis in 3D). /// After projection, all axes range from -1 to 1, except for the last axis, which is specified explicitly. template auto Orthographic(const Vector& minBounds, const Vector& maxBounds, T projNearPlane, T projFarPlane) { if constexpr (std::is_integral_v) { using VectorT = Vector; return OrthographicBuilder(VectorT(minBounds), VectorT(maxBounds), float(projNearPlane), float(projFarPlane)); } else { return OrthographicBuilder(minBounds, maxBounds, projNearPlane, projFarPlane); } } } // namespace mathter