I am writing a header file on C++ that implements interaction with quaternion. Quaternion can be interpreted as a + bi + cj + dk
, so its components are stored in m_value
in b, c, d, a
order. I also support representing a quaternion as a scalar-vector. I’ve noticed that in method updateComponents()
I use 2x more memory than I actually need. How can I fix that? m_value
and scalar-vector representation are required.
#ifndef QUAT_HPP
#define QUAT_HPP
#include <cmath>
template< typename T >
struct matrix_t
{
T data[16];
};
template< typename T >
struct vector3_t
{
T x, y, z;
};
template< typename T >
class Quat
{
public:
Quat() : scalar(0), vector{0, 0, 0}
{
updateComponents();
}
Quat(T a, T b, T c, T d) : scalar(a), vector{b, c, d}
{
updateComponents();
}
Quat(T angle, bool mode, vector3_t< T > axes)
{
if (!mode)
{
angle = angle * M_PI / 180;
}
T norm = std::sqrt(axes.x * axes.x + axes.y * axes.y + axes.z * axes.z);
scalar = std::cos(angle / 2);
vector.x = axes.x / norm * std::sin(angle / 2);
vector.y = axes.y / norm * std::sin(angle / 2);
vector.z = axes.z / norm * std::sin(angle / 2);
updateComponents();
}
const T* data() const { return m_value; };
Quat< T > operator+(const Quat< T >& q2) const
{
return Quat(scalar + q2.scalar, vector.x + q2.vector.x, vector.y + q2.vector.y, vector.z + q2.vector.z);
}
Quat< T >& operator+=(const Quat< T >& q2)
{
*this = *this + q2;
updateComponents();
return *this;
}
Quat< T > operator-(Quat q2) const
{
return Quat(scalar - q2.scalar, vector.x - q2.vector.x, vector.y - q2.vector.y, vector.z - q2.vector.z);
}
Quat< T >& operator-=(Quat q2)
{
*this = *this - q2;
updateComponents();
return *this;
}
Quat< T > operator*(Quat q2) const
{
T a1 = scalar, b1 = vector.x, c1 = vector.y, d1 = vector.z;
T a2 = q2.scalar, b2 = q2.vector.x, c2 = q2.vector.y, d2 = q2.vector.z;
return Quat(
a1 * a2 - b1 * b2 - c1 * c2 - d1 * d2,
a1 * b2 + a2 * b1 + c1 * d2 - c2 * d1,
a1 * c2 + a2 * c1 + d1 * b2 - d2 * b1,
a1 * d2 + a2 * d1 + b1 * c2 - b2 * c1);
}
Quat< T > operator*(T s) const { return Quat(scalar * s, vector.x * s, vector.y * s, vector.z * s); }
Quat< T > operator*(vector3_t< T > vec) const
{
Quat< T > q2 = Quat(0, vec.x, vec.y, vec.z);
return *this * q2;
}
Quat< T > operator~() const { return Quat(scalar, -vector.x, -vector.y, -vector.z); }
bool operator==(Quat q2) const
{
return (scalar == q2.scalar && vector.x == q2.vector.x && vector.y == q2.vector.y && vector.z == q2.vector.z);
}
bool operator!=(Quat q2) const { return !(*this == q2); }
explicit operator T() const
{
return std::sqrt(scalar * scalar + vector.x * vector.x + vector.y * vector.y + vector.z * vector.z);
}
matrix_t< T > rotation_matrix() const
{
Quat< T > q = normalize();
T s = q.scalar, x = q.vector.x, y = q.vector.y, z = q.vector.z;
T r_11 = 1 - 2 * y * y - 2 * z * z, r_12 = 2 * x * y - 2 * z * s, r_13 = 2 * x * z + 2 * y * s,
r_21 = 2 * x * y + 2 * z * s, r_22 = 1 - 2 * x * x - 2 * z * z, r_23 = 2 * y * z - 2 * x * s,
r_31 = 2 * x * z - 2 * y * s, r_32 = 2 * y * z + 2 * x * s, r_33 = 1 - 2 * x * x - 2 * y * y;
return { r_11, r_21, r_31, 0, r_12, r_22, r_32, 0, r_13, r_23, r_33, 0, 0, 0, 0, 1 };
}
matrix_t< T > matrix() const
{
return { scalar, -vector.x, -vector.y, -vector.z, vector.x, scalar, -vector.z, vector.y,
vector.y, vector.z, scalar, -vector.x, vector.z, -vector.y, vector.x, scalar };
}
T angle(bool mode = true) const { return mode ? 2 * std::acos(scalar) : 2 * std::acos(scalar) * 180 / M_PI; }
vector3_t< T > apply(vector3_t< T > vec) const
{
Quat< T > q = normalize();
Quat< T > qv = q * vec;
Quat< T > qq = qv * (~q);
return { qq.vector.x, qq.vector.y, qq.vector.z };
}
private:
T m_value[4];
T scalar;
vector3_t< T > vector;
void updateComponents()
{
m_value[3] = scalar;
m_value[0] = vector.x;
m_value[1] = vector.y;
m_value[2] = vector.z;
}
Quat< T > normalize() const
{
T norm = T(*this);
return *this * (1 / norm);
}
};
#endif
I’ve read about union
, but I think it won’t be as memory efficient as I expect.
John is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.