Changeset 1351


Ignore:
Timestamp:
May 9, 2012, 12:03:01 AM (7 years ago)
Author:
sam
Message:

math: implement quaternion creation from true Euler angles (as opposed
to the Tait-Bryan angles we had for now). Also, change quaternion storage
order to wxyz in order to match the constructors.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/orbital/orbital.cpp

    r1350 r1351  
    115115    //Doing the query with actual values, cause I want to stay SDL-free for now.
    116116
     117    int HMovement = Input::GetButtonState(275 /*SDLK_RIGHT*/) - Input::GetButtonState(276 /*SDLK_LEFT*/);
    117118    int VMovement = Input::GetButtonState(274 /*SDLK_DOWN*/) - Input::GetButtonState(273 /*SDLK_UP*/);
    118     int HMovement = Input::GetButtonState(275 /*SDLK_RIGHT*/) - Input::GetButtonState(276 /*SDLK_LEFT*/);
    119119    int RMovement = Input::GetButtonState(280 /*SDLK_PAGEUP*/) - Input::GetButtonState(281 /*SDLK_PAGEDOWN*/);
    120120
     
    146146    }
    147147
    148     /* Yaw around Y, Pitch around X, Roll around Z */
    149     mat4 anim = mat4(quat::fromeuler_zxy(m_angle.zyx));
     148    /* Yaw around Y, Pitch around X, Roll around Z. Since it's the camera
     149     * we want to move, use the inverse transform. */
     150    mat4 anim = mat4(1.f / quat::fromeuler_yxz(m_angle));
    150151#endif
    151152
  • trunk/src/lol/math/vector.h

    r1350 r1351  
    126126 */
    127127
    128 #define DECLARE_MEMBER_OPS(tname) \
    129     inline T& operator[](size_t n) { return *(&this->x + n); } \
    130     inline T const& operator[](size_t n) const { return *(&this->x + n); } \
     128#define DECLARE_MEMBER_OPS(tname, first) \
     129    inline T& operator[](size_t n) { return *(&this->first + n); } \
     130    inline T const& operator[](size_t n) const { return *(&this->first + n); } \
    131131    \
    132132    /* Visual Studio insists on having an assignment operator. */ \
     
    234234      : BVec2<T>(v[0], v[1]) {}
    235235
    236     DECLARE_MEMBER_OPS(Vec2)
     236    DECLARE_MEMBER_OPS(Vec2, x)
    237237
    238238#if !defined __ANDROID__
     
    252252    inline Cmplx(T X, T Y) : x(X), y(Y) {}
    253253
    254     DECLARE_MEMBER_OPS(Cmplx)
     254    DECLARE_MEMBER_OPS(Cmplx, x)
    255255
    256256    inline Cmplx<T> operator *(Cmplx<T> const &val) const
     
    492492    static Vec3<T> toeuler(Quat<T> const &q);
    493493
    494     DECLARE_MEMBER_OPS(Vec3)
     494    DECLARE_MEMBER_OPS(Vec3, x)
    495495
    496496#if !defined __ANDROID__
     
    901901      : BVec4<T>(v[0], v[1], v[2], v[3]) {}
    902902
    903     DECLARE_MEMBER_OPS(Vec4)
     903    DECLARE_MEMBER_OPS(Vec4, x)
    904904
    905905#if !defined __ANDROID__
     
    916916{
    917917    inline Quat() {}
    918     inline Quat(T W) : x(0), y(0), z(0), w(W) {}
    919     inline Quat(T W, T X, T Y, T Z) : x(X), y(Y), z(Z), w(W) {}
     918    inline Quat(T W) : w(W),  x(0), y(0), z(0) {}
     919    inline Quat(T W, T X, T Y, T Z) : w(W), x(X), y(Y), z(Z) {}
    920920
    921921    Quat(Mat3<T> const &m);
    922922    Quat(Mat4<T> const &m);
    923923
    924     DECLARE_MEMBER_OPS(Quat)
     924    DECLARE_MEMBER_OPS(Quat, w)
    925925
    926926    static Quat<T> rotate(T angle, T x, T y, T z);
    927927    static Quat<T> rotate(T angle, Vec3<T> const &v);
     928
     929    /* Convert from Euler angles. The axes in fromeuler_xyx are
     930     * x, then y', then x", ie. the axes are attached to the model.
     931     * If you want to rotate around static axes, just reverse the order
     932     * of the arguments. */
     933    static Quat<T> fromeuler_xyx(Vec3<T> const &v);
     934    static Quat<T> fromeuler_xzx(Vec3<T> const &v);
     935    static Quat<T> fromeuler_yxy(Vec3<T> const &v);
     936    static Quat<T> fromeuler_yzy(Vec3<T> const &v);
     937    static Quat<T> fromeuler_zxz(Vec3<T> const &v);
     938    static Quat<T> fromeuler_zyz(Vec3<T> const &v);
     939    static Quat<T> fromeuler_xyx(T phi, T theta, T psi);
     940    static Quat<T> fromeuler_xzx(T phi, T theta, T psi);
     941    static Quat<T> fromeuler_yxy(T phi, T theta, T psi);
     942    static Quat<T> fromeuler_yzy(T phi, T theta, T psi);
     943    static Quat<T> fromeuler_zxz(T phi, T theta, T psi);
     944    static Quat<T> fromeuler_zyz(T phi, T theta, T psi);
    928945
    929946    /* Convert from Tait-Bryan angles (incorrectly called Euler angles,
     
    979996#endif
    980997
    981     /* Storage order is still xyzw because operator[] uses &this->x */
    982     T x, y, z, w;
     998    /* XXX: storage order is wxyz, unlike vectors! */
     999    T w, x, y, z;
    9831000};
    9841001
  • trunk/src/math/vector.cpp

    r1350 r1351  
    539539}
    540540
    541 static inline quat fromeuler_generic(vec3 const &v, int s, int i, int j, int k)
     541static inline quat quat_fromeuler_generic(vec3 const &v, int i, int j, int k)
    542542{
    543543    using std::sin;
     
    549549    float s2 = sin(half_angles[2]), c2 = cos(half_angles[2]);
    550550
    551     vec4 v1(c0 * c1 * c2,  c0 * c1 * s2, c0 * s1 * c2,  s0 * c1 * c2);
    552     vec4 v2(s0 * s1 * s2, -s0 * s1 * c2, s0 * c1 * s2, -c0 * s1 * s2);
    553 
    554     if (s > 0)
    555         v1 += v2;
     551    quat ret;
     552
     553    if (i == k)
     554    {
     555        ret[0] = c1 * (c0 * c2 - s0 * s2);
     556        ret[1 + i] = c1 * (c0 * s2 + s0 * c2);
     557        ret[1 + j] = s1 * (c0 * c2 + s0 * s2);
     558        if ((2 + i - j) % 3)
     559            ret[4 - i - j] = s1 * (s0 * c2 - c0 * s2);
     560        else
     561            ret[4 - i - j] = s1 * (c0 * s2 - s0 * c2);
     562    }
    556563    else
    557         v1 -= v2;
    558 
    559     return quat(v1[0], v1[i], v1[j], v1[k]);
    560 }
    561 
    562 template<> quat quat::fromeuler_xyz(vec3 const &v)
    563 {
    564     return fromeuler_generic(v, -1, 3, 2, 1);
    565 }
    566 
    567 template<> quat quat::fromeuler_xzy(vec3 const &v)
    568 {
    569     return fromeuler_generic(v, 1, 3, 1, 2);
    570 }
    571 
    572 template<> quat quat::fromeuler_yxz(vec3 const &v)
    573 {
    574     return fromeuler_generic(v, 1, 2, 3, 1);
    575 }
    576 
    577 template<> quat quat::fromeuler_yzx(vec3 const &v)
    578 {
    579     return fromeuler_generic(v, -1, 1, 3, 2);
    580 }
    581 
    582 template<> quat quat::fromeuler_zxy(vec3 const &v)
    583 {
    584     return fromeuler_generic(v, -1, 2, 1, 3);
    585 }
    586 
    587 template<> quat quat::fromeuler_zyx(vec3 const &v)
    588 {
    589     return fromeuler_generic(v, 1, 1, 2, 3);
    590 }
    591 
    592 template<> quat quat::fromeuler_xyz(float phi, float theta, float psi)
    593 {
    594     return quat::fromeuler_zyx(vec3(phi, theta, psi));
    595 }
    596 
    597 template<> quat quat::fromeuler_xzy(float phi, float theta, float psi)
    598 {
    599     return quat::fromeuler_yxz(vec3(phi, theta, psi));
    600 }
    601 
    602 template<> quat quat::fromeuler_yxz(float phi, float theta, float psi)
    603 {
    604     return quat::fromeuler_yxz(vec3(phi, theta, psi));
    605 }
    606 
    607 template<> quat quat::fromeuler_yzx(float phi, float theta, float psi)
    608 {
    609     return quat::fromeuler_yxz(vec3(phi, theta, psi));
    610 }
    611 
    612 template<> quat quat::fromeuler_zxy(float phi, float theta, float psi)
    613 {
    614     return quat::fromeuler_yxz(vec3(phi, theta, psi));
    615 }
    616 
    617 template<> quat quat::fromeuler_zyx(float phi, float theta, float psi)
    618 {
    619     return quat::fromeuler_yxz(vec3(phi, theta, psi));
    620 }
     564    {
     565        vec4 v1(c0 * c1 * c2,  s0 * c1 * c2, c0 * s1 * c2,  c0 * c1 * s2);
     566        vec4 v2(s0 * s1 * s2, -c0 * s1 * s2, s0 * c1 * s2, -s0 * s1 * c2);
     567
     568        if ((2 + i - j) % 3)
     569            v1 -= v2;
     570        else
     571            v1 += v2;
     572
     573        ret[0] = v1[0];
     574        ret[1 + i] = v1[1];
     575        ret[1 + j] = v1[2];
     576        ret[4 - i - j] = v1[3];
     577    }
     578
     579    return ret;
     580}
     581
     582#define QUAT_FROMEULER_GENERIC(name, i, j, k) \
     583    template<> quat quat::fromeuler_##name(vec3 const &v) \
     584    { \
     585        return quat_fromeuler_generic(v, i, j, k); \
     586    } \
     587    \
     588    template<> quat quat::fromeuler_##name(float phi, float theta, float psi) \
     589    { \
     590        return quat::fromeuler_##name(vec3(phi, theta, psi)); \
     591    }
     592
     593QUAT_FROMEULER_GENERIC(xyx, 0, 1, 0)
     594QUAT_FROMEULER_GENERIC(xzx, 0, 2, 0)
     595QUAT_FROMEULER_GENERIC(yxy, 1, 0, 1)
     596QUAT_FROMEULER_GENERIC(yzy, 1, 2, 1)
     597QUAT_FROMEULER_GENERIC(zxz, 2, 0, 2)
     598QUAT_FROMEULER_GENERIC(zyz, 2, 1, 2)
     599
     600QUAT_FROMEULER_GENERIC(xyz, 0, 1, 2)
     601QUAT_FROMEULER_GENERIC(xzy, 0, 2, 1)
     602QUAT_FROMEULER_GENERIC(yxz, 1, 0, 2)
     603QUAT_FROMEULER_GENERIC(yzx, 1, 2, 0)
     604QUAT_FROMEULER_GENERIC(zxy, 2, 0, 1)
     605QUAT_FROMEULER_GENERIC(zyx, 2, 1, 0)
     606
     607#undef QUAT_FROMEULER_GENERIC
    621608
    622609template<> mat4 mat4::lookat(vec3 eye, vec3 center, vec3 up)
Note: See TracChangeset for help on using the changeset viewer.