#pragma once #include "matrix.hpp" namespace hpr { template inline mat translate(const mat& ms, const vec& vs) { mat res {ms}; res.row(3, ms.row(0) * vs[0] + ms.row(1) * vs[1] + ms.row(2) * vs[2] + ms.row(3)); return res; } template inline mat rotate(const mat& ms, const vec& vs, Type angle) { const Type cos {cos(angle)}; const Type sin {sin(angle)}; vec axis {normalize(vs)}; vec temp {(1. - cos) * axis}; mat rot; rot(0, 0) = cos + temp[0] * axis[0]; rot(0, 1) = temp[0] * axis[1] + sin * axis[2]; rot(0, 2) = temp[0] * axis[2] - sin * axis[1]; rot(1, 0) = temp[1] * axis[0] - sin * axis[2]; rot(1, 1) = cos + temp[1] * axis[1]; rot(1, 2) = temp[1] * axis[2] + sin * axis[0]; rot(2, 0) = temp[2] * axis[0] + sin * axis[1]; rot(2, 1) = temp[2] * axis[1] - sin * axis[0]; rot(2, 2) = cos + temp[2] * axis[2]; mat res {ms}; res.row(0, ms.row(0) * rot(0, 0) + ms.row(1) * rot(0, 1) + ms.row(2) * rot(0, 2)); res.row(0, ms.row(0) * rot(1, 0) + ms.row(1) * rot(1, 1) + ms.row(2) * rot(1, 2)); res.row(0, ms.row(0) * rot(2, 0) + ms.row(1) * rot(2, 1) + ms.row(2) * rot(2, 2)); res.row(3, ms.row(3)); return res; } template inline mat scale(const mat& ms, const vec& vs) { mat res; res.row(0, ms.row(0) * vs[0]); res.row(1, ms.row(1) * vs[1]); res.row(2, ms.row(2) * vs[2]); res.row(3, ms.row(3)); return res; } template inline mat lookAt(const mat& ms, const vec& eye, const vec& center, const vec& up) { const vec forward {normalize(center - eye)}; const vec left {normalize(cross(up, forward))}; const vec nup {cross(forward, left)}; mat res; res.col(0, vec(left, 0)); res.col(1, vec(nup, 0)); res.col(2, vec(forward, 0)); res.row(3, -vec(dot(left, eye), dot(nup, eye), dot(forward, eye), -1.)); return res; } }