Changeset 2915


Ignore:
Timestamp:
Sep 14, 2013, 4:01:38 PM (6 years ago)
Author:
sam
Message:

math: add lol::sq() square function and simplify quaternion conversions.

Location:
trunk/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/lol/math/functions.h

    r2816 r2915  
    168168
    169169#define LOL_GENERIC_FUNC(T) \
     170    static inline T sq(T x) { return x * x; } \
    170171    static inline T fract(T x) { return x - lol::floor(x); } \
    171172    static inline T min(T x, T y) { return std::min(x, y); } \
  • trunk/src/math/vector.cpp

    r2914 r2915  
    538538        return vec3(0.f);
    539539
    540     vec3 v(q.x, q.y, q.z), ret;
     540    /* (2 + i - j) % 3 means x-y-z direct order; otherwise indirect */
     541    float const sign = ((2 + i - j) % 3) ? 1.f : -1.f;
     542
     543    vec3 ret;
    541544
    542545    if (i != k)
    543546    {
    544         if ((2 + i - j) % 3)
    545         {
    546             ret[0] = atan2(2.f * (q.w * v[i] - v[j] * v[k]),
    547                            1.f - 2.f * (v[i] * v[i] + v[j] * v[j]));
    548             ret[1] = asin(2.f * (q.w * v[j] + v[i] * v[k]));
    549             ret[2] = atan2(2.f * (q.w * v[k] - v[j] * v[i]),
    550                            1.f - 2.f * (v[k] * v[k] + v[j] * v[j]));
    551         }
    552         else
    553         {
    554             ret[0] = atan2(2.f * (q.w * v[i] + v[j] * v[k]),
    555                            1.f - 2.f * (v[i] * v[i] + v[j] * v[j]));
    556             ret[1] = asin(2.f * (q.w * v[j] - v[i] * v[k]));
    557             ret[2] = atan2(2.f * (q.w * v[k] + v[j] * v[i]),
    558                            1.f - 2.f * (v[k] * v[k] + v[j] * v[j]));
    559         }
     547        ret[0] = atan2(2.f * (q.w * q[1 + i] - sign * (q[1 + j] * q[1 + k])),
     548                       1.f - 2.f * (sq(q[1 + i]) + sq(q[1 + j])));
     549        ret[1] = asin(2.f * (q.w * q[1 + j] + sign * (q[1 + i] * q[1 + k])));
     550        ret[2] = atan2(2.f * (q.w * q[1 + k] - sign * (q[1 + j] * q[1 + i])),
     551                       1.f - 2.f * (sq(q[1 + k]) + sq(q[1 + j])));
    560552    }
    561553    else
     
    571563    mat3 ret;
    572564
    573     vec3 radians = (F_PI / 180.0f) * v;
    574     float s0 = sin(radians[0]), c0 = cos(radians[0]);
    575     float s1 = sin(radians[1]), c1 = cos(radians[1]);
    576     float s2 = sin(radians[2]), c2 = cos(radians[2]);
    577 
     565    vec3 const radians = (F_PI / 180.0f) * v;
     566    float const s0 = sin(radians[0]), c0 = cos(radians[0]);
     567    float const s1 = sin(radians[1]), c1 = cos(radians[1]);
     568    float const s2 = sin(radians[2]), c2 = cos(radians[2]);
     569
     570    /* (2 + i - j) % 3 means x-y-z direct order; otherwise indirect */
     571    float const sign = ((2 + i - j) % 3) ? 1.f : -1.f;
     572
     573    /* k == i means X-Y-X style Euler angles; otherwise we’re
     574     * actually handling X-Y-Z style Tait-Bryan angles. */
    578575    if (k == i)
    579576    {
     
    581578
    582579        ret[i][i] =   c1;
     580        ret[i][j] =   s0 * s1;
     581        ret[i][k] = - sign * (c0 * s1);
     582
    583583        ret[j][i] =   s1 * s2;
    584         ret[i][j] =   s0 * s1;
    585584        ret[j][j] =   c0 * c2 - s0 * c1 * s2;
     585        ret[j][k] =   sign * (s0 * c2 + c0 * c1 * s2);
     586
     587        ret[k][i] =   sign * (s1 * c2);
     588        ret[k][j] = - sign * (c0 * s2 + s0 * c1 * c2);
    586589        ret[k][k] = - s0 * s2 + c0 * c1 * c2;
    587 
    588         if ((2 + i - j) % 3)
    589         {
    590             ret[k][i] =   s1 * c2;
    591             ret[k][j] = - c0 * s2 - s0 * c1 * c2;
    592             ret[i][k] = - c0 * s1;
    593             ret[j][k] =   s0 * c2 + c0 * c1 * s2;
    594         }
    595         else
    596         {
    597             ret[k][i] = - s1 * c2;
    598             ret[k][j] =   c0 * s2 + s0 * c1 * c2;
    599             ret[i][k] =   c0 * s1;
    600             ret[j][k] = - s0 * c2 - c0 * c1 * s2;
    601         }
    602590    }
    603591    else
    604592    {
    605593        ret[i][i] =   c1 * c2;
     594        ret[i][j] =   sign * (c0 * s2) + s0 * s1 * c2;
     595        ret[i][k] =   s0 * s2 - sign * (c0 * s1 * c2);
     596
     597        ret[j][i] = - sign * (c1 * s2);
     598        ret[j][j] =   c0 * c2 - sign * (s0 * s1 * s2);
     599        ret[j][k] =   sign * (s0 * c2) + c0 * s1 * s2;
     600
     601        ret[k][i] =   sign * s1;
     602        ret[k][j] = - sign * (s0 * c1);
    606603        ret[k][k] =   c0 * c1;
    607 
    608         if ((2 + i - j) % 3)
    609         {
    610             ret[j][i] = - c1 * s2;
    611             ret[k][i] =   s1;
    612 
    613             ret[i][j] =   c0 * s2 + s0 * s1 * c2;
    614             ret[j][j] =   c0 * c2 - s0 * s1 * s2;
    615             ret[k][j] = - s0 * c1;
    616 
    617             ret[i][k] =   s0 * s2 - c0 * s1 * c2;
    618             ret[j][k] =   s0 * c2 + c0 * s1 * s2;
    619         }
    620         else
    621         {
    622             ret[j][i] =   c1 * s2;
    623             ret[k][i] = - s1;
    624 
    625             ret[i][j] = - c0 * s2 + s0 * s1 * c2;
    626             ret[j][j] =   c0 * c2 + s0 * s1 * s2;
    627             ret[k][j] =   s0 * c1;
    628 
    629             ret[i][k] =   s0 * s2 + c0 * s1 * c2;
    630             ret[j][k] = - s0 * c2 + c0 * s1 * s2;
    631         }
    632604    }
    633605
     
    637609static inline quat quat_fromeuler_generic(vec3 const &v, int i, int j, int k)
    638610{
    639     vec3 half_angles = (F_PI / 360.0f) * v;
    640     float s0 = sin(half_angles[0]), c0 = cos(half_angles[0]);
    641     float s1 = sin(half_angles[1]), c1 = cos(half_angles[1]);
    642     float s2 = sin(half_angles[2]), c2 = cos(half_angles[2]);
     611    vec3 const half_angles = (F_PI / 360.0f) * v;
     612    float const s0 = sin(half_angles[0]), c0 = cos(half_angles[0]);
     613    float const s1 = sin(half_angles[1]), c1 = cos(half_angles[1]);
     614    float const s2 = sin(half_angles[2]), c2 = cos(half_angles[2]);
    643615
    644616    quat ret;
    645617
     618    /* (2 + i - j) % 3 means x-y-z direct order; otherwise indirect */
     619    float const sign = ((2 + i - j) % 3) ? 1.f : -1.f;
     620
     621    /* k == i means X-Y-X style Euler angles; otherwise we’re
     622     * actually handling X-Y-Z style Tait-Bryan angles. */
    646623    if (k == i)
    647624    {
     
    651628        ret[1 + i] = c1 * (c0 * s2 + s0 * c2);
    652629        ret[1 + j] = s1 * (c0 * c2 + s0 * s2);
    653         ret[1 + k] = ((2 + i - j) % 3) ? s1 * (s0 * c2 - c0 * s2)
    654                                        : s1 * (c0 * s2 - s0 * c2);
     630        ret[1 + k] = sign * (s0 * c2 - c0 * s2);
    655631    }
    656632    else
     
    659635        vec4 v2(s0 * s1 * s2, -c0 * s1 * s2, s0 * c1 * s2, -s0 * s1 * c2);
    660636
    661         if ((2 + i - j) % 3)
    662             v1 -= v2;
    663         else
    664             v1 += v2;
    665 
    666         ret[0] = v1[0];
    667         ret[1 + i] = v1[1];
    668         ret[1 + j] = v1[2];
    669         ret[1 + k] = v1[3];
    670     }
    671 
    672     return ret;
    673 }
    674 
    675 #define DEFINE_FROMEULER_GENERIC(name, i, j, k) \
     637        ret[0] = v1[0] + sign * v2[0];
     638        ret[1 + i] = v1[1] + sign * v2[1];
     639        ret[1 + j] = v1[2] + sign * v2[2];
     640        ret[1 + k] = v1[3] + sign * v2[3];
     641    }
     642
     643    return ret;
     644}
     645
     646#define DEFINE_GENERIC_EULER_CONVERSIONS(name, i, j, k) \
    676647    /* Create quaternions from Euler angles */ \
    677648    template<> quat quat::fromeuler_##name(vec3 const &v) \
     
    713684    }
    714685
    715 DEFINE_FROMEULER_GENERIC(xyx, 0, 1, 0)
    716 DEFINE_FROMEULER_GENERIC(xzx, 0, 2, 0)
    717 DEFINE_FROMEULER_GENERIC(yxy, 1, 0, 1)
    718 DEFINE_FROMEULER_GENERIC(yzy, 1, 2, 1)
    719 DEFINE_FROMEULER_GENERIC(zxz, 2, 0, 2)
    720 DEFINE_FROMEULER_GENERIC(zyz, 2, 1, 2)
    721 
    722 DEFINE_FROMEULER_GENERIC(xyz, 0, 1, 2)
    723 DEFINE_FROMEULER_GENERIC(xzy, 0, 2, 1)
    724 DEFINE_FROMEULER_GENERIC(yxz, 1, 0, 2)
    725 DEFINE_FROMEULER_GENERIC(yzx, 1, 2, 0)
    726 DEFINE_FROMEULER_GENERIC(zxy, 2, 0, 1)
    727 DEFINE_FROMEULER_GENERIC(zyx, 2, 1, 0)
    728 
    729 #undef DEFINE_FROMEULER_GENERIC
     686DEFINE_GENERIC_EULER_CONVERSIONS(xyx, 0, 1, 0)
     687DEFINE_GENERIC_EULER_CONVERSIONS(xzx, 0, 2, 0)
     688DEFINE_GENERIC_EULER_CONVERSIONS(yxy, 1, 0, 1)
     689DEFINE_GENERIC_EULER_CONVERSIONS(yzy, 1, 2, 1)
     690DEFINE_GENERIC_EULER_CONVERSIONS(zxz, 2, 0, 2)
     691DEFINE_GENERIC_EULER_CONVERSIONS(zyz, 2, 1, 2)
     692
     693DEFINE_GENERIC_EULER_CONVERSIONS(xyz, 0, 1, 2)
     694DEFINE_GENERIC_EULER_CONVERSIONS(xzy, 0, 2, 1)
     695DEFINE_GENERIC_EULER_CONVERSIONS(yxz, 1, 0, 2)
     696DEFINE_GENERIC_EULER_CONVERSIONS(yzx, 1, 2, 0)
     697DEFINE_GENERIC_EULER_CONVERSIONS(zxy, 2, 0, 1)
     698DEFINE_GENERIC_EULER_CONVERSIONS(zyx, 2, 1, 0)
     699
     700#undef DEFINE_GENERIC_EULER_CONVERSIONS
    730701
    731702template<> mat4 mat4::lookat(vec3 eye, vec3 center, vec3 up)
Note: See TracChangeset for help on using the changeset viewer.