HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_Matrix4.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  */
7 
8 #pragma once
9 
10 #ifndef __UT_Matrix4_h__
11 #define __UT_Matrix4_h__
12 
13 #include "UT_API.h"
14 #include "UT_Assert.h"
15 #include "UT_Axis.h"
16 #include "UT_FixedVector.h"
17 #include "UT_SymMatrix4.h"
18 #include "UT_Vector3.h"
19 #include "UT_Vector4.h"
20 #include "UT_VectorTypes.h"
21 #include "UT_XformOrder.h"
22 
23 #include <SYS/SYS_Math.h>
24 #include <iosfwd>
25 
26 #ifndef UT_DISABLE_VECTORIZE_MATRIX
27 #include <VM/VM_SIMD.h>
28 #endif
29 
30 
31 class UT_IStream;
32 class UT_JSONWriter;
33 class UT_JSONValue;
34 class UT_JSONParser;
35 
36 
37 // Free floating operators that return a UT_Matrix4 object.
38 template <typename T>
39 inline UT_Matrix4T<T> operator+(const UT_Matrix4T<T> &m1, const UT_Matrix4T<T> &m2);
40 template <typename T>
41 inline UT_Matrix4T<T> operator-(const UT_Matrix4T<T> &m1, const UT_Matrix4T<T> &m2);
42 template <typename T>
43 inline UT_Matrix4T<T> operator*(const UT_Matrix4T<T> &m1, const UT_Matrix4T<T> &m2);
44 template <typename T, typename S>
45 inline UT_Matrix4T<T> operator+(const UT_Matrix4T<T> &mat, const UT_Vector4T<S> &vec);
46 template <typename T, typename S>
47 inline UT_Matrix4T<T> operator+(const UT_Vector4T<S> &vec, const UT_Matrix4T<T> &mat);
48 template <typename T, typename S>
49 inline UT_Matrix4T<T> operator-(const UT_Matrix4T<T> &mat, const UT_Vector4T<S> &vec);
50 template <typename T, typename S>
51 inline UT_Matrix4T<T> operator-(const UT_Vector4T<S> &vec, const UT_Matrix4T<T> &mat);
52 template <typename T, typename S>
53 inline UT_Matrix4T<T> operator+(const UT_Matrix4T<T> &mat, S sc);
54 template <typename T, typename S>
55 inline UT_Matrix4T<T> operator-(const UT_Matrix4T<T> &mat, S sc);
56 template <typename T, typename S>
57 inline UT_Matrix4T<T> operator*(const UT_Matrix4T<T> &mat, S sc);
58 template <typename T, typename S>
59 inline UT_Matrix4T<T> operator/(const UT_Matrix4T<T> &mat, S sc);
60 template <typename T, typename S>
61 inline UT_Matrix4T<T> operator+(S sc, const UT_Matrix4T<T> &mat);
62 template <typename T, typename S>
63 inline UT_Matrix4T<T> operator-(S sc, const UT_Matrix4T<T> &mat);
64 template <typename T, typename S>
65 inline UT_Matrix4T<T> operator*(S sc, const UT_Matrix4T<T> &mat);
66 template <typename T, typename S>
67 inline UT_Matrix4T<T> operator/(S sc, const UT_Matrix4T<T> &mat);
68 
69 template <typename T>
70 inline UT_Matrix4T<T> SYSmin (const UT_Matrix4T<T> &v1, const UT_Matrix4T<T> &v2);
71 template <typename T>
72 inline UT_Matrix4T<T> SYSmax (const UT_Matrix4T<T> &v1, const UT_Matrix4T<T> &v2);
73 template <typename T,typename S>
74 inline UT_Matrix4T<T> SYSlerp(const UT_Matrix4T<T> &v1, const UT_Matrix4T<T> &v2, S t);
75 
76 /// Bilinear interpolation
77 template <typename T,typename S>
78 inline UT_Matrix4T<T> SYSbilerp(const UT_Matrix4T<T> &u0v0, const UT_Matrix4T<T> &u1v0,
79  const UT_Matrix4T<T> &u0v1, const UT_Matrix4T<T> &u1v1,
80  S u, S v)
81 { return SYSlerp(SYSlerp(u0v0, u0v1, v), SYSlerp(u1v0, u1v1, v), u); }
82 
83 /// Barycentric interpolation
84 template <typename T, typename S>
86  const UT_Matrix4T<T> &v1, const UT_Matrix4T<T> &v2, S u, S v)
87 { return v0 * (1 - u - v) + v1 * u + v2 *v; }
88 
89 /// This class implements a 4x4 fpreal matrix in row-major order.
90 ///
91 /// Most of Houdini operates with row vectors that are left-multiplied with
92 /// matrices. e.g., z = v * M
93 /// As a result, translation data is in row 3 of the matrix, rather than
94 /// column 3.
95 template <typename T>
97 {
98 public:
99 
100  typedef T value_type;
101  static constexpr const int tuple_size = 16;
102 
103  /// Construct uninitialized matrix.
104  SYS_FORCE_INLINE UT_Matrix4T() = default;
105 
106  /// Default copy constructor
107  constexpr UT_Matrix4T(const UT_Matrix4T &) = default;
108 
109  /// Default move constructor
110  constexpr UT_Matrix4T(UT_Matrix4T &&) = default;
111 
112  /// Construct identity matrix, multipled by scalar.
113  explicit constexpr UT_Matrix4T(fpreal64 val) noexcept
114  : matx{
115  {T(val),0,0,0},
116  {0,T(val),0,0},
117  {0,0,T(val),0},
118  {0,0,0,T(val)}}
119  {
120  SYS_STATIC_ASSERT(sizeof(UT_Matrix4T<T>) == tuple_size * sizeof(T));
121  }
122  /// Construct a deep copy of the input row-major data.
123  /// @{
124  template <typename S>
125  explicit constexpr UT_Matrix4T(const S m[4][4]) noexcept
126  : matx{
127  {T(m[0][0]),T(m[0][1]),T(m[0][2]),T(m[0][3])},
128  {T(m[1][0]),T(m[1][1]),T(m[1][2]),T(m[1][3])},
129  {T(m[2][0]),T(m[2][1]),T(m[2][2]),T(m[2][3])},
130  {T(m[3][0]),T(m[3][1]),T(m[3][2]),T(m[3][3])}}
131  {}
132  /// @}
133 
134  /// Arbitrary UT_FixedVector of the same size
135  template <typename S>
137  {
138  matx[0][0]=v[0]; matx[0][1]=v[1]; matx[0][2]=v[2]; matx[0][3]=v[3];
139  matx[1][0]=v[4]; matx[1][1]=v[5]; matx[1][2]=v[6]; matx[1][3]=v[7];
140  matx[2][0]=v[8]; matx[2][1]=v[9]; matx[2][2]=v[10];matx[2][3]=v[11];
141  matx[3][0]=v[12];matx[3][1]=v[13];matx[3][2]=v[14];matx[3][3]=v[15];
142  }
143 
144  /// This constructor is for convenience.
145  UT_Matrix4T(T val00, T val01, T val02, T val03,
146  T val10, T val11, T val12, T val13,
147  T val20, T val21, T val22, T val23,
148  T val30, T val31, T val32, T val33)
149  {
150  matx[0][0] = val00; matx[0][1] = val01; matx[0][2] = val02;
151  matx[0][3] = val03;
152  matx[1][0] = val10; matx[1][1] = val11; matx[1][2] = val12;
153  matx[1][3] = val13;
154  matx[2][0] = val20; matx[2][1] = val21; matx[2][2] = val22;
155  matx[2][3] = val23;
156  matx[3][0] = val30; matx[3][1] = val31; matx[3][2] = val32;
157  matx[3][3] = val33;
158  }
159 
160  /// Base type conversion constructor
161  template <typename S>
162  explicit UT_Matrix4T(const UT_Matrix4T<S> &m)
163  {
164  matx[0][0]=m(0,0); matx[0][1]=m(0,1); matx[0][2]=m(0,2); matx[0][3]=m(0,3);
165  matx[1][0]=m(1,0); matx[1][1]=m(1,1); matx[1][2]=m(1,2); matx[1][3]=m(1,3);
166  matx[2][0]=m(2,0); matx[2][1]=m(2,1); matx[2][2]=m(2,2); matx[2][3]=m(2,3);
167  matx[3][0]=m(3,0); matx[3][1]=m(3,1); matx[3][2]=m(3,2); matx[3][3]=m(3,3);
168  }
169  template <typename S>
170  explicit UT_Matrix4T(const UT_Matrix3T<S> &m)
171  {
172  matx[0][0]=m(0,0); matx[0][1]=m(0,1); matx[0][2]=m(0,2); matx[0][3]=(T)0.;
173  matx[1][0]=m(1,0); matx[1][1]=m(1,1); matx[1][2]=m(1,2); matx[1][3]=(T)0.;
174  matx[2][0]=m(2,0); matx[2][1]=m(2,1); matx[2][2]=m(2,2); matx[2][3]=(T)0.;
175  matx[3][0]=(T)0.; matx[3][1]=(T)0.; matx[3][2]=(T)0.; matx[3][3]=(T)1.;
176  }
177 
178  template <typename S>
179  explicit UT_Matrix4T(const UT_Matrix3T<S> &m, const UT_Vector3T<S> &t)
180  {
181  matx[0][0]=m(0,0); matx[0][1]=m(0,1); matx[0][2]=m(0,2); matx[0][3]=(T)0.;
182  matx[1][0]=m(1,0); matx[1][1]=m(1,1); matx[1][2]=m(1,2); matx[1][3]=(T)0.;
183  matx[2][0]=m(2,0); matx[2][1]=m(2,1); matx[2][2]=m(2,2); matx[2][3]=(T)0.;
184  matx[3][0]=(T)t[0]; matx[3][1]=(T)t[1]; matx[3][2]=(T)t[2]; matx[3][3]=(T)1.;
185  }
186 
187  template<typename S>
189  {
190  *this = m;
191  }
192 
193  /// Default copy assignment operator
194  UT_Matrix4T<T> &operator=(const UT_Matrix4T<T> &m) = default;
195 
196  /// Default move assignment operator
197  UT_Matrix4T<T> &operator=(UT_Matrix4T<T> &&m) = default;
198 
199  /// Conversion operator that expands a 3x3 into a 4x4 matrix by adding a
200  /// row and column of zeroes, except the diagonal element which is 1.
201  // @{
202  template <typename S>
204  {
205  matx[0][0]=m(0,0); matx[0][1]=m(0,1);
206  matx[0][2]=m(0,2); matx[0][3]=(T)0.;
207  matx[1][0]=m(1,0); matx[1][1]=m(1,1);
208  matx[1][2]=m(1,2); matx[1][3]=(T)0.;
209  matx[2][0]=m(2,0); matx[2][1]=m(2,1);
210  matx[2][2]=m(2,2); matx[2][3]=(T)0.;
211  matx[3][0]=(T)0.; matx[3][1]=(T)0.;
212  matx[3][2]=(T)0.; matx[3][3]=(T)1.;
213  return *this;
214  }
215  // @}
216  template <typename S>
218  {
219  matx[0][0]=m(0,0); matx[0][1]=m(0,1);
220  matx[0][2]=m(0,2); matx[0][3]=m(0,3);
221  matx[1][0]=m(1,0); matx[1][1]=m(1,1);
222  matx[1][2]=m(1,2); matx[1][3]=m(1,3);
223  matx[2][0]=m(2,0); matx[2][1]=m(2,1);
224  matx[2][2]=m(2,2); matx[2][3]=m(2,3);
225  matx[3][0]=m(3,0); matx[3][1]=m(3,1);
226  matx[3][2]=m(3,2); matx[3][3]=m(3,3);
227  return *this;
228  }
229 
230  /// Conversion from a symmetric to a non symmetric matrix
231  template <typename S>
233  {
234  matx[0][0] = m.q00; matx[0][1] = m.q01; matx[0][2] = m.q02;
235  matx[0][3] = m.q03; matx[1][0] = m.q01; matx[1][1] = m.q11;
236  matx[1][2] = m.q12; matx[1][3] = m.q13; matx[2][0] = m.q02;
237  matx[2][1] = m.q12; matx[2][2] = m.q22; matx[2][3] = m.q23;
238  matx[3][0] = m.q03; matx[3][1] = m.q13; matx[3][2] = m.q23;
239  matx[3][3] = m.q33;
240  return *this;
241  }
242 
244  {
245  return UT_Matrix4T<T>(
246  -matx[0][0], -matx[0][1], -matx[0][2], -matx[0][3],
247  -matx[1][0], -matx[1][1], -matx[1][2], -matx[1][3],
248  -matx[2][0], -matx[2][1], -matx[2][2], -matx[2][3],
249  -matx[3][0], -matx[3][1], -matx[3][2], -matx[3][3]);
250  }
251 
254  {
255  matx[0][0]+=m.matx[0][0]; matx[0][1]+=m.matx[0][1];
256  matx[0][2]+=m.matx[0][2]; matx[0][3]+=m.matx[0][3];
257 
258  matx[1][0]+=m.matx[1][0]; matx[1][1]+=m.matx[1][1];
259  matx[1][2]+=m.matx[1][2]; matx[1][3]+=m.matx[1][3];
260 
261  matx[2][0]+=m.matx[2][0]; matx[2][1]+=m.matx[2][1];
262  matx[2][2]+=m.matx[2][2]; matx[2][3]+=m.matx[2][3];
263 
264  matx[3][0]+=m.matx[3][0]; matx[3][1]+=m.matx[3][1];
265  matx[3][2]+=m.matx[3][2]; matx[3][3]+=m.matx[3][3];
266  return *this;
267  }
270  {
271  matx[0][0]-=m.matx[0][0]; matx[0][1]-=m.matx[0][1];
272  matx[0][2]-=m.matx[0][2]; matx[0][3]-=m.matx[0][3];
273 
274  matx[1][0]-=m.matx[1][0]; matx[1][1]-=m.matx[1][1];
275  matx[1][2]-=m.matx[1][2]; matx[1][3]-=m.matx[1][3];
276 
277  matx[2][0]-=m.matx[2][0]; matx[2][1]-=m.matx[2][1];
278  matx[2][2]-=m.matx[2][2]; matx[2][3]-=m.matx[2][3];
279 
280  matx[3][0]-=m.matx[3][0]; matx[3][1]-=m.matx[3][1];
281  matx[3][2]-=m.matx[3][2]; matx[3][3]-=m.matx[3][3];
282  return *this;
283  }
284  template<typename S>
285  inline UT_Matrix4T<T> &operator*=(const UT_Matrix4T<S> &m);
286  template<typename S>
287  inline UT_Matrix4T<T> &operator*=(const UT_Matrix3T<S> &m);
288 
289  // test for exact floating point equality.
290  // for equality within a threshold, see isEqual()
291  bool operator==(const UT_Matrix4T<T> &m) const
292  {
293  return (&m == this) || (
294  matx[0][0]==m.matx[0][0] && matx[0][1]==m.matx[0][1] &&
295  matx[0][2]==m.matx[0][2] && matx[0][3]==m.matx[0][3] &&
296 
297  matx[1][0]==m.matx[1][0] && matx[1][1]==m.matx[1][1] &&
298  matx[1][2]==m.matx[1][2] && matx[1][3]==m.matx[1][3] &&
299 
300  matx[2][0]==m.matx[2][0] && matx[2][1]==m.matx[2][1] &&
301  matx[2][2]==m.matx[2][2] && matx[2][3]==m.matx[2][3] &&
302 
303  matx[3][0]==m.matx[3][0] && matx[3][1]==m.matx[3][1] &&
304  matx[3][2]==m.matx[3][2] && matx[3][3]==m.matx[3][3] );
305  }
306 
307  bool operator!=(const UT_Matrix4T<T> &m) const
308  {
309  return !(*this == m);
310  }
311 
312  // Scalar operators:
313  UT_Matrix4T<T> &operator= (fpreal64 v)
314  {
315  matx[0][0]= v; matx[0][1]= 0; matx[0][2]= 0; matx[0][3]= 0;
316  matx[1][0]= 0; matx[1][1]= v; matx[1][2]= 0; matx[1][3]= 0;
317  matx[2][0]= 0; matx[2][1]= 0; matx[2][2]= v; matx[2][3]= 0;
318  matx[3][0]= 0; matx[3][1]= 0; matx[3][2]= 0; matx[3][3]= v;
319  return *this;
320  }
321  /// NOTE: DO NOT use this for scaling the transform,
322  /// since this scales the w column (3) as well,
323  /// causing problems with translation later.
324  /// Use M.scale(scalar) instead.
327  {
328  matx[0][0]*=scalar; matx[0][1]*=scalar;
329  matx[0][2]*=scalar; matx[0][3]*=scalar;
330 
331  matx[1][0]*=scalar; matx[1][1]*=scalar;
332  matx[1][2]*=scalar; matx[1][3]*=scalar;
333 
334  matx[2][0]*=scalar; matx[2][1]*=scalar;
335  matx[2][2]*=scalar; matx[2][3]*=scalar;
336 
337  matx[3][0]*=scalar; matx[3][1]*=scalar;
338  matx[3][2]*=scalar; matx[3][3]*=scalar;
339  return *this;
340  }
343  {
344  return operator*=( 1.0f/scalar );
345  }
346 
347  // Vector4 operators:
348  template <typename S>
349  inline UT_Matrix4T<T> &operator=(const UT_Vector4T<S> &vec);
350  template <typename S>
351  inline UT_Matrix4T<T> &operator+=(const UT_Vector4T<S> &vec);
352  template <typename S>
353  inline UT_Matrix4T<T> &operator-=(const UT_Vector4T<S> &vec);
354 
355  // Other matrix operations:
356 
357  /// Multiply the passed-in matrix (on the left) by this (on the right)
358  /// and assign the result to this.
359  /// (operator*= does right-multiplication)
360  /// @{
361  inline void leftMult( const UT_Matrix4T<T> &m );
362  void preMultiply(const UT_Matrix4T<T> &m) { leftMult(m); }
363  /// @}
364 
365  // Return the cofactor of the matrix, ie the determinant of the 3x3
366  // submatrix that results from removing row 'k' and column 'l' from the
367  // 4x4.
368  SYS_FORCE_INLINE T coFactor(int k, int l) const
369  {
370  int r[3], c[3];
371  T det;
372 
373  // r, c should evaluate to compile time constants
374  coVals(k, r);
375  coVals(l, c);
376 
377  det = matx[r[0]][c[0]]*
378  (matx[r[1]][c[1]]*matx[r[2]][c[2]]-
379  matx[r[1]][c[2]]*matx[r[2]][c[1]]) +
380  matx[r[0]][c[1]]*
381  (matx[r[1]][c[2]]*matx[r[2]][c[0]]-
382  matx[r[1]][c[0]]*matx[r[2]][c[2]]) +
383  matx[r[0]][c[2]]*
384  (matx[r[1]][c[0]]*matx[r[2]][c[1]]-
385  matx[r[1]][c[1]]*matx[r[2]][c[0]]);
386 
387  if ((k ^ l) & 1)
388  det = -det;
389 
390  return det;
391  }
392 
393  T determinant() const
394  {
395  return(matx[0][0]*coFactor(0,0) +
396  matx[0][1]*coFactor(0,1) +
397  matx[0][2]*coFactor(0,2) +
398  matx[0][3]*coFactor(0,3) );
399  }
400  /// Compute determinant of the upper-left 3x3 sub-matrix
401  T determinant3() const
402  {
403  return(matx[0][0]*
404  (matx[1][1]*matx[2][2]-matx[1][2]*matx[2][1]) +
405  matx[0][1]*
406  (matx[1][2]*matx[2][0]-matx[1][0]*matx[2][2]) +
407  matx[0][2]*
408  (matx[1][0]*matx[2][1]-matx[1][1]*matx[2][0]) );
409 
410  }
411  T trace() const
412  { return matx[0][0]+matx[1][1]+matx[2][2]+matx[3][3]; }
413 
414  /// Invert this matrix and return 0 if OK, 1 if singular.
415  // @{
416  int invert(T tol = 0.0F);
417  int invertDouble();
418  // @}
419 
420  /// Invert the matrix and return 0 if OK, 1 if singular.
421  /// Puts the inverted matrix in m, and leaves this matrix unchanged.
422  // @{
423  int invert(UT_Matrix4T<T> &m) const;
424  int invertDouble(UT_Matrix4T<T> &m) const;
425  // @}
426  int invertKramer();
427  int invertKramer(UT_Matrix4T<T> &m)const;
428 
429  // Solve a 4x4 system of equations A*x=b, where A is this matrix, b is
430  // given and x is unknown. The method returns 0 if the determinant is not
431  // 0, and 1 otherwise.
432  template <typename S>
433  int solve(const UT_Vector4T<S> &b,
434  UT_Vector4T<S> &x) const;
435 
436  // Solve a 4x4 system of equations x*A=b, where A is this matrix, b is
437  // given and x is unknown. The method returns 0 if the determinant is not
438  // 0, and 1 otherwise.
439  template <typename S>
440  int solveTranspose(const UT_Vector4T<S> &b,
441  UT_Vector4T<S> &x) const;
442 
443  // Computes a transform to orient to a given direction (v) at a given
444  // position (p) and with a scale (s). The up vector (up) is optional
445  // and will orient the matrix to this up vector. If no up vector is given,
446  // the z axis will be oriented to point in the v direction. If a
447  // quaternion (q) is specified, the orientation will be additionally
448  // transformed by the rotation specified by the quaternion. If a
449  // translation (tr) is specified, the entire frame of reference will
450  // be moved by this translation (unaffected by the scale or rotation).
451  // If an orientation (orient) is specified, the orientation (using the
452  // velocity and up vector) will not be performed and this orientation will
453  // instead be used to define an original orientation.
454  //
455  // The matrix is scaled non-uniformly about each axis using s3, if s3
456  // is non-zero. A uniform scale of pscale is applied regardless, so if
457  // s3 is non-zero, the x axis will be scaled by pscale * s3->x().
458  template <typename S>
459  void instanceT(const UT_Vector3T<S>& p, const UT_Vector3T<S>& v, T s,
460  const UT_Vector3T<S>* s3,
461  const UT_Vector3T<S>* up, const UT_QuaternionT<S>* q,
462  const UT_Vector3T<S>* tr, const UT_QuaternionT<S>* orient,
463  const UT_Vector3T<S>* pivot);
464  void instance(const UT_Vector3F& p, const UT_Vector3F& v, T s,
465  const UT_Vector3F* s3,
466  const UT_Vector3F* up, const UT_QuaternionF* q,
467  const UT_Vector3F* tr, const UT_QuaternionF* orient,
468  const UT_Vector3F* pivot = NULL )
469  { instanceT(p, v, s, s3, up, q, tr, orient, pivot); }
470  void instance(const UT_Vector3D& p, const UT_Vector3D& v, T s,
471  const UT_Vector3D* s3,
472  const UT_Vector3D* up, const UT_QuaternionD* q,
473  const UT_Vector3D* tr, const UT_QuaternionD* orient,
474  const UT_Vector3D* pivot = NULL )
475  { instanceT(p, v, s, s3, up, q, tr, orient, pivot); }
476 
477  template <typename S>
478  void instanceInverseT(const UT_Vector3T<S>& p, const UT_Vector3T<S>& v, T s,
479  const UT_Vector3T<S>* s3,
480  const UT_Vector3T<S>* up, const UT_QuaternionT<S>* q,
481  const UT_Vector3T<S>* tr, const UT_QuaternionT<S>* orient,
482  const UT_Vector3T<S>* pivot);
483  void instanceInverse(const UT_Vector3F& p, const UT_Vector3F& v, T s,
484  const UT_Vector3F* s3,
485  const UT_Vector3F* up, const UT_QuaternionF* q,
486  const UT_Vector3F* tr, const UT_QuaternionF* orient,
487  const UT_Vector3F* pivot = NULL )
488  { instanceInverseT(p, v, s, s3, up, q, tr, orient, pivot); }
489  void instanceInverse(const UT_Vector3D& p, const UT_Vector3D& v, T s,
490  const UT_Vector3D* s3,
491  const UT_Vector3D* up, const UT_QuaternionD* q,
492  const UT_Vector3D* tr, const UT_QuaternionD* orient,
493  const UT_Vector3D* pivot = NULL )
494  { instanceInverseT(p, v, s, s3, up, q, tr, orient, pivot); }
495 
496  // Transpose this matrix or return its transpose.
497  void transpose()
498  {
499  T tmp;
500  tmp=matx[0][1]; matx[0][1]=matx[1][0]; matx[1][0]=tmp;
501  tmp=matx[0][2]; matx[0][2]=matx[2][0]; matx[2][0]=tmp;
502  tmp=matx[0][3]; matx[0][3]=matx[3][0]; matx[3][0]=tmp;
503  tmp=matx[1][2]; matx[1][2]=matx[2][1]; matx[2][1]=tmp;
504  tmp=matx[1][3]; matx[1][3]=matx[3][1]; matx[3][1]=tmp;
505  tmp=matx[2][3]; matx[2][3]=matx[3][2]; matx[3][2]=tmp;
506  }
507 
508  // check for equality within a tolerance level
509  bool isEqual( const UT_Matrix4T<T> &m,
510  T tolerance=T(SYS_FTOLERANCE) ) const
511  {
512  return (&m == this) || (
513  SYSisEqual( matx[0][0], m.matx[0][0], tolerance ) &&
514  SYSisEqual( matx[0][1], m.matx[0][1], tolerance ) &&
515  SYSisEqual( matx[0][2], m.matx[0][2], tolerance ) &&
516  SYSisEqual( matx[0][3], m.matx[0][3], tolerance ) &&
517 
518  SYSisEqual( matx[1][0], m.matx[1][0], tolerance ) &&
519  SYSisEqual( matx[1][1], m.matx[1][1], tolerance ) &&
520  SYSisEqual( matx[1][2], m.matx[1][2], tolerance ) &&
521  SYSisEqual( matx[1][3], m.matx[1][3], tolerance ) &&
522 
523  SYSisEqual( matx[2][0], m.matx[2][0], tolerance ) &&
524  SYSisEqual( matx[2][1], m.matx[2][1], tolerance ) &&
525  SYSisEqual( matx[2][2], m.matx[2][2], tolerance ) &&
526  SYSisEqual( matx[2][3], m.matx[2][3], tolerance ) &&
527 
528  SYSisEqual( matx[3][0], m.matx[3][0], tolerance ) &&
529  SYSisEqual( matx[3][1], m.matx[3][1], tolerance ) &&
530  SYSisEqual( matx[3][2], m.matx[3][2], tolerance ) &&
531  SYSisEqual( matx[3][3], m.matx[3][3], tolerance ) );
532  }
533 
534  /// Post-multiply this matrix by a 3x3 rotation matrix determined by the
535  /// axis and angle of rotation in radians.
536  /// If 'norm' is not 0, the axis vector is normalized before computing the
537  /// rotation matrix. rotationMat() returns a rotation matrix, and could as
538  /// well be defined as a free floating function.
539  /// @{
540  template <typename S>
541  void rotate(UT_Vector3T<S> &axis, T theta, int norm=1);
542  void rotate(UT_Axis3::axis a, T theta);
543  template<UT_Axis3::axis A>
544  void rotate(T theta);
545  /// @}
546 
547  /// Post-multiply this matrix by a 3x3 rotation matrix (on the right)
548  /// for a quarter turn (90 degrees) around the specified axis
549  template<UT_Axis3::axis A,bool reverse=false>
551  {
552  constexpr uint col0 = (A == UT_Axis3::XAXIS) ? 1 : ((A == UT_Axis3::YAXIS) ? 2 : 0);
553  constexpr uint col1 = (A == UT_Axis3::XAXIS) ? 2 : ((A == UT_Axis3::YAXIS) ? 0 : 1);
554  for (uint row = 0; row < 4; ++row)
555  {
556  T v1 = matx[row][col0];
557  if (!reverse)
558  {
559  matx[row][col0] = -matx[row][col1];
560  matx[row][col1] = v1;
561  }
562  else
563  {
564  matx[row][col0] = matx[row][col1];
565  matx[row][col1] = -v1;
566  }
567  }
568  }
569 
570  /// Post-multiply this matrix by a 3x3 rotation matrix (on the right)
571  /// for a half turn (180 degrees) around the specified axis
572  template<UT_Axis3::axis A>
574  {
575  // In this case, order doesn't matter, so make col0 and col1 in increasing order.
576  constexpr uint col0 = (A == UT_Axis3::XAXIS) ? 1 : 0;
577  constexpr uint col1 = (A == UT_Axis3::ZAXIS) ? 1 : 2;
578  for (uint row = 0; row < 4; ++row)
579  {
580  matx[row][col0] = -matx[row][col0];
581  matx[row][col1] = -matx[row][col1];
582  }
583  }
584 
585  /// This is just a helper function for code handling quarter turns exactly.
586  /// NOTE: theta is in *radians* already, not degrees!
587  template<UT_Axis3::axis A>
589  {
590  if (theta)
591  rotate<A>(theta);
592  else if (qturns)
593  {
594  if (qturns&2)
595  rotateHalf<A>();
596  if (qturns&1)
597  rotateQuarter<A>();
598  }
599  }
600 
601  /// Create a rotation matrix for the given angle in radians around the axis
602  /// @{
603  template <typename S>
604  static UT_Matrix4T<T> rotationMat(UT_Vector3T<S> &axis, T theta, int norm=1);
605  static UT_Matrix4T<T> rotationMat(UT_Axis3::axis a, T theta);
606  /// @}
607 
608  /// Pre-multiply this matrix by a 3x3 rotation matrix determined by the
609  /// axis and angle of rotation in radians.
610  /// If 'norm' is not 0, the axis vector is normalized before computing the
611  /// rotation matrix. rotationMat() returns a rotation matrix, and could as
612  /// well be defined as a free floating function.
613  /// @{
614  template <typename S>
615  void prerotate(UT_Vector3T<S> &axis, T theta, int norm=1);
616  void prerotate(UT_Axis3::axis a, T theta);
617  template<UT_Axis3::axis A>
618  void prerotate(T theta);
619  /// @}
620 
621  /// Pre-multiply this matrix by a 3x3 rotation matrix (on the left)
622  /// for a quarter turn (90 degrees) around the specified axis
623  template<UT_Axis3::axis A,bool reverse=false>
625  {
626  constexpr uint row0 = (A == UT_Axis3::XAXIS) ? 1 : ((A == UT_Axis3::YAXIS) ? 2 : 0);
627  constexpr uint row1 = (A == UT_Axis3::XAXIS) ? 2 : ((A == UT_Axis3::YAXIS) ? 0 : 1);
628  T v1[4];
629  for (uint col = 0; col < 4; ++col)
630  v1[col] = matx[row0][col];
631  if (!reverse)
632  {
633  for (uint col = 0; col < 4; ++col)
634  matx[row0][col] = matx[row1][col];
635  for (uint col = 0; col < 4; ++col)
636  matx[row1][col] = -v1[col];
637  }
638  else
639  {
640  for (uint col = 0; col < 4; ++col)
641  matx[row0][col] = -matx[row1][col];
642  for (uint col = 0; col < 4; ++col)
643  matx[row1][col] = v1[col];
644  }
645  }
646 
647  /// Pre-multiply this matrix by a 3x3 rotation matrix (on the left)
648  /// for a half turn (180 degrees) around the specified axis
649  template<UT_Axis3::axis A>
651  {
652  // In this case, order doesn't matter, so make row0 and row1 in increasing order.
653  constexpr uint row0 = (A == UT_Axis3::XAXIS) ? 1 : 0;
654  constexpr uint row1 = (A == UT_Axis3::ZAXIS) ? 1 : 2;
655  for (uint col = 0; col < 4; ++col)
656  matx[row0][col] = -matx[row0][col];
657  for (uint col = 0; col < 4; ++col)
658  matx[row1][col] = -matx[row1][col];
659  }
660 
661  /// Post-rotate by rx, ry, rz radians around the three basic axes in the
662  /// order given by UT_XformOrder.
663  /// @{
664  void rotate(T rx, T ry, T rz, const UT_XformOrder &ord);
666  void rotate(const UT_Vector3T<T> &rad, const UT_XformOrder &ord)
667  { rotate(rad(0), rad(1), rad(2), ord); }
668  /// @}
669 
670  /// Pre-rotate by rx, ry, rz radians around the three basic axes in the
671  /// order given by UT_XformOrder.
672  /// @{
673  void prerotate(T rx, T ry, T rz,
674  const UT_XformOrder &ord);
676  void prerotate(const UT_Vector3T<T> &rad, const UT_XformOrder &ord)
677  { prerotate(rad(0), rad(1), rad(2), ord); }
678  /// @}
679 
680  /// Post-multiply this matrix by a scale matrix with diagonal (sx, sy, sz)
681  /// @{
682  void scale(T sx, T sy, T sz, T sw = 1.0f)
683  {
684  matx[0][0] *= sx; matx[0][1] *= sy;
685  matx[0][2] *= sz; matx[0][3] *= sw;
686 
687  matx[1][0] *= sx; matx[1][1] *= sy;
688  matx[1][2] *= sz; matx[1][3] *= sw;
689 
690  matx[2][0] *= sx; matx[2][1] *= sy;
691  matx[2][2] *= sz; matx[2][3] *= sw;
692 
693  matx[3][0] *= sx; matx[3][1] *= sy;
694  matx[3][2] *= sz; matx[3][3] *= sw;
695  }
697  { scale(s(0), s(1), s(2)); }
699  { scale(s, s, s); }
700  /// @}
701 
702  /// Pre-multiply this matrix by a scale matrix with diagonal (sx, sy, sz)
703  /// @{
704  void prescale(T sx, T sy, T sz, T sw = 1.0f)
705  {
706  matx[0][0] *= sx; matx[1][0] *= sy;
707  matx[2][0] *= sz; matx[3][0] *= sw;
708 
709  matx[0][1] *= sx; matx[1][1] *= sy;
710  matx[2][1] *= sz; matx[3][1] *= sw;
711 
712  matx[0][2] *= sx; matx[1][2] *= sy;
713  matx[2][2] *= sz; matx[3][2] *= sw;
714 
715  matx[0][3] *= sx; matx[1][3] *= sy;
716  matx[2][3] *= sz; matx[3][3] *= sw;
717  }
719  { prescale(s(0), s(1), s(2)); }
721  { prescale(s, s, s); }
722  /// @}
723 
724  /// Post-multiply this matrix by the shear matrix formed by (sxy, sxz, syz)
725  /// @{
726  void shear(T s_xy, T s_xz, T s_yz)
727  {
728  matx[0][0] += matx[0][1]*s_xy + matx[0][2]*s_xz;
729  matx[0][1] += matx[0][2]*s_yz;
730 
731  matx[1][0] += matx[1][1]*s_xy + matx[1][2]*s_xz;
732  matx[1][1] += matx[1][2]*s_yz;
733 
734  matx[2][0] += matx[2][1]*s_xy + matx[2][2]*s_xz;
735  matx[2][1] += matx[2][2]*s_yz;
736 
737  matx[3][0] += matx[3][1]*s_xy + matx[3][2]*s_xz;
738  matx[3][1] += matx[3][2]*s_yz;
739  }
741  void shear(const UT_Vector3T<T> &sh)
742  { shear(sh(0), sh(1), sh(2)); }
743  /// @}
744 
745  /// Post-multiply this matrix by the translation determined by dx, dy, dz.
746  /// @{
747  void translate(T dx, T dy, T dz = 0.0f)
748  {
749  T a;
750  a = matx[0][3];
751  matx[0][0] += a*dx; matx[0][1] += a*dy; matx[0][2] += a*dz;
752  a = matx[1][3];
753  matx[1][0] += a*dx; matx[1][1] += a*dy; matx[1][2] += a*dz;
754  a = matx[2][3];
755  matx[2][0] += a*dx; matx[2][1] += a*dy; matx[2][2] += a*dz;
756  a = matx[3][3];
757  matx[3][0] += a*dx; matx[3][1] += a*dy; matx[3][2] += a*dz;
758  }
760  void translate(const UT_Vector3T<T> &delta)
761  { translate(delta(0), delta(1), delta(2)); }
762  /// @}
763 
764  /// Pre-multiply this matrix by the translation determined by dx, dy, dz.
765  /// @{
766  void pretranslate(T dx, T dy, T dz = 0.0f)
767  {
768  matx[3][0] += matx[0][0]*dx + matx[1][0]*dy + matx[2][0]*dz;
769  matx[3][1] += matx[0][1]*dx + matx[1][1]*dy + matx[2][1]*dz;
770  matx[3][2] += matx[0][2]*dx + matx[1][2]*dy + matx[2][2]*dz;
771  matx[3][3] += matx[0][3]*dx + matx[1][3]*dy + matx[2][3]*dz;
772  }
774  void pretranslate(const UT_Vector3T<T> &delta)
775  { pretranslate(delta(0), delta(1), delta(2)); }
776  /// @}
777 
778  // Space change operation: right multiply this matrix by the 3x3 matrix
779  // of the transformation which moves the vector space defined by
780  // (iSrc, jSrc, cross(iSrc,jSrc)) into the space defined by
781  // (iDest, jDest, cross(iDest,jDest)). iSrc, jSrc, iDest, and jDest will
782  // be normalized before the operation if norm is 1. This matrix transforms
783  // iSrc into iDest, and jSrc into jDest.
784  template <typename S>
785  void changeSpace(UT_Vector3T<S> &iSrc, UT_Vector3T<S> &jSrc,
786  UT_Vector3T<S> &iDest,UT_Vector3T<S> &jDest,
787  int norm=1);
788 
789  // Multiply this matrix by the general transform matrix built from
790  // translations (tx,ty,tz), degree rotations (rx,ry,rz), scales (sx,sy,sz),
791  // and possibly a pivot point (px,py,pz). The second methos leaves us
792  // unchanged, and returns a new (this*xform) instead. The order of the
793  // multiplies (SRT, RST, RxRyRz, etc) is stored in 'order'. Normally you
794  // will ignore the 'reverse' parameter, which tells us to build the
795  // matrix from last to first xform, and to apply some inverses to
796  // txyz, rxyz, and sxyz.
797  void xform(const UT_XformOrder &order,
798  T tx=0.0f, T ty=0.0f, T tz=0.0f,
799  T rx=0.0f, T ry=0.0f, T rz=0.0f,
800  T sx=1.0f, T sy=1.0f, T sz=1.0f,
801  T px=0.0f, T py=0.0f, T pz=0.0f,
802  int reverse=0);
803 
804  // This version handles shears as well
805  void xform(const UT_XformOrder &order,
806  T tx, T ty, T tz,
807  T rx, T ry, T rz,
808  T sx, T sy, T sz,
809  T s_xy, T s_xz, T s_yz,
810  T px, T py, T pz,
811  int reverse=0);
812 
813  /// Define parameters for Houdini's pivot space.
814  template <typename S>
815  struct PivotSpaceT
816  {
817  /// Constructor with default values for data members
819  : myTranslate(0, 0, 0)
820  , myRotate(0, 0, 0)
821  {
822  }
823 
824  /// Convenience constructor with translate and rotate.
826  const UT_Vector3T<S> &rotate)
827  : myTranslate(translate)
828  , myRotate(rotate)
829  {
830  }
831 
832  UT_Vector3T<S> myTranslate; // Translate (corresponds to px, py, pz)
833  UT_Vector3T<S> myRotate; // Rotation (degrees, XYZ order)
834  };
835 
836  typedef PivotSpaceT<T> PivotSpace;
837 
838  // This version handles a more general PivotSpace.
839  void xform(const UT_XformOrder &order,
840  T tx, T ty, T tz,
841  T rx, T ry, T rz,
842  T sx, T sy, T sz,
843  const PivotSpace &pivot,
844  int reverse=0);
845 
846  // This version handles a more general PivotSpace as well as shears.
847  void xform(const UT_XformOrder &order,
848  T tx, T ty, T tz,
849  T rx, T ry, T rz,
850  T sx, T sy, T sz,
851  T s_xy, T s_xz, T s_yz,
852  const PivotSpace &pivot,
853  int reverse=0);
854 
855  /// Define parameters for Houdini's full transform model
857  {
858  /// Constructor with default values for data members
861  , myTranslate(0, 0, 0)
862  , myRotateOffset(0, 0, 0)
863  , myParentRotate(0, 0, 0)
864  , myRotate(0, 0, 0)
865  , myChildRotate(0, 0, 0)
866  , myRotatePivot(0, 0, 0)
867  , myScaleOffset(0, 0, 0)
868  , myScale(1, 1, 1)
869  , myShear(0, 0, 0)
870  , myScalePivot(0, 0, 0)
871  , myPivot(0, 0, 0)
872  , myPivotRotate(0, 0, 0)
873  {
874  }
875 
876  UT_XformOrder myOrder; /// transform and rotation order
878  UT_Vector3T<T> myRotateOffset; /// Rotation offset
879  UT_Vector3T<T> myParentRotate; /// Parent rotation (degrees, XYZ order)
880  UT_Vector3T<T> myRotate; /// Rotation (degrees, myOrder order)
881  UT_Vector3T<T> myChildRotate; /// Child rotation (degrees, XYZ order)
882  UT_Vector3T<T> myRotatePivot; /// Rotation pivot
883  UT_Vector3T<T> myScaleOffset; /// Scale offset
885  UT_Vector3T<T> myShear; /// Shear (within scale pivot)
886  UT_Vector3T<T> myScalePivot; /// Scale pivot
887  UT_Vector3T<T> myPivot; /// Overall pivot
888  UT_Vector3T<T> myPivotRotate; /// Overall pivot rotation(degrees,XYZ)
889  };
890 
891  void xform(const FullTransformModel &parms, T min_abs_scale = T(0));
892 
893  // These versions of xform and rotate can be used to apply selected parts
894  // of a transform. The applyType controls how far into the xform
895  // it should go. For example: applyXform(order, BEFORE_EQUAL, 'T', ...)
896  // will apply all the components of the transform up to and equal to the
897  // translates (depending on UT_XformOrder)
898  //
899  // For xform char can be T, R, S, P, or p (P is for pivot)
900  // For rotate char can be X, Y, or Z
901  //
902  // TODO add a reverse option
903 
904  enum applyType { BEFORE=1, EQUAL=2, AFTER=4, BEFORE_EQUAL=4, AFTER_EQUAL=6};
905  void xform(const UT_XformOrder &order,
906  applyType type, char limit,
907  T tx, T ty, T tz,
908  T rx, T ry, T rz,
909  T sx, T sy, T sz,
910  T px, T py, T pz);
911 
912  void rotate(const UT_XformOrder &order,
913  applyType type, char limit,
914  T rx, T ry, T rz);
915 
916  // extract only the translates from the matrix;
917  template <typename S>
918  inline void getTranslates(UT_Vector3T<S> &translates) const;
919  template <typename S>
920  inline void setTranslates(const UT_Vector3T<S> &translates);
921 
922  // This is a super-crack that returns the translation, scale, and radian
923  // rotation vectors given a transformation order and a valid xform matrix.
924  // It returns 0 if succesful, and non-zero otherwise: 1 if the embedded
925  // rotation matrix is invalid, 2 if the rotation order is invalid,
926  // and 3 for other problems. If any of the scaling values is 0, the method
927  // returns all zeroes, and a 0 return value.
928  template <typename S>
929  int explodeT(const UT_XformOrder &order,
931  UT_Vector3T<S> *shears) const;
934  UT_Vector3F *shears = 0) const
935  { return explodeT(order, r, s, t, shears); }
938  UT_Vector3D *shears = 0) const
939  { return explodeT(order, r, s, t, shears); }
940 
941  // This version of explode returns the t, r, and s, given a pivot value.
942  template <typename S>
943  int explodeT(const UT_XformOrder &order,
945  UT_Vector3T<S> &t, const UT_Vector3T<S> &p,
946  UT_Vector3T<S> *shears) const;
949  UT_Vector3F &t, const UT_Vector3F &p,
950  UT_Vector3F *shears = 0) const
951  { return explodeT(order, r, s, t, p, shears); }
954  UT_Vector3D &t, const UT_Vector3D &p,
955  UT_Vector3D *shears = 0) const
956  { return explodeT(order, r, s, t, p, shears); }
957 
958  // This version of explode returns the t, r, and s, given a PivotSpace.
959  template <typename S>
960  int explodeT(const UT_XformOrder &order,
962  UT_Vector3T<S> &t, const PivotSpaceT<S> &p,
963  UT_Vector3T<S> *shears) const;
966  UT_Vector3F &t, const PivotSpaceT<fpreal32> &p,
967  UT_Vector3F *shears = 0) const
968  { return explodeT(order, r, s, t, p, shears); }
971  UT_Vector3D &t, const PivotSpaceT<fpreal64> &p,
972  UT_Vector3D *shears = 0) const
973  { return explodeT(order, r, s, t, p, shears); }
974 
975 
976  // These versions treat the matrix as only containing a 2D
977  // transformation, that is in x, y, with a rotate around z.
978  template <typename S>
979  int explode2D(const UT_XformOrder &order,
981  S *shears = 0) const;
982 
983  template <typename S>
984  int explode2D(const UT_XformOrder &order,
985  S &r, UT_Vector2T<S> &s,
986  UT_Vector2T<S> &t, const UT_Vector2T<S> &p,
987  S *shears = 0) const;
988 
989  /// WARNING: This may not produce good results! Instead, get the
990  /// UT_Matrix3 part and call UT_Matrix3T::makeRotationMatrix().
991  template <typename S>
992  void extractRotate(UT_Matrix3T<S> &dst) const;
993 
994  /// Perform the polar decomposition of the 3x3 matrix M into an orthogonal
995  /// matrix Q and an symmetric positive-semidefinite matrix S. This is more
996  /// useful than explode() or extractRotate() when the desire is to blend
997  /// transforms. By default, it gives M=SQ, a left polar decomposition. If
998  /// reverse is false, then it gives M=QS, a right polar decomposition.
999  ///
1000  /// This method is similar to the UT_Matrix3 version except it only
1001  /// operates on the upper-right 3x3 portion.
1002  ///
1003  /// @pre The upper-right 3x3 portion of *this is non-singular
1004  /// @post The upper-right 3x3 porition = Q,
1005  /// and if stretch != 0: *stretch = S.
1006  /// @return True if successful
1007  bool polarDecompose(
1008  UT_Matrix3T<T> *stretch = nullptr,
1009  bool reverse = true,
1010  const int max_iter = 64,
1011  const T rel_tol = FLT_EPSILON);
1012 
1013  /// Turn this matrix into the "closest" rigid transformation
1014  /// (only rotations and translations) matrix.
1015  ///
1016  /// It uses polarDecompose and then negates the matrix if
1017  /// there is a negative determinant (scale). It returns false iff
1018  /// polarDecompose failed, possibly due to a singular matrix.
1019  ///
1020  /// This is currently the one true way to turn an arbitrary
1021  /// matrix4 into a rotation and translation matrix. If that
1022  /// ever changes, put a warning here, and you may want to update
1023  /// UT_Matrix3::makeRotationMatrix too.
1024  bool makeRigidMatrix(
1025  UT_Matrix3T<T> *stretch = nullptr,
1026  bool reverse = true,
1027  const int max_iter = 64,
1028  const T rel_tol = FLT_EPSILON);
1029 
1030  // Right multiply this matrix by a 3x3 matrix which scales by a given
1031  // amount along the direction of vector v. When applied to a vector w,
1032  // the stretched matrix (*this) stretches w in v by the amount given.
1033  // If norm is non-zero, v will be normalized prior to the operation.
1034  template <typename S>
1035  void stretch(UT_Vector3T<S> &v, T amount, int norm=1);
1036 
1037  T dot(unsigned i, unsigned j) const
1038  {
1039  return (i <= 3 && j <= 3) ?
1040  matx[i][0]*matx[j][0] + matx[i][1]*matx[j][1] +
1041  matx[i][2]*matx[j][2] + matx[i][3]*matx[j][3] : (T)0;
1042  }
1043 
1044  // Matrix += b * v1 * v2T
1045  template <typename S>
1046  void outerproductUpdate(T b,
1047  const UT_Vector4T<S> &v1, const UT_Vector4T<S> &v2);
1048 
1049  // Sets the current matrix to a linear interpolation of the two homogenous
1050  // matrices given.
1051  void lerp(const UT_Matrix4T<T> &a, const UT_Matrix4T<T> &b, T t)
1052  {
1053  if (t == 0)
1054  *this = a;
1055  else if(t == 1)
1056  *this = b;
1057  else
1058  {
1059  for (size_t i = 0; i < tuple_size; i++)
1060  myFloats[i] = SYSlerp(a.myFloats[i], b.myFloats[i], t);
1061  }
1062  }
1063 
1064  /// Set the matrix to identity
1065  void identity() { *this = 1; }
1066  /// Set the matrix to zero
1067  void zero() { *this = 0; }
1068 
1069  int isIdentity() const
1070  {
1071  // NB: DO NOT USE TOLERANCES!
1072  return(
1073  matx[0][0]==1.0f && matx[0][1]==0.0f &&
1074  matx[0][2]==0.0f && matx[0][3]==0.0f &&
1075  matx[1][0]==0.0f && matx[1][1]==1.0f &&
1076  matx[1][2]==0.0f && matx[1][3]==0.0f &&
1077  matx[2][0]==0.0f && matx[2][1]==0.0f &&
1078  matx[2][2]==1.0f && matx[2][3]==0.0f &&
1079  matx[3][0]==0.0f && matx[3][1]==0.0f &&
1080  matx[3][2]==0.0f && matx[3][3]==1.0f);
1081  }
1082 
1083  int isZero() const
1084  {
1085  // NB: DO NOT USE TOLERANCES!
1086  return(
1087  matx[0][0]==0.0f && matx[0][1]==0.0f &&
1088  matx[0][2]==0.0f && matx[0][3]==0.0f &&
1089  matx[1][0]==0.0f && matx[1][1]==0.0f &&
1090  matx[1][2]==0.0f && matx[1][3]==0.0f &&
1091  matx[2][0]==0.0f && matx[2][1]==0.0f &&
1092  matx[2][2]==0.0f && matx[2][3]==0.0f &&
1093  matx[3][0]==0.0f && matx[3][1]==0.0f &&
1094  matx[3][2]==0.0f && matx[3][3]==0.0f);
1095  }
1096 
1097 
1098  /// Return the raw matrix data.
1099  // @{
1100  const T *data() const { return myFloats; }
1101  T *data() { return myFloats; }
1102  // @}
1103 
1104  /// Compute a hash
1105  unsigned hash() const { return SYSvector_hash(data(), tuple_size); }
1106 
1107  /// Return a matrix entry. No bounds checking on subscripts.
1108  // @{
1110  T &operator()(unsigned row, unsigned col)
1111  {
1112  UT_ASSERT_P(row < 4 && col < 4);
1113  return matx[row][col];
1114  }
1116  T operator()(unsigned row, unsigned col) const
1117  {
1118  UT_ASSERT_P(row < 4 && col < 4);
1119  return matx[row][col];
1120  }
1121  // @}
1122 
1123  /// Return a matrix row. No bounds checking on subscript.
1124  // @{
1126  T *operator()(unsigned row)
1127  {
1128  UT_ASSERT_P(row < 4);
1129  return matx[row];
1130  }
1132  const T *operator()(unsigned row) const
1133  {
1134  UT_ASSERT_P(row < 4);
1135  return matx[row];
1136  }
1137  inline
1138  const UT_Vector4T<T> &operator[](unsigned row) const;
1139  inline
1140  UT_Vector4T<T> &operator[](unsigned row);
1141  // @}
1142 
1143  /// Dot product with another matrix
1144  /// Does dot(a,b) = sum_ij a_ij * b_ij
1145  T dot(const UT_Matrix4T<T> &m) const;
1146 
1147  /// Euclidean or Frobenius norm of a matrix.
1148  /// Does sqrt(sum(a_ij ^2))
1150  { return SYSsqrt(getEuclideanNorm2()); }
1151  /// Euclidean norm squared.
1152  T getEuclideanNorm2() const;
1153 
1154  /// Get the 1-norm of this matrix, assuming a row vector convention.
1155  /// Returns the maximum absolute row sum. ie. max_i(sum_j(abs(a_ij)))
1156  T getNorm1() const;
1157 
1158  /// Get the inf-norm of this matrix, assuming a row vector convention.
1159  /// Returns the maximum absolute column sum. ie. max_j(sum_i(abs(a_ij)))
1160  T getNormInf() const;
1161 
1162  /// Get the max-norm of this matrix
1163  /// Returns the maximum absolute entry. ie. max_j(max_i(abs(a_ij)))
1164  T getNormMax() const;
1165 
1166  /// L-Infinity Norm, but using col vector convention.
1167  SYS_DEPRECATED_REPLACE(19.0, "getNorm1")
1168  T getInfinityNorm() const { return getNormInf(); }
1169 
1170  /// Compute the exponential of A using Pade approximants with scaling and squaring by q
1171  UT_Matrix4T<T> &exp(int q);
1172 
1173  /// Compute the log of A using Taylor approximation
1174  UT_Matrix4T<T> &log(T tolerance = T(SYS_FTOLERANCE), int max_iterations = 10);
1175 
1176  /// Compute the square root of A
1177  UT_Matrix4T<T> &sqrt(T tolerance = T(SYS_FTOLERANCE), int max_iterations = 10);
1178 
1179  // I/O methods. Return 0 if read/write successful, -1 if unsuccessful.
1180  int save(std::ostream &os, int binary) const;
1181  bool load(UT_IStream &is);
1182  void dump(const char *msg="") const;
1183 
1184  void outAsciiNoName(std::ostream &os) const;
1185 
1186  /// @{
1187  /// Methods to serialize to a JSON stream. The matrix is stored as an
1188  /// array of 16 reals.
1189  bool save(UT_JSONWriter &w) const;
1190  bool save(UT_JSONValue &v) const;
1191  bool load(UT_JSONParser &p);
1192  /// @}
1193 
1194  static const UT_Matrix4T<T> &getIdentityMatrix();
1195 
1196  // I/O friends:
1197  friend std::ostream &operator<<(std::ostream &os, const UT_Matrix4T<T> &v)
1198  {
1199  v.writeClassName(os);
1200  v.outAsciiNoName(os);
1201  return os;
1202  }
1203 
1204  /// Returns the vector size
1205  static int entries() { return tuple_size; }
1206 
1207 
1208  // The matrix data:
1209  union {
1210  T matx[4][4];
1211  T myFloats[tuple_size];
1212  };
1213 
1214  /// Create a perspective projection matrix with the given parameters.
1215  /// This can be used to project points onto the so-called NDC coordinates
1216  /// of a camera. For example, given a point @c P (in the space of a
1217  /// camera):
1218  /// @code
1219  /// UT_Vector3 ndc;
1220  /// UT_Matrix4R proj;
1221  /// proj.perspective(zoom, image_aspect);
1222  /// ndc = P * proj;
1223  /// @endcode
1224  ///
1225  /// - @c zoom @n The zoom for the lens
1226  /// - @c image_aspect @n The aspect ratio of the image
1227  /// - @c pixel_aspect @n The pixel aspect (the aspect ratio of pixels)
1228  /// - @c near,far @n The near/far clipping planes
1229  /// - @c window @n The offset for the projection window.
1230  ///
1231  /// The projection transform will transform the z coordinate of the camera
1232  /// space point such that the near coordinate will map to 0 and the far
1233  /// coordinate will map to 1.
1234  /// That is <tt>n dz.z = fit(P.z, near, far, 0, 1); </tt>.
1235  /// Thus, if the near/far are set to 0/1, the NDC z-coordinate will
1236  /// be the same as the camera space z. If the near/far are set to 0/-1,
1237  /// the Z coordinate will be negated.
1238  ///
1239  /// @note Sometimes the @c zoom is expressed in terms of @c focal and @c
1240  /// aperture. In this case: <tt> zoom = focal/aperture </tt>
1241  /// @note Sometimes the @c image_aspect is expressed in terms of @c xres
1242  /// and @c yres. In this case: <tt> image_aspect = xres / yres </tt>
1243  /// @note To make a single transform from world space to NDC space given a
1244  /// camera matrix and a projection matrix, you would use
1245  /// <tt> worldToNDC = worldToCamera * projection; </tt>
1246  ///
1247  void perspective(fpreal zoom,
1248  fpreal image_aspect,
1249  fpreal pixel_aspect=1,
1250  fpreal clip_near=0, fpreal clip_far=1,
1251  fpreal window_xmin=0, fpreal window_xmax=1,
1252  fpreal window_ymin=0, fpreal window_ymax=1);
1253  /// Create an orthographic projection matrix with the given parameters.
1254  /// This can be used to project points onto the so-called NDC coordinates
1255  /// of a camera. For example, given a point @c P (in the space of a
1256  /// camera):
1257  /// @code
1258  /// UT_Vector3 ndc;
1259  /// UT_Matrix4R proj;
1260  /// proj.orthographic(zoom, 1, image_aspect);
1261  /// ndc = P * proj;
1262  /// @endcode
1263  ///
1264  /// - @c zoom @n The zoom for the lens
1265  /// - @c orthowidth @n An additional "zoom" factor
1266  /// - @c image_aspect @n The resolution of the image
1267  /// - @c pixel_aspect @n The pixel aspect (the aspect ratio of pixels)
1268  /// - @c near,far @n The near/far clipping planes
1269  /// - @c window @n The offset for the projection window.
1270  ///
1271  /// The projection transform will transform the z coordinate of the camera
1272  /// space point such that the near coordinate will map to 0 and the far
1273  /// coordinate will map to 1.
1274  /// That is <tt>n dz.z = fit(P.z, near, far, 0, 1); </tt>.
1275  /// Thus, if the near/far are set to 0/1, the NDC z-coordinate will
1276  /// be the same as the camera space z. If the near/far are set to 0/-1,
1277  /// the Z coordinate will be negated.
1278  ///
1279  /// @note Sometimes the @c zoom is expressed in terms of @c focal and @c
1280  /// aperture. In this case: <tt> zoom = focal/aperture </tt>
1281  /// @note Sometimes the @c image_aspect is expressed in terms of @c xrex
1282  /// and @c yres. In this case: <tt> image_aspect = xres / yres </tt>
1283  /// @note To make a single transform from world space to NDC space given a
1284  /// camera matrix and a projection matrix, you would use
1285  /// <tt> worldToNDC = worldToCamera * projection; </tt>
1286  ///
1287  void orthographic(fpreal zoom,
1288  fpreal orthowidth,
1289  fpreal image_aspect,
1290  fpreal pixel_aspect=1,
1291  fpreal clip_near=0, fpreal clip_far=1,
1292  fpreal window_xmin=0, fpreal window_xmax=1,
1293  fpreal window_ymin=0, fpreal window_ymax=1);
1294 
1295  /// Post-rotate by rx, ry, rz radians around the three basic axes in the
1296  /// order given by a templated UT_XformOrder.
1297  template <int ORDER>
1298  void rotate(T rx, T ry, T rz);
1299 
1300 private:
1301  // Operation to aid in cofactor computation
1303  void coVals(int k, int r[3]) const
1304  {
1305  switch (k)
1306  {
1307  case 0: r[0] = 1; r[1] = 2; r[2] = 3; break;
1308  case 1: r[0] = 0; r[1] = 2; r[2] = 3; break;
1309  case 2: r[0] = 0; r[1] = 1; r[2] = 3; break;
1310  case 3: r[0] = 0; r[1] = 1; r[2] = 2; break;
1311  }
1312  }
1313 
1314  static UT_Matrix4T<T> theIdentityMatrix;
1315 
1316  void writeClassName(std::ostream &os) const;
1317  static const char *className();
1318 };
1319 
1320 // Vector4 operators:
1321 
1322 template <typename T>
1323 template <typename S>
1324 inline
1326 {
1327  matx[0][0] = matx[0][1] = matx[0][2] = matx[0][3] = vec.x();
1328  matx[1][0] = matx[1][1] = matx[1][2] = matx[1][3] = vec.y();
1329  matx[2][0] = matx[2][1] = matx[2][2] = matx[2][3] = vec.z();
1330  matx[3][0] = matx[3][1] = matx[3][2] = matx[3][3] = vec.w();
1331  return *this;
1332 }
1333 
1334 template <typename T>
1335 template <typename S>
1336 inline
1338 {
1339  T x = vec.x(); T y = vec.y();
1340  T z = vec.z(); T w = vec.w();
1341  matx[0][0]+=x; matx[0][1]+=x; matx[0][2]+=x; matx[0][3]+=x;
1342  matx[1][0]+=y; matx[1][1]+=y; matx[1][2]+=y; matx[1][3]+=y;
1343  matx[2][0]+=z; matx[2][1]+=z; matx[2][2]+=z; matx[2][3]+=z;
1344  matx[3][0]+=w; matx[3][1]+=w; matx[3][2]+=w; matx[3][3]+=w;
1345  return *this;
1346 }
1347 
1348 template <typename T>
1349 template <typename S>
1350 inline
1352 {
1353  T x = vec.x(); T y = vec.y();
1354  T z = vec.z(); T w = vec.w();
1355  matx[0][0]-=x; matx[0][1]-=x; matx[0][2]-=x; matx[0][3]-=x;
1356  matx[1][0]-=y; matx[1][1]-=y; matx[1][2]-=y; matx[1][3]-=y;
1357  matx[2][0]-=z; matx[2][1]-=z; matx[2][2]-=z; matx[2][3]-=z;
1358  matx[3][0]-=w; matx[3][1]-=w; matx[3][2]-=w; matx[3][3]-=w;
1359  return *this;
1360 }
1361 
1362 template <typename T>
1363 template <typename S>
1364 inline
1366 {
1367  translates.x() = matx[3][0];
1368  translates.y() = matx[3][1];
1369  translates.z() = matx[3][2];
1370 }
1371 
1372 template <typename T>
1373 template <typename S>
1374 inline
1376 {
1377  matx[3][0] = translates.x();
1378  matx[3][1] = translates.y();
1379  matx[3][2] = translates.z();
1380 }
1381 
1382 template <typename T>
1383 inline
1385 {
1386  UT_ASSERT_P(row < 4);
1387  return *(const UT_Vector4T<T>*)(matx[row]);
1388 }
1389 
1390 template <typename T>
1391 inline
1393 {
1394  UT_ASSERT_P(row < 4);
1395  return *(UT_Vector4T<T>*)(matx[row]);
1396 }
1397 
1398 template <typename T>
1399 template <typename S>
1400 inline UT_Matrix4T<T> &
1402 {
1403  T a, b, c, d;
1404  a = matx[0][0]; b = matx[0][1]; c = matx[0][2]; d = matx[0][3];
1405  matx[0][0] = a*m(0,0) + b*m(1,0) + c*m(2,0) + d*m(3,0);
1406  matx[0][1] = a*m(0,1) + b*m(1,1) + c*m(2,1) + d*m(3,1);
1407  matx[0][2] = a*m(0,2) + b*m(1,2) + c*m(2,2) + d*m(3,2);
1408  matx[0][3] = a*m(0,3) + b*m(1,3) + c*m(2,3) + d*m(3,3);
1409 
1410  a = matx[1][0]; b = matx[1][1]; c = matx[1][2]; d = matx[1][3];
1411  matx[1][0] = a*m(0,0) + b*m(1,0) + c*m(2,0) + d*m(3,0);
1412  matx[1][1] = a*m(0,1) + b*m(1,1) + c*m(2,1) + d*m(3,1);
1413  matx[1][2] = a*m(0,2) + b*m(1,2) + c*m(2,2) + d*m(3,2);
1414  matx[1][3] = a*m(0,3) + b*m(1,3) + c*m(2,3) + d*m(3,3);
1415 
1416  a = matx[2][0]; b = matx[2][1]; c = matx[2][2]; d = matx[2][3];
1417  matx[2][0] = a*m(0,0) + b*m(1,0) + c*m(2,0) + d*m(3,0);
1418  matx[2][1] = a*m(0,1) + b*m(1,1) + c*m(2,1) + d*m(3,1);
1419  matx[2][2] = a*m(0,2) + b*m(1,2) + c*m(2,2) + d*m(3,2);
1420  matx[2][3] = a*m(0,3) + b*m(1,3) + c*m(2,3) + d*m(3,3);
1421 
1422  a = matx[3][0]; b = matx[3][1]; c = matx[3][2]; d = matx[3][3];
1423  matx[3][0] = a*m(0,0) + b*m(1,0) + c*m(2,0) + d*m(3,0);
1424  matx[3][1] = a*m(0,1) + b*m(1,1) + c*m(2,1) + d*m(3,1);
1425  matx[3][2] = a*m(0,2) + b*m(1,2) + c*m(2,2) + d*m(3,2);
1426  matx[3][3] = a*m(0,3) + b*m(1,3) + c*m(2,3) + d*m(3,3);
1427  return *this;
1428 }
1429 
1430 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1431 template <>
1432 template <>
1433 inline UT_Matrix4T<float> &
1435 {
1436  // rows of right matrix
1437  const v4uf m0(m.matx[0]);
1438  const v4uf m1(m.matx[1]);
1439  const v4uf m2(m.matx[2]);
1440  const v4uf m3(m.matx[3]);
1441 
1442  v4uf row;
1443 
1444  for (int i = 0; i < 4; i++)
1445  {
1446  row = m0 * v4uf(matx[i][0]);
1447  row += m1 * v4uf(matx[i][1]);
1448  row += m2 * v4uf(matx[i][2]);
1449  row += m3 * v4uf(matx[i][3]);
1450 
1451  VM_STORE(matx[i], row.vector);
1452  }
1453  return *this;
1454 }
1455 #endif
1456 
1457 template <typename T>
1458 template <typename S>
1459 inline UT_Matrix4T<T> &
1461 {
1462  T a, b, c;
1463  a = matx[0][0]; b = matx[0][1]; c = matx[0][2];
1464  matx[0][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
1465  matx[0][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
1466  matx[0][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
1467 
1468  a = matx[1][0]; b = matx[1][1]; c = matx[1][2];
1469  matx[1][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
1470  matx[1][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
1471  matx[1][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
1472 
1473  a = matx[2][0]; b = matx[2][1]; c = matx[2][2];
1474  matx[2][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
1475  matx[2][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
1476  matx[2][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
1477 
1478  a = matx[3][0]; b = matx[3][1]; c = matx[3][2];
1479  matx[3][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
1480  matx[3][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
1481  matx[3][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
1482  return *this;
1483 }
1484 
1485 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1486 #include "UT_Matrix3.h"
1487 template <>
1488 template <>
1489 inline UT_Matrix4T<float> &
1491 {
1492  const v4uf m0(m(0));
1493  const v4uf m1(m(1));
1494  const v4uf m2(m(2,0), m(2,1), m(2,2), 0);
1495 
1496  for (int i = 0; i < 4; ++i)
1497  {
1498  // Load ith row of this matrix
1499  v4uf row = m0 * v4uf(matx[i][0]);
1500  row += m1 * v4uf(matx[i][1]);
1501  row += m2 * v4uf(matx[i][2]);
1502 
1503  const float last = matx[i][3];
1504  vm_store(matx[i], row.vector);
1505  matx[i][3] = last;
1506  }
1507  return *this;
1508 }
1509 template <> inline void
1511 {
1512  // Lerp row by row
1513  for (int i = 0; i < 4; ++i) // Should unroll this
1514  {
1515  const v4uf ar(a.matx[i]);
1516  const v4uf br(b.matx[i]);
1517  const v4uf cr = SYSlerp(ar, br, t);
1518  vm_store(matx[i], cr.vector);
1519  }
1520 }
1521 #endif
1522 
1523 
1524 template <typename T>
1525 inline void
1527 {
1528  T a, b, c, d;
1529  a = matx[0][0]; b = matx[1][0]; c = matx[2][0]; d = matx[3][0];
1530  matx[0][0] = a*m(0,0) + b*m(0,1) + c*m(0,2) + d*m(0,3);
1531  matx[1][0] = a*m(1,0) + b*m(1,1) + c*m(1,2) + d*m(1,3);
1532  matx[2][0] = a*m(2,0) + b*m(2,1) + c*m(2,2) + d*m(2,3);
1533  matx[3][0] = a*m(3,0) + b*m(3,1) + c*m(3,2) + d*m(3,3);
1534 
1535  a = matx[0][1]; b = matx[1][1]; c = matx[2][1]; d = matx[3][1];
1536  matx[0][1] = a*m(0,0) + b*m(0,1) + c*m(0,2) + d*m(0,3);
1537  matx[1][1] = a*m(1,0) + b*m(1,1) + c*m(1,2) + d*m(1,3);
1538  matx[2][1] = a*m(2,0) + b*m(2,1) + c*m(2,2) + d*m(2,3);
1539  matx[3][1] = a*m(3,0) + b*m(3,1) + c*m(3,2) + d*m(3,3);
1540 
1541  a = matx[0][2]; b = matx[1][2]; c = matx[2][2]; d = matx[3][2];
1542  matx[0][2] = a*m(0,0) + b*m(0,1) + c*m(0,2) + d*m(0,3);
1543  matx[1][2] = a*m(1,0) + b*m(1,1) + c*m(1,2) + d*m(1,3);
1544  matx[2][2] = a*m(2,0) + b*m(2,1) + c*m(2,2) + d*m(2,3);
1545  matx[3][2] = a*m(3,0) + b*m(3,1) + c*m(3,2) + d*m(3,3);
1546 
1547  a = matx[0][3]; b = matx[1][3]; c = matx[2][3]; d = matx[3][3];
1548  matx[0][3] = a*m(0,0) + b*m(0,1) + c*m(0,2) + d*m(0,3);
1549  matx[1][3] = a*m(1,0) + b*m(1,1) + c*m(1,2) + d*m(1,3);
1550  matx[2][3] = a*m(2,0) + b*m(2,1) + c*m(2,2) + d*m(2,3);
1551  matx[3][3] = a*m(3,0) + b*m(3,1) + c*m(3,2) + d*m(3,3);
1552 }
1553 
1554 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1555 template <>
1556 inline void
1558 {
1559  const v4uf m0(matx[0]);
1560  const v4uf m1(matx[1]);
1561  const v4uf m2(matx[2]);
1562  const v4uf m3(matx[3]);
1563 
1564  for (int i = 0; i < 4; ++i)
1565  {
1566  const v4uf row = m0 * v4uf(m.matx[i][0])
1567  + m1 * v4uf(m.matx[i][1])
1568  + m2 * v4uf(m.matx[i][2])
1569  + m3 * v4uf(m.matx[i][3]);
1570 
1571  VM_STORE(matx[i], row.vector);
1572  }
1573 }
1574 #endif
1575 
1576 // Free floating functions:
1577 template <typename T>
1578 inline UT_Matrix4T<T>
1580 {
1581  T m[4][4];
1582  m[0][0] = m1(0,0)+m2(0,0); m[0][1] = m1(0,1)+m2(0,1);
1583  m[0][2] = m1(0,2)+m2(0,2); m[0][3] = m1(0,3)+m2(0,3);
1584 
1585  m[1][0] = m1(1,0)+m2(1,0); m[1][1] = m1(1,1)+m2(1,1);
1586  m[1][2] = m1(1,2)+m2(1,2); m[1][3] = m1(1,3)+m2(1,3);
1587 
1588  m[2][0] = m1(2,0)+m2(2,0); m[2][1] = m1(2,1)+m2(2,1);
1589  m[2][2] = m1(2,2)+m2(2,2); m[2][3] = m1(2,3)+m2(2,3);
1590 
1591  m[3][0] = m1(3,0)+m2(3,0); m[3][1] = m1(3,1)+m2(3,1);
1592  m[3][2] = m1(3,2)+m2(3,2); m[3][3] = m1(3,3)+m2(3,3);
1593  return UT_Matrix4T<T>(m);
1594 }
1595 template <typename T>
1596 inline UT_Matrix4T<T>
1598 {
1599  T m[4][4];
1600  m[0][0] = m1(0,0)-m2(0,0); m[0][1] = m1(0,1)-m2(0,1);
1601  m[0][2] = m1(0,2)-m2(0,2); m[0][3] = m1(0,3)-m2(0,3);
1602 
1603  m[1][0] = m1(1,0)-m2(1,0); m[1][1] = m1(1,1)-m2(1,1);
1604  m[1][2] = m1(1,2)-m2(1,2); m[1][3] = m1(1,3)-m2(1,3);
1605 
1606  m[2][0] = m1(2,0)-m2(2,0); m[2][1] = m1(2,1)-m2(2,1);
1607  m[2][2] = m1(2,2)-m2(2,2); m[2][3] = m1(2,3)-m2(2,3);
1608 
1609  m[3][0] = m1(3,0)-m2(3,0); m[3][1] = m1(3,1)-m2(3,1);
1610  m[3][2] = m1(3,2)-m2(3,2); m[3][3] = m1(3,3)-m2(3,3);
1611  return UT_Matrix4T<T>(m);
1612 }
1613 template <typename T>
1614 inline UT_Matrix4T<T>
1616 {
1617  T m[4][4];
1618  m[0][0] = m1(0,0)*m2(0,0) + m1(0,1)*m2(1,0) +
1619  m1(0,2)*m2(2,0) + m1(0,3)*m2(3,0) ;
1620  m[0][1] = m1(0,0)*m2(0,1) + m1(0,1)*m2(1,1) +
1621  m1(0,2)*m2(2,1) + m1(0,3)*m2(3,1) ;
1622  m[0][2] = m1(0,0)*m2(0,2) + m1(0,1)*m2(1,2) +
1623  m1(0,2)*m2(2,2) + m1(0,3)*m2(3,2) ;
1624  m[0][3] = m1(0,0)*m2(0,3) + m1(0,1)*m2(1,3) +
1625  m1(0,2)*m2(2,3) + m1(0,3)*m2(3,3) ;
1626 
1627  m[1][0] = m1(1,0)*m2(0,0) + m1(1,1)*m2(1,0) +
1628  m1(1,2)*m2(2,0) + m1(1,3)*m2(3,0) ;
1629  m[1][1] = m1(1,0)*m2(0,1) + m1(1,1)*m2(1,1) +
1630  m1(1,2)*m2(2,1) + m1(1,3)*m2(3,1) ;
1631  m[1][2] = m1(1,0)*m2(0,2) + m1(1,1)*m2(1,2) +
1632  m1(1,2)*m2(2,2) + m1(1,3)*m2(3,2) ;
1633  m[1][3] = m1(1,0)*m2(0,3) + m1(1,1)*m2(1,3) +
1634  m1(1,2)*m2(2,3) + m1(1,3)*m2(3,3) ;
1635 
1636  m[2][0] = m1(2,0)*m2(0,0) + m1(2,1)*m2(1,0) +
1637  m1(2,2)*m2(2,0) + m1(2,3)*m2(3,0) ;
1638  m[2][1] = m1(2,0)*m2(0,1) + m1(2,1)*m2(1,1) +
1639  m1(2,2)*m2(2,1) + m1(2,3)*m2(3,1) ;
1640  m[2][2] = m1(2,0)*m2(0,2) + m1(2,1)*m2(1,2) +
1641  m1(2,2)*m2(2,2) + m1(2,3)*m2(3,2) ;
1642  m[2][3] = m1(2,0)*m2(0,3) + m1(2,1)*m2(1,3) +
1643  m1(2,2)*m2(2,3) + m1(2,3)*m2(3,3) ;
1644 
1645  m[3][0] = m1(3,0)*m2(0,0) + m1(3,1)*m2(1,0) +
1646  m1(3,2)*m2(2,0) + m1(3,3)*m2(3,0) ;
1647  m[3][1] = m1(3,0)*m2(0,1) + m1(3,1)*m2(1,1) +
1648  m1(3,2)*m2(2,1) + m1(3,3)*m2(3,1) ;
1649  m[3][2] = m1(3,0)*m2(0,2) + m1(3,1)*m2(1,2) +
1650  m1(3,2)*m2(2,2) + m1(3,3)*m2(3,2) ;
1651  m[3][3] = m1(3,0)*m2(0,3) + m1(3,1)*m2(1,3) +
1652  m1(3,2)*m2(2,3) + m1(3,3)*m2(3,3) ;
1653  return UT_Matrix4T<T>(m);
1654 }
1655 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1656 template <>
1657 inline UT_Matrix4T<float>
1659 {
1661 
1662  const v4uf r0(m2.matx[0]);
1663  const v4uf r1(m2.matx[1]);
1664  const v4uf r2(m2.matx[2]);
1665  const v4uf r3(m2.matx[3]);
1666 
1667  for (int i = 0; i < 4; ++i)
1668  {
1669  const v4uf row = r0 * v4uf(m1.matx[i][0])
1670  + r1 * v4uf(m1.matx[i][1])
1671  + r2 * v4uf(m1.matx[i][2])
1672  + r3 * v4uf(m1.matx[i][3]);
1673 
1674  VM_STORE(result.matx[i], row.vector);
1675  }
1676  return result;
1677 }
1678 #endif
1679 
1680 template <typename T, typename S>
1681 inline UT_Matrix4T<T>
1683 {
1684  T m[4][4];
1685  T x=vec.x(); T y=vec.y(); T z=vec.z(); T w=vec.w();
1686  m[0][0] = m1(0,0) + x; m[0][1] = m1(0,1) + x;
1687  m[0][2] = m1(0,2) + x; m[0][3] = m1(0,3) + x;
1688 
1689  m[1][0] = m1(1,0) + y; m[1][1] = m1(1,1) + y;
1690  m[1][2] = m1(1,2) + y; m[1][3] = m1(1,3) + y;
1691 
1692  m[2][0] = m1(2,0) + z; m[2][1] = m1(2,1) + z;
1693  m[2][2] = m1(2,2) + z; m[2][3] = m1(2,3) + z;
1694 
1695  m[3][0] = m1(3,0) + w; m[3][1] = m1(3,1) + w;
1696  m[3][2] = m1(3,2) + w; m[3][3] = m1(3,3) + w;
1697  return UT_Matrix4T<T>(m);
1698 }
1699 
1700 template <typename T, typename S>
1701 inline UT_Matrix4T<T>
1702 operator+(const UT_Vector4T<S> &vec, const UT_Matrix4T<T> &mat)
1703 {
1704  return mat+vec;
1705 }
1706 
1707 template <typename T, typename S>
1708 inline UT_Matrix4T<T>
1710 {
1711  T m[4][4];
1712  T x=vec.x(); T y=vec.y(); T z=vec.z(); T w=vec.w();
1713  m[0][0] = m1(0,0) - x; m[0][1] = m1(0,1) - x;
1714  m[0][2] = m1(0,2) - x; m[0][3] = m1(0,3) - x;
1715 
1716  m[1][0] = m1(1,0) - y; m[1][1] = m1(1,1) - y;
1717  m[1][2] = m1(1,2) - y; m[1][3] = m1(1,3) - y;
1718 
1719  m[2][0] = m1(2,0) - z; m[2][1] = m1(2,1) - z;
1720  m[2][2] = m1(2,2) - z; m[2][3] = m1(2,3) - z;
1721 
1722  m[3][0] = m1(3,0) - w; m[3][1] = m1(3,1) - w;
1723  m[3][2] = m1(3,2) - w; m[3][3] = m1(3,3) - w;
1724  return UT_Matrix4T<T>(m);
1725 }
1726 
1727 template <typename T, typename S>
1728 inline UT_Matrix4T<T>
1730 {
1731  T m[4][4];
1732  T x=vec.x(); T y=vec.y(); T z=vec.z(); T w=vec.w();
1733  m[0][0] = x - m1(0,0); m[0][1] = x - m1(0,1);
1734  m[0][2] = x - m1(0,2); m[0][3] = x - m1(0,3);
1735 
1736  m[1][0] = y - m1(1,0); m[1][1] = y - m1(1,1);
1737  m[1][2] = y - m1(1,2); m[1][3] = y - m1(1,3);
1738 
1739  m[2][0] = z - m1(2,0); m[2][1] = z - m1(2,1);
1740  m[2][2] = z - m1(2,2); m[2][3] = z - m1(2,3);
1741 
1742  m[3][0] = w - m1(3,0); m[3][1] = w - m1(3,1);
1743  m[3][2] = w - m1(3,2); m[3][3] = w - m1(3,3);
1744  return UT_Matrix4T<T>(m);
1745 }
1746 
1747 template <typename T, typename S>
1748 inline UT_Matrix4T<T>
1750 {
1751  T m[4][4];
1752  m[0][0]=n(0,0)+sc; m[0][1]=n(0,1)+sc; m[0][2]=n(0,2)+sc; m[0][3]=n(0,3)+sc;
1753  m[1][0]=n(1,0)+sc; m[1][1]=n(1,1)+sc; m[1][2]=n(1,2)+sc; m[1][3]=n(1,3)+sc;
1754  m[2][0]=n(2,0)+sc; m[2][1]=n(2,1)+sc; m[2][2]=n(2,2)+sc; m[2][3]=n(2,3)+sc;
1755  m[3][0]=n(3,0)+sc; m[3][1]=n(3,1)+sc; m[3][2]=n(3,2)+sc; m[3][3]=n(3,3)+sc;
1756  return UT_Matrix4T<T>(m);
1757 }
1758 
1759 template <typename T, typename S>
1760 inline UT_Matrix4T<T>
1762 {
1763  T m[4][4];
1764  m[0][0]=sc-n(0,0); m[0][1]=sc-n(0,1); m[0][2]=sc-n(0,2); m[0][3]=sc-n(0,3);
1765  m[1][0]=sc-n(1,0); m[1][1]=sc-n(1,1); m[1][2]=sc-n(1,2); m[1][3]=sc-n(1,3);
1766  m[2][0]=sc-n(2,0); m[2][1]=sc-n(2,1); m[2][2]=sc-n(2,2); m[2][3]=sc-n(2,3);
1767  m[3][0]=sc-n(3,0); m[3][1]=sc-n(3,1); m[3][2]=sc-n(3,2); m[3][3]=sc-n(3,3);
1768  return UT_Matrix4T<T>(m);
1769 }
1770 
1771 template <typename T, typename S>
1772 inline UT_Matrix4T<T>
1773 operator*(S sc, const UT_Matrix4T<T> &m1)
1774 {
1775  return m1*sc;
1776 }
1777 
1778 template <typename T, typename S>
1779 inline UT_Matrix4T<T>
1781 {
1782  T m[4][4];
1783  m[0][0]=n(0,0)*sc; m[0][1]=n(0,1)*sc; m[0][2]=n(0,2)*sc; m[0][3]=n(0,3)*sc;
1784  m[1][0]=n(1,0)*sc; m[1][1]=n(1,1)*sc; m[1][2]=n(1,2)*sc; m[1][3]=n(1,3)*sc;
1785  m[2][0]=n(2,0)*sc; m[2][1]=n(2,1)*sc; m[2][2]=n(2,2)*sc; m[2][3]=n(2,3)*sc;
1786  m[3][0]=n(3,0)*sc; m[3][1]=n(3,1)*sc; m[3][2]=n(3,2)*sc; m[3][3]=n(3,3)*sc;
1787  return UT_Matrix4T<T>(m);
1788 }
1789 
1790 template <typename T, typename S>
1791 inline
1793 operator/(const UT_Matrix4T<T> &m1, S scalar)
1794 {
1795  return (m1 * (1.0f/scalar));
1796 }
1797 
1798 template <typename T, typename S>
1799 inline UT_Matrix4T<T>
1801 {
1802  T m[4][4];
1803  m[0][0]=sc/n(0,0); m[0][1]=sc/n(0,1); m[0][2]=sc/n(0,2); m[0][3]=sc/n(0,3);
1804  m[1][0]=sc/n(1,0); m[1][1]=sc/n(1,1); m[1][2]=sc/n(1,2); m[1][3]=sc/n(1,3);
1805  m[2][0]=sc/n(2,0); m[2][1]=sc/n(2,1); m[2][2]=sc/n(2,2); m[2][3]=sc/n(2,3);
1806  m[3][0]=sc/n(3,0); m[3][1]=sc/n(3,1); m[3][2]=sc/n(3,2); m[3][3]=sc/n(3,3);
1807  return UT_Matrix4T<T>(m);
1808 }
1809 
1810 /// Multiplication of a row or column vector by a matrix (ie. right vs. left
1811 /// multiplication respectively). The operator*() declared above is an alias
1812 /// for rowVecMult(). The functions that take a 4x4 matrix first extend
1813 /// the vector to 4D (with a trailing 1.0 element).
1814 //
1815 // @{
1816 // Notes on optimisation of matrix/vector multiplies:
1817 // - multiply(dest, mat) functions have been deprecated in favour of
1818 // rowVecMult/colVecMult routines, which produce temporaries. For these to
1819 // offer comparable performance, the compiler has to optimize away the
1820 // temporary, but most modern compilers can do this. Performance tests with
1821 // gcc3.3 indicate that this is a realistic expectation for modern
1822 // compilers.
1823 // - since matrix/vector multiplies cannot be done without temporary data,
1824 // the "primary" functions are the global matrix/vector
1825 // rowVecMult/colVecMult routines, rather than the member functions.
1826 // - inlining is explicitly requested only for non-deprecated functions
1827 // involving the native types (UT_Vector3 and UT_Matrix3)
1828 
1829 template <typename T, typename S>
1830 inline UT_Vector3T<T> rowVecMult(const UT_Vector3T<T> &v, const UT_Matrix4T<S> &m);
1831 template <typename T, typename S>
1832 inline UT_Vector3T<T> colVecMult(const UT_Matrix4T<S> &m, const UT_Vector3T<T> &v);
1833 
1834 template <typename T, typename S>
1835 inline UT_Vector3T<T> rowVecMult3(const UT_Vector3T<T> &v, const UT_Matrix4T<S> &m);
1836 template <typename T, typename S>
1837 inline UT_Vector3T<T> colVecMult3(const UT_Matrix4T<S> &m, const UT_Vector3T<T> &v);
1838 // @}
1839 
1840 template <typename T, typename S>
1841 inline UT_Vector3T<T>
1843 {
1844  return UT_Vector3T<T>(
1845  v.x()*m(0,0) + v.y()*m(1,0) + v.z()*m(2,0) + m(3,0),
1846  v.x()*m(0,1) + v.y()*m(1,1) + v.z()*m(2,1) + m(3,1),
1847  v.x()*m(0,2) + v.y()*m(1,2) + v.z()*m(2,2) + m(3,2)
1848  );
1849 }
1850 template <typename T, typename S>
1851 inline UT_Vector3T<T>
1853 {
1854  return rowVecMult(v, m);
1855 }
1856 
1857 template <typename T, typename S>
1858 inline UT_Vector3T<T>
1860 {
1861  return UT_Vector3T<T>(
1862  v.x()*m(0,0) + v.y()*m(1,0) + v.z()*m(2,0),
1863  v.x()*m(0,1) + v.y()*m(1,1) + v.z()*m(2,1),
1864  v.x()*m(0,2) + v.y()*m(1,2) + v.z()*m(2,2)
1865  );
1866 }
1867 
1868 template <typename T, typename S>
1869 inline UT_Vector3T<T>
1871 {
1872  return UT_Vector3T<T>(
1873  v.x()*m(0,0) + v.y()*m(0,1) + v.z()*m(0,2) + m(0,3),
1874  v.x()*m(1,0) + v.y()*m(1,1) + v.z()*m(1,2) + m(1,3),
1875  v.x()*m(2,0) + v.y()*m(2,1) + v.z()*m(2,2) + m(2,3)
1876  );
1877 }
1878 
1879 template <typename T, typename S>
1880 inline UT_Vector3T<T>
1882 {
1883  return UT_Vector3T<T>(
1884  v.x()*m(0,0) + v.y()*m(0,1) + v.z()*m(0,2),
1885  v.x()*m(1,0) + v.y()*m(1,1) + v.z()*m(1,2),
1886  v.x()*m(2,0) + v.y()*m(2,1) + v.z()*m(2,2)
1887  );
1888 }
1889 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1890 template <>
1891 inline UT_Vector3T<float>
1893 {
1894  const v4uf result =
1895  v4uf(m.matx[0]) * v4uf(v[0])
1896  + v4uf(m.matx[1]) * v4uf(v[1])
1897  + v4uf(m.matx[2]) * v4uf(v[2])
1898  + v4uf(m.matx[3]); // * v[3] == 1.0
1899 
1900  // Requires v4uf to be contiguous in memory
1901  return UT_Vector3T<float>((float*) &result);
1902 }
1903 template <>
1904 inline UT_Vector3T<float>
1906 {
1907  const v4uf result =
1908  v4uf(m.matx[0]) * v4uf(v[0])
1909  + v4uf(m.matx[1]) * v4uf(v[1])
1910  + v4uf(m.matx[2]) * v4uf(v[2]);
1911 
1912  // Requires v4uf to be contiguous in memory
1913  return UT_Vector3T<float>((float*) &result);
1914 }
1915 template <>
1916 inline UT_Vector3T<float>
1918 {
1919  const v4uf result =
1920  v4uf(m(0,0), m(1,0), m(2,0), m(3,0)) * v4uf(v[0])
1921  + v4uf(m(0,1), m(1,1), m(2,1), m(3,1)) * v4uf(v[1])
1922  + v4uf(m(0,2), m(1,2), m(2,2), m(3,2)) * v4uf(v[2])
1923  + v4uf(m(0,3), m(1,3), m(2,3), m(3,3)); // * v[3] == 1.0
1924 
1925  // Requires v4uf to be contiguous in memory
1926  return UT_Vector3T<float>((float*) &result);
1927 }
1928 template <>
1929 inline UT_Vector3T<float>
1931 {
1932  const v4uf result =
1933  v4uf(m(0,0), m(1,0), m(2,0), m(3,0)) * v4uf(v[0])
1934  + v4uf(m(0,1), m(1,1), m(2,1), m(3,1)) * v4uf(v[1])
1935  + v4uf(m(0,2), m(1,2), m(2,2), m(3,2)) * v4uf(v[2]);
1936 
1937  // Requires v4uf to be contiguous in memory
1938  return UT_Vector3T<float>((float*) &result);
1939 }
1940 #endif
1941 
1942 
1943 template <typename T>
1944 SYS_FORCE_INLINE void
1946 {
1947  operator=(::rowVecMult(*this, m));
1948 }
1949 template <typename T>
1950 SYS_FORCE_INLINE void
1952 {
1953  operator=(::rowVecMult(*this, m));
1954 }
1955 template <typename T>
1956 SYS_FORCE_INLINE void
1958 {
1959  operator=(::colVecMult(m, *this));
1960 }
1961 template <typename T>
1962 SYS_FORCE_INLINE void
1964 {
1965  operator=(::colVecMult(m, *this));
1966 }
1967 template <typename T>
1968 SYS_FORCE_INLINE void
1970 {
1971  operator=(::rowVecMult3(*this, m));
1972 }
1973 template <typename T>
1974 SYS_FORCE_INLINE void
1976 {
1977  operator=(::rowVecMult3(*this, m));
1978 }
1979 template <typename T>
1980 SYS_FORCE_INLINE void
1982 {
1983  operator=(::colVecMult3(m, *this));
1984 }
1985 template <typename T>
1986 SYS_FORCE_INLINE void
1988 {
1989  operator=(::colVecMult3(m, *this));
1990 }
1991 template <typename T>
1992 template <typename S>
1995 {
1996  rowVecMult(m);
1997  return *this;
1998 }
1999 template <typename T>
2000 template <typename S>
2001 SYS_FORCE_INLINE void
2003 {
2004  rowVecMult3(mat);
2005 }
2006 template <typename T>
2007 template <typename S>
2008 SYS_FORCE_INLINE void
2010 {
2011  colVecMult3(mat);
2012 }
2013 template <typename T>
2014 template <typename S>
2015 SYS_FORCE_INLINE void
2017 {
2018  dest = ::rowVecMult3(*this, mat);
2019 }
2020 template <typename T>
2021 template <typename S>
2022 SYS_FORCE_INLINE void
2024 {
2025  dest = ::colVecMult3(mat, *this);
2026 }
2027 template <typename T>
2028 template <typename S>
2029 SYS_FORCE_INLINE void
2031 {
2032  dest = ::rowVecMult(*this, mat);
2033 }
2034 
2035 template <typename T>
2036 static inline
2037 T dot(const UT_Matrix4T<T> &m1, const UT_Matrix4T<T> &m2){
2038  return m1.dot(m2);
2039 }
2040 
2041 template <typename T>
2042 inline
2044 {
2045  return UT_Matrix4T<T>(
2046  SYSmin(v1(0,0), v2(0,0)),
2047  SYSmin(v1(0,1), v2(0,1)),
2048  SYSmin(v1(0,2), v2(0,2)),
2049  SYSmin(v1(0,3), v2(0,3)),
2050  SYSmin(v1(1,0), v2(1,0)),
2051  SYSmin(v1(1,1), v2(1,1)),
2052  SYSmin(v1(1,2), v2(1,2)),
2053  SYSmin(v1(1,3), v2(1,3)),
2054  SYSmin(v1(2,0), v2(2,0)),
2055  SYSmin(v1(2,1), v2(2,1)),
2056  SYSmin(v1(2,2), v2(2,2)),
2057  SYSmin(v1(2,3), v2(2,3)),
2058  SYSmin(v1(3,0), v2(3,0)),
2059  SYSmin(v1(3,1), v2(3,1)),
2060  SYSmin(v1(3,2), v2(3,2)),
2061  SYSmin(v1(3,3), v2(3,3))
2062  );
2063 }
2064 
2065 template <typename T>
2066 inline
2068 {
2069  return UT_Matrix4T<T>(
2070  SYSmax(v1(0,0), v2(0,0)),
2071  SYSmax(v1(0,1), v2(0,1)),
2072  SYSmax(v1(0,2), v2(0,2)),
2073  SYSmax(v1(0,3), v2(0,3)),
2074  SYSmax(v1(1,0), v2(1,0)),
2075  SYSmax(v1(1,1), v2(1,1)),
2076  SYSmax(v1(1,2), v2(1,2)),
2077  SYSmax(v1(1,3), v2(1,3)),
2078  SYSmax(v1(2,0), v2(2,0)),
2079  SYSmax(v1(2,1), v2(2,1)),
2080  SYSmax(v1(2,2), v2(2,2)),
2081  SYSmax(v1(2,3), v2(2,3)),
2082  SYSmax(v1(3,0), v2(3,0)),
2083  SYSmax(v1(3,1), v2(3,1)),
2084  SYSmax(v1(3,2), v2(3,2)),
2085  SYSmax(v1(3,3), v2(3,3))
2086  );
2087 }
2088 
2089 template <typename T,typename S>
2090 inline
2092 {
2093  return UT_Matrix4T<T>(
2094  SYSlerp(v1(0,0), v2(0,0), t),
2095  SYSlerp(v1(0,1), v2(0,1), t),
2096  SYSlerp(v1(0,2), v2(0,2), t),
2097  SYSlerp(v1(0,3), v2(0,3), t),
2098  SYSlerp(v1(1,0), v2(1,0), t),
2099  SYSlerp(v1(1,1), v2(1,1), t),
2100  SYSlerp(v1(1,2), v2(1,2), t),
2101  SYSlerp(v1(1,3), v2(1,3), t),
2102  SYSlerp(v1(2,0), v2(2,0), t),
2103  SYSlerp(v1(2,1), v2(2,1), t),
2104  SYSlerp(v1(2,2), v2(2,2), t),
2105  SYSlerp(v1(2,3), v2(2,3), t),
2106  SYSlerp(v1(3,0), v2(3,0), t),
2107  SYSlerp(v1(3,1), v2(3,1), t),
2108  SYSlerp(v1(3,2), v2(3,2), t),
2109  SYSlerp(v1(3,3), v2(3,3), t)
2110  );
2111 }
2112 #ifndef UT_DISABLE_VECTORIZE_MATRIX
2113 template <>
2114 inline
2116 {
2118  for (int i = 0; i < 4; ++i)
2119  {
2120  const v4uf r1(v1.matx[i]);
2121  const v4uf r2(v2.matx[i]);
2122  const v4uf rr = SYSlerp(r1, r2, t);
2123  vm_store(result.matx[i], rr.vector);
2124  }
2125  return result;
2126 }
2127 #endif
2128 
2129 template<typename T>
2131 {
2133  typedef T DataType;
2134  static const exint TupleSize = 16;
2135  static const bool isVectorType = true;
2136 };
2137 
2138 // Overload for custom formatting of UT_Matrix4T<T> with UTformat.
2139 template<typename T>
2140 UT_API size_t format(char *buffer, size_t buffer_size, const UT_Matrix4T<T> &v);
2141 
2142 
2143 template <typename T> template<int ORDER>
2144 void
2145 UT_Matrix4T<T>::rotate(T rx, T ry, T rz)
2146 {
2147  switch(ORDER)
2148  {
2149  case 0://UT_XformOrder::XYZ:
2150  if(rx) rotate<UT_Axis3::XAXIS>(rx);
2151  if(ry) rotate<UT_Axis3::YAXIS>(ry);
2152  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
2153  break;
2154 
2155  case 1:
2156  //case UT_XformOrder::XZY:
2157  if(rx) rotate<UT_Axis3::XAXIS>(rx);
2158  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
2159  if(ry) rotate<UT_Axis3::YAXIS>(ry);
2160  break;
2161 
2162  case 2:
2163  //case UT_XformOrder::YXZ:
2164  if(ry) rotate<UT_Axis3::YAXIS>(ry);
2165  if(rx) rotate<UT_Axis3::XAXIS>(rx);
2166  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
2167  break;
2168 
2169  case 3:
2170  //case UT_XformOrder::YZX:
2171  if(ry) rotate<UT_Axis3::YAXIS>(ry);
2172  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
2173  if(rx) rotate<UT_Axis3::XAXIS>(rx);
2174  break;
2175 
2176  case 4:
2177  //case UT_XformOrder::ZXY:
2178  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
2179  if(rx) rotate<UT_Axis3::XAXIS>(rx);
2180  if(ry) rotate<UT_Axis3::YAXIS>(ry);
2181  break;
2182 
2183  case 5:
2184  //case UT_XformOrder::ZYX:
2185  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
2186  if(ry) rotate<UT_Axis3::YAXIS>(ry);
2187  if(rx) rotate<UT_Axis3::XAXIS>(rx);
2188  break;
2189 
2190  default:
2191  break;
2192  }
2193 }
2194 
2195 #endif
UT_Vector3T< T > myScaleOffset
Rotation pivot.
Definition: UT_Matrix4.h:883
void shear(T s_xy, T s_xz, T s_yz)
Definition: UT_Matrix4.h:726
Mat3< typename promote< S, T >::type > operator*(S scalar, const Mat3< T > &m)
Multiply each element of the given matrix by scalar and return the result.
Definition: Mat3.h:575
SYS_FORCE_INLINE void colVecMult3(const UT_Matrix4F &m)
Definition: UT_Matrix4.h:1981
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
void instance(const UT_Vector3D &p, const UT_Vector3D &v, T s, const UT_Vector3D *s3, const UT_Vector3D *up, const UT_QuaternionD *q, const UT_Vector3D *tr, const UT_QuaternionD *orient, const UT_Vector3D *pivot=NULL)
Definition: UT_Matrix4.h:470
#define SYS_STATIC_ASSERT(expr)
SYS_FORCE_INLINE void prerotateHalf()
Definition: UT_Matrix4.h:650
const UT_Vector4T< T > & operator[](unsigned row) const
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix4.h:1384
bool operator!=(const UT_Matrix4T< T > &m) const
Definition: UT_Matrix4.h:307
SYS_FORCE_INLINE void rotate(const UT_Vector3T< T > &rad, const UT_XformOrder &ord)
Definition: UT_Matrix4.h:666
SYS_FORCE_INLINE void prescale(T s)
Definition: UT_Matrix4.h:720
GLuint GLdouble GLdouble GLint GLint order
Definition: glew.h:3460
UT_API size_t format(char *buffer, size_t buffer_size, const UT_Matrix4T< T > &v)
#define VM_STORE
Definition: VM_BasicFunc.h:399
GLenum GLenum GLenum GLenum GLenum scale
Definition: glew.h:14163
SYS_FORCE_INLINE UT_Matrix4T< T > & operator*=(T scalar)
Definition: UT_Matrix4.h:326
MatType shear(Axis axis0, Axis axis1, typename MatType::value_type shear)
Set the matrix to a shear along axis0 by a fraction of axis1.
Definition: Mat.h:710
SYS_FORCE_INLINE void prerotateQuarter()
Definition: UT_Matrix4.h:624
int myOrder
Definition: GT_CurveEval.h:263
SYS_FORCE_INLINE void multiply3T(const UT_Matrix4T< S > &mat)
Definition: UT_Matrix4.h:2009
GLboolean invert
Definition: glcorearb.h:548
UT_Matrix4T< T > & operator=(UT_Matrix4T< T > &&m)=default
Default move assignment operator.
Define parameters for Houdini's full transform model.
Definition: UT_Matrix4.h:856
SYS_FORCE_INLINE void colVecMult(const UT_Matrix3F &m)
Definition: UT_Matrix3.h:1518
T * data()
Return the raw matrix data.
Definition: UT_Matrix4.h:1101
SYS_FORCE_INLINE T operator()(unsigned row, unsigned col) const
Return a matrix entry. No bounds checking on subscripts.
Definition: UT_Matrix4.h:1116
Transformation order of scales, rotates, and translates.
Definition: UT_XformOrder.h:23
SYS_FORCE_INLINE T coFactor(int k, int l) const
Definition: UT_Matrix4.h:368
Mat3< typename promote< T0, T1 >::type > operator+(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Add corresponding elements of m0 and m1 and return the result.
Definition: Mat3.h:591
UT_FixedVector< T, 16 > FixedVectorType
Definition: UT_Matrix4.h:2132
PivotSpaceT()
Constructor with default values for data members.
Definition: UT_Matrix4.h:818
const GLuint GLenum const void * binary
Definition: glcorearb.h:1923
SYS_FORCE_INLINE T & operator()(unsigned row, unsigned col)
Return a matrix entry. No bounds checking on subscripts.
Definition: UT_Matrix4.h:1110
SYS_FORCE_INLINE void rotateQuarter()
Definition: UT_Matrix4.h:550
const GLfloat * c
Definition: glew.h:16631
vfloat4 sqrt(const vfloat4 &a)
Definition: simd.h:7458
UT_Matrix4T< T > & operator=(const UT_Matrix4T< S > &m)
Definition: UT_Matrix4.h:217
int64 exint
Definition: SYS_Types.h:125
SYS_FORCE_INLINE void prerotate(const UT_Vector3T< T > &rad, const UT_XformOrder &ord)
Definition: UT_Matrix4.h:676
void reverse(I begin, I end)
Definition: pugixml.cpp:7190
bool isEqual(const UT_Matrix4T< T > &m, T tolerance=T(SYS_FTOLERANCE)) const
Definition: UT_Matrix4.h:509
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:88
#define UT_API
Definition: UT_API.h:14
SYS_FORCE_INLINE void prescale(const UT_Vector3T< T > &s)
Definition: UT_Matrix4.h:718
Symmetric 4x4 Matrices.
Definition: UT_SymMatrix4.h:19
T trace() const
Definition: UT_Matrix4.h:411
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:35
UT_Vector3T< T > myRotatePivot
Child rotation (degrees, XYZ order)
Definition: UT_Matrix4.h:882
UT_Vector3T< T > myRotateOffset
Translate.
Definition: UT_Matrix4.h:878
static const exint TupleSize
T determinant() const
Definition: UT_Matrix4.h:393
void prescale(T sx, T sy, T sz, T sw=1.0f)
Definition: UT_Matrix4.h:704
4D Vector class.
Definition: UT_Vector4.h:166
2D Vector class.
Definition: UT_Vector2.h:149
SYS_FORCE_INLINE void shear(const UT_Vector3T< T > &sh)
Definition: UT_Matrix4.h:741
GLdouble GLdouble t
Definition: glew.h:1403
GLuint buffer
Definition: glcorearb.h:659
UT_Vector3T< S > myTranslate
Definition: UT_Matrix4.h:832
Define parameters for Houdini's pivot space.
Definition: UT_Matrix4.h:815
UT_Matrix4T< T > SYSmin(const UT_Matrix4T< T > &v1, const UT_Matrix4T< T > &v2)
Definition: UT_Matrix4.h:2043
GLdouble l
Definition: glew.h:9164
UT_Matrix4T< T > SYSbilerp(const UT_Matrix4T< T > &u0v0, const UT_Matrix4T< T > &u1v0, const UT_Matrix4T< T > &u0v1, const UT_Matrix4T< T > &u1v1, S u, S v)
Bilinear interpolation.
Definition: UT_Matrix4.h:78
SYS_FORCE_INLINE void rotateHalf()
Definition: UT_Matrix4.h:573
GLint GLenum GLint x
Definition: glcorearb.h:408
PivotSpaceT< T > PivotSpace
Definition: UT_Matrix4.h:836
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
double fpreal64
Definition: SYS_Types.h:201
#define SYS_DEPRECATED_REPLACE(__V__, __R__)
GLdouble GLdouble GLdouble GLdouble q
Definition: glew.h:1419
T myFloats[tuple_size]
Definition: UT_Matrix4.h:1211
static int entries()
Returns the vector size.
Definition: UT_Matrix4.h:1205
GLuint64EXT * result
Definition: glew.h:14311
SYS_FORCE_INLINE T & y()
Definition: UT_Vector3.h:508
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
void instanceInverse(const UT_Vector3F &p, const UT_Vector3F &v, T s, const UT_Vector3F *s3, const UT_Vector3F *up, const UT_QuaternionF *q, const UT_Vector3F *tr, const UT_QuaternionF *orient, const UT_Vector3F *pivot=NULL)
Definition: UT_Matrix4.h:483
SYS_FORCE_INLINE UT_Matrix4T< T > & operator+=(const UT_Matrix4T< T > &m)
Definition: UT_Matrix4.h:253
UT_Matrix4T< T > & operator=(const UT_Matrix3T< S > &m)
Definition: UT_Matrix4.h:203
GLint limit
Definition: glew.h:13230
SYS_FORCE_INLINE UT_Matrix4T< T > & operator/=(T scalar)
Definition: UT_Matrix4.h:342
Mat3< typename promote< T0, T1 >::type > operator-(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Subtract corresponding elements of m0 and m1 and return the result.
Definition: Mat3.h:601
OIIO_FORCEINLINE const vint4 & operator+=(vint4 &a, const vint4 &b)
Definition: simd.h:4347
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:817
bool operator==(const UT_Matrix4T< T > &m) const
Definition: UT_Matrix4.h:291
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:170
UT_Matrix4T< T > SYSbarycentric(const UT_Matrix4T< T > &v0, const UT_Matrix4T< T > &v1, const UT_Matrix4T< T > &v2, S u, S v)
Barycentric interpolation.
Definition: UT_Matrix4.h:85
void rotate(UT_Vector3T< S > &axis, T theta, int norm=1)
const GLdouble * v
Definition: glcorearb.h:836
int explode(const UT_XformOrder &order, UT_Vector3F &r, UT_Vector3F &s, UT_Vector3F &t, const UT_Vector3F &p, UT_Vector3F *shears=0) const
Definition: UT_Matrix4.h:947
fpreal64 dot(const CE_VectorT< T > &a, const CE_VectorT< T > &b)
Definition: CE_Vector.h:130
static const bool isVectorType
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
SYS_FORCE_INLINE T & z()
Definition: UT_Vector3.h:510
int explode(const UT_XformOrder &order, UT_Vector3F &r, UT_Vector3F &s, UT_Vector3F &t, UT_Vector3F *shears=0) const
Definition: UT_Matrix4.h:932
UT_Vector3T< T > myShear
Scale.
Definition: UT_Matrix4.h:885
UT_Vector3T< T > rowVecMult(const UT_Vector3T< T > &v, const UT_Matrix4T< S > &m)
Definition: UT_Matrix4.h:1842
void scale(T sx, T sy, T sz, T sw=1.0f)
Definition: UT_Matrix4.h:682
T determinant3() const
Compute determinant of the upper-left 3x3 sub-matrix.
Definition: UT_Matrix4.h:401
SYS_FORCE_INLINE void pretranslate(const UT_Vector3T< T > &delta)
Definition: UT_Matrix4.h:774
Definition: VM_SIMD.h:188
SYS_FORCE_INLINE UT_Matrix4T< T > & operator-=(const UT_Matrix4T< T > &m)
Definition: UT_Matrix4.h:269
void pretranslate(T dx, T dy, T dz=0.0f)
Definition: UT_Matrix4.h:766
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:847
UT_Vector3T< T > myTranslate
transform and rotation order
Definition: UT_Matrix4.h:877
SYS_FORCE_INLINE void rowVecMult(const UT_Matrix3F &m)
Definition: UT_Matrix3.h:1506
FullTransformModel()
Constructor with default values for data members.
Definition: UT_Matrix4.h:859
UT_Vector3T< T > myScale
Scale offset.
Definition: UT_Matrix4.h:884
int isZero() const
Definition: UT_Matrix4.h:1083
UT_Vector3T< T > colVecMult(const UT_Matrix4T< S > &m, const UT_Vector3T< T > &v)
Definition: UT_Matrix4.h:1870
GLfloat GLfloat p
Definition: glew.h:16656
int isIdentity() const
Definition: UT_Matrix4.h:1069
void instance(const UT_Vector3F &p, const UT_Vector3F &v, T s, const UT_Vector3F *s3, const UT_Vector3F *up, const UT_QuaternionF *q, const UT_Vector3F *tr, const UT_QuaternionF *orient, const UT_Vector3F *pivot=NULL)
Definition: UT_Matrix4.h:464
SYS_FORCE_INLINE void rowVecMult3(const UT_Matrix4F &m)
Definition: UT_Matrix4.h:1969
void identity()
Set the matrix to identity.
Definition: UT_Matrix4.h:1065
T exp(const T &v)
Definition: simd.h:7610
UT_Matrix4T< T > SYSmax(const UT_Matrix4T< T > &v1, const UT_Matrix4T< T > &v2)
Definition: UT_Matrix4.h:2067
UT_Vector3T< T > myRotate
Parent rotation (degrees, XYZ order)
Definition: UT_Matrix4.h:880
const Vec2< S > & operator*=(Vec2< S > &v, const Matrix33< T > &m)
Definition: ImathMatrix.h:3322
UT_Vector3T< T > colVecMult3(const UT_Matrix4T< S > &m, const UT_Vector3T< T > &v)
Definition: UT_Matrix4.h:1881
SYS_FORCE_INLINE void translate(const UT_Vector3T< T > &delta)
Definition: UT_Matrix4.h:760
UT_Vector3T< T > myParentRotate
Rotation offset.
Definition: UT_Matrix4.h:879
ImageBuf OIIO_API rotate(const ImageBuf &src, float angle, string_view filtername=string_view(), float filterwidth=0.0f, bool recompute_roi=false, ROI roi={}, int nthreads=0)
GLfloat v0
Definition: glcorearb.h:815
void lerp(const UT_Matrix4T< T > &a, const UT_Matrix4T< T > &b, T t)
Definition: UT_Matrix4.h:1051
void instanceInverse(const UT_Vector3D &p, const UT_Vector3D &v, T s, const UT_Vector3D *s3, const UT_Vector3D *up, const UT_QuaternionD *q, const UT_Vector3D *tr, const UT_QuaternionD *orient, const UT_Vector3D *pivot=NULL)
Definition: UT_Matrix4.h:489
SYS_FORCE_INLINE UT_Vector3T< T > & operator*=(const UT_Matrix3T< S > &m)
Definition: UT_Matrix3.h:1531
GA_API const UT_StringHolder orient
SYS_FORCE_INLINE const T * operator()(unsigned row) const
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix4.h:1132
void setTranslates(const UT_Vector3T< S > &translates)
Definition: UT_Matrix4.h:1375
GLdouble n
Definition: glcorearb.h:2007
SYS_FORCE_INLINE void scale(const UT_Vector3T< T > &s)
Definition: UT_Matrix4.h:696
GLboolean * data
Definition: glcorearb.h:130
IFDmantra py
Definition: HDK_Image.dox:266
UT_Vector3T< S > myRotate
Definition: UT_Matrix4.h:833
T dot(unsigned i, unsigned j) const
Definition: UT_Matrix4.h:1037
GLuint GLfloat * val
Definition: glcorearb.h:1607
int explode(const UT_XformOrder &order, UT_Vector3D &r, UT_Vector3D &s, UT_Vector3D &t, const PivotSpaceT< fpreal64 > &p, UT_Vector3D *shears=0) const
Definition: UT_Matrix4.h:969
Quaternion class.
Definition: UT_Quaternion.h:51
SYS_FORCE_INLINE T * operator()(unsigned row)
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix4.h:1126
class UT_API UT_Matrix4T
UT_Matrix4T< T > operator-() const
Definition: UT_Matrix4.h:243
T log(const T &v)
Definition: simd.h:7665
const T * data() const
Return the raw matrix data.
Definition: UT_Matrix4.h:1100
UT_Matrix4T< T > SYSlerp(const UT_Matrix4T< T > &v1, const UT_Matrix4T< T > &v2, S t)
Definition: UT_Matrix4.h:2091
UT_Vector3T< T > rowVecMult3(const UT_Vector3T< T > &v, const UT_Matrix4T< S > &m)
Definition: UT_Matrix4.h:1859
SYS_FORCE_INLINE void scale(T s)
Definition: UT_Matrix4.h:698
GA_API const UT_StringHolder up
T getEuclideanNorm() const
Definition: UT_Matrix4.h:1149
fpreal64 fpreal
Definition: SYS_Types.h:277
UT_Vector3T< T > myPivotRotate
Overall pivot.
Definition: UT_Matrix4.h:888
constexpr UT_Matrix4T(fpreal64 val) noexcept
Construct identity matrix, multipled by scalar.
Definition: UT_Matrix4.h:113
UT_Vector3T< T > myScalePivot
Shear (within scale pivot)
Definition: UT_Matrix4.h:886
void zero()
Set the matrix to zero.
Definition: UT_Matrix4.h:1067
GLenum GLenum void * row
Definition: glew.h:4995
UT_Matrix4T< T > & operator=(const UT_SymMatrix4T< S > &m)
Conversion from a symmetric to a non symmetric matrix.
Definition: UT_Matrix4.h:232
GA_API const UT_StringHolder pivot
const GLdouble * m
Definition: glew.h:9166
int explode(const UT_XformOrder &order, UT_Vector3F &r, UT_Vector3F &s, UT_Vector3F &t, const PivotSpaceT< fpreal32 > &p, UT_Vector3F *shears=0) const
Definition: UT_Matrix4.h:964
SYS_FORCE_INLINE void rotateWithQTurns(T theta, uint qturns)
Definition: UT_Matrix4.h:588
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:77
GLfloat f
Definition: glcorearb.h:1925
GU_API void solve(const GU_Detail &gdp_a, const GA_Range &pts_a, const GU_Detail &gdp_b, const GA_Range &pts_b, Method method, bool compute_distortion, Result &result)
SYS_FORCE_INLINE T & x()
Definition: UT_Vector3.h:506
OIIO_FORCEINLINE const vint4 & operator-=(vint4 &a, const vint4 &b)
Definition: simd.h:4370
#define SYS_FTOLERANCE
Definition: SYS_Types.h:208
void leftMult(const UT_Matrix4T< T > &m)
Definition: UT_Matrix4.h:1526
UT_Matrix4T< T > operator/(const UT_Matrix4T< T > &mat, S sc)
Definition: UT_Matrix4.h:1793
UT_Vector3T< T > myChildRotate
Rotation (degrees, myOrder order)
Definition: UT_Matrix4.h:881
GLfloat GLfloat v1
Definition: glcorearb.h:816
PUGI__FN char_t * translate(char_t *buffer, const char_t *from, const char_t *to, size_t to_length)
Definition: pugixml.cpp:8352
UT_Vector3T< T > myPivot
Scale pivot.
Definition: UT_Matrix4.h:887
PivotSpaceT(const UT_Vector3T< S > &translate, const UT_Vector3T< S > &rotate)
Convenience constructor with translate and rotate.
Definition: UT_Matrix4.h:825
GLenum GLenum dst
Definition: glcorearb.h:1792
GLboolean r
Definition: glcorearb.h:1221
SYS_FORCE_INLINE void multiply(UT_Vector3T< T > &dest, const UT_Matrix4T< S > &mat) const
Definition: UT_Matrix4.h:2030
GLdouble s
Definition: glew.h:1395
unsigned int uint
Definition: SYS_Types.h:45
T matx[4][4]
Definition: UT_Matrix4.h:1210
void translate(T dx, T dy, T dz=0.0f)
Definition: UT_Matrix4.h:747
GLint y
Definition: glcorearb.h:102
v4sf vector
Definition: VM_SIMD.h:348
SYS_FORCE_INLINE void multiply3(const UT_Matrix4T< S > &mat)
Definition: UT_Matrix4.h:2002
int explode(const UT_XformOrder &order, UT_Vector3D &r, UT_Vector3D &s, UT_Vector3D &t, UT_Vector3D *shears=0) const
Definition: UT_Matrix4.h:936
UT_Matrix4T< T > & operator*=(const UT_Matrix4T< S > &m)
Definition: UT_Matrix4.h:1401
int explode(const UT_XformOrder &order, UT_Vector3D &r, UT_Vector3D &s, UT_Vector3D &t, const UT_Vector3D &p, UT_Vector3D *shears=0) const
Definition: UT_Matrix4.h:952
void getTranslates(UT_Vector3T< S > &translates) const
Definition: UT_Matrix4.h:1365
void preMultiply(const UT_Matrix4T< T > &m)
Definition: UT_Matrix4.h:362
unsigned hash() const
Compute a hash.
Definition: UT_Matrix4.h:1105
void transpose()
Definition: UT_Matrix4.h:497