Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1d4d8f94 authored by Mathias Agopian's avatar Mathias Agopian
Browse files

improve mat44 implementation

this will make it easier to create matrices of different sizes

Change-Id: I2c1771ba0823c42d737762e2dfc2cd47eb302767
parent 9b5534b0
Loading
Loading
Loading
Loading
+78 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@

#include <stdint.h>
#include <sys/types.h>
#include <math.h>
#include <utils/Debug.h>
#include <utils/String8.h>

@@ -171,6 +172,83 @@ String8 asString(const MATRIX& m) {

}; // namespace matrix

// -------------------------------------------------------------------------------------

/*
 * TMatProductOperators implements basic arithmetic and basic compound assignments
 * operators on a vector of type BASE<T>.
 *
 * BASE only needs to implement operator[] and size().
 * By simply inheriting from TMatProductOperators<BASE, T> BASE will automatically
 * get all the functionality here.
 */

template <template<typename T> class BASE, typename T>
class TMatProductOperators {
public:
    // multiply by a scalar
    BASE<T>& operator *= (T v) {
        BASE<T>& lhs(static_cast< BASE<T>& >(*this));
        for (size_t r=0 ; r<lhs.row_size() ; r++) {
            lhs[r] *= v;
        }
        return lhs;
    }

    // divide by a scalar
    BASE<T>& operator /= (T v) {
        BASE<T>& lhs(static_cast< BASE<T>& >(*this));
        for (size_t r=0 ; r<lhs.row_size() ; r++) {
            lhs[r] /= v;
        }
        return lhs;
    }

    // matrix * matrix, result is a matrix of the same type than the lhs matrix
    template<typename U>
    friend BASE<T> PURE operator *(const BASE<T>& lhs, const BASE<U>& rhs) {
        return matrix::multiply<BASE<T> >(lhs, rhs);
    }
};


/*
 * TMatSquareFunctions implements functions on a matrix of type BASE<T>.
 *
 * BASE only needs to implement:
 *  - operator[]
 *  - col_type
 *  - row_type
 *  - COL_SIZE
 *  - ROW_SIZE
 *
 * By simply inheriting from TMatSquareFunctions<BASE, T> BASE will automatically
 * get all the functionality here.
 */

template<template<typename U> class BASE, typename T>
class TMatSquareFunctions {
public:
    /*
     * NOTE: the functions below ARE NOT member methods. They are friend functions
     * with they definition inlined with their declaration. This makes these
     * template functions available to the compiler when (and only when) this class
     * is instantiated, at which point they're only templated on the 2nd parameter
     * (the first one, BASE<T> being known).
     */
    friend BASE<T> PURE inverse(const BASE<T>& m)   { return matrix::inverse(m); }
    friend BASE<T> PURE transpose(const BASE<T>& m) { return matrix::transpose(m); }
    friend T       PURE trace(const BASE<T>& m)     { return matrix::trace(m); }
};

template <template<typename T> class BASE, typename T>
class TMatDebug {
public:
    String8 asString() const {
        return matrix::asString(*this);
    }
};

// -------------------------------------------------------------------------------------
}; // namespace android

+68 −35
Original line number Diff line number Diff line
@@ -57,16 +57,16 @@ struct Impersonator {
};

/*
 * TVecArithmeticOperators implements basic arithmetic and basic compound assignments
 * TVec{Add|Product}Operators implements basic arithmetic and basic compound assignments
 * operators on a vector of type BASE<T>.
 *
 * BASE only needs to implement operator[] and size().
 * By simply inheriting from TVecArithmeticOperators<BASE, T> BASE will automatically
 * By simply inheriting from TVec{Add|Product}Operators<BASE, T> BASE will automatically
 * get all the functionality here.
 */

template <template<typename T> class BASE, typename T>
class TVecArithmeticOperators {
class TVecAddOperators {
public:
    /* compound assignment from a another vector of the same size but different
     * element type.
@@ -87,42 +87,93 @@ public:
        }
        return rhs;
    }
    template <typename OTHER>
    BASE<T>& operator *= (const BASE<OTHER>& v) {

    /* compound assignment from a another vector of the same type.
     * These operators can be used for implicit conversion and  handle operations
     * like "vector *= scalar" by letting the compiler implicitly convert a scalar
     * to a vector (assuming the BASE<T> allows it).
     */
    BASE<T>& operator += (const BASE<T>& v) {
        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
            rhs[i] *= v[i];
            rhs[i] += v[i];
        }
        return rhs;
    }
    template <typename OTHER>
    BASE<T>& operator /= (const BASE<OTHER>& v) {
    BASE<T>& operator -= (const BASE<T>& v) {
        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
            rhs[i] /= v[i];
            rhs[i] -= v[i];
        }
        return rhs;
    }

