/* math/axis.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ // project headers #include "math/axis.h" #include "math/mathlib.h" namespace math { Axis::Axis() { clear(); } Axis::Axis(const Axis & other) { assign(other); } void Axis::clear() { axis_vector[0] = Vector3f(1.0f, 0.0f, 0.0f); axis_vector[1] = Vector3f(0.0f, 1.0f, 0.0f); axis_vector[2] = Vector3f(0.0f, 0.0f, 1.0f); } void Axis::assign(const Axis & other) { for (size_t i=0; i < 3; i++) { axis_vector[i].assign(other.axis_vector[i]); } } Axis & Axis::operator=(const Axis & other) { assign(other); return *this; } // change heading, rotate around Z-axis (positive is left) void Axis::change_direction(const float angle) { float cosa = cosf(angle * M_PI / 180.0f); float sina = sinf(angle * M_PI / 180.0f); Vector3f forward = axis_vector[0] * cosa + axis_vector[1] * sina; Vector3f left = axis_vector[1] *cosa - axis_vector[0] * sina; axis_vector[0].assign(forward); axis_vector[1].assign(left); } // change pitch, rotate around negative Y-axis (positive is up) void Axis::change_pitch(const float angle) { float cosa = cosf(angle * M_PI / 180.0f); float sina = sinf(angle * M_PI / 180.0f); Vector3f forward = axis_vector[0] * cosa + axis_vector[2] * sina; Vector3f up = axis_vector[2] * cosa - axis_vector[0] * sina; axis_vector[0].assign(forward); axis_vector[2].assign(up); } // change roll, rotate around forward vector (positive is left) void Axis::change_roll(const float angle) { float cosa = cosf(angle * M_PI / 180.0f); float sina = sinf(angle * M_PI / 180.0f); Vector3f forward = axis_vector[2] * cosa + axis_vector[1] * sina; Vector3f up = axis_vector[1] * cosa - axis_vector[2] * sina; axis_vector[2].assign(forward); axis_vector[1].assign(up); } // perform a rotation about an arbitrary axis /* notes: http://mathworld.wolfram.com/RotationFormula.html */ void Axis::rotate(Vector3f const &normal, float angle) { float cosa = cosf(angle); float sina = sinf(angle); for (size_t i =0; i < 3; i++) { axis_vector[i] = axis_vector[i]*cosa + normal * dotproduct(normal, axis_vector[i]) * (1 - cosa) + crossproduct(axis_vector[i], normal)*sina; } } const Axis Axis::transpose() const { Axis t; for (size_t i = 0; i < 3; i++) for (size_t j = 0; j < 3; j++) t.axis_vector[i][j] = axis_vector[j][i]; return t; } const Axis Axis::operator*(const Axis &other) const { Axis t; for (size_t i = 0; i < 3; i++) t.axis_vector[i] = (*this) * other.axis_vector[i]; return t; } // write an axis to a std::ostream std::ostream &operator<<(std::ostream & os, Axis const & axis) { os << axis.forward() << " "; os << axis.left() << " "; os << axis.up(); return os; } // read an axis from a std::istream std::istream &operator>>(std::istream & is, Axis & axis) { is >> axis[0]; is >> axis[1]; is >> axis[2]; return is; } // local-to-global coordinates Vector3f operator*(Axis const &axis, Vector3f const &vector) { return (Vector3f(vector[0] * axis[0] + vector[1] * axis[1] + vector[2] * axis[2])); } }