etk/etk/math/Vector4D.h

441 lines
12 KiB
C++

/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license APACHE v2.0 (see license file)
*/
#pragma once
#include <etk/types.h>
#include <math.h>
#ifdef ETK_BUILD_LINEARMATH
#include <LinearMath/btScalar.h>
#include <LinearMath/btMinMax.h>
#include <LinearMath/btVector3.h>
#include <LinearMath/btQuaternion.h>
#else
namespace etk {
template <typename T> class Vector4D;
};
#endif
namespace etk {
/**
* @brief Vectorial 4-dimention vector (x/y/z/w)
*/
template <typename T> class Vector4D {
public:
T m_floats[4]; //!< all internal values
public:
/**
* @brief No initialization constructor (faster ...)
*/
Vector4D() {
#ifdef DEBUG
// in debug mode we set supid value to prevent forget of the inits ...
m_floats[0] = T(34673363);
m_floats[1] = T(34523535);
m_floats[2] = T(43523424);
m_floats[3] = T(23452345);
#endif
}
/**
* @brief Constructor from scalars.
* @param _xxx X value
* @param _yyy Y value
* @param _zzz Z value
* @param _www W value
*/
Vector4D(const T& _xxx, const T& _yyy, const T& _zzz, const T& _www) {
m_floats[0] = _xxx;
m_floats[1] = _yyy;
m_floats[2] = _zzz;
m_floats[3] = _www;
}
/**
* @brief Add a vector to this one.
* @param[in] _obj The vector to add to this one
* @return Local reference of the vector
*/
Vector4D<T>& operator+=(const Vector4D<T>& _obj) {
m_floats[0] += _obj.m_floats[0];
m_floats[1] += _obj.m_floats[1];
m_floats[2] += _obj.m_floats[2];
m_floats[3] += _obj.m_floats[3];
return *this;
}
/**
* @brief Add a vector to this one.
* @param[in] _obj The vector to add to this one
* @return New vector containing the value
*/
Vector4D<T> operator+(const Vector4D<T>& _obj) {
return Vector4D<T>(m_floats[0] + _obj.m_floats[0],
m_floats[1] + _obj.m_floats[1],
m_floats[2] + _obj.m_floats[2],
m_floats[3] + _obj.m_floats[3]);
}
/**
* @brief Subtract a vector from this one
* @param _obj The vector to subtract
* @return Local reference of the vector
*/
Vector4D<T>& operator-=(const Vector4D<T>& _obj) {
m_floats[0] -= _obj.m_floats[0];
m_floats[1] -= _obj.m_floats[1];
m_floats[2] -= _obj.m_floats[2];
m_floats[3] -= _obj.m_floats[3];
return *this;
}
/**
* @brief Subtract a vector from this one
* @param _obj The vector to subtract
* @return New vector containing the value
*/
Vector4D<T> operator-(const Vector4D<T>& _obj) {
return Vector4D<T>(m_floats[0] - _obj.m_floats[0],
m_floats[1] - _obj.m_floats[1],
m_floats[2] - _obj.m_floats[2],
m_floats[3] - _obj.m_floats[3]);
}
/**
* @brief Scale the vector
* @param[in] _val Scale factor
* @return Local reference of the vector
*/
Vector4D<T>& operator*=(const T& _val) {
m_floats[0] *= _val;
m_floats[1] *= _val;
m_floats[2] *= _val;
m_floats[3] *= _val;
return *this;
}
/**
* @brief Scale the vector
* @param[in] _val Scale factor
* @return New vector containing the value
*/
Vector4D<T> operator*(const T& _val) {
return Vector4D<T>(m_floats[0] * _val,
m_floats[1] * _val,
m_floats[2] * _val,
m_floats[3] * _val);
}
/**
* @brief Inversely scale the vector
* @param[in] _val Scale factor to divide by.
* @return Local reference of the vector
*/
Vector4D<T>& operator/=(const T& _val) {
if (_val != 0) {
m_floats[0] /= _val;
m_floats[1] /= _val;
m_floats[2] /= _val;
m_floats[3] /= _val;
return *this;
}
return *this;
}
/**
* @brief Inversely scale the vector
* @param[in] _val Scale factor to divide by.
* @return New vector containing the value
*/
Vector4D<T> operator/(const T& _val) {
if (_val != 0) {
return Vector4D<T>(m_floats[0] / _val,
m_floats[1] / _val,
m_floats[2] / _val,
m_floats[3] / _val);
}
return *this;
}
/**
* @brief Return the dot product
* @param _obj The other vector in the dot product
* @return Dot result value
*/
float dot(const Vector4D<T>& _obj) const {
return m_floats[0] * _obj.m_floats[0] +
m_floats[1] * _obj.m_floats[1] +
m_floats[2] * _obj.m_floats[2] +
m_floats[3] * _obj.m_floats[3];
}
/**
* @brief Return the squared length of the vector.
* @return Squared length value.
*/
float length2() const {
return dot(*this);
}
/**
* @brief Return the length of the vector
* @return Length value
*/
float length() const {
#ifdef ETK_BUILD_LINEARMATH
return btSqrt(length2());
#else
#if __CPP_VERSION__ >= 2011 && !defined(__TARGET_OS__MacOs) && !defined(__TARGET_OS__IOs)
return std::sqrt(length2());
#else
return sqrt(length2());
#endif
#endif
}
/**
* @brief Return the distance squared between the ends of this and another vector
* This is symantically treating the vector like a point
* @param[in] _obj The other vector to compare distance
* @return the square distance of the 2 points
*/
float distance2(const Vector4D<T>& _obj) const {
return (_obj - *this).length2();
}
/**
* @brief Return the distance between the ends of this and another vector
* This is symantically treating the vector like a point
* @param[in] _obj The other vector to compare distance
* @return the distance of the 2 points
*/
float distance(const Vector4D<T>& _obj) const {
return (_obj - *this).length();
}
/**
* @brief Normalize this vector x^2 + y^2 + z^2 + w^2 = 1
* @return Local reference of the vector normalized
*/
Vector4D<T>& normalize() {
return *this /= length();
}
/**
* @brief Return a normalized version of this vector
* @return New vector containing the value
*/
Vector4D<T> normalized() const {
return *this / length();
}
/**
* @brief Return a vector will the absolute values of each element
* @return New vector with the absolute value
*/
Vector4D<T> absolute() const {
return Vector4D<T>( abs(m_floats[0]),
abs(m_floats[1]),
abs(m_floats[2]),
abs(m_floats[3]));
}
/**
* @brief Multiply this vector by the other.
* @param _obj The other vector
* @return Local reference of the vector
*/
Vector4D<T>& operator*=(const Vector4D<T>& _obj) {
m_floats[0] *= _obj.m_floats[0];
m_floats[1] *= _obj.m_floats[1];
m_floats[2] *= _obj.m_floats[2];
m_floats[3] *= _obj.m_floats[3];
return *this;
}
/**
* @brief Multiply this vector by the other.
* @param _obj The other vector
* @return New vector containing the value
*/
Vector4D<T> operator*(const Vector4D<T>& _obj) {
return Vector4D<T>(m_floats[0] * _obj.m_floats[0],
m_floats[1] * _obj.m_floats[1],
m_floats[2] * _obj.m_floats[2],
m_floats[3] * _obj.m_floats[3]);
}
/**
* @brief Get X value
* @return the x value
*/
const T& getX() const {
return m_floats[0];
}
/**
* @brief Get Y value
* @return the y value
*/
const T& getY() const {
return m_floats[1];
}
/**
* @brief Get Z value
* @return the z value
*/
const T& getZ() const {
return m_floats[2];
}
/**
* @brief Get W value
* @return the w value
*/
const T& getW() const {
return m_floats[3];
}
/**
* @brief Set the x value
* @param[in] _x New value
*/
void setX(T _x) {
m_floats[0] = _x;
};
/**
* @brief Set the y value
* @param[in] _y New value
*/
void setY(T _y) {
m_floats[1] = _y;
};
/**
* @brief Set the z value
* @param[in] _z New value
*/
void setZ(T _z) {
m_floats[2] = _z;
};
/**
* @brief Set the w value
* @param[in] _w New value
*/
void setW(T _w) {
m_floats[3] = _w;
};
/**
* @brief Get X value
* @return the x value
*/
const T& x() const {
return m_floats[0];
}
/**
* @brief Get Y value
* @return the y value
*/
const T& y() const {
return m_floats[1];
}
/**
* @brief Get Z value
* @return the z value
*/
const T& z() const {
return m_floats[2];
}
/**
* @brief Get W value
* @return the w value
*/
const T& w() const {
return m_floats[3];
}
/**
* @brief Cast the vector in the type T* requested.
* @return Pointer on the data
*/
operator T *() {
return &m_floats[0];
}
/**
* @brief Cast the vector in the type const T* requested.
* @return Pointer on the const data
*/
operator const T *() const {
return &m_floats[0];
}
/**
* @brief Equality compare operator with an other object.
* @param[in] _obj Reference on the comparing object
* @return true The Objects are identical
* @return false The Objects are NOT identical
*/
bool operator==(const Vector4D<T>& _obj) const {
return ( (m_floats[3] == _obj.m_floats[3])
&& (m_floats[2] == _obj.m_floats[2])
&& (m_floats[1] == _obj.m_floats[1])
&& (m_floats[0] == _obj.m_floats[0]));
}
/**
* @brief In-Equality compare operator with an other object.
* @param[in] _obj Reference on the comparing object
* @return true The Objects are NOT identical
* @return false The Objects are identical
*/
bool operator!=(const Vector4D<T>& _obj) const {
return ( (m_floats[3] != _obj.m_floats[3])
|| (m_floats[2] != _obj.m_floats[2])
|| (m_floats[1] != _obj.m_floats[1])
|| (m_floats[0] != _obj.m_floats[0]));
}
/**
* @brief Set each element to the max of the current values and the values of another Vector
* @param _obj The other Vector to compare with
*/
void setMax(const Vector4D<T>& _obj) {
btSetMax(m_floats[0], _obj.m_floats[0]);
btSetMax(m_floats[1], _obj.m_floats[1]);
btSetMax(m_floats[2], _obj.m_floats[2]);
btSetMax(m_floats[3], _obj.m_floats[3]);
}
/**
* @brief Set each element to the min of the current values and the values of another Vector
* @param _obj The other Vector to compare with
*/
void setMin(const Vector4D<T>& _obj) {
btSetMin(m_floats[0], _obj.m_floats[0]);
btSetMin(m_floats[1], _obj.m_floats[1]);
btSetMin(m_floats[2], _obj.m_floats[2]);
btSetMin(m_floats[3], _obj.m_floats[3]);
}
/**
* @brief Set Value on the vector
* @param[in] _xxx X value.
* @param[in] _yyy Y value.
* @param[in] _zzz Z value.
* @param[in] _www W value.
*/
void setValue(const T& _xxx, const T& _yyy, const T& _zzz, const T& _www) {
m_floats[0]=_xxx;
m_floats[1]=_yyy;
m_floats[2]=_zzz;
m_floats[3]=_www;
}
/**
* @brief Set 0 value on all the vector
*/
void setZero() {
setValue(0,0,0,0);
}
/**
* @brief Check if the vector is equal to (0,0,0,0)
* @return true The value is equal to (0,0,0,0)
* @return false The value is NOT equal to (0,0,0,0)
*/
bool isZero() const {
return m_floats[0] == 0
&& m_floats[1] == 0
&& m_floats[2] == 0
&& m_floats[3] == 0;
}
};
//! @not_in_doc
std::ostream& operator <<(std::ostream& _os, const etk::Vector4D<int32_t>& _obj);
//! @not_in_doc
std::ostream& operator <<(std::ostream& _os, const etk::Vector4D<float>& _obj);
//! @not_in_doc
std::ostream& operator <<(std::ostream& _os, const etk::Vector4D<uint32_t>& _obj);
//! @not_in_doc
std::ostream& operator <<(std::ostream& _os, const etk::Vector4D<bool>& _obj);
}
// To siplify the writing of the code ==> this permit to have the same name with the glsl language...
using vec4 = etk::Vector4D<float>; //!< wrapper on etk::Vector4D<float> to have the same naming has OpenGL shader
using ivec4 = etk::Vector4D<int32_t>; //!< wrapper on etk::Vector4D<int32_t> to have the same naming has OpenGL shader
// not compatible with glsl ... but it is better to have a same writing
using uivec4 = etk::Vector4D<uint32_t>; //!< wrapper on etk::Vector4D<uint32_t> to have the same naming has OpenGL shader
using bvec4 = etk::Vector4D<bool>; //!< wrapper on etk::Vector4D<bool> to have the same naming has OpenGL shader