#pragma once #include #include namespace hpr { template inline Matrix translate(const Matrix& ms, const Vector& vs) { Matrix res {ms}; res.col(3, ms.row(0) * vs[0] + ms.row(1) * vs[1] + ms.row(2) * vs[2] + ms.row(3)); return res; } template inline Matrix rotate(const Matrix& ms, const Vector& vs, T angle) { const T cosv = cos(angle); const T sinv = sin(angle); Vector axis {normalize(vs)}; Vector temp {(static_cast(1) - cosv) * axis}; Matrix rot; rot(0, 0) = cosv + temp[0] * axis[0]; rot(0, 1) = temp[0] * axis[1] + sinv * axis[2]; rot(0, 2) = temp[0] * axis[2] - sinv * axis[1]; rot(1, 0) = temp[1] * axis[0] - sinv * axis[2]; rot(1, 1) = cosv + temp[1] * axis[1]; rot(1, 2) = temp[1] * axis[2] + sinv * axis[0]; rot(2, 0) = temp[2] * axis[0] + sinv * axis[1]; rot(2, 1) = temp[2] * axis[1] - sinv * axis[0]; rot(2, 2) = cosv + temp[2] * axis[2]; Matrix 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(1, ms.row(0) * rot(1, 0) + ms.row(1) * rot(1, 1) + ms.row(2) * rot(1, 2)); res.row(2, 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 Matrix rotate(const Matrix& ms, const Quaternion& q) { return ms * Matrix(q); } template inline Matrix scale(const Matrix& ms, const Vector& vs) { Matrix 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 Matrix lookAt(const Vector& eye, const Vector& center, const Vector& up) { const Vector forward {normalize(center - eye)}; const Vector right {normalize(cross(forward, up))}; const Vector nup {cross(right, forward)}; const Vector translation {dot(right, eye), dot(nup, eye), -dot(forward, eye)}; Matrix res = Matrix::identity(); res.row(0, Vector(right, 0)); res.row(1, Vector(nup, 0)); res.row(2, Vector(-forward, 0)); res.col(3, Vector(-translation, static_cast(1))); return res; } }