#if !defined( INCLUDED_MATH_VECTOR_H ) #define INCLUDED_MATH_VECTOR_H /// \file /// \brief Vector data types and related operations. #if 0 #define lrint( dbl ) ( (int)( ( dbl ) + 0.5 ) ) #define lrintf( flt ) ( (int)( ( flt ) + 0.5 ) ) #endif #if defined ( _MSC_VER ) inline int lrint( double flt ){ int i; _asm { fld flt fistp i }; return i; } #else // lrint is part of ISO C99 #define _ISOC9X_SOURCE 1 #define _ISOC99_SOURCE 1 #define __USE_ISOC9X 1 #define __USE_ISOC99 1 #endif #include #include #include #include //#include "debugging/debugging.h" /// \brief Returns true if \p self is equal to other \p other within \p epsilon. template inline bool float_equal_epsilon( const Element& self, const OtherElement& other, const Element& epsilon ){ return fabs( other - self ) < epsilon; } /// \brief Returns the value midway between \p self and \p other. template inline Element float_mid( const Element& self, const Element& other ){ return Element( ( self + other ) * 0.5 ); } /// \brief Returns \p f rounded to the nearest integer. Note that this is not the same behaviour as casting from float to int. template inline int float_to_integer( const Element& f ){ return lrint( f ); } /// \brief Returns \p f rounded to the nearest multiple of \snap. template inline Element float_snapped( const Element& f, const OtherElement& snap ){ return Element( float_to_integer( f / snap ) * snap ); } /// \brief Returns true if \p f has no decimal fraction part. template inline bool float_is_integer( const Element& f ){ return f == Element( float_to_integer( f ) ); } /// \brief Returns \p self modulated by the range [0, \p modulus) /// \p self must be in the range [\p -modulus, \p modulus) template inline Element float_mod_range( const Element& self, const ModulusElement& modulus ){ return Element( ( self < 0.0 ) ? self + modulus : self ); } /// \brief Returns \p self modulated by the range [0, \p modulus) template inline Element float_mod( const Element& self, const ModulusElement& modulus ){ return float_mod_range( Element( fmod( static_cast( self ), static_cast( modulus ) ) ), modulus ); } template class BasicVector2 { Element m_elements[2]; public: BasicVector2(){ } BasicVector2( const Element& x_, const Element& y_ ){ x() = x_; y() = y_; } Element& x(){ return m_elements[0]; } const Element& x() const { return m_elements[0]; } Element& y(){ return m_elements[1]; } const Element& y() const { return m_elements[1]; } const Element& operator[]( std::size_t i ) const { return m_elements[i]; } Element& operator[]( std::size_t i ){ return m_elements[i]; } }; template inline BasicVector2 vector2_added( const BasicVector2& self, const BasicVector2& other ){ return BasicVector2( Element( self.x() + other.x() ), Element( self.y() + other.y() ) ); } template inline BasicVector2 operator+( const BasicVector2& self, const BasicVector2& other ){ return vector2_added( self, other ); } template inline void vector2_add( BasicVector2& self, const BasicVector2& other ){ self.x() += Element( other.x() ); self.y() += Element( other.y() ); } template inline void operator+=( BasicVector2& self, const BasicVector2& other ){ vector2_add( self, other ); } template inline BasicVector2 vector2_subtracted( const BasicVector2& self, const BasicVector2& other ){ return BasicVector2( Element( self.x() - other.x() ), Element( self.y() - other.y() ) ); } template inline BasicVector2 operator-( const BasicVector2& self, const BasicVector2& other ){ return vector2_subtracted( self, other ); } template inline void vector2_subtract( BasicVector2& self, const BasicVector2& other ){ self.x() -= Element( other.x() ); self.y() -= lement( other.y() ); } template inline void operator-=( BasicVector2& self, const BasicVector2& other ){ vector2_subtract( self, other ); } template inline BasicVector2 vector2_scaled( const BasicVector2& self, OtherElement other ){ return BasicVector2( Element( self.x() * other ), Element( self.y() * other ) ); } template inline BasicVector2 operator*( const BasicVector2& self, OtherElement other ){ return vector2_scaled( self, other ); } template inline void vector2_scale( BasicVector2& self, OtherElement other ){ self.x() *= Element( other ); self.y() *= Element( other ); } template inline void operator*=( BasicVector2& self, OtherElement other ){ vector2_scale( self, other ); } template inline BasicVector2 vector2_scaled( const BasicVector2& self, const BasicVector2& other ){ return BasicVector2( Element( self.x() * other.x() ), Element( self.y() * other.y() ) ); } template inline BasicVector2 operator*( const BasicVector2& self, const BasicVector2& other ){ return vector2_scaled( self, other ); } template inline void vector2_scale( BasicVector2& self, const BasicVector2& other ){ self.x() *= Element( other.x() ); self.y() *= Element( other.y() ); } template inline void operator*=( BasicVector2& self, const BasicVector2& other ){ vector2_scale( self, other ); } template inline BasicVector2 vector2_divided( const BasicVector2& self, const BasicVector2& other ){ return BasicVector2( Element( self.x() / other.x() ), Element( self.y() / other.y() ) ); } template inline BasicVector2 operator/( const BasicVector2& self, const BasicVector2& other ){ return vector2_divided( self, other ); } template inline void vector2_divide( BasicVector2& self, const BasicVector2& other ){ self.x() /= Element( other.x() ); self.y() /= Element( other.y() ); } template inline void operator/=( BasicVector2& self, const BasicVector2& other ){ vector2_divide( self, other ); } template inline BasicVector2 vector2_divided( const BasicVector2& self, OtherElement other ){ return BasicVector2( Element( self.x() / other ), Element( self.y() / other ) ); } template inline BasicVector2 operator/( const BasicVector2& self, OtherElement other ){ return vector2_divided( self, other ); } template inline void vector2_divide( BasicVector2& self, OtherElement other ){ self.x() /= Element( other ); self.y() /= Element( other ); } template inline void operator/=( BasicVector2& self, OtherElement other ){ vector2_divide( self, other ); } template inline double vector2_dot( const BasicVector2& self, const BasicVector2& other ){ return self.x() * other.x() + self.y() * other.y(); } template inline double vector2_length_squared( const BasicVector2& self ){ return vector2_dot( self, self ); } typedef BasicVector2 Vector2; /// \brief A 3-element vector. template class BasicVector3 { Element m_elements[3]; public: BasicVector3(){ } template BasicVector3( const BasicVector3& other ){ x() = static_cast( other.x() ); y() = static_cast( other.y() ); z() = static_cast( other.z() ); } BasicVector3( const Element& x_, const Element& y_, const Element& z_ ){ x() = x_; y() = y_; z() = z_; } Element& x(){ return m_elements[0]; } const Element& x() const { return m_elements[0]; } Element& y(){ return m_elements[1]; } const Element& y() const { return m_elements[1]; } Element& z(){ return m_elements[2]; } const Element& z() const { return m_elements[2]; } const Element& operator[]( std::size_t i ) const { return m_elements[i]; } Element& operator[]( std::size_t i ){ return m_elements[i]; } operator BasicVector2&( ) { return reinterpret_cast&>( *this ); } operator const BasicVector2&( ) const { return reinterpret_cast&>( *this ); } }; /// \brief A 3-element vector stored in single-precision floating-point. typedef BasicVector3 Vector3; const Vector3 g_vector3_identity( 0, 0, 0 ); const Vector3 g_vector3_max = Vector3( FLT_MAX, FLT_MAX, FLT_MAX ); const Vector3 g_vector3_axis_x( 1, 0, 0 ); const Vector3 g_vector3_axis_y( 0, 1, 0 ); const Vector3 g_vector3_axis_z( 0, 0, 1 ); const Vector3 g_vector3_axes[3] = { g_vector3_axis_x, g_vector3_axis_y, g_vector3_axis_z }; template inline Element* vector3_to_array( BasicVector3& self ){ return reinterpret_cast( &self ); } template inline const Element* vector3_to_array( const BasicVector3& self ){ return reinterpret_cast( &self ); } template inline void vector3_swap( BasicVector3& self, BasicVector3& other ){ std::swap( self.x(), other.x() ); std::swap( self.y(), other.y() ); std::swap( self.z(), other.z() ); } template inline bool vector3_equal( const BasicVector3& self, const BasicVector3& other ){ return self.x() == other.x() && self.y() == other.y() && self.z() == other.z(); } template inline bool operator==( const BasicVector3& self, const BasicVector3& other ){ return vector3_equal( self, other ); } template inline bool operator!=( const BasicVector3& self, const BasicVector3& other ){ return !vector3_equal( self, other ); } template inline bool vector3_equal_epsilon( const BasicVector3& self, const BasicVector3& other, Epsilon epsilon ){ return float_equal_epsilon( self.x(), other.x(), epsilon ) && float_equal_epsilon( self.y(), other.y(), epsilon ) && float_equal_epsilon( self.z(), other.z(), epsilon ); } template inline BasicVector3 vector3_added( const BasicVector3& self, const BasicVector3& other ){ return BasicVector3( Element( self.x() + other.x() ), Element( self.y() + other.y() ), Element( self.z() + other.z() ) ); } template inline BasicVector3 operator+( const BasicVector3& self, const BasicVector3& other ){ return vector3_added( self, other ); } template inline void vector3_add( BasicVector3& self, const BasicVector3& other ){ self.x() += static_cast( other.x() ); self.y() += static_cast( other.y() ); self.z() += static_cast( other.z() ); } template inline void operator+=( BasicVector3& self, const BasicVector3& other ){ vector3_add( self, other ); } template inline BasicVector3 vector3_subtracted( const BasicVector3& self, const BasicVector3& other ){ return BasicVector3( Element( self.x() - other.x() ), Element( self.y() - other.y() ), Element( self.z() - other.z() ) ); } template inline BasicVector3 operator-( const BasicVector3& self, const BasicVector3& other ){ return vector3_subtracted( self, other ); } template inline void vector3_subtract( BasicVector3& self, const BasicVector3& other ){ self.x() -= static_cast( other.x() ); self.y() -= static_cast( other.y() ); self.z() -= static_cast( other.z() ); } template inline void operator-=( BasicVector3& self, const BasicVector3& other ){ vector3_subtract( self, other ); } template inline BasicVector3 vector3_scaled( const BasicVector3& self, const BasicVector3& other ){ return BasicVector3( Element( self.x() * other.x() ), Element( self.y() * other.y() ), Element( self.z() * other.z() ) ); } template inline BasicVector3 operator*( const BasicVector3& self, const BasicVector3& other ){ return vector3_scaled( self, other ); } template inline void vector3_scale( BasicVector3& self, const BasicVector3& other ){ self.x() *= static_cast( other.x() ); self.y() *= static_cast( other.y() ); self.z() *= static_cast( other.z() ); } template inline void operator*=( BasicVector3& self, const BasicVector3& other ){ vector3_scale( self, other ); } template inline BasicVector3 vector3_scaled( const BasicVector3& self, const OtherElement& scale ){ return BasicVector3( Element( self.x() * scale ), Element( self.y() * scale ), Element( self.z() * scale ) ); } template inline BasicVector3 operator*( const BasicVector3& self, const OtherElement& scale ){ return vector3_scaled( self, scale ); } template inline void vector3_scale( BasicVector3& self, const OtherElement& scale ){ self.x() *= static_cast( scale ); self.y() *= static_cast( scale ); self.z() *= static_cast( scale ); } template inline void operator*=( BasicVector3& self, const OtherElement& scale ){ vector3_scale( self, scale ); } template inline BasicVector3 vector3_divided( const BasicVector3& self, const BasicVector3& other ){ return BasicVector3( Element( self.x() / other.x() ), Element( self.y() / other.y() ), Element( self.z() / other.z() ) ); } template inline BasicVector3 operator/( const BasicVector3& self, const BasicVector3& other ){ return vector3_divided( self, other ); } template inline void vector3_divide( BasicVector3& self, const BasicVector3& other ){ self.x() /= static_cast( other.x() ); self.y() /= static_cast( other.y() ); self.z() /= static_cast( other.z() ); } template inline void operator/=( BasicVector3& self, const BasicVector3& other ){ vector3_divide( self, other ); } template inline BasicVector3 vector3_divided( const BasicVector3& self, const OtherElement& divisor ){ return BasicVector3( Element( self.x() / divisor ), Element( self.y() / divisor ), Element( self.z() / divisor ) ); } template inline BasicVector3 operator/( const BasicVector3& self, const OtherElement& divisor ){ return vector3_divided( self, divisor ); } template inline void vector3_divide( BasicVector3& self, const OtherElement& divisor ){ self.x() /= static_cast( divisor ); self.y() /= static_cast( divisor ); self.z() /= static_cast( divisor ); } template inline void operator/=( BasicVector3& self, const OtherElement& divisor ){ vector3_divide( self, divisor ); } template inline double vector3_dot( const BasicVector3& self, const BasicVector3& other ){ return self.x() * other.x() + self.y() * other.y() + self.z() * other.z(); } template inline BasicVector3 vector3_mid( const BasicVector3& begin, const BasicVector3& end ){ return vector3_scaled( vector3_added( begin, end ), 0.5 ); } template inline BasicVector3 vector3_cross( const BasicVector3& self, const BasicVector3& other ){ return BasicVector3( Element( self.y() * other.z() - self.z() * other.y() ), Element( self.z() * other.x() - self.x() * other.z() ), Element( self.x() * other.y() - self.y() * other.x() ) ); } template inline BasicVector3 vector3_negated( const BasicVector3& self ){ return BasicVector3( -self.x(), -self.y(), -self.z() ); } template inline void vector3_negate( BasicVector3& self ){ self = vector3_negated( self ); } template inline double vector3_length_squared( const BasicVector3& self ){ return vector3_dot( self, self ); } template inline double vector3_length( const BasicVector3& self ){ return sqrt( vector3_length_squared( self ) ); } template inline Element float_divided( Element f, Element other ){ //ASSERT_MESSAGE(other != 0, "float_divided: invalid divisor"); return f / other; } template inline BasicVector3 vector3_normalised( const BasicVector3& self ){ return vector3_scaled( self, float_divided( 1.0, vector3_length( self ) ) ); } template inline void vector3_normalise( BasicVector3& self ){ self = vector3_normalised( self ); } template inline BasicVector3 vector3_snapped( const BasicVector3& self ){ return BasicVector3( Element( float_to_integer( self.x() ) ), Element( float_to_integer( self.y() ) ), Element( float_to_integer( self.z() ) ) ); } template inline void vector3_snap( BasicVector3& self ){ self = vector3_snapped( self ); } template inline BasicVector3 vector3_snapped( const BasicVector3& self, const OtherElement& snap ){ return BasicVector3( Element( float_snapped( self.x(), snap ) ), Element( float_snapped( self.y(), snap ) ), Element( float_snapped( self.z(), snap ) ) ); } template inline void vector3_snap( BasicVector3& self, const OtherElement& snap ){ self = vector3_snapped( self, snap ); } inline Vector3 vector3_for_spherical( double theta, double phi ){ return Vector3( static_cast( cos( theta ) * cos( phi ) ), static_cast( sin( theta ) * cos( phi ) ), static_cast( sin( phi ) ) ); } /// \brief A 4-element vector stored in single-precision floating-point. class Vector4 { float m_elements[4]; public: Vector4(){ } Vector4( float x_, float y_, float z_, float w_ ){ x() = x_; y() = y_; z() = z_; w() = w_; } Vector4( const Vector3& self, float w_ ){ x() = self.x(); y() = self.y(); z() = self.z(); w() = w_; } float& x(){ return m_elements[0]; } float x() const { return m_elements[0]; } float& y(){ return m_elements[1]; } float y() const { return m_elements[1]; } float& z(){ return m_elements[2]; } float z() const { return m_elements[2]; } float& w(){ return m_elements[3]; } float w() const { return m_elements[3]; } float index( std::size_t i ) const { return m_elements[i]; } float& index( std::size_t i ){ return m_elements[i]; } float operator[]( std::size_t i ) const { return m_elements[i]; } float& operator[]( std::size_t i ){ return m_elements[i]; } operator Vector3&() { return reinterpret_cast( *this ); } operator const Vector3&() const { return reinterpret_cast( *this ); } bool operator==( const Vector4& other ) const { return x() == other.x() && y() == other.y() && z() == other.z() && w() == other.w(); } }; inline float* vector4_to_array( Vector4& self ){ return reinterpret_cast( &self ); } inline const float* vector4_to_array( const Vector4& self ){ return reinterpret_cast( &self ); } inline Vector3& vector4_to_vector3( Vector4& self ){ return reinterpret_cast( self ); } inline const Vector3& vector4_to_vector3( const Vector4& self ){ return reinterpret_cast( self ); } inline Vector4 vector4_added( const Vector4& self, const Vector4& other ){ return Vector4( float(self.x() + other.x() ), float(self.y() + other.y() ), float(self.z() + other.z() ), float(self.w() + other.w() ) ); } inline Vector4 operator+( const Vector4& self, const Vector4& other ){ return vector4_added( self, other ); } inline void vector4_add( Vector4& self, const Vector4& other ){ self.x() += static_cast( other.x() ); self.y() += static_cast( other.y() ); self.z() += static_cast( other.z() ); self.w() += static_cast( other.w() ); } inline void operator+=( Vector4& self, const Vector4& other ){ vector4_add( self, other ); } inline Vector4 vector4_subtracted( const Vector4& self, const Vector4& other ){ return Vector4( float(self.x() - other.x() ), float(self.y() - other.y() ), float(self.z() - other.z() ), float(self.w() - other.w() ) ); } inline Vector4 operator-( const Vector4& self, const Vector4& other ){ return vector4_subtracted( self, other ); } inline void vector4_subtract( Vector4& self, const Vector4& other ){ self.x() -= static_cast( other.x() ); self.y() -= static_cast( other.y() ); self.z() -= static_cast( other.z() ); self.w() -= static_cast( other.w() ); } inline void operator-=( Vector4& self, const Vector4& other ){ vector4_subtract( self, other ); } inline Vector4 vector4_scaled( const Vector4& self, const Vector4& other ){ return Vector4( float(self.x() * other.x() ), float(self.y() * other.y() ), float(self.z() * other.z() ), float(self.w() * other.w() ) ); } inline Vector4 operator*( const Vector4& self, const Vector4& other ){ return vector4_scaled( self, other ); } inline void vector4_scale( Vector4& self, const Vector4& other ){ self.x() *= static_cast( other.x() ); self.y() *= static_cast( other.y() ); self.z() *= static_cast( other.z() ); self.w() *= static_cast( other.w() ); } inline void operator*=( Vector4& self, const Vector4& other ){ vector4_scale( self, other ); } inline Vector4 vector4_scaled( const Vector4& self, const float& scale ){ return Vector4( float(self.x() * scale), float(self.y() * scale), float(self.z() * scale), float(self.w() * scale) ); } inline Vector4 operator*( const Vector4& self, const float& scale ){ return vector4_scaled( self, scale ); } inline void vector4_scale( Vector4& self, const float& scale ){ self.x() *= static_cast( scale ); self.y() *= static_cast( scale ); self.z() *= static_cast( scale ); self.w() *= static_cast( scale ); } inline void operator*=( Vector4& self, const float& scale ){ vector4_scale( self, scale ); } inline Vector4 vector4_divided( const Vector4& self, const float& divisor ){ return Vector4( float(self.x() / divisor), float(self.y() / divisor), float(self.z() / divisor), float(self.w() / divisor) ); } inline Vector4 operator/( const Vector4& self, const float& divisor ){ return vector4_divided( self, divisor ); } inline void vector4_divide( Vector4& self, const float& divisor ){ self.x() /= static_cast( divisor ); self.y() /= static_cast( divisor ); self.z() /= static_cast( divisor ); self.w() /= static_cast( divisor ); } inline void operator/=( Vector4& self, const float& divisor ){ vector4_divide( self, divisor ); } #endif