Initial revision
[blender.git] / intern / moto / include / MT_Matrix4x4.h
1 /**
2  * $Id$
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  */
31
32 /**
33
34  * $Id$
35  * Copyright (C) 2001 NaN Technologies B.V.
36  * A 4x4 matrix compatible with other stuff.
37  */
38
39 #ifndef MT_MATRIX4X4_H
40 #define MT_MATRIX4X4_H
41
42 #include <MT_assert.h>
43
44 #include "MT_Vector4.h"
45 #include "MT_Transform.h"
46
47 // Row-major 4x4 matrix
48
49 class MT_Matrix4x4 {
50 public:
51         /**
52          * Empty contructor.
53          */
54     MT_Matrix4x4() {}
55         /**
56          * Initialize all fields with the values pointed at by m. A
57          * contigous block of 16 values is read.  */
58     MT_Matrix4x4(const float *m) { setValue(m); }
59         /**
60          * Initialize all fields with the values pointed at by m. A
61          * contigous block of 16 values is read.  */
62     MT_Matrix4x4(const double *m) { setValue(m); }
63     
64         /**
65          * Initialise with these 16 explicit values.
66          */
67     MT_Matrix4x4(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz, MT_Scalar xw,
68                  MT_Scalar yx, MT_Scalar yy, MT_Scalar yz, MT_Scalar yw,
69                  MT_Scalar zx, MT_Scalar zy, MT_Scalar zz, MT_Scalar zw,
70                  MT_Scalar wx, MT_Scalar wy, MT_Scalar wz, MT_Scalar ww) { 
71         setValue(xx, xy, xz, xw, 
72                  yx, yy, yz, yw,
73                  zx, zy, zz, zw,
74                                  wx, wy, wz, ww);
75     }
76         
77         /** 
78          * Initialize from an MT_Transform.
79          */ 
80         MT_Matrix4x4(const MT_Transform &t) {
81
82                 const MT_Matrix3x3 &basis = t.getBasis();
83                 const MT_Vector3 &origin = t.getOrigin();       
84
85                 setValue(
86                         basis[0][0],basis[0][1],basis[0][2],origin[0],
87                         basis[1][0],basis[1][1],basis[1][2],origin[1],
88                         basis[2][0],basis[2][1],basis[2][2],origin[2],
89                         MT_Scalar(0),MT_Scalar(0),MT_Scalar(0),MT_Scalar(1)
90                 );
91         }
92                 
93         /**
94          * Get the i-th row.
95          */
96     MT_Vector4&       operator[](int i)       { return m_el[i]; }
97         /**
98          * Get the i-th row.
99          */
100     const MT_Vector4& operator[](int i) const { return m_el[i]; }
101
102     /**
103          * Set the matrix to the values pointer at by m. A contiguous
104          * block of 16 values is copied.  */
105     void setValue(const float *m) {
106         m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m_el[3][0] = *m++;
107         m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++; m_el[3][1] = *m++;
108         m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m++; m_el[3][2] = *m++;
109         m_el[0][3] = *m++; m_el[1][3] = *m++; m_el[2][3] = *m++; m_el[3][3] = *m;
110     }
111
112     /**
113          * Set the matrix to the values pointer at by m. A contiguous
114          * block of 16 values is copied.
115          */
116     void setValue(const double *m) {
117         m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m_el[3][0] = *m++;
118         m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++; m_el[3][1] = *m++;
119         m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m++; m_el[3][2] = *m++;
120         m_el[0][3] = *m++; m_el[1][3] = *m++; m_el[2][3] = *m++; m_el[3][3] = *m;
121     }
122
123     /**
124          * Set the matrix to these 16 explicit values.
125          */
126     void setValue(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz, MT_Scalar xw,
127                   MT_Scalar yx, MT_Scalar yy, MT_Scalar yz, MT_Scalar yw,
128                   MT_Scalar zx, MT_Scalar zy, MT_Scalar zz, MT_Scalar zw,
129                   MT_Scalar wx, MT_Scalar wy, MT_Scalar wz, MT_Scalar ww) {
130         m_el[0][0] = xx; m_el[0][1] = xy; m_el[0][2] = xz; m_el[0][3] = xw;
131         m_el[1][0] = yx; m_el[1][1] = yy; m_el[1][2] = yz; m_el[1][3] = yw;
132         m_el[2][0] = zx; m_el[2][1] = zy; m_el[2][2] = zz; m_el[2][3] = zw;
133         m_el[3][0] = wx; m_el[3][1] = wy; m_el[3][2] = wz; m_el[3][3] = ww;
134     }
135         
136         /**
137          * Scale the columns of this matrix with x, y, z, w respectively. 
138          */
139     void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) {
140         m_el[0][0] *= x; m_el[0][1] *= y; m_el[0][2] *= z; m_el[0][3] *= w;
141         m_el[1][0] *= x; m_el[1][1] *= y; m_el[1][2] *= z; m_el[1][3] *= w;
142         m_el[2][0] *= x; m_el[2][1] *= y; m_el[2][2] *= z; m_el[2][3] *= w;
143         m_el[3][0] *= x; m_el[3][1] *= y; m_el[3][2] *= z; m_el[3][3] *= w;
144     }
145
146         /**
147          * Return a column-scaled version of this matrix.
148          */
149     MT_Matrix4x4 scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) const {
150         return MT_Matrix4x4(m_el[0][0] * x, m_el[0][1] * y, m_el[0][2] * z, m_el[0][3] * w,
151                             m_el[1][0] * x, m_el[1][1] * y, m_el[1][2] * z, m_el[1][3] * w,
152                             m_el[2][0] * x, m_el[2][1] * y, m_el[2][2] * z, m_el[2][3] * w,
153                             m_el[3][0] * x, m_el[3][1] * y, m_el[3][2] * z, m_el[3][3] * w);
154     }
155
156         /**
157          * Set this matrix to I.
158          */
159     void setIdentity() { 
160         setValue(MT_Scalar(1.0), MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0),
161                  MT_Scalar(0.0), MT_Scalar(1.0), MT_Scalar(0.0), MT_Scalar(0.0),
162                  MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(1.0), MT_Scalar(0.0),
163                              MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(1.0)); 
164     }
165
166         /**
167          * Read the element from row i, column j.
168          */
169         float getElement(int i, int j) {
170                 return m_el[i][j];
171         }
172         
173     /**
174          * Copy the contents to a contiguous block of 16 floats.
175          */
176     void getValue(float *m) const {
177         *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0]; *m++ = m_el[3][0];
178         *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1]; *m++ = m_el[3][1];
179         *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m++ = m_el[3][2];
180         *m++ = m_el[0][3]; *m++ = m_el[1][3]; *m++ = m_el[2][3]; *m = m_el[3][3];
181     }
182
183     /**
184          * Copy the contents to a contiguous block of 16 doubles.
185          */
186     void getValue(double *m) const {
187         *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0]; *m++ = m_el[3][0];
188         *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1]; *m++ = m_el[3][1];
189         *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m++ = m_el[3][2];
190         *m++ = m_el[0][3]; *m++ = m_el[1][3]; *m++ = m_el[2][3]; *m = m_el[3][3];
191     }
192
193         /** 
194          * Left-multiply this matrix with the argument.
195          */
196     MT_Matrix4x4& operator*=(const MT_Matrix4x4& m); 
197
198         /**
199          * Left-multiply column c with row vector c.
200          */
201     MT_Scalar tdot(int c, const MT_Vector4& v) const {
202         return m_el[0][c] * v[0]
203                         + m_el[1][c] * v[1]
204                         + m_el[2][c] * v[2]
205                         + m_el[3][c] * v[3];
206     }
207
208         /* I'll postpone this for now... - nzc*/ 
209 /*      MT_Scalar    determinant() const; */
210 /*      MT_Matrix4x4 adjoint() const; */
211 /*      MT_Matrix4x4 inverse() const;  */
212
213         MT_Matrix4x4 absolute() const;
214
215         MT_Matrix4x4 transposed() const; 
216         void         transpose();
217
218         void         invert();
219   
220 protected:
221         /**
222          * Access with [row index][column index]
223          */
224     MT_Vector4 m_el[4];
225 };
226
227 /* These multiplicators do exactly what you ask from them: they
228  * multiply in the indicated order. */
229 MT_Vector4   operator*(const MT_Matrix4x4& m, const MT_Vector4& v);
230 MT_Vector4   operator*(const MT_Vector4& v, const MT_Matrix4x4& m);
231 MT_Matrix4x4 operator*(const MT_Matrix4x4& m1, const MT_Matrix4x4& m2);
232
233 /*  MT_Matrix4x4 MT_multTransposeLeft(const MT_Matrix4x4& m1, const MT_Matrix4x4& m2); */
234 /*  MT_Matrix4x4 MT_multTransposeRight(const MT_Matrix4x4& m1, const MT_Matrix4x4& m2); */
235
236 inline MT_OStream& operator<<(MT_OStream& os, const MT_Matrix4x4& m) {
237     return os << m[0] << GEN_endl
238                           << m[1] << GEN_endl
239                           << m[2] << GEN_endl
240                           << m[3] << GEN_endl;
241
242
243         
244 }
245
246 #ifdef GEN_INLINED
247 #include "MT_Matrix4x4.inl"
248 #endif
249
250 #endif