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