PyRNA API support for matrix types as Mathutils matrix (with callbacks) rather then...
[blender-staging.git] / intern / moto / include / MT_Matrix3x3.h
1 /**
2  * $Id$
3  * ***** BEGIN GPL 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.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /*
30
31  * Copyright (c) 2000 Gino van den Bergen <gino@acm.org>
32  *
33  * Permission to use, copy, modify, distribute and sell this software
34  * and its documentation for any purpose is hereby granted without fee,
35  * provided that the above copyright notice appear in all copies and
36  * that both that copyright notice and this permission notice appear
37  * in supporting documentation.  Gino van den Bergen makes no
38  * representations about the suitability of this software for any
39  * purpose.  It is provided "as is" without express or implied warranty.
40  *
41  */
42
43 #ifndef MT_MATRIX3X3_H
44 #define MT_MATRIX3X3_H
45
46 #include <MT_assert.h>
47
48 #include "MT_Vector3.h"
49 #include "MT_Quaternion.h"
50
51 class MT_Matrix3x3 {
52 public:
53     MT_Matrix3x3() {}
54     MT_Matrix3x3(const float *m) { setValue(m); }
55     MT_Matrix3x3(const double *m) { setValue(m); }
56     MT_Matrix3x3(const MT_Quaternion& q) { setRotation(q); }
57     
58         MT_Matrix3x3(const MT_Quaternion& q, const MT_Vector3& s) { 
59                 setRotation(q); 
60                 scale(s[0], s[1], s[2]);
61         }
62         
63         MT_Matrix3x3(const MT_Vector3& euler) { setEuler(euler); }
64         MT_Matrix3x3(const MT_Vector3& euler, const MT_Vector3& s) { 
65                 setEuler(euler); 
66                 scale(s[0], s[1], s[2]);
67         }
68         
69     MT_Matrix3x3(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz,
70                  MT_Scalar yx, MT_Scalar yy, MT_Scalar yz,
71                  MT_Scalar zx, MT_Scalar zy, MT_Scalar zz) { 
72         setValue(xx, xy, xz, 
73                  yx, yy, yz, 
74                  zx, zy, zz);
75     }
76     
77     MT_Vector3&       operator[](int i)       { return m_el[i]; }
78     const MT_Vector3& operator[](int i) const { return m_el[i]; }
79
80         MT_Vector3 getColumn(int i) const {
81                 return MT_Vector3(m_el[0][i], m_el[1][i], m_el[2][i]);
82         }
83         void setColumn(int i, const MT_Vector3& v) {
84                 m_el[0][i] = v[0];
85                 m_el[1][i] = v[1];
86                 m_el[2][i] = v[2];
87         }
88     
89     void setValue(const float *m) {
90         m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m++;
91         m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++; m++;
92         m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m;
93     }
94
95     void setValue(const double *m) {
96         m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++; m++;
97         m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++; m++;
98         m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m;
99     }
100
101     void setValue3x3(const float *m) {
102         m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++;
103         m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++;
104         m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m;
105     }
106
107     void setValue3x3(const double *m) {
108         m_el[0][0] = *m++; m_el[1][0] = *m++; m_el[2][0] = *m++;
109         m_el[0][1] = *m++; m_el[1][1] = *m++; m_el[2][1] = *m++;
110         m_el[0][2] = *m++; m_el[1][2] = *m++; m_el[2][2] = *m;
111     }
112
113     void setValue(MT_Scalar xx, MT_Scalar xy, MT_Scalar xz, 
114                   MT_Scalar yx, MT_Scalar yy, MT_Scalar yz, 
115                   MT_Scalar zx, MT_Scalar zy, MT_Scalar zz) {
116         m_el[0][0] = xx; m_el[0][1] = xy; m_el[0][2] = xz;
117         m_el[1][0] = yx; m_el[1][1] = yy; m_el[1][2] = yz;
118         m_el[2][0] = zx; m_el[2][1] = zy; m_el[2][2] = zz;
119     }
120   
121     void setRotation(const MT_Quaternion& q) {
122         MT_Scalar d = q.length2();
123         MT_assert(!MT_fuzzyZero2(d));
124         MT_Scalar s = MT_Scalar(2.0) / d;
125         MT_Scalar xs = q[0] * s,   ys = q[1] * s,   zs = q[2] * s;
126         MT_Scalar wx = q[3] * xs,  wy = q[3] * ys,  wz = q[3] * zs;
127         MT_Scalar xx = q[0] * xs,  xy = q[0] * ys,  xz = q[0] * zs;
128         MT_Scalar yy = q[1] * ys,  yz = q[1] * zs,  zz = q[2] * zs;
129         setValue(MT_Scalar(1.0) - (yy + zz), xy - wz        ,         xz + wy,
130                  xy + wz        , MT_Scalar(1.0) - (xx + zz),         yz - wx,
131                  xz - wy        , yz + wx,         MT_Scalar(1.0) - (xx + yy));
132     }
133     
134         /**
135          * setEuler
136          * @param euler a const reference to a MT_Vector3 of euler angles
137          * These angles are used to produce a rotation matrix. The euler
138          * angles are applied in ZYX order. I.e a vector is first rotated 
139          * about X then Y and then Z
140          **/
141
142         void setEuler(const MT_Vector3& euler) {
143                 MT_Scalar ci = cos(euler[0]); 
144                 MT_Scalar cj = cos(euler[1]); 
145                 MT_Scalar ch = cos(euler[2]);
146                 MT_Scalar si = sin(euler[0]); 
147                 MT_Scalar sj = sin(euler[1]); 
148                 MT_Scalar sh = sin(euler[2]);
149                 MT_Scalar cc = ci * ch; 
150                 MT_Scalar cs = ci * sh; 
151                 MT_Scalar sc = si * ch; 
152                 MT_Scalar ss = si * sh;
153                 
154                 setValue(cj * ch, sj * sc - cs, sj * cc + ss,
155                                  cj * sh, sj * ss + cc, sj * cs - sc, 
156                                  -sj,      cj * si,      cj * ci);
157         }
158
159         void getEuler(MT_Scalar& yaw, MT_Scalar& pitch, MT_Scalar& roll) const
160                 {                       
161                         if (m_el[2][0] != -1.0 && m_el[2][0] != 1.0) {
162                                 pitch = MT_Scalar(-asin(m_el[2][0]));
163                                 yaw = MT_Scalar(atan2(m_el[2][1] / cos(pitch), m_el[2][2] / cos(pitch)));
164                                 roll = MT_Scalar(atan2(m_el[1][0] / cos(pitch), m_el[0][0] / cos(pitch)));                              
165                         }
166                         else {
167                                 roll = MT_Scalar(0);
168                                 if (m_el[2][0] == -1.0) {
169                                         pitch = MT_PI / 2.0;
170                                         yaw = MT_Scalar(atan2(m_el[0][1], m_el[0][2]));
171                                 }
172                                 else {
173                                         pitch = - MT_PI / 2.0;
174                                         yaw = MT_Scalar(atan2(m_el[0][1], m_el[0][2]));
175                                 }
176                         }
177                 }
178
179     void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z) {
180         m_el[0][0] *= x; m_el[0][1] *= y; m_el[0][2] *= z;
181         m_el[1][0] *= x; m_el[1][1] *= y; m_el[1][2] *= z;
182         m_el[2][0] *= x; m_el[2][1] *= y; m_el[2][2] *= z;
183     }
184
185     MT_Matrix3x3 scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z) const {
186         return MT_Matrix3x3(m_el[0][0] * x, m_el[0][1] * y, m_el[0][2] * z,
187                             m_el[1][0] * x, m_el[1][1] * y, m_el[1][2] * z,
188                             m_el[2][0] * x, m_el[2][1] * y, m_el[2][2] * z);
189     }
190     
191     void setIdentity() { 
192         setValue(MT_Scalar(1.0), MT_Scalar(0.0), MT_Scalar(0.0), 
193                  MT_Scalar(0.0), MT_Scalar(1.0), MT_Scalar(0.0), 
194                  MT_Scalar(0.0), MT_Scalar(0.0), MT_Scalar(1.0)); 
195     }
196     
197     void getValue(float *m) const {
198         *m++ = (float) m_el[0][0]; *m++ = (float) m_el[1][0]; *m++ = (float) m_el[2][0]; *m++ = (float) 0.0;
199         *m++ = (float) m_el[0][1]; *m++ = (float) m_el[1][1]; *m++ = (float) m_el[2][1]; *m++ = (float) 0.0;
200         *m++ = (float) m_el[0][2]; *m++ = (float) m_el[1][2]; *m++ = (float) m_el[2][2]; *m   = (float) 0.0;
201     }
202
203     void getValue(double *m) const {
204         *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0]; *m++ = 0.0;
205         *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1]; *m++ = 0.0;
206         *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2]; *m   = 0.0;
207     }
208
209     void getValue3x3(float *m) const {
210         *m++ = (float) m_el[0][0]; *m++ = (float) m_el[1][0]; *m++ = (float) m_el[2][0];
211         *m++ = (float) m_el[0][1]; *m++ = (float) m_el[1][1]; *m++ = (float) m_el[2][1];
212         *m++ = (float) m_el[0][2]; *m++ = (float) m_el[1][2]; *m++ = (float) m_el[2][2];
213     }
214
215     void getValue3x3(double *m) const {
216         *m++ = m_el[0][0]; *m++ = m_el[1][0]; *m++ = m_el[2][0];
217         *m++ = m_el[0][1]; *m++ = m_el[1][1]; *m++ = m_el[2][1];
218         *m++ = m_el[0][2]; *m++ = m_el[1][2]; *m++ = m_el[2][2];
219     }
220
221     MT_Quaternion getRotation() const;
222
223     MT_Matrix3x3& operator*=(const MT_Matrix3x3& m); 
224
225     MT_Scalar tdot(int c, const MT_Vector3& v) const {
226         return m_el[0][c] * v[0] + m_el[1][c] * v[1] + m_el[2][c] * v[2];
227     }
228   
229     MT_Scalar cofac(int r1, int c1, int r2, int c2) const {
230         return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
231     }
232
233     MT_Scalar    determinant() const;
234         MT_Matrix3x3 adjoint() const;
235
236     MT_Matrix3x3 absolute() const;
237
238     MT_Matrix3x3 transposed() const;
239     void         transpose();
240
241     MT_Matrix3x3 inverse() const; 
242         void         invert();
243   
244 protected:
245
246     MT_Vector3 m_el[3];
247 };
248
249 MT_Vector3   operator*(const MT_Matrix3x3& m, const MT_Vector3& v);
250 MT_Vector3   operator*(const MT_Vector3& v, const MT_Matrix3x3& m);
251 MT_Matrix3x3 operator*(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2);
252
253 MT_Matrix3x3 MT_multTransposeLeft(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2);
254 MT_Matrix3x3 MT_multTransposeRight(const MT_Matrix3x3& m1, const MT_Matrix3x3& m2);
255
256 inline MT_OStream& operator<<(MT_OStream& os, const MT_Matrix3x3& m) {
257     return os << m[0] << GEN_endl << m[1] << GEN_endl << m[2] << GEN_endl;
258 }
259
260 #ifdef GEN_INLINED
261 #include "MT_Matrix3x3.inl"
262 #endif
263
264 #endif
265