    /* compound assignment from a another vector of the same type.
     * These operators can be used for implicit conversion and  handle operations
     * like "vector *= scalar" by letting the compiler implicitly convert a scalar
     * to a vector (assuming the BASE<T> allows it).
    /*
     * NOTE: the functions below ARE NOT member methods. They are friend functions
     * with they definition inlined with their declaration. This makes these
     * template functions available to the compiler when (and only when) this class
     * is instantiated, at which point they're only templated on the 2nd parameter
     * (the first one, BASE<T> being known).
     */
    BASE<T>& operator += (const BASE<T>& v) {

    /* The operators below handle operation between vectors of the same side
     * but of a different element type.
     */
    template<typename RT>
    friend inline
    BASE<T> PURE operator +(const BASE<T>& lv, const BASE<RT>& rv) {
        return BASE<T>(lv) += rv;
    }
    template<typename RT>
    friend inline
    BASE<T> PURE operator -(const BASE<T>& lv, const BASE<RT>& rv) {
        return BASE<T>(lv) -= rv;
    }

    /* The operators below (which are not templates once this class is instanced,
     * i.e.: BASE<T> is known) can be used for implicit conversion on both sides.
     * These handle operations like "vector * scalar" and "scalar * vector" by
     * letting the compiler implicitly convert a scalar to a vector (assuming
     * the BASE<T> allows it).
     */
    friend inline
    BASE<T> PURE operator +(const BASE<T>& lv, const BASE<T>& rv) {
        return BASE<T>(lv) += rv;
    }
    friend inline
    BASE<T> PURE operator -(const BASE<T>& lv, const BASE<T>& rv) {
        return BASE<T>(lv) -= rv;
    }
};

template <template<typename T> class BASE, typename T>
class TVecProductOperators {
public:
    /* compound assignment from a another vector of the same size but different
     * element type.
     */
    template <typename OTHER>
    BASE<T>& operator *= (const BASE<OTHER>& v) {
        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
            rhs[i] += v[i];
            rhs[i] *= v[i];
        }
        return rhs;
    }
    BASE<T>& operator -= (const BASE<T>& v) {
    template <typename OTHER>
    BASE<T>& operator /= (const BASE<OTHER>& v) {
        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
            rhs[i] -= v[i];
            rhs[i] /= v[i];
        }
        return rhs;
    }

