/* * Copyright (C) 2020 Christopher J. Howard * * This file is part of Antkeeper source code. * * Antkeeper source code is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Antkeeper source code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Antkeeper source code. If not, see . */ #ifndef ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP #define ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP #include "math/matrix-type.hpp" #include "math/vector-type.hpp" #include "math/vector-functions.hpp" #include namespace math { /// @addtogroup matrix /// @{ /** * Adds two matrices. * * @param x First matrix. * @param y Second matrix. * @return Sum of the two matrices. */ template matrix add(const matrix& x, const matrix& y); /// @copydoc add(const matrix&, const matrix&) template matrix add(const matrix& x, const matrix& y); /// @copydoc add(const matrix&, const matrix&) template matrix add(const matrix& x, const matrix& y); /** * Reinterprets data as an `NxM` matrix of type `T`. * * @tparam N Number of columns. * @tparam M Number of rows. * @tparam T Element type. * @param data Data to reinterpret. */ template matrix& as_matrix(T& data); /** * Calculates the determinant of a matrix. * * @param m Matrix of which to take the determinant. */ template T determinant(const matrix& m); /// @copydoc determinant(const matrix&) template T determinant(const matrix& m); /// @copydoc determinant(const matrix&) template T determinant(const matrix& m); /** * Calculates the inverse of a matrix. * * @param m Matrix of which to take the inverse. */ template matrix inverse(const matrix& m); /// @copydoc inverse(const matrix&) template matrix inverse(const matrix& m); /// @copydoc inverse(const matrix&) template matrix inverse(const matrix& m); /** * Performs a component-wise multiplication of two matrices. * * @param x First matrix multiplicand. * @param y Second matrix multiplicand. */ template matrix componentwise_mul(const matrix& x, const matrix& y); /// @copydoc componentwise_mul(const matrix&, const matrix&) template matrix componentwise_mul(const matrix& x, const matrix& y); /// @copydoc componentwise_mul(const matrix&, const matrix&) template matrix componentwise_mul(const matrix& x, const matrix& y); /** * Creates a viewing transformation matrix. * * @param position Position of the view point. * @param target Position of the target. * @param up Normalized direction of the up vector. * @return Viewing transformation matrix. */ template matrix look_at(const vector& position, const vector& target, vector up); /** * Multiplies two matrices. * * @param x First matrix. * @param y Second matrix. * @return Product of the two matrices. */ template matrix mul(const matrix& x, const matrix& y); /// @copydoc mul(const matrix&, const matrix&); template matrix mul(const matrix& x, const matrix& y); /// @copydoc mul(const matrix&, const matrix&); template matrix mul(const matrix& x, const matrix& y); /** * Multiplies a matrix by a scalar. * * @param m Matrix. * @param s Scalar. * @return Product of the matrix and the scalar.. */ template matrix mul(const matrix& m, T s); /** * Transforms a vector by a matrix. * * @param m Matrix. * @param v Vector. * @return Transformed vector. */ template vector mul(const matrix& m, const vector& v); /// @copydoc mul(const matrix&, const vector&) template vector mul(const matrix& m, const vector& v); /// @copydoc mul(const matrix&, const vector&) template vector mul(const matrix& m, const vector& v); /** * Creates an orthographic projection matrix which will transform the near and far clipping planes to `[-1, 1]`, respectively. * * @param left Signed distance to the left clipping plane. * @param right Signed distance to the right clipping plane. * @param bottom Signed distance to the bottom clipping plane. * @param top Signed distance to the top clipping plane. * @param z_near Signed distance to the near clipping plane. * @param z_far Signed distance to the far clipping plane. * @return Orthographic projection matrix. */ template matrix ortho(T left, T right, T bottom, T top, T z_near, T z_far); /** * Creates an orthographic projection matrix which will transform the near and far clipping planes to `[0, 1]`, respectively. * * @param left Signed distance to the left clipping plane. * @param right Signed distance to the right clipping plane. * @param bottom Signed distance to the bottom clipping plane. * @param top Signed distance to the top clipping plane. * @param z_near Signed distance to the near clipping plane. * @param z_far Signed distance to the far clipping plane. * @return Orthographic projection matrix. */ template matrix ortho_half_z(T left, T right, T bottom, T top, T z_near, T z_far); /** * Calculates the outer product of a pair of vectors. * * @param c Parameter to be treated as a column vector. * @param r Parameter to be treated as a row vector. */ template matrix outer_product(const vector& c, const vector& r); /// @copydoc outer_product(const vector&, const vector&) template matrix outer_product(const vector& c, const vector& r); /// @copydoc outer_product(const vector&, const vector&) template matrix outer_product(const vector& c, const vector r); /** * Creates a perspective projection matrix which will transform the near and far clipping planes to `[-1, 1]`, respectively. * * @param vertical_fov Vertical field of view angle, in radians. * @param aspect_ratio Aspect ratio which determines the horizontal field of view. * @param z_near Distance to the near clipping plane. * @param z_far Distance to the far clipping plane. * @return Perspective projection matrix. */ template matrix perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far); /** * Creates a perspective projection matrix which will transform the near and far clipping planes to `[0, 1]`, respectively. * * @param vertical_fov Vertical field of view angle, in radians. * @param aspect_ratio Aspect ratio which determines the horizontal field of view. * @param z_near Distance to the near clipping plane. * @param z_far Distance to the far clipping plane. * @return Perspective projection matrix. */ template matrix perspective_half_z(T vertical_fov, T aspect_ratio, T z_near, T z_far); /** * Resizes a matrix. Any new elements will be set to `1` if in the diagonal, and `0` otherwise. * * @param m Matrix to resize. * @return Resized matrix. */ template matrix resize(const matrix& m); /** * Rotates a matrix. * * @param m Matrix to rotate. * @param angle Angle of rotation (in radians). * @param axis Axis of rotation * @return Rotated matrix. */ template matrix rotate(const matrix& m, T angle, const vector& axis); /** * Scales a matrix. * * @param m Matrix to scale. * @param v Scale vector. * @return Scaled matrix. */ template matrix scale(const matrix& m, const vector& v); /** * Subtracts a matrix from another matrix. * * @param x First matrix. * @param y Second matrix. * @return Difference between the two matrices. */ template matrix sub(const matrix& x, const matrix& y); /// @copydoc sub(const matrix&, const matrix&) template matrix sub(const matrix& x, const matrix& y); /// @copydoc sub(const matrix&, const matrix&) template matrix sub(const matrix& x, const matrix& y); /** * Translates a matrix. * * @param m Matrix to translate. * @param v Translation vector. * @return Translated matrix. */ template matrix translate(const matrix& m, const vector& v); /** * Calculates the transpose of a matrix. * * @param m Matrix of which to take the transpose. */ template matrix transpose(const matrix& m); /// @copydoc transpose(const matrix&) template matrix transpose(const matrix& m); /// @copydoc transpose(const matrix&) template matrix transpose(const matrix& m); /** * Types casts each matrix element and returns a matrix of the casted type. * * @tparam T2 Target matrix element type. * @tparam T1 Source matrix element type. * @tparam N Number of columns. * @tparam M Number of rows. * @param m Matrix to type cast. * @return Type-casted matrix. */ template matrix type_cast(const matrix& m); template matrix add(const matrix& x, const matrix& y) { return {{ x[0] + y[0], x[1] + y[1] }}; } template matrix add(const matrix& x, const matrix& y) { return {{ x[0] + y[0], x[1] + y[1], x[2] + y[2] }}; } template matrix add(const matrix& x, const matrix& y) { return {{ x[0] + y[0], x[1] + y[1], x[2] + y[2], x[3] + y[3] }}; } template inline matrix& as_matrix(T& data) { static_assert(std::is_pod>::value); return reinterpret_cast&>(data); } template T determinant(const matrix& m) { return m[0][0] * m[1][1] - m[0][1] * m[1][0]; } template T determinant(const matrix& m) { return m[0][0] * m [1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0] + m[0][2] * m[1][0] * m[2][1] - m[0][0] * m[1][2] * m[2][1] - m[0][1] * m[1][0] * m[2][2] - m[0][2] * m[1][1] * m[2][0]; } template T determinant(const matrix& m) { return m[0][3] * m[1][2] * m[2][1] * m[3][0] - m[0][2] * m[1][3] * m[2][1] * m[3][0] - m[0][3] * m[1][1] * m[2][2] * m[3][0] + m[0][1] * m[1][3] * m[2][2] * m[3][0] + m[0][2] * m[1][1] * m[2][3] * m[3][0] - m[0][1] * m[1][2] * m[2][3] * m[3][0] - m[0][3] * m[1][2] * m[2][0] * m[3][1] + m[0][2] * m[1][3] * m[2][0] * m[3][1] + m[0][3] * m[1][0] * m[2][2] * m[3][1] - m[0][0] * m[1][3] * m[2][2] * m[3][1] - m[0][2] * m[1][0] * m[2][3] * m[3][1] + m[0][0] * m[1][2] * m[2][3] * m[3][1] + m[0][3] * m[1][1] * m[2][0] * m[3][2] - m[0][1] * m[1][3] * m[2][0] * m[3][2] - m[0][3] * m[1][0] * m[2][1] * m[3][2] + m[0][0] * m[1][3] * m[2][1] * m[3][2] + m[0][1] * m[1][0] * m[2][3] * m[3][2] - m[0][0] * m[1][1] * m[2][3] * m[3][2] - m[0][2] * m[1][1] * m[2][0] * m[3][3] + m[0][1] * m[1][2] * m[2][0] * m[3][3] + m[0][2] * m[1][0] * m[2][1] * m[3][3] - m[0][0] * m[1][2] * m[2][1] * m[3][3] - m[0][1] * m[1][0] * m[2][2] * m[3][3] + m[0][0] * m[1][1] * m[2][2] * m[3][3]; } template matrix inverse(const matrix& m) { static_assert(std::is_floating_point::value); const T rd(T(1) / determinant(m)); return {{ { m[1][1] * rd, -m[0][1] * rd}, {-m[1][0] * rd, m[0][0] * rd} }}; } template matrix inverse(const matrix& m) { static_assert(std::is_floating_point::value); const T rd(T(1) / determinant(m)); return {{ { (m[1][1] * m[2][2] - m[1][2] * m[2][1]) * rd, (m[0][2] * m[2][1] - m[0][1] * m[2][2]) * rd, (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * rd }, { (m[1][2] * m[2][0] - m[1][0] * m[2][2]) * rd, (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * rd, (m[0][2] * m[1][0] - m[0][0] * m[1][2]) * rd }, { (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * rd, (m[0][1] * m[2][0] - m[0][0] * m[2][1]) * rd, (m[0][0] * m[1][1] - m[0][1] * m[1][0]) * rd } }}; } template matrix inverse(const matrix& m) { static_assert(std::is_floating_point::value); const T rd(T(1) / determinant(m)); return {{ { (m[1][2] * m[2][3] * m[3][1] - m[1][3] * m[2][2] * m[3][1] + m[1][3] * m[2][1] * m[3][2] - m[1][1] * m[2][3] * m[3][2] - m[1][2] * m[2][1] * m[3][3] + m[1][1] * m[2][2] * m[3][3]) * rd, (m[0][3] * m[2][2] * m[3][1] - m[0][2] * m[2][3] * m[3][1] - m[0][3] * m[2][1] * m[3][2] + m[0][1] * m[2][3] * m[3][2] + m[0][2] * m[2][1] * m[3][3] - m[0][1] * m[2][2] * m[3][3]) * rd, (m[0][2] * m[1][3] * m[3][1] - m[0][3] * m[1][2] * m[3][1] + m[0][3] * m[1][1] * m[3][2] - m[0][1] * m[1][3] * m[3][2] - m[0][2] * m[1][1] * m[3][3] + m[0][1] * m[1][2] * m[3][3]) * rd, (m[0][3] * m[1][2] * m[2][1] - m[0][2] * m[1][3] * m[2][1] - m[0][3] * m[1][1] * m[2][2] + m[0][1] * m[1][3] * m[2][2] + m[0][2] * m[1][1] * m[2][3] - m[0][1] * m[1][2] * m[2][3]) * rd }, { (m[1][3] * m[2][2] * m[3][0] - m[1][2] * m[2][3] * m[3][0] - m[1][3] * m[2][0] * m[3][2] + m[1][0] * m[2][3] * m[3][2] + m[1][2] * m[2][0] * m[3][3] - m[1][0] * m[2][2] * m[3][3]) * rd, (m[0][2] * m[2][3] * m[3][0] - m[0][3] * m[2][2] * m[3][0] + m[0][3] * m[2][0] * m[3][2] - m[0][0] * m[2][3] * m[3][2] - m[0][2] * m[2][0] * m[3][3] + m[0][0] * m[2][2] * m[3][3]) * rd, (m[0][3] * m[1][2] * m[3][0] - m[0][2] * m[1][3] * m[3][0] - m[0][3] * m[1][0] * m[3][2] + m[0][0] * m[1][3] * m[3][2] + m[0][2] * m[1][0] * m[3][3] - m[0][0] * m[1][2] * m[3][3]) * rd, (m[0][2] * m[1][3] * m[2][0] - m[0][3] * m[1][2] * m[2][0] + m[0][3] * m[1][0] * m[2][2] - m[0][0] * m[1][3] * m[2][2] - m[0][2] * m[1][0] * m[2][3] + m[0][0] * m[1][2] * m[2][3]) * rd }, { (m[1][1] * m[2][3] * m[3][0] - m[1][3] * m[2][1] * m[3][0] + m[1][3] * m[2][0] * m[3][1] - m[1][0] * m[2][3] * m[3][1] - m[1][1] * m[2][0] * m[3][3] + m[1][0] * m[2][1] * m[3][3]) * rd, (m[0][3] * m[2][1] * m[3][0] - m[0][1] * m[2][3] * m[3][0] - m[0][3] * m[2][0] * m[3][1] + m[0][0] * m[2][3] * m[3][1] + m[0][1] * m[2][0] * m[3][3] - m[0][0] * m[2][1] * m[3][3]) * rd, (m[0][1] * m[1][3] * m[3][0] - m[0][3] * m[1][1] * m[3][0] + m[0][3] * m[1][0] * m[3][1] - m[0][0] * m[1][3] * m[3][1] - m[0][1] * m[1][0] * m[3][3] + m[0][0] * m[1][1] * m[3][3]) * rd, (m[0][3] * m[1][1] * m[2][0] - m[0][1] * m[1][3] * m[2][0] - m[0][3] * m[1][0] * m[2][1] + m[0][0] * m[1][3] * m[2][1] + m[0][1] * m[1][0] * m[2][3] - m[0][0] * m[1][1] * m[2][3]) * rd }, { (m[1][2] * m[2][1] * m[3][0] - m[1][1] * m[2][2] * m[3][0] - m[1][2] * m[2][0] * m[3][1] + m[1][0] * m[2][2] * m[3][1] + m[1][1] * m[2][0] * m[3][2] - m[1][0] * m[2][1] * m[3][2]) * rd, (m[0][1] * m[2][2] * m[3][0] - m[0][2] * m[2][1] * m[3][0] + m[0][2] * m[2][0] * m[3][1] - m[0][0] * m[2][2] * m[3][1] - m[0][1] * m[2][0] * m[3][2] + m[0][0] * m[2][1] * m[3][2]) * rd, (m[0][2] * m[1][1] * m[3][0] - m[0][1] * m[1][2] * m[3][0] - m[0][2] * m[1][0] * m[3][1] + m[0][0] * m[1][2] * m[3][1] + m[0][1] * m[1][0] * m[3][2] - m[0][0] * m[1][1] * m[3][2]) * rd, (m[0][1] * m[1][2] * m[2][0] - m[0][2] * m[1][1] * m[2][0] + m[0][2] * m[1][0] * m[2][1] - m[0][0] * m[1][2] * m[2][1] - m[0][1] * m[1][0] * m[2][2] + m[0][0] * m[1][1] * m[2][2]) * rd } }}; } template matrix componentwise_mul(const matrix& x, const matrix& y) { return {{ {x[0][0] * y[0][0], x[0][1] * y[0][1]}, {x[1][0] * y[1][0], x[1][1] * y[1][1]} }}; } template matrix componentwise_mul(const matrix& x, const matrix& y) { return {{ {x[0][0] * y[0][0], x[0][1] * y[0][1], x[0][2] * y[0][2]}, {x[1][0] * y[1][0], x[1][1] * y[1][1], x[1][2] * y[1][2]}, {x[2][0] * y[2][0], x[2][1] * y[2][1], x[2][2] * y[2][2]} }}; } template matrix componentwise_mul(const matrix& x, const matrix& y) { return {{ {x[0][0] * y[0][0], x[0][1] * y[0][1], x[0][2] * y[0][2], x[0][3] * y[0][3]}, {x[1][0] * y[1][0], x[1][1] * y[1][1], x[1][2] * y[1][2], x[1][3] * y[1][3]}, {x[2][0] * y[2][0], x[2][1] * y[2][1], x[2][2] * y[2][2], x[2][3] * y[2][3]}, {x[3][0] * y[3][0], x[3][1] * y[3][1], x[3][2] * y[3][2], x[3][3] * y[3][3]} }}; } template matrix look_at(const vector& position, const vector& target, vector up) { vector forward = normalize(sub(target, position)); vector right = normalize(cross(forward, up)); up = cross(right, forward); matrix m = {{ {right[0], up[0], -forward[0], T(0)}, {right[1], up[1], -forward[1], T(0)}, {right[2], up[2], -forward[2], T(0)}, {T(0), T(0), T(0), T(1)} }}; return translate(m, negate(position)); } template matrix mul(const matrix& x, const matrix& y) { return {{ x[0] * y[0][0] + x[1] * y[0][1], x[0] * y[1][0] + x[1] * y[1][1] }}; } template matrix mul(const matrix& x, const matrix& y) { return {{ x[0] * y[0][0] + x[1] * y[0][1] + x[2] * y[0][2], x[0] * y[1][0] + x[1] * y[1][1] + x[2] * y[1][2], x[0] * y[2][0] + x[1] * y[2][1] + x[2] * y[2][2] }}; } template matrix mul(const matrix& x, const matrix& y) { return {{ x[0] * y[0][0] + x[1] * y[0][1] + x[2] * y[0][2] + x[3] * y[0][3], x[0] * y[1][0] + x[1] * y[1][1] + x[2] * y[1][2] + x[3] * y[1][3], x[0] * y[2][0] + x[1] * y[2][1] + x[2] * y[2][2] + x[3] * y[2][3], x[0] * y[3][0] + x[1] * y[3][1] + x[2] * y[3][2] + x[3] * y[3][3] }}; } /// @private template inline matrix mul(const matrix& m, T s, std::index_sequence) { return {{(m[I] * s)...}}; } template inline matrix mul(const matrix& m, T s) { return mul(m, s, std::make_index_sequence{}); } template vector mul(const matrix& m, const vector& v) { return { m[0][0] * v[0] + m[1][0] * v[1], m[0][1] * v[0] + m[1][1] * v[1] }; } template vector mul(const matrix& m, const vector& v) { return { m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2], m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2], m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] }; } template vector mul(const matrix& m, const vector& v) { return { m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3], m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3], m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3], m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3] }; } template matrix ortho(T left, T right, T bottom, T top, T z_near, T z_far) { return {{ {T(2) / (right - left), T(0), T(0), T(0)}, {T(0), T(2) / (top - bottom), T(0), T(0)}, {T(0), T(0), T(-2) / (z_far - z_near), T(0)}, {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((z_far + z_near) / (z_far - z_near)), T(1)} }}; } template matrix ortho_half_z(T left, T right, T bottom, T top, T z_near, T z_far) { return {{ {T(2) / (right - left), T(0), T(0), T(0)}, {T(0), T(2) / (top - bottom), T(0), T(0)}, {T(0), T(0), T(-1) / (z_far - z_near), T(0)}, {-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -z_near / (z_far - z_near), T(1)} }}; } template matrix outer_product(const vector& c, const vector& r) { return {{ {c[0] * r[0], c[1] * r[0]}, {c[0] * r[1], c[1] * r[1]} }}; } template matrix outer_product(const vector& c, const vector& r) { return {{ {c[0] * r[0], c[1] * r[0], c[2] * r[0]}, {c[0] * r[1], c[1] * r[1], c[2] * r[1]}, {c[0] * r[2], c[1] * r[2], c[2] * r[2]} }}; } template matrix outer_product(const vector& c, const vector r) { return {{ {c[0] * r[0], c[1] * r[0], c[2] * r[0], c[3] * r[0]}, {c[0] * r[1], c[1] * r[1], c[2] * r[1], c[3] * r[1]}, {c[0] * r[2], c[1] * r[2], c[2] * r[2], c[3] * r[2]}, {c[0] * r[3], c[1] * r[3], c[2] * r[3], c[3] * r[3]} }}; } template matrix perspective(T vertical_fov, T aspect_ratio, T z_near, T z_far) { T half_fov = vertical_fov * T(0.5); T f = std::cos(half_fov) / std::sin(half_fov); return {{ {f / aspect_ratio, T(0), T(0), T(0)}, {T(0), f, T(0), T(0)}, {T(0), T(0), (z_far + z_near) / (z_near - z_far), T(-1)}, {T(0), T(0), (T(2) * z_far * z_near) / (z_near - z_far), T(0)} }}; } template matrix perspective_half_z(T vertical_fov, T aspect_ratio, T z_near, T z_far) { T half_fov = vertical_fov * T(0.5); T f = std::cos(half_fov) / std::sin(half_fov); return {{ {f / aspect_ratio, T(0), T(0), T(0)}, {T(0), f, T(0), T(0)}, {T(0), T(0), z_far / (z_near - z_far), T(-1)}, {T(0), T(0), -(z_far * z_near) / (z_far - z_near), T(0)} }}; } template matrix resize(const matrix& m) { matrix resized; for (std::size_t i = 0; i < N1; ++i) { for (std::size_t j = 0; j < M1; ++j) { resized[i][j] = (i < N0 && j < M0) ? m[i][j] : ((i == j) ? T(1) : T(0)); } } return resized; } template matrix rotate(const matrix& m, T angle, const vector& axis) { const T c = std::cos(angle); const T s = std::sin(angle); const vector temp = mul(axis, T(1) - c); matrix rotation; rotation[0][0] = axis[0] * temp[0] + c rotation[0][1] = axis[1] * temp[0] + axis[2] * s; rotation[0][2] = axis[2] * temp[0] - axis[1] * s; rotation[0][3] = T(0); rotation[1][0] = axis[0] * temp[1] - axis[2] * s rotation[1][1] = axis[1] * temp[1] + c; rotation[1][2] = axis[2] * temp[1] + axis[0] * s; rotation[1][3] = T(0); rotation[2][0] = axis[0] * temp[2] + axis[1] * s; rotation[2][1] = axis[1] * temp[2] - axis[0] * s; rotation[2][2] = axis[2] * temp[2] + c rotation[2][3] = T(0); rotation[3][0] = T(0); rotation[3][1] = T(0); rotation[3][2] = T(0); rotation[3][3] = T(1); return mul(m, rotation); } template matrix scale(const matrix& m, const vector& v) { return mul(m, matrix {{ {v[0], T(0), T(0), T(0)}, {T(0), v[1], T(0), T(0)}, {T(0), T(0), v[2], T(0)}, {T(0), T(0), T(0), T(1)} }}); } template matrix sub(const matrix& x, const matrix& y) { return {{ x[0] - y[0], x[1] - y[1] }}; } template matrix sub(const matrix& x, const matrix& y) { return {{ x[0] - y[0], x[1] - y[1], x[2] - y[2] }}; } template matrix sub(const matrix& x, const matrix& y) { return {{ x[0] - y[0], x[1] - y[1], x[2] - y[2], x[3] - y[3] }}; } template matrix translate(const matrix& m, const vector& v) { return mul(m, matrix {{ {T(1), T(0), T(0), T(0)}, {T(0), T(1), T(0), T(0)}, {T(0), T(0), T(1), T(0)}, {v[0], v[1], v[2], T(1)} }}); } template matrix transpose(const matrix& m) { return {{ { m[0][0], m[1][0] }, { m[0][1], m[1][1] } }}; } template matrix transpose(const matrix& m) { return {{ { m[0][0], m[1][0], m[2][0] }, { m[0][1], m[1][1], m[2][1] }, { m[0][2], m[1][2], m[2][2] } }}; } template matrix transpose(const matrix& m) { return {{ { m[0][0], m[1][0], m[2][0], m[3][0] }, { m[0][1], m[1][1], m[2][1], m[3][1] }, { m[0][2], m[1][2], m[2][2], m[3][2] }, { m[0][3], m[1][3], m[2][3], m[3][3] } }}; } /// @private template inline matrix type_cast(const matrix& m, std::index_sequence) { return {type_cast(m[I])...}; } template matrix type_cast(const matrix& m) { return type_cast(m, std::make_index_sequence{}); } /// @} } // namespace math #endif // ANTKEEPER_MATH_MATRIX_FUNCTIONS_HPP