OSDN Git Service

improve mat44 implementation
authorMathias Agopian <mathias@google.com>
Mon, 2 Sep 2013 04:35:36 +0000 (21:35 -0700)
committerMathias Agopian <mathias@google.com>
Tue, 3 Sep 2013 23:38:49 +0000 (16:38 -0700)
this will make it easier to create matrices of different sizes

Change-Id: I2c1771ba0823c42d737762e2dfc2cd47eb302767

include/ui/TMatHelpers.h
include/ui/TVecHelpers.h
include/ui/mat4.h
include/ui/vec2.h
include/ui/vec3.h
include/ui/vec4.h

index b778af0..cead10a 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <math.h>
 #include <utils/Debug.h>
 #include <utils/String8.h>
 
@@ -172,6 +173,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
 
 #undef PURE
index 081c69c..bb7dbfc 100644 (file)
@@ -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;
     }
index 08a67c7..d9647cc 100644 (file)
@@ -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) {
@@ -320,42 +325,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,47 +372,17 @@ 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);
-}
 
-template <typename T>
-tvec4<T> PURE diag(const tmat44<T>& m) {
+/* FIXME: this should go into TMatSquareFunctions<> but for some reason
+ * BASE<T>::col_type is not accessible from there (???)
+ */
+template<typename T>
+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;
 
index b4edfc6..c31d0e4 100644 (file)
@@ -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) { }
 };
 
 // ----------------------------------------------------------------------------------------
index 591b8b2..dde59a9 100644 (file)
@@ -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),
index 798382d..e03d331 100644 (file)
@@ -26,7 +26,8 @@ namespace android {
 // -------------------------------------------------------------------------------------
 
 template <typename T>
-class tvec4 :   public TVecArithmeticOperators<tvec4, T>,
+class tvec4 :   public TVecProductOperators<tvec4, T>,
+                public TVecAddOperators<tvec4, T>,
                 public TVecUnaryOperators<tvec4, T>,
                 public TVecComparisonOperators<tvec4, T>,
                 public TVecFunctions<tvec4, T>
@@ -85,6 +86,13 @@ public:
     template<typename A>
     explicit tvec4(const tvec4<A>& v) : x(v.x), y(v.y), z(v.z), w(v.w) { }
 
+    template<typename A>
+    tvec4(const Impersonator< tvec4<A> >& v)
+        : x(((const tvec4<A>&)v).x),
+          y(((const tvec4<A>&)v).y),
+          z(((const tvec4<A>&)v).z),
+          w(((const tvec4<A>&)v).w) { }
+
     template<typename A, typename B>
     tvec4(const Impersonator< tvec3<A> >& v, B w)
         : x(((const tvec3<A>&)v).x),