    /* compound assignment from a another vector of the same type.
     * These operators can be used for implicit conversion and  handle operations
     * like "vector *= scalar" by letting the compiler implicitly convert a scalar
     * to a vector (assuming the BASE<T> allows it).
     */
    BASE<T>& operator *= (const BASE<T>& v) {
        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
@@ -151,16 +202,6 @@ public:
     */
    template<typename RT>
    friend inline
    BASE<T> PURE operator +(const BASE<T>& lv, const BASE<RT>& rv) {
        return BASE<T>(lv) += rv;
    }
    template<typename RT>
    friend inline
    BASE<T> PURE operator -(const BASE<T>& lv, const BASE<RT>& rv) {
        return BASE<T>(lv) -= rv;
    }
    template<typename RT>
    friend inline
    BASE<T> PURE operator *(const BASE<T>& lv, const BASE<RT>& rv) {
        return BASE<T>(lv) *= rv;
    }
@@ -177,14 +218,6 @@ public:
     * the BASE<T> allows it).
     */
    friend inline
    BASE<T> PURE operator +(const BASE<T>& lv, const BASE<T>& rv) {
        return BASE<T>(lv) += rv;
    }
    friend inline
    BASE<T> PURE operator -(const BASE<T>& lv, const BASE<T>& rv) {
        return BASE<T>(lv) -= rv;
    }
    friend inline
    BASE<T> PURE operator *(const BASE<T>& lv, const BASE<T>& rv) {
        return BASE<T>(lv) *= rv;
    }
+38 −117
Original line number Diff line number Diff line
@@ -33,7 +33,11 @@ namespace android {

template <typename T>
class tmat44 :  public TVecUnaryOperators<tmat44, T>,
                public TVecComparisonOperators<tmat44, T>
                public TVecComparisonOperators<tmat44, T>,
                public TVecAddOperators<tmat44, T>,
                public TMatProductOperators<tmat44, T>,
                public TMatSquareFunctions<tmat44, T>,
                public TMatDebug<tmat44, T>
{
public:
    enum no_init { NO_INIT };
@@ -108,6 +112,17 @@ public:
    template <typename A, typename B, typename C, typename D>
    tmat44(const tvec4<A>& v0, const tvec4<B>& v1, const tvec4<C>& v2, const tvec4<D>& v3);

    // construct from 16 scalars
    template <
        typename A, typename B, typename C, typename D,
        typename E, typename F, typename G, typename H,
        typename I, typename J, typename K, typename L,
        typename M, typename N, typename O, typename P>
    tmat44( A m00, B m01, C m02, D m03,
            E m10, F m11, G m12, H m13,
            I m20, J m21, K m22, L m23,
            M m30, N m31, O m32, P m33);

    // construct from a C array
    template <typename U>
    explicit tmat44(U const* rawArray);
@@ -131,33 +146,6 @@ public:

    template <typename A, typename B>
    static tmat44 rotate(A radian, const tvec3<B>& about);


    /*
     * Compound assignment arithmetic operators
     */

    // add another matrix of the same size
    template <typename U>
    tmat44& operator += (const tmat44<U>& v);

    // subtract another matrix of the same size
    template <typename U>
    tmat44& operator -= (const tmat44<U>& v);

    // multiply by a scalar
    template <typename U>
    tmat44& operator *= (U v);

    // divide by a scalar
    template <typename U>
    tmat44& operator /= (U v);

    /*
     * debugging
     */

    String8 asString() const;
};

// ----------------------------------------------------------------------------------------
@@ -195,6 +183,23 @@ tmat44<T>::tmat44(const tvec4<U>& v) {
    mValue[3] = col_type(0,0,0,v.w);
}

// construct from 16 scalars
template<typename T>
template <
    typename A, typename B, typename C, typename D,
    typename E, typename F, typename G, typename H,
    typename I, typename J, typename K, typename L,
    typename M, typename N, typename O, typename P>
tmat44<T>::tmat44(  A m00, B m01, C m02, D m03,
                    E m10, F m11, G m12, H m13,
                    I m20, J m21, K m22, L m23,
                    M m30, N m31, O m32, P m33) {
    mValue[0] = col_type(m00, m01, m02, m03);
    mValue[1] = col_type(m10, m11, m12, m13);
    mValue[2] = col_type(m20, m21, m22, m23);
    mValue[3] = col_type(m30, m31, m32, m33);
}

template <typename T>
template <typename U>
tmat44<T>::tmat44(const tmat44<U>& rhs) {
@@ -319,42 +324,6 @@ tmat44<T> tmat44<T>::rotate(A radian, const tvec3<B>& about) {
    }
}

// ----------------------------------------------------------------------------------------
// Compound assignment arithmetic operators
// ----------------------------------------------------------------------------------------

template <typename T>
template <typename U>
tmat44<T>& tmat44<T>::operator += (const tmat44<U>& v) {
    for (size_t r=0 ; r<row_size() ; r++)
        mValue[r] += v[r];
    return *this;
}

template <typename T>
template <typename U>
tmat44<T>& tmat44<T>::operator -= (const tmat44<U>& v) {
    for (size_t r=0 ; r<row_size() ; r++)
        mValue[r] -= v[r];
    return *this;
}

template <typename T>
template <typename U>
tmat44<T>& tmat44<T>::operator *= (U v) {
    for (size_t r=0 ; r<row_size() ; r++)
        mValue[r] *= v;
    return *this;
}

template <typename T>
template <typename U>
tmat44<T>& tmat44<T>::operator /= (U v) {
    for (size_t r=0 ; r<row_size() ; r++)
        mValue[r] /= v;
    return *this;
}

// ----------------------------------------------------------------------------------------
// Arithmetic operators outside of class
// ----------------------------------------------------------------------------------------
@@ -367,24 +336,6 @@ tmat44<T>& tmat44<T>::operator /= (U v) {
 * it determines the output type (only relevant when T != U).
 */

// matrix + matrix, result is a matrix of the same type than the lhs matrix
template <typename T, typename U>
tmat44<T> PURE operator +(const tmat44<T>& lhs, const tmat44<U>& rhs) {
    tmat44<T> result(tmat44<T>::NO_INIT);
    for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
        result[r] = lhs[r] + rhs[r];
    return result;
}

// matrix - matrix, result is a matrix of the same type than the lhs matrix
template <typename T, typename U>
tmat44<T> PURE operator -(const tmat44<T>& lhs, const tmat44<U>& rhs) {
    tmat44<T> result(tmat44<T>::NO_INIT);
    for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
        result[r] = lhs[r] - rhs[r];
    return result;
}

// matrix * vector, result is a vector of the same type than the input vector
template <typename T, typename U>
typename tmat44<U>::col_type PURE operator *(const tmat44<T>& lv, const tvec4<U>& rv) {
@@ -421,46 +372,16 @@ tmat44<T> PURE operator *(U rv, const tmat44<T>& lv) {
    return result;
}

// matrix * matrix, result is a matrix of the same type than the lhs matrix
template <typename T, typename U>
tmat44<T> PURE operator *(const tmat44<T>& lhs, const tmat44<U>& rhs) {
    return matrix::multiply< tmat44<T> >(lhs, rhs);
}

// ----------------------------------------------------------------------------------------
// Functions
// ----------------------------------------------------------------------------------------

// inverse a matrix
template <typename T>
tmat44<T> PURE inverse(const tmat44<T>& m) {
    return matrix::inverse(m);
}

template <typename T>
tmat44<T> PURE transpose(const tmat44<T>& m) {
    return matrix::transpose(m);
}

template <typename T>
T PURE trace(const tmat44<T>& m) {
    return matrix::trace(m);
}

/* FIXME: this should go into TMatSquareFunctions<> but for some reason
 * BASE<T>::col_type is not accessible from there (???)
 */
template<typename T>
tvec4<T> PURE diag(const tmat44<T>& m) {
typename tmat44<T>::col_type PURE diag(const tmat44<T>& m) {
    return matrix::diag(m);
}

// ----------------------------------------------------------------------------------------
// Debugging
// ----------------------------------------------------------------------------------------

template <typename T>
String8 tmat44<T>::asString() const {
    return matrix::asString(*this);
}

// ----------------------------------------------------------------------------------------

typedef tmat44<float> mat4;
+7 −1
Original line number Diff line number Diff line
@@ -27,7 +27,8 @@ namespace android {
// -------------------------------------------------------------------------------------

template <typename T>
class tvec2 :   public TVecArithmeticOperators<tvec2, T>,
class tvec2 :   public TVecProductOperators<tvec2, T>,
                public TVecAddOperators<tvec2, T>,
                public TVecUnaryOperators<tvec2, T>,
                public TVecComparisonOperators<tvec2, T>,
                public TVecFunctions<tvec2, T>
@@ -73,6 +74,11 @@ public:

    template<typename A>
    explicit tvec2(const tvec2<A>& v) : x(v.x), y(v.y) { }

    template<typename A>
    tvec2(const Impersonator< tvec2<A> >& v)
        : x(((const tvec2<A>&)v).x),
          y(((const tvec2<A>&)v).y) { }
};

// ----------------------------------------------------------------------------------------
+8 −1
Original line number Diff line number Diff line
@@ -26,7 +26,8 @@ namespace android {
// -------------------------------------------------------------------------------------

template <typename T>
class tvec3 :   public TVecArithmeticOperators<tvec3, T>,
class tvec3 :   public TVecProductOperators<tvec3, T>,
                public TVecAddOperators<tvec3, T>,
                public TVecUnaryOperators<tvec3, T>,
                public TVecComparisonOperators<tvec3, T>,
                public TVecFunctions<tvec3, T>
@@ -78,6 +79,12 @@ public:
    template<typename A>
    explicit tvec3(const tvec3<A>& v) : x(v.x), y(v.y), z(v.z) { }

    template<typename A>
    tvec3(const Impersonator< tvec3<A> >& v)
        : x(((const tvec3<A>&)v).x),
          y(((const tvec3<A>&)v).y),
          z(((const tvec3<A>&)v).z) { }

    template<typename A, typename B>
    tvec3(const Impersonator< tvec2<A> >& v, B z)
        : x(((const tvec2<A>&)v).x),
Loading