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