Changeset 1047


Ignore:
Timestamp:
Nov 1, 2011, 6:55:23 PM (10 years ago)
Author:
sam
Message:

core: implement a quaternion class and tighten some vector operation rules
to avoid common programming errors.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/matrix.cpp

    r1046 r1047  
    5454}
    5555
    56 template<> vec2 normalize(vec2 v)
    57 {
    58     float norm = v.len();
    59     if (!norm)
    60         return vec2(0);
    61     return v / norm;
    62 }
    63 
    64 template<> vec3 normalize(vec3 v)
    65 {
    66     float norm = v.len();
    67     if (!norm)
    68         return vec3(0);
    69     return v / norm;
    70 }
    71 
    72 template<> vec4 normalize(vec4 v)
    73 {
    74     float norm = v.len();
    75     if (!norm)
    76         return vec4(0.0f);
    77     return v / norm;
    78 }
    79 
    8056static inline float det3(float a, float b, float c,
    8157                         float d, float e, float f,
     
    152128}
    153129
     130template<> void quat::printf() const
     131{
     132    Log::Debug("[ %6.6f %6.6f %6.6f %6.6f ]\n", x, y, z, w);
     133}
     134
    154135template<> void mat4::printf() const
    155136{
     
    183164}
    184165
     166template<> std::ostream &operator<<(std::ostream &stream, iquat const &v)
     167{
     168    return stream << "(" << v.x << ", " << v.y << ", "
     169                         << v.z << ", " << v.w << ")";
     170}
     171
    185172template<> std::ostream &operator<<(std::ostream &stream, vec2 const &v)
    186173{
     
    194181
    195182template<> std::ostream &operator<<(std::ostream &stream, vec4 const &v)
     183{
     184    return stream << "(" << v.x << ", " << v.y << ", "
     185                         << v.z << ", " << v.w << ")";
     186}
     187
     188template<> std::ostream &operator<<(std::ostream &stream, quat const &v)
    196189{
    197190    return stream << "(" << v.x << ", " << v.y << ", "
  • trunk/src/matrix.h

    r1046 r1047  
    2525{
    2626
    27 #define VECTOR_OP(elems, op) \
    28     template<typename U> \
    29     inline Vec##elems<T> operator op(Vec##elems<U> const &val) const \
    30     { \
    31         Vec##elems<T> ret; \
    32         for (int n = 0; n < elems; n++) \
     27#define VECTOR_OP(op) \
     28    inline type_t operator op(type_t const &val) const \
     29    { \
     30        type_t ret; \
     31        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
    3332            ret[n] = (*this)[n] op val[n]; \
    3433        return ret; \
    3534    } \
    3635    \
    37     template<typename U> \
    38     inline Vec##elems<T> operator op##=(Vec##elems<U> const &val) \
     36    inline type_t operator op##=(type_t const &val) \
    3937    { \
    4038        return *this = (*this) op val; \
    4139    }
    4240
    43 #define BOOL_OP(elems, op, op2, ret) \
    44     inline bool operator op(Vec##elems<T> const &val) const \
    45     { \
    46         for (int n = 0; n < elems; n++) \
     41#define BOOL_OP(op, op2, ret) \
     42    inline bool operator op(type_t const &val) const \
     43    { \
     44        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
    4745            if (!((*this)[n] op2 val[n])) \
    4846                return !ret; \
     
    5048    }
    5149
    52 #define SCALAR_OP(elems, op) \
    53     inline Vec##elems<T> operator op(T const &val) const \
    54     { \
    55         Vec##elems<T> ret; \
    56         for (int n = 0; n < elems; n++) \
     50#define SCALAR_OP(op) \
     51    inline type_t operator op(T const &val) const \
     52    { \
     53        type_t ret; \
     54        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
    5755            ret[n] = (*this)[n] op val; \
    5856        return ret; \
    5957    } \
    6058    \
    61     inline Vec##elems<T> operator op##=(T const &val) \
     59    inline type_t operator op##=(T const &val) \
    6260    { \
    6361        return *this = (*this) op val; \
    6462    }
    6563
    66 #define LINEAR_OPS(elems) \
     64#define LINEAR_OPS() \
    6765    inline T& operator[](int n) { return *(&x + n); } \
    6866    inline T const& operator[](int n) const { return *(&x + n); } \
    6967    \
    70     VECTOR_OP(elems, -) \
    71     VECTOR_OP(elems, +) \
    72     \
    73     BOOL_OP(elems, ==, ==, true) \
    74     BOOL_OP(elems, !=, ==, false) \
    75     \
    76     SCALAR_OP(elems, *) \
    77     SCALAR_OP(elems, /) \
    78     \
    79     inline Vec##elems<T> operator -() const \
    80     { \
    81         Vec##elems<T> ret; \
    82         for (int n = 0; n < elems; n++) \
     68    VECTOR_OP(-) \
     69    VECTOR_OP(+) \
     70    \
     71    BOOL_OP(==, ==, true) \
     72    BOOL_OP(!=, ==, false) \
     73    \
     74    SCALAR_OP(*) \
     75    SCALAR_OP(/) \
     76    \
     77    inline type_t operator -() const \
     78    { \
     79        type_t ret; \
     80        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
    8381            ret[n] = -(*this)[n]; \
    8482        return ret; \
     
    8886    { \
    8987        T acc = 0; \
    90         for (int n = 0; n < elems; n++) \
     88        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
    9189            acc += (*this)[n] * (*this)[n]; \
    9290        return acc; \
     
    9997    } \
    10098    \
    101     template<typename U> \
    102     friend Vec##elems<U> normalize(Vec##elems<U>); \
    103     \
    10499    void printf() const;
    105100
     101#define QUATERNION_OPS() \
     102    inline type_t operator *(type_t const &val) const \
     103    { \
     104        type_t ret; \
     105        Vec3<T> v1(x, y, z); \
     106        Vec3<T> v2(val.x, val.y, val.z); \
     107        Vec3<T> v3 = cross(v1, v2) + w * v2 + val.w * v1; \
     108        ret.x = v3.x; \
     109        ret.y = v3.y; \
     110        ret.z = v3.z; \
     111        ret.w = w * val.w - dot(v1, v2); \
     112        return ret; \
     113    } \
     114    \
     115    inline type_t operator *=(type_t const &val) \
     116    { \
     117        return *this = (*this) * val; \
     118    } \
     119    \
     120    inline type_t operator ~() const \
     121    { \
     122        type_t ret; \
     123        for (int n = 0; n < 3; n++) \
     124            ret[n] = -(*this)[n]; \
     125        ret[3] = (*this)[3]; \
     126        return ret; \
     127    } \
     128    \
     129    inline T norm() const { return sqlen(); }
     130
    106131#define OTHER_OPS(elems) \
    107     VECTOR_OP(elems, *) \
    108     VECTOR_OP(elems, /) \
    109     \
    110     BOOL_OP(elems, <=, <=, true) \
    111     BOOL_OP(elems, >=, >=, true) \
    112     BOOL_OP(elems, <, <, true) \
    113     BOOL_OP(elems, >, >, true) \
     132    VECTOR_OP(*) \
     133    VECTOR_OP(/) \
     134    \
     135    BOOL_OP(<=, <=, true) \
     136    BOOL_OP(>=, >=, true) \
     137    BOOL_OP(<, <, true) \
     138    BOOL_OP(>, >, true) \
    114139    \
    115140    template<typename U> \
     
    117142    { \
    118143        Vec##elems<U> ret; \
    119         for (int n = 0; n < elems; n++) \
     144        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
    120145            ret[n] = static_cast<U>((*this)[n]); \
    121146        return ret; \
     
    196221template <typename T> struct Vec2
    197222{
     223    typedef Vec2<T> type_t;
     224
    198225    inline Vec2() { }
    199226    explicit inline Vec2(T val) { x = y = val; }
    200227    inline Vec2(T _x, T _y) { x = _x; y = _y; }
    201228
    202     LINEAR_OPS(2)
     229    LINEAR_OPS()
    203230    OTHER_OPS(2)
    204231
     
    233260template <typename T> struct Vec3
    234261{
     262    typedef Vec3<T> type_t;
     263
    235264    inline Vec3() { }
    236265    explicit inline Vec3(T val) { x = y = z = val; }
     
    239268    inline Vec3(T _x, Vec2<T> _yz) { x = _x; y = _yz.x; z = _yz.y; }
    240269
    241     LINEAR_OPS(3)
     270    LINEAR_OPS()
    242271    OTHER_OPS(3)
    243272
     
    276305template <typename T> struct Vec4
    277306{
     307    typedef Vec4<T> type_t;
     308
    278309    inline Vec4() { }
    279310    explicit inline Vec4(T val) : x(val), y(val), z(val), w(val) { }
     
    286317    inline Vec4(T _x, Vec3<T> _yzw) : x(_x), y(_yzw.x), z(_yzw.y), w(_yzw.z) { }
    287318
    288     LINEAR_OPS(4)
     319    LINEAR_OPS()
    289320    OTHER_OPS(4)
    290321
     
    315346typedef Vec4<uint64_t> u64vec4;
    316347
    317 #define SCALAR_GLOBAL(elems, op, U) \
     348/*
     349 * 4-element quaternions
     350 */
     351
     352template <typename T> struct Quat
     353{
     354    typedef Quat<T> type_t;
     355
     356    inline Quat() { }
     357    inline Quat(T val) : x(0), y(0), z(0), w(val) { }
     358    inline Quat(T _x, T _y, T _z, T _w) : x(_x), y(_y), z(_z), w(_w) { }
     359
     360    LINEAR_OPS()
     361    QUATERNION_OPS()
     362
     363#if !defined __ANDROID__
     364    template<typename U>
     365    friend std::ostream &operator<<(std::ostream &stream, Quat<U> const &v);
     366#endif
     367
     368    T x, y, z, w;
     369};
     370
     371template<typename T>
     372static inline Quat<T> re(Quat<T> const &val)
     373{
     374    return ~val / val.norm();
     375}
     376
     377template<typename T>
     378static inline Quat<T> operator /(T x, Quat<T> const &y)
     379{
     380    return x * re(y);
     381}
     382
     383template<typename T>
     384static inline Quat<T> operator /(Quat<T> x, Quat<T> const &y)
     385{
     386    return x * re(y);
     387}
     388
     389typedef Quat<half> f16quat;
     390typedef Quat<float> quat;
     391typedef Quat<int8_t> i8quat;
     392typedef Quat<uint8_t> u8quat;
     393typedef Quat<int16_t> i16quat;
     394typedef Quat<uint16_t> u16quat;
     395typedef Quat<int32_t> iquat;
     396typedef Quat<uint32_t> uquat;
     397typedef Quat<int64_t> i64quat;
     398typedef Quat<uint64_t> u64quat;
     399
     400/*
     401 * Common operators for all vector types, including quaternions
     402 */
     403
     404#define SCALAR_GLOBAL(tname, op, U) \
    318405    template<typename T> \
    319     static inline Vec##elems<U> operator op(U const &val, \
    320                                             Vec##elems<T> const &that) \
    321     { \
    322         Vec##elems<U> ret; \
    323         for (int n = 0; n < elems; n++) \
     406    static inline tname<U> operator op(U const &val, tname<T> const &that) \
     407    { \
     408        tname<U> ret; \
     409        for (unsigned int n = 0; n < sizeof(that) / sizeof(that[0]); n++) \
    324410            ret[n] = val op that[n]; \
    325411        return ret; \
    326412    }
    327413
    328 #define SCALAR_GLOBAL2(elems, op) \
    329     SCALAR_GLOBAL(elems, op, int) \
    330     SCALAR_GLOBAL(elems, op, float)
    331 
    332 #define GLOBALS(elems) \
    333     SCALAR_GLOBAL2(elems, -) \
    334     SCALAR_GLOBAL2(elems, +) \
    335     SCALAR_GLOBAL2(elems, *) \
    336     SCALAR_GLOBAL2(elems, /)
    337 
    338 GLOBALS(2)
    339 GLOBALS(3)
    340 GLOBALS(4)
     414#define SCALAR_GLOBAL2(tname, op) \
     415    SCALAR_GLOBAL(tname, op, int) \
     416    SCALAR_GLOBAL(tname, op, float)
     417
     418#define GLOBALS(tname) \
     419    SCALAR_GLOBAL2(tname, *) \
     420    \
     421    template<typename T> \
     422    static inline tname<T> normalize(tname<T> const &val) \
     423    { \
     424        T norm = val.len(); \
     425        return norm ? val / norm : val * 0; \
     426    }
     427
     428GLOBALS(Vec2)
     429GLOBALS(Vec3)
     430GLOBALS(Vec4)
     431GLOBALS(Quat)
    341432
    342433/*
     
    346437template <typename T> struct Mat4
    347438{
     439    typedef Mat4<T> type_t;
     440
    348441    inline Mat4() { }
    349442    explicit inline Mat4(T val)
  • trunk/test/Makefile.am

    r1043 r1047  
    2525testsuite_SOURCES = testsuite.cpp \
    2626    unit/matrix.cpp unit/half.cpp unit/trig.cpp unit/build.cpp \
    27     unit/real.cpp unit/image.cpp
     27    unit/real.cpp unit/image.cpp unit/quat.cpp
    2828testsuite_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@
    2929testsuite_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@
Note: See TracChangeset for help on using the changeset viewer.