// Copyright (C) 2012-2015 ChaosForge Ltd // http://chaosforge.org/ // // This file is part of Nova libraries. // For conditions of distribution and use, see copying.txt file in root folder. #ifndef NV_CORE_TRANSFORM_HH #define NV_CORE_TRANSFORM_HH #include #include namespace nv { class transform { public: typedef float value_type; 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( float radians, const vec3& axis ) { m_orientation = math::angle_axis( radians, 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 += math::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 = math::mat4_cast( m_orientation ); result[3] = vec4( m_position, 1.0f ); return result; } transform inverse() const { quat new_orient( math::inverse( m_orientation ) ); // TODO: simplify return transform( -math::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; } transform scaled( float v ) const { return transform( v * m_position, v * m_orientation ); } 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 ); } inline transform operator*( float value, const transform& lhs ) { return lhs.scaled( value ); } template <> struct enum_to_type< TRANSFORM > { typedef transform type; }; template <> struct type_to_enum< transform > { static const datatype type = TRANSFORM; }; namespace math { inline transform lerp( const transform& a, const transform& b, float value ) { return transform( math::lerp( a.get_position(), b.get_position(), value ), math::lerp( a.get_orientation(), b.get_orientation(), value ) ); } } } #endif // NV_CORE_TRANSFORM_HH