root/trunk/dep/include/g3dlite/G3D/Matrix3.h @ 2

Revision 2, 10.4 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/**
2  @file Matrix3.h
3 
4  3x3 matrix class
5 
6  @maintainer Morgan McGuire, matrix@graphics3d.com
7 
8  @cite Portions based on Dave Eberly's Magic Software Library at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
9 
10  @created 2001-06-02
11  @edited  2006-04-05
12 */
13
14#ifndef G3D_MATRIX3_H
15#define G3D_MATRIX3_H
16
17#include "G3D/platform.h"
18#include "G3D/System.h"
19#include "G3D/Vector3.h"
20#include "G3D/Vector4.h"
21
22namespace G3D {
23
24/**
25  3x3 matrix.  Do not subclass.
26 */
27class Matrix3 {
28private:
29
30    float elt[3][3];
31
32    // Hidden operators
33    bool operator<(const Matrix3&) const;
34    bool operator>(const Matrix3&) const;
35    bool operator<=(const Matrix3&) const;
36    bool operator>=(const Matrix3&) const;
37
38public:
39
40    /** Initial values are undefined for performance.  See also
41        Matrix3::zero(), Matrix3::identity(), Matrix3::fromAxisAngle, etc.*/
42    inline Matrix3() {}
43
44    Matrix3 (const float aafEntry[3][3]);
45    Matrix3 (const Matrix3& rkMatrix);
46    Matrix3 (float fEntry00, float fEntry01, float fEntry02,
47             float fEntry10, float fEntry11, float fEntry12,
48             float fEntry20, float fEntry21, float fEntry22);
49
50    bool fuzzyEq(const Matrix3& b) const;
51
52    /** Constructs a matrix from a quaternion.
53        @cite Graphics Gems II, p. 351--354
54            @cite Implementation from Watt and Watt, pg 362*/
55    Matrix3(const class Quat& q);
56
57
58    /**
59     Sets all elements.
60     */
61    void set(float fEntry00, float fEntry01, float fEntry02,
62             float fEntry10, float fEntry11, float fEntry12,
63             float fEntry20, float fEntry21, float fEntry22);
64
65    /**
66     * member access, allows use of construct mat[r][c]
67     */
68    inline float* operator[] (int iRow) {
69        debugAssert(iRow >= 0);
70        debugAssert(iRow < 3);
71        return (float*)&elt[iRow][0];
72    }
73
74    inline const float* operator[] (int iRow) const {
75        debugAssert(iRow >= 0);
76        debugAssert(iRow < 3);
77        return (const float*)&elt[iRow][0];
78    }
79
80    inline operator float* () {
81        return (float*)&elt[0][0];
82    }
83
84    inline operator const float* () const{
85        return (const float*)&elt[0][0];
86    }
87
88    Vector3 getColumn (int iCol) const;
89    Vector3 getRow (int iRow) const;
90    void setColumn(int iCol, const Vector3 &vector);
91    void setRow(int iRow, const Vector3 &vector);
92
93    // assignment and comparison
94    inline Matrix3& operator= (const Matrix3& rkMatrix) {
95        System::memcpy(elt, rkMatrix.elt, 9 * sizeof(float));
96        return *this;
97    }
98
99    bool operator== (const Matrix3& rkMatrix) const;
100    bool operator!= (const Matrix3& rkMatrix) const;
101
102    // arithmetic operations
103    Matrix3 operator+ (const Matrix3& rkMatrix) const;
104    Matrix3 operator- (const Matrix3& rkMatrix) const;
105    /** Matrix-matrix multiply */
106    Matrix3 operator* (const Matrix3& rkMatrix) const;
107    Matrix3 operator- () const;
108
109    Matrix3& operator+= (const Matrix3& rkMatrix);
110    Matrix3& operator-= (const Matrix3& rkMatrix);
111    Matrix3& operator*= (const Matrix3& rkMatrix);
112
113    /**
114     * matrix * vector [3x3 * 3x1 = 3x1]
115     */
116    inline Vector3 operator* (const Vector3& v) const {
117        Vector3 kProd;
118
119        for (int r = 0; r < 3; ++r) {
120            kProd[r] =
121                elt[r][0] * v[0] +
122                elt[r][1] * v[1] +
123                elt[r][2] * v[2];
124        }
125
126        return kProd;
127    }
128
129
130    /**
131     * vector * matrix [1x3 * 3x3 = 1x3]
132     */
133    friend Vector3 operator* (const Vector3& rkVector,
134                              const Matrix3& rkMatrix);
135
136    /**
137     * matrix * scalar
138     */
139    Matrix3 operator* (float fScalar) const;
140
141    /** scalar * matrix */
142    friend Matrix3 operator* (double fScalar, const Matrix3& rkMatrix);
143    friend Matrix3 operator* (float fScalar, const Matrix3& rkMatrix);
144    friend Matrix3 operator* (int fScalar, const Matrix3& rkMatrix);
145
146private:
147    /** Multiplication where out != A and out != B */
148    static void _mul(const Matrix3& A, const Matrix3& B, Matrix3& out);
149public:
150
151    /** Optimized implementation of out = A * B.  It is safe (but slow) to call
152        with A, B, and out possibly pointer equal to one another.*/
153    // This is a static method so that it is not ambiguous whether "this"
154    // is an input or output argument.
155    inline static void mul(const Matrix3& A, const Matrix3& B, Matrix3& out) {
156        if ((&out == &A) || (&out == &B)) {
157            // We need a temporary anyway, so revert to the stack method.
158            out = A * B;
159        } else {
160            // Optimized in-place multiplication.
161            _mul(A, B, out);
162        }
163    }
164
165private:
166    static void _transpose(const Matrix3& A, Matrix3& out);
167public:
168
169    /** Optimized implementation of out = A.transpose().  It is safe (but slow) to call
170        with A and out possibly pointer equal to one another.
171   
172        Note that <CODE>A.transpose() * v</CODE> can be computed
173        more efficiently as <CODE>v * A</CODE>.
174    */
175    inline static void transpose(const Matrix3& A, Matrix3& out) {
176        if (&A == &out) {
177            out = A.transpose();
178        } else {
179            _transpose(A, out);
180        }
181    }
182
183    /** Returns true if the rows and column L2 norms are 1.0 and the rows are orthogonal. */
184    bool isOrthonormal() const;
185
186    Matrix3 transpose () const;
187    bool inverse (Matrix3& rkInverse, float fTolerance = 1e-06) const;
188    Matrix3 inverse (float fTolerance = 1e-06) const;
189    float determinant () const;
190
191    /** singular value decomposition */
192    void singularValueDecomposition (Matrix3& rkL, Vector3& rkS,
193                                     Matrix3& rkR) const;
194    /** singular value decomposition */
195    void singularValueComposition (const Matrix3& rkL,
196                                   const Vector3& rkS, const Matrix3& rkR);
197
198    /** Gram-Schmidt orthonormalization (applied to columns of rotation matrix) */
199    void orthonormalize();
200
201    /** orthogonal Q, diagonal D, upper triangular U stored as (u01,u02,u12) */
202    void qDUDecomposition (Matrix3& rkQ, Vector3& rkD,
203                           Vector3& rkU) const;
204
205    float spectralNorm () const;
206
207    /** matrix must be orthonormal */
208    void toAxisAngle(Vector3& rkAxis, float& rfRadians) const;
209
210    static Matrix3 fromAxisAngle(const Vector3& rkAxis, float fRadians);
211
212    /**
213     * The matrix must be orthonormal.  The decomposition is yaw*pitch*roll
214     * where yaw is rotation about the Up vector, pitch is rotation about the
215     * right axis, and roll is rotation about the Direction axis.
216     */
217    bool toEulerAnglesXYZ (float& rfYAngle, float& rfPAngle,
218                           float& rfRAngle) const;
219    bool toEulerAnglesXZY (float& rfYAngle, float& rfPAngle,
220                           float& rfRAngle) const;
221    bool toEulerAnglesYXZ (float& rfYAngle, float& rfPAngle,
222                           float& rfRAngle) const;
223    bool toEulerAnglesYZX (float& rfYAngle, float& rfPAngle,
224                           float& rfRAngle) const;
225    bool toEulerAnglesZXY (float& rfYAngle, float& rfPAngle,
226                           float& rfRAngle) const;
227    bool toEulerAnglesZYX (float& rfYAngle, float& rfPAngle,
228                           float& rfRAngle) const;
229    static Matrix3 fromEulerAnglesXYZ (float fYAngle, float fPAngle, float fRAngle);
230    static Matrix3 fromEulerAnglesXZY (float fYAngle, float fPAngle, float fRAngle);
231    static Matrix3 fromEulerAnglesYXZ (float fYAngle, float fPAngle, float fRAngle);
232    static Matrix3 fromEulerAnglesYZX (float fYAngle, float fPAngle, float fRAngle);
233    static Matrix3 fromEulerAnglesZXY (float fYAngle, float fPAngle, float fRAngle);
234    static Matrix3 fromEulerAnglesZYX (float fYAngle, float fPAngle, float fRAngle);
235
236    /** eigensolver, matrix must be symmetric */
237    void eigenSolveSymmetric (float afEigenvalue[3],
238                              Vector3 akEigenvector[3]) const;
239
240    static void tensorProduct (const Vector3& rkU, const Vector3& rkV,
241                               Matrix3& rkProduct);
242        std::string toString() const;
243
244    static const float EPSILON; 
245
246    // Special values.
247    // The unguaranteed order of initialization of static variables across
248    // translation units can be a source of annoying bugs, so now the static
249    // special values (like Vector3::ZERO, Color3::WHITE, ...) are wrapped
250    // inside static functions that return references to them.
251    // These functions are intentionally not inlined, because:
252    // "You might be tempted to write [...] them as inline functions
253    // inside their respective header files, but this is something you
254    // must definitely not do. An inline function can be duplicated
255    // in every file in which it appears – and this duplication
256    // includes the static object definition. Because inline functions
257    // automatically default to internal linkage, this would result in
258    // having multiple static objects across the various translation
259    // units, which would certainly cause problems. So you must
260    // ensure that there is only one definition of each wrapping
261    // function, and this means not making the wrapping functions inline",
262    // according to Chapter 10 of "Thinking in C++, 2nd ed. Volume 1" by Bruce Eckel,
263    // http://www.mindview.net/
264    static const Matrix3& zero();
265    static const Matrix3& identity(); 
266
267    // Deprecated.
268    /** @deprecated Use Matrix3::zero() */
269    static const Matrix3 ZERO;
270    /** @deprecated Use Matrix3::identity() */
271    static const Matrix3 IDENTITY;
272
273protected:
274    // support for eigensolver
275    void tridiagonal (float afDiag[3], float afSubDiag[3]);
276    bool qLAlgorithm (float afDiag[3], float afSubDiag[3]);
277
278    // support for singular value decomposition
279    static const float ms_fSvdEpsilon;
280    static const int ms_iSvdMaxIterations;
281    static void bidiagonalize (Matrix3& kA, Matrix3& kL,
282                               Matrix3& kR);
283    static void golubKahanStep (Matrix3& kA, Matrix3& kL,
284                                Matrix3& kR);
285
286    // support for spectral norm
287    static float maxCubicRoot (float afCoeff[3]);
288
289};
290
291
292//----------------------------------------------------------------------------
293/**  <code>v * M == M.transpose() * v</code> */
294inline Vector3 operator* (const Vector3& rkPoint, const Matrix3& rkMatrix) {
295    Vector3 kProd;
296
297    for (int r = 0; r < 3; ++r) {
298        kProd[r] =
299            rkPoint[0] * rkMatrix.elt[0][r] +
300            rkPoint[1] * rkMatrix.elt[1][r] +
301            rkPoint[2] * rkMatrix.elt[2][r];
302    }
303
304    return kProd;
305}
306
307
308} // namespace
309
310#endif
311
Note: See TracBrowser for help on using the browser.