mat3.h File Reference

Go to the documentation of this file. Source: include/ffw/graphics/mat3.h

/* This file is part of FineFramework project */
#ifndef FFW_MAT3X3
#define FFW_MAT3X3

#include <cstring>
#include "vec3.h"
#include "quaternion.h"

namespace ffw {
    template <class T> struct Mat3x3 {
    public:
        T ptr[9];

        inline Mat3x3() {
            ptr[0] = 1.0f;  ptr[3] = 0.0f;  ptr[6] = 0.0f;
            ptr[1] = 0.0f;  ptr[4] = 1.0f;  ptr[7] = 0.0f;
            ptr[2] = 0.0f;  ptr[5] = 0.0f;  ptr[8] = 1.0f;
        }

        inline Mat3x3(T xx, T yx, T zx,
            T xy, T yy, T zy,
            T xz, T yz, T zz) {
            ptr[0] = xx;    ptr[3] = yx;    ptr[6] = zx;
            ptr[1] = xy;    ptr[4] = yy;    ptr[7] = zy;
            ptr[2] = xz;    ptr[5] = yz;    ptr[8] = zz;
        }

        inline Mat3x3(T val) {
            ptr[0] = val;   ptr[3] = 0.0f;  ptr[6] = 0.0f;
            ptr[1] = 0.0f;  ptr[4] = val;   ptr[7] = 0.0f;
            ptr[2] = 0.0f;  ptr[5] = 0.0f;  ptr[8] = val;
        }

        inline Mat3x3(std::initializer_list<T> list) {
            if (list.size() != 9) {
                ptr[0] = 1.0f;  ptr[3] = 0.0f;  ptr[6] = 0.0f;
                ptr[1] = 0.0f;  ptr[4] = 1.0f;  ptr[7] = 0.0f;
                ptr[2] = 0.0f;  ptr[5] = 0.0f;  ptr[8] = 1.0f;
                return;
            }
            for (int i = 0; i < 9; i++) {
                ptr[i] = *(list.begin() + i);
            }
        }

        inline void set(T xx, T yx, T zx,
            T xy, T yy, T zy,
            T xz, T yz, T zz) {
            ptr[0] = xx;    ptr[3] = yx;    ptr[6] = zx;
            ptr[1] = xy;    ptr[4] = yy;    ptr[7] = zy;
            ptr[2] = xz;    ptr[5] = yz;    ptr[8] = zz;
        }

        inline void set(T val) {
            ptr[0] = val;   ptr[3] = 0.0f;  ptr[6] = 0.0f;
            ptr[1] = 0.0f;  ptr[4] = val;   ptr[7] = 0.0f;
            ptr[2] = 0.0f;  ptr[5] = 0.0f;  ptr[8] = val;
        }

        inline void set(T m[9]) {
            std::memcpy(ptr, m, sizeof(T) * 9);
        }

        inline void set(std::initializer_list<T> list) {
            if (list.size() != 9) {
                return;
            }
            for (int i = 0; i < 9; i++) {
                ptr[i] = *(list.begin() + i);
            }
        }

        inline T* getPtr() {
            return &ptr[0];
        }

        inline const T* getPtr() const {
            return &ptr[0];
        }

        inline ffw::Mat3x3<T>& operator = (const ffw::Mat3x3<T> &m) {
            ptr[0] = m.ptr[0];  ptr[3] = m.ptr[3];  ptr[6] = m.ptr[6];
            ptr[1] = m.ptr[1];  ptr[4] = m.ptr[4];  ptr[7] = m.ptr[7];
            ptr[2] = m.ptr[2];  ptr[5] = m.ptr[5];  ptr[8] = m.ptr[8];
            return *this;
        }

        inline ffw::Mat3x3<T> operator + (const ffw::Mat3x3<T> &m) const {
            Mat3x3 r;
            r.ptr[0] = ptr[0] + m.ptr[0];
            r.ptr[1] = ptr[1] + m.ptr[1];
            r.ptr[2] = ptr[2] + m.ptr[2];

            r.ptr[3] = ptr[3] + m.ptr[3];
            r.ptr[4] = ptr[4] + m.ptr[4];
            r.ptr[5] = ptr[5] + m.ptr[5];

            r.ptr[6] = ptr[6] + m.ptr[6];
            r.ptr[7] = ptr[7] + m.ptr[7];
            r.ptr[8] = ptr[8] + m.ptr[8];
            return r;
        }

        inline ffw::Mat3x3<T>&  operator += (const ffw::Mat3x3<T> &m) {
            ptr[0] += m.ptr[0];
            ptr[1] += m.ptr[1];
            ptr[2] += m.ptr[2];

            ptr[3] += m.ptr[3];
            ptr[4] += m.ptr[4];
            ptr[5] += m.ptr[5];

            ptr[6] += m.ptr[6];
            ptr[7] += m.ptr[7];
            ptr[8] += m.ptr[8];
            return *this;
        }

        inline ffw::Mat3x3<T> operator - (const ffw::Mat3x3<T> &m) const {
            Mat3x3 r;
            r.ptr[0] = ptr[0] - m.ptr[0];
            r.ptr[1] = ptr[1] - m.ptr[1];
            r.ptr[2] = ptr[2] - m.ptr[2];

            r.ptr[3] = ptr[3] - m.ptr[3];
            r.ptr[4] = ptr[4] - m.ptr[4];
            r.ptr[5] = ptr[5] - m.ptr[5];

            r.ptr[6] = ptr[6] - m.ptr[6];
            r.ptr[7] = ptr[7] - m.ptr[7];
            r.ptr[8] = ptr[8] - m.ptr[8];
            return r;
        }

        inline ffw::Mat3x3<T>&  operator -= (const ffw::Mat3x3<T> &m) {
            ptr[0] -= m.ptr[0];
            ptr[1] -= m.ptr[1];
            ptr[2] -= m.ptr[2];

            ptr[3] -= m.ptr[3];
            ptr[4] -= m.ptr[4];
            ptr[5] -= m.ptr[5];

            ptr[6] -= m.ptr[6];
            ptr[7] -= m.ptr[7];
            ptr[8] -= m.ptr[8];
            return *this;
        }

        inline ffw::Mat3x3<T> operator * (const ffw::Mat3x3<T> &m) const {
            Mat3x3 r;
            r.ptr[0] = ptr[0] * m.ptr[0] + ptr[3] * m.ptr[1] + ptr[6] * m.ptr[2];
            r.ptr[1] = ptr[1] * m.ptr[0] + ptr[4] * m.ptr[1] + ptr[7] * m.ptr[2];
            r.ptr[2] = ptr[2] * m.ptr[0] + ptr[5] * m.ptr[1] + ptr[8] * m.ptr[2];

            r.ptr[3] = ptr[0] * m.ptr[3] + ptr[3] * m.ptr[4] + ptr[6] * m.ptr[5];
            r.ptr[4] = ptr[1] * m.ptr[3] + ptr[4] * m.ptr[4] + ptr[7] * m.ptr[5];
            r.ptr[5] = ptr[2] * m.ptr[3] + ptr[5] * m.ptr[4] + ptr[8] * m.ptr[5];

            r.ptr[6] = ptr[0] * m.ptr[6] + ptr[3] * m.ptr[7] + ptr[6] * m.ptr[8];
            r.ptr[7] = ptr[1] * m.ptr[6] + ptr[4] * m.ptr[7] + ptr[7] * m.ptr[8];
            r.ptr[8] = ptr[2] * m.ptr[6] + ptr[5] * m.ptr[7] + ptr[8] * m.ptr[8];
            return r;
        }

        inline ffw::Mat3x3<T>&  operator *= (const ffw::Mat3x3<T> &m) {
            *this = *this * m;
            return *this;
        }

        template <class S>
        inline ffw::Vec3<S> operator * (const ffw::Vec3<S>& v) const {
            ffw::Vec3f r;
            r.x = v.x*ptr[0] + v.y*ptr[3] + v.z*ptr[6];
            r.y = v.x*ptr[1] + v.y*ptr[4] + v.z*ptr[7];
            r.z = v.x*ptr[2] + v.y*ptr[5] + v.z*ptr[8];
            return r;
        }

        inline T& operator [] (int x) {
            return ptr[x];
        }

        inline const T& operator [] (int x) const {
            return ptr[x];
        }

        inline ffw::Mat3x3<T>& rotate(const ffw::Quaternion<T>& q) {
            // Taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm
            auto sqw = q.w*q.w;
            auto sqx = q.x*q.x;
            auto sqy = q.y*q.y;
            auto sqz = q.z*q.z;

            // invs (inverse square length) is only required if quaternion is not already normalised
            auto invs = T(1) / (sqx + sqy + sqz + sqw);
            ptr[0] = (sqx - sqy - sqz + sqw)*invs; // since sqw + sqx + sqy + sqz =1/invs*invs
            ptr[4] = (-sqx + sqy - sqz + sqw)*invs;
            ptr[8] = (-sqx - sqy + sqz + sqw)*invs;

            auto tmp1 = q.x*q.y;
            auto tmp2 = q.z*q.w;
            ptr[1] = T(2.0) * (tmp1 + tmp2)*invs;
            ptr[3] = T(2.0) * (tmp1 - tmp2)*invs;

            tmp1 = q.x*q.z;
            tmp2 = q.y*q.w;
            ptr[2] = T(2.0) * (tmp1 - tmp2)*invs;
            ptr[6] = T(2.0) * (tmp1 + tmp2)*invs;
            tmp1 = q.y*q.z;
            tmp2 = q.x*q.w;
            ptr[5] = T(2.0) * (tmp1 + tmp2)*invs;
            ptr[7] = T(2.0) * (tmp1 - tmp2)*invs;

            return *this;
        }

        inline ffw::Mat3x3<T>& scale(T x, T y, T z) {
            Mat3x3 m;
            m[0] = x;
            m[5] = y;
            m[10] = z;
            (*this) *= m;
            return *this;
        }

        inline ffw::Mat3x3<T>& transpose() {
            std::swap(ptr[1], ptr[3]);
            std::swap(ptr[2], ptr[6]);
            std::swap(ptr[5], ptr[7]);
            return *this;
        }

        inline T determinant() const {
            T det =
                ptr[0] * (ptr[4] * ptr[8] - ptr[5] * ptr[7]) -
                ptr[3] * (ptr[1] * ptr[8] - ptr[7] * ptr[2]) +
                ptr[6] * (ptr[1] * ptr[5] - ptr[4] * ptr[2]);
            return det;
        }

        inline ffw::Mat3x3<T>& inverse() {
            T det = 1 / determinant();

            T inv[9];
            inv[0] = ptr[4] * ptr[8] - ptr[5] * ptr[7];
            inv[3] = ptr[6] * ptr[5] - ptr[3] * ptr[8];
            inv[6] = ptr[3] * ptr[7] - ptr[6] * ptr[4];
            inv[1] = ptr[7] * ptr[2] - ptr[1] * ptr[8];
            inv[4] = ptr[0] * ptr[8] - ptr[6] * ptr[2];
            inv[7] = ptr[1] * ptr[6] - ptr[0] * ptr[7];
            inv[2] = ptr[1] * ptr[5] - ptr[2] * ptr[4];
            inv[5] = ptr[2] * ptr[3] - ptr[0] * ptr[5];
            inv[8] = ptr[0] * ptr[4] - ptr[1] * ptr[3];
            for (int i = 0; i < 9; i++)ptr[i] = inv[i] * det;
            return *this;
        }
    };
    typedef Mat3x3<float> Mat3x3f;
    typedef Mat3x3<double> Mat3x3d;
    typedef Mat3x3<int> Mat3x3i;
};
#endif