// Copyright (C) 2012-2014 ChaosForge Ltd // http://chaosforge.org/ // // This file is part of NV Libraries. // For conditions of distribution and use, see copyright notice in nv.hh #ifndef NV_CORE_TRANSFORM_HH #define NV_CORE_TRANSFORM_HH #include #include namespace nv { class transform { public: transform() {} explicit transform( const vec3& a_position ) : m_position( a_position ) {} explicit transform( const quat& a_orientation ) : m_orientation( a_orientation ) {} explicit transform( const mat4& a_matrix ) { set( a_matrix ); } transform( const vec3& a_position, const quat& a_orientation ) : m_position( a_position ), m_orientation( a_orientation ) {} void set_position( const vec3& a_position ) { m_position = a_position; } void set_orientation( const quat& a_orientation ) { m_orientation = a_orientation; } void set_orientation( const vec3& axis, float angle ) { m_orientation = glm::angleAxis( angle, axis ); } const vec3& get_position() const { return m_position; } const quat& get_orientation() const { return m_orientation; } public: void move( const vec3& heading, float distance ) { m_position += glm::normalize( heading ) * distance; } void translate( const vec3& absolute ) { m_position += absolute; } void rotate( const vec3& axis, f32 angle ) { quat temp( angle, axis ); m_orientation = temp * m_orientation; } void set( const mat4& from ) { m_orientation = quat( from ); m_position = vec3( from[3] ); } mat4 extract() const { mat4 result = glm::mat4_cast( m_orientation ); result[3] = vec4( m_position, 1.0f ); return result; } transform inverse() const { quat new_orient( glm::inverse( m_orientation ) ); // TODO: simplify return transform( -glm::mat3_cast(new_orient) * m_position, new_orient ); } transform& operator*=(const transform& rhs) { m_position = m_position + m_orientation * rhs.m_position; m_orientation = m_orientation * rhs.m_orientation; return *this; } vec3 transformed( const vec3& v ) const { return m_orientation * v + m_position; } private: vec3 m_position; quat m_orientation; }; inline transform operator*(transform lhs, const transform& rhs) { lhs *= rhs; return lhs; } inline vec3 operator*(const vec3 lhs, const transform& rhs) { return rhs.transformed( lhs ); } template <> struct enum_to_type< TRANSFORM > { typedef transform type; }; template <> struct type_to_enum< transform > { static const datatype type = TRANSFORM; }; template<> inline transform interpolate( const transform& a, const transform& b, float value ) { return transform( glm::mix ( a.get_position(), b.get_position(), value ), glm::slerp( a.get_orientation(), b.get_orientation(), value ) ); } } #endif // NV_CORE_TRANSFORM_HH