Kaynağa Gözat

math: support all Tait-Bryan angle combinations in quaternions.

legacy
Sam Hocevar sam 12 yıl önce
ebeveyn
işleme
e1d0beae1a
2 değiştirilmiş dosya ile 91 ekleme ve 12 silme
  1. +21
    -2
      src/lol/math/vector.h
  2. +70
    -10
      src/math/vector.cpp

+ 21
- 2
src/lol/math/vector.h Dosyayı Görüntüle

@@ -925,8 +925,27 @@ template <typename T> struct Quat

static Quat<T> rotate(T angle, T x, T y, T z);
static Quat<T> rotate(T angle, Vec3<T> const &v);
static Quat<T> fromeuler(T x, T y, T z);
static Quat<T> fromeuler(Vec3<T> const &v);

/* Convert from Tait-Bryan angles (incorrectly called Euler angles,
* but since everyone does it…). The axes in fromeuler_xyz are
* x, then y', then z", ie. the axes are attached to the model.
* If you want to apply yaw around x, pitch around y, and roll
* around z, use fromeuler_xyz.
* If you want to rotate around static axes, reverse the order in
* the function name (_zyx instead of _xyz) AND reverse the order
* of the arguments. */
static Quat<T> fromeuler_xyz(Vec3<T> const &v);
static Quat<T> fromeuler_xzy(Vec3<T> const &v);
static Quat<T> fromeuler_yxz(Vec3<T> const &v);
static Quat<T> fromeuler_yzx(Vec3<T> const &v);
static Quat<T> fromeuler_zxy(Vec3<T> const &v);
static Quat<T> fromeuler_zyx(Vec3<T> const &v);
static Quat<T> fromeuler_xyz(T phi, T theta, T psi);
static Quat<T> fromeuler_xzy(T phi, T theta, T psi);
static Quat<T> fromeuler_yxz(T phi, T theta, T psi);
static Quat<T> fromeuler_yzx(T phi, T theta, T psi);
static Quat<T> fromeuler_zxy(T phi, T theta, T psi);
static Quat<T> fromeuler_zyx(T phi, T theta, T psi);

inline Quat<T> operator *(Quat<T> const &val) const
{


+ 70
- 10
src/math/vector.cpp Dosyayı Görüntüle

@@ -538,25 +538,85 @@ template<> mat3 mat3::fromeuler(float x, float y, float z)
return mat3::fromeuler(vec3(x, y, z));
}

template<> quat quat::fromeuler(vec3 const &v)
static inline quat fromeuler_generic(vec3 const &v, int s, int i, int j, int k)
{
using std::sin;
using std::cos;

vec3 half_angles = (M_PI / 360.0f) * v;
float sx = sin(half_angles.x), cx = cos(half_angles.x);
float sy = sin(half_angles.y), cy = cos(half_angles.y);
float sz = sin(half_angles.z), cz = cos(half_angles.z);
float s0 = sin(half_angles[0]), c0 = cos(half_angles[0]);
float s1 = sin(half_angles[1]), c1 = cos(half_angles[1]);
float s2 = sin(half_angles[2]), c2 = cos(half_angles[2]);

return quat(cx * cy * cz + sx * sy * sz,
sx * cy * cz - cx * sy * sz,
cx * sy * cz + sx * cy * sz,
cx * cy * sz - sx * sy * cz);
vec4 v1(c0 * c1 * c2, c0 * c1 * s2, c0 * s1 * c2, s0 * c1 * c2);
vec4 v2(s0 * s1 * s2, -s0 * s1 * c2, s0 * c1 * s2, -c0 * s1 * s2);

if (s > 0)
v1 += v2;
else
v1 -= v2;

return quat(v1[0], v1[i], v1[j], v1[k]);
}

template<> quat quat::fromeuler_xyz(vec3 const &v)
{
return fromeuler_generic(v, -1, 3, 2, 1);
}

template<> quat quat::fromeuler_xzy(vec3 const &v)
{
return fromeuler_generic(v, 1, 3, 1, 2);
}

template<> quat quat::fromeuler_yxz(vec3 const &v)
{
return fromeuler_generic(v, 1, 2, 3, 1);
}

template<> quat quat::fromeuler_yzx(vec3 const &v)
{
return fromeuler_generic(v, -1, 1, 3, 2);
}

template<> quat quat::fromeuler_zxy(vec3 const &v)
{
return fromeuler_generic(v, -1, 2, 1, 3);
}

template<> quat quat::fromeuler_zyx(vec3 const &v)
{
return fromeuler_generic(v, 1, 1, 2, 3);
}

template<> quat quat::fromeuler_xyz(float phi, float theta, float psi)
{
return quat::fromeuler_zyx(vec3(phi, theta, psi));
}

template<> quat quat::fromeuler_xzy(float phi, float theta, float psi)
{
return quat::fromeuler_yxz(vec3(phi, theta, psi));
}

template<> quat quat::fromeuler_yxz(float phi, float theta, float psi)
{
return quat::fromeuler_yxz(vec3(phi, theta, psi));
}

template<> quat quat::fromeuler_yzx(float phi, float theta, float psi)
{
return quat::fromeuler_yxz(vec3(phi, theta, psi));
}

template<> quat quat::fromeuler_zxy(float phi, float theta, float psi)
{
return quat::fromeuler_yxz(vec3(phi, theta, psi));
}

template<> quat quat::fromeuler(float x, float y, float z)
template<> quat quat::fromeuler_zyx(float phi, float theta, float psi)
{
return quat::fromeuler(vec3(x, y, z));
return quat::fromeuler_yxz(vec3(phi, theta, psi));
}

template<> mat4 mat4::lookat(vec3 eye, vec3 center, vec3 up)


Yükleniyor…
İptal
Kaydet